1 /* 2 $Id: DestructionTest2.cpp 301 2002-07-18 05:32:00Z tylerdauwalder $ 3 4 This file implements a test class for testing BLocker functionality. 5 It tests use cases "Destruction" and "Locking 4". 6 7 The test works like the following: 8 - the main thread acquires the lock 9 - it creates a new thread and sleeps 10 - the new thread attempts to acquire the lock but times out 11 - the new thread then attempts to acquire the lock again 12 - before the new thread times out a second time, the first thread releases 13 the lock 14 - at this time, the new thread acquires the lock and goes to sleep 15 - the first thread attempts to acquire the lock 16 - the second thread deletes the lock 17 - the first thread is woken up indicating that the lock wasn't acquired. 18 19 */ 20 21 22 #include <ThreadedTestCaller.h> 23 #include "DestructionTest2.h" 24 #include <cppunit/TestSuite.h> 25 #include <Locker.h> 26 27 // This constant is used to determine the number of microseconds to 28 // sleep during major steps of the test. 29 30 const bigtime_t SNOOZE_TIME = 200000; 31 32 33 /* 34 * Method: DestructionTest2::DestructionTest2() 35 * Descr: This is the only constructor for this test class. 36 */ 37 38 39 DestructionTest2::DestructionTest2(std::string name, 40 bool isBenaphore) : 41 LockerTestCase(name, isBenaphore) 42 { 43 } 44 45 46 /* 47 * Method: DestructionTest2::~DestructionTest2() 48 * Descr: This is the only destructor for this test class. 49 */ 50 51 52 DestructionTest2::~DestructionTest2() 53 { 54 } 55 56 57 /* 58 * Method: DestructionTest2::TestThread1() 59 * Descr: This method immediately acquires the lock, sleeps 60 * for SNOOZE_TIME and then releases the lock. It sleeps 61 * again for SNOOZE_TIME and then tries to re-acquire the 62 * lock. By this time, the other thread should have 63 * deleted the lock. This acquisition should fail. 64 */ 65 66 void DestructionTest2::TestThread1(void) 67 { 68 CPPUNIT_ASSERT(theLocker->LockWithTimeout(SNOOZE_TIME) == B_OK); 69 NextSubTest(); 70 snooze(SNOOZE_TIME); 71 NextSubTest(); 72 theLocker->Unlock(); 73 NextSubTest(); 74 snooze(SNOOZE_TIME); 75 NextSubTest(); 76 CPPUNIT_ASSERT(theLocker->LockWithTimeout(SNOOZE_TIME * 10) == B_BAD_SEM_ID); 77 NextSubTest(); 78 } 79 80 81 /* 82 * Method: DestructionTest2::TestThread2() 83 * Descr: This method sleeps for SNOOZE_TIME/10 and then attempts to acquire 84 * the lock for SNOOZE_TIME/10 seconds. This acquisition will timeout 85 * because the other thread is holding the lock. Then it acquires the 86 * lock by using a larger timeout. It sleeps again for 2*SNOOZE_TIME and 87 * then deletes the lock. This should wake up the other thread. 88 */ 89 90 void DestructionTest2::TestThread2(void) 91 { 92 BLocker *tmpLock; 93 94 snooze(SNOOZE_TIME/10); 95 NextSubTest(); 96 CPPUNIT_ASSERT(theLocker->LockWithTimeout(SNOOZE_TIME / 10) == B_TIMED_OUT); 97 NextSubTest(); 98 CPPUNIT_ASSERT(theLocker->LockWithTimeout(SNOOZE_TIME * 10) == B_OK); 99 NextSubTest(); 100 snooze(SNOOZE_TIME); 101 NextSubTest(); 102 snooze(SNOOZE_TIME); 103 NextSubTest(); 104 tmpLock = theLocker; 105 theLocker = NULL; 106 delete tmpLock; 107 } 108 109 110 /* 111 * Method: DestructionTest2::suite() 112 * Descr: This static member function returns a test suite for performing 113 * all combinations of "DestructionTest2". The test suite contains 114 * two instances of the test. One is performed on a benaphore, 115 * the other on a semaphore based BLocker. Each individual test 116 * is created as a ThreadedTestCase (typedef'd as 117 * DestructionTest2Caller) with two independent threads. 118 */ 119 120 CppUnit::Test *DestructionTest2::suite(void) 121 { 122 typedef BThreadedTestCaller<DestructionTest2> DestructionTest2Caller; 123 CppUnit::TestSuite *testSuite = new CppUnit::TestSuite("DestructionTest2"); 124 125 // Make a benaphore based test object, create a ThreadedTestCase for it and add 126 // two threads to it. 127 DestructionTest2 *theTest = new DestructionTest2("Benaphore", true); 128 DestructionTest2Caller *threadedTest1 = new DestructionTest2Caller("BLocker::Destruction Test #2 (benaphore)", theTest); 129 threadedTest1->addThread("A", &DestructionTest2::TestThread1); 130 threadedTest1->addThread("B", &DestructionTest2::TestThread2); 131 132 // Make a semaphore based test object, create a ThreadedTestCase for it and add 133 // three threads to it. 134 theTest = new DestructionTest2("Semaphore", false); 135 DestructionTest2Caller *threadedTest2 = new DestructionTest2Caller("BLocker::Destruction Test #2 (semaphore)", theTest); 136 threadedTest2->addThread("A", &DestructionTest2::TestThread1); 137 threadedTest2->addThread("B", &DestructionTest2::TestThread2); 138 139 testSuite->addTest(threadedTest1); 140 testSuite->addTest(threadedTest2); 141 return(testSuite); 142 } 143 144 145 146 147