1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/thread/queue.cpp
3 // Purpose: Unit test for wxMessageQueue
4 // Author: Evgeniy Tarassov
7 // Copyright: (c) 2007 Evgeniy Tarassov
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 // ----------------------------------------------------------------------------
13 // ----------------------------------------------------------------------------
22 #include "wx/dynarray.h"
23 #include "wx/thread.h"
26 #include "wx/msgqueue.h"
28 // ----------------------------------------------------------------------------
30 // ----------------------------------------------------------------------------
32 class QueueTestCase
: public CppUnit::TestCase
44 typedef wxMessageQueue
<int> Queue
;
46 // This class represents a thread that waits (following WaitTestType type)
47 // for exactly maxMsgCount messages from its message queue and if another
48 // MyThread is specified, then every message received is posted
49 // to that next thread.
50 class MyThread
: public wxThread
53 MyThread(WaitTestType type
, MyThread
*next
, int maxMsgCount
)
54 : wxThread(wxTHREAD_JOINABLE
),
55 m_type(type
), m_nextThread(next
), m_maxMsgCount(maxMsgCount
)
58 // thread execution starts here
59 virtual void *Entry();
61 // Thread message queue
69 MyThread
* m_nextThread
;
74 WX_DEFINE_ARRAY_PTR(MyThread
*, ArrayThread
);
76 CPPUNIT_TEST_SUITE( QueueTestCase
);
77 CPPUNIT_TEST( TestReceive
);
78 CPPUNIT_TEST( TestReceiveTimeout
);
79 CPPUNIT_TEST_SUITE_END();
82 void TestReceiveTimeout();
84 DECLARE_NO_COPY_CLASS(QueueTestCase
)
87 // register in the unnamed registry so that these tests are run by default
88 CPPUNIT_TEST_SUITE_REGISTRATION( QueueTestCase
);
90 // also include in it's own registry so that these tests can be run alone
91 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( QueueTestCase
, "QueueTestCase" );
93 // this function creates the given number of threads and posts msgCount
94 // messages to the last created thread which, in turn, posts all the messages
95 // it receives to the previously created thread which does the same and so on
96 // in cascade -- at the end, each thread will have received all msgCount
97 // messages directly or indirectly
98 void QueueTestCase::TestReceive()
100 const int msgCount
= 100;
101 const int threadCount
= 10;
106 for ( i
= 0; i
< threadCount
; ++i
)
108 MyThread
*previousThread
= i
== 0 ? NULL
: threads
[i
-1];
110 new MyThread(WaitInfinitlyLong
, previousThread
, msgCount
);
112 CPPUNIT_ASSERT_EQUAL ( thread
->Create(), wxTHREAD_NO_ERROR
);
116 for ( i
= 0; i
< threadCount
; ++i
)
121 MyThread
* lastThread
= threads
[threadCount
- 1];
123 for ( i
= 0; i
< msgCount
; ++i
)
125 lastThread
->GetQueue().Post(i
);
128 for ( i
= 0; i
< threadCount
; ++i
)
130 // each thread should return the number of messages received.
131 // if it returns a negative, then it detected some problem.
132 wxThread::ExitCode code
= threads
[i
]->Wait();
133 CPPUNIT_ASSERT_EQUAL( code
, (wxThread::ExitCode
)wxMSGQUEUE_NO_ERROR
);
137 // this function creates two threads, each one waiting (with a timeout) for
138 // exactly two messages.
139 // Exactly to messages are posted into first thread queue, but
140 // only one message is posted to the second thread queue.
141 // Therefore first thread should return with wxMSGQUEUE_NO_ERROR, but the second
142 // should return wxMSGQUEUUE_TIMEOUT.
143 void QueueTestCase::TestReceiveTimeout()
145 MyThread
* thread1
= new MyThread(WaitWithTimeout
, NULL
, 2);
146 MyThread
* thread2
= new MyThread(WaitWithTimeout
, NULL
, 2);
148 CPPUNIT_ASSERT_EQUAL ( thread1
->Create(), wxTHREAD_NO_ERROR
);
149 CPPUNIT_ASSERT_EQUAL ( thread2
->Create(), wxTHREAD_NO_ERROR
);
154 // Post two messages to the first thread
155 CPPUNIT_ASSERT_EQUAL( thread1
->GetQueue().Post(0), wxMSGQUEUE_NO_ERROR
);
156 CPPUNIT_ASSERT_EQUAL( thread1
->GetQueue().Post(1), wxMSGQUEUE_NO_ERROR
);
158 // ...but only one message to the second
159 CPPUNIT_ASSERT_EQUAL( thread2
->GetQueue().Post(0), wxMSGQUEUE_NO_ERROR
);
161 wxThread::ExitCode code1
= thread1
->Wait();
162 wxThread::ExitCode code2
= thread2
->Wait();
164 CPPUNIT_ASSERT_EQUAL( code1
, (wxThread::ExitCode
)wxMSGQUEUE_NO_ERROR
);
165 CPPUNIT_ASSERT_EQUAL( code2
, (wxThread::ExitCode
)wxMSGQUEUE_TIMEOUT
);
168 // every thread tries to read exactly m_maxMsgCount messages from its queue
169 // following the waiting strategy specified in m_type. If it succeeds then it
170 // returns 0. Otherwise it returns the error code - one of wxMessageQueueError.
171 void *QueueTestCase::MyThread::Entry()
173 int messagesReceived
= 0;
174 while ( messagesReceived
< m_maxMsgCount
)
176 wxMessageQueueError result
;
177 int msg
= -1; // just to suppress "possibly uninitialized" warnings
179 if ( m_type
== WaitWithTimeout
)
180 result
= m_queue
.ReceiveTimeout(1000, msg
);
182 result
= m_queue
.Receive(msg
);
184 if ( result
== wxMSGQUEUE_MISC_ERROR
)
185 return (wxThread::ExitCode
)wxMSGQUEUE_MISC_ERROR
;
187 if ( result
== wxMSGQUEUE_NO_ERROR
)
189 if ( m_nextThread
!= NULL
)
191 wxMessageQueueError res
= m_nextThread
->GetQueue().Post(msg
);
193 if ( res
== wxMSGQUEUE_MISC_ERROR
)
194 return (wxThread::ExitCode
)wxMSGQUEUE_MISC_ERROR
;
196 CPPUNIT_ASSERT_EQUAL( wxMSGQUEUE_NO_ERROR
, res
);
202 CPPUNIT_ASSERT_EQUAL ( result
, wxMSGQUEUE_TIMEOUT
);
207 if ( messagesReceived
!= m_maxMsgCount
)
209 CPPUNIT_ASSERT_EQUAL( m_type
, WaitWithTimeout
);
211 return (wxThread::ExitCode
)wxMSGQUEUE_TIMEOUT
;
214 return (wxThread::ExitCode
)wxMSGQUEUE_NO_ERROR
;