//------------------------------------------------------------------------------ // InstantiateObjectTester.cpp // /** Testing of instantiate_object(BMessage* archive, image_id* id) @note No cases are currently defined for NULL 'id' parameter, since NULL is a valid value for it. Perhaps there should be to ensure that the instantiate_object is, in fact, dealing with that case correctly. There are also no tests against instantiate_object(BMessage*) as it simply calls instantiate_object(BMessage*, image_id*) with NULL for the image_id parameter. */ //------------------------------------------------------------------------------ // Standard Includes ----------------------------------------------------------- #include #include // System Includes ------------------------------------------------------------- #include #include #include // Project Includes ------------------------------------------------------------ #include #include // Local Includes -------------------------------------------------------------- #include "remoteobjectdef/RemoteTestObject.h" #include "InstantiateObjectTester.h" #include "LocalTestObject.h" // Local Defines --------------------------------------------------------------- #define FORMAT_AND_THROW(MSG, ERR) \ FormatAndThrow(__LINE__, __FILE__, MSG, ERR) // Globals --------------------------------------------------------------------- const char* gInvalidClassName = "TInvalidClassName"; const char* gInvalidSig = "application/x-vnd.InvalidSignature"; const char* gLocalClassName = "TIOTest"; const char* gLocalSig = "application/x-vnd.LocalSignature"; const char* gRemoteClassName = "TRemoteTestObject"; const char* gRemoteSig = "application/x-vnd.RemoteObjectDef"; const char* gValidSig = gRemoteSig; #if !TEST_R5 const char* gRemoteLib = "/lib/libsupporttest_RemoteTestObject.so"; #else const char* gRemoteLib = "/lib/libsupporttest_RemoteTestObject_r5.so"; #endif void FormatAndThrow(int line, const char* file, const char* msg, int err); //------------------------------------------------------------------------------ TInstantiateObjectTester::TInstantiateObjectTester(string name) : BTestCase(name), fAddonId(B_ERROR) { ; } //------------------------------------------------------------------------------ /** instantiate_object(BMessage* archive, image_id* id) @case Invalid archive @param archive NULL @param id Valid image_id pointer @results Returns NULL. *id is set to B_BAD_VALUE. errno is set to B_BAD_VALUE. */ void TInstantiateObjectTester::Case1() { errno = B_OK; image_id id = B_OK; TIOTest* Test = (TIOTest*)instantiate_object(NULL, &id); CPPUNIT_ASSERT(Test == NULL); CPPUNIT_ASSERT(id == B_BAD_VALUE); CPPUNIT_ASSERT(errno == B_BAD_VALUE); } //------------------------------------------------------------------------------ /** instantiate_object(BMessage* archive, image_id* id) @case No class name @param archive Valid BMessage pointer without string field "class" @param id Valid image_id pointer @results Returns NULL. *id is set to B_BAD_VALUE. errno is set to B_OK. */ void TInstantiateObjectTester::Case2() { errno = B_OK; BMessage Archive; image_id id = B_OK; TIOTest* Test = (TIOTest*)instantiate_object(&Archive, &id); CPPUNIT_ASSERT(Test == NULL); CPPUNIT_ASSERT(id == B_BAD_VALUE); CPPUNIT_ASSERT(errno == B_OK); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // Invalid class name tests //------------------------------------------------------------------------------ /** instantiate_object(BMessage* archive, image_id* id) @case Invalid class name @param archive Valid BMessage pointer, with string field labeled "class" containing an invalid class name @param id Valid image_id pointer @results Returns NULL. *id is set to B_BAD_VALUE. errno is set to B_BAD_VALUE. */ void TInstantiateObjectTester::Case3() { errno = B_OK; BMessage Archive; Archive.AddString("class", gInvalidClassName); image_id id = B_OK; TIOTest* Test = (TIOTest*)instantiate_object(&Archive, &id); CPPUNIT_ASSERT(Test == NULL); CPPUNIT_ASSERT(id == B_BAD_VALUE); CPPUNIT_ASSERT(errno == B_BAD_VALUE); } //------------------------------------------------------------------------------ /** instantiate_object(BMessage* archive, image_id* id) @case Invalid class name and signature @param archive Valid BMessage pointer, with string fields labeled "class" and "add_on", containing invalid class name and signature, respectively @param id Valid image_id pointer @results Returns NULL. *id is set to B_BAD_VALUE. errno is set to B_LAUNCH_FAILED_APP_NOT_FOUND. */ void TInstantiateObjectTester::Case4() { errno = B_OK; BMessage Archive; Archive.AddString("class", gInvalidClassName); Archive.AddString("add_on", gInvalidSig); image_id id = B_OK; TIOTest* Test = (TIOTest*)instantiate_object(&Archive, &id); CPPUNIT_ASSERT(Test == NULL); CPPUNIT_ASSERT(id == B_BAD_VALUE); CPPUNIT_ASSERT(errno == B_LAUNCH_FAILED_APP_NOT_FOUND); } //------------------------------------------------------------------------------ /** instantiate_object(BMessage* archive, image_id* id) @case Invalid class name, valid signature @param archive Valid BMessage pointer with string fields labeled "class" and "add_on", containing invalid class name and valid signature, respectively @param id Valid image_id pointer @requires RemoteObjectDef add-on must be built and accessible @results Returns NULL. *id is > 0 (add-on was loaded) errno is set to B_BAD_VALUE. */ void TInstantiateObjectTester::Case5() { errno = B_OK; BMessage Archive; Archive.AddString("class", gInvalidClassName); Archive.AddString("add_on", gValidSig); image_id id = B_OK; TIOTest* Test = (TIOTest*)instantiate_object(&Archive, &id); CPPUNIT_ASSERT(Test == NULL); // The system implementation returns the image_id of the last addon searched // Implies the addon is not unloaded. How to verify this behaviour? Should // the addon be unloaded if it doesn't contain our function? Addons do, // after all, eat into our allowable memory. // Verified that addon is *not* unloaded in the Be implementation. If Case8 // runs after this case without explicitely unloaded the addon here, it // fails because it depends on the addon image not being available within // the team. CPPUNIT_ASSERT(id > 0); unload_add_on(id); CPPUNIT_ASSERT(errno == B_BAD_VALUE); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // Valid class name tests //------------------------------------------------------------------------------ /** instantiate_object(BMessage* archive, image_id* id) @case Valid archive of class defined in local image @param archive Valid BMessage pointer with string field "class" containing name of locally defined class which can be instantiated via archiving mechanism @param id Valid image_id pointer @requires locally defined class which can be instantiated via archiving mechanism @results Returns valid TIOTest instance. *id is set to B_BAD_VALUE (no image was loaded). errno is set to B_OK. */ // No sig // Local app -- local class void TInstantiateObjectTester::Case6() { errno = B_OK; BMessage Archive; Archive.AddString("class", gLocalClassName); image_id id = B_OK; TIOTest* Test = (TIOTest*)instantiate_object(&Archive, &id); CPPUNIT_ASSERT(Test != NULL); CPPUNIT_ASSERT(id == B_BAD_VALUE); CPPUNIT_ASSERT(errno == B_OK); } //------------------------------------------------------------------------------ /** instantiate_object(BMessage* archive, image_id* id) @case Valid archive of class defined in add-on explicitely loaded by this team @param archive Valid BMessage pointer with string field "class" containing name of remotely defined class which can be instantiated via archiving mechanism @param id Valid image_id pointer @requires RemoteObjectDef add-on must be built and accessible @results Returns valid TRemoteTestObject instance. *id is set to B_BAD_VALUE (no image was loaded). errno is set to B_OK. */ void TInstantiateObjectTester::Case7() { errno = B_OK; LoadAddon(); BMessage Archive; Archive.AddString("class", gRemoteClassName); image_id id = B_OK; TRemoteTestObject* Test = (TRemoteTestObject*)instantiate_object(&Archive, &id); CPPUNIT_ASSERT(Test != NULL); CPPUNIT_ASSERT(id == B_BAD_VALUE); CPPUNIT_ASSERT(errno == B_OK); UnloadAddon(); } //------------------------------------------------------------------------------ /** instantiate_object(BMessage* archive, image_id* id) @case Valid archive of remotely-defined class, without required signature of the defining add-on @param archive Valid BMessage pointer with string field "class" containing name of remotely-defined class; no "add-on" field @param id Valid image_id pointer @results Returns NULL. *id is set to B_BAD_VALUE (no image loaded). errno is set to B_BAD_VALUE. */ void TInstantiateObjectTester::Case8() {debugger(__PRETTY_FUNCTION__); errno = B_OK; BMessage Archive; CPPUNIT_ASSERT(Archive.AddString("class", gRemoteClassName) == B_OK); image_id id = B_OK; TRemoteTestObject* Test = (TRemoteTestObject*)instantiate_object(&Archive, &id); CPPUNIT_ASSERT(Test == NULL); CPPUNIT_ASSERT(id == B_BAD_VALUE); CPPUNIT_ASSERT(errno == B_BAD_VALUE); } //------------------------------------------------------------------------------ /** instantiate_object(BMessage* archive, image_id* id) @case Valid archive naming locally defined class with invalid signature @param archive Valid BMessage pointer with string field "class" containing name of locally defined class and string field "add_on" containing invalid signature @param id Valid image_id pointer @results Returns NULL. *id is set to B_BAD_VALUE (no image loaded). errno is set to B_LAUNCH_FAILED_APP_NOT_FOUND. */ void TInstantiateObjectTester::Case9() { errno = B_OK; BMessage Archive; CPPUNIT_ASSERT(Archive.AddString("class", gLocalClassName) == B_OK); CPPUNIT_ASSERT(Archive.AddString("add_on", gInvalidSig) == B_OK); image_id id = B_OK; TIOTest* Test = (TIOTest*)instantiate_object(&Archive, &id); CPPUNIT_ASSERT(Test == NULL); CPPUNIT_ASSERT(id == B_BAD_VALUE); CPPUNIT_ASSERT(errno == B_LAUNCH_FAILED_APP_NOT_FOUND); } //------------------------------------------------------------------------------ /** instantiate_object(BMessage* archive, image_id* id) @case Valid archive of class defined in add-on explicitely loaded by this team, but with an invalid signature @param archive Valid BMessage pointer with string field "class" containing name of remotely-defined class and string field "add_on" containing invalid signature @param id Valid image_id pointer @requires RemoteObjectDef add-on must be built and accessible @results Returns NULL. *id is set to B_BAD_VALUE (no image loaded). errno is set to B_LAUNCH_FAILED_APP_NOT_FOUND. */ void TInstantiateObjectTester::Case10() { errno = B_OK; LoadAddon(); BMessage Archive; Archive.AddString("class", gRemoteClassName); Archive.AddString("add_on", gInvalidSig); image_id id = B_OK; TIOTest* Test = (TIOTest*)instantiate_object(&Archive, &id); CPPUNIT_ASSERT(Test == NULL); CPPUNIT_ASSERT(id == B_BAD_VALUE); CPPUNIT_ASSERT(errno == B_LAUNCH_FAILED_APP_NOT_FOUND); UnloadAddon(); } //------------------------------------------------------------------------------ /** instantiate_object(BMessage* archive, image_id* id) @case Valid archive of remotely-defined class, with invalid signature @param archive Valid BMessage pointer with string field "class" containing name of remotely-defined class and string field add-on containing invalid signature @param id Valid image_id pointer @results Returns NULL. *id is set to B_BAD_VALUE. errno is set to B_LAUNCH_FAILED_APP_NOT_FOUND */ void TInstantiateObjectTester::Case11() { errno = B_OK; BMessage Archive; Archive.AddString("class", gRemoteClassName); Archive.AddString("add_on", gInvalidSig); image_id id = B_OK; TIOTest* Test = (TIOTest*)instantiate_object(&Archive, &id); CPPUNIT_ASSERT(Test == NULL); CPPUNIT_ASSERT(id == B_BAD_VALUE); CPPUNIT_ASSERT(errno == B_LAUNCH_FAILED_APP_NOT_FOUND); } //------------------------------------------------------------------------------ /** instantiate_object(BMessage* archive, image_id* id) @case Valid archive of locally-defined class with correct signature @param archive Valid BMessage pointer with string field "class" containing name of locally-defined class and string field "add_on" containing signature of current team @param id Valid image_id pointer @requires locally defined class which can be instantiated via archiving mechanism @results Returns valid TIOTest instance. *id is set to B_BAD_VALUE (no image loaded). errno is set to B_OK. @note This test is not currently used; GetLocalSignature() doesn't seem to work without a BApplication instance constructed. See GetLocalSignature() for more info. */ void TInstantiateObjectTester::Case12() { errno = B_OK; BMessage Archive; Archive.AddString("class", gLocalClassName); Archive.AddString("add_on", GetLocalSignature().c_str()); image_id id = B_OK; TIOTest* Test = (TIOTest*)instantiate_object(&Archive, &id); CPPUNIT_ASSERT(Test != NULL); CPPUNIT_ASSERT(id == B_BAD_VALUE); CPPUNIT_ASSERT(errno == B_OK); } //------------------------------------------------------------------------------ /** instantiate_object(BMessage* archive, image_id* id) @case Valid archive of class defined in add-on explicitely loaded by this team with signature of add-on @param archive Valid BMessage pointer with string field "class" containing name of remotely-defined class and string field "add_on" containing signature of loaded add-on @param id Valid image_id pointer @requires RemoteObjectDef add-on must be built and accessible @results Returns valid instance of TRemoteTestObject. *id is set to B_BAD_VALUE (image load not necessary). errno is set to B_OK. */ void TInstantiateObjectTester::Case13() { errno = B_OK; LoadAddon(); BMessage Archive; Archive.AddString("class", gRemoteClassName); Archive.AddString("add_on", gRemoteSig); image_id id = B_OK; TRemoteTestObject* Test = (TRemoteTestObject*)instantiate_object(&Archive, &id); CPPUNIT_ASSERT(Test != NULL); CPPUNIT_ASSERT(id == B_BAD_VALUE); CPPUNIT_ASSERT(errno == B_OK); UnloadAddon(); } //------------------------------------------------------------------------------ /** instantiate_object(BMessage* archive, image_id* id) @case Valid archive of remotely-defined class with correct signature @param archive Valid BMessage pointer with string field "class" containing name of remotely-defined class and string field "add_on" containing signature of defining add-on @param id Valid image_id pointer @requires RemoteObjectDef must be built and accessible @results Returns valid instance of TRemoteTestObject. *id > 0 (image was loaded). errno is set to B_OK. */ void TInstantiateObjectTester::Case14() { errno = B_OK; BMessage Archive; Archive.AddString("class", gRemoteClassName); Archive.AddString("add_on", gRemoteSig); image_id id = B_OK; TRemoteTestObject* Test = (TRemoteTestObject*)instantiate_object(&Archive, &id); CPPUNIT_ASSERT(Test != NULL); CPPUNIT_ASSERT(id > 0); unload_add_on(id); CPPUNIT_ASSERT(errno == B_OK); } //------------------------------------------------------------------------------ CppUnit::Test* TInstantiateObjectTester::Suite() { CppUnit::TestSuite* SuiteOfTests = new CppUnit::TestSuite; // SuiteOfTests->addTest( // new CppUnit::TestCaller("BArchivable::instantiate_object() Test", // &TInstantiateObjectTester::RunTests)); ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case1); ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case2); ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case3); ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case4); ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case5); ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case6); ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case8); ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case7); ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case9); ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case10); ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case11); // ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case12); ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case13); ADD_TEST(SuiteOfTests, TInstantiateObjectTester, Case14); return SuiteOfTests; } //------------------------------------------------------------------------------ void TInstantiateObjectTester::LoadAddon() { if (fAddonId > 0) return; // We're not testing the roster, so I'm going to just // find the add-on manually. std::string libPath = std::string(BTestShell::GlobalTestDir()) + gRemoteLib; cout << "dir == '" << libPath << "'" << endl; fAddonId = load_add_on(libPath.c_str()); RES(fAddonId); if (fAddonId <= 0) { FORMAT_AND_THROW(" failed to load addon: ", fAddonId); } } //------------------------------------------------------------------------------ void TInstantiateObjectTester::UnloadAddon() { if (fAddonId > 0) { status_t err = unload_add_on(fAddonId); fAddonId = B_ERROR; if (err) { FORMAT_AND_THROW(" failed to unload addon: ", err); } } } //------------------------------------------------------------------------------ std::string TInstantiateObjectTester::GetLocalSignature() { BRoster Roster; app_info ai; team_id team; // Get the team_id of this app thread_id tid = find_thread(NULL); thread_info ti; status_t err = get_thread_info(tid, &ti); if (err) { FORMAT_AND_THROW(" failed to get thread_info: ", err); } // Get the app_info via the team_id team = ti.team; team_info info; err = get_team_info(team, &info); if (err) { FORMAT_AND_THROW(" failed to get team_info: ", err); } team = info.team; // It seems that this call to GetRunningAppInfo() is not working because we // don't have an instance of BApplication somewhere -- the roster, therefore, // doesn't know about us. err = Roster.GetRunningAppInfo(team, &ai); if (err) { FORMAT_AND_THROW(" failed to get app_info: ", err); } // Return the signature from the app_info return ai.signature; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void FormatAndThrow(int line, const char *file, const char *msg, int err) { std::string s("line: "); s += IntToStr(line); s += " "; s += file; s += msg; s += strerror(err); s += "("; s += IntToStr(err); s += ")"; CppUnit::Exception re(s.c_str()); throw re; } //------------------------------------------------------------------------------ void TInstantiateObjectTester::RunTests() { NextSubTest(); Case1(); NextSubTest(); Case2(); NextSubTest(); Case3(); NextSubTest(); Case4(); NextSubTest(); Case5(); NextSubTest(); Case6(); NextSubTest(); Case7(); NextSubTest(); Case8(); NextSubTest(); Case9(); NextSubTest(); Case10(); NextSubTest(); Case11(); NextSubTest(); Case12(); NextSubTest(); Case13(); NextSubTest(); Case14(); } /* * $Log $ * * $Id $ * */