13 type OssCopySuite struct {
18 var _ = Suite(&OssCopySuite{})
20 // SetUpSuite runs once when the suite starts running
21 func (s *OssCopySuite) SetUpSuite(c *C) {
22 client, err := New(endpoint, accessID, accessKey)
26 s.client.CreateBucket(bucketName)
28 bucket, err := s.client.Bucket(bucketName)
32 testLogger.Println("test copy started")
35 // TearDownSuite runs before each test or benchmark starts running
36 func (s *OssCopySuite) TearDownSuite(c *C) {
38 keyMarker := KeyMarker("")
39 uploadIDMarker := UploadIDMarker("")
41 lmur, err := s.bucket.ListMultipartUploads(keyMarker, uploadIDMarker)
43 for _, upload := range lmur.Uploads {
44 var imur = InitiateMultipartUploadResult{Bucket: bucketName,
45 Key: upload.Key, UploadID: upload.UploadID}
46 err = s.bucket.AbortMultipartUpload(imur)
49 keyMarker = KeyMarker(lmur.NextKeyMarker)
50 uploadIDMarker = UploadIDMarker(lmur.NextUploadIDMarker)
51 if !lmur.IsTruncated {
59 lor, err := s.bucket.ListObjects(marker)
61 for _, object := range lor.Objects {
62 err = s.bucket.DeleteObject(object.Key)
65 marker = Marker(lor.NextMarker)
72 err := s.client.DeleteBucket(s.bucket.BucketName)
75 testLogger.Println("test copy completed")
78 // SetUpTest runs after each test or benchmark runs
79 func (s *OssCopySuite) SetUpTest(c *C) {
80 err := removeTempFiles("../oss", ".jpg")
84 // TearDownTest runs once after all tests or benchmarks have finished running
85 func (s *OssCopySuite) TearDownTest(c *C) {
86 err := removeTempFiles("../oss", ".jpg")
90 // TestCopyRoutineWithoutRecovery is multi-routine copy without resumable recovery
91 func (s *OssCopySuite) TestCopyRoutineWithoutRecovery(c *C) {
92 srcObjectName := objectNamePrefix + RandStr(8)
93 destObjectName := srcObjectName + "-dest"
94 fileName := "../sample/BingWallpaper-2015-11-07.jpg"
95 newFile := "copy-new-file.jpg"
98 err := s.bucket.UploadFile(srcObjectName, fileName, 100*1024, Routines(3))
102 // Does not specify parameter 'routines', by default it's single routine
103 err = s.bucket.CopyFile(bucketName, srcObjectName, destObjectName, 100*1024)
106 err = s.bucket.GetObjectToFile(destObjectName, newFile)
109 eq, err := compareFiles(fileName, newFile)
111 c.Assert(eq, Equals, true)
113 err = s.bucket.DeleteObject(destObjectName)
117 // Specify one routine.
118 err = s.bucket.CopyFile(bucketName, srcObjectName, destObjectName, 100*1024, Routines(1))
121 err = s.bucket.GetObjectToFile(destObjectName, newFile)
124 eq, err = compareFiles(fileName, newFile)
126 c.Assert(eq, Equals, true)
128 err = s.bucket.DeleteObject(destObjectName)
132 // Specify three routines, which is less than parts count 5
133 err = s.bucket.CopyFile(bucketName, srcObjectName, destObjectName, 100*1024, Routines(3))
136 err = s.bucket.GetObjectToFile(destObjectName, newFile)
139 eq, err = compareFiles(fileName, newFile)
141 c.Assert(eq, Equals, true)
143 err = s.bucket.DeleteObject(destObjectName)
147 // Specify 5 routines which is the same as parts count
148 err = s.bucket.CopyFile(bucketName, srcObjectName, destObjectName, 100*1024, Routines(5))
151 err = s.bucket.GetObjectToFile(destObjectName, newFile)
154 eq, err = compareFiles(fileName, newFile)
156 c.Assert(eq, Equals, true)
158 err = s.bucket.DeleteObject(destObjectName)
162 // Specify routine count 10, which is more than parts count
163 err = s.bucket.CopyFile(bucketName, srcObjectName, destObjectName, 100*1024, Routines(10))
166 err = s.bucket.GetObjectToFile(destObjectName, newFile)
169 eq, err = compareFiles(fileName, newFile)
171 c.Assert(eq, Equals, true)
173 err = s.bucket.DeleteObject(destObjectName)
177 // Invalid routine count, will use single routine
178 err = s.bucket.CopyFile(bucketName, srcObjectName, destObjectName, 100*1024, Routines(-1))
181 err = s.bucket.GetObjectToFile(destObjectName, newFile)
184 eq, err = compareFiles(fileName, newFile)
186 c.Assert(eq, Equals, true)
188 err = s.bucket.DeleteObject(destObjectName)
193 err = s.bucket.CopyFile(bucketName, srcObjectName, destObjectName, 100*1024, Routines(3), Meta("myprop", "mypropval"))
195 meta, err := s.bucket.GetObjectDetailedMeta(destObjectName)
197 c.Assert(meta.Get("X-Oss-Meta-Myprop"), Equals, "mypropval")
199 err = s.bucket.GetObjectToFile(destObjectName, newFile)
202 eq, err = compareFiles(fileName, newFile)
204 c.Assert(eq, Equals, true)
206 err = s.bucket.DeleteObject(destObjectName)
210 err = s.bucket.DeleteObject(srcObjectName)
214 // CopyErrorHooker is a copypart request hook
215 func CopyErrorHooker(part copyPart) error {
216 if part.Number == 5 {
217 time.Sleep(time.Second)
218 return fmt.Errorf("ErrorHooker")
223 // TestCopyRoutineWithoutRecoveryNegative is a multiple routines copy without checkpoint
224 func (s *OssCopySuite) TestCopyRoutineWithoutRecoveryNegative(c *C) {
225 srcObjectName := objectNamePrefix + RandStr(8)
226 destObjectName := srcObjectName + "-dest"
227 fileName := "../sample/BingWallpaper-2015-11-07.jpg"
229 // Upload source file
230 err := s.bucket.UploadFile(srcObjectName, fileName, 100*1024, Routines(3))
233 copyPartHooker = CopyErrorHooker
234 // Worker routine errors
235 err = s.bucket.CopyFile(bucketName, srcObjectName, destObjectName, 100*1024, Routines(2))
237 c.Assert(err, NotNil)
238 c.Assert(err.Error(), Equals, "ErrorHooker")
239 copyPartHooker = defaultCopyPartHook
241 // Source bucket does not exist
242 err = s.bucket.CopyFile("notexist", srcObjectName, destObjectName, 100*1024, Routines(2))
243 c.Assert(err, NotNil)
245 // Target object does not exist
246 err = s.bucket.CopyFile(bucketName, "notexist", destObjectName, 100*1024, Routines(2))
248 // The part size is invalid
249 err = s.bucket.CopyFile(bucketName, srcObjectName, destObjectName, 1024, Routines(2))
250 c.Assert(err, NotNil)
252 err = s.bucket.CopyFile(bucketName, srcObjectName, destObjectName, 1024*1024*1024*100, Routines(2))
253 c.Assert(err, NotNil)
255 // Delete the source file
256 err = s.bucket.DeleteObject(srcObjectName)
260 // TestCopyRoutineWithRecovery is a multiple routines copy with resumable recovery
261 func (s *OssCopySuite) TestCopyRoutineWithRecovery(c *C) {
262 srcObjectName := objectNamePrefix + RandStr(8)
263 destObjectName := srcObjectName + "-dest"
264 fileName := "../sample/BingWallpaper-2015-11-07.jpg"
265 newFile := RandStr(8) + ".jpg"
267 // Upload source file
268 err := s.bucket.UploadFile(srcObjectName, fileName, 100*1024, Routines(3))
272 // Routines default value, CP's default path is destObjectName+.cp
273 // Copy object with checkpoint enabled, single runtine.
274 // Copy 4 parts---the CopyErrorHooker makes sure the copy of part 5 will fail.
275 copyPartHooker = CopyErrorHooker
276 err = s.bucket.CopyFile(bucketName, srcObjectName, destObjectName, 1024*100, Checkpoint(true, destObjectName+".cp"))
277 c.Assert(err, NotNil)
278 c.Assert(err.Error(), Equals, "ErrorHooker")
279 copyPartHooker = defaultCopyPartHook
282 ccp := copyCheckpoint{}
283 err = ccp.load(destObjectName + ".cp")
285 c.Assert(ccp.Magic, Equals, copyCpMagic)
286 c.Assert(len(ccp.MD5), Equals, len("LC34jZU5xK4hlxi3Qn3XGQ=="))
287 c.Assert(ccp.SrcBucketName, Equals, bucketName)
288 c.Assert(ccp.SrcObjectKey, Equals, srcObjectName)
289 c.Assert(ccp.DestBucketName, Equals, bucketName)
290 c.Assert(ccp.DestObjectKey, Equals, destObjectName)
291 c.Assert(len(ccp.CopyID), Equals, len("3F79722737D1469980DACEDCA325BB52"))
292 c.Assert(ccp.ObjStat.Size, Equals, int64(482048))
293 c.Assert(len(ccp.ObjStat.LastModified), Equals, len("2015-12-17 18:43:03 +0800 CST"))
294 c.Assert(ccp.ObjStat.Etag, Equals, "\"2351E662233817A7AE974D8C5B0876DD-5\"")
295 c.Assert(len(ccp.Parts), Equals, 5)
296 c.Assert(len(ccp.todoParts()), Equals, 1)
297 c.Assert(ccp.PartStat[4], Equals, false)
299 // Second copy, finish the last part
300 err = s.bucket.CopyFile(bucketName, srcObjectName, destObjectName, 1024*100, Checkpoint(true, destObjectName+".cp"))
303 err = s.bucket.GetObjectToFile(destObjectName, newFile)
306 eq, err := compareFiles(fileName, newFile)
308 c.Assert(eq, Equals, true)
310 err = s.bucket.DeleteObject(destObjectName)
314 err = ccp.load(fileName + ".cp")
315 c.Assert(err, NotNil)
317 //multicopy with empty checkpoint path
318 copyPartHooker = CopyErrorHooker
319 err = s.bucket.CopyFile(bucketName, srcObjectName, destObjectName, 1024*100, Checkpoint(true, ""))
320 c.Assert(err, NotNil)
321 c.Assert(err.Error(), Equals, "ErrorHooker")
322 copyPartHooker = defaultCopyPartHook
323 ccp = copyCheckpoint{}
324 err = ccp.load(destObjectName + ".cp")
325 c.Assert(err, NotNil)
327 //multi copy with checkpoint dir
328 copyPartHooker = CopyErrorHooker
329 err = s.bucket.CopyFile(bucketName, srcObjectName, destObjectName, 1024*100, Routines(2), CheckpointDir(true, "./"))
330 c.Assert(err, NotNil)
331 c.Assert(err.Error(), Equals, "ErrorHooker")
332 copyPartHooker = defaultCopyPartHook
335 ccp = copyCheckpoint{}
336 cpConf := cpConfig{IsEnable: true, DirPath: "./"}
337 cpFilePath := getCopyCpFilePath(&cpConf, bucketName, srcObjectName, s.bucket.BucketName, destObjectName, "")
338 err = ccp.load(cpFilePath)
340 c.Assert(ccp.Magic, Equals, copyCpMagic)
341 c.Assert(len(ccp.MD5), Equals, len("LC34jZU5xK4hlxi3Qn3XGQ=="))
342 c.Assert(ccp.SrcBucketName, Equals, bucketName)
343 c.Assert(ccp.SrcObjectKey, Equals, srcObjectName)
344 c.Assert(ccp.DestBucketName, Equals, bucketName)
345 c.Assert(ccp.DestObjectKey, Equals, destObjectName)
346 c.Assert(len(ccp.CopyID), Equals, len("3F79722737D1469980DACEDCA325BB52"))
347 c.Assert(ccp.ObjStat.Size, Equals, int64(482048))
348 c.Assert(len(ccp.ObjStat.LastModified), Equals, len("2015-12-17 18:43:03 +0800 CST"))
349 c.Assert(ccp.ObjStat.Etag, Equals, "\"2351E662233817A7AE974D8C5B0876DD-5\"")
350 c.Assert(len(ccp.Parts), Equals, 5)
351 c.Assert(len(ccp.todoParts()), Equals, 1)
352 c.Assert(ccp.PartStat[4], Equals, false)
354 // Second copy, finish the last part.
355 err = s.bucket.CopyFile(bucketName, srcObjectName, destObjectName, 1024*100, Routines(2), CheckpointDir(true, "./"))
358 err = s.bucket.GetObjectToFile(destObjectName, newFile)
361 eq, err = compareFiles(fileName, newFile)
363 c.Assert(eq, Equals, true)
365 err = s.bucket.DeleteObject(destObjectName)
369 err = ccp.load(srcObjectName + ".cp")
370 c.Assert(err, NotNil)
372 // First copy without error.
373 err = s.bucket.CopyFile(bucketName, srcObjectName, destObjectName, 1024*100, Routines(3), Checkpoint(true, destObjectName+".cp"))
376 err = s.bucket.GetObjectToFile(destObjectName, newFile)
379 eq, err = compareFiles(fileName, newFile)
381 c.Assert(eq, Equals, true)
383 err = s.bucket.DeleteObject(destObjectName)
387 // Copy with multiple coroutines, no errors.
388 err = s.bucket.CopyFile(bucketName, srcObjectName, destObjectName, 1024*100, Routines(10), Checkpoint(true, destObjectName+".cp"))
391 err = s.bucket.GetObjectToFile(destObjectName, newFile)
394 eq, err = compareFiles(fileName, newFile)
396 c.Assert(eq, Equals, true)
398 err = s.bucket.DeleteObject(destObjectName)
403 err = s.bucket.CopyFile(bucketName, srcObjectName, destObjectName, 1024*100, Routines(5), Checkpoint(true, destObjectName+".cp"), Meta("myprop", "mypropval"))
406 meta, err := s.bucket.GetObjectDetailedMeta(destObjectName)
408 c.Assert(meta.Get("X-Oss-Meta-Myprop"), Equals, "mypropval")
410 err = s.bucket.GetObjectToFile(destObjectName, newFile)
413 eq, err = compareFiles(fileName, newFile)
415 c.Assert(eq, Equals, true)
417 err = s.bucket.DeleteObject(destObjectName)
421 // Delete the source file
422 err = s.bucket.DeleteObject(srcObjectName)
426 // TestCopyRoutineWithRecoveryNegative is a multiple routineed copy without checkpoint
427 func (s *OssCopySuite) TestCopyRoutineWithRecoveryNegative(c *C) {
428 srcObjectName := objectNamePrefix + RandStr(8)
429 destObjectName := srcObjectName + "-dest"
431 // Source bucket does not exist
432 err := s.bucket.CopyFile("notexist", srcObjectName, destObjectName, 100*1024, Checkpoint(true, destObjectName+".cp"))
433 c.Assert(err, NotNil)
434 c.Assert(err, NotNil)
436 // Source object does not exist
437 err = s.bucket.CopyFile(bucketName, "notexist", destObjectName, 100*1024, Routines(2), Checkpoint(true, destObjectName+".cp"))
438 c.Assert(err, NotNil)
440 // Specify part size is invalid.
441 err = s.bucket.CopyFile(bucketName, srcObjectName, destObjectName, 1024, Checkpoint(true, destObjectName+".cp"))
442 c.Assert(err, NotNil)
444 err = s.bucket.CopyFile(bucketName, srcObjectName, destObjectName, 1024*1024*1024*100, Routines(2), Checkpoint(true, destObjectName+".cp"))
445 c.Assert(err, NotNil)
448 // TestCopyFileCrossBucket is a cross bucket's direct copy.
449 func (s *OssCopySuite) TestCopyFileCrossBucket(c *C) {
450 destBucketName := bucketName + "-desc"
451 srcObjectName := objectNamePrefix + RandStr(8)
452 destObjectName := srcObjectName + "-dest"
453 fileName := "../sample/BingWallpaper-2015-11-07.jpg"
454 newFile := RandStr(8) + ".jpg"
456 destBucket, err := s.client.Bucket(destBucketName)
459 // Create a target bucket
460 err = s.client.CreateBucket(destBucketName)
462 // Upload source file
463 err = s.bucket.UploadFile(srcObjectName, fileName, 100*1024, Routines(3))
468 err = destBucket.CopyFile(bucketName, srcObjectName, destObjectName, 1024*100, Routines(5), Checkpoint(true, destObjectName+".cp"))
471 err = destBucket.GetObjectToFile(destObjectName, newFile)
474 eq, err := compareFiles(fileName, newFile)
476 c.Assert(eq, Equals, true)
478 err = destBucket.DeleteObject(destObjectName)
482 // Copy file with options
483 err = destBucket.CopyFile(bucketName, srcObjectName, destObjectName, 1024*100, Routines(10), Checkpoint(true, "copy.cp"), Meta("myprop", "mypropval"))
486 err = destBucket.GetObjectToFile(destObjectName, newFile)
489 eq, err = compareFiles(fileName, newFile)
491 c.Assert(eq, Equals, true)
493 err = destBucket.DeleteObject(destObjectName)
497 // Delete target bucket
498 ForceDeleteBucket(s.client, destBucketName, c)
501 func (s *OssCopySuite) TestVersioningCopyFileCrossBucket(c *C) {
502 // create a bucket with default proprety
503 client, err := New(endpoint, accessID, accessKey)
506 bucketName := bucketNamePrefix + RandLowStr(6)
507 err = client.CreateBucket(bucketName)
510 bucket, err := client.Bucket(bucketName)
512 // put bucket version:enabled
513 var versioningConfig VersioningConfig
514 versioningConfig.Status = string(VersionEnabled)
515 err = client.SetBucketVersioning(bucketName, versioningConfig)
519 objectName := objectNamePrefix + RandStr(8)
520 fileName := "test-file-" + RandStr(8)
521 fileData := RandStr(500 * 1024)
522 CreateFile(fileName, fileData, c)
523 newFile := "test-file-" + RandStr(8)
524 destBucketName := bucketName + "-desc"
525 srcObjectName := objectNamePrefix + RandStr(8)
526 destObjectName := srcObjectName + "-dest"
528 // Create dest bucket
529 err = client.CreateBucket(destBucketName)
531 destBucket, err := client.Bucket(destBucketName)
534 err = client.SetBucketVersioning(destBucketName, versioningConfig)
537 // Upload source file
538 var respHeader http.Header
539 options := []Option{Routines(3), GetResponseHeader(&respHeader)}
540 err = bucket.UploadFile(srcObjectName, fileName, 100*1024, options...)
541 versionId := GetVersionId(respHeader)
542 c.Assert(len(versionId) > 0, Equals, true)
547 // overwrite emtpy object
548 err = bucket.PutObject(srcObjectName, strings.NewReader(""))
552 var respCopyHeader http.Header
553 options = []Option{Routines(5), Checkpoint(true, destObjectName+".cp"), GetResponseHeader(&respCopyHeader), VersionId(versionId)}
554 err = destBucket.CopyFile(bucketName, srcObjectName, destObjectName, 1024*100, options...)
556 versionIdCopy := GetVersionId(respCopyHeader)
557 c.Assert(len(versionIdCopy) > 0, Equals, true)
559 err = destBucket.GetObjectToFile(destObjectName, newFile, VersionId(versionIdCopy))
562 eq, err := compareFiles(fileName, newFile)
564 c.Assert(eq, Equals, true)
566 err = destBucket.DeleteObject(destObjectName)
570 // Copy file with options meta
571 options = []Option{Routines(10), Checkpoint(true, "copy.cp"), Meta("myprop", "mypropval"), GetResponseHeader(&respCopyHeader), VersionId(versionId)}
572 err = destBucket.CopyFile(bucketName, srcObjectName, destObjectName, 1024*100, options...)
574 versionIdCopy = GetVersionId(respCopyHeader)
576 err = destBucket.GetObjectToFile(destObjectName, newFile, VersionId(versionIdCopy))
579 eq, err = compareFiles(fileName, newFile)
581 c.Assert(eq, Equals, true)
585 destBucket.DeleteObject(destObjectName)
586 bucket.DeleteObject(objectName)
587 ForceDeleteBucket(client, bucketName, c)
588 ForceDeleteBucket(client, destBucketName, c)
591 // TestCopyFileChoiceOptions
592 func (s *OssCopySuite) TestCopyFileChoiceOptions(c *C) {
593 destBucketName := bucketName + "-desc"
594 srcObjectName := objectNamePrefix + RandStr(8)
595 destObjectName := srcObjectName + "-dest"
596 fileName := "../sample/BingWallpaper-2015-11-07.jpg"
597 newFile := RandStr(8) + ".jpg"
599 destBucket, err := s.client.Bucket(destBucketName)
602 // Create a target bucket
603 err = s.client.CreateBucket(destBucketName)
605 // Upload source file
606 err = s.bucket.UploadFile(srcObjectName, fileName, 100*1024, Routines(3))
610 // copyfile with properties
612 ObjectACL(ACLPublicRead),
613 RequestPayer(Requester),
614 TrafficLimitHeader(1024 * 1024 * 8),
615 ObjectStorageClass(StorageArchive),
616 ServerSideEncryption("AES256"),
617 Routines(5), // without checkpoint
621 err = destBucket.CopyFile(bucketName, srcObjectName, destObjectName, 1024*100, options...)
625 meta, err := destBucket.GetObjectDetailedMeta(destObjectName)
627 c.Assert(meta.Get("X-Oss-Storage-Class"), Equals, "Archive")
628 c.Assert(meta.Get("X-Oss-Server-Side-Encryption"), Equals, "AES256")
630 aclResult, err := destBucket.GetObjectACL(destObjectName)
631 c.Assert(aclResult.ACL, Equals, "public-read")
634 err = destBucket.DeleteObject(destObjectName)
638 // Copy file with options
640 ObjectACL(ACLPublicRead),
641 RequestPayer(Requester),
642 TrafficLimitHeader(1024 * 1024 * 8),
643 ObjectStorageClass(StorageArchive),
644 ServerSideEncryption("AES256"),
646 Checkpoint(true, "copy.cp"), // with checkpoint
649 err = destBucket.CopyFile(bucketName, srcObjectName, destObjectName, 1024*100, options...)
653 meta, err = destBucket.GetObjectDetailedMeta(destObjectName)
655 c.Assert(meta.Get("X-Oss-Storage-Class"), Equals, "Archive")
656 c.Assert(meta.Get("X-Oss-Server-Side-Encryption"), Equals, "AES256")
658 aclResult, err = destBucket.GetObjectACL(destObjectName)
659 c.Assert(aclResult.ACL, Equals, "public-read")
662 err = destBucket.DeleteObject(destObjectName)
666 // Delete target bucket
667 err = s.client.DeleteBucket(destBucketName)