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