/// <summary> /// Helper function to set up an original entity and then run the **Throttle** Behavior against the specified storage account. /// </summary> /// <param name="entityPartitionKey"></param> /// <param name="entityRowKey"></param> /// <param name="targetStorageAccount">Specify which storage account to tamper with. 0 = Head; Count-1 = Tail</param> /// <param name="targetApi">Will call this RTable API while HttpMangler is enabled</param> /// <param name="targetApiExpectedToFail">True means the targetAPi is expected to fail when HttpMangler is enabled</param> /// <param name="checkOriginalEntityUnchanged">True means verify that the original entity (via GetRow()) is unchanged after this function.</param> /// <param name="checkStorageAccountsConsistent">True means verify that the individual storage accounts are consistent.</param> /// <param name="skipInitialSessions">Skip this many initial sessions. (Let them go through without being tampered)</param> protected void SetupAndRunDelayTableBehavior( string entityPartitionKey, string entityRowKey, int targetStorageAccount, TargetRTableWrapperApi<SampleRTableEntity> targetApi, bool targetApiExpectedToFail, bool checkOriginalEntityUnchanged, bool checkStorageAccountsConsistent, out DateTime httpManglerStartTime, int skipInitialSessions = 0) { Assert.IsTrue(0 <= targetStorageAccount && targetStorageAccount < this.actualStorageAccountsUsed.Count, "SetupAndRunDelayTableBehavior() is called with out-of-range targetStorageAccount={0}", targetStorageAccount); int index = this.actualStorageAccountsUsed[targetStorageAccount]; string accountNameToTamper = this.rtableTestConfiguration.StorageInformation.AccountNames[index]; Console.WriteLine("SetupAndRunDelayTableBehavior(): accountNameToTamper={0} skipInitialSessions={1}", accountNameToTamper, skipInitialSessions); // Throttle behavior ProxyBehavior[] behaviors = new[] { TamperBehaviors.TamperAllResponsesIf( DelayResponse, AzureStorageSelectors.TableTraffic().IfUrlContains(repTable.TableName)) }; // // Arrange and Act: // SampleRTableEntity originalEntity = this.SetupAndRunHttpManglerBehaviorHelper( entityPartitionKey, entityRowKey, behaviors, targetApi, targetApiExpectedToFail, out httpManglerStartTime); // // Assert: // if (checkOriginalEntityUnchanged) { // Validate originalEntity remain unchanged. this.ExecuteReadRowAndValidate(entityPartitionKey, entityRowKey, originalEntity); } // For debug purposes: read from the Head and Tail accounts, and check for consistency this.ReadFromIndividualAccountsDirectly(entityPartitionKey, entityRowKey, checkStorageAccountsConsistent); }
/// <summary> /// Helper function to set up an original entity and then run the **Tamper** Behavior against the specified storage account. /// This function takes a targetApi of this form: Func<string, string, SampleRTableEntity> targetApi /// </summary> /// <param name="entityPartitionKey"></param> /// <param name="entityRowKey"></param> /// <param name="targetStorageAccount"></param> /// <param name="targetApi"></param> /// <param name="targetApiExpectedToFail"></param> protected void SetupAndRunTamperTableBehavior( string entityPartitionKey, string entityRowKey, int targetStorageAccount, Func<string, string, SampleRTableEntity> targetApi, bool targetApiExpectedToFail, bool checkOriginalEntityUnchanged, bool checkStorageAccountsConsistent) { Assert.IsTrue(0 <= targetStorageAccount && targetStorageAccount < this.actualStorageAccountsUsed.Count, "SetupAndRunTamperTableBehavior() is called with out-of-range targetStorageAccount={0}", targetStorageAccount); int index = this.actualStorageAccountsUsed[targetStorageAccount]; string accountNameToTamper = this.rtableTestConfiguration.StorageInformation.AccountNames[index]; Console.WriteLine("SetupAndRunTamperTableBehavior(): accountNameToTamper={0}", accountNameToTamper); // Tamper behavior ProxyBehavior[] behaviors = new[] { TamperBehaviors.TamperAllRequestsIf( Actions.ThrottleTableRequest, AzureStorageSelectors.TableTraffic().IfHostNameContains(accountNameToTamper + ".")) }; // // Arrange and Act: // SampleRTableEntity originalEntity = this.SetupAndRunHttpManglerBehaviorHelper( entityPartitionKey, entityRowKey, behaviors, targetApi, targetApiExpectedToFail); // // Assert: // if (checkOriginalEntityUnchanged) { // Validate originalEntity remain unchanged. this.ExecuteReadRowAndValidate(entityPartitionKey, entityRowKey, originalEntity); } // For debug purposes: read from the Head and Tail accounts, and check for consistency this.ReadFromIndividualAccountsDirectly(entityPartitionKey, entityRowKey, checkStorageAccountsConsistent); }
/// <summary> /// Helper function to set up an original entity and then run the **Delay** Behavior against the specified storage account. /// </summary> /// <param name="entityPartitionKey"></param> /// <param name="entityRowKey"></param> /// <param name="targetStorageAccount">Specify which storage account to tamper with. 0 = Head; Count-1 = Tail</param> /// <param name="delayInMs">This much delay will be introduced to transmissions to the specified storage account.</param> /// <param name="targetApi">Will call this RTable API while HttpMangler is enabled</param> /// <param name="targetApiExpectedToFail">True means the targetAPi is expected to fail when HttpMangler is enabled</param> protected void SetupAndRunDelayTableBehavior( string entityPartitionKey, string entityRowKey, int targetStorageAccount, int delayInMs, TargetRTableWrapperApi<SampleRTableEntity> targetApi, bool targetApiExpectedToFail) { Assert.IsTrue(0 <= targetStorageAccount && targetStorageAccount < this.actualStorageAccountsUsed.Count, "SetupAndRunDelayTableBehavior() is called with out-of-range targetStorageAccount={0}", targetStorageAccount); int index = this.actualStorageAccountsUsed[targetStorageAccount]; string accountNameToTamper = this.rtableTestConfiguration.StorageInformation.AccountNames[index]; Console.WriteLine("SetupAndRunDelayTableBehavior(): accountNameToTamper={0}", accountNameToTamper); // Delay bahavior ProxyBehavior[] behaviors = new[] { DelayBehaviors.DelayAllRequestsIf( delayInMs, AzureStorageSelectors.TableTraffic().IfHostNameContains(accountNameToTamper + ".")) }; // // Arrange and Act: // DateTime httpManglerStartTime; SampleRTableEntity originalEntity = this.SetupAndRunHttpManglerBehaviorHelper( entityPartitionKey, entityRowKey, behaviors, targetApi, targetApiExpectedToFail, out httpManglerStartTime); // // Assert: // if (targetApiExpectedToFail) { // targetApi is expected to fail, so originalEntity should be untouched. this.ExecuteReadRowAndValidate(entityPartitionKey, entityRowKey, originalEntity); } else { // For debug purposes: read from the Head and Tail accounts, and check for consistency this.ReadFromIndividualAccountsDirectly(entityPartitionKey, entityRowKey, true); } }
/// <summary> /// Helper function to create some initial entities and then call the specified batchOperation with HttpMangler enabled. /// </summary> /// <param name="count"></param> /// <param name="jobType"></param> /// <param name="jobId"></param> /// <param name="targetStorageAccount"></param> /// <param name="opTypes"></param> /// <param name="targetApiExpectedToFail"></param> /// <param name="checkOriginalEntityUnchanged"></param> /// <param name="checkStorageAccountsConsistent"></param> /// <param name="httpManglerStartTime"></param> /// <param name="skipInitialSessions"></param> /// <returns>ParitionKey of the initial entities created</returns> protected string SetupAndRunTemperBatchOperation( int count, string jobType, string jobId, int targetStorageAccount, List<TableOperationType> opTypes, bool targetApiExpectedToFail, bool checkOriginalEntityUnchanged, bool checkStorageAccountsConsistent, out DateTime httpManglerStartTime, int skipInitialSessions = 0) { Assert.IsTrue(0 <= targetStorageAccount && targetStorageAccount < this.actualStorageAccountsUsed.Count, "SetupAndRunTemperBatchOperation() is called with out-of-range targetStorageAccount={0}", targetStorageAccount); int index = this.actualStorageAccountsUsed[targetStorageAccount]; string accountNameToTamper = this.rtableTestConfiguration.StorageInformation.AccountNames[index]; Console.WriteLine("SetupAndRunTemperBatchOperation(): accountNameToTamper={0} skipInitialSessions={1}", accountNameToTamper, skipInitialSessions); Assert.AreEqual(count, opTypes.Count, "count and opTypes.Count should be the same"); // // Tamper behavior // ProxyBehavior[] behaviors = new[] { TamperBehaviors.TamperAllRequestsIf( (session => { session.Abort();}), skipInitialSessions, AzureStorageSelectors.TableTraffic().IfHostNameContains(accountNameToTamper + ".")) }; string jobIdTemplate = jobId + "-{0}"; string messageTemplate = "message-{0}"; string updatedMessageTemplate = "updated-" + messageTemplate; string partitionKey = string.Empty; // // Insert entities // for (int i = 0; i < count; i++) { SampleRTableEntity originalEntity = new SampleRTableEntity( jobType, string.Format(jobIdTemplate, i), string.Format(messageTemplate, i)); this.repTable.Execute(TableOperation.Insert(originalEntity)); partitionKey = originalEntity.PartitionKey; } // // Retrieve entities and use them to create batchOperation to Replace or Delete // IEnumerable<SampleRTableEntity> allEntities = this.rtableWrapper.GetAllRows(partitionKey); TableBatchOperation batchOperation = new TableBatchOperation(); int m = 0; foreach (SampleRTableEntity entity in allEntities) { Console.WriteLine("{0}", entity.ToString()); Console.WriteLine("---------------------------------------"); if (opTypes[m] == TableOperationType.Replace) { SampleRTableEntity replaceEntity = new SampleRTableEntity( entity.JobType, entity.JobId, string.Format(updatedMessageTemplate, m)) { ETag = entity._rtable_Version.ToString() }; batchOperation.Replace(replaceEntity); } else if (opTypes[m] == TableOperationType.Delete) { entity.ETag = entity._rtable_Version.ToString(); batchOperation.Delete(entity); } else { throw new ArgumentException( string.Format("opType={0} is NOT supported", opTypes[m]), "opType"); } m++; } // // Enable HttpMangler // Call this.repTable.ExecuteBatch(batchOperation) // this.RunHttpManglerBehaviorHelper( batchOperation, behaviors, targetApiExpectedToFail, out httpManglerStartTime); if (checkOriginalEntityUnchanged) { Console.WriteLine("Validate originalEntity remain unchanged."); allEntities = this.rtableWrapper.GetAllRows(partitionKey); batchOperation = new TableBatchOperation(); m = 0; foreach (SampleRTableEntity entity in allEntities) { Console.WriteLine("{0}", entity.ToString()); Console.WriteLine("---------------------------------------"); Assert.AreEqual(string.Format(jobType, m), entity.JobType, "JobType does not match"); Assert.AreEqual(string.Format(jobIdTemplate, m), entity.JobId, "JobId does not match"); Assert.AreEqual(string.Format(messageTemplate, m), entity.Message, "Message does not match"); m++; } Console.WriteLine("Passed validation"); } // // After httpMangler is turned off, read from individual accounts... // Console.WriteLine("\nAfter httpMangler is turned off, read from individual accounts..."); for (int i = 0; i < count; i++) { this.ReadFromIndividualAccountsDirectly( jobType, string.Format(jobIdTemplate, i), checkStorageAccountsConsistent); } return partitionKey; }