00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 #ifndef QUEUETEST_H_
00017 #define QUEUETEST_H_
00018 #include <cppunit/extensions/HelperMacros.h>
00019 #include <cppunit/TestAssert.h>
00020 #include <stdexcept>
00021 #include "baseTest.h"
00022 
00023 namespace test {
00024 
00025 template<typename QueueType, typename ParaType, char const* CLASS_NAME>
00026 class QueueTest: public CppUnit::TestFixture, public BaseTest<ParaType> {
00027         CPPUNIT_TEST_SUITE(QueueTest);
00028         CPPUNIT_TEST(testEmptyST);
00029         CPPUNIT_TEST(testEnqueueST);
00030         CPPUNIT_TEST(testDequeueST);
00031         CPPUNIT_TEST(testEnqueueMT);
00032         CPPUNIT_TEST(testDequeueMT);
00033         CPPUNIT_TEST(testEnDequeuePairMT);
00034         CPPUNIT_TEST(testBound);
00035         CPPUNIT_TEST_SUITE_END();
00036 
00037 private:
00038         QueueType *queue;
00039 public:
00040         QueueTest() {
00041         }
00042 
00043         QueueType * getQueue() {
00044                 return queue;
00045         }
00046 
00047         void setUp() {
00048                 queue = new QueueType();
00049         }
00050 
00051         void reset() {
00052                 delete queue;
00053                 queue = new QueueType();
00054         }
00055 
00056         void tearDown() {
00057                 delete queue;
00058         }
00059 
00060         void testEmptyST();
00061         void testEnqueueST();
00062         void testDequeueST();
00063         void testEnqueueMT();
00064         void testDequeueMT();
00065         void testEnDequeuePairMT();
00066         void testBound();
00067 };
00068 
00069 #define ThreadDequeue_T ThreadDequeue<QueueType, ParaType, CLASS_NAME>
00070 #define ThreadEnqueue_T ThreadEnqueue<QueueType, ParaType, CLASS_NAME>
00071 
00072 template<typename QueueType, typename ParaType, char const* CLASS_NAME> 
00073 class ThreadEnqueue: public TestThread<ParaType> {
00074 private:
00075         QueueType *queue;
00076         QueueTest<QueueType, ParaType, CLASS_NAME> *testcase;
00077         int elementNum;
00078         int operationNum;
00079 
00080 public:
00081         ThreadEnqueue(QueueType * q, QueueTest<QueueType, ParaType, CLASS_NAME>* qt, 
00082             int nElement, int nOperation, int threadId = 0) :
00083         TestThread<ParaType>(threadId), queue(q), testcase(qt), 
00084         elementNum(nElement), operationNum(nOperation)
00085     {
00086         }
00087 
00088         void* run() {
00089                 for (int i = 0; i < operationNum; ++i) {
00090             int index = (i + ((this->threadId) * elementNum))%(testcase->NELEMENT*testcase->MAXTHREADN);
00091                         queue->enqueue(testcase->data[index]);
00092                         this->inVec.push_back(testcase->data[index]);
00093                 }
00094         return NULL;
00095         }
00096 };
00097 
00098 template<typename QueueType, typename ParaType, char const* CLASS_NAME> 
00099 class ThreadDequeue: public TestThread<ParaType> {
00100 private:
00101         QueueType *queue;
00102         QueueTest<QueueType, ParaType, CLASS_NAME> *testcase;
00103         int elementNum;
00104         int operationNum;
00105 
00106 public:
00107 
00108         ThreadDequeue(QueueType * q,
00109                         QueueTest<QueueType, ParaType, CLASS_NAME> * qt, int nElement,
00110                         int nOperation) :
00111                 queue(q), testcase(qt), elementNum(nElement), operationNum(nOperation) {
00112         }
00113 
00114         void* run() {
00115                 for (int i = 0; i < operationNum; ++i) {
00116                         ParaType tmp;
00117                         if (queue->dequeue(tmp)) {
00118                                 this->outVec.push_back(tmp);
00119                         }
00120                 }
00121         return NULL;
00122         }
00123 };
00124 template<typename QueueType, typename ParaType, char const* CLASS_NAME> class ThreadDequeueFactory: public ThreadFactory<
00125                 ParaType> {
00126 private:
00127         QueueType *queue;
00128         QueueTest<QueueType, ParaType, CLASS_NAME> *testcase;
00129 public:
00130         ThreadDequeueFactory(QueueType * q, QueueTest<QueueType, ParaType,
00131                         CLASS_NAME> * qt) :
00132                 queue(q), testcase(qt) {
00133         }
00134 
00135         virtual Runnable ** createThreads(int threadNum, int elementNum,
00136                         int operationNum) {
00137                 testcase->reset();
00138                 queue = testcase->getQueue();
00139                 this->inVec.clear();
00140                 this->outVec.clear();
00141 
00142                 for (int i = 0; i < threadNum; ++i) {
00143                         ThreadEnqueue_T threadEnqueue(queue, testcase, elementNum, i);
00144                         threadEnqueue.run();
00145 
00146                         copy(threadEnqueue.inVec.begin(), threadEnqueue.inVec.end(),
00147                                         back_inserter(this->inVec));
00148                 }
00149                 Runnable ** threads;
00150                 threads = new Runnable*[threadNum];
00151                 for (int i = 0; i < threadNum; ++i)
00152                         threads[i]
00153                                         = new ThreadDequeue<QueueType, ParaType, CLASS_NAME> (queue, testcase, elementNum, operationNum);
00154 
00155                 return threads;
00156         }
00157 
00158         virtual void verifyResult(int threadNum, int elementNum) {
00159                 CPPUNIT_ASSERT(queue->size() == 0);
00160 
00161                 ThreadFactory<ParaType>::verifyResult(threadNum, elementNum);
00162         }
00163 };
00164 
00165 template<typename QueueType, typename ParaType, char const* CLASS_NAME> class ThreadEnqueueFactory: public ThreadFactory<
00166                 ParaType> {
00167 private:
00168         QueueType *queue;
00169         QueueTest<QueueType, ParaType, CLASS_NAME> *testcase;
00170 public:
00171         ThreadEnqueueFactory(QueueType * q, QueueTest<QueueType, ParaType,
00172                         CLASS_NAME> * qt) :
00173                 queue(q), testcase(qt) {
00174         }
00175 
00176         virtual Runnable ** createThreads(int threadNum, int elementNum,
00177                         int operationNum) {
00178                 testcase->reset();
00179                 queue = testcase->getQueue();
00180                 this->inVec.clear();
00181                 this->outVec.clear();
00182 
00183                 Runnable ** threads;
00184                 threads = new Runnable*[threadNum];
00185                 for (int i = 0; i < threadNum; ++i)
00186                         threads[i]
00187                                         = new ThreadEnqueue<QueueType, ParaType, CLASS_NAME> (queue, testcase, elementNum, operationNum, i);
00188 
00189                 return threads;
00190         }
00191 
00192         virtual void verifyResult(int threadNum, int elementNum) {
00193                 
00194                 while (!queue->empty()) {
00195                         ParaType tmp;
00196                         if (queue->dequeue(tmp)) {
00197                                 this->outVec.push_back(tmp);
00198                         }
00199                 }
00200 
00201                 ThreadFactory<ParaType>::verifyResult(threadNum, elementNum);
00202         }
00203 };
00204 
00205 template<typename QueueType, typename ParaType, char const* CLASS_NAME> class ThreadEnDequeueFactory: public ThreadFactory<
00206                 ParaType> {
00207 private:
00208         QueueType *queue;
00209         QueueTest<QueueType, ParaType, CLASS_NAME> *testcase;
00210 public:
00211         ThreadEnDequeueFactory(QueueType * q, QueueTest<QueueType, ParaType,
00212                         CLASS_NAME> * qt) :
00213                 queue(q), testcase(qt) {
00214         }
00215 
00216         virtual Runnable ** createThreads(int threadNum, int elementNum,
00217                         int operationNum) {
00218                 testcase->reset();
00219                 queue = testcase->getQueue();
00220                 this->inVec.clear();
00221                 this->outVec.clear();
00222 
00223                 for (int i = 0; i < threadNum; ++i) {
00224                         ThreadEnqueue_T threadEnqueue(queue, testcase, elementNum, i);
00225                         threadEnqueue.run();
00226 
00227                         copy(threadEnqueue.inVec.begin(), threadEnqueue.inVec.end(),
00228                                         back_inserter(this->inVec));
00229                 }
00230                 Runnable ** threads;
00231                 threads = new Runnable*[threadNum];
00232 
00233                 for (int i = 0; i < threadNum; i += 2) {
00234                         threads[i]
00235                                         = new ThreadEnqueue<QueueType, ParaType, CLASS_NAME> (queue, testcase, elementNum, operationNum, i
00236                                                         / 2);
00237                         if (i + 1 < threadNum)
00238                                 threads[i + 1] = new ThreadDequeue<QueueType, ParaType,
00239                                                 CLASS_NAME> (queue, testcase, elementNum, operationNum);
00240                 }
00241                 return threads;
00242         }
00243 
00244         virtual void verifyResult(int threadNum, int elementNum) {
00245                 while (!queue->empty()) {
00246                         ParaType tmp;
00247                         if (queue->dequeue(tmp)) {
00248                                 this->outVec.push_back(tmp);
00249                         }
00250                 }
00251 
00252                 ThreadFactory<ParaType>::verifyResult(threadNum, elementNum);
00253 
00254         }
00255 };
00256 
00257 template<typename QueueType, typename ParaType, char const* CLASS_NAME> void QueueTest<
00258                 QueueType, ParaType, CLASS_NAME>::testEmptyST() {
00259         CPPUNIT_ASSERT(true == queue->empty());
00260         CPPUNIT_ASSERT(0 == queue->size());
00261 }
00262 
00263 template<typename QueueType, typename ParaType, char const* CLASS_NAME> void QueueTest<
00264                 QueueType, ParaType, CLASS_NAME>::testEnqueueST() {
00265         ThreadEnqueue_T threadEnqueue(queue, this, BaseTest<ParaType>::NELEMENT,
00266                         BaseTest<ParaType>::NOPERATION);
00267         threadEnqueue.run();
00268         CPPUNIT_ASSERT(BaseTest<ParaType>::NOPERATION == queue->size());
00269 
00270         
00271         vector<ParaType> outVec;
00272         while (!queue->empty()) {
00273                 ParaType tmp;
00274                 if (queue->dequeue(tmp)) {
00275                         outVec.push_back(tmp);
00276                 }
00277         }
00278 
00279         sort(threadEnqueue.inVec.begin(), threadEnqueue.inVec.end());
00280         sort(outVec.begin(), outVec.end());
00281 
00282         CPPUNIT_ASSERT(threadEnqueue.inVec == outVec);
00283 }
00284 
00285 template<typename QueueType, typename ParaType, char const* CLASS_NAME> void QueueTest<
00286                 QueueType, ParaType, CLASS_NAME>::testDequeueST() {
00287         ThreadEnqueue_T threadEnqueue(queue, this, BaseTest<ParaType>::NELEMENT,
00288                         BaseTest<ParaType>::NOPERATION);
00289         ThreadDequeue_T threadDequeue(queue, this, BaseTest<ParaType>::NELEMENT,
00290                         BaseTest<ParaType>::NOPERATION);
00291         threadEnqueue.run();
00292         threadDequeue.run();
00293 
00294         CPPUNIT_ASSERT(0 == queue->size());
00295 
00296         sort(threadEnqueue.inVec.begin(), threadEnqueue.inVec.end());
00297         sort(threadDequeue.outVec.begin(), threadDequeue.outVec.end());
00298 
00299         CPPUNIT_ASSERT(threadEnqueue.inVec == threadDequeue.outVec);
00300 }
00301 
00302 template<typename QueueType, typename ParaType, char const* CLASS_NAME> void QueueTest<
00303                 QueueType, ParaType, CLASS_NAME>::testEnqueueMT() {
00304         ThreadEnqueueFactory<QueueType, ParaType, CLASS_NAME> factory(queue, this);
00305         ThreadRunner::runThreads(&factory, CLASS_NAME, "testEnqueueMT");
00306 }
00307 
00308 template<typename QueueType, typename ParaType, char const* CLASS_NAME> void QueueTest<
00309                 QueueType, ParaType, CLASS_NAME>::testDequeueMT() {
00310         ThreadDequeueFactory<QueueType, ParaType, CLASS_NAME> dequeueFactory(queue,
00311                         this);
00312         ThreadRunner::runThreads(&dequeueFactory, CLASS_NAME, "testDequeueMT");
00313 }
00314 
00315 template<typename QueueType, typename ParaType, char const* CLASS_NAME> void QueueTest<
00316                 QueueType, ParaType, CLASS_NAME>::testEnDequeuePairMT() {
00317         ThreadEnDequeueFactory<QueueType, ParaType, CLASS_NAME>
00318                         factory(queue, this);
00319         ThreadRunner::runThreads(&factory, CLASS_NAME, "testEnDequeuePairMT");
00320 }
00321 
00322 template<typename QueueType, typename ParaType, char const* CLASS_NAME> void QueueTest<
00323                 QueueType, ParaType, CLASS_NAME>::testBound() {
00324         ParaType tmp;
00325         bool res = queue->dequeue(tmp);
00326         CPPUNIT_ASSERT(!res);
00327 }
00328 }
00329 #endif