public void CloudBlockBlobDownloadRangeToStreamAPMRetry() { byte[] buffer = GetRandomBuffer(1 * 1024 * 1024); int offset = 1024; CloudBlobContainer container = GetRandomContainerReference(); try { container.Create(); CloudBlockBlob blob = container.GetBlockBlobReference("blob1"); using (MemoryStream originalBlob = new MemoryStream(buffer)) { using (AutoResetEvent waitHandle = new AutoResetEvent(false)) { ICancellableAsyncResult result = blob.BeginUploadFromStream(originalBlob, ar => waitHandle.Set(), null); waitHandle.WaitOne(); blob.EndUploadFromStream(result); } } using (MemoryStream originalBlob = new MemoryStream()) { originalBlob.Write(buffer, offset, buffer.Length - offset); using (AutoResetEvent waitHandle = new AutoResetEvent(false)) { using (MemoryStream downloadedBlob = new MemoryStream()) { Exception manglerEx = null; using (HttpMangler proxy = new HttpMangler(false, new[] { TamperBehaviors.TamperNRequestsIf( session => ThreadPool.QueueUserWorkItem(state => { Thread.Sleep(1000); try { session.Abort(); } catch (Exception e) { manglerEx = e; } }), 2, AzureStorageSelectors.BlobTraffic().IfHostNameContains(container.ServiceClient.Credentials.AccountName)) })) { OperationContext operationContext = new OperationContext(); BlobRequestOptions options = new BlobRequestOptions() { UseTransactionalMD5 = true }; ICancellableAsyncResult result = blob.BeginDownloadRangeToStream(downloadedBlob, offset, buffer.Length - offset, null, options, operationContext, ar => waitHandle.Set(), null); waitHandle.WaitOne(); blob.EndDownloadToStream(result); TestHelper.AssertStreamsAreEqual(originalBlob, downloadedBlob); } if (manglerEx != null) { throw manglerEx; } } } } } finally { container.DeleteIfExists(); } }
public void UseTransactionalMD5GetTestAPM() { BlobRequestOptions optionsWithNoMD5 = new BlobRequestOptions() { UseTransactionalMD5 = false, }; BlobRequestOptions optionsWithMD5 = new BlobRequestOptions() { UseTransactionalMD5 = true, }; byte[] buffer = GetRandomBuffer(3 * 1024 * 1024); MD5 hasher = MD5.Create(); string md5 = Convert.ToBase64String(hasher.ComputeHash(buffer)); string lastCheckMD5 = null; int checkCount = 0; OperationContext opContextWithMD5Check = new OperationContext(); opContextWithMD5Check.ResponseReceived += (_, args) => { if (args.Response.ContentLength >= buffer.Length) { lastCheckMD5 = args.Response.Headers[HttpResponseHeader.ContentMd5]; checkCount++; } }; CloudBlobContainer container = GetRandomContainerReference(); try { container.Create(); using (AutoResetEvent waitHandle = new AutoResetEvent(false)) { IAsyncResult result; CloudBlockBlob blockBlob = container.GetBlockBlobReference("blob1"); using (Stream blobStream = blockBlob.OpenWrite()) { blobStream.Write(buffer, 0, buffer.Length); blobStream.Write(buffer, 0, buffer.Length); } checkCount = 0; using (Stream stream = new MemoryStream()) { result = blockBlob.BeginDownloadToStream(stream, null, optionsWithNoMD5, opContextWithMD5Check, ar => waitHandle.Set(), null); waitHandle.WaitOne(); blockBlob.EndDownloadRangeToStream(result); Assert.IsNotNull(lastCheckMD5); result = blockBlob.BeginDownloadToStream(stream, null, optionsWithMD5, opContextWithMD5Check, ar => waitHandle.Set(), null); waitHandle.WaitOne(); blockBlob.EndDownloadRangeToStream(result); Assert.IsNotNull(lastCheckMD5); result = blockBlob.BeginDownloadRangeToStream(stream, buffer.Length, buffer.Length, null, optionsWithNoMD5, opContextWithMD5Check, ar => waitHandle.Set(), null); waitHandle.WaitOne(); blockBlob.EndDownloadRangeToStream(result); Assert.IsNull(lastCheckMD5); result = blockBlob.BeginDownloadRangeToStream(stream, buffer.Length, buffer.Length, null, optionsWithMD5, opContextWithMD5Check, ar => waitHandle.Set(), null); waitHandle.WaitOne(); blockBlob.EndDownloadRangeToStream(result); Assert.AreEqual(md5, lastCheckMD5); result = blockBlob.BeginDownloadRangeToStream(stream, 1024, 4 * 1024 * 1024 + 1, null, optionsWithNoMD5, opContextWithMD5Check, ar => waitHandle.Set(), null); waitHandle.WaitOne(); blockBlob.EndDownloadRangeToStream(result); Assert.IsNull(lastCheckMD5); result = blockBlob.BeginDownloadRangeToStream(stream, 1024, 4 * 1024 * 1024 + 1, null, optionsWithMD5, opContextWithMD5Check, ar => waitHandle.Set(), null); waitHandle.WaitOne(); StorageException storageEx = TestHelper.ExpectedException <StorageException>( () => blockBlob.EndDownloadRangeToStream(result), "Downloading more than 4MB with transactional MD5 should not be supported"); Assert.IsInstanceOfType(storageEx.InnerException, typeof(ArgumentOutOfRangeException)); } Assert.AreEqual(5, checkCount); CloudPageBlob pageBlob = container.GetPageBlobReference("blob2"); using (Stream blobStream = pageBlob.OpenWrite(buffer.Length * 2)) { blobStream.Write(buffer, 0, buffer.Length); blobStream.Write(buffer, 0, buffer.Length); } checkCount = 0; using (Stream stream = new MemoryStream()) { result = pageBlob.BeginDownloadToStream(stream, null, optionsWithNoMD5, opContextWithMD5Check, ar => waitHandle.Set(), null); waitHandle.WaitOne(); pageBlob.EndDownloadRangeToStream(result); Assert.IsNull(lastCheckMD5); result = pageBlob.BeginDownloadToStream(stream, null, optionsWithMD5, opContextWithMD5Check, ar => waitHandle.Set(), null); waitHandle.WaitOne(); StorageException storageEx = TestHelper.ExpectedException <StorageException>( () => pageBlob.EndDownloadRangeToStream(result), "Page blob will not have MD5 set by default; with UseTransactional, download should fail"); result = pageBlob.BeginDownloadRangeToStream(stream, buffer.Length, buffer.Length, null, optionsWithNoMD5, opContextWithMD5Check, ar => waitHandle.Set(), null); waitHandle.WaitOne(); pageBlob.EndDownloadRangeToStream(result); Assert.IsNull(lastCheckMD5); result = pageBlob.BeginDownloadRangeToStream(stream, buffer.Length, buffer.Length, null, optionsWithMD5, opContextWithMD5Check, ar => waitHandle.Set(), null); waitHandle.WaitOne(); pageBlob.EndDownloadRangeToStream(result); Assert.AreEqual(md5, lastCheckMD5); result = pageBlob.BeginDownloadRangeToStream(stream, 1024, 4 * 1024 * 1024 + 1, null, optionsWithNoMD5, opContextWithMD5Check, ar => waitHandle.Set(), null); waitHandle.WaitOne(); pageBlob.EndDownloadRangeToStream(result); Assert.IsNull(lastCheckMD5); result = pageBlob.BeginDownloadRangeToStream(stream, 1024, 4 * 1024 * 1024 + 1, null, optionsWithMD5, opContextWithMD5Check, ar => waitHandle.Set(), null); waitHandle.WaitOne(); storageEx = TestHelper.ExpectedException <StorageException>( () => pageBlob.EndDownloadRangeToStream(result), "Downloading more than 4MB with transactional MD5 should not be supported"); Assert.IsInstanceOfType(storageEx.InnerException, typeof(ArgumentOutOfRangeException)); } Assert.AreEqual(5, checkCount); } } finally { container.DeleteIfExists(); } }