public void TableServiceContextTimeoutDuringSaveChangesNonBatchSync() { 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(4000 * 3, XStoreSelectors.TableTraffic().IfHostNameContains(tableClient.Credentials.AccountName).SkipNSessions(10)) })) { try { 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); } } }
internal static void ExecuteAPMMethodWithCancellation <T>(int cancellationDelayInMS, ProxyBehavior[] behaviors, Func <IRequestOptions, OperationContext, AsyncCallback, object, ICancellableAsyncResult> begin, Func <IAsyncResult, T> end) { string failMessage = null; StorageException storageException = null; OperationContext opContext = new OperationContext(); using (HttpMangler proxy = new HttpMangler(false, behaviors)) { Debug.WriteLine("Begin"); using (ManualResetEvent completedEvent = new ManualResetEvent(false)) { ICancellableAsyncResult saveResult = begin(null , opContext, (resp) => { try { end(resp); failMessage = "Request succeeded even after cancellation"; } catch (StorageException ex) { storageException = ex; } catch (Exception badEx) { failMessage = badEx.ToString(); } finally { completedEvent.Set(); } }, null); Thread.Sleep(cancellationDelayInMS); Debug.WriteLine("Cancelling Request"); saveResult.Cancel(); completedEvent.WaitOne(); TestHelper.AssertNAttempts(opContext, 1); } } // Do not use IsNull here so that test result contains failMessage Assert.AreEqual(null, failMessage); Assert.IsNotNull(storageException); Assert.AreEqual("A task was canceled.", storageException.Message); Assert.AreEqual(306, storageException.RequestInformation.HttpStatusCode); //TODO: Httpclient null or unused? Assert.AreEqual(null, storageException.RequestInformation.HttpStatusMessage); }
internal static void ExecuteMethodWithRetry <T>(int ExpectedAttempts, ProxyBehavior[] behaviors, Func <IRequestOptions, OperationContext, T> method) { OperationContext opContext = new OperationContext(); using (HttpMangler proxy = new HttpMangler(false, behaviors)) { method(null, opContext); TestHelper.AssertNAttempts(opContext, ExpectedAttempts); } }
internal static void VerifyHeaderWasSent(string headerName, string headerValue, Func <Session, bool> selector, Action act) { string retrievedHeaderValue = null; using (HttpMangler proxy = new HttpMangler(false, new ProxyBehavior[] { new ProxyBehavior(session => { retrievedHeaderValue = session.oRequest.headers[headerName]; }, selector, null, TriggerType.BeforeRequest) })) { act(); } Assert.AreEqual(headerValue, retrievedHeaderValue); }
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(ex.Message, "The operation timed out."); Assert.IsTrue(ex.InnerException is TimeoutException); } } }
internal static void ExecuteAPMMethodWithRetry <T>(int ExpectedAttempts, ProxyBehavior[] behaviors, Func <IRequestOptions, OperationContext, AsyncCallback, object, ICancellableAsyncResult> begin, Func <IAsyncResult, T> end) { string failMessage = null; OperationContext opContext = new OperationContext(); using (HttpMangler proxy = new HttpMangler(false, behaviors)) { Debug.WriteLine("Begin"); using (ManualResetEvent completedEvent = new ManualResetEvent(false)) { ICancellableAsyncResult saveResult = begin(null , opContext, (resp) => { try { Debug.WriteLine("End"); end(resp); } catch (Exception badEx) { failMessage = badEx.ToString(); } finally { completedEvent.Set(); } }, null); completedEvent.WaitOne(); TestHelper.AssertNAttempts(opContext, ExpectedAttempts); } } // Do not use IsNull here so that test result contains failMessage Assert.AreEqual(null, failMessage); }
internal static void ValidateIngressEgress(Func <Session, bool> selector, Func <RequestResult> act) { RequestResult res = null; long observedIngressBodyBytes = 0; long observedEgressBodyBytes = 0; bool isChunked = false; using (HttpMangler proxy = new HttpMangler(false, new ProxyBehavior[] { new ProxyBehavior(session => observedEgressBodyBytes += session.requestBodyBytes.Length, selector, null, TriggerType.BeforeRequest), new ProxyBehavior(session => { isChunked = session.oResponse.headers.ExistsAndContains("Transfer-Encoding", "chunked"); observedIngressBodyBytes += session.responseBodyBytes.Length; }, selector, null, TriggerType.AfterSessionComplete), })) { res = act(); } Assert.IsNotNull(res); // If chunked use more lenient evaluation if (isChunked) { Assert.IsTrue(res.IngressBytes < observedIngressBodyBytes); // 5 bytes for chunked encoded if (res.IngressBytes == 0) { Assert.IsTrue(observedIngressBodyBytes == 5); } } else { Assert.AreEqual(res.IngressBytes, observedIngressBodyBytes); } //TODO: HttpClient:Not supported //Assert.AreEqual(res.EgressBytes, observedEgressBodyBytes); }
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)) { 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)) })) { foreach (var options in new[] { new BlobRequestOptions() { ChecksumOptions = new ChecksumOptions { UseTransactionalMD5 = true, UseTransactionalCRC64 = false } }, new BlobRequestOptions() { ChecksumOptions = new ChecksumOptions { UseTransactionalMD5 = false, UseTransactionalCRC64 = true } } }) { using (MemoryStream downloadedBlob = new MemoryStream()) { OperationContext operationContext = new OperationContext(); 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 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(); } }