mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-10-18 12:08:32 +02:00
* build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/storage/azblob Bumps [github.com/Azure/azure-sdk-for-go/sdk/storage/azblob](https://github.com/Azure/azure-sdk-for-go) from 1.8.0 to 1.8.2. - [Release notes](https://github.com/Azure/azure-sdk-for-go/releases) - [Commits](https://github.com/Azure/azure-sdk-for-go/compare/sdk/azcore/v1.8.0...sdk/azidentity/v1.8.2) --- updated-dependencies: - dependency-name: github.com/Azure/azure-sdk-for-go/sdk/storage/azblob dependency-version: 1.8.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * test: restore loadBucketMetadataFromFiler stub after TestGetBucketMetadata TestGetBucketMetadata replaced the package-level loadBucketMetadataFromFiler with a stub that sleeps one second per load and never restored it. Every test running after it in the same binary paid that sleep on each bucket metadata cache miss: TestPutObjectUploadACL (~245s) and TestCopyObjectDestinationACL (~46s) each created a fresh BucketRegistry per subtest, so the stub fired hundreds of times. In CI this stretched the Test job past 11 minutes and left it exposed to runner cancellation. Restore the real loader via t.Cleanup so the slow stub is scoped to the test that needs it. --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Chris Lu <chris.lu@gmail.com>
230 lines
5.5 KiB
Go
230 lines
5.5 KiB
Go
package s3api
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"reflect"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/aws/aws-sdk-go/service/s3"
|
|
"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
|
|
"github.com/seaweedfs/seaweedfs/weed/pb/iam_pb"
|
|
"github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
|
|
"github.com/seaweedfs/seaweedfs/weed/s3api/s3err"
|
|
)
|
|
|
|
type BucketMetadataTestCase struct {
|
|
filerEntry *filer_pb.Entry
|
|
expectBucketMetadata *BucketMetaData
|
|
}
|
|
|
|
var (
|
|
//bad entry
|
|
badEntry = &filer_pb.Entry{
|
|
Name: "badEntry",
|
|
}
|
|
|
|
//good entry
|
|
goodEntryAcl, _ = json.Marshal(s3_constants.PublicRead)
|
|
goodEntry = &filer_pb.Entry{
|
|
Name: "entryWithValidAcp",
|
|
Extended: map[string][]byte{
|
|
s3_constants.ExtOwnershipKey: []byte(s3_constants.OwnershipBucketOwnerEnforced),
|
|
s3_constants.ExtAmzOwnerKey: []byte(AccountAdmin.DisplayName),
|
|
s3_constants.ExtAmzAclKey: goodEntryAcl,
|
|
},
|
|
}
|
|
|
|
//ownership is ""
|
|
ownershipEmptyStr = &filer_pb.Entry{
|
|
Name: "ownershipEmptyStr",
|
|
Extended: map[string][]byte{
|
|
s3_constants.ExtOwnershipKey: []byte(""),
|
|
},
|
|
}
|
|
|
|
//ownership valid
|
|
ownershipValid = &filer_pb.Entry{
|
|
Name: "ownershipValid",
|
|
Extended: map[string][]byte{
|
|
s3_constants.ExtOwnershipKey: []byte(s3_constants.OwnershipBucketOwnerEnforced),
|
|
},
|
|
}
|
|
|
|
//owner is ""
|
|
acpEmptyStr = &filer_pb.Entry{
|
|
Name: "acpEmptyStr",
|
|
Extended: map[string][]byte{
|
|
s3_constants.ExtAmzOwnerKey: []byte(""),
|
|
},
|
|
}
|
|
|
|
//owner not exists
|
|
acpEmptyObject = &filer_pb.Entry{
|
|
Name: "acpEmptyObject",
|
|
Extended: map[string][]byte{
|
|
s3_constants.ExtAmzOwnerKey: []byte("xxxxx"),
|
|
},
|
|
}
|
|
|
|
//grants is nil
|
|
acpOwnerNilAcp, _ = json.Marshal(make([]*s3.Grant, 0))
|
|
acpOwnerNil = &filer_pb.Entry{
|
|
Name: "acpOwnerNil",
|
|
Extended: map[string][]byte{
|
|
s3_constants.ExtAmzAclKey: acpOwnerNilAcp,
|
|
},
|
|
}
|
|
|
|
//load filer is
|
|
loadFilerBucket = make(map[string]int, 1)
|
|
loadFilerBucketLock sync.Mutex
|
|
//override `loadBucketMetadataFromFiler` to avoid really load from filer
|
|
)
|
|
|
|
var tcs = []*BucketMetadataTestCase{
|
|
{
|
|
badEntry, &BucketMetaData{
|
|
Name: badEntry.Name,
|
|
ObjectOwnership: s3_constants.DefaultOwnershipForExists,
|
|
Owner: &s3.Owner{
|
|
DisplayName: &AccountAdmin.DisplayName,
|
|
ID: &AccountAdmin.Id,
|
|
},
|
|
Acl: nil,
|
|
},
|
|
},
|
|
{
|
|
goodEntry, &BucketMetaData{
|
|
Name: goodEntry.Name,
|
|
ObjectOwnership: s3_constants.OwnershipBucketOwnerEnforced,
|
|
Owner: &s3.Owner{
|
|
DisplayName: &AccountAdmin.DisplayName,
|
|
ID: &AccountAdmin.Id,
|
|
},
|
|
Acl: s3_constants.PublicRead,
|
|
},
|
|
},
|
|
{
|
|
ownershipEmptyStr, &BucketMetaData{
|
|
Name: ownershipEmptyStr.Name,
|
|
ObjectOwnership: s3_constants.DefaultOwnershipForExists,
|
|
Owner: &s3.Owner{
|
|
DisplayName: &AccountAdmin.DisplayName,
|
|
ID: &AccountAdmin.Id,
|
|
},
|
|
Acl: nil,
|
|
},
|
|
},
|
|
{
|
|
ownershipValid, &BucketMetaData{
|
|
Name: ownershipValid.Name,
|
|
ObjectOwnership: s3_constants.OwnershipBucketOwnerEnforced,
|
|
Owner: &s3.Owner{
|
|
DisplayName: &AccountAdmin.DisplayName,
|
|
ID: &AccountAdmin.Id,
|
|
},
|
|
Acl: nil,
|
|
},
|
|
},
|
|
{
|
|
acpEmptyStr, &BucketMetaData{
|
|
Name: acpEmptyStr.Name,
|
|
ObjectOwnership: s3_constants.DefaultOwnershipForExists,
|
|
Owner: &s3.Owner{
|
|
DisplayName: &AccountAdmin.DisplayName,
|
|
ID: &AccountAdmin.Id,
|
|
},
|
|
Acl: nil,
|
|
},
|
|
},
|
|
{
|
|
acpEmptyObject, &BucketMetaData{
|
|
Name: acpEmptyObject.Name,
|
|
ObjectOwnership: s3_constants.DefaultOwnershipForExists,
|
|
Owner: &s3.Owner{
|
|
DisplayName: &AccountAdmin.DisplayName,
|
|
ID: &AccountAdmin.Id,
|
|
},
|
|
Acl: nil,
|
|
},
|
|
},
|
|
{
|
|
acpOwnerNil, &BucketMetaData{
|
|
Name: acpOwnerNil.Name,
|
|
ObjectOwnership: s3_constants.DefaultOwnershipForExists,
|
|
Owner: &s3.Owner{
|
|
DisplayName: &AccountAdmin.DisplayName,
|
|
ID: &AccountAdmin.Id,
|
|
},
|
|
Acl: make([]*s3.Grant, 0),
|
|
},
|
|
},
|
|
}
|
|
|
|
func TestBuildBucketMetadata(t *testing.T) {
|
|
iam := &IdentityAccessManagement{}
|
|
_ = iam.loadS3ApiConfiguration(&iam_pb.S3ApiConfiguration{})
|
|
for _, tc := range tcs {
|
|
resultBucketMetadata := buildBucketMetadata(iam, tc.filerEntry)
|
|
if !reflect.DeepEqual(resultBucketMetadata, tc.expectBucketMetadata) {
|
|
t.Fatalf("result is unexpected: \nresult: %v, \nexpect: %v", resultBucketMetadata, tc.expectBucketMetadata)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestGetBucketMetadata(t *testing.T) {
|
|
original := loadBucketMetadataFromFiler
|
|
t.Cleanup(func() { loadBucketMetadataFromFiler = original })
|
|
loadBucketMetadataFromFiler = func(r *BucketRegistry, bucketName string) (*BucketMetaData, error) {
|
|
time.Sleep(time.Second)
|
|
loadFilerBucketLock.Lock()
|
|
loadFilerBucket[bucketName] = loadFilerBucket[bucketName] + 1
|
|
loadFilerBucketLock.Unlock()
|
|
return &BucketMetaData{
|
|
Name: bucketName,
|
|
}, nil
|
|
}
|
|
|
|
br := NewBucketRegistry(nil)
|
|
|
|
//start 40 goroutine for
|
|
var wg sync.WaitGroup
|
|
closeCh := make(chan struct{})
|
|
for i := 0; i < 40; i++ {
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
outLoop:
|
|
for {
|
|
for j := 0; j < 5; j++ {
|
|
select {
|
|
case <-closeCh:
|
|
break outLoop
|
|
default:
|
|
reqBucket := fmt.Sprintf("%c", 67+j)
|
|
_, errCode := br.GetBucketMetadata(reqBucket)
|
|
if errCode != s3err.ErrNone {
|
|
close(closeCh)
|
|
t.Error("not expect")
|
|
}
|
|
}
|
|
}
|
|
time.Sleep(10 * time.Microsecond)
|
|
}
|
|
}()
|
|
}
|
|
time.Sleep(time.Second)
|
|
close(closeCh)
|
|
wg.Wait()
|
|
|
|
//Each bucket is loaded from the filer only once
|
|
for bucketName, loadCount := range loadFilerBucket {
|
|
if loadCount != 1 {
|
|
t.Fatalf("lock is uneffict: %s, %d", bucketName, loadCount)
|
|
}
|
|
}
|
|
}
|