183f04694STyler Dauwalder #include "RegistrarThreadManagerTest.h" 283f04694STyler Dauwalder 383f04694STyler Dauwalder #include <cppunit/Test.h> 483f04694STyler Dauwalder #include <cppunit/TestCaller.h> 583f04694STyler Dauwalder #include <cppunit/TestSuite.h> 683f04694STyler Dauwalder #include <TestApp.h> 783f04694STyler Dauwalder #include <TestUtils.h> 883f04694STyler Dauwalder 983f04694STyler Dauwalder #if !TEST_R5 1083f04694STyler Dauwalder #include <RegistrarThread.h> 1183f04694STyler Dauwalder #include <RegistrarThreadManager.h> 1283f04694STyler Dauwalder #endif // !TEST_R5 1383f04694STyler Dauwalder 1483f04694STyler Dauwalder #include <stdio.h> 1583f04694STyler Dauwalder 1683f04694STyler Dauwalder // Suite 1783f04694STyler Dauwalder CppUnit::Test* 1883f04694STyler Dauwalder RegistrarThreadManagerTest::Suite() { 1983f04694STyler Dauwalder CppUnit::TestSuite *suite = new CppUnit::TestSuite(); 2083f04694STyler Dauwalder typedef CppUnit::TestCaller<RegistrarThreadManagerTest> TC; 2183f04694STyler Dauwalder 22*cc24797bSTyler Dauwalder suite->addTest( new TC("RegistrarThreadManager::Shutdown Test", 2383f04694STyler Dauwalder &RegistrarThreadManagerTest::ShutdownTest) ); 24*cc24797bSTyler Dauwalder suite->addTest( new TC("RegistrarThreadManager::Thread Limit Test", 25*cc24797bSTyler Dauwalder &RegistrarThreadManagerTest::ThreadLimitTest) ); 2683f04694STyler Dauwalder 2783f04694STyler Dauwalder 2883f04694STyler Dauwalder return suite; 2983f04694STyler Dauwalder } 3083f04694STyler Dauwalder 3183f04694STyler Dauwalder #if !TEST_R5 3283f04694STyler Dauwalder // Base test thread class 3383f04694STyler Dauwalder class TestThread : public RegistrarThread { 3483f04694STyler Dauwalder public: 3583f04694STyler Dauwalder TestThread(const char *name, int32 priority, BMessenger managerMessenger) 3683f04694STyler Dauwalder : RegistrarThread(name, priority, managerMessenger) 3783f04694STyler Dauwalder { 3883f04694STyler Dauwalder } 3983f04694STyler Dauwalder 4083f04694STyler Dauwalder void DoSomethingUseless() { 4183f04694STyler Dauwalder fIntVal++; 4283f04694STyler Dauwalder snooze(1000); 4383f04694STyler Dauwalder } 4483f04694STyler Dauwalder 4583f04694STyler Dauwalder private: 4683f04694STyler Dauwalder int64 fIntVal; 4783f04694STyler Dauwalder }; 4883f04694STyler Dauwalder 4983f04694STyler Dauwalder // Test thread that terminates quickly 5083f04694STyler Dauwalder class TerminatingThread : public TestThread { 5183f04694STyler Dauwalder public: 5283f04694STyler Dauwalder TerminatingThread(const char *name, int32 priority, BMessenger managerMessenger) 5383f04694STyler Dauwalder : TestThread(name, priority, managerMessenger) 5483f04694STyler Dauwalder { 5583f04694STyler Dauwalder } 5683f04694STyler Dauwalder 5783f04694STyler Dauwalder protected: 5883f04694STyler Dauwalder virtual status_t ThreadFunction() { 5983f04694STyler Dauwalder DoSomethingUseless(); 6083f04694STyler Dauwalder fIsFinished = true; 6183f04694STyler Dauwalder return B_OK; 6283f04694STyler Dauwalder } 6383f04694STyler Dauwalder }; 6483f04694STyler Dauwalder 6583f04694STyler Dauwalder // Test thread that never terminates, but pays attention 6683f04694STyler Dauwalder // to its fShouldExit member 6783f04694STyler Dauwalder class WellBehavedInfiniteThread : public TestThread { 6883f04694STyler Dauwalder public: 6983f04694STyler Dauwalder WellBehavedInfiniteThread(const char *name, int32 priority, BMessenger managerMessenger) 7083f04694STyler Dauwalder : TestThread(name, priority, managerMessenger) 7183f04694STyler Dauwalder { 7283f04694STyler Dauwalder } 7383f04694STyler Dauwalder 7483f04694STyler Dauwalder protected: 7583f04694STyler Dauwalder virtual status_t ThreadFunction() { 7683f04694STyler Dauwalder while (true) { 7783f04694STyler Dauwalder DoSomethingUseless(); 7883f04694STyler Dauwalder if (fShouldExit) 7983f04694STyler Dauwalder break; 8083f04694STyler Dauwalder } 8183f04694STyler Dauwalder fIsFinished = true; 8283f04694STyler Dauwalder return B_OK; 8383f04694STyler Dauwalder } 8483f04694STyler Dauwalder }; 8583f04694STyler Dauwalder 8683f04694STyler Dauwalder // Test thread that never terminates and completely ignores 8783f04694STyler Dauwalder // its fShouldExit member 8883f04694STyler Dauwalder class NaughtyInfiniteThread : public TestThread { 8983f04694STyler Dauwalder public: 9083f04694STyler Dauwalder NaughtyInfiniteThread(const char *name, int32 priority, BMessenger managerMessenger) 9183f04694STyler Dauwalder : TestThread(name, priority, managerMessenger) 9283f04694STyler Dauwalder { 9383f04694STyler Dauwalder } 9483f04694STyler Dauwalder 9583f04694STyler Dauwalder protected: 9683f04694STyler Dauwalder virtual status_t ThreadFunction() { 9783f04694STyler Dauwalder while (true) { 9883f04694STyler Dauwalder DoSomethingUseless(); 9983f04694STyler Dauwalder } 10083f04694STyler Dauwalder fIsFinished = true; 10183f04694STyler Dauwalder return B_OK; 10283f04694STyler Dauwalder } 10383f04694STyler Dauwalder }; 10483f04694STyler Dauwalder #endif // !TEST_R5 10583f04694STyler Dauwalder 10683f04694STyler Dauwalder 10783f04694STyler Dauwalder // setUp 10883f04694STyler Dauwalder void 10983f04694STyler Dauwalder RegistrarThreadManagerTest::setUp() 11083f04694STyler Dauwalder { 11183f04694STyler Dauwalder BTestCase::setUp(); 11283f04694STyler Dauwalder #if !TEST_R5 11383f04694STyler Dauwalder // Setup our application 11483f04694STyler Dauwalder fApplication = new BTestApp("application/x-vnd.obos.RegistrarThreadManagerTest"); 11583f04694STyler Dauwalder if (fApplication->Init() != B_OK) { 11683f04694STyler Dauwalder fprintf(stderr, "Failed to initialize application (perhaps the obos registrar isn't running?).\n"); 11783f04694STyler Dauwalder delete fApplication; 11883f04694STyler Dauwalder fApplication = NULL; 11983f04694STyler Dauwalder } 12083f04694STyler Dauwalder #endif // !TEST_R5 12183f04694STyler Dauwalder } 12283f04694STyler Dauwalder 12383f04694STyler Dauwalder // tearDown 12483f04694STyler Dauwalder void 12583f04694STyler Dauwalder RegistrarThreadManagerTest::tearDown() 12683f04694STyler Dauwalder { 12783f04694STyler Dauwalder #if !TEST_R5 12883f04694STyler Dauwalder // Terminate the Application 12983f04694STyler Dauwalder if (fApplication) { 13083f04694STyler Dauwalder fApplication->Terminate(); 13183f04694STyler Dauwalder delete fApplication; 13283f04694STyler Dauwalder fApplication = NULL; 13383f04694STyler Dauwalder } 13483f04694STyler Dauwalder #endif // !TEST_R5 13583f04694STyler Dauwalder BTestCase::tearDown(); 13683f04694STyler Dauwalder } 13783f04694STyler Dauwalder 13883f04694STyler Dauwalder void 13983f04694STyler Dauwalder RegistrarThreadManagerTest::ShutdownTest() 14083f04694STyler Dauwalder { 14183f04694STyler Dauwalder #if TEST_R5 14283f04694STyler Dauwalder Outputf("(no tests performed for R5 version)\n"); 14383f04694STyler Dauwalder #else 14483f04694STyler Dauwalder NextSubTest(); 14583f04694STyler Dauwalder status_t err = B_OK; 14683f04694STyler Dauwalder NextSubTest(); 14783f04694STyler Dauwalder RegistrarThreadManager manager; 14883f04694STyler Dauwalder NextSubTest(); 14983f04694STyler Dauwalder CHK(fApplication && fApplication->InitCheck() == B_OK); 15083f04694STyler Dauwalder NextSubTest(); 15183f04694STyler Dauwalder // fApplication->AddHandler(&manager); 15283f04694STyler Dauwalder NextSubTest(); 15383f04694STyler Dauwalder BMessenger managerMessenger(NULL, fApplication, &err); 15483f04694STyler Dauwalder NextSubTest(); 15583f04694STyler Dauwalder CHK(err == B_OK && managerMessenger.IsValid()); 15683f04694STyler Dauwalder NextSubTest(); 15783f04694STyler Dauwalder 15883f04694STyler Dauwalder // Launch a bunch of threads 15983f04694STyler Dauwalder const uint termThreads = 2; 16083f04694STyler Dauwalder const uint niceThreads = 2; 16183f04694STyler Dauwalder const uint evilThreads = 2; 16283f04694STyler Dauwalder 16383f04694STyler Dauwalder for (uint i = 0; i < termThreads; i++) { 16483f04694STyler Dauwalder NextSubTest(); 16583f04694STyler Dauwalder char name[1024]; 16683f04694STyler Dauwalder sprintf(name, "terminating #%d", i); 16783f04694STyler Dauwalder RegistrarThread *thread = new TerminatingThread(name, B_NORMAL_PRIORITY, managerMessenger); 16883f04694STyler Dauwalder CHK(thread != NULL); 16983f04694STyler Dauwalder CHK(thread->InitCheck() == B_OK); 17083f04694STyler Dauwalder CHK(manager.LaunchThread(thread) == B_OK); 17183f04694STyler Dauwalder } 17283f04694STyler Dauwalder 17383f04694STyler Dauwalder for (uint i = 0; i < niceThreads; i++) { 17483f04694STyler Dauwalder NextSubTest(); 17583f04694STyler Dauwalder char name[1024]; 17683f04694STyler Dauwalder sprintf(name, "nice #%d", i); 17783f04694STyler Dauwalder RegistrarThread *thread = new WellBehavedInfiniteThread(name, B_NORMAL_PRIORITY, managerMessenger); 17883f04694STyler Dauwalder CHK(thread != NULL); 17983f04694STyler Dauwalder CHK(thread->InitCheck() == B_OK); 18083f04694STyler Dauwalder CHK(manager.LaunchThread(thread) == B_OK); 18183f04694STyler Dauwalder } 18283f04694STyler Dauwalder 18383f04694STyler Dauwalder for (uint i = 0; i < evilThreads; i++) { 18483f04694STyler Dauwalder NextSubTest(); 18583f04694STyler Dauwalder char name[1024]; 18683f04694STyler Dauwalder sprintf(name, "evil #%d", i); 18783f04694STyler Dauwalder RegistrarThread *thread = new NaughtyInfiniteThread(name, B_NORMAL_PRIORITY, managerMessenger); 18883f04694STyler Dauwalder CHK(thread != NULL); 18983f04694STyler Dauwalder CHK(thread->InitCheck() == B_OK); 19083f04694STyler Dauwalder CHK(manager.LaunchThread(thread) == B_OK); 19183f04694STyler Dauwalder } 19283f04694STyler Dauwalder 19383f04694STyler Dauwalder // Check the number of threads before doing a cleanup 19483f04694STyler Dauwalder NextSubTest(); // <= 13 19583f04694STyler Dauwalder CHK(manager.ThreadCount() == (termThreads + niceThreads + evilThreads)); 19683f04694STyler Dauwalder 19783f04694STyler Dauwalder // Do the cleanup and check again (the terminating threads 19883f04694STyler Dauwalder // should be gone) 19983f04694STyler Dauwalder NextSubTest(); 20083f04694STyler Dauwalder snooze(500000); // give them time to terminate 20183f04694STyler Dauwalder CHK(manager.CleanupThreads() == B_OK); 20283f04694STyler Dauwalder CHK(manager.ThreadCount() == (niceThreads + evilThreads)); 20383f04694STyler Dauwalder 20483f04694STyler Dauwalder // Now do a shutdown and check again (the nice infinite threads 20583f04694STyler Dauwalder // should be gone) 20683f04694STyler Dauwalder NextSubTest(); 20783f04694STyler Dauwalder CHK(manager.ShutdownThreads() == B_OK); 20883f04694STyler Dauwalder snooze(1000000); // give them time to quit nicely 20983f04694STyler Dauwalder CHK(manager.CleanupThreads() == B_OK); 21083f04694STyler Dauwalder CHK(manager.ThreadCount() == evilThreads); 21183f04694STyler Dauwalder 21283f04694STyler Dauwalder 21383f04694STyler Dauwalder // Now finally kill any remaining threads (which should rid us of 21483f04694STyler Dauwalder // the naughty infinite threads) 21583f04694STyler Dauwalder NextSubTest(); 21683f04694STyler Dauwalder CHK(manager.KillThreads() == B_OK); 21783f04694STyler Dauwalder CHK(manager.ThreadCount() == 0); 21883f04694STyler Dauwalder 21983f04694STyler Dauwalder #endif // !TEST_R5 22083f04694STyler Dauwalder } 22183f04694STyler Dauwalder 222*cc24797bSTyler Dauwalder void 223*cc24797bSTyler Dauwalder RegistrarThreadManagerTest::ThreadLimitTest() 224*cc24797bSTyler Dauwalder { 225*cc24797bSTyler Dauwalder #if TEST_R5 226*cc24797bSTyler Dauwalder Outputf("(no tests performed for R5 version)\n"); 227*cc24797bSTyler Dauwalder #else 228*cc24797bSTyler Dauwalder NextSubTest(); 229*cc24797bSTyler Dauwalder status_t err = B_OK; 230*cc24797bSTyler Dauwalder RegistrarThreadManager manager; 231*cc24797bSTyler Dauwalder CHK(fApplication && fApplication->InitCheck() == B_OK); 232*cc24797bSTyler Dauwalder BMessenger managerMessenger(NULL, fApplication, &err); 233*cc24797bSTyler Dauwalder CHK(err == B_OK && managerMessenger.IsValid()); 234*cc24797bSTyler Dauwalder 235*cc24797bSTyler Dauwalder const uint termThreads = 2; 236*cc24797bSTyler Dauwalder 237*cc24797bSTyler Dauwalder // This test is only useful if the thread limit of the manager 238*cc24797bSTyler Dauwalder // class is > kTermThreads 239*cc24797bSTyler Dauwalder CHK(termThreads < RegistrarThreadManager::kThreadLimit); 240*cc24797bSTyler Dauwalder 241*cc24797bSTyler Dauwalder // Launch some terminating threads 242*cc24797bSTyler Dauwalder uint i; 243*cc24797bSTyler Dauwalder for (i = 0; i < termThreads; i++) { 244*cc24797bSTyler Dauwalder NextSubTest(); 245*cc24797bSTyler Dauwalder char name[1024]; 246*cc24797bSTyler Dauwalder sprintf(name, "terminating #%d", i); 247*cc24797bSTyler Dauwalder RegistrarThread *thread = new TerminatingThread(name, B_NORMAL_PRIORITY, managerMessenger); 248*cc24797bSTyler Dauwalder CHK(thread != NULL); 249*cc24797bSTyler Dauwalder CHK(thread->InitCheck() == B_OK); 250*cc24797bSTyler Dauwalder CHK(manager.LaunchThread(thread) == B_OK); 251*cc24797bSTyler Dauwalder } 252*cc24797bSTyler Dauwalder 253*cc24797bSTyler Dauwalder // Now fill up the manager with non-terminating threads 254*cc24797bSTyler Dauwalder for (; i < RegistrarThreadManager::kThreadLimit; i++) { 255*cc24797bSTyler Dauwalder NextSubTest(); 256*cc24797bSTyler Dauwalder char name[1024]; 257*cc24797bSTyler Dauwalder sprintf(name, "nice #%d", i); 258*cc24797bSTyler Dauwalder RegistrarThread *thread = new WellBehavedInfiniteThread(name, B_NORMAL_PRIORITY, managerMessenger); 259*cc24797bSTyler Dauwalder CHK(thread != NULL); 260*cc24797bSTyler Dauwalder CHK(thread->InitCheck() == B_OK); 261*cc24797bSTyler Dauwalder CHK(manager.LaunchThread(thread) == B_OK); 262*cc24797bSTyler Dauwalder } 263*cc24797bSTyler Dauwalder CHK(manager.ThreadCount() == RegistrarThreadManager::kThreadLimit); 264*cc24797bSTyler Dauwalder 265*cc24797bSTyler Dauwalder // Now try to launch just one more... 266*cc24797bSTyler Dauwalder NextSubTest(); 267*cc24797bSTyler Dauwalder { 268*cc24797bSTyler Dauwalder char *name = "hopeless thread"; 269*cc24797bSTyler Dauwalder RegistrarThread *thread = new WellBehavedInfiniteThread(name, B_NORMAL_PRIORITY, managerMessenger); 270*cc24797bSTyler Dauwalder CHK(thread != NULL); 271*cc24797bSTyler Dauwalder CHK(thread->InitCheck() == B_OK); 272*cc24797bSTyler Dauwalder CHK(manager.LaunchThread(thread) == B_NO_MORE_THREADS); 273*cc24797bSTyler Dauwalder delete thread; 274*cc24797bSTyler Dauwalder } 275*cc24797bSTyler Dauwalder 276*cc24797bSTyler Dauwalder // Now wait a little bit for our terminating threads to quit, 277*cc24797bSTyler Dauwalder // cleanup after them, and make sure we can now launch that 278*cc24797bSTyler Dauwalder // many threads again 279*cc24797bSTyler Dauwalder NextSubTest(); 280*cc24797bSTyler Dauwalder snooze(500000); 281*cc24797bSTyler Dauwalder manager.CleanupThreads(); 282*cc24797bSTyler Dauwalder 283*cc24797bSTyler Dauwalder for (i = 0; i < termThreads; i++) { 284*cc24797bSTyler Dauwalder NextSubTest(); 285*cc24797bSTyler Dauwalder char name[1024]; 286*cc24797bSTyler Dauwalder sprintf(name, "2nd round nice #%d", i); 287*cc24797bSTyler Dauwalder RegistrarThread *thread = new TerminatingThread(name, B_NORMAL_PRIORITY, managerMessenger); 288*cc24797bSTyler Dauwalder CHK(thread != NULL); 289*cc24797bSTyler Dauwalder CHK(thread->InitCheck() == B_OK); 290*cc24797bSTyler Dauwalder CHK(manager.LaunchThread(thread) == B_OK); 291*cc24797bSTyler Dauwalder } 292*cc24797bSTyler Dauwalder 293*cc24797bSTyler Dauwalder // Now try once more to launch just one more... 294*cc24797bSTyler Dauwalder NextSubTest(); 295*cc24797bSTyler Dauwalder { 296*cc24797bSTyler Dauwalder char *name = "hopeless thread"; 297*cc24797bSTyler Dauwalder RegistrarThread *thread = new WellBehavedInfiniteThread(name, B_NORMAL_PRIORITY, managerMessenger); 298*cc24797bSTyler Dauwalder CHK(thread != NULL); 299*cc24797bSTyler Dauwalder CHK(thread->InitCheck() == B_OK); 300*cc24797bSTyler Dauwalder CHK(manager.LaunchThread(thread) == B_NO_MORE_THREADS); 301*cc24797bSTyler Dauwalder delete thread; 302*cc24797bSTyler Dauwalder } 303*cc24797bSTyler Dauwalder 304*cc24797bSTyler Dauwalder // Cleanup 305*cc24797bSTyler Dauwalder NextSubTest(); 306*cc24797bSTyler Dauwalder manager.ShutdownThreads(); 307*cc24797bSTyler Dauwalder snooze(500000); 308*cc24797bSTyler Dauwalder 309*cc24797bSTyler Dauwalder #endif // !TEST_R5 310*cc24797bSTyler Dauwalder } 311