00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef PQUEUETEST_H_
00017 #define PQUEUETEST_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 PQueueTest: public CppUnit::TestFixture, public BaseTest<ParaType> {
00027 CPPUNIT_TEST_SUITE(PQueueTest);
00028 CPPUNIT_TEST(testEmptyST);
00029 CPPUNIT_TEST(testEnqueueST);
00030 CPPUNIT_TEST(testDequeueST);
00031 CPPUNIT_TEST(testEnqueueMT);
00032 CPPUNIT_TEST(testDequeueMT);
00033 CPPUNIT_TEST(testBound);
00034
00035 CPPUNIT_TEST_SUITE_END ();
00036
00037 private:
00038 QueueType *queue;
00039 public:
00040 PQueueTest() {
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> class ThreadEnqueue: public TestThread<
00073 ParaType> {
00074 private:
00075 QueueType *queue;
00076 PQueueTest<QueueType, ParaType, CLASS_NAME> *testcase;
00077 int elementNum;
00078 int operationNum;
00079
00080 public:
00081 ThreadEnqueue(QueueType * q,
00082 PQueueTest<QueueType, ParaType, CLASS_NAME>* qt, int nElement,
00083 int nOperation, int threadId = 0) : TestThread<ParaType>(threadId),
00084 queue(q), testcase(qt), elementNum(nElement), operationNum(nOperation)
00085 {
00086
00087
00088 RandArrayGenerator<ParaType>::getRandUniqueArray(testcase->data,
00089 testcase->BaseTest<ParaType>::NELEMENT * testcase->BaseTest<
00090 ParaType>::MAXTHREADN);
00091 }
00092
00093 void* run() {
00094 for (int i = 0; i < operationNum; ++i) {
00095 queue->enqueue(testcase->data[i + ((this->threadId) * elementNum)]);
00096
00097 this->inVec.push_back(testcase->data[i + ((this->threadId)
00098 * elementNum)]);
00099 }
00100 return NULL;
00101 }
00102 };
00103
00104 template<typename QueueType, typename ParaType, char const* CLASS_NAME> class ThreadDequeue: public TestThread<
00105 ParaType> {
00106 private:
00107 QueueType *queue;
00108 PQueueTest<QueueType, ParaType, CLASS_NAME> *testcase;
00109 int elementNum;
00110 int operationNum;
00111
00112 public:
00113
00114 ThreadDequeue(QueueType * q,
00115 PQueueTest<QueueType, ParaType, CLASS_NAME> * qt, int nElement,
00116 int nOperation) :
00117 queue(q), testcase(qt), elementNum(nElement), operationNum(nOperation) {
00118 }
00119
00120 void* run() {
00121 for (int i = 0; i < operationNum; ++i) {
00122 ParaType tmp;
00123 if (queue->dequeue(tmp)) {
00124 this->outVec.push_back(tmp);
00125 }
00126 }
00127 return NULL;
00128 }
00129 };
00130 template<typename QueueType, typename ParaType, char const* CLASS_NAME> class ThreadDequeueFactory: public ThreadFactory<
00131 ParaType> {
00132 private:
00133 QueueType *queue;
00134 PQueueTest<QueueType, ParaType, CLASS_NAME> *testcase;
00135 public:
00136 ThreadDequeueFactory(QueueType * q, PQueueTest<QueueType, ParaType,
00137 CLASS_NAME> * qt) :
00138 queue(q), testcase(qt) {
00139 }
00140
00141 virtual Runnable ** createThreads(int threadNum, int elementNum,
00142 int operationNum) {
00143 testcase->reset();
00144 queue = testcase->getQueue();
00145 this->inVec.clear();
00146 this->outVec.clear();
00147
00148 for (int i = 0; i < threadNum; ++i) {
00149 ThreadEnqueue_T threadEnqueue(queue, testcase, elementNum, i);
00150 threadEnqueue.run();
00151
00152 copy(threadEnqueue.inVec.begin(), threadEnqueue.inVec.end(),
00153 back_inserter(this->inVec));
00154 }
00155 Runnable ** threads;
00156 threads = new Runnable*[threadNum];
00157 for (int i = 0; i < threadNum; ++i)
00158 threads[i]
00159 = new ThreadDequeue<QueueType, ParaType, CLASS_NAME> (queue, testcase, elementNum, operationNum);
00160
00161 return threads;
00162 }
00163
00164 virtual void verifyResult(int threadNum, int elementNum) {
00165 CPPUNIT_ASSERT(queue->size() == 0);
00166
00167
00168 sort(this->inVec.begin(), this->inVec.end());
00169 this->inVec.erase(unique(this->inVec.begin(),this->inVec.end()),this->inVec.end());
00170
00171 ThreadFactory<ParaType>::verifyResult(threadNum, elementNum);
00172 }
00173 };
00174
00175 template<typename QueueType, typename ParaType, char const* CLASS_NAME> class ThreadEnqueueFactory: public ThreadFactory<
00176 ParaType> {
00177 private:
00178 QueueType *queue;
00179 PQueueTest<QueueType, ParaType, CLASS_NAME> *testcase;
00180 public:
00181 ThreadEnqueueFactory(QueueType * q, PQueueTest<QueueType, ParaType,
00182 CLASS_NAME> * qt) :
00183 queue(q), testcase(qt) {
00184 }
00185
00186 virtual Runnable ** createThreads(int threadNum, int elementNum,
00187 int operationNum) {
00188 testcase->reset();
00189 queue = testcase->getQueue();
00190 this->inVec.clear();
00191 this->outVec.clear();
00192
00193 Runnable ** threads;
00194 threads = new Runnable*[threadNum];
00195 for (int i = 0; i < threadNum; ++i)
00196 threads[i]
00197 = new ThreadEnqueue<QueueType, ParaType, CLASS_NAME> (queue, testcase, elementNum, operationNum, i);
00198
00199 return threads;
00200 }
00201
00202 virtual void verifyResult(int threadNum, int elementNum) {
00203
00204 while (!queue->empty()) {
00205 ParaType tmp;
00206 if (queue->dequeue(tmp)) {
00207 this->outVec.push_back(tmp);
00208 }
00209 }
00210
00211
00212 sort(this->inVec.begin(), this->inVec.end());
00213 this->inVec.erase(unique(this->inVec.begin(),this->inVec.end()),this->inVec.end());
00214
00215 ThreadFactory<ParaType>::verifyResult(threadNum, elementNum);
00216 }
00217 };
00218
00219 template<typename QueueType, typename ParaType, char const* CLASS_NAME> class ThreadEnDequeueFactory: public ThreadFactory<
00220 ParaType> {
00221 private:
00222 QueueType *queue;
00223 PQueueTest<QueueType, ParaType, CLASS_NAME> *testcase;
00224 public:
00225 ThreadEnDequeueFactory(QueueType * q, PQueueTest<QueueType, ParaType,
00226 CLASS_NAME> * qt) :
00227 queue(q), testcase(qt) {
00228 }
00229
00230 virtual Runnable ** createThreads(int threadNum, int elementNum,
00231 int operationNum) {
00232 testcase->reset();
00233 queue = testcase->getQueue();
00234 this->inVec.clear();
00235 this->outVec.clear();
00236
00237 for (int i = 0; i < threadNum; ++i) {
00238 ThreadEnqueue_T threadEnqueue(queue, testcase, elementNum, i);
00239 threadEnqueue.run();
00240
00241 copy(threadEnqueue.inVec.begin(), threadEnqueue.inVec.end(),
00242 back_inserter(this->inVec));
00243 }
00244 Runnable ** threads;
00245 threads = new Runnable*[threadNum];
00246
00247 for (int i = 0; i < threadNum; i += 2) {
00248 threads[i]
00249 = new ThreadEnqueue<QueueType, ParaType, CLASS_NAME> (queue, testcase, elementNum, operationNum, i
00250 / 2);
00251 if (i + 1 < threadNum) {
00252 threads[i + 1] = new ThreadDequeue<QueueType, ParaType,
00253 CLASS_NAME> (queue, testcase, elementNum, operationNum);
00254 }
00255 }
00256 return threads;
00257 }
00258
00259 virtual void verifyResult(int threadNum, int elementNum) {
00260 while (!queue->empty()) {
00261 ParaType tmp;
00262 if (queue->dequeue(tmp)) {
00263 this->outVec.push_back(tmp);
00264 }
00265 }
00266
00267
00268 sort(this->inVec.begin(), this->inVec.end());
00269
00270
00271
00272
00273
00274
00275
00276 this->inVec.erase(unique(this->inVec.begin(),this->inVec.end()),this->inVec.end());
00277
00278
00279 sort(this->outVec.begin(), this->outVec.end());
00280
00281
00282
00283
00284
00285
00286
00287 this->outVec.erase(unique(this->outVec.begin(),this->outVec.end()),this->outVec.end());
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304 ThreadFactory<ParaType>::verifyResult(threadNum, elementNum);
00305
00306 }
00307 };
00308
00309 template<typename QueueType, typename ParaType, char const* CLASS_NAME> void PQueueTest<
00310 QueueType, ParaType, CLASS_NAME>::testEmptyST() {
00311 CPPUNIT_ASSERT(true == queue->empty());
00312 CPPUNIT_ASSERT(0 == queue->size());
00313 }
00314
00315 template<typename QueueType, typename ParaType, char const* CLASS_NAME>
00316 void PQueueTest<QueueType, ParaType, CLASS_NAME>::testEnqueueST() {
00317 ThreadEnqueue_T threadEnqueue(queue, this, BaseTest<ParaType>::NELEMENT,
00318 BaseTest<ParaType>::NOPERATION);
00319 threadEnqueue.run();
00320
00321 CPPUNIT_ASSERT(BaseTest<ParaType>::NOPERATION == queue->size());
00322
00323
00324 vector<ParaType> outVec;
00325 while (!queue->empty()) {
00326 ParaType tmp;
00327 if (queue->dequeue(tmp)) {
00328 outVec.push_back(tmp);
00329 }
00330 }
00331
00332 sort(threadEnqueue.inVec.begin(), threadEnqueue.inVec.end());
00333 sort(outVec.begin(), outVec.end());
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 CPPUNIT_ASSERT(threadEnqueue.inVec == outVec);
00351 }
00352
00353 template<typename QueueType, typename ParaType, char const* CLASS_NAME> void PQueueTest<
00354 QueueType, ParaType, CLASS_NAME>::testDequeueST() {
00355 ThreadEnqueue_T threadEnqueue(queue, this, BaseTest<ParaType>::NELEMENT,
00356 BaseTest<ParaType>::NOPERATION);
00357 ThreadDequeue_T threadDequeue(queue, this, BaseTest<ParaType>::NELEMENT,
00358 BaseTest<ParaType>::NOPERATION);
00359 threadEnqueue.run();
00360
00361
00362 threadDequeue.run();
00363
00364
00365
00366
00367 CPPUNIT_ASSERT(0 == queue->size());
00368
00369 sort(threadEnqueue.inVec.begin(), threadEnqueue.inVec.end());
00370 sort(threadDequeue.outVec.begin(), threadDequeue.outVec.end());
00371
00372 CPPUNIT_ASSERT(threadEnqueue.inVec == threadDequeue.outVec);
00373 }
00374
00375 template<typename QueueType, typename ParaType, char const* CLASS_NAME> void PQueueTest<
00376 QueueType, ParaType, CLASS_NAME>::testEnqueueMT() {
00377 ThreadEnqueueFactory<QueueType, ParaType, CLASS_NAME> factory(queue, this);
00378 ThreadRunner::runThreads(&factory, CLASS_NAME, "testEnqueueMT");
00379 }
00380
00381 template<typename QueueType, typename ParaType, char const* CLASS_NAME> void PQueueTest<
00382 QueueType, ParaType, CLASS_NAME>::testDequeueMT() {
00383 ThreadDequeueFactory<QueueType, ParaType, CLASS_NAME> dequeueFactory(queue,
00384 this);
00385 ThreadRunner::runThreads(&dequeueFactory, CLASS_NAME, "testDequeueMT");
00386 }
00387
00388 template<typename QueueType, typename ParaType, char const* CLASS_NAME> void PQueueTest<
00389 QueueType, ParaType, CLASS_NAME>::testEnDequeuePairMT() {
00390 ThreadEnDequeueFactory<QueueType, ParaType, CLASS_NAME>
00391 factory(queue, this);
00392 ThreadRunner::runThreads(&factory, CLASS_NAME, "testEnDequeuePairMT");
00393 }
00394
00395 template<typename QueueType, typename ParaType, char const* CLASS_NAME> void PQueueTest<
00396 QueueType, ParaType, CLASS_NAME>::testBound() {
00397 ParaType tmp;
00398 bool res = queue->dequeue(tmp);
00399 CPPUNIT_ASSERT(!res);
00400 }
00401 }
00402 #endif