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  }