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