NDBT_Test.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:28k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2003 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. #include <ndb_global.h>
  14. #include "NDBT.hpp"
  15. #include "NDBT_Test.hpp"
  16. #include <PortDefs.h>
  17. #include <getarg.h>
  18. #include <time.h>
  19. // No verbose outxput
  20. NDBT_Context::NDBT_Context(){
  21.   tab = NULL;
  22.   suite = NULL;
  23.   testcase = NULL;
  24.   ndb = NULL;
  25.   records = 1;
  26.   loops = 1;
  27.   stopped = false;
  28.   remote_mgm ="";
  29.   propertyMutexPtr = NdbMutex_Create();
  30.   propertyCondPtr = NdbCondition_Create();
  31. }
  32.  
  33. char * NDBT_Context::getRemoteMgm() const {
  34.   return remote_mgm;
  35. void NDBT_Context::setRemoteMgm(char * mgm) {
  36.   remote_mgm = strdup(mgm);
  37. NDBT_Context::~NDBT_Context(){
  38.   NdbCondition_Destroy(propertyCondPtr);
  39.   NdbMutex_Destroy(propertyMutexPtr);
  40. }
  41. const NdbDictionary::Table* NDBT_Context::getTab(){
  42.   assert(tab != NULL);
  43.   return tab;
  44. }
  45. NDBT_TestSuite* NDBT_Context::getSuite(){ 
  46.   assert(suite != NULL);
  47.   return suite;
  48. }
  49. NDBT_TestCase* NDBT_Context::getCase(){ 
  50.   assert(testcase != NULL);
  51.   return testcase;
  52. }
  53. int NDBT_Context::getNumRecords() const{ 
  54.   return records;   
  55. }
  56. int NDBT_Context::getNumLoops() const{ 
  57.   return loops;
  58. }
  59. int NDBT_Context::getNoOfRunningSteps() const {
  60.   return testcase->getNoOfRunningSteps();
  61.   
  62. }
  63. int NDBT_Context::getNoOfCompletedSteps() const {
  64.   return testcase->getNoOfCompletedSteps();
  65. }
  66. Uint32 NDBT_Context::getProperty(const char* _name, Uint32 _default){ 
  67.   Uint32 val;
  68.   NdbMutex_Lock(propertyMutexPtr);
  69.   if(!props.get(_name, &val))
  70.     val = _default;
  71.   NdbMutex_Unlock(propertyMutexPtr);
  72.   return val;
  73. }
  74. bool NDBT_Context::getPropertyWait(const char* _name, Uint32 _waitVal){ 
  75.   bool result;
  76.   NdbMutex_Lock(propertyMutexPtr);
  77.   Uint32 val =! _waitVal;
  78.   
  79.   while((!props.get(_name, &val) || (props.get(_name, &val) && val != _waitVal)) &&  
  80. !stopped)
  81.     NdbCondition_Wait(propertyCondPtr,
  82.       propertyMutexPtr);
  83.   result = (val == _waitVal);
  84.   NdbMutex_Unlock(propertyMutexPtr);
  85.   return stopped;
  86. }
  87. const char* NDBT_Context::getProperty(const char* _name, const char* _default){ 
  88.   const char* val;
  89.   NdbMutex_Lock(propertyMutexPtr);
  90.   if(!props.get(_name, &val))
  91.     val = _default;
  92.   NdbMutex_Unlock(propertyMutexPtr);
  93.   return val;
  94. }
  95. const char* NDBT_Context::getPropertyWait(const char* _name, const char* _waitVal){ 
  96.   const char* val;
  97.   NdbMutex_Lock(propertyMutexPtr);
  98.   while(!props.get(_name, &val) && (strcmp(val, _waitVal)==0))
  99.     NdbCondition_Wait(propertyCondPtr,
  100.       propertyMutexPtr);
  101.   NdbMutex_Unlock(propertyMutexPtr);
  102.   return val;
  103. }
  104. void  NDBT_Context::setProperty(const char* _name, Uint32 _val){ 
  105.   NdbMutex_Lock(propertyMutexPtr);
  106.   const bool b = props.put(_name, _val, true);
  107.   assert(b == true);
  108.   NdbMutex_Unlock(propertyMutexPtr);
  109. }
  110. void
  111. NDBT_Context::decProperty(const char * name){
  112.   NdbMutex_Lock(propertyMutexPtr);
  113.   Uint32 val = 0;
  114.   if(props.get(name, &val)){
  115.     assert(val > 0);
  116.     props.put(name, (val - 1), true);
  117.   }
  118.   NdbCondition_Broadcast(propertyCondPtr);
  119.   NdbMutex_Unlock(propertyMutexPtr);
  120. }
  121. void
  122. NDBT_Context::incProperty(const char * name){
  123.   NdbMutex_Lock(propertyMutexPtr);
  124.   Uint32 val = 0;
  125.   props.get(name, &val);
  126.   props.put(name, (val + 1), true);
  127.   NdbCondition_Broadcast(propertyCondPtr);
  128.   NdbMutex_Unlock(propertyMutexPtr);
  129. }
  130. void  NDBT_Context::setProperty(const char* _name, const char* _val){ 
  131.   NdbMutex_Lock(propertyMutexPtr);
  132.   const bool b = props.put(_name, _val);
  133.   assert(b == true);
  134.   NdbMutex_Unlock(propertyMutexPtr);
  135. }
  136. void NDBT_Context::stopTest(){ 
  137.   NdbMutex_Lock(propertyMutexPtr);
  138.   g_info << "|- stopTest called" << endl;
  139.   stopped = true;
  140.   NdbCondition_Broadcast(propertyCondPtr);
  141.   NdbMutex_Unlock(propertyMutexPtr);
  142. }
  143. bool NDBT_Context::isTestStopped(){ 
  144.   NdbMutex_Lock(propertyMutexPtr);
  145.   bool val = stopped;
  146.   NdbMutex_Unlock(propertyMutexPtr);
  147.   return val;
  148. }
  149. void NDBT_Context::wait(){
  150.   NdbMutex_Lock(propertyMutexPtr);
  151.   NdbCondition_Wait(propertyCondPtr,
  152.     propertyMutexPtr);
  153.   NdbMutex_Unlock(propertyMutexPtr);
  154. }
  155. void NDBT_Context::wait_timeout(int msec){
  156.   NdbMutex_Lock(propertyMutexPtr);
  157.   NdbCondition_WaitTimeout(propertyCondPtr,
  158.    propertyMutexPtr,
  159.    msec);
  160.   NdbMutex_Unlock(propertyMutexPtr);
  161. }
  162. void NDBT_Context::broadcast(){
  163.   NdbMutex_Lock(propertyMutexPtr);
  164.   NdbCondition_Broadcast(propertyCondPtr);
  165.   NdbMutex_Unlock(propertyMutexPtr);
  166. }
  167. Uint32 NDBT_Context::getDbProperty(const char*){ 
  168.   abort();
  169.   return 0;
  170. }
  171. bool NDBT_Context::setDbProperty(const char*, Uint32){ 
  172.   abort();
  173.   return true;
  174. }
  175. void NDBT_Context::setTab(const NdbDictionary::Table* ptab){ 
  176.   assert(ptab != NULL);
  177.   tab = ptab;
  178. }
  179. void NDBT_Context::setSuite(NDBT_TestSuite* psuite){ 
  180.   assert(psuite != NULL);
  181.   suite = psuite;
  182. }
  183. void NDBT_Context::setCase(NDBT_TestCase* pcase){ 
  184.   assert(pcase != NULL);
  185.   testcase = pcase;
  186. }
  187. void NDBT_Context::setNumRecords(int _records){ 
  188.   records = _records;
  189.   
  190. }
  191. void NDBT_Context::setNumLoops(int _loops){ 
  192.   loops = _loops;
  193. }
  194. NDBT_Step::NDBT_Step(NDBT_TestCase* ptest, const char* pname, 
  195.      NDBT_TESTFUNC* pfunc): name(pname){
  196.   assert(pfunc != NULL);
  197.   func = pfunc;
  198.   testcase = ptest;
  199.   step_no = -1;
  200. }
  201. int NDBT_Step::execute(NDBT_Context* ctx) {
  202.   assert(ctx != NULL);
  203.   int result;  
  204.   g_info << "  |- " << name << " started [" << ctx->suite->getDate() << "]" 
  205.  << endl;
  206.   
  207.   result = setUp();
  208.   if (result != NDBT_OK){
  209.     return result;
  210.   }
  211.   result = func(ctx, this);
  212.   if (result != NDBT_OK) {
  213.     g_err << "  |- " << name << " FAILED [" << ctx->suite->getDate() 
  214.    << "]" << endl;
  215.   }  
  216.    else {
  217.     g_info << "  |- " << name << " PASSED [" << ctx->suite->getDate() << "]"
  218.    << endl;
  219.   }
  220.   
  221.   tearDown();
  222.   
  223.   return result;
  224. }
  225. void NDBT_Step::setContext(NDBT_Context* pctx){
  226.   assert(pctx != NULL);
  227.   m_ctx = pctx;
  228. }
  229. NDBT_Context* NDBT_Step::getContext(){
  230.   assert(m_ctx != NULL);
  231.   return m_ctx;
  232. }
  233. NDBT_NdbApiStep::NDBT_NdbApiStep(NDBT_TestCase* ptest, 
  234.    const char* pname, 
  235.    NDBT_TESTFUNC* pfunc)
  236.   : NDBT_Step(ptest, pname, pfunc),
  237.     ndb(NULL) {
  238. }
  239. int
  240. NDBT_NdbApiStep::setUp(){
  241.   ndb = new Ndb( "TEST_DB" );
  242.   ndb->init(1024);
  243.   int result = ndb->waitUntilReady(300); // 5 minutes
  244.   if (result != 0){
  245.     g_err << name << ": Ndb was not ready" << endl;
  246.     return NDBT_FAILED;
  247.   }
  248.   return NDBT_OK;
  249. }
  250. void 
  251. NDBT_NdbApiStep::tearDown(){
  252.   delete ndb;
  253.   ndb = NULL;
  254. }
  255. Ndb* NDBT_NdbApiStep::getNdb(){ 
  256.   assert(ndb != NULL);
  257.   return ndb;
  258. }
  259. NDBT_ParallelStep::NDBT_ParallelStep(NDBT_TestCase* ptest, 
  260.      const char* pname, 
  261.      NDBT_TESTFUNC* pfunc)
  262.   : NDBT_NdbApiStep(ptest, pname, pfunc) {
  263. }
  264. NDBT_Verifier::NDBT_Verifier(NDBT_TestCase* ptest, 
  265.      const char* pname, 
  266.      NDBT_TESTFUNC* pfunc)
  267.   : NDBT_NdbApiStep(ptest, pname, pfunc) {
  268. }
  269. NDBT_Initializer::NDBT_Initializer(NDBT_TestCase* ptest, 
  270.    const char* pname, 
  271.    NDBT_TESTFUNC* pfunc)
  272.   : NDBT_NdbApiStep(ptest, pname, pfunc) {
  273. }
  274. NDBT_Finalizer::NDBT_Finalizer(NDBT_TestCase* ptest, 
  275.        const char* pname, 
  276.        NDBT_TESTFUNC* pfunc)
  277.   : NDBT_NdbApiStep(ptest, pname, pfunc) {
  278. }
  279. NDBT_TestCase::NDBT_TestCase(NDBT_TestSuite* psuite, 
  280.      const char* pname, 
  281.      const char* pcomment) : 
  282.   name(strdup(pname)) ,
  283.   comment(strdup(pcomment)),
  284.   suite(psuite)
  285. {
  286.   _name.assign(pname);
  287.   _comment.assign(pcomment);
  288.   name= _name.c_str();
  289.   comment= _comment.c_str();
  290.   assert(suite != NULL);
  291. }
  292. NDBT_TestCaseImpl1::NDBT_TestCaseImpl1(NDBT_TestSuite* psuite, 
  293.        const char* pname, 
  294.        const char* pcomment) : 
  295.   NDBT_TestCase(psuite, pname, pcomment){
  296.   numStepsOk = 0;
  297.   numStepsFail = 0;
  298.   numStepsCompleted = 0;
  299.   waitThreadsMutexPtr = NdbMutex_Create();
  300.   waitThreadsCondPtr = NdbCondition_Create();
  301. }
  302. NDBT_TestCaseImpl1::~NDBT_TestCaseImpl1(){
  303.   NdbCondition_Destroy(waitThreadsCondPtr);
  304.   NdbMutex_Destroy(waitThreadsMutexPtr);
  305.   size_t i;
  306.   for(i = 0; i < initializers.size();  i++)
  307.     delete initializers[i];
  308.   initializers.clear();
  309.   for(i = 0; i < verifiers.size();  i++)
  310.     delete verifiers[i];
  311.   verifiers.clear();
  312.   for(i = 0; i < finalizers.size();  i++)
  313.     delete finalizers[i];
  314.   finalizers.clear();
  315.   for(i = 0; i < steps.size();  i++)
  316.     delete steps[i];
  317.   steps.clear();
  318.   results.clear();
  319.   for(i = 0; i < testTables.size();  i++)
  320.     delete testTables[i];
  321.   testTables.clear();
  322.   for(i = 0; i < testResults.size();  i++)
  323.     delete testResults[i];
  324.   testResults.clear();
  325. }
  326. int NDBT_TestCaseImpl1::addStep(NDBT_Step* pStep){
  327.   assert(pStep != NULL);
  328.   steps.push_back(pStep);
  329.   pStep->setStepNo(steps.size());
  330.   int res = NORESULT;
  331.   results.push_back(res);
  332.   return 0;
  333. }
  334. int NDBT_TestCaseImpl1::addVerifier(NDBT_Verifier* pVerifier){
  335.   assert(pVerifier != NULL);
  336.   verifiers.push_back(pVerifier);
  337.   return 0;
  338. }
  339. int NDBT_TestCaseImpl1::addInitializer(NDBT_Initializer* pInitializer){
  340.   assert(pInitializer != NULL);
  341.   initializers.push_back(pInitializer);
  342.   return 0;
  343. }
  344. int NDBT_TestCaseImpl1::addFinalizer(NDBT_Finalizer* pFinalizer){
  345.   assert(pFinalizer != NULL);
  346.   finalizers.push_back(pFinalizer);
  347.   return 0;
  348. }
  349. void NDBT_TestCaseImpl1::addTable(const char* tableName, bool isVerify) {
  350.   assert(tableName != NULL);
  351.   const NdbDictionary::Table* pTable = NDBT_Tables::getTable(tableName);
  352.   assert(pTable != NULL);
  353.   testTables.push_back(pTable);
  354.   isVerifyTables = isVerify;
  355. }
  356. bool NDBT_TestCaseImpl1::tableExists(NdbDictionary::Table* aTable) {
  357.   for (unsigned i = 0; i < testTables.size(); i++) {
  358.     if (strcasecmp(testTables[i]->getName(), aTable->getName()) == 0) {
  359.       return true;
  360.     }
  361.   }
  362.   return false;
  363. }
  364. bool NDBT_TestCaseImpl1::isVerify(const NdbDictionary::Table* aTable) {
  365.   if (testTables.size() > 0) {
  366.     int found = false;
  367.     // OK, we either exclude or include this table in the actual test
  368.     for (unsigned i = 0; i < testTables.size(); i++) {
  369.       if (strcasecmp(testTables[i]->getName(), aTable->getName()) == 0) {
  370. // Found one!
  371. if (isVerifyTables) {
  372.   // Found one to test
  373.   found = true;
  374. } else {
  375.   // Skip this one!
  376.   found = false;
  377. }
  378.       }
  379.     } // for
  380.     return found;
  381.   } else {
  382.     // No included or excluded test tables, i.e., all tables should be      
  383.     // tested
  384.     return true;
  385.   }
  386.   return true;
  387. }
  388. void  NDBT_TestCase::setProperty(const char* _name, Uint32 _val){ 
  389.   const bool b = props.put(_name, _val);
  390.   assert(b == true);
  391. }
  392. void  NDBT_TestCase::setProperty(const char* _name, const char* _val){ 
  393.   const bool b = props.put(_name, _val);
  394.   assert(b == true);
  395. }
  396. void *
  397. runStep(void * s){
  398.   assert(s != NULL);
  399.   NDBT_Step* pStep = (NDBT_Step*)s;
  400.   NDBT_Context* ctx = pStep->getContext();
  401.   assert(ctx != NULL);
  402.    // Execute function
  403.   int res = pStep->execute(ctx);
  404.   if(res != NDBT_OK){
  405.     ctx->stopTest();
  406.   }
  407.   // Report 
  408.   NDBT_TestCaseImpl1* pCase = (NDBT_TestCaseImpl1*)ctx->getCase();
  409.   assert(pCase != NULL);
  410.   pCase->reportStepResult(pStep, res);
  411.   return NULL;
  412. }
  413. extern "C" 
  414. void *
  415. runStep_C(void * s)
  416. {
  417.   runStep(s);
  418.   return NULL;
  419. }
  420. void NDBT_TestCaseImpl1::startStepInThread(int stepNo, NDBT_Context* ctx){  
  421.   NDBT_Step* pStep = steps[stepNo];
  422.   pStep->setContext(ctx);
  423.   char buf[16];
  424.   BaseString::snprintf(buf, sizeof(buf), "step_%d", stepNo);
  425.   NdbThread* pThread = NdbThread_Create(runStep_C,
  426. (void**)pStep,
  427. 65535,
  428. buf, 
  429. NDB_THREAD_PRIO_LOW);
  430.   threads.push_back(pThread);
  431. }
  432. void NDBT_TestCaseImpl1::waitSteps(){
  433.   NdbMutex_Lock(waitThreadsMutexPtr);
  434.   while(numStepsCompleted != steps.size())
  435.     NdbCondition_Wait(waitThreadsCondPtr,
  436.      waitThreadsMutexPtr);
  437.   unsigned completedSteps = 0;  
  438.   unsigned i;
  439.   for(i=0; i<steps.size(); i++){
  440.     if (results[i] != NORESULT){
  441.       completedSteps++;
  442.       if (results[i] == NDBT_OK)
  443. numStepsOk++;
  444.       else
  445. numStepsFail++;
  446.     }       
  447.   }
  448.   assert(completedSteps == steps.size());
  449.   assert(completedSteps == numStepsCompleted);
  450.   
  451.   NdbMutex_Unlock(waitThreadsMutexPtr);
  452.   void *status;
  453.   for(i=0; i<steps.size();i++){
  454.     NdbThread_WaitFor(threads[i], &status);
  455.     NdbThread_Destroy(&threads[i]);   
  456.   }
  457.   threads.clear();
  458. }
  459. int
  460. NDBT_TestCaseImpl1::getNoOfRunningSteps() const {
  461.   return steps.size() - getNoOfCompletedSteps();
  462. }
  463. int 
  464. NDBT_TestCaseImpl1::getNoOfCompletedSteps() const {
  465.   return numStepsCompleted;
  466. }
  467. void NDBT_TestCaseImpl1::reportStepResult(const NDBT_Step* pStep, int result){
  468.   NdbMutex_Lock(waitThreadsMutexPtr);
  469.   assert(pStep != NULL);
  470.   for (unsigned i = 0; i < steps.size(); i++){
  471.     if(steps[i] != NULL && steps[i] == pStep){
  472.       results[i] = result;
  473.       numStepsCompleted++;
  474.     }
  475.   }
  476.   if(numStepsCompleted == steps.size()){
  477.     NdbCondition_Signal(waitThreadsCondPtr);
  478.   }
  479.   NdbMutex_Unlock(waitThreadsMutexPtr);
  480. }
  481. int NDBT_TestCase::execute(NDBT_Context* ctx){
  482.   int res;
  483.   ndbout << "- " << name << " started [" << ctx->suite->getDate()
  484.  << "]" << endl;
  485.   ctx->setCase(this);
  486.   // Copy test case properties to ctx
  487.   Properties::Iterator it(&props);
  488.   for(const char * key = it.first(); key != 0; key = it.next()){
  489.     PropertiesType pt;
  490.     const bool b = props.getTypeOf(key, &pt);
  491.     assert(b == true);
  492.     switch(pt){
  493.     case PropertiesType_Uint32:{
  494.       Uint32 val;
  495.       props.get(key, &val);
  496.       ctx->setProperty(key, val);
  497.       break;
  498.     }
  499.     case PropertiesType_char:{
  500.       const char * val;
  501.       props.get(key, &val);
  502.       ctx->setProperty(key, val);
  503.       break;
  504.     }
  505.     default:
  506.       abort();
  507.     }
  508.   }
  509.   // start timer so that we get a time even if
  510.   // test case consist only of initializer
  511.   startTimer(ctx);
  512.   
  513.   if ((res = runInit(ctx)) == NDBT_OK){
  514.     // If initialiser is ok, run steps
  515.     
  516.     res = runSteps(ctx);
  517.     if (res == NDBT_OK){
  518.       // If steps is ok, run verifier
  519.       res = runVerifier(ctx);
  520.     } 
  521.     
  522.   }
  523.   stopTimer(ctx);
  524.   printTimer(ctx);
  525.   // Always run finalizer to clean up db
  526.   runFinal(ctx); 
  527.   if (res == NDBT_OK) {
  528.     ndbout << "- " << name << " PASSED [" << ctx->suite->getDate() << "]" 
  529.    << endl;
  530.   }
  531.   else {
  532.     ndbout << "- " << name << " FAILED [" << ctx->suite->getDate() << "]" 
  533.    << endl;
  534.   }
  535.   return res;
  536. }
  537. void NDBT_TestCase::startTimer(NDBT_Context* ctx){
  538.   timer.doStart();
  539. }
  540. void NDBT_TestCase::stopTimer(NDBT_Context* ctx){
  541.   timer.doStop();
  542. }
  543. void NDBT_TestCase::printTimer(NDBT_Context* ctx){
  544.   if (suite->timerIsOn()){
  545.     g_info << endl; 
  546.     timer.printTestTimer(ctx->getNumLoops(), ctx->getNumRecords());
  547.   }
  548. }
  549. int NDBT_TestCaseImpl1::runInit(NDBT_Context* ctx){
  550.   int res = NDBT_OK;
  551.   for (unsigned i = 0; i < initializers.size(); i++){
  552.     initializers[i]->setContext(ctx);
  553.     res = initializers[i]->execute(ctx);
  554.     if (res != NDBT_OK)
  555.       break;
  556.   }
  557.   return res;
  558. }
  559. int NDBT_TestCaseImpl1::runSteps(NDBT_Context* ctx){
  560.   int res = NDBT_OK;
  561.   // Reset variables
  562.   numStepsOk = 0;
  563.   numStepsFail = 0;
  564.   numStepsCompleted = 0;
  565.   unsigned i;
  566.   for (i = 0; i < steps.size(); i++)
  567.     startStepInThread(i, ctx);
  568.   waitSteps();
  569.   for(i = 0; i < steps.size(); i++)
  570.     if (results[i] != NDBT_OK)
  571.       res = NDBT_FAILED;
  572.   return res;
  573. }
  574. int NDBT_TestCaseImpl1::runVerifier(NDBT_Context* ctx){
  575.   int res = NDBT_OK;
  576.   for (unsigned i = 0; i < verifiers.size(); i++){
  577.     verifiers[i]->setContext(ctx);
  578.     res = verifiers[i]->execute(ctx);
  579.     if (res != NDBT_OK)
  580.       break;
  581.   }
  582.   return res;
  583. }
  584. int NDBT_TestCaseImpl1::runFinal(NDBT_Context* ctx){
  585.   int res = NDBT_OK;
  586.   for (unsigned i = 0; i < finalizers.size(); i++){
  587.     finalizers[i]->setContext(ctx);
  588.     res = finalizers[i]->execute(ctx);
  589.     if (res != NDBT_OK)
  590.       break;
  591.   }
  592.   return res;
  593. }
  594. void NDBT_TestCaseImpl1::saveTestResult(const NdbDictionary::Table* ptab, 
  595. int result){
  596.   testResults.push_back(new NDBT_TestCaseResult(ptab->getName(), 
  597. result,
  598. timer.elapsedTime()));
  599. }
  600. void NDBT_TestCaseImpl1::printTestResult(){
  601.   char buf[255];
  602.   ndbout << name<<endl;
  603.   for (unsigned i = 0; i < testResults.size(); i++){
  604.     NDBT_TestCaseResult* tcr = testResults[i];
  605.     const char* res;
  606.     if (tcr->getResult() == NDBT_OK)
  607.       res = "OK";
  608.     else if (tcr->getResult() == NDBT_FAILED)
  609.       res = "FAIL";
  610.     else if (tcr->getResult() == FAILED_TO_CREATE)
  611.       res = "FAILED TO CREATE TABLE";
  612.     else if (tcr->getResult() == FAILED_TO_DISCOVER)
  613.       res = "FAILED TO DISCOVER TABLE";
  614.     BaseString::snprintf(buf, 255," %-10s %-5s %-20s", tcr->getName(), res, tcr->getTimeStr());
  615.     ndbout << buf<<endl;    
  616.   }
  617. }
  618. NDBT_TestSuite::NDBT_TestSuite(const char* pname):name(pname){
  619.    numTestsOk = 0;
  620.    numTestsFail = 0;
  621.    numTestsExecuted = 0;
  622.    records = 0;
  623.    loops = 0;
  624.    createTable = true;
  625. }
  626. NDBT_TestSuite::~NDBT_TestSuite(){
  627.   for(unsigned i=0; i<tests.size(); i++){
  628.     delete tests[i];
  629.   }
  630.   tests.clear();
  631. }
  632. void NDBT_TestSuite::setCreateTable(bool _flag){
  633.   createTable = _flag;
  634. }
  635. bool NDBT_TestSuite::timerIsOn(){
  636.   return (timer != 0);
  637. }
  638. int NDBT_TestSuite::addTest(NDBT_TestCase* pTest){
  639.   assert(pTest != NULL);
  640.   tests.push_back(pTest);
  641.   return 0;
  642. }
  643. int NDBT_TestSuite::executeAll(const char* _testname){
  644.   if(tests.size() == 0)
  645.     return NDBT_FAILED;
  646.   Ndb ndb("TEST_DB");
  647.   ndb.init(1024);
  648.   int result = ndb.waitUntilReady(300); // 5 minutes
  649.   if (result != 0){
  650.     g_err << name <<": Ndb was not ready" << endl;
  651.     return NDBT_FAILED;
  652.   }
  653.   ndbout << name << " started [" << getDate() << "]" << endl;
  654.   testSuiteTimer.doStart();
  655.   for (int t=0; t < NDBT_Tables::getNumTables(); t++){
  656.     const NdbDictionary::Table* ptab = NDBT_Tables::getTable(t);
  657.     ndbout << "|- " << ptab->getName() << endl;
  658.     execute(&ndb, ptab, _testname);
  659.   }
  660.   testSuiteTimer.doStop();
  661.   return reportAllTables(_testname);
  662. }
  663. int 
  664. NDBT_TestSuite::executeOne(const char* _tabname, const char* _testname){
  665.   
  666.   if(tests.size() == 0)
  667.     return NDBT_FAILED;
  668.   Ndb ndb("TEST_DB");
  669.   ndb.init(1024);
  670.   int result = ndb.waitUntilReady(300); // 5 minutes
  671.   if (result != 0){
  672.     g_err << name <<": Ndb was not ready" << endl;
  673.     return NDBT_FAILED;
  674.   }
  675.   ndbout << name << " started [" << getDate() << "]" << endl;
  676.   const NdbDictionary::Table* ptab = NDBT_Tables::getTable(_tabname);
  677.   if (ptab == NULL)
  678.     return NDBT_FAILED;
  679.   ndbout << "|- " << ptab->getName() << endl;
  680.   execute(&ndb, ptab, _testname);
  681.   if (numTestsFail > 0){
  682.     return NDBT_FAILED;
  683.   }else{
  684.     return NDBT_OK;
  685.   }
  686. }
  687. void NDBT_TestSuite::execute(Ndb* ndb, const NdbDictionary::Table* pTab, 
  688.      const char* _testname){
  689.   int result; 
  690.  
  691.   for (unsigned t = 0; t < tests.size(); t++){
  692.     if (_testname != NULL && 
  693. strcasecmp(tests[t]->getName(), _testname) != 0)
  694.       continue;
  695.     if (tests[t]->isVerify(pTab) == false) {
  696.       continue;
  697.     }
  698.     tests[t]->initBeforeTest();
  699.     NdbDictionary::Dictionary* pDict = ndb->getDictionary();
  700.     const NdbDictionary::Table* pTab2 = pDict->getTable(pTab->getName());
  701.     if (createTable == true){
  702.       if(pTab2 != 0 && pDict->dropTable(pTab->getName()) != 0){
  703. numTestsFail++;
  704. numTestsExecuted++;
  705. g_err << "ERROR0: Failed to drop table " << pTab->getName() << endl;
  706. tests[t]->saveTestResult(pTab, FAILED_TO_CREATE);
  707. continue;
  708.       }
  709.       
  710.       if(NDBT_Tables::createTable(ndb, pTab->getName()) != 0){
  711. numTestsFail++;
  712. numTestsExecuted++;
  713. g_err << "ERROR1: Failed to create table " << pTab->getName()
  714.               << pDict->getNdbError() << endl;
  715. tests[t]->saveTestResult(pTab, FAILED_TO_CREATE);
  716. continue;
  717.       }
  718.       pTab2 = pDict->getTable(pTab->getName());
  719.     } else if(!pTab2) {
  720.       pTab2 = pTab;
  721.     } 
  722.     
  723.     ctx = new NDBT_Context();
  724.     ctx->setTab(pTab2);
  725.     ctx->setNumRecords(records);
  726.     ctx->setNumLoops(loops);
  727.     if(remote_mgm != NULL)
  728.       ctx->setRemoteMgm(remote_mgm);
  729.     ctx->setSuite(this);
  730.     result = tests[t]->execute(ctx);
  731.     tests[t]->saveTestResult(pTab, result);
  732.     if (result != NDBT_OK)
  733.       numTestsFail++;
  734.     else
  735.       numTestsOk++;
  736.     numTestsExecuted++;
  737.     if (result == NDBT_OK && createTable == true){
  738.       pDict->dropTable(pTab->getName());
  739.     }
  740.     
  741.     delete ctx;
  742.   }
  743. }
  744. int 
  745. NDBT_TestSuite::report(const char* _tcname){
  746.   int result;
  747.   ndbout << "Completed " << name << " [" << getDate() << "]" << endl;
  748.   printTestCaseSummary(_tcname);
  749.   ndbout << numTestsExecuted << " test(s) executed" << endl;
  750.   ndbout << numTestsOk << " test(s) OK" 
  751.  << endl;
  752.   if(numTestsFail > 0)
  753.     ndbout << numTestsFail << " test(s) failed"
  754.    << endl;
  755.   testSuiteTimer.printTotalTime();
  756.   if (numTestsFail > 0 || numTestsExecuted == 0){
  757.     result = NDBT_FAILED;
  758.   }else{
  759.     result = NDBT_OK;
  760.   }
  761.   return result;
  762. }
  763. void NDBT_TestSuite::printTestCaseSummary(const char* _tcname){
  764.   ndbout << "= SUMMARY OF TEST EXECUTION ==============" << endl;
  765.   for (unsigned t = 0; t < tests.size(); t++){
  766.     if (_tcname != NULL && 
  767. strcasecmp(tests[t]->getName(), _tcname) != 0)
  768.       continue;
  769.     tests[t]->printTestResult();
  770.   }
  771.   ndbout << "==========================================" << endl;
  772. }
  773. int NDBT_TestSuite::reportAllTables(const char* _testname){
  774.   int result;
  775.   ndbout << "Completed running test [" << getDate() << "]" << endl;
  776.   const int totalNumTests = numTestsExecuted;
  777.   printTestCaseSummary(_testname);
  778.   ndbout << numTestsExecuted<< " test(s) executed" << endl;
  779.   ndbout << numTestsOk << " test(s) OK("
  780.  <<(int)(((float)numTestsOk/totalNumTests)*100.0) <<"%)" 
  781.  << endl;
  782.   if(numTestsFail > 0)
  783.     ndbout << numTestsFail << " test(s) failed("
  784.    <<(int)(((float)numTestsFail/totalNumTests)*100.0) <<"%)" 
  785.    << endl;
  786.   testSuiteTimer.printTotalTime();
  787.   if (numTestsExecuted > 0){
  788.     if (numTestsFail > 0){
  789.       result = NDBT_FAILED;
  790.     }else{
  791.       result = NDBT_OK;
  792.     }
  793.   } else {
  794.     result = NDBT_FAILED;
  795.   }
  796.   return result;
  797. }
  798. int NDBT_TestSuite::execute(int argc, const char** argv){
  799.   int res = NDBT_FAILED;
  800.   /* Arguments:
  801.        Run only a subset of tests
  802.        -n testname Which test to run
  803.        Recommendations to test functions:
  804.        --records Number of records to use(default: 10000)
  805.        --loops Number of loops to execute in the test(default: 100)
  806.        Other parameters should:
  807.        * be calculated from the above two parameters 
  808.        * be divided into different test cases, ex. one testcase runs
  809.          with FragmentType = Single and another perfoms the same 
  810.          test with FragmentType = Large
  811.        * let the test case iterate over all/subset of appropriate parameters
  812.          ex. iterate over FragmentType = Single to FragmentType = AllLarge
  813.        Remeber that the intention is that it should be _easy_ to run 
  814.        a complete test suite without any greater knowledge of what 
  815.        should be tested ie. keep arguments at a minimum
  816.   */
  817.   int _records = 1000;
  818.   int _loops = 5;
  819.   int _timer = 0;
  820.   char * _remote_mgm =NULL;
  821.   char* _testname = NULL;
  822.   const char* _tabname = NULL;
  823.   int _print = false;
  824.   int _print_html = false;
  825.   int _print_cases = false;
  826.   int _verbose = false;
  827. #ifndef DBUG_OFF
  828.   const char *debug_option= 0;
  829. #endif
  830.   struct getargs args[] = {
  831.     { "print", '', arg_flag, &_print, "Print execution tree", "" },
  832.     { "print_html", '', arg_flag, &_print_html, "Print execution tree in html table format", "" },
  833.     { "print_cases", '', arg_flag, &_print_cases, "Print list of test cases", "" },
  834.     { "records", 'r', arg_integer, &_records, "Number of records", "records" },
  835.     { "loops", 'l', arg_integer, &_loops, "Number of loops", "loops" },
  836.     { "testname", 'n', arg_string, &_testname, "Name of test to run", "testname" },
  837.     { "remote_mgm", 'm', arg_string, &_remote_mgm, 
  838.       "host:port to mgmsrv of remote cluster", "host:port" },
  839.     { "timer", 't', arg_flag, &_timer, "Print execution time", "time" },
  840. #ifndef DBUG_OFF
  841.     { "debug", 0, arg_string, &debug_option,
  842.       "Specify debug options e.g. d:t:i:o,out.trace", "options" },
  843. #endif
  844.     { "verbose", 'v', arg_flag, &_verbose, "Print verbose status", "verbose" }
  845.   };
  846.   int num_args = sizeof(args) / sizeof(args[0]);
  847.   int optind = 0;
  848.   if(getarg(args, num_args, argc, argv, &optind)) {
  849.     arg_printusage(args, num_args, argv[0], "tabname1 tabname2 ... tabnameNn");
  850.     return NDBT_WRONGARGS;
  851.   }
  852. #ifndef DBUG_OFF
  853.   if (debug_option)
  854.     DBUG_PUSH(debug_option);
  855. #endif
  856.   // Check if table name is supplied
  857.   if (argv[optind] != NULL)
  858.     _tabname = argv[optind];
  859.   if (_print == true){
  860.     printExecutionTree();
  861.     return 0;
  862.   }
  863.   if (_print_html == true){
  864.     printExecutionTreeHTML();
  865.     return 0;
  866.   }
  867.   if (_print_cases == true){
  868.     printCases();
  869.     return NDBT_ProgramExit(NDBT_FAILED);
  870.   }
  871.   if (_verbose)
  872.     setOutputLevel(2); // Show g_info
  873.   else 
  874.    setOutputLevel(0); // Show only g_err ?
  875.   remote_mgm = _remote_mgm;
  876.   records = _records;
  877.   loops = _loops;
  878.   timer = _timer;
  879.   if(optind == argc){
  880.     // No table specified
  881.     res = executeAll(_testname);
  882.   } else {
  883.     testSuiteTimer.doStart(); 
  884.     Ndb ndb("TEST_DB"); ndb.init();
  885.     for(int i = optind; i<argc; i++){
  886.       executeOne(argv[i], _testname);
  887.     }
  888.     testSuiteTimer.doStop();
  889.     res = report(_testname);
  890.   }
  891.   
  892.   return NDBT_ProgramExit(res);
  893. }
  894.  
  895. void NDBT_TestSuite::printExecutionTree(){
  896.   ndbout << "Testsuite: " << name << endl;
  897.   for (unsigned t = 0; t < tests.size(); t++){
  898.     tests[t]->print();
  899.     ndbout << endl;
  900.   } 
  901. }
  902. void NDBT_TestSuite::printExecutionTreeHTML(){
  903.   ndbout << "<tr>" << endl;
  904.   ndbout << "<td><h3>" << name << "</h3></td>" << endl;
  905.   ndbout << "</tr>" << endl;
  906.   for (unsigned t = 0; t < tests.size(); t++){
  907.     tests[t]->printHTML();
  908.     ndbout << endl;
  909.   } 
  910. }
  911. void NDBT_TestSuite::printCases(){
  912.   ndbout << "# Testsuite: " << name << endl;
  913.   ndbout << "# Number of tests: " << tests.size() << endl; 
  914.   for (unsigned t = 0; t < tests.size(); t++){
  915.     ndbout << name << " -n " << tests[t]->getName() << endl;
  916.   } 
  917. }
  918. const char* NDBT_TestSuite::getDate(){
  919.   static char theTime[128];
  920.   struct tm* tm_now;
  921.   time_t now;
  922.   now = time((time_t*)NULL);
  923. #ifdef NDB_WIN32
  924.   tm_now = localtime(&now);
  925. #else
  926.   tm_now = gmtime(&now);
  927. #endif
  928.   
  929.   BaseString::snprintf(theTime, 128,
  930.    "%d-%.2d-%.2d %.2d:%.2d:%.2d",
  931.    tm_now->tm_year + 1900, 
  932.    tm_now->tm_mon + 1, 
  933.    tm_now->tm_mday,
  934.    tm_now->tm_hour,
  935.    tm_now->tm_min,
  936.    tm_now->tm_sec);
  937.   return theTime;
  938. }
  939. void NDBT_TestCaseImpl1::printHTML(){
  940.   ndbout << "<tr><td>&nbsp;</td>" << endl;
  941.   ndbout << "<td name=tc>" << endl << name << "</td><td width=70%>" 
  942.  << comment << "</td></tr>" << endl;  
  943. }
  944. void NDBT_TestCaseImpl1::print(){
  945.   ndbout << "Test case: " << name << endl;
  946.   ndbout << "Description: "<< comment << endl;
  947.   ndbout << "Parameters: " << endl;
  948.   Properties::Iterator it(&props);
  949.   for(const char * key = it.first(); key != 0; key = it.next()){
  950.     PropertiesType pt;
  951.     const bool b = props.getTypeOf(key, &pt);
  952.     assert(b == true);
  953.     switch(pt){
  954.     case PropertiesType_Uint32:{
  955.       Uint32 val;
  956.       props.get(key, &val);
  957.       ndbout << "      " << key << ": " << val << endl;
  958.       break;
  959.     }
  960.     case PropertiesType_char:{
  961.       const char * val;
  962.       props.get(key, &val);
  963.       ndbout << "    " << key << ": " << val << endl;
  964.       break;
  965.     }
  966.     default:
  967.       abort();
  968.     }  
  969.   }
  970.   unsigned i; 
  971.   for(i=0; i<initializers.size(); i++){
  972.     ndbout << "Initializers[" << i << "]: " << endl;
  973.     initializers[i]->print();
  974.   }
  975.   for(i=0; i<steps.size(); i++){
  976.     ndbout << "Step[" << i << "]: " << endl;
  977.     steps[i]->print();
  978.   }
  979.   for(i=0; i<verifiers.size(); i++){
  980.     ndbout << "Verifier[" << i << "]: " << endl;
  981.     verifiers[i]->print();
  982.   }
  983.   for(i=0; i<finalizers.size(); i++){
  984.     ndbout << "Finalizer[" << i << "]: " << endl;
  985.     finalizers[i]->print();
  986.   }
  987.       
  988. }
  989. void NDBT_Step::print(){
  990.   ndbout << "      "<< name << endl;
  991. }
  992. void
  993. NDBT_Context::sync_down(const char * key){
  994.   Uint32 threads = getProperty(key, (unsigned)0);
  995.   if(threads){
  996.     decProperty(key);
  997.   }
  998. }
  999. void
  1000. NDBT_Context::sync_up_and_wait(const char * key, Uint32 value){
  1001.   setProperty(key, value);
  1002.   getPropertyWait(key, (unsigned)0);
  1003. }
  1004. template class Vector<NDBT_TestCase*>;
  1005. template class Vector<NDBT_TestCaseResult*>;
  1006. template class Vector<NDBT_Step*>;
  1007. template class Vector<NdbThread*>;
  1008. template class Vector<NDBT_Verifier*>;
  1009. template class Vector<NDBT_Initializer*>;
  1010. template class Vector<NDBT_Finalizer*>;
  1011. template class Vector<const NdbDictionary::Table*>;