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.

236 lines
5.5 KiB

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