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 TableServiceContextTimeoutDuringSaveChangesNonBatchAPM() { CloudTableClient tableClient = GenerateCloudTableClient(); TableServiceContext ctx = tableClient.GetTableServiceContext(); for (int m = 0; m < 100; m++) { BaseEntity ent = new BaseEntity("testpartition", m.ToString()); ent.Randomize(); ent.A = ent.RowKey; ctx.AddObject(currentTable.Name, ent); } OperationContext opContext = new OperationContext(); TableRequestOptions requestOptions = new TableRequestOptions() { MaximumExecutionTime = TimeSpan.FromSeconds(5) }; using (HttpMangler proxy = new HttpMangler(false, new[] { DelayBehaviors.DelayAllRequestsIf(2000, XStoreSelectors.TableTraffic().IfHostNameContains(tableClient.Credentials.AccountName).SkipNSessions(10)) })) { try { using (ManualResetEvent evt = new ManualResetEvent(false)) { IAsyncResult result = ctx.BeginSaveChangesWithRetries(SaveChangesOptions.None, requestOptions, opContext, (res) => { result = res; evt.Set(); }, null); evt.WaitOne(); ctx.EndSaveChangesWithRetries(result); } ctx.SaveChangesWithRetries(SaveChangesOptions.None, requestOptions, opContext); } catch (StorageException ex) { Assert.AreEqual(ex.RequestInformation.HttpStatusCode, (int)HttpStatusCode.RequestTimeout); Assert.AreEqual("The client could not finish the operation within specified timeout.", ex.Message); Assert.IsTrue(ex.InnerException is TimeoutException); } } }
public void CloudFileDownloadToStreamAPMRetry() { byte[] buffer = GetRandomBuffer(1 * 1024 * 1024); CloudFileShare share = GetRandomShareReference(); try { share.Create(); CloudFile file = share.GetRootDirectoryReference().GetFileReference("file1"); using (MemoryStream originalFile = new MemoryStream(buffer)) { using (AutoResetEvent waitHandle = new AutoResetEvent(false)) { ICancellableAsyncResult result = file.BeginUploadFromStream(originalFile, ar => waitHandle.Set(), null); waitHandle.WaitOne(); file.EndUploadFromStream(result); using (MemoryStream downloadedFile = 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.FileTraffic().IfHostNameContains(share.ServiceClient.Credentials.AccountName)) })) { OperationContext operationContext = new OperationContext(); result = file.BeginDownloadToStream(downloadedFile, null, null, operationContext, ar => waitHandle.Set(), null); waitHandle.WaitOne(); file.EndDownloadToStream(result); TestHelper.AssertStreamsAreEqual(originalFile, downloadedFile); } if (manglerEx != null) { throw manglerEx; } } } } } finally { share.DeleteIfExists(); } }
/// <summary> /// This help function is for getting the reference behavior of the Storage DLL when HttpMangler is enabled. /// Edit HttpMangler.cs to use HandleFiddlerEvent_DEBUG(). /// </summary> /// <param name="entityPartitionKey"></param> /// <param name="entityRowKey"></param> /// <param name="targetStorageAccount"></param> /// <param name="targetApiExpectedToFail"></param> /// <param name="behaviors"></param> protected void SetupAndRunXStoreHttpManglerTest( string entityPartitionKey, string entityRowKey, int targetStorageAccount, bool targetApiExpectedToFail, ProxyBehavior[] behaviors) { Assert.IsTrue(0 <= targetStorageAccount && targetStorageAccount < this.actualStorageAccountsUsed.Count, "targetStorageAccount={0} is out-of-range", targetStorageAccount); int index = this.actualStorageAccountsUsed[targetStorageAccount]; string accountNameToTamper = this.rtableTestConfiguration.StorageInformation.AccountNames[index]; Console.WriteLine("accountNameToTamper={0}", accountNameToTamper); CloudTableClient tableClient = this.cloudTableClients[targetStorageAccount]; CloudTable table = tableClient.GetTableReference(this.repTable.TableName); // // Insert // string jobType = entityPartitionKey; string jobId = entityRowKey; string referenceMessage = SampleRTableEntity.GenerateRandomMessage(); SampleRTableEntity originalEntity = new SampleRTableEntity(jobType, jobId, referenceMessage); Console.WriteLine("\nCalling XStore Insert..."); TableOperation insertOperation = TableOperation.Insert(originalEntity); TableResult insertResult = table.Execute(insertOperation); Assert.IsNotNull(insertResult, "insertResult = null"); Console.WriteLine("insertResult.HttpStatusCode = {0}", insertResult.HttpStatusCode); Console.WriteLine("insertResult.ETag = {0}", insertResult.Etag); Assert.AreEqual((int)HttpStatusCode.NoContent, insertResult.HttpStatusCode, "insertResult.HttpStatusCode mismatch"); Assert.IsFalse(string.IsNullOrEmpty(insertResult.Etag), "insertResult.ETag = null or empty"); ITableEntity row = (ITableEntity)insertResult.Result; // // Retrieve // Console.WriteLine("Calling XStore Retrieve..."); TableOperation retrieveOperation = TableOperation.Retrieve<SampleRTableEntity>(row.PartitionKey, row.RowKey); TableResult retrieveResult = table.Execute(retrieveOperation); Assert.IsNotNull(retrieveResult, "retrieveResult = null"); Console.WriteLine("retrieveResult.HttpStatusCode = {0}", retrieveResult.HttpStatusCode); Assert.AreEqual((int)HttpStatusCode.OK, retrieveResult.HttpStatusCode, "retrieveResult.HttpStatusCode mismatch"); SampleRTableEntity retrievedEntity = (SampleRTableEntity)retrieveResult.Result; Console.WriteLine("retrieveEntity:\n{0}", retrievedEntity); Assert.IsTrue(originalEntity.Equals(retrievedEntity), "originalEntity != retrievedEntity"); // // Replace with HttpMangler enabled // Console.WriteLine("Calling XStore TableOperation.Replace with HttpMangler enabled..."); referenceMessage = SampleRTableEntity.GenerateRandomMessage(); retrievedEntity.Message = referenceMessage; TableOperation updateOperation = TableOperation.Replace(retrievedEntity); bool abortTest = false; try { using (HttpMangler proxy = new HttpMangler(false, behaviors)) { Console.WriteLine("Calling table.Execute(updateOperation)"); TableResult updateResult = table.Execute(updateOperation); if (targetApiExpectedToFail) { // if targetApi is expected to fail, and we are here, that means something is wrong. abortTest = true; throw new Exception("SetupAndRunXStoreHttpManglerTest(): Should not reach here. HttpMangler allowed an targetApi() to go through UNEXPECTEDLY."); } } } catch (Exception ex) { if (abortTest) { throw; } else { Console.WriteLine("\nException is Expected. targetApi(entity1) threw an exception: {0}\n", ex.ToString()); } } // // Retrieve again // Console.WriteLine("After HttpMangler is disabled, calling XStore Retrieve again..."); retrieveOperation = TableOperation.Retrieve<SampleRTableEntity>(row.PartitionKey, row.RowKey); retrieveResult = table.Execute(retrieveOperation); Assert.IsNotNull(retrieveResult, "retrieveResult = null"); Console.WriteLine("retrieveResult.HttpStatusCode = {0}", retrieveResult.HttpStatusCode); Assert.AreEqual((int)HttpStatusCode.OK, retrieveResult.HttpStatusCode, "retrieveResult.HttpStatusCode mismatch"); SampleRTableEntity retrievedEntity2 = (SampleRTableEntity)retrieveResult.Result; Console.WriteLine("retrieveEntity2:\n{0}", retrievedEntity2); Assert.IsTrue(originalEntity.Equals(retrievedEntity2), "originalEntity != retrievedEntity2"); }
/// <summary> /// Run the specified HttpMangler proxy behaviors for the specified batchOperation. /// </summary> /// <param name="batchOperation"></param> /// <param name="behaviors"></param> /// <param name="targetApiExpectedToFail"></param> /// <param name="httpManglerStartTime"></param> protected void RunHttpManglerBehaviorHelper( TableBatchOperation batchOperation, ProxyBehavior[] behaviors, bool targetApiExpectedToFail, out DateTime httpManglerStartTime) { // // Act // // Call targetApi(entity1) and tamper the request httpManglerStartTime = DateTime.UtcNow; Console.WriteLine("\nRunHttpManglerBehaviorHelper(): Call this.repTable.ExecuteBatch(batchOperation) with HttpMangler enabled..."); bool abortTest = false; try { using (HttpMangler proxy = new HttpMangler(false, behaviors)) { Console.WriteLine("Calling targetApi(entity1)"); this.repTable.ExecuteBatch(batchOperation); if (targetApiExpectedToFail) { // if targetApi is expected to fail, and we are here, that means something is wrong. abortTest = true; throw new Exception("RunHttpManglerBehaviorHelper(): Should not reach here. HttpMangler allowed this.repTable.ExecuteBatch(batchOperation) to go through UNEXPECTEDLY."); } } } catch (Exception ex) { if (targetApiExpectedToFail == false) { // if targetApi is NOT expected to fail, and we are here, that means something is wrong. throw new Exception( string.Format("RunHttpManglerBehaviorHelper(): this.repTable.ExecuteBatch(batchOperation) is NOT unexpected to throw an exception. Got this exception: {0}", ex.ToString())); } if (abortTest) { throw; } else { Console.WriteLine("\nException is Expected. this.repTable.ExecuteBatch(batchOperation) threw an exception: {0}\n", ex.ToString()); } } }
/// <summary> /// Run the specified HttpMangler proxy behaviors for the specified Api, which takes this form: /// Func<string, string, SampleRTableEntity> targetApi /// </summary> /// <param name="originalEntity"></param> /// <param name="behaviors"></param> /// <param name="targetApi"></param> /// <param name="targetApiExpectedToFail"></param> /// <param name="httpManglerStartTime"></param> protected void RunHttpManglerBehaviorHelper( SampleRTableEntity originalEntity, ProxyBehavior[] behaviors, Func<string, string, SampleRTableEntity> targetApi, bool targetApiExpectedToFail, out DateTime httpManglerStartTime) { // // Act // // Call targetApi(entity1) and tamper the request httpManglerStartTime = DateTime.UtcNow; Console.WriteLine("\nRunHttpManglerBehaviorHelper(): Call targetApi(entity1) with HttpMangler enabled..."); originalEntity.Message = SampleRTableEntity.GenerateRandomMessage(); bool abortTest = false; try { using (HttpMangler proxy = new HttpMangler(false, behaviors)) { Console.WriteLine("Calling targetApi(entity1)"); targetApi(originalEntity.PartitionKey, originalEntity.RowKey); if (targetApiExpectedToFail) { // if targetApi is expected to fail, and we are here, that means something is wrong. abortTest = true; throw new Exception("RunHttpManglerBehaviorHelper(): Should not reach here. HttpMangler allowed an targetApi() to go through UNEXPECTEDLY."); } } } catch (Exception ex) { if (targetApiExpectedToFail == false) { // if targetApi is NOT expected to fail, and we are here, that means something is wrong. throw new Exception( string.Format("RunHttpManglerBehaviorHelper(): targetApi() is NOT unexpected to throw an exception. Got this exception: {0}", ex.ToString())); } if (abortTest) { throw; } else { Console.WriteLine("\nException is Expected. targetApi(entity1) threw an exception: {0}\n", ex.ToString()); } } }