1// RosterWatchingTestApp1.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-watching-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		switch (_message->what) {
117			case B_SOME_APP_LAUNCHED:
118			case B_SOME_APP_QUIT:
119			case B_SOME_APP_ACTIVATED:
120				message.AddBool("don't ignore", true);
121				break;
122		}
123		unitTesterMessenger.SendMessage(&message);
124	}
125
126	virtual bool QuitRequested()
127	{
128		unitTesterMessenger.SendMessage(MSG_QUIT_REQUESTED);
129		return true;
130	}
131
132	virtual void ReadyToRun()
133	{
134		unitTesterMessenger.SendMessage(MSG_READY_TO_RUN);
135	}
136};
137
138// main
139int
140main(int argc, char **argv)
141{
142	// find app file and get signature from resources
143	char path[B_PATH_NAME_LENGTH];
144	status_t error = get_app_path(path);
145	char signature[B_MIME_TYPE_LENGTH];
146	if (error == B_OK) {
147		// init app file
148		BFile file;
149		error = file.SetTo(path, B_READ_ONLY);
150		// get signature
151		BString signatureString;
152		if (error == B_OK) {
153			if (file.ReadAttrString("signature", &signatureString) == B_OK
154				&& signatureString.Length() > 0) {
155				strcpy(signature, signatureString.String());
156			} else
157				strcpy(signature, kDefaultTestAppSignature);
158		} else
159			printf("ERROR: Couldn't init app file: %s\n", strerror(error));
160	} else
161		printf("ERROR: Couldn't get app ref: %s\n", strerror(error));
162	// create the app
163	TestApp *app = NULL;
164	if (error == B_OK) {
165		app = new TestApp(signature);
166//		unitTesterMessenger = BMessenger(kUnitTesterSignature);
167		error = init_unit_tester_messenger();
168		if (error != B_OK)
169			printf("ERROR: Couldn't init messenger: %s\n", strerror(error));
170		// send started message
171		BMessage message(MSG_STARTED);
172		message.AddString("path", path);
173		unitTesterMessenger.SendMessage(&message);
174		// send main() args message
175		BMessage argsMessage(MSG_MAIN_ARGS);
176		argsMessage.AddInt32("argc", argc);
177		for (int i = 0; i < argc; i++)
178			argsMessage.AddString("argv", argv[i]);
179		unitTesterMessenger.SendMessage(&argsMessage);
180		// run the app
181		app->Run();
182		delete app;
183		// send terminated message
184		unitTesterMessenger.SendMessage(MSG_TERMINATED);
185	}
186	return 0;
187}
188
189