Add idempotent object deletion
This commit is contained in:
@@ -29,16 +29,18 @@ type fakeS3API struct {
|
||||
getETag *string
|
||||
getLastModified *time.Time
|
||||
|
||||
putOut *s3.PutObjectOutput
|
||||
putErr error
|
||||
putOut *s3.PutObjectOutput
|
||||
putErr error
|
||||
deleteErr error
|
||||
|
||||
headErr error
|
||||
|
||||
lastList *s3.ListObjectsV2Input
|
||||
lastLists []*s3.ListObjectsV2Input
|
||||
lastGet *s3.GetObjectInput
|
||||
lastPut *s3.PutObjectInput
|
||||
lastHead *s3.HeadObjectInput
|
||||
lastList *s3.ListObjectsV2Input
|
||||
lastLists []*s3.ListObjectsV2Input
|
||||
lastGet *s3.GetObjectInput
|
||||
lastPut *s3.PutObjectInput
|
||||
lastDelete *s3.DeleteObjectInput
|
||||
lastHead *s3.HeadObjectInput
|
||||
}
|
||||
|
||||
func (f *fakeS3API) ListObjectsV2(_ context.Context, params *s3.ListObjectsV2Input, _ ...func(*s3.Options)) (*s3.ListObjectsV2Output, error) {
|
||||
@@ -116,6 +118,14 @@ func (f *fakeS3API) PutObject(_ context.Context, params *s3.PutObjectInput, _ ..
|
||||
return f.putOut, nil
|
||||
}
|
||||
|
||||
func (f *fakeS3API) DeleteObject(_ context.Context, params *s3.DeleteObjectInput, _ ...func(*s3.Options)) (*s3.DeleteObjectOutput, error) {
|
||||
f.lastDelete = params
|
||||
if f.deleteErr != nil {
|
||||
return nil, f.deleteErr
|
||||
}
|
||||
return &s3.DeleteObjectOutput{}, nil
|
||||
}
|
||||
|
||||
func (f *fakeS3API) HeadObject(_ context.Context, params *s3.HeadObjectInput, _ ...func(*s3.Options)) (*s3.HeadObjectOutput, error) {
|
||||
f.lastHead = params
|
||||
if f.headErr != nil {
|
||||
@@ -275,6 +285,37 @@ func TestS3BackendExistsNotFound(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestS3BackendDeleteMapsRequestAndErrors(t *testing.T) {
|
||||
client := &fakeS3API{}
|
||||
backend := &S3Backend{bucket: "bucket-1", client: client}
|
||||
if err := backend.Delete(context.Background(), `locks\source.lock`); err != nil {
|
||||
t.Fatalf("Delete() error = %v", err)
|
||||
}
|
||||
if client.lastDelete == nil || *client.lastDelete.Bucket != "bucket-1" || *client.lastDelete.Key != "locks/source.lock" {
|
||||
t.Fatalf("DeleteObject input = %#v, want normalized bucket and key", client.lastDelete)
|
||||
}
|
||||
|
||||
wantErr := errors.New("permission denied")
|
||||
client.deleteErr = wantErr
|
||||
err := backend.Delete(context.Background(), "locks/source.lock")
|
||||
if !errors.Is(err, wantErr) || !strings.Contains(err.Error(), "locks/source.lock") {
|
||||
t.Fatalf("Delete() error = %v, want contextual backend error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestS3BackendDeleteHonorsCancellation(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cancel()
|
||||
client := &fakeS3API{}
|
||||
err := (&S3Backend{bucket: "bucket-1", client: client}).Delete(ctx, "locks/source.lock")
|
||||
if !errors.Is(err, context.Canceled) {
|
||||
t.Fatalf("Delete() error = %v, want context.Canceled", err)
|
||||
}
|
||||
if client.lastDelete != nil {
|
||||
t.Fatal("Delete() called S3 after cancellation")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewS3BackendFromConfigUsesClientOptions(t *testing.T) {
|
||||
original := newS3Client
|
||||
t.Cleanup(func() { newS3Client = original })
|
||||
|
||||
Reference in New Issue
Block a user