1package azblob_test 2 3import ( 4 "context" 5 "encoding/base64" 6 "fmt" 7 "io/ioutil" 8 "time" 9 10 "crypto/md5" 11 12 "bytes" 13 "strings" 14 15 "github.com/Azure/azure-storage-blob-go/azblob" 16 chk "gopkg.in/check.v1" // go get gopkg.in/check.v1 17) 18 19func (s *aztestsSuite) TestStageGetBlocks(c *chk.C) { 20 bsu := getBSU() 21 container, _ := createNewContainer(c, bsu) 22 defer delContainer(c, container) 23 24 blob := container.NewBlockBlobURL(generateBlobName()) 25 26 blockID := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%6d", 0))) 27 28 putResp, err := blob.StageBlock(context.Background(), blockID, getReaderToRandomBytes(1024), azblob.LeaseAccessConditions{}, nil) 29 c.Assert(err, chk.IsNil) 30 c.Assert(putResp.Response().StatusCode, chk.Equals, 201) 31 c.Assert(putResp.ContentMD5(), chk.Not(chk.Equals), "") 32 c.Assert(putResp.RequestID(), chk.Not(chk.Equals), "") 33 c.Assert(putResp.Version(), chk.Not(chk.Equals), "") 34 c.Assert(putResp.Date().IsZero(), chk.Equals, false) 35 36 blockList, err := blob.GetBlockList(context.Background(), azblob.BlockListAll, azblob.LeaseAccessConditions{}) 37 c.Assert(err, chk.IsNil) 38 c.Assert(blockList.Response().StatusCode, chk.Equals, 200) 39 c.Assert(blockList.LastModified().IsZero(), chk.Equals, true) 40 c.Assert(blockList.ETag(), chk.Equals, azblob.ETagNone) 41 c.Assert(blockList.ContentType(), chk.Not(chk.Equals), "") 42 c.Assert(blockList.BlobContentLength(), chk.Equals, int64(-1)) 43 c.Assert(blockList.RequestID(), chk.Not(chk.Equals), "") 44 c.Assert(blockList.Version(), chk.Not(chk.Equals), "") 45 c.Assert(blockList.Date().IsZero(), chk.Equals, false) 46 c.Assert(blockList.CommittedBlocks, chk.HasLen, 0) 47 c.Assert(blockList.UncommittedBlocks, chk.HasLen, 1) 48 49 listResp, err := blob.CommitBlockList(context.Background(), []string{blockID}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) 50 c.Assert(err, chk.IsNil) 51 c.Assert(listResp.Response().StatusCode, chk.Equals, 201) 52 c.Assert(listResp.LastModified().IsZero(), chk.Equals, false) 53 c.Assert(listResp.ETag(), chk.Not(chk.Equals), azblob.ETagNone) 54 c.Assert(listResp.ContentMD5(), chk.Not(chk.Equals), "") 55 c.Assert(listResp.RequestID(), chk.Not(chk.Equals), "") 56 c.Assert(listResp.Version(), chk.Not(chk.Equals), "") 57 c.Assert(listResp.Date().IsZero(), chk.Equals, false) 58 59 blockList, err = blob.GetBlockList(context.Background(), azblob.BlockListAll, azblob.LeaseAccessConditions{}) 60 c.Assert(err, chk.IsNil) 61 c.Assert(blockList.Response().StatusCode, chk.Equals, 200) 62 c.Assert(blockList.LastModified().IsZero(), chk.Equals, false) 63 c.Assert(blockList.ETag(), chk.Not(chk.Equals), azblob.ETagNone) 64 c.Assert(blockList.ContentType(), chk.Not(chk.Equals), "") 65 c.Assert(blockList.BlobContentLength(), chk.Equals, int64(1024)) 66 c.Assert(blockList.RequestID(), chk.Not(chk.Equals), "") 67 c.Assert(blockList.Version(), chk.Not(chk.Equals), "") 68 c.Assert(blockList.Date().IsZero(), chk.Equals, false) 69 c.Assert(blockList.CommittedBlocks, chk.HasLen, 1) 70 c.Assert(blockList.UncommittedBlocks, chk.HasLen, 0) 71} 72 73func (s *aztestsSuite) TestStageBlockFromURL(c *chk.C) { 74 bsu := getBSU() 75 credential, err := getGenericCredential("") 76 if err != nil { 77 c.Fatal("Invalid credential") 78 } 79 container, _ := createNewContainer(c, bsu) 80 defer delContainer(c, container) 81 82 testSize := 8 * 1024 * 1024 // 8MB 83 r, sourceData := getRandomDataAndReader(testSize) 84 ctx := context.Background() // Use default Background context 85 srcBlob := container.NewBlockBlobURL(generateBlobName()) 86 destBlob := container.NewBlockBlobURL(generateBlobName()) 87 88 // Prepare source blob for copy. 89 uploadSrcResp, err := srcBlob.Upload(ctx, r, azblob.BlobHTTPHeaders{}, azblob.Metadata{}, azblob.BlobAccessConditions{}) 90 c.Assert(err, chk.IsNil) 91 c.Assert(uploadSrcResp.Response().StatusCode, chk.Equals, 201) 92 93 // Get source blob URL with SAS for StageFromURL. 94 srcBlobParts := azblob.NewBlobURLParts(srcBlob.URL()) 95 96 srcBlobParts.SAS, err = azblob.BlobSASSignatureValues{ 97 Protocol: azblob.SASProtocolHTTPS, // Users MUST use HTTPS (not HTTP) 98 ExpiryTime: time.Now().UTC().Add(48 * time.Hour), // 48-hours before expiration 99 ContainerName: srcBlobParts.ContainerName, 100 BlobName: srcBlobParts.BlobName, 101 Permissions: azblob.BlobSASPermissions{Read: true}.String(), 102 }.NewSASQueryParameters(credential) 103 if err != nil { 104 c.Fatal(err) 105 } 106 107 srcBlobURLWithSAS := srcBlobParts.URL() 108 109 // Stage blocks from URL. 110 blockID1, blockID2 := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%6d", 0))), base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%6d", 1))) 111 stageResp1, err := destBlob.StageBlockFromURL(ctx, blockID1, srcBlobURLWithSAS, 0, 4*1024*1024, azblob.LeaseAccessConditions{}, azblob.ModifiedAccessConditions{}) 112 c.Assert(err, chk.IsNil) 113 c.Assert(stageResp1.Response().StatusCode, chk.Equals, 201) 114 c.Assert(stageResp1.ContentMD5(), chk.Not(chk.Equals), "") 115 c.Assert(stageResp1.RequestID(), chk.Not(chk.Equals), "") 116 c.Assert(stageResp1.Version(), chk.Not(chk.Equals), "") 117 c.Assert(stageResp1.Date().IsZero(), chk.Equals, false) 118 119 stageResp2, err := destBlob.StageBlockFromURL(ctx, blockID2, srcBlobURLWithSAS, 4*1024*1024, azblob.CountToEnd, azblob.LeaseAccessConditions{}, azblob.ModifiedAccessConditions{}) 120 c.Assert(err, chk.IsNil) 121 c.Assert(stageResp2.Response().StatusCode, chk.Equals, 201) 122 c.Assert(stageResp2.ContentMD5(), chk.Not(chk.Equals), "") 123 c.Assert(stageResp2.RequestID(), chk.Not(chk.Equals), "") 124 c.Assert(stageResp2.Version(), chk.Not(chk.Equals), "") 125 c.Assert(stageResp2.Date().IsZero(), chk.Equals, false) 126 127 // Check block list. 128 blockList, err := destBlob.GetBlockList(context.Background(), azblob.BlockListAll, azblob.LeaseAccessConditions{}) 129 c.Assert(err, chk.IsNil) 130 c.Assert(blockList.Response().StatusCode, chk.Equals, 200) 131 c.Assert(blockList.CommittedBlocks, chk.HasLen, 0) 132 c.Assert(blockList.UncommittedBlocks, chk.HasLen, 2) 133 134 // Commit block list. 135 listResp, err := destBlob.CommitBlockList(context.Background(), []string{blockID1, blockID2}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) 136 c.Assert(err, chk.IsNil) 137 c.Assert(listResp.Response().StatusCode, chk.Equals, 201) 138 139 // Check data integrity through downloading. 140 downloadResp, err := destBlob.BlobURL.Download(ctx, 0, azblob.CountToEnd, azblob.BlobAccessConditions{}, false) 141 c.Assert(err, chk.IsNil) 142 destData, err := ioutil.ReadAll(downloadResp.Body(azblob.RetryReaderOptions{})) 143 c.Assert(err, chk.IsNil) 144 c.Assert(destData, chk.DeepEquals, sourceData) 145} 146 147func (s *aztestsSuite) TestBlobSASQueryParamOverrideResponseHeaders(c *chk.C) { 148 bsu := getBSU() 149 credential, err := getGenericCredential("") 150 if err != nil { 151 c.Fatal("Invalid credential") 152 } 153 container, _ := createNewContainer(c, bsu) 154 defer delContainer(c, container) 155 156 testSize := 8 * 1024 * 1024 // 8MB 157 r, _ := getRandomDataAndReader(testSize) 158 ctx := context.Background() // Use default Background context 159 blob := container.NewBlockBlobURL(generateBlobName()) 160 161 uploadResp, err := blob.Upload(ctx, r, azblob.BlobHTTPHeaders{}, azblob.Metadata{}, azblob.BlobAccessConditions{}) 162 c.Assert(err, chk.IsNil) 163 c.Assert(uploadResp.Response().StatusCode, chk.Equals, 201) 164 165 // Get blob URL with SAS. 166 blobParts := azblob.NewBlobURLParts(blob.URL()) 167 168 cacheControlVal := "cache-control-override" 169 contentDispositionVal := "content-disposition-override" 170 contentEncodingVal := "content-encoding-override" 171 contentLanguageVal := "content-language-override" 172 contentTypeVal := "content-type-override" 173 174 blobParts.SAS, err = azblob.BlobSASSignatureValues{ 175 Protocol: azblob.SASProtocolHTTPS, // Users MUST use HTTPS (not HTTP) 176 ExpiryTime: time.Now().UTC().Add(48 * time.Hour), // 48-hours before expiration 177 ContainerName: blobParts.ContainerName, 178 BlobName: blobParts.BlobName, 179 Permissions: azblob.BlobSASPermissions{Read: true}.String(), 180 CacheControl: cacheControlVal, 181 ContentDisposition: contentDispositionVal, 182 ContentEncoding: contentEncodingVal, 183 ContentLanguage: contentLanguageVal, 184 ContentType: contentTypeVal, 185 }.NewSASQueryParameters(credential) 186 if err != nil { 187 c.Fatal(err) 188 } 189 190 blobURL := azblob.NewBlobURL(blobParts.URL(), azblob.NewPipeline(azblob.NewAnonymousCredential(), azblob.PipelineOptions{})) 191 192 gResp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{}) 193 c.Assert(err, chk.IsNil) 194 c.Assert(gResp.CacheControl(), chk.Equals, cacheControlVal) 195 c.Assert(gResp.ContentDisposition(), chk.Equals, contentDispositionVal) 196 c.Assert(gResp.ContentEncoding(), chk.Equals, contentEncodingVal) 197 c.Assert(gResp.ContentLanguage(), chk.Equals, contentLanguageVal) 198 c.Assert(gResp.ContentType(), chk.Equals, contentTypeVal) 199} 200 201func (s *aztestsSuite) TestStageBlockWithMD5(c *chk.C) { 202 bsu := getBSU() 203 container, _ := createNewContainer(c, bsu) 204 defer delContainer(c, container) 205 206 blob := container.NewBlockBlobURL(generateBlobName()) 207 blockID := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%6d", 0))) 208 209 // test put block with valid MD5 value 210 readerToBody, body := getRandomDataAndReader(1024) 211 md5Value := md5.Sum(body) 212 putResp, err := blob.StageBlock(context.Background(), blockID, readerToBody, azblob.LeaseAccessConditions{}, md5Value[:]) 213 c.Assert(err, chk.IsNil) 214 c.Assert(putResp.Response().StatusCode, chk.Equals, 201) 215 c.Assert(putResp.ContentMD5(), chk.DeepEquals, md5Value[:]) 216 c.Assert(putResp.RequestID(), chk.Not(chk.Equals), "") 217 c.Assert(putResp.Version(), chk.Not(chk.Equals), "") 218 c.Assert(putResp.Date().IsZero(), chk.Equals, false) 219 220 // test put block with bad MD5 value 221 readerToBody, body = getRandomDataAndReader(1024) 222 _, badMD5 := getRandomDataAndReader(16) 223 putResp, err = blob.StageBlock(context.Background(), blockID, readerToBody, azblob.LeaseAccessConditions{}, badMD5[:]) 224 validateStorageError(c, err, azblob.ServiceCodeMd5Mismatch) 225} 226 227func (s *aztestsSuite) TestBlobPutBlobNonEmptyBody(c *chk.C) { 228 bsu := getBSU() 229 containerURL, _ := createNewContainer(c, bsu) 230 defer deleteContainer(c, containerURL) 231 blobURL, _ := getBlockBlobURL(c, containerURL) 232 233 _, err := blobURL.Upload(ctx, strings.NewReader(blockBlobDefaultData), azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) 234 c.Assert(err, chk.IsNil) 235 236 resp, err := blobURL.Download(ctx, 0, 0, azblob.BlobAccessConditions{}, false) 237 c.Assert(err, chk.IsNil) 238 data, err := ioutil.ReadAll(resp.Response().Body) 239 c.Assert(string(data), chk.Equals, blockBlobDefaultData) 240} 241 242func (s *aztestsSuite) TestBlobPutBlobHTTPHeaders(c *chk.C) { 243 bsu := getBSU() 244 containerURL, _ := createNewContainer(c, bsu) 245 defer deleteContainer(c, containerURL) 246 blobURL, _ := getBlockBlobURL(c, containerURL) 247 248 _, err := blobURL.Upload(ctx, bytes.NewReader(nil), basicHeaders, nil, azblob.BlobAccessConditions{}) 249 c.Assert(err, chk.IsNil) 250 251 resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{}) 252 c.Assert(err, chk.IsNil) 253 h := resp.NewHTTPHeaders() 254 h.ContentMD5 = nil // the service generates a MD5 value, omit before comparing 255 c.Assert(h, chk.DeepEquals, basicHeaders) 256} 257 258func (s *aztestsSuite) TestBlobPutBlobMetadataNotEmpty(c *chk.C) { 259 bsu := getBSU() 260 containerURL, _ := createNewContainer(c, bsu) 261 defer deleteContainer(c, containerURL) 262 blobURL, _ := getBlockBlobURL(c, containerURL) 263 264 _, err := blobURL.Upload(ctx, bytes.NewReader(nil), azblob.BlobHTTPHeaders{}, basicMetadata, azblob.BlobAccessConditions{}) 265 c.Assert(err, chk.IsNil) 266 267 resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{}) 268 c.Assert(err, chk.IsNil) 269 c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata) 270} 271 272func (s *aztestsSuite) TestBlobPutBlobMetadataEmpty(c *chk.C) { 273 bsu := getBSU() 274 containerURL, _ := createNewContainer(c, bsu) 275 defer deleteContainer(c, containerURL) 276 blobURL, _ := getBlockBlobURL(c, containerURL) 277 278 _, err := blobURL.Upload(ctx, bytes.NewReader(nil), azblob.BlobHTTPHeaders{}, azblob.Metadata{}, azblob.BlobAccessConditions{}) 279 c.Assert(err, chk.IsNil) 280 281 resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{}) 282 c.Assert(err, chk.IsNil) 283 c.Assert(resp.NewMetadata(), chk.HasLen, 0) 284} 285 286func (s *aztestsSuite) TestBlobPutBlobMetadataInvalid(c *chk.C) { 287 bsu := getBSU() 288 containerURL, _ := createNewContainer(c, bsu) 289 defer deleteContainer(c, containerURL) 290 blobURL, _ := getBlockBlobURL(c, containerURL) 291 292 _, err := blobURL.Upload(ctx, nil, azblob.BlobHTTPHeaders{}, azblob.Metadata{"In valid!": "bar"}, azblob.BlobAccessConditions{}) 293 c.Assert(strings.Contains(err.Error(), validationErrorSubstring), chk.Equals, true) 294} 295 296func (s *aztestsSuite) TestBlobPutBlobIfModifiedSinceTrue(c *chk.C) { 297 bsu := getBSU() 298 containerURL, _ := createNewContainer(c, bsu) 299 defer deleteContainer(c, containerURL) 300 blobURL, _ := createNewBlockBlob(c, containerURL) 301 302 currentTime := getRelativeTimeGMT(-10) 303 304 _, err := blobURL.Upload(ctx, bytes.NewReader(nil), azblob.BlobHTTPHeaders{}, nil, 305 azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}}) 306 c.Assert(err, chk.IsNil) 307 308 validateUpload(c, blobURL) 309} 310 311func (s *aztestsSuite) TestBlobPutBlobIfModifiedSinceFalse(c *chk.C) { 312 bsu := getBSU() 313 containerURL, _ := createNewContainer(c, bsu) 314 defer deleteContainer(c, containerURL) 315 blobURL, _ := createNewBlockBlob(c, containerURL) 316 317 currentTime := getRelativeTimeGMT(10) 318 319 _, err := blobURL.Upload(ctx, bytes.NewReader(nil), azblob.BlobHTTPHeaders{}, nil, 320 azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}}) 321 validateStorageError(c, err, azblob.ServiceCodeConditionNotMet) 322} 323 324func (s *aztestsSuite) TestBlobPutBlobIfUnmodifiedSinceTrue(c *chk.C) { 325 bsu := getBSU() 326 containerURL, _ := createNewContainer(c, bsu) 327 defer deleteContainer(c, containerURL) 328 blobURL, _ := createNewBlockBlob(c, containerURL) 329 330 currentTime := getRelativeTimeGMT(10) 331 332 _, err := blobURL.Upload(ctx, bytes.NewReader(nil), azblob.BlobHTTPHeaders{}, nil, 333 azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}}) 334 c.Assert(err, chk.IsNil) 335 336 validateUpload(c, blobURL) 337} 338 339func (s *aztestsSuite) TestBlobPutBlobIfUnmodifiedSinceFalse(c *chk.C) { 340 bsu := getBSU() 341 containerURL, _ := createNewContainer(c, bsu) 342 defer deleteContainer(c, containerURL) 343 blobURL, _ := createNewBlockBlob(c, containerURL) 344 345 currentTime := getRelativeTimeGMT(-10) 346 347 _, err := blobURL.Upload(ctx, bytes.NewReader(nil), azblob.BlobHTTPHeaders{}, nil, 348 azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}}) 349 validateStorageError(c, err, azblob.ServiceCodeConditionNotMet) 350} 351 352func (s *aztestsSuite) TestBlobPutBlobIfMatchTrue(c *chk.C) { 353 bsu := getBSU() 354 containerURL, _ := createNewContainer(c, bsu) 355 defer deleteContainer(c, containerURL) 356 blobURL, _ := createNewBlockBlob(c, containerURL) 357 358 resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{}) 359 c.Assert(err, chk.IsNil) 360 361 _, err = blobURL.Upload(ctx, bytes.NewReader(nil), azblob.BlobHTTPHeaders{}, nil, 362 azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: resp.ETag()}}) 363 c.Assert(err, chk.IsNil) 364 365 validateUpload(c, blobURL) 366} 367 368func (s *aztestsSuite) TestBlobPutBlobIfMatchFalse(c *chk.C) { 369 bsu := getBSU() 370 containerURL, _ := createNewContainer(c, bsu) 371 defer deleteContainer(c, containerURL) 372 blobURL, _ := createNewBlockBlob(c, containerURL) 373 374 _, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{}) 375 c.Assert(err, chk.IsNil) 376 377 _, err = blobURL.Upload(ctx, bytes.NewReader(nil), azblob.BlobHTTPHeaders{}, nil, 378 azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: azblob.ETag("garbage")}}) 379 validateStorageError(c, err, azblob.ServiceCodeConditionNotMet) 380} 381 382func (s *aztestsSuite) TestBlobPutBlobIfNoneMatchTrue(c *chk.C) { 383 bsu := getBSU() 384 containerURL, _ := createNewContainer(c, bsu) 385 defer deleteContainer(c, containerURL) 386 blobURL, _ := createNewBlockBlob(c, containerURL) 387 388 _, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{}) 389 c.Assert(err, chk.IsNil) 390 391 _, err = blobURL.Upload(ctx, bytes.NewReader(nil), azblob.BlobHTTPHeaders{}, nil, 392 azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: azblob.ETag("garbage")}}) 393 c.Assert(err, chk.IsNil) 394 395 validateUpload(c, blobURL) 396} 397 398func (s *aztestsSuite) TestBlobPutBlobIfNoneMatchFalse(c *chk.C) { 399 bsu := getBSU() 400 containerURL, _ := createNewContainer(c, bsu) 401 defer deleteContainer(c, containerURL) 402 blobURL, _ := createNewBlockBlob(c, containerURL) 403 404 resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{}) 405 c.Assert(err, chk.IsNil) 406 407 _, err = blobURL.Upload(ctx, bytes.NewReader(nil), azblob.BlobHTTPHeaders{}, nil, 408 azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: resp.ETag()}}) 409 validateStorageError(c, err, azblob.ServiceCodeConditionNotMet) 410} 411 412func (s *aztestsSuite) TestBlobGetBlockListNone(c *chk.C) { 413 bsu := getBSU() 414 containerURL, _ := createNewContainer(c, bsu) 415 defer deleteContainer(c, containerURL) 416 blobURL, _ := getBlockBlobURL(c, containerURL) 417 418 _, err := blobURL.StageBlock(ctx, azblob.BlockID{0}.ToBase64(), strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil) 419 c.Assert(err, chk.IsNil) 420 421 resp, err := blobURL.GetBlockList(ctx, azblob.BlockListNone, azblob.LeaseAccessConditions{}) 422 c.Assert(err, chk.IsNil) 423 c.Assert(resp.CommittedBlocks, chk.HasLen, 0) 424 c.Assert(resp.UncommittedBlocks, chk.HasLen, 0) // Not specifying a block list type should default to only returning committed blocks 425} 426 427func (s *aztestsSuite) TestBlobGetBlockListUncommitted(c *chk.C) { 428 bsu := getBSU() 429 containerURL, _ := createNewContainer(c, bsu) 430 defer deleteContainer(c, containerURL) 431 blobURL, _ := getBlockBlobURL(c, containerURL) 432 433 _, err := blobURL.StageBlock(ctx, azblob.BlockID{0}.ToBase64(), strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil) 434 c.Assert(err, chk.IsNil) 435 436 resp, err := blobURL.GetBlockList(ctx, azblob.BlockListUncommitted, azblob.LeaseAccessConditions{}) 437 c.Assert(err, chk.IsNil) 438 c.Assert(resp.CommittedBlocks, chk.HasLen, 0) 439 c.Assert(resp.UncommittedBlocks, chk.HasLen, 1) 440} 441 442func (s *aztestsSuite) TestBlobGetBlockListCommitted(c *chk.C) { 443 bsu := getBSU() 444 containerURL, _ := createNewContainer(c, bsu) 445 defer deleteContainer(c, containerURL) 446 blobURL, _ := getBlockBlobURL(c, containerURL) 447 448 _, err := blobURL.StageBlock(ctx, azblob.BlockID{0}.ToBase64(), strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil) 449 c.Assert(err, chk.IsNil) 450 451 _, err = blobURL.CommitBlockList(ctx, []string{azblob.BlockID{0}.ToBase64()}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) 452 453 resp, err := blobURL.GetBlockList(ctx, azblob.BlockListCommitted, azblob.LeaseAccessConditions{}) 454 c.Assert(err, chk.IsNil) 455 c.Assert(resp.CommittedBlocks, chk.HasLen, 1) 456 c.Assert(resp.UncommittedBlocks, chk.HasLen, 0) 457} 458 459func (s *aztestsSuite) TestBlobGetBlockListCommittedEmpty(c *chk.C) { 460 bsu := getBSU() 461 containerURL, _ := createNewContainer(c, bsu) 462 defer deleteContainer(c, containerURL) 463 blobURL, _ := getBlockBlobURL(c, containerURL) 464 465 _, err := blobURL.StageBlock(ctx, azblob.BlockID{0}.ToBase64(), strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil) 466 c.Assert(err, chk.IsNil) 467 468 resp, err := blobURL.GetBlockList(ctx, azblob.BlockListCommitted, azblob.LeaseAccessConditions{}) 469 c.Assert(err, chk.IsNil) 470 c.Assert(resp.CommittedBlocks, chk.HasLen, 0) 471 c.Assert(resp.UncommittedBlocks, chk.HasLen, 0) 472} 473 474func (s *aztestsSuite) TestBlobGetBlockListBothEmpty(c *chk.C) { 475 bsu := getBSU() 476 containerURL, _ := createNewContainer(c, bsu) 477 defer deleteContainer(c, containerURL) 478 blobURL, _ := getBlockBlobURL(c, containerURL) 479 480 _, err := blobURL.GetBlockList(ctx, azblob.BlockListAll, azblob.LeaseAccessConditions{}) 481 validateStorageError(c, err, azblob.ServiceCodeBlobNotFound) 482} 483 484func (s *aztestsSuite) TestBlobGetBlockListBothNotEmpty(c *chk.C) { 485 bsu := getBSU() 486 containerURL, _ := createNewContainer(c, bsu) 487 defer deleteContainer(c, containerURL) 488 blobURL, _ := getBlockBlobURL(c, containerURL) 489 490 // Put and commit two blocks 491 _, err := blobURL.StageBlock(ctx, azblob.BlockID{0}.ToBase64(), strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil) 492 c.Assert(err, chk.IsNil) 493 _, err = blobURL.StageBlock(ctx, azblob.BlockID{1}.ToBase64(), strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil) 494 c.Assert(err, chk.IsNil) 495 _, err = blobURL.CommitBlockList(ctx, []string{azblob.BlockID{1}.ToBase64(), azblob.BlockID{0}.ToBase64()}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) 496 c.Assert(err, chk.IsNil) 497 498 // Put two uncommitted blocks 499 _, err = blobURL.StageBlock(ctx, azblob.BlockID{3}.ToBase64(), strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil) 500 c.Assert(err, chk.IsNil) 501 _, err = blobURL.StageBlock(ctx, azblob.BlockID{2}.ToBase64(), strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil) 502 c.Assert(err, chk.IsNil) 503 504 resp, err := blobURL.GetBlockList(ctx, azblob.BlockListAll, azblob.LeaseAccessConditions{}) 505 c.Assert(err, chk.IsNil) 506 c.Assert(resp.CommittedBlocks[0].Name, chk.Equals, azblob.BlockID{1}.ToBase64()) 507 c.Assert(resp.CommittedBlocks[1].Name, chk.Equals, azblob.BlockID{0}.ToBase64()) // Committed blocks are returned in the order they are committed (in the commit list) 508 c.Assert(resp.UncommittedBlocks[0].Name, chk.Equals, azblob.BlockID{2}.ToBase64()) // Uncommitted blocks are returned in alphabetical order 509 c.Assert(resp.UncommittedBlocks[1].Name, chk.Equals, azblob.BlockID{3}.ToBase64()) 510} 511 512func (s *aztestsSuite) TestBlobGetBlockListInvalidType(c *chk.C) { 513 bsu := getBSU() 514 containerURL, _ := createNewContainer(c, bsu) 515 defer deleteContainer(c, containerURL) 516 blobURL, _ := getBlockBlobURL(c, containerURL) 517 518 _, err := blobURL.StageBlock(ctx, azblob.BlockID{0}.ToBase64(), strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil) 519 c.Assert(err, chk.IsNil) 520 521 _, err = blobURL.GetBlockList(ctx, azblob.BlockListType("garbage"), azblob.LeaseAccessConditions{}) 522 validateStorageError(c, err, azblob.ServiceCodeInvalidQueryParameterValue) 523} 524 525func (s *aztestsSuite) TestBlobGetBlockListSnapshot(c *chk.C) { 526 bsu := getBSU() 527 containerURL, _ := createNewContainer(c, bsu) 528 defer deleteContainer(c, containerURL) 529 blobURL, _ := getBlockBlobURL(c, containerURL) 530 531 _, err := blobURL.StageBlock(ctx, azblob.BlockID{0}.ToBase64(), strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil) 532 c.Assert(err, chk.IsNil) 533 _, err = blobURL.CommitBlockList(ctx, []string{azblob.BlockID{0}.ToBase64()}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) 534 c.Assert(err, chk.IsNil) 535 536 resp, err := blobURL.CreateSnapshot(ctx, nil, azblob.BlobAccessConditions{}) 537 c.Assert(err, chk.IsNil) 538 snapshotURL := blobURL.WithSnapshot(resp.Snapshot()) 539 540 resp2, err := snapshotURL.GetBlockList(ctx, azblob.BlockListAll, azblob.LeaseAccessConditions{}) 541 c.Assert(err, chk.IsNil) 542 c.Assert(resp2.CommittedBlocks, chk.HasLen, 1) 543} 544 545func (s *aztestsSuite) TestBlobPutBlockIDInvalidCharacters(c *chk.C) { 546 bsu := getBSU() 547 containerURL, _ := createNewContainer(c, bsu) 548 defer deleteContainer(c, containerURL) 549 blobURL, _ := getBlockBlobURL(c, containerURL) 550 551 _, err := blobURL.StageBlock(ctx, "!!", strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil) 552 validateStorageError(c, err, azblob.ServiceCodeInvalidQueryParameterValue) 553} 554 555func (s *aztestsSuite) TestBlobPutBlockIDInvalidLength(c *chk.C) { 556 bsu := getBSU() 557 containerURL, _ := createNewContainer(c, bsu) 558 defer deleteContainer(c, containerURL) 559 blobURL, _ := getBlockBlobURL(c, containerURL) 560 561 _, err := blobURL.StageBlock(ctx, azblob.BlockID{0}.ToBase64(), strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil) 562 c.Assert(err, chk.IsNil) 563 _, err = blobURL.StageBlock(ctx, "00000000", strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil) 564 validateStorageError(c, err, azblob.ServiceCodeInvalidBlobOrBlock) 565} 566 567func (s *aztestsSuite) TestBlobPutBlockEmptyBody(c *chk.C) { 568 bsu := getBSU() 569 containerURL, _ := createNewContainer(c, bsu) 570 defer deleteContainer(c, containerURL) 571 blobURL, _ := getBlockBlobURL(c, containerURL) 572 573 _, err := blobURL.StageBlock(ctx, azblob.BlockID{0}.ToBase64(), strings.NewReader(""), azblob.LeaseAccessConditions{}, nil) 574 validateStorageError(c, err, azblob.ServiceCodeInvalidHeaderValue) 575} 576 577func setupPutBlockListTest(c *chk.C) (containerURL azblob.ContainerURL, blobURL azblob.BlockBlobURL, id string) { 578 bsu := getBSU() 579 containerURL, _ = createNewContainer(c, bsu) 580 blobURL, _ = getBlockBlobURL(c, containerURL) 581 id = azblob.BlockID{0}.ToBase64() 582 _, err := blobURL.StageBlock(ctx, id, strings.NewReader(blockBlobDefaultData), azblob.LeaseAccessConditions{}, nil) 583 c.Assert(err, chk.IsNil) 584 return 585} 586 587func (s *aztestsSuite) TestBlobPutBlockListInvalidID(c *chk.C) { 588 containerURL, blobURL, id := setupPutBlockListTest(c) 589 defer deleteContainer(c, containerURL) 590 591 _, err := blobURL.CommitBlockList(ctx, []string{id[:2]}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) 592 validateStorageError(c, err, azblob.ServiceCodeInvalidBlockID) 593} 594 595func (s *aztestsSuite) TestBlobPutBlockListDuplicateBlocks(c *chk.C) { 596 containerURL, blobURL, id := setupPutBlockListTest(c) 597 defer deleteContainer(c, containerURL) 598 599 _, err := blobURL.CommitBlockList(ctx, []string{id, id}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) 600 c.Assert(err, chk.IsNil) 601 602 resp, err := blobURL.GetBlockList(ctx, azblob.BlockListAll, azblob.LeaseAccessConditions{}) 603 c.Assert(err, chk.IsNil) 604 c.Assert(resp.CommittedBlocks, chk.HasLen, 2) 605} 606 607func (s *aztestsSuite) TestBlobPutBlockListEmptyList(c *chk.C) { 608 containerURL, blobURL, _ := setupPutBlockListTest(c) 609 defer deleteContainer(c, containerURL) 610 611 _, err := blobURL.CommitBlockList(ctx, []string{}, azblob.BlobHTTPHeaders{}, azblob.Metadata{}, azblob.BlobAccessConditions{}) 612 c.Assert(err, chk.IsNil) 613 614 resp, err := blobURL.GetBlockList(ctx, azblob.BlockListAll, azblob.LeaseAccessConditions{}) 615 c.Assert(err, chk.IsNil) 616 c.Assert(resp.CommittedBlocks, chk.HasLen, 0) 617} 618 619func (s *aztestsSuite) TestBlobPutBlockListMetadataEmpty(c *chk.C) { 620 containerURL, blobURL, id := setupPutBlockListTest(c) 621 defer deleteContainer(c, containerURL) 622 623 _, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, azblob.Metadata{}, azblob.BlobAccessConditions{}) 624 c.Assert(err, chk.IsNil) 625 626 resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{}) 627 c.Assert(err, chk.IsNil) 628 c.Assert(resp.NewMetadata(), chk.HasLen, 0) 629} 630 631func (s *aztestsSuite) TestBlobPutBlockListMetadataNonEmpty(c *chk.C) { 632 containerURL, blobURL, id := setupPutBlockListTest(c) 633 defer deleteContainer(c, containerURL) 634 635 _, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, basicMetadata, azblob.BlobAccessConditions{}) 636 c.Assert(err, chk.IsNil) 637 638 resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{}) 639 c.Assert(err, chk.IsNil) 640 c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata) 641} 642 643func (s *aztestsSuite) TestBlobPutBlockListHTTPHeaders(c *chk.C) { 644 containerURL, blobURL, id := setupPutBlockListTest(c) 645 defer deleteContainer(c, containerURL) 646 647 _, err := blobURL.CommitBlockList(ctx, []string{id}, basicHeaders, nil, azblob.BlobAccessConditions{}) 648 c.Assert(err, chk.IsNil) 649 650 resp, _ := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{}) 651 h := resp.NewHTTPHeaders() 652 c.Assert(h, chk.DeepEquals, basicHeaders) 653} 654 655func (s *aztestsSuite) TestBlobPutBlockListHTTPHeadersEmpty(c *chk.C) { 656 containerURL, blobURL, id := setupPutBlockListTest(c) 657 defer deleteContainer(c, containerURL) 658 659 _, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{ContentDisposition: "my_disposition"}, nil, azblob.BlobAccessConditions{}) 660 c.Assert(err, chk.IsNil) 661 662 _, err = blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) 663 c.Assert(err, chk.IsNil) 664 665 resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{}) 666 c.Assert(err, chk.IsNil) 667 c.Assert(resp.ContentDisposition(), chk.Equals, "") 668} 669 670func validateBlobCommitted(c *chk.C, blobURL azblob.BlockBlobURL) { 671 resp, err := blobURL.GetBlockList(ctx, azblob.BlockListAll, azblob.LeaseAccessConditions{}) 672 c.Assert(err, chk.IsNil) 673 c.Assert(resp.CommittedBlocks, chk.HasLen, 1) 674} 675 676func (s *aztestsSuite) TestBlobPutBlockListIfModifiedSinceTrue(c *chk.C) { 677 containerURL, blobURL, id := setupPutBlockListTest(c) 678 defer deleteContainer(c, containerURL) 679 _, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) // The blob must actually exist to have a modifed time 680 c.Assert(err, chk.IsNil) 681 682 currentTime := getRelativeTimeGMT(-10) 683 684 _, err = blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, 685 azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}}) 686 c.Assert(err, chk.IsNil) 687 688 validateBlobCommitted(c, blobURL) 689} 690 691func (s *aztestsSuite) TestBlobPutBlockListIfModifiedSinceFalse(c *chk.C) { 692 containerURL, blobURL, id := setupPutBlockListTest(c) 693 defer deleteContainer(c, containerURL) 694 695 currentTime := getRelativeTimeGMT(10) 696 697 _, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, 698 azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}}) 699 validateStorageError(c, err, azblob.ServiceCodeConditionNotMet) 700} 701 702func (s *aztestsSuite) TestBlobPutBlockListIfUnmodifiedSinceTrue(c *chk.C) { 703 containerURL, blobURL, id := setupPutBlockListTest(c) 704 defer deleteContainer(c, containerURL) 705 _, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) // The blob must actually exist to have a modifed time 706 c.Assert(err, chk.IsNil) 707 708 currentTime := getRelativeTimeGMT(10) 709 710 _, err = blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, 711 azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}}) 712 c.Assert(err, chk.IsNil) 713 714 validateBlobCommitted(c, blobURL) 715} 716 717func (s *aztestsSuite) TestBlobPutBlockListIfUnmodifiedSinceFalse(c *chk.C) { 718 containerURL, blobURL, id := setupPutBlockListTest(c) 719 blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) // The blob must actually exist to have a modifed time 720 defer deleteContainer(c, containerURL) 721 722 currentTime := getRelativeTimeGMT(-10) 723 724 _, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, 725 azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}}) 726 727 validateStorageError(c, err, azblob.ServiceCodeConditionNotMet) 728} 729 730func (s *aztestsSuite) TestBlobPutBlockListIfMatchTrue(c *chk.C) { 731 containerURL, blobURL, id := setupPutBlockListTest(c) 732 defer deleteContainer(c, containerURL) 733 resp, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) // The blob must actually exist to have a modifed time 734 c.Assert(err, chk.IsNil) 735 736 _, err = blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, 737 azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: resp.ETag()}}) 738 c.Assert(err, chk.IsNil) 739 740 validateBlobCommitted(c, blobURL) 741} 742 743func (s *aztestsSuite) TestBlobPutBlockListIfMatchFalse(c *chk.C) { 744 containerURL, blobURL, id := setupPutBlockListTest(c) 745 defer deleteContainer(c, containerURL) 746 _, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) // The blob must actually exist to have a modifed time 747 c.Assert(err, chk.IsNil) 748 749 _, err = blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, 750 azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: azblob.ETag("garbage")}}) 751 752 validateStorageError(c, err, azblob.ServiceCodeConditionNotMet) 753} 754 755func (s *aztestsSuite) TestBlobPutBlockListIfNoneMatchTrue(c *chk.C) { 756 containerURL, blobURL, id := setupPutBlockListTest(c) 757 defer deleteContainer(c, containerURL) 758 _, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) // The blob must actually exist to have a modifed time 759 c.Assert(err, chk.IsNil) 760 761 _, err = blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, 762 azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: azblob.ETag("garbage")}}) 763 c.Assert(err, chk.IsNil) 764 765 validateBlobCommitted(c, blobURL) 766} 767 768func (s *aztestsSuite) TestBlobPutBlockListIfNoneMatchFalse(c *chk.C) { 769 containerURL, blobURL, id := setupPutBlockListTest(c) 770 defer deleteContainer(c, containerURL) 771 resp, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) // The blob must actually exist to have a modifed time 772 c.Assert(err, chk.IsNil) 773 774 _, err = blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, 775 azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: resp.ETag()}}) 776 777 validateStorageError(c, err, azblob.ServiceCodeConditionNotMet) 778} 779 780func (s *aztestsSuite) TestBlobPutBlockListValidateData(c *chk.C) { 781 containerURL, blobURL, id := setupPutBlockListTest(c) 782 defer deleteContainer(c, containerURL) 783 784 _, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) 785 786 resp, err := blobURL.Download(ctx, 0, 0, azblob.BlobAccessConditions{}, false) 787 c.Assert(err, chk.IsNil) 788 data, _ := ioutil.ReadAll(resp.Response().Body) 789 c.Assert(string(data), chk.Equals, blockBlobDefaultData) 790} 791 792func (s *aztestsSuite) TestBlobPutBlockListModifyBlob(c *chk.C) { 793 containerURL, blobURL, id := setupPutBlockListTest(c) 794 defer deleteContainer(c, containerURL) 795 796 _, err := blobURL.CommitBlockList(ctx, []string{id}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) 797 c.Assert(err, chk.IsNil) 798 799 _, err = blobURL.StageBlock(ctx, "0001", bytes.NewReader([]byte("new data")), azblob.LeaseAccessConditions{}, nil) 800 c.Assert(err, chk.IsNil) 801 _, err = blobURL.StageBlock(ctx, "0010", bytes.NewReader([]byte("new data")), azblob.LeaseAccessConditions{}, nil) 802 c.Assert(err, chk.IsNil) 803 _, err = blobURL.StageBlock(ctx, "0011", bytes.NewReader([]byte("new data")), azblob.LeaseAccessConditions{}, nil) 804 c.Assert(err, chk.IsNil) 805 _, err = blobURL.StageBlock(ctx, "0100", bytes.NewReader([]byte("new data")), azblob.LeaseAccessConditions{}, nil) 806 c.Assert(err, chk.IsNil) 807 808 _, err = blobURL.CommitBlockList(ctx, []string{"0001", "0011"}, azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{}) 809 c.Assert(err, chk.IsNil) 810 811 resp, err := blobURL.GetBlockList(ctx, azblob.BlockListAll, azblob.LeaseAccessConditions{}) 812 c.Assert(err, chk.IsNil) 813 c.Assert(resp.CommittedBlocks, chk.HasLen, 2) 814 c.Assert(resp.CommittedBlocks[0].Name, chk.Equals, "0001") 815 c.Assert(resp.CommittedBlocks[1].Name, chk.Equals, "0011") 816 c.Assert(resp.UncommittedBlocks, chk.HasLen, 0) 817} 818