]> git.saurik.com Git - wxWidgets.git/blame - tests/thread/queue.cpp
wxMessageBox off the main thread lost result code.
[wxWidgets.git] / tests / thread / queue.cpp
CommitLineData
6aaee6af
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: tests/thread/queue.cpp
3// Purpose: Unit test for wxMessageQueue
4// Author: Evgeniy Tarassov
5// Created: 31/10/2007
6aaee6af
VZ
6// Copyright: (c) 2007 Evgeniy Tarassov
7// Licence: wxWindows licence
8///////////////////////////////////////////////////////////////////////////////
9
10// ----------------------------------------------------------------------------
11// headers
12// ----------------------------------------------------------------------------
13
14#include "testprec.h"
15
16#ifdef __BORLANDC__
17 #pragma hdrstop
18#endif
19
20#ifndef WX_PRECOMP
21 #include "wx/dynarray.h"
22 #include "wx/thread.h"
23#endif // WX_PRECOMP
24
25#include "wx/msgqueue.h"
26
27// ----------------------------------------------------------------------------
28// test class
29// ----------------------------------------------------------------------------
30
31class QueueTestCase : public CppUnit::TestCase
32{
33public:
34 QueueTestCase() { }
35
6aaee6af
VZ
36 enum WaitTestType
37 {
38 WaitWithTimeout = 0,
39 WaitInfinitlyLong
40 };
41
5098c258
VZ
42private:
43 typedef wxMessageQueue<int> Queue;
44
6aaee6af
VZ
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
50 {
51 public:
52 MyThread(WaitTestType type, MyThread *next, int maxMsgCount)
53 : wxThread(wxTHREAD_JOINABLE),
54 m_type(type), m_nextThread(next), m_maxMsgCount(maxMsgCount)
55 {}
56
57 // thread execution starts here
58 virtual void *Entry();
59
60 // Thread message queue
61 Queue& GetQueue()
62 {
63 return m_queue;
64 }
65
66 private:
67 WaitTestType m_type;
68 MyThread* m_nextThread;
69 int m_maxMsgCount;
70 Queue m_queue;
71 };
72
73 WX_DEFINE_ARRAY_PTR(MyThread *, ArrayThread);
74
75 CPPUNIT_TEST_SUITE( QueueTestCase );
76 CPPUNIT_TEST( TestReceive );
77 CPPUNIT_TEST( TestReceiveTimeout );
78 CPPUNIT_TEST_SUITE_END();
79
80 void TestReceive();
81 void TestReceiveTimeout();
82
83 DECLARE_NO_COPY_CLASS(QueueTestCase)
84};
85
86// register in the unnamed registry so that these tests are run by default
87CPPUNIT_TEST_SUITE_REGISTRATION( QueueTestCase );
88
e3778b4d 89// also include in its own registry so that these tests can be run alone
6aaee6af
VZ
90CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( QueueTestCase, "QueueTestCase" );
91
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
97void QueueTestCase::TestReceive()
98{
99 const int msgCount = 100;
100 const int threadCount = 10;
101
102 ArrayThread threads;
103
104 int i;
105 for ( i = 0; i < threadCount; ++i )
106 {
107 MyThread *previousThread = i == 0 ? NULL : threads[i-1];
108 MyThread *thread =
109 new MyThread(WaitInfinitlyLong, previousThread, msgCount);
110
111 CPPUNIT_ASSERT_EQUAL ( thread->Create(), wxTHREAD_NO_ERROR );
112 threads.Add(thread);
113 }
114
115 for ( i = 0; i < threadCount; ++i )
116 {
117 threads[i]->Run();
118 }
119
120 MyThread* lastThread = threads[threadCount - 1];
121
122 for ( i = 0; i < msgCount; ++i )
123 {
124 lastThread->GetQueue().Post(i);
125 }
126
127 for ( i = 0; i < threadCount; ++i )
128 {
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 );
133 }
134}
135
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.
142void QueueTestCase::TestReceiveTimeout()
143{
144 MyThread* thread1 = new MyThread(WaitWithTimeout, NULL, 2);
145 MyThread* thread2 = new MyThread(WaitWithTimeout, NULL, 2);
146
147 CPPUNIT_ASSERT_EQUAL ( thread1->Create(), wxTHREAD_NO_ERROR );
148 CPPUNIT_ASSERT_EQUAL ( thread2->Create(), wxTHREAD_NO_ERROR );
149
150 thread1->Run();
151 thread2->Run();
152
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 );
156
157 // ...but only one message to the second
158 CPPUNIT_ASSERT_EQUAL( thread2->GetQueue().Post(0), wxMSGQUEUE_NO_ERROR );
159
160 wxThread::ExitCode code1 = thread1->Wait();
161 wxThread::ExitCode code2 = thread2->Wait();
162
163 CPPUNIT_ASSERT_EQUAL( code1, (wxThread::ExitCode)wxMSGQUEUE_NO_ERROR );
164 CPPUNIT_ASSERT_EQUAL( code2, (wxThread::ExitCode)wxMSGQUEUE_TIMEOUT );
165}
166
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.
170void *QueueTestCase::MyThread::Entry()
171{
172 int messagesReceived = 0;
173 while ( messagesReceived < m_maxMsgCount )
174 {
175 wxMessageQueueError result;
5811b24f 176 int msg = -1; // just to suppress "possibly uninitialized" warnings
6aaee6af
VZ
177
178 if ( m_type == WaitWithTimeout )
179 result = m_queue.ReceiveTimeout(1000, msg);
180 else
181 result = m_queue.Receive(msg);
182
183 if ( result == wxMSGQUEUE_MISC_ERROR )
184 return (wxThread::ExitCode)wxMSGQUEUE_MISC_ERROR;
185
186 if ( result == wxMSGQUEUE_NO_ERROR )
187 {
188 if ( m_nextThread != NULL )
189 {
190 wxMessageQueueError res = m_nextThread->GetQueue().Post(msg);
191
192 if ( res == wxMSGQUEUE_MISC_ERROR )
193 return (wxThread::ExitCode)wxMSGQUEUE_MISC_ERROR;
194
195 CPPUNIT_ASSERT_EQUAL( wxMSGQUEUE_NO_ERROR, res );
196 }
197 ++messagesReceived;
198 continue;
199 }
200
201 CPPUNIT_ASSERT_EQUAL ( result, wxMSGQUEUE_TIMEOUT );
202
203 break;
204 }
205
206 if ( messagesReceived != m_maxMsgCount )
207 {
208 CPPUNIT_ASSERT_EQUAL( m_type, WaitWithTimeout );
209
210 return (wxThread::ExitCode)wxMSGQUEUE_TIMEOUT;
211 }
212
213 return (wxThread::ExitCode)wxMSGQUEUE_NO_ERROR;
214}