vfs: check userland buffers before reading them.
[haiku.git] / src / tests / kits / support / blocker / ConcurrencyTest2.cpp
blob66e822af41ecfffefe3a212303f283be522514e9
1 /*
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"
18 #include "Locker.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
62 * threads.
65 void
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);
106 return(testSuite);
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());
121 NextSubTest();
122 snooze(SNOOZE_TIME);
123 NextSubTest();
124 theLocker->Unlock();
125 NextSubTest();
126 LockingLoop();
127 NextSubTest();
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)
144 bool timeoutLock;
145 bool result;
147 if (firstAcquisition) {
148 timeoutLock = ((lockAttempt % 2) == 1);
149 } else {
150 timeoutLock = (((lockAttempt / 2) % 2) == 1);
152 if (timeoutLock) {
153 result = (theLocker->LockWithTimeout(1000000) == B_OK);
154 } else {
155 result = theLocker->Lock();
157 return(result);
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);
173 NextSubTest();
174 CPPUNIT_ASSERT(theLocker->LockWithTimeout(SNOOZE_TIME/10) == B_TIMED_OUT);
175 NextSubTest();
176 LockingLoop();
177 NextSubTest();
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
190 * the lock.
191 * - The thread acquires the lock.
192 * - The thread confirms that mutual exclusion is OK by testing
193 * lockTestValue.
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)
207 int i;
208 SafetyLock theSafetyLock(theLocker);
210 for (i = 0; i < MAXLOOP; i++) {
211 CheckLock(0);
212 CPPUNIT_ASSERT(AcquireLock(i, true));
214 CPPUNIT_ASSERT(!lockTestValue);
215 lockTestValue = true;
216 CheckLock(1);
218 CPPUNIT_ASSERT(AcquireLock(i, false));
219 CheckLock(2);
221 theLocker->Unlock();
222 CheckLock(1);
224 CPPUNIT_ASSERT(lockTestValue);
225 lockTestValue = false;
226 theLocker->Unlock();
227 CheckLock(0);