]> git.saurik.com Git - wxWidgets.git/blob - tests/thread/queue.cpp
Use std::isfinite() for wxFinite() for C++11 compilers.
[wxWidgets.git] / tests / thread / queue.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/thread/queue.cpp
3 // Purpose: Unit test for wxMessageQueue
4 // Author: Evgeniy Tarassov
5 // Created: 31/10/2007
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
31 class QueueTestCase : public CppUnit::TestCase
32 {
33 public:
34 QueueTestCase() { }
35
36 enum WaitTestType
37 {
38 WaitWithTimeout = 0,
39 WaitInfinitlyLong
40 };
41
42 private:
43 typedef wxMessageQueue<int> Queue;
44
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
87 CPPUNIT_TEST_SUITE_REGISTRATION( QueueTestCase );
88
89 // also include in its own registry so that these tests can be run alone
90 CPPUNIT_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
97 void 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.
142 void 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.
170 void *QueueTestCase::MyThread::Entry()
171 {
172 int messagesReceived = 0;
173 while ( messagesReceived < m_maxMsgCount )
174 {
175 wxMessageQueueError result;
176 int msg = -1; // just to suppress "possibly uninitialized" warnings
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 }