1//------------------------------------------------------------------------------
2//	LockTargetTester.cpp
3//
4//------------------------------------------------------------------------------
5
6// Standard Includes -----------------------------------------------------------
7#include <stdio.h>
8
9// System Includes -------------------------------------------------------------
10#include <Message.h>
11#include <OS.h>
12
13#include <Handler.h>
14#include <Looper.h>
15#include <Messenger.h>
16
17// Project Includes ------------------------------------------------------------
18#include <TestUtils.h>
19#include <ThreadedTestCaller.h>
20#include <cppunit/TestSuite.h>
21
22// Local Includes --------------------------------------------------------------
23#include "Helpers.h"
24#include "LockTargetTester.h"
25#include "SMTarget.h"
26
27// Local Defines ---------------------------------------------------------------
28
29// Globals ---------------------------------------------------------------------
30
31//------------------------------------------------------------------------------
32
33// constructor
34LockTargetTester::LockTargetTester()
35	: BThreadedTestCase(),
36	  fHandler(NULL),
37	  fLooper(NULL)
38{
39}
40
41// constructor
42LockTargetTester::LockTargetTester(std::string name)
43	: BThreadedTestCase(name),
44	  fHandler(NULL),
45	  fLooper(NULL)
46{
47}
48
49// destructor
50LockTargetTester::~LockTargetTester()
51{
52	if (fLooper) {
53		fLooper->Lock();
54		if (fHandler) {
55			fLooper->RemoveHandler(fHandler);
56			delete fHandler;
57		}
58		fLooper->Quit();
59	}
60}
61
62/*
63	bool LockTarget() const
64	@case 1			this is uninitialized
65	@results		should return false.
66 */
67void LockTargetTester::LockTargetTest1()
68{
69	BMessenger messenger;
70	CHK(messenger.LockTarget() == false);
71}
72
73/*
74	bool LockTarget() const
75	@case 2			this is initialized to local target with preferred handler,
76					looper is not locked
77	@results		should lock the looper and return true.
78 */
79void LockTargetTester::LockTargetTest2()
80{
81	status_t result = B_OK;
82	BLooper *looper = new BLooper;
83	looper->Run();
84	LooperQuitter quitter(looper);
85	BMessenger messenger(NULL, looper, &result);
86	CHK(messenger.LockTarget() == true);
87	CHK(looper->IsLocked() == true);
88	looper->Unlock();
89	CHK(looper->IsLocked() == false);
90}
91
92/*
93	bool LockTarget() const
94	@case 3			this is initialized to local target with specific handler,
95					looper is not locked
96	@results		should lock the looper and return true.
97 */
98void LockTargetTester::LockTargetTest3()
99{
100	// create looper and handler
101	status_t result = B_OK;
102	BLooper *looper = new BLooper;
103	looper->Run();
104	LooperQuitter quitter(looper);
105	BHandler *handler = new BHandler;
106	HandlerDeleter deleter(handler);
107	CHK(looper->Lock());
108	looper->AddHandler(handler);
109	looper->Unlock();
110	// create the messenger and do the checks
111	BMessenger messenger(handler, NULL, &result);
112	CHK(messenger.LockTarget() == true);
113	CHK(looper->IsLocked() == true);
114	looper->Unlock();
115	CHK(looper->IsLocked() == false);
116}
117
118/*
119	bool LockTarget() const
120	@case 4			this is initialized to local target with preferred handler,
121					looper is locked by another thread
122	@results		should block until the looper is unlocked, lock it and
123					return true.
124	@thread A		- locks the looper
125					- waits 100ms
126					- unlocks the looper
127 */
128void LockTargetTester::LockTargetTest4A()
129{
130	CHK(fLooper->Lock() == true);
131	snooze(100000);
132	fLooper->Unlock();
133}
134
135/*
136	bool LockTarget() const
137	@case 4			this is initialized to local target with preferred handler,
138					looper is locked by another thread
139	@results		should block until the looper is unlocked, lock it and
140					return true.
141	@thread B		- waits 50ms (until thread A has acquired the looper lock)
142					- tries to lock the looper via messenger and blocks
143					- acquires the lock successfully after 50ms
144					- unlocks the looper
145 */
146void LockTargetTester::LockTargetTest4B()
147{
148	enum { JITTER = 10000 };	// Maybe critical on slow machines.
149	snooze(50000);
150	BMessenger messenger(NULL, fLooper);
151	bigtime_t time = system_time();
152	CHK(messenger.LockTarget() == true);
153	time = system_time() - time - 50000;
154	CHK(fLooper->IsLocked() == true);
155	fLooper->Unlock();
156	CHK(fLooper->IsLocked() == false);
157	CHK(time > -JITTER && time < JITTER);
158}
159
160/*
161	bool LockTarget() const
162	@case 5			this is initialized to local target with specific handler,
163					looper is locked by another thread
164	@results		should block until the looper is unlocked, lock it and
165					return true.
166	@thread A		- locks the looper
167					- waits 100ms
168					- unlocks the looper
169 */
170void LockTargetTester::LockTargetTest5A()
171{
172	CHK(fLooper->Lock() == true);
173	snooze(100000);
174	fLooper->Unlock();
175}
176
177/*
178	bool LockTarget() const
179	@case 5			this is initialized to local target with specific handler,
180					looper is locked by another thread
181	@results		should block until the looper is unlocked, lock it and
182					return true.
183	@thread B		- waits 50ms (until thread A has acquired the looper lock)
184					- tries to lock the looper via messenger and blocks
185					- acquires the lock successfully after 50ms
186					- unlocks the looper
187 */
188void LockTargetTester::LockTargetTest5B()
189{
190	enum { JITTER = 10000 };	// Maybe critical on slow machines.
191	snooze(50000);
192	BMessenger messenger(fHandler, NULL);
193	bigtime_t time = system_time();
194	CHK(messenger.LockTarget() == true);
195	time = system_time() - time - 50000;
196	CHK(fLooper->IsLocked() == true);
197	fLooper->Unlock();
198	CHK(fLooper->IsLocked() == false);
199	CHK(time > -JITTER && time < JITTER);
200}
201
202/*
203	bool LockTarget() const
204	@case 6			this is initialized to remote target with preferred
205					handler, looper is not locked
206	@results		should not lock the looper and return false.
207 */
208void LockTargetTester::LockTargetTest6()
209{
210	RemoteSMTarget target(true);
211	BMessenger messenger(target.Messenger());
212	CHK(messenger.LockTarget() == false);
213}
214
215/*
216	bool LockTarget() const
217	@case 7			this is initialized to remote target with specific handler,
218					looper is not locked
219	@results		should not lock the looper and return false.
220 */
221void LockTargetTester::LockTargetTest7()
222{
223	RemoteSMTarget target(false);
224	BMessenger messenger(target.Messenger());
225	CHK(messenger.LockTarget() == false);
226}
227
228
229Test* LockTargetTester::Suite()
230{
231	typedef BThreadedTestCaller<LockTargetTester> TC;
232
233	TestSuite* testSuite = new TestSuite;
234
235	ADD_TEST4(BMessenger, testSuite, LockTargetTester, LockTargetTest1);
236	ADD_TEST4(BMessenger, testSuite, LockTargetTester, LockTargetTest2);
237	ADD_TEST4(BMessenger, testSuite, LockTargetTester, LockTargetTest3);
238	// test4
239	LockTargetTester *test4
240		= new LockTargetTester("LockTargetTest4");
241	test4->fLooper = new BLooper;
242	test4->fLooper->Run();
243	// test4 test caller
244	TC *caller4 = new TC("BMessenger::LockTargetTest4", test4);
245	caller4->addThread("A", &LockTargetTester::LockTargetTest4A);
246	caller4->addThread("B", &LockTargetTester::LockTargetTest4B);
247	testSuite->addTest(caller4);
248	// test5
249	LockTargetTester *test5
250		= new LockTargetTester("LockTargetTest5");
251	// create looper and handler
252	test5->fLooper = new BLooper;
253	test5->fLooper->Run();
254	test5->fHandler = new BHandler;
255	if (test5->fLooper->Lock()) {
256		test5->fLooper->AddHandler(test5->fHandler);
257		test5->fLooper->Unlock();
258	} else
259		printf("ERROR: Can't init LockTargetTester test5!\n");
260	// test5 test caller
261	TC *caller5 = new TC("BMessenger::LockTargetTest5", test5);
262	caller5->addThread("A", &LockTargetTester::LockTargetTest5A);
263	caller5->addThread("B", &LockTargetTester::LockTargetTest5B);
264	testSuite->addTest(caller5);
265	// tests 6-7
266	ADD_TEST4(BMessenger, testSuite, LockTargetTester, LockTargetTest6);
267	ADD_TEST4(BMessenger, testSuite, LockTargetTester, LockTargetTest7);
268
269	return testSuite;
270}
271
272
273