1 /* Copyright (C) 2014 InfiniDB, Inc.
2
3 This program is free software; you can redistribute it and/or
4 modify it under the terms of the GNU General Public License
5 as published by the Free Software Foundation; version 2 of
6 the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16 MA 02110-1301, USA. */
17
18 // $Id: tdriver-datalist.cpp 9210 2013-01-21 14:10:42Z rdempsey $
19 #include <iostream>
20 #include <sstream>
21 #include <list>
22
23 #include <pthread.h>
24 #include <time.h>
25 #include <sys/time.h>
26
27 #include <cppunit/extensions/HelperMacros.h>
28 #include <cppunit/extensions/TestFactoryRegistry.h>
29 #include <cppunit/ui/text/TestRunner.h>
30
31 #include "fifo.h"
32 #include "wsdl.h"
33 #include "constantdatalist.h"
34 #include "bucketdl.h"
35 #include "bandeddl.h"
36 #include "elementtype.h"
37 #include "stopwatch.cpp"
38
39 // #undef CPPUNIT_ASSERT
40 // #define CPPUNIT_ASSERT(x)
41
42 using namespace std;
43 using namespace joblist;
44 Stopwatch timer;
45
46 struct DLElement
47 {
48 public:
49 int i;
operator <DLElement50 bool operator<(const DLElement& c) const
51 {
52 return (i < c.i);
53 }
getHashStringDLElement54 const char* getHashString(int mode, int* len) const
55 {
56 *len = 4;
57 return (char*) &i;
58 }
59 };
60
operator >>(istream & is,DLElement & dl)61 istream& operator>>(istream& is, DLElement& dl)
62 {
63 is.read((char*)&dl.i, sizeof(int));
64 return is;
65 }
operator <<(ostream & os,const DLElement & dl)66 ostream& operator<<(ostream& os, const DLElement& dl)
67 {
68 os.write((char*)&dl.i, sizeof(int));
69 return os;
70 }
71
72 int64_t count = 150000000/*1000000*/;
73 int maxElements = 32000000/*50000*/; //max elements in memory at once for the benchmarks
74 int buckets = 16; // # of buckets to use in bucketDL tests.
75 #define MAXINT64 (uint64_t) 0xffffffffffffffffLL
76
77 /* Note, this is like what we'll use for banding operations */
78 class BandGrouper
79 {
80 public:
operator ()(const char * data,uint32_t len) const81 uint32_t operator()(const char* data, uint32_t len) const
82 {
83 stringstream ss(string(data, len));
84 ElementType dle;
85
86 ss >> dle;
87 // cout << "bandGrouper sees " << dle.i << " returning " << dle.i/(::count/buckets) << endl;
88 return dle.first / (::count / buckets);
89 }
90 };
91
timespec_sub(const struct timespec & tv1,const struct timespec & tv2,struct timespec & diff)92 void timespec_sub(const struct timespec& tv1, const struct timespec& tv2,
93 struct timespec& diff)
94 {
95 if (tv2.tv_nsec < tv1.tv_nsec)
96 {
97 diff.tv_sec = tv2.tv_sec - tv1.tv_sec - 1;
98 diff.tv_nsec = tv1.tv_nsec - tv2.tv_nsec;
99 }
100 else
101 {
102 diff.tv_sec = tv2.tv_sec - tv1.tv_sec;
103 diff.tv_nsec = tv2.tv_nsec - tv1.tv_nsec;
104 }
105 }
106
107 int cCount = 0, pCount = 0;
108
MP_FIFO_stress_producer(void * arg)109 void* MP_FIFO_stress_producer(void* arg)
110 {
111 FIFO<ElementType>* f = reinterpret_cast<FIFO<ElementType> *>(arg);
112 uint64_t i;
113 ElementType val;
114 uint64_t id = ::pCount++;
115
116 // cout << "producer " << id << " started" << endl;
117 for (i = 0; i < (uint32_t) ::count / 10; i++)
118 {
119 val.first = (id << 60) | i;
120 val.second = val.first;
121 f->insert(val);
122 }
123
124 return NULL;
125 }
126
MP_FIFO_stress_consumer(void * arg)127 void* MP_FIFO_stress_consumer(void* arg)
128 {
129 FIFO<ElementType>* f = reinterpret_cast<FIFO<ElementType> *>(arg);
130 int it;
131 ElementType val;
132 bool ret;
133 // int id = ::cCount++;
134 uint64_t pCounter[10]; // 10 producers right now; make this a global var...
135 uint64_t pnum, pnext;
136
137 memset(pCounter, 0, 8 * 10);
138
139 // cout << "consumer " << id << " started" << endl;
140 it = f->getIterator();
141 ret = f->next(it, &val);
142
143 while (ret)
144 {
145 pnum = val.first >> 60;
146 pnext = pCounter[pnum]++;
147 // cerr << id << ": .first=0x" << hex << val.first << dec << " pnum:" << pnum << " val:" << pnext << endl;
148 CPPUNIT_ASSERT((val.first & 0xfffffffffffffffLL) == pnext);
149 CPPUNIT_ASSERT(val.second == val.first);
150 ret = f->next(it, &val);
151 }
152
153 return NULL;
154 }
155
FIFO_stress_consumer(void * arg)156 void* FIFO_stress_consumer(void* arg)
157 {
158 FIFO<ElementType>* f = reinterpret_cast<FIFO<ElementType> *>(arg);
159 uint64_t i;
160 int it;
161 ElementType val;
162 bool ret;
163 int id = ++::cCount;
164
165 cout << "consumer " << id << " started" << endl;
166 it = f->getIterator();
167
168 for (i = 0; i < MAXINT64; i++)
169 {
170 // cout << id << ": " << i << " ";
171 ret = f->next(it, &val);
172
173 if (!ret)
174 {
175 cout << "consumer " << id << " exiting" << endl;
176 return NULL;
177 }
178
179 else
180 {
181 // cout << "first: " << val.first << " second: " << val.second << endl;
182 CPPUNIT_ASSERT(ret == true);
183 CPPUNIT_ASSERT(val.first == i && val.second == i);
184 }
185
186 }
187
188 return NULL;
189 }
190
FIFO_bench_consumer(void * arg)191 void* FIFO_bench_consumer(void* arg)
192 {
193 FIFO<int>* f = reinterpret_cast<FIFO<int> *>(arg);
194 int i, it, val;
195 bool ret;
196
197 it = f->getIterator();
198
199 for (i = 0; i < ::count; i++)
200 {
201 // cout << "t " << i << endl;
202 ret = f->next(it, &val);
203 // CPPUNIT_ASSERT(ret == true);
204 }
205
206 return NULL;
207 }
208
FIFO_2_helper(void * arg)209 void* FIFO_2_helper(void* arg)
210 {
211 FIFO<DLElement>* f = reinterpret_cast<FIFO<DLElement> *>(arg);
212 int i;
213 DLElement fe;
214
215 for (i = 0; i < ::count; i++)
216 {
217 fe.i = i;
218 #ifdef DEBUG
219 cout << "inserting " << i << endl;
220 #endif
221 f->insert(fe);
222 }
223
224 sleep(5); // causes the test to block on moreData until endOfInput is called
225 f->endOfInput();
226 return NULL;
227 }
228
WSDL_2_helper(void * arg)229 void* WSDL_2_helper(void* arg)
230 {
231 WSDL<ElementType>* w = reinterpret_cast<WSDL<ElementType> *>(arg);
232 uint32_t i, id;
233 bool nextRet;
234 ElementType dle;
235
236 id = w->getIterator();
237
238 // cout << "id = " << id << endl;
239 for (i = 0; i < ::count; i++)
240 {
241 nextRet = w->next(id, &dle);
242 // cout << "tgot " << dle.i << endl;
243 CPPUNIT_ASSERT(nextRet == true);
244 CPPUNIT_ASSERT(dle.first == i && dle.second == i);
245 }
246
247 return NULL;
248 }
249
BandedDL_1_helper(void * arg)250 void* BandedDL_1_helper(void* arg)
251 {
252 BandedDL<ElementType>* w = reinterpret_cast<BandedDL<ElementType> *>(arg);
253 uint32_t i, id;
254 bool nextRet;
255 ElementType dle;
256
257 id = w->getIterator();
258
259 // cout << "id = " << id << endl;
260 for (i = 0; i < ::count; i++)
261 {
262 nextRet = w->next(id, &dle);
263 // cout << "tgot " << dle.i << endl;
264 // CPPUNIT_ASSERT(nextRet == true);
265 // CPPUNIT_ASSERT(dle.first == i && dle.second == i);
266 }
267
268 return NULL;
269 }
270
BandedDL_2_helper(void * arg)271 void* BandedDL_2_helper(void* arg)
272 {
273 BandedDL<StringElementType>* w = reinterpret_cast<BandedDL<StringElementType> *>(arg);
274 uint32_t i, id;
275 bool nextRet;
276 StringElementType dle;
277
278 id = w->getIterator();
279
280 // cout << "id = " << id << endl;
281 for (i = 0; i < ::count; i++)
282 {
283 ostringstream os;
284
285 os << "blah blah" << i;
286 nextRet = w->next(id, &dle);
287 // cout << "tgot " << dle.i << endl;
288 CPPUNIT_ASSERT(nextRet == true);
289 CPPUNIT_ASSERT(dle.first == i && dle.second == os.str());
290 }
291
292 return NULL;
293 }
294
WSDL_bench_helper(void * arg)295 void* WSDL_bench_helper(void* arg)
296 {
297 WSDL<ElementType>* w = reinterpret_cast<WSDL<ElementType> *>(arg);
298 int i, id;
299 bool nextRet;
300 ElementType e;
301
302 id = w->getIterator();
303
304 for (i = 0; i < ::count; i++)
305 nextRet = w->next(id, &e);
306
307 return NULL;
308 }
309
SWSDL_bench_helper(void * arg)310 void* SWSDL_bench_helper(void* arg)
311 {
312 SWSDL<ElementType>* sw = reinterpret_cast<SWSDL<ElementType> *>(arg);
313 int i, id;
314 bool nextRet;
315 ElementType e;
316
317 id = sw->getIterator();
318
319 for (i = 0; i < ::count * 8; i++)
320 nextRet = sw->next(id, &e);
321
322 return NULL;
323 }
324
BDL_bench_helper(void * arg)325 void* BDL_bench_helper(void* arg)
326 {
327 BandedDL<ElementType>* sw = reinterpret_cast<BandedDL<ElementType> *>(arg);
328 int i, id;
329 bool nextRet;
330 ElementType e;
331
332 id = sw->getIterator();
333
334 for (i = 0; i < ::count * 8; i++)
335 nextRet = sw->next(id, &e);
336
337 return NULL;
338 }
339
SWSDL_producer(void * arg)340 void* SWSDL_producer(void* arg)
341 {
342 SWSDL<ElementType>* sw = reinterpret_cast<SWSDL<ElementType> *>(arg);
343
344 for (int i = 0; i < ::count; i++)
345 sw->insert(ElementType(i, i));
346
347 return NULL;
348 }
349
BDL_producer(void * arg)350 void* BDL_producer(void* arg)
351 {
352 BandedDL<ElementType>* sw = reinterpret_cast<BandedDL<ElementType> *>(arg);
353 ElementType dle;
354
355 for (int i = 0; i < ::count; i++)
356 {
357 //dle.first = dle.second = i;
358 sw->insert(ElementType(i, i));
359 }
360
361 //sw->endOfInput();
362 //cout << "end of input size is " << sw->totalSize() << endl;
363 return NULL;
364 }
365
ZDL_producer(void * arg)366 void* ZDL_producer(void* arg)
367 {
368 ZDL<ElementType>* zdl = reinterpret_cast<ZDL<ElementType> *>(arg);
369
370 for (int i = 0; i < ::count; i++)
371 {
372 zdl.insert(ElementType((int) N * rand() / (RAND_MAX + 1.0), i));
373 }
374
375 return NULL;
376 }
377
ZDL_consumer(void * arg)378 void* ZDL_consumer(void* arg)
379 {
380 ZDL<ElementType>* zdl = reinterpret_cast<ZDL<ElementType> *>(arg);
381 int i, id;
382 bool nextRet;
383 ElementType e;
384
385 id = zdl->getIterator();
386 nextRet = zdl->next(id, &e);
387
388 while (nextRet)
389 nextRet = zdl->next(id, &e);
390
391 return NULL;
392 }
393
SWSDL_consumer(void * arg)394 void* SWSDL_consumer(void* arg)
395 {
396 SWSDL<ElementType>* sw = reinterpret_cast<SWSDL<ElementType> *>(arg);
397 int i, id;
398 bool nextRet;
399 ElementType e;
400
401 id = sw->getIterator();
402 nextRet = sw->next(id, &e);
403
404 while (nextRet)
405 nextRet = zdl->next(id, &e);
406
407 return NULL;
408 }
409
410 class DataListDriver : public CppUnit::TestFixture
411 {
412
413 CPPUNIT_TEST_SUITE(DataListDriver);
414
415 //CPPUNIT_TEST(FIFO_1);
416 //CPPUNIT_TEST(FIFO_2);
417 //CPPUNIT_TEST(MP_FIFO_stress); //10 consumers 10 producers
418 // CPPUNIT_TEST(FIFO_stress); // 10 consumers 1 producer; doesn't stop
419 // CPPUNIT_TEST(FIFO_bench);
420 // CPPUNIT_TEST(FIFO_singlethread_bench);
421 //CPPUNIT_TEST(WSDL_1);
422 //CPPUNIT_TEST(WSDL_2);
423 //CPPUNIT_TEST(WSDL_3); // WSDL_1 with StringElementTypes
424 // CPPUNIT_TEST(WSDL_bench);
425 // CPPUNIT_TEST(WSDL_singlethread_bench);
426 //CPPUNIT_TEST(CON_DL_1); // ConstantDataList
427 //CPPUNIT_TEST(BucketDL_1);
428
429 //CPPUNIT_TEST(BandedDL_1); // WSDL_2 ported to BandedDLs
430 //CPPUNIT_TEST(BandedDL_2); // BandedDL_1 that uses StringElementTypes
431
432 // make sure the DataList consumer-side interface works.
433 //CPPUNIT_TEST(BandedDL_as_WSDL_1);
434
435 // random inserts to bucketDL, create bandedDL, make sure it's in order
436 //CPPUNIT_TEST(BandedDL_as_WSDL_2);
437
438 /* tests prompted by feedback */
439 //CPPUNIT_TEST(polymorphism_1);
440
441 // make sure we can store basic types (int in this case)
442 //CPPUNIT_TEST(polymorphism_2);
443
444 // make sure we can create a FIFO, fill it, cast it to a DataList, and read the elements.
445 //CPPUNIT_TEST(polymorphism_3);
446 //CPPUNIT_TEST(SWSDL_bench);
447 //CPPUNIT_TEST(BDL_multiproducer_bench);
448 //CPPUNIT_TEST(BDL_consumer_bench);
449 //CPPUNIT_TEST(SWSDL_multiproducer_bench);
450 CPPUNIT_TEST(SWSDL_consumer_bench);
451 //CPPUNIT_TEST(BDL_singlethread_bench);
452 CPPUNIT_TEST(ZDL_bench);
453 CPPUNIT_TEST_SUITE_END();
454
455 private:
456 public:
457
FIFO_1()458 void FIFO_1()
459 {
460 int i, it;
461 DLElement dummy;
462 FIFO<DLElement> f(1, 20);
463 bool nextRet;
464
465 for (i = 0; i < 10; i++)
466 {
467 dummy.i = i;
468 f.insert(dummy);
469 }
470
471 f.endOfInput();
472 it = f.getIterator();
473 CPPUNIT_ASSERT(it == 0);
474
475 for (i = 0; i < 10; i++)
476 {
477 nextRet = f.next(it, &dummy);
478 CPPUNIT_ASSERT(nextRet == true);
479 CPPUNIT_ASSERT(dummy.i == i);
480 }
481 }
482
FIFO_2()483 void FIFO_2()
484 {
485 int i, it;
486 DLElement fe;
487 FIFO<DLElement> fifo(1, 2000);
488 pthread_t thread;
489 bool ret;
490
491 fe.i = 0;
492 pthread_create(&thread, NULL, FIFO_2_helper, &fifo);
493 sleep(1); // make sure the thread sleeps after 2000 inserts
494 it = fifo.getIterator();
495
496 for (i = 0; i < ::count; i++)
497 {
498 if (i % 100000 == 0)
499 cout << i << "/" << ::count << endl;
500
501 ret = fifo.next(it, &fe);
502 // cout << "fe = " << fe.i << endl;
503 CPPUNIT_ASSERT(ret == true);
504 CPPUNIT_ASSERT(fe.i == i);
505 }
506
507 ret = fifo.next(it, &fe); // should sleep until the thread calls endOfInput()
508 CPPUNIT_ASSERT(ret == false);
509 pthread_join(thread, NULL);
510 }
511
MP_FIFO_stress()512 void MP_FIFO_stress()
513 {
514 int64_t i;
515 FIFO<ElementType> f(10, 25000);
516 pthread_t consumer[10];
517 pthread_t producer[10];
518
519 f.setMultipleProducers(true);
520
521 for (i = 0; i < 10; i++)
522 pthread_create(&consumer[i], NULL, MP_FIFO_stress_consumer, &f);
523
524 for (i = 0; i < 10; i++)
525 pthread_create(&producer[i], NULL, MP_FIFO_stress_producer, &f);
526
527 for (i = 0; i < 10; i++)
528 pthread_join(producer[i], NULL);
529
530 f.endOfInput();
531
532 /*
533 // for (i = 0; i < MAXINT64; i++) {
534 for (i = 0; i < ::count; i++) {
535 if ((i % 10000000) == 0)
536 cout << i << endl;
537 f.insert(ElementType(i, i));
538 }
539 f.endOfInput();
540 */
541 for (i = 0; i < 10; i++)
542 pthread_join(consumer[i], NULL);
543 }
544
FIFO_stress()545 void FIFO_stress()
546 {
547 int64_t i;
548 FIFO<ElementType> f(10, 25000);
549 pthread_t consumer[10];
550
551 for (i = 0; i < 10; i++)
552 pthread_create(&consumer[i], NULL, FIFO_stress_consumer, &f);
553
554 // for (i = 0; i < MAXINT64; i++) {
555 for (i = 0; i < ::count; i++)
556 {
557 if ((i % 10000000) == 0)
558 cout << i << endl;
559
560 f.insert(ElementType(i, i));
561 }
562
563 f.endOfInput();
564
565 for (i = 0; i < 10; i++)
566 pthread_join(consumer[i], NULL);
567 }
568
FIFO_bench()569 void FIFO_bench()
570 {
571 int i;
572 FIFO<int> f(1, ::maxElements);
573 pthread_t consumer;
574 struct timespec tv1, tv2, diff;
575
576
577 pthread_create(&consumer, NULL, FIFO_bench_consumer, &f);
578 clock_gettime(CLOCK_REALTIME, &tv1);
579
580 for (i = 0; i < ::count; i++)
581 {
582 f.insert(i);
583 }
584
585 f.endOfInput();
586 pthread_join(consumer, NULL);
587 clock_gettime(CLOCK_REALTIME, &tv2);
588 timespec_sub(tv1, tv2, diff);
589 cout << "producer & consumer passed " << ::count << " elements in " <<
590 diff.tv_sec << "s " << diff.tv_nsec << "ns" << endl;
591
592 }
593
FIFO_singlethread_bench()594 void FIFO_singlethread_bench()
595 {
596 int i, it, e;
597 FIFO<int> f(1, ::count);
598 bool more;
599 struct timespec tv1, tv2, diff;
600
601 clock_gettime(CLOCK_REALTIME, &tv1);
602
603 for (i = 0; i < ::count; i++)
604 {
605 f.insert(i);
606 }
607
608 f.endOfInput();
609 clock_gettime(CLOCK_REALTIME, &tv2);
610 timespec_sub(tv1, tv2, diff);
611
612 cout << "FIFO_singlethreaded_bench: inserted " << ::count <<
613 " ints in " << diff.tv_sec << "s " << diff.tv_nsec << "ns" << endl;
614
615 it = f.getIterator();
616
617 for (i = 0; i < ::count; i++)
618 {
619 more = f.next(it, &e);
620 }
621
622 clock_gettime(CLOCK_REALTIME, &tv1);
623 timespec_sub(tv2, tv1, diff);
624 cout << "FIFO_singlethread_bench: consumed, took " << diff.tv_sec << "s " <<
625 diff.tv_nsec << "ns" << endl;
626 }
627
628
WSDL_1()629 void WSDL_1()
630 {
631 WSDL<ElementType> w(1, ::count / 100);
632 ElementType dle;
633 uint32_t i, id;
634 bool nextRet;
635
636 for (i = 0; i < ::count; i++)
637 {
638 // cout << "inserting " << i << endl;
639 dle.first = dle.second = i;
640 w.insert(dle);
641 }
642
643 w.endOfInput();
644 id = w.getIterator();
645
646 for (i = 0; i < ::count; i++)
647 {
648 nextRet = w.next(id, &dle);
649 // cout << i << ":got " << dle.first << " " << dle.second << endl;
650 CPPUNIT_ASSERT(nextRet == true);
651 CPPUNIT_ASSERT(dle.first == i && dle.second == i);
652 }
653 }
654
WSDL_2()655 void WSDL_2()
656 {
657 WSDL<ElementType> w(2, ::count / 10);
658 ElementType dle;
659 uint32_t i, id, size;
660 bool nextRet;
661 pthread_t consumer1;
662
663 pthread_create(&consumer1, NULL, WSDL_2_helper, &w);
664
665 // thread should wait here waiting on endOfInput()
666
667 for (i = 0; i < ::count; i++)
668 {
669 dle.first = dle.second = i;
670 w.insert(dle);
671 }
672
673 sleep(1);
674 w.endOfInput();
675
676 /* let the thread consume the loaded set; make sure that the load
677 doesn't happen until the main thread finishes with the loaded set */
678
679 sleep(1);
680 size = w.totalSize();
681 id = w.getIterator();
682
683 for (i = 0; i < ::count; i++)
684 {
685 nextRet = w.next(id, &dle);
686 // cout << "got " << dle.i << endl;
687 CPPUNIT_ASSERT(nextRet == true);
688 CPPUNIT_ASSERT(dle.first == i && dle.second == i);
689 }
690
691 pthread_join(consumer1, NULL);
692 }
693
WSDL_3()694 void WSDL_3()
695 {
696 WSDL<StringElementType> w(1, ::count / 10);
697 StringElementType dle;
698 uint32_t i, id;
699 bool nextRet;
700
701 for (i = 0; i < ::count; i++)
702 {
703 ostringstream os;
704
705 os << "blah blah blah" << i;
706 // cout << "inserting " << i << endl;
707 dle.first = i;
708 dle.second = os.str();
709 w.insert(dle);
710 }
711
712 w.endOfInput();
713 id = w.getIterator();
714
715 for (i = 0; i < ::count; i++)
716 {
717 ostringstream os;
718
719 os << "blah blah blah" << i;
720 nextRet = w.next(id, &dle);
721 // cout << i << ":got " << dle.first << " " << dle.second << endl;
722 CPPUNIT_ASSERT(nextRet == true);
723 CPPUNIT_ASSERT(dle.first == i && dle.second == os.str());
724 }
725 }
726
WSDL_bench()727 void WSDL_bench()
728 {
729 WSDL<ElementType> w(1, ::maxElements);
730 int i;
731 pthread_t consumer;
732 struct timespec ts1, ts2, diff;
733
734 clock_gettime(CLOCK_REALTIME, &ts1);
735 pthread_create(&consumer, NULL, WSDL_bench_helper, &w);
736
737 for (i = 0; i < ::count; i++)
738 w.insert(ElementType(i, i));
739
740 w.endOfInput();
741 cout << "end of input size is " << w.totalSize() << endl;
742 pthread_join(consumer, NULL);
743 clock_gettime(CLOCK_REALTIME, &ts2);
744 timespec_sub(ts1, ts2, diff);
745 cout << "WSDL_bench: producer & consumer passed " << ::count << " elements in " <<
746 diff.tv_sec << "s " << diff.tv_nsec << "ns" << endl;
747 }
748
WSDL_singlethread_bench()749 void WSDL_singlethread_bench()
750 {
751 WSDL<int> w(1, ::maxElements);
752 int i, id, e;
753 bool nextRet;
754 struct timespec ts1, ts2, diff;
755
756 clock_gettime(CLOCK_REALTIME, &ts1);
757
758 for (i = 0; i < ::count; i++)
759 w.insert(i);
760
761 w.endOfInput();
762 id = w.getIterator();
763
764 for (i = 0; i < ::count; i++)
765 nextRet = w.next(id, &e);
766
767 clock_gettime(CLOCK_REALTIME, &ts2);
768 timespec_sub(ts1, ts2, diff);
769 cout << "WSDL_singlethread_bench: producer & consumer passed " <<
770 ::count << " elements in " << diff.tv_sec << "s " << diff.tv_nsec <<
771 "ns" << endl;
772 }
773
SWSDL_bench()774 void SWSDL_bench()
775 {
776 /*
777 SWSDL<ElementType> sw(1, ::maxElements);
778 int i;
779 pthread_t consumer;
780 pthread_t producer;
781 struct timespec ts1, ts2, diff;
782
783 clock_gettime(CLOCK_REALTIME, &ts1);
784 pthread_create(&producer, NULL, SWSDL_producer, &sw);
785 pthread_create(&consumer, NULL, SWSDL_bench_helper, &sw);
786
787 pthread_join(producer, NULL);
788 pthread_join(consumer, NULL);
789 clock_gettime(CLOCK_REALTIME, &ts2);
790 timespec_sub(ts1, ts2, diff);
791 cout << "SWSDL_bench: producer & consumer passed " << ::count << " elements in " <<
792 diff.tv_sec << "s " << diff.tv_nsec << "ns" << endl;
793 */
794 SWSDL<ElementType> sw(1, ::maxElements);
795 int i;
796 pthread_t consumer;
797 struct timespec ts1, ts2, diff;
798
799 clock_gettime(CLOCK_REALTIME, &ts1);
800 pthread_create(&consumer, NULL, SWSDL_bench_helper, &sw);
801
802 for (i = 0; i < ::count; i++)
803 sw.insert(ElementType(i, i));
804
805 sw.endOfInput();
806 cout << "end of input size is " << sw.totalSize() << endl;
807 pthread_join(consumer, NULL);
808 clock_gettime(CLOCK_REALTIME, &ts2);
809 timespec_sub(ts1, ts2, diff);
810 cout << "SWSDL_bench: producer & consumer passed " << ::count << " elements in " <<
811 diff.tv_sec << "s " << diff.tv_nsec << "ns" << endl;
812 }
813
SWSDL_multiproducer_bench()814 void SWSDL_multiproducer_bench()
815 {
816 SWSDL<ElementType> sw(1, ::maxElements);
817 sw.setMultipleProducers(true);
818 int i, id;
819 ElementType e;
820 bool nextRet;
821 uint32_t numOfThreads = 8;
822 pthread_t producer[numOfThreads];
823 struct timespec ts1, ts2, diff;
824
825 clock_gettime(CLOCK_REALTIME, &ts1);
826
827 for (i = 0; i < numOfThreads; i++)
828 pthread_create(&producer[i], NULL, SWSDL_producer, &sw);
829
830 for (i = 0; i < numOfThreads; i++)
831 pthread_join(producer[i], NULL);
832
833 sw.endOfInput();
834 cout << "end of input size is " << sw.totalSize() << endl;
835 clock_gettime(CLOCK_REALTIME, &ts2);
836 timespec_sub(ts1, ts2, diff);
837 cout << "# of Producer: " << numOfThreads << endl;
838 cout << "SWSDL_producer_phase_bench: producer & consumer passed " <<
839 ::count* numOfThreads << " elements in " << diff.tv_sec << "s " << diff.tv_nsec <<
840 "ns" << endl;
841 clock_gettime(CLOCK_REALTIME, &ts1);
842 id = sw.getIterator();
843
844 for (i = 0; i < ::count; i++)
845 nextRet = sw.next(id, &e);
846
847 clock_gettime(CLOCK_REALTIME, &ts2);
848 timespec_sub(ts1, ts2, diff);
849
850 cout << "SWSDL_consumer_phase_bench: producer & consumer passed " <<
851 ::count* numOfThreads << " elements in " << diff.tv_sec << "s " << diff.tv_nsec <<
852 "ns" << endl;
853 }
854
SWSDL_consumer_bench()855 void SWSDL_consumer_bench()
856 {
857 SWSDL<ElementType> sw(4);
858 sw.setMultipleProducers(true);
859 ElementType dle;
860 uint32_t i, id;
861 bool nextRet;
862 uint32_t numOfProducers = 8;
863 uint32_t numOfConsumers = 4;
864 pthread_t producer[numOfProducers];
865 pthread_t consumer[numOfConsumers];
866 struct timespec ts1, ts2, diff;
867
868 clock_gettime(CLOCK_REALTIME, &ts1);
869
870 for (i = 0; i < numOfProducers; i++)
871 pthread_create(&producer[i], NULL, SWSDL_producer, &sw);
872
873 for (i = 0; i < numOfConsumers; i++)
874 pthread_create(&consumer[i], NULL, SWSDL_consumer, &sw);
875
876 for (i = 0; i < numOfThreads; i++)
877 pthread_join(producer[i], NULL);
878
879 sw.endOfInput();
880
881 clock_gettime(CLOCK_REALTIME, &ts2);
882 timespec_sub(ts1, ts2, diff);
883
884 cout << "# of Producer: " << numOfThreads << endl;
885 cout << "SWSDL_consumer_bench: producer & consumer passed " <<
886 ::count* numOfThreads << " elements in " << diff.tv_sec << "s " << diff.tv_nsec <<
887 "ns" << endl;
888 }
889
890
BDL_multiproducer_bench()891 void BDL_multiproducer_bench()
892 {
893 BandedDL<ElementType> w(2);
894 w.setMultipleProducers(true);
895 ElementType dle;
896 uint32_t i, id;
897 bool nextRet;
898 uint32_t numOfThreads = 8;
899 pthread_t producer[numOfThreads];
900 struct timespec ts1, ts2, diff;
901
902 clock_gettime(CLOCK_REALTIME, &ts1);
903
904 for (i = 0; i < numOfThreads; i++)
905 pthread_create(&producer[i], NULL, BDL_producer, &w);
906
907 for (i = 0; i < numOfThreads; i++)
908 pthread_join(producer[i], NULL);
909
910 w.endOfInput();
911 cout << "end of input size is " << w.totalSize() << endl;
912 clock_gettime(CLOCK_REALTIME, &ts2);
913 timespec_sub(ts1, ts2, diff);
914 cout << "# of Producer: " << numOfThreads << endl;
915 cout << "BDL_producer_phase_bench: producer & consumer passed " <<
916 ::count* numOfThreads << " elements in " << diff.tv_sec << "s " << diff.tv_nsec <<
917 "ns" << endl;
918
919 clock_gettime(CLOCK_REALTIME, &ts1);
920 id = w.getIterator();
921
922 for (i = 0; i < ::count; i++)
923 {
924 nextRet = w.next(id, &dle);
925 }
926
927 clock_gettime(CLOCK_REALTIME, &ts2);
928 timespec_sub(ts1, ts2, diff);
929
930 cout << "BDL_consumer_phase_bench: producer & consumer passed " <<
931 ::count* numOfThreads << " elements in " << diff.tv_sec << "s " << diff.tv_nsec <<
932 "ns" << endl;
933 /*
934 SWSDL<ElementType> sw(1, ::maxElements);
935 int i;
936 pthread_t consumer;
937 struct timespec ts1, ts2, diff;
938
939 clock_gettime(CLOCK_REALTIME, &ts1);
940 pthread_create(&consumer, NULL, SWSDL_bench_helper, &sw);
941 for (i = 0; i < ::count; i++)
942 sw.insert(ElementType(i, i));
943
944 sw.endOfInput();
945 cout << "end of input size is " << sw.totalSize() << endl;
946 pthread_join(consumer, NULL);
947 clock_gettime(CLOCK_REALTIME, &ts2);
948 timespec_sub(ts1, ts2, diff);
949 cout << "SWSDL_bench: producer & consumer passed " << ::count << " elements in " <<
950 diff.tv_sec << "s " << diff.tv_nsec << "ns" << endl;
951 */
952 }
953
BDL_consumer_bench()954 void BDL_consumer_bench()
955 {
956 BandedDL<ElementType> w(2);
957 w.setMultipleProducers(true);
958 ElementType dle;
959 uint32_t i, id;
960 bool nextRet;
961 uint32_t numOfThreads = 8;
962 pthread_t producer[numOfThreads];
963 pthread_t consumer;
964 struct timespec ts1, ts2, diff;
965
966 clock_gettime(CLOCK_REALTIME, &ts1);
967
968 for (i = 0; i < numOfThreads; i++)
969 pthread_create(&producer[i], NULL, BDL_producer, &w);
970
971 for (i = 0; i < numOfThreads; i++)
972 pthread_join(producer[i], NULL);
973
974 w.endOfInput();
975 //pthread_create(&consumer, NULL, BDL_bench_helper, &w);
976 //cout << "end of input size is " << w.totalSize() << endl;
977 //clock_gettime(CLOCK_REALTIME, &ts2);
978 //timespec_sub(ts1, ts2, diff);
979 //cout << "# of Producer: " << numOfThreads << endl;
980 //cout << "BDL_producer_phase_bench: producer & consumer passed " <<
981 // ::count * numOfThreads << " elements in " << diff.tv_sec << "s " << diff.tv_nsec <<
982 // "ns" << endl;
983
984 //clock_gettime(CLOCK_REALTIME, &ts1);
985 id = w.getIterator();
986
987 for (i = 0; i < ::count * 8; i++)
988 {
989 nextRet = w.next(id, &dle);
990 }
991
992 clock_gettime(CLOCK_REALTIME, &ts2);
993 timespec_sub(ts1, ts2, diff);
994 cout << "end of input size is " << w.totalSize() << endl;
995 cout << "BDL_consumer_phase_bench: producer & consumer passed " <<
996 ::count* numOfThreads << " elements in " << diff.tv_sec << "s " << diff.tv_nsec <<
997 "ns" << endl;
998 /*
999 SWSDL<ElementType> sw(1, ::maxElements);
1000 int i;
1001 pthread_t consumer;
1002 struct timespec ts1, ts2, diff;
1003
1004 clock_gettime(CLOCK_REALTIME, &ts1);
1005 pthread_create(&consumer, NULL, SWSDL_bench_helper, &sw);
1006 for (i = 0; i < ::count; i++)
1007 sw.insert(ElementType(i, i));
1008
1009 sw.endOfInput();
1010 cout << "end of input size is " << sw.totalSize() << endl;
1011 pthread_join(consumer, NULL);
1012 clock_gettime(CLOCK_REALTIME, &ts2);
1013 timespec_sub(ts1, ts2, diff);
1014 cout << "SWSDL_bench: producer & consumer passed " << ::count << " elements in " <<
1015 diff.tv_sec << "s " << diff.tv_nsec << "ns" << endl;
1016 */
1017 }
1018
BDL_singlethread_bench()1019 void BDL_singlethread_bench()
1020 {
1021 /*SWSDL<ElementType> sw(1, ::maxElements);
1022 int i;
1023 pthread_t consumer;
1024 pthread_t producer;
1025 struct timespec ts1, ts2, diff;
1026
1027 clock_gettime(CLOCK_REALTIME, &ts1);
1028 pthread_create(&producer, NULL, SWSDL_producer, &sw);
1029 pthread_join(producer, NULL);
1030 pthread_create(&consumer, NULL, SWSDL_bench_helper, &sw);
1031
1032 pthread_join(consumer, NULL);
1033 clock_gettime(CLOCK_REALTIME, &ts2);
1034 timespec_sub(ts1, ts2, diff);*/
1035 SWSDL<ElementType> sw(1, ::maxElements);
1036 int i, id;
1037 ElementType e;
1038 bool nextRet;
1039 struct timespec ts1, ts2, diff;
1040
1041 clock_gettime(CLOCK_REALTIME, &ts1);
1042 cout << "start of input size is " << ::count << endl;
1043
1044 for (i = 0; i < ::count; i++)
1045 sw.insert(ElementType(i, i));
1046
1047 //cout << "end of input size is " << sw.totalSize() << endl;
1048 //sw.endOfInput();
1049 //id = sw.getIterator();
1050 for (i = 0; i < ::count; i++)
1051 nextRet = sw.next(id, &e);
1052
1053 clock_gettime(CLOCK_REALTIME, &ts2);
1054 timespec_sub(ts1, ts2, diff);
1055
1056 //cout << "SWSDL_consumer_phase_bench: producer & consumer passed " <<
1057 // ::count << " elements in " << diff.tv_sec << "s " << diff.tv_nsec <<
1058 // "ns" << endl;
1059 }
1060
CON_DL_1()1061 void CON_DL_1()
1062 {
1063 DLElement d, d2;
1064 int i = 0;
1065 bool nextRet;
1066
1067 d.i = 1;
1068
1069 ConstantDataList<DLElement> c(d);
1070
1071 nextRet = c.next(i, &d2);
1072 CPPUNIT_ASSERT(nextRet == true);
1073 CPPUNIT_ASSERT(d.i == 1 && d2.i == 1);
1074
1075 d.i = 2;
1076 c.insert(d);
1077 nextRet = c.next(i, &d2);
1078 CPPUNIT_ASSERT(nextRet == true);
1079 CPPUNIT_ASSERT(d.i == 2 && d2.i == 2);
1080 }
1081
BucketDL_1()1082 void BucketDL_1()
1083 {
1084 BucketDL<ElementType> bdl(16, 1, ::count / 100);
1085 ElementType dle;
1086 uint32_t i, it, eCount = 0, buckets;
1087 bool nextRet;
1088
1089 for (i = 0; i < ::count; i++)
1090 {
1091 // if (i % 1000000 == 0) cout << i << endl;
1092 dle.first = dle.second = i;
1093 bdl.insert(dle);
1094 }
1095
1096 bdl.endOfInput();
1097 // cout << "inserted " << ::count << " elements" << endl;
1098
1099 buckets = bdl.bucketCount();
1100
1101 for (i = 0; i < buckets; i++)
1102 {
1103 it = bdl.getIterator(i);
1104
1105 do
1106 {
1107 nextRet = bdl.next(i, it, &dle);
1108
1109 if (nextRet)
1110 {
1111 CPPUNIT_ASSERT(dle.first >= 0 && dle.first <= (uint64_t) ::count);
1112 CPPUNIT_ASSERT(++eCount <= ::count);
1113 }
1114 }
1115 while (nextRet == true);
1116 }
1117
1118 CPPUNIT_ASSERT(eCount == ::count);
1119 }
1120
BandedDL_1()1121 void BandedDL_1()
1122 {
1123 BandedDL<ElementType> w(2);
1124 ElementType dle;
1125 uint32_t i, id, size;
1126 bool nextRet;
1127 pthread_t consumer1;
1128
1129 pthread_create(&consumer1, NULL, BandedDL_1_helper, &w);
1130
1131 // thread should wait here waiting on endOfInput()
1132
1133 for (i = 0; i < ::count; i++)
1134 {
1135 dle.first = dle.second = i;
1136 w.insert(dle);
1137
1138 if (((i + 1) % (::count / 10)) == 0)
1139 {
1140 cout << "inserted " << i + 1 << "/" << ::count << endl;
1141 w.saveBand();
1142 }
1143 }
1144
1145 sleep(1);
1146 w.endOfInput();
1147
1148 /* let the thread consume the loaded set; make sure that the load
1149 doesn't happen until the main thread finishes with the loaded set */
1150
1151 sleep(5);
1152 size = w.totalSize();
1153 id = w.getIterator();
1154
1155 for (i = 0; i < ::count; i++)
1156 {
1157 nextRet = w.next(id, &dle);
1158 // cout << "got " << dle.i << endl;
1159 CPPUNIT_ASSERT(nextRet == true);
1160 CPPUNIT_ASSERT(dle.first == i);
1161 }
1162
1163 pthread_join(consumer1, NULL);
1164 }
1165
BandedDL_2()1166 void BandedDL_2()
1167 {
1168 BandedDL<StringElementType> w(2);
1169 StringElementType dle;
1170 uint32_t i, id, size;
1171 bool nextRet;
1172 pthread_t consumer1;
1173
1174 pthread_create(&consumer1, NULL, BandedDL_2_helper, &w);
1175
1176 // thread should wait here waiting on endOfInput()
1177
1178 for (i = 0; i < ::count; i++)
1179 {
1180 ostringstream os;
1181
1182 os << "blah blah" << i;
1183
1184 dle.first = i;
1185 dle.second = os.str();
1186 w.insert(dle);
1187
1188 if (((i + 1) % (::count / 10)) == 0)
1189 {
1190 cout << "inserted " << i + 1 << "/" << ::count << endl;
1191 w.saveBand();
1192 }
1193 }
1194
1195 sleep(1);
1196 w.endOfInput();
1197
1198 /* let the thread consume the loaded set; make sure that the load
1199 doesn't happen until the main thread finishes with the loaded set */
1200
1201 cout << "endofInput finished\n";
1202
1203 sleep(5);
1204 size = w.totalSize();
1205 id = w.getIterator();
1206
1207 for (i = 0; i < ::count; i++)
1208 {
1209 ostringstream os;
1210
1211 os << "blah blah" << i;
1212 nextRet = w.next(id, &dle);
1213 // cout << "got " << dle.i << endl;
1214 CPPUNIT_ASSERT(nextRet == true);
1215 CPPUNIT_ASSERT(dle.first == i && dle.second == os.str());
1216 }
1217
1218 pthread_join(consumer1, NULL);
1219 }
1220
BandedDL_as_WSDL_1()1221 void BandedDL_as_WSDL_1()
1222 {
1223 BandedDL<ElementType> bdl(1);
1224 ElementType e;
1225 uint32_t i, it;
1226 bool more;
1227
1228 for (i = 1; i <= ::count; i++)
1229 {
1230 e.first = e.second = i;
1231 bdl.insert(e);
1232
1233 if (i % (::count / 10) == 0)
1234 bdl.saveBand();
1235 }
1236
1237 bdl.endOfInput();
1238
1239 it = bdl.getIterator();
1240
1241 for (i = 1; i <= ::count; i++)
1242 {
1243 more = bdl.next(it, &e);
1244 CPPUNIT_ASSERT(more == true);
1245 CPPUNIT_ASSERT(e.first == i && e.second == i);
1246 }
1247
1248 more = bdl.next(it, &e);
1249 CPPUNIT_ASSERT(more == false);
1250
1251 bdl.restart();
1252
1253 /* make sure it can be read again */
1254 for (i = 1; i <= ::count; i++)
1255 {
1256 more = bdl.next(it, &e);
1257
1258 if (!more)
1259 cerr << i << endl;
1260
1261 CPPUNIT_ASSERT(more == true);
1262 CPPUNIT_ASSERT(e.first == i && e.second == i);
1263 }
1264
1265 more = bdl.next(it, &e);
1266 CPPUNIT_ASSERT(more == false);
1267 }
1268
BandedDL_as_WSDL_2()1269 void BandedDL_as_WSDL_2()
1270 {
1271 BucketDL<ElementType> bucketDL(::buckets, 1, 1000, BandGrouper());
1272 uint32_t last, i, it;
1273 ElementType dle;
1274 bool more;
1275
1276 srand(time(NULL));
1277
1278 for (i = 0; i < ::count; i++)
1279 {
1280 dle.first = dle.second = rand() % ::count; // artificial max
1281 bucketDL.insert(dle);
1282 }
1283
1284 bucketDL.endOfInput();
1285
1286 // cout << "made bucketdl" << endl;
1287
1288 BandedDL<ElementType> bdl(bucketDL, 1);
1289
1290 // cout << "made bandeddl" << endl;
1291
1292 it = bdl.getIterator();
1293 last = 0;
1294 // duplicates were removed, there won't be ::count elements in bdl
1295 more = bdl.next(it, &dle);
1296
1297 while (more)
1298 {
1299 CPPUNIT_ASSERT(dle.first < (uint64_t) ::count);
1300 // cout << dle.first << " >= " << last << endl;
1301 CPPUNIT_ASSERT(dle.first >= last);
1302 last = dle.first;
1303 more = bdl.next(it, &dle);
1304 }
1305
1306 // cerr << "read through bandeddl" << endl;
1307
1308 more = bdl.next(it, &dle);
1309 CPPUNIT_ASSERT(more == false);
1310
1311 }
1312
ZDL_bench()1313 void ZDL_bench()
1314 {
1315 ZDL<ElementType> zdl(4);
1316 zdl.setMultipleProducers(true);
1317 ElementType dle;
1318 uint32_t i, id;
1319 bool nextRet;
1320 uint32_t numOfProducers = 8;
1321 uint32_t numOfConsumers = 4;
1322 pthread_t producer[numOfProducers];
1323 pthread_t consumer[numOfConsumers];
1324 struct timespec ts1, ts2, diff;
1325
1326 clock_gettime(CLOCK_REALTIME, &ts1);
1327
1328 for (i = 0; i < numOfProducers; i++)
1329 pthread_create(&producer[i], NULL, ZDL_producer, &zdl);
1330
1331 for (i = 0; i < numOfConsumers; i++)
1332 pthread_create(&consumer[i], NULL, ZDL_consumer, &zdl);
1333
1334 for (i = 0; i < numOfThreads; i++)
1335 pthread_join(producer[i], NULL);
1336
1337 zdl.endOfInput();
1338
1339 //clock_gettime(CLOCK_REALTIME, &ts1);
1340 id = w.getIterator();
1341
1342 for (i = 0; i < ::count * 8; i++)
1343 {
1344 nextRet = w.next(id, &dle);
1345 }
1346
1347 clock_gettime(CLOCK_REALTIME, &ts2);
1348 timespec_sub(ts1, ts2, diff);
1349 cout << "end of input size is " << w.totalSize() << endl;
1350 cout << "ZDL_consumer_producer_bench: producer & consumer passed " <<
1351 ::count* numOfProducers << " elements in " << diff.tv_sec << "s " << diff.tv_nsec <<
1352 "ns" << endl;
1353
1354 }
1355
1356 /* Sanity test */
polymorphism_1()1357 void polymorphism_1()
1358 {
1359 DataList<DLElement>* dl;
1360 FIFO<DLElement>* f;
1361 DLElement dle;
1362 int it, i;
1363 bool more;
1364
1365 f = new FIFO<DLElement>(1, 20);
1366 dl = (DataList<DLElement>*) f;
1367
1368 it = dl->getIterator();
1369
1370 for (i = 0; i < 10; i++)
1371 {
1372 dle.i = i;
1373 dl->insert(dle);
1374 }
1375
1376 dl->endOfInput();
1377
1378 for (i = 0; i < 10; i++)
1379 {
1380 more = dl->next(it, &dle);
1381 // cout << dle.i << endl;
1382 CPPUNIT_ASSERT(more == true);
1383 CPPUNIT_ASSERT(dle.i == i);
1384 }
1385
1386 delete f;
1387 }
1388
1389 /* Sanity test 2. Can we stuff basic datatypes into DataLists? Apparently not. WHY?*/
polymorphism_2()1390 void polymorphism_2()
1391 {
1392 DataList<int>* dl;
1393 FIFO<int>* f = new FIFO<int>(1, 20);
1394 int it, i, dle;
1395 bool more;
1396
1397 dl = (DataList<int>*) f;
1398
1399 it = dl->getIterator();
1400
1401 for (i = 0; i < 10; i++)
1402 dl->insert(i);
1403
1404 dl->endOfInput();
1405
1406 for (i = 0; i < 10; i++)
1407 {
1408 more = dl->next(it, &dle);
1409 CPPUNIT_ASSERT(more == true);
1410 CPPUNIT_ASSERT(dle == i);
1411 // cout << "dle[" << i << "]: " << dle << endl;
1412 }
1413
1414 delete f;
1415 }
1416
polymorphism_3()1417 void polymorphism_3()
1418 {
1419 DataList<DLElement>* dl;
1420 FIFO<DLElement>* f;
1421 int it, i;
1422 DLElement dle;
1423 bool more;
1424
1425 f = new FIFO<DLElement>(1, 20);
1426 dl = (DataList<DLElement>*) f;
1427
1428 it = dl->getIterator();
1429
1430 for (i = 0; i < 10; i++)
1431 {
1432 dle.i = i;
1433 f->insert(dle);
1434 }
1435
1436 f->endOfInput();
1437
1438 for (i = 0; i < 10; i++)
1439 {
1440 // cout << "next" << endl;
1441 more = dl->next(it, &dle);
1442 CPPUNIT_ASSERT(more == true);
1443 CPPUNIT_ASSERT(dle.i == i);
1444 // cout << "dle[" << i << "]: " << dle.i << endl;
1445 }
1446
1447 delete f;
1448 }
1449
1450
1451
1452
1453
1454
1455 };
1456
1457 CPPUNIT_TEST_SUITE_REGISTRATION(DataListDriver);
1458
1459
main(int argc,char ** argv)1460 int main( int argc, char** argv)
1461 {
1462 CppUnit::TextUi::TestRunner runner;
1463 CppUnit::TestFactoryRegistry& registry = CppUnit::TestFactoryRegistry::getRegistry();
1464 runner.addTest( registry.makeTest() );
1465 bool wasSuccessful = runner.run( "", false );
1466 return (wasSuccessful ? 0 : 1);
1467 }
1468
1469
1470