1 /* 2 Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License, version 2.0, 6 as published by the Free Software Foundation. 7 8 This program is also distributed with certain software (including 9 but not limited to OpenSSL) that is licensed under separate terms, 10 as designated in a particular file or component or in included license 11 documentation. The authors of MySQL hereby grant you an additional 12 permission to link the program and your derivative works with the 13 separately licensed software that they have included with MySQL. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License, version 2.0, for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software 22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 */ 24 25 #ifndef NDBT_TEST_HPP 26 #define NDBT_TEST_HPP 27 28 #include <ndb_global.h> 29 #include <kernel/ndb_limits.h> 30 31 #include "NDBT_ReturnCodes.h" 32 #include <Properties.hpp> 33 #include <NdbThread.h> 34 #include <NdbSleep.h> 35 #include <NdbCondition.h> 36 #include <NdbTimer.hpp> 37 #include <Vector.hpp> 38 #include <NdbApi.hpp> 39 #include <NdbDictionary.hpp> 40 #include <ndb_rand.h> 41 42 class NDBT_Step; 43 class NDBT_TestCase; 44 class NDBT_TestSuite; 45 class NDBT_TestCaseImpl1; 46 47 class NDBT_Context { 48 public: 49 Ndb_cluster_connection& m_cluster_connection; 50 51 NDBT_Context(Ndb_cluster_connection&); 52 ~NDBT_Context(); 53 const NdbDictionary::Table* getTab(); 54 const NdbDictionary::Table** getTables(); 55 int getNumTables() const; 56 const char * getTableName(int) const; 57 NDBT_TestSuite* getSuite(); 58 NDBT_TestCase* getCase(); 59 60 // Get arguments 61 int getNumRecords() const; 62 int getNumLoops() const; 63 64 // Common place to store state between 65 // steps, for example information from one step to the 66 // verifier about how many records have been inserted 67 Uint32 getProperty(const char*, Uint32 = 0 ); 68 const char* getProperty(const char*, const char* ); 69 void setProperty(const char*, Uint32); 70 void setProperty(const char*, const char*); 71 72 // Signal that a property value that another 73 // thread might be waiting for has changed 74 void broadcast(); 75 // Wait for the signal that a property has changed 76 void wait(); 77 void wait_timeout(int msec); 78 79 // Wait until the property has been set to a certain value 80 bool getPropertyWait(const char*, Uint32); 81 const char* getPropertyWait(const char*, const char* ); 82 83 void decProperty(const char *); 84 void incProperty(const char *); 85 Uint32 casProperty(const char *, Uint32 oldValue, Uint32 newValue); 86 87 // Communicate with other tests 88 void stopTest(); 89 bool isTestStopped(); 90 91 // Communicate with tests in other API nodes 92 // This is done using a "system" table in the database 93 Uint32 getDbProperty(const char*); 94 bool setDbProperty(const char*, Uint32); 95 96 void setTab(const NdbDictionary::Table*); 97 void addTab(const NdbDictionary::Table*); 98 99 /** 100 * Get no of steps running/completed 101 */ 102 int getNoOfRunningSteps() const ; 103 int getNoOfCompletedSteps() const ; 104 105 /** 106 * Thread sync 107 */ 108 void sync_down(const char * key); 109 void sync_up_and_wait(const char * key, Uint32 count = 0); 110 private: 111 friend class NDBT_Step; 112 friend class NDBT_TestSuite; 113 friend class NDBT_TestCase; 114 friend class NDBT_TestCaseImpl1; 115 116 void setSuite(NDBT_TestSuite*); 117 void setCase(NDBT_TestCase*); 118 void setNumRecords(int); 119 void setNumLoops(int); 120 Vector<const NdbDictionary::Table*> tables; 121 NDBT_TestSuite* suite; 122 NDBT_TestCase* testcase; 123 Ndb* ndb; 124 int records; 125 int loops; 126 bool stopped; 127 Properties props; 128 NdbMutex* propertyMutexPtr; 129 NdbCondition* propertyCondPtr; 130 }; 131 132 typedef int (NDBT_TESTFUNC)(NDBT_Context*, NDBT_Step*); 133 134 class NDBT_Step { 135 public: 136 NDBT_Step(NDBT_TestCase* ptest, 137 const char* pname, 138 NDBT_TESTFUNC* pfunc); ~NDBT_Step()139 virtual ~NDBT_Step() {} 140 int execute(NDBT_Context*); 141 void setContext(NDBT_Context*); 142 NDBT_Context* getContext(); 143 void print(); getName()144 const char* getName() { return name; } getStepNo()145 int getStepNo() { return step_no; } setStepNo(int n)146 void setStepNo(int n) { step_no = n; } 147 protected: 148 NDBT_Context* m_ctx; 149 const char* name; 150 NDBT_TESTFUNC* func; 151 NDBT_TestCase* testcase; 152 int step_no; 153 154 private: 155 int setUp(Ndb_cluster_connection&); 156 void tearDown(); 157 Ndb* m_ndb; 158 159 public: 160 Ndb* getNdb() const; 161 162 }; 163 164 class NDBT_ParallelStep : public NDBT_Step { 165 public: 166 NDBT_ParallelStep(NDBT_TestCase* ptest, 167 const char* pname, 168 NDBT_TESTFUNC* pfunc); ~NDBT_ParallelStep()169 virtual ~NDBT_ParallelStep() {} 170 }; 171 172 class NDBT_Verifier : public NDBT_Step { 173 public: 174 NDBT_Verifier(NDBT_TestCase* ptest, 175 const char* name, 176 NDBT_TESTFUNC* func); ~NDBT_Verifier()177 virtual ~NDBT_Verifier() {} 178 }; 179 180 class NDBT_Initializer : public NDBT_Step { 181 public: 182 NDBT_Initializer(NDBT_TestCase* ptest, 183 const char* name, 184 NDBT_TESTFUNC* func); ~NDBT_Initializer()185 virtual ~NDBT_Initializer() {} 186 }; 187 188 class NDBT_Finalizer : public NDBT_Step { 189 public: 190 NDBT_Finalizer(NDBT_TestCase* ptest, 191 const char* name, 192 NDBT_TESTFUNC* func); ~NDBT_Finalizer()193 virtual ~NDBT_Finalizer() {} 194 }; 195 196 197 enum NDBT_DriverType { 198 DummyDriver, 199 NdbApiDriver 200 }; 201 202 203 class NDBT_TestCase { 204 public: 205 NDBT_TestCase(NDBT_TestSuite* psuite, 206 const char* name, 207 const char* comment); ~NDBT_TestCase()208 virtual ~NDBT_TestCase() {} 209 getStepThreadStackSizePropName()210 static const char* getStepThreadStackSizePropName() 211 { return "StepThreadStackSize"; }; 212 213 // This is the default executor of a test case 214 // When a test case is executed it will need to be suplied with a number of 215 // different parameters and settings, these are passed to the test in the 216 // NDBT_Context object 217 virtual int execute(NDBT_Context*); 218 void setProperty(const char*, Uint32); 219 void setProperty(const char*, const char*); 220 virtual void print() = 0; 221 virtual void printHTML() = 0; 222 getName() const223 const char* getName() const { return _name.c_str(); }; 224 virtual bool tableExists(NdbDictionary::Table* aTable) = 0; 225 virtual bool isVerify(const NdbDictionary::Table* aTable) = 0; 226 227 virtual void saveTestResult(const char*, int result) = 0; 228 virtual void printTestResult() = 0; initBeforeTest()229 void initBeforeTest(){ timer.doReset();}; 230 setDriverType(NDBT_DriverType type)231 void setDriverType(NDBT_DriverType type) { m_driverType= type; } getDriverType() const232 NDBT_DriverType getDriverType() const { return m_driverType; } 233 234 /** 235 * Get no of steps running/completed 236 */ 237 virtual int getNoOfRunningSteps() const = 0; 238 virtual int getNoOfCompletedSteps() const = 0; 239 240 bool m_all_tables; 241 bool m_has_run; 242 243 protected: 244 virtual int runInit(NDBT_Context* ctx) = 0; 245 virtual int runSteps(NDBT_Context* ctx) = 0; 246 virtual int runVerifier(NDBT_Context* ctx) = 0; 247 virtual int runFinal(NDBT_Context* ctx) = 0; 248 virtual void addTable(const char* aTableName, bool isVerify=true) = 0; 249 250 void startTimer(NDBT_Context*); 251 void stopTimer(NDBT_Context*); 252 void printTimer(NDBT_Context*); 253 254 BaseString _name; 255 BaseString _comment; 256 NDBT_TestSuite* suite; 257 Properties props; 258 NdbTimer timer; 259 bool isVerifyTables; 260 NDBT_DriverType m_driverType; 261 }; 262 263 static const int FAILED_TO_CREATE = 1000; 264 static const int FAILED_TO_DISCOVER = 1001; 265 266 267 class NDBT_TestCaseResult{ 268 public: NDBT_TestCaseResult(const char * name,int _result,NDB_TICKS _ticks)269 NDBT_TestCaseResult(const char* name, int _result, NDB_TICKS _ticks): 270 m_result(_result){ 271 m_name.assign(name); 272 m_ticks = _ticks; 273 274 }; getName()275 const char* getName(){return m_name.c_str(); }; getResult()276 int getResult(){return m_result; }; getTimeStr()277 const char* getTimeStr(){ 278 // Convert to Uint32 in order to be able to print it to screen 279 Uint32 lapTime = (Uint32)m_ticks; 280 Uint32 secTime = lapTime/1000; 281 BaseString::snprintf(buf, 255, "%d secs (%d ms)", secTime, lapTime); 282 return buf; 283 } 284 private: 285 char buf[255]; 286 int m_result; 287 BaseString m_name; 288 NDB_TICKS m_ticks; 289 }; 290 291 class NDBT_TestCaseImpl1 : public NDBT_TestCase { 292 public: 293 NDBT_TestCaseImpl1(NDBT_TestSuite* psuite, 294 const char* name, 295 const char* comment); 296 virtual ~NDBT_TestCaseImpl1(); 297 int addStep(NDBT_Step*); 298 int addVerifier(NDBT_Verifier*); 299 int addInitializer(NDBT_Initializer*, bool first= false); 300 int addFinalizer(NDBT_Finalizer*); 301 void addTable(const char*, bool); 302 bool tableExists(NdbDictionary::Table*); 303 bool isVerify(const NdbDictionary::Table*); 304 void reportStepResult(const NDBT_Step*, int result); 305 // int execute(NDBT_Context* ctx); 306 int runInit(NDBT_Context* ctx); 307 int runSteps(NDBT_Context* ctx); 308 int runVerifier(NDBT_Context* ctx); 309 int runFinal(NDBT_Context* ctx); 310 void print(); 311 void printHTML(); 312 313 virtual int getNoOfRunningSteps() const; 314 virtual int getNoOfCompletedSteps() const; 315 private: 316 static const int NORESULT = 999; 317 318 void saveTestResult(const char*, int result); 319 void printTestResult(); 320 321 void startStepInThread(int stepNo, NDBT_Context* ctx); 322 void waitSteps(); 323 Vector<NDBT_Step*> steps; 324 Vector<NdbThread*> threads; 325 Vector<int> results; 326 Vector<NDBT_Verifier*> verifiers; 327 Vector<NDBT_Initializer*> initializers; 328 Vector<NDBT_Finalizer*> finalizers; 329 Vector<const NdbDictionary::Table*> testTables; 330 Vector<NDBT_TestCaseResult*> testResults; 331 unsigned numStepsFail; 332 unsigned numStepsOk; 333 unsigned numStepsCompleted; 334 NdbMutex* waitThreadsMutexPtr; 335 NdbCondition* waitThreadsCondPtr; 336 }; 337 338 339 // A NDBT_TestSuite is a collection of TestCases 340 // the test suite will know how to execute the test cases 341 class NDBT_TestSuite { 342 public: 343 NDBT_TestSuite(const char* name); 344 ~NDBT_TestSuite(); 345 346 // Default executor of a test suite 347 // supply argc and argv as parameters 348 int execute(int, const char**); 349 350 // NDBT's test tables are fixed and it always create 351 // and drop fixed table when execute, add this method 352 // in order to run CTX only and adapt to some new 353 // customized testsuite 354 int executeOneCtx(Ndb_cluster_connection&, 355 const NdbDictionary::Table* ptab, const char* testname = NULL); 356 357 // These function can be used from main in the test program 358 // to control the behaviour of the testsuite 359 void setCreateTable(bool); // Create table before test func is called 360 void setCreateAllTables(bool); // Create all tables before testsuite is executed 361 void setRunAllTables(bool); // Run once with all tables 362 void setConnectCluster(bool); // Connect to cluster before testsuite is executed 363 364 // Prints the testsuite, testcases and teststeps 365 void printExecutionTree(); 366 void printExecutionTreeHTML(); 367 368 // Prints list of testcases 369 void printCases(); 370 371 // Print summary of executed tests 372 void printTestCaseSummary(const char* tcname = NULL); 373 374 /** 375 * Returns current date and time in the format of 2002-12-04 10:00:01 376 */ 377 const char* getDate(); 378 379 // Returns true if timing info should be printed 380 bool timerIsOn(); 381 382 int addTest(NDBT_TestCase* pTest); 383 384 // Table create tweaks 385 int createHook(Ndb*, NdbDictionary::Table&, int when); 386 Vector<BaseString> m_tables_in_test; 387 388 void setTemporaryTables(bool val); 389 bool getTemporaryTables() const; 390 391 void setLogging(bool val); 392 bool getLogging() const; 393 394 bool getForceShort() const; 395 396 int createTables(Ndb_cluster_connection&) const; 397 int dropTables(Ndb_cluster_connection&) const; 398 setDriverType(NDBT_DriverType type)399 void setDriverType(NDBT_DriverType type) { m_driverType= type; } getDriverType() const400 NDBT_DriverType getDriverType() const { return m_driverType; } 401 402 private: 403 int executeOne(Ndb_cluster_connection&, 404 const char* _tabname, const char* testname = NULL); 405 int executeAll(Ndb_cluster_connection&, 406 const char* testname = NULL); 407 void execute(Ndb_cluster_connection&, 408 const NdbDictionary::Table*, const char* testname = NULL); 409 410 int report(const char* _tcname = NULL); 411 int reportAllTables(const char* ); 412 const char* name; 413 char* remote_mgm; 414 int numTestsOk; 415 int numTestsFail; 416 int numTestsExecuted; 417 Vector<NDBT_TestCase*> tests; 418 NDBT_Context* ctx; 419 int records; 420 int loops; 421 int timer; 422 NdbTimer testSuiteTimer; 423 bool m_createTable; 424 bool m_createAll; 425 bool m_connect_cluster; 426 bool diskbased; 427 bool runonce; 428 const char* tsname; 429 bool temporaryTables; 430 bool m_logging; 431 NDBT_DriverType m_driverType; 432 bool m_noddl; 433 bool m_forceShort; 434 }; 435 436 437 438 #define NDBT_TESTSUITE(suitname) \ 439 class C##suitname : public NDBT_TestSuite { \ 440 public: \ 441 C##suitname():NDBT_TestSuite(#suitname){ \ 442 NDBT_TestCaseImpl1* pt; pt = NULL; \ 443 NDBT_Step* pts; pts = NULL; \ 444 NDBT_Verifier* ptv; ptv = NULL; \ 445 NDBT_Initializer* pti; pti = NULL; \ 446 NDBT_Finalizer* ptf; ptf = NULL; 447 448 // The default driver type to use for all tests in suite 449 #define DRIVER(type) \ 450 setDriverType(type) 451 452 #define TESTCASE(testname, comment) \ 453 pt = new NDBT_TestCaseImpl1(this, testname, comment); \ 454 addTest(pt); 455 456 // The driver type to use for a particular testcase 457 #define TESTCASE_DRIVER(type) \ 458 pt->setDriverType(type); 459 460 #define TC_PROPERTY(propname, propval) \ 461 pt->setProperty(propname, propval); 462 463 #define STEP(stepfunc) \ 464 pts = new NDBT_ParallelStep(pt, #stepfunc, stepfunc); \ 465 pt->addStep(pts); 466 467 // Add a number of equal steps to the testcase 468 #define STEPS(stepfunc, num) \ 469 { int i; for (i = 0; i < num; i++){ \ 470 pts = new NDBT_ParallelStep(pt, #stepfunc, stepfunc); \ 471 pt->addStep(pts);\ 472 } } 473 474 #define VERIFIER(stepfunc) \ 475 ptv = new NDBT_Verifier(pt, #stepfunc, stepfunc); \ 476 pt->addVerifier(ptv); 477 478 #define INITIALIZER(stepfunc) \ 479 pti = new NDBT_Initializer(pt, #stepfunc, stepfunc); \ 480 pt->addInitializer(pti); 481 482 #define FINALIZER(stepfunc) \ 483 ptf = new NDBT_Finalizer(pt, #stepfunc, stepfunc); \ 484 pt->addFinalizer(ptf); 485 486 // Test case can be run only on this table(s), can be multiple tables 487 // Ex TABLE("T1") 488 // TABLE("T3") 489 // Means test will only be run on T1 and T3 490 #define TABLE(tableName) \ 491 pt->addTable(tableName, true); 492 493 // Test case can be run on all tables except 494 // Ex NOT_TABLE("T10") 495 // Means test will be run on all tables execept T10 496 #define NOT_TABLE(tableName) \ 497 pt->addTable(tableName, false); 498 499 // Text case will only be run once, not once per table as normally 500 #define ALL_TABLES() \ 501 pt->m_all_tables= true; 502 503 #define NDBT_TESTSUITE_END(suitname) \ 504 } } ; 505 506 #define NDBT_TESTSUITE_INSTANCE(suitname) \ 507 C##suitname suitname 508 509 // Helper functions for retrieving variables from NDBT_Step 510 #define GETNDB(ps) ((NDBT_Step*)ps)->getNdb() 511 512 #define POSTUPGRADE(testname) \ 513 TESTCASE(testname "--post-upgrade", \ 514 "checks being run after upgrade has completed") 515 516 #endif 517