xref: /haiku/src/tests/kits/app/broster/BroadcastTester.cpp (revision 1e36cfc2721ef13a187c6f7354dc9cbc485e89d3)
1 //------------------------------------------------------------------------------
2 //	BroadcastTester.cpp
3 //
4 //------------------------------------------------------------------------------
5 
6 // Standard Includes -----------------------------------------------------------
7 #include <stdio.h>
8 #include <utime.h>
9 
10 // System Includes -------------------------------------------------------------
11 #include <Message.h>
12 #include <OS.h>
13 #include <AppFileInfo.h>
14 #include <Application.h>
15 #include <File.h>
16 #include <FindDirectory.h>
17 #include <Handler.h>
18 #include <Looper.h>
19 #include <Message.h>
20 #include <MessageQueue.h>
21 #include <Path.h>
22 #include <Roster.h>
23 #include <String.h>
24 
25 // Project Includes ------------------------------------------------------------
26 #include <TestShell.h>
27 #include <TestUtils.h>
28 #include <cppunit/TestAssert.h>
29 
30 // Local Includes --------------------------------------------------------------
31 #include "AppRunner.h"
32 #include "BroadcastTester.h"
33 #include "LaunchTesterHelper.h"
34 #include "RosterTestAppDefs.h"
35 
36 // Local Defines ---------------------------------------------------------------
37 
38 // Globals ---------------------------------------------------------------------
39 
40 //------------------------------------------------------------------------------
41 
42 static const char *testerSignature
43 	= "application/x-vnd.obos-roster-broadcast-test";
44 static const char *appType1	= "application/x-vnd.obos-roster-broadcast-app1";
45 static const char *appType2	= "application/x-vnd.obos-roster-broadcast-app2";
46 static const char *appType3	= "application/x-vnd.obos-roster-broadcast-app3";
47 static const char *appType4	= "application/x-vnd.obos-roster-broadcast-app4";
48 
49 static const char *testDir		= "/tmp/testdir";
50 static const char *appFile1		= "/tmp/testdir/app1";
51 static const char *appFile2		= "/tmp/testdir/app2";
52 static const char *appFile3		= "/tmp/testdir/app3";
53 static const char *appFile4		= "/tmp/testdir/app4";
54 
55 
56 // ref_for_path
57 static
58 entry_ref
59 ref_for_path(const char *filename, bool traverse = true)
60 {
61 	entry_ref ref;
62 	BEntry entry;
63 	CHK(entry.SetTo(filename, traverse) == B_OK);
64 	CHK(entry.GetRef(&ref) == B_OK);
65 	return ref;
66 }
67 
68 // create_app
69 static
70 entry_ref
71 create_app(const char *filename, const char *signature,
72 		   bool install = false, bool makeExecutable = true,
73 		   uint32 appFlags = B_SINGLE_LAUNCH)
74 {
75 	BString testApp;
76 	CHK(find_test_app("RosterBroadcastTestApp1", &testApp) == B_OK);
77 	system((string("cp ") + testApp.String() + " " + filename).c_str());
78 	if (makeExecutable)
79 		system((string("chmod a+x ") + filename).c_str());
80 	BFile file;
81 	CHK(file.SetTo(filename, B_READ_WRITE) == B_OK);
82 	BAppFileInfo appFileInfo;
83 	CHK(appFileInfo.SetTo(&file) == B_OK);
84 	if (signature)
85 		CHK(appFileInfo.SetSignature(signature) == B_OK);
86 	CHK(appFileInfo.SetAppFlags(appFlags) == B_OK);
87 	if (install && signature)
88 		CHK(BMimeType(signature).Install() == B_OK);
89 	// We write the signature into a separate attribute, just in case we
90 	// decide to also test files without BEOS:APP_SIG attribute.
91 	BString signatureString(signature);
92 	file.WriteAttrString("signature", &signatureString);
93 	return ref_for_path(filename);
94 }
95 
96 
97 // setUp
98 void
99 BroadcastTester::setUp()
100 {
101 	RosterLaunchApp *app = new RosterLaunchApp(testerSignature);
102 	fApplication = app;
103 	app->SetHandler(new RosterBroadcastHandler);
104 	system((string("mkdir ") + testDir).c_str());
105 }
106 
107 // tearDown
108 void
109 BroadcastTester::tearDown()
110 {
111 	BMimeType(appType1).Delete();
112 	BMimeType(appType2).Delete();
113 	BMimeType(appType3).Delete();
114 	BMimeType(appType4).Delete();
115 	delete fApplication;
116 	system((string("rm -rf ") + testDir).c_str());
117 }
118 
119 // SimpleAppLauncher
120 class SimpleAppLauncher : public LaunchCaller {
121 public:
122 	SimpleAppLauncher() : fRef() {}
123 	SimpleAppLauncher(const entry_ref &ref) : fRef(ref) {}
124 	virtual ~SimpleAppLauncher() {}
125 	virtual status_t operator()(const char *type, BList *messages, int32 argc,
126 								const char **argv, team_id *team)
127 	{
128 		return be_roster->Launch(&fRef, (BMessage*)NULL, team);
129 	}
130 	virtual bool SupportsRefs() const { return true; }
131 	virtual const entry_ref *Ref() const { return &fRef; }
132 
133 	virtual LaunchCaller *CloneInternal()
134 	{
135 		return new SimpleAppLauncher;
136 	}
137 
138 protected:
139 	entry_ref fRef;
140 };
141 
142 /*
143 	status_t Broadcast(BMessage *message) const
144 	@case 1			NULL message
145 	@results		Should return B_BAD_VALUE.
146 */
147 void BroadcastTester::BroadcastTestA1()
148 {
149 // R5: crashes when passing a NULL message.
150 #ifndef TEST_R5
151 	CHK(be_roster->Broadcast(NULL) == B_BAD_VALUE);
152 #endif
153 }
154 
155 /*
156 	status_t Broadcast(BMessage *message) const
157 	@case 2			valid message, several apps, one is B_ARGV_ONLY
158 	@results		Should return B_OK and send the message to all (including
159 					the B_ARGV_ONLY) apps. Replies go to be_app_messenger.
160 */
161 void BroadcastTester::BroadcastTestA2()
162 {
163 	LaunchContext context;
164 	BRoster roster;
165 	// launch app 1
166 	entry_ref ref1(create_app(appFile1, appType1));
167 	SimpleAppLauncher caller1(ref1);
168 	team_id team1;
169 	CHK(context(caller1, appType1, &team1) == B_OK);
170 	// launch app 2
171 	entry_ref ref2(create_app(appFile2, appType2, false, true,
172 							  B_SINGLE_LAUNCH | B_ARGV_ONLY));
173 	SimpleAppLauncher caller2(ref2);
174 	team_id team2;
175 	CHK(context(caller2, appType2, &team2) == B_OK);
176 	// launch app 3
177 	entry_ref ref3(create_app(appFile3, appType3));
178 	SimpleAppLauncher caller3(ref3);
179 	team_id team3;
180 	CHK(context(caller3, appType3, &team3) == B_OK);
181 	// launch app 4
182 	entry_ref ref4(create_app(appFile4, appType4));
183 	SimpleAppLauncher caller4(ref4);
184 	team_id team4;
185 	CHK(context(caller4, appType4, &team4) == B_OK);
186 	// wait for the apps to run
187 	context.WaitForMessage(team1, MSG_READY_TO_RUN);
188 	context.WaitForMessage(team2, MSG_READY_TO_RUN);
189 	context.WaitForMessage(team3, MSG_READY_TO_RUN);
190 	context.WaitForMessage(team4, MSG_READY_TO_RUN);
191 	// broadcast a message
192 	BMessage message(MSG_1);
193 	CHK(roster.Broadcast(&message) == B_OK);
194 	// wait for the apps to report the receipt of the message
195 	context.WaitForMessage(team1, MSG_MESSAGE_RECEIVED);
196 	context.WaitForMessage(team2, MSG_MESSAGE_RECEIVED);
197 	context.WaitForMessage(team3, MSG_MESSAGE_RECEIVED);
198 	context.WaitForMessage(team4, MSG_MESSAGE_RECEIVED);
199 	// check the messages
200 	context.Terminate();
201 	// app 1
202 	int32 cookie = 0;
203 	CHK(context.CheckNextMessage(caller1, team1, cookie, MSG_STARTED));
204 	CHK(context.CheckMainArgsMessage(caller1, team1, cookie, &ref1, false));
205 	CHK(context.CheckNextMessage(caller1, team1, cookie, MSG_READY_TO_RUN));
206 	CHK(context.CheckMessageMessage(caller1, team1, cookie, &message));
207 	CHK(context.CheckNextMessage(caller1, team1, cookie, MSG_2));
208 	CHK(context.CheckNextMessage(caller1, team1, cookie, MSG_QUIT_REQUESTED));
209 	CHK(context.CheckNextMessage(caller1, team1, cookie, MSG_TERMINATED));
210 	// app 2
211 	cookie = 0;
212 	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_STARTED));
213 	CHK(context.CheckMainArgsMessage(caller2, team2, cookie, &ref2, false));
214 	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_READY_TO_RUN));
215 	CHK(context.CheckMessageMessage(caller2, team2, cookie, &message));
216 	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_2));
217 	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_QUIT_REQUESTED));
218 	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_TERMINATED));
219 	// app 3
220 	cookie = 0;
221 	CHK(context.CheckNextMessage(caller3, team3, cookie, MSG_STARTED));
222 	CHK(context.CheckMainArgsMessage(caller3, team3, cookie, &ref3, false));
223 	CHK(context.CheckNextMessage(caller3, team3, cookie, MSG_READY_TO_RUN));
224 	CHK(context.CheckMessageMessage(caller3, team3, cookie, &message));
225 	CHK(context.CheckNextMessage(caller3, team3, cookie, MSG_2));
226 	CHK(context.CheckNextMessage(caller3, team3, cookie, MSG_QUIT_REQUESTED));
227 	CHK(context.CheckNextMessage(caller3, team3, cookie, MSG_TERMINATED));
228 	// app 4
229 	cookie = 0;
230 	CHK(context.CheckNextMessage(caller4, team4, cookie, MSG_STARTED));
231 	CHK(context.CheckMainArgsMessage(caller4, team4, cookie, &ref4, false));
232 	CHK(context.CheckNextMessage(caller4, team4, cookie, MSG_READY_TO_RUN));
233 	CHK(context.CheckMessageMessage(caller4, team4, cookie, &message));
234 	CHK(context.CheckNextMessage(caller4, team4, cookie, MSG_2));
235 	CHK(context.CheckNextMessage(caller4, team4, cookie, MSG_QUIT_REQUESTED));
236 	CHK(context.CheckNextMessage(caller4, team4, cookie, MSG_TERMINATED));
237 }
238 
239 /*
240 	status_t Broadcast(BMessage *message, BMessenger replyTo) const
241 	@case 1			NULL message
242 	@results		Should return B_BAD_VALUE.
243 */
244 void BroadcastTester::BroadcastTestB1()
245 {
246 // R5: crashes when passing a NULL message.
247 #ifndef TEST_R5
248 	BMessenger replyTo(dynamic_cast<RosterLaunchApp*>(be_app)->Handler());
249 	CHK(be_roster->Broadcast(NULL, replyTo) == B_BAD_VALUE);
250 #endif
251 }
252 
253 /*
254 	status_t Broadcast(BMessage *message, BMessenger replyTo) const
255 	@case 2			valid message, several apps, one is B_ARGV_ONLY
256 	@results		Should return B_OK and send the message to all (including
257 					the B_ARGV_ONLY) apps. Replies go to the specified
258 					messenger.
259 */
260 void BroadcastTester::BroadcastTestB2()
261 {
262 	LaunchContext context;
263 	BRoster roster;
264 	// launch app 1
265 	entry_ref ref1(create_app(appFile1, appType1));
266 	SimpleAppLauncher caller1(ref1);
267 	team_id team1;
268 	CHK(context(caller1, appType1, &team1) == B_OK);
269 	// launch app 2
270 	entry_ref ref2(create_app(appFile2, appType2, false, true,
271 							  B_SINGLE_LAUNCH | B_ARGV_ONLY));
272 	SimpleAppLauncher caller2(ref2);
273 	team_id team2;
274 	CHK(context(caller2, appType2, &team2) == B_OK);
275 	// launch app 3
276 	entry_ref ref3(create_app(appFile3, appType3));
277 	SimpleAppLauncher caller3(ref3);
278 	team_id team3;
279 	CHK(context(caller3, appType3, &team3) == B_OK);
280 	// launch app 4
281 	entry_ref ref4(create_app(appFile4, appType4));
282 	SimpleAppLauncher caller4(ref4);
283 	team_id team4;
284 	CHK(context(caller4, appType4, &team4) == B_OK);
285 	// wait for the apps to run
286 	context.WaitForMessage(team1, MSG_READY_TO_RUN);
287 	context.WaitForMessage(team2, MSG_READY_TO_RUN);
288 	context.WaitForMessage(team3, MSG_READY_TO_RUN);
289 	context.WaitForMessage(team4, MSG_READY_TO_RUN);
290 	// broadcast a message
291 	BMessage message(MSG_1);
292 	BMessenger replyTo(dynamic_cast<RosterLaunchApp*>(be_app)->Handler());
293 	CHK(roster.Broadcast(&message, replyTo) == B_OK);
294 	// wait for the apps to report the receipt of the message
295 	context.WaitForMessage(team1, MSG_MESSAGE_RECEIVED);
296 	context.WaitForMessage(team2, MSG_MESSAGE_RECEIVED);
297 	context.WaitForMessage(team3, MSG_MESSAGE_RECEIVED);
298 	context.WaitForMessage(team4, MSG_MESSAGE_RECEIVED);
299 	// check the messages
300 	context.Terminate();
301 	// app 1
302 	int32 cookie = 0;
303 	CHK(context.CheckNextMessage(caller1, team1, cookie, MSG_STARTED));
304 	CHK(context.CheckMainArgsMessage(caller1, team1, cookie, &ref1, false));
305 	CHK(context.CheckNextMessage(caller1, team1, cookie, MSG_READY_TO_RUN));
306 	CHK(context.CheckMessageMessage(caller1, team1, cookie, &message));
307 	CHK(context.CheckNextMessage(caller1, team1, cookie, MSG_REPLY));
308 	CHK(context.CheckNextMessage(caller1, team1, cookie, MSG_QUIT_REQUESTED));
309 	CHK(context.CheckNextMessage(caller1, team1, cookie, MSG_TERMINATED));
310 	// app 2
311 	cookie = 0;
312 	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_STARTED));
313 	CHK(context.CheckMainArgsMessage(caller2, team2, cookie, &ref2, false));
314 	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_READY_TO_RUN));
315 	CHK(context.CheckMessageMessage(caller2, team2, cookie, &message));
316 	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_REPLY));
317 	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_QUIT_REQUESTED));
318 	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_TERMINATED));
319 	// app 3
320 	cookie = 0;
321 	CHK(context.CheckNextMessage(caller3, team3, cookie, MSG_STARTED));
322 	CHK(context.CheckMainArgsMessage(caller3, team3, cookie, &ref3, false));
323 	CHK(context.CheckNextMessage(caller3, team3, cookie, MSG_READY_TO_RUN));
324 	CHK(context.CheckMessageMessage(caller3, team3, cookie, &message));
325 	CHK(context.CheckNextMessage(caller3, team3, cookie, MSG_REPLY));
326 	CHK(context.CheckNextMessage(caller3, team3, cookie, MSG_QUIT_REQUESTED));
327 	CHK(context.CheckNextMessage(caller3, team3, cookie, MSG_TERMINATED));
328 	// app 4
329 	cookie = 0;
330 	CHK(context.CheckNextMessage(caller4, team4, cookie, MSG_STARTED));
331 	CHK(context.CheckMainArgsMessage(caller4, team4, cookie, &ref4, false));
332 	CHK(context.CheckNextMessage(caller4, team4, cookie, MSG_READY_TO_RUN));
333 	CHK(context.CheckMessageMessage(caller4, team4, cookie, &message));
334 	CHK(context.CheckNextMessage(caller4, team4, cookie, MSG_REPLY));
335 	CHK(context.CheckNextMessage(caller4, team4, cookie, MSG_QUIT_REQUESTED));
336 	CHK(context.CheckNextMessage(caller4, team4, cookie, MSG_TERMINATED));
337 }
338 
339 /*
340 	status_t Broadcast(BMessage *message, BMessenger replyTo) const
341 	@case 3			valid message, several apps, one is B_ARGV_ONLY,
342 					invalid replyTo
343 	@results		Should return B_OK and send the message to all (including
344 					the B_ARGV_ONLY) apps. Replies go to the roster!
345 */
346 void BroadcastTester::BroadcastTestB3()
347 {
348 	LaunchContext context;
349 	BRoster roster;
350 	// launch app 1
351 	entry_ref ref1(create_app(appFile1, appType1));
352 	SimpleAppLauncher caller1(ref1);
353 	team_id team1;
354 	CHK(context(caller1, appType1, &team1) == B_OK);
355 	// launch app 2
356 	entry_ref ref2(create_app(appFile2, appType2, false, true,
357 							  B_SINGLE_LAUNCH | B_ARGV_ONLY));
358 	SimpleAppLauncher caller2(ref2);
359 	team_id team2;
360 	CHK(context(caller2, appType2, &team2) == B_OK);
361 	// launch app 3
362 	entry_ref ref3(create_app(appFile3, appType3));
363 	SimpleAppLauncher caller3(ref3);
364 	team_id team3;
365 	CHK(context(caller3, appType3, &team3) == B_OK);
366 	// launch app 4
367 	entry_ref ref4(create_app(appFile4, appType4));
368 	SimpleAppLauncher caller4(ref4);
369 	team_id team4;
370 	CHK(context(caller4, appType4, &team4) == B_OK);
371 	// wait for the apps to run
372 	context.WaitForMessage(team1, MSG_READY_TO_RUN);
373 	context.WaitForMessage(team2, MSG_READY_TO_RUN);
374 	context.WaitForMessage(team3, MSG_READY_TO_RUN);
375 	context.WaitForMessage(team4, MSG_READY_TO_RUN);
376 	// broadcast a message
377 	BMessage message(MSG_1);
378 	BMessenger replyTo;
379 	CHK(roster.Broadcast(&message, replyTo) == B_OK);
380 	// wait for the apps to report the receipt of the message
381 	context.WaitForMessage(team1, MSG_MESSAGE_RECEIVED);
382 	context.WaitForMessage(team2, MSG_MESSAGE_RECEIVED);
383 	context.WaitForMessage(team3, MSG_MESSAGE_RECEIVED);
384 	context.WaitForMessage(team4, MSG_MESSAGE_RECEIVED);
385 	// check the messages
386 	context.Terminate();
387 	// app 1
388 	int32 cookie = 0;
389 	CHK(context.CheckNextMessage(caller1, team1, cookie, MSG_STARTED));
390 	CHK(context.CheckMainArgsMessage(caller1, team1, cookie, &ref1, false));
391 	CHK(context.CheckNextMessage(caller1, team1, cookie, MSG_READY_TO_RUN));
392 	CHK(context.CheckMessageMessage(caller1, team1, cookie, &message));
393 //	CHK(context.CheckNextMessage(caller1, team1, cookie, MSG_2));
394 	CHK(context.CheckNextMessage(caller1, team1, cookie, MSG_QUIT_REQUESTED));
395 	CHK(context.CheckNextMessage(caller1, team1, cookie, MSG_TERMINATED));
396 	// app 2
397 	cookie = 0;
398 	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_STARTED));
399 	CHK(context.CheckMainArgsMessage(caller2, team2, cookie, &ref2, false));
400 	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_READY_TO_RUN));
401 	CHK(context.CheckMessageMessage(caller2, team2, cookie, &message));
402 //	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_2));
403 	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_QUIT_REQUESTED));
404 	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_TERMINATED));
405 	// app 3
406 	cookie = 0;
407 	CHK(context.CheckNextMessage(caller3, team3, cookie, MSG_STARTED));
408 	CHK(context.CheckMainArgsMessage(caller3, team3, cookie, &ref3, false));
409 	CHK(context.CheckNextMessage(caller3, team3, cookie, MSG_READY_TO_RUN));
410 	CHK(context.CheckMessageMessage(caller3, team3, cookie, &message));
411 //	CHK(context.CheckNextMessage(caller3, team3, cookie, MSG_2));
412 	CHK(context.CheckNextMessage(caller3, team3, cookie, MSG_QUIT_REQUESTED));
413 	CHK(context.CheckNextMessage(caller3, team3, cookie, MSG_TERMINATED));
414 	// app 4
415 	cookie = 0;
416 	CHK(context.CheckNextMessage(caller4, team4, cookie, MSG_STARTED));
417 	CHK(context.CheckMainArgsMessage(caller4, team4, cookie, &ref4, false));
418 	CHK(context.CheckNextMessage(caller4, team4, cookie, MSG_READY_TO_RUN));
419 	CHK(context.CheckMessageMessage(caller4, team4, cookie, &message));
420 //	CHK(context.CheckNextMessage(caller4, team4, cookie, MSG_2));
421 	CHK(context.CheckNextMessage(caller4, team4, cookie, MSG_QUIT_REQUESTED));
422 	CHK(context.CheckNextMessage(caller4, team4, cookie, MSG_TERMINATED));
423 }
424 
425 
426 Test* BroadcastTester::Suite()
427 {
428 	TestSuite* SuiteOfTests = new TestSuite;
429 
430 	ADD_TEST4(BRoster, SuiteOfTests, BroadcastTester, BroadcastTestA1);
431 	ADD_TEST4(BRoster, SuiteOfTests, BroadcastTester, BroadcastTestA2);
432 
433 	ADD_TEST4(BRoster, SuiteOfTests, BroadcastTester, BroadcastTestB1);
434 	ADD_TEST4(BRoster, SuiteOfTests, BroadcastTester, BroadcastTestB2);
435 	ADD_TEST4(BRoster, SuiteOfTests, BroadcastTester, BroadcastTestB3);
436 
437 	return SuiteOfTests;
438 }
439 
440