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