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