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
ref_for_path(const char * filename,bool traverse=true)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
create_app(const char * filename,const char * signature,bool install=false,bool makeExecutable=true,uint32 appFlags=B_SINGLE_LAUNCH)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
setUp()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
tearDown()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:
SimpleAppLauncher()123 SimpleAppLauncher() : fRef() {}
SimpleAppLauncher(const entry_ref & ref)124 SimpleAppLauncher(const entry_ref &ref) : fRef(ref) {}
~SimpleAppLauncher()125 virtual ~SimpleAppLauncher() {}
operator ()(const char * type,BList * messages,int32 argc,const char ** argv,team_id * team)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 }
SupportsRefs() const131 virtual bool SupportsRefs() const { return true; }
Ref() const132 virtual const entry_ref *Ref() const { return &fRef; }
133
CloneInternal()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 */
BroadcastTestA1()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 */
BroadcastTestA2()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 */
BroadcastTestB1()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 */
BroadcastTestB2()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 */
BroadcastTestB3()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
Suite()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