1 /* Copyright (C) 2014 InfiniDB, Inc.
2 Copyright (C) 2016 MariaDB Corporation
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; version 2 of
7 the License.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 MA 02110-1301, USA. */
18
19 #include <string>
20 #include <stdexcept>
21 #include <typeinfo>
22 using namespace std;
23
24 #include <cppunit/extensions/HelperMacros.h>
25
26 #include<sstream>
27 #include<exception>
28 #include<iostream>
29 #include <unistd.h>
30 #include <cstdlib>
31 #include <pthread.h>
32 #include <values.h>
33 #include <signal.h>
34 #include <errno.h>
35 #include <sys/types.h>
36 #include <sys/ipc.h>
37 #include <sys/sem.h>
38 #include <sys/shm.h>
39
40 #include "configcpp.h"
41 using namespace config;
42
43 #include "messagequeue.h"
44 #include "bytestream.h"
45 using namespace messageqcpp;
46
47 #include "calpontselectexecutionplan.h"
48 #include "simplefilter.h"
49 #include "simplecolumn.h"
50 #include "expressionparser.h"
51 #include "constantcolumn.h"
52 #include "treenode.h"
53 #include "operator.h"
54 #include "arithmeticcolumn.h"
55 #include "aggregatecolumn.h"
56 #include "existsfilter.h"
57 #include "functioncolumn.h"
58 #include "selectfilter.h"
59 #include "objectreader.h"
60 #include "objectidmanager.h"
61 #include "sessionmanager.h"
62 #include "sessionmonitor.h"
63 #include "treenodeimpl.h"
64
65 using namespace execplan;
66
67 const char* OIDBitmapFilename = NULL;
68 int maxNewTxns = 1000;
69
70 class ExecPlanTest : public CppUnit::TestFixture
71 {
72
73 CPPUNIT_TEST_SUITE( ExecPlanTest );
74
75 CPPUNIT_TEST( selectExecutionPlan_1 );
76 CPPUNIT_TEST( selectExecutionPlan_2 );
77 CPPUNIT_TEST( expressionParser_1 );
78 CPPUNIT_TEST( expressionParser_2 );
79 CPPUNIT_TEST( aggregatecolumn_1 );
80 CPPUNIT_TEST( arithmeticExpression_1 );
81 CPPUNIT_TEST( arithmeticExpression_2 );
82 CPPUNIT_TEST( arithmeticExpression_3 );
83 CPPUNIT_TEST( copyTree );
84 CPPUNIT_TEST( treeNodeImpl );
85 CPPUNIT_TEST( serializeSimpleColumn );
86 CPPUNIT_TEST( serializeAggregateColumn );
87 CPPUNIT_TEST( serializeOperator );
88 CPPUNIT_TEST( serializeFilter );
89 CPPUNIT_TEST( serializeFunctionColumn );
90 CPPUNIT_TEST( serializeConstantColumn );
91 CPPUNIT_TEST( serializeParseTree );
92 CPPUNIT_TEST( serializeArithmeticColumn );
93 CPPUNIT_TEST( serializeSimpleFilter );
94 CPPUNIT_TEST( serializeCSEP );
95 CPPUNIT_TEST( serializeSelectFilter );
96 CPPUNIT_TEST( serializeExistsFilter );
97
98 CPPUNIT_TEST( sessionManager_1 );
99 CPPUNIT_TEST( sessionManager_2 );
100 CPPUNIT_TEST( sessionManager_3 );
101 CPPUNIT_TEST( sessionManager_4 );
102
103 unlink("/tmp/CalpontSessionMonitorShm");
104 //CPPUNIT_TEST( MonitorTestPlan_1 );
105 //CPPUNIT_TEST( MonitorTestPlan_1 );
106 unlink("/tmp/CalpontSessionMonitorShm");
107 CPPUNIT_TEST( objectIDManager_1 );
108
109 if (OIDBitmapFilename != NULL)
110 unlink(OIDBitmapFilename);
111
112 CPPUNIT_TEST_SUITE_END();
113
114 private:
115 boost::shared_ptr<CalpontSystemCatalog> csc;
116 public:
117
walkfnString(const ParseTree * n)118 static void walkfnString(const ParseTree* n)
119 {
120 cout << *(n->data()) << endl;
121 }
122
walkfnInt(const ExpressionTree<int> * n)123 static void walkfnInt(const ExpressionTree<int>* n)
124 {
125 cout << n->data() << endl;
126 }
127
setUp()128 void setUp()
129 {
130 csc = CalpontSystemCatalog::makeCalpontSystemCatalog(0);
131 csc->identity(CalpontSystemCatalog::FE);
132 }
133
tearDown()134 void tearDown()
135 {
136 }
137
selectExecutionPlan_1()138 void selectExecutionPlan_1()
139 {
140 cout << "SQL: select region.r_regionkey from region, nation where nation.n_regionkey = region.r_regionkey and nation.n_regionkey != 3;" << endl;
141
142 CalpontSelectExecutionPlan csep;
143 CPPUNIT_ASSERT (csep.location() == CalpontSelectExecutionPlan::MAIN);
144 CPPUNIT_ASSERT (csep.dependent() == false);
145 CPPUNIT_ASSERT (csep.subSelects().size() == 0);
146
147 // returned columns
148 CalpontSelectExecutionPlan::ReturnedColumnList colList;
149 SimpleColumn* sc = new SimpleColumn("tpch.region.r_regionkey", 0);
150 colList.push_back(sc);
151 ArithmeticColumn* ac = new ArithmeticColumn("a+sum(r_regionkey)", 0);
152 colList.push_back(ac);
153 csep.returnedCols (colList);
154 CPPUNIT_ASSERT(csep.returnedCols().size() == 2);
155
156 // filters
157 CalpontSelectExecutionPlan::FilterTokenList filterTokenList;
158
159 SimpleFilter* sf = new SimpleFilter();
160 SimpleColumn* lhs = new SimpleColumn();
161 *lhs = *sc;
162 SimpleColumn* rhs = new SimpleColumn("tpch.nation.n_regionkey", 0);
163 CPPUNIT_ASSERT (*lhs == *sc);
164 CPPUNIT_ASSERT (*rhs != *lhs);
165 Operator* op = new Operator("=");
166
167 sf->op(op);
168 sf->lhs(lhs);
169 sf->rhs(rhs);
170 filterTokenList.push_back (sf);
171
172 filterTokenList.push_back( new Operator ("And") );
173 SimpleFilter* sf1 = new SimpleFilter (new Operator("="), sc->clone(), ac->clone());
174
175 filterTokenList.push_back (sf1);
176
177 csep.filterTokenList (filterTokenList);
178 ParseTree* filterList = const_cast<ParseTree*> (csep.filters());
179
180 // draw filterList tree
181 filterList->drawTree("selectExecutionPlan_1.dot");
182 csep.filters (filterList);
183
184 // Group by
185 CalpontSelectExecutionPlan::GroupByColumnList groupByList;
186 groupByList.push_back(sc->clone());
187 csep.groupByCols (groupByList);
188 CPPUNIT_ASSERT(csep.groupByCols().size() == 1);
189
190 // Having
191 CalpontSelectExecutionPlan::FilterTokenList havingTokenList;
192 SimpleFilter* having = new SimpleFilter( new Operator("="),
193 new ArithmeticColumn("sum(volumn)", 0),
194 new ConstantColumn(8));
195 havingTokenList.push_back (having);
196 csep.havingTokenList (havingTokenList);
197 CPPUNIT_ASSERT (*sf1 != *having);
198 CPPUNIT_ASSERT (csep.havingTokenList().size() == 1);
199
200 // Order by
201 CalpontSelectExecutionPlan::OrderByColumnList orderByList;
202 ArithmeticColumn* o1 = new ArithmeticColumn(*ac);
203 o1->asc(false);
204 orderByList.push_back(o1);
205 csep.orderByCols(orderByList);
206 CPPUNIT_ASSERT(csep.orderByCols().size() == 1);
207
208 // another csep
209 CalpontSelectExecutionPlan* newcsep = new CalpontSelectExecutionPlan(CalpontSelectExecutionPlan::FROM);
210 CalpontSelectExecutionPlan::ReturnedColumnList ncolList;
211 SimpleColumn* newsc = new SimpleColumn("tpch.region.r_regionkey", 0);
212 ncolList.push_back(newsc);
213 newcsep->returnedCols (ncolList);
214 CalpontSelectExecutionPlan::FilterTokenList nfilterTokenList;
215 SimpleFilter* newsf = new SimpleFilter ( new Operator (">"),
216 sc->clone(),
217 newsc->clone());
218 nfilterTokenList.push_back(newsf);
219 newcsep->filterTokenList (nfilterTokenList);
220 CalpontSelectExecutionPlan::FilterTokenList nhavingTokenList;
221 SimpleFilter* newhaving = new SimpleFilter ( new Operator (">"),
222 sc->clone(),
223 newsc->clone());
224 CPPUNIT_ASSERT (*newsf == *newhaving);
225 nhavingTokenList.push_back(newhaving);
226 newcsep->havingTokenList (nhavingTokenList);
227 CPPUNIT_ASSERT (*newcsep != csep);
228 CPPUNIT_ASSERT (*newcsep->filters() == *newcsep->having());
229 ByteStream b;
230 csep.serialize (b);
231 newcsep->unserialize (b);
232 CPPUNIT_ASSERT (csep == *newcsep);
233 CalpontSelectExecutionPlan::SelectList selectList;
234 selectList.push_back(newcsep);
235 csep.subSelects(selectList);
236 cout << "\nCalpont Execution Plan:" << endl;
237 cout << csep;
238 cout << " --- end of test 1 ---" << endl;
239 }
240
selectExecutionPlan_2()241 void selectExecutionPlan_2()
242 {
243 CalpontSelectExecutionPlan cep;
244
245 // select filter
246 CalpontSelectExecutionPlan* subselect = new CalpontSelectExecutionPlan;
247 subselect->location(CalpontSelectExecutionPlan::WHERE);
248 subselect->dependent (false);
249 CPPUNIT_ASSERT (subselect->location() == CalpontSelectExecutionPlan::WHERE);
250 CPPUNIT_ASSERT (subselect->dependent() == false);
251 ByteStream selb;
252 subselect->serialize(selb);
253 CalpontSelectExecutionPlan* subselect1 = new CalpontSelectExecutionPlan;
254 subselect->location(CalpontSelectExecutionPlan::WHERE);
255 subselect1->unserialize(selb);
256
257 SelectFilter* sef = new SelectFilter ( new SimpleColumn ("tpch.region.r_regionkey", 0),
258 new Operator (">="),
259 subselect);
260 cout << *sef;
261 ByteStream b;
262 sef->serialize(b);
263 SelectFilter* newsef = new SelectFilter ( new SimpleColumn ("tpch.nation.n_regionke", 0),
264 new Operator ("<="),
265 subselect1);
266 newsef->unserialize(b);
267 CPPUNIT_ASSERT(*sef == *newsef);
268 delete sef;
269 delete newsef;
270
271 // simple filter
272 Filter* sf = new SimpleFilter(new Operator("="),
273 new SimpleColumn ("tpch.nation.n_regionke", 0),
274 new SimpleColumn ("tpch.region.r_regionkey", 0));
275 cout << *sf;
276
277 ByteStream sfb;
278 SimpleFilter* sf2 = new SimpleFilter();
279 sf2->serialize (sfb);
280 sf->unserialize (sfb);
281 CPPUNIT_ASSERT (*sf == *sf2);
282 delete sf2;
283 delete sf;
284
285 // exist filter
286 CalpontSelectExecutionPlan* cep1 = new CalpontSelectExecutionPlan();
287 ExistsFilter* filter = new ExistsFilter();
288 delete filter;
289 filter = new ExistsFilter(cep1);
290 filter->exists(cep1);
291 const CalpontSelectExecutionPlan* cep2 = filter->exists();
292 cout << *filter;
293 CPPUNIT_ASSERT (*cep1 == *cep2);
294 CalpontSelectExecutionPlan::Parser parser;
295 std::vector<Token> tokens;
296 Token t;
297 t.value = filter;
298 tokens.push_back(t);
299 cep.filters(parser.parse(tokens.begin(), tokens.end()));
300 cout << cep;
301
302 cout << " --- end of test 2 ---" << endl;
303 }
304
305
expressionParser_1()306 void expressionParser_1()
307 {
308 cout << "\nPost order of int expression tree(pointer):" << endl;
309 ExpressionTree<int>* et = new ExpressionTree<int>(3);
310 ExpressionTree<int>* et1 = new ExpressionTree<int>(5);
311 ExpressionTree<int>* et2 = new ExpressionTree<int>(6);
312 et->left(et1);
313 et->right(et2);
314 et->walk(walkfnInt);
315 et->destroyTree(et);
316 cout << " --- end of test 3 ---" << endl;
317 }
318
expressionParser_2()319 void expressionParser_2()
320 {
321 cout << "\nPost order of int expression tree (reference):" << endl;
322 ExpressionTree<int> et(3);
323 ExpressionTree<int> et1(5);
324 ExpressionTree<int> et2(6);
325 et.left(&et1);
326 et.right(&et2);
327 et.walk(walkfnInt);
328 cout << " --- end of test 4 ---" << endl;
329 }
330
aggregatecolumn_1()331 void aggregatecolumn_1()
332 {
333 cout << "\naggregate column: " << endl;
334 AggregateColumn a;
335 cout << a;
336 cout << "\nsum(p_type)" << endl;
337 AggregateColumn d("sum", "p_type");
338 cout << d;
339 a.functionName("avg");
340 ArithmeticColumn* b = new ArithmeticColumn("a-(b-c)");
341 a.functionParms(b);
342 CPPUNIT_ASSERT(a.functionName() == "avg");
343 cout << *const_cast<ReturnedColumn*>(a.functionParms());
344 cout << " --- end of test 5 ---" << endl;
345 }
346
arithmeticExpression_1()347 void arithmeticExpression_1()
348 {
349 cout << "\narithmetic expression: " << endl;
350 string exp("substr(a)+ 100.00 * sum(tpch.part.p_type) / sum(tpch.lineitem.l_extendedprice *(1-tpch.lineitem.l_discount))");
351 cout << exp << endl;
352 ArithmeticColumn a(exp, 0);
353 ParseTree* pt = const_cast<ParseTree*>(a.expression());
354
355 if (pt != NULL)
356 {
357 pt->walk(walkfnString);
358 pt->drawTree("arithmeticExpression_1.dot");
359 }
360
361 cout << " --- end of test 6 ---" << endl;
362 }
363
copyTree()364 void copyTree()
365 {
366 //cout << "\narithmetic expression: " << endl;
367 string exp("substr(a)+ 100.00 * sum(tpch.part.p_type) / sum(tpch.lineitem.l_extendedprice *(1-tpch.lineitem.l_discount))");
368 ArithmeticColumn a(exp);
369 ParseTree* pt = const_cast<ParseTree*>(a.expression());
370
371 ParseTree* newTree = new ParseTree();
372
373 // copy 1st time
374 newTree->copyTree(*pt);
375
376 // copy 2nd time, see if the existing tree is deleted.
377 newTree->copyTree (*pt);
378
379 // explicitly delete the 2nd copied tree
380 delete newTree;
381 }
382
arithmeticExpression_2()383 void arithmeticExpression_2()
384 {
385 cout << "\nbuild arithmetic column by using accessing methods:" << endl;
386 CalpontSelectExecutionPlan::Parser parser;
387 std::vector<Token> tokens;
388 Token t;
389
390 ArithmeticColumn b;
391 cout << b;
392
393 ConstantColumn* c1 = new ConstantColumn();
394 c1->constval("'ASIA'");
395 c1->type(ConstantColumn::LITERAL);
396 //CPPUNIT_ASSERT (c1->data() == "'ASIA'(l)");
397
398 t.value = c1;
399 tokens.push_back(t);
400
401 t.value = new Operator ("/");
402 tokens.push_back(t);
403
404 ConstantColumn* c2 = new ConstantColumn(5);
405 CPPUNIT_ASSERT (c2->type() == ConstantColumn::NUM);
406 t.value = c2;
407 tokens.push_back(t);
408
409 ParseTree* tree = parser.parse(tokens.begin(), tokens.end());
410 b.expression (tree);
411
412 cout << b;
413 cout << " --- end of test 7 ---" << endl;
414 }
415
arithmeticExpression_3()416 void arithmeticExpression_3()
417 {
418 // invalid expression test
419 try
420 {
421 ArithmeticColumn a ("-a+b", 0);
422 ArithmeticColumn d("a* b-", 0);
423 }
424 catch (const runtime_error& e)
425 {
426 cerr << e.what() << endl;
427 }
428
429 try
430 {
431 ArithmeticColumn e("a+substr (c from 1 4", 0);
432 }
433 catch (const runtime_error& e)
434 {
435 cerr << e.what() << endl;
436 }
437
438 try
439 {
440 ArithmeticColumn f("a + b c", 0);
441 }
442 catch (const runtime_error& e)
443 {
444 cerr << e.what() << endl;
445 }
446
447 try
448 {
449 ArithmeticColumn b("a + ((b+ c -e)", 0);
450 }
451 catch (const runtime_error& e)
452 {
453 cerr << e.what() << endl;
454 }
455
456 try
457 {
458 ArithmeticColumn g("a ++ b", 0); // valid
459 }
460 catch (const runtime_error& e)
461 {
462 cerr << e.what() << endl;
463 }
464 }
465
treeNodeImpl()466 void treeNodeImpl ()
467 {
468 TreeNodeImpl* node1 = new TreeNodeImpl();
469 TreeNodeImpl* node2 = new TreeNodeImpl( "node2" );
470 CPPUNIT_ASSERT (node2->data() == "node2");
471 CPPUNIT_ASSERT (*node1 != *node2);
472
473 ByteStream b;
474 node2->serialize (b);
475 node1->unserialize (b);
476 CPPUNIT_ASSERT (*node1 == *node2);
477
478 node2->data ("node3");
479 cout << *node2;
480
481 TreeNodeImpl* node4 = node2->clone();
482 CPPUNIT_ASSERT (*node2 == node4);
483
484 delete node1;
485 delete node2;
486 delete node4;
487 }
488
serializeSimpleColumn()489 void serializeSimpleColumn()
490 {
491 SimpleColumn s1, s2;
492 TreeNode* t;
493 ByteStream b;
494
495 t = &s2;
496
497 CPPUNIT_ASSERT(s1 == s2);
498 CPPUNIT_ASSERT(!(s1 != s2));
499 CPPUNIT_ASSERT(s1 == t);
500 CPPUNIT_ASSERT(!(s1 != t));
501
502 s1.schemaName("Schema Name 1");
503 s1.tableName("Table Name 1");
504 s1.columnName("Column Name 1");
505 //s1.tcn(5);
506 s1.data("sc1");
507
508 s1.serialize(b);
509
510 CPPUNIT_ASSERT(s2.schemaName() == "");
511 CPPUNIT_ASSERT(s2.tableName() == "");
512 CPPUNIT_ASSERT(s2.columnName() == "");
513 //CPPUNIT_ASSERT(s2.tcn() == 0);
514
515 CPPUNIT_ASSERT(s1 != s2);
516 CPPUNIT_ASSERT(s1 == s1);
517 CPPUNIT_ASSERT(s1 != t);
518 CPPUNIT_ASSERT(!(s1 == t));
519
520 s2.unserialize(b);
521 CPPUNIT_ASSERT(b.length() == 0);
522
523 CPPUNIT_ASSERT(s2.schemaName() == "Schema Name 1");
524 CPPUNIT_ASSERT(s2.tableName() == "Table Name 1");
525 CPPUNIT_ASSERT(s2.columnName() == "Column Name 1");
526 //CPPUNIT_ASSERT(s2.tcn() == 5);
527 CPPUNIT_ASSERT(s2.data() == "sc1");
528
529 CPPUNIT_ASSERT(s1 == s2);
530 CPPUNIT_ASSERT(!(s1 != s2));
531 CPPUNIT_ASSERT(s1 == t);
532 CPPUNIT_ASSERT(!(s1 != t));
533 }
534
serializeAggregateColumn()535 void serializeAggregateColumn()
536 {
537 AggregateColumn a1, a2;
538 SimpleColumn* s1;
539 TreeNode* t;
540 ByteStream b;
541
542 t = &a2;
543
544 s1 = new SimpleColumn();
545
546 CPPUNIT_ASSERT(a1 == a2);
547 CPPUNIT_ASSERT(!(a1 != a2));
548 CPPUNIT_ASSERT(a1 == t);
549 CPPUNIT_ASSERT(!(a1 != t));
550
551 a1.functionName("AggregateColumn test");
552 a1.data("agg1");
553 a1.functionParms(s1);
554
555 a1.serialize(b);
556
557 CPPUNIT_ASSERT(a2.functionName() == "");
558 CPPUNIT_ASSERT(a2.data() == "");
559 CPPUNIT_ASSERT(a2.functionParms() == NULL);
560
561 CPPUNIT_ASSERT(a1 != a2);
562 CPPUNIT_ASSERT(!(a1 == a2));
563 CPPUNIT_ASSERT(a1 != t);
564 CPPUNIT_ASSERT(!(a1 == t));
565
566 a2.unserialize(b);
567 CPPUNIT_ASSERT(b.length() == 0);
568
569 CPPUNIT_ASSERT(a2.functionName() == "AggregateColumn test");
570 CPPUNIT_ASSERT(a2.data() == "agg1");
571 CPPUNIT_ASSERT(a2.functionParms() != NULL);
572 CPPUNIT_ASSERT(*(a2.functionParms()) == s1);
573
574 CPPUNIT_ASSERT(a1 == a2);
575 CPPUNIT_ASSERT(!(a1 != a2));
576 CPPUNIT_ASSERT(a1 == t);
577 CPPUNIT_ASSERT(!(a1 != t));
578 }
579
serializeOperator()580 void serializeOperator()
581 {
582 Operator o1, o2;
583 TreeNode* t;
584 ByteStream b;
585
586 t = &o2;
587
588 CPPUNIT_ASSERT(o1 == o2);
589 CPPUNIT_ASSERT(!(o1 != o2));
590 CPPUNIT_ASSERT(o1 == t);
591 CPPUNIT_ASSERT(!(o1 != t));
592
593 o1.data("=");
594
595 CPPUNIT_ASSERT(o1 != o2);
596 CPPUNIT_ASSERT(!(o1 == o2));
597 CPPUNIT_ASSERT(o1 != t);
598 CPPUNIT_ASSERT(!(o1 == t));
599
600 o1.serialize(b);
601
602 CPPUNIT_ASSERT(o2.data() == "");
603 o2.unserialize(b);
604 CPPUNIT_ASSERT(b.length() == 0);
605 CPPUNIT_ASSERT(o2.data() == "=");
606
607 CPPUNIT_ASSERT(o1 == o2);
608 CPPUNIT_ASSERT(!(o1 != o2));
609 CPPUNIT_ASSERT(o1 == t);
610 CPPUNIT_ASSERT(!(o1 != t));
611 }
612
serializeFilter()613 void serializeFilter()
614 {
615 Filter f1, f2;
616 TreeNode* t;
617 ByteStream b;
618
619 t = &f2;
620
621 CPPUNIT_ASSERT(f1 == f2);
622 CPPUNIT_ASSERT(!(f1 != f2));
623 CPPUNIT_ASSERT(f1 == t);
624 CPPUNIT_ASSERT(!(f1 != t));
625
626 f1.data("Filter test");
627
628 CPPUNIT_ASSERT(f1 != f2);
629 CPPUNIT_ASSERT(!(f1 == f2));
630 CPPUNIT_ASSERT(f1 != t);
631 CPPUNIT_ASSERT(!(f1 == t));
632
633 f1.serialize(b);
634
635 CPPUNIT_ASSERT(f2.data() == "");
636 f2.unserialize(b);
637 CPPUNIT_ASSERT(b.length() == 0);
638 CPPUNIT_ASSERT(f2.data() == "Filter test");
639
640 CPPUNIT_ASSERT(f1 == f2);
641 CPPUNIT_ASSERT(!(f1 != f2));
642 CPPUNIT_ASSERT(f1 == t);
643 CPPUNIT_ASSERT(!(f1 != t));
644 }
645
serializeFunctionColumn()646 void serializeFunctionColumn()
647 {
648 FunctionColumn fc1, fc2;
649 TreeNode* t;
650 ByteStream b;
651
652 t = &fc2;
653
654 CPPUNIT_ASSERT(fc1 == fc2);
655 CPPUNIT_ASSERT(!(fc1 != fc2));
656 CPPUNIT_ASSERT(fc1 == t);
657 CPPUNIT_ASSERT(!(fc1 != t));
658
659 /* FunctionColumn */
660 fc1.sessionID(0);
661 fc1.functionName("FunctionColumn test");
662 fc1.functionParms("tpch.region.r_regionkey, tpch.nation.n_nationkey");
663 fc1.data("fc1");
664
665 CPPUNIT_ASSERT(fc1 != fc2);
666 CPPUNIT_ASSERT(!(fc1 == fc2));
667 CPPUNIT_ASSERT(fc1 != t);
668 CPPUNIT_ASSERT(!(fc1 == t));
669
670 FunctionColumn::FunctionParm functionParms;
671 functionParms = fc1.functionParms();
672 CPPUNIT_ASSERT(functionParms.size() == 2);
673
674 fc1.serialize(b);
675
676 CPPUNIT_ASSERT(fc2.functionName() == "");
677 CPPUNIT_ASSERT(fc2.functionParms().size() == 0);
678
679 fc2.unserialize(b);
680 CPPUNIT_ASSERT(b.length() == 0);
681 CPPUNIT_ASSERT(fc2.functionName() == "FunctionColumn test");
682 CPPUNIT_ASSERT(fc2.functionParms().size() == 2);
683 functionParms = fc2.functionParms();
684 CPPUNIT_ASSERT(functionParms.size() == 2);
685
686 CPPUNIT_ASSERT(fc1 == fc2);
687 CPPUNIT_ASSERT(!(fc1 != fc2));
688 CPPUNIT_ASSERT(fc1 == t);
689 CPPUNIT_ASSERT(!(fc1 != t));
690 }
691
serializeConstantColumn()692 void serializeConstantColumn()
693 {
694 ConstantColumn c1, c2;
695 TreeNode* t;
696 ByteStream b;
697
698 t = &c2;
699
700 CPPUNIT_ASSERT(c1 == c2);
701 CPPUNIT_ASSERT(!(c1 != c2));
702 CPPUNIT_ASSERT(c1 == t);
703 CPPUNIT_ASSERT(!(c1 != t));
704
705 c1.type(5);
706 c1.constval("ConstantColumn test");
707 c1.data("c1");
708
709 CPPUNIT_ASSERT(c1 != c2);
710 CPPUNIT_ASSERT(!(c1 == c2));
711 CPPUNIT_ASSERT(c1 != t);
712 CPPUNIT_ASSERT(!(c1 == t));
713
714 c1.serialize(b);
715 CPPUNIT_ASSERT(c2.constval() == "");
716 c2.unserialize(b);
717 CPPUNIT_ASSERT(b.length() == 0);
718 CPPUNIT_ASSERT(c2.type() == 5);
719 CPPUNIT_ASSERT(c2.constval() == "ConstantColumn test");
720
721 CPPUNIT_ASSERT(c1 == c2);
722 CPPUNIT_ASSERT(!(c1 != c2));
723 CPPUNIT_ASSERT(c1 == t);
724 CPPUNIT_ASSERT(!(c1 != t));
725 }
726
makeParseTree()727 ParseTree* makeParseTree()
728 {
729 ParseTree* t[5];
730 SimpleColumn* s[5];
731 int i;
732
733 /* ParseTree (ExpressionTree<TreeNode*>) */
734
735 /*
736 t0(s0)
737 / \
738 s1 s2
739 / \
740 s3 s4
741 */
742
743 for (i = 0; i < 5; i++)
744 {
745 t[i] = new ParseTree(NULL);
746 s[i] = new SimpleColumn();
747 t[i]->data(s[i]);
748 }
749
750 s[0]->schemaName("Schema Name 0");
751 s[1]->schemaName("Schema Name 1");
752 s[2]->schemaName("Schema Name 2");
753 s[3]->schemaName("Schema Name 3");
754 s[4]->schemaName("Schema Name 4");
755
756 t[0]->left(t[1]);
757 t[0]->right(t[2]);
758 t[1]->left(t[3]);
759 t[2]->right(t[4]);
760
761 return t[0];
762 }
763
verifyParseTree(const ParseTree * t)764 void verifyParseTree(const ParseTree* t)
765 {
766 const ParseTree* ct, *ct2;
767 SimpleColumn* s;
768
769 CPPUNIT_ASSERT(t != NULL);
770 s = dynamic_cast<SimpleColumn*>(t->data());
771 CPPUNIT_ASSERT(s != NULL);
772 CPPUNIT_ASSERT(s->schemaName() == "Schema Name 0");
773 ct = t->left();
774 CPPUNIT_ASSERT(ct != NULL);
775 s = dynamic_cast<SimpleColumn*>(ct->data());
776 CPPUNIT_ASSERT(s != NULL);
777 CPPUNIT_ASSERT(s->schemaName() == "Schema Name 1");
778 ct2 = ct->left();
779 CPPUNIT_ASSERT(ct2 != NULL);
780 s = dynamic_cast<SimpleColumn*>(ct2->data());
781 CPPUNIT_ASSERT(s != NULL);
782 CPPUNIT_ASSERT(s->schemaName() == "Schema Name 3");
783 CPPUNIT_ASSERT(ct->right() == NULL);
784 CPPUNIT_ASSERT(ct2->left() == NULL);
785 CPPUNIT_ASSERT(ct2->right() == NULL);
786 ct = t->right();
787 CPPUNIT_ASSERT(ct != NULL);
788 s = dynamic_cast<SimpleColumn*>(ct->data());
789 CPPUNIT_ASSERT(s != NULL);
790 CPPUNIT_ASSERT(s->schemaName() == "Schema Name 2");
791 ct2 = ct->right();
792 CPPUNIT_ASSERT(ct2 != NULL);
793 s = dynamic_cast<SimpleColumn*>(ct2->data());
794 CPPUNIT_ASSERT(s != NULL);
795 CPPUNIT_ASSERT(s->schemaName() == "Schema Name 4");
796 CPPUNIT_ASSERT(ct->left() == NULL);
797 CPPUNIT_ASSERT(ct2->left() == NULL);
798 CPPUNIT_ASSERT(ct2->right() == NULL);
799 }
800
serializeParseTree()801 void serializeParseTree()
802 {
803 ByteStream b;
804 ParseTree* t, *tmodel;
805
806 t = makeParseTree();
807 tmodel = makeParseTree();
808 verifyParseTree(t); //sanity check on the test itself
809
810 CPPUNIT_ASSERT(*t == *tmodel);
811 CPPUNIT_ASSERT(!(*t != *tmodel));
812
813 ObjectReader::writeParseTree(t, b);
814
815 delete t;
816
817 t = ObjectReader::createParseTree(b);
818 CPPUNIT_ASSERT(b.length() == 0);
819 CPPUNIT_ASSERT(t != NULL);
820 verifyParseTree(t);
821
822 CPPUNIT_ASSERT(*t == *tmodel);
823 CPPUNIT_ASSERT(!(*t != *tmodel));
824
825 delete t;
826 delete tmodel;
827 }
828
makeArithmeticColumn()829 ArithmeticColumn* makeArithmeticColumn()
830 {
831 ArithmeticColumn* ret;
832 ParseTree* t;
833
834 t = makeParseTree();
835 ret = new ArithmeticColumn();
836 ret->expression(t);
837 ret->alias("ArithmeticColumn");
838 ret->data("AD");
839 return ret;
840 }
841
serializeArithmeticColumn()842 void serializeArithmeticColumn()
843 {
844 ParseTree* t;
845 const ParseTree* ct;
846 ArithmeticColumn ac, ac2;
847 TreeNode* tn;
848 ByteStream b;
849
850 tn = &ac2;
851
852 CPPUNIT_ASSERT(ac == ac2);
853 CPPUNIT_ASSERT(!(ac != ac2));
854 CPPUNIT_ASSERT(ac == tn);
855 CPPUNIT_ASSERT(!(ac != tn));
856
857 t = makeParseTree();
858
859 ac.expression(t);
860 ac.alias("ArithmeticColumn");
861 ac.data("AD");
862
863 CPPUNIT_ASSERT(ac != ac2);
864 CPPUNIT_ASSERT(!(ac == ac2));
865 CPPUNIT_ASSERT(ac != tn);
866 CPPUNIT_ASSERT(!(ac == tn));
867
868 ac.serialize(b);
869 ac2.unserialize(b);
870 CPPUNIT_ASSERT(b.length() == 0);
871 ct = ac2.expression();
872 verifyParseTree(ct);
873 CPPUNIT_ASSERT(ac2.alias() == "ArithmeticColumn");
874 CPPUNIT_ASSERT(ac2.data() == "AD");
875
876 CPPUNIT_ASSERT(ac == ac2);
877 CPPUNIT_ASSERT(!(ac != ac2));
878 CPPUNIT_ASSERT(ac == tn);
879 CPPUNIT_ASSERT(!(ac != tn));
880 }
881
serializeSimpleFilter()882 void serializeSimpleFilter()
883 {
884 ArithmeticColumn* pac1, *pac2;
885 const ArithmeticColumn* cpac1, *cpac2;
886 SimpleFilter sf1, sf2;
887 Operator* o1;
888 const Operator* co2;
889 TreeNode* t;
890 ByteStream b;
891
892 t = &sf2;
893
894 CPPUNIT_ASSERT(sf1 == sf2);
895 CPPUNIT_ASSERT(!(sf1 != sf2));
896 CPPUNIT_ASSERT(sf1 == t);
897 CPPUNIT_ASSERT(!(sf1 != t));
898
899 pac1 = makeArithmeticColumn();
900 pac2 = makeArithmeticColumn();
901
902 CPPUNIT_ASSERT(b.length() == 0);
903 CPPUNIT_ASSERT(pac1 != NULL);
904 CPPUNIT_ASSERT(pac2 != NULL);
905
906 o1 = new Operator("=");
907 sf1.lhs(pac1);
908 sf1.rhs(pac2);
909 sf1.op(o1);
910
911 sf1.serialize(b);
912
913 CPPUNIT_ASSERT(sf1 != sf2);
914 CPPUNIT_ASSERT(!(sf1 == sf2));
915 CPPUNIT_ASSERT(sf1 != t);
916 CPPUNIT_ASSERT(!(sf1 == t));
917
918 sf2.unserialize(b);
919 CPPUNIT_ASSERT(b.length() == 0);
920
921 cpac1 = dynamic_cast<const ArithmeticColumn*>(sf2.lhs());
922 CPPUNIT_ASSERT(cpac1 != NULL);
923 verifyParseTree(cpac1->expression());
924 cpac2 = dynamic_cast<const ArithmeticColumn*>(sf2.rhs());
925 CPPUNIT_ASSERT(cpac2 != NULL);
926 verifyParseTree(cpac2->expression());
927 co2 = sf2.op();
928 CPPUNIT_ASSERT(co2 != NULL);
929 CPPUNIT_ASSERT(co2->data() == o1->data());
930
931 CPPUNIT_ASSERT(sf1 == sf2);
932 CPPUNIT_ASSERT(!(sf1 != sf2));
933 CPPUNIT_ASSERT(sf1 == t);
934 CPPUNIT_ASSERT(!(sf1 != t));
935
936 }
937
serializeCSEP()938 void serializeCSEP()
939 {
940 /*
941 * CalpontSelectExecutionPlan
942 * This is a large class; it makes more sense to write == operators
943 * for everything than to write a giant equivalance test here.
944 * For now this is mostly a regression test.
945 */
946
947 CalpontSelectExecutionPlan csep1, csep2;
948 CalpontSelectExecutionPlan::ReturnedColumnList colList;
949 ParseTree* filterList;
950 CalpontExecutionPlan* cep;
951 ByteStream b;
952
953 cep = &csep2;
954
955 CPPUNIT_ASSERT(csep1 == csep2);
956 CPPUNIT_ASSERT(!(csep1 != csep2));
957 CPPUNIT_ASSERT(csep1 == cep);
958 CPPUNIT_ASSERT(!(csep1 != cep));
959
960 // returned columns
961 SimpleColumn* sc = new SimpleColumn("tpch.region.r_regionkey");
962 colList.push_back(sc);
963
964 // filters
965 CalpontSelectExecutionPlan::Parser parser;
966 std::vector<Token> tokens;
967 Token t;
968
969 SimpleFilter* sf = new SimpleFilter();
970 SimpleColumn* lhs = new SimpleColumn(*sc);
971 SimpleColumn* rhs = new SimpleColumn("tpch.nation.n_regionkey");
972 Operator* op = new Operator("=");
973
974 sf->op(op);
975 sf->lhs(lhs);
976 sf->rhs(rhs);
977
978 t.value = sf;
979 tokens.push_back(t);
980
981 Operator* op1 = new Operator ("and");
982 t.value = op1;
983 tokens.push_back(t);
984
985 SimpleFilter* sf1 = new SimpleFilter();
986 SimpleColumn* lhs1 = new SimpleColumn (*rhs);
987 ConstantColumn* constCol = new ConstantColumn("3", ConstantColumn::NUM);
988 Operator* op2 = new Operator("!=");
989
990 sf1->op(op2);
991 sf1->lhs(lhs1);
992 sf1->rhs(constCol);
993
994 t.value = sf1;
995 tokens.push_back(t);
996
997 filterList = parser.parse(tokens.begin(), tokens.end());
998
999 // draw filterList tree
1000 filterList->drawTree("selectExecutionPlan_1.dot");
1001
1002 // calpont execution plan
1003 csep1.returnedCols (colList);
1004 csep1.filters (filterList);
1005
1006 CPPUNIT_ASSERT(csep1 != csep2);
1007 CPPUNIT_ASSERT(!(csep1 == csep2));
1008 CPPUNIT_ASSERT(csep1 != cep);
1009 CPPUNIT_ASSERT(!(csep1 == cep));
1010
1011 csep1.serialize(b);
1012 csep2.unserialize(b);
1013 CPPUNIT_ASSERT(b.length() == 0);
1014
1015 CPPUNIT_ASSERT(csep1 == csep2);
1016 CPPUNIT_ASSERT(!(csep1 != csep2));
1017 CPPUNIT_ASSERT(csep1 == cep);
1018 CPPUNIT_ASSERT(!(csep1 != cep));
1019
1020 CalpontSelectExecutionPlan csep3, csep4;
1021
1022 // subselect
1023 CalpontSelectExecutionPlan* subselect = new CalpontSelectExecutionPlan;
1024 subselect->location(CalpontSelectExecutionPlan::WHERE);
1025 subselect->dependent (false);
1026 CPPUNIT_ASSERT (subselect->location() == CalpontSelectExecutionPlan::WHERE);
1027 CPPUNIT_ASSERT (subselect->dependent() == false);
1028 CalpontSelectExecutionPlan::SelectList selectList;
1029 selectList.push_back(subselect);
1030 csep3.subSelects(selectList);
1031
1032 // exist filter
1033 CalpontSelectExecutionPlan* cep1 = new CalpontSelectExecutionPlan();
1034 ExistsFilter* filter = new ExistsFilter();
1035 delete filter;
1036 filter = new ExistsFilter(cep1);
1037 filter->exists(cep1);
1038 //CalpontSelectExecutionPlan* cep2 = const_cast<CalpontSelectExecutionPlan*>(filter->exists());
1039
1040 CalpontSelectExecutionPlan::Parser parser1;
1041 std::vector<Token> tokens1;
1042 Token t1;
1043 t1.value = filter;
1044 tokens1.push_back(t1);
1045 csep3.filters(parser1.parse(tokens1.begin(), tokens1.end()));
1046
1047 csep3.serialize(b);
1048 csep4.unserialize(b);
1049
1050 CPPUNIT_ASSERT(csep3 == csep4);
1051 CPPUNIT_ASSERT(!(csep3 != csep4));
1052
1053
1054 }
1055
serializeSelectFilter()1056 void serializeSelectFilter()
1057 {
1058 ByteStream b;
1059 ArithmeticColumn* pac1;
1060 Operator* o1;
1061 const Operator* co2;
1062 CalpontSelectExecutionPlan csep1;
1063 SelectFilter sel1, sel2;
1064 const ArithmeticColumn* cpac1;
1065 const ParseTree* ct;
1066 TreeNode* t;
1067
1068 t = &sel2;
1069
1070 CPPUNIT_ASSERT(sel1 == sel2);
1071 CPPUNIT_ASSERT(!(sel1 != sel2));
1072 CPPUNIT_ASSERT(sel1 == t);
1073 CPPUNIT_ASSERT(!(sel1 != t));
1074
1075 pac1 = makeArithmeticColumn();
1076 o1 = new Operator("=");
1077 sel1.lhs(pac1);
1078 sel1.op(o1);
1079
1080 CPPUNIT_ASSERT(sel1 != sel2);
1081 CPPUNIT_ASSERT(!(sel1 == sel2));
1082 CPPUNIT_ASSERT(sel1 != t);
1083 CPPUNIT_ASSERT(!(sel1 == t));
1084
1085 sel1.serialize(b);
1086 sel2.unserialize(b);
1087 CPPUNIT_ASSERT(b.length() == 0);
1088
1089 CPPUNIT_ASSERT(sel1 == sel2);
1090 CPPUNIT_ASSERT(!(sel1 != sel2));
1091 CPPUNIT_ASSERT(sel1 == t);
1092 CPPUNIT_ASSERT(!(sel1 != t));
1093
1094 cpac1 = dynamic_cast<const ArithmeticColumn*>(sel2.lhs());
1095 CPPUNIT_ASSERT(cpac1 != NULL);
1096 ct = cpac1->expression();
1097 verifyParseTree(ct);
1098 co2 = sel2.op();
1099 CPPUNIT_ASSERT(co2 != NULL);
1100 CPPUNIT_ASSERT(co2->data() == o1->data());
1101 }
1102
1103 /* ExistFilters get tested as part of the CSEP test at the moment. */
serializeExistsFilter()1104 void serializeExistsFilter()
1105 {
1106 ExistsFilter ef1, ef2;
1107 ByteStream b;
1108
1109 ef2.data("ExistsFilter test");
1110 ef1.serialize(b);
1111 ef2.unserialize(b);
1112 CPPUNIT_ASSERT(b.length() == 0);
1113 CPPUNIT_ASSERT(ef2.data() == "");
1114 }
1115
objectIDManager_1()1116 void objectIDManager_1()
1117 {
1118 int oid, oidBase;
1119
1120 // fake out the objmgr...
1121 setenv("CALPONT_CONFIG_FILE", "/usr/local/mariadb/columnstore/etc/Columnstore.xml", 1);
1122 Config* cf = Config::makeConfig();
1123 cf->setConfig("OIDManager", "OIDBitmapFile", "./oidbitmap");
1124
1125 try
1126 {
1127 ObjectIDManager o;
1128
1129 OIDBitmapFilename = strdup(o.getFilename().c_str());
1130 oidBase = o.allocOID();
1131 oid = o.allocOID();
1132 CPPUNIT_ASSERT(oid == oidBase + 1);
1133 oid = o.allocOIDs(20);
1134 CPPUNIT_ASSERT(oid == oidBase + 2);
1135 oid = o.allocOIDs(20);
1136 CPPUNIT_ASSERT(oid == oidBase + 22);
1137 o.returnOID(oidBase + 5);
1138 oid = o.allocOID();
1139 CPPUNIT_ASSERT(oid == oidBase + 5);
1140 o.returnOID(oidBase + 5);
1141 oid = o.allocOIDs(20);
1142 CPPUNIT_ASSERT(oid == oidBase + 42);
1143 oid = o.allocOID();
1144 CPPUNIT_ASSERT(oid == oidBase + 5);
1145 o.returnOIDs(oidBase, oidBase + 61);
1146 oid = o.allocOID();
1147 CPPUNIT_ASSERT(oid == oidBase);
1148 o.returnOID(0);
1149 }
1150 catch (...)
1151 {
1152 if (OIDBitmapFilename != NULL)
1153 unlink(OIDBitmapFilename); // XXXPAT: fix this when libstdc++ regains its sanity
1154
1155 throw;
1156 }
1157
1158 unlink(OIDBitmapFilename);
1159 }
1160
1161 /*
1162 * destroySemaphores() and destroyShmseg() will print error messages
1163 * if there are no objects to destroy. That's OK.
1164 */
destroySemaphores()1165 void destroySemaphores()
1166 {
1167 key_t semkey;
1168 int sems, err;
1169
1170 semkey = SESSIONMANAGER_SYSVKEY;
1171 sems = semget(semkey, 2, 0666);
1172
1173 if (sems != -1)
1174 {
1175 err = semctl(sems, 0, IPC_RMID);
1176
1177 if (err == -1)
1178 perror("tdriver: semctl");
1179 }
1180 }
1181
destroyShmseg()1182 void destroyShmseg()
1183 {
1184 key_t shmkey;
1185 int shms, err;
1186
1187 shmkey = SESSIONMANAGER_SYSVKEY;
1188 shms = shmget(shmkey, 0, 0666);
1189
1190 if (shms != -1)
1191 {
1192 err = shmctl(shms, IPC_RMID, NULL);
1193
1194 if (err == -1 && errno != EINVAL)
1195 {
1196 perror("tdriver: shmctl");
1197 return;
1198 }
1199 }
1200 }
1201
sessionManager_1()1202 void sessionManager_1()
1203 {
1204 SessionManager* sm = NULL;
1205 SessionManager::TxnID txn;
1206 const SessionManager::SIDTIDEntry* activeTxns;
1207 int len;
1208 string filename;
1209
1210 // destroySemaphores();
1211 // destroyShmseg();
1212
1213 try
1214 {
1215 sm = new SessionManager();
1216 //CPPUNIT_ASSERT(sm->verID() == 0);
1217 filename = sm->getTxnIDFilename();
1218 delete sm;
1219 sm = new SessionManager();
1220 txn = sm->newTxnID(0);
1221 CPPUNIT_ASSERT(txn.valid == true);
1222 // CPPUNIT_ASSERT(txn.id == 1);
1223 // CPPUNIT_ASSERT(sm->verID() == 1);
1224 txn = sm->newTxnID(1);
1225 CPPUNIT_ASSERT(txn.valid == true);
1226 // CPPUNIT_ASSERT(txn.id == 2);
1227 // CPPUNIT_ASSERT(sm->verID() == 2);
1228 activeTxns = sm->SIDTIDMap(len);
1229 CPPUNIT_ASSERT(activeTxns != NULL);
1230 CPPUNIT_ASSERT(len == 2);
1231 txn = sm->getTxnID(0);
1232 CPPUNIT_ASSERT(txn.valid == true);
1233 // CPPUNIT_ASSERT(txn.id == 1);
1234 CPPUNIT_ASSERT(txn.valid == activeTxns[0].txnid.valid);
1235 // CPPUNIT_ASSERT(txn.id == activeTxns[0].txnid.id);
1236 txn = sm->getTxnID(1);
1237 CPPUNIT_ASSERT(txn.valid == true);
1238 // CPPUNIT_ASSERT(txn.id == 2);
1239 CPPUNIT_ASSERT(txn.valid == activeTxns[1].txnid.valid);
1240 // CPPUNIT_ASSERT(txn.id == activeTxns[1].txnid.id);
1241 delete [] activeTxns;
1242
1243 //make sure it's consistent across invocations
1244 delete sm;
1245 sm = new SessionManager();
1246 activeTxns = sm->SIDTIDMap(len);
1247 CPPUNIT_ASSERT(activeTxns != NULL);
1248 CPPUNIT_ASSERT(len == 2);
1249 txn = sm->getTxnID(0);
1250 CPPUNIT_ASSERT(txn.valid == true);
1251 // CPPUNIT_ASSERT(txn.id == 1);
1252 CPPUNIT_ASSERT(txn.valid == activeTxns[0].txnid.valid);
1253 // CPPUNIT_ASSERT(txn.id == activeTxns[0].txnid.id);
1254 txn = sm->getTxnID(1);
1255 CPPUNIT_ASSERT(txn.valid == true);
1256 // CPPUNIT_ASSERT(txn.id == 2);
1257 CPPUNIT_ASSERT(txn.valid == activeTxns[1].txnid.valid);
1258 // CPPUNIT_ASSERT(txn.id == activeTxns[1].txnid.id);
1259 sm->rolledback(txn);
1260 CPPUNIT_ASSERT(txn.valid == false);
1261 txn = sm->getTxnID(0);
1262 sm->committed(txn);
1263 CPPUNIT_ASSERT(txn.valid == false);
1264 delete [] activeTxns;
1265 activeTxns = sm->SIDTIDMap(len);
1266 CPPUNIT_ASSERT(len == 0);
1267 delete [] activeTxns;
1268 }
1269 catch (runtime_error& e)
1270 {
1271 cout << "caught runtime_error (why doesn't cppunit notice these?): " << e.what() << endl;
1272
1273 if (sm != NULL)
1274 delete sm;
1275
1276 // destroySemaphores();
1277 // destroyShmseg();
1278 throw logic_error("Hey! Stop!");
1279 }
1280 catch (exception& e)
1281 {
1282 cout << "caught exception: " << e.what() << endl;
1283
1284 if (sm != NULL)
1285 delete sm;
1286
1287 // destroySemaphores();
1288 // destroyShmseg();
1289 throw;
1290 }
1291
1292 delete sm;
1293 // destroySemaphores();
1294 // destroyShmseg();
1295 }
1296
1297 /** Verifies that we can only have MaxTxns (1000 right now) active transactions at
1298 any given time */
sessionManager_2()1299 void sessionManager_2()
1300 {
1301 int i;
1302 SessionManager* sm;
1303 SessionManager::TxnID txns[1001];
1304 string filename;
1305
1306 // destroySemaphores();
1307 // destroyShmseg();
1308
1309 sm = new SessionManager();
1310 filename = sm->getTxnIDFilename();
1311 delete sm;
1312 sm = new SessionManager();
1313
1314 for (i = 0; i < 1000; i++)
1315 {
1316 txns[i] = sm->newTxnID(i, false);
1317 CPPUNIT_ASSERT(txns[i].valid == true);
1318 //CPPUNIT_ASSERT(sm->verID() == txns[i].id);
1319 }
1320
1321 txns[1000] = sm->newTxnID(i, false);
1322 CPPUNIT_ASSERT(txns[1000].valid == false);
1323
1324 for (i = 999; i >= 0; i--)
1325 {
1326 SessionManager::TxnID tmp = sm->getTxnID(i);
1327 CPPUNIT_ASSERT(tmp.valid == txns[i].valid == true);
1328 CPPUNIT_ASSERT(tmp.id == txns[i].id);
1329 sm->committed(txns[i]);
1330 tmp = sm->getTxnID(i);
1331 CPPUNIT_ASSERT(tmp.valid == false);
1332 CPPUNIT_ASSERT(txns[i].valid == false);
1333 }
1334
1335 try
1336 {
1337 sm->committed(txns[1000]);
1338 }
1339 // expected exception
1340 catch (invalid_argument& e)
1341 { }
1342
1343 delete sm;
1344 // destroySemaphores();
1345 // destroyShmseg();
1346 }
1347
1348 /** Verifies that transaction IDs get saved and restored correctly across "reboots" */
sessionManager_3()1349 void sessionManager_3()
1350 {
1351
1352 SessionManager* sm;
1353 string filename;
1354 SessionManager::TxnID txnid;
1355
1356 // scrub env
1357 sm = new SessionManager();
1358 filename = sm->getTxnIDFilename();
1359 delete sm;
1360 // destroyShmseg();
1361 // destroySemaphores();
1362
1363 sm = new SessionManager();
1364
1365 txnid = sm->newTxnID(0);
1366 // CPPUNIT_ASSERT(txnid.id == 1);
1367
1368 delete sm;
1369 // destroyShmseg();
1370 // destroySemaphores();
1371
1372 sm = new SessionManager();
1373 sm->committed(txnid);
1374 txnid = sm->newTxnID(1);
1375 // CPPUNIT_ASSERT(txnid.id == 2);
1376
1377 delete sm;
1378 sm = new SessionManager();
1379 sm->committed(txnid);
1380
1381 // destroyShmseg();
1382 // destroySemaphores();
1383
1384 }
1385
sessionManager_4()1386 void sessionManager_4()
1387 {
1388 char* buf;
1389 int len;
1390 SessionManager sm;
1391
1392 buf = sm.getShmContents(len);
1393 CPPUNIT_ASSERT(len > 0);
1394 CPPUNIT_ASSERT(buf != NULL);
1395 delete [] buf;
1396 }
1397
1398
1399 SessionManager* manager;
1400 SessionManager::TxnID managerTxns[1000];
1401
createTxns(const int & start,const int & end)1402 int createTxns(const int& start, const int& end)
1403 {
1404
1405 const int first = start;
1406 const int last = end;
1407 int newTxns = 0;
1408 int verifyLen = 0;
1409
1410 verifyLen = manager->verifySize();
1411
1412 for (int idx = first; idx < last && verifyLen < maxNewTxns; idx++)
1413 {
1414 managerTxns[idx] = manager->newTxnID((uint32_t)idx + 1000);
1415 CPPUNIT_ASSERT(managerTxns[idx].id > 0);
1416 CPPUNIT_ASSERT(managerTxns[idx].valid == true);
1417 verifyLen = manager->verifySize();
1418 newTxns++;
1419 }
1420
1421 CPPUNIT_ASSERT(newTxns == last - first);
1422 return newTxns;
1423 }
1424
closeTxns(const int & start,const int & end)1425 int closeTxns(const int& start, const int& end)
1426 {
1427
1428 int first = start;
1429 int last = end;
1430 int totalClosed = 0;
1431
1432 for (int idx = first; idx < last ; idx++)
1433 {
1434 try
1435 {
1436 SessionManager::TxnID tmp = manager->getTxnID(idx + 1000);
1437
1438 if (tmp.valid == true)
1439 {
1440 manager->committed(tmp);
1441 CPPUNIT_ASSERT(tmp.valid == false);
1442 totalClosed++;
1443 }
1444
1445 }
1446 catch (exception& e)
1447 {
1448 cerr << e.what() << endl;
1449 continue;
1450 }
1451 }
1452
1453 return totalClosed;
1454
1455 } //closeTxns
1456
MonitorTestPlan_1()1457 void MonitorTestPlan_1()
1458 {
1459
1460 int currStartTxn = 0;
1461 int currEndTxn = 5;
1462 int txnCntIncr = 5;
1463 const int sleepTime = 11;
1464 const int iterMax = 1;
1465 vector<SessionMonitor::MonSIDTIDEntry*> toTxns;
1466
1467 destroySemaphores();
1468 destroyShmseg();
1469
1470 manager = new SessionManager();
1471 manager->reset();
1472 CPPUNIT_ASSERT(manager->verifySize() == 0);
1473
1474 SessionMonitor* monitor = NULL;
1475
1476 for (int jdx = 0; jdx < iterMax; jdx++)
1477 {
1478
1479 // store the current state of the SessionManager
1480 monitor = new SessionMonitor();
1481 delete monitor;
1482 int idx = 0;
1483 int grpStart = currStartTxn;
1484
1485 for (idx = 0; idx < 3; idx++ )
1486 {
1487
1488 createTxns(currStartTxn, currEndTxn);
1489 CPPUNIT_ASSERT(manager->verifySize() == (idx + 1)*txnCntIncr);
1490
1491 currStartTxn += txnCntIncr;
1492 currEndTxn += txnCntIncr;
1493 sleep(sleepTime); //make sessions time out
1494
1495 monitor = new SessionMonitor(); // read Monitor data
1496 toTxns.clear();
1497 toTxns = monitor->timedOutTxns(); // get timed out txns
1498 CPPUNIT_ASSERT(toTxns.size() == (uint32_t)txnCntIncr * idx);
1499
1500 delete monitor;
1501 }
1502
1503 int grpEnd = currEndTxn;
1504 monitor = new SessionMonitor();
1505 closeTxns(grpStart, grpEnd); // close this iteration of txns
1506 CPPUNIT_ASSERT(manager->verifySize() == 0);
1507 toTxns = monitor->timedOutTxns(); // get timed out txns
1508 CPPUNIT_ASSERT(toTxns.size() == 0);
1509
1510 delete monitor;
1511
1512 }
1513
1514 monitor = new SessionMonitor(); // readload Monitor data
1515
1516 toTxns.clear();
1517 toTxns = monitor->timedOutTxns(); // get timed out txns
1518 CPPUNIT_ASSERT(toTxns.size() == 0);
1519 delete monitor;
1520
1521 CPPUNIT_ASSERT(manager->verifySize() == 0);
1522
1523 if (manager)
1524 delete manager;
1525
1526 }
1527
1528 };
1529
1530 CPPUNIT_TEST_SUITE_REGISTRATION( ExecPlanTest );
1531
1532 #include <cppunit/extensions/TestFactoryRegistry.h>
1533 #include <cppunit/ui/text/TestRunner.h>
1534
main(int argc,char ** argv)1535 int main( int argc, char** argv)
1536 {
1537 CppUnit::TextUi::TestRunner runner;
1538 CppUnit::TestFactoryRegistry& registry = CppUnit::TestFactoryRegistry::getRegistry();
1539 runner.addTest( registry.makeTest() );
1540 bool wasSuccessful = runner.run( "", false );
1541 return (wasSuccessful ? 0 : 1);
1542 }
1543
1544
1545