1 //------------------------------------------------------------------------------ 2 // InstantiateObjectTester.cpp 3 // 4 /** 5 Testing of instantiate_object(BMessage* archive, image_id* id) 6 @note No cases are currently defined for NULL 'id' parameter, since NULL 7 is a valid value for it. Perhaps there should be to ensure that the 8 instantiate_object is, in fact, dealing with that case correctly. 9 There are also no tests against instantiate_object(BMessage*) as it 10 simply calls instantiate_object(BMessage*, image_id*) with NULL for 11 the image_id parameter. 12 */ 13 //------------------------------------------------------------------------------ 14 15 #include "InstantiateObjectTester.h" 16 17 // Standard Includes ----------------------------------------------------------- 18 #include <errno.h> 19 #include <stdexcept> 20 #include <iostream> 21 22 // System Includes ------------------------------------------------------------- 23 #include <Roster.h> 24 #include <Entry.h> 25 #include <Path.h> 26 27 // Project Includes ------------------------------------------------------------ 28 #include <cppunit/Exception.h> 29 #include <TestShell.h> 30 31 // Local Includes -------------------------------------------------------------- 32 #include "remoteobjectdef/RemoteTestObject.h" 33 #include "LocalTestObject.h" 34 35 using namespace std; 36 37 // Local Defines --------------------------------------------------------------- 38 #define FORMAT_AND_THROW(MSG, ERR) \ 39 FormatAndThrow(__LINE__, __FILE__, MSG, ERR) 40 41 // Globals --------------------------------------------------------------------- 42 const char* gInvalidClassName = "TInvalidClassName"; 43 const char* gInvalidSig = "application/x-vnd.InvalidSignature"; 44 const char* gLocalClassName = "TIOTest"; 45 const char* gLocalSig = "application/x-vnd.LocalSignature"; 46 const char* gRemoteClassName = "TRemoteTestObject"; 47 const char* gRemoteSig = "application/x-vnd.RemoteObjectDef"; 48 const char* gValidSig = gRemoteSig; 49 #if !TEST_R5 50 const char* gRemoteLib = "/lib/libsupporttest_RemoteTestObject.so"; 51 #else 52 const char* gRemoteLib = "/lib/libsupporttest_RemoteTestObject_r5.so"; 53 #endif 54 55 void FormatAndThrow(int line, const char* file, const char* msg, int err); 56 57 //------------------------------------------------------------------------------ 58 TInstantiateObjectTester::TInstantiateObjectTester(string name) 59 : BTestCase(name), fAddonId(B_ERROR) 60 { 61 ; 62 } 63 //------------------------------------------------------------------------------ 64 /** 65 instantiate_object(BMessage* archive, image_id* id) 66 @case Invalid archive 67 @param archive NULL 68 @param id Valid image_id pointer 69 @results Returns NULL. 70 *id is set to B_BAD_VALUE. 71 errno is set to B_BAD_VALUE. 72 */ 73 void TInstantiateObjectTester::Case1() 74 { 75 errno = B_OK; 76 image_id id = B_OK; 77 TIOTest* Test = (TIOTest*)instantiate_object(NULL, &id); 78 CPPUNIT_ASSERT(Test == NULL); 79 CPPUNIT_ASSERT(id == B_BAD_VALUE); 80 CPPUNIT_ASSERT(errno == B_BAD_VALUE); 81 } 82 //------------------------------------------------------------------------------ 83 /** 84 instantiate_object(BMessage* archive, image_id* id) 85 @case No class name 86 @param archive Valid BMessage pointer without string field "class" 87 @param id Valid image_id pointer 88 @results Returns NULL. 89 *id is set to B_BAD_VALUE. 90 errno is set to B_OK. 91 */ 92 void TInstantiateObjectTester::Case2() 93 { 94 errno = B_OK; 95 BMessage Archive; 96 image_id id = B_OK; 97 TIOTest* Test = (TIOTest*)instantiate_object(&Archive, &id); 98 CPPUNIT_ASSERT(Test == NULL); 99 CPPUNIT_ASSERT(id == B_BAD_VALUE); 100 CPPUNIT_ASSERT(errno == B_OK); 101 } 102 //------------------------------------------------------------------------------ 103 104 //------------------------------------------------------------------------------ 105 // Invalid class name tests 106 //------------------------------------------------------------------------------ 107 /** 108 instantiate_object(BMessage* archive, image_id* id) 109 @case Invalid class name 110 @param archive Valid BMessage pointer, with string field labeled "class" 111 containing an invalid class name 112 @param id Valid image_id pointer 113 @results Returns NULL. 114 *id is set to B_BAD_VALUE. 115 errno is set to B_BAD_VALUE. 116 */ 117 void TInstantiateObjectTester::Case3() 118 { 119 errno = B_OK; 120 BMessage Archive; 121 Archive.AddString("class", gInvalidClassName); 122 image_id id = B_OK; 123 TIOTest* Test = (TIOTest*)instantiate_object(&Archive, &id); 124 CPPUNIT_ASSERT(Test == NULL); 125 CPPUNIT_ASSERT(id == B_BAD_VALUE); 126 CPPUNIT_ASSERT(errno == B_BAD_VALUE); 127 } 128 //------------------------------------------------------------------------------ 129 /** 130 instantiate_object(BMessage* archive, image_id* id) 131 @case Invalid class name and signature 132 @param archive Valid BMessage pointer, with string fields labeled "class" 133 and "add_on", containing invalid class name and signature, 134 respectively 135 @param id Valid image_id pointer 136 @results Returns NULL. 137 *id is set to B_BAD_VALUE. 138 errno is set to B_LAUNCH_FAILED_APP_NOT_FOUND. 139 */ 140 void TInstantiateObjectTester::Case4() 141 { 142 errno = B_OK; 143 BMessage Archive; 144 Archive.AddString("class", gInvalidClassName); 145 Archive.AddString("add_on", gInvalidSig); 146 image_id id = B_OK; 147 TIOTest* Test = (TIOTest*)instantiate_object(&Archive, &id); 148 CPPUNIT_ASSERT(Test == NULL); 149 CPPUNIT_ASSERT(id == B_BAD_VALUE); 150 CPPUNIT_ASSERT(errno == B_LAUNCH_FAILED_APP_NOT_FOUND); 151 } 152 //------------------------------------------------------------------------------ 153 /** 154 instantiate_object(BMessage* archive, image_id* id) 155 @case Invalid class name, valid signature 156 @param archive Valid BMessage pointer with string fields labeled "class" 157 and "add_on", containing invalid class name and valid 158 signature, respectively 159 @param id Valid image_id pointer 160 @requires RemoteObjectDef add-on must be built and accessible 161 @results Returns NULL. 162 *id is > 0 (add-on was loaded) 163 errno is set to B_BAD_VALUE. 164 */ 165 void TInstantiateObjectTester::Case5() 166 { 167 errno = B_OK; 168 BMessage Archive; 169 Archive.AddString("class", gInvalidClassName); 170 Archive.AddString("add_on", gValidSig); 171 image_id id = B_OK; 172 TIOTest* Test = (TIOTest*)instantiate_object(&Archive, &id); 173 CPPUNIT_ASSERT(Test == NULL); 174 // The system implementation returns the image_id of the last addon searched 175 // Implies the addon is not unloaded. How to verify this behaviour? Should 176 // the addon be unloaded if it doesn't contain our function? Addons do, 177 // after all, eat into our allowable memory. 178 179 // Verified that addon is *not* unloaded in the Be implementation. If Case8 180 // runs after this case without explicitely unloaded the addon here, it 181 // fails because it depends on the addon image not being available within 182 // the team. 183 CPPUNIT_ASSERT(id > 0); 184 unload_add_on(id); 185 CPPUNIT_ASSERT(errno == B_BAD_VALUE); 186 } 187 //------------------------------------------------------------------------------ 188 189 190 //------------------------------------------------------------------------------ 191 // Valid class name tests 192 //------------------------------------------------------------------------------ 193 /** 194 instantiate_object(BMessage* archive, image_id* id) 195 @case Valid archive of class defined in local image 196 @param archive Valid BMessage pointer with string field "class" containing 197 name of locally defined class which can be instantiated via 198 archiving mechanism 199 @param id Valid image_id pointer 200 @requires locally defined class which can be instantiated via 201 archiving mechanism 202 @results Returns valid TIOTest instance. 203 *id is set to B_BAD_VALUE (no image was loaded). 204 errno is set to B_OK. 205 */ 206 // No sig 207 // Local app -- local class 208 void TInstantiateObjectTester::Case6() 209 { 210 errno = B_OK; 211 BMessage Archive; 212 Archive.AddString("class", gLocalClassName); 213 image_id id = B_OK; 214 TIOTest* Test = (TIOTest*)instantiate_object(&Archive, &id); 215 CPPUNIT_ASSERT(Test != NULL); 216 CPPUNIT_ASSERT(id == B_BAD_VALUE); 217 CPPUNIT_ASSERT(errno == B_OK); 218 } 219 //------------------------------------------------------------------------------ 220 /** 221 instantiate_object(BMessage* archive, image_id* id) 222 @case Valid archive of class defined in add-on explicitely loaded 223 by this team 224 @param archive Valid BMessage pointer with string field "class" containing 225 name of remotely defined class which can be instantiated via 226 archiving mechanism 227 @param id Valid image_id pointer 228 @requires RemoteObjectDef add-on must be built and accessible 229 @results Returns valid TRemoteTestObject instance. 230 *id is set to B_BAD_VALUE (no image was loaded). 231 errno is set to B_OK. 232 */ 233 void TInstantiateObjectTester::Case7() 234 { 235 errno = B_OK; 236 LoadAddon(); 237 238 BMessage Archive; 239 Archive.AddString("class", gRemoteClassName); 240 image_id id = B_OK; 241 TRemoteTestObject* Test = (TRemoteTestObject*)instantiate_object(&Archive, 242 &id); 243 CPPUNIT_ASSERT(Test != NULL); 244 CPPUNIT_ASSERT(id == B_BAD_VALUE); 245 CPPUNIT_ASSERT(errno == B_OK); 246 247 UnloadAddon(); 248 } 249 //------------------------------------------------------------------------------ 250 /** 251 instantiate_object(BMessage* archive, image_id* id) 252 @case Valid archive of remotely-defined class, without required 253 signature of the defining add-on 254 @param archive Valid BMessage pointer with string field "class" containing 255 name of remotely-defined class; no "add-on" field 256 @param id Valid image_id pointer 257 @results Returns NULL. 258 *id is set to B_BAD_VALUE (no image loaded). 259 errno is set to B_BAD_VALUE. 260 */ 261 void TInstantiateObjectTester::Case8() 262 { 263 errno = B_OK; 264 BMessage Archive; 265 CPPUNIT_ASSERT(Archive.AddString("class", gRemoteClassName) == B_OK); 266 image_id id = B_OK; 267 TRemoteTestObject* Test = (TRemoteTestObject*)instantiate_object(&Archive, 268 &id); 269 CPPUNIT_ASSERT(Test == NULL); 270 CPPUNIT_ASSERT(id == B_BAD_VALUE); 271 CPPUNIT_ASSERT(errno == B_BAD_VALUE); 272 } 273 //------------------------------------------------------------------------------ 274 /** 275 instantiate_object(BMessage* archive, image_id* id) 276 @case Valid archive naming locally defined class with invalid 277 signature 278 @param archive Valid BMessage pointer with string field "class" containing 279 name of locally defined class and string field "add_on" 280 containing invalid signature 281 @param id Valid image_id pointer 282 @results Returns NULL. 283 *id is set to B_BAD_VALUE (no image loaded). 284 errno is set to B_LAUNCH_FAILED_APP_NOT_FOUND. 285 */ 286 void TInstantiateObjectTester::Case9() 287 { 288 errno = B_OK; 289 BMessage Archive; 290 CPPUNIT_ASSERT(Archive.AddString("class", gLocalClassName) == B_OK); 291 CPPUNIT_ASSERT(Archive.AddString("add_on", gInvalidSig) == B_OK); 292 image_id id = B_OK; 293 TIOTest* Test = (TIOTest*)instantiate_object(&Archive, &id); 294 CPPUNIT_ASSERT(Test == NULL); 295 CPPUNIT_ASSERT(id == B_BAD_VALUE); 296 CPPUNIT_ASSERT(errno == B_LAUNCH_FAILED_APP_NOT_FOUND); 297 } 298 //------------------------------------------------------------------------------ 299 /** 300 instantiate_object(BMessage* archive, image_id* id) 301 @case Valid archive of class defined in add-on explicitely loaded 302 by this team, but with an invalid signature 303 @param archive Valid BMessage pointer with string field "class" containing 304 name of remotely-defined class and string field "add_on" 305 containing invalid signature 306 @param id Valid image_id pointer 307 @requires RemoteObjectDef add-on must be built and accessible 308 @results Returns NULL. 309 *id is set to B_BAD_VALUE (no image loaded). 310 errno is set to B_LAUNCH_FAILED_APP_NOT_FOUND. 311 */ 312 void TInstantiateObjectTester::Case10() 313 { 314 errno = B_OK; 315 LoadAddon(); 316 317 BMessage Archive; 318 Archive.AddString("class", gRemoteClassName); 319 Archive.AddString("add_on", gInvalidSig); 320 image_id id = B_OK; 321 TIOTest* Test = (TIOTest*)instantiate_object(&Archive, &id); 322 CPPUNIT_ASSERT(Test == NULL); 323 CPPUNIT_ASSERT(id == B_BAD_VALUE); 324 CPPUNIT_ASSERT(errno == B_LAUNCH_FAILED_APP_NOT_FOUND); 325 326 UnloadAddon(); 327 } 328 //------------------------------------------------------------------------------ 329 /** 330 instantiate_object(BMessage* archive, image_id* id) 331 @case Valid archive of remotely-defined class, with invalid 332 signature 333 @param archive Valid BMessage pointer with string field "class" containing 334 name of remotely-defined class and string field add-on 335 containing invalid signature 336 @param id Valid image_id pointer 337 @results Returns NULL. 338 *id is set to B_BAD_VALUE. 339 errno is set to B_LAUNCH_FAILED_APP_NOT_FOUND 340 */ 341 void TInstantiateObjectTester::Case11() 342 { 343 errno = B_OK; 344 BMessage Archive; 345 Archive.AddString("class", gRemoteClassName); 346 Archive.AddString("add_on", gInvalidSig); 347 image_id id = B_OK; 348 TIOTest* Test = (TIOTest*)instantiate_object(&Archive, &id); 349 CPPUNIT_ASSERT(Test == NULL); 350 CPPUNIT_ASSERT(id == B_BAD_VALUE); 351 CPPUNIT_ASSERT(errno == B_LAUNCH_FAILED_APP_NOT_FOUND); 352 } 353 //------------------------------------------------------------------------------ 354 /** 355 instantiate_object(BMessage* archive, image_id* id) 356 @case Valid archive of locally-defined class with correct 357 signature 358 @param archive Valid BMessage pointer with string field "class" containing 359 name of locally-defined class and string field "add_on" 360 containing signature of current team 361 @param id Valid image_id pointer 362 @requires locally defined class which can be instantiated via 363 archiving mechanism 364 @results Returns valid TIOTest instance. 365 *id is set to B_BAD_VALUE (no image loaded). 366 errno is set to B_OK. 367 @note This test is not currently used; GetLocalSignature() doesn't 368 seem to work without a BApplication instance constructed. 369 See GetLocalSignature() for more info. 370 */ 371 void TInstantiateObjectTester::Case12() 372 { 373 errno = B_OK; 374 BMessage Archive; 375 Archive.AddString("class", gLocalClassName); 376 Archive.AddString("add_on", GetLocalSignature().c_str()); 377 image_id id = B_OK; 378 TIOTest* Test = (TIOTest*)instantiate_object(&Archive, &id); 379 CPPUNIT_ASSERT(Test != NULL); 380 CPPUNIT_ASSERT(id == B_BAD_VALUE); 381 CPPUNIT_ASSERT(errno == B_OK); 382 } 383 //------------------------------------------------------------------------------ 384 /** 385 instantiate_object(BMessage* archive, image_id* id) 386 @case Valid archive of class defined in add-on explicitely loaded 387 by this team with signature of add-on 388 @param archive Valid BMessage pointer with string field "class" containing 389 name of remotely-defined class and string field "add_on" 390 containing signature of loaded add-on 391 @param id Valid image_id pointer 392 @requires RemoteObjectDef add-on must be built and accessible 393 @results Returns valid instance of TRemoteTestObject. 394 *id is set to B_BAD_VALUE (image load not necessary). 395 errno is set to B_OK. 396 */ 397 void TInstantiateObjectTester::Case13() 398 { 399 errno = B_OK; 400 LoadAddon(); 401 402 BMessage Archive; 403 Archive.AddString("class", gRemoteClassName); 404 Archive.AddString("add_on", gRemoteSig); 405 image_id id = B_OK; 406 TRemoteTestObject* Test = (TRemoteTestObject*)instantiate_object(&Archive, &id); 407 CPPUNIT_ASSERT(Test != NULL); 408 CPPUNIT_ASSERT(id == B_BAD_VALUE); 409 CPPUNIT_ASSERT(errno == B_OK); 410 411 UnloadAddon(); 412 } 413 //------------------------------------------------------------------------------ 414 /** 415 instantiate_object(BMessage* archive, image_id* id) 416 @case Valid archive of remotely-defined class with correct 417 signature 418 @param archive Valid BMessage pointer with string field "class" containing 419 name of remotely-defined class and string field "add_on" 420 containing signature of defining add-on 421 @param id Valid image_id pointer 422 @requires RemoteObjectDef must be built and accessible 423 @results Returns valid instance of TRemoteTestObject. 424 *id > 0 (image was loaded). 425 errno is set to B_OK. 426 */ 427 void TInstantiateObjectTester::Case14() 428 { 429 errno = B_OK; 430 BMessage Archive; 431 Archive.AddString("class", gRemoteClassName); 432 Archive.AddString("add_on", gRemoteSig); 433 image_id id = B_OK; 434 TRemoteTestObject* Test = (TRemoteTestObject*)instantiate_object(&Archive, &id); 435 CPPUNIT_ASSERT(Test != NULL); 436 CPPUNIT_ASSERT(id > 0); 437 unload_add_on(id); 438 CPPUNIT_ASSERT(errno == B_OK); 439 } 440 //------------------------------------------------------------------------------ 441 CppUnit::Test* TInstantiateObjectTester::Suite() 442 { 443 CppUnit::TestSuite* SuiteOfTests = new CppUnit::TestSuite; 444 445 // SuiteOfTests->addTest( 446 // new CppUnit::TestCaller<TInstantiateObjectTester>("BArchivable::instantiate_object() Test", 447 // &TInstantiateObjectTester::RunTests)); 448 449 ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case1); 450 ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case2); 451 ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case3); 452 ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case4); 453 ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case5); 454 ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case6); 455 ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case8); 456 ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case7); 457 ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case9); 458 ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case10); 459 ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case11); 460 // ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case12); 461 ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case13); 462 ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case14); 463 464 return SuiteOfTests; 465 } 466 //------------------------------------------------------------------------------ 467 void TInstantiateObjectTester::LoadAddon() 468 { 469 if (fAddonId > 0) 470 return; 471 472 // We're not testing the roster, so I'm going to just 473 // find the add-on manually. 474 std::string libPath = std::string(BTestShell::GlobalTestDir()) + gRemoteLib; 475 cout << "dir == '" << libPath << "'" << endl; 476 fAddonId = load_add_on(libPath.c_str()); 477 478 RES(fAddonId); 479 if (fAddonId <= 0) 480 { 481 FORMAT_AND_THROW(" failed to load addon: ", fAddonId); 482 } 483 } 484 //------------------------------------------------------------------------------ 485 void TInstantiateObjectTester::UnloadAddon() 486 { 487 if (fAddonId > 0) 488 { 489 status_t err = unload_add_on(fAddonId); 490 fAddonId = B_ERROR; 491 if (err) 492 { 493 FORMAT_AND_THROW(" failed to unload addon: ", err); 494 } 495 } 496 } 497 //------------------------------------------------------------------------------ 498 std::string TInstantiateObjectTester::GetLocalSignature() 499 { 500 BRoster Roster; 501 app_info ai; 502 team_id team; 503 504 // Get the team_id of this app 505 thread_id tid = find_thread(NULL); 506 thread_info ti; 507 status_t err = get_thread_info(tid, &ti); 508 if (err) 509 { 510 FORMAT_AND_THROW(" failed to get thread_info: ", err); 511 } 512 513 // Get the app_info via the team_id 514 team = ti.team; 515 team_info info; 516 err = get_team_info(team, &info); 517 if (err) 518 { 519 FORMAT_AND_THROW(" failed to get team_info: ", err); 520 } 521 522 team = info.team; 523 524 // It seems that this call to GetRunningAppInfo() is not working because we 525 // don't have an instance of BApplication somewhere -- the roster, therefore, 526 // doesn't know about us. 527 err = Roster.GetRunningAppInfo(team, &ai); 528 if (err) 529 { 530 FORMAT_AND_THROW(" failed to get app_info: ", err); 531 } 532 533 // Return the signature from the app_info 534 return ai.signature; 535 } 536 //------------------------------------------------------------------------------ 537 538 //------------------------------------------------------------------------------ 539 void FormatAndThrow(int line, const char *file, const char *msg, int err) 540 { 541 std::string s("line: "); 542 s += IntToStr(line); 543 s += " "; 544 s += file; 545 s += msg; 546 s += strerror(err); 547 s += "("; 548 s += IntToStr(err); 549 s += ")"; 550 CppUnit::Exception re(s.c_str()); 551 throw re; 552 } 553 //------------------------------------------------------------------------------ 554 555 void 556 TInstantiateObjectTester::RunTests() { 557 NextSubTest(); 558 Case1(); 559 NextSubTest(); 560 Case2(); 561 NextSubTest(); 562 Case3(); 563 NextSubTest(); 564 Case4(); 565 NextSubTest(); 566 Case5(); 567 NextSubTest(); 568 Case6(); 569 NextSubTest(); 570 Case7(); 571 NextSubTest(); 572 Case8(); 573 NextSubTest(); 574 Case9(); 575 NextSubTest(); 576 Case10(); 577 NextSubTest(); 578 Case11(); 579 NextSubTest(); 580 Case12(); 581 NextSubTest(); 582 Case13(); 583 NextSubTest(); 584 Case14(); 585 } 586 587 /* 588 * $Log $ 589 * 590 * $Id $ 591 * 592 */ 593 594 595