2 $Id: ConcurrencyTest2.cpp 301 2002-07-18 05:32:00Z tylerdauwalder $
4 This file implements a test class for testing BLocker functionality.
5 It tests use cases "Locking 1", "Locking 2", "Unlocking", "Is Locked",
6 "Locking Thread" and "Count Locks". It is essentially the same as Test1.cpp
7 except it makes the first LockWithTimeout inside the threads timeout. The
8 reason for this is because the implementation of BLocker by Be and with OpenBeOS
9 is such that after one timeout occurs on a benaphore style BLocker, the lock
10 effectively becomes a semaphore style BLocker. This test tests that condition.
15 #include "ThreadedTestCaller.h"
16 #include "ConcurrencyTest2.h"
17 #include "cppunit/TestSuite.h"
21 // This constant indicates the number of times the thread should test the
22 // acquisition and release of the BLocker.
24 const int32 MAXLOOP
= 10000;
26 // This constant is used to determine the number of microseconds to
27 // sleep during major steps of the test.
29 const bigtime_t SNOOZE_TIME
= 200000;
32 * Method: ConcurrencyTest2::ConcurrencyTest2()
33 * Descr: This is the only constructor for this test case. It takes a
34 * test name and a flag to indicate whether to test a benaphore
35 * or semaphore type BLocker.
39 ConcurrencyTest2::ConcurrencyTest2(std::string name
, bool benaphoreFlag
) :
40 LockerTestCase(name
, benaphoreFlag
), lockTestValue(false)
46 * Method: ConcurrencyTest2::~ConcurrencyTest2()
47 * Descr: This is the descriptor for this test case.
51 ConcurrencyTest2::~ConcurrencyTest2()
57 * Method: ConcurrencyTest2::setUp()
58 * Descr: This member is called before starting the actual test threads
59 * and is used to ensure that the class is initialized for the
60 * testing. It just sets the "lockTestValue" flag to false. This
61 * flag is used to show that there is mutual exclusion between the
66 ConcurrencyTest2::setUp(void)
68 lockTestValue
= false;
73 * Method: ConcurrencyTest2::suite()
74 * Descr: This static member function returns a test suite for performing
75 * all combinations of "ConcurrencyTest2". The test suite contains
76 * two instances of the test. One is performed on a benaphore,
77 * the other on a semaphore based BLocker. Each individual test
78 * is created as a ThreadedTestCase (typedef'd as
79 * ConcurrencyTest2Caller) with three independent threads.
82 CppUnit::Test
*ConcurrencyTest2::suite(void)
84 typedef BThreadedTestCaller
<ConcurrencyTest2
>
85 ConcurrencyTest2Caller
;
86 CppUnit::TestSuite
*testSuite
= new CppUnit::TestSuite("ConcurrencyTest2");
88 // Make a benaphore based test object, create a ThreadedTestCase for it and add
89 // three threads to it.
90 ConcurrencyTest2
*theTest
= new ConcurrencyTest2("Benaphore", true);
91 ConcurrencyTest2Caller
*threadedTest1
= new ConcurrencyTest2Caller("BLocker::Concurrency Test #2 (benaphore)", theTest
);
92 threadedTest1
->addThread("Acquire", &ConcurrencyTest2::AcquireThread
);
93 threadedTest1
->addThread("Timeout1", &ConcurrencyTest2::TimeoutThread
);
94 threadedTest1
->addThread("Timeout2", &ConcurrencyTest2::TimeoutThread
);
96 // Make a semaphore based test object, create a ThreadedTestCase for it and add
97 // three threads to it.
98 theTest
= new ConcurrencyTest2("Semaphore", false);
99 ConcurrencyTest2Caller
*threadedTest2
= new ConcurrencyTest2Caller("BLocker::Concurrency Test #2 (semaphore)", theTest
);
100 threadedTest2
->addThread("Acquire", &ConcurrencyTest2::AcquireThread
);
101 threadedTest2
->addThread("Timeout1", &ConcurrencyTest2::TimeoutThread
);
102 threadedTest2
->addThread("Timeout2", &ConcurrencyTest2::TimeoutThread
);
104 testSuite
->addTest(threadedTest1
);
105 testSuite
->addTest(threadedTest2
);
111 * Method: ConcurrencyTest2::AcquireThread()
112 * Descr: This member function acquires the lock, sleeps for SNOOZE_TIME,
113 * releases the lock and then launches into the lock loop test.
116 void ConcurrencyTest2::AcquireThread(void)
118 SafetyLock
theSafetyLock(theLocker
);
120 CPPUNIT_ASSERT(theLocker
->Lock());
132 * Method: ConcurrencyTest2::AcquireLock()
133 * Descr: This member function is passed the number of times through the
134 * acquisition loop (lockAttempt) and whether or not this is
135 * the first acquisition of the lock within this iteration.
136 * Based on these values, it may do a LockWithTimeout() or just
137 * a plain Lock() on theLocker. This is done to get coverage of
138 * both lock acquisition methods on the BLocker.
141 bool ConcurrencyTest2::AcquireLock(int lockAttempt
,
142 bool firstAcquisition
)
147 if (firstAcquisition
) {
148 timeoutLock
= ((lockAttempt
% 2) == 1);
150 timeoutLock
= (((lockAttempt
/ 2) % 2) == 1);
153 result
= (theLocker
->LockWithTimeout(1000000) == B_OK
);
155 result
= theLocker
->Lock();
162 * Method: ConcurrencyTest2::TimeoutThread()
163 * Descr: This member function sleeps for a short time and then attempts to
164 * acquire the lock for SNOOZE_TIME/10 seconds. This acquisition
165 * should timeout. Then the locking loop is started.
168 void ConcurrencyTest2::TimeoutThread(void)
170 SafetyLock
theSafetyLock(theLocker
);
172 snooze(SNOOZE_TIME
/2);
174 CPPUNIT_ASSERT(theLocker
->LockWithTimeout(SNOOZE_TIME
/10) == B_TIMED_OUT
);
182 * Method: ConcurrencyTest2::TestThread()
183 * Descr: This method is the core of the test. Each of the three threads
184 * run this method to perform the concurrency test. First, the
185 * SafetyLock class (see LockerTestCase.h) is used to make sure that
186 * the lock is released if an assertion happens. Then, each thread
187 * iterates MAXLOOP times through the main loop where the following
188 * actions are performed:
189 * - CheckLock() is used to show that the thread does not have
191 * - The thread acquires the lock.
192 * - The thread confirms that mutual exclusion is OK by testing
194 * - The thread confirms the lock is held once by the thread.
195 * - The thread acquires the lock again.
196 * - The thread confirms the lock is held twice now by the thread.
197 * - The thread releases the lock once.
198 * - The thread confirms the lock is held once now.
199 * - The thread confirms that mutual exclusion is still OK by
200 * testing lockTestValue.
201 * - The thread releases the lock again.
202 * - The thread confirms that the lock is no longer held.
205 void ConcurrencyTest2::LockingLoop(void)
208 SafetyLock
theSafetyLock(theLocker
);
210 for (i
= 0; i
< MAXLOOP
; i
++) {
212 CPPUNIT_ASSERT(AcquireLock(i
, true));
214 CPPUNIT_ASSERT(!lockTestValue
);
215 lockTestValue
= true;
218 CPPUNIT_ASSERT(AcquireLock(i
, false));
224 CPPUNIT_ASSERT(lockTestValue
);
225 lockTestValue
= false;