upload_test.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. package oss
  2. import (
  3. "fmt"
  4. "io"
  5. "os"
  6. "time"
  7. . "gopkg.in/check.v1"
  8. )
  9. type OssUploadSuite struct {
  10. client *Client
  11. bucket *Bucket
  12. }
  13. var _ = Suite(&OssUploadSuite{})
  14. // SetUpSuite runs once when the suite starts running
  15. func (s *OssUploadSuite) SetUpSuite(c *C) {
  16. client, err := New(endpoint, accessID, accessKey)
  17. c.Assert(err, IsNil)
  18. s.client = client
  19. s.client.CreateBucket(bucketName)
  20. bucket, err := s.client.Bucket(bucketName)
  21. c.Assert(err, IsNil)
  22. s.bucket = bucket
  23. testLogger.Println("test upload started")
  24. }
  25. // TearDownSuite runs before each test or benchmark starts running
  26. func (s *OssUploadSuite) TearDownSuite(c *C) {
  27. // Delete part
  28. keyMarker := KeyMarker("")
  29. uploadIDMarker := UploadIDMarker("")
  30. for {
  31. lmur, err := s.bucket.ListMultipartUploads(keyMarker, uploadIDMarker)
  32. c.Assert(err, IsNil)
  33. for _, upload := range lmur.Uploads {
  34. var imur = InitiateMultipartUploadResult{Bucket: s.bucket.BucketName,
  35. Key: upload.Key, UploadID: upload.UploadID}
  36. err = s.bucket.AbortMultipartUpload(imur)
  37. c.Assert(err, IsNil)
  38. }
  39. keyMarker = KeyMarker(lmur.NextKeyMarker)
  40. uploadIDMarker = UploadIDMarker(lmur.NextUploadIDMarker)
  41. if !lmur.IsTruncated {
  42. break
  43. }
  44. }
  45. // Delete objects
  46. marker := Marker("")
  47. for {
  48. lor, err := s.bucket.ListObjects(marker)
  49. c.Assert(err, IsNil)
  50. for _, object := range lor.Objects {
  51. err = s.bucket.DeleteObject(object.Key)
  52. c.Assert(err, IsNil)
  53. }
  54. marker = Marker(lor.NextMarker)
  55. if !lor.IsTruncated {
  56. break
  57. }
  58. }
  59. // Delete bucket
  60. err := s.client.DeleteBucket(s.bucket.BucketName)
  61. c.Assert(err, IsNil)
  62. testLogger.Println("test upload completed")
  63. }
  64. // SetUpTest runs after each test or benchmark runs
  65. func (s *OssUploadSuite) SetUpTest(c *C) {
  66. err := removeTempFiles("../oss", ".jpg")
  67. c.Assert(err, IsNil)
  68. }
  69. // TearDownTest runs once after all tests or benchmarks have finished running
  70. func (s *OssUploadSuite) TearDownTest(c *C) {
  71. err := removeTempFiles("../oss", ".jpg")
  72. c.Assert(err, IsNil)
  73. }
  74. // TestUploadRoutineWithoutRecovery tests multiroutineed upload without checkpoint
  75. func (s *OssUploadSuite) TestUploadRoutineWithoutRecovery(c *C) {
  76. objectName := objectNamePrefix + randStr(8)
  77. fileName := "../sample/BingWallpaper-2015-11-07.jpg"
  78. newFile := randStr(8) + ".jpg"
  79. // Routines is not specified, by default single routine
  80. err := s.bucket.UploadFile(objectName, fileName, 100*1024)
  81. c.Assert(err, IsNil)
  82. os.Remove(newFile)
  83. err = s.bucket.GetObjectToFile(objectName, newFile)
  84. c.Assert(err, IsNil)
  85. eq, err := compareFiles(fileName, newFile)
  86. c.Assert(err, IsNil)
  87. c.Assert(eq, Equals, true)
  88. err = s.bucket.DeleteObject(objectName)
  89. c.Assert(err, IsNil)
  90. // Specify routine count as 1
  91. err = s.bucket.UploadFile(objectName, fileName, 100*1024, Routines(1))
  92. c.Assert(err, IsNil)
  93. os.Remove(newFile)
  94. err = s.bucket.GetObjectToFile(objectName, newFile)
  95. c.Assert(err, IsNil)
  96. eq, err = compareFiles(fileName, newFile)
  97. c.Assert(err, IsNil)
  98. c.Assert(eq, Equals, true)
  99. err = s.bucket.DeleteObject(objectName)
  100. c.Assert(err, IsNil)
  101. // Specify routine count as 3, which is smaller than parts count 5
  102. err = s.bucket.UploadFile(objectName, fileName, 100*1024, Routines(3))
  103. c.Assert(err, IsNil)
  104. os.Remove(newFile)
  105. err = s.bucket.GetObjectToFile(objectName, newFile)
  106. c.Assert(err, IsNil)
  107. eq, err = compareFiles(fileName, newFile)
  108. c.Assert(err, IsNil)
  109. c.Assert(eq, Equals, true)
  110. err = s.bucket.DeleteObject(objectName)
  111. c.Assert(err, IsNil)
  112. // Specify routine count as 5, which is same as the part count 5
  113. err = s.bucket.UploadFile(objectName, fileName, 100*1024, Routines(5))
  114. c.Assert(err, IsNil)
  115. os.Remove(newFile)
  116. err = s.bucket.GetObjectToFile(objectName, newFile)
  117. c.Assert(err, IsNil)
  118. eq, err = compareFiles(fileName, newFile)
  119. c.Assert(err, IsNil)
  120. c.Assert(eq, Equals, true)
  121. err = s.bucket.DeleteObject(objectName)
  122. c.Assert(err, IsNil)
  123. // Specify routine count as 10, which is bigger than the part count 5.
  124. err = s.bucket.UploadFile(objectName, fileName, 100*1024, Routines(10))
  125. c.Assert(err, IsNil)
  126. os.Remove(newFile)
  127. err = s.bucket.GetObjectToFile(objectName, newFile)
  128. c.Assert(err, IsNil)
  129. eq, err = compareFiles(fileName, newFile)
  130. c.Assert(err, IsNil)
  131. c.Assert(eq, Equals, true)
  132. err = s.bucket.DeleteObject(objectName)
  133. c.Assert(err, IsNil)
  134. // Invalid routine count, it will use 1 automatically.
  135. err = s.bucket.UploadFile(objectName, fileName, 100*1024, Routines(0))
  136. os.Remove(newFile)
  137. err = s.bucket.GetObjectToFile(objectName, newFile)
  138. c.Assert(err, IsNil)
  139. eq, err = compareFiles(fileName, newFile)
  140. c.Assert(err, IsNil)
  141. c.Assert(eq, Equals, true)
  142. err = s.bucket.DeleteObject(objectName)
  143. c.Assert(err, IsNil)
  144. // Invalid routine count, it will use 1 automatically
  145. err = s.bucket.UploadFile(objectName, fileName, 100*1024, Routines(-1))
  146. os.Remove(newFile)
  147. err = s.bucket.GetObjectToFile(objectName, newFile)
  148. c.Assert(err, IsNil)
  149. eq, err = compareFiles(fileName, newFile)
  150. c.Assert(err, IsNil)
  151. c.Assert(eq, Equals, true)
  152. err = s.bucket.DeleteObject(objectName)
  153. c.Assert(err, IsNil)
  154. // Option
  155. err = s.bucket.UploadFile(objectName, fileName, 100*1024, Routines(3), Meta("myprop", "mypropval"))
  156. meta, err := s.bucket.GetObjectDetailedMeta(objectName)
  157. c.Assert(err, IsNil)
  158. c.Assert(meta.Get("X-Oss-Meta-Myprop"), Equals, "mypropval")
  159. os.Remove(newFile)
  160. err = s.bucket.GetObjectToFile(objectName, newFile)
  161. c.Assert(err, IsNil)
  162. eq, err = compareFiles(fileName, newFile)
  163. c.Assert(err, IsNil)
  164. c.Assert(eq, Equals, true)
  165. err = s.bucket.DeleteObject(objectName)
  166. c.Assert(err, IsNil)
  167. }
  168. // ErrorHooker is a UploadPart hook---it will fail the 5th part's upload.
  169. func ErrorHooker(id int, chunk FileChunk) error {
  170. if chunk.Number == 5 {
  171. time.Sleep(time.Second)
  172. return fmt.Errorf("ErrorHooker")
  173. }
  174. return nil
  175. }
  176. // TestUploadRoutineWithoutRecoveryNegative is multiroutineed upload without checkpoint
  177. func (s *OssUploadSuite) TestUploadRoutineWithoutRecoveryNegative(c *C) {
  178. objectName := objectNamePrefix + randStr(8)
  179. fileName := "../sample/BingWallpaper-2015-11-07.jpg"
  180. uploadPartHooker = ErrorHooker
  181. // Worker routine error
  182. err := s.bucket.UploadFile(objectName, fileName, 100*1024, Routines(2))
  183. c.Assert(err, NotNil)
  184. c.Assert(err.Error(), Equals, "ErrorHooker")
  185. uploadPartHooker = defaultUploadPart
  186. // Local file does not exist
  187. err = s.bucket.UploadFile(objectName, "NotExist", 100*1024, Routines(2))
  188. c.Assert(err, NotNil)
  189. // The part size is invalid
  190. err = s.bucket.UploadFile(objectName, fileName, 1024, Routines(2))
  191. c.Assert(err, NotNil)
  192. err = s.bucket.UploadFile(objectName, fileName, 1024*1024*1024*100, Routines(2))
  193. c.Assert(err, NotNil)
  194. }
  195. // TestUploadRoutineWithRecovery is multi-routine upload with resumable recovery
  196. func (s *OssUploadSuite) TestUploadRoutineWithRecovery(c *C) {
  197. objectName := objectNamePrefix + randStr(8)
  198. fileName := "../sample/BingWallpaper-2015-11-07.jpg"
  199. newFile := "upload-new-file-2.jpg"
  200. // Use default routines and default CP file path (fileName+.cp)
  201. // First upload for 4 parts
  202. uploadPartHooker = ErrorHooker
  203. err := s.bucket.UploadFile(objectName, fileName, 100*1024, Checkpoint(true, fileName+".cp"))
  204. c.Assert(err, NotNil)
  205. c.Assert(err.Error(), Equals, "ErrorHooker")
  206. uploadPartHooker = defaultUploadPart
  207. // Check CP
  208. ucp := uploadCheckpoint{}
  209. err = ucp.load(fileName + ".cp")
  210. c.Assert(err, IsNil)
  211. c.Assert(ucp.Magic, Equals, uploadCpMagic)
  212. c.Assert(len(ucp.MD5), Equals, len("LC34jZU5xK4hlxi3Qn3XGQ=="))
  213. c.Assert(ucp.FilePath, Equals, fileName)
  214. c.Assert(ucp.FileStat.Size, Equals, int64(482048))
  215. c.Assert(len(ucp.FileStat.LastModified.String()) > 0, Equals, true)
  216. c.Assert(ucp.FileStat.MD5, Equals, "")
  217. c.Assert(ucp.ObjectKey, Equals, objectName)
  218. c.Assert(len(ucp.UploadID), Equals, len("3F79722737D1469980DACEDCA325BB52"))
  219. c.Assert(len(ucp.Parts), Equals, 5)
  220. c.Assert(len(ucp.todoParts()), Equals, 1)
  221. c.Assert(len(ucp.allParts()), Equals, 5)
  222. // Second upload, finish the remaining part
  223. err = s.bucket.UploadFile(objectName, fileName, 100*1024, Checkpoint(true, fileName+".cp"))
  224. c.Assert(err, IsNil)
  225. os.Remove(newFile)
  226. err = s.bucket.GetObjectToFile(objectName, newFile)
  227. c.Assert(err, IsNil)
  228. eq, err := compareFiles(fileName, newFile)
  229. c.Assert(err, IsNil)
  230. c.Assert(eq, Equals, true)
  231. err = s.bucket.DeleteObject(objectName)
  232. c.Assert(err, IsNil)
  233. err = ucp.load(fileName + ".cp")
  234. c.Assert(err, NotNil)
  235. // Resumable upload with empty checkpoint path
  236. uploadPartHooker = ErrorHooker
  237. err = s.bucket.UploadFile(objectName, fileName, 100*1024, Routines(3), CheckpointDir(true, ""))
  238. c.Assert(err, NotNil)
  239. c.Assert(err.Error(), Equals, "ErrorHooker")
  240. uploadPartHooker = defaultUploadPart
  241. ucp = uploadCheckpoint{}
  242. err = ucp.load(fileName + ".cp")
  243. c.Assert(err, NotNil)
  244. // Resumable upload with checkpoint dir
  245. uploadPartHooker = ErrorHooker
  246. err = s.bucket.UploadFile(objectName, fileName, 100*1024, Routines(3), CheckpointDir(true, "./"))
  247. c.Assert(err, NotNil)
  248. c.Assert(err.Error(), Equals, "ErrorHooker")
  249. uploadPartHooker = defaultUploadPart
  250. // Check CP
  251. ucp = uploadCheckpoint{}
  252. cpConf := cpConfig{IsEnable: true, DirPath: "./"}
  253. cpFilePath := getUploadCpFilePath(&cpConf, fileName, s.bucket.BucketName, objectName)
  254. err = ucp.load(cpFilePath)
  255. c.Assert(err, IsNil)
  256. c.Assert(ucp.Magic, Equals, uploadCpMagic)
  257. c.Assert(len(ucp.MD5), Equals, len("LC34jZU5xK4hlxi3Qn3XGQ=="))
  258. c.Assert(ucp.FilePath, Equals, fileName)
  259. c.Assert(ucp.FileStat.Size, Equals, int64(482048))
  260. c.Assert(len(ucp.FileStat.LastModified.String()) > 0, Equals, true)
  261. c.Assert(ucp.FileStat.MD5, Equals, "")
  262. c.Assert(ucp.ObjectKey, Equals, objectName)
  263. c.Assert(len(ucp.UploadID), Equals, len("3F79722737D1469980DACEDCA325BB52"))
  264. c.Assert(len(ucp.Parts), Equals, 5)
  265. c.Assert(len(ucp.todoParts()), Equals, 1)
  266. c.Assert(len(ucp.allParts()), Equals, 5)
  267. err = s.bucket.UploadFile(objectName, fileName, 100*1024, Routines(3), CheckpointDir(true, "./"))
  268. c.Assert(err, IsNil)
  269. os.Remove(newFile)
  270. err = s.bucket.GetObjectToFile(objectName, newFile)
  271. c.Assert(err, IsNil)
  272. eq, err = compareFiles(fileName, newFile)
  273. c.Assert(err, IsNil)
  274. c.Assert(eq, Equals, true)
  275. err = s.bucket.DeleteObject(objectName)
  276. c.Assert(err, IsNil)
  277. err = ucp.load(cpFilePath)
  278. c.Assert(err, NotNil)
  279. // Upload all 5 parts without error
  280. err = s.bucket.UploadFile(objectName, fileName, 100*1024, Routines(3), Checkpoint(true, objectName+".cp"))
  281. c.Assert(err, IsNil)
  282. os.Remove(newFile)
  283. err = s.bucket.GetObjectToFile(objectName, newFile)
  284. c.Assert(err, IsNil)
  285. eq, err = compareFiles(fileName, newFile)
  286. c.Assert(err, IsNil)
  287. c.Assert(eq, Equals, true)
  288. err = s.bucket.DeleteObject(objectName)
  289. c.Assert(err, IsNil)
  290. // Upload all 5 parts with 10 routines without error
  291. err = s.bucket.UploadFile(objectName, fileName, 100*1024, Routines(10), Checkpoint(true, objectName+".cp"))
  292. c.Assert(err, IsNil)
  293. os.Remove(newFile)
  294. err = s.bucket.GetObjectToFile(objectName, newFile)
  295. c.Assert(err, IsNil)
  296. eq, err = compareFiles(fileName, newFile)
  297. c.Assert(err, IsNil)
  298. c.Assert(eq, Equals, true)
  299. err = s.bucket.DeleteObject(objectName)
  300. c.Assert(err, IsNil)
  301. // Option
  302. err = s.bucket.UploadFile(objectName, fileName, 100*1024, Routines(3), Checkpoint(true, objectName+".cp"), Meta("myprop", "mypropval"))
  303. meta, err := s.bucket.GetObjectDetailedMeta(objectName)
  304. c.Assert(err, IsNil)
  305. c.Assert(meta.Get("X-Oss-Meta-Myprop"), Equals, "mypropval")
  306. os.Remove(newFile)
  307. err = s.bucket.GetObjectToFile(objectName, newFile)
  308. c.Assert(err, IsNil)
  309. eq, err = compareFiles(fileName, newFile)
  310. c.Assert(err, IsNil)
  311. c.Assert(eq, Equals, true)
  312. err = s.bucket.DeleteObject(objectName)
  313. c.Assert(err, IsNil)
  314. }
  315. // TestUploadRoutineWithRecoveryNegative is multiroutineed upload without checkpoint
  316. func (s *OssUploadSuite) TestUploadRoutineWithRecoveryNegative(c *C) {
  317. objectName := objectNamePrefix + randStr(8)
  318. fileName := "../sample/BingWallpaper-2015-11-07.jpg"
  319. // The local file does not exist
  320. err := s.bucket.UploadFile(objectName, "NotExist", 100*1024, Checkpoint(true, "NotExist.cp"))
  321. c.Assert(err, NotNil)
  322. err = s.bucket.UploadFile(objectName, "NotExist", 100*1024, Routines(2), Checkpoint(true, "NotExist.cp"))
  323. c.Assert(err, NotNil)
  324. // Specified part size is invalid
  325. err = s.bucket.UploadFile(objectName, fileName, 1024, Checkpoint(true, fileName+".cp"))
  326. c.Assert(err, NotNil)
  327. err = s.bucket.UploadFile(objectName, fileName, 1024, Routines(2), Checkpoint(true, fileName+".cp"))
  328. c.Assert(err, NotNil)
  329. err = s.bucket.UploadFile(objectName, fileName, 1024*1024*1024*100, Checkpoint(true, fileName+".cp"))
  330. c.Assert(err, NotNil)
  331. err = s.bucket.UploadFile(objectName, fileName, 1024*1024*1024*100, Routines(2), Checkpoint(true, fileName+".cp"))
  332. c.Assert(err, NotNil)
  333. }
  334. // TestUploadLocalFileChange tests the file is updated while being uploaded
  335. func (s *OssUploadSuite) TestUploadLocalFileChange(c *C) {
  336. objectName := objectNamePrefix + randStr(8)
  337. fileName := "../sample/BingWallpaper-2015-11-07.jpg"
  338. localFile := randStr(8) + ".jpg"
  339. newFile := randStr(8) + ".jpg"
  340. os.Remove(localFile)
  341. err := copyFile(fileName, localFile)
  342. c.Assert(err, IsNil)
  343. // First upload for 4 parts
  344. uploadPartHooker = ErrorHooker
  345. err = s.bucket.UploadFile(objectName, localFile, 100*1024, Checkpoint(true, localFile+".cp"))
  346. c.Assert(err, NotNil)
  347. c.Assert(err.Error(), Equals, "ErrorHooker")
  348. uploadPartHooker = defaultUploadPart
  349. os.Remove(localFile)
  350. err = copyFile(fileName, localFile)
  351. c.Assert(err, IsNil)
  352. // Updating the file. The second upload will re-upload all 5 parts.
  353. err = s.bucket.UploadFile(objectName, localFile, 100*1024, Checkpoint(true, localFile+".cp"))
  354. c.Assert(err, IsNil)
  355. os.Remove(newFile)
  356. err = s.bucket.GetObjectToFile(objectName, newFile)
  357. c.Assert(err, IsNil)
  358. eq, err := compareFiles(fileName, newFile)
  359. c.Assert(err, IsNil)
  360. c.Assert(eq, Equals, true)
  361. err = s.bucket.DeleteObject(objectName)
  362. c.Assert(err, IsNil)
  363. }
  364. func copyFile(src, dst string) error {
  365. srcFile, err := os.Open(src)
  366. if err != nil {
  367. return err
  368. }
  369. defer srcFile.Close()
  370. dstFile, err := os.Create(dst)
  371. if err != nil {
  372. return err
  373. }
  374. defer dstFile.Close()
  375. _, err = io.Copy(dstFile, srcFile)
  376. return err
  377. }