1//------------------------------------------------------------------------------
2//	LockTargetWithTimeoutTester.cpp
3//
4//------------------------------------------------------------------------------
5
6// Standard Includes -----------------------------------------------------------
7#include <stdio.h>
8
9// System Includes -------------------------------------------------------------
10#include <Message.h>
11#include <OS.h>
12#include <Handler.h>
13#include <Looper.h>
14#include <Messenger.h>
15
16// Project Includes ------------------------------------------------------------
17#include <TestUtils.h>
18#include <ThreadedTestCaller.h>
19#include <cppunit/TestSuite.h>
20
21// Local Includes --------------------------------------------------------------
22#include "Helpers.h"
23#include "LockTargetWithTimeoutTester.h"
24#include "SMTarget.h"
25
26// Local Defines ---------------------------------------------------------------
27
28// Globals ---------------------------------------------------------------------
29
30//------------------------------------------------------------------------------
31
32// constructor
33LockTargetWithTimeoutTester::LockTargetWithTimeoutTester()
34	: BThreadedTestCase(),
35	  fHandler(NULL),
36	  fLooper(NULL)
37{
38}
39
40// constructor
41LockTargetWithTimeoutTester::LockTargetWithTimeoutTester(std::string name)
42	: BThreadedTestCase(name),
43	  fHandler(NULL),
44	  fLooper(NULL)
45{
46}
47
48// destructor
49LockTargetWithTimeoutTester::~LockTargetWithTimeoutTester()
50{
51	if (fLooper) {
52		fLooper->Lock();
53		if (fHandler) {
54			fLooper->RemoveHandler(fHandler);
55			delete fHandler;
56		}
57		fLooper->Quit();
58	}
59}
60
61/*
62	status_t LockTargetWithTimeout(bigtime_t timeout) const
63	@case 1			this is uninitialized
64	@results		should return B_BAD_VALUE.
65 */
66void LockTargetWithTimeoutTester::LockTargetWithTimeoutTest1()
67{
68	BMessenger messenger;
69	CHK(messenger.LockTargetWithTimeout(0) == B_BAD_VALUE);
70}
71
72/*
73	status_t LockTargetWithTimeout(bigtime_t timeout) const
74	@case 2			this is initialized to local target with preferred handler,
75					looper is not locked
76	@results		should lock the looper and return B_OK.
77 */
78void LockTargetWithTimeoutTester::LockTargetWithTimeoutTest2()
79{
80	status_t result = B_OK;
81	BLooper *looper = new BLooper;
82	looper->Run();
83	LooperQuitter quitter(looper);
84	BMessenger messenger(NULL, looper, &result);
85	CHK(messenger.LockTargetWithTimeout(0) == B_OK);
86	CHK(looper->IsLocked() == true);
87	looper->Unlock();
88	CHK(looper->IsLocked() == false);
89}
90
91/*
92	status_t LockTargetWithTimeout(bigtime_t timeout) const
93	@case 3			this is initialized to local target with specific handler,
94					looper is not locked
95	@results		should lock the looper and return B_OK.
96 */
97void LockTargetWithTimeoutTester::LockTargetWithTimeoutTest3()
98{
99	// create looper and handler
100	status_t result = B_OK;
101	BLooper *looper = new BLooper;
102	looper->Run();
103	LooperQuitter quitter(looper);
104	BHandler *handler = new BHandler;
105	HandlerDeleter deleter(handler);
106	CHK(looper->Lock());
107	looper->AddHandler(handler);
108	looper->Unlock();
109	// create the messenger and do the checks
110	BMessenger messenger(handler, NULL, &result);
111	CHK(messenger.LockTargetWithTimeout(0) == B_OK);
112	CHK(looper->IsLocked() == true);
113	looper->Unlock();
114	CHK(looper->IsLocked() == false);
115}
116
117/*
118	status_t LockTargetWithTimeout(bigtime_t timeout) const
119	@case 4			this is initialized to local target with preferred handler,
120					looper is locked by another thread, timeout is 100ms
121	@results		should block until the looper is unlocked (after 50ms),
122					lock it and return B_OK.
123	@thread A		- locks the looper
124					- waits 100ms
125					- unlocks the looper
126 */
127void LockTargetWithTimeoutTester::LockTargetWithTimeoutTest4A()
128{
129	CHK(fLooper->Lock() == true);
130	snooze(100000);
131	fLooper->Unlock();
132}
133
134/*
135	status_t LockTargetWithTimeout(bigtime_t timeout) const
136	@case 4			this is initialized to local target with preferred handler,
137					looper is locked by another thread, timeout is 100ms
138	@results		should block until the looper is unlocked (after 50ms),
139					lock it and return B_OK.
140	@thread B		- waits 50ms (until thread A has acquired the looper lock)
141					- tries to lock the looper via messenger and blocks
142					- acquires the lock successfully after 50ms
143					- unlocks the looper
144 */
145void LockTargetWithTimeoutTester::LockTargetWithTimeoutTest4B()
146{
147	enum { JITTER = 10000 };	// Maybe critical on slow machines.
148	snooze(50000);
149	BMessenger messenger(NULL, fLooper);
150	bigtime_t time = system_time();
151	CHK(messenger.LockTargetWithTimeout(100000) == B_OK);
152	time = system_time() - time - 50000;
153	CHK(fLooper->IsLocked() == true);
154	fLooper->Unlock();
155	CHK(fLooper->IsLocked() == false);
156	CHK(time > -JITTER && time < JITTER);
157}
158
159/*
160	status_t LockTargetWithTimeout(bigtime_t timeout) const
161	@case 5			this is initialized to local target with preferred handler,
162					looper is locked by another thread, timeout is 25ms
163	@results		should block for 25ms, not until the looper is unlocked
164					(after 50ms), should return B_TIMED_OUT.
165	@thread A		- locks the looper
166					- waits 100ms
167					- unlocks the looper
168 */
169void LockTargetWithTimeoutTester::LockTargetWithTimeoutTest5A()
170{
171	CHK(fLooper->Lock() == true);
172	snooze(100000);
173	fLooper->Unlock();
174}
175
176/*
177	status_t LockTargetWithTimeout(bigtime_t timeout) const
178	@case 5			this is initialized to local target with preferred handler,
179					looper is locked by another thread, timeout is 25ms
180	@results		should block for 25ms, not until the looper is unlocked
181					(after 50ms), should return B_TIMED_OUT.
182	@thread B		- waits 50ms (until thread A has acquired the looper lock)
183					- tries to lock the looper via messenger and blocks
184					- times out after 25ms
185 */
186void LockTargetWithTimeoutTester::LockTargetWithTimeoutTest5B()
187{
188	enum { JITTER = 10000 };	// Maybe critical on slow machines.
189	snooze(50000);
190	BMessenger messenger(NULL, fLooper);
191	bigtime_t time = system_time();
192	CHK(messenger.LockTargetWithTimeout(25000) == B_TIMED_OUT);
193	time = system_time() - time - 25000;
194	CHK(fLooper->IsLocked() == false);
195	CHK(time > -JITTER && time < JITTER);
196}
197
198/*
199	status_t LockTargetWithTimeout(bigtime_t timeout) const
200	@case 6			this is initialized to local target with specific handler,
201					looper is locked by another thread, timeout is 100ms
202	@results		should block until the looper is unlocked (after 50ms),
203					lock it and return B_OK.
204	@thread A		- locks the looper
205					- waits 100ms
206					- unlocks the looper
207 */
208void LockTargetWithTimeoutTester::LockTargetWithTimeoutTest6A()
209{
210	CHK(fLooper->Lock() == true);
211	snooze(100000);
212	fLooper->Unlock();
213}
214
215/*
216	status_t LockTargetWithTimeout(bigtime_t timeout) const
217	@case 6			this is initialized to local target with specific handler,
218					looper is locked by another thread, timeout is 100ms
219	@results		should block until the looper is unlocked (after 50ms),
220					lock it and return B_OK.
221	@thread B		- waits 50ms (until thread A has acquired the looper lock)
222					- tries to lock the looper via messenger and blocks
223					- acquires the lock successfully after 50ms
224					- unlocks the looper
225 */
226void LockTargetWithTimeoutTester::LockTargetWithTimeoutTest6B()
227{
228	enum { JITTER = 10000 };	// Maybe critical on slow machines.
229	snooze(50000);
230	BMessenger messenger(fHandler, NULL);
231	bigtime_t time = system_time();
232	CHK(messenger.LockTargetWithTimeout(100000) == B_OK);
233	time = system_time() - time - 50000;
234	CHK(fLooper->IsLocked() == true);
235	fLooper->Unlock();
236	CHK(fLooper->IsLocked() == false);
237	CHK(time > -JITTER && time < JITTER);
238}
239
240/*
241	status_t LockTargetWithTimeout(bigtime_t timeout) const
242	@case 7			this is initialized to local target with specific handler,
243					looper is locked by another thread, timeout is 25ms
244	@results		should block for 25ms, not until the looper is unlocked
245					(after 50ms), should return B_TIMED_OUT.
246	@thread A		- locks the looper
247					- waits 100ms
248					- unlocks the looper
249 */
250void LockTargetWithTimeoutTester::LockTargetWithTimeoutTest7A()
251{
252	CHK(fLooper->Lock() == true);
253	snooze(100000);
254	fLooper->Unlock();
255}
256
257/*
258	status_t LockTargetWithTimeout(bigtime_t timeout) const
259	@case 7			this is initialized to local target with specific handler,
260					looper is locked by another thread, timeout is 25ms
261	@results		should block for 25ms, not until the looper is unlocked
262					(after 50ms), should return B_TIMED_OUT.
263	@thread B		- waits 50ms (until thread A has acquired the looper lock)
264					- tries to lock the looper via messenger and blocks
265					- times out after 25ms
266 */
267void LockTargetWithTimeoutTester::LockTargetWithTimeoutTest7B()
268{
269	enum { JITTER = 10000 };	// Maybe critical on slow machines.
270	snooze(50000);
271	BMessenger messenger(fHandler, NULL);
272	bigtime_t time = system_time();
273	CHK(messenger.LockTargetWithTimeout(25000) == B_TIMED_OUT);
274	time = system_time() - time - 25000;
275	CHK(fLooper->IsLocked() == false);
276	CHK(time > -JITTER && time < JITTER);
277}
278
279/*
280	status_t LockTargetWithTimeout(bigtime_t timeout) const
281	@case 8			this is initialized to remote target with preferred
282					handler, looper is not locked
283	@results		should not lock the looper and return B_BAD_VALUE.
284 */
285void LockTargetWithTimeoutTester::LockTargetWithTimeoutTest8()
286{
287	RemoteSMTarget target(true);
288	BMessenger messenger(target.Messenger());
289	CHK(messenger.LockTargetWithTimeout(10000) == B_BAD_VALUE);
290}
291
292/*
293	status_t LockTargetWithTimeout(bigtime_t timeout) const
294	@case 9			this is initialized to remote target with specific handler,
295					looper is not locked
296	@results		should not lock the looper and return B_BAD_VALUE.
297 */
298void LockTargetWithTimeoutTester::LockTargetWithTimeoutTest9()
299{
300	RemoteSMTarget target(false);
301	BMessenger messenger(target.Messenger());
302	CHK(messenger.LockTargetWithTimeout(10000) == B_BAD_VALUE);
303}
304
305
306Test* LockTargetWithTimeoutTester::Suite()
307{
308	typedef BThreadedTestCaller<LockTargetWithTimeoutTester> TC;
309
310	TestSuite* testSuite = new TestSuite;
311
312	ADD_TEST4(BMessenger, testSuite, LockTargetWithTimeoutTester,
313			 LockTargetWithTimeoutTest1);
314	ADD_TEST4(BMessenger, testSuite, LockTargetWithTimeoutTester,
315			 LockTargetWithTimeoutTest2);
316	ADD_TEST4(BMessenger, testSuite, LockTargetWithTimeoutTester,
317			 LockTargetWithTimeoutTest3);
318	// test4
319	LockTargetWithTimeoutTester *test4
320		= new LockTargetWithTimeoutTester("LockTargetWithTimeoutTest4");
321	test4->fLooper = new BLooper;
322	test4->fLooper->Run();
323	// test4 test caller
324	TC *caller4 = new TC("BMessenger::LockTargetWithTimeoutTest4", test4);
325	caller4->addThread("A",
326		&LockTargetWithTimeoutTester::LockTargetWithTimeoutTest4A);
327	caller4->addThread("B",
328		&LockTargetWithTimeoutTester::LockTargetWithTimeoutTest4B);
329	testSuite->addTest(caller4);
330	// test5
331	LockTargetWithTimeoutTester *test5
332		= new LockTargetWithTimeoutTester("LockTargetWithTimeoutTest5");
333	test5->fLooper = new BLooper;
334	test5->fLooper->Run();
335	// test5 test caller
336	TC *caller5 = new TC("BMessenger::LockTargetWithTimeoutTest5", test5);
337	caller5->addThread("A",
338		&LockTargetWithTimeoutTester::LockTargetWithTimeoutTest5A);
339	caller5->addThread("B",
340		&LockTargetWithTimeoutTester::LockTargetWithTimeoutTest5B);
341	testSuite->addTest(caller5);
342	// test6
343	LockTargetWithTimeoutTester *test6
344		= new LockTargetWithTimeoutTester("LockTargetWithTimeoutTest6");
345	// create looper and handler
346	test6->fLooper = new BLooper;
347	test6->fLooper->Run();
348	test6->fHandler = new BHandler;
349	if (test6->fLooper->Lock()) {
350		test6->fLooper->AddHandler(test6->fHandler);
351		test6->fLooper->Unlock();
352	} else
353		printf("ERROR: Can't init LockTargetWithTimeoutTester test6!\n");
354	// test6 test caller
355	TC *caller6 = new TC("BMessenger::LockTargetWithTimeoutTest6", test6);
356	caller6->addThread("A",
357		&LockTargetWithTimeoutTester::LockTargetWithTimeoutTest6A);
358	caller6->addThread("B",
359		&LockTargetWithTimeoutTester::LockTargetWithTimeoutTest6B);
360	testSuite->addTest(caller6);
361	// test7
362	LockTargetWithTimeoutTester *test7
363		= new LockTargetWithTimeoutTester("LockTargetWithTimeoutTest7");
364	// create looper and handler
365	test7->fLooper = new BLooper;
366	test7->fLooper->Run();
367	test7->fHandler = new BHandler;
368	if (test7->fLooper->Lock()) {
369		test7->fLooper->AddHandler(test7->fHandler);
370		test7->fLooper->Unlock();
371	} else
372		printf("ERROR: Can't init LockTargetWithTimeoutTester test7!\n");
373	// test7 test caller
374	TC *caller7 = new TC("BMessenger::LockTargetWithTimeoutTest7", test7);
375	caller7->addThread("A",
376		&LockTargetWithTimeoutTester::LockTargetWithTimeoutTest7A);
377	caller7->addThread("B",
378		&LockTargetWithTimeoutTester::LockTargetWithTimeoutTest7B);
379	testSuite->addTest(caller7);
380	// tests 8-9
381	ADD_TEST4(BMessenger, testSuite, LockTargetWithTimeoutTester,
382			 LockTargetWithTimeoutTest8);
383	ADD_TEST4(BMessenger, testSuite, LockTargetWithTimeoutTester,
384			 LockTargetWithTimeoutTest9);
385
386	return testSuite;
387}
388
389
390