@@ -50,7 +50,7 @@ public void SetupDefaultBehaviors()
5050 } ;
5151 } ;
5252
53- this . blobManager . OnUploadFromStreamAsync = ( descriptor , stream , options ) =>
53+ this . blobManager . OnUploadFromStreamAsync = ( descriptor , stream , options , metadata ) =>
5454 {
5555 return new TestResponse < BlobContentInfo > ( )
5656 {
@@ -362,15 +362,15 @@ public void BlobManagerValidatesTheBlobNameBeforeUploadingABlob()
362362 this . mockDescriptor . Name = name ;
363363
364364 Assert . ThrowsAsync < ArgumentException > (
365- ( ) => this . blobManager . UploadBlobAsync ( this . mockDescriptor , uploadStream , CancellationToken . None , Policy . NoOpAsync ( ) ) ) ;
365+ ( ) => this . blobManager . UploadBlobAsync ( this . mockDescriptor , uploadStream , CancellationToken . None , retryPolicy : Policy . NoOpAsync ( ) ) ) ;
366366 } ) ;
367367
368368 validBlobNames . ForEach ( name =>
369369 {
370370 this . mockDescriptor . Name = name ;
371371
372372 Assert . DoesNotThrowAsync (
373- ( ) => this . blobManager . UploadBlobAsync ( this . mockDescriptor , uploadStream , CancellationToken . None , Policy . NoOpAsync ( ) ) ) ;
373+ ( ) => this . blobManager . UploadBlobAsync ( this . mockDescriptor , uploadStream , CancellationToken . None , retryPolicy : Policy . NoOpAsync ( ) ) ) ;
374374 } ) ;
375375 }
376376 }
@@ -403,15 +403,15 @@ public void BlobManagerValidatesTheContainerNameBeforeUploadingABlob()
403403 this . mockDescriptor . ContainerName = name ;
404404
405405 Assert . ThrowsAsync < ArgumentException > (
406- ( ) => this . blobManager . UploadBlobAsync ( this . mockDescriptor , uploadStream , CancellationToken . None , Policy . NoOpAsync ( ) ) ) ;
406+ ( ) => this . blobManager . UploadBlobAsync ( this . mockDescriptor , uploadStream , CancellationToken . None , retryPolicy : Policy . NoOpAsync ( ) ) ) ;
407407 } ) ;
408408
409409 validContainerNames . ForEach ( name =>
410410 {
411411 this . mockDescriptor . ContainerName = name ;
412412
413413 Assert . DoesNotThrowAsync (
414- ( ) => this . blobManager . UploadBlobAsync ( this . mockDescriptor , uploadStream , CancellationToken . None , Policy . NoOpAsync ( ) ) ) ;
414+ ( ) => this . blobManager . UploadBlobAsync ( this . mockDescriptor , uploadStream , CancellationToken . None , retryPolicy : Policy . NoOpAsync ( ) ) ) ;
415415 } ) ;
416416 }
417417 }
@@ -422,7 +422,7 @@ public async Task BlobManagerSupportsDependencyDescriptorBaseClassParameterConve
422422 using ( MemoryStream uploadStream = new MemoryStream ( ) )
423423 {
424424 bool supported = false ;
425- this . blobManager . OnUploadFromStreamAsync = ( descriptor , stream , options ) =>
425+ this . blobManager . OnUploadFromStreamAsync = ( descriptor , stream , options , metadata ) =>
426426 {
427427 supported = true ;
428428
@@ -436,7 +436,7 @@ public async Task BlobManagerSupportsDependencyDescriptorBaseClassParameterConve
436436 } ;
437437
438438 DependencyDescriptor baseDescriptor = new DependencyDescriptor ( this . mockDescriptor ) ;
439- await this . blobManager . UploadBlobAsync ( baseDescriptor , uploadStream , CancellationToken . None , Policy . NoOpAsync ( ) )
439+ await this . blobManager . UploadBlobAsync ( baseDescriptor , uploadStream , CancellationToken . None , retryPolicy : Policy . NoOpAsync ( ) )
440440 . ConfigureAwait ( false ) ;
441441
442442 Assert . IsTrue ( supported ) ;
@@ -448,7 +448,7 @@ public async Task BlobManagerUploadsTheExpectedBlobFromAStream()
448448 {
449449 using ( MemoryStream uploadStream = new MemoryStream ( ) )
450450 {
451- this . blobManager . OnUploadFromStreamAsync = ( descriptor , stream , options ) =>
451+ this . blobManager . OnUploadFromStreamAsync = ( descriptor , stream , options , metadata ) =>
452452 {
453453 Assert . IsTrue ( object . ReferenceEquals ( this . mockDescriptor , descriptor ) ) ;
454454 Assert . AreEqual ( descriptor . ContentEncoding . WebName , options . HttpHeaders . ContentEncoding ) ;
@@ -463,7 +463,7 @@ public async Task BlobManagerUploadsTheExpectedBlobFromAStream()
463463 } ;
464464 } ;
465465
466- await this . blobManager . UploadBlobAsync ( this . mockDescriptor , uploadStream , CancellationToken . None , Policy . NoOpAsync ( ) )
466+ await this . blobManager . UploadBlobAsync ( this . mockDescriptor , uploadStream , CancellationToken . None , retryPolicy : Policy . NoOpAsync ( ) )
467467 . ConfigureAwait ( false ) ;
468468 }
469469 }
@@ -474,7 +474,7 @@ public async Task BlobManagerUsesETagsToEnableOptimisticConcurrencyOnBlobUploads
474474 using ( MemoryStream uploadStream = new MemoryStream ( ) )
475475 {
476476 this . mockDescriptor . ETag = "\" 0x123456789\" " ;
477- this . blobManager . OnUploadFromStreamAsync = ( descriptor , stream , options ) =>
477+ this . blobManager . OnUploadFromStreamAsync = ( descriptor , stream , options , metadata ) =>
478478 {
479479 Assert . IsNotNull ( options . Conditions ) ;
480480 Assert . IsTrue ( options . Conditions . IfMatch . HasValue ) ;
@@ -489,7 +489,7 @@ public async Task BlobManagerUsesETagsToEnableOptimisticConcurrencyOnBlobUploads
489489 } ;
490490 } ;
491491
492- await this . blobManager . UploadBlobAsync ( this . mockDescriptor , uploadStream , CancellationToken . None , Policy . NoOpAsync ( ) )
492+ await this . blobManager . UploadBlobAsync ( this . mockDescriptor , uploadStream , CancellationToken . None , retryPolicy : Policy . NoOpAsync ( ) )
493493 . ConfigureAwait ( false ) ;
494494 }
495495 }
@@ -499,7 +499,7 @@ public async Task BlobManagerReturnsTheExpectedBlobDescriptorOnUploads()
499499 {
500500 using ( MemoryStream uploadStream = new MemoryStream ( ) )
501501 {
502- BlobDescriptor actualDescriptor = await this . blobManager . UploadBlobAsync ( this . mockDescriptor , uploadStream , CancellationToken . None , Policy . NoOpAsync ( ) )
502+ BlobDescriptor actualDescriptor = await this . blobManager . UploadBlobAsync ( this . mockDescriptor , uploadStream , CancellationToken . None , retryPolicy : Policy . NoOpAsync ( ) )
503503 . ConfigureAwait ( false ) as BlobDescriptor ;
504504
505505 Assert . IsNotNull ( actualDescriptor ) ;
@@ -511,12 +511,47 @@ public async Task BlobManagerReturnsTheExpectedBlobDescriptorOnUploads()
511511 }
512512 }
513513
514+ [ Test ]
515+ public async Task BlobManagerIncludesMetadataInBlobsUploadedWhenProvided ( )
516+ {
517+ using ( MemoryStream uploadStream = new MemoryStream ( ) )
518+ {
519+ IDictionary < string , IConvertible > expectedMetadata = new Dictionary < string , IConvertible >
520+ {
521+ { "Metadata1" , "Value1" } ,
522+ { "Metadata2" , 1234 } ,
523+ { "Metadata3" , true } ,
524+ { "Metadata4" , Guid . NewGuid ( ) . ToString ( ) }
525+ } ;
526+
527+ bool confirmed = false ;
528+ this . blobManager . OnUploadFromStreamAsync = ( descriptor , stream , options , metadata ) =>
529+ {
530+ CollectionAssert . AreEquivalent ( expectedMetadata , metadata ) ;
531+ confirmed = true ;
532+
533+ return new TestResponse < BlobContentInfo > ( )
534+ {
535+ RawResponse = new TestResponse ( ( int ) HttpStatusCode . OK , "\" 0x123456789\" " )
536+ {
537+ ContentStream = new MemoryStream ( )
538+ }
539+ } ;
540+ } ;
541+
542+ BlobDescriptor actualDescriptor = await this . blobManager . UploadBlobAsync ( this . mockDescriptor , uploadStream , CancellationToken . None , expectedMetadata , Policy . NoOpAsync ( ) )
543+ . ConfigureAwait ( false ) as BlobDescriptor ;
544+
545+ Assert . IsTrue ( confirmed ) ;
546+ }
547+ }
548+
514549 [ Test ]
515550 public void BlobManagerThrowsIfAFailedResponseIsReturnedOnAnAttemptToUploadABlob ( )
516551 {
517552 using ( MemoryStream uploadStream = new MemoryStream ( ) )
518553 {
519- this . blobManager . OnUploadFromStreamAsync = ( descriptor , stream , options ) =>
554+ this . blobManager . OnUploadFromStreamAsync = ( descriptor , stream , options , metadata ) =>
520555 {
521556 return new TestResponse < BlobContentInfo > ( )
522557 {
@@ -528,7 +563,7 @@ public void BlobManagerThrowsIfAFailedResponseIsReturnedOnAnAttemptToUploadABlob
528563 } ;
529564
530565 DependencyException error = Assert . ThrowsAsync < DependencyException > (
531- ( ) => this . blobManager . UploadBlobAsync ( this . mockDescriptor , uploadStream , CancellationToken . None , Policy . NoOpAsync ( ) ) ) ;
566+ ( ) => this . blobManager . UploadBlobAsync ( this . mockDescriptor , uploadStream , CancellationToken . None , retryPolicy : Policy . NoOpAsync ( ) ) ) ;
532567
533568 Assert . IsTrue ( error . Message . Contains ( "BadRequest" ) ) ;
534569 }
@@ -540,7 +575,7 @@ public void BlobManagerAppliesTheRetryPolicyProvidedToHandleTransientErrorsWhenU
540575 using ( MemoryStream uploadStream = new MemoryStream ( ) )
541576 {
542577 int uploadAttempts = 0 ;
543- this . blobManager . OnUploadFromStreamAsync = ( descriptor , stream , options ) =>
578+ this . blobManager . OnUploadFromStreamAsync = ( descriptor , stream , options , metadata ) =>
544579 {
545580 uploadAttempts ++ ;
546581 throw new RequestFailedException ( "Transient Error" ) ;
@@ -549,7 +584,7 @@ public void BlobManagerAppliesTheRetryPolicyProvidedToHandleTransientErrorsWhenU
549584 IAsyncPolicy expectedRetryPolicy = Policy . Handle < RequestFailedException > ( ) . RetryAsync ( 3 ) ;
550585
551586 Assert . ThrowsAsync < DependencyException > (
552- ( ) => this . blobManager . UploadBlobAsync ( this . mockDescriptor , uploadStream , CancellationToken . None , expectedRetryPolicy ) ) ;
587+ ( ) => this . blobManager . UploadBlobAsync ( this . mockDescriptor , uploadStream , CancellationToken . None , retryPolicy : expectedRetryPolicy ) ) ;
553588
554589 Assert . IsTrue ( uploadAttempts == 4 ) ;
555590 }
@@ -561,7 +596,7 @@ public void BlobManagerDefaultRetryPolicyDoesNotRetryNonTransientErrorsWhenUploa
561596 using ( MemoryStream uploadStream = new MemoryStream ( ) )
562597 {
563598 int uploadAttempts = 0 ;
564- this . blobManager . OnUploadFromStreamAsync = ( descriptor , stream , options ) =>
599+ this . blobManager . OnUploadFromStreamAsync = ( descriptor , stream , options , metadata ) =>
565600 {
566601 uploadAttempts ++ ;
567602 throw new RequestFailedException (
@@ -582,7 +617,7 @@ public void BlobManagerDefaultRetryPolicyHandleSignatureMismatchErrors()
582617 using ( MemoryStream uploadStream = new MemoryStream ( ) )
583618 {
584619 int uploadAttempts = 0 ;
585- this . blobManager . OnUploadFromStreamAsync = ( descriptor , stream , options ) =>
620+ this . blobManager . OnUploadFromStreamAsync = ( descriptor , stream , options , metadata ) =>
586621 {
587622 if ( uploadAttempts <= 1 )
588623 {
@@ -616,7 +651,7 @@ public TestBlobManager(DependencyBlobStore storeDescription)
616651
617652 public Func < BlobDescriptor , Stream , Response > OnDownloadToStreamAsync { get ; set ; }
618653
619- public Func < BlobDescriptor , Stream , BlobUploadOptions , Response < BlobContentInfo > > OnUploadFromStreamAsync { get ; set ; }
654+ public Func < BlobDescriptor , Stream , BlobUploadOptions , IDictionary < string , IConvertible > , Response < BlobContentInfo > > OnUploadFromStreamAsync { get ; set ; }
620655
621656 public new BlobContainerClient CreateContainerClient ( BlobDescriptor descriptor , DependencyBlobStore blobStore )
622657 {
@@ -632,10 +667,10 @@ protected override Task<Response> DownloadToStreamAsync(BlobDescriptor descripto
632667 return Task . FromResult ( response ) ;
633668 }
634669
635- protected override Task < Response < BlobContentInfo > > UploadFromStreamAsync ( BlobDescriptor descriptor , Stream stream , BlobUploadOptions uploadOptions , CancellationToken cancellationToken )
670+ protected override Task < Response < BlobContentInfo > > UploadFromStreamAsync ( BlobDescriptor descriptor , Stream stream , BlobUploadOptions uploadOptions , CancellationToken cancellationToken , IDictionary < string , IConvertible > metadata = null )
636671 {
637672 Response < BlobContentInfo > response = this . OnUploadFromStreamAsync != null
638- ? this . OnUploadFromStreamAsync ? . Invoke ( descriptor , stream , uploadOptions )
673+ ? this . OnUploadFromStreamAsync ? . Invoke ( descriptor , stream , uploadOptions , metadata )
639674 : null ;
640675
641676 return Task . FromResult ( response ) ;
0 commit comments