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