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(); } }