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