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