xref: /haiku/src/tests/kits/support/blocker/ConcurrencyTest1.cpp (revision 1deede7388b04dbeec5af85cae7164735ea9e70d)
1 /*
2 	$Id: ConcurrencyTest1.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 "Locking 1", "Locking 2", "Unlocking", "Is Locked",
6 	"Locking Thread" and "Count Locks".
7 
8 	*/
9 
10 
11 #include <ThreadedTestCaller.h>
12 #include "ConcurrencyTest1.h"
13 #include <cppunit/TestSuite.h>
14 #include <Locker.h>
15 
16 
17 // This constant indicates the number of times the thread should test the
18 // acquisition and release of the BLocker.
19 
20 const int32 MAXLOOP = 10000;
21 
22 
23 /*
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.
28  */
29 
30 
31 	ConcurrencyTest1::ConcurrencyTest1(std::string name, bool benaphoreFlag) :
32 	LockerTestCase(name, benaphoreFlag), lockTestValue(false)
33 {
34 	}
35 
36 
37 /*
38  *  Method:  ConcurrencyTest1::~ConcurrencyTest1()
39  *   Descr:  This is the descriptor for this test case.
40  */
41 
42 
43 	ConcurrencyTest1::~ConcurrencyTest1()
44 {
45 	}
46 
47 
48 /*
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.
55  */
56 
57 void
58 	ConcurrencyTest1::setUp(void)
59 {
60 	lockTestValue = false;
61 	}
62 
63 
64 /*
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.
72  */
73 
74 CppUnit::Test *ConcurrencyTest1::suite(void)
75 {
76 	typedef BThreadedTestCaller<ConcurrencyTest1>
77 		ConcurrencyTest1Caller;
78 
79 
80 	CppUnit::TestSuite *testSuite = new CppUnit::TestSuite("ConcurrencyTest1");
81 
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);
89 
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);
97 
98 	testSuite->addTest(threadedTest1);
99 	testSuite->addTest(threadedTest2);
100 	return(testSuite);
101 	}
102 
103 
104 /*
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.
112  */
113 
114 bool ConcurrencyTest1::AcquireLock(int lockAttempt,
115                                                        bool firstAcquisition)
116 {
117 	bool timeoutLock;
118 	bool result;
119 
120 	if (firstAcquisition) {
121 		timeoutLock = ((lockAttempt % 2) == 1);
122 	} else {
123 		timeoutLock = (((lockAttempt / 2) % 2) == 1);
124 	}
125 	if (timeoutLock) {
126 		result = (theLocker->LockWithTimeout(1000000) == B_OK);
127 	} else {
128 		result = theLocker->Lock();
129 	}
130 	return(result);
131 }
132 
133 
134 /*
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.
156  */
157 
158 void ConcurrencyTest1::TestThread(void)
159 {
160 	int i;
161 	SafetyLock theSafetyLock(theLocker);
162 
163 	for (i = 0; i < MAXLOOP; i++) {
164 		// Print out 10 sub test markers per thread
165 		if (i % (MAXLOOP / 10) == 0)
166 			NextSubTest();
167 
168 		CheckLock(0);
169 		CPPUNIT_ASSERT(AcquireLock(i, true));
170 
171 		CPPUNIT_ASSERT(!lockTestValue);
172 		lockTestValue = true;
173 		CheckLock(1);
174 
175 		CPPUNIT_ASSERT(AcquireLock(i, false));
176 		CheckLock(2);
177 
178 		theLocker->Unlock();
179 		CheckLock(1);
180 
181 		CPPUNIT_ASSERT(lockTestValue);
182 		lockTestValue = false;
183 		theLocker->Unlock();
184 		CheckLock(0);
185 	}
186 }
187 
188 
189 
190 
191