summaryrefslogtreecommitdiff
path: root/tests/Dynamic_Priority_Test.cpp
diff options
context:
space:
mode:
authorcdgill <cdgill@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1998-06-30 23:11:15 +0000
committercdgill <cdgill@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1998-06-30 23:11:15 +0000
commit2563dc28b95fb2b39b7014f5daa3176e26350b62 (patch)
treeb45b77cecc23d206426ec9009ce6474bead95fce /tests/Dynamic_Priority_Test.cpp
parentb19b4e76bf1355568553bea0f5a4b5df4a83e074 (diff)
downloadATCD-2563dc28b95fb2b39b7014f5daa3176e26350b62.tar.gz
Dynamic Priority Queue test
Diffstat (limited to 'tests/Dynamic_Priority_Test.cpp')
-rw-r--r--tests/Dynamic_Priority_Test.cpp284
1 files changed, 284 insertions, 0 deletions
diff --git a/tests/Dynamic_Priority_Test.cpp b/tests/Dynamic_Priority_Test.cpp
new file mode 100644
index 00000000000..503e165881e
--- /dev/null
+++ b/tests/Dynamic_Priority_Test.cpp
@@ -0,0 +1,284 @@
+// $Id$
+//
+// ============================================================================
+//
+// = LIBRARY
+// tests
+//
+// = FILENAME
+// Dynamic_Priority_Test.cpp (based on Priority_Buffer_Test.cpp)
+//
+// = DESCRIPTION
+// This is a test to verify and illustrate the static and dynamic
+// priority mechanisms of the ACE_Message_Queue class and the
+// ACE_Dynamic_Message_Queue class. As in the Priority_Buffer_Test,
+// a producer generates messages and enqueues them, and a consumer
+// dequeues them and checks their ordering.
+//
+// In these tests, every effort is made to ensure that there is plenty
+// of time for the messages to be enqueued and dequeued, with messages
+// that *should* meet their deadlines actually meeting them,
+// while messages that should miss their deadlines are delayed
+// so that they actually miss them. It is, however, remotely
+// possible that this test could yield a false negative:
+// the dynamic queues could work correctly but due to timing
+// variations the test could indicate failure.
+//
+// Three message queues are obtained from the message queue factory,
+// one static, two dynamic (one deadline based, and one laxity based)
+// and the same supplier behavior is used each time: the messages
+// are preallocated and their static information valued, the current
+// time is obtained and deadlines are set, with half of the messages
+// given late deadlines, and the other half of the messages given
+// reachable deadlines. The producer then immediately enqueues all
+// messages.
+//
+// In each test, the consumer is passed the filled queue and a string with
+// the expected order in which the messages should dequeue.
+//
+// = AUTHOR
+// Chris Gill
+//
+// ============================================================================
+
+#include "ace/Message_Queue.h"
+#include "ace/Thread_Manager.h"
+#include "test_config.h"
+
+#if defined(__BORLANDC__) && __BORLANDC__ >= 0x0530
+USELIB("..\ace\aced.lib");
+//---------------------------------------------------------------------------
+#endif /* defined(__BORLANDC__) && __BORLANDC__ >= 0x0530 */
+
+// structure used to pass arguments to test functions
+
+struct ArgStruct
+{
+ ACE_Message_Queue<ACE_MT_SYNCH> *queue_;
+ const char *order_string_;
+ ACE_Message_Block **array_;
+};
+
+// order in which messages are sent
+static const char send_order [] = "abcdefghijklmnop";
+
+// order in which messages are received with static prioritization
+static const char static_receipt_order [] = "ponmlkjihgfedcba";
+
+// order in which messages are received with deadline prioritization
+static const char deadline_receipt_order [] = "hgfedcbaponmlkji";
+
+// order in which messages are received with laxity prioritization
+static const char laxity_receipt_order [] = "hfgedbcapnomljki";
+
+// fast and slow execution time values (sec, usec)
+static const ACE_Time_Value fast_execution (0, 10);
+static const ACE_Time_Value slow_execution (0, 100);
+
+// Make the queue be capable of being *very* large.
+static const long max_queue = LONG_MAX;
+
+// The consumer dequeues a message from the passed Message_Queue,
+// and checks its data character against the passed string of characters
+// which has the expected ordering. The supplier and consumer do not
+// allocate or deallocate messages, to avoid timing delays and timing
+// jitter in the test: the main function is responsible for all
+// initialization allocation and cleanup before, between, and after
+// (but not during) the transfer of messages from the supplier to the
+// consumer.
+
+static void *
+consumer (void * args)
+{
+ ACE_ASSERT (args != 0);
+
+ ACE_Message_Queue<ACE_MT_SYNCH> *msg_queue = ((ArgStruct *) args)->queue_;
+ const char *receipt_order = ((ArgStruct *) args)->order_string_;
+
+ ACE_ASSERT (receipt_order != 0);
+ ACE_ASSERT (msg_queue != 0);
+
+ u_int local_count = 0;
+
+ // Keep looping, reading a message out of the queue, until we
+ // reach the end of the receipt order string, which signals us to quit.
+ for (const char *expected = receipt_order; *expected != '\0'; ++expected)
+ {
+ ACE_Message_Block *mb = 0;
+
+ int result = msg_queue->dequeue_head (mb);
+
+ if (result == -1)
+ break;
+
+ local_count++;
+
+ ACE_ASSERT (*expected == *mb->rd_ptr ());
+ }
+
+ ACE_ASSERT (local_count == ACE_OS::strlen (receipt_order));
+ return 0;
+}
+
+// The producer runs through the passed send string, setting the read
+// pointer of the current message to the current character position in
+// the string, and then queueing the message in the message list, where
+// it is removed by the consumer thread.
+
+static void *
+producer (void *args)
+{
+ ACE_ASSERT (args != 0);
+
+ ACE_Message_Queue<ACE_MT_SYNCH> *msg_queue = ((ArgStruct *) args)->queue_;
+ const char *send_order = ((ArgStruct *) args)->order_string_;
+ ACE_Message_Block **block_array = ((ArgStruct *) args)->array_;
+
+ ACE_ASSERT (send_order != 0);
+ ACE_ASSERT (block_array != 0);
+
+ // iterate through the send order string and the message block array,
+ // setting the current message block's read pointer to the current
+ // position in the send order string.
+ int local_count;
+ const char *c;
+ for (local_count = 0, c = send_order; *c != '\0'; ++local_count, ++c)
+ {
+ // point to the current message block
+ ACE_Message_Block *mb = block_array [local_count];
+ ACE_ASSERT (mb != 0);
+
+ // Set the current send character in the current message block
+ // at its read pointer position, and adjust the write pointer
+ *mb->rd_ptr () = *c;
+ mb->wr_ptr (1);
+
+ // Enqueue the message block in priority order.
+ if (msg_queue->enqueue_prio (mb) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ASYS_TEXT ("(%t) %p\n"), ASYS_TEXT ("put_next")), 0);
+ }
+
+ return 0;
+}
+
+
+int run_test (ACE_Message_Queue<ACE_MT_SYNCH>* msg_queue, const char *send_order, const char *receipt_order)
+{
+ u_int i = 0;
+ u_int array_size = ACE_OS::strlen (send_order);
+
+ ACE_ASSERT (msg_queue != 0);
+ ACE_ASSERT (send_order != 0);
+ ACE_ASSERT (receipt_order != 0);
+ ACE_ASSERT (ACE_OS::strlen (send_order) == ACE_OS::strlen (receipt_order));
+
+ ArgStruct supplier_args, consumer_args;
+
+ supplier_args.queue_ = msg_queue;
+ supplier_args.order_string_ = send_order;
+
+ // allocate message blocks, fill in pointer array, set static information
+ ACE_NEW_RETURN (supplier_args.array_, ACE_Message_Block * [array_size], -1);
+ for (i = 0; i < array_size; ++i)
+ {
+ // construct a message new block off the heap, to hold a single character
+ ACE_NEW_RETURN (supplier_args.array_[i], ACE_Message_Block (1), -1);
+
+ // assign static (minimal) message priority in ascending order
+ supplier_args.array_[i]->msg_priority (i);
+
+ // assign every other message short or long execution time
+ supplier_args.array_[i]->msg_execution_time (((i % 2) ? slow_execution : fast_execution));
+ }
+
+ consumer_args.queue_ = msg_queue;
+ consumer_args.order_string_ = receipt_order;
+ consumer_args.array_ = 0;
+
+ // Construct pending and late absolute deadline times.
+
+ ACE_Time_Value current_time (0, 0);
+ ACE_Time_Value future_deadline (1, 0);
+ ACE_Time_Value near_deadline (0, 500000);
+ ACE_Time_Value recent_deadline (0, -1);
+ ACE_Time_Value past_deadline (0, -500000);
+
+ current_time = ACE_OS::gettimeofday ();
+
+ future_deadline += current_time;
+ near_deadline += current_time;
+ recent_deadline += current_time;
+ past_deadline += current_time;
+
+ // Set absolute time of deadline associated with the message.
+ for (i = 0; i < array_size; ++i)
+ {
+ switch ((4*i)/array_size)
+ {
+ case 0:
+ supplier_args.array_[i]->msg_deadline_time (future_deadline);
+ break;
+
+ case 1:
+ supplier_args.array_[i]->msg_deadline_time (near_deadline);
+ break;
+
+ case 2:
+ supplier_args.array_[i]->msg_deadline_time (recent_deadline);
+ break;
+
+ case 3:
+ supplier_args.array_[i]->msg_deadline_time (past_deadline);
+ break;
+
+ // should never reach here, but its better to make sure
+ default:
+ ACE_ASSERT ((4*i)/array_size < 4);
+ break;
+ }
+ }
+
+ // run the producer
+ producer (&supplier_args);
+
+ // run the consumer
+ consumer (&consumer_args);
+
+ // free all the allocated message blocks
+ for (i = 0; i < array_size; ++i)
+ {
+ delete supplier_args.array_[i];
+ }
+
+ // free the allocated pointer array
+ delete [] supplier_args.array_;
+
+ return 0;
+}
+
+
+int
+main (int, ASYS_TCHAR *[])
+{
+ ACE_START_TEST (ASYS_TEXT ("Dynamic_Priority_Test"));
+
+ ACE_Message_Queue<ACE_MT_SYNCH> *test_queue = 0;
+
+ test_queue = ACE_Message_Queue_Factory<ACE_MT_SYNCH>::create_static_message_queue (max_queue);
+ run_test (test_queue, send_order, static_receipt_order);
+ delete test_queue;
+
+ test_queue = ACE_Message_Queue_Factory<ACE_MT_SYNCH>::create_deadline_message_queue (max_queue);
+ run_test (test_queue, send_order, deadline_receipt_order);
+ delete test_queue;
+
+ test_queue = ACE_Message_Queue_Factory<ACE_MT_SYNCH>::create_laxity_message_queue (max_queue);
+ run_test (test_queue, send_order, laxity_receipt_order);
+ delete test_queue;
+
+ ACE_END_TEST;
+ return 0;
+}
+
+
+