1*83f04694STyler Dauwalder #include "RegistrarThreadManagerTest.h" 2*83f04694STyler Dauwalder 3*83f04694STyler Dauwalder #include <cppunit/Test.h> 4*83f04694STyler Dauwalder #include <cppunit/TestCaller.h> 5*83f04694STyler Dauwalder #include <cppunit/TestSuite.h> 6*83f04694STyler Dauwalder #include <TestApp.h> 7*83f04694STyler Dauwalder #include <TestUtils.h> 8*83f04694STyler Dauwalder 9*83f04694STyler Dauwalder #if !TEST_R5 10*83f04694STyler Dauwalder #include <RegistrarThread.h> 11*83f04694STyler Dauwalder #include <RegistrarThreadManager.h> 12*83f04694STyler Dauwalder #endif // !TEST_R5 13*83f04694STyler Dauwalder 14*83f04694STyler Dauwalder #include <stdio.h> 15*83f04694STyler Dauwalder 16*83f04694STyler Dauwalder // Suite 17*83f04694STyler Dauwalder CppUnit::Test* 18*83f04694STyler Dauwalder RegistrarThreadManagerTest::Suite() { 19*83f04694STyler Dauwalder CppUnit::TestSuite *suite = new CppUnit::TestSuite(); 20*83f04694STyler Dauwalder typedef CppUnit::TestCaller<RegistrarThreadManagerTest> TC; 21*83f04694STyler Dauwalder 22*83f04694STyler Dauwalder suite->addTest( new TC("RegistrarThreadManager::Shutdown test", 23*83f04694STyler Dauwalder &RegistrarThreadManagerTest::ShutdownTest) ); 24*83f04694STyler Dauwalder 25*83f04694STyler Dauwalder 26*83f04694STyler Dauwalder return suite; 27*83f04694STyler Dauwalder } 28*83f04694STyler Dauwalder 29*83f04694STyler Dauwalder #if !TEST_R5 30*83f04694STyler Dauwalder // Base test thread class 31*83f04694STyler Dauwalder class TestThread : public RegistrarThread { 32*83f04694STyler Dauwalder public: 33*83f04694STyler Dauwalder TestThread(const char *name, int32 priority, BMessenger managerMessenger) 34*83f04694STyler Dauwalder : RegistrarThread(name, priority, managerMessenger) 35*83f04694STyler Dauwalder { 36*83f04694STyler Dauwalder } 37*83f04694STyler Dauwalder 38*83f04694STyler Dauwalder void DoSomethingUseless() { 39*83f04694STyler Dauwalder fIntVal++; 40*83f04694STyler Dauwalder snooze(1000); 41*83f04694STyler Dauwalder } 42*83f04694STyler Dauwalder 43*83f04694STyler Dauwalder private: 44*83f04694STyler Dauwalder int64 fIntVal; 45*83f04694STyler Dauwalder }; 46*83f04694STyler Dauwalder 47*83f04694STyler Dauwalder // Test thread that terminates quickly 48*83f04694STyler Dauwalder class TerminatingThread : public TestThread { 49*83f04694STyler Dauwalder public: 50*83f04694STyler Dauwalder TerminatingThread(const char *name, int32 priority, BMessenger managerMessenger) 51*83f04694STyler Dauwalder : TestThread(name, priority, managerMessenger) 52*83f04694STyler Dauwalder { 53*83f04694STyler Dauwalder } 54*83f04694STyler Dauwalder 55*83f04694STyler Dauwalder protected: 56*83f04694STyler Dauwalder virtual status_t ThreadFunction() { 57*83f04694STyler Dauwalder DoSomethingUseless(); 58*83f04694STyler Dauwalder fIsFinished = true; 59*83f04694STyler Dauwalder return B_OK; 60*83f04694STyler Dauwalder } 61*83f04694STyler Dauwalder }; 62*83f04694STyler Dauwalder 63*83f04694STyler Dauwalder // Test thread that never terminates, but pays attention 64*83f04694STyler Dauwalder // to its fShouldExit member 65*83f04694STyler Dauwalder class WellBehavedInfiniteThread : public TestThread { 66*83f04694STyler Dauwalder public: 67*83f04694STyler Dauwalder WellBehavedInfiniteThread(const char *name, int32 priority, BMessenger managerMessenger) 68*83f04694STyler Dauwalder : TestThread(name, priority, managerMessenger) 69*83f04694STyler Dauwalder { 70*83f04694STyler Dauwalder } 71*83f04694STyler Dauwalder 72*83f04694STyler Dauwalder protected: 73*83f04694STyler Dauwalder virtual status_t ThreadFunction() { 74*83f04694STyler Dauwalder while (true) { 75*83f04694STyler Dauwalder DoSomethingUseless(); 76*83f04694STyler Dauwalder if (fShouldExit) 77*83f04694STyler Dauwalder break; 78*83f04694STyler Dauwalder } 79*83f04694STyler Dauwalder fIsFinished = true; 80*83f04694STyler Dauwalder return B_OK; 81*83f04694STyler Dauwalder } 82*83f04694STyler Dauwalder }; 83*83f04694STyler Dauwalder 84*83f04694STyler Dauwalder // Test thread that never terminates and completely ignores 85*83f04694STyler Dauwalder // its fShouldExit member 86*83f04694STyler Dauwalder class NaughtyInfiniteThread : public TestThread { 87*83f04694STyler Dauwalder public: 88*83f04694STyler Dauwalder NaughtyInfiniteThread(const char *name, int32 priority, BMessenger managerMessenger) 89*83f04694STyler Dauwalder : TestThread(name, priority, managerMessenger) 90*83f04694STyler Dauwalder { 91*83f04694STyler Dauwalder } 92*83f04694STyler Dauwalder 93*83f04694STyler Dauwalder protected: 94*83f04694STyler Dauwalder virtual status_t ThreadFunction() { 95*83f04694STyler Dauwalder while (true) { 96*83f04694STyler Dauwalder DoSomethingUseless(); 97*83f04694STyler Dauwalder } 98*83f04694STyler Dauwalder fIsFinished = true; 99*83f04694STyler Dauwalder return B_OK; 100*83f04694STyler Dauwalder } 101*83f04694STyler Dauwalder }; 102*83f04694STyler Dauwalder #endif // !TEST_R5 103*83f04694STyler Dauwalder 104*83f04694STyler Dauwalder 105*83f04694STyler Dauwalder // setUp 106*83f04694STyler Dauwalder void 107*83f04694STyler Dauwalder RegistrarThreadManagerTest::setUp() 108*83f04694STyler Dauwalder { 109*83f04694STyler Dauwalder BTestCase::setUp(); 110*83f04694STyler Dauwalder #if !TEST_R5 111*83f04694STyler Dauwalder // Setup our application 112*83f04694STyler Dauwalder fApplication = new BTestApp("application/x-vnd.obos.RegistrarThreadManagerTest"); 113*83f04694STyler Dauwalder if (fApplication->Init() != B_OK) { 114*83f04694STyler Dauwalder fprintf(stderr, "Failed to initialize application (perhaps the obos registrar isn't running?).\n"); 115*83f04694STyler Dauwalder delete fApplication; 116*83f04694STyler Dauwalder fApplication = NULL; 117*83f04694STyler Dauwalder } 118*83f04694STyler Dauwalder #endif // !TEST_R5 119*83f04694STyler Dauwalder } 120*83f04694STyler Dauwalder 121*83f04694STyler Dauwalder // tearDown 122*83f04694STyler Dauwalder void 123*83f04694STyler Dauwalder RegistrarThreadManagerTest::tearDown() 124*83f04694STyler Dauwalder { 125*83f04694STyler Dauwalder #if !TEST_R5 126*83f04694STyler Dauwalder // Terminate the Application 127*83f04694STyler Dauwalder if (fApplication) { 128*83f04694STyler Dauwalder fApplication->Terminate(); 129*83f04694STyler Dauwalder delete fApplication; 130*83f04694STyler Dauwalder fApplication = NULL; 131*83f04694STyler Dauwalder } 132*83f04694STyler Dauwalder #endif // !TEST_R5 133*83f04694STyler Dauwalder BTestCase::tearDown(); 134*83f04694STyler Dauwalder } 135*83f04694STyler Dauwalder 136*83f04694STyler Dauwalder void 137*83f04694STyler Dauwalder RegistrarThreadManagerTest::ShutdownTest() 138*83f04694STyler Dauwalder { 139*83f04694STyler Dauwalder #if TEST_R5 140*83f04694STyler Dauwalder Outputf("(no tests performed for R5 version)\n"); 141*83f04694STyler Dauwalder #else 142*83f04694STyler Dauwalder NextSubTest(); 143*83f04694STyler Dauwalder status_t err = B_OK; 144*83f04694STyler Dauwalder NextSubTest(); 145*83f04694STyler Dauwalder RegistrarThreadManager manager; 146*83f04694STyler Dauwalder NextSubTest(); 147*83f04694STyler Dauwalder CHK(fApplication && fApplication->InitCheck() == B_OK); 148*83f04694STyler Dauwalder NextSubTest(); 149*83f04694STyler Dauwalder // fApplication->AddHandler(&manager); 150*83f04694STyler Dauwalder NextSubTest(); 151*83f04694STyler Dauwalder BMessenger managerMessenger(NULL, fApplication, &err); 152*83f04694STyler Dauwalder NextSubTest(); 153*83f04694STyler Dauwalder CHK(err == B_OK && managerMessenger.IsValid()); 154*83f04694STyler Dauwalder NextSubTest(); 155*83f04694STyler Dauwalder 156*83f04694STyler Dauwalder // Launch a bunch of threads 157*83f04694STyler Dauwalder const uint termThreads = 2; 158*83f04694STyler Dauwalder const uint niceThreads = 2; 159*83f04694STyler Dauwalder const uint evilThreads = 2; 160*83f04694STyler Dauwalder 161*83f04694STyler Dauwalder for (uint i = 0; i < termThreads; i++) { 162*83f04694STyler Dauwalder NextSubTest(); 163*83f04694STyler Dauwalder char name[1024]; 164*83f04694STyler Dauwalder sprintf(name, "terminating #%d", i); 165*83f04694STyler Dauwalder RegistrarThread *thread = new TerminatingThread(name, B_NORMAL_PRIORITY, managerMessenger); 166*83f04694STyler Dauwalder CHK(thread != NULL); 167*83f04694STyler Dauwalder CHK(thread->InitCheck() == B_OK); 168*83f04694STyler Dauwalder CHK(manager.LaunchThread(thread) == B_OK); 169*83f04694STyler Dauwalder } 170*83f04694STyler Dauwalder 171*83f04694STyler Dauwalder for (uint i = 0; i < niceThreads; i++) { 172*83f04694STyler Dauwalder NextSubTest(); 173*83f04694STyler Dauwalder char name[1024]; 174*83f04694STyler Dauwalder sprintf(name, "nice #%d", i); 175*83f04694STyler Dauwalder RegistrarThread *thread = new WellBehavedInfiniteThread(name, B_NORMAL_PRIORITY, managerMessenger); 176*83f04694STyler Dauwalder CHK(thread != NULL); 177*83f04694STyler Dauwalder CHK(thread->InitCheck() == B_OK); 178*83f04694STyler Dauwalder CHK(manager.LaunchThread(thread) == B_OK); 179*83f04694STyler Dauwalder } 180*83f04694STyler Dauwalder 181*83f04694STyler Dauwalder for (uint i = 0; i < evilThreads; i++) { 182*83f04694STyler Dauwalder NextSubTest(); 183*83f04694STyler Dauwalder char name[1024]; 184*83f04694STyler Dauwalder sprintf(name, "evil #%d", i); 185*83f04694STyler Dauwalder RegistrarThread *thread = new NaughtyInfiniteThread(name, B_NORMAL_PRIORITY, managerMessenger); 186*83f04694STyler Dauwalder CHK(thread != NULL); 187*83f04694STyler Dauwalder CHK(thread->InitCheck() == B_OK); 188*83f04694STyler Dauwalder CHK(manager.LaunchThread(thread) == B_OK); 189*83f04694STyler Dauwalder } 190*83f04694STyler Dauwalder 191*83f04694STyler Dauwalder // Check the number of threads before doing a cleanup 192*83f04694STyler Dauwalder NextSubTest(); // <= 13 193*83f04694STyler Dauwalder CHK(manager.ThreadCount() == (termThreads + niceThreads + evilThreads)); 194*83f04694STyler Dauwalder 195*83f04694STyler Dauwalder // Do the cleanup and check again (the terminating threads 196*83f04694STyler Dauwalder // should be gone) 197*83f04694STyler Dauwalder NextSubTest(); 198*83f04694STyler Dauwalder snooze(500000); // give them time to terminate 199*83f04694STyler Dauwalder CHK(manager.CleanupThreads() == B_OK); 200*83f04694STyler Dauwalder CHK(manager.ThreadCount() == (niceThreads + evilThreads)); 201*83f04694STyler Dauwalder 202*83f04694STyler Dauwalder // Now do a shutdown and check again (the nice infinite threads 203*83f04694STyler Dauwalder // should be gone) 204*83f04694STyler Dauwalder NextSubTest(); 205*83f04694STyler Dauwalder CHK(manager.ShutdownThreads() == B_OK); 206*83f04694STyler Dauwalder snooze(1000000); // give them time to quit nicely 207*83f04694STyler Dauwalder CHK(manager.CleanupThreads() == B_OK); 208*83f04694STyler Dauwalder CHK(manager.ThreadCount() == evilThreads); 209*83f04694STyler Dauwalder 210*83f04694STyler Dauwalder 211*83f04694STyler Dauwalder // Now finally kill any remaining threads (which should rid us of 212*83f04694STyler Dauwalder // the naughty infinite threads) 213*83f04694STyler Dauwalder NextSubTest(); 214*83f04694STyler Dauwalder CHK(manager.KillThreads() == B_OK); 215*83f04694STyler Dauwalder CHK(manager.ThreadCount() == 0); 216*83f04694STyler Dauwalder 217*83f04694STyler Dauwalder #endif // !TEST_R5 218*83f04694STyler Dauwalder } 219*83f04694STyler Dauwalder 220