1// RosterLaunchTestApp1.cpp
2
3#include <stdio.h>
4#include <string.h>
5
6#include <Application.h>
7#include <Entry.h>
8#include <File.h>
9#include <Message.h>
10#include <Messenger.h>
11#include <OS.h>
12#include <Resources.h>
13#include <Roster.h>
14#include <String.h>
15
16#include "RosterTestAppDefs.h"
17
18BMessenger unitTesterMessenger;
19
20static const char *kUnitTesterSignature
21	= "application/x-vnd.obos-roster-launch-test";
22
23// init_unit_tester_messenger
24static
25status_t
26init_unit_tester_messenger()
27{
28	// Unfortunately BeOS R5 doesn't update the roster-side information about
29	// the app looper's port ID once a BApplication has been created, and
30	// thus we can't construct a BMessenger targeting a BApplication created
31	// after the first one using the signature/team ID constructor.
32	// We need to do some hacking.
33	struct fake_messenger {
34		port_id	fPort;
35		int32	fHandlerToken;
36		team_id	fTeam;
37		int32	extra0;
38		int32	extra1;
39		bool	fPreferredTarget;
40		bool	extra2;
41		bool	extra3;
42		bool	extra4;
43	} &fake = *(fake_messenger*)&unitTesterMessenger;
44	// get team
45	status_t error = B_OK;
46	fake.fTeam = BRoster().TeamFor(kUnitTesterSignature);
47	if (fake.fTeam < 0)
48		error = fake.fTeam;
49	// find app looper port
50	bool found = false;
51	int32 cookie = 0;
52	port_info info;
53	while (error == B_OK && !found) {
54		error = get_next_port_info(fake.fTeam, &cookie, &info);
55		found = (error == B_OK && !strcmp("AppLooperPort", info.name));
56	}
57	// init messenger
58	if (error == B_OK) {
59		fake.fPort = info.port;
60		fake.fHandlerToken = 0;
61		fake.fPreferredTarget = true;
62	}
63	return error;
64}
65
66// get_app_path
67status_t
68get_app_path(char *buffer)
69{
70	status_t error = (buffer ? B_OK : B_BAD_VALUE);
71	image_info info;
72	int32 cookie = 0;
73	bool found = false;
74	if (error == B_OK) {
75		while (!found && get_next_image_info(0, &cookie, &info) == B_OK) {
76			if (info.type == B_APP_IMAGE) {
77				strncpy(buffer, info.name, B_PATH_NAME_LENGTH);
78				buffer[B_PATH_NAME_LENGTH] = 0;
79				found = true;
80			}
81		}
82	}
83	if (error == B_OK && !found)
84		error = B_ENTRY_NOT_FOUND;
85	return error;
86}
87
88// TestApp
89class TestApp : public BApplication {
90public:
91	TestApp(const char *signature) : BApplication(signature)
92	{
93	}
94
95	virtual void ArgvReceived(int32 argc, char **argv)
96	{
97		BMessage message(MSG_ARGV_RECEIVED);
98		message.AddInt32("argc", argc);
99		for (int32 i = 0; i < argc; i++)
100			message.AddString("argv", argv[i]);
101		unitTesterMessenger.SendMessage(&message);
102	}
103
104	virtual void RefsReceived(BMessage *_message)
105	{
106		BMessage message(*_message);
107		message.what = MSG_REFS_RECEIVED;
108		unitTesterMessenger.SendMessage(&message);
109	}
110
111	virtual void MessageReceived(BMessage *_message)
112	{
113		BMessage message(MSG_MESSAGE_RECEIVED);
114		message.AddMessage("message", _message);
115		message.AddInt32("sender", _message->ReturnAddress().Team());
116		unitTesterMessenger.SendMessage(&message);
117	}
118
119	virtual bool QuitRequested()
120	{
121		unitTesterMessenger.SendMessage(MSG_QUIT_REQUESTED);
122		return true;
123	}
124
125	virtual void ReadyToRun()
126	{
127		unitTesterMessenger.SendMessage(MSG_READY_TO_RUN);
128	}
129};
130
131// main
132int
133main(int argc, char **argv)
134{
135	// find app file and get signature from resources
136	char path[B_PATH_NAME_LENGTH];
137	status_t error = get_app_path(path);
138	char signature[B_MIME_TYPE_LENGTH];
139	if (error == B_OK) {
140		// init app file
141		BFile file;
142		error = file.SetTo(path, B_READ_ONLY);
143		// get signature
144		BString signatureString;
145		if (error == B_OK) {
146			if (file.ReadAttrString("signature", &signatureString) == B_OK
147				&& signatureString.Length() > 0) {
148				strcpy(signature, signatureString.String());
149			} else
150				strcpy(signature, kDefaultTestAppSignature);
151		} else
152			printf("ERROR: Couldn't init app file: %s\n", strerror(error));
153	} else
154		printf("ERROR: Couldn't get app ref: %s\n", strerror(error));
155	// create the app
156	TestApp *app = NULL;
157	if (error == B_OK) {
158		app = new TestApp(signature);
159//		unitTesterMessenger = BMessenger(kUnitTesterSignature);
160		error = init_unit_tester_messenger();
161		if (error != B_OK)
162			printf("ERROR: Couldn't init messenger: %s\n", strerror(error));
163		// send started message
164		BMessage message(MSG_STARTED);
165		message.AddString("path", path);
166		unitTesterMessenger.SendMessage(&message);
167		// send main() args message
168		BMessage argsMessage(MSG_MAIN_ARGS);
169		argsMessage.AddInt32("argc", argc);
170		for (int i = 0; i < argc; i++)
171			argsMessage.AddString("argv", argv[i]);
172		unitTesterMessenger.SendMessage(&argsMessage);
173		// run the app
174		app->Run();
175		delete app;
176		// send terminated message
177		unitTesterMessenger.SendMessage(MSG_TERMINATED);
178	}
179	return 0;
180}
181
182