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