xref: /haiku/src/tests/kits/support/blocker/SemaphoreLockCountTest1.cpp (revision d5cd5d63ff0ad395989db6cf4841a64d5b545d1d)
1 /*
2 	$Id: SemaphoreLockCountTest1.cpp,v 1.2 2002/07/18 05:32:00 tylerdauwalder Exp $
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 
34 const 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 
67 bool 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 
87 void SemaphoreLockCountTest1::TestThread1(void)
88 {
89 	SafetyLock theSafetyLock1(theLocker);
90 	SafetyLock theSafetyLock2(&thread2Lock);
91 	SafetyLock theSafetyLock3(&thread3Lock);
92 
93 	NextSubTest();
94 	assert(thread2Lock.Lock());
95 	assert(thread3Lock.Lock());
96 
97 	NextSubTest();
98 	assert(CheckLockRequests(1));
99 	assert(theLocker->Lock());
100 
101 	NextSubTest();
102 	assert(CheckLockRequests(2));
103 
104 	NextSubTest();
105 	thread2Lock.Unlock();
106 	snooze(SNOOZE_TIME);
107 	assert(CheckLockRequests(4));
108 
109 	NextSubTest();
110 	thread3Lock.Unlock();
111 	snooze(SNOOZE_TIME);
112 	assert(CheckLockRequests(6));
113 
114 	NextSubTest();
115 	theLocker->Unlock();
116 	snooze(SNOOZE_TIME);
117 	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 
131 void SemaphoreLockCountTest1::TestThread2(void)
132 {
133 	SafetyLock theSafetyLock1(theLocker);
134 
135 	NextSubTest();
136 	snooze(SNOOZE_TIME / 10);
137 	assert(thread2Lock.Lock());
138 
139 	NextSubTest();
140 	assert(theLocker->LockWithTimeout(SNOOZE_TIME / 10) == B_TIMED_OUT);
141 	assert(theLocker->Lock());
142 	int actual = theLocker->CountLockRequests();
143 	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 
158 void SemaphoreLockCountTest1::TestThread3(void)
159 {
160 	SafetyLock theSafetyLock1(theLocker);
161 
162 	NextSubTest();
163 	snooze(SNOOZE_TIME / 10);
164 	assert(thread3Lock.Lock());
165 
166 	NextSubTest();
167 	assert(theLocker->LockWithTimeout(SNOOZE_TIME / 10) == B_TIMED_OUT);
168 	assert(theLocker->Lock());
169 	int actual = theLocker->CountLockRequests();
170 	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 
183 CppUnit::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