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