vfs: check userland buffers before reading them.
[haiku.git] / src / tests / kits / support / blocker / ConcurrencyTest1.cpp
blobf0716ae7ebe8a0ce52c90819bc5de1cf58dd26d1
1 /*
2 $Id: ConcurrencyTest1.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".
8 */
11 #include <ThreadedTestCaller.h>
12 #include "ConcurrencyTest1.h"
13 #include <cppunit/TestSuite.h>
14 #include <Locker.h>
17 // This constant indicates the number of times the thread should test the
18 // acquisition and release of the BLocker.
20 const int32 MAXLOOP = 10000;
24 * Method: ConcurrencyTest1::ConcurrencyTest1()
25 * Descr: This is the only constructor for this test case. It takes a
26 * test name and a flag to indicate whether to test a benaphore
27 * or semaphore type BLocker.
31 ConcurrencyTest1::ConcurrencyTest1(std::string name, bool benaphoreFlag) :
32 LockerTestCase(name, benaphoreFlag), lockTestValue(false)
38 * Method: ConcurrencyTest1::~ConcurrencyTest1()
39 * Descr: This is the descriptor for this test case.
43 ConcurrencyTest1::~ConcurrencyTest1()
49 * Method: ConcurrencyTest1::setUp()
50 * Descr: This member is called before starting the actual test threads
51 * and is used to ensure that the class is initialized for the
52 * testing. It just sets the "lockTestValue" flag to false. This
53 * flag is used to show that there is mutual exclusion between the
54 * threads.
57 void
58 ConcurrencyTest1::setUp(void)
60 lockTestValue = false;
65 * Method: ConcurrencyTest1::suite()
66 * Descr: This static member function returns a test suite for performing
67 * all combinations of "ConcurrencyTest1". The test suite contains
68 * two instances of the test. One is performed on a benaphore,
69 * the other on a semaphore based BLocker. Each individual test
70 * is created as a ThreadedTestCase (typedef'd as
71 * ConcurrencyTest1Caller) with three independent threads.
74 CppUnit::Test *ConcurrencyTest1::suite(void)
76 typedef BThreadedTestCaller<ConcurrencyTest1>
77 ConcurrencyTest1Caller;
80 CppUnit::TestSuite *testSuite = new CppUnit::TestSuite("ConcurrencyTest1");
82 // Make a benaphore based test object, create a ThreadedTestCase for it and add
83 // three threads to it.
84 ConcurrencyTest1 *theTest = new ConcurrencyTest1("Benaphore", true);
85 ConcurrencyTest1Caller *threadedTest1 = new ConcurrencyTest1Caller("BLocker::Concurrency Test #1 (benaphore)", theTest);
86 threadedTest1->addThread("A", &ConcurrencyTest1::TestThread);
87 threadedTest1->addThread("B", &ConcurrencyTest1::TestThread);
88 threadedTest1->addThread("C", &ConcurrencyTest1::TestThread);
90 // Make a semaphore based test object, create a ThreadedTestCase for it and add
91 // three threads to it.
92 theTest = new ConcurrencyTest1("Semaphore", false);
93 ConcurrencyTest1Caller *threadedTest2 = new ConcurrencyTest1Caller("BLocker::Concurrency Test #1 (semaphore)", theTest);
94 threadedTest2->addThread("A", &ConcurrencyTest1::TestThread);
95 threadedTest2->addThread("B", &ConcurrencyTest1::TestThread);
96 threadedTest2->addThread("C", &ConcurrencyTest1::TestThread);
98 testSuite->addTest(threadedTest1);
99 testSuite->addTest(threadedTest2);
100 return(testSuite);
105 * Method: ConcurrencyTest1::AcquireLock()
106 * Descr: This member function is passed the number of times through the
107 * acquisition loop (lockAttempt) and whether or not this is
108 * the first acquisition of the lock within this iteration.
109 * Based on these values, it may do a LockWithTimeout() or just
110 * a plain Lock() on theLocker. This is done to get coverage of
111 * both lock acquisition methods on the BLocker.
114 bool ConcurrencyTest1::AcquireLock(int lockAttempt,
115 bool firstAcquisition)
117 bool timeoutLock;
118 bool result;
120 if (firstAcquisition) {
121 timeoutLock = ((lockAttempt % 2) == 1);
122 } else {
123 timeoutLock = (((lockAttempt / 2) % 2) == 1);
125 if (timeoutLock) {
126 result = (theLocker->LockWithTimeout(1000000) == B_OK);
127 } else {
128 result = theLocker->Lock();
130 return(result);
135 * Method: ConcurrencyTest1::TestThread()
136 * Descr: This method is the core of the test. Each of the three threads
137 * run this method to perform the concurrency test. First, the
138 * SafetyLock class (see LockerTestCase.h) is used to make sure that
139 * the lock is released if an assertion happens. Then, each thread
140 * iterates MAXLOOP times through the main loop where the following
141 * actions are performed:
142 * - CheckLock() is used to show that the thread does not have
143 * the lock.
144 * - The thread acquires the lock.
145 * - The thread confirms that mutual exclusion is OK by testing
146 * lockTestValue.
147 * - The thread confirms the lock is held once by the thread.
148 * - The thread acquires the lock again.
149 * - The thread confirms the lock is held twice now by the thread.
150 * - The thread releases the lock once.
151 * - The thread confirms the lock is held once now.
152 * - The thread confirms that mutual exclusion is still OK by
153 * testing lockTestValue.
154 * - The thread releases the lock again.
155 * - The thread confirms that the lock is no longer held.
158 void ConcurrencyTest1::TestThread(void)
160 int i;
161 SafetyLock theSafetyLock(theLocker);
163 for (i = 0; i < MAXLOOP; i++) {
164 // Print out 10 sub test markers per thread
165 if (i % (MAXLOOP / 10) == 0)
166 NextSubTest();
168 CheckLock(0);
169 CPPUNIT_ASSERT(AcquireLock(i, true));
171 CPPUNIT_ASSERT(!lockTestValue);
172 lockTestValue = true;
173 CheckLock(1);
175 CPPUNIT_ASSERT(AcquireLock(i, false));
176 CheckLock(2);
178 theLocker->Unlock();
179 CheckLock(1);
181 CPPUNIT_ASSERT(lockTestValue);
182 lockTestValue = false;
183 theLocker->Unlock();
184 CheckLock(0);