1package azblob 2 3import ( 4 "bytes" 5 "context" 6 "errors" 7 "os" 8 "strconv" 9 "strings" 10 "time" 11 12 chk "gopkg.in/check.v1" // go get gopkg.in/check.v1 13) 14 15func delContainer(c *chk.C, container ContainerURL) { 16 resp, err := container.Delete(context.Background(), ContainerAccessConditions{}) 17 c.Assert(err, chk.IsNil) 18 c.Assert(resp.Response().StatusCode, chk.Equals, 202) 19} 20 21func (s *aztestsSuite) TestNewContainerURLValidName(c *chk.C) { 22 bsu := getBSU() 23 testURL := bsu.NewContainerURL(containerPrefix) 24 25 correctURL := "https://" + os.Getenv("ACCOUNT_NAME") + ".blob.core.windows.net/" + containerPrefix 26 temp := testURL.URL() 27 c.Assert(temp.String(), chk.Equals, correctURL) 28} 29 30func (s *aztestsSuite) TestCreateRootContainerURL(c *chk.C) { 31 bsu := getBSU() 32 testURL := bsu.NewContainerURL(ContainerNameRoot) 33 34 correctURL := "https://" + os.Getenv("ACCOUNT_NAME") + ".blob.core.windows.net/$root" 35 temp := testURL.URL() 36 c.Assert(temp.String(), chk.Equals, correctURL) 37} 38 39func (s *aztestsSuite) TestAccountWithPipeline(c *chk.C) { 40 bsu := getBSU() 41 bsu = bsu.WithPipeline(testPipeline{}) // testPipeline returns an identifying message as an error 42 containerURL := bsu.NewContainerURL("name") 43 44 _, err := containerURL.Create(ctx, Metadata{}, PublicAccessBlob) 45 46 c.Assert(err.Error(), chk.Equals, testPipelineMessage) 47} 48 49func (s *aztestsSuite) TestContainerCreateInvalidName(c *chk.C) { 50 bsu := getBSU() 51 containerURL := bsu.NewContainerURL("foo bar") 52 53 _, err := containerURL.Create(ctx, Metadata{}, PublicAccessBlob) 54 55 validateStorageError(c, err, ServiceCodeInvalidResourceName) 56} 57 58func (s *aztestsSuite) TestContainerCreateEmptyName(c *chk.C) { 59 bsu := getBSU() 60 containerURL := bsu.NewContainerURL("") 61 62 _, err := containerURL.Create(ctx, Metadata{}, PublicAccessBlob) 63 64 validateStorageError(c, err, ServiceCodeInvalidQueryParameterValue) 65} 66 67func (s *aztestsSuite) TestContainerCreateNameCollision(c *chk.C) { 68 bsu := getBSU() 69 containerURL, containerName := createNewContainer(c, bsu) 70 71 defer deleteContainer(c, containerURL) 72 73 containerURL = bsu.NewContainerURL(containerName) 74 _, err := containerURL.Create(ctx, Metadata{}, PublicAccessBlob) 75 76 validateStorageError(c, err, ServiceCodeContainerAlreadyExists) 77} 78 79func (s *aztestsSuite) TestContainerCreateInvalidMetadata(c *chk.C) { 80 bsu := getBSU() 81 containerURL, _ := getContainerURL(c, bsu) 82 83 _, err := containerURL.Create(ctx, Metadata{"1 foo": "bar"}, PublicAccessBlob) 84 85 c.Assert(err, chk.NotNil) 86 c.Assert(strings.Contains(err.Error(), invalidHeaderErrorSubstring), chk.Equals, true) 87} 88 89func (s *aztestsSuite) TestContainerCreateNilMetadata(c *chk.C) { 90 bsu := getBSU() 91 containerURL, _ := getContainerURL(c, bsu) 92 93 _, err := containerURL.Create(ctx, nil, PublicAccessBlob) 94 defer deleteContainer(c, containerURL) 95 c.Assert(err, chk.IsNil) 96 97 response, err := containerURL.GetProperties(ctx, LeaseAccessConditions{}) 98 c.Assert(err, chk.IsNil) 99 c.Assert(response.NewMetadata(), chk.HasLen, 0) 100} 101 102func (s *aztestsSuite) TestContainerCreateEmptyMetadata(c *chk.C) { 103 bsu := getBSU() 104 containerURL, _ := getContainerURL(c, bsu) 105 106 _, err := containerURL.Create(ctx, Metadata{}, PublicAccessBlob) 107 defer deleteContainer(c, containerURL) 108 c.Assert(err, chk.IsNil) 109 110 response, err := containerURL.GetProperties(ctx, LeaseAccessConditions{}) 111 c.Assert(err, chk.IsNil) 112 c.Assert(response.NewMetadata(), chk.HasLen, 0) 113} 114 115// Note that for all tests that create blobs, deleting the container also deletes any blobs within that container, thus we 116// simply delete the whole container after the test 117 118func (s *aztestsSuite) TestContainerCreateAccessContainer(c *chk.C) { 119 bsu := getBSU() 120 containerURL, _ := getContainerURL(c, bsu) 121 122 _, err := containerURL.Create(ctx, nil, PublicAccessContainer) 123 defer deleteContainer(c, containerURL) 124 c.Assert(err, chk.IsNil) 125 126 blobURL := containerURL.NewBlockBlobURL(blobPrefix) 127 blobURL.Upload(ctx, bytes.NewReader([]byte("Content")), BlobHTTPHeaders{}, basicMetadata, BlobAccessConditions{}, DefaultAccessTier, nil, ClientProvidedKeyOptions{}) 128 129 // Anonymous enumeration should be valid with container access 130 containerURL2 := NewContainerURL(containerURL.URL(), NewPipeline(NewAnonymousCredential(), PipelineOptions{})) 131 response, err := containerURL2.ListBlobsFlatSegment(ctx, Marker{}, 132 ListBlobsSegmentOptions{}) 133 c.Assert(err, chk.IsNil) 134 c.Assert(response.Segment.BlobItems[0].Name, chk.Equals, blobPrefix) 135 136 // Getting blob data anonymously should still be valid with container access 137 blobURL2 := containerURL2.NewBlockBlobURL(blobPrefix) 138 resp, err := blobURL2.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{}) 139 c.Assert(err, chk.IsNil) 140 c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata) 141} 142 143func (s *aztestsSuite) TestContainerCreateAccessBlob(c *chk.C) { 144 bsu := getBSU() 145 containerURL, _ := getContainerURL(c, bsu) 146 147 _, err := containerURL.Create(ctx, nil, PublicAccessBlob) 148 defer deleteContainer(c, containerURL) 149 c.Assert(err, chk.IsNil) 150 151 blobURL := containerURL.NewBlockBlobURL(blobPrefix) 152 blobURL.Upload(ctx, bytes.NewReader([]byte("Content")), BlobHTTPHeaders{}, basicMetadata, BlobAccessConditions{}, DefaultAccessTier, nil, ClientProvidedKeyOptions{}) 153 154 // Reference the same container URL but with anonymous credentials 155 containerURL2 := NewContainerURL(containerURL.URL(), NewPipeline(NewAnonymousCredential(), PipelineOptions{})) 156 _, err = containerURL2.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{}) 157 validateStorageError(c, err, ServiceCodeNoAuthenticationInformation) // Listing blobs is not publicly accessible 158 159 // Accessing blob specific data should be public 160 blobURL2 := containerURL2.NewBlockBlobURL(blobPrefix) 161 resp, err := blobURL2.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{}) 162 c.Assert(err, chk.IsNil) 163 c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata) 164} 165 166func (s *aztestsSuite) TestContainerCreateAccessNone(c *chk.C) { 167 bsu := getBSU() 168 containerURL, _ := getContainerURL(c, bsu) 169 170 _, err := containerURL.Create(ctx, nil, PublicAccessNone) 171 defer deleteContainer(c, containerURL) 172 173 blobURL := containerURL.NewBlockBlobURL(blobPrefix) 174 blobURL.Upload(ctx, bytes.NewReader([]byte("Content")), BlobHTTPHeaders{}, basicMetadata, BlobAccessConditions{}, DefaultAccessTier, nil, ClientProvidedKeyOptions{}) 175 176 // Reference the same container URL but with anonymous credentials 177 containerURL2 := NewContainerURL(containerURL.URL(), NewPipeline(NewAnonymousCredential(), PipelineOptions{})) 178 // Listing blobs is not public 179 _, err = containerURL2.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{}) 180 validateStorageError(c, err, ServiceCodeNoAuthenticationInformation) 181 182 // Blob data is not public 183 blobURL2 := containerURL2.NewBlockBlobURL(blobPrefix) 184 _, err = blobURL2.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{}) 185 c.Assert(err, chk.NotNil) 186 serr := err.(StorageError) 187 c.Assert(serr.Response().StatusCode, chk.Equals, 401) // HEAD request does not return a status code 188} 189 190func validateContainerDeleted(c *chk.C, containerURL ContainerURL) { 191 _, err := containerURL.GetAccessPolicy(ctx, LeaseAccessConditions{}) 192 validateStorageError(c, err, ServiceCodeContainerNotFound) 193} 194 195func (s *aztestsSuite) TestContainerDelete(c *chk.C) { 196 bsu := getBSU() 197 containerURL, _ := createNewContainer(c, bsu) 198 199 _, err := containerURL.Delete(ctx, ContainerAccessConditions{}) 200 c.Assert(err, chk.IsNil) 201 202 validateContainerDeleted(c, containerURL) 203} 204 205func (s *aztestsSuite) TestContainerDeleteNonExistant(c *chk.C) { 206 bsu := getBSU() 207 containerURL, _ := getContainerURL(c, bsu) 208 209 _, err := containerURL.Delete(ctx, ContainerAccessConditions{}) 210 validateStorageError(c, err, ServiceCodeContainerNotFound) 211} 212 213func (s *aztestsSuite) TestContainerDeleteIfModifiedSinceTrue(c *chk.C) { 214 currentTime := getRelativeTimeGMT(-10) // Ensure the requests occur at different times 215 bsu := getBSU() 216 containerURL, _ := createNewContainer(c, bsu) 217 218 _, err := containerURL.Delete(ctx, 219 ContainerAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}}) 220 c.Assert(err, chk.IsNil) 221 validateContainerDeleted(c, containerURL) 222} 223 224func (s *aztestsSuite) TestContainerDeleteIfModifiedSinceFalse(c *chk.C) { 225 bsu := getBSU() 226 containerURL, _ := createNewContainer(c, bsu) 227 228 defer deleteContainer(c, containerURL) 229 230 currentTime := getRelativeTimeGMT(10) 231 232 _, err := containerURL.Delete(ctx, 233 ContainerAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}}) 234 validateStorageError(c, err, ServiceCodeConditionNotMet) 235} 236 237func (s *aztestsSuite) TestContainerDeleteIfUnModifiedSinceTrue(c *chk.C) { 238 bsu := getBSU() 239 containerURL, _ := createNewContainer(c, bsu) 240 241 currentTime := getRelativeTimeGMT(10) 242 _, err := containerURL.Delete(ctx, 243 ContainerAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}}) 244 c.Assert(err, chk.IsNil) 245 246 validateContainerDeleted(c, containerURL) 247} 248 249func (s *aztestsSuite) TestContainerDeleteIfUnModifiedSinceFalse(c *chk.C) { 250 currentTime := getRelativeTimeGMT(-10) // Ensure the requests occur at different times 251 252 bsu := getBSU() 253 containerURL, _ := createNewContainer(c, bsu) 254 255 defer deleteContainer(c, containerURL) 256 257 _, err := containerURL.Delete(ctx, 258 ContainerAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}}) 259 validateStorageError(c, err, ServiceCodeConditionNotMet) 260} 261 262func (s *aztestsSuite) TestContainerAccessConditionsUnsupportedConditions(c *chk.C) { 263 // This test defines that the library will panic if the user specifies conditional headers 264 // that will be ignored by the service 265 bsu := getBSU() 266 containerURL, _ := createNewContainer(c, bsu) 267 defer deleteContainer(c, containerURL) 268 269 invalidEtag := ETag("invalid") 270 _, err := containerURL.SetMetadata(ctx, basicMetadata, 271 ContainerAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: invalidEtag}}) 272 c.Assert(err, chk.Not(chk.Equals), nil) 273} 274 275func (s *aztestsSuite) TestContainerListBlobsNonexistantPrefix(c *chk.C) { 276 bsu := getBSU() 277 containerURL, _ := createNewContainer(c, bsu) 278 defer deleteContainer(c, containerURL) 279 createNewBlockBlob(c, containerURL) 280 281 resp, err := containerURL.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{Prefix: blobPrefix + blobPrefix}) 282 283 c.Assert(err, chk.IsNil) 284 c.Assert(resp.Segment.BlobItems, chk.HasLen, 0) 285} 286 287func (s *aztestsSuite) TestContainerListBlobsSpecificValidPrefix(c *chk.C) { 288 bsu := getBSU() 289 containerURL, _ := createNewContainer(c, bsu) 290 defer deleteContainer(c, containerURL) 291 _, blobName := createNewBlockBlob(c, containerURL) 292 293 resp, err := containerURL.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{Prefix: blobPrefix}) 294 295 c.Assert(err, chk.IsNil) 296 c.Assert(resp.Segment.BlobItems, chk.HasLen, 1) 297 c.Assert(resp.Segment.BlobItems[0].Name, chk.Equals, blobName) 298} 299 300func (s *aztestsSuite) TestContainerListBlobsValidDelimiter(c *chk.C) { 301 bsu := getBSU() 302 containerURL, _ := createNewContainer(c, bsu) 303 defer deleteContainer(c, containerURL) 304 createBlockBlobWithPrefix(c, containerURL, "a/1") 305 createBlockBlobWithPrefix(c, containerURL, "a/2") 306 createBlockBlobWithPrefix(c, containerURL, "b/1") 307 _, blobName := createBlockBlobWithPrefix(c, containerURL, "blob") 308 309 resp, err := containerURL.ListBlobsHierarchySegment(ctx, Marker{}, "/", ListBlobsSegmentOptions{}) 310 311 c.Assert(err, chk.IsNil) 312 c.Assert(len(resp.Segment.BlobItems), chk.Equals, 1) 313 c.Assert(len(resp.Segment.BlobPrefixes), chk.Equals, 2) 314 c.Assert(resp.Segment.BlobPrefixes[0].Name, chk.Equals, "a/") 315 c.Assert(resp.Segment.BlobPrefixes[1].Name, chk.Equals, "b/") 316 c.Assert(resp.Segment.BlobItems[0].Name, chk.Equals, blobName) 317} 318 319func (s *aztestsSuite) TestContainerListBlobsWithSnapshots(c *chk.C) { 320 bsu := getBSU() 321 containerURL, _ := createNewContainer(c, bsu) 322 defer deleteContainer(c, containerURL) 323 324 _, err := containerURL.ListBlobsHierarchySegment(ctx, Marker{}, "/", ListBlobsSegmentOptions{Details: BlobListingDetails{Snapshots: true}}) 325 c.Assert(err, chk.Not(chk.Equals), nil) 326} 327 328func (s *aztestsSuite) TestContainerListBlobsInvalidDelimiter(c *chk.C) { 329 bsu := getBSU() 330 containerURL, _ := createNewContainer(c, bsu) 331 defer deleteContainer(c, containerURL) 332 createBlockBlobWithPrefix(c, containerURL, "a/1") 333 createBlockBlobWithPrefix(c, containerURL, "a/2") 334 createBlockBlobWithPrefix(c, containerURL, "b/1") 335 createBlockBlobWithPrefix(c, containerURL, "blob") 336 337 resp, err := containerURL.ListBlobsHierarchySegment(ctx, Marker{}, "^", ListBlobsSegmentOptions{}) 338 339 c.Assert(err, chk.IsNil) 340 c.Assert(resp.Segment.BlobItems, chk.HasLen, 4) 341} 342 343func (s *aztestsSuite) TestContainerListBlobsIncludeTypeMetadata(c *chk.C) { 344 bsu := getBSU() 345 container, _ := createNewContainer(c, bsu) 346 defer deleteContainer(c, container) 347 _, blobNameNoMetadata := createBlockBlobWithPrefix(c, container, "a") 348 blobMetadata, blobNameMetadata := createBlockBlobWithPrefix(c, container, "b") 349 _, err := blobMetadata.SetMetadata(ctx, Metadata{"field": "value"}, BlobAccessConditions{}, ClientProvidedKeyOptions{}) 350 c.Assert(err, chk.IsNil) 351 352 resp, err := container.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{Details: BlobListingDetails{Metadata: true}}) 353 354 c.Assert(err, chk.IsNil) 355 c.Assert(resp.Segment.BlobItems[0].Name, chk.Equals, blobNameNoMetadata) 356 c.Assert(resp.Segment.BlobItems[0].Metadata, chk.HasLen, 0) 357 c.Assert(resp.Segment.BlobItems[1].Name, chk.Equals, blobNameMetadata) 358 c.Assert(resp.Segment.BlobItems[1].Metadata["field"], chk.Equals, "value") 359} 360 361func (s *aztestsSuite) TestContainerListBlobsIncludeTypeSnapshots(c *chk.C) { 362 bsu := getBSU() 363 containerURL, _ := createNewContainer(c, bsu) 364 defer deleteContainer(c, containerURL) 365 blob, blobName := createNewBlockBlob(c, containerURL) 366 _, err := blob.CreateSnapshot(ctx, Metadata{}, BlobAccessConditions{}, ClientProvidedKeyOptions{}) 367 c.Assert(err, chk.IsNil) 368 369 resp, err := containerURL.ListBlobsFlatSegment(ctx, Marker{}, 370 ListBlobsSegmentOptions{Details: BlobListingDetails{Snapshots: true}}) 371 372 c.Assert(err, chk.IsNil) 373 c.Assert(resp.Segment.BlobItems, chk.HasLen, 2) 374 c.Assert(resp.Segment.BlobItems[0].Name, chk.Equals, blobName) 375 c.Assert(resp.Segment.BlobItems[0].Snapshot, chk.NotNil) 376 c.Assert(resp.Segment.BlobItems[1].Name, chk.Equals, blobName) 377 c.Assert(resp.Segment.BlobItems[1].Snapshot, chk.Equals, "") 378} 379 380func (s *aztestsSuite) TestContainerListBlobsIncludeTypeCopy(c *chk.C) { 381 bsu := getBSU() 382 containerURL, _ := createNewContainer(c, bsu) 383 defer deleteContainer(c, containerURL) 384 blobURL, blobName := createNewBlockBlob(c, containerURL) 385 blobCopyURL, blobCopyName := createBlockBlobWithPrefix(c, containerURL, "copy") 386 _, err := blobCopyURL.StartCopyFromURL(ctx, blobURL.URL(), Metadata{}, ModifiedAccessConditions{}, BlobAccessConditions{}, DefaultAccessTier, nil) 387 c.Assert(err, chk.IsNil) 388 389 resp, err := containerURL.ListBlobsFlatSegment(ctx, Marker{}, 390 ListBlobsSegmentOptions{Details: BlobListingDetails{Copy: true}}) 391 392 // These are sufficient to show that the blob copy was in fact included 393 c.Assert(err, chk.IsNil) 394 c.Assert(resp.Segment.BlobItems, chk.HasLen, 2) 395 c.Assert(resp.Segment.BlobItems[1].Name, chk.Equals, blobName) 396 c.Assert(resp.Segment.BlobItems[0].Name, chk.Equals, blobCopyName) 397 c.Assert(*resp.Segment.BlobItems[0].Properties.ContentLength, chk.Equals, int64(len(blockBlobDefaultData))) 398 temp := blobURL.URL() 399 c.Assert(*resp.Segment.BlobItems[0].Properties.CopySource, chk.Equals, temp.String()) 400 c.Assert(resp.Segment.BlobItems[0].Properties.CopyStatus, chk.Equals, CopyStatusSuccess) 401} 402 403func (s *aztestsSuite) TestContainerListBlobsIncludeTypeUncommitted(c *chk.C) { 404 bsu := getBSU() 405 containerURL, _ := createNewContainer(c, bsu) 406 defer deleteContainer(c, containerURL) 407 blobURL, blobName := getBlockBlobURL(c, containerURL) 408 _, err := blobURL.StageBlock(ctx, blockID, strings.NewReader(blockBlobDefaultData), LeaseAccessConditions{}, nil, ClientProvidedKeyOptions{}) 409 c.Assert(err, chk.IsNil) 410 411 resp, err := containerURL.ListBlobsFlatSegment(ctx, Marker{}, 412 ListBlobsSegmentOptions{Details: BlobListingDetails{UncommittedBlobs: true}}) 413 414 c.Assert(err, chk.IsNil) 415 c.Assert(resp.Segment.BlobItems, chk.HasLen, 1) 416 c.Assert(resp.Segment.BlobItems[0].Name, chk.Equals, blobName) 417} 418 419func testContainerListBlobsIncludeTypeDeletedImpl(c *chk.C, bsu ServiceURL) error { 420 containerURL, _ := createNewContainer(c, bsu) 421 defer deleteContainer(c, containerURL) 422 blobURL, _ := createNewBlockBlob(c, containerURL) 423 424 resp, err := containerURL.ListBlobsFlatSegment(ctx, Marker{}, 425 ListBlobsSegmentOptions{Details: BlobListingDetails{Versions: true, Deleted: true}}) 426 c.Assert(err, chk.IsNil) 427 c.Assert(resp.Segment.BlobItems, chk.HasLen, 1) 428 429 _, err = blobURL.Delete(ctx, DeleteSnapshotsOptionInclude, BlobAccessConditions{}) 430 c.Assert(err, chk.IsNil) 431 432 resp, err = containerURL.ListBlobsFlatSegment(ctx, Marker{}, 433 ListBlobsSegmentOptions{Details: BlobListingDetails{Versions: true, Deleted: true}}) 434 c.Assert(err, chk.IsNil) 435 if len(resp.Segment.BlobItems) != 1 { 436 return errors.New("DeletedBlobNotFound") 437 } 438 439 // TODO: => Write function to enable/disable versioning from code itself. 440 // resp.Segment.BlobItems[0].Deleted == true/false if versioning is disabled/enabled. 441 c.Assert(resp.Segment.BlobItems[0].Deleted, chk.Equals, false) 442 return nil 443} 444 445func (s *aztestsSuite) TestContainerListBlobsIncludeTypeDeleted(c *chk.C) { 446 bsu := getBSU() 447 448 runTestRequiringServiceProperties(c, bsu, "DeletedBlobNotFound", enableSoftDelete, 449 testContainerListBlobsIncludeTypeDeletedImpl, disableSoftDelete) 450} 451 452func testContainerListBlobsIncludeMultipleImpl(c *chk.C, bsu ServiceURL) error { 453 containerURL, _ := createNewContainer(c, bsu) 454 defer deleteContainer(c, containerURL) 455 456 blobURL, _ := createBlockBlobWithPrefix(c, containerURL, "z") 457 _, err := blobURL.CreateSnapshot(ctx, Metadata{}, BlobAccessConditions{}, ClientProvidedKeyOptions{}) 458 c.Assert(err, chk.IsNil) 459 blobURL2, _ := createBlockBlobWithPrefix(c, containerURL, "copy") 460 resp2, err := blobURL2.StartCopyFromURL(ctx, blobURL.URL(), Metadata{}, ModifiedAccessConditions{}, BlobAccessConditions{}, DefaultAccessTier, nil) 461 c.Assert(err, chk.IsNil) 462 waitForCopy(c, blobURL2, resp2) 463 blobURL3, _ := createBlockBlobWithPrefix(c, containerURL, "deleted") 464 465 _, err = blobURL3.Delete(ctx, DeleteSnapshotsOptionNone, BlobAccessConditions{}) 466 467 resp, err := containerURL.ListBlobsFlatSegment(ctx, Marker{}, 468 ListBlobsSegmentOptions{Details: BlobListingDetails{Snapshots: true, Copy: true, Deleted: true, Versions: true}}) 469 470 c.Assert(err, chk.IsNil) 471 if len(resp.Segment.BlobItems) != 6 { 472 // If there are fewer blobs in the container than there should be, it will be because one was permanently deleted. 473 return errors.New("DeletedBlobNotFound") 474 } 475 476 //c.Assert(resp.Segment.BlobItems[0].Name, chk.Equals, blobName2) 477 //c.Assert(resp.Segment.BlobItems[1].Name, chk.Equals, blobName) // With soft delete, the overwritten blob will have a backup snapshot 478 //c.Assert(resp.Segment.BlobItems[2].Name, chk.Equals, blobName) 479 return nil 480} 481 482func (s *aztestsSuite) TestContainerListBlobsIncludeMultiple(c *chk.C) { 483 bsu := getBSU() 484 485 runTestRequiringServiceProperties(c, bsu, "DeletedBlobNotFound", enableSoftDelete, 486 testContainerListBlobsIncludeMultipleImpl, disableSoftDelete) 487} 488 489func (s *aztestsSuite) TestContainerListBlobsMaxResultsNegative(c *chk.C) { 490 bsu := getBSU() 491 containerURL, _ := createNewContainer(c, bsu) 492 493 defer deleteContainer(c, containerURL) 494 _, err := containerURL.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{MaxResults: -2}) 495 c.Assert(err, chk.Not(chk.IsNil)) 496} 497 498func (s *aztestsSuite) TestContainerListBlobsMaxResultsZero(c *chk.C) { 499 bsu := getBSU() 500 containerURL, _ := createNewContainer(c, bsu) 501 defer deleteContainer(c, containerURL) 502 createNewBlockBlob(c, containerURL) 503 504 resp, err := containerURL.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{MaxResults: 0}) 505 506 c.Assert(err, chk.IsNil) 507 c.Assert(resp.Segment.BlobItems, chk.HasLen, 1) 508} 509 510func (s *aztestsSuite) TestContainerListBlobsMaxResultsInsufficient(c *chk.C) { 511 bsu := getBSU() 512 containerURL, _ := createNewContainer(c, bsu) 513 defer deleteContainer(c, containerURL) 514 _, blobName := createBlockBlobWithPrefix(c, containerURL, "a") 515 createBlockBlobWithPrefix(c, containerURL, "b") 516 517 resp, err := containerURL.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{MaxResults: 1}) 518 519 c.Assert(err, chk.IsNil) 520 c.Assert(resp.Segment.BlobItems, chk.HasLen, 1) 521 c.Assert(resp.Segment.BlobItems[0].Name, chk.Equals, blobName) 522} 523 524func (s *aztestsSuite) TestContainerListBlobsMaxResultsExact(c *chk.C) { 525 bsu := getBSU() 526 containerURL, _ := createNewContainer(c, bsu) 527 defer deleteContainer(c, containerURL) 528 _, blobName := createBlockBlobWithPrefix(c, containerURL, "a") 529 _, blobName2 := createBlockBlobWithPrefix(c, containerURL, "b") 530 531 resp, err := containerURL.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{MaxResults: 2}) 532 533 c.Assert(err, chk.IsNil) 534 c.Assert(resp.Segment.BlobItems, chk.HasLen, 2) 535 c.Assert(resp.Segment.BlobItems[0].Name, chk.Equals, blobName) 536 c.Assert(resp.Segment.BlobItems[1].Name, chk.Equals, blobName2) 537} 538 539func (s *aztestsSuite) TestContainerListBlobsMaxResultsSufficient(c *chk.C) { 540 bsu := getBSU() 541 containerURL, _ := createNewContainer(c, bsu) 542 defer deleteContainer(c, containerURL) 543 _, blobName := createBlockBlobWithPrefix(c, containerURL, "a") 544 _, blobName2 := createBlockBlobWithPrefix(c, containerURL, "b") 545 546 resp, err := containerURL.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{MaxResults: 3}) 547 548 c.Assert(err, chk.IsNil) 549 c.Assert(resp.Segment.BlobItems, chk.HasLen, 2) 550 c.Assert(resp.Segment.BlobItems[0].Name, chk.Equals, blobName) 551 c.Assert(resp.Segment.BlobItems[1].Name, chk.Equals, blobName2) 552} 553 554func (s *aztestsSuite) TestContainerListBlobsNonExistentContainer(c *chk.C) { 555 bsu := getBSU() 556 containerURL, _ := getContainerURL(c, bsu) 557 558 _, err := containerURL.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{}) 559 560 c.Assert(err, chk.NotNil) 561} 562 563func (s *aztestsSuite) TestContainerWithNewPipeline(c *chk.C) { 564 bsu := getBSU() 565 pipeline := testPipeline{} 566 containerURL, _ := getContainerURL(c, bsu) 567 containerURL = containerURL.WithPipeline(pipeline) 568 569 _, err := containerURL.Create(ctx, Metadata{}, PublicAccessBlob) 570 571 c.Assert(err, chk.NotNil) 572 c.Assert(err.Error(), chk.Equals, testPipelineMessage) 573} 574 575func (s *aztestsSuite) TestContainerGetSetPermissionsMultiplePolicies(c *chk.C) { 576 bsu := getBSU() 577 containerURL, _ := createNewContainer(c, bsu) 578 579 defer deleteContainer(c, containerURL) 580 581 // Define the policies 582 start := generateCurrentTimeWithModerateResolution() 583 expiry := start.Add(5 * time.Minute) 584 expiry2 := start.Add(time.Minute) 585 readWrite := AccessPolicyPermission{Read: true, Write: true}.String() 586 readOnly := AccessPolicyPermission{Read: true}.String() 587 permissions := []SignedIdentifier{ 588 {ID: "0000", 589 AccessPolicy: AccessPolicy{ 590 Start: &start, 591 Expiry: &expiry, 592 Permission: &readWrite, 593 }, 594 }, 595 {ID: "0001", 596 AccessPolicy: AccessPolicy{ 597 Start: &start, 598 Expiry: &expiry2, 599 Permission: &readOnly, 600 }, 601 }, 602 } 603 604 _, err := containerURL.SetAccessPolicy(ctx, PublicAccessNone, permissions, 605 ContainerAccessConditions{}) 606 607 c.Assert(err, chk.IsNil) 608 609 resp, err := containerURL.GetAccessPolicy(ctx, LeaseAccessConditions{}) 610 c.Assert(err, chk.IsNil) 611 c.Assert(resp.Items, chk.DeepEquals, permissions) 612} 613 614func (s *aztestsSuite) TestContainerGetPermissionsPublicAccessNotNone(c *chk.C) { 615 bsu := getBSU() 616 containerURL, _ := getContainerURL(c, bsu) 617 containerURL.Create(ctx, nil, PublicAccessBlob) // We create the container explicitly so we can be sure the access policy is not empty 618 619 defer deleteContainer(c, containerURL) 620 621 resp, err := containerURL.GetAccessPolicy(ctx, LeaseAccessConditions{}) 622 623 c.Assert(err, chk.IsNil) 624 c.Assert(resp.BlobPublicAccess(), chk.Equals, PublicAccessBlob) 625} 626 627func (s *aztestsSuite) TestContainerSetPermissionsPublicAccessNone(c *chk.C) { 628 // Test the basic one by making an anonymous request to ensure it's actually doing it and also with GetPermissions 629 // For all the others, can just use GetPermissions since we've validated that it at least registers on the server correctly 630 bsu := getBSU() 631 containerURL, containerName := createNewContainer(c, bsu) 632 defer deleteContainer(c, containerURL) 633 _, blobName := createNewBlockBlob(c, containerURL) 634 635 // Container is created with PublicAccessBlob, so setting it to None will actually test that it is changed through this method 636 _, err := containerURL.SetAccessPolicy(ctx, PublicAccessNone, nil, ContainerAccessConditions{}) 637 c.Assert(err, chk.IsNil) 638 639 pipeline := NewPipeline(NewAnonymousCredential(), PipelineOptions{}) 640 bsu2 := NewServiceURL(bsu.URL(), pipeline) 641 containerURL2 := bsu2.NewContainerURL(containerName) 642 blobURL2 := containerURL2.NewBlockBlobURL(blobName) 643 _, err = blobURL2.Download(ctx, 0, 0, BlobAccessConditions{}, false, ClientProvidedKeyOptions{}) 644 645 // Get permissions via the original container URL so the request succeeds 646 resp, _ := containerURL.GetAccessPolicy(ctx, LeaseAccessConditions{}) 647 648 // If we cannot access a blob's data, we will also not be able to enumerate blobs 649 validateStorageError(c, err, ServiceCodeNoAuthenticationInformation) 650 c.Assert(resp.BlobPublicAccess(), chk.Equals, PublicAccessNone) 651} 652 653func (s *aztestsSuite) TestContainerSetPermissionsPublicAccessBlob(c *chk.C) { 654 bsu := getBSU() 655 containerURL, _ := createNewContainer(c, bsu) 656 657 defer deleteContainer(c, containerURL) 658 659 _, err := containerURL.SetAccessPolicy(ctx, PublicAccessBlob, nil, ContainerAccessConditions{}) 660 c.Assert(err, chk.IsNil) 661 662 resp, err := containerURL.GetAccessPolicy(ctx, LeaseAccessConditions{}) 663 c.Assert(err, chk.IsNil) 664 c.Assert(resp.BlobPublicAccess(), chk.Equals, PublicAccessBlob) 665} 666 667func (s *aztestsSuite) TestContainerSetPermissionsPublicAccessContainer(c *chk.C) { 668 bsu := getBSU() 669 containerURL, _ := createNewContainer(c, bsu) 670 671 defer deleteContainer(c, containerURL) 672 673 _, err := containerURL.SetAccessPolicy(ctx, PublicAccessContainer, nil, ContainerAccessConditions{}) 674 c.Assert(err, chk.IsNil) 675 676 resp, err := containerURL.GetAccessPolicy(ctx, LeaseAccessConditions{}) 677 c.Assert(err, chk.IsNil) 678 c.Assert(resp.BlobPublicAccess(), chk.Equals, PublicAccessContainer) 679} 680 681func (s *aztestsSuite) TestContainerSetPermissionsACLSinglePolicy(c *chk.C) { 682 bsu := getBSU() 683 credential, err := getGenericCredential("") 684 if err != nil { 685 c.Fatal("Invalid credential") 686 } 687 containerURL, containerName := createNewContainer(c, bsu) 688 defer deleteContainer(c, containerURL) 689 _, blobName := createNewBlockBlob(c, containerURL) 690 691 start := time.Now().UTC().Add(-15 * time.Second) 692 expiry := start.Add(5 * time.Minute).UTC() 693 listOnly := AccessPolicyPermission{List: true}.String() 694 permissions := []SignedIdentifier{{ 695 ID: "0000", 696 AccessPolicy: AccessPolicy{ 697 Start: &start, 698 Expiry: &expiry, 699 Permission: &listOnly, 700 }, 701 }} 702 _, err = containerURL.SetAccessPolicy(ctx, PublicAccessNone, permissions, ContainerAccessConditions{}) 703 c.Assert(err, chk.IsNil) 704 705 serviceSASValues := BlobSASSignatureValues{Identifier: "0000", ContainerName: containerName} 706 queryParams, err := serviceSASValues.NewSASQueryParameters(credential) 707 if err != nil { 708 c.Fatal(err) 709 } 710 711 sasURL := bsu.URL() 712 sasURL.RawQuery = queryParams.Encode() 713 sasPipeline := NewPipeline(NewAnonymousCredential(), PipelineOptions{}) 714 sasBlobServiceURL := NewServiceURL(sasURL, sasPipeline) 715 716 // Verifies that the SAS can access the resource 717 sasContainer := sasBlobServiceURL.NewContainerURL(containerName) 718 resp, err := sasContainer.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{}) 719 c.Assert(err, chk.IsNil) 720 c.Assert(resp.Segment.BlobItems[0].Name, chk.Equals, blobName) 721 722 // Verifies that successful sas access is not just because it's public 723 anonymousBlobService := NewServiceURL(bsu.URL(), sasPipeline) 724 anonymousContainer := anonymousBlobService.NewContainerURL(containerName) 725 _, err = anonymousContainer.ListBlobsFlatSegment(ctx, Marker{}, ListBlobsSegmentOptions{}) 726 validateStorageError(c, err, ServiceCodeNoAuthenticationInformation) 727} 728 729func (s *aztestsSuite) TestContainerSetPermissionsACLMoreThanFive(c *chk.C) { 730 bsu := getBSU() 731 containerURL, _ := createNewContainer(c, bsu) 732 733 defer deleteContainer(c, containerURL) 734 735 start := time.Now().UTC() 736 expiry := start.Add(5 * time.Minute).UTC() 737 permissions := make([]SignedIdentifier, 6, 6) 738 listOnly := AccessPolicyPermission{Read: true}.String() 739 for i := 0; i < 6; i++ { 740 permissions[i] = SignedIdentifier{ 741 ID: "000" + strconv.Itoa(i), 742 AccessPolicy: AccessPolicy{ 743 Start: &start, 744 Expiry: &expiry, 745 Permission: &listOnly, 746 }, 747 } 748 } 749 750 _, err := containerURL.SetAccessPolicy(ctx, PublicAccessBlob, permissions, ContainerAccessConditions{}) 751 validateStorageError(c, err, ServiceCodeInvalidXMLDocument) 752} 753 754func (s *aztestsSuite) TestContainerSetPermissionsDeleteAndModifyACL(c *chk.C) { 755 bsu := getBSU() 756 containerURL, _ := createNewContainer(c, bsu) 757 758 defer deleteContainer(c, containerURL) 759 760 start := generateCurrentTimeWithModerateResolution() 761 expiry := start.Add(5 * time.Minute).UTC() 762 listOnly := AccessPolicyPermission{Read: true}.String() 763 permissions := make([]SignedIdentifier, 2, 2) 764 for i := 0; i < 2; i++ { 765 permissions[i] = SignedIdentifier{ 766 ID: "000" + strconv.Itoa(i), 767 AccessPolicy: AccessPolicy{ 768 Start: &start, 769 Expiry: &expiry, 770 Permission: &listOnly, 771 }, 772 } 773 } 774 775 _, err := containerURL.SetAccessPolicy(ctx, PublicAccessBlob, permissions, ContainerAccessConditions{}) 776 c.Assert(err, chk.IsNil) 777 778 resp, err := containerURL.GetAccessPolicy(ctx, LeaseAccessConditions{}) 779 c.Assert(err, chk.IsNil) 780 c.Assert(resp.Items, chk.DeepEquals, permissions) 781 782 permissions = resp.Items[:1] // Delete the first policy by removing it from the slice 783 permissions[0].ID = "0004" // Modify the remaining policy which is at index 0 in the new slice 784 _, err = containerURL.SetAccessPolicy(ctx, PublicAccessBlob, permissions, ContainerAccessConditions{}) 785 786 resp, err = containerURL.GetAccessPolicy(ctx, LeaseAccessConditions{}) 787 c.Assert(err, chk.IsNil) 788 c.Assert(resp.Items, chk.HasLen, 1) 789 c.Assert(resp.Items, chk.DeepEquals, permissions) 790} 791 792func (s *aztestsSuite) TestContainerSetPermissionsDeleteAllPolicies(c *chk.C) { 793 bsu := getBSU() 794 containerURL, _ := createNewContainer(c, bsu) 795 796 defer deleteContainer(c, containerURL) 797 798 start := time.Now().UTC() 799 expiry := start.Add(5 * time.Minute).UTC() 800 permissions := make([]SignedIdentifier, 2, 2) 801 listOnly := AccessPolicyPermission{Read: true}.String() 802 for i := 0; i < 2; i++ { 803 permissions[i] = SignedIdentifier{ 804 ID: "000" + strconv.Itoa(i), 805 AccessPolicy: AccessPolicy{ 806 Start: &start, 807 Expiry: &expiry, 808 Permission: &listOnly, 809 }, 810 } 811 } 812 813 _, err := containerURL.SetAccessPolicy(ctx, PublicAccessBlob, permissions, ContainerAccessConditions{}) 814 c.Assert(err, chk.IsNil) 815 816 _, err = containerURL.SetAccessPolicy(ctx, PublicAccessBlob, []SignedIdentifier{}, ContainerAccessConditions{}) 817 c.Assert(err, chk.IsNil) 818 819 resp, err := containerURL.GetAccessPolicy(ctx, LeaseAccessConditions{}) 820 c.Assert(err, chk.IsNil) 821 c.Assert(resp.Items, chk.HasLen, 0) 822} 823 824func (s *aztestsSuite) TestContainerSetPermissionsInvalidPolicyTimes(c *chk.C) { 825 bsu := getBSU() 826 containerURL, _ := createNewContainer(c, bsu) 827 828 defer deleteContainer(c, containerURL) 829 830 // Swap start and expiry 831 expiry := time.Now().UTC() 832 start := expiry.Add(5 * time.Minute).UTC() 833 permissions := make([]SignedIdentifier, 2, 2) 834 listOnly := AccessPolicyPermission{Read: true}.String() 835 for i := 0; i < 2; i++ { 836 permissions[i] = SignedIdentifier{ 837 ID: "000" + strconv.Itoa(i), 838 AccessPolicy: AccessPolicy{ 839 Start: &start, 840 Expiry: &expiry, 841 Permission: &listOnly, 842 }, 843 } 844 } 845 846 _, err := containerURL.SetAccessPolicy(ctx, PublicAccessBlob, permissions, ContainerAccessConditions{}) 847 c.Assert(err, chk.IsNil) 848} 849 850func (s *aztestsSuite) TestContainerSetPermissionsNilPolicySlice(c *chk.C) { 851 bsu := getBSU() 852 containerURL, _ := createNewContainer(c, bsu) 853 854 defer deleteContainer(c, containerURL) 855 856 _, err := containerURL.SetAccessPolicy(ctx, PublicAccessBlob, nil, ContainerAccessConditions{}) 857 c.Assert(err, chk.IsNil) 858} 859 860func (s *aztestsSuite) TestContainerSetPermissionsSignedIdentifierTooLong(c *chk.C) { 861 bsu := getBSU() 862 containerURL, _ := createNewContainer(c, bsu) 863 864 defer deleteContainer(c, containerURL) 865 866 id := "" 867 for i := 0; i < 65; i++ { 868 id += "a" 869 } 870 expiry := time.Now().UTC() 871 start := expiry.Add(5 * time.Minute).UTC() 872 permissions := make([]SignedIdentifier, 2, 2) 873 listOnly := AccessPolicyPermission{Read: true}.String() 874 for i := 0; i < 2; i++ { 875 permissions[i] = SignedIdentifier{ 876 ID: id, 877 AccessPolicy: AccessPolicy{ 878 Start: &start, 879 Expiry: &expiry, 880 Permission: &listOnly, 881 }, 882 } 883 } 884 885 _, err := containerURL.SetAccessPolicy(ctx, PublicAccessBlob, permissions, ContainerAccessConditions{}) 886 validateStorageError(c, err, ServiceCodeInvalidXMLDocument) 887} 888 889func (s *aztestsSuite) TestContainerSetPermissionsIfModifiedSinceTrue(c *chk.C) { 890 currentTime := getRelativeTimeGMT(-10) 891 bsu := getBSU() 892 container, _ := createNewContainer(c, bsu) 893 894 defer deleteContainer(c, container) 895 896 _, err := container.SetAccessPolicy(ctx, PublicAccessNone, nil, 897 ContainerAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}}) 898 c.Assert(err, chk.IsNil) 899 900 resp, err := container.GetAccessPolicy(ctx, LeaseAccessConditions{}) 901 c.Assert(err, chk.IsNil) 902 c.Assert(resp.BlobPublicAccess(), chk.Equals, PublicAccessNone) 903} 904 905func (s *aztestsSuite) TestContainerSetPermissionsIfModifiedSinceFalse(c *chk.C) { 906 bsu := getBSU() 907 containerURL, _ := createNewContainer(c, bsu) 908 909 defer deleteContainer(c, containerURL) 910 911 currentTime := getRelativeTimeGMT(10) 912 913 _, err := containerURL.SetAccessPolicy(ctx, PublicAccessNone, nil, 914 ContainerAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}}) 915 validateStorageError(c, err, ServiceCodeConditionNotMet) 916} 917 918func (s *aztestsSuite) TestContainerSetPermissionsIfUnModifiedSinceTrue(c *chk.C) { 919 bsu := getBSU() 920 containerURL, _ := createNewContainer(c, bsu) 921 922 defer deleteContainer(c, containerURL) 923 924 currentTime := getRelativeTimeGMT(10) 925 926 _, err := containerURL.SetAccessPolicy(ctx, PublicAccessNone, nil, 927 ContainerAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}}) 928 c.Assert(err, chk.IsNil) 929 930 resp, err := containerURL.GetAccessPolicy(ctx, LeaseAccessConditions{}) 931 c.Assert(err, chk.IsNil) 932 c.Assert(resp.BlobPublicAccess(), chk.Equals, PublicAccessNone) 933} 934 935func (s *aztestsSuite) TestContainerSetPermissionsIfUnModifiedSinceFalse(c *chk.C) { 936 currentTime := getRelativeTimeGMT(-10) 937 938 bsu := getBSU() 939 containerURL, _ := createNewContainer(c, bsu) 940 941 defer deleteContainer(c, containerURL) 942 943 _, err := containerURL.SetAccessPolicy(ctx, PublicAccessNone, nil, 944 ContainerAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}}) 945 validateStorageError(c, err, ServiceCodeConditionNotMet) 946} 947 948func (s *aztestsSuite) TestContainerGetPropertiesAndMetadataNoMetadata(c *chk.C) { 949 bsu := getBSU() 950 containerURL, _ := createNewContainer(c, bsu) 951 952 defer deleteContainer(c, containerURL) 953 954 resp, err := containerURL.GetProperties(ctx, LeaseAccessConditions{}) 955 c.Assert(err, chk.IsNil) 956 c.Assert(resp.NewMetadata(), chk.HasLen, 0) 957} 958 959func (s *aztestsSuite) TestContainerGetPropsAndMetaNonExistantContainer(c *chk.C) { 960 bsu := getBSU() 961 containerURL, _ := getContainerURL(c, bsu) 962 963 _, err := containerURL.GetProperties(ctx, LeaseAccessConditions{}) 964 validateStorageError(c, err, ServiceCodeContainerNotFound) 965} 966 967func (s *aztestsSuite) TestContainerSetMetadataEmpty(c *chk.C) { 968 bsu := getBSU() 969 containerURL, _ := getContainerURL(c, bsu) 970 _, err := containerURL.Create(ctx, basicMetadata, PublicAccessBlob) 971 972 defer deleteContainer(c, containerURL) 973 974 _, err = containerURL.SetMetadata(ctx, Metadata{}, ContainerAccessConditions{}) 975 c.Assert(err, chk.IsNil) 976 977 resp, err := containerURL.GetProperties(ctx, LeaseAccessConditions{}) 978 c.Assert(err, chk.IsNil) 979 c.Assert(resp.NewMetadata(), chk.HasLen, 0) 980} 981 982func (*aztestsSuite) TestContainerSetMetadataNil(c *chk.C) { 983 bsu := getBSU() 984 containerURL, _ := getContainerURL(c, bsu) 985 _, err := containerURL.Create(ctx, basicMetadata, PublicAccessBlob) 986 987 defer deleteContainer(c, containerURL) 988 989 _, err = containerURL.SetMetadata(ctx, nil, ContainerAccessConditions{}) 990 c.Assert(err, chk.IsNil) 991 992 resp, err := containerURL.GetProperties(ctx, LeaseAccessConditions{}) 993 c.Assert(err, chk.IsNil) 994 c.Assert(resp.NewMetadata(), chk.HasLen, 0) 995} 996 997func (*aztestsSuite) TestContainerSetMetadataInvalidField(c *chk.C) { 998 bsu := getBSU() 999 containerURL, _ := createNewContainer(c, bsu) 1000 1001 defer deleteContainer(c, containerURL) 1002 1003 _, err := containerURL.SetMetadata(ctx, Metadata{"!nval!d Field!@#%": "value"}, ContainerAccessConditions{}) 1004 c.Assert(err, chk.NotNil) 1005 c.Assert(strings.Contains(err.Error(), invalidHeaderErrorSubstring), chk.Equals, true) 1006} 1007 1008func (*aztestsSuite) TestContainerSetMetadataNonExistant(c *chk.C) { 1009 bsu := getBSU() 1010 containerURL, _ := getContainerURL(c, bsu) 1011 1012 _, err := containerURL.SetMetadata(ctx, nil, ContainerAccessConditions{}) 1013 validateStorageError(c, err, ServiceCodeContainerNotFound) 1014} 1015 1016func (s *aztestsSuite) TestContainerSetMetadataIfModifiedSinceTrue(c *chk.C) { 1017 currentTime := getRelativeTimeGMT(-10) 1018 1019 bsu := getBSU() 1020 containerURL, _ := createNewContainer(c, bsu) 1021 1022 defer deleteContainer(c, containerURL) 1023 1024 _, err := containerURL.SetMetadata(ctx, basicMetadata, 1025 ContainerAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}}) 1026 c.Assert(err, chk.IsNil) 1027 1028 resp, err := containerURL.GetProperties(ctx, LeaseAccessConditions{}) 1029 1030 c.Assert(err, chk.IsNil) 1031 c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata) 1032 1033} 1034 1035func (s *aztestsSuite) TestContainerSetMetadataIfModifiedSinceFalse(c *chk.C) { 1036 bsu := getBSU() 1037 containerURL, _ := createNewContainer(c, bsu) 1038 1039 defer deleteContainer(c, containerURL) 1040 1041 currentTime := getRelativeTimeGMT(10) 1042 1043 _, err := containerURL.SetMetadata(ctx, basicMetadata, 1044 ContainerAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}}) 1045 1046 validateStorageError(c, err, ServiceCodeConditionNotMet) 1047} 1048 1049func (s *aztestsSuite) TestContainerNewBlobURL(c *chk.C) { 1050 bsu := getBSU() 1051 containerURL, _ := getContainerURL(c, bsu) 1052 1053 blobURL := containerURL.NewBlobURL(blobPrefix) 1054 tempBlob := blobURL.URL() 1055 tempContainer := containerURL.URL() 1056 c.Assert(tempBlob.String(), chk.Equals, tempContainer.String()+"/"+blobPrefix) 1057 c.Assert(blobURL, chk.FitsTypeOf, BlobURL{}) 1058} 1059 1060func (s *aztestsSuite) TestContainerNewBlockBlobURL(c *chk.C) { 1061 bsu := getBSU() 1062 containerURL, _ := getContainerURL(c, bsu) 1063 1064 blobURL := containerURL.NewBlockBlobURL(blobPrefix) 1065 tempBlob := blobURL.URL() 1066 tempContainer := containerURL.URL() 1067 c.Assert(tempBlob.String(), chk.Equals, tempContainer.String()+"/"+blobPrefix) 1068 c.Assert(blobURL, chk.FitsTypeOf, BlockBlobURL{}) 1069} 1070