public void RandomTests_ParallelSessionsProfile() { try { Utility.WrapNativeSyncInvokeInMTA(() => { try { // Number of parallel sessions tests const int sessionCount = 100; // Instantiate multiple test sessions. SessionTest[] sessionTests = new SessionTest[sessionCount]; // Number of service instances const int instanceCount = 5; // Instantiate the required service instances. InstanceRecord[] instances = new InstanceRecord[instanceCount]; // Max number of partition per instance const int maxPartitionsPerInstance = 3; // If Partition type is int64 range, than use this to set the low value range const int int64PartitionKeyLowValMultiplier = 10000; // Initialize Service Instances and randomly allocate partitions for each. InitializeInstances(instances, true, maxPartitionsPerInstance); // Initialize Partitions and respective reliable sessions foreach (InstanceRecord instance in instances) { InitializePartitions(instance, true, new PartitionKeyType(), int64PartitionKeyLowValMultiplier); foreach (PartitionRecord partition in instance.Partitions) { this.InitializeReliableSessions(instance.InstanceName, partition); } } // Min Segment Size to set the boundaries for random segment size const int minSegmentSize = 100; // Max Segment Size to set the boundaries for random segment size const int maxSegmentSize = 499; // Min Message count to set the boundaries for random messages per session const int minMessageCountPerSession = 500; // Min Message count to set the boundaries for random messages per session const int maxMessageCountPerSession = 2500; // Wait for send Segment Wait In MilliSeconds Per Message const int waitPerMessage = 1000; // in milliseconds // Dictionary of unique pairs of inbound and outbound sessions Dictionary <string, string> checkForUniqueness = new Dictionary <string, string>(); // Initialize and Setup the session tests by randomly selecting message sizes and abort sessions. for (int i = 0; i < sessionCount; i++) { // Pick a random Source Partition and Target Partition and setup the session test between them PartitionRecord sourcePartitionRecord = GetRandomPartitionRecord(instances); PartitionRecord targetPartitionRecord = GetRandomPartitionRecord(instances); if (!String.Equals(sourcePartitionRecord.PartitionKey, targetPartitionRecord.PartitionKey)) { int segmentSize = RandGen.Next(minSegmentSize, maxSegmentSize); int messageCount = RandGen.Next(minMessageCountPerSession, maxMessageCountPerSession); SessionTest sessionTest = new SessionTest(segmentSize, messageCount, waitPerMessage, i); SetupSessionTest(sessionTest, sourcePartitionRecord, targetPartitionRecord); // Check if it's an unique test session combination before adding it to the test sessions. if ( checkForUniqueness.ContainsKey(sourcePartitionRecord.PartitionKey + targetPartitionRecord.PartitionKey)) { sessionTest.SkipTest = true; } else { checkForUniqueness.Add( sourcePartitionRecord.PartitionKey + targetPartitionRecord.PartitionKey, ""); LogHelper.Log("SessionId: {0}; Unique Partitions: s: {1} t: {2}", sessionTest.SessionId, sourcePartitionRecord.PartitionKey, targetPartitionRecord.PartitionKey); } sessionTests[i] = sessionTest; } else { i--; } } // Randomly start the tests in parallel const int maxTestDelay = sessionCount * 10; // Cache all run test() in an action delegate array with random delay starts Action[] testActions = sessionTests.Select( element => (element.SkipTest) ? null : new Action(() => element.RunTest(RandGen.Next() % maxTestDelay))) .ToArray(); // Create and start tasks for all non skipped tests Task[] tempTestTasksToRun = testActions .Where(element => element != null) .Select(element => Task.Factory.StartNew(element)).ToArray(); LogHelper.Log("Total number of Tests started = {0}", tempTestTasksToRun.Count()); Task.WaitAll(tempTestTasksToRun); LogHelper.Log("Total number of Tests {0} ran to completion.", tempTestTasksToRun.Count()); } catch (Exception ex) { LogHelper.Log("Caught Exception: {0}", ex); throw; } }, "MultipleParallelSessions"); } catch (Exception e) { VS.Assert.IsTrue(false, "Unexpected exception {0} during RandomTests_ParallelSessionsProfile()", e.ToString()); } }
/// <summary> /// Setup a session from source partition to target partition. /// </summary> /// <param name="sessionTest"></param> /// <param name="sourcePartition"></param> /// <param name="targetPartition"></param> private void SetupSessionTest(SessionTest sessionTest, PartitionRecord sourcePartition, PartitionRecord targetPartition) { VS.Assert.IsFalse(sourcePartition == targetPartition, "sourcePartition {0} equals targetPartition {1} in SetupSessionTests", sourcePartition, targetPartition); IReliableSessionManager sourceSessionManager = sourcePartition.SessionManager; Uri targetSvcInstance = targetPartition.InstanceName; string targetEndpoint = targetPartition.Endpoint; Task <IReliableMessagingSession> newOutboundSessionTask = null; bool testSkipped = false; try { // Setup the outbound session from source to target partition switch (targetPartition.PartitionType) { case PartitionKeyType.Singleton: newOutboundSessionTask = sourceSessionManager.CreateOutboundSessionAsync(targetSvcInstance, targetEndpoint, new CancellationToken()); break; case PartitionKeyType.StringKey: string targetStringKey = targetPartition.StringPartitionPartitionKey; newOutboundSessionTask = sourceSessionManager.CreateOutboundSessionAsync(targetSvcInstance, targetStringKey, targetEndpoint, new CancellationToken()); break; case PartitionKeyType.Int64Key: IntegerPartitionKeyRange targetInt64Key = targetPartition.Int64PartitionPartitionKey; long rangeSize = targetInt64Key.IntegerKeyHigh - targetInt64Key.IntegerKeyLow + 1; long targetPartitionNumber = targetInt64Key.IntegerKeyLow + (RandGen.Next() % rangeSize); newOutboundSessionTask = sourceSessionManager.CreateOutboundSessionAsync(targetSvcInstance, targetPartitionNumber, targetEndpoint, new CancellationToken()); break; } VS.Assert.IsNotNull(newOutboundSessionTask, "Null newOutboundSessionTask in SetupSessionTests"); newOutboundSessionTask.Wait(); sessionTest.OutboundSession = newOutboundSessionTask.Result; } catch (System.AggregateException e) { Exception inner = e.InnerException.InnerException; VS.Assert.AreEqual(inner.GetType(), typeof(System.Runtime.InteropServices.COMException), "Unexpected AggregateException {0} from CreateOutboundSessionAsync", inner.GetType().ToString()); // Due to random nature of source and target selection, it might be possible we create a duplicate selection. // in this case, we skip the test. System.Runtime.InteropServices.COMException realException = (System.Runtime.InteropServices.COMException)inner; uint hresult = (uint)realException.ErrorCode; uint expectedError = (uint)NativeTypes.FABRIC_ERROR_CODE.FABRIC_E_RELIABLE_SESSION_ALREADY_EXISTS; VS.Assert.AreEqual(expectedError, hresult, "Unexpected error HRESULT code {0} from CreateOutboundSessionAsync", hresult); testSkipped = true; LogHelper.Log("Test# skipped due to {0} exception ", hresult); } if (testSkipped) { sessionTest.SkipTest = true; } else { // initialize snapshot test and open the session for message communication. sessionTest.OutboundSession.OpenAsync(new CancellationToken()).Wait(); sessionTest.InboundSession = targetPartition.InboundSessions[sourcePartition.PartitionKey]; sessionTest.SnapshotOutbound = sessionTest.OutboundSession.GetDataSnapshot(); sessionTest.SnapshotInbound = sessionTest.InboundSession.GetDataSnapshot(); VS.Assert.IsFalse(sessionTest.InboundSession == sessionTest.OutboundSession, "sourcePartition equals targetPartition in SetupSessionTests"); } }