~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to storage/ndb/test/src/NDBT_Test.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

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