public UnitTestThread(ThreadQueue readFrom, ThreadQueue writeTo, TimeSpan toWait, int numItems) { m_from = readFrom; m_to = writeTo; m_numItems = Math.Max(1, numItems); m_toWait = toWait; }
public void Add(String key, ThreadQueue value) { Dictionary.Add(key, value); }
public UnitTestThread(ThreadQueue readFrom, ThreadQueue writeTo) { m_from = readFrom; m_to = writeTo; }
// public static void Main( string[] args ) // { // // if ( args != null && args.Length > 0 ) // { // foreach( string arg in args ) // { // switch( arg ) // { // // case "-unittest": // // // // Unit test // // // Environment.Exit( ThreadQueue.UnitTest() ) ; // break ; // // default: // Console.WriteLine("Error: unknown argument {0}", arg ) ; // break ; // } // } // } // } public static int UnitTest() { // Generic item to produce random values Random rand = new Random(); string testDescription = string.Format( "***\n" + "*** Unit test to ensure that an item only comes off of the queue once, not\n" + "*** multiple times for each Remove() operation\n" + "***\n"); Console.WriteLine(testDescription); ArrayList allThreads = new ArrayList(); ArrayList consumers = new ArrayList(); ThreadQueue startQueue = new ThreadQueue(); ThreadQueue feedQueue = new ThreadQueue(); feedQueue.HighWater = rand.Next(11, 250); feedQueue.LowWater = rand.Next(1, feedQueue.HighWater); feedQueue.EnableHighWater = true; // Create a queue, and start running against it for (int i = 0; i < rand.Next(7, 23); i++) { UnitTestThread feeder = new UnitTestThread(startQueue, feedQueue, new TimeSpan(Timeout.Infinite), rand.Next(1, 100)); Thread feederThread = new Thread(new ThreadStart(feeder.Start)); feederThread.Name = string.Format("Feeder {0}", i); feedQueue.AddProducer(feederThread); allThreads.Add(feederThread); } for (int i = 0; i < rand.Next(2, 7); i++) { // Note:, the first thread will always do one item at a time int numItems = i == 0 ? 1 : rand.Next(2, 23); TimeSpan toWait = i == 0 ? new TimeSpan(Timeout.Infinite) : new TimeSpan(0, 0, 0, 0, rand.Next(10, 10 * 1000)); UnitTestThread consumer = new UnitTestThread(feedQueue, null, toWait, numItems); Thread consumerThread = new Thread(new ThreadStart(consumer.Start)); consumerThread.Name = string.Format("Consumer: {0}, numPerCall: {1}, toWait: {2}", i, numItems, toWait); consumers.Add(consumer); allThreads.Add(consumerThread); } // Queue up some items int totalItems = rand.Next(10 * 1000, 20 * 1000); Console.WriteLine("Total items to process: {0}", totalItems); for (int i = 0; i < totalItems; i++) { startQueue.Add(i, false); } foreach (Thread thd in allThreads) { Console.WriteLine("Starting thread: {0}...", thd.Name); thd.Start(); } // Wait for all the threads to finish bool isAlive = false; do { Console.WriteLine( "StartQueue: {0} items, FeedQueue: {1} (LowWater: {2}, HighWater: {3})", startQueue.Count, feedQueue.Count, feedQueue.LowWater, feedQueue.HighWater); isAlive = false; foreach (Thread thd in allThreads) { isAlive |= thd.IsAlive; if (isAlive) { break; } } if (isAlive) { Thread.Sleep(2 * 1000); } }while(isAlive); Console.WriteLine( "*Finished: StartQueue: {0} items, FeedQueue: {1}", startQueue.Count, feedQueue.Count); Console.WriteLine("Consumer counts: "); long consumerCount = 0; foreach (UnitTestThread consumer in consumers) { Console.WriteLine("\t{0} items", consumer.NumProcessed); consumerCount += consumer.NumProcessed; } if (consumerCount != totalItems) { Console.WriteLine("***\n" + "*** Failed test, consumers consumed {0} of {1} items\n" + "***\n", consumerCount, totalItems); } else { Console.WriteLine("***\n" + "*** Passed test, consumers consumed {0} of {1} items\n" + "***\n", consumerCount, totalItems); } // // Unit test for items flowing from one Queue to another to make sure all the // items get from the head to the tail // // Create several queues to shuffle the objects along ThreadQueue[] queues = new ThreadQueue[rand.Next(5, 15)]; for (int i = 0; i < queues.Length; i++) { queues[i] = new ThreadQueue(); } Console.WriteLine("* Created {0} queues", queues.Length); // Prime the first queue with some objects totalItems = rand.Next(10, 20000); for (int i = 0; i < totalItems; i++) { queues[0].Add(rand.Next(-10000, -1000).ToString(), false); } Console.WriteLine("* Primed the first queue with {0} items", totalItems); ArrayList allThds = new ArrayList(); Console.Write("* Threads per queue (queue number: thread count):\n*"); // Setup threads to read from the queues and write to the next queue for (int i = 0; i < queues.Length - 1; i++) { int numThds; // Create at a minimum of threads reading from each queue for (numThds = 0; numThds < rand.Next(5, 30); numThds++) { ThreadQueue fromQueue = queues[i]; ThreadQueue toQueue = (i == queues.Length) ? null : queues[i + 1]; UnitTestThread test = new UnitTestThread(fromQueue, toQueue); // Create the thread Thread thd = new Thread(new ThreadStart(test.Start)); thd.Name = String.Format("{0} -> {1}", i, i + 1); if (i == 1) { // Make this thread a producer of itself fromQueue.AddProducer(thd); } // Set the thread as a producer for the next queue toQueue.AddProducer(thd); allThds.Add(thd); } // // Add one loop that continually takes and item from it's queue and // // places it back up the stream some where // // int earlier = rand.Next( 0, i - 1 ) ; // readFromOwn = new UnitTestThread( queues[i], queues[i+1], queues[ earlier ] ); // loop = new Thread( new ThreadStart(readFromOwn.Start ) ) ; // loop.Name = String.Format("{0} -> {1}", i, earlier ) ; // allThds.Add( loop ) ; // // numThds++ ; Console.Write(" {0}:{1},", i, numThds); } Console.WriteLine(""); // Disable the high water on the last queue queues[queues.Length - 1].EnableHighWater = false; // Start all the threads foreach (Thread thd in allThds) { thd.Start(); } DateTime endTime = DateTime.Now + new TimeSpan(0, 10, 0); // Wait for all of the elements to end up in the last queue while (queues[queues.Length - 1].Count < totalItems && DateTime.Now < endTime) { Thread.Sleep(5000); Console.WriteLine("* {0} of {1} items have arrived in the final queue (#{2})", queues[queues.Length - 1].Count, totalItems, queues.Length - 1); } int waitingThreads = 0; // Kill all of the threads foreach (Thread thd in allThds) { thd.Join(new TimeSpan(0, 0, 5)); if (thd.IsAlive) { if ((thd.ThreadState & System.Threading.ThreadState.WaitSleepJoin) != 0) { waitingThreads++; } thd.Abort(); } } int itemsProcessed = queues[queues.Length - 1].Count; if (itemsProcessed != totalItems || waitingThreads != 0) { Console.WriteLine("* Failed test, only {0} of {1} items were processed " + " and {2} of {3} threads were waiting", itemsProcessed, totalItems, waitingThreads, allThds.Count); } else { Console.WriteLine("* Passed test, final queue has {0} of {1} items, " + "{2} of {3} threads were waiting", itemsProcessed, totalItems, waitingThreads, allThds.Count); } int toReturn = (itemsProcessed == totalItems) ? 0 : -1; return(toReturn); }