mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2024-12-13 09:29:07 +08:00
237 lines
5.5 KiB
Go
237 lines
5.5 KiB
Go
|
package s3api
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"github.com/aws/aws-sdk-go/private/protocol/json/jsonutil"
|
||
|
"github.com/aws/aws-sdk-go/service/s3"
|
||
|
"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
|
||
|
"github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
|
||
|
"github.com/seaweedfs/seaweedfs/weed/s3api/s3err"
|
||
|
"reflect"
|
||
|
"sync"
|
||
|
"testing"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
type BucketMetadataTestCase struct {
|
||
|
filerEntry *filer_pb.Entry
|
||
|
expectBucketMetadata *BucketMetaData
|
||
|
}
|
||
|
|
||
|
var (
|
||
|
//bad entry
|
||
|
badEntry = &filer_pb.Entry{
|
||
|
Name: "badEntry",
|
||
|
}
|
||
|
|
||
|
//good entry
|
||
|
goodEntryAcp, _ = jsonutil.BuildJSON(&s3.AccessControlPolicy{
|
||
|
Owner: &s3.Owner{
|
||
|
DisplayName: &AccountAdmin.Name,
|
||
|
ID: &AccountAdmin.Id,
|
||
|
},
|
||
|
Grants: s3_constants.PublicRead,
|
||
|
})
|
||
|
goodEntry = &filer_pb.Entry{
|
||
|
Name: "entryWithValidAcp",
|
||
|
Extended: map[string][]byte{
|
||
|
s3_constants.ExtOwnershipKey: []byte(s3_constants.OwnershipBucketOwnerEnforced),
|
||
|
s3_constants.ExtAcpKey: goodEntryAcp,
|
||
|
},
|
||
|
}
|
||
|
|
||
|
//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),
|
||
|
},
|
||
|
}
|
||
|
|
||
|
//acp is ""
|
||
|
acpEmptyStr = &filer_pb.Entry{
|
||
|
Name: "acpEmptyStr",
|
||
|
Extended: map[string][]byte{
|
||
|
s3_constants.ExtAcpKey: []byte(""),
|
||
|
},
|
||
|
}
|
||
|
|
||
|
//acp is empty object
|
||
|
acpEmptyObjectAcp, _ = jsonutil.BuildJSON(&s3.AccessControlPolicy{
|
||
|
Owner: nil,
|
||
|
Grants: nil,
|
||
|
})
|
||
|
acpEmptyObject = &filer_pb.Entry{
|
||
|
Name: "acpEmptyObject",
|
||
|
Extended: map[string][]byte{
|
||
|
s3_constants.ExtAcpKey: acpEmptyObjectAcp,
|
||
|
},
|
||
|
}
|
||
|
|
||
|
//acp owner is nil
|
||
|
acpOwnerNilAcp, _ = jsonutil.BuildJSON(&s3.AccessControlPolicy{
|
||
|
Owner: nil,
|
||
|
Grants: make([]*s3.Grant, 1),
|
||
|
})
|
||
|
acpOwnerNil = &filer_pb.Entry{
|
||
|
Name: "acpOwnerNil",
|
||
|
Extended: map[string][]byte{
|
||
|
s3_constants.ExtAcpKey: acpOwnerNilAcp,
|
||
|
},
|
||
|
}
|
||
|
|
||
|
//load filer is
|
||
|
loadFilerBucket = make(map[string]int, 1)
|
||
|
//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.Name,
|
||
|
ID: &AccountAdmin.Id,
|
||
|
},
|
||
|
Acl: nil,
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
goodEntry, &BucketMetaData{
|
||
|
Name: goodEntry.Name,
|
||
|
ObjectOwnership: s3_constants.OwnershipBucketOwnerEnforced,
|
||
|
Owner: &s3.Owner{
|
||
|
DisplayName: &AccountAdmin.Name,
|
||
|
ID: &AccountAdmin.Id,
|
||
|
},
|
||
|
Acl: s3_constants.PublicRead,
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
ownershipEmptyStr, &BucketMetaData{
|
||
|
Name: ownershipEmptyStr.Name,
|
||
|
ObjectOwnership: s3_constants.DefaultOwnershipForExists,
|
||
|
Owner: &s3.Owner{
|
||
|
DisplayName: &AccountAdmin.Name,
|
||
|
ID: &AccountAdmin.Id,
|
||
|
},
|
||
|
Acl: nil,
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
ownershipValid, &BucketMetaData{
|
||
|
Name: ownershipValid.Name,
|
||
|
ObjectOwnership: s3_constants.OwnershipBucketOwnerEnforced,
|
||
|
Owner: &s3.Owner{
|
||
|
DisplayName: &AccountAdmin.Name,
|
||
|
ID: &AccountAdmin.Id,
|
||
|
},
|
||
|
Acl: nil,
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
acpEmptyStr, &BucketMetaData{
|
||
|
Name: acpEmptyStr.Name,
|
||
|
ObjectOwnership: s3_constants.DefaultOwnershipForExists,
|
||
|
Owner: &s3.Owner{
|
||
|
DisplayName: &AccountAdmin.Name,
|
||
|
ID: &AccountAdmin.Id,
|
||
|
},
|
||
|
Acl: nil,
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
acpEmptyObject, &BucketMetaData{
|
||
|
Name: acpEmptyObject.Name,
|
||
|
ObjectOwnership: s3_constants.DefaultOwnershipForExists,
|
||
|
Owner: &s3.Owner{
|
||
|
DisplayName: &AccountAdmin.Name,
|
||
|
ID: &AccountAdmin.Id,
|
||
|
},
|
||
|
Acl: nil,
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
acpOwnerNil, &BucketMetaData{
|
||
|
Name: acpOwnerNil.Name,
|
||
|
ObjectOwnership: s3_constants.DefaultOwnershipForExists,
|
||
|
Owner: &s3.Owner{
|
||
|
DisplayName: &AccountAdmin.Name,
|
||
|
ID: &AccountAdmin.Id,
|
||
|
},
|
||
|
Acl: make([]*s3.Grant, 0),
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
func TestBuildBucketMetadata(t *testing.T) {
|
||
|
for _, tc := range tcs {
|
||
|
resultBucketMetadata := buildBucketMetadata(tc.filerEntry)
|
||
|
if !reflect.DeepEqual(resultBucketMetadata, tc.expectBucketMetadata) {
|
||
|
t.Fatalf("result is unexpect: \nresult: %v, \nexpect: %v", resultBucketMetadata, tc.expectBucketMetadata)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestGetBucketMetadata(t *testing.T) {
|
||
|
loadBucketMetadataFromFiler = func(r *BucketRegistry, bucketName string) (*BucketMetaData, error) {
|
||
|
time.Sleep(time.Second)
|
||
|
loadFilerBucket[bucketName] = loadFilerBucket[bucketName] + 1
|
||
|
return &BucketMetaData{
|
||
|
Name: bucketName,
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
br := &BucketRegistry{
|
||
|
metadataCache: make(map[string]*BucketMetaData),
|
||
|
notFound: make(map[string]struct{}),
|
||
|
s3a: 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)
|
||
|
}
|
||
|
}
|
||
|
}
|