| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- ///////////////////////////////////////////////////////////////////////////////
- // Name: tests/thread/queue.cpp
- // Purpose: Unit test for wxMessageQueue
- // Author: Evgeniy Tarassov
- // Created: 31/10/2007
- // Copyright: (c) 2007 Evgeniy Tarassov
- // Licence: wxWindows licence
- ///////////////////////////////////////////////////////////////////////////////
- // ----------------------------------------------------------------------------
- // headers
- // ----------------------------------------------------------------------------
- #include "testprec.h"
- #ifdef __BORLANDC__
- #pragma hdrstop
- #endif
- #ifndef WX_PRECOMP
- #include "wx/dynarray.h"
- #include "wx/thread.h"
- #endif // WX_PRECOMP
- #include "wx/msgqueue.h"
- // ----------------------------------------------------------------------------
- // test class
- // ----------------------------------------------------------------------------
- class QueueTestCase : public CppUnit::TestCase
- {
- public:
- QueueTestCase() { }
- enum WaitTestType
- {
- WaitWithTimeout = 0,
- WaitInfinitlyLong
- };
- private:
- typedef wxMessageQueue<int> Queue;
- // This class represents a thread that waits (following WaitTestType type)
- // for exactly maxMsgCount messages from its message queue and if another
- // MyThread is specified, then every message received is posted
- // to that next thread.
- class MyThread : public wxThread
- {
- public:
- MyThread(WaitTestType type, MyThread *next, int maxMsgCount)
- : wxThread(wxTHREAD_JOINABLE),
- m_type(type), m_nextThread(next), m_maxMsgCount(maxMsgCount)
- {}
- // thread execution starts here
- virtual void *Entry();
- // Thread message queue
- Queue& GetQueue()
- {
- return m_queue;
- }
- private:
- WaitTestType m_type;
- MyThread* m_nextThread;
- int m_maxMsgCount;
- Queue m_queue;
- };
- WX_DEFINE_ARRAY_PTR(MyThread *, ArrayThread);
- CPPUNIT_TEST_SUITE( QueueTestCase );
- CPPUNIT_TEST( TestReceive );
- CPPUNIT_TEST( TestReceiveTimeout );
- CPPUNIT_TEST_SUITE_END();
- void TestReceive();
- void TestReceiveTimeout();
- DECLARE_NO_COPY_CLASS(QueueTestCase)
- };
- // register in the unnamed registry so that these tests are run by default
- CPPUNIT_TEST_SUITE_REGISTRATION( QueueTestCase );
- // also include in its own registry so that these tests can be run alone
- CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( QueueTestCase, "QueueTestCase" );
- // this function creates the given number of threads and posts msgCount
- // messages to the last created thread which, in turn, posts all the messages
- // it receives to the previously created thread which does the same and so on
- // in cascade -- at the end, each thread will have received all msgCount
- // messages directly or indirectly
- void QueueTestCase::TestReceive()
- {
- const int msgCount = 100;
- const int threadCount = 10;
- ArrayThread threads;
- int i;
- for ( i = 0; i < threadCount; ++i )
- {
- MyThread *previousThread = i == 0 ? NULL : threads[i-1];
- MyThread *thread =
- new MyThread(WaitInfinitlyLong, previousThread, msgCount);
- CPPUNIT_ASSERT_EQUAL ( thread->Create(), wxTHREAD_NO_ERROR );
- threads.Add(thread);
- }
- for ( i = 0; i < threadCount; ++i )
- {
- threads[i]->Run();
- }
- MyThread* lastThread = threads[threadCount - 1];
- for ( i = 0; i < msgCount; ++i )
- {
- lastThread->GetQueue().Post(i);
- }
- for ( i = 0; i < threadCount; ++i )
- {
- // each thread should return the number of messages received.
- // if it returns a negative, then it detected some problem.
- wxThread::ExitCode code = threads[i]->Wait();
- CPPUNIT_ASSERT_EQUAL( code, (wxThread::ExitCode)wxMSGQUEUE_NO_ERROR );
- }
- }
- // this function creates two threads, each one waiting (with a timeout) for
- // exactly two messages.
- // Exactly to messages are posted into first thread queue, but
- // only one message is posted to the second thread queue.
- // Therefore first thread should return with wxMSGQUEUE_NO_ERROR, but the second
- // should return wxMSGQUEUUE_TIMEOUT.
- void QueueTestCase::TestReceiveTimeout()
- {
- MyThread* thread1 = new MyThread(WaitWithTimeout, NULL, 2);
- MyThread* thread2 = new MyThread(WaitWithTimeout, NULL, 2);
- CPPUNIT_ASSERT_EQUAL ( thread1->Create(), wxTHREAD_NO_ERROR );
- CPPUNIT_ASSERT_EQUAL ( thread2->Create(), wxTHREAD_NO_ERROR );
- thread1->Run();
- thread2->Run();
- // Post two messages to the first thread
- CPPUNIT_ASSERT_EQUAL( thread1->GetQueue().Post(0), wxMSGQUEUE_NO_ERROR );
- CPPUNIT_ASSERT_EQUAL( thread1->GetQueue().Post(1), wxMSGQUEUE_NO_ERROR );
- // ...but only one message to the second
- CPPUNIT_ASSERT_EQUAL( thread2->GetQueue().Post(0), wxMSGQUEUE_NO_ERROR );
- wxThread::ExitCode code1 = thread1->Wait();
- wxThread::ExitCode code2 = thread2->Wait();
- CPPUNIT_ASSERT_EQUAL( code1, (wxThread::ExitCode)wxMSGQUEUE_NO_ERROR );
- CPPUNIT_ASSERT_EQUAL( code2, (wxThread::ExitCode)wxMSGQUEUE_TIMEOUT );
- }
- // every thread tries to read exactly m_maxMsgCount messages from its queue
- // following the waiting strategy specified in m_type. If it succeeds then it
- // returns 0. Otherwise it returns the error code - one of wxMessageQueueError.
- void *QueueTestCase::MyThread::Entry()
- {
- int messagesReceived = 0;
- while ( messagesReceived < m_maxMsgCount )
- {
- wxMessageQueueError result;
- int msg = -1; // just to suppress "possibly uninitialized" warnings
- if ( m_type == WaitWithTimeout )
- result = m_queue.ReceiveTimeout(1000, msg);
- else
- result = m_queue.Receive(msg);
- if ( result == wxMSGQUEUE_MISC_ERROR )
- return (wxThread::ExitCode)wxMSGQUEUE_MISC_ERROR;
- if ( result == wxMSGQUEUE_NO_ERROR )
- {
- if ( m_nextThread != NULL )
- {
- wxMessageQueueError res = m_nextThread->GetQueue().Post(msg);
- if ( res == wxMSGQUEUE_MISC_ERROR )
- return (wxThread::ExitCode)wxMSGQUEUE_MISC_ERROR;
- CPPUNIT_ASSERT_EQUAL( wxMSGQUEUE_NO_ERROR, res );
- }
- ++messagesReceived;
- continue;
- }
- CPPUNIT_ASSERT_EQUAL ( result, wxMSGQUEUE_TIMEOUT );
- break;
- }
- if ( messagesReceived != m_maxMsgCount )
- {
- CPPUNIT_ASSERT_EQUAL( m_type, WaitWithTimeout );
- return (wxThread::ExitCode)wxMSGQUEUE_TIMEOUT;
- }
- return (wxThread::ExitCode)wxMSGQUEUE_NO_ERROR;
- }
|