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 //------------------------------------------------------------------------------
TInstantiateObjectTester(string name)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 */
Case1()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 */
Case2()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 */
Case3()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 */
Case4()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 */
Case5()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
Case6()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 */
Case7()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 */
Case8()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 */
Case9()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 */
Case10()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 */
Case11()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 */
Case12()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 */
Case13()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 */
Case14()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 //------------------------------------------------------------------------------
Suite()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 //------------------------------------------------------------------------------
LoadAddon()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 //------------------------------------------------------------------------------
UnloadAddon()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 //------------------------------------------------------------------------------
GetLocalSignature()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 //------------------------------------------------------------------------------
FormatAndThrow(int line,const char * file,const char * msg,int err)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
RunTests()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