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