📄 ndbt_test.cpp
字号:
// start timer so that we get a time even if // test case consist only of initializer startTimer(ctx); if ((res = runInit(ctx)) == NDBT_OK){ // If initialiser is ok, run steps res = runSteps(ctx); if (res == NDBT_OK){ // If steps is ok, run verifier res = runVerifier(ctx); } } stopTimer(ctx); printTimer(ctx); // Always run finalizer to clean up db runFinal(ctx); if (res == NDBT_OK) { ndbout << "- " << name << " PASSED [" << ctx->suite->getDate() << "]" << endl; } else { ndbout << "- " << name << " FAILED [" << ctx->suite->getDate() << "]" << endl; } return res;}void NDBT_TestCase::startTimer(NDBT_Context* ctx){ timer.doStart();}void NDBT_TestCase::stopTimer(NDBT_Context* ctx){ timer.doStop();}void NDBT_TestCase::printTimer(NDBT_Context* ctx){ if (suite->timerIsOn()){ g_info << endl; timer.printTestTimer(ctx->getNumLoops(), ctx->getNumRecords()); }}int NDBT_TestCaseImpl1::runInit(NDBT_Context* ctx){ int res = NDBT_OK; for (unsigned i = 0; i < initializers.size(); i++){ initializers[i]->setContext(ctx); res = initializers[i]->execute(ctx); if (res != NDBT_OK) break; } return res;}int NDBT_TestCaseImpl1::runSteps(NDBT_Context* ctx){ int res = NDBT_OK; // Reset variables numStepsOk = 0; numStepsFail = 0; numStepsCompleted = 0; unsigned i; for (i = 0; i < steps.size(); i++) startStepInThread(i, ctx); waitSteps(); for(i = 0; i < steps.size(); i++) if (results[i] != NDBT_OK) res = NDBT_FAILED; return res;}int NDBT_TestCaseImpl1::runVerifier(NDBT_Context* ctx){ int res = NDBT_OK; for (unsigned i = 0; i < verifiers.size(); i++){ verifiers[i]->setContext(ctx); res = verifiers[i]->execute(ctx); if (res != NDBT_OK) break; } return res;}int NDBT_TestCaseImpl1::runFinal(NDBT_Context* ctx){ int res = NDBT_OK; for (unsigned i = 0; i < finalizers.size(); i++){ finalizers[i]->setContext(ctx); res = finalizers[i]->execute(ctx); if (res != NDBT_OK) break; } return res;}void NDBT_TestCaseImpl1::saveTestResult(const NdbDictionary::Table* ptab, int result){ testResults.push_back(new NDBT_TestCaseResult(ptab->getName(), result, timer.elapsedTime()));}void NDBT_TestCaseImpl1::printTestResult(){ char buf[255]; ndbout << name<<endl; for (unsigned i = 0; i < testResults.size(); i++){ NDBT_TestCaseResult* tcr = testResults[i]; const char* res; if (tcr->getResult() == NDBT_OK) res = "OK"; else if (tcr->getResult() == NDBT_FAILED) res = "FAIL"; else if (tcr->getResult() == FAILED_TO_CREATE) res = "FAILED TO CREATE TABLE"; else if (tcr->getResult() == FAILED_TO_DISCOVER) res = "FAILED TO DISCOVER TABLE"; BaseString::snprintf(buf, 255," %-10s %-5s %-20s", tcr->getName(), res, tcr->getTimeStr()); ndbout << buf<<endl; }}NDBT_TestSuite::NDBT_TestSuite(const char* pname):name(pname){ numTestsOk = 0; numTestsFail = 0; numTestsExecuted = 0; records = 0; loops = 0; createTable = true;}NDBT_TestSuite::~NDBT_TestSuite(){ for(unsigned i=0; i<tests.size(); i++){ delete tests[i]; } tests.clear();}void NDBT_TestSuite::setCreateTable(bool _flag){ createTable = _flag;}bool NDBT_TestSuite::timerIsOn(){ return (timer != 0);}int NDBT_TestSuite::addTest(NDBT_TestCase* pTest){ assert(pTest != NULL); tests.push_back(pTest); return 0;}int NDBT_TestSuite::executeAll(Ndb_cluster_connection& con, const char* _testname){ if(tests.size() == 0) return NDBT_FAILED; Ndb ndb(&con, "TEST_DB"); ndb.init(1024); int result = ndb.waitUntilReady(500); // 5 minutes if (result != 0){ g_err << name <<": Ndb was not ready" << endl; return NDBT_FAILED; } ndbout << name << " started [" << getDate() << "]" << endl; testSuiteTimer.doStart(); for (int t=0; t < NDBT_Tables::getNumTables(); t++){ const NdbDictionary::Table* ptab = NDBT_Tables::getTable(t); ndbout << "|- " << ptab->getName() << endl; execute(con, &ndb, ptab, _testname); } testSuiteTimer.doStop(); return reportAllTables(_testname);}int NDBT_TestSuite::executeOne(Ndb_cluster_connection& con, const char* _tabname, const char* _testname){ if(tests.size() == 0) return NDBT_FAILED; Ndb ndb(&con, "TEST_DB"); ndb.init(1024); int result = ndb.waitUntilReady(300); // 5 minutes if (result != 0){ g_err << name <<": Ndb was not ready" << endl; return NDBT_FAILED; } ndbout << name << " started [" << getDate() << "]" << endl; const NdbDictionary::Table* ptab = NDBT_Tables::getTable(_tabname); if (ptab == NULL) return NDBT_FAILED; ndbout << "|- " << ptab->getName() << endl; execute(con, &ndb, ptab, _testname); if (numTestsFail > 0){ return NDBT_FAILED; }else{ return NDBT_OK; }}void NDBT_TestSuite::execute(Ndb_cluster_connection& con, Ndb* ndb, const NdbDictionary::Table* pTab, const char* _testname){ int result; for (unsigned t = 0; t < tests.size(); t++){ if (_testname != NULL && strcasecmp(tests[t]->getName(), _testname) != 0) continue; if (tests[t]->isVerify(pTab) == false) { continue; } tests[t]->initBeforeTest(); NdbDictionary::Dictionary* pDict = ndb->getDictionary(); const NdbDictionary::Table* pTab2 = pDict->getTable(pTab->getName()); if (createTable == true){ if(pTab2 != 0 && pDict->dropTable(pTab->getName()) != 0){ numTestsFail++; numTestsExecuted++; g_err << "ERROR0: Failed to drop table " << pTab->getName() << endl; tests[t]->saveTestResult(pTab, FAILED_TO_CREATE); continue; } if(NDBT_Tables::createTable(ndb, pTab->getName()) != 0){ numTestsFail++; numTestsExecuted++; g_err << "ERROR1: Failed to create table " << pTab->getName() << pDict->getNdbError() << endl; tests[t]->saveTestResult(pTab, FAILED_TO_CREATE); continue; } pTab2 = pDict->getTable(pTab->getName()); } else if(!pTab2) { pTab2 = pTab; } ctx = new NDBT_Context(con); ctx->setTab(pTab2); ctx->setNumRecords(records); ctx->setNumLoops(loops); if(remote_mgm != NULL) ctx->setRemoteMgm(remote_mgm); ctx->setSuite(this); result = tests[t]->execute(ctx); tests[t]->saveTestResult(pTab, result); if (result != NDBT_OK) numTestsFail++; else numTestsOk++; numTestsExecuted++; if (result == NDBT_OK && createTable == true){ pDict->dropTable(pTab->getName()); } delete ctx; }}int NDBT_TestSuite::report(const char* _tcname){ int result; ndbout << "Completed " << name << " [" << getDate() << "]" << endl; printTestCaseSummary(_tcname); ndbout << numTestsExecuted << " test(s) executed" << endl; ndbout << numTestsOk << " test(s) OK" << endl; if(numTestsFail > 0) ndbout << numTestsFail << " test(s) failed" << endl; testSuiteTimer.printTotalTime(); if (numTestsFail > 0 || numTestsExecuted == 0){ result = NDBT_FAILED; }else{ result = NDBT_OK; } return result;}void NDBT_TestSuite::printTestCaseSummary(const char* _tcname){ ndbout << "= SUMMARY OF TEST EXECUTION ==============" << endl; for (unsigned t = 0; t < tests.size(); t++){ if (_tcname != NULL && strcasecmp(tests[t]->getName(), _tcname) != 0) continue; tests[t]->printTestResult(); } ndbout << "==========================================" << endl;}int NDBT_TestSuite::reportAllTables(const char* _testname){ int result; ndbout << "Completed running test [" << getDate() << "]" << endl; const int totalNumTests = numTestsExecuted; printTestCaseSummary(_testname); ndbout << numTestsExecuted<< " test(s) executed" << endl; ndbout << numTestsOk << " test(s) OK(" <<(int)(((float)numTestsOk/totalNumTests)*100.0) <<"%)" << endl; if(numTestsFail > 0) ndbout << numTestsFail << " test(s) failed(" <<(int)(((float)numTestsFail/totalNumTests)*100.0) <<"%)" << endl; testSuiteTimer.printTotalTime(); if (numTestsExecuted > 0){ if (numTestsFail > 0){ result = NDBT_FAILED; }else{ result = NDBT_OK; } } else { result = NDBT_FAILED; } return result;}int NDBT_TestSuite::execute(int argc, const char** argv){ int res = NDBT_FAILED; /* Arguments: Run only a subset of tests -n testname Which test to run Recommendations to test functions: --records Number of records to use(default: 10000) --loops Number of loops to execute in the test(default: 100) Other parameters should: * be calculated from the above two parameters * be divided into different test cases, ex. one testcase runs with FragmentType = Single and another perfoms the same test with FragmentType = Large * let the test case iterate over all/subset of appropriate parameters ex. iterate over FragmentType = Single to FragmentType = AllLarge Remeber that the intention is that it should be _easy_ to run a complete test suite without any greater knowledge of what should be tested ie. keep arguments at a minimum */ int _records = 1000; int _loops = 5; int _timer = 0; char * _remote_mgm =NULL; char* _testname = NULL; const char* _tabname = NULL; int _print = false; int _print_html = false; int _print_cases = false; int _verbose = false;#ifndef DBUG_OFF const char *debug_option= 0;#endif struct getargs args[] = { { "print", '\0', arg_flag, &_print, "Print execution tree", "" }, { "print_html", '\0', arg_flag, &_print_html, "Print execution tree in html table format", "" }, { "print_cases", '\0', arg_flag, &_print_cases, "Print list of test cases", "" }, { "records", 'r', arg_integer, &_records, "Number of records", "records" }, { "loops", 'l', arg_integer, &_loops, "Number of loops", "loops" }, { "testname", 'n', arg_string, &_testname, "Name of test to run", "testname" }, { "remote_mgm", 'm', arg_string, &_remote_mgm, "host:port to mgmsrv of remote cluster", "host:port" }, { "timer", 't', arg_flag, &_timer, "Print execution time", "time" },#ifndef DBUG_OFF { "debug", 0, arg_string, &debug_option, "Specify debug options e.g. d:t:i:o,out.trace", "options" },#endif { "verbose", 'v', arg_flag, &_verbose, "Print verbose status", "verbose" } }; int num_args = sizeof(args) / sizeof(args[0]); int optind = 0; if(getarg(args, num_args, argc, argv, &optind)) { arg_printusage(args, num_args, argv[0], "tabname1 tabname2 ... tabnameN\n"); return NDBT_WRONGARGS; }#ifndef DBUG_OFF if (debug_option) DBUG_PUSH(debug_option);#endif // Check if table name is supplied if (argv[optind] != NULL) _tabname = argv[optind]; if (_print == true){ printExecutionTree(); return 0; } if (_print_html == true){ printExecutionTreeHTML(); return 0; } if (_print_cases == true){ printCases(); return NDBT_ProgramExit(NDBT_FAILED); } if (_verbose) setOutputLevel(2); // Show g_info else setOutputLevel(0); // Show only g_err ? remote_mgm = _remote_mgm; records = _records; loops = _loops; timer = _timer; Ndb_cluster_connection con; if(con.connect(12, 5, 1)) { return NDBT_ProgramExit(NDBT_FAILED); } if(optind == argc){ // No table specified res = executeAll(con, _testname); } else { testSuiteTimer.doStart(); for(int i = optind; i<argc; i++){ executeOne(con, argv[i], _testname); } testSuiteTimer.doStop(); res = report(_testname); } return NDBT_ProgramExit(res);} void NDBT_TestSuite::printExecutionTree(){ ndbout << "Testsuite: " << name << endl; for (unsigned t = 0; t < tests.size(); t++){ tests[t]->print(); ndbout << endl; } }void NDBT_TestSuite::printExecutionTreeHTML(){ ndbout << "<tr>" << endl; ndbout << "<td><h3>" << name << "</h3></td>" << endl; ndbout << "</tr>" << endl; for (unsigned t = 0; t < tests.size(); t++){ tests[t]->printHTML(); ndbout << endl; } }void NDBT_TestSuite::printCases(){ ndbout << "# Testsuite: " << name << endl; ndbout << "# Number of tests: " << tests.size() << endl; for (unsigned t = 0; t < tests.size(); t++){ ndbout << name << " -n " << tests[t]->getName() << endl; } }const char* NDBT_TestSuite::getDate(){ static char theTime[128]; struct tm* tm_now; time_t now; now = time((time_t*)NULL);#ifdef NDB_WIN32 tm_now = localtime(&now);#else tm_now = gmtime(&now);#endif BaseString::snprintf(theTime, 128, "%d-%.2d-%.2d %.2d:%.2d:%.2d", tm_now->tm_year + 1900, tm_now->tm_mon + 1, tm_now->tm_mday, tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec); return theTime;}void NDBT_TestCaseImpl1::printHTML(){ ndbout << "<tr><td> </td>" << endl; ndbout << "<td name=tc>" << endl << name << "</td><td width=70%>" << comment << "</td></tr>" << endl; }void NDBT_TestCaseImpl1::print(){ ndbout << "Test case: " << name << endl; ndbout << "Description: "<< comment << endl; ndbout << "Parameters: " << endl; Properties::Iterator it(&props); for(const char * key = it.first(); key != 0; key = it.next()){ PropertiesType pt; const bool b = props.getTypeOf(key, &pt); assert(b == true); switch(pt){ case PropertiesType_Uint32:{ Uint32 val; props.get(key, &val); ndbout << " " << key << ": " << val << endl; break; } case PropertiesType_char:{ const char * val; props.get(key, &val); ndbout << " " << key << ": " << val << endl; break; } default: abort(); } } unsigned i; for(i=0; i<initializers.size(); i++){ ndbout << "Initializers[" << i << "]: " << endl; initializers[i]->print(); } for(i=0; i<steps.size(); i++){ ndbout << "Step[" << i << "]: " << endl; steps[i]->print(); } for(i=0; i<verifiers.size(); i++){ ndbout << "Verifier[" << i << "]: " << endl; verifiers[i]->print(); } for(i=0; i<finalizers.size(); i++){ ndbout << "Finalizer[" << i << "]: " << endl; finalizers[i]->print(); } }void NDBT_Step::print(){ ndbout << " "<< name << endl;}voidNDBT_Context::sync_down(const char * key){ Uint32 threads = getProperty(key, (unsigned)0); if(threads){ decProperty(key); }}voidNDBT_Context::sync_up_and_wait(const char * key, Uint32 value){ setProperty(key, value); getPropertyWait(key, (unsigned)0);}template class Vector<NDBT_TestCase*>;template class Vector<NDBT_TestCaseResult*>;template class Vector<NDBT_Step*>;template class Vector<NdbThread*>;template class Vector<NDBT_Verifier*>;template class Vector<NDBT_Initializer*>;template class Vector<NDBT_Finalizer*>;template class Vector<const NdbDictionary::Table*>;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -