package simples3 import ( "bytes" "io" "io/ioutil" "net/http" "net/http/httptest" "os" "testing" ) type tConfig struct { AccessKey string SecretKey string Endpoint string Region string } func TestS3_FileUpload(t *testing.T) { testTxt, err := os.Open("testdata/test.txt") if err != nil { return } defer testTxt.Close() testPng, err := os.Open("testdata/avatar.png") if err != nil { return } defer testPng.Close() type args struct { u UploadInput } tests := []struct { name string fields tConfig args args wantErr bool }{ { name: "Upload test.txt", fields: tConfig{ AccessKey: os.Getenv("AWS_S3_ACCESS_KEY"), SecretKey: os.Getenv("AWS_S3_SECRET_KEY"), Endpoint: os.Getenv("AWS_S3_ENDPOINT"), Region: os.Getenv("AWS_S3_REGION"), }, args: args{ UploadInput{ Bucket: os.Getenv("AWS_S3_BUCKET"), ObjectKey: "test.txt", ContentType: "text/plain", FileName: "test.txt", Body: testTxt, }, }, wantErr: false, }, { name: "Upload avatar.png", fields: tConfig{ AccessKey: os.Getenv("AWS_S3_ACCESS_KEY"), SecretKey: os.Getenv("AWS_S3_SECRET_KEY"), Endpoint: os.Getenv("AWS_S3_ENDPOINT"), Region: os.Getenv("AWS_S3_REGION"), }, args: args{ UploadInput{ Bucket: os.Getenv("AWS_S3_BUCKET"), ObjectKey: "xyz/image.png", ContentType: "image/png", FileName: "avatar.png", Body: testPng, }, }, wantErr: false, }, } for _, testcase := range tests { tt := testcase t.Run(tt.name, func(t *testing.T) { s3 := New(tt.fields.Region, tt.fields.AccessKey, tt.fields.SecretKey) s3.SetEndpoint(tt.fields.Endpoint) resp, err := s3.FileUpload(tt.args.u) if (err != nil) != tt.wantErr { t.Errorf("S3.FileUpload() error = %v, wantErr %v", err, tt.wantErr) } // check for empty response if (resp == UploadResponse{}) { t.Errorf("S3.FileUpload() returned empty response, %v", resp) } }) } } func TestS3_FileDownload(t *testing.T) { testTxt, err := os.Open("testdata/test.txt") if err != nil { t.Fatal(err) } defer testTxt.Close() testTxtData, err := ioutil.ReadAll(testTxt) if err != nil { t.Fatal(err) } testPng, err := os.Open("testdata/avatar.png") if err != nil { t.Fatal(err) } defer testPng.Close() testPngData, err := ioutil.ReadAll(testPng) if err != nil { t.Fatal(err) } type args struct { u DownloadInput } tests := []struct { name string fields tConfig args args wantErr bool wantResponse []byte }{ { name: "txt", fields: tConfig{ AccessKey: os.Getenv("AWS_S3_ACCESS_KEY"), SecretKey: os.Getenv("AWS_S3_SECRET_KEY"), Endpoint: os.Getenv("AWS_S3_ENDPOINT"), Region: os.Getenv("AWS_S3_REGION"), }, args: args{ u: DownloadInput{ Bucket: os.Getenv("AWS_S3_BUCKET"), ObjectKey: "test.txt", }, }, wantErr: false, wantResponse: testTxtData, }, { name: "png", fields: tConfig{ AccessKey: os.Getenv("AWS_S3_ACCESS_KEY"), SecretKey: os.Getenv("AWS_S3_SECRET_KEY"), Endpoint: os.Getenv("AWS_S3_ENDPOINT"), Region: os.Getenv("AWS_S3_REGION"), }, args: args{ u: DownloadInput{ Bucket: os.Getenv("AWS_S3_BUCKET"), ObjectKey: "xyz/image.png", }, }, wantErr: false, wantResponse: testPngData, }, } for _, testcase := range tests { tt := testcase t.Run(tt.name, func(t *testing.T) { s3 := New(tt.fields.Region, tt.fields.AccessKey, tt.fields.SecretKey) s3.SetEndpoint(tt.fields.Endpoint) resp, err := s3.FileDownload(tt.args.u) if (err != nil) != tt.wantErr { t.Fatalf("S3.FileDownload() error = %v, wantErr %v", err, tt.wantErr) } got, err := ioutil.ReadAll(resp) if err != nil { t.Fatalf("error = %v", err) } resp.Close() if !bytes.Equal(got, tt.wantResponse) { t.Fatalf("S3.FileDownload() = %v, want %v", got, tt.wantResponse) } }) } } func TestS3_FileDelete(t *testing.T) { type args struct { u DeleteInput } tests := []struct { name string fields tConfig args args wantErr bool }{ { name: "Delete test.txt", fields: tConfig{ AccessKey: os.Getenv("AWS_S3_ACCESS_KEY"), SecretKey: os.Getenv("AWS_S3_SECRET_KEY"), Endpoint: os.Getenv("AWS_S3_ENDPOINT"), Region: os.Getenv("AWS_S3_REGION"), }, args: args{ DeleteInput{ Bucket: os.Getenv("AWS_S3_BUCKET"), ObjectKey: "test.txt", }, }, wantErr: false, }, { name: "Delete avatar.png", fields: tConfig{ AccessKey: os.Getenv("AWS_S3_ACCESS_KEY"), SecretKey: os.Getenv("AWS_S3_SECRET_KEY"), Endpoint: os.Getenv("AWS_S3_ENDPOINT"), Region: os.Getenv("AWS_S3_REGION"), }, args: args{ DeleteInput{ Bucket: os.Getenv("AWS_S3_BUCKET"), ObjectKey: "xyz/image.png", }, }, wantErr: false, }, } for _, testcase := range tests { tt := testcase t.Run(tt.name, func(t *testing.T) { s3 := New(tt.fields.Region, tt.fields.AccessKey, tt.fields.SecretKey) s3.SetEndpoint(tt.fields.Endpoint) if err := s3.FileDelete(tt.args.u); (err != nil) != tt.wantErr { t.Errorf("S3.FileDelete() error = %v, wantErr %v", err, tt.wantErr) } }) } } func TestS3_NewUsingIAM(t *testing.T) { var ( iam = `test-new-s3-using-iam` resp = `{"Code" : "Success","LastUpdated" : "2018-12-24T10:18:01Z", "Type" : "AWS-HMAC","AccessKeyId" : "abc", "SecretAccessKey" : "abc","Token" : "abc", "Expiration" : "2018-12-24T16:24:59Z"}` ) ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != "GET" { t.Errorf("Expected 'GET' request, got '%s'", r.Method) } if r.URL.EscapedPath() == "/" { w.WriteHeader(http.StatusOK) io.WriteString(w, iam) } if r.URL.EscapedPath() == "/"+iam { w.WriteHeader(http.StatusOK) w.Header().Set("Content-Type", "application/json") io.WriteString(w, resp) } })) defer ts.Close() s3, err := newUsingIAMImpl(ts.URL, "abc") if err != nil { t.Errorf("S3.FileDelete() error = %v", err) } if s3.AccessKey != "abc" && s3.SecretKey != "abc" && s3.Region != "abc" { t.Errorf("S3.FileDelete() got = %v", s3) } } func TestCustomEndpoint(t *testing.T) { s3 := New("us-east-1", "AccessKey", "SuperSecretKey") // no protocol specified, should default to https s3.SetEndpoint("example.com") if s3.getURL("bucket1") != "https://example.com/bucket1" { t.Errorf("S3.SetEndpoint() got = %v", s3.Endpoint) } // explicit http protocol s3.SetEndpoint("http://localhost:9000") if s3.getURL("bucket2") != "http://localhost:9000/bucket2" { t.Errorf("S3.SetEndpoint() got = %v", s3.Endpoint) } // explicit http protocol s3.SetEndpoint("https://example.com") if s3.getURL("bucket3") != "https://example.com/bucket3" { t.Errorf("S3.SetEndpoint() got = %v", s3.Endpoint) } }