xref: /haiku/src/tests/kits/storage/NodeInfoTest.cpp (revision bb24170e40e943e21fbe6160f67d0a2b29fd3b01)
1 // NodeInfoTest.cpp
2 
3 #include <stdio.h>
4 #include <string>
5 #include <unistd.h>
6 
7 #include <Application.h>
8 #include <Bitmap.h>
9 #include <Directory.h>
10 #include <Entry.h>
11 #include <fs_attr.h>
12 #include <Node.h>
13 #include <NodeInfo.h>
14 #include <Path.h>
15 #include <TypeConstants.h>
16 
17 #include <cppunit/Test.h>
18 #include <cppunit/TestCaller.h>
19 #include <cppunit/TestSuite.h>
20 #include <TestShell.h>
21 #include <TestUtils.h>
22 #include <cppunit/TestAssert.h>
23 
24 #include "NodeInfoTest.h"
25 #include "../app/bmessenger/Helpers.h"
26 
27 // test dirs/files/types
28 static const char *testDir			= "/tmp/testDir";
29 static const char *testFile1		= "/tmp/testDir/file1";
30 static const char *testFile2		= "/tmp/testDir/file2";
31 static const char *testFile3		= "/tmp/testDir/file3";
32 static const char *testFile4		= "/tmp/testDir/file4";
33 static const char *abstractTestEntry = "/tmp/testDir/abstract-entry";
34 static const char *testType1		= "application/x-vnd.obos.node-info-test1";
35 static const char *testType2		= "application/x-vnd.obos.node-info-test2";
36 static const char *invalidTestType	= "invalid-mime-type";
37 static const char *tooLongTestType	=
38 "0123456789012345678901234567890123456789012345678901234567890123456789"
39 "0123456789012345678901234567890123456789012345678901234567890123456789"
40 "0123456789012345678901234567890123456789012345678901234567890123456789"
41 "0123456789012345678901234567890123456789012345678901234567890123456789"
42 ;
43 static const char *testAppSignature1
44 	= "application/x-vnd.obos.node-info-test-app1";
45 static const char *testAppSignature2
46 	= "application/x-vnd.obos.node-info-test-app2";
47 
48 
49 // attributes
50 static const char *kTypeAttribute			= "BEOS:TYPE";
51 static const char *kMiniIconAttribute		= "BEOS:M:STD_ICON";
52 static const char *kLargeIconAttribute		= "BEOS:L:STD_ICON";
53 static const char *kPreferredAppAttribute	= "BEOS:PREF_APP";
54 static const char *kAppHintAttribute		= "BEOS:PPATH";
55 
56 enum {
57 	MINI_ICON_TYPE	= 'MICN',
58 	LARGE_ICON_TYPE	= 'ICON',
59 };
60 
61 // create_test_icon
62 static
63 BBitmap *
64 create_test_icon(icon_size size, int fill)
65 {
66 	BBitmap *icon = NULL;
67 	// create
68 	switch (size) {
69 		case B_MINI_ICON:
70 			icon = new BBitmap(BRect(0, 0, 15, 15), B_CMAP8);
71 			break;
72 		case B_LARGE_ICON:
73 			icon = new BBitmap(BRect(0, 0, 31, 31), B_CMAP8);
74 			break;
75 	}
76 	// fill
77 	if (icon)
78 		memset(icon->Bits(), fill, icon->BitsLength());
79 	return icon;
80 }
81 
82 // icon_equal
83 static
84 bool
85 icon_equal(const BBitmap *icon1, const BBitmap *icon2)
86 {
87 	return (icon1->Bounds() == icon2->Bounds()
88 			&& icon1->BitsLength() == icon2->BitsLength()
89 			&& memcmp(icon1->Bits(), icon2->Bits(), icon1->BitsLength()) == 0);
90 }
91 
92 
93 // Suite
94 CppUnit::Test*
95 NodeInfoTest::Suite() {
96 	CppUnit::TestSuite *suite = new CppUnit::TestSuite();
97 	typedef CppUnit::TestCaller<NodeInfoTest> TC;
98 
99 	suite->addTest( new TC("BNodeInfo::Init Test1", &NodeInfoTest::InitTest1) );
100 	suite->addTest( new TC("BNodeInfo::Init Test2", &NodeInfoTest::InitTest2) );
101 	suite->addTest( new TC("BNodeInfo::Type Test", &NodeInfoTest::TypeTest) );
102 	suite->addTest( new TC("BNodeInfo::Icon Test", &NodeInfoTest::IconTest) );
103 	suite->addTest( new TC("BNodeInfo::Preferred App Test",
104 						   &NodeInfoTest::PreferredAppTest) );
105 	suite->addTest( new TC("BNodeInfo::App Hint Test",
106 						   &NodeInfoTest::AppHintTest) );
107 	suite->addTest( new TC("BNodeInfo::Tracker Icon Test",
108 						   &NodeInfoTest::TrackerIconTest) );
109 
110 	return suite;
111 }
112 
113 // setUp
114 void
115 NodeInfoTest::setUp()
116 {
117 	BasicTest::setUp();
118 	// create test dir and files
119 	execCommand(
120 		string("mkdir ") + testDir
121 		+ "; touch " + testFile1
122 			   + " " + testFile2
123 			   + " " + testFile3
124 			   + " " + testFile4
125 	);
126 	// create app
127 	fApplication = new BApplication("application/x-vnd.obos.node-info-test");
128 	// create icons
129 	fIconM1 = create_test_icon(B_MINI_ICON, 1);
130 	fIconM2 = create_test_icon(B_MINI_ICON, 2);
131 	fIconM3 = create_test_icon(B_MINI_ICON, 3);
132 	fIconM4 = create_test_icon(B_MINI_ICON, 4);
133 	fIconL1 = create_test_icon(B_LARGE_ICON, 1);
134 	fIconL2 = create_test_icon(B_LARGE_ICON, 2);
135 	fIconL3 = create_test_icon(B_LARGE_ICON, 3);
136 	fIconL4 = create_test_icon(B_LARGE_ICON, 4);
137 }
138 
139 // tearDown
140 void
141 NodeInfoTest::tearDown()
142 {
143 	// delete the icons
144 	delete fIconM1;
145 	delete fIconM2;
146 	delete fIconM3;
147 	delete fIconM4;
148 	delete fIconL1;
149 	delete fIconL2;
150 	delete fIconL3;
151 	delete fIconL4;
152 	fIconM1 = fIconM2 = fIconL1 = fIconL2 = NULL;
153 	// delete the application
154 	delete fApplication;
155 	fApplication = NULL;
156 	// remove the types we've added
157 	const char * const testTypes[] = {
158 		testType1, testType2, testAppSignature1, testAppSignature2
159 	};
160 	for (uint32 i = 0; i < sizeof(testTypes) / sizeof(const char*); i++) {
161 		BMimeType type(testTypes[i]);
162 		type.Delete();
163 	}
164 
165 	// delete the test dir
166 	execCommand(string("rm -rf ") + testDir);
167 
168 	BasicTest::tearDown();
169 }
170 
171 // InitTest1
172 void
173 NodeInfoTest::InitTest1()
174 {
175 	// BNodeInfo()
176 	// * InitCheck() == B_NO_INIT
177 	NextSubTest();
178 	{
179 		BNodeInfo nodeInfo;
180 		CHK(nodeInfo.InitCheck() == B_NO_INIT);
181 	}
182 
183 	// BNodeInfo(BNode *node)
184 	// * NULL node => InitCheck() == B_BAD_VALUE
185 	NextSubTest();
186 	{
187 		BNodeInfo nodeInfo(NULL);
188 		CHK(nodeInfo.InitCheck() == B_BAD_VALUE);
189 	}
190 	// * invalid node => InitCheck() == B_BAD_VALUE
191 	NextSubTest();
192 	{
193 		BNode node;
194 		BNodeInfo nodeInfo(&node);
195 		CHK(nodeInfo.InitCheck() == B_BAD_VALUE);
196 	}
197 	// * valid node => InitCheck() == B_OK
198 	NextSubTest();
199 	{
200 		BNode node(testFile1);
201 		BNodeInfo nodeInfo(&node);
202 		CHK(nodeInfo.InitCheck() == B_OK);
203 	}
204 }
205 
206 // InitTest2
207 void
208 NodeInfoTest::InitTest2()
209 {
210 	// status_t SetTo(BNode *node)
211 	// * NULL node => InitCheck() == B_NO_INIT
212 	NextSubTest();
213 	{
214 		BNodeInfo nodeInfo;
215 		CHK(nodeInfo.SetTo(NULL) == B_BAD_VALUE);
216 		CHK(nodeInfo.InitCheck() == B_BAD_VALUE);
217 	}
218 	// * invalid node => InitCheck() == B_BAD_VALUE
219 	NextSubTest();
220 	{
221 		BNode node;
222 		BNodeInfo nodeInfo;
223 		CHK(nodeInfo.SetTo(&node) == B_BAD_VALUE);
224 		CHK(nodeInfo.InitCheck() == B_BAD_VALUE);
225 	}
226 	// * valid node => InitCheck() == B_OK
227 	// * reinitialize invalid/valid => InitCheck() == B_BAD_VALUE/B_OK
228 	NextSubTest();
229 	{
230 		BNode node(testFile1);
231 		BNodeInfo nodeInfo;
232 		CHK(nodeInfo.SetTo(&node) == B_OK);
233 		CHK(nodeInfo.InitCheck() == B_OK);
234 		// reinit with NULL node
235 		CHK(nodeInfo.SetTo(NULL) == B_BAD_VALUE);
236 		CHK(nodeInfo.InitCheck() == B_BAD_VALUE);
237 		// reinit with valid node
238 		BNode node2(testFile2);
239 		CHK(nodeInfo.SetTo(&node2) == B_OK);
240 		CHK(nodeInfo.InitCheck() == B_OK);
241 	}
242 }
243 
244 // CheckAttr
245 static
246 void
247 CheckAttr(BNode &node, const char *name, type_code type, const void *data,
248 		  int32 dataSize)
249 {
250 	attr_info info;
251 	CHK(node.GetAttrInfo(name, &info) == B_OK);
252 	CHK(info.type == type);
253 	CHK(info.size == dataSize);
254 	char *buffer = new char[dataSize];
255 	AutoDeleter<char> deleter(buffer, true);
256 	CHK(node.ReadAttr(name, type, 0, buffer, dataSize) == dataSize);
257 	CHK(memcmp(buffer, data, dataSize) == 0);
258 }
259 
260 // CheckNoAttr
261 static
262 void
263 CheckNoAttr(BNode &node, const char *name)
264 {
265 	attr_info info;
266 	CHK(node.GetAttrInfo(name, &info) == B_ENTRY_NOT_FOUND);
267 }
268 
269 // CheckStringAttr
270 /*static
271 void
272 CheckStringAttr(BNode &node, const char *name, const char *data)
273 {
274 	CheckAttr(node, name, B_STRING_TYPE, data, strlen(data) + 1);
275 }*/
276 
277 // CheckTypeAttr
278 static
279 void
280 CheckTypeAttr(BNode &node, const char *data)
281 {
282 	CheckAttr(node, kTypeAttribute, B_MIME_STRING_TYPE, data,
283 			  strlen(data) + 1);
284 }
285 
286 // CheckIconAttr
287 static
288 void
289 CheckIconAttr(BNode &node, BBitmap *data)
290 {
291 	const char *attribute = NULL;
292 	uint32 type = 0;
293 	switch (data->Bounds().IntegerWidth()) {
294 		case 15:
295 			attribute = kMiniIconAttribute;
296 			type = MINI_ICON_TYPE;
297 			break;
298 		case 31:
299 			attribute = kLargeIconAttribute;
300 			type = LARGE_ICON_TYPE;
301 			break;
302 		default:
303 			CHK(false);
304 			break;
305 	}
306 	CheckAttr(node, attribute, type, data->Bits(), data->BitsLength());
307 }
308 
309 // CheckPreferredAppAttr
310 static
311 void
312 CheckPreferredAppAttr(BNode &node, const char *data)
313 {
314 	CheckAttr(node, kPreferredAppAttribute, B_MIME_STRING_TYPE, data,
315 			  strlen(data) + 1);
316 }
317 
318 // CheckAppHintAttr
319 static
320 void
321 CheckAppHintAttr(BNode &node, const entry_ref *ref)
322 {
323 	BPath path;
324 	CHK(path.SetTo(ref) == B_OK);
325 	const char *data = path.Path();
326 // R5: Attribute is of type B_MIME_STRING_TYPE though it contains a path name!
327 	CheckAttr(node, kAppHintAttribute, B_MIME_STRING_TYPE, data,
328 			  strlen(data) + 1);
329 }
330 
331 // TypeTest
332 void
333 NodeInfoTest::TypeTest()
334 {
335 	// status_t GetType(char *type) const
336 	// * NULL type => B_BAD_ADDRESS/B_BAD_VALUE
337 	NextSubTest();
338 	{
339 		BNode node(testFile1);
340 		BNodeInfo nodeInfo;
341 		CHK(nodeInfo.SetTo(&node) == B_OK);
342 		CHK(equals(nodeInfo.GetType(NULL), B_BAD_ADDRESS, B_BAD_VALUE));
343 	}
344 	// * uninitialized => B_NO_INIT
345 	NextSubTest();
346 	{
347 		BNodeInfo nodeInfo;
348 		char type[B_MIME_TYPE_LENGTH];
349 		CHK(nodeInfo.GetType(type) == B_NO_INIT);
350 	}
351 	// * has no type => B_ENTRY_NOT_FOUND
352 	NextSubTest();
353 	{
354 		BNode node(testFile1);
355 		BNodeInfo nodeInfo;
356 		CHK(nodeInfo.SetTo(&node) == B_OK);
357 		char type[B_MIME_TYPE_LENGTH];
358 		CHK(nodeInfo.GetType(type) == B_ENTRY_NOT_FOUND);
359 	}
360 	// * set, get, reset, get
361 	NextSubTest();
362 	{
363 		BNode node(testFile1);
364 		BNodeInfo nodeInfo;
365 		CHK(nodeInfo.SetTo(&node) == B_OK);
366 		// set
367 		CHK(nodeInfo.SetType(testType1) == B_OK);
368 		// get
369 		char type[B_MIME_TYPE_LENGTH];
370 		CHK(nodeInfo.GetType(type) == B_OK);
371 		CHK(strcmp(testType1, type) == 0);
372 		CheckTypeAttr(node, testType1);
373 		// reset
374 		CHK(nodeInfo.SetType(testType2) == B_OK);
375 		// get
376 		CHK(nodeInfo.GetType(type) == B_OK);
377 		CHK(strcmp(testType2, type) == 0);
378 		CheckTypeAttr(node, testType2);
379 	}
380 
381 	// status_t SetType(const char *type)
382 	// * NULL type => B_OK, unsets the type
383 	NextSubTest();
384 	{
385 		BNode node(testFile1);
386 		BNodeInfo nodeInfo;
387 		CHK(nodeInfo.SetTo(&node) == B_OK);
388 		CHK(nodeInfo.SetType(NULL) == B_OK);
389 		// get
390 		char type[B_MIME_TYPE_LENGTH];
391 		CHK(nodeInfo.GetType(type) == B_ENTRY_NOT_FOUND);
392 		CheckNoAttr(node, kTypeAttribute);
393 	}
394 	// * uninitialized => B_NO_INIT
395 	NextSubTest();
396 	{
397 		BNodeInfo nodeInfo;
398 		CHK(nodeInfo.SetType(testType1) == B_NO_INIT);
399 	}
400 	// * invalid MIME type => B_OK
401 	NextSubTest();
402 	{
403 		BNode node(testFile1);
404 		BNodeInfo nodeInfo;
405 		CHK(nodeInfo.SetTo(&node) == B_OK);
406 		CHK(nodeInfo.SetType(invalidTestType) == B_OK);
407 		// get
408 		char type[B_MIME_TYPE_LENGTH];
409 		CHK(nodeInfo.GetType(type) == B_OK);
410 		CHK(strcmp(invalidTestType, type) == 0);
411 		CheckTypeAttr(node, invalidTestType);
412 	}
413 	// * type string too long => B_OK/B_BAD_VALUE
414 	NextSubTest();
415 	{
416 		BNode node(testFile1);
417 		BNodeInfo nodeInfo;
418 		CHK(nodeInfo.SetTo(&node) == B_OK);
419 		// remove attr first
420 		CHK(nodeInfo.SetType(NULL) == B_OK);
421 // R5: Doesn't complain when setting a too long string.
422 // OBOS: Handles this as an error case.
423 #ifdef TEST_R5
424 		CHK(nodeInfo.SetType(tooLongTestType) == B_OK);
425 		// get
426 		char type[1024];
427 		CHK(nodeInfo.GetType(type) == B_OK);
428 // R5: Returns a string one character shorter than the original string
429 //		CHK(strcmp(tooLongTestType, type) == 0);
430 		CheckTypeAttr(node, tooLongTestType);
431 #else
432 		CHK(nodeInfo.SetType(tooLongTestType) == B_BAD_VALUE);
433 		CheckNoAttr(node, kTypeAttribute);
434 #endif
435 	}
436 }
437 
438 // IconTest
439 void
440 NodeInfoTest::IconTest()
441 {
442 	// status_t GetIcon(BBitmap *icon, icon_size k) const
443 	// * NULL icon => B_BAD_VALUE
444 // R5: Crashes when passing a NULL icon.
445 #ifndef TEST_R5
446 	NextSubTest();
447 	{
448 		BNode node(testFile1);
449 		BNodeInfo nodeInfo;
450 		CHK(nodeInfo.SetTo(&node) == B_OK);
451 		CHK(nodeInfo.GetIcon(NULL, B_MINI_ICON) == B_BAD_VALUE);
452 		CHK(nodeInfo.GetIcon(NULL, B_LARGE_ICON) == B_BAD_VALUE);
453 	}
454 #endif
455 	// * uninitialized => B_NO_INIT
456 	NextSubTest();
457 	{
458 		BNodeInfo nodeInfo;
459 		BBitmap icon(BRect(0, 0, 15, 15), B_CMAP8);
460 		CHK(nodeInfo.GetIcon(&icon, B_MINI_ICON) == B_NO_INIT);
461 		BBitmap icon2(BRect(0, 0, 31, 31), B_CMAP8);
462 		CHK(nodeInfo.GetIcon(&icon2, B_LARGE_ICON) == B_NO_INIT);
463 	}
464 	// * icon dimensions != icon size => B_BAD_VALUE
465 	NextSubTest();
466 	{
467 		BNode node(testFile1);
468 		BNodeInfo nodeInfo;
469 		CHK(nodeInfo.SetTo(&node) == B_OK);
470 		BBitmap icon(BRect(0, 0, 31, 31), B_CMAP8);
471 		CHK(nodeInfo.GetIcon(&icon, B_MINI_ICON) == B_BAD_VALUE);
472 		BBitmap icon2(BRect(0, 0, 15, 15), B_CMAP8);
473 		CHK(nodeInfo.GetIcon(&icon2, B_LARGE_ICON) == B_BAD_VALUE);
474 	}
475 	// * has no icon => B_ENTRY_NOT_FOUND
476 	NextSubTest();
477 	{
478 		BNode node(testFile1);
479 		BNodeInfo nodeInfo;
480 		CHK(nodeInfo.SetTo(&node) == B_OK);
481 		BBitmap icon(BRect(0, 0, 15, 15), B_CMAP8);
482 		CHK(nodeInfo.GetIcon(&icon, B_MINI_ICON) == B_ENTRY_NOT_FOUND);
483 	}
484 	// * set, get, reset, get
485 	NextSubTest();
486 	{
487 		BNode node(testFile1);
488 		BNodeInfo nodeInfo;
489 		CHK(nodeInfo.SetTo(&node) == B_OK);
490 		// mini
491 		// set
492 		CHK(nodeInfo.SetIcon(fIconM1, B_MINI_ICON) == B_OK);
493 		// get
494 		BBitmap icon(BRect(0, 0, 15, 15), B_CMAP8);
495 		CHK(nodeInfo.GetIcon(&icon, B_MINI_ICON) == B_OK);
496 		CHK(icon_equal(fIconM1, &icon));
497 		CheckIconAttr(node, fIconM1);
498 		// reset
499 		CHK(nodeInfo.SetIcon(fIconM2, B_MINI_ICON) == B_OK);
500 		// get
501 		BBitmap icon2(BRect(0, 0, 15, 15), B_CMAP8);
502 		CHK(nodeInfo.GetIcon(&icon2, B_MINI_ICON) == B_OK);
503 		CHK(icon_equal(fIconM2, &icon2));
504 		CheckIconAttr(node, fIconM2);
505 		// large
506 		// set
507 		CHK(nodeInfo.SetIcon(fIconL1, B_LARGE_ICON) == B_OK);
508 		// get
509 		BBitmap icon3(BRect(0, 0, 31, 31), B_CMAP8);
510 		CHK(nodeInfo.GetIcon(&icon3, B_LARGE_ICON) == B_OK);
511 		CHK(icon_equal(fIconL1, &icon3));
512 		CheckIconAttr(node, fIconL1);
513 		// reset
514 		CHK(nodeInfo.SetIcon(fIconL2, B_LARGE_ICON) == B_OK);
515 		// get
516 		BBitmap icon4(BRect(0, 0, 31, 31), B_CMAP8);
517 		CHK(nodeInfo.GetIcon(&icon4, B_LARGE_ICON) == B_OK);
518 		CHK(icon_equal(fIconL2, &icon4));
519 		CheckIconAttr(node, fIconL2);
520 	}
521 	// * bitmap color_space != B_CMAP8 => B_OK
522 	NextSubTest();
523 	{
524 		BNode node(testFile1);
525 		BNodeInfo nodeInfo;
526 		CHK(nodeInfo.SetTo(&node) == B_OK);
527 		// mini
528 		BBitmap icon(BRect(0, 0, 15, 15), B_RGB32);
529 		CHK(nodeInfo.GetIcon(&icon, B_MINI_ICON) == B_OK);
530 		BBitmap icon2(BRect(0, 0, 15, 15), B_RGB32);
531 		icon2.SetBits(fIconM2->Bits(), fIconM2->BitsLength(), 0, B_CMAP8);
532 		CHK(icon_equal(&icon, &icon2));
533 		// large
534 // R5: Crashes for some weird reason in GetIcon().
535 #ifndef TEST_R5
536 		BBitmap icon3(BRect(0, 0, 31, 31), B_RGB32);
537 		CHK(nodeInfo.GetIcon(&icon3, B_LARGE_ICON) == B_OK);
538 		BBitmap icon4(BRect(0, 0, 31, 31), B_RGB32);
539 		icon4.SetBits(fIconL2->Bits(), fIconL2->BitsLength(), 0, B_CMAP8);
540 		CHK(icon_equal(&icon3, &icon4));
541 #endif
542 	}
543 
544 	// status_t SetIcon(const BBitmap *icon, icon_size k)
545 	// * NULL icon => unsets icon, B_OK
546 	NextSubTest();
547 	{
548 		BNode node(testFile1);
549 		BNodeInfo nodeInfo;
550 		CHK(nodeInfo.SetTo(&node) == B_OK);
551 		// mini
552 		// set
553 		CHK(nodeInfo.SetIcon(NULL, B_MINI_ICON) == B_OK);
554 		// get
555 		BBitmap icon(BRect(0, 0, 15, 15), B_CMAP8);
556 		CHK(nodeInfo.GetIcon(&icon, B_MINI_ICON) == B_ENTRY_NOT_FOUND);
557 		CheckNoAttr(node, kMiniIconAttribute);
558 		// large
559 		// set
560 		CHK(nodeInfo.SetIcon(NULL, B_LARGE_ICON) == B_OK);
561 		// get
562 		BBitmap icon2(BRect(0, 0, 31, 31), B_CMAP8);
563 		CHK(nodeInfo.GetIcon(&icon2, B_LARGE_ICON) == B_ENTRY_NOT_FOUND);
564 		CheckNoAttr(node, kLargeIconAttribute);
565 	}
566 	// * uninitialized => B_NO_INIT
567 	NextSubTest();
568 	{
569 		BNodeInfo nodeInfo;
570 		BBitmap icon(BRect(0, 0, 15, 15), B_CMAP8);
571 		CHK(nodeInfo.SetIcon(&icon, B_MINI_ICON) == B_NO_INIT);
572 		BBitmap icon2(BRect(0, 0, 31, 31), B_CMAP8);
573 		CHK(nodeInfo.SetIcon(&icon2, B_LARGE_ICON) == B_NO_INIT);
574 	}
575 	// * icon dimensions != icon size => B_BAD_VALUE
576 	NextSubTest();
577 	{
578 		BNode node(testFile1);
579 		BNodeInfo nodeInfo;
580 		CHK(nodeInfo.SetTo(&node) == B_OK);
581 		BBitmap icon(BRect(0, 0, 31, 31), B_CMAP8);
582 		CHK(nodeInfo.SetIcon(&icon, B_MINI_ICON) == B_BAD_VALUE);
583 		BBitmap icon2(BRect(0, 0, 15, 15), B_CMAP8);
584 		CHK(nodeInfo.SetIcon(&icon2, B_LARGE_ICON) == B_BAD_VALUE);
585 	}
586 }
587 
588 // PreferredAppTest
589 void
590 NodeInfoTest::PreferredAppTest()
591 {
592 	// status_t GetPreferredApp(char *signature, app_verb verb = B_OPEN) const
593 	// * NULL signature => B_BAD_ADDRESS/B_BAD_VALUE
594 	NextSubTest();
595 	{
596 		BNode node(testFile1);
597 		BNodeInfo nodeInfo;
598 		CHK(nodeInfo.SetTo(&node) == B_OK);
599 		CHK(equals(nodeInfo.GetPreferredApp(NULL), B_BAD_ADDRESS,
600 				   B_BAD_VALUE));
601 	}
602 	// * uninitialized => B_NO_INIT
603 	NextSubTest();
604 	{
605 		BNodeInfo nodeInfo;
606 		char signature[B_MIME_TYPE_LENGTH];
607 		CHK(nodeInfo.GetPreferredApp(signature) == B_NO_INIT);
608 	}
609 	// * has no preferred app => B_ENTRY_NOT_FOUND
610 	NextSubTest();
611 	{
612 		BNode node(testFile1);
613 		BNodeInfo nodeInfo;
614 		CHK(nodeInfo.SetTo(&node) == B_OK);
615 		char signature[B_MIME_TYPE_LENGTH];
616 		CHK(nodeInfo.GetPreferredApp(signature) == B_ENTRY_NOT_FOUND);
617 	}
618 	// * set, get, reset, get
619 	NextSubTest();
620 	{
621 		BNode node(testFile1);
622 		BNodeInfo nodeInfo;
623 		CHK(nodeInfo.SetTo(&node) == B_OK);
624 		// set
625 		CHK(nodeInfo.SetPreferredApp(testAppSignature1) == B_OK);
626 		// get
627 		char signature[B_MIME_TYPE_LENGTH];
628 		CHK(nodeInfo.GetPreferredApp(signature) == B_OK);
629 		CHK(strcmp(testAppSignature1, signature) == 0);
630 		CheckPreferredAppAttr(node, testAppSignature1);
631 		// reset
632 		CHK(nodeInfo.SetPreferredApp(testAppSignature2) == B_OK);
633 		// get
634 		CHK(nodeInfo.GetPreferredApp(signature) == B_OK);
635 		CHK(strcmp(testAppSignature2, signature) == 0);
636 		CheckPreferredAppAttr(node, testAppSignature2);
637 	}
638 
639 	// status_t SetPreferredApp(const char *signature, app_verb verb = B_OPEN)
640 	// * NULL signature => unsets the preferred app
641 	NextSubTest();
642 	{
643 		BNode node(testFile1);
644 		BNodeInfo nodeInfo;
645 		CHK(nodeInfo.SetTo(&node) == B_OK);
646 		CHK(nodeInfo.SetPreferredApp(NULL) == B_OK);
647 		// get
648 		char signature[B_MIME_TYPE_LENGTH];
649 		CHK(nodeInfo.GetPreferredApp(signature) == B_ENTRY_NOT_FOUND);
650 		CheckNoAttr(node, kPreferredAppAttribute);
651 	}
652 	// * uninitialized => B_NO_INIT
653 	NextSubTest();
654 	{
655 		BNodeInfo nodeInfo;
656 		CHK(nodeInfo.SetPreferredApp(testAppSignature1) == B_NO_INIT);
657 	}
658 	// * invalid MIME type => B_OK
659 	NextSubTest();
660 	{
661 		BNode node(testFile1);
662 		BNodeInfo nodeInfo;
663 		CHK(nodeInfo.SetTo(&node) == B_OK);
664 		CHK(nodeInfo.SetPreferredApp(invalidTestType) == B_OK);
665 		// get
666 		char signature[B_MIME_TYPE_LENGTH];
667 		CHK(nodeInfo.GetPreferredApp(signature) == B_OK);
668 		CHK(strcmp(invalidTestType, signature) == 0);
669 		CheckPreferredAppAttr(node, invalidTestType);
670 	}
671 	// * signature string too long => B_BAD_VALUE
672 	NextSubTest();
673 	{
674 		BNode node(testFile1);
675 		BNodeInfo nodeInfo;
676 		CHK(nodeInfo.SetTo(&node) == B_OK);
677 		// unset
678 		CHK(nodeInfo.SetPreferredApp(NULL) == B_OK);
679 		// try to set
680 		CHK(nodeInfo.SetPreferredApp(tooLongTestType) == B_BAD_VALUE);
681 		// get
682 		char signature[1024];
683 		CHK(nodeInfo.GetPreferredApp(signature) == B_ENTRY_NOT_FOUND);
684 		CheckNoAttr(node, kPreferredAppAttribute);
685 	}
686 }
687 
688 // AppHintTest
689 void
690 NodeInfoTest::AppHintTest()
691 {
692 	// init test refs
693 	entry_ref testRef1, testRef2, abstractRef;
694 	CHK(get_ref_for_path(testFile3, &testRef1) == B_OK);
695 	CHK(get_ref_for_path(testFile4, &testRef2) == B_OK);
696 	CHK(get_ref_for_path(abstractTestEntry, &abstractRef) == B_OK);
697 
698 	// status_t GetAppHint(entry_ref *ref) const
699 	// * NULL ref => B_BAD_VALUE
700 	NextSubTest();
701 	{
702 		BNode node(testFile1);
703 		BNodeInfo nodeInfo;
704 		CHK(nodeInfo.SetTo(&node) == B_OK);
705 		CHK(nodeInfo.GetAppHint(NULL) == B_BAD_VALUE);
706 	}
707 	// * uninitialized => B_NO_INIT
708 	NextSubTest();
709 	{
710 		BNodeInfo nodeInfo;
711 		entry_ref ref;
712 		CHK(nodeInfo.GetAppHint(&ref) == B_NO_INIT);
713 	}
714 	// * has no app hint => B_ENTRY_NOT_FOUND
715 	NextSubTest();
716 	{
717 		BNode node(testFile1);
718 		BNodeInfo nodeInfo;
719 		CHK(nodeInfo.SetTo(&node) == B_OK);
720 		entry_ref ref;
721 		CHK(nodeInfo.GetAppHint(&ref) == B_ENTRY_NOT_FOUND);
722 	}
723 	// * set, get, reset, get
724 	NextSubTest();
725 	{
726 		BNode node(testFile1);
727 		BNodeInfo nodeInfo;
728 		CHK(nodeInfo.SetTo(&node) == B_OK);
729 		// set
730 		CHK(nodeInfo.SetAppHint(&testRef1) == B_OK);
731 		// get
732 		entry_ref ref;
733 		CHK(nodeInfo.GetAppHint(&ref) == B_OK);
734 		CHK(ref == testRef1);
735 		CheckAppHintAttr(node, &testRef1);
736 		// reset
737 		CHK(nodeInfo.SetAppHint(&testRef2) == B_OK);
738 		// get
739 		CHK(nodeInfo.GetAppHint(&ref) == B_OK);
740 		CHK(ref == testRef2);
741 		CheckAppHintAttr(node, &testRef2);
742 	}
743 
744 	// status_t SetAppHint(const entry_ref *ref)
745 	// * NULL ref => B_OK
746 	NextSubTest();
747 	{
748 		BNode node(testFile1);
749 		BNodeInfo nodeInfo;
750 		CHK(nodeInfo.SetTo(&node) == B_OK);
751 		CHK(nodeInfo.SetAppHint(NULL) == B_OK);
752 		// get
753 		entry_ref ref;
754 		CHK(nodeInfo.GetAppHint(&ref) == B_ENTRY_NOT_FOUND);
755 		CheckNoAttr(node, kAppHintAttribute);
756 	}
757 	// * uninitialized => B_NO_INIT
758 	NextSubTest();
759 	{
760 		BNodeInfo nodeInfo;
761 		CHK(nodeInfo.SetAppHint(&testRef1) == B_NO_INIT);
762 	}
763 	// * invalid/abstract ref => != B_OK
764 	NextSubTest();
765 	{
766 		BNode node(testFile1);
767 		BNodeInfo nodeInfo;
768 		CHK(nodeInfo.SetTo(&node) == B_OK);
769 		// invalid ref
770 		entry_ref invalidRef;
771 		CHK(nodeInfo.SetAppHint(&invalidRef) != B_OK);
772 		// abstract ref
773 		CHK(nodeInfo.SetAppHint(&abstractRef) == B_OK);
774 		// get
775 		entry_ref ref;
776 		CHK(nodeInfo.GetAppHint(&ref) == B_OK);
777 		CHK(ref == abstractRef);
778 		CheckAppHintAttr(node, &abstractRef);
779 	}
780 }
781 
782 // TestTrackerIcon
783 static
784 void
785 TestTrackerIcon(BNodeInfo &nodeInfo, entry_ref *ref, icon_size size,
786 				BBitmap *expectedIcon)
787 {
788 	// mini
789 	if (size == B_MINI_ICON) {
790 		// non-static
791 		BBitmap icon(BRect(0, 0, 15, 15), B_CMAP8);
792 		CHK(nodeInfo.GetTrackerIcon(&icon, B_MINI_ICON) == B_OK);
793 		CHK(icon_equal(expectedIcon, &icon));
794 		// static
795 		BBitmap icon1(BRect(0, 0, 15, 15), B_CMAP8);
796 		CHK(BNodeInfo::GetTrackerIcon(ref, &icon1, B_MINI_ICON) == B_OK);
797 		CHK(icon_equal(expectedIcon, &icon1));
798 	} else {
799 		// large
800 		// non-static
801 		BBitmap icon2(BRect(0, 0, 31, 31), B_CMAP8);
802 		CHK(nodeInfo.GetTrackerIcon(&icon2, B_LARGE_ICON) == B_OK);
803 		CHK(icon_equal(expectedIcon, &icon2));
804 		// static
805 		BBitmap icon3(BRect(0, 0, 31, 31), B_CMAP8);
806 		CHK(BNodeInfo::GetTrackerIcon(ref, &icon3, B_LARGE_ICON) == B_OK);
807 		CHK(icon_equal(expectedIcon, &icon3));
808 	}
809 }
810 
811 // TrackerIconTest
812 void
813 NodeInfoTest::TrackerIconTest()
814 {
815 	entry_ref testRef1;
816 	CHK(get_ref_for_path(testFile1, &testRef1) == B_OK);
817 	BBitmap octetMIcon(BRect(0, 0, 15, 15), B_CMAP8);
818 	BBitmap octetLIcon(BRect(0, 0, 31, 31), B_CMAP8);
819 	BMimeType octetType("application/octet-stream");
820 	CHK(octetType.GetIcon(&octetMIcon, B_MINI_ICON) == B_OK);
821 	CHK(octetType.GetIcon(&octetLIcon, B_LARGE_ICON) == B_OK);
822 
823 	// static status_t GetTrackerIcon(const entry_ref *ref, BBitmap *icon,
824 	//								  icon_size k = B_LARGE_ICON)
825 	// * NULL ref => B_BAD_VALUE
826 	NextSubTest();
827 	{
828 		BBitmap icon(BRect(0, 0, 15, 15), B_CMAP8);
829 		CHK(BNodeInfo::GetTrackerIcon(NULL, &icon, B_MINI_ICON)
830 			== B_BAD_VALUE);
831 		BBitmap icon2(BRect(0, 0, 31, 31), B_CMAP8);
832 		CHK(BNodeInfo::GetTrackerIcon(NULL, &icon2, B_LARGE_ICON)
833 			== B_BAD_VALUE);
834 	}
835 
836 	// status_t GetTrackerIcon(BBitmap *icon, icon_size k = B_LARGE_ICON) const
837 	// * uninitialized => B_NO_INIT
838 	NextSubTest();
839 	{
840 		BNodeInfo nodeInfo;
841 		BBitmap icon(BRect(0, 0, 15, 15), B_CMAP8);
842 		CHK(nodeInfo.GetTrackerIcon(&icon, B_MINI_ICON) == B_NO_INIT);
843 		BBitmap icon2(BRect(0, 0, 31, 31), B_CMAP8);
844 		CHK(nodeInfo.GetTrackerIcon(&icon2, B_LARGE_ICON) == B_NO_INIT);
845 	}
846 
847 	// status_t GetTrackerIcon(BBitmap *icon, icon_size k = B_LARGE_ICON) const
848 	// static status_t GetTrackerIcon(const entry_ref *ref, BBitmap *icon,
849 	//								  icon_size k = B_LARGE_ICON)
850 	// * NULL icon => B_BAD_VALUE
851 	NextSubTest();
852 	{
853 		// non-static
854 		BNode node(testFile1);
855 		BNodeInfo nodeInfo;
856 		CHK(nodeInfo.SetTo(&node) == B_OK);
857 		CHK(nodeInfo.GetTrackerIcon(NULL, B_MINI_ICON) == B_BAD_VALUE);
858 		CHK(nodeInfo.GetTrackerIcon(NULL, B_LARGE_ICON) == B_BAD_VALUE);
859 		// static
860 		CHK(BNodeInfo::GetTrackerIcon(&testRef1, NULL, B_MINI_ICON)
861 			== B_BAD_VALUE);
862 		BBitmap icon2(BRect(0, 0, 31, 31), B_CMAP8);
863 		CHK(BNodeInfo::GetTrackerIcon(&testRef1, NULL, B_LARGE_ICON)
864 			== B_BAD_VALUE);
865 	}
866 	// * icon dimensions != icon size => B_BAD_VALUE
867 	NextSubTest();
868 	{
869 		// non-static
870 		BNode node(testFile1);
871 		BNodeInfo nodeInfo;
872 		CHK(nodeInfo.SetTo(&node) == B_OK);
873 		BBitmap icon(BRect(0, 0, 31, 31), B_CMAP8);
874 		CHK(nodeInfo.GetTrackerIcon(&icon, B_MINI_ICON) == B_BAD_VALUE);
875 		BBitmap icon2(BRect(0, 0, 15, 15), B_CMAP8);
876 		CHK(nodeInfo.GetTrackerIcon(&icon2, B_LARGE_ICON) == B_BAD_VALUE);
877 		// static
878 		CHK(BNodeInfo::GetTrackerIcon(&testRef1, &icon, B_MINI_ICON)
879 			== B_BAD_VALUE);
880 		CHK(BNodeInfo::GetTrackerIcon(&testRef1, &icon2, B_LARGE_ICON)
881 			== B_BAD_VALUE);
882 	}
883 
884 	// initialization for further tests
885 	BNode node(testFile1);
886 	BNodeInfo nodeInfo;
887 	CHK(nodeInfo.SetTo(&node) == B_OK);
888 	// install file type
889 	BMimeType type(testType1);
890 	CHK(type.Install() == B_OK);
891 	// set icons for file
892 	CHK(nodeInfo.SetIcon(fIconM1, B_MINI_ICON) == B_OK);
893 	CHK(nodeInfo.SetIcon(fIconL1, B_LARGE_ICON) == B_OK);
894 	// install application type with icons for type, and make it the file's
895 	// preferred application
896 	BMimeType appType(testAppSignature1);
897 	CHK(appType.Install() == B_OK);
898 	CHK(appType.SetIconForType(testType1, fIconM2, B_MINI_ICON) == B_OK);
899 	CHK(appType.SetIconForType(testType1, fIconL2, B_LARGE_ICON) == B_OK);
900 	CHK(nodeInfo.SetPreferredApp(testAppSignature1) == B_OK);
901 	// set icons for type in MIME database
902 	CHK(type.SetIcon(fIconM3, B_MINI_ICON) == B_OK);
903 	CHK(type.SetIcon(fIconL3, B_LARGE_ICON) == B_OK);
904 	// install application type with icons for type, and make it the type's
905 	// preferred application
906 	BMimeType appType2(testAppSignature2);
907 	CHK(appType2.Install() == B_OK);
908 	CHK(appType2.SetIconForType(testType1, fIconM4, B_MINI_ICON) == B_OK);
909 	CHK(appType2.SetIconForType(testType1, fIconL4, B_LARGE_ICON) == B_OK);
910 	CHK(type.SetPreferredApp(testAppSignature2) == B_OK);
911 
912 	// * has icon, but not type => B_OK,
913 	//   returns the "application/octet-stream" icon
914 	NextSubTest();
915 	{
916 		TestTrackerIcon(nodeInfo, &testRef1, B_MINI_ICON, &octetMIcon);
917 		TestTrackerIcon(nodeInfo, &testRef1, B_LARGE_ICON, &octetLIcon);
918 	}
919 	// set invalid file type
920 	CHK(nodeInfo.SetType(invalidTestType) == B_OK);
921 	// * has icon, but invalid type => B_OK, returns file icon
922 	NextSubTest();
923 	{
924 		TestTrackerIcon(nodeInfo, &testRef1, B_MINI_ICON, fIconM1);
925 		TestTrackerIcon(nodeInfo, &testRef1, B_LARGE_ICON, fIconL1);
926 	}
927 	// set file type
928 	CHK(nodeInfo.SetType(testType1) == B_OK);
929 	// * has icon => B_OK
930 	NextSubTest();
931 	{
932 		TestTrackerIcon(nodeInfo, &testRef1, B_MINI_ICON, fIconM1);
933 		TestTrackerIcon(nodeInfo, &testRef1, B_LARGE_ICON, fIconL1);
934 	}
935 	// unset icons
936 	CHK(nodeInfo.SetIcon(NULL, B_MINI_ICON) == B_OK);
937 	CHK(nodeInfo.SetIcon(NULL, B_LARGE_ICON) == B_OK);
938 	// * has no icon, but preferred app with icon for type => B_OK
939 	NextSubTest();
940 	{
941 		TestTrackerIcon(nodeInfo, &testRef1, B_MINI_ICON, fIconM2);
942 		TestTrackerIcon(nodeInfo, &testRef1, B_LARGE_ICON, fIconL2);
943 	}
944 	// unset icons for type for preferred app
945 	CHK(appType.SetIconForType(testType1, NULL, B_MINI_ICON) == B_OK);
946 	CHK(appType.SetIconForType(testType1, NULL, B_LARGE_ICON) == B_OK);
947 	// * no icon, preferred app without icon for type,
948 	//   but icon for type in MIME data base => B_OK
949 	NextSubTest();
950 	{
951 		TestTrackerIcon(nodeInfo, &testRef1, B_MINI_ICON, fIconM3);
952 		TestTrackerIcon(nodeInfo, &testRef1, B_LARGE_ICON, fIconL3);
953 	}
954 	// unset preferred app
955 	CHK(nodeInfo.SetPreferredApp(NULL) == B_OK);
956 	// * no icon, no preferred app,
957 	//   but icon for type in MIME data base => B_OK
958 	NextSubTest();
959 	{
960 		TestTrackerIcon(nodeInfo, &testRef1, B_MINI_ICON, fIconM3);
961 		TestTrackerIcon(nodeInfo, &testRef1, B_LARGE_ICON, fIconL3);
962 	}
963 	// unset icons for type
964 	CHK(type.SetIcon(NULL, B_MINI_ICON) == B_OK);
965 	CHK(type.SetIcon(NULL, B_LARGE_ICON) == B_OK);
966 	// * no icon, no preferred app, no icon for type in MIME data base, but
967 	//   preferred app for type in MIME database and app has icon for type
968 	//   => B_OK
969 	NextSubTest();
970 	{
971 		TestTrackerIcon(nodeInfo, &testRef1, B_MINI_ICON, fIconM4);
972 		TestTrackerIcon(nodeInfo, &testRef1, B_LARGE_ICON, fIconL4);
973 	}
974 	// unset icons for type for preferred app
975 	CHK(appType2.SetIconForType(testType1, NULL, B_MINI_ICON) == B_OK);
976 	CHK(appType2.SetIconForType(testType1, NULL, B_LARGE_ICON) == B_OK);
977 	// * no icon, no preferred app, no icon for type in MIME data base,
978 	//   preferred app for type in MIME database and app has no icon for type
979 	//   => B_OK, returns the "application/octet-stream" icon
980 	NextSubTest();
981 	{
982 		TestTrackerIcon(nodeInfo, &testRef1, B_MINI_ICON, &octetMIcon);
983 		TestTrackerIcon(nodeInfo, &testRef1, B_LARGE_ICON, &octetLIcon);
984 	}
985 	// unset preferred application
986 	CHK(type.SetPreferredApp(NULL) == B_OK);
987 	// * no icon, no preferred app, no icon for type in MIME data base,
988 	//   no preferred app for type in MIME database => B_OK,
989 	//   returns the "application/octet-stream" icon
990 	NextSubTest();
991 	{
992 		TestTrackerIcon(nodeInfo, &testRef1, B_MINI_ICON, &octetMIcon);
993 		TestTrackerIcon(nodeInfo, &testRef1, B_LARGE_ICON, &octetLIcon);
994 	}
995 }
996 
997