github.com/release-engineering/exodus-rsync@v1.11.2/internal/gw/s3_helpers_test.go (about)

     1  package gw
     2  
     3  import (
     4  	"context"
     5  	"sync"
     6  	"testing"
     7  
     8  	"github.com/aws/aws-sdk-go/aws/awserr"
     9  	"github.com/aws/aws-sdk-go/aws/request"
    10  	"github.com/aws/aws-sdk-go/service/s3"
    11  )
    12  
    13  type blobMap map[string][]error
    14  
    15  type fakeS3 struct {
    16  	t  *testing.T
    17  	mu sync.Mutex
    18  
    19  	blobs blobMap
    20  }
    21  
    22  func newFakeS3(t *testing.T, client *client) *fakeS3 {
    23  	out := fakeS3{t: t, blobs: make(blobMap)}
    24  
    25  	out.install(client)
    26  
    27  	return &out
    28  }
    29  
    30  func (f *fakeS3) reset() {
    31  	f.blobs = make(blobMap)
    32  }
    33  
    34  func (f *fakeS3) install(client *client) {
    35  	handlers := &client.s3.Client.Handlers
    36  
    37  	// Clear all default handlers, preventing requests from
    38  	// actually being sent or parsed.
    39  	handlers.Clear()
    40  
    41  	// This handler is invoked to unpack the response from AWS into
    42  	// an output object and is an appropriate place to hook in our own logic.
    43  	handlers.Unmarshal.PushBack(f.unmarshal)
    44  }
    45  
    46  func (f *fakeS3) unmarshal(r *request.Request) {
    47  	switch v := r.Params.(type) {
    48  	case *s3.HeadObjectInput:
    49  		f.headObject(r, v)
    50  	case *s3.PutObjectInput:
    51  		f.putObject(r, v)
    52  	default:
    53  		r.Error = awserr.New("NotImplemented", "not supported by fake S3", nil)
    54  	}
    55  }
    56  
    57  func (f *fakeS3) headObject(r *request.Request, input *s3.HeadObjectInput) {
    58  	f.mu.Lock()
    59  	defer f.mu.Unlock()
    60  
    61  	errors, haveBlob := f.blobs[*input.Key]
    62  	if !haveBlob {
    63  		r.Error = awserr.New("NotFound", "object not found", nil)
    64  		return
    65  	}
    66  
    67  	if errors == nil || len(errors) == 0 {
    68  		// No specific instructions for this blob, don't need to do anything.
    69  		return
    70  	}
    71  
    72  	// Pop the next error.
    73  	err := errors[0]
    74  	f.blobs[*input.Key] = errors[1:]
    75  
    76  	if err != nil {
    77  		r.Error = err
    78  	}
    79  }
    80  
    81  func (f *fakeS3) putObject(r *request.Request, input *s3.PutObjectInput) {
    82  	f.mu.Lock()
    83  	defer f.mu.Unlock()
    84  
    85  	errors, haveBlob := f.blobs[*input.Key]
    86  	if !haveBlob {
    87  		// Mark that we have this blob, and don't return any errors for it.
    88  		f.blobs[*input.Key] = make([]error, 0)
    89  	}
    90  
    91  	if errors == nil || len(errors) == 0 {
    92  		// No specific instructions for this blob, write succeeds
    93  		return
    94  	}
    95  
    96  	// Pop the next error.
    97  	err := errors[0]
    98  	f.blobs[*input.Key] = errors[1:]
    99  
   100  	if err != nil {
   101  		r.Error = err
   102  	}
   103  }
   104  
   105  func newClientWithFakeS3(t *testing.T) (*client, *fakeS3) {
   106  	cfg := testConfig(t)
   107  
   108  	iface, err := Package.NewClient(context.Background(), cfg)
   109  	if err != nil {
   110  		t.Fatal("creating client:", err)
   111  	}
   112  
   113  	out := iface.(*client)
   114  
   115  	return out, newFakeS3(t, out)
   116  }