MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NDBT_Test.cpp
1 /*
2  Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #include <ndb_global.h>
19 #include <ndb_opts.h>
20 
21 #include "NDBT.hpp"
22 #include "NDBT_Test.hpp"
23 
24 NDBT_Context::NDBT_Context(Ndb_cluster_connection& con)
25  : m_cluster_connection(con)
26 {
27  suite = NULL;
28  testcase = NULL;
29  ndb = NULL;
30  records = 1;
31  loops = 1;
32  stopped = false;
33  propertyMutexPtr = NdbMutex_Create();
34  propertyCondPtr = NdbCondition_Create();
35 }
36 
37 
38 NDBT_Context::~NDBT_Context(){
39  NdbCondition_Destroy(propertyCondPtr);
40  NdbMutex_Destroy(propertyMutexPtr);
41 }
42 
43 const NdbDictionary::Table* NDBT_Context::getTab(){
44  assert(tables.size());
45  return tables[0];
46 }
47 
48 NDBT_TestSuite* NDBT_Context::getSuite(){
49  assert(suite != NULL);
50  return suite;
51 }
52 
53 NDBT_TestCase* NDBT_Context::getCase(){
54  assert(testcase != NULL);
55  return testcase;
56 }
57 
58 const char* NDBT_Context::getTableName(int n) const
59 {
60  assert(suite != NULL);
61  return suite->m_tables_in_test[n].c_str();
62 }
63 
64 int NDBT_Context::getNumTables() const
65 {
66  assert(suite != NULL);
67  return suite->m_tables_in_test.size();
68 }
69 
70 int NDBT_Context::getNumRecords() const{
71  return records;
72 }
73 
74 int NDBT_Context::getNumLoops() const{
75  return loops;
76 }
77 
79  return testcase->getNoOfRunningSteps();
80 
81 }
82 int NDBT_Context::getNoOfCompletedSteps() const {
83  return testcase->getNoOfCompletedSteps();
84 }
85 
86 
87 Uint32 NDBT_Context::getProperty(const char* _name, Uint32 _default){
88  Uint32 val;
89  NdbMutex_Lock(propertyMutexPtr);
90  if(!props.get(_name, &val))
91  val = _default;
92  NdbMutex_Unlock(propertyMutexPtr);
93  return val;
94 }
95 
96 bool NDBT_Context::getPropertyWait(const char* _name, Uint32 _waitVal){
97  bool result;
98  NdbMutex_Lock(propertyMutexPtr);
99  Uint32 val =! _waitVal;
100 
101  while((!props.get(_name, &val) || (props.get(_name, &val) && val != _waitVal)) &&
102  !stopped)
103  NdbCondition_Wait(propertyCondPtr,
104  propertyMutexPtr);
105  result = (val == _waitVal);
106  NdbMutex_Unlock(propertyMutexPtr);
107  return stopped;
108 }
109 
110 const char* NDBT_Context::getProperty(const char* _name, const char* _default){
111  const char* val;
112  NdbMutex_Lock(propertyMutexPtr);
113  if(!props.get(_name, &val))
114  val = _default;
115  NdbMutex_Unlock(propertyMutexPtr);
116  return val;
117 }
118 
119 const char* NDBT_Context::getPropertyWait(const char* _name, const char* _waitVal){
120  const char* val;
121  NdbMutex_Lock(propertyMutexPtr);
122  while(!props.get(_name, &val) && (strcmp(val, _waitVal)==0))
123  NdbCondition_Wait(propertyCondPtr,
124  propertyMutexPtr);
125 
126  NdbMutex_Unlock(propertyMutexPtr);
127  return val;
128 }
129 
130 void NDBT_Context::setProperty(const char* _name, Uint32 _val){
131  NdbMutex_Lock(propertyMutexPtr);
132  const bool b = props.put(_name, _val, true);
133  assert(b == true);
134  NdbCondition_Broadcast(propertyCondPtr);
135  NdbMutex_Unlock(propertyMutexPtr);
136 }
137 
138 void
139 NDBT_Context::decProperty(const char * name){
140  NdbMutex_Lock(propertyMutexPtr);
141  Uint32 val = 0;
142  if(props.get(name, &val)){
143  assert(val > 0);
144  props.put(name, (val - 1), true);
145  }
146  NdbCondition_Broadcast(propertyCondPtr);
147  NdbMutex_Unlock(propertyMutexPtr);
148 }
149 
150 void
151 NDBT_Context::incProperty(const char * name){
152  NdbMutex_Lock(propertyMutexPtr);
153  Uint32 val = 0;
154  props.get(name, &val);
155  props.put(name, (val + 1), true);
156  NdbCondition_Broadcast(propertyCondPtr);
157  NdbMutex_Unlock(propertyMutexPtr);
158 }
159 
160 Uint32
161 NDBT_Context::casProperty(const char * name, Uint32 oldValue, Uint32 newValue)
162 {
163  NdbMutex_Lock(propertyMutexPtr);
164  Uint32 val = 0;
165  props.get(name, &val);
166  if (val == oldValue)
167  {
168  props.put(name, newValue, true);
169  NdbCondition_Broadcast(propertyCondPtr);
170  }
171  NdbMutex_Unlock(propertyMutexPtr);
172  return val;
173 }
174 
175 void NDBT_Context::setProperty(const char* _name, const char* _val){
176  NdbMutex_Lock(propertyMutexPtr);
177  const bool b = props.put(_name, _val, true);
178  assert(b == true);
179  NdbCondition_Broadcast(propertyCondPtr);
180  NdbMutex_Unlock(propertyMutexPtr);
181 }
182 
183 void NDBT_Context::stopTest(){
184  NdbMutex_Lock(propertyMutexPtr);
185  g_info << "|- stopTest called" << endl;
186  stopped = true;
187  NdbCondition_Broadcast(propertyCondPtr);
188  NdbMutex_Unlock(propertyMutexPtr);
189 }
190 
191 bool NDBT_Context::isTestStopped(){
192  NdbMutex_Lock(propertyMutexPtr);
193  bool val = stopped;
194  NdbMutex_Unlock(propertyMutexPtr);
195  return val;
196 }
197 
198 void NDBT_Context::wait(){
199  NdbMutex_Lock(propertyMutexPtr);
200  NdbCondition_Wait(propertyCondPtr,
201  propertyMutexPtr);
202  NdbMutex_Unlock(propertyMutexPtr);
203 }
204 
205 void NDBT_Context::wait_timeout(int msec){
206  NdbMutex_Lock(propertyMutexPtr);
207  NdbCondition_WaitTimeout(propertyCondPtr,
208  propertyMutexPtr,
209  msec);
210  NdbMutex_Unlock(propertyMutexPtr);
211 }
212 
213 void NDBT_Context::broadcast(){
214  NdbMutex_Lock(propertyMutexPtr);
215  NdbCondition_Broadcast(propertyCondPtr);
216  NdbMutex_Unlock(propertyMutexPtr);
217 }
218 
219 Uint32 NDBT_Context::getDbProperty(const char*){
220  abort();
221  return 0;
222 }
223 
224 bool NDBT_Context::setDbProperty(const char*, Uint32){
225  abort();
226  return true;
227 }
228 
229 void NDBT_Context::setTab(const NdbDictionary::Table* ptab){
230  tables.clear();
231  tables.push_back(ptab);
232  tables.push_back(0);
233 }
234 
235 void NDBT_Context::addTab(const NdbDictionary::Table* ptab){
236  if(tables.size())
237  tables.back() = ptab;
238  else
239  tables.push_back(ptab);
240 
241  tables.push_back(0);
242 }
243 
244 
245 const NdbDictionary::Table**
246 NDBT_Context::getTables()
247 {
248  return tables.getBase();
249 }
250 
251 void NDBT_Context::setSuite(NDBT_TestSuite* psuite){
252  assert(psuite != NULL);
253  suite = psuite;
254 }
255 
256 void NDBT_Context::setCase(NDBT_TestCase* pcase){
257  assert(pcase != NULL);
258  testcase = pcase;
259 }
260 
261 void NDBT_Context::setNumRecords(int _records){
262  records = _records;
263 
264 }
265 
266 void NDBT_Context::setNumLoops(int _loops){
267  loops = _loops;
268 }
269 
270 NDBT_Step::NDBT_Step(NDBT_TestCase* ptest, const char* pname,
271  NDBT_TESTFUNC* pfunc) :
272  m_ctx(NULL), name(pname), func(pfunc),
273  testcase(ptest), step_no(-1), m_ndb(NULL)
274 {
275 }
276 
277 #include "../../src/ndbapi/ndb_internal.hpp"
278 
279 int
280 NDBT_Step::setUp(Ndb_cluster_connection& con){
281 
282  switch(testcase->getDriverType())
283  {
284  case DummyDriver:
285  break;
286 
287  case NdbApiDriver:
288  {
289  m_ndb = new Ndb(&con, "TEST_DB" );
290  m_ndb->init(1024);
291 
292  Ndb_internal::setForceShortRequests(m_ndb,
293  m_ctx->suite->getForceShort());
294 
295  int result = m_ndb->waitUntilReady(300); // 5 minutes
296  if (result != 0){
297  g_err << "Ndb was not ready" << endl;
298  return NDBT_FAILED;
299  }
300  break;
301  }
302 
303  default:
304  abort();
305  break;
306 
307  }
308 
309  return NDBT_OK;
310 }
311 
312 
313 void
314 NDBT_Step::tearDown(){
315  delete m_ndb;
316  m_ndb = NULL;
317 }
318 
319 
320 Ndb* NDBT_Step::getNdb() const {
321  assert(m_ndb != NULL);
322  return m_ndb;
323 }
324 
325 
326 int NDBT_Step::execute(NDBT_Context* ctx) {
327  assert(ctx != NULL);
328 
329  int result;
330 
331  g_info << " |- " << name << " started [" << ctx->suite->getDate() << "]"
332  << endl;
333 
334  result = setUp(ctx->m_cluster_connection);
335  if (result != NDBT_OK){
336  return result;
337  }
338 
339  result = func(ctx, this);
340 
341  if (result != NDBT_OK) {
342  g_err << " |- " << name << " FAILED [" << ctx->suite->getDate()
343  << "]" << endl;
344  }
345  else {
346  g_info << " |- " << name << " PASSED [" << ctx->suite->getDate() << "]"
347  << endl;
348  }
349 
350  tearDown();
351 
352  return result;
353 }
354 
355 void NDBT_Step::setContext(NDBT_Context* pctx){
356  assert(pctx != NULL);
357  m_ctx = pctx;
358 }
359 
360 NDBT_Context* NDBT_Step::getContext(){
361  assert(m_ctx != NULL);
362  return m_ctx;
363 }
364 
365 
366 NDBT_ParallelStep::NDBT_ParallelStep(NDBT_TestCase* ptest,
367  const char* pname,
368  NDBT_TESTFUNC* pfunc)
369  : NDBT_Step(ptest, pname, pfunc) {
370 }
371 NDBT_Verifier::NDBT_Verifier(NDBT_TestCase* ptest,
372  const char* pname,
373  NDBT_TESTFUNC* pfunc)
374  : NDBT_Step(ptest, pname, pfunc) {
375 }
376 NDBT_Initializer::NDBT_Initializer(NDBT_TestCase* ptest,
377  const char* pname,
378  NDBT_TESTFUNC* pfunc)
379  : NDBT_Step(ptest, pname, pfunc) {
380 }
381 NDBT_Finalizer::NDBT_Finalizer(NDBT_TestCase* ptest,
382  const char* pname,
383  NDBT_TESTFUNC* pfunc)
384  : NDBT_Step(ptest, pname, pfunc) {
385 }
386 
387 NDBT_TestCase::NDBT_TestCase(NDBT_TestSuite* psuite,
388  const char* pname,
389  const char* pcomment) :
390  _name(pname) ,
391  _comment(pcomment),
392  suite(psuite)
393 {
394  assert(suite != NULL);
395 
396  m_all_tables = false;
397  m_has_run = false;
398 }
399 
400 NDBT_TestCaseImpl1::NDBT_TestCaseImpl1(NDBT_TestSuite* psuite,
401  const char* pname,
402  const char* pcomment) :
403  NDBT_TestCase(psuite, pname, pcomment){
404 
405  numStepsOk = 0;
406  numStepsFail = 0;
407  numStepsCompleted = 0;
408  waitThreadsMutexPtr = NdbMutex_Create();
409  waitThreadsCondPtr = NdbCondition_Create();
410 
411  m_driverType= psuite->getDriverType();
412 }
413 
414 NDBT_TestCaseImpl1::~NDBT_TestCaseImpl1(){
415  NdbCondition_Destroy(waitThreadsCondPtr);
416  NdbMutex_Destroy(waitThreadsMutexPtr);
417  size_t i;
418  for(i = 0; i < initializers.size(); i++)
419  delete initializers[i];
420  initializers.clear();
421  for(i = 0; i < verifiers.size(); i++)
422  delete verifiers[i];
423  verifiers.clear();
424  for(i = 0; i < finalizers.size(); i++)
425  delete finalizers[i];
426  finalizers.clear();
427  for(i = 0; i < steps.size(); i++)
428  delete steps[i];
429  steps.clear();
430  results.clear();
431  for(i = 0; i < testTables.size(); i++)
432  delete testTables[i];
433  testTables.clear();
434  for(i = 0; i < testResults.size(); i++)
435  delete testResults[i];
436  testResults.clear();
437 
438 }
439 
440 int NDBT_TestCaseImpl1::addStep(NDBT_Step* pStep){
441  assert(pStep != NULL);
442  steps.push_back(pStep);
443  pStep->setStepNo(steps.size());
444  int res = NORESULT;
445  results.push_back(res);
446  return 0;
447 }
448 
449 int NDBT_TestCaseImpl1::addVerifier(NDBT_Verifier* pVerifier){
450  assert(pVerifier != NULL);
451  verifiers.push_back(pVerifier);
452  return 0;
453 }
454 
455 int NDBT_TestCaseImpl1::addInitializer(NDBT_Initializer* pInitializer,
456  bool first){
457  assert(pInitializer != NULL);
458  if (first)
459  initializers.push(pInitializer, 0);
460  else
461  initializers.push_back(pInitializer);
462  return 0;
463 }
464 
465 int NDBT_TestCaseImpl1::addFinalizer(NDBT_Finalizer* pFinalizer){
466  assert(pFinalizer != NULL);
467  finalizers.push_back(pFinalizer);
468  return 0;
469 }
470 
471 void NDBT_TestCaseImpl1::addTable(const char* tableName, bool isVerify) {
472  assert(tableName != NULL);
473  const NdbDictionary::Table* pTable = NDBT_Tables::getTable(tableName);
474  assert(pTable != NULL);
475  testTables.push_back(pTable);
476  isVerifyTables = isVerify;
477 }
478 
479 bool NDBT_TestCaseImpl1::tableExists(NdbDictionary::Table* aTable) {
480  for (unsigned i = 0; i < testTables.size(); i++) {
481  if (strcasecmp(testTables[i]->getName(), aTable->getName()) == 0) {
482  return true;
483  }
484  }
485  return false;
486 }
487 
488 bool NDBT_TestCaseImpl1::isVerify(const NdbDictionary::Table* aTable) {
489  if (testTables.size() > 0) {
490  int found = false;
491  // OK, we either exclude or include this table in the actual test
492  for (unsigned i = 0; i < testTables.size(); i++) {
493  if (strcasecmp(testTables[i]->getName(), aTable->getName()) == 0) {
494  // Found one!
495  if (isVerifyTables) {
496  // Found one to test
497  found = true;
498  } else {
499  // Skip this one!
500  found = false;
501  }
502  }
503  } // for
504  return found;
505  } else {
506  // No included or excluded test tables, i.e., all tables should be
507  // tested
508  return true;
509  }
510  return true;
511 }
512 
513 void NDBT_TestCase::setProperty(const char* _name, Uint32 _val){
514  const bool b = props.put(_name, _val);
515  assert(b == true);
516 }
517 
518 void NDBT_TestCase::setProperty(const char* _name, const char* _val){
519  const bool b = props.put(_name, _val);
520  assert(b == true);
521 }
522 
523 
524 void *
525 runStep(void * s){
526  assert(s != NULL);
527  NDBT_Step* pStep = (NDBT_Step*)s;
528  NDBT_Context* ctx = pStep->getContext();
529  assert(ctx != NULL);
530  // Execute function
531  int res = pStep->execute(ctx);
532  if(res != NDBT_OK){
533  ctx->stopTest();
534  }
535  // Report
536  NDBT_TestCaseImpl1* pCase = (NDBT_TestCaseImpl1*)ctx->getCase();
537  assert(pCase != NULL);
538  pCase->reportStepResult(pStep, res);
539  return NULL;
540 }
541 
542 extern "C"
543 void *
544 runStep_C(void * s)
545 {
546  runStep(s);
547  return NULL;
548 }
549 
550 
551 void NDBT_TestCaseImpl1::startStepInThread(int stepNo, NDBT_Context* ctx){
552  NDBT_Step* pStep = steps[stepNo];
553  pStep->setContext(ctx);
554  char buf[16];
555  BaseString::snprintf(buf, sizeof(buf), "step_%d", stepNo);
556  Uint32 stackSize = ctx->getProperty(NDBT_TestCase::getStepThreadStackSizePropName(),
557  Uint32(0));
558 
559  NdbThread* pThread = NdbThread_Create(runStep_C,
560  (void**)pStep,
561  stackSize,
562  buf,
563  NDB_THREAD_PRIO_LOW);
564  threads.push_back(pThread);
565 }
566 
567 void NDBT_TestCaseImpl1::waitSteps(){
568  NdbMutex_Lock(waitThreadsMutexPtr);
569  while(numStepsCompleted != steps.size())
570  NdbCondition_Wait(waitThreadsCondPtr,
571  waitThreadsMutexPtr);
572 
573  unsigned completedSteps = 0;
574  unsigned i;
575  for(i=0; i<steps.size(); i++){
576  if (results[i] != NORESULT){
577  completedSteps++;
578  if (results[i] == NDBT_OK)
579  numStepsOk++;
580  else
581  numStepsFail++;
582  }
583  }
584  assert(completedSteps == steps.size());
585  assert(completedSteps == numStepsCompleted);
586 
587  NdbMutex_Unlock(waitThreadsMutexPtr);
588  void *status;
589  for(i=0; i<steps.size();i++){
590  NdbThread_WaitFor(threads[i], &status);
591  NdbThread_Destroy(&threads[i]);
592  }
593  threads.clear();
594 }
595 
596 
597 int
599  return steps.size() - getNoOfCompletedSteps();
600 }
601 
602 int
603 NDBT_TestCaseImpl1::getNoOfCompletedSteps() const {
604  return numStepsCompleted;
605 }
606 
607 void NDBT_TestCaseImpl1::reportStepResult(const NDBT_Step* pStep, int result){
608  NdbMutex_Lock(waitThreadsMutexPtr);
609  assert(pStep != NULL);
610  for (unsigned i = 0; i < steps.size(); i++){
611  if(steps[i] != NULL && steps[i] == pStep){
612  results[i] = result;
613  numStepsCompleted++;
614  }
615  }
616  if(numStepsCompleted == steps.size()){
617  NdbCondition_Signal(waitThreadsCondPtr);
618  }
619  NdbMutex_Unlock(waitThreadsMutexPtr);
620 }
621 
622 
623 int NDBT_TestCase::execute(NDBT_Context* ctx){
624  int res;
625 
626  ndbout << "- " << _name << " started [" << ctx->suite->getDate()
627  << "]" << endl;
628 
629  ctx->setCase(this);
630 
631  // Copy test case properties to ctx
632  Properties::Iterator it(&props);
633  for(const char * key = it.first(); key != 0; key = it.next()){
634 
635  PropertiesType pt;
636  const bool b = props.getTypeOf(key, &pt);
637  assert(b == true);
638  switch(pt){
639  case PropertiesType_Uint32:{
640  Uint32 val;
641  props.get(key, &val);
642  ctx->setProperty(key, val);
643  break;
644  }
645  case PropertiesType_char:{
646  const char * val;
647  props.get(key, &val);
648  ctx->setProperty(key, val);
649  break;
650  }
651  default:
652  abort();
653  }
654  }
655 
656  // start timer so that we get a time even if
657  // test case consist only of initializer
658  startTimer(ctx);
659 
660  if ((res = runInit(ctx)) == NDBT_OK){
661  // If initialiser is ok, run steps
662 
663  res = runSteps(ctx);
664  if (res == NDBT_OK){
665  // If steps is ok, run verifier
666  res = runVerifier(ctx);
667  }
668 
669  }
670 
671  stopTimer(ctx);
672  printTimer(ctx);
673 
674  // Always run finalizer to clean up db
675  runFinal(ctx);
676 
677  if (res == NDBT_OK) {
678  ndbout << "- " << _name << " PASSED [" << ctx->suite->getDate() << "]"
679  << endl;
680  }
681  else {
682  ndbout << "- " << _name << " FAILED [" << ctx->suite->getDate() << "]"
683  << endl;
684  }
685  return res;
686 }
687 
688 void NDBT_TestCase::startTimer(NDBT_Context* ctx){
689  timer.doStart();
690 }
691 
692 void NDBT_TestCase::stopTimer(NDBT_Context* ctx){
693  timer.doStop();
694 }
695 
696 void NDBT_TestCase::printTimer(NDBT_Context* ctx){
697  if (suite->timerIsOn()){
698  g_info << endl;
699  timer.printTestTimer(ctx->getNumLoops(), ctx->getNumRecords());
700  }
701 }
702 
703 int NDBT_TestCaseImpl1::runInit(NDBT_Context* ctx){
704  int res = NDBT_OK;
705  for (unsigned i = 0; i < initializers.size(); i++){
706  initializers[i]->setContext(ctx);
707  res = initializers[i]->execute(ctx);
708  if (res != NDBT_OK)
709  break;
710  }
711  return res;
712 }
713 
714 int NDBT_TestCaseImpl1::runSteps(NDBT_Context* ctx){
715  int res = NDBT_OK;
716 
717  // Reset variables
718  numStepsOk = 0;
719  numStepsFail = 0;
720  numStepsCompleted = 0;
721  unsigned i;
722  for (i = 0; i < steps.size(); i++)
723  startStepInThread(i, ctx);
724  waitSteps();
725 
726  for(i = 0; i < steps.size(); i++)
727  if (results[i] != NDBT_OK)
728  res = NDBT_FAILED;
729  return res;
730 }
731 
732 int NDBT_TestCaseImpl1::runVerifier(NDBT_Context* ctx){
733  int res = NDBT_OK;
734  for (unsigned i = 0; i < verifiers.size(); i++){
735  verifiers[i]->setContext(ctx);
736  res = verifiers[i]->execute(ctx);
737  if (res != NDBT_OK)
738  break;
739  }
740  return res;
741 }
742 
743 int NDBT_TestCaseImpl1::runFinal(NDBT_Context* ctx){
744  int res = NDBT_OK;
745  for (unsigned i = 0; i < finalizers.size(); i++){
746  finalizers[i]->setContext(ctx);
747  res = finalizers[i]->execute(ctx);
748  if (res != NDBT_OK)
749  break;
750  }
751  return res;
752 }
753 
754 
755 void NDBT_TestCaseImpl1::saveTestResult(const char* test_name,
756  int result){
757  testResults.push_back(new NDBT_TestCaseResult(test_name,
758  result,
759  timer.elapsedTime()));
760 }
761 
762 void NDBT_TestCaseImpl1::printTestResult(){
763 
764  char buf[255];
765  ndbout << _name<<endl;
766 
767  for (unsigned i = 0; i < testResults.size(); i++){
768  NDBT_TestCaseResult* tcr = testResults[i];
769  const char* res = "<unknown>";
770  if (tcr->getResult() == NDBT_OK)
771  res = "OK";
772  else if (tcr->getResult() == NDBT_FAILED)
773  res = "FAIL";
774  else if (tcr->getResult() == FAILED_TO_CREATE)
775  res = "FAILED TO CREATE TABLE";
776  else if (tcr->getResult() == FAILED_TO_DISCOVER)
777  res = "FAILED TO DISCOVER TABLE";
778  BaseString::snprintf(buf, 255," %-10s %-5s %-20s",
779  tcr->getName(),
780  res,
781  tcr->getTimeStr());
782  ndbout << buf<<endl;
783  }
784 }
785 
786 
787 
788 
789 
790 NDBT_TestSuite::NDBT_TestSuite(const char* pname) :
791  name(pname),
792  m_createTable(true),
793  m_createAll(false),
794  m_connect_cluster(true),
795  m_logging(true),
796  m_driverType(NdbApiDriver)
797 {
798  numTestsOk = 0;
799  numTestsFail = 0;
800  numTestsExecuted = 0;
801  records = 0;
802  loops = 0;
803  diskbased = false;
804  tsname = NULL;
805  temporaryTables = false;
806  runonce = false;
807  m_noddl = false;
808  m_forceShort = false;
809 }
810 
811 
812 NDBT_TestSuite::~NDBT_TestSuite(){
813  for(unsigned i=0; i<tests.size(); i++){
814  delete tests[i];
815  }
816  tests.clear();
817 }
818 
819 void NDBT_TestSuite::setCreateTable(bool _flag){
820  m_createTable = _flag;
821 }
822 
823 void NDBT_TestSuite::setRunAllTables(bool _flag){
824  runonce = _flag;
825 }
826 void NDBT_TestSuite::setCreateAllTables(bool _flag){
827  m_createAll = _flag;
828 }
829 void NDBT_TestSuite::setConnectCluster(bool _flag){
830  assert(m_createTable == false);
831  m_connect_cluster = _flag;
832 }
833 
834 void NDBT_TestSuite::setTemporaryTables(bool val){
835  temporaryTables = val;
836 }
837 
838 bool NDBT_TestSuite::getTemporaryTables() const {
839  return temporaryTables;
840 }
841 
842 void NDBT_TestSuite::setLogging(bool val){
843  m_logging = val;
844 }
845 
846 bool NDBT_TestSuite::getLogging() const {
847  return m_logging;
848 }
849 
850 bool NDBT_TestSuite::getForceShort() const {
851  return m_forceShort;
852 }
853 
854 bool NDBT_TestSuite::timerIsOn(){
855  return (timer != 0);
856 }
857 
858 int NDBT_TestSuite::addTest(NDBT_TestCase* pTest){
859  assert(pTest != NULL);
860  tests.push_back(pTest);
861  return 0;
862 }
863 
864 int NDBT_TestSuite::executeAll(Ndb_cluster_connection& con,
865  const char* _testname){
866 
867  if(tests.size() == 0)
868  return NDBT_FAILED;
869 
870  ndbout << name << " started [" << getDate() << "]" << endl;
871 
872  if(!runonce)
873  {
874  testSuiteTimer.doStart();
875  for (int t=0; t < NDBT_Tables::getNumTables(); t++){
876  const NdbDictionary::Table* ptab = NDBT_Tables::getTable(t);
877  ndbout << "|- " << ptab->getName() << endl;
878  execute(con, ptab, _testname);
879  }
880  testSuiteTimer.doStop();
881  }
882  else
883  {
884  for (unsigned i = 0; i < tests.size(); i++){
885  if (_testname != NULL && strcasecmp(tests[i]->getName(), _testname) != 0)
886  continue;
887 
888  tests[i]->initBeforeTest();
889  ctx = new NDBT_Context(con);
890 
891  ctx->setNumRecords(records);
892  ctx->setNumLoops(loops);
893  ctx->setSuite(this);
894  ctx->setProperty("NoDDL", (Uint32) m_noddl);
895 
896  int result = tests[i]->execute(ctx);
897 
898  tests[i]->saveTestResult("", result);
899  if (result != NDBT_OK)
900  numTestsFail++;
901  else
902  numTestsOk++;
903  numTestsExecuted++;
904 
905  delete ctx;
906  }
907  }
908  return reportAllTables(_testname);
909 }
910 
911 int
912 NDBT_TestSuite::executeOne(Ndb_cluster_connection& con,
913  const char* _tabname, const char* _testname){
914 
915  if(tests.size() == 0)
916  return NDBT_FAILED;
917 
918  ndbout << name << " started [" << getDate() << "]" << endl;
919 
920  const NdbDictionary::Table* ptab = NDBT_Tables::getTable(_tabname);
921  if (ptab == NULL)
922  return NDBT_FAILED;
923 
924  ndbout << "|- " << ptab->getName() << endl;
925 
926  execute(con, ptab, _testname);
927 
928  if (numTestsFail > 0){
929  return NDBT_FAILED;
930  }else{
931  return NDBT_OK;
932  }
933 }
934 
935 int
936 NDBT_TestSuite::executeOneCtx(Ndb_cluster_connection& con,
937  const NdbDictionary::Table *ptab, const char* _testname){
938 
939  testSuiteTimer.doStart();
940 
941  do{
942  if(tests.size() == 0)
943  break;
944 
945  Ndb ndb(&con, "TEST_DB");
946  ndb.init(1024);
947 
948  Ndb_internal::setForceShortRequests(&ndb, m_forceShort);
949 
950  int result = ndb.waitUntilReady(300); // 5 minutes
951  if (result != 0){
952  g_err << name <<": Ndb was not ready" << endl;
953  break;
954  }
955 
956  ndbout << name << " started [" << getDate() << "]" << endl;
957  ndbout << "|- " << ptab->getName() << endl;
958 
959  for (unsigned t = 0; t < tests.size(); t++){
960 
961  if (_testname != NULL &&
962  strcasecmp(tests[t]->getName(), _testname) != 0)
963  continue;
964 
965  tests[t]->initBeforeTest();
966 
967  ctx = new NDBT_Context(con);
968  ctx->setTab(ptab);
969  ctx->setNumRecords(records);
970  ctx->setNumLoops(loops);
971  ctx->setSuite(this);
972  ctx->setProperty("NoDDL", (Uint32) m_noddl);
973 
974  result = tests[t]->execute(ctx);
975  if (result != NDBT_OK)
976  numTestsFail++;
977  else
978  numTestsOk++;
979  numTestsExecuted++;
980 
981  delete ctx;
982  }
983 
984  if (numTestsFail > 0)
985  break;
986  }while(0);
987 
988  testSuiteTimer.doStop();
989  int res = report(_testname);
990  return NDBT_ProgramExit(res);
991 }
992 
993 int
994 NDBT_TestSuite::createHook(Ndb* ndb, NdbDictionary::Table& tab, int when)
995 {
996  if (when == 0) {
997  if (diskbased)
998  {
999  for (int i = 0; i < tab.getNoOfColumns(); i++)
1000  {
1001  NdbDictionary::Column* col = tab.getColumn(i);
1002  if (! col->getPrimaryKey())
1003  {
1004  col->setStorageType(NdbDictionary::Column::StorageTypeDisk);
1005  }
1006  }
1007  }
1008  else if (temporaryTables)
1009  {
1010  tab.setTemporary(true);
1011  tab.setLogging(false);
1012  }
1013 
1014  if (tsname != NULL) {
1015  tab.setTablespaceName(tsname);
1016  }
1017  }
1018  return 0;
1019 }
1020 
1021 void NDBT_TestSuite::execute(Ndb_cluster_connection& con,
1022  const NdbDictionary::Table* pTab,
1023  const char* _testname){
1024  int result;
1025 
1026  for (unsigned t = 0; t < tests.size(); t++){
1027 
1028  if (_testname != NULL &&
1029  strcasecmp(tests[t]->getName(), _testname) != 0)
1030  continue;
1031 
1032  if (tests[t]->m_all_tables && tests[t]->m_has_run)
1033  {
1034  continue;
1035  }
1036 
1037  if (tests[t]->isVerify(pTab) == false) {
1038  continue;
1039  }
1040 
1041  tests[t]->initBeforeTest();
1042 
1043  ctx = new NDBT_Context(con);
1044  ctx->setNumRecords(records);
1045  ctx->setNumLoops(loops);
1046  ctx->setSuite(this);
1047  ctx->setTab(pTab);
1048  ctx->setProperty("NoDDL", (Uint32) m_noddl);
1049 
1050  result = tests[t]->execute(ctx);
1051  tests[t]->saveTestResult(pTab->getName(), result);
1052  if (result != NDBT_OK)
1053  numTestsFail++;
1054  else
1055  numTestsOk++;
1056  numTestsExecuted++;
1057 
1058  tests[t]->m_has_run = true;
1059 
1060  delete ctx;
1061  }
1062 }
1063 
1064 
1065 
1066 int
1067 NDBT_TestSuite::createTables(Ndb_cluster_connection& con) const
1068 {
1069  Ndb ndb(&con, "TEST_DB");
1070  ndb.init(1);
1071 
1073  for(unsigned i = 0; i<m_tables_in_test.size(); i++)
1074  {
1075  const char *tab_name= m_tables_in_test[i].c_str();
1076  if (pDict->dropTable(tab_name) != 0 &&
1077  pDict->getNdbError().code != 723) // No such table
1078  {
1079  g_err << "runCreateTables: Failed to drop table " << tab_name << endl
1080  << pDict->getNdbError() << endl;
1081  return NDBT_FAILED;
1082  }
1083  if(NDBT_Tables::createTable(&ndb, tab_name, !getLogging()) != 0)
1084  {
1085  g_err << "runCreateTables: Failed to create table " << tab_name << endl
1086  << pDict->getNdbError() << endl;
1087  return NDBT_FAILED;
1088  }
1089 
1090  if (i == 0){
1091  // Update ctx with a pointer to the first created table
1092  const NdbDictionary::Table* pTab2 = pDict->getTable(tab_name);
1093  ctx->setTab(pTab2);
1094  }
1095  g_info << "created " << tab_name << endl;
1096  }
1097 
1098  return NDBT_OK;
1099 }
1100 
1101 
1102 static int
1103 runCreateTables(NDBT_Context* ctx, NDBT_Step* step)
1104 {
1105  NDBT_TestSuite* suite= ctx->getSuite();
1106  return suite->createTables(ctx->m_cluster_connection);
1107 }
1108 
1109 
1110 static int
1111 runCreateTable(NDBT_Context* ctx, NDBT_Step* step)
1112 {
1113  Ndb ndb(&ctx->m_cluster_connection, "TEST_DB");
1114  ndb.init(1);
1115 
1117  const NdbDictionary::Table* pTab = ctx->getTab();
1118  const char *tab_name= pTab->getName();
1119  if (pDict->dropTable(tab_name) != 0 &&
1120  pDict->getNdbError().code != 723) // No such table
1121  {
1122  g_err << "runCreateTable: Failed to drop table " << tab_name << endl
1123  << pDict->getNdbError() << endl;
1124  return NDBT_FAILED;
1125  }
1126 
1127  if(NDBT_Tables::createTable(&ndb, tab_name,
1128  !ctx->getSuite()->getLogging()) != 0)
1129  {
1130  g_err << "runCreateTable: Failed to create table " << tab_name
1131  << pDict->getNdbError() << endl;
1132  return NDBT_FAILED;
1133  }
1134 
1135  // Update ctx with a pointer to the created table
1136  const NdbDictionary::Table* pTab2 = pDict->getTable(tab_name);
1137  ctx->setTab(pTab2);
1138  ctx->setProperty("$table", tab_name);
1139 
1140  return NDBT_OK;
1141 }
1142 
1143 
1144 int
1145 NDBT_TestSuite::dropTables(Ndb_cluster_connection& con) const
1146 {
1147  Ndb ndb(&con, "TEST_DB");
1148  ndb.init(1);
1149 
1151  for(unsigned i = 0; i<m_tables_in_test.size(); i++)
1152  {
1153  const char *tab_name= m_tables_in_test[i].c_str();
1154  pDict->dropTable(tab_name);
1155  }
1156  return NDBT_OK;
1157 }
1158 
1159 
1160 static int
1161 runDropTables(NDBT_Context* ctx, NDBT_Step* step)
1162 {
1163  NDBT_TestSuite* suite= ctx->getSuite();
1164  return suite->dropTables(ctx->m_cluster_connection);
1165 }
1166 
1167 
1168 static int
1169 runDropTable(NDBT_Context* ctx, NDBT_Step* step)
1170 {
1171  const char * tab_name = ctx->getProperty("$table", (const char*)0);
1172  if (tab_name)
1173  {
1174  Ndb ndb(&ctx->m_cluster_connection, "TEST_DB");
1175  ndb.init(1);
1176 
1178  pDict->dropTable(tab_name);
1179  }
1180  return NDBT_OK;
1181 }
1182 
1183 
1184 static int
1185 runCheckTableExists(NDBT_Context* ctx, NDBT_Step* step)
1186 {
1187  Ndb ndb(&ctx->m_cluster_connection, "TEST_DB");
1188  ndb.init(1);
1189 
1191  const NdbDictionary::Table* pTab = ctx->getTab();
1192  const char *tab_name= pTab->getName();
1193 
1194  const NdbDictionary::Table* pDictTab = pDict->getTable(tab_name);
1195 
1196  if (pDictTab == NULL)
1197  {
1198  g_err << "runCheckTableExists : Failed to find table "
1199  << tab_name << endl;
1200  g_err << "Required schema : " << *((NDBT_Table*)pTab) << endl;
1201  return NDBT_FAILED;
1202  }
1203 
1204  /* Todo : better check that table in DB is same as
1205  * table we expect
1206  */
1207 
1208  // Update ctx with a pointer to dict table
1209  ctx->setTab(pDictTab);
1210  ctx->setProperty("$table", tab_name);
1211 
1212  return NDBT_OK;
1213 }
1214 
1215 static int
1216 runEmptyDropTable(NDBT_Context* ctx, NDBT_Step* step)
1217 {
1218  return NDBT_OK;
1219 }
1220 
1221 int
1222 NDBT_TestSuite::report(const char* _tcname){
1223  int result;
1224  ndbout << "Completed " << name << " [" << getDate() << "]" << endl;
1225  printTestCaseSummary(_tcname);
1226  ndbout << numTestsExecuted << " test(s) executed" << endl;
1227  ndbout << numTestsOk << " test(s) OK"
1228  << endl;
1229  if(numTestsFail > 0)
1230  ndbout << numTestsFail << " test(s) failed"
1231  << endl;
1232  testSuiteTimer.printTotalTime();
1233  if (numTestsFail > 0 || numTestsExecuted == 0){
1234  result = NDBT_FAILED;
1235  }else{
1236  result = NDBT_OK;
1237  }
1238  return result;
1239 }
1240 
1241 void NDBT_TestSuite::printTestCaseSummary(const char* _tcname){
1242  ndbout << "= SUMMARY OF TEST EXECUTION ==============" << endl;
1243  for (unsigned t = 0; t < tests.size(); t++){
1244  if (_tcname != NULL &&
1245  strcasecmp(tests[t]->getName(), _tcname) != 0)
1246  continue;
1247 
1248  tests[t]->printTestResult();
1249  }
1250  ndbout << "==========================================" << endl;
1251 }
1252 
1253 int NDBT_TestSuite::reportAllTables(const char* _testname){
1254  int result;
1255  ndbout << "Completed running test [" << getDate() << "]" << endl;
1256  const int totalNumTests = numTestsExecuted;
1257  printTestCaseSummary(_testname);
1258  ndbout << numTestsExecuted<< " test(s) executed" << endl;
1259  ndbout << numTestsOk << " test(s) OK("
1260  <<(int)(((float)numTestsOk/totalNumTests)*100.0) <<"%)"
1261  << endl;
1262  if(numTestsFail > 0)
1263  ndbout << numTestsFail << " test(s) failed("
1264  <<(int)(((float)numTestsFail/totalNumTests)*100.0) <<"%)"
1265  << endl;
1266  testSuiteTimer.printTotalTime();
1267  if (numTestsExecuted > 0){
1268  if (numTestsFail > 0){
1269  result = NDBT_FAILED;
1270  }else{
1271  result = NDBT_OK;
1272  }
1273  } else {
1274  result = NDBT_FAILED;
1275  }
1276  return result;
1277 }
1278 
1279 static int opt_print = false;
1280 static int opt_print_html = false;
1281 static int opt_print_cases = false;
1282 static int opt_records;
1283 static int opt_loops;
1284 static int opt_timer;
1285 static char * opt_testname = NULL;
1286 static int opt_verbose;
1287 unsigned opt_seed = 0;
1288 static int opt_nologging = 0;
1289 static int opt_temporary = 0;
1290 static int opt_noddl = 0;
1291 static int opt_forceShort = 0;
1292 
1293 static struct my_option my_long_options[] =
1294 {
1295  NDB_STD_OPTS(""),
1296  { "print", NDB_OPT_NOSHORT, "Print execution tree",
1297  (uchar **) &opt_print, (uchar **) &opt_print, 0,
1298  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
1299  { "print_html", NDB_OPT_NOSHORT, "Print execution tree in html table format",
1300  (uchar **) &opt_print_html, (uchar **) &opt_print_html, 0,
1301  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
1302  { "print_cases", NDB_OPT_NOSHORT, "Print list of test cases",
1303  (uchar **) &opt_print_cases, (uchar **) &opt_print_cases, 0,
1304  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
1305  { "records", 'r', "Number of records",
1306  (uchar **) &opt_records, (uchar **) &opt_records, 0,
1307  GET_INT, REQUIRED_ARG, 1000, 0, 0, 0, 0, 0 },
1308  { "loops", 'l', "Number of loops",
1309  (uchar **) &opt_loops, (uchar **) &opt_loops, 0,
1310  GET_INT, REQUIRED_ARG, 5, 0, 0, 0, 0, 0 },
1311  { "seed", NDB_OPT_NOSHORT, "Random seed",
1312  (uchar **) &opt_seed, (uchar **) &opt_seed, 0,
1313  GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
1314  { "testname", 'n', "Name of test to run",
1315  (uchar **) &opt_testname, (uchar **) &opt_testname, 0,
1316  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
1317  { "timer", 't', "Print execution time",
1318  (uchar **) &opt_timer, (uchar **) &opt_timer, 0,
1319  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
1320  { "verbose", 'v', "Print verbose status",
1321  (uchar **) &opt_verbose, (uchar **) &opt_verbose, 0,
1322  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
1323  { "temporary-tables", 'T', "Create temporary table(s)",
1324  (uchar **) &opt_temporary, (uchar **) &opt_temporary, 0,
1325  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
1326  { "nologging", NDB_OPT_NOSHORT, "Create table(s) wo/ logging",
1327  (uchar **) &opt_nologging, (uchar **) &opt_nologging, 0,
1328  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
1329  { "noddl", NDB_OPT_NOSHORT,
1330  "Don't create/drop tables as part of running tests",
1331  (uchar**) &opt_noddl, (uchar**) &opt_noddl, 0,
1332  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
1333  { "forceshortreqs", NDB_OPT_NOSHORT, "Use short signals for NdbApi requests",
1334  (uchar**) &opt_forceShort, (uchar**) &opt_forceShort, 0,
1335  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
1336  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
1337 };
1338 
1339 extern int global_flag_skip_invalidate_cache;
1340 
1341 const char *load_default_groups[]= { "mysql_cluster",0 };
1342 
1343 static void short_usage_sub(void)
1344 {
1345  ndb_short_usage_sub("[tabname1 tabname2 ... tabnameN]");
1346 }
1347 static void usage()
1348 {
1349  ndb_usage(short_usage_sub, load_default_groups, my_long_options);
1350 }
1351 
1352 int NDBT_TestSuite::execute(int argc, const char** argv){
1353  int res = NDBT_FAILED;
1354  /* Arguments:
1355  Run only a subset of tests
1356  -n testname Which test to run
1357  Recommendations to test functions:
1358  --records Number of records to use(default: 10000)
1359  --loops Number of loops to execute in the test(default: 100)
1360 
1361  Other parameters should:
1362  * be calculated from the above two parameters
1363  * be divided into different test cases, ex. one testcase runs
1364  with FragmentType = Single and another perfoms the same
1365  test with FragmentType = Large
1366  * let the test case iterate over all/subset of appropriate parameters
1367  ex. iterate over FragmentType = Single to FragmentType = AllLarge
1368 
1369  Remeber that the intention is that it should be _easy_ to run
1370  a complete test suite without any greater knowledge of what
1371  should be tested ie. keep arguments at a minimum
1372  */
1373 
1374  char **_argv= (char **)argv;
1375 
1376  if (!my_progname)
1377  my_progname= _argv[0];
1378 
1379  ndb_opt_set_usage_funcs(short_usage_sub, usage);
1380 
1381  load_defaults("my",load_default_groups,&argc,&_argv);
1382 
1383  int ho_error;
1384 #ifndef DBUG_OFF
1385  opt_debug= "d:t:i:F:L";
1386 #endif
1387  if ((ho_error=handle_options(&argc, &_argv, my_long_options,
1388  ndb_std_get_one_option)))
1389  {
1390  usage();
1391  return NDBT_ProgramExit(NDBT_WRONGARGS);
1392  }
1393 
1394  if (opt_verbose)
1395  setOutputLevel(2); // Show g_info
1396  else
1397  setOutputLevel(0); // Show only g_err ?
1398 
1399  records = opt_records;
1400  loops = opt_loops;
1401  timer = opt_timer;
1402  if (opt_nologging)
1403  setLogging(false);
1404  temporaryTables = opt_temporary;
1405  m_noddl = opt_noddl;
1406  m_forceShort = opt_forceShort;
1407 
1408  if (opt_seed == 0)
1409  {
1410  opt_seed = (unsigned)NdbTick_CurrentMillisecond();
1411  }
1412  ndbout_c("random seed: %u", opt_seed);
1413  srand(opt_seed);
1414  srandom(opt_seed);
1415 
1416  global_flag_skip_invalidate_cache = 1;
1417 
1418  int num_tables= argc;
1419  if (argc == 0)
1420  num_tables = NDBT_Tables::getNumTables();
1421 
1422  for(int i = 0; i<num_tables; i++)
1423  {
1424  if (argc == 0)
1425  m_tables_in_test.push_back(NDBT_Tables::getTable(i)->getName());
1426  else
1427  m_tables_in_test.push_back(_argv[i]);
1428  }
1429 
1430  if (m_createTable)
1431  {
1432  for (unsigned t = 0; t < tests.size(); t++)
1433  {
1434  const char* createFuncName= NULL;
1435  NDBT_TESTFUNC* createFunc= NULL;
1436  const char* dropFuncName= NULL;
1437  NDBT_TESTFUNC* dropFunc= NULL;
1438 
1439  if (!m_noddl)
1440  {
1441  createFuncName= m_createAll ? "runCreateTable" : "runCreateTable";
1442  createFunc= m_createAll ? &runCreateTables : &runCreateTable;
1443  dropFuncName= m_createAll ? "runDropTables" : "runDropTable";
1444  dropFunc= m_createAll ? &runDropTables : &runDropTable;
1445  }
1446  else
1447  {
1448  /* No DDL allowed, so we substitute 'do nothing' variants
1449  * of the create + drop table test procs
1450  */
1451  createFuncName= "runCheckTableExists";
1452  createFunc= &runCheckTableExists;
1453  dropFuncName= "runEmptyDropTable";
1454  dropFunc= &runEmptyDropTable;
1455  }
1456 
1457  NDBT_TestCaseImpl1* pt= (NDBT_TestCaseImpl1*)tests[t];
1458  NDBT_Initializer* pti =
1459  new NDBT_Initializer(pt,
1460  createFuncName,
1461  *createFunc);
1462  pt->addInitializer(pti, true);
1463  NDBT_Finalizer* ptf =
1464  new NDBT_Finalizer(pt,
1465  dropFuncName,
1466  *dropFunc);
1467  pt->addFinalizer(ptf);
1468  }
1469  }
1470 
1471  if (opt_print == true){
1472  printExecutionTree();
1473  return 0;
1474  }
1475 
1476  if (opt_print_html == true){
1477  printExecutionTreeHTML();
1478  return 0;
1479  }
1480 
1481  if (opt_print_cases == true){
1482  printCases();
1483  return 0;
1484  }
1485 
1486  Ndb_cluster_connection con(opt_ndb_connectstring, opt_ndb_nodeid);
1487  if(m_connect_cluster && con.connect(12, 5, 1))
1488  {
1489  return NDBT_ProgramExit(NDBT_FAILED);
1490  }
1491 
1492  if(argc == 0){
1493  // No table specified
1494  res = executeAll(con, opt_testname);
1495  } else {
1496  testSuiteTimer.doStart();
1497  for(int i = 0; i<argc; i++){
1498  executeOne(con, _argv[i], opt_testname);
1499  }
1500  testSuiteTimer.doStop();
1501  res = report(opt_testname);
1502  }
1503 
1504  return NDBT_ProgramExit(res);
1505 }
1506 
1507 
1508 void NDBT_TestSuite::printExecutionTree(){
1509  ndbout << "Testsuite: " << name << endl;
1510  for (unsigned t = 0; t < tests.size(); t++){
1511  tests[t]->print();
1512  ndbout << endl;
1513  }
1514 }
1515 
1516 void NDBT_TestSuite::printExecutionTreeHTML(){
1517  ndbout << "<tr>" << endl;
1518  ndbout << "<td><h3>" << name << "</h3></td>" << endl;
1519  ndbout << "</tr>" << endl;
1520  for (unsigned t = 0; t < tests.size(); t++){
1521  tests[t]->printHTML();
1522  ndbout << endl;
1523  }
1524 
1525 }
1526 
1527 void NDBT_TestSuite::printCases(){
1528  ndbout << "# Testsuite: " << name << endl;
1529  ndbout << "# Number of tests: " << tests.size() << endl;
1530  for (unsigned t = 0; t < tests.size(); t++){
1531  ndbout << name << " -n " << tests[t]->getName() << endl;
1532  }
1533 }
1534 
1536  static char theTime[128];
1537  struct tm* tm_now;
1538  time_t now;
1539  now = time((time_t*)NULL);
1540 #ifdef NDB_WIN32
1541  tm_now = localtime(&now);
1542 #else
1543  tm_now = gmtime(&now);
1544 #endif
1545 
1546  BaseString::snprintf(theTime, 128,
1547  "%d-%.2d-%.2d %.2d:%.2d:%.2d",
1548  tm_now->tm_year + 1900,
1549  tm_now->tm_mon + 1,
1550  tm_now->tm_mday,
1551  tm_now->tm_hour,
1552  tm_now->tm_min,
1553  tm_now->tm_sec);
1554 
1555  return theTime;
1556 }
1557 
1558 void NDBT_TestCaseImpl1::printHTML(){
1559 
1560  ndbout << "<tr><td>&nbsp;</td>" << endl;
1561  ndbout << "<td name=tc>" << endl << _name << "</td><td width=70%>"
1562  << _comment << "</td></tr>" << endl;
1563 }
1564 
1565 void NDBT_TestCaseImpl1::print(){
1566  ndbout << "Test case: " << _name << endl;
1567  ndbout << "Description: "<< _comment << endl;
1568 
1569  ndbout << "Parameters: " << endl;
1570 
1571  Properties::Iterator it(&props);
1572  for(const char * key = it.first(); key != 0; key = it.next()){
1573  PropertiesType pt;
1574  const bool b = props.getTypeOf(key, &pt);
1575  assert(b == true);
1576  switch(pt){
1577  case PropertiesType_Uint32:{
1578  Uint32 val;
1579  props.get(key, &val);
1580  ndbout << " " << key << ": " << val << endl;
1581  break;
1582  }
1583  case PropertiesType_char:{
1584  const char * val;
1585  props.get(key, &val);
1586  ndbout << " " << key << ": " << val << endl;
1587  break;
1588  }
1589  default:
1590  abort();
1591  }
1592  }
1593  unsigned i;
1594  for(i=0; i<initializers.size(); i++){
1595  ndbout << "Initializers[" << i << "]: " << endl;
1596  initializers[i]->print();
1597  }
1598  for(i=0; i<steps.size(); i++){
1599  ndbout << "Step[" << i << "]: " << endl;
1600  steps[i]->print();
1601  }
1602  for(i=0; i<verifiers.size(); i++){
1603  ndbout << "Verifier[" << i << "]: " << endl;
1604  verifiers[i]->print();
1605  }
1606  for(i=0; i<finalizers.size(); i++){
1607  ndbout << "Finalizer[" << i << "]: " << endl;
1608  finalizers[i]->print();
1609  }
1610 
1611 }
1612 
1613 void NDBT_Step::print(){
1614  ndbout << " "<< name << endl;
1615 
1616 }
1617 
1618 void
1619 NDBT_Context::sync_down(const char * key){
1620  Uint32 threads = getProperty(key, (unsigned)0);
1621  if(threads){
1622  decProperty(key);
1623  }
1624 }
1625 
1626 void
1627 NDBT_Context::sync_up_and_wait(const char * key, Uint32 value){
1628  setProperty(key, value);
1629  getPropertyWait(key, (unsigned)0);
1630 }
1631 
1632 template class Vector<NDBT_TestCase*>;
1633 template class Vector<NDBT_TestCaseResult*>;
1634 template class Vector<NDBT_Step*>;
1635 template class Vector<NdbThread*>;
1636 template class Vector<NDBT_Verifier*>;
1637 template class Vector<NDBT_Initializer*>;
1638 template class Vector<NDBT_Finalizer*>;