diff options
Diffstat (limited to 'storage/ndb/src/common/portlib/NdbPortLibTest.cpp')
-rw-r--r-- | storage/ndb/src/common/portlib/NdbPortLibTest.cpp | 608 |
1 files changed, 608 insertions, 0 deletions
diff --git a/storage/ndb/src/common/portlib/NdbPortLibTest.cpp b/storage/ndb/src/common/portlib/NdbPortLibTest.cpp new file mode 100644 index 00000000000..d7892411851 --- /dev/null +++ b/storage/ndb/src/common/portlib/NdbPortLibTest.cpp @@ -0,0 +1,608 @@ +/* Copyright (C) 2003 MySQL AB + + 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; either version 2 of the License, or + (at your option) any later version. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/** + * NdbPortLibTest.cpp + * Test the functionality of portlib + * TODO - Add tests for NdbMem + */ + +#include <ndb_global.h> + +#include "NdbOut.hpp" +#include "NdbThread.h" +#include "NdbMutex.h" +#include "NdbCondition.h" +#include "NdbSleep.h" +#include "NdbTick.h" +#include "NdbEnv.h" +#include "NdbHost.h" +#include "NdbMain.h" + +int TestHasFailed; +int verbose = 0; + +static void fail(const char* test, const char* cause) +{ + TestHasFailed = 1; + ndbout << test << " failed, " << cause << endl; +} + +// test 1 variables and funcs + +extern "C" void* thread1func(void* arg) +{ + int arg1; + int returnvalue = 8; + arg1 = *(int*)arg; + ndbout << "thread1: thread1func called with arg = " << arg1 << endl; + + // delay(1000); + if (arg1 != 7) + fail("TEST1", "Wrong arg"); + + return returnvalue; +} + +// test 2 variables and funcs + +NdbMutex* test2mutex; + +extern "C" void* test2func(void* arg) +{ + + int arg1; + arg1 = *(int*)arg; + ndbout << "thread" << arg1 << " started in test2func" << endl; + + if (NdbMutex_Lock(test2mutex) != 0) + fail("TEST2", "Failed to lock mutex"); + + ndbout << "thread" << arg1 << ", test2func " << endl; + + if (NdbMutex_Unlock(test2mutex) != 0) + fail("TEST2", "Failed to unlock mutex"); + + int returnvalue = arg1; + return returnvalue; +} + + +// test 3 and 7 variables and funcs + +NdbMutex* testmutex; +NdbCondition* testcond; +int testthreadsdone; + +extern "C" void* testfunc(void* arg) +{ + int tmpVar; + int threadno; + int result; + + threadno = *(int*)arg; + + ndbout << "Thread" << threadno << " started in testfunc" << endl; + do + { + + if ((threadno % 2) == 0) + result = NdbSleep_SecSleep(1); + else + result = NdbSleep_MilliSleep(100); + + if (result != 0) + fail("TEST3", "Wrong result from sleep function"); + + if (NdbMutex_Lock(testmutex) != 0) + fail("TEST3", "Wrong result from NdbMutex_Lock function"); + + ndbout << "thread" << threadno << ", testfunc " << endl; + testthreadsdone++; + tmpVar = testthreadsdone; + + if (NdbCondition_Signal(testcond) != 0) + fail("TEST3", "Wrong result from NdbCondition_Signal function"); + + if (NdbMutex_Unlock(testmutex) != 0) + fail("TEST3", "Wrong result from NdbMutex_Unlock function"); + + } + while(tmpVar<100); + + return 0; +} + +extern "C" void* testTryLockfunc(void* arg) +{ + int tmpVar = 0; + int threadno; + int result; + + threadno = *(int*)arg; + + ndbout << "Thread" << threadno << " started" << endl; + do + { + + if ((threadno % 2) == 0) + result = NdbSleep_SecSleep(1); + else + result = NdbSleep_MilliSleep(100); + + if (result != 0) + fail("TEST3", "Wrong result from sleep function"); + + if (NdbMutex_Trylock(testmutex) == 0){ + + ndbout << "thread" << threadno << ", testTryLockfunc locked" << endl; + testthreadsdone++; + tmpVar = testthreadsdone; + + if (NdbCondition_Signal(testcond) != 0) + fail("TEST3", "Wrong result from NdbCondition_Signal function"); + + if (NdbMutex_Unlock(testmutex) != 0) + fail("TEST3", "Wrong result from NdbMutex_Unlock function"); + } + + } + while(tmpVar<100); + + return 0; +} + + + +void testMicros(int count); +Uint64 time_diff(Uint64 s1, Uint64 s2, Uint32 m1, Uint32 m2); + +NDB_COMMAND(PortLibTest, "portlibtest", "portlibtest", "Test the portable function layer", 4096){ + + ndbout << "= TESTING ARGUMENT PASSING ============" << endl; + ndbout << "ARGC: " << argc << endl; + for(int i = 1; i < argc; i++){ + ndbout << " ARGV"<<i<<": " << (char*)argv[i] << endl; + } + ndbout << endl << endl; + + + struct NdbThread* thread1var; + void *status = 0; + int arg = 7; + + TestHasFailed = 0; + // create one thread and wait for it to return + ndbout << "= TEST1 ===============================" << endl; + + thread1var = NdbThread_Create(thread1func, // Function + (void**)&arg,// Arg + 2048, // Stacksize + (char*)"thread1", // Thread name + NDB_THREAD_PRIO_MEAN); // Thread priority + + + if(NdbThread_WaitFor(thread1var, &status) != 0) + fail("TEST1", "NdbThread_WaitFor failed"); + // NOTE! thread return value is not yet used in Ndb and thus not tested(does not work) + //ndbout << "thread1 returned, status = " << status << endl; + //if (status != 8) + // fail("TEST1", "Wrong status"); + ndbout << "TEST1 completed" << endl; + + + NdbThread_Destroy(&thread1var); + + // Create 10 threads that will wait for a mutex before printing it's message to screen + ndbout << "= TEST2 ===============================" << endl; +#define T2_THREADS 10 + NdbThread* threads[T2_THREADS]; + int args[T2_THREADS]; + void *status2 = 0; + test2mutex = NdbMutex_Create(); + NdbMutex_Lock(test2mutex); + + for (int i = 0; i < T2_THREADS; i++) + { + args[i] = i; + threads[i] = NdbThread_Create(test2func, // Function + (void**)&args[i],// Arg + 2048, // Stacksize + (char*)"test2thread", // Thread name + NDB_THREAD_PRIO_MEAN); // Thread priority + if (threads[i] == NULL) + fail("TEST2", "NdbThread_Create failed"); + } + + ndbout << "All threads created" << endl; + + NdbMutex_Unlock(test2mutex); + + for (int i = 0; i < T2_THREADS; i++) + { + if (NdbThread_WaitFor(threads[i], &status2)) + fail("TEST2", "NdbThread_WaitFor failed"); + + NdbThread_Destroy(&threads[i]); + // Don't test return values + // ndbout << "thread" << i << " returned, status = " << status2 << endl; + // if (status2 != i) + // fail("TEST2", "Wrong status"); + } + + if (NdbMutex_Lock(test2mutex) != 0) + fail("TEST2", "NdbMutex_Lock failed"); + if (NdbMutex_Unlock(test2mutex) != 0) + fail("TEST2", "NdbMutex_Unlock failed"); + if (NdbMutex_Destroy(test2mutex) != 0) + fail("TEST2", "NdbMutex_Destroy failed"); + ndbout << "TEST2 completed" << endl; + + ndbout << "= TEST3 ===============================" << endl; + // Create 10 threads that will by synchronised by a condition + // When they are awakened and have the mutex they will increment a global variable +#define T3_THREADS 10 + NdbThread* t3threads[T3_THREADS]; + int t3args[T3_THREADS]; + void *status3 = 0; + + testmutex = NdbMutex_Create(); + testcond = NdbCondition_Create(); + testthreadsdone = 0; + + for (int i = 0; i < T3_THREADS; i++) + { + t3args[i] = i; + t3threads[i] = NdbThread_Create(testfunc, // Function + (void**)&t3args[i],// Arg + 2048, // Stacksize + (char*)"test3thread", // Thread name + NDB_THREAD_PRIO_MEAN); // Thread priority + } + + ndbout << "All threads created" << endl; + + if (NdbMutex_Lock(testmutex) != 0) + fail("TEST3", "NdbMutex_Lock failed"); + + while (testthreadsdone < T3_THREADS*10) + { + if(NdbCondition_Wait(testcond, testmutex) != 0) + fail("TEST3", "NdbCondition_Wait failed"); + ndbout << "Condition signaled, there are " << testthreadsdone << " completed threads" << endl; + } + if (NdbMutex_Unlock(testmutex) != 0) + fail("TEST3", "NdbMutex_Unlock failed"); + + for (int i = 0; i < T3_THREADS; i++) + { + if (NdbThread_WaitFor(t3threads[i], &status3) != 0) + fail("TEST3", "NdbThread_WaitFor failed"); + + NdbThread_Destroy(&t3threads[i]); + //ndbout << "thread" << i << " returned, status = " << status3 << endl; + //if (status3 != i) + // fail("TEST3", "Wrong status"); + } + + NdbMutex_Destroy(testmutex); + NdbCondition_Destroy(testcond); + ndbout << "TEST3 completed" << endl; + + ndbout << "= TEST4 ===============================" << endl; + // Check tick functions + + //#if 0 + + int sleeptimes[] = {78, 12, 199, 567, 899}; + + + for (int i = 0; i < 5; i++) + { + ndbout << "*------------------------------- Measure" << i << endl; + + NDB_TICKS millisec_now; + NDB_TICKS millisec_now2; + + millisec_now = NdbTick_CurrentMillisecond(); + NdbSleep_MilliSleep(sleeptimes[i]); + millisec_now2 = NdbTick_CurrentMillisecond(); + + ndbout << " Time before sleep = " << millisec_now << endl; + ndbout << " Time after sleep = " << millisec_now2 << endl; + ndbout << " Tried to sleep "<<sleeptimes[i]<<" milliseconds." << endl; + ndbout << " Sleep time was " << millisec_now2 -millisec_now <<" milliseconds." << endl; + + } + + ndbout << "TEST4 completed" << endl; + + ndbout << "= TEST5 ===============================" << endl; + // Check NdbOut + + ndbout << "Testing hex and dec functions of NdbOut" << endl; + + for (int i = 0; i<= 0xFF; i++) + { + ndbout << i << "=" <<hex << i << "="<<dec << i << ", "; + } + + ndbout << endl<< "Testing that hex is reset to dec by endl" << endl; + ndbout << hex << 67 << endl; + ndbout << 67 << endl; + + ndbout << "TEST5 completed" << endl; + + + ndbout << "= TEST6 ===============================" << endl; + const char* theEnvHostNamePtr; + char buf[255]; + char theHostHostName[256]; + theEnvHostNamePtr = NdbEnv_GetEnv("HOSTNAME", buf, 255); + if(theEnvHostNamePtr == NULL) + fail("TEST6", "Could not get HOSTNAME from env"); + else{ + ndbout << "HOSTNAME from GetEnv" << theEnvHostNamePtr << endl; + + NdbHost_GetHostName(theHostHostName); + + ndbout << "HOSTNAME from GetHostName" <<theHostHostName << endl; + + if (strcmp(theEnvHostNamePtr, theHostHostName) != 0) + fail("TEST6", "NdbHost_GetHostName or NdbEnv_GetEnv failed"); + } + + ndbout << "= TEST7 ===============================" << endl; + + testmutex = NdbMutex_Create(); + testcond = NdbCondition_Create(); + testthreadsdone = 0; + + for (int i = 0; i < T3_THREADS; i++) + { + t3args[i] = i; + t3threads[i] = NdbThread_Create(testfunc, // Function + (void**)&t3args[i],// Arg + 2048, // Stacksize + (char*)"test7thread", // Thread name + NDB_THREAD_PRIO_MEAN); // Thread priority + } + + ndbout << "All threads created" << endl; + + if (NdbMutex_Lock(testmutex) != 0) + fail("TEST7", "NdbMutex_Lock failed"); + + while (testthreadsdone < T3_THREADS*10) + { + // just testing the functionality without timing out, therefor 20 sec. + if(NdbCondition_WaitTimeout(testcond, testmutex, 20000) != 0) + fail("TEST7", "NdbCondition_WaitTimeout failed"); + ndbout << "Condition signaled, there are " << testthreadsdone << " completed threads" << endl; + } + if (NdbMutex_Unlock(testmutex) != 0) + fail("TEST7", "NdbMutex_Unlock failed"); + + for (int i = 0; i < T3_THREADS; i++) + { + if (NdbThread_WaitFor(t3threads[i], &status3) != 0) + fail("TEST7", "NdbThread_WaitFor failed"); + + NdbThread_Destroy(&t3threads[i]); + } + + NdbMutex_Destroy(testmutex); + NdbCondition_Destroy(testcond); + + ndbout << "TEST7 completed" << endl; + + + ndbout << "= TEST8 ===============================" << endl; + ndbout << " NdbCondition_WaitTimeout" << endl; + testmutex = NdbMutex_Create(); + testcond = NdbCondition_Create(); + + for (int i = 0; i < 5; i++) + { + ndbout << "*------------------------------- Measure" << i << endl; + + NDB_TICKS millisec_now; + NDB_TICKS millisec_now2; + + millisec_now = NdbTick_CurrentMillisecond(); + if (NdbCondition_WaitTimeout(testcond, testmutex, sleeptimes[i]) != 0) + fail("TEST8", "NdbCondition_WaitTimeout failed"); + millisec_now2 = NdbTick_CurrentMillisecond(); + + ndbout << " Time before WaitTimeout = " << millisec_now << endl; + ndbout << " Time after WaitTimeout = " << millisec_now2 << endl; + ndbout << " Tried to wait "<<sleeptimes[i]<<" milliseconds." << endl; + ndbout << " Wait time was " << millisec_now2 -millisec_now <<" milliseconds." << endl; + + } + + ndbout << "TEST8 completed" << endl; + + + ndbout << "= TEST9 ===============================" << endl; + ndbout << " NdbTick_CurrentXXXXXsecond compare" << endl; + + for (int i = 0; i < 5; i++) + { + ndbout << "*------------------------------- Measure" << i << endl; + + NDB_TICKS millisec_now; + NDB_TICKS millisec_now2; + Uint32 usec_now, usec_now2; + Uint64 msec_now, msec_now2; + + + millisec_now = NdbTick_CurrentMillisecond(); + NdbTick_CurrentMicrosecond( &msec_now, &usec_now); + + NdbSleep_MilliSleep(sleeptimes[i]); + + millisec_now2 = NdbTick_CurrentMillisecond(); + NdbTick_CurrentMicrosecond( &msec_now2, &usec_now2); + + Uint64 usecdiff = time_diff(msec_now,msec_now2,usec_now,usec_now2); + NDB_TICKS msecdiff = millisec_now2 -millisec_now; + + ndbout << " Slept "<<sleeptimes[i]<<" milliseconds." << endl; + ndbout << " Measured " << msecdiff <<" milliseconds with milli function ." << endl; + ndbout << " Measured " << usecdiff/1000 << "," << usecdiff%1000<<" milliseconds with micro function ." << endl; + } + + ndbout << "TEST9 completed" << endl; + + + const int iter = 20; + ndbout << "Testing microsecond timer - " << iter << " iterations" << endl; + testMicros(iter); + ndbout << "Testing microsecond timer - COMPLETED" << endl; + +#if defined NDB_OSE || defined NDB_SOFTOSE + ndbout << "system_tick() = " << system_tick() << " us per tick" << endl; +#endif + + + ndbout << "= TEST10 ===============================" << endl; + + testmutex = NdbMutex_Create(); + testcond = NdbCondition_Create(); + testthreadsdone = 0; + + for (int i = 0; i < T3_THREADS; i++) + { + t3args[i] = i; + t3threads[i] = NdbThread_Create(testTryLockfunc, // Function + (void**)&t3args[i],// Arg + 2048, // Stacksize + (char*)"test10thread", // Thread name + NDB_THREAD_PRIO_MEAN); // Thread priority + } + + ndbout << "All threads created" << endl; + + if (NdbMutex_Lock(testmutex) != 0) + fail("TEST10", "NdbMutex_Lock failed"); + + while (testthreadsdone < T3_THREADS*10) + { + if(NdbCondition_Wait(testcond, testmutex) != 0) + fail("TEST10", "NdbCondition_WaitTimeout failed"); + ndbout << "Condition signaled, there are " << testthreadsdone << " completed threads" << endl; + } + if (NdbMutex_Unlock(testmutex) != 0) + fail("TEST10", "NdbMutex_Unlock failed"); + + for (int i = 0; i < T3_THREADS; i++) + { + if (NdbThread_WaitFor(t3threads[i], &status3) != 0) + fail("TEST10", "NdbThread_WaitFor failed"); + + NdbThread_Destroy(&t3threads[i]); + } + + NdbMutex_Destroy(testmutex); + NdbCondition_Destroy(testcond); + + ndbout << "TEST10 completed" << endl; + + + // Check total status of test + + if (TestHasFailed == 1) + ndbout << endl << "TEST FAILED!" << endl; + else + ndbout << endl << "TEST PASSED!" << endl; + + return TestHasFailed; + +}; + +Uint64 time_diff(Uint64 s1, Uint64 s2, Uint32 m1, Uint32 m2){ + + Uint64 diff = 0; + diff += (s2 - s1) * 1000000; + if(m2 >= m1) + diff += (m2 - m1); + else { + diff += m2; + diff -= m1; + } + + // if(0) + // ndbout("(s1,m1) = (%d, %d) (s2,m2) = (%d, %d) -> diff = %d\n", + // (Uint32)s1,m1,(Uint32)s2,m2, (Uint32)diff); + + return diff; +}; + +void +testMicros(int count){ + Uint32 avg = 0; + Uint32 sum2 = 0; + + for(int i = 0; i<count; i++){ + Uint64 s1, s2; + Uint32 m1, m2; + if(NdbTick_CurrentMicrosecond(&s1, &m1) != 0){ + ndbout << "Failed to get current micro" << endl; + TestHasFailed = 1; + return; + } + Uint32 r = (rand() % 1000) + 1; + NdbSleep_MilliSleep(r); + if(NdbTick_CurrentMicrosecond(&s2, &m2) != 0){ + ndbout << "Failed to get current micro" << endl; + TestHasFailed = 1; + return; + } + Uint64 m = time_diff(s1,s2,m1,m2); + if(verbose) + ndbout << "Slept for " << r << " ms" + << " - Measured " << m << " us" << endl; + + if(m > (r*1000)){ + avg += (m - (r*1000)); + sum2 += (m - (r*1000)) * (m - (r*1000)); + } else { + avg += ((r*1000) - m); + sum2 += ((r*1000) - m) * ((r*1000) - m); + } +#if 0 + m /= 1000; + if(m > r && ((m - r) > 10)){ + ndbout << "Difference to big: " << (m - r) << " - Test failed" << endl; + TestHasFailed = 1; + } + if(m < r && ((r - m) > 10)){ + ndbout << "Difference to big: " << (r - m) << " - Test failed" << endl; + TestHasFailed = 1; + } +#endif + } + + Uint32 dev = (avg * avg - sum2) / count; dev /= count; + avg /= count; + + Uint32 t = 0; + while((t*t)<dev) t++; + ndbout << "NOTE - measure are compared to NdbSleep_MilliSleep(...)" << endl; + ndbout << "Average error = " << avg << " us" << endl; + ndbout << "Stddev error = " << t << " us" << endl; +} |