You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

259 lines
6.1 KiB

5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
  1. package s3api
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "github.com/aws/aws-sdk-go/service/s3"
  6. "github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
  7. "github.com/seaweedfs/seaweedfs/weed/pb/iam_pb"
  8. "github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
  9. "github.com/seaweedfs/seaweedfs/weed/s3api/s3err"
  10. "reflect"
  11. "sync"
  12. "testing"
  13. "time"
  14. )
  15. type BucketMetadataTestCase struct {
  16. filerEntry *filer_pb.Entry
  17. expectBucketMetadata *BucketMetaData
  18. }
  19. var (
  20. //bad entry
  21. badEntry = &filer_pb.Entry{
  22. Name: "badEntry",
  23. }
  24. //good entry
  25. goodEntryAcl, _ = json.Marshal(s3_constants.PublicRead)
  26. goodEntry = &filer_pb.Entry{
  27. Name: "entryWithValidAcp",
  28. Extended: map[string][]byte{
  29. s3_constants.ExtOwnershipKey: []byte(s3_constants.OwnershipBucketOwnerEnforced),
  30. s3_constants.ExtAmzOwnerKey: []byte(AccountAdmin.DisplayName),
  31. s3_constants.ExtAmzAclKey: goodEntryAcl,
  32. },
  33. }
  34. //ownership is ""
  35. ownershipEmptyStr = &filer_pb.Entry{
  36. Name: "ownershipEmptyStr",
  37. Extended: map[string][]byte{
  38. s3_constants.ExtOwnershipKey: []byte(""),
  39. },
  40. }
  41. //ownership valid
  42. ownershipValid = &filer_pb.Entry{
  43. Name: "ownershipValid",
  44. Extended: map[string][]byte{
  45. s3_constants.ExtOwnershipKey: []byte(s3_constants.OwnershipBucketOwnerEnforced),
  46. },
  47. }
  48. //owner is ""
  49. acpEmptyStr = &filer_pb.Entry{
  50. Name: "acpEmptyStr",
  51. Extended: map[string][]byte{
  52. s3_constants.ExtAmzOwnerKey: []byte(""),
  53. },
  54. }
  55. //owner not exists
  56. acpEmptyObject = &filer_pb.Entry{
  57. Name: "acpEmptyObject",
  58. Extended: map[string][]byte{
  59. s3_constants.ExtAmzOwnerKey: []byte("xxxxx"),
  60. },
  61. }
  62. //grants is nil
  63. acpOwnerNilAcp, _ = json.Marshal(make([]*s3.Grant, 0))
  64. acpOwnerNil = &filer_pb.Entry{
  65. Name: "acpOwnerNil",
  66. Extended: map[string][]byte{
  67. s3_constants.ExtAmzAclKey: acpOwnerNilAcp,
  68. },
  69. }
  70. //load filer is
  71. loadFilerBucket = make(map[string]int, 1)
  72. //override `loadBucketMetadataFromFiler` to avoid really load from filer
  73. )
  74. var tcs = []*BucketMetadataTestCase{
  75. {
  76. badEntry, &BucketMetaData{
  77. Name: badEntry.Name,
  78. ObjectOwnership: s3_constants.DefaultObjectOwnership,
  79. Owner: &s3.Owner{
  80. DisplayName: &AccountAdmin.DisplayName,
  81. ID: &AccountAdmin.Id,
  82. },
  83. Acl: nil,
  84. },
  85. },
  86. {
  87. goodEntry, &BucketMetaData{
  88. Name: goodEntry.Name,
  89. ObjectOwnership: s3_constants.OwnershipBucketOwnerEnforced,
  90. Owner: &s3.Owner{
  91. DisplayName: &AccountAdmin.DisplayName,
  92. ID: &AccountAdmin.Id,
  93. },
  94. Acl: s3_constants.PublicRead,
  95. },
  96. },
  97. {
  98. ownershipEmptyStr, &BucketMetaData{
  99. Name: ownershipEmptyStr.Name,
  100. ObjectOwnership: s3_constants.DefaultObjectOwnership,
  101. Owner: &s3.Owner{
  102. DisplayName: &AccountAdmin.DisplayName,
  103. ID: &AccountAdmin.Id,
  104. },
  105. Acl: []*s3.Grant{
  106. {
  107. Permission: &s3_constants.PermissionFullControl,
  108. Grantee: &s3.Grantee{
  109. Type: &s3_constants.GrantTypeCanonicalUser,
  110. ID: &AccountAdmin.Id,
  111. },
  112. },
  113. },
  114. },
  115. },
  116. {
  117. ownershipValid, &BucketMetaData{
  118. Name: ownershipValid.Name,
  119. ObjectOwnership: s3_constants.OwnershipBucketOwnerEnforced,
  120. Owner: &s3.Owner{
  121. DisplayName: &AccountAdmin.DisplayName,
  122. ID: &AccountAdmin.Id,
  123. },
  124. Acl: []*s3.Grant{
  125. {
  126. Permission: &s3_constants.PermissionFullControl,
  127. Grantee: &s3.Grantee{
  128. Type: &s3_constants.GrantTypeCanonicalUser,
  129. ID: &AccountAdmin.Id,
  130. },
  131. },
  132. },
  133. },
  134. },
  135. {
  136. acpEmptyStr, &BucketMetaData{
  137. Name: acpEmptyStr.Name,
  138. ObjectOwnership: s3_constants.DefaultObjectOwnership,
  139. Owner: &s3.Owner{
  140. DisplayName: &AccountAdmin.DisplayName,
  141. ID: &AccountAdmin.Id,
  142. },
  143. Acl: []*s3.Grant{
  144. {
  145. Permission: &s3_constants.PermissionFullControl,
  146. Grantee: &s3.Grantee{
  147. Type: &s3_constants.GrantTypeCanonicalUser,
  148. ID: &AccountAdmin.Id,
  149. },
  150. },
  151. },
  152. },
  153. },
  154. {
  155. acpEmptyObject, &BucketMetaData{
  156. Name: acpEmptyObject.Name,
  157. ObjectOwnership: s3_constants.DefaultObjectOwnership,
  158. Owner: &s3.Owner{
  159. DisplayName: &AccountAdmin.DisplayName,
  160. ID: &AccountAdmin.Id,
  161. },
  162. Acl: []*s3.Grant{
  163. {
  164. Permission: &s3_constants.PermissionFullControl,
  165. Grantee: &s3.Grantee{
  166. Type: &s3_constants.GrantTypeCanonicalUser,
  167. ID: &AccountAdmin.Id,
  168. },
  169. },
  170. },
  171. },
  172. },
  173. {
  174. acpOwnerNil, &BucketMetaData{
  175. Name: acpOwnerNil.Name,
  176. ObjectOwnership: s3_constants.DefaultObjectOwnership,
  177. Owner: &s3.Owner{
  178. DisplayName: &AccountAdmin.DisplayName,
  179. ID: &AccountAdmin.Id,
  180. },
  181. Acl: make([]*s3.Grant, 0),
  182. },
  183. },
  184. }
  185. func TestBuildBucketMetadata(t *testing.T) {
  186. iam := &IdentityAccessManagement{}
  187. _ = iam.LoadS3ApiConfiguration(&iam_pb.S3ApiConfiguration{})
  188. for _, tc := range tcs {
  189. resultBucketMetadata := buildBucketMetadata(iam, tc.filerEntry)
  190. if !reflect.DeepEqual(resultBucketMetadata, tc.expectBucketMetadata) {
  191. t.Fatalf("result is unexpect: \nresult: %v, \nexpect: %v", resultBucketMetadata, tc.expectBucketMetadata)
  192. }
  193. }
  194. }
  195. func TestGetBucketMetadata(t *testing.T) {
  196. loadBucketMetadataFromFiler = func(r *BucketRegistry, bucketName string) (*BucketMetaData, error) {
  197. time.Sleep(time.Second)
  198. loadFilerBucket[bucketName] = loadFilerBucket[bucketName] + 1
  199. return &BucketMetaData{
  200. Name: bucketName,
  201. }, nil
  202. }
  203. br := &BucketRegistry{
  204. metadataCache: make(map[string]*BucketMetaData),
  205. notFound: make(map[string]struct{}),
  206. s3a: nil,
  207. }
  208. //start 40 goroutine for
  209. var wg sync.WaitGroup
  210. closeCh := make(chan struct{})
  211. for i := 0; i < 40; i++ {
  212. wg.Add(1)
  213. go func() {
  214. defer wg.Done()
  215. outLoop:
  216. for {
  217. for j := 0; j < 5; j++ {
  218. select {
  219. case <-closeCh:
  220. break outLoop
  221. default:
  222. reqBucket := fmt.Sprintf("%c", 67+j)
  223. _, errCode := br.GetBucketMetadata(reqBucket)
  224. if errCode != s3err.ErrNone {
  225. close(closeCh)
  226. t.Error("not expect")
  227. }
  228. }
  229. }
  230. time.Sleep(10 * time.Microsecond)
  231. }
  232. }()
  233. }
  234. time.Sleep(time.Second)
  235. close(closeCh)
  236. wg.Wait()
  237. //Each bucket is loaded from the filer only once
  238. for bucketName, loadCount := range loadFilerBucket {
  239. if loadCount != 1 {
  240. t.Fatalf("lock is uneffict: %s, %d", bucketName, loadCount)
  241. }
  242. }
  243. }