1// CommonTestApp.cpp
2
3#include <stdio.h>
4#include <cstring>
5
6#include <OS.h>
7
8#include "CommonTestApp.h"
9
10// constructor
11CommonTestApp::CommonTestApp(const char *signature)
12			 : BApplication(signature),
13			   fQuitOnSecondTry(false),
14			   fEventThread(-1),
15			   fEventDelay(0),
16			   fEventCount(0),
17			   fEventHandler(NULL),
18			   fMessageHandler(NULL),
19			   fReportDestruction(false)
20{
21}
22
23// constructor
24CommonTestApp::CommonTestApp(const char *signature, status_t *result)
25			 : BApplication(signature, result),
26			   fQuitOnSecondTry(false),
27			   fEventThread(-1),
28			   fEventDelay(0),
29			   fEventCount(0),
30			   fEventHandler(NULL),
31			   fMessageHandler(NULL),
32			   fReportDestruction(false)
33{
34}
35
36// destructor
37CommonTestApp::~CommonTestApp()
38{
39	if (fEventThread >= 0) {
40		int32 result;
41		wait_for_thread(fEventThread, &result);
42	}
43	if (fReportDestruction)
44		report("BApplication::~BApplication()\n");
45	delete fEventHandler;
46	delete fMessageHandler;
47}
48
49// ArgvReceived
50void
51CommonTestApp::ArgvReceived(int32 argc, char **argv)
52{
53	report("BApplication::ArgvReceived()\n");
54	if (argc > 1) {
55		report("args:");
56		for (int32 i = 1; i < argc; i++)
57			report(" %s", argv[i]);
58		report("\n");
59	}
60}
61
62// MessageReceived
63void
64CommonTestApp::MessageReceived(BMessage *message)
65{
66	if (fMessageHandler)
67		fMessageHandler->MessageReceived(message);
68	BApplication::MessageReceived(message);
69}
70
71// QuitRequested
72bool
73CommonTestApp::QuitRequested()
74{
75	report("BApplication::QuitRequested()\n");
76	static bool firstTry = true;
77	if (firstTry && fQuitOnSecondTry) {
78		firstTry = false;
79		return false;
80	}
81	return BApplication::QuitRequested();
82}
83
84// ReadyToRun
85void
86CommonTestApp::ReadyToRun()
87{
88	report("BApplication::ReadyToRun()\n");
89}
90
91// Run
92thread_id
93CommonTestApp::Run()
94{
95	thread_id result = BApplication::Run();
96	report("BApplication::Run() done: %d\n", (result == find_thread(NULL)));
97	return result;
98}
99
100// SetQuittingPolicy
101void
102CommonTestApp::SetQuittingPolicy(bool onSecondTry)
103{
104	fQuitOnSecondTry = onSecondTry;
105}
106
107// SetReportDestruction
108void
109CommonTestApp::SetReportDestruction(bool reportDestruction)
110{
111	fReportDestruction = reportDestruction;
112}
113
114// RunEventThread
115status_t
116CommonTestApp::RunEventThread(bigtime_t delay, int32 count,
117							  EventHandler *handler)
118{
119	status_t error = B_OK;
120	fEventDelay = delay;
121	fEventCount = count;
122	fEventHandler = handler;
123	// spawn the thread
124	fEventThread = spawn_thread(&_EventThreadEntry, "event thread",
125								B_NORMAL_PRIORITY, this);
126	if (fEventThread < 0)
127		error = fEventThread;
128	if (error == B_OK)
129		error = resume_thread(fEventThread);
130	// cleanup on error
131	if (error != B_OK && fEventThread >= 0) {
132		kill_thread(fEventThread);
133		fEventThread = -1;
134	}
135	return error;
136}
137
138// SetMessageHandler
139void
140CommonTestApp::SetMessageHandler(BHandler *handler)
141{
142	delete fMessageHandler;
143	fMessageHandler = handler;
144}
145
146// _EventThreadEntry
147int32
148CommonTestApp::_EventThreadEntry(void *data)
149{
150	int32 result = 0;
151	if (CommonTestApp *app = (CommonTestApp*)data)
152		result = app->_EventLoop();
153	return result;
154}
155
156// _EventLoop
157int32
158CommonTestApp::_EventLoop()
159{
160	for (; fEventCount > 0; fEventCount--) {
161		snooze(fEventDelay);
162		if (fEventHandler)
163			fEventHandler->HandleEvent(this);
164	}
165	return 0;
166}
167
168static const char *kAppRunnerTeamPort = "app runner team port";
169static bool connectionEstablished = false;
170static port_id outputPort = -1;
171
172// init_connection
173status_t
174init_connection()
175{
176	status_t error = B_OK;
177	// create a port
178	outputPort = create_port(10, "common test app port");
179	if (outputPort < 0)
180		error = outputPort;
181	// find the remote port
182	port_id port = -1;
183	if (error == B_OK) {
184		port = find_port(kAppRunnerTeamPort);
185		if (port < 0)
186			error = port;
187	}
188	// send the port ID
189	if (error == B_OK) {
190		ssize_t written = write_port(port, outputPort, &be_app_messenger,
191									 sizeof(BMessenger));
192		if (written < 0)
193			error = written;
194	}
195	connectionEstablished = (error == B_OK);
196	return error;
197}
198
199// report
200void
201report(const char *format,...)
202{
203	va_list args;
204	va_start(args, format);
205	if (connectionEstablished)
206		vreport(format, args);
207	else
208		vprintf(format, args);
209	va_end(args);
210}
211
212// vreport
213void
214vreport(const char *format, va_list args)
215{
216	char buffer[10240];
217	vsprintf(buffer, format, args);
218	int32 length = strlen(buffer);
219	write_port(outputPort, 0, buffer, length);
220}
221
222