1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/thread/queue.cpp
3 // Purpose: Unit test for wxMessageQueue
4 // Author: Evgeniy Tarassov
6 // Copyright: (c) 2007 Evgeniy Tarassov
7 // Licence: wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
10 // ----------------------------------------------------------------------------
12 // ----------------------------------------------------------------------------
21 #include "wx/dynarray.h"
22 #include "wx/thread.h"
25 #include "wx/msgqueue.h"
27 // ----------------------------------------------------------------------------
29 // ----------------------------------------------------------------------------
31 class QueueTestCase
: public CppUnit::TestCase
43 typedef wxMessageQueue
<int> Queue
;
45 // This class represents a thread that waits (following WaitTestType type)
46 // for exactly maxMsgCount messages from its message queue and if another
47 // MyThread is specified, then every message received is posted
48 // to that next thread.
49 class MyThread
: public wxThread
52 MyThread(WaitTestType type
, MyThread
*next
, int maxMsgCount
)
53 : wxThread(wxTHREAD_JOINABLE
),
54 m_type(type
), m_nextThread(next
), m_maxMsgCount(maxMsgCount
)
57 // thread execution starts here
58 virtual void *Entry();
60 // Thread message queue
68 MyThread
* m_nextThread
;
73 WX_DEFINE_ARRAY_PTR(MyThread
*, ArrayThread
);
75 CPPUNIT_TEST_SUITE( QueueTestCase
);
76 CPPUNIT_TEST( TestReceive
);
77 CPPUNIT_TEST( TestReceiveTimeout
);
78 CPPUNIT_TEST_SUITE_END();
81 void TestReceiveTimeout();
83 DECLARE_NO_COPY_CLASS(QueueTestCase
)
86 // register in the unnamed registry so that these tests are run by default
87 CPPUNIT_TEST_SUITE_REGISTRATION( QueueTestCase
);
89 // also include in its own registry so that these tests can be run alone
90 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( QueueTestCase
, "QueueTestCase" );
92 // this function creates the given number of threads and posts msgCount
93 // messages to the last created thread which, in turn, posts all the messages
94 // it receives to the previously created thread which does the same and so on
95 // in cascade -- at the end, each thread will have received all msgCount
96 // messages directly or indirectly
97 void QueueTestCase::TestReceive()
99 const int msgCount
= 100;
100 const int threadCount
= 10;
105 for ( i
= 0; i
< threadCount
; ++i
)
107 MyThread
*previousThread
= i
== 0 ? NULL
: threads
[i
-1];
109 new MyThread(WaitInfinitlyLong
, previousThread
, msgCount
);
111 CPPUNIT_ASSERT_EQUAL ( thread
->Create(), wxTHREAD_NO_ERROR
);
115 for ( i
= 0; i
< threadCount
; ++i
)
120 MyThread
* lastThread
= threads
[threadCount
- 1];
122 for ( i
= 0; i
< msgCount
; ++i
)
124 lastThread
->GetQueue().Post(i
);
127 for ( i
= 0; i
< threadCount
; ++i
)
129 // each thread should return the number of messages received.
130 // if it returns a negative, then it detected some problem.
131 wxThread::ExitCode code
= threads
[i
]->Wait();
132 CPPUNIT_ASSERT_EQUAL( code
, (wxThread::ExitCode
)wxMSGQUEUE_NO_ERROR
);
136 // this function creates two threads, each one waiting (with a timeout) for
137 // exactly two messages.
138 // Exactly to messages are posted into first thread queue, but
139 // only one message is posted to the second thread queue.
140 // Therefore first thread should return with wxMSGQUEUE_NO_ERROR, but the second
141 // should return wxMSGQUEUUE_TIMEOUT.
142 void QueueTestCase::TestReceiveTimeout()
144 MyThread
* thread1
= new MyThread(WaitWithTimeout
, NULL
, 2);
145 MyThread
* thread2
= new MyThread(WaitWithTimeout
, NULL
, 2);
147 CPPUNIT_ASSERT_EQUAL ( thread1
->Create(), wxTHREAD_NO_ERROR
);
148 CPPUNIT_ASSERT_EQUAL ( thread2
->Create(), wxTHREAD_NO_ERROR
);
153 // Post two messages to the first thread
154 CPPUNIT_ASSERT_EQUAL( thread1
->GetQueue().Post(0), wxMSGQUEUE_NO_ERROR
);
155 CPPUNIT_ASSERT_EQUAL( thread1
->GetQueue().Post(1), wxMSGQUEUE_NO_ERROR
);
157 // ...but only one message to the second
158 CPPUNIT_ASSERT_EQUAL( thread2
->GetQueue().Post(0), wxMSGQUEUE_NO_ERROR
);
160 wxThread::ExitCode code1
= thread1
->Wait();
161 wxThread::ExitCode code2
= thread2
->Wait();
163 CPPUNIT_ASSERT_EQUAL( code1
, (wxThread::ExitCode
)wxMSGQUEUE_NO_ERROR
);
164 CPPUNIT_ASSERT_EQUAL( code2
, (wxThread::ExitCode
)wxMSGQUEUE_TIMEOUT
);
167 // every thread tries to read exactly m_maxMsgCount messages from its queue
168 // following the waiting strategy specified in m_type. If it succeeds then it
169 // returns 0. Otherwise it returns the error code - one of wxMessageQueueError.
170 void *QueueTestCase::MyThread::Entry()
172 int messagesReceived
= 0;
173 while ( messagesReceived
< m_maxMsgCount
)
175 wxMessageQueueError result
;
176 int msg
= -1; // just to suppress "possibly uninitialized" warnings
178 if ( m_type
== WaitWithTimeout
)
179 result
= m_queue
.ReceiveTimeout(1000, msg
);
181 result
= m_queue
.Receive(msg
);
183 if ( result
== wxMSGQUEUE_MISC_ERROR
)
184 return (wxThread::ExitCode
)wxMSGQUEUE_MISC_ERROR
;
186 if ( result
== wxMSGQUEUE_NO_ERROR
)
188 if ( m_nextThread
!= NULL
)
190 wxMessageQueueError res
= m_nextThread
->GetQueue().Post(msg
);
192 if ( res
== wxMSGQUEUE_MISC_ERROR
)
193 return (wxThread::ExitCode
)wxMSGQUEUE_MISC_ERROR
;
195 CPPUNIT_ASSERT_EQUAL( wxMSGQUEUE_NO_ERROR
, res
);
201 CPPUNIT_ASSERT_EQUAL ( result
, wxMSGQUEUE_TIMEOUT
);
206 if ( messagesReceived
!= m_maxMsgCount
)
208 CPPUNIT_ASSERT_EQUAL( m_type
, WaitWithTimeout
);
210 return (wxThread::ExitCode
)wxMSGQUEUE_TIMEOUT
;
213 return (wxThread::ExitCode
)wxMSGQUEUE_NO_ERROR
;