1//------------------------------------------------------------------------------
2//	BMessageRunnerTester.cpp
3//
4//------------------------------------------------------------------------------
5
6// Standard Includes -----------------------------------------------------------
7#include <algorithm>
8#include <stdio.h>
9
10// System Includes -------------------------------------------------------------
11#include <Application.h>
12#include <Handler.h>
13#include <Looper.h>
14#include <Message.h>
15#include <MessageRunner.h>
16#include <Messenger.h>
17#include <OS.h>
18
19// Project Includes ------------------------------------------------------------
20#include <TestShell.h>
21#include <TestUtils.h>
22#include <cppunit/TestAssert.h>
23
24// Local Includes --------------------------------------------------------------
25#include "BMessageRunnerTester.h"
26#include "MessageRunnerTestHelpers.h"
27
28// Local Defines ---------------------------------------------------------------
29
30// Globals ---------------------------------------------------------------------
31
32//------------------------------------------------------------------------------
33
34
35using namespace std;
36
37
38static const char *kTesterSignature
39	= "application/x-vnd.obos-messagerunner-constructor-test";
40
41static const bigtime_t kMinTimeInterval = 50000;
42
43// check_message_runner_info
44static
45void
46check_message_runner_info(const BMessageRunner &runner, status_t error,
47						  bigtime_t interval = 0, int32 count = 0)
48{
49	bigtime_t runnerInterval = 0;
50	int32 runnerCount = 0;
51	CHK(runner.GetInfo(&runnerInterval, &runnerCount) == error);
52	if (error == B_OK) {
53		CHK(runnerInterval == interval);
54		CHK(runnerCount == count);
55	}
56}
57
58/*
59	BMessageRunner(BMessenger target, const BMessage *message,
60				   bigtime_t interval, int32 count)
61	@case 1			target is invalid, message is valid, interval > 0,
62					count > 0
63	@results		InitCheck() should return B_OK. The message runner turns
64					to unusable as soon as the first message had to be sent.
65					GetInfo() should return B_OK.
66 */
67void TBMessageRunnerTester::BMessageRunnerA1()
68{
69	MessageRunnerTestApp app(kTesterSignature);
70	BMessenger target;
71	BMessage message(MSG_RUNNER_MESSAGE);
72	bigtime_t interval = 100000;
73	int32 count = 5;
74	BMessageRunner runner(target, &message, interval, count);
75	CHK(runner.InitCheck() == B_OK);
76	check_message_runner_info(runner, B_OK, interval, count);
77	snooze(interval + 10000);
78	check_message_runner_info(runner, B_BAD_VALUE);
79	CHK(app.CountReplies() == 0);
80}
81
82/*
83	BMessageRunner(BMessenger target, const BMessage *message,
84				   bigtime_t interval, int32 count)
85	@case 2			target is valid, message is NULL, interval > 0, count > 0
86	@results		InitCheck() should return B_BAD_VALUE.
87					GetInfo() should return B_BAD_VALUE.
88 */
89void TBMessageRunnerTester::BMessageRunnerA2()
90{
91// R5: chrashes when passing a NULL message
92#ifndef TEST_R5
93	MessageRunnerTestApp app(kTesterSignature);
94	MessageRunnerTestLooper *looper = app.TestLooper();
95	BMessenger target(looper);
96	bigtime_t interval = 100000;
97	int32 count = 5;
98	BMessageRunner runner(target, NULL, interval, count);
99	CHK(runner.InitCheck() == B_BAD_VALUE);
100	check_message_runner_info(runner, B_BAD_VALUE);
101#endif
102}
103
104/*
105	BMessageRunner(BMessenger target, const BMessage *message,
106				   bigtime_t interval, int32 count)
107	@case 3			target is valid, message is valid, interval == 0, count > 0
108	@results		R5: InitCheck() should return B_ERROR.
109						GetInfo() should return B_BAD_VALUE.
110					Haiku: InitCheck() should return B_OK.
111						  GetInfo() should return B_OK.
112						  A minimal time interval is used (50000).
113 */
114void TBMessageRunnerTester::BMessageRunnerA3()
115{
116	MessageRunnerTestApp app(kTesterSignature);
117	MessageRunnerTestLooper *looper = app.TestLooper();
118	BMessenger target(looper);
119	BMessage message(MSG_RUNNER_MESSAGE);
120	bigtime_t interval = 0;
121	int32 count = 5;
122	BMessageRunner runner(target, &message, interval, count);
123#ifdef TEST_R5
124	CHK(runner.InitCheck() == B_ERROR);
125	check_message_runner_info(runner, B_BAD_VALUE);
126#else
127	bigtime_t startTime = system_time();
128	CHK(runner.InitCheck() == B_OK);
129	interval = max(interval, kMinTimeInterval);
130	check_message_runner_info(runner, B_OK, interval, count);
131	snooze((count + 1) * interval + 10000);
132	CHK(looper->CheckMessages(startTime, interval, count));
133	CHK(app.CountReplies() == count);
134#endif
135}
136
137/*
138	BMessageRunner(BMessenger target, const BMessage *message,
139				   bigtime_t interval, int32 count)
140	@case 4			target is valid, message is valid, interval < 0, count > 0
141	@results		InitCheck() should return B_OK.
142					GetInfo() should return B_OK.
143					A minimal time interval is used (50000).
144 */
145void TBMessageRunnerTester::BMessageRunnerA4()
146{
147	MessageRunnerTestApp app(kTesterSignature);
148	MessageRunnerTestLooper *looper = app.TestLooper();
149	BMessenger target(looper);
150	BMessage message(MSG_RUNNER_MESSAGE);
151	bigtime_t interval = -1;
152	int32 count = 5;
153	BMessageRunner runner(target, &message, interval, count);
154	bigtime_t startTime = system_time();
155	CHK(runner.InitCheck() == B_OK);
156	interval = max(interval, kMinTimeInterval);
157	check_message_runner_info(runner, B_OK, interval, count);
158	snooze((count + 1) * interval + 10000);
159	CHK(looper->CheckMessages(startTime, interval, count));
160	CHK(app.CountReplies() == count);
161}
162
163/*
164	BMessageRunner(BMessenger target, const BMessage *message,
165				   bigtime_t interval, int32 count)
166	@case 5			target is valid, message is valid,
167					interval == LONGLONG_MAX, count > 0
168	@results		InitCheck() should return B_OK.
169					GetInfo() should return B_OK.
170					No message should be delivered.
171 */
172void TBMessageRunnerTester::BMessageRunnerA5()
173{
174// R5: doesn't behave very well. In worst case registrar time loop gets
175// locked up and system wide message runners don't get messages anymore.
176#ifndef TEST_R5
177	MessageRunnerTestApp app(kTesterSignature);
178	MessageRunnerTestLooper *looper = app.TestLooper();
179	BMessenger target(looper);
180	BMessage message(MSG_RUNNER_MESSAGE);
181	bigtime_t interval = LONGLONG_MAX;
182	int32 count = 5;
183	BMessageRunner runner(target, &message, interval, count);
184	bigtime_t startTime = system_time();
185	CHK(runner.InitCheck() == B_OK);
186	interval = max(interval, kMinTimeInterval);
187	check_message_runner_info(runner, B_OK, interval, count);
188	snooze(10000);
189	CHK(looper->CheckMessages(startTime, interval, 0));
190	CHK(app.CountReplies() == 0);
191#endif
192}
193
194/*
195	BMessageRunner(BMessenger target, const BMessage *message,
196				   bigtime_t interval, int32 count)
197	@case 6			target is valid, message is valid, interval > 0, count == 0
198	@results		InitCheck() should return B_ERROR.
199					GetInfo() should return B_BAD_VALUE.
200 */
201void TBMessageRunnerTester::BMessageRunnerA6()
202{
203	MessageRunnerTestApp app(kTesterSignature);
204	MessageRunnerTestLooper *looper = app.TestLooper();
205	BMessenger target(looper);
206	BMessage message(MSG_RUNNER_MESSAGE);
207	bigtime_t interval = 100000;
208	int32 count = 0;
209	BMessageRunner runner(target, &message, interval, count);
210	CHK(runner.InitCheck() == B_ERROR);
211	check_message_runner_info(runner, B_BAD_VALUE);
212}
213
214/*
215	BMessageRunner(BMessenger target, const BMessage *message,
216				   bigtime_t interval, int32 count)
217	@case 7			target is valid, message is valid, interval > 0, count < 0
218	@results		InitCheck() should return B_OK.
219					GetInfo() should return B_OK.
220					Unlimited number of messages.
221 */
222void TBMessageRunnerTester::BMessageRunnerA7()
223{
224	MessageRunnerTestApp app(kTesterSignature);
225	MessageRunnerTestLooper *looper = app.TestLooper();
226	BMessenger target(looper);
227	BMessage message(MSG_RUNNER_MESSAGE);
228	bigtime_t interval = 100000;
229	int32 count = 5;
230	BMessageRunner runner(target, &message, interval, count);
231	bigtime_t startTime = system_time();
232	CHK(runner.InitCheck() == B_OK);
233	interval = max(interval, kMinTimeInterval);
234	check_message_runner_info(runner, B_OK, interval, count);
235	int32 checkCount = 5;
236	snooze(checkCount * interval + 10000);
237	CHK(looper->CheckMessages(startTime, interval, checkCount));
238	CHK(app.CountReplies() == checkCount);
239}
240
241/*
242	BMessageRunner(BMessenger target, const BMessage *message,
243				   bigtime_t interval, int32 count)
244	@case 8			target is valid, message is valid, interval > 0, count > 0
245	@results		InitCheck() should return B_OK.
246					GetInfo() should return B_OK.
247					count messages are sent.
248 */
249void TBMessageRunnerTester::BMessageRunnerA8()
250{
251	MessageRunnerTestApp app(kTesterSignature);
252	MessageRunnerTestLooper *looper = app.TestLooper();
253	BMessenger target(looper);
254	BMessage message(MSG_RUNNER_MESSAGE);
255	bigtime_t interval = 100000;
256	int32 count = 5;
257	BMessageRunner runner(target, &message, interval, count);
258	bigtime_t startTime = system_time();
259	CHK(runner.InitCheck() == B_OK);
260	interval = max(interval, kMinTimeInterval);
261	check_message_runner_info(runner, B_OK, interval, count);
262	snooze((count + 1) * interval + 10000);
263	CHK(looper->CheckMessages(startTime, interval, count));
264	CHK(app.CountReplies() == count);
265}
266
267/*
268	BMessageRunner(BMessenger target, const BMessage *message,
269				   bigtime_t interval, int32 count, BMessenger replyTo)
270	@case 1			target is invalid, message is valid, interval > 0,
271					count > 0
272	@results		InitCheck() should return B_OK. The message runner turns
273					to unusable as soon as the first message had to be sent.
274					GetInfo() should return B_OK.
275 */
276void TBMessageRunnerTester::BMessageRunnerB1()
277{
278	MessageRunnerTestApp app(kTesterSignature);
279	BMessenger target;
280	BMessage message(MSG_RUNNER_MESSAGE);
281	bigtime_t interval = 100000;
282	int32 count = 5;
283	MessageRunnerTestHandler *handler = app.TestHandler();
284	BMessenger replyTo(handler);
285	BMessageRunner runner(target, &message, interval, count, replyTo);
286	CHK(runner.InitCheck() == B_OK);
287	check_message_runner_info(runner, B_OK, interval, count);
288	snooze(interval + 10000);
289	check_message_runner_info(runner, B_BAD_VALUE);
290	CHK(app.CountReplies() == 0);
291	CHK(handler->CountReplies() == 0);
292}
293
294/*
295	BMessageRunner(BMessenger target, const BMessage *message,
296				   bigtime_t interval, int32 count, BMessenger replyTo)
297	@case 2			target is valid, message is NULL, interval > 0, count > 0
298	@results		InitCheck() should return B_BAD_VALUE.
299					GetInfo() should return B_BAD_VALUE.
300 */
301void TBMessageRunnerTester::BMessageRunnerB2()
302{
303// R5: chrashes when passing a NULL message
304#ifndef TEST_R5
305	MessageRunnerTestApp app(kTesterSignature);
306	MessageRunnerTestLooper *looper = app.TestLooper();
307	BMessenger target(looper);
308	bigtime_t interval = 100000;
309	int32 count = 5;
310	MessageRunnerTestHandler *handler = app.TestHandler();
311	BMessenger replyTo(handler);
312	BMessageRunner runner(target, NULL, interval, count, replyTo);
313	CHK(runner.InitCheck() == B_BAD_VALUE);
314	check_message_runner_info(runner, B_BAD_VALUE);
315#endif
316}
317
318/*
319	BMessageRunner(BMessenger target, const BMessage *message,
320				   bigtime_t interval, int32 count, BMessenger replyTo)
321	@case 3			target is valid, message is valid, interval == 0, count > 0
322	@results		R5: InitCheck() should return B_ERROR.
323						GetInfo() should return B_BAD_VALUE.
324					Haiku: InitCheck() should return B_OK.
325						  GetInfo() should return B_OK.
326						  A minimal time interval is used (50000).
327 */
328void TBMessageRunnerTester::BMessageRunnerB3()
329{
330	MessageRunnerTestApp app(kTesterSignature);
331	MessageRunnerTestLooper *looper = app.TestLooper();
332	BMessenger target(looper);
333	BMessage message(MSG_RUNNER_MESSAGE);
334	bigtime_t interval = 0;
335	int32 count = 5;
336	MessageRunnerTestHandler *handler = app.TestHandler();
337	BMessenger replyTo(handler);
338	BMessageRunner runner(target, &message, interval, count, replyTo);
339#ifdef TEST_R5
340	CHK(runner.InitCheck() == B_ERROR);
341	check_message_runner_info(runner, B_BAD_VALUE);
342#else
343	bigtime_t startTime = system_time();
344	CHK(runner.InitCheck() == B_OK);
345	interval = max(interval, kMinTimeInterval);
346	check_message_runner_info(runner, B_OK, interval, count);
347	snooze((count + 1) * interval + 10000);
348	CHK(looper->CheckMessages(startTime, interval, count));
349	CHK(app.CountReplies() == 0);
350	CHK(handler->CountReplies() == count);
351#endif
352}
353
354/*
355	BMessageRunner(BMessenger target, const BMessage *message,
356				   bigtime_t interval, int32 count, BMessenger replyTo)
357	@case 4			target is valid, message is valid, interval < 0, count > 0
358	@results		InitCheck() should return B_OK.
359					GetInfo() should return B_OK.
360					A minimal time interval is used (50000).
361 */
362void TBMessageRunnerTester::BMessageRunnerB4()
363{
364	MessageRunnerTestApp app(kTesterSignature);
365	MessageRunnerTestLooper *looper = app.TestLooper();
366	BMessenger target(looper);
367	BMessage message(MSG_RUNNER_MESSAGE);
368	bigtime_t interval = -1;
369	int32 count = 5;
370	MessageRunnerTestHandler *handler = app.TestHandler();
371	BMessenger replyTo(handler);
372	BMessageRunner runner(target, &message, interval, count, replyTo);
373	bigtime_t startTime = system_time();
374	CHK(runner.InitCheck() == B_OK);
375	interval = max(interval, kMinTimeInterval);
376	check_message_runner_info(runner, B_OK, interval, count);
377	snooze((count + 1) * interval + 10000);
378	CHK(looper->CheckMessages(startTime, interval, count));
379	CHK(app.CountReplies() == 0);
380	CHK(handler->CountReplies() == count);
381}
382
383/*
384	BMessageRunner(BMessenger target, const BMessage *message,
385				   bigtime_t interval, int32 count, BMessenger replyTo)
386	@case 5			target is valid, message is valid,
387					interval == LONGLONG_MAX, count > 0
388	@results		InitCheck() should return B_OK.
389					GetInfo() should return B_OK.
390					No message should be delivered.
391 */
392void TBMessageRunnerTester::BMessageRunnerB5()
393{
394// R5: doesn't behave very well. In worst case registrar time loop gets
395// locked up and system wide message runners don't get messages anymore.
396#ifndef TEST_R5
397	MessageRunnerTestApp app(kTesterSignature);
398	MessageRunnerTestLooper *looper = app.TestLooper();
399	BMessenger target(looper);
400	BMessage message(MSG_RUNNER_MESSAGE);
401	bigtime_t interval = LONGLONG_MAX;
402	int32 count = 5;
403	MessageRunnerTestHandler *handler = app.TestHandler();
404	BMessenger replyTo(handler);
405	BMessageRunner runner(target, &message, interval, count, replyTo);
406	bigtime_t startTime = system_time();
407	CHK(runner.InitCheck() == B_OK);
408	interval = max(interval, kMinTimeInterval);
409	check_message_runner_info(runner, B_OK, interval, count);
410	snooze(10000);
411	CHK(looper->CheckMessages(startTime, interval, 0));
412	CHK(app.CountReplies() == 0);
413	CHK(handler->CountReplies() == 0);
414#endif
415}
416
417/*
418	BMessageRunner(BMessenger target, const BMessage *message,
419				   bigtime_t interval, int32 count, BMessenger replyTo)
420	@case 6			target is valid, message is valid, interval > 0, count == 0
421	@results		InitCheck() should return B_ERROR.
422					GetInfo() should return B_BAD_VALUE.
423 */
424void TBMessageRunnerTester::BMessageRunnerB6()
425{
426	MessageRunnerTestApp app(kTesterSignature);
427	MessageRunnerTestLooper *looper = app.TestLooper();
428	BMessenger target(looper);
429	BMessage message(MSG_RUNNER_MESSAGE);
430	bigtime_t interval = 100000;
431	int32 count = 0;
432	MessageRunnerTestHandler *handler = app.TestHandler();
433	BMessenger replyTo(handler);
434	BMessageRunner runner(target, &message, interval, count, replyTo);
435	CHK(runner.InitCheck() == B_ERROR);
436	check_message_runner_info(runner, B_BAD_VALUE);
437}
438
439/*
440	BMessageRunner(BMessenger target, const BMessage *message,
441				   bigtime_t interval, int32 count, BMessenger replyTo)
442	@case 7			target is valid, message is valid, interval > 0, count < 0
443	@results		InitCheck() should return B_OK.
444					GetInfo() should return B_OK.
445					Unlimited number of messages.
446 */
447void TBMessageRunnerTester::BMessageRunnerB7()
448{
449	MessageRunnerTestApp app(kTesterSignature);
450	MessageRunnerTestLooper *looper = app.TestLooper();
451	BMessenger target(looper);
452	BMessage message(MSG_RUNNER_MESSAGE);
453	bigtime_t interval = 100000;
454	int32 count = 5;
455	MessageRunnerTestHandler *handler = app.TestHandler();
456	BMessenger replyTo(handler);
457	BMessageRunner runner(target, &message, interval, count, replyTo);
458	bigtime_t startTime = system_time();
459	CHK(runner.InitCheck() == B_OK);
460	interval = max(interval, kMinTimeInterval);
461	check_message_runner_info(runner, B_OK, interval, count);
462	int32 checkCount = 5;
463	snooze(checkCount * interval + 10000);
464	CHK(looper->CheckMessages(startTime, interval, checkCount));
465	CHK(app.CountReplies() == 0);
466	CHK(handler->CountReplies() == checkCount);
467}
468
469/*
470	BMessageRunner(BMessenger target, const BMessage *message,
471				   bigtime_t interval, int32 count, BMessenger replyTo)
472	@case 8			target is valid, message is valid, interval > 0, count > 0
473	@results		InitCheck() should return B_OK.
474					GetInfo() should return B_OK.
475					count messages are sent.
476 */
477void TBMessageRunnerTester::BMessageRunnerB8()
478{
479	MessageRunnerTestApp app(kTesterSignature);
480	MessageRunnerTestLooper *looper = app.TestLooper();
481	BMessenger target(looper);
482	BMessage message(MSG_RUNNER_MESSAGE);
483	bigtime_t interval = 100000;
484	int32 count = 5;
485	MessageRunnerTestHandler *handler = app.TestHandler();
486	BMessenger replyTo(handler);
487	BMessageRunner runner(target, &message, interval, count, replyTo);
488	bigtime_t startTime = system_time();
489	CHK(runner.InitCheck() == B_OK);
490	interval = max(interval, kMinTimeInterval);
491	check_message_runner_info(runner, B_OK, interval, count);
492	snooze((count + 1) * interval + 10000);
493	CHK(looper->CheckMessages(startTime, interval, count));
494	CHK(app.CountReplies() == 0);
495	CHK(handler->CountReplies() == count);
496}
497
498/*
499	BMessageRunner(BMessenger target, const BMessage *message,
500				   bigtime_t interval, int32 count, BMessenger replyTo)
501	@case 9			target is valid, message is valid, interval > 0, count > 0,
502					replyTo is invalid
503	@results		InitCheck() should return B_OK.
504					GetInfo() should return B_OK.
505					count messages are sent. The replies go to the registrar!
506 */
507void TBMessageRunnerTester::BMessageRunnerB9()
508{
509	MessageRunnerTestApp app(kTesterSignature);
510	MessageRunnerTestLooper *looper = app.TestLooper();
511	BMessenger target(looper);
512	BMessage message(MSG_RUNNER_MESSAGE);
513	bigtime_t interval = 100000;
514	int32 count = 5;
515	MessageRunnerTestHandler *handler = app.TestHandler();
516	BMessenger replyTo(handler);
517	BMessageRunner runner(target, &message, interval, count, replyTo);
518	bigtime_t startTime = system_time();
519	CHK(runner.InitCheck() == B_OK);
520	interval = max(interval, kMinTimeInterval);
521	check_message_runner_info(runner, B_OK, interval, count);
522	snooze((count + 1) * interval + 10000);
523	CHK(looper->CheckMessages(startTime, interval, count));
524	CHK(app.CountReplies() == 0);
525	CHK(handler->CountReplies() == count);
526}
527
528
529Test* TBMessageRunnerTester::Suite()
530{
531	TestSuite* SuiteOfTests = new TestSuite;
532
533	ADD_TEST4(BMessageRunner, SuiteOfTests, TBMessageRunnerTester,
534			  BMessageRunnerA1);
535	ADD_TEST4(BMessageRunner, SuiteOfTests, TBMessageRunnerTester,
536			  BMessageRunnerA2);
537	ADD_TEST4(BMessageRunner, SuiteOfTests, TBMessageRunnerTester,
538			  BMessageRunnerA3);
539	ADD_TEST4(BMessageRunner, SuiteOfTests, TBMessageRunnerTester,
540			  BMessageRunnerA4);
541	ADD_TEST4(BMessageRunner, SuiteOfTests, TBMessageRunnerTester,
542			  BMessageRunnerA5);
543	ADD_TEST4(BMessageRunner, SuiteOfTests, TBMessageRunnerTester,
544			  BMessageRunnerA6);
545	ADD_TEST4(BMessageRunner, SuiteOfTests, TBMessageRunnerTester,
546			  BMessageRunnerA7);
547	ADD_TEST4(BMessageRunner, SuiteOfTests, TBMessageRunnerTester,
548			  BMessageRunnerA8);
549
550	ADD_TEST4(BMessageRunner, SuiteOfTests, TBMessageRunnerTester,
551			  BMessageRunnerB1);
552	ADD_TEST4(BMessageRunner, SuiteOfTests, TBMessageRunnerTester,
553			  BMessageRunnerB2);
554	ADD_TEST4(BMessageRunner, SuiteOfTests, TBMessageRunnerTester,
555			  BMessageRunnerB3);
556	ADD_TEST4(BMessageRunner, SuiteOfTests, TBMessageRunnerTester,
557			  BMessageRunnerB4);
558	ADD_TEST4(BMessageRunner, SuiteOfTests, TBMessageRunnerTester,
559			  BMessageRunnerB5);
560	ADD_TEST4(BMessageRunner, SuiteOfTests, TBMessageRunnerTester,
561			  BMessageRunnerB6);
562	ADD_TEST4(BMessageRunner, SuiteOfTests, TBMessageRunnerTester,
563			  BMessageRunnerB7);
564	ADD_TEST4(BMessageRunner, SuiteOfTests, TBMessageRunnerTester,
565			  BMessageRunnerB8);
566	ADD_TEST4(BMessageRunner, SuiteOfTests, TBMessageRunnerTester,
567			  BMessageRunnerB9);
568
569	return SuiteOfTests;
570}
571
572