xref: /haiku/src/tests/kits/support/blocker/DestructionTest2.cpp (revision 71452e98334eaac603bf542d159e24788a46bebb)
1 /*
2 	$Id: DestructionTest2.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 "Destruction" and "Locking 4".
6 
7 	The test works like the following:
8 		- the main thread acquires the lock
9 		- it creates a new thread and sleeps
10 		- the new thread attempts to acquire the lock but times out
11 		- the new thread then attempts to acquire the lock again
12 		- before the new thread times out a second time, the first thread releases
13 		  the lock
14 		- at this time, the new thread acquires the lock and goes to sleep
15 		- the first thread attempts to acquire the lock
16 		- the second thread deletes the lock
17 		- the first thread is woken up indicating that the lock wasn't acquired.
18 
19 	*/
20 
21 
22 #include <ThreadedTestCaller.h>
23 #include "DestructionTest2.h"
24 #include <cppunit/TestSuite.h>
25 #include <Locker.h>
26 
27 // This constant is used to determine the number of microseconds to
28 // sleep during major steps of the test.
29 
30 const bigtime_t SNOOZE_TIME = 200000;
31 
32 
33 /*
34  *  Method:  DestructionTest2::DestructionTest2()
35  *   Descr:  This is the only constructor for this test class.
36  */
37 
38 
39 	DestructionTest2::DestructionTest2(std::string name,
40 											   bool isBenaphore) :
41 		LockerTestCase(name, isBenaphore)
42 {
43 	}
44 
45 
46 /*
47  *  Method:  DestructionTest2::~DestructionTest2()
48  *   Descr:  This is the only destructor for this test class.
49  */
50 
51 
52 	DestructionTest2::~DestructionTest2()
53 {
54 	}
55 
56 
57 /*
58  *  Method:  DestructionTest2::TestThread1()
59  *   Descr:  This method immediately acquires the lock, sleeps
60  *           for SNOOZE_TIME and then releases the lock.  It sleeps
61  *           again for SNOOZE_TIME and then tries to re-acquire the
62  *           lock.  By this time, the other thread should have
63  *           deleted the lock.  This acquisition should fail.
64  */
65 
66 void DestructionTest2::TestThread1(void)
67 {
68 	CPPUNIT_ASSERT(theLocker->LockWithTimeout(SNOOZE_TIME) == B_OK);
69 	NextSubTest();
70 	snooze(SNOOZE_TIME);
71 	NextSubTest();
72 	theLocker->Unlock();
73 	NextSubTest();
74 	snooze(SNOOZE_TIME);
75 	NextSubTest();
76 	CPPUNIT_ASSERT(theLocker->LockWithTimeout(SNOOZE_TIME * 10) == B_BAD_SEM_ID);
77 	NextSubTest();
78 }
79 
80 
81 /*
82  *  Method:  DestructionTest2::TestThread2()
83  *   Descr:  This method sleeps for SNOOZE_TIME/10 and then attempts to acquire
84  *           the lock for SNOOZE_TIME/10 seconds.  This acquisition will timeout
85  *           because the other thread is holding the lock.  Then it acquires the
86  *           lock by using a larger timeout. It sleeps again for 2*SNOOZE_TIME and
87  *           then deletes the lock.  This should wake up the other thread.
88  */
89 
90 void DestructionTest2::TestThread2(void)
91 {
92 	BLocker *tmpLock;
93 
94 	snooze(SNOOZE_TIME/10);
95 	NextSubTest();
96 	CPPUNIT_ASSERT(theLocker->LockWithTimeout(SNOOZE_TIME / 10) == B_TIMED_OUT);
97 	NextSubTest();
98 	CPPUNIT_ASSERT(theLocker->LockWithTimeout(SNOOZE_TIME * 10) == B_OK);
99 	NextSubTest();
100 	snooze(SNOOZE_TIME);
101 	NextSubTest();
102 	snooze(SNOOZE_TIME);
103 	NextSubTest();
104 	tmpLock = theLocker;
105 	theLocker = NULL;
106 	delete tmpLock;
107 }
108 
109 
110 /*
111  *  Method:  DestructionTest2::suite()
112  *   Descr:  This static member function returns a test suite for performing
113  *           all combinations of "DestructionTest2".  The test suite contains
114  *           two instances of the test.  One is performed on a benaphore,
115  *           the other on a semaphore based BLocker.  Each individual test
116  *           is created as a ThreadedTestCase (typedef'd as
117  *           DestructionTest2Caller) with two independent threads.
118  */
119 
120 CppUnit::Test *DestructionTest2::suite(void)
121 {
122 	typedef BThreadedTestCaller<DestructionTest2> DestructionTest2Caller;
123 	CppUnit::TestSuite *testSuite = new CppUnit::TestSuite("DestructionTest2");
124 
125 	// Make a benaphore based test object, create a ThreadedTestCase for it and add
126 	// two threads to it.
127 	DestructionTest2 *theTest = new DestructionTest2("Benaphore", true);
128 	DestructionTest2Caller *threadedTest1 = new DestructionTest2Caller("BLocker::Destruction Test #2 (benaphore)", theTest);
129 	threadedTest1->addThread("A", &DestructionTest2::TestThread1);
130 	threadedTest1->addThread("B", &DestructionTest2::TestThread2);
131 
132 	// Make a semaphore based test object, create a ThreadedTestCase for it and add
133 	// three threads to it.
134 	theTest = new DestructionTest2("Semaphore", false);
135 	DestructionTest2Caller *threadedTest2 = new DestructionTest2Caller("BLocker::Destruction Test #2 (semaphore)", theTest);
136 	threadedTest2->addThread("A", &DestructionTest2::TestThread1);
137 	threadedTest2->addThread("B", &DestructionTest2::TestThread2);
138 
139 	testSuite->addTest(threadedTest1);
140 	testSuite->addTest(threadedTest2);
141 	return(testSuite);
142 }
143 
144 
145 
146 
147