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