static void PrintTest(Type lockType, ILockTest lockTest) { string lockName = lockType == null ? "No lock" : lockType.ToString(); Console.WriteLine("Lock: '{0}' - {1}\n\t\tDescription: {2}", lockName, lockTest.GetType().ToString(), lockTest.Description); }
static int Main(string[] args) { testParameters = new TestParameters(); testParameters.MaxWaitSeconds = 5; Type[] lockTypes = new Type[] { typeof(NoOpLock), typeof(SimpleSpinLock), typeof(LockTest.Synchronization.SpinLock), typeof(Lock) }; TestSpecification[] testSpecifications = new TestSpecification[] { new TestSpecification(typeof(UnbalancedCallTest), "Unbalanced calls"), new TestSpecification(typeof(AutoLockTest), "Automatic lock management"), new TestSpecification(typeof(ConcurrencyTest), ConcurrencyTest.Variant.Default, "Concurrent access - 2 threads"), new TestSpecification(typeof(ConcurrencyTest), ConcurrencyTest.Variant.ObjectLock, "Concurrent access - 2 threads"), new TestSpecification(typeof(ConcurrencyTest), ConcurrencyTest.Variant.ManyThreads, "Concurrent access - many threads"), new TestSpecification(typeof(ConcurrencyTest), ConcurrencyTest.Variant.BoundedWait, "Concurrent access - bounded wait sanity"), new TestSpecification(typeof(TimeoutTest), "Waits with maximum timeouts") }; if (args.Length > 0 && args[0] == "-?") { PrintUsage(lockTypes, testSpecifications); return -1; } int argStart = 0; if (args.Length > 0) { if (args[0] == "-t") { if (args.Length > 1) { testParameters.MaxWaitSeconds = int.Parse(args[1]); } else { PrintUsage(lockTypes, testSpecifications); return -1; } argStart+=2; } } bool[] variationMask = null; int variationsIncluded = lockTypes.Length * testSpecifications.Length; if (argStart < args.Length) { variationsIncluded = 0; variationMask = new bool[lockTypes.Length * testSpecifications.Length]; for (int argumentIndex = argStart; argumentIndex < args.Length; argumentIndex++) { uint variationIndex = 0; bool invalidIndex = false; try { variationIndex = uint.Parse(args[argumentIndex]); } catch (FormatException) { invalidIndex = true; } if (!invalidIndex && variationIndex >= variationMask.Length) { invalidIndex = true; } if (invalidIndex) { Console.WriteLine("{0} is not a valid integer test variation", args[argumentIndex]); PrintUsage(lockTypes, testSpecifications); return -1; } variationMask[variationIndex] = true; variationsIncluded++; } } List<Thread> testThreads = new List<Thread>(); Dictionary<Thread, ILockTest> threadToTestMap = new Dictionary<Thread, ILockTest>(); int currentVariationIndex = 0; foreach (Type lockType in lockTypes) { ISyncLock syncLock = (ISyncLock)CreateTypeInstance(lockType); foreach (TestSpecification testSpecification in testSpecifications) { int thisVariationIndex = currentVariationIndex++; if (variationMask != null && !variationMask[thisVariationIndex]) { continue; } ILockTest test = CreateTest(testSpecification.TestType, testSpecification.Parameters); Console.WriteLine("Testing: {3}: {0} - Variation: {1}: {2}", (syncLock == null) ? "No lock" : syncLock.ToString(), test, test.Description, thisVariationIndex); test.Initialize(); currentTest = test; Thread testThread = new Thread(TestThread); testThreads.Add(testThread); threadToTestMap.Add(testThread, test); testThread.Start(syncLock); int testWaitTime = testParameters.MaxWaitSeconds * 2; bool completedInTime = testThread.Join(testWaitTime * 1000); if (!completedInTime) { if (null == lastTestException) { lastTestException = new TimeoutException(string.Format("Variation failed to complete within {0} seconds", testWaitTime)); } } if (lastTestException != null) { Console.Error.WriteLine("Error: {0}: {1}", lastTestException.GetType(), lastTestException.Message); failedTests++; Console.WriteLine("FAILED: {0} - Variation: {1}", syncLock == null ? "No lock" : syncLock.ToString(), currentTest); continue; } passedTests++; Console.WriteLine("PASSED: {0} - Variation: {1}", syncLock, test); } } Console.WriteLine("\t{0} passed, {1} failed, {2} skipped, {3} total", passedTests, failedTests, lockTypes.Length * testSpecifications.Length - variationsIncluded, lockTypes.Length * testSpecifications.Length); if (failedTests == 0) { Console.WriteLine("Success -- all variations passed."); } else { Console.WriteLine("Failure -- one or more variations failed"); } foreach (Thread testThread in testThreads) { Console.WriteLine("Thread id: {0}, State: {1}", testThread.ManagedThreadId, testThread.ThreadState.ToString()); if (testThread.ThreadState == ThreadState.Running || testThread.ThreadState == ThreadState.WaitSleepJoin) { ILockTest runningTest = threadToTestMap[testThread]; Console.WriteLine("Unfinished test will be forcibly terminated: {0}: {1}", runningTest.GetType().ToString(), runningTest.Description); testThread.Abort(); } } int exitCode = ( failedTests == 0 ) ? 0 : 1; Console.WriteLine("Exiting test with {0}\n", exitCode); return exitCode; }