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