MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NdbPortLibTest.cpp
1 /*
2  Copyright (C) 2003-2006, 2008 MySQL AB
3  All rights reserved. Use is subject to license terms.
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; version 2 of the License.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
25 #include <ndb_global.h>
26 
27 #include "NdbOut.hpp"
28 #include "NdbThread.h"
29 #include "NdbMutex.h"
30 #include "NdbCondition.h"
31 #include "NdbSleep.h"
32 #include "NdbTick.h"
33 #include "NdbEnv.h"
34 #include "NdbHost.h"
35 #include "NdbMain.h"
36 
37 int TestHasFailed;
38 int verbose = 0;
39 
40 static void fail(const char* test, const char* cause)
41 {
42  TestHasFailed = 1;
43  ndbout << test << " failed, " << cause << endl;
44 }
45 
46 // test 1 variables and funcs
47 
48 extern "C" void* thread1func(void* arg)
49 {
50  int arg1;
51  int returnvalue = 8;
52  arg1 = *(int*)arg;
53  ndbout << "thread1: thread1func called with arg = " << arg1 << endl;
54 
55  // delay(1000);
56  if (arg1 != 7)
57  fail("TEST1", "Wrong arg");
58 
59  return (void*) returnvalue;
60 }
61 
62 // test 2 variables and funcs
63 
64 NdbMutex* test2mutex;
65 
66 extern "C" void* test2func(void* arg)
67 {
68 
69  int arg1;
70  arg1 = *(int*)arg;
71  ndbout << "thread" << arg1 << " started in test2func" << endl;
72 
73  if (NdbMutex_Lock(test2mutex) != 0)
74  fail("TEST2", "Failed to lock mutex");
75 
76  ndbout << "thread" << arg1 << ", test2func " << endl;
77 
78  if (NdbMutex_Unlock(test2mutex) != 0)
79  fail("TEST2", "Failed to unlock mutex");
80 
81  int returnvalue = arg1;
82  return (void*) returnvalue;
83 }
84 
85 
86 // test 3 and 7 variables and funcs
87 
88 NdbMutex* testmutex;
89 NdbCondition* testcond;
90 int testthreadsdone;
91 
92 extern "C" void* testfunc(void* arg)
93 {
94  int tmpVar;
95  int threadno;
96  int result;
97 
98  threadno = *(int*)arg;
99 
100  ndbout << "Thread" << threadno << " started in testfunc" << endl;
101  do
102  {
103 
104  if ((threadno % 2) == 0)
105  result = NdbSleep_SecSleep(1);
106  else
107  result = NdbSleep_MilliSleep(100);
108 
109  if (result != 0)
110  fail("TEST3", "Wrong result from sleep function");
111 
112  if (NdbMutex_Lock(testmutex) != 0)
113  fail("TEST3", "Wrong result from NdbMutex_Lock function");
114 
115  ndbout << "thread" << threadno << ", testfunc " << endl;
116  testthreadsdone++;
117  tmpVar = testthreadsdone;
118 
119  if (NdbCondition_Signal(testcond) != 0)
120  fail("TEST3", "Wrong result from NdbCondition_Signal function");
121 
122  if (NdbMutex_Unlock(testmutex) != 0)
123  fail("TEST3", "Wrong result from NdbMutex_Unlock function");
124 
125  }
126  while(tmpVar<100);
127 
128  return 0;
129 }
130 
131 extern "C" void* testTryLockfunc(void* arg)
132 {
133  int tmpVar = 0;
134  int threadno;
135  int result;
136 
137  threadno = *(int*)arg;
138 
139  ndbout << "Thread" << threadno << " started" << endl;
140  do
141  {
142 
143  if ((threadno % 2) == 0)
144  result = NdbSleep_SecSleep(1);
145  else
146  result = NdbSleep_MilliSleep(100);
147 
148  if (result != 0)
149  fail("TEST3", "Wrong result from sleep function");
150 
151  if (NdbMutex_Trylock(testmutex) == 0){
152 
153  ndbout << "thread" << threadno << ", testTryLockfunc locked" << endl;
154  testthreadsdone++;
155  tmpVar = testthreadsdone;
156 
157  if (NdbCondition_Signal(testcond) != 0)
158  fail("TEST3", "Wrong result from NdbCondition_Signal function");
159 
160  if (NdbMutex_Unlock(testmutex) != 0)
161  fail("TEST3", "Wrong result from NdbMutex_Unlock function");
162  }
163 
164  }
165  while(tmpVar<100);
166 
167  return 0;
168 }
169 
170 
171 
172 void testMicros(int count);
173 Uint64 time_diff(Uint64 s1, Uint64 s2, Uint32 m1, Uint32 m2);
174 
175 NDB_COMMAND(PortLibTest, "portlibtest", "portlibtest", "Test the portable function layer", 4096){
176 
177  ndbout << "= TESTING ARGUMENT PASSING ============" << endl;
178  ndbout << "ARGC: " << argc << endl;
179  for(int i = 1; i < argc; i++){
180  ndbout << " ARGV"<<i<<": " << (char*)argv[i] << endl;
181  }
182  ndbout << endl << endl;
183 
184 
185  struct NdbThread* thread1var;
186  void *status = 0;
187  int arg = 7;
188 
189  TestHasFailed = 0;
190  // create one thread and wait for it to return
191  ndbout << "= TEST1 ===============================" << endl;
192 
193  thread1var = NdbThread_Create(thread1func, // Function
194  (void**)&arg,// Arg
195  2048, // Stacksize
196  (char*)"thread1", // Thread name
197  NDB_THREAD_PRIO_MEAN); // Thread priority
198 
199 
200  if(NdbThread_WaitFor(thread1var, &status) != 0)
201  fail("TEST1", "NdbThread_WaitFor failed");
202  // NOTE! thread return value is not yet used in Ndb and thus not tested(does not work)
203  //ndbout << "thread1 returned, status = " << status << endl;
204  //if (status != 8)
205  // fail("TEST1", "Wrong status");
206  ndbout << "TEST1 completed" << endl;
207 
208 
209  NdbThread_Destroy(&thread1var);
210 
211  // Create 10 threads that will wait for a mutex before printing it's message to screen
212  ndbout << "= TEST2 ===============================" << endl;
213 #define T2_THREADS 10
214  NdbThread* threads[T2_THREADS];
215  int args[T2_THREADS];
216  void *status2 = 0;
217  test2mutex = NdbMutex_Create();
218  NdbMutex_Lock(test2mutex);
219 
220  for (int i = 0; i < T2_THREADS; i++)
221  {
222  args[i] = i;
223  threads[i] = NdbThread_Create(test2func, // Function
224  (void**)&args[i],// Arg
225  2048, // Stacksize
226  (char*)"test2thread", // Thread name
227  NDB_THREAD_PRIO_MEAN); // Thread priority
228  if (threads[i] == NULL)
229  fail("TEST2", "NdbThread_Create failed");
230  }
231 
232  ndbout << "All threads created" << endl;
233 
234  NdbMutex_Unlock(test2mutex);
235 
236  for (int i = 0; i < T2_THREADS; i++)
237  {
238  if (NdbThread_WaitFor(threads[i], &status2))
239  fail("TEST2", "NdbThread_WaitFor failed");
240 
241  NdbThread_Destroy(&threads[i]);
242  // Don't test return values
243  // ndbout << "thread" << i << " returned, status = " << status2 << endl;
244  // if (status2 != i)
245  // fail("TEST2", "Wrong status");
246  }
247 
248  if (NdbMutex_Lock(test2mutex) != 0)
249  fail("TEST2", "NdbMutex_Lock failed");
250  if (NdbMutex_Unlock(test2mutex) != 0)
251  fail("TEST2", "NdbMutex_Unlock failed");
252  if (NdbMutex_Destroy(test2mutex) != 0)
253  fail("TEST2", "NdbMutex_Destroy failed");
254  ndbout << "TEST2 completed" << endl;
255 
256  ndbout << "= TEST3 ===============================" << endl;
257  // Create 10 threads that will by synchronised by a condition
258  // When they are awakened and have the mutex they will increment a global variable
259 #define T3_THREADS 10
260  NdbThread* t3threads[T3_THREADS];
261  int t3args[T3_THREADS];
262  void *status3 = 0;
263 
264  testmutex = NdbMutex_Create();
265  testcond = NdbCondition_Create();
266  testthreadsdone = 0;
267 
268  for (int i = 0; i < T3_THREADS; i++)
269  {
270  t3args[i] = i;
271  t3threads[i] = NdbThread_Create(testfunc, // Function
272  (void**)&t3args[i],// Arg
273  2048, // Stacksize
274  (char*)"test3thread", // Thread name
275  NDB_THREAD_PRIO_MEAN); // Thread priority
276  }
277 
278  ndbout << "All threads created" << endl;
279 
280  if (NdbMutex_Lock(testmutex) != 0)
281  fail("TEST3", "NdbMutex_Lock failed");
282 
283  while (testthreadsdone < T3_THREADS*10)
284  {
285  if(NdbCondition_Wait(testcond, testmutex) != 0)
286  fail("TEST3", "NdbCondition_Wait failed");
287  ndbout << "Condition signaled, there are " << testthreadsdone << " completed threads" << endl;
288  }
289  if (NdbMutex_Unlock(testmutex) != 0)
290  fail("TEST3", "NdbMutex_Unlock failed");
291 
292  for (int i = 0; i < T3_THREADS; i++)
293  {
294  if (NdbThread_WaitFor(t3threads[i], &status3) != 0)
295  fail("TEST3", "NdbThread_WaitFor failed");
296 
297  NdbThread_Destroy(&t3threads[i]);
298  //ndbout << "thread" << i << " returned, status = " << status3 << endl;
299  //if (status3 != i)
300  // fail("TEST3", "Wrong status");
301  }
302 
303  NdbMutex_Destroy(testmutex);
304  NdbCondition_Destroy(testcond);
305  ndbout << "TEST3 completed" << endl;
306 
307  ndbout << "= TEST4 ===============================" << endl;
308  // Check tick functions
309 
310  //#if 0
311 
312  int sleeptimes[] = {78, 12, 199, 567, 899};
313 
314 
315  for (int i = 0; i < 5; i++)
316  {
317  ndbout << "*------------------------------- Measure" << i << endl;
318 
319  NDB_TICKS millisec_now;
320  NDB_TICKS millisec_now2;
321 
322  millisec_now = NdbTick_CurrentMillisecond();
323  NdbSleep_MilliSleep(sleeptimes[i]);
324  millisec_now2 = NdbTick_CurrentMillisecond();
325 
326  ndbout << " Time before sleep = " << millisec_now << endl;
327  ndbout << " Time after sleep = " << millisec_now2 << endl;
328  ndbout << " Tried to sleep "<<sleeptimes[i]<<" milliseconds." << endl;
329  ndbout << " Sleep time was " << millisec_now2 -millisec_now <<" milliseconds." << endl;
330 
331  }
332 
333  ndbout << "TEST4 completed" << endl;
334 
335  ndbout << "= TEST5 ===============================" << endl;
336  // Check NdbOut
337 
338  ndbout << "Testing hex and dec functions of NdbOut" << endl;
339 
340  for (int i = 0; i<= 0xFF; i++)
341  {
342  ndbout << i << "=" <<hex << i << "="<<dec << i << ", ";
343  }
344 
345  ndbout << endl<< "Testing that hex is reset to dec by endl" << endl;
346  ndbout << hex << 67 << endl;
347  ndbout << 67 << endl;
348 
349  ndbout << "TEST5 completed" << endl;
350 
351 
352  ndbout << "= TEST6 ===============================" << endl;
353  const char* theEnvHostNamePtr;
354  char buf[255];
355  char theHostHostName[256];
356  theEnvHostNamePtr = NdbEnv_GetEnv("HOSTNAME", buf, 255);
357  if(theEnvHostNamePtr == NULL)
358  fail("TEST6", "Could not get HOSTNAME from env");
359  else{
360  ndbout << "HOSTNAME from GetEnv" << theEnvHostNamePtr << endl;
361 
362  NdbHost_GetHostName(theHostHostName);
363 
364  ndbout << "HOSTNAME from GetHostName" <<theHostHostName << endl;
365 
366  if (strcmp(theEnvHostNamePtr, theHostHostName) != 0)
367  fail("TEST6", "NdbHost_GetHostName or NdbEnv_GetEnv failed");
368  }
369 
370  ndbout << "= TEST7 ===============================" << endl;
371 
372  testmutex = NdbMutex_Create();
373  testcond = NdbCondition_Create();
374  testthreadsdone = 0;
375 
376  for (int i = 0; i < T3_THREADS; i++)
377  {
378  t3args[i] = i;
379  t3threads[i] = NdbThread_Create(testfunc, // Function
380  (void**)&t3args[i],// Arg
381  2048, // Stacksize
382  (char*)"test7thread", // Thread name
383  NDB_THREAD_PRIO_MEAN); // Thread priority
384  }
385 
386  ndbout << "All threads created" << endl;
387 
388  if (NdbMutex_Lock(testmutex) != 0)
389  fail("TEST7", "NdbMutex_Lock failed");
390 
391  while (testthreadsdone < T3_THREADS*10)
392  {
393  // just testing the functionality without timing out, therefor 20 sec.
394  if(NdbCondition_WaitTimeout(testcond, testmutex, 20000) != 0)
395  fail("TEST7", "NdbCondition_WaitTimeout failed");
396  ndbout << "Condition signaled, there are " << testthreadsdone << " completed threads" << endl;
397  }
398  if (NdbMutex_Unlock(testmutex) != 0)
399  fail("TEST7", "NdbMutex_Unlock failed");
400 
401  for (int i = 0; i < T3_THREADS; i++)
402  {
403  if (NdbThread_WaitFor(t3threads[i], &status3) != 0)
404  fail("TEST7", "NdbThread_WaitFor failed");
405 
406  NdbThread_Destroy(&t3threads[i]);
407  }
408 
409  NdbMutex_Destroy(testmutex);
410  NdbCondition_Destroy(testcond);
411 
412  ndbout << "TEST7 completed" << endl;
413 
414 
415  ndbout << "= TEST8 ===============================" << endl;
416  ndbout << " NdbCondition_WaitTimeout" << endl;
417  testmutex = NdbMutex_Create();
418  testcond = NdbCondition_Create();
419 
420  for (int i = 0; i < 5; i++)
421  {
422  ndbout << "*------------------------------- Measure" << i << endl;
423 
424  NDB_TICKS millisec_now;
425  NDB_TICKS millisec_now2;
426 
427  millisec_now = NdbTick_CurrentMillisecond();
428  if (NdbCondition_WaitTimeout(testcond, testmutex, sleeptimes[i]) != 0)
429  fail("TEST8", "NdbCondition_WaitTimeout failed");
430  millisec_now2 = NdbTick_CurrentMillisecond();
431 
432  ndbout << " Time before WaitTimeout = " << millisec_now << endl;
433  ndbout << " Time after WaitTimeout = " << millisec_now2 << endl;
434  ndbout << " Tried to wait "<<sleeptimes[i]<<" milliseconds." << endl;
435  ndbout << " Wait time was " << millisec_now2 -millisec_now <<" milliseconds." << endl;
436 
437  }
438 
439  ndbout << "TEST8 completed" << endl;
440 
441 
442  ndbout << "= TEST9 ===============================" << endl;
443  ndbout << " NdbTick_CurrentXXXXXsecond compare" << endl;
444 
445  for (int i = 0; i < 5; i++)
446  {
447  ndbout << "*------------------------------- Measure" << i << endl;
448 
449  NDB_TICKS millisec_now;
450  NDB_TICKS millisec_now2;
451  Uint32 usec_now, usec_now2;
452  Uint64 msec_now, msec_now2;
453 
454 
455  millisec_now = NdbTick_CurrentMillisecond();
456  NdbTick_CurrentMicrosecond( &msec_now, &usec_now);
457 
458  NdbSleep_MilliSleep(sleeptimes[i]);
459 
460  millisec_now2 = NdbTick_CurrentMillisecond();
461  NdbTick_CurrentMicrosecond( &msec_now2, &usec_now2);
462 
463  Uint64 usecdiff = time_diff(msec_now,msec_now2,usec_now,usec_now2);
464  NDB_TICKS msecdiff = millisec_now2 -millisec_now;
465 
466  ndbout << " Slept "<<sleeptimes[i]<<" milliseconds." << endl;
467  ndbout << " Measured " << msecdiff <<" milliseconds with milli function ." << endl;
468  ndbout << " Measured " << usecdiff/1000 << "," << usecdiff%1000<<" milliseconds with micro function ." << endl;
469  }
470 
471  ndbout << "TEST9 completed" << endl;
472 
473 
474  const int iter = 20;
475  ndbout << "Testing microsecond timer - " << iter << " iterations" << endl;
476  testMicros(iter);
477  ndbout << "Testing microsecond timer - COMPLETED" << endl;
478 
479  ndbout << "= TEST10 ===============================" << endl;
480 
481  testmutex = NdbMutex_Create();
482  testcond = NdbCondition_Create();
483  testthreadsdone = 0;
484 
485  for (int i = 0; i < T3_THREADS; i++)
486  {
487  t3args[i] = i;
488  t3threads[i] = NdbThread_Create(testTryLockfunc, // Function
489  (void**)&t3args[i],// Arg
490  2048, // Stacksize
491  (char*)"test10thread", // Thread name
492  NDB_THREAD_PRIO_MEAN); // Thread priority
493  }
494 
495  ndbout << "All threads created" << endl;
496 
497  if (NdbMutex_Lock(testmutex) != 0)
498  fail("TEST10", "NdbMutex_Lock failed");
499 
500  while (testthreadsdone < T3_THREADS*10)
501  {
502  if(NdbCondition_Wait(testcond, testmutex) != 0)
503  fail("TEST10", "NdbCondition_WaitTimeout failed");
504  ndbout << "Condition signaled, there are " << testthreadsdone << " completed threads" << endl;
505  }
506  if (NdbMutex_Unlock(testmutex) != 0)
507  fail("TEST10", "NdbMutex_Unlock failed");
508 
509  for (int i = 0; i < T3_THREADS; i++)
510  {
511  if (NdbThread_WaitFor(t3threads[i], &status3) != 0)
512  fail("TEST10", "NdbThread_WaitFor failed");
513 
514  NdbThread_Destroy(&t3threads[i]);
515  }
516 
517  NdbMutex_Destroy(testmutex);
518  NdbCondition_Destroy(testcond);
519 
520  ndbout << "TEST10 completed" << endl;
521 
522 
523  // Check total status of test
524 
525  if (TestHasFailed == 1)
526  ndbout << endl << "TEST FAILED!" << endl;
527  else
528  ndbout << endl << "TEST PASSED!" << endl;
529 
530  return TestHasFailed;
531 
532 };
533 
534 Uint64 time_diff(Uint64 s1, Uint64 s2, Uint32 m1, Uint32 m2){
535 
536  Uint64 diff = 0;
537  diff += (s2 - s1) * 1000000;
538  if(m2 >= m1)
539  diff += (m2 - m1);
540  else {
541  diff += m2;
542  diff -= m1;
543  }
544 
545  // if(0)
546  // ndbout("(s1,m1) = (%d, %d) (s2,m2) = (%d, %d) -> diff = %d\n",
547  // (Uint32)s1,m1,(Uint32)s2,m2, (Uint32)diff);
548 
549  return diff;
550 };
551 
552 void
553 testMicros(int count){
554  Uint32 avg = 0;
555  Uint32 sum2 = 0;
556 
557  for(int i = 0; i<count; i++){
558  Uint64 s1, s2;
559  Uint32 m1, m2;
560  if(NdbTick_CurrentMicrosecond(&s1, &m1) != 0){
561  ndbout << "Failed to get current micro" << endl;
562  TestHasFailed = 1;
563  return;
564  }
565  Uint32 r = (rand() % 1000) + 1;
566  NdbSleep_MilliSleep(r);
567  if(NdbTick_CurrentMicrosecond(&s2, &m2) != 0){
568  ndbout << "Failed to get current micro" << endl;
569  TestHasFailed = 1;
570  return;
571  }
572  Uint64 m = time_diff(s1,s2,m1,m2);
573  if(verbose)
574  ndbout << "Slept for " << r << " ms"
575  << " - Measured " << m << " us" << endl;
576 
577  if(m > (r*1000)){
578  avg += (m - (r*1000));
579  sum2 += (m - (r*1000)) * (m - (r*1000));
580  } else {
581  avg += ((r*1000) - m);
582  sum2 += ((r*1000) - m) * ((r*1000) - m);
583  }
584 #if 0
585  m /= 1000;
586  if(m > r && ((m - r) > 10)){
587  ndbout << "Difference to big: " << (m - r) << " - Test failed" << endl;
588  TestHasFailed = 1;
589  }
590  if(m < r && ((r - m) > 10)){
591  ndbout << "Difference to big: " << (r - m) << " - Test failed" << endl;
592  TestHasFailed = 1;
593  }
594 #endif
595  }
596 
597  Uint32 dev = (avg * avg - sum2) / count; dev /= count;
598  avg /= count;
599 
600  Uint32 t = 0;
601  while((t*t)<dev) t++;
602  ndbout << "NOTE - measure are compared to NdbSleep_MilliSleep(...)" << endl;
603  ndbout << "Average error = " << avg << " us" << endl;
604  ndbout << "Stddev error = " << t << " us" << endl;
605 }