1// MessageRunnerTestHelpers.cpp
2
3#include <stdio.h>
4
5#include <Autolock.h>
6
7#include "MessageRunnerTestHelpers.h"
8
9enum {
10	JITTER	= 10000,
11};
12
13// constructor
14MessageRunnerTestHandler::MessageRunnerTestHandler()
15	: BHandler("message runner test handler"),
16	  fReplyCount()
17{
18}
19
20// destructor
21MessageRunnerTestHandler::~MessageRunnerTestHandler()
22{
23}
24
25// MessageReceived
26void
27MessageRunnerTestHandler::MessageReceived(BMessage *message)
28{
29	switch (message->what) {
30		case MSG_REPLY:
31			fReplyCount++;
32			break;
33	}
34}
35
36
37///////////////////////////
38// MessageRunnerTestLooper
39
40struct MessageRunnerTestLooper::MessageInfo {
41	bigtime_t	time;
42};
43
44// constructor
45MessageRunnerTestLooper::MessageRunnerTestLooper()
46	: BLooper(),
47	  fMessageInfos()
48{
49}
50
51// destructor
52MessageRunnerTestLooper::~MessageRunnerTestLooper()
53{
54	for (int32 i = 0; MessageInfo *info = MessageInfoAt(i); i++)
55		delete info;
56}
57
58// MessageReceived
59void
60MessageRunnerTestLooper::MessageReceived(BMessage *message)
61{
62	switch (message->what) {
63		case MSG_RUNNER_MESSAGE:
64		{
65			MessageInfo *info = new MessageInfo;
66			info->time = system_time();
67			fMessageInfos.AddItem(info);
68			message->SendReply(MSG_REPLY);
69			break;
70		}
71	}
72}
73
74// CheckMessages
75bool
76MessageRunnerTestLooper::CheckMessages(bigtime_t startTime, bigtime_t interval,
77									   int32 count)
78{
79	return CheckMessages(0, startTime, interval, count);
80}
81
82// CheckMessages
83bool
84MessageRunnerTestLooper::CheckMessages(int32 skip, bigtime_t startTime,
85									   bigtime_t interval, int32 count)
86{
87	BAutolock _lock(this);
88	bool result = (fMessageInfos.CountItems() == count + skip);
89if (!result) {
90printf("message counts don't match: %ld vs. %ld\n", fMessageInfos.CountItems(),
91count + skip);
92}
93	for (int32 i = 0; result && i < count; i++) {
94		MessageInfo *info = MessageInfoAt(i + skip);
95		bigtime_t expectedTime = startTime + (i + 1) * interval;
96		result = (expectedTime - JITTER < info->time
97				  && info->time < expectedTime + JITTER);
98if (!result)
99printf("message out of time: %lld vs. %lld\n", info->time, expectedTime);
100	}
101	return result;
102}
103
104// MessageInfoAt
105MessageRunnerTestLooper::MessageInfo*
106MessageRunnerTestLooper::MessageInfoAt(int32 index) const
107{
108	return static_cast<MessageInfo*>(fMessageInfos.ItemAt(index));
109}
110
111
112////////////////////////
113// MessageRunnerTestApp
114
115// constructor
116MessageRunnerTestApp::MessageRunnerTestApp(const char *signature)
117	: BApplication(signature),
118	  fThread(-1),
119	  fReplyCount(0),
120	  fLooper(NULL),
121	  fHandler(NULL)
122{
123	// create a looper
124	fLooper = new MessageRunnerTestLooper;
125	fLooper->Run();
126	// create a handler
127	fHandler = new MessageRunnerTestHandler;
128	AddHandler(fHandler);
129	// start out message loop in a different thread
130	Unlock();
131	fThread = spawn_thread(_ThreadEntry, "message runner app thread",
132						   B_NORMAL_PRIORITY, this);
133	resume_thread(fThread);
134}
135
136// destructor
137MessageRunnerTestApp::~MessageRunnerTestApp()
138{
139	// quit the looper
140	fLooper->Lock();
141	fLooper->Quit();
142	// shut down our message loop
143	BMessage reply;
144	PostMessage(B_QUIT_REQUESTED);
145	int32 dummy;
146	wait_for_thread(fThread, &dummy);
147	// delete the handler
148	Lock();
149	RemoveHandler(fHandler);
150	delete fHandler;
151}
152
153// MessageReceived
154void
155MessageRunnerTestApp::MessageReceived(BMessage *message)
156{
157	switch (message->what) {
158		case MSG_REPLY:
159			fReplyCount++;
160			break;
161	}
162}
163
164// QuitRequested
165bool
166MessageRunnerTestApp::QuitRequested()
167{
168	return true;
169}
170
171// _ThreadEntry
172int32
173MessageRunnerTestApp::_ThreadEntry(void *data)
174{
175	MessageRunnerTestApp *app = static_cast<MessageRunnerTestApp*>(data);
176	app->Lock();
177	app->Run();
178	return 0;
179}
180
181