1/*
2	$Id: BenaphoreLockCountTest1.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 "Count Lock Requests" for a benaphore style BLocker.
6
7	The test works by:
8		- checking the lock requests
9		- acquiring the lock
10		- checking the lock requests
11		- staring a thread which times out acquiring the lock and then blocks
12		  again waiting for the lock
13		- checking the lock requests
14		- start a second thread which times out acquiring the lock and then blocks
15		  again waiting for the lock
16		- checking the lock requests
17		- release the lock
18		- each blocked thread acquires the lock, checks the lock requests and releases
19		  the lock before terminating
20		- the main thread checks the lock requests one last time
21
22	*/
23
24
25#include "BenaphoreLockCountTest1.h"
26
27#include <cppunit/Test.h>
28#include <cppunit/TestSuite.h>
29
30#include <Locker.h>
31
32#include <ThreadedTestCaller.h>
33
34
35// This constant is used to determine the number of microseconds to
36// sleep during major steps of the test.
37
38const bigtime_t SNOOZE_TIME = 100000;
39
40
41/*
42 *  Method:  BenaphoreLockCountTest1::BenaphoreLockCountTest1()
43 *   Descr:  This is the constructor for this test class.
44 */
45
46
47	BenaphoreLockCountTest1::BenaphoreLockCountTest1(std::string name) :
48		LockerTestCase(name, true)
49{
50	}
51
52
53/*
54 *  Method:  BenaphoreLockCountTest1::~BenaphoreLockTestCountTest1()
55 *   Descr:  This is the destructor for this test class.
56 */
57
58
59	BenaphoreLockCountTest1::~BenaphoreLockCountTest1()
60{
61	}
62
63
64/*
65 *  Method:  BenaphoreLockCountTest1::CheckLockRequests()
66 *   Descr:  This member function checks the actual number of lock requests
67 *           that the BLocker thinks are outstanding versus the number
68 *           passed in.  If they match, true is returned.
69 */
70
71bool BenaphoreLockCountTest1::CheckLockRequests(int expected)
72{
73	int actual = theLocker->CountLockRequests();
74	return(actual == expected);
75}
76
77
78/*
79 *  Method:  BenaphoreLockCountTest1::TestThread1()
80 *   Descr:  This member function performs the main portion of the test.
81 *           It first acquires thread2Lock and thread3Lock.  This ensures
82 *           that thread2 and thread3 will block until this thread wants
83 *           them to start running.  It then checks the lock count, acquires
84 *           the lock and checks the lock count again.  It unlocks each
85 *           of the other two threads in turn and rechecks the lock count.
86 *           Finally, it releases the lock and sleeps for a short while
87 *           for the other two threads to finish.  At the end, it checks
88 *           the lock count on final time.
89 */
90
91void BenaphoreLockCountTest1::TestThread1(void)
92{
93	SafetyLock theSafetyLock1(theLocker);
94	SafetyLock theSafetyLock2(&thread2Lock);
95	SafetyLock theSafetyLock3(&thread3Lock);
96
97	CPPUNIT_ASSERT(thread2Lock.Lock());
98	NextSubTest();
99	CPPUNIT_ASSERT(thread3Lock.Lock());
100	NextSubTest();
101
102	CPPUNIT_ASSERT(CheckLockRequests(0));
103	NextSubTest();
104	CPPUNIT_ASSERT(theLocker->Lock());
105	NextSubTest();
106
107	CPPUNIT_ASSERT(CheckLockRequests(1));
108	NextSubTest();
109
110	thread2Lock.Unlock();
111	NextSubTest();
112	snooze(SNOOZE_TIME);
113	NextSubTest();
114	CPPUNIT_ASSERT(CheckLockRequests(3));
115	NextSubTest();
116
117	thread3Lock.Unlock();
118	NextSubTest();
119	snooze(SNOOZE_TIME);
120	NextSubTest();
121	CPPUNIT_ASSERT(CheckLockRequests(5));
122	NextSubTest();
123
124	theLocker->Unlock();
125	NextSubTest();
126	snooze(SNOOZE_TIME);
127	NextSubTest();
128	CPPUNIT_ASSERT(CheckLockRequests(2));
129	NextSubTest();
130	}
131
132
133/*
134 *  Method:  BenaphoreLockCountTest1::TestThread2()
135 *   Descr:  This member function defines the actions of the second thread of
136 *           the test.  First it sleeps for a short while and then blocks on
137 *           the thread2Lock.  When the first thread releases it, this thread
138 *           begins its testing.  It times out attempting to acquire the main
139 *           lock and then blocks to acquire the lock.  Once that lock is
140 *           acquired, the lock count is checked before finishing this thread.
141 */
142
143void BenaphoreLockCountTest1::TestThread2(void)
144{
145	SafetyLock theSafetyLock1(theLocker);
146
147	snooze(SNOOZE_TIME / 10);
148	NextSubTest();
149	CPPUNIT_ASSERT(thread2Lock.Lock());
150	NextSubTest();
151
152	CPPUNIT_ASSERT(theLocker->LockWithTimeout(SNOOZE_TIME / 10) == B_TIMED_OUT);
153	NextSubTest();
154	CPPUNIT_ASSERT(theLocker->Lock());
155	NextSubTest();
156	int actual = theLocker->CountLockRequests();
157	NextSubTest();
158	CPPUNIT_ASSERT((actual == 3) || (actual == 4));
159	NextSubTest();
160	theLocker->Unlock();
161	NextSubTest();
162}
163
164
165/*
166 *  Method:  BenaphoreLockCountTest1::TestThread3()
167 *   Descr:  This member function defines the actions of the second thread of
168 *           the test.  First it sleeps for a short while and then blocks on
169 *           the thread3Lock.  When the first thread releases it, this thread
170 *           begins its testing.  It times out attempting to acquire the main
171 *           lock and then blocks to acquire the lock.  Once that lock is
172 *           acquired, the lock count is checked before finishing this thread.
173 */
174
175void BenaphoreLockCountTest1::TestThread3(void)
176{
177	SafetyLock theSafetyLock1(theLocker);
178
179	snooze(SNOOZE_TIME / 10);
180	NextSubTest();
181	CPPUNIT_ASSERT(thread3Lock.Lock());
182	NextSubTest();
183
184	CPPUNIT_ASSERT(theLocker->LockWithTimeout(SNOOZE_TIME / 10) == B_TIMED_OUT);
185	NextSubTest();
186	CPPUNIT_ASSERT(theLocker->Lock());
187	NextSubTest();
188	int actual = theLocker->CountLockRequests();
189	NextSubTest();
190	CPPUNIT_ASSERT((actual == 3) || (actual == 4));
191	NextSubTest();
192	theLocker->Unlock();
193	NextSubTest();
194}
195
196
197/*
198 *  Method:  BenaphoreLockCountTest1::suite()
199 *   Descr:  This static member function returns a test caller for performing
200 *           the "BenaphoreLockCountTest1" test.  The test caller
201 *           is created as a ThreadedTestCaller (typedef'd as
202 *           BenaphoreLockCountTest1Caller) with three independent threads.
203 */
204
205CppUnit::Test *BenaphoreLockCountTest1::suite(void)
206{
207	BenaphoreLockCountTest1 *theTest = new BenaphoreLockCountTest1("");
208	BThreadedTestCaller<BenaphoreLockCountTest1> *threadedTest =
209		new BThreadedTestCaller<BenaphoreLockCountTest1>("BLocker::Benaphore Lock Count Test #1", theTest);
210	threadedTest->addThread("A", &BenaphoreLockCountTest1::TestThread1);
211	threadedTest->addThread("B", &BenaphoreLockCountTest1::TestThread2);
212	threadedTest->addThread("C", &BenaphoreLockCountTest1::TestThread3);
213	return(threadedTest);
214}
215
216