github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/integration/integration_gcs_test.go (about) 1 //go:build integration 2 // +build integration 3 4 // can be executed with 5 // go test -v -tags integration -run TestGCSIntegration ./integration/... 6 7 package main 8 9 import ( 10 "context" 11 "crypto/tls" 12 "errors" 13 "fmt" 14 "io" 15 "net/http" 16 "path/filepath" 17 "strings" 18 "testing" 19 20 "github.com/SAP/jenkins-library/pkg/gcs" 21 "github.com/stretchr/testify/assert" 22 "github.com/stretchr/testify/require" 23 "github.com/testcontainers/testcontainers-go" 24 "github.com/testcontainers/testcontainers-go/wait" 25 "google.golang.org/api/option" 26 ) 27 28 func TestGCSIntegrationClient(t *testing.T) { 29 t.Parallel() 30 ctx := context.Background() 31 testdataPath, err := filepath.Abs("testdata/TestGCSIntegration") 32 assert.NoError(t, err) 33 34 req := testcontainers.GenericContainerRequest{ 35 ContainerRequest: testcontainers.ContainerRequest{ 36 AlwaysPullImage: true, 37 Image: "fsouza/fake-gcs-server:1.30.2", 38 ExposedPorts: []string{"4443/tcp"}, 39 WaitingFor: wait.ForListeningPort("4443/tcp"), 40 Cmd: []string{"-scheme", "https", "-public-host", "localhost"}, 41 BindMounts: map[string]string{ 42 testdataPath: "/data", 43 }, 44 }, 45 Started: true, 46 } 47 48 gcsContainer, err := testcontainers.GenericContainer(ctx, req) 49 require.NoError(t, err) 50 defer gcsContainer.Terminate(ctx) 51 52 ip, err := gcsContainer.Host(ctx) 53 require.NoError(t, err) 54 port, err := gcsContainer.MappedPort(ctx, "4443") 55 endpoint := fmt.Sprintf("https://%s:%s/storage/v1/", ip, port.Port()) 56 httpclient := http.Client{ 57 Transport: &http.Transport{ 58 TLSClientConfig: &tls.Config{ 59 InsecureSkipVerify: true, 60 }, 61 }, 62 } 63 64 t.Run("Test list files - success", func(t *testing.T) { 65 bucketID := "sample-bucket" 66 gcsClient, err := gcs.NewClient(gcs.WithClientOptions(option.WithEndpoint(endpoint), option.WithoutAuthentication(), option.WithHTTPClient(&httpclient))) 67 assert.NoError(t, err) 68 fileNames, err := gcsClient.ListFiles(bucketID) 69 assert.NoError(t, err) 70 assert.Equal(t, []string{"dir/test_file2.yaml", "test_file.txt"}, fileNames) 71 err = gcsClient.Close() 72 assert.NoError(t, err) 73 }) 74 75 t.Run("Test list files in missing bucket", func(t *testing.T) { 76 bucketID := "missing-bucket" 77 gcsClient, err := gcs.NewClient(gcs.WithClientOptions(option.WithEndpoint(endpoint), option.WithoutAuthentication(), option.WithHTTPClient(&httpclient))) 78 defer gcsClient.Close() 79 assert.NoError(t, err) 80 _, err = gcsClient.ListFiles(bucketID) 81 assert.Error(t, err, "bucket doesn't exist") 82 err = gcsClient.Close() 83 assert.NoError(t, err) 84 }) 85 86 t.Run("Test upload & download files - success", func(t *testing.T) { 87 bucketID := "upload-bucket" 88 file1Reader, file1Writer := io.Pipe() 89 file2Reader, file2Writer := io.Pipe() 90 gcsClient, err := gcs.NewClient(gcs.WithOpenFileFunction(openFileMock), gcs.WithCreateFileFunction(getCreateFileMock(file1Writer, file2Writer)), 91 gcs.WithClientOptions(option.WithEndpoint(endpoint), option.WithoutAuthentication(), option.WithHTTPClient(&httpclient))) 92 assert.NoError(t, err) 93 err = gcsClient.UploadFile(bucketID, "file1", "test/file1") 94 assert.NoError(t, err) 95 err = gcsClient.UploadFile(bucketID, "folder/file2", "test/folder/file2") 96 assert.NoError(t, err) 97 fileNames, err := gcsClient.ListFiles(bucketID) 98 assert.NoError(t, err) 99 assert.Equal(t, []string{"placeholder", "test/file1", "test/folder/file2"}, fileNames) 100 go gcsClient.DownloadFile(bucketID, "test/file1", "file1") 101 fileContent, err := io.ReadAll(file1Reader) 102 assert.NoError(t, err) 103 assert.Equal(t, file1Content, string(fileContent)) 104 go gcsClient.DownloadFile(bucketID, "test/folder/file2", "file2") 105 fileContent, err = io.ReadAll(file2Reader) 106 assert.NoError(t, err) 107 assert.Equal(t, file2Content, string(fileContent)) 108 109 err = gcsClient.Close() 110 assert.NoError(t, err) 111 }) 112 113 t.Run("Test upload missing file", func(t *testing.T) { 114 bucketID := "upload-bucket" 115 gcsClient, err := gcs.NewClient(gcs.WithOpenFileFunction(openFileMock), 116 gcs.WithClientOptions(option.WithEndpoint(endpoint), option.WithoutAuthentication(), option.WithHTTPClient(&httpclient))) 117 assert.NoError(t, err) 118 err = gcsClient.UploadFile(bucketID, "file3", "test/file3") 119 assert.Contains(t, err.Error(), "could not open source file") 120 err = gcsClient.Close() 121 assert.NoError(t, err) 122 }) 123 124 t.Run("Test download missing file", func(t *testing.T) { 125 bucketID := "upload-bucket" 126 gcsClient, err := gcs.NewClient(gcs.WithOpenFileFunction(openFileMock), 127 gcs.WithClientOptions(option.WithEndpoint(endpoint), option.WithoutAuthentication(), option.WithHTTPClient(&httpclient))) 128 assert.NoError(t, err) 129 err = gcsClient.DownloadFile(bucketID, "test/file3", "file3") 130 assert.Contains(t, err.Error(), "could not open source file") 131 err = gcsClient.Close() 132 assert.NoError(t, err) 133 }) 134 135 t.Run("Test download file - failed file creation", func(t *testing.T) { 136 bucketID := "upload-bucket" 137 _, file1Writer := io.Pipe() 138 _, file2Writer := io.Pipe() 139 gcsClient, err := gcs.NewClient(gcs.WithOpenFileFunction(openFileMock), gcs.WithCreateFileFunction(getCreateFileMock(file1Writer, file2Writer)), 140 gcs.WithClientOptions(option.WithEndpoint(endpoint), option.WithoutAuthentication(), option.WithHTTPClient(&httpclient))) 141 assert.NoError(t, err) 142 err = gcsClient.DownloadFile(bucketID, "placeholder", "file3") 143 assert.Contains(t, err.Error(), "could not create target file") 144 err = gcsClient.Close() 145 assert.NoError(t, err) 146 }) 147 } 148 149 const ( 150 file1Content = `test file` 151 file2Content = ` 152 foo : bar 153 pleh : help 154 stuff : {'foo': 'bar', 'bar': 'foo'} 155 ` 156 ) 157 158 func openFileMock(name string) (io.ReadCloser, error) { 159 var fileContent string 160 switch name { 161 case "file1": 162 fileContent = file1Content 163 case "folder/file2": 164 fileContent = file2Content 165 default: 166 return nil, errors.New("open file faled") 167 } 168 return io.NopCloser(strings.NewReader(fileContent)), nil 169 } 170 171 func getCreateFileMock(file1Writer io.WriteCloser, file2Writer io.WriteCloser) func(name string) (io.WriteCloser, error) { 172 return func(name string) (io.WriteCloser, error) { 173 switch name { 174 case "file1": 175 return file1Writer, nil 176 case "file2": 177 return file2Writer, nil 178 default: 179 return nil, errors.New("could not create target file") 180 } 181 } 182 }