1
/* Copyright (C) 2003 MySQL AB
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.
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.
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 */
16
#include <ndb_global.h>
17
//#define NDB_OPTS_SKIP_USAGE
19
#include <my_pthread.h>
22
#include "NDBT_Test.hpp"
30
NDBT_Context::NDBT_Context(Ndb_cluster_connection& con)
31
: m_cluster_connection(con)
40
propertyMutexPtr = NdbMutex_Create();
41
propertyCondPtr = NdbCondition_Create();
45
char * NDBT_Context::getRemoteMgm() const {
48
void NDBT_Context::setRemoteMgm(char * mgm) {
49
remote_mgm = strdup(mgm);
53
NDBT_Context::~NDBT_Context(){
54
NdbCondition_Destroy(propertyCondPtr);
55
NdbMutex_Destroy(propertyMutexPtr);
58
const NdbDictionary::Table* NDBT_Context::getTab(){
59
assert(tables.size());
63
NDBT_TestSuite* NDBT_Context::getSuite(){
64
assert(suite != NULL);
68
NDBT_TestCase* NDBT_Context::getCase(){
69
assert(testcase != NULL);
73
const char* NDBT_Context::getTableName(int n) const
75
assert(suite != NULL);
76
return suite->m_tables_in_test[n].c_str();
79
int NDBT_Context::getNumTables() const
81
assert(suite != NULL);
82
return suite->m_tables_in_test.size();
85
int NDBT_Context::getNumRecords() const{
89
int NDBT_Context::getNumLoops() const{
93
int NDBT_Context::getNoOfRunningSteps() const {
94
return testcase->getNoOfRunningSteps();
97
int NDBT_Context::getNoOfCompletedSteps() const {
98
return testcase->getNoOfCompletedSteps();
102
Uint32 NDBT_Context::getProperty(const char* _name, Uint32 _default){
104
NdbMutex_Lock(propertyMutexPtr);
105
if(!props.get(_name, &val))
107
NdbMutex_Unlock(propertyMutexPtr);
111
bool NDBT_Context::getPropertyWait(const char* _name, Uint32 _waitVal){
113
NdbMutex_Lock(propertyMutexPtr);
114
Uint32 val =! _waitVal;
116
while((!props.get(_name, &val) || (props.get(_name, &val) && val != _waitVal)) &&
118
NdbCondition_Wait(propertyCondPtr,
120
result = (val == _waitVal);
121
NdbMutex_Unlock(propertyMutexPtr);
125
const char* NDBT_Context::getProperty(const char* _name, const char* _default){
127
NdbMutex_Lock(propertyMutexPtr);
128
if(!props.get(_name, &val))
130
NdbMutex_Unlock(propertyMutexPtr);
134
const char* NDBT_Context::getPropertyWait(const char* _name, const char* _waitVal){
136
NdbMutex_Lock(propertyMutexPtr);
137
while(!props.get(_name, &val) && (strcmp(val, _waitVal)==0))
138
NdbCondition_Wait(propertyCondPtr,
141
NdbMutex_Unlock(propertyMutexPtr);
145
void NDBT_Context::setProperty(const char* _name, Uint32 _val){
146
NdbMutex_Lock(propertyMutexPtr);
147
const bool b = props.put(_name, _val, true);
149
NdbCondition_Broadcast(propertyCondPtr);
150
NdbMutex_Unlock(propertyMutexPtr);
154
NDBT_Context::decProperty(const char * name){
155
NdbMutex_Lock(propertyMutexPtr);
157
if(props.get(name, &val)){
159
props.put(name, (val - 1), true);
161
NdbCondition_Broadcast(propertyCondPtr);
162
NdbMutex_Unlock(propertyMutexPtr);
166
NDBT_Context::incProperty(const char * name){
167
NdbMutex_Lock(propertyMutexPtr);
169
props.get(name, &val);
170
props.put(name, (val + 1), true);
171
NdbCondition_Broadcast(propertyCondPtr);
172
NdbMutex_Unlock(propertyMutexPtr);
175
void NDBT_Context::setProperty(const char* _name, const char* _val){
176
NdbMutex_Lock(propertyMutexPtr);
177
const bool b = props.put(_name, _val);
179
NdbCondition_Broadcast(propertyCondPtr);
180
NdbMutex_Unlock(propertyMutexPtr);
183
void NDBT_Context::stopTest(){
184
NdbMutex_Lock(propertyMutexPtr);
185
g_info << "|- stopTest called" << endl;
187
NdbCondition_Broadcast(propertyCondPtr);
188
NdbMutex_Unlock(propertyMutexPtr);
191
bool NDBT_Context::isTestStopped(){
192
NdbMutex_Lock(propertyMutexPtr);
194
NdbMutex_Unlock(propertyMutexPtr);
198
void NDBT_Context::wait(){
199
NdbMutex_Lock(propertyMutexPtr);
200
NdbCondition_Wait(propertyCondPtr,
202
NdbMutex_Unlock(propertyMutexPtr);
205
void NDBT_Context::wait_timeout(int msec){
206
NdbMutex_Lock(propertyMutexPtr);
207
NdbCondition_WaitTimeout(propertyCondPtr,
210
NdbMutex_Unlock(propertyMutexPtr);
213
void NDBT_Context::broadcast(){
214
NdbMutex_Lock(propertyMutexPtr);
215
NdbCondition_Broadcast(propertyCondPtr);
216
NdbMutex_Unlock(propertyMutexPtr);
219
Uint32 NDBT_Context::getDbProperty(const char*){
224
bool NDBT_Context::setDbProperty(const char*, Uint32){
229
void NDBT_Context::setTab(const NdbDictionary::Table* ptab){
231
tables.push_back(ptab);
235
void NDBT_Context::addTab(const NdbDictionary::Table* ptab){
237
tables.back() = ptab;
239
tables.push_back(ptab);
245
const NdbDictionary::Table**
246
NDBT_Context::getTables()
248
return tables.getBase();
251
void NDBT_Context::setSuite(NDBT_TestSuite* psuite){
252
assert(psuite != NULL);
256
void NDBT_Context::setCase(NDBT_TestCase* pcase){
257
assert(pcase != NULL);
261
void NDBT_Context::setNumRecords(int _records){
266
void NDBT_Context::setNumLoops(int _loops){
270
NDBT_Step::NDBT_Step(NDBT_TestCase* ptest, const char* pname,
271
NDBT_TESTFUNC* pfunc): name(pname){
272
assert(pfunc != NULL);
278
int NDBT_Step::execute(NDBT_Context* ctx) {
283
g_info << " |- " << name << " started [" << ctx->suite->getDate() << "]"
286
result = setUp(ctx->m_cluster_connection);
287
if (result != NDBT_OK){
291
result = func(ctx, this);
293
if (result != NDBT_OK) {
294
g_err << " |- " << name << " FAILED [" << ctx->suite->getDate()
298
g_info << " |- " << name << " PASSED [" << ctx->suite->getDate() << "]"
307
void NDBT_Step::setContext(NDBT_Context* pctx){
308
assert(pctx != NULL);
312
NDBT_Context* NDBT_Step::getContext(){
313
assert(m_ctx != NULL);
317
NDBT_NdbApiStep::NDBT_NdbApiStep(NDBT_TestCase* ptest,
319
NDBT_TESTFUNC* pfunc)
320
: NDBT_Step(ptest, pname, pfunc),
326
NDBT_NdbApiStep::setUp(Ndb_cluster_connection& con){
327
ndb = new Ndb(&con, "TEST_DB" );
330
int result = ndb->waitUntilReady(300); // 5 minutes
332
g_err << name << ": Ndb was not ready" << endl;
339
NDBT_NdbApiStep::tearDown(){
344
Ndb* NDBT_NdbApiStep::getNdb(){
350
NDBT_ParallelStep::NDBT_ParallelStep(NDBT_TestCase* ptest,
352
NDBT_TESTFUNC* pfunc)
353
: NDBT_NdbApiStep(ptest, pname, pfunc) {
355
NDBT_Verifier::NDBT_Verifier(NDBT_TestCase* ptest,
357
NDBT_TESTFUNC* pfunc)
358
: NDBT_NdbApiStep(ptest, pname, pfunc) {
360
NDBT_Initializer::NDBT_Initializer(NDBT_TestCase* ptest,
362
NDBT_TESTFUNC* pfunc)
363
: NDBT_NdbApiStep(ptest, pname, pfunc) {
365
NDBT_Finalizer::NDBT_Finalizer(NDBT_TestCase* ptest,
367
NDBT_TESTFUNC* pfunc)
368
: NDBT_NdbApiStep(ptest, pname, pfunc) {
371
NDBT_TestCase::NDBT_TestCase(NDBT_TestSuite* psuite,
373
const char* pcomment) :
374
name(strdup(pname)) ,
375
comment(strdup(pcomment)),
379
_comment.assign(pcomment);
381
comment= _comment.c_str();
382
assert(suite != NULL);
384
m_all_tables = false;
388
NDBT_TestCaseImpl1::NDBT_TestCaseImpl1(NDBT_TestSuite* psuite,
390
const char* pcomment) :
391
NDBT_TestCase(psuite, pname, pcomment){
395
numStepsCompleted = 0;
396
waitThreadsMutexPtr = NdbMutex_Create();
397
waitThreadsCondPtr = NdbCondition_Create();
400
NDBT_TestCaseImpl1::~NDBT_TestCaseImpl1(){
401
NdbCondition_Destroy(waitThreadsCondPtr);
402
NdbMutex_Destroy(waitThreadsMutexPtr);
404
for(i = 0; i < initializers.size(); i++)
405
delete initializers[i];
406
initializers.clear();
407
for(i = 0; i < verifiers.size(); i++)
410
for(i = 0; i < finalizers.size(); i++)
411
delete finalizers[i];
413
for(i = 0; i < steps.size(); i++)
417
for(i = 0; i < testTables.size(); i++)
418
delete testTables[i];
420
for(i = 0; i < testResults.size(); i++)
421
delete testResults[i];
426
int NDBT_TestCaseImpl1::addStep(NDBT_Step* pStep){
427
assert(pStep != NULL);
428
steps.push_back(pStep);
429
pStep->setStepNo(steps.size());
431
results.push_back(res);
435
int NDBT_TestCaseImpl1::addVerifier(NDBT_Verifier* pVerifier){
436
assert(pVerifier != NULL);
437
verifiers.push_back(pVerifier);
441
int NDBT_TestCaseImpl1::addInitializer(NDBT_Initializer* pInitializer){
442
assert(pInitializer != NULL);
443
initializers.push_back(pInitializer);
447
int NDBT_TestCaseImpl1::addFinalizer(NDBT_Finalizer* pFinalizer){
448
assert(pFinalizer != NULL);
449
finalizers.push_back(pFinalizer);
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;
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) {
470
bool NDBT_TestCaseImpl1::isVerify(const NdbDictionary::Table* aTable) {
471
if (testTables.size() > 0) {
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) {
477
if (isVerifyTables) {
488
// No included or excluded test tables, i.e., all tables should be
495
void NDBT_TestCase::setProperty(const char* _name, Uint32 _val){
496
const bool b = props.put(_name, _val);
500
void NDBT_TestCase::setProperty(const char* _name, const char* _val){
501
const bool b = props.put(_name, _val);
509
NDBT_Step* pStep = (NDBT_Step*)s;
510
NDBT_Context* ctx = pStep->getContext();
513
int res = pStep->execute(ctx);
518
NDBT_TestCaseImpl1* pCase = (NDBT_TestCaseImpl1*)ctx->getCase();
519
assert(pCase != NULL);
520
pCase->reportStepResult(pStep, res);
533
void NDBT_TestCaseImpl1::startStepInThread(int stepNo, NDBT_Context* ctx){
534
NDBT_Step* pStep = steps[stepNo];
535
pStep->setContext(ctx);
537
BaseString::snprintf(buf, sizeof(buf), "step_%d", stepNo);
538
NdbThread* pThread = NdbThread_Create(runStep_C,
542
NDB_THREAD_PRIO_LOW);
543
threads.push_back(pThread);
546
void NDBT_TestCaseImpl1::waitSteps(){
547
NdbMutex_Lock(waitThreadsMutexPtr);
548
while(numStepsCompleted != steps.size())
549
NdbCondition_Wait(waitThreadsCondPtr,
550
waitThreadsMutexPtr);
552
unsigned completedSteps = 0;
554
for(i=0; i<steps.size(); i++){
555
if (results[i] != NORESULT){
557
if (results[i] == NDBT_OK)
563
assert(completedSteps == steps.size());
564
assert(completedSteps == numStepsCompleted);
566
NdbMutex_Unlock(waitThreadsMutexPtr);
568
for(i=0; i<steps.size();i++){
569
NdbThread_WaitFor(threads[i], &status);
570
NdbThread_Destroy(&threads[i]);
577
NDBT_TestCaseImpl1::getNoOfRunningSteps() const {
578
return steps.size() - getNoOfCompletedSteps();
582
NDBT_TestCaseImpl1::getNoOfCompletedSteps() const {
583
return numStepsCompleted;
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){
595
if(numStepsCompleted == steps.size()){
596
NdbCondition_Signal(waitThreadsCondPtr);
598
NdbMutex_Unlock(waitThreadsMutexPtr);
602
int NDBT_TestCase::execute(NDBT_Context* ctx){
605
ndbout << "- " << name << " started [" << ctx->suite->getDate()
610
// Copy test case properties to ctx
611
Properties::Iterator it(&props);
612
for(const char * key = it.first(); key != 0; key = it.next()){
615
const bool b = props.getTypeOf(key, &pt);
618
case PropertiesType_Uint32:{
620
props.get(key, &val);
621
ctx->setProperty(key, val);
624
case PropertiesType_char:{
626
props.get(key, &val);
627
ctx->setProperty(key, val);
635
// start timer so that we get a time even if
636
// test case consist only of initializer
639
if ((res = runInit(ctx)) == NDBT_OK){
640
// If initialiser is ok, run steps
644
// If steps is ok, run verifier
645
res = runVerifier(ctx);
653
// Always run finalizer to clean up db
656
if (res == NDBT_OK) {
657
ndbout << "- " << name << " PASSED [" << ctx->suite->getDate() << "]"
661
ndbout << "- " << name << " FAILED [" << ctx->suite->getDate() << "]"
667
void NDBT_TestCase::startTimer(NDBT_Context* ctx){
671
void NDBT_TestCase::stopTimer(NDBT_Context* ctx){
675
void NDBT_TestCase::printTimer(NDBT_Context* ctx){
676
if (suite->timerIsOn()){
678
timer.printTestTimer(ctx->getNumLoops(), ctx->getNumRecords());
682
int NDBT_TestCaseImpl1::runInit(NDBT_Context* ctx){
684
for (unsigned i = 0; i < initializers.size(); i++){
685
initializers[i]->setContext(ctx);
686
res = initializers[i]->execute(ctx);
693
int NDBT_TestCaseImpl1::runSteps(NDBT_Context* ctx){
699
numStepsCompleted = 0;
701
for (i = 0; i < steps.size(); i++)
702
startStepInThread(i, ctx);
705
for(i = 0; i < steps.size(); i++)
706
if (results[i] != NDBT_OK)
711
int NDBT_TestCaseImpl1::runVerifier(NDBT_Context* ctx){
713
for (unsigned i = 0; i < verifiers.size(); i++){
714
verifiers[i]->setContext(ctx);
715
res = verifiers[i]->execute(ctx);
722
int NDBT_TestCaseImpl1::runFinal(NDBT_Context* ctx){
724
for (unsigned i = 0; i < finalizers.size(); i++){
725
finalizers[i]->setContext(ctx);
726
res = finalizers[i]->execute(ctx);
734
void NDBT_TestCaseImpl1::saveTestResult(const NdbDictionary::Table* ptab,
736
testResults.push_back(new NDBT_TestCaseResult(ptab->getName(),
738
timer.elapsedTime()));
741
void NDBT_TestCaseImpl1::printTestResult(){
744
ndbout << name<<endl;
746
for (unsigned i = 0; i < testResults.size(); i++){
747
NDBT_TestCaseResult* tcr = testResults[i];
749
if (tcr->getResult() == NDBT_OK)
751
else if (tcr->getResult() == NDBT_FAILED)
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());
766
NDBT_TestSuite::NDBT_TestSuite(const char* pname):name(pname){
769
numTestsExecuted = 0;
775
createAllTables = false;
776
temporaryTables = false;
780
NDBT_TestSuite::~NDBT_TestSuite(){
781
for(unsigned i=0; i<tests.size(); i++){
787
void NDBT_TestSuite::setCreateTable(bool _flag){
791
void NDBT_TestSuite::setRunAllTables(bool _flag){
794
void NDBT_TestSuite::setCreateAllTables(bool _flag){
795
createAllTables = _flag;
798
void NDBT_TestSuite::setTemporaryTables(bool val){
799
temporaryTables = val;
802
bool NDBT_TestSuite::getTemporaryTables() const {
803
return temporaryTables;
806
bool NDBT_TestSuite::timerIsOn(){
810
int NDBT_TestSuite::addTest(NDBT_TestCase* pTest){
811
assert(pTest != NULL);
812
tests.push_back(pTest);
817
g_create_hook(Ndb* ndb, NdbDictionary::Table& tab, int when, void* arg)
819
NDBT_TestSuite* ts = (NDBT_TestSuite*)arg;
821
return ts->createHook(ndb, tab, when);
825
int NDBT_TestSuite::executeAll(Ndb_cluster_connection& con,
826
const char* _testname){
828
if(tests.size() == 0)
830
Ndb ndb(&con, "TEST_DB");
833
int result = ndb.waitUntilReady(500); // 5 minutes
835
g_err << name <<": Ndb was not ready" << endl;
839
ndbout << name << " started [" << getDate() << "]" << endl;
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);
850
testSuiteTimer.doStop();
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)
860
tests[i]->initBeforeTest();
861
ctx = new NDBT_Context(con);
864
for (t=0; t < (Uint32)NDBT_Tables::getNumTables(); t++)
866
const NdbDictionary::Table* pTab = NDBT_Tables::getTable(t);
867
const NdbDictionary::Table* pTab2 = pDict->getTable(pTab->getName());
869
if(pTab2 != 0 && pDict->dropTable(pTab->getName()) != 0)
873
g_err << "ERROR0: Failed to drop table " << pTab->getName() << endl;
874
tests[i]->saveTestResult(pTab, FAILED_TO_CREATE);
878
if (NDBT_Tables::createTable(&ndb, pTab->getName(), false, false,
879
g_create_hook, this) != 0) {
882
g_err << "ERROR1: Failed to create table " << pTab->getName()
883
<< pDict->getNdbError() << endl;
884
tests[i]->saveTestResult(pTab, FAILED_TO_CREATE);
887
pTab2 = pDict->getTable(pTab->getName());
892
ctx->setNumRecords(records);
893
ctx->setNumLoops(loops);
894
if(remote_mgm != NULL)
895
ctx->setRemoteMgm(remote_mgm);
898
const NdbDictionary::Table** tables= ctx->getTables();
900
result = tests[i]->execute(ctx);
901
tests[i]->saveTestResult(tables[0], result);
902
if (result != NDBT_OK)
908
if(result == NDBT_OK)
910
for(t = 0; tables[t] != 0; t++)
912
pDict->dropTable(tables[t]->getName());
919
return reportAllTables(_testname);
923
NDBT_TestSuite::executeOne(Ndb_cluster_connection& con,
924
const char* _tabname, const char* _testname){
926
if(tests.size() == 0)
928
Ndb ndb(&con, "TEST_DB");
931
int result = ndb.waitUntilReady(300); // 5 minutes
933
g_err << name <<": Ndb was not ready" << endl;
937
ndbout << name << " started [" << getDate() << "]" << endl;
939
const NdbDictionary::Table* ptab = NDBT_Tables::getTable(_tabname);
943
ndbout << "|- " << ptab->getName() << endl;
945
execute(con, &ndb, ptab, _testname);
947
if (numTestsFail > 0){
955
NDBT_TestSuite::executeOneCtx(Ndb_cluster_connection& con,
956
const NdbDictionary::Table *ptab, const char* _testname){
958
testSuiteTimer.doStart();
961
if(tests.size() == 0)
964
Ndb ndb(&con, "TEST_DB");
967
int result = ndb.waitUntilReady(300); // 5 minutes
969
g_err << name <<": Ndb was not ready" << endl;
973
ndbout << name << " started [" << getDate() << "]" << endl;
974
ndbout << "|- " << ptab->getName() << endl;
976
for (unsigned t = 0; t < tests.size(); t++){
978
if (_testname != NULL &&
979
strcasecmp(tests[t]->getName(), _testname) != 0)
982
tests[t]->initBeforeTest();
984
ctx = new NDBT_Context(con);
986
ctx->setNumRecords(records);
987
ctx->setNumLoops(loops);
988
if(remote_mgm != NULL)
989
ctx->setRemoteMgm(remote_mgm);
992
result = tests[t]->execute(ctx);
993
if (result != NDBT_OK)
1002
if (numTestsFail > 0)
1006
testSuiteTimer.doStop();
1007
int res = report(_testname);
1008
return NDBT_ProgramExit(res);
1012
NDBT_TestSuite::createHook(Ndb* ndb, NdbDictionary::Table& tab, int when)
1017
for (int i = 0; i < tab.getNoOfColumns(); i++)
1019
NdbDictionary::Column* col = tab.getColumn(i);
1020
if (! col->getPrimaryKey())
1022
col->setStorageType(NdbDictionary::Column::StorageTypeDisk);
1026
else if (temporaryTables)
1028
tab.setTemporary(true);
1029
tab.setLogging(false);
1032
if (tsname != NULL) {
1033
tab.setTablespaceName(tsname);
1039
void NDBT_TestSuite::execute(Ndb_cluster_connection& con,
1040
Ndb* ndb, const NdbDictionary::Table* pTab,
1041
const char* _testname){
1044
for (unsigned t = 0; t < tests.size(); t++){
1046
if (_testname != NULL &&
1047
strcasecmp(tests[t]->getName(), _testname) != 0)
1050
if (tests[t]->m_all_tables && tests[t]->m_has_run)
1055
if (tests[t]->isVerify(pTab) == false) {
1059
tests[t]->initBeforeTest();
1061
NdbDictionary::Dictionary* pDict = ndb->getDictionary();
1062
const NdbDictionary::Table* pTab2 = pDict->getTable(pTab->getName());
1063
if (createTable == true){
1065
if(pTab2 != 0 && pDict->dropTable(pTab->getName()) != 0){
1068
g_err << "ERROR0: Failed to drop table " << pTab->getName() << endl;
1069
tests[t]->saveTestResult(pTab, FAILED_TO_CREATE);
1073
if (NDBT_Tables::createTable(ndb, pTab->getName(), false, false,
1074
g_create_hook, this) != 0) {
1077
g_err << "ERROR1: Failed to create table " << pTab->getName()
1078
<< pDict->getNdbError() << endl;
1079
tests[t]->saveTestResult(pTab, FAILED_TO_CREATE);
1082
pTab2 = pDict->getTable(pTab->getName());
1087
ctx = new NDBT_Context(con);
1089
ctx->setNumRecords(records);
1090
ctx->setNumLoops(loops);
1091
if(remote_mgm != NULL)
1092
ctx->setRemoteMgm(remote_mgm);
1093
ctx->setSuite(this);
1095
result = tests[t]->execute(ctx);
1096
tests[t]->saveTestResult(pTab, result);
1097
if (result != NDBT_OK)
1103
if (result == NDBT_OK && createTable == true && createAllTables == false){
1104
pDict->dropTable(pTab->getName());
1107
tests[t]->m_has_run = true;
1117
NDBT_TestSuite::report(const char* _tcname){
1119
ndbout << "Completed " << name << " [" << getDate() << "]" << endl;
1120
printTestCaseSummary(_tcname);
1121
ndbout << numTestsExecuted << " test(s) executed" << endl;
1122
ndbout << numTestsOk << " test(s) OK"
1124
if(numTestsFail > 0)
1125
ndbout << numTestsFail << " test(s) failed"
1127
testSuiteTimer.printTotalTime();
1128
if (numTestsFail > 0 || numTestsExecuted == 0){
1129
result = NDBT_FAILED;
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)
1143
tests[t]->printTestResult();
1145
ndbout << "==========================================" << endl;
1148
int NDBT_TestSuite::reportAllTables(const char* _testname){
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) <<"%)"
1157
if(numTestsFail > 0)
1158
ndbout << numTestsFail << " test(s) failed("
1159
<<(int)(((float)numTestsFail/totalNumTests)*100.0) <<"%)"
1161
testSuiteTimer.printTotalTime();
1162
if (numTestsExecuted > 0){
1163
if (numTestsFail > 0){
1164
result = NDBT_FAILED;
1169
result = NDBT_FAILED;
1175
OPT_INTERACTIVE = NDB_STD_OPTIONS_LAST,
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;
1194
static struct my_option my_long_options[] =
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}
1231
extern int global_flag_skip_invalidate_cache;
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);
1241
int NDBT_TestSuite::execute(int argc, const char** argv){
1242
int res = NDBT_FAILED;
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)
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
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
1263
char **_argv= (char **)argv;
1266
my_progname= _argv[0];
1268
const char *load_default_groups[]= { "mysql_cluster",0 };
1269
load_defaults("my",load_default_groups,&argc,&_argv);
1273
opt_debug= "d:t:i:F:L";
1275
if ((ho_error=handle_options(&argc, &_argv, my_long_options,
1276
ndb_std_get_one_option)))
1279
return NDBT_ProgramExit(NDBT_WRONGARGS);
1282
if (opt_print == true){
1283
printExecutionTree();
1287
if (opt_print_html == true){
1288
printExecutionTreeHTML();
1292
if (opt_print_cases == true){
1298
setOutputLevel(2); // Show g_info
1300
setOutputLevel(0); // Show only g_err ?
1302
remote_mgm = opt_remote_mgm;
1303
records = opt_records;
1307
Ndb_cluster_connection con;
1308
if(con.connect(12, 5, 1))
1310
return NDBT_ProgramExit(NDBT_FAILED);
1315
opt_seed = NdbTick_CurrentMillisecond();
1317
ndbout_c("random seed: %u", opt_seed);
1321
global_flag_skip_invalidate_cache = 1;
1324
Ndb ndb(&con, "TEST_DB");
1326
if (ndb.waitUntilReady(500)){
1327
g_err << "Ndb was not ready" << endl;
1328
return NDBT_ProgramExit(NDBT_FAILED);
1330
NdbDictionary::Dictionary* pDict = ndb.getDictionary();
1332
int num_tables= argc;
1334
num_tables = NDBT_Tables::getNumTables();
1336
for(int i = 0; i<num_tables; i++)
1339
m_tables_in_test.push_back(NDBT_Tables::getTable(i)->getName());
1341
m_tables_in_test.push_back(_argv[i]);
1342
if (createAllTables == true)
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)
1348
g_err << "ERROR0: Failed to drop table " << tab_name
1349
<< pDict->getNdbError() << endl;
1350
return NDBT_ProgramExit(NDBT_FAILED);
1352
if(NDBT_Tables::createTable(&ndb, tab_name) != 0)
1354
g_err << "ERROR1: Failed to create table " << tab_name
1355
<< pDict->getNdbError() << endl;
1356
return NDBT_ProgramExit(NDBT_FAILED);
1363
// No table specified
1364
res = executeAll(con, opt_testname);
1366
testSuiteTimer.doStart();
1367
for(int i = 0; i<argc; i++){
1368
executeOne(con, _argv[i], opt_testname);
1370
testSuiteTimer.doStop();
1371
res = report(opt_testname);
1374
if (res == NDBT_OK && createAllTables == true)
1376
Ndb ndb(&con, "TEST_DB");
1378
if (ndb.waitUntilReady(500)){
1379
g_err << "Ndb was not ready" << endl;
1380
return NDBT_ProgramExit(NDBT_FAILED);
1382
NdbDictionary::Dictionary* pDict = ndb.getDictionary();
1383
for(unsigned i = 0; i<m_tables_in_test.size(); i++)
1385
pDict->dropTable(m_tables_in_test[i].c_str());
1389
return NDBT_ProgramExit(res);
1394
void NDBT_TestSuite::printExecutionTree(){
1395
ndbout << "Testsuite: " << name << endl;
1396
for (unsigned t = 0; t < tests.size(); t++){
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();
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;
1421
const char* NDBT_TestSuite::getDate(){
1422
static char theTime[128];
1425
now = time((time_t*)NULL);
1427
tm_now = localtime(&now);
1429
tm_now = gmtime(&now);
1432
BaseString::snprintf(theTime, 128,
1433
"%d-%.2d-%.2d %.2d:%.2d:%.2d",
1434
tm_now->tm_year + 1900,
1444
void NDBT_TestCaseImpl1::printHTML(){
1446
ndbout << "<tr><td> </td>" << endl;
1447
ndbout << "<td name=tc>" << endl << name << "</td><td width=70%>"
1448
<< comment << "</td></tr>" << endl;
1451
void NDBT_TestCaseImpl1::print(){
1452
ndbout << "Test case: " << name << endl;
1453
ndbout << "Description: "<< comment << endl;
1455
ndbout << "Parameters: " << endl;
1457
Properties::Iterator it(&props);
1458
for(const char * key = it.first(); key != 0; key = it.next()){
1460
const bool b = props.getTypeOf(key, &pt);
1463
case PropertiesType_Uint32:{
1465
props.get(key, &val);
1466
ndbout << " " << key << ": " << val << endl;
1469
case PropertiesType_char:{
1471
props.get(key, &val);
1472
ndbout << " " << key << ": " << val << endl;
1480
for(i=0; i<initializers.size(); i++){
1481
ndbout << "Initializers[" << i << "]: " << endl;
1482
initializers[i]->print();
1484
for(i=0; i<steps.size(); i++){
1485
ndbout << "Step[" << i << "]: " << endl;
1488
for(i=0; i<verifiers.size(); i++){
1489
ndbout << "Verifier[" << i << "]: " << endl;
1490
verifiers[i]->print();
1492
for(i=0; i<finalizers.size(); i++){
1493
ndbout << "Finalizer[" << i << "]: " << endl;
1494
finalizers[i]->print();
1499
void NDBT_Step::print(){
1500
ndbout << " "<< name << endl;
1505
NDBT_Context::sync_down(const char * key){
1506
Uint32 threads = getProperty(key, (unsigned)0);
1513
NDBT_Context::sync_up_and_wait(const char * key, Uint32 value){
1514
setProperty(key, value);
1515
getPropertyWait(key, (unsigned)0);
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*>;