github.com/aliyun/aliyun-oss-go-sdk@v3.0.2+incompatible/oss/download_test.go (about)

     1  package oss
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"net/http"
     7  	"os"
     8  	"strings"
     9  	"time"
    10  
    11  	. "gopkg.in/check.v1"
    12  )
    13  
    14  type OssDownloadSuite struct {
    15  	cloudBoxControlClient *Client
    16  	client                *Client
    17  	bucket                *Bucket
    18  }
    19  
    20  var _ = Suite(&OssDownloadSuite{})
    21  
    22  // SetUpSuite runs once when the suite starts running
    23  func (s *OssDownloadSuite) SetUpSuite(c *C) {
    24  	bucketName := bucketNamePrefix + RandLowStr(6)
    25  	if cloudboxControlEndpoint == "" {
    26  		client, err := New(endpoint, accessID, accessKey)
    27  		c.Assert(err, IsNil)
    28  		s.client = client
    29  
    30  		s.client.CreateBucket(bucketName)
    31  
    32  		bucket, err := s.client.Bucket(bucketName)
    33  		c.Assert(err, IsNil)
    34  		s.bucket = bucket
    35  
    36  		testLogger.Println("test crc started")
    37  	} else {
    38  		client, err := New(cloudboxEndpoint, accessID, accessKey)
    39  		c.Assert(err, IsNil)
    40  		s.client = client
    41  
    42  		controlClient, err := New(cloudboxControlEndpoint, accessID, accessKey)
    43  		c.Assert(err, IsNil)
    44  		s.cloudBoxControlClient = controlClient
    45  		controlClient.CreateBucket(bucketName)
    46  
    47  		bucket, err := s.client.Bucket(bucketName)
    48  		c.Assert(err, IsNil)
    49  		s.bucket = bucket
    50  	}
    51  
    52  	testLogger.Println("test download started")
    53  }
    54  
    55  // TearDownSuite runs before each test or benchmark starts running
    56  func (s *OssDownloadSuite) TearDownSuite(c *C) {
    57  	// Delete part
    58  	keyMarker := KeyMarker("")
    59  	uploadIDMarker := UploadIDMarker("")
    60  	for {
    61  		lmur, err := s.bucket.ListMultipartUploads(keyMarker, uploadIDMarker)
    62  		c.Assert(err, IsNil)
    63  		for _, upload := range lmur.Uploads {
    64  			var imur = InitiateMultipartUploadResult{Bucket: s.bucket.BucketName,
    65  				Key: upload.Key, UploadID: upload.UploadID}
    66  			err = s.bucket.AbortMultipartUpload(imur)
    67  			c.Assert(err, IsNil)
    68  		}
    69  		keyMarker = KeyMarker(lmur.NextKeyMarker)
    70  		uploadIDMarker = UploadIDMarker(lmur.NextUploadIDMarker)
    71  		if !lmur.IsTruncated {
    72  			break
    73  		}
    74  	}
    75  
    76  	// Delete objects
    77  	marker := Marker("")
    78  	for {
    79  		lor, err := s.bucket.ListObjects(marker)
    80  		c.Assert(err, IsNil)
    81  		for _, object := range lor.Objects {
    82  			err = s.bucket.DeleteObject(object.Key)
    83  			c.Assert(err, IsNil)
    84  		}
    85  		marker = Marker(lor.NextMarker)
    86  		if !lor.IsTruncated {
    87  			break
    88  		}
    89  	}
    90  
    91  	// Delete bucket
    92  	if s.cloudBoxControlClient != nil {
    93  		err := s.cloudBoxControlClient.DeleteBucket(s.bucket.BucketName)
    94  		c.Assert(err, IsNil)
    95  	} else {
    96  		err := s.client.DeleteBucket(s.bucket.BucketName)
    97  		c.Assert(err, IsNil)
    98  	}
    99  
   100  	testLogger.Println("test download completed")
   101  }
   102  
   103  // SetUpTest runs after each test or benchmark runs
   104  func (s *OssDownloadSuite) SetUpTest(c *C) {
   105  	err := removeTempFiles("../oss", ".jpg")
   106  	c.Assert(err, IsNil)
   107  }
   108  
   109  // TearDownTest runs once after all tests or benchmarks have finished running
   110  func (s *OssDownloadSuite) TearDownTest(c *C) {
   111  	err := removeTempFiles("../oss", ".jpg")
   112  	c.Assert(err, IsNil)
   113  
   114  	err = removeTempFiles("../oss", ".temp")
   115  	c.Assert(err, IsNil)
   116  }
   117  
   118  // TestDownloadRoutineWithoutRecovery multipart downloads without checkpoint
   119  func (s *OssDownloadSuite) TestDownloadRoutineWithoutRecovery(c *C) {
   120  	objectName := objectNamePrefix + RandStr(8)
   121  	fileName := "../sample/BingWallpaper-2015-11-07.jpg"
   122  	newFile := RandStr(8) + ".jpg"
   123  
   124  	// Upload a file
   125  	err := s.bucket.UploadFile(objectName, fileName, 100*1024, Routines(3))
   126  	c.Assert(err, IsNil)
   127  
   128  	// Download the file by default
   129  	err = s.bucket.DownloadFile(objectName, newFile, 100*1024)
   130  	c.Assert(err, IsNil)
   131  
   132  	// Check
   133  	eq, err := compareFiles(fileName, newFile)
   134  	c.Assert(err, IsNil)
   135  	c.Assert(eq, Equals, true)
   136  
   137  	// Use 2 coroutines to download the file and total parts count is 5
   138  	os.Remove(newFile)
   139  	err = s.bucket.DownloadFile(objectName, newFile, 100*1024, Routines(2))
   140  	c.Assert(err, IsNil)
   141  
   142  	// Check
   143  	eq, err = compareFiles(fileName, newFile)
   144  	c.Assert(err, IsNil)
   145  	c.Assert(eq, Equals, true)
   146  
   147  	// Use 5 coroutines to download the file and the total parts count is 5.
   148  	os.Remove(newFile)
   149  	err = s.bucket.DownloadFile(objectName, newFile, 100*1024, Routines(5))
   150  	c.Assert(err, IsNil)
   151  
   152  	// Check
   153  	eq, err = compareFiles(fileName, newFile)
   154  	c.Assert(err, IsNil)
   155  	c.Assert(eq, Equals, true)
   156  
   157  	// Use 10 coroutines to download the file and the total parts count is 5.
   158  	os.Remove(newFile)
   159  	err = s.bucket.DownloadFile(objectName, newFile, 100*1024, Routines(10))
   160  	c.Assert(err, IsNil)
   161  
   162  	// Check
   163  	eq, err = compareFiles(fileName, newFile)
   164  	c.Assert(err, IsNil)
   165  	c.Assert(eq, Equals, true)
   166  
   167  	err = s.bucket.DeleteObject(objectName)
   168  	c.Assert(err, IsNil)
   169  }
   170  
   171  // DownErrorHooker requests hook by downloadPart
   172  func DownErrorHooker(part downloadPart) error {
   173  	if part.Index == 4 {
   174  		time.Sleep(time.Second)
   175  		return fmt.Errorf("ErrorHooker")
   176  	}
   177  	return nil
   178  }
   179  
   180  // TestDownloadRoutineWithRecovery multi-routine resumable download
   181  func (s *OssDownloadSuite) TestDownloadRoutineWithRecovery(c *C) {
   182  	objectName := objectNamePrefix + RandStr(8)
   183  	fileName := "../sample/BingWallpaper-2015-11-07.jpg"
   184  	newFile := RandStr(8) + ".jpg"
   185  
   186  	// Upload a file
   187  	err := s.bucket.UploadFile(objectName, fileName, 100*1024, Routines(3))
   188  	c.Assert(err, IsNil)
   189  
   190  	// Download a file with default checkpoint
   191  	downloadPartHooker = DownErrorHooker
   192  	err = s.bucket.DownloadFile(objectName, newFile, 100*1024, Checkpoint(true, newFile+".cp"))
   193  	c.Assert(err, NotNil)
   194  	c.Assert(err.Error(), Equals, "ErrorHooker")
   195  	downloadPartHooker = defaultDownloadPartHook
   196  
   197  	// Check
   198  	dcp := downloadCheckpoint{}
   199  	err = dcp.load(newFile + ".cp")
   200  	c.Assert(err, IsNil)
   201  	c.Assert(dcp.Magic, Equals, downloadCpMagic)
   202  	c.Assert(len(dcp.MD5), Equals, len("LC34jZU5xK4hlxi3Qn3XGQ=="))
   203  	c.Assert(dcp.FilePath, Equals, newFile)
   204  	c.Assert(dcp.ObjStat.Size, Equals, int64(482048))
   205  	c.Assert(len(dcp.ObjStat.LastModified) > 0, Equals, true)
   206  	c.Assert(dcp.ObjStat.Etag, Equals, "\"2351E662233817A7AE974D8C5B0876DD-5\"")
   207  	c.Assert(dcp.Object, Equals, objectName)
   208  	c.Assert(len(dcp.Parts), Equals, 5)
   209  	c.Assert(len(dcp.todoParts()), Equals, 1)
   210  
   211  	err = s.bucket.DownloadFile(objectName, newFile, 100*1024, Checkpoint(true, newFile+".cp"))
   212  	c.Assert(err, IsNil)
   213  	//download success, checkpoint file has been deleted
   214  	err = dcp.load(newFile + ".cp")
   215  	c.Assert(err, NotNil)
   216  
   217  	eq, err := compareFiles(fileName, newFile)
   218  	c.Assert(err, IsNil)
   219  	c.Assert(eq, Equals, true)
   220  
   221  	// Resumable download with empty checkpoint file path
   222  	downloadPartHooker = DownErrorHooker
   223  	err = s.bucket.DownloadFile(objectName, newFile, 100*1024, Checkpoint(true, ""))
   224  	c.Assert(err, NotNil)
   225  	c.Assert(err.Error(), Equals, "ErrorHooker")
   226  	downloadPartHooker = defaultDownloadPartHook
   227  
   228  	dcp = downloadCheckpoint{}
   229  	err = dcp.load(newFile + ".cp")
   230  	c.Assert(err, NotNil)
   231  
   232  	// Resumable download with checkpoint dir
   233  	os.Remove(newFile)
   234  	downloadPartHooker = DownErrorHooker
   235  	err = s.bucket.DownloadFile(objectName, newFile, 100*1024, CheckpointDir(true, "./"))
   236  	c.Assert(err, NotNil)
   237  	c.Assert(err.Error(), Equals, "ErrorHooker")
   238  	downloadPartHooker = defaultDownloadPartHook
   239  
   240  	// Check
   241  	dcp = downloadCheckpoint{}
   242  	cpConf := cpConfig{IsEnable: true, DirPath: "./"}
   243  	cpFilePath := getDownloadCpFilePath(&cpConf, s.bucket.BucketName, objectName, "", newFile)
   244  	err = dcp.load(cpFilePath)
   245  	c.Assert(err, IsNil)
   246  	c.Assert(dcp.Magic, Equals, downloadCpMagic)
   247  	c.Assert(len(dcp.MD5), Equals, len("LC34jZU5xK4hlxi3Qn3XGQ=="))
   248  	c.Assert(dcp.FilePath, Equals, newFile)
   249  	c.Assert(dcp.ObjStat.Size, Equals, int64(482048))
   250  	c.Assert(len(dcp.ObjStat.LastModified) > 0, Equals, true)
   251  	c.Assert(dcp.ObjStat.Etag, Equals, "\"2351E662233817A7AE974D8C5B0876DD-5\"")
   252  	c.Assert(dcp.Object, Equals, objectName)
   253  	c.Assert(len(dcp.Parts), Equals, 5)
   254  	c.Assert(len(dcp.todoParts()), Equals, 1)
   255  
   256  	err = s.bucket.DownloadFile(objectName, newFile, 100*1024, CheckpointDir(true, "./"))
   257  	c.Assert(err, IsNil)
   258  	//download success, checkpoint file has been deleted
   259  	err = dcp.load(cpFilePath)
   260  	c.Assert(err, NotNil)
   261  
   262  	eq, err = compareFiles(fileName, newFile)
   263  	c.Assert(err, IsNil)
   264  	c.Assert(eq, Equals, true)
   265  
   266  	// Resumable download with checkpoint at a time. No error is expected in the download procedure.
   267  	os.Remove(newFile)
   268  	err = s.bucket.DownloadFile(objectName, newFile, 100*1024, Checkpoint(true, newFile+".cp"))
   269  	c.Assert(err, IsNil)
   270  
   271  	err = dcp.load(newFile + ".cp")
   272  	c.Assert(err, NotNil)
   273  
   274  	eq, err = compareFiles(fileName, newFile)
   275  	c.Assert(err, IsNil)
   276  	c.Assert(eq, Equals, true)
   277  
   278  	// Resumable download with checkpoint at a time. No error is expected in the download procedure.
   279  	os.Remove(newFile)
   280  	err = s.bucket.DownloadFile(objectName, newFile, 100*1024, Routines(10), Checkpoint(true, newFile+".cp"))
   281  	c.Assert(err, IsNil)
   282  
   283  	err = dcp.load(newFile + ".cp")
   284  	c.Assert(err, NotNil)
   285  
   286  	eq, err = compareFiles(fileName, newFile)
   287  	c.Assert(err, IsNil)
   288  	c.Assert(eq, Equals, true)
   289  
   290  	err = s.bucket.DeleteObject(objectName)
   291  	c.Assert(err, IsNil)
   292  }
   293  
   294  // TestDownloadOption options
   295  func (s *OssDownloadSuite) TestDownloadOption(c *C) {
   296  	objectName := objectNamePrefix + RandStr(8)
   297  	fileName := "../sample/BingWallpaper-2015-11-07.jpg"
   298  	newFile := RandStr(8) + ".jpg"
   299  
   300  	// Upload the file
   301  	err := s.bucket.UploadFile(objectName, fileName, 100*1024, Routines(3))
   302  	c.Assert(err, IsNil)
   303  
   304  	meta, err := s.bucket.GetObjectDetailedMeta(objectName)
   305  	c.Assert(err, IsNil)
   306  
   307  	// IfMatch
   308  	os.Remove(newFile)
   309  	err = s.bucket.DownloadFile(objectName, newFile, 100*1024, Routines(3), IfMatch(meta.Get("Etag")))
   310  	c.Assert(err, IsNil)
   311  
   312  	eq, err := compareFiles(fileName, newFile)
   313  	c.Assert(err, IsNil)
   314  	c.Assert(eq, Equals, true)
   315  
   316  	// IfNoneMatch
   317  	os.Remove(newFile)
   318  	err = s.bucket.DownloadFile(objectName, newFile, 100*1024, Routines(3), IfNoneMatch(meta.Get("Etag")))
   319  	c.Assert(err, NotNil)
   320  
   321  	// IfMatch
   322  	err = s.bucket.DownloadFile(objectName, newFile, 100*1024, Routines(3), IfMatch(meta.Get("Etag")))
   323  	c.Assert(err, IsNil)
   324  
   325  	eq, err = compareFiles(fileName, newFile)
   326  	c.Assert(err, IsNil)
   327  	c.Assert(eq, Equals, true)
   328  
   329  	// IfNoneMatch
   330  	err = s.bucket.DownloadFile(objectName, newFile, 100*1024, Routines(3), IfNoneMatch(meta.Get("Etag")))
   331  	c.Assert(err, NotNil)
   332  }
   333  
   334  // TestDownloadObjectChange tests the file is updated during the upload
   335  func (s *OssDownloadSuite) TestDownloadObjectChange(c *C) {
   336  	objectName := objectNamePrefix + RandStr(8)
   337  	fileName := "../sample/BingWallpaper-2015-11-07.jpg"
   338  	newFile := RandStr(8) + ".jpg"
   339  
   340  	// Upload a file
   341  	err := s.bucket.UploadFile(objectName, fileName, 100*1024, Routines(3))
   342  	c.Assert(err, IsNil)
   343  
   344  	// Download with default checkpoint
   345  	downloadPartHooker = DownErrorHooker
   346  	err = s.bucket.DownloadFile(objectName, newFile, 100*1024, Checkpoint(true, newFile+".cp"))
   347  	c.Assert(err, NotNil)
   348  	c.Assert(err.Error(), Equals, "ErrorHooker")
   349  	downloadPartHooker = defaultDownloadPartHook
   350  
   351  	err = s.bucket.UploadFile(objectName, fileName, 100*1024, Routines(3))
   352  	c.Assert(err, IsNil)
   353  
   354  	err = s.bucket.DownloadFile(objectName, newFile, 100*1024, Checkpoint(true, newFile+".cp"))
   355  	c.Assert(err, IsNil)
   356  
   357  	eq, err := compareFiles(fileName, newFile)
   358  	c.Assert(err, IsNil)
   359  	c.Assert(eq, Equals, true)
   360  }
   361  
   362  // TestDownloadNegative tests downloading negative
   363  func (s *OssDownloadSuite) TestDownloadNegative(c *C) {
   364  	objectName := objectNamePrefix + RandStr(8)
   365  	fileName := "../sample/BingWallpaper-2015-11-07.jpg"
   366  	newFile := RandStr(8) + ".jpg"
   367  
   368  	// Upload a file
   369  	err := s.bucket.UploadFile(objectName, fileName, 100*1024, Routines(3))
   370  	c.Assert(err, IsNil)
   371  
   372  	// Worker routine error
   373  	downloadPartHooker = DownErrorHooker
   374  	err = s.bucket.DownloadFile(objectName, newFile, 100*1024, Routines(2))
   375  	c.Assert(err, NotNil)
   376  	c.Assert(err.Error(), Equals, "ErrorHooker")
   377  	downloadPartHooker = defaultDownloadPartHook
   378  
   379  	// Local file does not exist
   380  	err = s.bucket.DownloadFile(objectName, "/tmp/", 100*1024, Routines(2))
   381  	c.Assert(err, NotNil)
   382  
   383  	// Invalid part size
   384  	err = s.bucket.DownloadFile(objectName, newFile, 0, Routines(2))
   385  	c.Assert(err, NotNil)
   386  
   387  	err = s.bucket.DownloadFile(objectName, newFile, 1024*1024*1024*100, Routines(2))
   388  	c.Assert(err, IsNil)
   389  
   390  	err = s.bucket.DeleteObject(objectName)
   391  	c.Assert(err, IsNil)
   392  
   393  	// Local file does not exist
   394  	err = s.bucket.DownloadFile(objectName, "/tmp/", 100*1024)
   395  	c.Assert(err, NotNil)
   396  
   397  	err = s.bucket.DownloadFile(objectName, "/tmp/", 100*1024, Routines(2))
   398  	c.Assert(err, NotNil)
   399  
   400  	// Invalid part size
   401  	err = s.bucket.DownloadFile(objectName, newFile, -1)
   402  	c.Assert(err, NotNil)
   403  
   404  	err = s.bucket.DownloadFile(objectName, newFile, 0, Routines(2))
   405  	c.Assert(err, NotNil)
   406  
   407  	err = s.bucket.DownloadFile(objectName, newFile, 1024*1024*1024*100)
   408  	c.Assert(err, NotNil)
   409  
   410  	err = s.bucket.DownloadFile(objectName, newFile, 1024*1024*1024*100, Routines(2))
   411  	c.Assert(err, NotNil)
   412  }
   413  
   414  // TestDownloadWithRange tests concurrent downloading with range specified and checkpoint enabled
   415  func (s *OssDownloadSuite) TestDownloadWithRange(c *C) {
   416  	objectName := objectNamePrefix + RandStr(8)
   417  	fileName := "../sample/BingWallpaper-2015-11-07.jpg"
   418  	newFile := RandStr(8) + ".jpg"
   419  	newFileGet := RandStr(8) + "-.jpg"
   420  
   421  	// Upload a file
   422  	err := s.bucket.UploadFile(objectName, fileName, 100*1024, Routines(3))
   423  	c.Assert(err, IsNil)
   424  
   425  	fileSize, err := getFileSize(fileName)
   426  	c.Assert(err, IsNil)
   427  
   428  	// Download with range, from 1024 to 4096
   429  	os.Remove(newFile)
   430  	err = s.bucket.DownloadFile(objectName, newFile, 100*1024, Routines(3), Range(1024, 4095))
   431  	c.Assert(err, IsNil)
   432  
   433  	// Check
   434  	eq, err := compareFilesWithRange(fileName, 1024, newFile, 0, 3072)
   435  	c.Assert(err, IsNil)
   436  	c.Assert(eq, Equals, true)
   437  
   438  	os.Remove(newFileGet)
   439  	err = s.bucket.GetObjectToFile(objectName, newFileGet, Range(1024, 4095))
   440  	c.Assert(err, IsNil)
   441  
   442  	// Compare get and download
   443  	eq, err = compareFiles(newFile, newFileGet)
   444  	c.Assert(err, IsNil)
   445  	c.Assert(eq, Equals, true)
   446  
   447  	// Download with range, from 1024 to 4096
   448  	os.Remove(newFile)
   449  	err = s.bucket.DownloadFile(objectName, newFile, 1024, Routines(3), NormalizedRange("1024-4095"))
   450  	c.Assert(err, IsNil)
   451  
   452  	// Check
   453  	eq, err = compareFilesWithRange(fileName, 1024, newFile, 0, 3072)
   454  	c.Assert(err, IsNil)
   455  	c.Assert(eq, Equals, true)
   456  
   457  	os.Remove(newFileGet)
   458  	err = s.bucket.GetObjectToFile(objectName, newFileGet, NormalizedRange("1024-4095"))
   459  	c.Assert(err, IsNil)
   460  
   461  	// Compare get and download
   462  	eq, err = compareFiles(newFile, newFileGet)
   463  	c.Assert(err, IsNil)
   464  	c.Assert(eq, Equals, true)
   465  
   466  	// Download with range, from 2048 to the end
   467  	os.Remove(newFile)
   468  	err = s.bucket.DownloadFile(objectName, newFile, 1024*1024, Routines(3), NormalizedRange("2048-"))
   469  	c.Assert(err, IsNil)
   470  
   471  	// Check
   472  	eq, err = compareFilesWithRange(fileName, 2048, newFile, 0, fileSize-2048)
   473  	c.Assert(err, IsNil)
   474  	c.Assert(eq, Equals, true)
   475  
   476  	os.Remove(newFileGet)
   477  	err = s.bucket.GetObjectToFile(objectName, newFileGet, NormalizedRange("2048-"))
   478  	c.Assert(err, IsNil)
   479  
   480  	// Compare get and download
   481  	eq, err = compareFiles(newFile, newFileGet)
   482  	c.Assert(err, IsNil)
   483  	c.Assert(eq, Equals, true)
   484  
   485  	// Download with range, the last 4096
   486  	os.Remove(newFile)
   487  	err = s.bucket.DownloadFile(objectName, newFile, 1024, Routines(3), NormalizedRange("-4096"))
   488  	c.Assert(err, IsNil)
   489  
   490  	// Check
   491  	eq, err = compareFilesWithRange(fileName, fileSize-4096, newFile, 0, 4096)
   492  	c.Assert(err, IsNil)
   493  	c.Assert(eq, Equals, true)
   494  
   495  	os.Remove(newFileGet)
   496  	err = s.bucket.GetObjectToFile(objectName, newFileGet, NormalizedRange("-4096"))
   497  	c.Assert(err, IsNil)
   498  
   499  	// Compare get and download
   500  	eq, err = compareFiles(newFile, newFileGet)
   501  	c.Assert(err, IsNil)
   502  	c.Assert(eq, Equals, true)
   503  
   504  	err = s.bucket.DeleteObject(objectName)
   505  	c.Assert(err, IsNil)
   506  }
   507  
   508  // TestDownloadWithCheckoutAndRange tests concurrent downloading with range specified and checkpoint enabled
   509  func (s *OssDownloadSuite) TestDownloadWithCheckoutAndRange(c *C) {
   510  	objectName := objectNamePrefix + RandStr(8)
   511  	fileName := "../sample/BingWallpaper-2015-11-07.jpg"
   512  	newFile := RandStr(8) + ".jpg"
   513  	newFileGet := RandStr(8) + "-get.jpg"
   514  
   515  	// Upload a file
   516  	err := s.bucket.UploadFile(objectName, fileName, 100*1024, Routines(3), Checkpoint(true, fileName+".cp"))
   517  	c.Assert(err, IsNil)
   518  
   519  	fileSize, err := getFileSize(fileName)
   520  	c.Assert(err, IsNil)
   521  
   522  	// Download with range, from 1024 to 4096
   523  	os.Remove(newFile)
   524  	err = s.bucket.DownloadFile(objectName, newFile, 100*1024, Routines(3), Checkpoint(true, newFile+".cp"), Range(1024, 4095))
   525  	c.Assert(err, IsNil)
   526  
   527  	// Check
   528  	eq, err := compareFilesWithRange(fileName, 1024, newFile, 0, 3072)
   529  	c.Assert(err, IsNil)
   530  	c.Assert(eq, Equals, true)
   531  
   532  	os.Remove(newFileGet)
   533  	err = s.bucket.GetObjectToFile(objectName, newFileGet, Range(1024, 4095))
   534  	c.Assert(err, IsNil)
   535  
   536  	// Compare get and download
   537  	eq, err = compareFiles(newFile, newFileGet)
   538  	c.Assert(err, IsNil)
   539  	c.Assert(eq, Equals, true)
   540  
   541  	// Download with range, from 1024 to 4096
   542  	os.Remove(newFile)
   543  	err = s.bucket.DownloadFile(objectName, newFile, 1024, Routines(3), Checkpoint(true, newFile+".cp"), NormalizedRange("1024-4095"))
   544  	c.Assert(err, IsNil)
   545  
   546  	// Check
   547  	eq, err = compareFilesWithRange(fileName, 1024, newFile, 0, 3072)
   548  	c.Assert(err, IsNil)
   549  	c.Assert(eq, Equals, true)
   550  
   551  	os.Remove(newFileGet)
   552  	err = s.bucket.GetObjectToFile(objectName, newFileGet, NormalizedRange("1024-4095"))
   553  	c.Assert(err, IsNil)
   554  
   555  	// Compare get and download
   556  	eq, err = compareFiles(newFile, newFileGet)
   557  	c.Assert(err, IsNil)
   558  	c.Assert(eq, Equals, true)
   559  
   560  	// Download with range, from 2048 to the end
   561  	os.Remove(newFile)
   562  	err = s.bucket.DownloadFile(objectName, newFile, 1024*1024, Routines(3), Checkpoint(true, newFile+".cp"), NormalizedRange("2048-"))
   563  	c.Assert(err, IsNil)
   564  
   565  	// Check
   566  	eq, err = compareFilesWithRange(fileName, 2048, newFile, 0, fileSize-2048)
   567  	c.Assert(err, IsNil)
   568  	c.Assert(eq, Equals, true)
   569  
   570  	os.Remove(newFileGet)
   571  	err = s.bucket.GetObjectToFile(objectName, newFileGet, NormalizedRange("2048-"))
   572  	c.Assert(err, IsNil)
   573  
   574  	// Compare get and download
   575  	eq, err = compareFiles(newFile, newFileGet)
   576  	c.Assert(err, IsNil)
   577  	c.Assert(eq, Equals, true)
   578  
   579  	// Download with range, the last 4096 bytes
   580  	os.Remove(newFile)
   581  	err = s.bucket.DownloadFile(objectName, newFile, 1024, Routines(3), Checkpoint(true, newFile+".cp"), NormalizedRange("-4096"))
   582  	c.Assert(err, IsNil)
   583  
   584  	// Check
   585  	eq, err = compareFilesWithRange(fileName, fileSize-4096, newFile, 0, 4096)
   586  	c.Assert(err, IsNil)
   587  	c.Assert(eq, Equals, true)
   588  
   589  	os.Remove(newFileGet)
   590  	err = s.bucket.GetObjectToFile(objectName, newFileGet, NormalizedRange("-4096"))
   591  	c.Assert(err, IsNil)
   592  
   593  	// Compare get and download
   594  	eq, err = compareFiles(newFile, newFileGet)
   595  	c.Assert(err, IsNil)
   596  	c.Assert(eq, Equals, true)
   597  
   598  	err = s.bucket.DeleteObject(objectName)
   599  	c.Assert(err, IsNil)
   600  }
   601  
   602  // TestCombineCRCInDownloadParts tests combineCRCInParts
   603  func (s *OssDownloadSuite) TestCombineCRCInDownloadParts(c *C) {
   604  	crc := combineCRCInParts(nil)
   605  	c.Assert(crc == 0, Equals, true)
   606  
   607  	crc = combineCRCInParts(make([]downloadPart, 0))
   608  	c.Assert(crc == 0, Equals, true)
   609  
   610  	parts := make([]downloadPart, 1)
   611  	parts[0].CRC64 = 10278880121275185425
   612  	crc = combineCRCInParts(parts)
   613  	c.Assert(crc == 10278880121275185425, Equals, true)
   614  
   615  	parts = make([]downloadPart, 2)
   616  	parts[0].CRC64 = 6748440630437108969
   617  	parts[0].Start = 0
   618  	parts[0].End = 4
   619  	parts[1].CRC64 = 10278880121275185425
   620  	parts[1].Start = 5
   621  	parts[1].End = 8
   622  	crc = combineCRCInParts(parts)
   623  	c.Assert(crc == 11051210869376104954, Equals, true)
   624  }
   625  
   626  func getFileSize(fileName string) (int64, error) {
   627  	file, err := os.Open(fileName)
   628  	if err != nil {
   629  		return 0, err
   630  	}
   631  	defer file.Close()
   632  
   633  	stat, err := file.Stat()
   634  	if err != nil {
   635  		return 0, err
   636  	}
   637  
   638  	return stat.Size(), nil
   639  }
   640  
   641  // compareFilesWithRange compares the content between fileL and fileR with specified range
   642  func compareFilesWithRange(fileL string, offsetL int64, fileR string, offsetR int64, size int64) (bool, error) {
   643  	finL, err := os.Open(fileL)
   644  	if err != nil {
   645  		return false, err
   646  	}
   647  	defer finL.Close()
   648  	finL.Seek(offsetL, os.SEEK_SET)
   649  
   650  	finR, err := os.Open(fileR)
   651  	if err != nil {
   652  		return false, err
   653  	}
   654  	defer finR.Close()
   655  	finR.Seek(offsetR, os.SEEK_SET)
   656  
   657  	statL, err := finL.Stat()
   658  	if err != nil {
   659  		return false, err
   660  	}
   661  
   662  	statR, err := finR.Stat()
   663  	if err != nil {
   664  		return false, err
   665  	}
   666  
   667  	if (offsetL+size > statL.Size()) || (offsetR+size > statR.Size()) {
   668  		return false, nil
   669  	}
   670  
   671  	part := statL.Size() - offsetL
   672  	if part > 16*1024 {
   673  		part = 16 * 1024
   674  	}
   675  
   676  	bufL := make([]byte, part)
   677  	bufR := make([]byte, part)
   678  	for readN := int64(0); readN < size; {
   679  		n, _ := finL.Read(bufL)
   680  		if 0 == n {
   681  			break
   682  		}
   683  
   684  		n, _ = finR.Read(bufR)
   685  		if 0 == n {
   686  			break
   687  		}
   688  
   689  		tailer := part
   690  		if tailer > size-readN {
   691  			tailer = size - readN
   692  		}
   693  		readN += tailer
   694  
   695  		if !bytes.Equal(bufL[0:tailer], bufR[0:tailer]) {
   696  			return false, nil
   697  		}
   698  	}
   699  
   700  	return true, nil
   701  }
   702  
   703  func (s *OssDownloadSuite) TestVersioningDownloadWithoutCheckPoint(c *C) {
   704  	// create a bucket with default proprety
   705  	client, err := New(endpoint, accessID, accessKey)
   706  	c.Assert(err, IsNil)
   707  
   708  	bucketName := bucketNamePrefix + RandLowStr(6)
   709  	err = client.CreateBucket(bucketName)
   710  	c.Assert(err, IsNil)
   711  
   712  	bucket, err := client.Bucket(bucketName)
   713  
   714  	// put bucket version:enabled
   715  	var versioningConfig VersioningConfig
   716  	versioningConfig.Status = string(VersionEnabled)
   717  	err = client.SetBucketVersioning(bucketName, versioningConfig)
   718  	c.Assert(err, IsNil)
   719  	time.Sleep(timeoutInOperation)
   720  
   721  	// begin test
   722  	objectName := objectNamePrefix + RandStr(8)
   723  	fileName := "test-file-" + RandStr(8)
   724  	fileData := RandStr(500 * 1024)
   725  	CreateFile(fileName, fileData, c)
   726  
   727  	newFile := RandStr(8) + ".jpg"
   728  	newFileGet := RandStr(8) + "-.jpg"
   729  
   730  	// Upload a file
   731  	var respHeader http.Header
   732  	options := []Option{Routines(3), GetResponseHeader(&respHeader)}
   733  	err = bucket.UploadFile(objectName, fileName, 100*1024, options...)
   734  	c.Assert(err, IsNil)
   735  	versionId := GetVersionId(respHeader)
   736  	c.Assert(len(versionId) > 0, Equals, true)
   737  
   738  	fileSize, err := getFileSize(fileName)
   739  	c.Assert(err, IsNil)
   740  
   741  	// overwrite emtpy object
   742  	err = bucket.PutObject(objectName, strings.NewReader(""))
   743  	c.Assert(err, IsNil)
   744  
   745  	// Download with range, from 1024 to 4096
   746  	os.Remove(newFile)
   747  	options = []Option{Routines(3), Range(1024, 4095), VersionId(versionId)}
   748  	err = bucket.DownloadFile(objectName, newFile, 100*1024, options...)
   749  	c.Assert(err, IsNil)
   750  
   751  	// Check
   752  	eq, err := compareFilesWithRange(fileName, 1024, newFile, 0, 3072)
   753  	c.Assert(err, IsNil)
   754  	c.Assert(eq, Equals, true)
   755  
   756  	os.Remove(newFileGet)
   757  	options = []Option{Range(1024, 4095), VersionId(versionId)}
   758  	err = bucket.GetObjectToFile(objectName, newFileGet, options...)
   759  	c.Assert(err, IsNil)
   760  
   761  	// Compare get and download
   762  	eq, err = compareFiles(newFile, newFileGet)
   763  	c.Assert(err, IsNil)
   764  	c.Assert(eq, Equals, true)
   765  
   766  	// Download with range, from 1024 to 4096
   767  	os.Remove(newFile)
   768  	options = []Option{Routines(3), NormalizedRange("1024-4095"), VersionId(versionId)}
   769  	err = bucket.DownloadFile(objectName, newFile, 1024, options...)
   770  	c.Assert(err, IsNil)
   771  
   772  	// Check
   773  	eq, err = compareFilesWithRange(fileName, 1024, newFile, 0, 3072)
   774  	c.Assert(err, IsNil)
   775  	c.Assert(eq, Equals, true)
   776  
   777  	os.Remove(newFileGet)
   778  	options = []Option{NormalizedRange("1024-4095"), VersionId(versionId)}
   779  	err = bucket.GetObjectToFile(objectName, newFileGet, options...)
   780  	c.Assert(err, IsNil)
   781  
   782  	// Compare get and download
   783  	eq, err = compareFiles(newFile, newFileGet)
   784  	c.Assert(err, IsNil)
   785  	c.Assert(eq, Equals, true)
   786  
   787  	// Download with range, from 2048 to the end
   788  	os.Remove(newFile)
   789  	options = []Option{NormalizedRange("2048-"), VersionId(versionId)}
   790  	err = bucket.DownloadFile(objectName, newFile, 1024*1024, options...)
   791  	c.Assert(err, IsNil)
   792  
   793  	// Check
   794  	eq, err = compareFilesWithRange(fileName, 2048, newFile, 0, fileSize-2048)
   795  	c.Assert(err, IsNil)
   796  	c.Assert(eq, Equals, true)
   797  
   798  	os.Remove(newFileGet)
   799  	options = []Option{NormalizedRange("2048-"), VersionId(versionId)}
   800  	err = bucket.GetObjectToFile(objectName, newFileGet, options...)
   801  	c.Assert(err, IsNil)
   802  
   803  	// Compare get and download
   804  	eq, err = compareFiles(newFile, newFileGet)
   805  	c.Assert(err, IsNil)
   806  	c.Assert(eq, Equals, true)
   807  
   808  	// Download with range, the last 4096
   809  	os.Remove(newFile)
   810  	options = []Option{Routines(3), NormalizedRange("-4096"), VersionId(versionId)}
   811  	err = bucket.DownloadFile(objectName, newFile, 1024, options...)
   812  	c.Assert(err, IsNil)
   813  
   814  	// Check
   815  	eq, err = compareFilesWithRange(fileName, fileSize-4096, newFile, 0, 4096)
   816  	c.Assert(err, IsNil)
   817  	c.Assert(eq, Equals, true)
   818  
   819  	os.Remove(newFileGet)
   820  	options = []Option{NormalizedRange("-4096"), VersionId(versionId)}
   821  	err = bucket.GetObjectToFile(objectName, newFileGet, options...)
   822  	c.Assert(err, IsNil)
   823  
   824  	// Compare get and download
   825  	eq, err = compareFiles(newFile, newFileGet)
   826  	c.Assert(err, IsNil)
   827  	c.Assert(eq, Equals, true)
   828  
   829  	// download whole file
   830  	os.Remove(newFileGet)
   831  	options = []Option{Routines(3), VersionId(versionId)}
   832  	err = bucket.GetObjectToFile(objectName, newFileGet, options...)
   833  	c.Assert(err, IsNil)
   834  
   835  	// Compare get and download
   836  	eq, err = compareFiles(fileName, newFileGet)
   837  	c.Assert(err, IsNil)
   838  	c.Assert(eq, Equals, true)
   839  
   840  	os.Remove(fileName)
   841  	os.Remove(newFileGet)
   842  	err = bucket.DeleteObject(objectName)
   843  	c.Assert(err, IsNil)
   844  	ForceDeleteBucket(client, bucketName, c)
   845  }
   846  
   847  func (s *OssDownloadSuite) TestVersioningDownloadWithCheckPoint(c *C) {
   848  	// create a bucket with default proprety
   849  	client, err := New(endpoint, accessID, accessKey)
   850  	c.Assert(err, IsNil)
   851  
   852  	bucketName := bucketNamePrefix + RandLowStr(6)
   853  	err = client.CreateBucket(bucketName)
   854  	c.Assert(err, IsNil)
   855  
   856  	bucket, err := client.Bucket(bucketName)
   857  
   858  	// put bucket version:enabled
   859  	var versioningConfig VersioningConfig
   860  	versioningConfig.Status = string(VersionEnabled)
   861  	err = client.SetBucketVersioning(bucketName, versioningConfig)
   862  	c.Assert(err, IsNil)
   863  	time.Sleep(timeoutInOperation)
   864  
   865  	// begin test
   866  	objectName := objectNamePrefix + RandStr(8)
   867  	fileName := "test-file-" + RandStr(8)
   868  	fileData := RandStr(500 * 1024)
   869  	CreateFile(fileName, fileData, c)
   870  	newFile := RandStr(8) + ".jpg"
   871  
   872  	// Upload a file
   873  	var respHeader http.Header
   874  	options := []Option{Routines(3), GetResponseHeader(&respHeader)}
   875  	err = bucket.UploadFile(objectName, fileName, 100*1024, options...)
   876  	c.Assert(err, IsNil)
   877  	versionId := GetVersionId(respHeader)
   878  	c.Assert(len(versionId) > 0, Equals, true)
   879  
   880  	// Resumable download with checkpoint dir
   881  	os.Remove(newFile)
   882  	downloadPartHooker = DownErrorHooker
   883  	options = []Option{CheckpointDir(true, "./"), VersionId(versionId)}
   884  
   885  	strPayer := getPayer(options)
   886  	c.Assert(strPayer, Equals, "")
   887  
   888  	err = bucket.DownloadFile(objectName, newFile, 100*1024, options...)
   889  	c.Assert(err, NotNil)
   890  	c.Assert(err.Error(), Equals, "ErrorHooker")
   891  
   892  	// download again
   893  	downloadPartHooker = defaultDownloadPartHook
   894  	options = []Option{CheckpointDir(true, "./"), VersionId(versionId), GetResponseHeader(&respHeader)}
   895  	err = bucket.DownloadFile(objectName, newFile, 100*1024, options...)
   896  	c.Assert(err, IsNil)
   897  	c.Assert(GetVersionId(respHeader), Equals, versionId)
   898  
   899  	eq, err := compareFiles(fileName, newFile)
   900  	c.Assert(err, IsNil)
   901  	c.Assert(eq, Equals, true)
   902  
   903  	os.Remove(fileName)
   904  	os.Remove(newFile)
   905  	err = bucket.DeleteObject(objectName)
   906  	c.Assert(err, IsNil)
   907  	ForceDeleteBucket(client, bucketName, c)
   908  }
   909  
   910  func (s *OssDownloadSuite) TestdownloadFileChoiceOptions(c *C) {
   911  	// create a bucket with default proprety
   912  	client, err := New(endpoint, accessID, accessKey)
   913  	c.Assert(err, IsNil)
   914  
   915  	bucketName := bucketNamePrefix + RandLowStr(6)
   916  	err = client.CreateBucket(bucketName)
   917  	c.Assert(err, IsNil)
   918  
   919  	bucket, err := client.Bucket(bucketName)
   920  
   921  	// begin test
   922  	objectName := objectNamePrefix + RandStr(8)
   923  	fileName := "test-file-" + RandStr(8)
   924  	fileData := RandStr(500 * 1024)
   925  	CreateFile(fileName, fileData, c)
   926  	newFile := RandStr(8) + ".jpg"
   927  
   928  	// Upload a file
   929  	var respHeader http.Header
   930  	options := []Option{Routines(3), GetResponseHeader(&respHeader)}
   931  	err = bucket.UploadFile(objectName, fileName, 100*1024, options...)
   932  	c.Assert(err, IsNil)
   933  
   934  	// Resumable download with checkpoint dir
   935  	os.Remove(newFile)
   936  
   937  	// downloadFile with properties
   938  	options = []Option{
   939  		ObjectACL(ACLPublicRead),
   940  		RequestPayer(Requester),
   941  		TrafficLimitHeader(1024 * 1024 * 8),
   942  	}
   943  
   944  	err = bucket.DownloadFile(objectName, newFile, 100*1024, options...)
   945  	c.Assert(err, IsNil)
   946  
   947  	eq, err := compareFiles(fileName, newFile)
   948  	c.Assert(err, IsNil)
   949  	c.Assert(eq, Equals, true)
   950  
   951  	os.Remove(fileName)
   952  	os.Remove(newFile)
   953  	err = bucket.DeleteObject(objectName)
   954  	c.Assert(err, IsNil)
   955  	ForceDeleteBucket(client, bucketName, c)
   956  }
   957  
   958  func (s *OssDownloadSuite) TestdownloadFileWithCpChoiceOptions(c *C) {
   959  	// create a bucket with default proprety
   960  	client, err := New(endpoint, accessID, accessKey)
   961  	c.Assert(err, IsNil)
   962  
   963  	bucketName := bucketNamePrefix + RandLowStr(6)
   964  	err = client.CreateBucket(bucketName)
   965  	c.Assert(err, IsNil)
   966  
   967  	bucket, err := client.Bucket(bucketName)
   968  
   969  	// begin test
   970  	objectName := objectNamePrefix + RandStr(8)
   971  	fileName := "test-file-" + RandStr(8)
   972  	fileData := RandStr(500 * 1024)
   973  	CreateFile(fileName, fileData, c)
   974  	newFile := RandStr(8) + ".jpg"
   975  
   976  	// Upload a file
   977  	var respHeader http.Header
   978  	options := []Option{Routines(3), GetResponseHeader(&respHeader)}
   979  	err = bucket.UploadFile(objectName, fileName, 100*1024, options...)
   980  	c.Assert(err, IsNil)
   981  
   982  	// Resumable download with checkpoint dir
   983  	os.Remove(newFile)
   984  
   985  	// DownloadFile with properties
   986  	options = []Option{
   987  		ObjectACL(ACLPublicRead),
   988  		RequestPayer(Requester),
   989  		TrafficLimitHeader(1024 * 1024 * 8),
   990  		CheckpointDir(true, "./"),
   991  	}
   992  
   993  	err = bucket.DownloadFile(objectName, newFile, 100*1024, options...)
   994  	c.Assert(err, IsNil)
   995  
   996  	eq, err := compareFiles(fileName, newFile)
   997  	c.Assert(err, IsNil)
   998  	c.Assert(eq, Equals, true)
   999  
  1000  	os.Remove(fileName)
  1001  	os.Remove(newFile)
  1002  	err = bucket.DeleteObject(objectName)
  1003  	c.Assert(err, IsNil)
  1004  	ForceDeleteBucket(client, bucketName, c)
  1005  }