/// <summary> /// Create service instances. /// </summary> /// <param name="instances">Create and initialize the service instances</param> /// <param name="isRandomNumberOfPartitions">True if random number of Partitions (less than or equal to max number of partitions) per instance, false initialize max number of partitions</param> /// <param name="numOfPartitionsPerInstance">Number of partitions per instance</param> static void InitializeInstances(InstanceRecord[] instances, bool isRandomNumberOfPartitions, int numOfPartitionsPerInstance) { for (int instanceIndex = 0; instanceIndex < instances.Count(); instanceIndex++) { Uri instanceName = new Uri("fabric:/test/svcInstance/" + instanceIndex); // Initialize partitions int partitionCount = numOfPartitionsPerInstance; if (isRandomNumberOfPartitions) { partitionCount = RandGen.Next(1, numOfPartitionsPerInstance); } instances[instanceIndex] = new InstanceRecord(instanceName, partitionCount); } }
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> /// Create and Initialize partitions for the given service instance . /// </summary> /// <param name="instance">Initialize partitions for this service instance</param> /// <param name="isRandomPartitionType">true - if the partition type is selected randomly - String or Int64</param> /// <param name="type">Set the partition type to this parameter, if isRandomPartitionType is false. /// Singleton type is not allowed as we will set this type if instance partitions count = 1</param> /// <param name="int64PartitionKeyLowValMultiplier"></param> static void InitializePartitions(InstanceRecord instance, bool isRandomPartitionType, PartitionKeyType type, int int64PartitionKeyLowValMultiplier) { // Singletone is not a valid type VS.Assert.IsTrue(type != PartitionKeyType.Singleton, "unexpected partition key type {0} in StartSessionManagersForServiceInstance", type); // Ensure we have a valid partitions count > 0 Uri instanceName = instance.InstanceName; int partitionCount = instance.CountOfPartitions; VS.Assert.IsTrue(partitionCount > 0, "unexpected partitionCount {0} in StartSessionManagersForServiceInstance", partitionCount); // singleton case if (partitionCount == 1) { PartitionRecord newPartition = new PartitionRecord( instanceName, PartitionKeyType.Singleton, null, new IntegerPartitionKeyRange()); instance.Partitions[0] = newPartition; return; } bool stringPartitions = false; // randomly allocate string or int64 partition type. if (isRandomPartitionType) { stringPartitions = (RandGen.Next() % 2) == 0; // decide if we have string or int64 partitions } else { if (type == PartitionKeyType.StringKey) { stringPartitions = true; } } for (int i = 0; i < partitionCount; i++) { PartitionRecord newPartition; if (stringPartitions) { // string partition key string partitionKey = i.ToString(CultureInfo.InvariantCulture); newPartition = new PartitionRecord( instanceName, PartitionKeyType.StringKey, partitionKey, new IntegerPartitionKeyRange()); instance.Partitions[i] = newPartition; LogHelper.Log("Created; Instance: {0} StringPartition: {1}", instanceName, partitionKey); } // numerical partition key -- single number range IntegerPartitionKeyRange partitionInt64Key = new IntegerPartitionKeyRange { IntegerKeyLow = i * int64PartitionKeyLowValMultiplier, IntegerKeyHigh = i * int64PartitionKeyLowValMultiplier + (RandGen.Next() % (int64PartitionKeyLowValMultiplier - 1)) }; newPartition = new PartitionRecord( instanceName, PartitionKeyType.Int64Key, null, partitionInt64Key); instance.Partitions[i] = newPartition; LogHelper.Log("Created; Instance: {0} Int64Partition: {1}-{2}", instanceName, partitionInt64Key.IntegerKeyLow, partitionInt64Key.IntegerKeyHigh); } }
public static PartitionRecord GetRandomPartitionRecord(InstanceRecord[] instances) { InstanceRecord randomInstanceRecord = instances[RandGen.Next(instances.Count())]; return(randomInstanceRecord.Partitions[RandGen.Next(randomInstanceRecord.CountOfPartitions)]); }