func Start() error { t := log.Start() defer log.End(t) o, err := option.New(os.Args[1:]) if err != nil { return err } handler, err := NewHandler(o) if err != nil { return err } s := http.Server{ Handler: &handler, ReadTimeout: 10 * time.Second, MaxHeaderBytes: 1 << 20, } l, err := net.Listen("tcp", addr) if err != nil { return err } if err := s.Serve(netutil.LimitListener(l, o.MaxConn)); err != nil { log.Fatalf("fail: err=%v", err) } log.Println("listening: addr=%s", addr) return nil }
func TestEnvar(t *testing.T) { o, err := option.New([]string{}) if err != nil { t.Fatal(err) } if o.ProjectID != os.Getenv("RESIZER_PROJECT_ID") { t.Error("wrong ProjectID:", o.ProjectID) } if o.Bucket != os.Getenv("RESIZER_BUCKET") { t.Error("wrong Bucket:", o.Bucket) } if o.JSON != os.Getenv("RESIZER_JSON") { t.Error("wrong JSON:", o.JSON) } if o.DBUser != os.Getenv("RESIZER_DB_USER") { t.Error("wrong DBUser:"******"RESIZER_DB_PASSWORD") { t.Error("wrong DBPassword:"******"RESIZER_DB_PROTOCOL") { t.Error("wrong DBProtocol:", o.DBProtocol) } if o.DBAddress != os.Getenv("RESIZER_DB_ADDRESS") { t.Error("wrong DBAddress:", o.DBAddress) } if o.DBName != os.Getenv("RESIZER_DB_NAME") { t.Error("wrong DBName:", o.DBName) } SplitedHosts := strings.Split(os.Getenv("RESIZER_HOSTS"), ",") if o.Hosts[0] != SplitedHosts[0] { t.Error("wrong Hosts:", o.Hosts, "expect:", SplitedHosts) } }
func TestValidateFormat(t *testing.T) { o, err := option.New(os.Args[1:]) if err != nil { t.Fatalf("fail to create options: error=%v", err) } if f, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"400"}, "height": []string{"0"}, }, o.Hosts); err != nil { t.Fatalf("fail to validate: error=%v", err) } else if f.ValidatedFormat != "jpeg" { t.Errorf("default format should be jpeg") } if f, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"400"}, "height": []string{"0"}, "format": []string{"jpeg"}, }, o.Hosts); err != nil { t.Errorf("jpeg format is allowed") } else if f.ValidatedFormat != "jpeg" { t.Errorf("format should be jpeg") } if f, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"400"}, "height": []string{"0"}, "format": []string{"png"}, }, o.Hosts); err != nil { t.Errorf("png format is allowed") } else if f.ValidatedFormat != "png" { t.Errorf("format should be png") } if f, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"400"}, "height": []string{"0"}, "format": []string{"gif"}, }, o.Hosts); err != nil { t.Errorf("gif format is allowed") } else if f.ValidatedFormat != "gif" { t.Errorf("format should be gif") } if _, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"400"}, "height": []string{"0"}, "format": []string{"foo"}, }, o.Hosts); err == nil { t.Errorf("format is allowed only jpeg or png or gif") } }
func TestInit(t *testing.T) { var err error o, err := option.New(os.Args[1:]) if err != nil { t.Fatalf("fail to create options: error=%v", err) } s, err = storage.New(o) if err != nil { t.Fatalf("Can't create instance: %v", err) } }
func TestNew(t *testing.T) { var err error o, err := option.New(os.Args[1:]) if err != nil { t.Fatalf("fail to create options: error=%v", err) } u, err = uploader.New(o) if err != nil { t.Fatalf("fail to new: error=%v", err) } }
func TestSerialization(t *testing.T) { o, err := option.New(os.Args[1:]) if err != nil { t.Fatalf("fail to create options: error=%v", err) } f1, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"400"}, "height": []string{"300"}, "method": []string{"thumbnail"}, "format": []string{"png"}, "quality": []string{"30"}, }, o.Hosts) if err != nil { t.Fatalf("should be valid image: error=%v", err) } f2, err := storage.NewImage(map[string][]string{ "quality": []string{"80"}, "format": []string{"png"}, "method": []string{"thumbnail"}, "height": []string{"300"}, "width": []string{"400"}, "url": []string{"http://0.0.0.0"}, "filename": []string{"dummy"}, }, o.Hosts) if err != nil { t.Fatalf("should be valid image: error=%v", err) } f3, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"200"}, "height": []string{"500"}, "method": []string{"thumbnail"}, "format": []string{"png"}, "quality": []string{"80"}, }, o.Hosts) if err != nil { t.Fatalf("should be valid image: error=%v", err) } if f1.ValidatedHash != f2.ValidatedHash { t.Errorf("RequestedHash with equal request should be equal: %+v %+v", f1, f2) } if f1.ValidatedHash == f3.ValidatedHash { t.Errorf("RequestedHash with different file shouldn't be equal: %+v %+v", f1, f3) } if f2.ValidatedHash == f3.ValidatedHash { t.Errorf("RequestedHash with different file shouldn't be equal: %+v %+v", f2, f3) } }
func TestFlags(t *testing.T) { o, err := option.New([]string{ "--id", "AAAA", "--bucket", "BBBB", "--json", "CCCC", "--dbuser", "DDDD", "--dbpassword", "EEEE", "--dbprotocol", "FFFF", "--dbaddress", "GGGG", "--dbname", "HHHH", "--host", "IIII", "--host", "JJJJ", }) if err != nil { t.Fatal(err) } if o.ProjectID != "AAAA" { t.Error("wrong ProjectID:", o.ProjectID) } if o.Bucket != "BBBB" { t.Error("wrong Bucket:", o.Bucket) } if o.JSON != "CCCC" { t.Error("wrong JSON:", o.JSON) } if o.DBUser != "DDDD" { t.Error("wrong DBUser:"******"EEEE" { t.Error("wrong DBPassword:"******"FFFF" { t.Error("wrong DBProtocol:", o.DBProtocol) } if o.DBAddress != "GGGG" { t.Error("wrong DBAddress:", o.DBAddress) } if o.DBName != "HHHH" { t.Error("wrong DBName:", o.DBName) } if o.Hosts[0] != "IIII" { t.Error("wrong Hosts[0]:", o.Hosts[0]) } if o.Hosts[1] != "JJJJ" { t.Error("wrong Hosts[1]:", o.Hosts[0]) } }
func TestGuessSizeError(t *testing.T) { o, err := option.New(os.Args[1:]) if err != nil { t.Fatalf("fail to create options: error=%v", err) } func() { f, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"200"}, "height": []string{"100"}, }, o.Hosts) if err != nil { t.Fatalf("should be valid image: error=%v", err) } if _, err := f.Normalize(image.Point{0, 300}); err == nil { t.Errorf("with zero source width should return error") } }() func() { f, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"200"}, "height": []string{"100"}, }, o.Hosts) if err != nil { t.Fatalf("should be valid image: error=%v", err) } if _, err := f.Normalize(image.Point{400, 0}); err == nil { t.Errorf("with zero source height should return error") } }() func() { f, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"200"}, "height": []string{"100"}, }, o.Hosts) if err != nil { t.Fatalf("should be valid image: error=%v", err) } if _, err := f.Normalize(image.ZP); err == nil { t.Errorf("source size with zero point should return error") } }() }
func TestValidateMethod(t *testing.T) { o, err := option.New(os.Args[1:]) if err != nil { t.Fatalf("fail to create options: error=%v", err) } if f, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"400"}, "height": []string{"0"}, }, o.Hosts); err != nil { t.Fatalf("fail to validate: error=%v", err) } else if f.ValidatedMethod != "normal" { t.Errorf("default method should be normal") } if f, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"400"}, "height": []string{"0"}, "method": []string{"normal"}, }, o.Hosts); err != nil { t.Fatalf("fail to validate: error=%v", err) } else if f.ValidatedMethod != "normal" { t.Errorf("format should be normal") } if f, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"400"}, "height": []string{"0"}, "method": []string{"thumbnail"}, }, o.Hosts); err != nil { t.Errorf("thumbnail format is allowed") } else if f.ValidatedMethod != "thumbnail" { t.Errorf("format should be thumbnail") } if _, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"400"}, "height": []string{"0"}, "method": []string{"foo"}, }, o.Hosts); err == nil { t.Errorf("format other than normal or thumbnail isn't allowed") } }
func TestNewImage(t *testing.T) { o, err := option.New(os.Args[1:]) if err != nil { t.Fatalf("fail to create options: error=%v", err) } if _, err := storage.NewImage(map[string][]string{}, o.Hosts); err == nil { t.Fatalf("fail to NewFile: error=%v", err) } q := map[string][]string{ "url": []string{"http://0.0.0.0"}, "method": []string{storage.MethodThumbnail}, "width": []string{"400"}, "height": []string{"300"}, "format": []string{storage.FormatPng}, "quality": []string{"80"}, } f, err := storage.NewImage(q, o.Hosts) if err != nil { t.Fatalf("fail to New: error=%v", err) } if f.ValidatedURL != "http://0.0.0.0" { t.Errorf("URL is expected '%s', but actual '%s'", "http://0.0.0.0", f.ValidatedURL) } if f.ValidatedMethod != storage.MethodThumbnail { t.Errorf("Method is expected '%s', but actual '%s'", storage.MethodThumbnail, f.ValidatedMethod) } if f.ValidatedWidth != 400 { t.Errorf("RequestedWidth is expected %d, but actual %d", 400, f.ValidatedWidth) } if f.ValidatedHeight != 300 { t.Errorf("RequestedHeight is expected %d, but actual %d", 300, f.ValidatedHeight) } if f.ValidatedFormat != storage.FormatPng { t.Errorf("Format is expected '%s', but actual '%s'", storage.FormatPng, f.ValidatedFormat) } if f.ValidatedQuality != 0 { t.Errorf("Quality is expected %d, but actual %d", 0, f.ValidatedQuality) } }
func BenchmarkProcess(b *testing.B) { if err := fetcher.Init(); err != nil { b.Fatal(err) } o, err := option.New(os.Args[1:]) if err != nil { b.Fatal(err) } for i := 0; i < b.N; i++ { o, err := storage.NewImage(map[string][]string{ "url": []string{""}, "width": []string{"800"}, "height": []string{"0"}, }, o.Hosts) if err != nil { b.Fatalf("%s", err) } path, err := fetcher.Fetch(o.ValidatedURL) if err != nil { b.Fatalf("%s", err.Error()) } var bs []byte w := bytes.NewBuffer(bs) p := processor.New() image, err := p.Preprocess(path) if err != nil { b.Fatalf("%s", err.Error()) } if _, err := p.Process(image, w, o); err != nil { b.Fatalf("%s", err.Error()) } } }
func TestNormalizeWithMethodThumbnail(t *testing.T) { o, err := option.New(os.Args[1:]) if err != nil { t.Fatalf("fail to create options: error=%v", err) } for i, points := range []map[string]image.Point{ map[string]image.Point{ "source": image.Point{400, 300}, "target": image.Point{200, 0}, "dest": image.Point{200, 150}, "canvas": image.Point{200, 150}, }, map[string]image.Point{ "source": image.Point{400, 300}, "target": image.Point{0, 150}, "dest": image.Point{200, 150}, "canvas": image.Point{200, 150}, }, map[string]image.Point{ "source": image.Point{400, 300}, "target": image.Point{200, 150}, "dest": image.Point{200, 150}, "canvas": image.Point{200, 150}, }, map[string]image.Point{ "source": image.Point{400, 300}, "target": image.Point{300, 150}, "dest": image.Point{300, 225}, "canvas": image.Point{300, 150}, }, map[string]image.Point{ "source": image.Point{400, 300}, "target": image.Point{500, 150}, "dest": image.Point{400, 300}, "canvas": image.Point{400, 150}, }, map[string]image.Point{ "source": image.Point{400, 300}, "target": image.Point{200, 200}, "dest": image.Point{266, 200}, "canvas": image.Point{200, 200}, }, map[string]image.Point{ "source": image.Point{400, 300}, "target": image.Point{200, 400}, "dest": image.Point{400, 300}, "canvas": image.Point{200, 300}, }, map[string]image.Point{ "source": image.Point{400, 300}, "target": image.Point{500, 450}, "dest": image.Point{400, 300}, "canvas": image.Point{400, 300}, }, map[string]image.Point{ "source": image.Point{400, 300}, "target": image.Point{600, 450}, "dest": image.Point{400, 300}, "canvas": image.Point{400, 300}, }, map[string]image.Point{ "source": image.Point{400, 300}, "target": image.Point{700, 450}, "dest": image.Point{400, 300}, "canvas": image.Point{400, 300}, }, } { source := points["source"] target := points["target"] dest := points["dest"] canvas := points["canvas"] f, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "method": []string{"thumbnail"}, "width": []string{strconv.Itoa(target.X)}, "height": []string{strconv.Itoa(target.Y)}, }, o.Hosts) if err != nil { t.Fatalf("should be valid image: error=%v", err) } if f, err := f.Normalize(source); err != nil { t.Errorf("Normalize with thumbnail method should not return error: %v", err) } else if f.DestWidth != dest.X { t.Errorf("DestWidth(%d) expected %d, but actual %d", i, dest.X, f.DestWidth) } else if f.DestHeight != dest.Y { t.Errorf("DestHeight(%d) expected %d, but actual %d", i, dest.Y, f.DestHeight) } else if f.CanvasWidth != canvas.X { t.Errorf("CanvasWidth(%d) expected %d, but actual %d", i, canvas.X, f.CanvasWidth) } else if f.CanvasHeight != canvas.Y { t.Errorf("CanvasHeight(%d) expected %d, but actual %d", i, canvas.Y, f.CanvasHeight) } } }
func TestValidateURL(t *testing.T) { o, err := option.New(os.Args[1:]) if err != nil { t.Fatalf("fail to create options: error=%v", err) } // ローカルホストと特定のホストとそのサブドメインを許可する for _, host := range []string{ "0.0.0.0", "255.255.255.255", "localhost", } { // http, https プロトコルを許可する for _, protocol := range []string{ "http", "https", } { url := fmt.Sprintf("%s://%s", protocol, host) if _, err := storage.NewImage(map[string][]string{ "url": []string{url}, "width": []string{"400"}, }, o.Hosts); err != nil { t.Errorf("should allow %s error=%v", url, err) } url = fmt.Sprintf("%s:%d", url, 99999) if _, err := storage.NewImage(map[string][]string{ "url": []string{url}, "width": []string{"400"}, }, o.Hosts); err != nil { t.Errorf("should allow %s error=%v", url, err) } } // その他のプロトコルを許可しない for _, protocol := range []string{ "ftp", "ssh", "git", } { url := fmt.Sprintf("%s://%s", protocol, host) if _, err := storage.NewImage(map[string][]string{ "url": []string{url}, "width": []string{"400"}, }, o.Hosts); err == nil { t.Errorf("shouldn't allow %s", url) } url = fmt.Sprintf("%s:%d", url, 99999) if _, err := storage.NewImage(map[string][]string{ "url": []string{}, "width": []string{"400"}, }, o.Hosts); err == nil { t.Errorf("shouldn't allow %s", url) } } } // その他のホストとそのサブドメインを許可しない for _, host := range []string{ "example.com", "foo.bar.baz.example.com", } { // どのようなプロトコルも許可しない for _, protocol := range []string{ "http", "https", "ftp", "ssh", "git", } { url := fmt.Sprintf("%s://%s", protocol, host) if _, err := storage.NewImage(map[string][]string{ "url": []string{url}, "width": []string{"400"}, }, o.Hosts); err == nil { t.Errorf("shouldn't allow %s", url) } url = fmt.Sprintf("%s:%d", url, 99999) if _, err := storage.NewImage(map[string][]string{ "url": []string{url}, "width": []string{"400"}, }, o.Hosts); err == nil { t.Errorf("shouldn't allow %s", url) } } } }
func TestValidateQuality(t *testing.T) { o, err := option.New(os.Args[1:]) if err != nil { t.Fatalf("fail to create options: error=%v", err) } if f, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"400"}, "height": []string{"0"}, }, o.Hosts); err != nil { t.Errorf("fail to validate: error=%v", err) } else if f.ValidatedQuality != 100 { t.Errorf("default quality should be 100") } if _, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"400"}, "height": []string{"0"}, "quality": []string{"-1"}, }, o.Hosts); err == nil { t.Errorf("negative quality shouldn't be allowed") } if _, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"400"}, "height": []string{"0"}, "quality": []string{"101"}, }, o.Hosts); err == nil { t.Errorf("over 100 quality shouldn't be allowed") } if f, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"400"}, "height": []string{"0"}, "quality": []string{"67"}, "format": []string{storage.FormatJpeg}, }, o.Hosts); err != nil { t.Errorf("fail to validate: error=%v", err) } else if f.ValidatedQuality != 67 { t.Errorf("Quality with png format should be 67, but actual %d", f.ValidatedQuality) } if f, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"400"}, "height": []string{"0"}, "quality": []string{"67"}, "format": []string{storage.FormatPng}, }, o.Hosts); err != nil { t.Errorf("fail to validate: error=%v", err) } else if f.ValidatedQuality != 0 { t.Errorf("Quality with png format should be 0, but actual %d", f.ValidatedQuality) } if f, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"400"}, "height": []string{"0"}, "quality": []string{"67"}, "format": []string{storage.FormatGif}, }, o.Hosts); err != nil { t.Errorf("fail to validate: error=%v", err) } else if f.ValidatedQuality != 0 { t.Errorf("Quality with gif format should be 0, but actual %d", f.ValidatedQuality) } }
func TestValidateSize(t *testing.T) { o, err := option.New(os.Args[1:]) if err != nil { t.Fatalf("fail to create options: error=%v", err) } if _, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"-100"}, "height": []string{"100"}, }, o.Hosts); err == nil { t.Errorf("negative width isn't allowed") } if _, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"100"}, "height": []string{"-100"}, }, o.Hosts); err == nil { t.Errorf("negative height isn't allowed") } if _, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"-100"}, "height": []string{"-100"}, }, o.Hosts); err == nil { t.Errorf("negative width and height isn't allowed") } func() { if _, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"0"}, "height": []string{"0"}, }, o.Hosts); err == nil { t.Errorf("zero size isn't allowed") } }() if _, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"0"}, "height": []string{"100"}, }, o.Hosts); err != nil { t.Errorf("zero width is allowed err=", err) } if _, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"100"}, "height": []string{"0"}, }, o.Hosts); err != nil { t.Errorf("zero height is allowed err=", err) } if _, err := storage.NewImage(map[string][]string{ "url": []string{"http://0.0.0.0"}, "width": []string{"100"}, "height": []string{"100"}, }, o.Hosts); err != nil { t.Errorf("non-zero size is allowed err=", err) } }