xref: /haiku/src/tests/kits/storage/EntryTest.cpp (revision 4c8e85b316c35a9161f5a1c50ad70bc91c83a76f)
1 // EntryTest.cpp
2 
3 #include <errno.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include <unistd.h>
7 
8 #include <list>
9 using std::list;
10 #include <map>
11 using std::map;
12 #include <set>
13 using std::set;
14 
15 #include <cppunit/TestCaller.h>
16 #include <cppunit/TestSuite.h>
17 
18 #include <Entry.h>
19 #include <Directory.h>
20 #include <Path.h>
21 
22 #include "EntryTest.h"
23 
24 enum test_entry_kind {
25 	DIR_ENTRY,
26 	FILE_ENTRY,
27 	LINK_ENTRY,
28 	ABSTRACT_ENTRY,
29 	BAD_ENTRY,
30 };
31 
32 struct TestEntry {
33 	TestEntry();
34 
35 	void init(TestEntry &super, string name, test_entry_kind kind,
36 			  bool relative = false);
37 	void initDir(TestEntry &super, string name);
38 	void initFile(TestEntry &super, string name);
39 	void initRLink(TestEntry &super, string name, TestEntry &target);
40 	void initALink(TestEntry &super, string name, TestEntry &target);
41 	void initPath(const char *pathName = NULL);
42 	void completeInit();
43 	bool isConcrete() const { return !(isAbstract() || isBad()); }
44 	bool isAbstract() const { return kind == ABSTRACT_ENTRY; }
45 	bool isBad() const { return kind == BAD_ENTRY; }
46 	const entry_ref &get_ref();
47 
48 	TestEntry *		super;
49 	string			name;
50 	test_entry_kind	kind;
51 	string			path;
52 	TestEntry *		target;
53 	string			link;
54 	entry_ref		ref;
55 	bool			relative;
56 	// C strings
57 	const char *	cname;
58 	const char *	cpath;
59 	const char *	clink;
60 };
61 
62 static list<TestEntry*> allTestEntries;
63 
64 static TestEntry badTestEntry;
65 static TestEntry testDir;
66 static TestEntry dir1;
67 static TestEntry dir2;
68 static TestEntry file1;
69 static TestEntry file2;
70 static TestEntry file3;
71 static TestEntry file4;
72 static TestEntry subDir1;
73 static TestEntry abstractEntry1;
74 static TestEntry badEntry1;
75 static TestEntry absDirLink1;
76 static TestEntry absDirLink2;
77 static TestEntry absDirLink3;
78 static TestEntry absDirLink4;
79 static TestEntry relDirLink1;
80 static TestEntry relDirLink2;
81 static TestEntry relDirLink3;
82 static TestEntry relDirLink4;
83 static TestEntry absFileLink1;
84 static TestEntry absFileLink2;
85 static TestEntry absFileLink3;
86 static TestEntry absFileLink4;
87 static TestEntry relFileLink1;
88 static TestEntry relFileLink2;
89 static TestEntry relFileLink3;
90 static TestEntry relFileLink4;
91 static TestEntry absCyclicLink1;
92 static TestEntry absCyclicLink2;
93 static TestEntry relCyclicLink1;
94 static TestEntry relCyclicLink2;
95 static TestEntry absBadLink1;
96 static TestEntry absBadLink2;
97 static TestEntry absBadLink3;
98 static TestEntry absBadLink4;
99 static TestEntry relBadLink1;
100 static TestEntry relBadLink2;
101 static TestEntry relBadLink3;
102 static TestEntry relBadLink4;
103 static TestEntry absVeryBadLink1;
104 static TestEntry absVeryBadLink2;
105 static TestEntry absVeryBadLink3;
106 static TestEntry absVeryBadLink4;
107 static TestEntry relVeryBadLink1;
108 static TestEntry relVeryBadLink2;
109 static TestEntry relVeryBadLink3;
110 static TestEntry relVeryBadLink4;
111 static TestEntry tooLongEntry1;
112 static TestEntry tooLongDir1;
113 static TestEntry tooLongDir2;
114 static TestEntry tooLongDir3;
115 static TestEntry tooLongDir4;
116 static TestEntry tooLongDir5;
117 static TestEntry tooLongDir6;
118 static TestEntry tooLongDir7;
119 static TestEntry tooLongDir8;
120 static TestEntry tooLongDir9;
121 static TestEntry tooLongDir10;
122 static TestEntry tooLongDir11;
123 static TestEntry tooLongDir12;
124 static TestEntry tooLongDir13;
125 static TestEntry tooLongDir14;
126 static TestEntry tooLongDir15;
127 static TestEntry tooLongDir16;
128 
129 static string setUpCommandLine;
130 static string tearDownCommandLine;
131 
132 // forward declarations
133 static TestEntry *resolve_link(TestEntry *entry);
134 static string get_shortest_relative_path(TestEntry *dir, TestEntry *entry);
135 
136 static const status_t kErrors[] = {
137 	B_BAD_ADDRESS,
138 	B_BAD_VALUE,
139 	B_CROSS_DEVICE_LINK,
140 	B_DEVICE_FULL,
141 	B_DIRECTORY_NOT_EMPTY,
142 	B_ENTRY_NOT_FOUND,
143 	B_ERROR,
144 	B_FILE_ERROR,
145 	B_FILE_EXISTS,
146 	B_IS_A_DIRECTORY,
147 	B_LINK_LIMIT,
148 	B_NAME_TOO_LONG,
149 	B_NO_MORE_FDS,
150 	B_NOT_A_DIRECTORY,
151 	B_OK,
152 	B_PARTITION_TOO_SMALL,
153 	B_READ_ONLY_DEVICE,
154 	B_UNSUPPORTED,
155 	E2BIG
156 };
157 static const int32 kErrorCount = sizeof(kErrors) / sizeof(status_t);
158 
159 // get_error_index
160 static
161 int32
162 get_error_index(status_t error)
163 {
164 	int32 result = -1;
165 	for (int32 i = 0; result == -1 && i < kErrorCount; i++) {
166 		if (kErrors[i] == error)
167 			result = i;
168 	}
169 	if (result == -1)
170 		printf("WARNING: error %lx is not in the list of errors\n", error);
171 	return result;
172 }
173 
174 // fuzzy_error
175 static
176 status_t
177 fuzzy_error(status_t error1, status_t error2)
178 {
179 	status_t result = error1;
180 	// encode the two errors in one value
181 	int32 index1 = get_error_index(error1);
182 	int32 index2 = get_error_index(error2);
183 	if (index1 >= 0 && index2 >= 0)
184 		result = index1 * kErrorCount + index2 + 1;
185 	return result;
186 }
187 
188 // fuzzy_equals
189 static
190 bool
191 fuzzy_equals(status_t error, status_t fuzzyError)
192 {
193 	bool result = false;
194 	if (fuzzyError <= 0)
195 		result = (error == fuzzyError);
196 	else {
197 		// decode the error
198 		int32 index1 = (fuzzyError - 1) / kErrorCount;
199 		int32 index2 = (fuzzyError - 1) % kErrorCount;
200 		if (index1 >= kErrorCount)
201 			printf("WARNING: bad fuzzy error: %lx\n", fuzzyError);
202 		else {
203 			status_t error1 = kErrors[index1];
204 			status_t error2 = kErrors[index2];
205 			result = (error == error1 || error == error2);
206 		}
207 	}
208 	return result;
209 }
210 
211 
212 // Suite
213 CppUnit::Test*
214 EntryTest::Suite()
215 {
216 	CppUnit::TestSuite *suite = new CppUnit::TestSuite();
217 	typedef CppUnit::TestCaller<EntryTest> TC;
218 
219 	StatableTest::AddBaseClassTests<EntryTest>("BEntry::", suite);
220 
221 	suite->addTest( new TC("BEntry::Init Test1", &EntryTest::InitTest1) );
222 	suite->addTest( new TC("BEntry::Init Test2", &EntryTest::InitTest2) );
223 	suite->addTest( new TC("BEntry::Special cases for Exists(), GetPath(),...",
224 						   &EntryTest::SpecialGetCasesTest) );
225 	suite->addTest( new TC("BEntry::Rename Test", &EntryTest::RenameTest) );
226 	suite->addTest( new TC("BEntry::MoveTo Test", &EntryTest::MoveToTest) );
227 	suite->addTest( new TC("BEntry::Remove Test", &EntryTest::RemoveTest) );
228 	suite->addTest( new TC("BEntry::Comparison Test",
229 						   &EntryTest::ComparisonTest) );
230 	suite->addTest( new TC("BEntry::Assignment Test",
231 						   &EntryTest::AssignmentTest) );
232 	suite->addTest( new TC("BEntry::C Functions Test",
233 						   &EntryTest::CFunctionsTest) );
234 //	suite->addTest( new TC("BEntry::Miscellaneous Test", &EntryTest::MiscTest) );
235 
236 	return suite;
237 }
238 
239 // CreateROStatables
240 void
241 EntryTest::CreateROStatables(TestStatables& testEntries)
242 {
243 	CreateRWStatables(testEntries);
244 }
245 
246 // CreateRWStatables
247 void
248 EntryTest::CreateRWStatables(TestStatables& testStatables)
249 {
250 	TestEntry *testEntries[] = {
251 		&dir1, &dir2, &file1, &subDir1,
252 		&absDirLink1, &absDirLink2, &absDirLink3, &absDirLink4,
253 		&relDirLink1, &relDirLink2, &relDirLink3, &relDirLink4,
254 		&absFileLink1, &absFileLink2, &absFileLink3, &absFileLink4,
255 		&relFileLink1, &relFileLink2, &relFileLink3, &relFileLink4,
256 		&absBadLink1, &absBadLink2, &absBadLink3, &absBadLink4,
257 		&relBadLink1, &relBadLink2, &relBadLink3, &relBadLink4,
258 		&absVeryBadLink1, &absVeryBadLink2, &absVeryBadLink3, &absVeryBadLink4,
259 		&relVeryBadLink1, &relVeryBadLink2, &relVeryBadLink3, &relVeryBadLink4
260 	};
261 	int32 testEntryCount = sizeof(testEntries) / sizeof(TestEntry*);
262 	for (int32 i = 0; i < testEntryCount; i++) {
263 		TestEntry *testEntry = testEntries[i];
264 		const char *filename = testEntry->cpath;
265 		testStatables.add(new BEntry(filename), filename);
266 	}
267 }
268 
269 // CreateUninitializedStatables
270 void
271 EntryTest::CreateUninitializedStatables(TestStatables& testEntries)
272 {
273 	testEntries.add(new BEntry, "");
274 }
275 
276 // setUp
277 void
278 EntryTest::setUp()
279 {
280 	StatableTest::setUp();
281 	execCommand(setUpCommandLine);
282 }
283 
284 // tearDown
285 void
286 EntryTest::tearDown()
287 {
288 	StatableTest::tearDown();
289 	execCommand(tearDownCommandLine);
290 }
291 
292 // examine_entry
293 static
294 void
295 examine_entry(BEntry &entry, TestEntry *testEntry, bool traverse)
296 {
297 	if (traverse)
298 		testEntry = resolve_link(testEntry);
299 	// Exists()
300 	CPPUNIT_ASSERT( entry.Exists() == testEntry->isConcrete() );
301 	// GetPath()
302 	BPath path;
303 	CPPUNIT_ASSERT( entry.GetPath(&path) == B_OK );
304 	CPPUNIT_ASSERT( path == testEntry->cpath );
305 	// GetName()
306 	char name[B_FILE_NAME_LENGTH + 1];
307 	CPPUNIT_ASSERT( entry.GetName(name) == B_OK );
308 	CPPUNIT_ASSERT( testEntry->name == name );
309 	// GetParent(BEntry *)
310 	BEntry parentEntry;
311 	CPPUNIT_ASSERT( entry.GetParent(&parentEntry) == B_OK );
312 	CPPUNIT_ASSERT( parentEntry.InitCheck() == B_OK );
313 	CPPUNIT_ASSERT( parentEntry.GetPath(&path) == B_OK );
314 	CPPUNIT_ASSERT( path == testEntry->super->cpath );
315 	parentEntry.Unset();
316 	path.Unset();
317 	// GetParent(BDirectory *)
318 	BDirectory parentDir;
319 	CPPUNIT_ASSERT( entry.GetParent(&parentDir) == B_OK );
320 	CPPUNIT_ASSERT( parentDir.GetEntry(&parentEntry) == B_OK );
321 	CPPUNIT_ASSERT( parentEntry.InitCheck() == B_OK );
322 	CPPUNIT_ASSERT( parentEntry.GetPath(&path) == B_OK );
323 	CPPUNIT_ASSERT( path == testEntry->super->cpath );
324 	// GetRef()
325 	entry_ref ref;
326 	CPPUNIT_ASSERT( entry.GetRef(&ref) == B_OK );
327 	// We can't get a ref of an entry with a too long path name yet.
328 	if (testEntry->path.length() < B_PATH_NAME_LENGTH)
329 		CPPUNIT_ASSERT( ref == testEntry->get_ref() );
330 }
331 
332 // InitTest1Paths
333 void
334 EntryTest::InitTest1Paths(TestEntry &_testEntry, status_t error, bool traverse)
335 {
336 	TestEntry *testEntry = &_testEntry;
337 	// absolute path
338 	NextSubTest();
339 	{
340 //printf("%s\n", testEntry->cpath);
341 		BEntry entry(testEntry->cpath, traverse);
342 		status_t result = entry.InitCheck();
343 if (!fuzzy_equals(result, error))
344 printf("error: %lx (%lx)\n", result, error);
345 		CPPUNIT_ASSERT( fuzzy_equals(result, error) );
346 		if (result == B_OK)
347 			examine_entry(entry, testEntry, traverse);
348 	}
349 	// relative path
350 	NextSubTest();
351 	{
352 //printf("%s\n", testEntry->cpath);
353 		if (chdir(testEntry->super->cpath) == 0) {
354 			BEntry entry(testEntry->cname, traverse);
355 			status_t result = entry.InitCheck();
356 if (!fuzzy_equals(result, error))
357 printf("error: %lx (%lx)\n", result, error);
358 			CPPUNIT_ASSERT( fuzzy_equals(result, error) );
359 			if (error == B_OK)
360 				examine_entry(entry, testEntry, traverse);
361 			RestoreCWD();
362 		}
363 	}
364 }
365 
366 // InitTest1Refs
367 void
368 EntryTest::InitTest1Refs(TestEntry &_testEntry, status_t error, bool traverse)
369 {
370 	TestEntry *testEntry = &_testEntry;
371 	// absolute path
372 	NextSubTest();
373 	{
374 //printf("%s\n", testEntry->cpath);
375 		BEntry entry(&testEntry->get_ref(), traverse);
376 		status_t result = entry.InitCheck();
377 if (!fuzzy_equals(result, error))
378 printf("error: %lx (%lx)\n", result, error);
379 		CPPUNIT_ASSERT( fuzzy_equals(result, error) );
380 		if (error == B_OK)
381 			examine_entry(entry, testEntry, traverse);
382 	}
383 }
384 
385 // InitTest1DirPaths
386 void
387 EntryTest::InitTest1DirPaths(TestEntry &_testEntry, status_t error,
388 							 bool traverse)
389 {
390 	TestEntry *testEntry = &_testEntry;
391 	// absolute path
392 	NextSubTest();
393 	{
394 		if (!testEntry->isBad()
395 			&& testEntry->path.length() < B_PATH_NAME_LENGTH) {
396 //printf("%s\n", testEntry->cpath);
397 			BDirectory dir("/boot/home/Desktop");
398 			CPPUNIT_ASSERT( dir.InitCheck() == B_OK );
399 			BEntry entry(&dir, testEntry->cpath, traverse);
400 		status_t result = entry.InitCheck();
401 if (!fuzzy_equals(result, error))
402 printf("error: %lx (%lx)\n", result, error);
403 		CPPUNIT_ASSERT( fuzzy_equals(result, error) );
404 			if (error == B_OK)
405 				examine_entry(entry, testEntry, traverse);
406 		}
407 	}
408 	// relative path (one level)
409 	NextSubTest();
410 	{
411 		if (!testEntry->isBad()
412 			&& testEntry->super->path.length() < B_PATH_NAME_LENGTH) {
413 //printf("%s + %s\n", testEntry->super->cpath, testEntry->cname);
414 			BDirectory dir(testEntry->super->cpath);
415 			CPPUNIT_ASSERT( dir.InitCheck() == B_OK );
416 			BEntry entry(&dir, testEntry->cname, traverse);
417 			status_t result = entry.InitCheck();
418 if (!fuzzy_equals(result, error))
419 printf("error: %lx (%lx)\n", result, error);
420 			CPPUNIT_ASSERT( fuzzy_equals(result, error) );
421 			if (error == B_OK)
422 				examine_entry(entry, testEntry, traverse);
423 		}
424 	}
425 	// relative path (two levels)
426 	NextSubTest();
427 	{
428 		if (!testEntry->super->isBad() && !testEntry->super->super->isBad()) {
429 			string entryName  = testEntry->super->name + "/" + testEntry->name;
430 //printf("%s + %s\n", testEntry->super->super->cpath, entryName.c_str());
431 			BDirectory dir(testEntry->super->super->cpath);
432 			CPPUNIT_ASSERT( dir.InitCheck() == B_OK );
433 			BEntry entry(&dir, entryName.c_str(), traverse);
434 			status_t result = entry.InitCheck();
435 if (!fuzzy_equals(result, error))
436 printf("error: %lx (%lx)\n", result, error);
437 			CPPUNIT_ASSERT( fuzzy_equals(result, error) );
438 			if (error == B_OK)
439 				examine_entry(entry, testEntry, traverse);
440 		}
441 	}
442 }
443 
444 // InitTest1
445 void
446 EntryTest::InitTest1()
447 {
448 	// 1. default constructor
449 	NextSubTest();
450 	{
451 		BEntry entry;
452 		CPPUNIT_ASSERT( entry.InitCheck() == B_NO_INIT );
453 	}
454 
455 	// 2. BEntry(const char *, bool)
456 	// don't traverse
457 	InitTest1Paths(dir1, B_OK);
458 	InitTest1Paths(dir2, B_OK);
459 	InitTest1Paths(file1, B_OK);
460 	InitTest1Paths(subDir1, B_OK);
461 	InitTest1Paths(abstractEntry1, B_OK);
462 	InitTest1Paths(badEntry1, B_ENTRY_NOT_FOUND);
463 	InitTest1Paths(absDirLink1, B_OK);
464 	InitTest1Paths(absDirLink2, B_OK);
465 	InitTest1Paths(absDirLink3, B_OK);
466 	InitTest1Paths(absDirLink4, B_OK);
467 	InitTest1Paths(relDirLink1, B_OK);
468 	InitTest1Paths(relDirLink2, B_OK);
469 	InitTest1Paths(relDirLink3, B_OK);
470 	InitTest1Paths(relDirLink4, B_OK);
471 	InitTest1Paths(absFileLink1, B_OK);
472 	InitTest1Paths(absFileLink2, B_OK);
473 	InitTest1Paths(absFileLink3, B_OK);
474 	InitTest1Paths(absFileLink4, B_OK);
475 	InitTest1Paths(relFileLink1, B_OK);
476 	InitTest1Paths(relFileLink2, B_OK);
477 	InitTest1Paths(relFileLink3, B_OK);
478 	InitTest1Paths(relFileLink4, B_OK);
479 	InitTest1Paths(absCyclicLink1, B_OK);
480 	InitTest1Paths(relCyclicLink1, B_OK);
481 	InitTest1Paths(absBadLink1, B_OK);
482 	InitTest1Paths(absBadLink2, B_OK);
483 	InitTest1Paths(absBadLink3, B_OK);
484 	InitTest1Paths(absBadLink4, B_OK);
485 	InitTest1Paths(relBadLink1, B_OK);
486 	InitTest1Paths(relBadLink2, B_OK);
487 	InitTest1Paths(relBadLink3, B_OK);
488 	InitTest1Paths(relBadLink4, B_OK);
489 	InitTest1Paths(absVeryBadLink1, B_OK);
490 	InitTest1Paths(absVeryBadLink2, B_OK);
491 	InitTest1Paths(absVeryBadLink3, B_OK);
492 	InitTest1Paths(absVeryBadLink4, B_OK);
493 	InitTest1Paths(relVeryBadLink1, B_OK);
494 	InitTest1Paths(relVeryBadLink2, B_OK);
495 	InitTest1Paths(relVeryBadLink3, B_OK);
496 	InitTest1Paths(relVeryBadLink4, B_OK);
497 // R5: returns E2BIG instead of B_NAME_TOO_LONG
498 	InitTest1Paths(tooLongEntry1, fuzzy_error(E2BIG, B_NAME_TOO_LONG));
499 // R5: returns B_ERROR instead of B_NAME_TOO_LONG
500 	InitTest1Paths(tooLongDir16, fuzzy_error(B_ERROR, B_NAME_TOO_LONG));
501 	// traverse
502 	InitTest1Paths(dir1, B_OK, true);
503 	InitTest1Paths(dir2, B_OK, true);
504 	InitTest1Paths(file1, B_OK, true);
505 	InitTest1Paths(subDir1, B_OK, true);
506 	InitTest1Paths(abstractEntry1, B_OK, true);
507 	InitTest1Paths(badEntry1, B_ENTRY_NOT_FOUND, true);
508 	InitTest1Paths(absDirLink1, B_OK, true);
509 	InitTest1Paths(absDirLink2, B_OK, true);
510 	InitTest1Paths(absDirLink3, B_OK, true);
511 	InitTest1Paths(absDirLink4, B_OK, true);
512 	InitTest1Paths(relDirLink1, B_OK, true);
513 	InitTest1Paths(relDirLink2, B_OK, true);
514 	InitTest1Paths(relDirLink3, B_OK, true);
515 	InitTest1Paths(relDirLink4, B_OK, true);
516 	InitTest1Paths(absFileLink1, B_OK, true);
517 	InitTest1Paths(absFileLink2, B_OK, true);
518 	InitTest1Paths(absFileLink3, B_OK, true);
519 	InitTest1Paths(absFileLink4, B_OK, true);
520 	InitTest1Paths(relFileLink1, B_OK, true);
521 	InitTest1Paths(relFileLink2, B_OK, true);
522 	InitTest1Paths(relFileLink3, B_OK, true);
523 	InitTest1Paths(relFileLink4, B_OK, true);
524 	InitTest1Paths(absCyclicLink1, B_LINK_LIMIT, true);
525 	InitTest1Paths(relCyclicLink1, B_LINK_LIMIT, true);
526 	InitTest1Paths(absBadLink1, B_ENTRY_NOT_FOUND, true);
527 	InitTest1Paths(absBadLink2, B_ENTRY_NOT_FOUND, true);
528 	InitTest1Paths(absBadLink3, B_ENTRY_NOT_FOUND, true);
529 	InitTest1Paths(absBadLink4, B_ENTRY_NOT_FOUND, true);
530 	InitTest1Paths(relBadLink1, B_ENTRY_NOT_FOUND, true);
531 	InitTest1Paths(relBadLink2, B_ENTRY_NOT_FOUND, true);
532 	InitTest1Paths(relBadLink3, B_ENTRY_NOT_FOUND, true);
533 	InitTest1Paths(relBadLink4, B_ENTRY_NOT_FOUND, true);
534 	InitTest1Paths(absVeryBadLink1, B_ENTRY_NOT_FOUND, true);
535 	InitTest1Paths(absVeryBadLink2, B_ENTRY_NOT_FOUND, true);
536 	InitTest1Paths(absVeryBadLink3, B_ENTRY_NOT_FOUND, true);
537 	InitTest1Paths(absVeryBadLink4, B_ENTRY_NOT_FOUND, true);
538 	InitTest1Paths(relVeryBadLink1, B_ENTRY_NOT_FOUND, true);
539 	InitTest1Paths(relVeryBadLink2, B_ENTRY_NOT_FOUND, true);
540 	InitTest1Paths(relVeryBadLink3, B_ENTRY_NOT_FOUND, true);
541 	InitTest1Paths(relVeryBadLink4, B_ENTRY_NOT_FOUND, true);
542 // R5: returns E2BIG instead of B_NAME_TOO_LONG
543 	InitTest1Paths(tooLongEntry1, fuzzy_error(E2BIG, B_NAME_TOO_LONG), true);
544 // R5: returns B_ERROR instead of B_NAME_TOO_LONG
545 	InitTest1Paths(tooLongDir16, fuzzy_error(B_ERROR, B_NAME_TOO_LONG), true);
546 
547 	// special cases (root dir)
548 	NextSubTest();
549 	{
550 		BEntry entry("/");
551 		CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
552 	}
553 	// special cases (fs root dir)
554 	NextSubTest();
555 	{
556 		BEntry entry("/boot");
557 		CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
558 	}
559 	// bad args
560 	NextSubTest();
561 	{
562 		BEntry entry((const char*)NULL);
563 		CPPUNIT_ASSERT( entry.InitCheck() == B_BAD_VALUE );
564 	}
565 
566 	// 3. BEntry(const entry_ref *, bool)
567 	// don't traverse
568 	InitTest1Refs(dir1, B_OK);
569 	InitTest1Refs(dir2, B_OK);
570 	InitTest1Refs(file1, B_OK);
571 	InitTest1Refs(subDir1, B_OK);
572 	InitTest1Refs(abstractEntry1, B_OK);
573 	InitTest1Refs(absDirLink1, B_OK);
574 	InitTest1Refs(absDirLink2, B_OK);
575 	InitTest1Refs(absDirLink3, B_OK);
576 	InitTest1Refs(absDirLink4, B_OK);
577 	InitTest1Refs(relDirLink1, B_OK);
578 	InitTest1Refs(relDirLink2, B_OK);
579 	InitTest1Refs(relDirLink3, B_OK);
580 	InitTest1Refs(relDirLink4, B_OK);
581 	InitTest1Refs(absFileLink1, B_OK);
582 	InitTest1Refs(absFileLink2, B_OK);
583 	InitTest1Refs(absFileLink3, B_OK);
584 	InitTest1Refs(absFileLink4, B_OK);
585 	InitTest1Refs(relFileLink1, B_OK);
586 	InitTest1Refs(relFileLink2, B_OK);
587 	InitTest1Refs(relFileLink3, B_OK);
588 	InitTest1Refs(relFileLink4, B_OK);
589 	InitTest1Refs(absCyclicLink1, B_OK);
590 	InitTest1Refs(relCyclicLink1, B_OK);
591 	InitTest1Refs(absBadLink1, B_OK);
592 	InitTest1Refs(absBadLink2, B_OK);
593 	InitTest1Refs(absBadLink3, B_OK);
594 	InitTest1Refs(absBadLink4, B_OK);
595 	InitTest1Refs(relBadLink1, B_OK);
596 	InitTest1Refs(relBadLink2, B_OK);
597 	InitTest1Refs(relBadLink3, B_OK);
598 	InitTest1Refs(relBadLink4, B_OK);
599 	InitTest1Refs(absVeryBadLink1, B_OK);
600 	InitTest1Refs(absVeryBadLink2, B_OK);
601 	InitTest1Refs(absVeryBadLink3, B_OK);
602 	InitTest1Refs(absVeryBadLink4, B_OK);
603 	InitTest1Refs(relVeryBadLink1, B_OK);
604 	InitTest1Refs(relVeryBadLink2, B_OK);
605 	InitTest1Refs(relVeryBadLink3, B_OK);
606 	InitTest1Refs(relVeryBadLink4, B_OK);
607 	// traverse
608 	InitTest1Refs(dir1, B_OK, true);
609 	InitTest1Refs(dir2, B_OK, true);
610 	InitTest1Refs(file1, B_OK, true);
611 	InitTest1Refs(subDir1, B_OK, true);
612 	InitTest1Refs(abstractEntry1, B_OK, true);
613 	InitTest1Refs(absDirLink1, B_OK, true);
614 	InitTest1Refs(absDirLink2, B_OK, true);
615 	InitTest1Refs(absDirLink3, B_OK, true);
616 	InitTest1Refs(absDirLink4, B_OK, true);
617 	InitTest1Refs(relDirLink1, B_OK, true);
618 	InitTest1Refs(relDirLink2, B_OK, true);
619 	InitTest1Refs(relDirLink3, B_OK, true);
620 	InitTest1Refs(relDirLink4, B_OK, true);
621 	InitTest1Refs(absFileLink1, B_OK, true);
622 	InitTest1Refs(absFileLink2, B_OK, true);
623 	InitTest1Refs(absFileLink3, B_OK, true);
624 	InitTest1Refs(absFileLink4, B_OK, true);
625 	InitTest1Refs(relFileLink1, B_OK, true);
626 	InitTest1Refs(relFileLink2, B_OK, true);
627 	InitTest1Refs(relFileLink3, B_OK, true);
628 	InitTest1Refs(relFileLink4, B_OK, true);
629 	InitTest1Refs(absCyclicLink1, B_LINK_LIMIT, true);
630 	InitTest1Refs(relCyclicLink1, B_LINK_LIMIT, true);
631 	InitTest1Refs(absBadLink1, B_ENTRY_NOT_FOUND, true);
632 	InitTest1Refs(absBadLink2, B_ENTRY_NOT_FOUND, true);
633 	InitTest1Refs(absBadLink3, B_ENTRY_NOT_FOUND, true);
634 	InitTest1Refs(absBadLink4, B_ENTRY_NOT_FOUND, true);
635 	InitTest1Refs(relBadLink1, B_ENTRY_NOT_FOUND, true);
636 	InitTest1Refs(relBadLink2, B_ENTRY_NOT_FOUND, true);
637 	InitTest1Refs(relBadLink3, B_ENTRY_NOT_FOUND, true);
638 	InitTest1Refs(relBadLink4, B_ENTRY_NOT_FOUND, true);
639 	InitTest1Refs(absVeryBadLink1, B_ENTRY_NOT_FOUND, true);
640 	InitTest1Refs(absVeryBadLink2, B_ENTRY_NOT_FOUND, true);
641 	InitTest1Refs(absVeryBadLink3, B_ENTRY_NOT_FOUND, true);
642 	InitTest1Refs(absVeryBadLink4, B_ENTRY_NOT_FOUND, true);
643 	InitTest1Refs(relVeryBadLink1, B_ENTRY_NOT_FOUND, true);
644 	InitTest1Refs(relVeryBadLink2, B_ENTRY_NOT_FOUND, true);
645 	InitTest1Refs(relVeryBadLink3, B_ENTRY_NOT_FOUND, true);
646 	InitTest1Refs(relVeryBadLink4, B_ENTRY_NOT_FOUND, true);
647 	// bad args
648 	NextSubTest();
649 	{
650 		BEntry entry((const entry_ref*)NULL);
651 		CPPUNIT_ASSERT( entry.InitCheck() == B_BAD_VALUE );
652 	}
653 
654 	// 4. BEntry(const BDirectory *, const char *, bool)
655 	// don't traverse
656 	InitTest1DirPaths(dir1, B_OK);
657 	InitTest1DirPaths(dir2, B_OK);
658 	InitTest1DirPaths(file1, B_OK);
659 	InitTest1DirPaths(subDir1, B_OK);
660 	InitTest1DirPaths(abstractEntry1, B_OK);
661 	InitTest1DirPaths(badEntry1, B_ENTRY_NOT_FOUND);
662 	InitTest1DirPaths(absDirLink1, B_OK);
663 	InitTest1DirPaths(absDirLink2, B_OK);
664 	InitTest1DirPaths(absDirLink3, B_OK);
665 	InitTest1DirPaths(absDirLink4, B_OK);
666 	InitTest1DirPaths(relDirLink1, B_OK);
667 	InitTest1DirPaths(relDirLink2, B_OK);
668 	InitTest1DirPaths(relDirLink3, B_OK);
669 	InitTest1DirPaths(relDirLink4, B_OK);
670 	InitTest1DirPaths(absFileLink1, B_OK);
671 	InitTest1DirPaths(absFileLink2, B_OK);
672 	InitTest1DirPaths(absFileLink3, B_OK);
673 	InitTest1DirPaths(absFileLink4, B_OK);
674 	InitTest1DirPaths(relFileLink1, B_OK);
675 	InitTest1DirPaths(relFileLink2, B_OK);
676 	InitTest1DirPaths(relFileLink3, B_OK);
677 	InitTest1DirPaths(relFileLink4, B_OK);
678 	InitTest1DirPaths(absCyclicLink1, B_OK);
679 	InitTest1DirPaths(relCyclicLink1, B_OK);
680 	InitTest1DirPaths(absBadLink1, B_OK);
681 	InitTest1DirPaths(absBadLink2, B_OK);
682 	InitTest1DirPaths(absBadLink3, B_OK);
683 	InitTest1DirPaths(absBadLink4, B_OK);
684 	InitTest1DirPaths(relBadLink1, B_OK);
685 	InitTest1DirPaths(relBadLink2, B_OK);
686 	InitTest1DirPaths(relBadLink3, B_OK);
687 	InitTest1DirPaths(relBadLink4, B_OK);
688 	InitTest1DirPaths(absVeryBadLink1, B_OK);
689 	InitTest1DirPaths(absVeryBadLink2, B_OK);
690 	InitTest1DirPaths(absVeryBadLink3, B_OK);
691 	InitTest1DirPaths(absVeryBadLink4, B_OK);
692 	InitTest1DirPaths(relVeryBadLink1, B_OK);
693 	InitTest1DirPaths(relVeryBadLink2, B_OK);
694 	InitTest1DirPaths(relVeryBadLink3, B_OK);
695 	InitTest1DirPaths(relVeryBadLink4, B_OK);
696 // R5: returns E2BIG instead of B_NAME_TOO_LONG
697 	InitTest1DirPaths(tooLongEntry1, fuzzy_error(E2BIG, B_NAME_TOO_LONG));
698 // Haiku: Fails, because the implementation concatenates the dir and leaf
699 // 		 name.
700 #if !TEST_OBOS /* !!!POSIX ONLY!!! */
701 	InitTest1DirPaths(tooLongDir16, B_OK, true);
702 #endif
703 	// traverse
704 	InitTest1DirPaths(dir1, B_OK, true);
705 	InitTest1DirPaths(dir2, B_OK, true);
706 	InitTest1DirPaths(file1, B_OK, true);
707 	InitTest1DirPaths(subDir1, B_OK, true);
708 	InitTest1DirPaths(abstractEntry1, B_OK, true);
709 	InitTest1DirPaths(badEntry1, B_ENTRY_NOT_FOUND, true);
710 	InitTest1DirPaths(absDirLink1, B_OK, true);
711 	InitTest1DirPaths(absDirLink2, B_OK, true);
712 	InitTest1DirPaths(absDirLink3, B_OK, true);
713 	InitTest1DirPaths(absDirLink4, B_OK, true);
714 	InitTest1DirPaths(relDirLink1, B_OK, true);
715 	InitTest1DirPaths(relDirLink2, B_OK, true);
716 	InitTest1DirPaths(relDirLink3, B_OK, true);
717 	InitTest1DirPaths(relDirLink4, B_OK, true);
718 	InitTest1DirPaths(absFileLink1, B_OK, true);
719 	InitTest1DirPaths(absFileLink2, B_OK, true);
720 	InitTest1DirPaths(absFileLink3, B_OK, true);
721 	InitTest1DirPaths(absFileLink4, B_OK, true);
722 	InitTest1DirPaths(relFileLink1, B_OK, true);
723 	InitTest1DirPaths(relFileLink2, B_OK, true);
724 	InitTest1DirPaths(relFileLink3, B_OK, true);
725 	InitTest1DirPaths(relFileLink4, B_OK, true);
726 	InitTest1DirPaths(absCyclicLink1, B_LINK_LIMIT, true);
727 	InitTest1DirPaths(relCyclicLink1, B_LINK_LIMIT, true);
728 	InitTest1DirPaths(absBadLink1, B_ENTRY_NOT_FOUND, true);
729 	InitTest1DirPaths(absBadLink2, B_ENTRY_NOT_FOUND, true);
730 	InitTest1DirPaths(absBadLink3, B_ENTRY_NOT_FOUND, true);
731 	InitTest1DirPaths(absBadLink4, B_ENTRY_NOT_FOUND, true);
732 	InitTest1DirPaths(relBadLink1, B_ENTRY_NOT_FOUND, true);
733 	InitTest1DirPaths(relBadLink2, B_ENTRY_NOT_FOUND, true);
734 	InitTest1DirPaths(relBadLink3, B_ENTRY_NOT_FOUND, true);
735 	InitTest1DirPaths(relBadLink4, B_ENTRY_NOT_FOUND, true);
736 	InitTest1DirPaths(absVeryBadLink1, B_ENTRY_NOT_FOUND, true);
737 	InitTest1DirPaths(absVeryBadLink2, B_ENTRY_NOT_FOUND, true);
738 	InitTest1DirPaths(absVeryBadLink3, B_ENTRY_NOT_FOUND, true);
739 	InitTest1DirPaths(absVeryBadLink4, B_ENTRY_NOT_FOUND, true);
740 	InitTest1DirPaths(relVeryBadLink1, B_ENTRY_NOT_FOUND, true);
741 	InitTest1DirPaths(relVeryBadLink2, B_ENTRY_NOT_FOUND, true);
742 	InitTest1DirPaths(relVeryBadLink3, B_ENTRY_NOT_FOUND, true);
743 	InitTest1DirPaths(relVeryBadLink4, B_ENTRY_NOT_FOUND, true);
744 // R5: returns E2BIG instead of B_NAME_TOO_LONG
745 	InitTest1DirPaths(tooLongEntry1, fuzzy_error(E2BIG, B_NAME_TOO_LONG), true);
746 // Haiku: Fails, because the implementation concatenates the dir and leaf
747 // 		 name.
748 #if !TEST_OBOS /* !!!POSIX ONLY!!! */
749 	InitTest1DirPaths(tooLongDir16, B_OK, true);
750 #endif
751 
752 	// special cases (root dir)
753 	NextSubTest();
754 	{
755 		BDirectory dir("/");
756 		BEntry entry(&dir, ".");
757 		CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
758 	}
759 	// special cases (fs root dir)
760 	NextSubTest();
761 	{
762 		BDirectory dir("/");
763 		BEntry entry(&dir, "boot");
764 		CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
765 	}
766 	// NULL path
767 	NextSubTest();
768 	{
769 		BDirectory dir("/");
770 		BEntry entry(&dir, (const char*)NULL);
771 		CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
772 	}
773 	// bad args (NULL dir)
774 // R5: crashs
775 #if !TEST_R5
776 	NextSubTest();
777 	{
778 		chdir("/");
779 		BEntry entry((const BDirectory*)NULL, "tmp");
780 		CPPUNIT_ASSERT( entry.InitCheck() == B_BAD_VALUE );
781 		RestoreCWD();
782 	}
783 #endif
784 	// strange args (badly initialized dir, absolute path)
785 	NextSubTest();
786 	{
787 		BDirectory dir(badEntry1.cpath);
788 		CPPUNIT_ASSERT( dir.InitCheck() == B_ENTRY_NOT_FOUND );
789 		BEntry entry(&dir, "/tmp");
790 		CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
791 	}
792 	// bad args (NULL dir and path)
793 // R5: crashs
794 #if !TEST_R5
795 	NextSubTest();
796 	{
797 		BEntry entry((const BDirectory*)NULL, (const char*)NULL);
798 		CPPUNIT_ASSERT( entry.InitCheck() == B_BAD_VALUE );
799 	}
800 #endif
801 	// bad args(NULL dir, absolute path)
802 // R5: crashs
803 #if !TEST_R5
804 	NextSubTest();
805 	{
806 		BEntry entry((const BDirectory*)NULL, "/tmp");
807 		CPPUNIT_ASSERT( entry.InitCheck() == B_BAD_VALUE );
808 	}
809 #endif
810 }
811 
812 // InitTest2Paths
813 void
814 EntryTest::InitTest2Paths(TestEntry &_testEntry, status_t error, bool traverse)
815 {
816 	TestEntry *testEntry = &_testEntry;
817 	BEntry entry;
818 	// absolute path
819 	NextSubTest();
820 	{
821 //printf("%s\n", testEntry->cpath);
822 		status_t result = entry.SetTo(testEntry->cpath, traverse);
823 if (!fuzzy_equals(result, error))
824 printf("error: %lx (%lx)\n", result, error);
825 		CPPUNIT_ASSERT( fuzzy_equals(result, error) );
826 		CPPUNIT_ASSERT( fuzzy_equals(entry.InitCheck(), error) );
827 		if (result == B_OK)
828 			examine_entry(entry, testEntry, traverse);
829 	}
830 	// relative path
831 	NextSubTest();
832 	{
833 //printf("%s\n", testEntry->cpath);
834 		if (chdir(testEntry->super->cpath) == 0) {
835 			status_t result = entry.SetTo(testEntry->cname, traverse);
836 if (!fuzzy_equals(result, error))
837 printf("error: %lx (%lx)\n", result, error);
838 			CPPUNIT_ASSERT( fuzzy_equals(result, error) );
839 			CPPUNIT_ASSERT( fuzzy_equals(entry.InitCheck(), error) );
840 			if (result == B_OK)
841 				examine_entry(entry, testEntry, traverse);
842 			RestoreCWD();
843 		}
844 	}
845 }
846 
847 // InitTest2Refs
848 void
849 EntryTest::InitTest2Refs(TestEntry &_testEntry, status_t error, bool traverse)
850 {
851 	TestEntry *testEntry = &_testEntry;
852 	BEntry entry;
853 	// absolute path
854 	NextSubTest();
855 	{
856 //printf("%s\n", testEntry->cpath);
857 		status_t result = entry.SetTo(&testEntry->get_ref(), traverse);
858 if (!fuzzy_equals(result, error))
859 printf("error: %lx (%lx)\n", result, error);
860 		CPPUNIT_ASSERT( fuzzy_equals(result, error) );
861 		CPPUNIT_ASSERT( fuzzy_equals(entry.InitCheck(), error) );
862 		if (result == B_OK)
863 			examine_entry(entry, testEntry, traverse);
864 	}
865 }
866 
867 // InitTest2DirPaths
868 void
869 EntryTest::InitTest2DirPaths(TestEntry &_testEntry, status_t error,
870 							 bool traverse)
871 {
872 	TestEntry *testEntry = &_testEntry;
873 	BEntry entry;
874 	// absolute path
875 	NextSubTest();
876 	{
877 		if (!testEntry->isBad()
878 			&& testEntry->path.length() < B_PATH_NAME_LENGTH) {
879 //printf("%s\n", testEntry->cpath);
880 			BDirectory dir("/boot/home/Desktop");
881 			CPPUNIT_ASSERT( dir.InitCheck() == B_OK );
882 			status_t result = entry.SetTo(&dir, testEntry->cpath, traverse);
883 if (!fuzzy_equals(result, error))
884 printf("error: %lx (%lx)\n", result, error);
885 			CPPUNIT_ASSERT( fuzzy_equals(result, error) );
886 			CPPUNIT_ASSERT( fuzzy_equals(entry.InitCheck(), error) );
887 			if (result == B_OK)
888 				examine_entry(entry, testEntry, traverse);
889 		}
890 	}
891 	// relative path (one level)
892 	NextSubTest();
893 	{
894 		if (!testEntry->isBad()
895 			&& testEntry->super->path.length() < B_PATH_NAME_LENGTH) {
896 //printf("%s + %s\n", testEntry->super->cpath, testEntry->cname);
897 			BDirectory dir(testEntry->super->cpath);
898 			CPPUNIT_ASSERT( dir.InitCheck() == B_OK );
899 			status_t result = entry.SetTo(&dir, testEntry->cname, traverse);
900 if (!fuzzy_equals(result, error))
901 printf("error: %lx (%lx)\n", result, error);
902 			CPPUNIT_ASSERT( fuzzy_equals(result, error) );
903 			CPPUNIT_ASSERT( fuzzy_equals(entry.InitCheck(), error) );
904 			if (result == B_OK)
905 				examine_entry(entry, testEntry, traverse);
906 		}
907 	}
908 	// relative path (two levels)
909 	NextSubTest();
910 	{
911 		if (!testEntry->super->isBad() && !testEntry->super->super->isBad()) {
912 			string entryName  = testEntry->super->name + "/" + testEntry->name;
913 //printf("%s + %s\n", testEntry->super->super->cpath, entryName.c_str());
914 			BDirectory dir(testEntry->super->super->cpath);
915 			CPPUNIT_ASSERT( dir.InitCheck() == B_OK );
916 			status_t result = entry.SetTo(&dir, entryName.c_str(), traverse);
917 if (!fuzzy_equals(result, error))
918 printf("error: %lx (%lx)\n", result, error);
919 			CPPUNIT_ASSERT( fuzzy_equals(result, error) );
920 			CPPUNIT_ASSERT( fuzzy_equals(entry.InitCheck(), error) );
921 			if (result == B_OK)
922 				examine_entry(entry, testEntry, traverse);
923 		}
924 	}
925 }
926 
927 // InitTest2
928 void
929 EntryTest::InitTest2()
930 {
931 	BEntry entry;
932 	// 2. SetTo(const char *, bool)
933 	// don't traverse
934 	InitTest2Paths(dir1, B_OK);
935 	InitTest2Paths(dir2, B_OK);
936 	InitTest2Paths(file1, B_OK);
937 	InitTest2Paths(subDir1, B_OK);
938 	InitTest2Paths(abstractEntry1, B_OK);
939 	InitTest2Paths(badEntry1, B_ENTRY_NOT_FOUND);
940 	InitTest2Paths(absDirLink1, B_OK);
941 	InitTest2Paths(absDirLink2, B_OK);
942 	InitTest2Paths(absDirLink3, B_OK);
943 	InitTest2Paths(absDirLink4, B_OK);
944 	InitTest2Paths(relDirLink1, B_OK);
945 	InitTest2Paths(relDirLink2, B_OK);
946 	InitTest2Paths(relDirLink3, B_OK);
947 	InitTest2Paths(relDirLink4, B_OK);
948 	InitTest2Paths(absFileLink1, B_OK);
949 	InitTest2Paths(absFileLink2, B_OK);
950 	InitTest2Paths(absFileLink3, B_OK);
951 	InitTest2Paths(absFileLink4, B_OK);
952 	InitTest2Paths(relFileLink1, B_OK);
953 	InitTest2Paths(relFileLink2, B_OK);
954 	InitTest2Paths(relFileLink3, B_OK);
955 	InitTest2Paths(relFileLink4, B_OK);
956 	InitTest2Paths(absCyclicLink1, B_OK);
957 	InitTest2Paths(relCyclicLink1, B_OK);
958 	InitTest2Paths(absBadLink1, B_OK);
959 	InitTest2Paths(absBadLink2, B_OK);
960 	InitTest2Paths(absBadLink3, B_OK);
961 	InitTest2Paths(absBadLink4, B_OK);
962 	InitTest2Paths(relBadLink1, B_OK);
963 	InitTest2Paths(relBadLink2, B_OK);
964 	InitTest2Paths(relBadLink3, B_OK);
965 	InitTest2Paths(relBadLink4, B_OK);
966 	InitTest2Paths(absVeryBadLink1, B_OK);
967 	InitTest2Paths(absVeryBadLink2, B_OK);
968 	InitTest2Paths(absVeryBadLink3, B_OK);
969 	InitTest2Paths(absVeryBadLink4, B_OK);
970 	InitTest2Paths(relVeryBadLink1, B_OK);
971 	InitTest2Paths(relVeryBadLink2, B_OK);
972 	InitTest2Paths(relVeryBadLink3, B_OK);
973 	InitTest2Paths(relVeryBadLink4, B_OK);
974 // R5: returns E2BIG instead of B_NAME_TOO_LONG
975 	InitTest2Paths(tooLongEntry1, fuzzy_error(E2BIG, B_NAME_TOO_LONG));
976 // R5: returns B_ERROR instead of B_NAME_TOO_LONG
977 	InitTest2Paths(tooLongDir16, fuzzy_error(B_ERROR, B_NAME_TOO_LONG));
978 	// traverse
979 	InitTest2Paths(dir1, B_OK, true);
980 	InitTest2Paths(dir2, B_OK, true);
981 	InitTest2Paths(file1, B_OK, true);
982 	InitTest2Paths(subDir1, B_OK, true);
983 	InitTest2Paths(abstractEntry1, B_OK, true);
984 	InitTest2Paths(badEntry1, B_ENTRY_NOT_FOUND, true);
985 	InitTest2Paths(absDirLink1, B_OK, true);
986 	InitTest2Paths(absDirLink2, B_OK, true);
987 	InitTest2Paths(absDirLink3, B_OK, true);
988 	InitTest2Paths(absDirLink4, B_OK, true);
989 	InitTest2Paths(relDirLink1, B_OK, true);
990 	InitTest2Paths(relDirLink2, B_OK, true);
991 	InitTest2Paths(relDirLink3, B_OK, true);
992 	InitTest2Paths(relDirLink4, B_OK, true);
993 	InitTest2Paths(absFileLink1, B_OK, true);
994 	InitTest2Paths(absFileLink2, B_OK, true);
995 	InitTest2Paths(absFileLink3, B_OK, true);
996 	InitTest2Paths(absFileLink4, B_OK, true);
997 	InitTest2Paths(relFileLink1, B_OK, true);
998 	InitTest2Paths(relFileLink2, B_OK, true);
999 	InitTest2Paths(relFileLink3, B_OK, true);
1000 	InitTest2Paths(relFileLink4, B_OK, true);
1001 	InitTest2Paths(absCyclicLink1, B_LINK_LIMIT, true);
1002 	InitTest2Paths(relCyclicLink1, B_LINK_LIMIT, true);
1003 	InitTest2Paths(absBadLink1, B_ENTRY_NOT_FOUND, true);
1004 	InitTest2Paths(absBadLink2, B_ENTRY_NOT_FOUND, true);
1005 	InitTest2Paths(absBadLink3, B_ENTRY_NOT_FOUND, true);
1006 	InitTest2Paths(absBadLink4, B_ENTRY_NOT_FOUND, true);
1007 	InitTest2Paths(relBadLink1, B_ENTRY_NOT_FOUND, true);
1008 	InitTest2Paths(relBadLink2, B_ENTRY_NOT_FOUND, true);
1009 	InitTest2Paths(relBadLink3, B_ENTRY_NOT_FOUND, true);
1010 	InitTest2Paths(relBadLink4, B_ENTRY_NOT_FOUND, true);
1011 	InitTest2Paths(absVeryBadLink1, B_ENTRY_NOT_FOUND, true);
1012 	InitTest2Paths(absVeryBadLink2, B_ENTRY_NOT_FOUND, true);
1013 	InitTest2Paths(absVeryBadLink3, B_ENTRY_NOT_FOUND, true);
1014 	InitTest2Paths(absVeryBadLink4, B_ENTRY_NOT_FOUND, true);
1015 	InitTest2Paths(relVeryBadLink1, B_ENTRY_NOT_FOUND, true);
1016 	InitTest2Paths(relVeryBadLink2, B_ENTRY_NOT_FOUND, true);
1017 	InitTest2Paths(relVeryBadLink3, B_ENTRY_NOT_FOUND, true);
1018 	InitTest2Paths(relVeryBadLink4, B_ENTRY_NOT_FOUND, true);
1019 // R5: returns E2BIG instead of B_NAME_TOO_LONG
1020 	InitTest2Paths(tooLongEntry1, fuzzy_error(E2BIG, B_NAME_TOO_LONG), true);
1021 // R5: returns B_ERROR instead of B_NAME_TOO_LONG
1022 	InitTest2Paths(tooLongDir16, fuzzy_error(B_ERROR, B_NAME_TOO_LONG), true);
1023 	// special cases (root dir)
1024 	NextSubTest();
1025 	CPPUNIT_ASSERT( entry.SetTo("/") == B_OK );
1026 	CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
1027 	entry.Unset();
1028 	// special cases (fs root dir)
1029 	NextSubTest();
1030 	CPPUNIT_ASSERT( entry.SetTo("/boot") == B_OK );
1031 	CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
1032 	entry.Unset();
1033 	// bad args
1034 	NextSubTest();
1035 	CPPUNIT_ASSERT( entry.SetTo((const char*)NULL) == B_BAD_VALUE );
1036 	CPPUNIT_ASSERT( entry.InitCheck() == B_BAD_VALUE );
1037 	entry.Unset();
1038 
1039 	// 3. BEntry(const entry_ref *, bool)
1040 	// don't traverse
1041 	InitTest2Refs(dir1, B_OK);
1042 	InitTest2Refs(dir2, B_OK);
1043 	InitTest2Refs(file1, B_OK);
1044 	InitTest2Refs(subDir1, B_OK);
1045 	InitTest2Refs(abstractEntry1, B_OK);
1046 	InitTest2Refs(absDirLink1, B_OK);
1047 	InitTest2Refs(absDirLink2, B_OK);
1048 	InitTest2Refs(absDirLink3, B_OK);
1049 	InitTest2Refs(absDirLink4, B_OK);
1050 	InitTest2Refs(relDirLink1, B_OK);
1051 	InitTest2Refs(relDirLink2, B_OK);
1052 	InitTest2Refs(relDirLink3, B_OK);
1053 	InitTest2Refs(relDirLink4, B_OK);
1054 	InitTest2Refs(absFileLink1, B_OK);
1055 	InitTest2Refs(absFileLink2, B_OK);
1056 	InitTest2Refs(absFileLink3, B_OK);
1057 	InitTest2Refs(absFileLink4, B_OK);
1058 	InitTest2Refs(relFileLink1, B_OK);
1059 	InitTest2Refs(relFileLink2, B_OK);
1060 	InitTest2Refs(relFileLink3, B_OK);
1061 	InitTest2Refs(relFileLink4, B_OK);
1062 	InitTest2Refs(absCyclicLink1, B_OK);
1063 	InitTest2Refs(relCyclicLink1, B_OK);
1064 	InitTest2Refs(absBadLink1, B_OK);
1065 	InitTest2Refs(absBadLink2, B_OK);
1066 	InitTest2Refs(absBadLink3, B_OK);
1067 	InitTest2Refs(absBadLink4, B_OK);
1068 	InitTest2Refs(relBadLink1, B_OK);
1069 	InitTest2Refs(relBadLink2, B_OK);
1070 	InitTest2Refs(relBadLink3, B_OK);
1071 	InitTest2Refs(relBadLink4, B_OK);
1072 	InitTest2Refs(absVeryBadLink1, B_OK);
1073 	InitTest2Refs(absVeryBadLink2, B_OK);
1074 	InitTest2Refs(absVeryBadLink3, B_OK);
1075 	InitTest2Refs(absVeryBadLink4, B_OK);
1076 	InitTest2Refs(relVeryBadLink1, B_OK);
1077 	InitTest2Refs(relVeryBadLink2, B_OK);
1078 	InitTest2Refs(relVeryBadLink3, B_OK);
1079 	InitTest2Refs(relVeryBadLink4, B_OK);
1080 	// traverse
1081 	InitTest2Refs(dir1, B_OK, true);
1082 	InitTest2Refs(dir2, B_OK, true);
1083 	InitTest2Refs(file1, B_OK, true);
1084 	InitTest2Refs(subDir1, B_OK, true);
1085 	InitTest2Refs(abstractEntry1, B_OK, true);
1086 	InitTest2Refs(absDirLink1, B_OK, true);
1087 	InitTest2Refs(absDirLink2, B_OK, true);
1088 	InitTest2Refs(absDirLink3, B_OK, true);
1089 	InitTest2Refs(absDirLink4, B_OK, true);
1090 	InitTest2Refs(relDirLink1, B_OK, true);
1091 	InitTest2Refs(relDirLink2, B_OK, true);
1092 	InitTest2Refs(relDirLink3, B_OK, true);
1093 	InitTest2Refs(relDirLink4, B_OK, true);
1094 	InitTest2Refs(absFileLink1, B_OK, true);
1095 	InitTest2Refs(absFileLink2, B_OK, true);
1096 	InitTest2Refs(absFileLink3, B_OK, true);
1097 	InitTest2Refs(absFileLink4, B_OK, true);
1098 	InitTest2Refs(relFileLink1, B_OK, true);
1099 	InitTest2Refs(relFileLink2, B_OK, true);
1100 	InitTest2Refs(relFileLink3, B_OK, true);
1101 	InitTest2Refs(relFileLink4, B_OK, true);
1102 	InitTest2Refs(absCyclicLink1, B_LINK_LIMIT, true);
1103 	InitTest2Refs(relCyclicLink1, B_LINK_LIMIT, true);
1104 	InitTest2Refs(absBadLink1, B_ENTRY_NOT_FOUND, true);
1105 	InitTest2Refs(absBadLink2, B_ENTRY_NOT_FOUND, true);
1106 	InitTest2Refs(absBadLink3, B_ENTRY_NOT_FOUND, true);
1107 	InitTest2Refs(absBadLink4, B_ENTRY_NOT_FOUND, true);
1108 	InitTest2Refs(relBadLink1, B_ENTRY_NOT_FOUND, true);
1109 	InitTest2Refs(relBadLink2, B_ENTRY_NOT_FOUND, true);
1110 	InitTest2Refs(relBadLink3, B_ENTRY_NOT_FOUND, true);
1111 	InitTest2Refs(relBadLink4, B_ENTRY_NOT_FOUND, true);
1112 	InitTest2Refs(absVeryBadLink1, B_ENTRY_NOT_FOUND, true);
1113 	InitTest2Refs(absVeryBadLink2, B_ENTRY_NOT_FOUND, true);
1114 	InitTest2Refs(absVeryBadLink3, B_ENTRY_NOT_FOUND, true);
1115 	InitTest2Refs(absVeryBadLink4, B_ENTRY_NOT_FOUND, true);
1116 	InitTest2Refs(relVeryBadLink1, B_ENTRY_NOT_FOUND, true);
1117 	InitTest2Refs(relVeryBadLink2, B_ENTRY_NOT_FOUND, true);
1118 	InitTest2Refs(relVeryBadLink3, B_ENTRY_NOT_FOUND, true);
1119 	InitTest2Refs(relVeryBadLink4, B_ENTRY_NOT_FOUND, true);
1120 	// bad args
1121 	NextSubTest();
1122 	CPPUNIT_ASSERT( entry.SetTo((const entry_ref*)NULL) == B_BAD_VALUE );
1123 	CPPUNIT_ASSERT( entry.InitCheck() == B_BAD_VALUE );
1124 	entry.Unset();
1125 
1126 	// 4. BEntry(const BDirectory *, const char *, bool)
1127 	// don't traverse
1128 	InitTest2DirPaths(dir1, B_OK);
1129 	InitTest2DirPaths(dir2, B_OK);
1130 	InitTest2DirPaths(file1, B_OK);
1131 	InitTest2DirPaths(subDir1, B_OK);
1132 	InitTest2DirPaths(abstractEntry1, B_OK);
1133 	InitTest2DirPaths(badEntry1, B_ENTRY_NOT_FOUND);
1134 	InitTest2DirPaths(absDirLink1, B_OK);
1135 	InitTest2DirPaths(absDirLink2, B_OK);
1136 	InitTest2DirPaths(absDirLink3, B_OK);
1137 	InitTest2DirPaths(absDirLink4, B_OK);
1138 	InitTest2DirPaths(relDirLink1, B_OK);
1139 	InitTest2DirPaths(relDirLink2, B_OK);
1140 	InitTest2DirPaths(relDirLink3, B_OK);
1141 	InitTest2DirPaths(relDirLink4, B_OK);
1142 	InitTest2DirPaths(absFileLink1, B_OK);
1143 	InitTest2DirPaths(absFileLink2, B_OK);
1144 	InitTest2DirPaths(absFileLink3, B_OK);
1145 	InitTest2DirPaths(absFileLink4, B_OK);
1146 	InitTest2DirPaths(relFileLink1, B_OK);
1147 	InitTest2DirPaths(relFileLink2, B_OK);
1148 	InitTest2DirPaths(relFileLink3, B_OK);
1149 	InitTest2DirPaths(relFileLink4, B_OK);
1150 	InitTest2DirPaths(absCyclicLink1, B_OK);
1151 	InitTest2DirPaths(relCyclicLink1, B_OK);
1152 	InitTest2DirPaths(absBadLink1, B_OK);
1153 	InitTest2DirPaths(absBadLink2, B_OK);
1154 	InitTest2DirPaths(absBadLink3, B_OK);
1155 	InitTest2DirPaths(absBadLink4, B_OK);
1156 	InitTest2DirPaths(relBadLink1, B_OK);
1157 	InitTest2DirPaths(relBadLink2, B_OK);
1158 	InitTest2DirPaths(relBadLink3, B_OK);
1159 	InitTest2DirPaths(relBadLink4, B_OK);
1160 	InitTest2DirPaths(absVeryBadLink1, B_OK);
1161 	InitTest2DirPaths(absVeryBadLink2, B_OK);
1162 	InitTest2DirPaths(absVeryBadLink3, B_OK);
1163 	InitTest2DirPaths(absVeryBadLink4, B_OK);
1164 	InitTest2DirPaths(relVeryBadLink1, B_OK);
1165 	InitTest2DirPaths(relVeryBadLink2, B_OK);
1166 	InitTest2DirPaths(relVeryBadLink3, B_OK);
1167 	InitTest2DirPaths(relVeryBadLink4, B_OK);
1168 // R5: returns E2BIG instead of B_NAME_TOO_LONG
1169 	InitTest2DirPaths(tooLongEntry1, fuzzy_error(E2BIG, B_NAME_TOO_LONG));
1170 // Haiku: Fails, because the implementation concatenates the dir and leaf
1171 // 		 name.
1172 #if !TEST_OBOS /* !!!POSIX ONLY!!! */
1173 	InitTest2DirPaths(tooLongDir16, B_OK, true);
1174 #endif
1175 	// traverse
1176 	InitTest2DirPaths(dir1, B_OK, true);
1177 	InitTest2DirPaths(dir2, B_OK, true);
1178 	InitTest2DirPaths(file1, B_OK, true);
1179 	InitTest2DirPaths(subDir1, B_OK, true);
1180 	InitTest2DirPaths(abstractEntry1, B_OK, true);
1181 	InitTest2DirPaths(badEntry1, B_ENTRY_NOT_FOUND, true);
1182 	InitTest2DirPaths(absDirLink1, B_OK, true);
1183 	InitTest2DirPaths(absDirLink2, B_OK, true);
1184 	InitTest2DirPaths(absDirLink3, B_OK, true);
1185 	InitTest2DirPaths(absDirLink4, B_OK, true);
1186 	InitTest2DirPaths(relDirLink1, B_OK, true);
1187 	InitTest2DirPaths(relDirLink2, B_OK, true);
1188 	InitTest2DirPaths(relDirLink3, B_OK, true);
1189 	InitTest2DirPaths(relDirLink4, B_OK, true);
1190 	InitTest2DirPaths(absFileLink1, B_OK, true);
1191 	InitTest2DirPaths(absFileLink2, B_OK, true);
1192 	InitTest2DirPaths(absFileLink3, B_OK, true);
1193 	InitTest2DirPaths(absFileLink4, B_OK, true);
1194 	InitTest2DirPaths(relFileLink1, B_OK, true);
1195 	InitTest2DirPaths(relFileLink2, B_OK, true);
1196 	InitTest2DirPaths(relFileLink3, B_OK, true);
1197 	InitTest2DirPaths(relFileLink4, B_OK, true);
1198 	InitTest2DirPaths(absCyclicLink1, B_LINK_LIMIT, true);
1199 	InitTest2DirPaths(relCyclicLink1, B_LINK_LIMIT, true);
1200 	InitTest2DirPaths(absBadLink1, B_ENTRY_NOT_FOUND, true);
1201 	InitTest2DirPaths(absBadLink2, B_ENTRY_NOT_FOUND, true);
1202 	InitTest2DirPaths(absBadLink3, B_ENTRY_NOT_FOUND, true);
1203 	InitTest2DirPaths(absBadLink4, B_ENTRY_NOT_FOUND, true);
1204 	InitTest2DirPaths(relBadLink1, B_ENTRY_NOT_FOUND, true);
1205 	InitTest2DirPaths(relBadLink2, B_ENTRY_NOT_FOUND, true);
1206 	InitTest2DirPaths(relBadLink3, B_ENTRY_NOT_FOUND, true);
1207 	InitTest2DirPaths(relBadLink4, B_ENTRY_NOT_FOUND, true);
1208 	InitTest2DirPaths(absVeryBadLink1, B_ENTRY_NOT_FOUND, true);
1209 	InitTest2DirPaths(absVeryBadLink2, B_ENTRY_NOT_FOUND, true);
1210 	InitTest2DirPaths(absVeryBadLink3, B_ENTRY_NOT_FOUND, true);
1211 	InitTest2DirPaths(absVeryBadLink4, B_ENTRY_NOT_FOUND, true);
1212 	InitTest2DirPaths(relVeryBadLink1, B_ENTRY_NOT_FOUND, true);
1213 	InitTest2DirPaths(relVeryBadLink2, B_ENTRY_NOT_FOUND, true);
1214 	InitTest2DirPaths(relVeryBadLink3, B_ENTRY_NOT_FOUND, true);
1215 	InitTest2DirPaths(relVeryBadLink4, B_ENTRY_NOT_FOUND, true);
1216 // R5: returns E2BIG instead of B_NAME_TOO_LONG
1217 	InitTest2DirPaths(tooLongEntry1, fuzzy_error(E2BIG, B_NAME_TOO_LONG), true);
1218 // Haiku: Fails, because the implementation concatenates the dir and leaf
1219 // 		 name.
1220 #if !TEST_OBOS /* !!!POSIX ONLY!!! */
1221 	InitTest2DirPaths(tooLongDir16, B_OK, true);
1222 #endif
1223 	// special cases (root dir)
1224 	NextSubTest();
1225 	{
1226 		BDirectory dir("/");
1227 		CPPUNIT_ASSERT( entry.SetTo(&dir, ".") == B_OK );
1228 		CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
1229 		entry.Unset();
1230 	}
1231 	// special cases (fs root dir)
1232 	NextSubTest();
1233 	{
1234 		BDirectory dir("/");
1235 		CPPUNIT_ASSERT( entry.SetTo(&dir, "boot") == B_OK );
1236 		CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
1237 		entry.Unset();
1238 	}
1239 	// NULL path
1240 	NextSubTest();
1241 	{
1242 		BDirectory dir("/");
1243 		CPPUNIT_ASSERT( entry.SetTo(&dir, (const char*)NULL) == B_OK );
1244 		CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
1245 		entry.Unset();
1246 	}
1247 	// bad args (NULL dir)
1248 // R5: crashs
1249 #if !TEST_R5
1250 	NextSubTest();
1251 	{
1252 		chdir("/");
1253 		CPPUNIT_ASSERT( entry.SetTo((const BDirectory*)NULL, "tmp")
1254 						== B_BAD_VALUE );
1255 		CPPUNIT_ASSERT( entry.InitCheck() == B_BAD_VALUE );
1256 		RestoreCWD();
1257 		entry.Unset();
1258 	}
1259 #endif
1260 	// strange args (badly initialized dir, absolute path)
1261 	NextSubTest();
1262 	{
1263 		BDirectory dir(badEntry1.cpath);
1264 		CPPUNIT_ASSERT( dir.InitCheck() == B_ENTRY_NOT_FOUND );
1265 		CPPUNIT_ASSERT( entry.SetTo(&dir, "/tmp") == B_OK );
1266 		CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
1267 	}
1268 	// bad args (NULL dir and path)
1269 // R5: crashs
1270 #if !TEST_R5
1271 	NextSubTest();
1272 	{
1273 		CPPUNIT_ASSERT( entry.SetTo((const BDirectory*)NULL, (const char*)NULL)
1274 						== B_BAD_VALUE );
1275 		CPPUNIT_ASSERT( entry.InitCheck() == B_BAD_VALUE );
1276 		entry.Unset();
1277 	}
1278 #endif
1279 	// bad args(NULL dir, absolute path)
1280 // R5: crashs
1281 #if !TEST_R5
1282 	NextSubTest();
1283 	{
1284 		CPPUNIT_ASSERT( entry.SetTo((const BDirectory*)NULL, "/tmp")
1285 						== B_BAD_VALUE );
1286 		CPPUNIT_ASSERT( entry.InitCheck() == B_BAD_VALUE );
1287 		entry.Unset();
1288 	}
1289 #endif
1290 }
1291 
1292 // SpecialGetCasesTest
1293 //
1294 // Tests special (mostly error) cases for Exists(), GetPath(), GetName(),
1295 // GetParent() and GetRef(). The other cases have already been tested in
1296 // InitTest1/2().
1297 void
1298 EntryTest::SpecialGetCasesTest()
1299 {
1300 	BEntry entry;
1301 	// 1. Exists()
1302 	// uninitialized
1303 	NextSubTest();
1304 	CPPUNIT_ASSERT( entry.InitCheck() == B_NO_INIT );
1305 	CPPUNIT_ASSERT( entry.Exists() == false );
1306 	entry.Unset();
1307 	// badly initialized
1308 	NextSubTest();
1309 	CPPUNIT_ASSERT( entry.SetTo(badEntry1.cpath) == B_ENTRY_NOT_FOUND );
1310 	CPPUNIT_ASSERT( entry.Exists() == false );
1311 	entry.Unset();
1312 	// root
1313 	NextSubTest();
1314 	CPPUNIT_ASSERT( entry.SetTo("/") == B_OK );
1315 	CPPUNIT_ASSERT( entry.Exists() == true );
1316 	entry.Unset();
1317 
1318 	// 2. GetPath()
1319 	BPath path;
1320 	// uninitialized
1321 	NextSubTest();
1322 	CPPUNIT_ASSERT( entry.InitCheck() == B_NO_INIT );
1323 	CPPUNIT_ASSERT( entry.GetPath(&path) == B_NO_INIT );
1324 	entry.Unset();
1325 	// badly initialized
1326 	NextSubTest();
1327 	CPPUNIT_ASSERT( entry.SetTo(badEntry1.cpath) == B_ENTRY_NOT_FOUND );
1328 	CPPUNIT_ASSERT( entry.GetPath(&path) == B_NO_INIT );
1329 	entry.Unset();
1330 	// too long pathname
1331 // Haiku: Fails, because the implementation concatenates the dir and leaf
1332 // 		 name.
1333 #if !TEST_OBOS /* !!!POSIX ONLY!!! */
1334 	NextSubTest();
1335 	BDirectory dir(tooLongDir16.super->super->cpath);
1336 	string entryName = tooLongDir16.super->name + "/" + tooLongDir16.name;
1337 	CPPUNIT_ASSERT( entry.SetTo(&dir, entryName.c_str()) == B_OK );
1338 	CPPUNIT_ASSERT( entry.GetPath(&path) == B_OK );
1339 	CPPUNIT_ASSERT( path == tooLongDir16.cpath );
1340 	entry.Unset();
1341 #endif
1342 
1343 	// 3. GetName()
1344 	char name[B_FILE_NAME_LENGTH + 1];
1345 	// uninitialized
1346 	NextSubTest();
1347 	CPPUNIT_ASSERT( entry.InitCheck() == B_NO_INIT );
1348 	CPPUNIT_ASSERT( entry.GetName(name) == B_NO_INIT );
1349 	entry.Unset();
1350 	// badly initialized
1351 	NextSubTest();
1352 	CPPUNIT_ASSERT( entry.SetTo(badEntry1.cpath) == B_ENTRY_NOT_FOUND );
1353 	CPPUNIT_ASSERT( entry.GetName(name) == B_NO_INIT );
1354 	entry.Unset();
1355 
1356 	// 4. GetParent(BEntry *)
1357 	BEntry parentEntry;
1358 	// uninitialized
1359 	NextSubTest();
1360 	CPPUNIT_ASSERT( entry.InitCheck() == B_NO_INIT );
1361 	CPPUNIT_ASSERT( entry.GetParent(&parentEntry) == B_NO_INIT );
1362 	entry.Unset();
1363 	// badly initialized
1364 	NextSubTest();
1365 	CPPUNIT_ASSERT( entry.SetTo(badEntry1.cpath) == B_ENTRY_NOT_FOUND );
1366 	CPPUNIT_ASSERT( entry.GetParent(&parentEntry) == B_NO_INIT );
1367 	entry.Unset();
1368 	// parent of root dir
1369 	NextSubTest();
1370 	CPPUNIT_ASSERT( entry.SetTo("/") == B_OK );
1371 	CPPUNIT_ASSERT( entry.GetParent(&parentEntry) == B_ENTRY_NOT_FOUND );
1372 	entry.Unset();
1373 
1374 	// 5. GetParent(BDirectory *)
1375 	BDirectory parentDir;
1376 	// uninitialized
1377 	NextSubTest();
1378 	CPPUNIT_ASSERT( entry.InitCheck() == B_NO_INIT );
1379 	CPPUNIT_ASSERT( entry.GetParent(&parentDir) == B_NO_INIT );
1380 	entry.Unset();
1381 	// badly initialized
1382 	NextSubTest();
1383 	CPPUNIT_ASSERT( entry.SetTo(badEntry1.cpath) == B_ENTRY_NOT_FOUND );
1384 	CPPUNIT_ASSERT( entry.GetParent(&parentDir) == B_NO_INIT );
1385 	entry.Unset();
1386 	// parent of root dir
1387 	NextSubTest();
1388 	CPPUNIT_ASSERT( entry.SetTo("/") == B_OK );
1389 	CPPUNIT_ASSERT( entry.GetParent(&parentDir) == B_ENTRY_NOT_FOUND );
1390 	entry.Unset();
1391 
1392 	// 6. GetRef()
1393 	entry_ref ref, ref2;
1394 	// uninitialized
1395 	NextSubTest();
1396 	CPPUNIT_ASSERT( entry.InitCheck() == B_NO_INIT );
1397 	CPPUNIT_ASSERT( entry.GetRef(&ref) == B_NO_INIT );
1398 	entry.Unset();
1399 	// badly initialized
1400 	NextSubTest();
1401 	CPPUNIT_ASSERT( entry.SetTo(badEntry1.cpath) == B_ENTRY_NOT_FOUND );
1402 	CPPUNIT_ASSERT( entry.GetRef(&ref) == B_NO_INIT );
1403 	entry.Unset();
1404 	// ref for root dir
1405 	NextSubTest();
1406 	CPPUNIT_ASSERT( entry.SetTo("/") == B_OK );
1407 	CPPUNIT_ASSERT( entry.GetRef(&ref) == B_OK );
1408 	entry.Unset();
1409 }
1410 
1411 // RenameTestEntry
1412 void
1413 EntryTest::RenameTestEntry(TestEntry *testEntry, TestEntry *newTestEntry,
1414 						   string newName, bool existing, bool clobber,
1415 						   status_t error, uint32 kind)
1416 {
1417 	NextSubTest();
1418 	BEntry entry;
1419 	BDirectory dir;
1420 	// get all the names
1421 	string pathname = testEntry->path;
1422 	string dirname = testEntry->super->path;
1423 	string newPathname = newTestEntry->path;
1424 //printf("path: `%s', dir: `%s', new name: `%s'\n", pathname.c_str(),
1425 //dirname.c_str(), newPathname.c_str());
1426 	// create the entries
1427 	switch (kind) {
1428 		case B_FILE_NODE:
1429 			CreateFile(pathname.c_str());
1430 			break;
1431 		case B_DIRECTORY_NODE:
1432 			CreateDir(pathname.c_str());
1433 			break;
1434 		case B_SYMLINK_NODE:
1435 			CreateLink(pathname.c_str(), file1.cpath);
1436 			break;
1437 	}
1438 	if (existing)
1439 		CreateFile(newPathname.c_str());
1440 	// rename the file
1441 	CPPUNIT_ASSERT( entry.SetTo(pathname.c_str()) == B_OK );
1442 	CPPUNIT_ASSERT( dir.SetTo(dirname.c_str()) == B_OK );
1443 	status_t result = entry.Rename(newName.c_str(), clobber);
1444 if (result != error) {
1445 printf("`%s'.Rename(`%s', %d): ", pathname.c_str(), newName.c_str(), clobber);
1446 printf("error: %lx (%lx)\n", result, error);
1447 }
1448 	CPPUNIT_ASSERT( result == error );
1449 	// check and cleanup
1450 	if (error == B_OK) {
1451 		switch (kind) {
1452 			case B_FILE_NODE:
1453 				CPPUNIT_ASSERT( !PingFile(pathname.c_str()) );
1454 				CPPUNIT_ASSERT( PingFile(newPathname.c_str()) );
1455 				break;
1456 			case B_DIRECTORY_NODE:
1457 				CPPUNIT_ASSERT( !PingDir(pathname.c_str()) );
1458 				CPPUNIT_ASSERT( PingDir(newPathname.c_str()) );
1459 				break;
1460 			case B_SYMLINK_NODE:
1461 				CPPUNIT_ASSERT( !PingLink(pathname.c_str()) );
1462 				CPPUNIT_ASSERT( PingLink(newPathname.c_str(), file1.cpath) );
1463 				break;
1464 		}
1465 		RemoveFile(newPathname.c_str());
1466 	} else {
1467 		switch (kind) {
1468 			case B_FILE_NODE:
1469 				CPPUNIT_ASSERT( PingFile(pathname.c_str()) );
1470 				break;
1471 			case B_DIRECTORY_NODE:
1472 				CPPUNIT_ASSERT( PingDir(pathname.c_str()) );
1473 				break;
1474 			case B_SYMLINK_NODE:
1475 				CPPUNIT_ASSERT( PingLink(pathname.c_str(), file1.cpath) );
1476 				break;
1477 		}
1478 		if (existing) {
1479 			CPPUNIT_ASSERT( PingFile(newPathname.c_str()) );
1480 			RemoveFile(newPathname.c_str());
1481 		}
1482 		RemoveFile(pathname.c_str());
1483 	}
1484 }
1485 
1486 // RenameTestEntry
1487 void
1488 EntryTest::RenameTestEntry(TestEntry *testEntry, TestEntry *newTestEntry,
1489 						   bool existing, bool clobber, status_t error,
1490 						   uint32 kind)
1491 {
1492 	// relative path
1493 	string relPath = get_shortest_relative_path(testEntry->super,
1494 												newTestEntry);
1495 	if (relPath.length() > 0) {
1496 		RenameTestEntry(testEntry, newTestEntry, relPath, existing,
1497 						clobber, error, B_FILE_NODE);
1498 	}
1499 	// absolute path
1500 	RenameTestEntry(testEntry, newTestEntry, newTestEntry->path, existing,
1501 					clobber, error, B_FILE_NODE);
1502 }
1503 
1504 // RenameTestFile
1505 void
1506 EntryTest::RenameTestFile(TestEntry *testEntry, TestEntry *newTestEntry,
1507 						  bool existing, bool clobber, status_t error)
1508 {
1509 	RenameTestEntry(testEntry, newTestEntry, existing, clobber, error,
1510 					B_FILE_NODE);
1511 }
1512 
1513 // RenameTestDir
1514 void
1515 EntryTest::RenameTestDir(TestEntry *testEntry, TestEntry *newTestEntry,
1516 						 bool existing, bool clobber, status_t error)
1517 {
1518 	RenameTestEntry(testEntry, newTestEntry, existing, clobber, error,
1519 					B_DIRECTORY_NODE);
1520 }
1521 
1522 // RenameTestLink
1523 void
1524 EntryTest::RenameTestLink(TestEntry *testEntry, TestEntry *newTestEntry,
1525 						  bool existing, bool clobber, status_t error)
1526 {
1527 	RenameTestEntry(testEntry, newTestEntry, existing, clobber, error,
1528 					B_SYMLINK_NODE);
1529 }
1530 
1531 // RenameTest
1532 void
1533 EntryTest::RenameTest()
1534 {
1535 	BDirectory dir;
1536 	BEntry entry;
1537 	// file
1538 	// same dir
1539 	RenameTestFile(&file2, &file2, false, false, B_FILE_EXISTS);
1540 	RenameTestFile(&file2, &file2, false, true, B_NOT_ALLOWED);
1541 	RenameTestFile(&file2, &file4, false, false, B_OK);
1542 	// different dir
1543 	RenameTestFile(&file2, &file3, false, false, B_OK);
1544 	// different dir, existing file, clobber
1545 	RenameTestFile(&file2, &file3, true, true, B_OK);
1546 	// different dir, existing file, no clobber
1547 	RenameTestFile(&file2, &file3, true, false, B_FILE_EXISTS);
1548 	// dir
1549 	// same dir
1550 	RenameTestDir(&file2, &file2, false, false, B_FILE_EXISTS);
1551 	RenameTestDir(&file2, &file2, false, true, B_NOT_ALLOWED);
1552 	RenameTestDir(&file2, &file4, false, false, B_OK);
1553 	// different dir
1554 	RenameTestDir(&file2, &file3, false, false, B_OK);
1555 	// different dir, existing file, clobber
1556 	RenameTestDir(&file2, &file3, true, true, B_OK);
1557 	// different dir, existing file, no clobber
1558 	RenameTestDir(&file2, &file3, true, false, B_FILE_EXISTS);
1559 	// link
1560 	// same dir
1561 	RenameTestLink(&file2, &file2, false, false, B_FILE_EXISTS);
1562 	RenameTestLink(&file2, &file2, false, true, B_NOT_ALLOWED);
1563 	RenameTestLink(&file2, &file4, false, false, B_OK);
1564 	// different dir
1565 	RenameTestLink(&file2, &file3, false, false, B_OK);
1566 	// different dir, existing file, clobber
1567 	RenameTestLink(&file2, &file3, true, true, B_OK);
1568 	// different dir, existing file, no clobber
1569 	RenameTestLink(&file2, &file3, true, false, B_FILE_EXISTS);
1570 
1571 	// try to clobber a non-empty directory
1572 	NextSubTest();
1573 	CreateFile(file3.cpath);
1574 	CPPUNIT_ASSERT( entry.SetTo(file3.cpath) == B_OK );
1575 	CPPUNIT_ASSERT( entry.Rename(dir1.cpath, true) == B_DIRECTORY_NOT_EMPTY );
1576 	CPPUNIT_ASSERT( PingDir(dir1.cpath) );
1577 	CPPUNIT_ASSERT( PingFile(file3.cpath, &entry) );
1578 	RemoveFile(file3.cpath);
1579 	entry.Unset();
1580 	dir.Unset();
1581 	// clobber an empty directory
1582 	NextSubTest();
1583 	CreateFile(file3.cpath);
1584 	CPPUNIT_ASSERT( entry.SetTo(file3.cpath) == B_OK );
1585 	CPPUNIT_ASSERT( entry.Rename(subDir1.cpath, true) == B_OK );
1586 	CPPUNIT_ASSERT( PingFile(subDir1.cpath, &entry) );
1587 	CPPUNIT_ASSERT( !PingFile(file3.cpath) );
1588 	RemoveFile(subDir1.cpath);
1589 	entry.Unset();
1590 	dir.Unset();
1591 	// abstract entry
1592 	NextSubTest();
1593 	CPPUNIT_ASSERT( entry.SetTo(file2.cpath) == B_OK );
1594 	CPPUNIT_ASSERT( entry.Rename(file4.cname) == B_ENTRY_NOT_FOUND );
1595 	entry.Unset();
1596 	dir.Unset();
1597 	// uninitialized entry
1598 	NextSubTest();
1599 	CPPUNIT_ASSERT( entry.InitCheck() == B_NO_INIT );
1600 	CPPUNIT_ASSERT( entry.Rename(file4.cpath) == B_NO_INIT );
1601 	entry.Unset();
1602 	dir.Unset();
1603 	// badly initialized entry
1604 	NextSubTest();
1605 	CPPUNIT_ASSERT( entry.SetTo(badEntry1.cpath) == B_ENTRY_NOT_FOUND );
1606 	CPPUNIT_ASSERT( entry.Rename(file4.cpath) == B_NO_INIT );
1607 	entry.Unset();
1608 	dir.Unset();
1609 	// Verify attempts to rename root
1610 	NextSubTest();
1611 	BEntry root("/");
1612 	CPPUNIT_ASSERT( root.Rename("/", false) == B_FILE_EXISTS );
1613 	CPPUNIT_ASSERT( root.Rename("/", true) == B_NOT_ALLOWED );
1614 	// Verify abstract entries
1615 	NextSubTest();
1616 	BEntry abstract(abstractEntry1.cpath);
1617 	CPPUNIT_ASSERT( abstract.InitCheck() == B_OK );
1618 	CPPUNIT_ASSERT( !abstract.Exists() );
1619 	CPPUNIT_ASSERT( abstract.Rename("/boot/DoesntMatter") == B_ENTRY_NOT_FOUND );
1620 	CPPUNIT_ASSERT( abstract.Rename("/boot/DontMatter", true) == B_ENTRY_NOT_FOUND );
1621 	CPPUNIT_ASSERT( abstract.Rename("/DoesntMatter") == B_CROSS_DEVICE_LINK );
1622 	CPPUNIT_ASSERT( abstract.Rename("/DontMatter", true) == B_CROSS_DEVICE_LINK );
1623 	// bad args
1624 	NextSubTest();
1625 	CPPUNIT_ASSERT( entry.SetTo(file1.cpath) == B_OK );
1626 	CPPUNIT_ASSERT( equals(entry.Rename(NULL, false), B_FILE_EXISTS,
1627 						   B_BAD_VALUE) );
1628 	CPPUNIT_ASSERT( equals(entry.Rename(NULL, true), B_NOT_ALLOWED,
1629 						   B_BAD_VALUE) );
1630 }
1631 
1632 // MoveToTestEntry
1633 void
1634 EntryTest::MoveToTestEntry(TestEntry *testEntry, TestEntry *testDir,
1635 						   string newName, bool existing, bool clobber,
1636 						   status_t error, uint32 kind)
1637 {
1638 	NextSubTest();
1639 	BEntry entry;
1640 	BDirectory dir;
1641 	// get all the names
1642 	string pathname = testEntry->path;
1643 	string dirname = testDir->path;
1644 	string newPathname = dirname + "/";
1645 	if (newName.length() == 0)
1646 		newPathname += testEntry->name;
1647 	else {
1648 		// check, if the new path is absolute
1649 		if (newName.find("/") == 0)
1650 			newPathname = newName;
1651 		else
1652 			newPathname += newName;
1653 	}
1654 //printf("path: `%s', dir: `%s', new name: `%s'\n", pathname.c_str(),
1655 //dirname.c_str(), newPathname.c_str());
1656 	// create the entries
1657 	switch (kind) {
1658 		case B_FILE_NODE:
1659 			CreateFile(pathname.c_str());
1660 			break;
1661 		case B_DIRECTORY_NODE:
1662 			CreateDir(pathname.c_str());
1663 			break;
1664 		case B_SYMLINK_NODE:
1665 			CreateLink(pathname.c_str(), file1.cpath);
1666 			break;
1667 	}
1668 	if (existing)
1669 		CreateFile(newPathname.c_str());
1670 	// move the file
1671 	CPPUNIT_ASSERT( entry.SetTo(pathname.c_str()) == B_OK );
1672 	CPPUNIT_ASSERT( dir.SetTo(dirname.c_str()) == B_OK );
1673 	if (newName.length() == 0) {
1674 		status_t result = entry.MoveTo(&dir, NULL, clobber);
1675 if (result != error) {
1676 printf("`%s'.MoveTo(`%s', NULL, %d): ", pathname.c_str(), dirname.c_str(), clobber);
1677 printf("error: %lx (%lx)\n", result, error);
1678 }
1679 		CPPUNIT_ASSERT( result == error );
1680 	} else {
1681 		status_t result = entry.MoveTo(&dir, newName.c_str(), clobber);
1682 if (result != error) {
1683 printf("`%s'.MoveTo(`%s', `%s', %d): ", pathname.c_str(), newName.c_str(), dirname.c_str(), clobber);
1684 printf("error: %lx (%lx)\n", result, error);
1685 }
1686 		CPPUNIT_ASSERT( result == error );
1687 	}
1688 	// check and cleanup
1689 	if (error == B_OK) {
1690 		switch (kind) {
1691 			case B_FILE_NODE:
1692 				CPPUNIT_ASSERT( !PingFile(pathname.c_str()) );
1693 				CPPUNIT_ASSERT( PingFile(newPathname.c_str()) );
1694 				break;
1695 			case B_DIRECTORY_NODE:
1696 				CPPUNIT_ASSERT( !PingDir(pathname.c_str()) );
1697 				CPPUNIT_ASSERT( PingDir(newPathname.c_str()) );
1698 				break;
1699 			case B_SYMLINK_NODE:
1700 				CPPUNIT_ASSERT( !PingLink(pathname.c_str()) );
1701 				CPPUNIT_ASSERT( PingLink(newPathname.c_str(), file1.cpath) );
1702 				break;
1703 		}
1704 		RemoveFile(newPathname.c_str());
1705 	} else {
1706 		switch (kind) {
1707 			case B_FILE_NODE:
1708 				CPPUNIT_ASSERT( PingFile(pathname.c_str()) );
1709 				break;
1710 			case B_DIRECTORY_NODE:
1711 				CPPUNIT_ASSERT( PingDir(pathname.c_str()) );
1712 				break;
1713 			case B_SYMLINK_NODE:
1714 				CPPUNIT_ASSERT( PingLink(pathname.c_str(), file1.cpath) );
1715 				break;
1716 		}
1717 		if (existing) {
1718 			CPPUNIT_ASSERT( PingFile(newPathname.c_str()) );
1719 			RemoveFile(newPathname.c_str());
1720 		}
1721 		RemoveFile(pathname.c_str());
1722 	}
1723 }
1724 
1725 // MoveToTestEntry
1726 void
1727 EntryTest::MoveToTestEntry(TestEntry *testEntry, TestEntry *testDir,
1728 						   TestEntry *newTestEntry, bool existing,
1729 						   bool clobber, status_t error, uint32 kind)
1730 {
1731 	if (newTestEntry) {
1732 		// Here is the right place to play a little bit with the dir and path
1733 		// arguments. At this time we only pass the leaf name and the
1734 		// absolute path name.
1735 		MoveToTestEntry(testEntry, testDir, newTestEntry->name, existing,
1736 						clobber, error, B_FILE_NODE);
1737 		MoveToTestEntry(testEntry, &subDir1, newTestEntry->path, existing,
1738 						clobber, error, B_FILE_NODE);
1739 	} else {
1740 		MoveToTestEntry(testEntry, testDir, "", existing, clobber, error,
1741 						B_FILE_NODE);
1742 	}
1743 }
1744 
1745 // MoveToTestFile
1746 void
1747 EntryTest::MoveToTestFile(TestEntry *testEntry, TestEntry *testDir,
1748 						  TestEntry *newTestEntry, bool existing, bool clobber,
1749 						  status_t error)
1750 {
1751 	MoveToTestEntry(testEntry, testDir, newTestEntry, existing, clobber, error,
1752 					B_FILE_NODE);
1753 }
1754 
1755 // MoveToTestDir
1756 void
1757 EntryTest::MoveToTestDir(TestEntry *testEntry, TestEntry *testDir,
1758 						 TestEntry *newTestEntry, bool existing, bool clobber,
1759 						 status_t error)
1760 {
1761 	MoveToTestEntry(testEntry, testDir, newTestEntry, existing, clobber, error,
1762 					B_DIRECTORY_NODE);
1763 }
1764 
1765 // MoveToTestLink
1766 void
1767 EntryTest::MoveToTestLink(TestEntry *testEntry, TestEntry *testDir,
1768 						  TestEntry *newTestEntry, bool existing, bool clobber,
1769 						  status_t error)
1770 {
1771 	MoveToTestEntry(testEntry, testDir, newTestEntry, existing, clobber, error,
1772 					B_SYMLINK_NODE);
1773 }
1774 
1775 // MoveToTest
1776 void
1777 EntryTest::MoveToTest()
1778 {
1779 	BDirectory dir;
1780 	BEntry entry;
1781 	// 1. NULL path
1782 	// file
1783 	// same dir
1784 	MoveToTestFile(&file2, file2.super, NULL, false, false, B_FILE_EXISTS);
1785 	MoveToTestFile(&file2, file2.super, NULL, false, true, B_NOT_ALLOWED);
1786 	// different dir
1787 	MoveToTestFile(&file2, &dir2, NULL, false, false, B_OK);
1788 	// different dir, existing file, clobber
1789 	MoveToTestFile(&file2, &dir2, NULL, true, true, B_OK);
1790 	// different dir, existing file, no clobber
1791 	MoveToTestFile(&file2, &dir2, NULL, true, false, B_FILE_EXISTS);
1792 	// dir
1793 	// same dir
1794 	MoveToTestDir(&file2, file2.super, NULL, false, false, B_FILE_EXISTS);
1795 	MoveToTestDir(&file2, file2.super, NULL, false, true, B_NOT_ALLOWED);
1796 	// different dir
1797 	MoveToTestDir(&file2, &dir2, NULL, false, false, B_OK);
1798 	// different dir, existing file, clobber
1799 	MoveToTestDir(&file2, &dir2, NULL, true, true, B_OK);
1800 	// different dir, existing file, no clobber
1801 	MoveToTestDir(&file2, &dir2, NULL, true, false, B_FILE_EXISTS);
1802 	// link
1803 	// same dir
1804 	MoveToTestLink(&file2, file2.super, NULL, false, false, B_FILE_EXISTS);
1805 	MoveToTestLink(&file2, file2.super, NULL, false, true, B_NOT_ALLOWED);
1806 	// different dir
1807 	MoveToTestLink(&file2, &dir2, NULL, false, false, B_OK);
1808 	// different dir, existing file, clobber
1809 	MoveToTestLink(&file2, &dir2, NULL, true, true, B_OK);
1810 	// different dir, existing file, no clobber
1811 	MoveToTestLink(&file2, &dir2, NULL, true, false, B_FILE_EXISTS);
1812 
1813 	// 2. non NULL path
1814 	// file
1815 	// same dir
1816 	MoveToTestFile(&file2, file2.super, &file2, false, false,
1817 				   B_FILE_EXISTS);
1818 	MoveToTestFile(&file2, file2.super, &file2, false, true,
1819 				   B_NOT_ALLOWED);
1820 	MoveToTestFile(&file2, file2.super, &file3, false, false, B_OK);
1821 	// different dir
1822 	MoveToTestFile(&file2, &dir2, &file3, false, false, B_OK);
1823 	// different dir, existing file, clobber
1824 	MoveToTestFile(&file2, &dir2, &file3, true, true, B_OK);
1825 	// different dir, existing file, no clobber
1826 	MoveToTestFile(&file2, &dir2, &file3, true, false, B_FILE_EXISTS);
1827 	// dir
1828 	// same dir
1829 	MoveToTestDir(&file2, file2.super, &file2, false, false,
1830 				  B_FILE_EXISTS);
1831 	MoveToTestDir(&file2, file2.super, &file2, false, true,
1832 				  B_NOT_ALLOWED);
1833 	MoveToTestDir(&file2, file2.super, &file3, false, false, B_OK);
1834 	// different dir
1835 	MoveToTestDir(&file2, &dir2, &file3, false, false, B_OK);
1836 	// different dir, existing file, clobber
1837 	MoveToTestDir(&file2, &dir2, &file3, true, true, B_OK);
1838 	// different dir, existing file, no clobber
1839 	MoveToTestDir(&file2, &dir2, &file3, true, false, B_FILE_EXISTS);
1840 	// link
1841 	// same dir
1842 	MoveToTestLink(&file2, file2.super, &file2, false, false,
1843 				   B_FILE_EXISTS);
1844 	MoveToTestLink(&file2, file2.super, &file2, false, true,
1845 				   B_NOT_ALLOWED);
1846 	MoveToTestLink(&file2, file2.super, &file3, false, false, B_OK);
1847 	// different dir
1848 	MoveToTestLink(&file2, &dir2, &file3, false, false, B_OK);
1849 	// different dir, existing file, clobber
1850 	MoveToTestLink(&file2, &dir2, &file3, true, true, B_OK);
1851 	// different dir, existing file, no clobber
1852 	MoveToTestLink(&file2, &dir2, &file3, true, false, B_FILE_EXISTS);
1853 
1854 	// try to clobber a non-empty directory
1855 	CreateFile(file3.cpath);
1856 	CPPUNIT_ASSERT( entry.SetTo(file3.cpath) == B_OK );
1857 	CPPUNIT_ASSERT( dir.SetTo(dir1.super->cpath) == B_OK );
1858 	CPPUNIT_ASSERT( entry.MoveTo(&dir, dir1.cname, true)
1859 					== B_DIRECTORY_NOT_EMPTY );
1860 	CPPUNIT_ASSERT( PingDir(dir1.cpath) );
1861 	CPPUNIT_ASSERT( PingFile(file3.cpath, &entry) );
1862 	RemoveFile(file3.cpath);
1863 	entry.Unset();
1864 	dir.Unset();
1865 	// clobber an empty directory
1866 	CreateFile(file3.cpath);
1867 	CPPUNIT_ASSERT( entry.SetTo(file3.cpath) == B_OK );
1868 	CPPUNIT_ASSERT( dir.SetTo(subDir1.super->cpath) == B_OK );
1869 	CPPUNIT_ASSERT( entry.MoveTo(&dir, subDir1.cname, true) == B_OK );
1870 	CPPUNIT_ASSERT( PingFile(subDir1.cpath, &entry) );
1871 	CPPUNIT_ASSERT( !PingFile(file3.cpath) );
1872 	RemoveFile(subDir1.cpath);
1873 	entry.Unset();
1874 	dir.Unset();
1875 	// abstract entry
1876 	CPPUNIT_ASSERT( entry.SetTo(file2.cpath) == B_OK );
1877 	CPPUNIT_ASSERT( dir.SetTo(dir2.cpath) == B_OK );
1878 	CPPUNIT_ASSERT( entry.MoveTo(&dir) == B_ENTRY_NOT_FOUND );
1879 	entry.Unset();
1880 	dir.Unset();
1881 	// uninitialized entry
1882 	CPPUNIT_ASSERT( entry.InitCheck() == B_NO_INIT );
1883 	CPPUNIT_ASSERT( dir.SetTo(dir2.cpath) == B_OK );
1884 	CPPUNIT_ASSERT( entry.MoveTo(&dir) == B_NO_INIT );
1885 	entry.Unset();
1886 	dir.Unset();
1887 	// badly initialized entry
1888 	CPPUNIT_ASSERT( entry.SetTo(badEntry1.cpath) == B_ENTRY_NOT_FOUND );
1889 	CPPUNIT_ASSERT( dir.SetTo(dir2.cpath) == B_OK );
1890 	CPPUNIT_ASSERT( entry.MoveTo(&dir) == B_NO_INIT );
1891 	entry.Unset();
1892 	dir.Unset();
1893 	// bad args (NULL dir)
1894 // R5: crashs
1895 #if !TEST_R5
1896 	CreateFile(file2.cpath);
1897 	CPPUNIT_ASSERT( entry.SetTo(file2.cpath) == B_OK );
1898 	CPPUNIT_ASSERT( entry.MoveTo(NULL, file3.cpath) == B_BAD_VALUE );
1899 	RemoveFile(file3.cpath);
1900 	entry.Unset();
1901 	dir.Unset();
1902 #endif
1903 	// uninitialized dir, absolute path
1904 	CreateFile(file2.cpath);
1905 	CPPUNIT_ASSERT( entry.SetTo(file2.cpath) == B_OK );
1906 	CPPUNIT_ASSERT( dir.InitCheck() == B_NO_INIT );
1907 	CPPUNIT_ASSERT( entry.MoveTo(&dir, file3.cpath) == B_BAD_VALUE );
1908 	RemoveFile(file3.cpath);
1909 	entry.Unset();
1910 	dir.Unset();
1911 }
1912 
1913 // RemoveTest
1914 void
1915 EntryTest::RemoveTest()
1916 {
1917 	BEntry entry;
1918 	// file
1919 	NextSubTest();
1920 	CPPUNIT_ASSERT( entry.SetTo(file1.cpath) == B_OK );
1921 	CPPUNIT_ASSERT( entry.Remove() == B_OK );
1922 	CPPUNIT_ASSERT( !PingFile(file1.cpath) );
1923 	entry.Unset();
1924 	// symlink
1925 	NextSubTest();
1926 	CPPUNIT_ASSERT( entry.SetTo(absFileLink1.cpath) == B_OK );
1927 	CPPUNIT_ASSERT( entry.Remove() == B_OK );
1928 	CPPUNIT_ASSERT( !PingLink(absFileLink1.cpath) );
1929 	entry.Unset();
1930 	// empty dir
1931 	NextSubTest();
1932 	CPPUNIT_ASSERT( entry.SetTo(subDir1.cpath) == B_OK );
1933 	CPPUNIT_ASSERT( entry.Remove() == B_OK );
1934 	CPPUNIT_ASSERT( !PingDir(subDir1.cpath) );
1935 	entry.Unset();
1936 	// non-empty dir
1937 	NextSubTest();
1938 	CPPUNIT_ASSERT( entry.SetTo(dir1.cpath) == B_OK );
1939 	CPPUNIT_ASSERT( entry.Remove() == B_DIRECTORY_NOT_EMPTY );
1940 	CPPUNIT_ASSERT( PingDir(dir1.cpath) );
1941 	entry.Unset();
1942 	// abstract entry
1943 	NextSubTest();
1944 	CPPUNIT_ASSERT( entry.SetTo(abstractEntry1.cpath) == B_OK );
1945 	CPPUNIT_ASSERT( entry.Remove() == B_ENTRY_NOT_FOUND );
1946 	entry.Unset();
1947 	// uninitialized
1948 	NextSubTest();
1949 	CPPUNIT_ASSERT( entry.InitCheck() == B_NO_INIT );
1950 	CPPUNIT_ASSERT( entry.Remove() == B_NO_INIT );
1951 	entry.Unset();
1952 	// badly initialized
1953 	NextSubTest();
1954 	CPPUNIT_ASSERT( entry.SetTo(badEntry1.cpath) == B_ENTRY_NOT_FOUND );
1955 	CPPUNIT_ASSERT( entry.Remove() == B_NO_INIT );
1956 	entry.Unset();
1957 }
1958 
1959 // compareEntries
1960 static
1961 void
1962 compareEntries(const BEntry &entry, const BEntry &entry2,
1963 			   const TestEntry *testEntry, const TestEntry *testEntry2,
1964 			   bool traversed, bool traversed2)
1965 {
1966 	if (!testEntry->isBad() && !testEntry2->isBad()
1967 		&& (!traversed && testEntry->isConcrete())
1968 		&& (!traversed2 && testEntry2->isConcrete())) {
1969 //printf("compare: `%s', `%s'\n", testEntry->cpath, testEntry2->cpath);
1970 //printf("InitCheck(): %x, %x\n", entry.InitCheck(), entry2.InitCheck());
1971 		CPPUNIT_ASSERT( (entry == entry2) == (testEntry == testEntry2) );
1972 		CPPUNIT_ASSERT( (entry == entry2) == (testEntry2 == testEntry) );
1973 		CPPUNIT_ASSERT( (entry != entry2) == (testEntry != testEntry2) );
1974 		CPPUNIT_ASSERT( (entry != entry2) == (testEntry2 != testEntry) );
1975 	}
1976 }
1977 
1978 // ComparisonTest
1979 void
1980 EntryTest::ComparisonTest()
1981 {
1982 	// uninitialized
1983 	NextSubTest();
1984 	{
1985 		BEntry entry;
1986 		BEntry entry2;
1987 		CPPUNIT_ASSERT( entry == entry2 );
1988 		CPPUNIT_ASSERT( entry2 == entry );
1989 		CPPUNIT_ASSERT( !(entry != entry2) );
1990 		CPPUNIT_ASSERT( !(entry2 != entry) );
1991 	}
1992 	// initialized + uninitialized
1993 	NextSubTest();
1994 	{
1995 		BEntry entry(file1.cpath);
1996 		BEntry entry2;
1997 		CPPUNIT_ASSERT( !(entry == entry2) );
1998 		CPPUNIT_ASSERT( !(entry2 == entry) );
1999 		CPPUNIT_ASSERT( entry != entry2 );
2000 		CPPUNIT_ASSERT( entry2 != entry );
2001 	}
2002 	{
2003 		BEntry entry;
2004 		BEntry entry2(file1.cpath);
2005 		CPPUNIT_ASSERT( !(entry == entry2) );
2006 		CPPUNIT_ASSERT( !(entry2 == entry) );
2007 		CPPUNIT_ASSERT( entry != entry2 );
2008 		CPPUNIT_ASSERT( entry2 != entry );
2009 	}
2010 	// initialized
2011 	TestEntry *testEntries[] = {
2012 		&dir1, &dir2, &file1, &subDir1, &abstractEntry1, &badEntry1,
2013 		&absDirLink1, &absDirLink2, &absDirLink3, &absDirLink4,
2014 		&relDirLink1, &relDirLink2, &relDirLink3, &relDirLink4,
2015 		&absFileLink1, &absFileLink2, &absFileLink3, &absFileLink4,
2016 		&relFileLink1, &relFileLink2, &relFileLink3, &relFileLink4,
2017 		&absBadLink1, &absBadLink2, &absBadLink3, &absBadLink4,
2018 		&relBadLink1, &relBadLink2, &relBadLink3, &relBadLink4,
2019 		&absVeryBadLink1, &absVeryBadLink2, &absVeryBadLink3, &absVeryBadLink4,
2020 		&relVeryBadLink1, &relVeryBadLink2, &relVeryBadLink3, &relVeryBadLink4
2021 	};
2022 	int32 testEntryCount = sizeof(testEntries) / sizeof(TestEntry*);
2023 	for (int32 i = 0; i < testEntryCount; i++) {
2024 		NextSubTest();
2025 		TestEntry *testEntry = testEntries[i];
2026 		TestEntry *traversedTestEntry = resolve_link(testEntry);
2027 		BEntry entry(testEntry->cpath);
2028 		BEntry traversedEntry(testEntry->cpath, true);
2029 		for (int32 k = 0; k < testEntryCount; k++) {
2030 			TestEntry *testEntry2 = testEntries[k];
2031 			TestEntry *traversedTestEntry2 = resolve_link(testEntry2);
2032 			BEntry entry2(testEntry2->cpath);
2033 			BEntry traversedEntry2(testEntry2->cpath, true);
2034 			compareEntries(entry, entry2, testEntry, testEntry2, false, false);
2035 			compareEntries(traversedEntry, entry2,
2036 						   traversedTestEntry, testEntry2, true, false);
2037 			compareEntries(entry, traversedEntry2,
2038 						   testEntry, traversedTestEntry2, false, true);
2039 			compareEntries(traversedEntry, traversedEntry2,
2040 						   traversedTestEntry, traversedTestEntry2,
2041 						   true, true);
2042 		}
2043 	}
2044 }
2045 
2046 // AssignmentTest
2047 void
2048 EntryTest::AssignmentTest()
2049 {
2050 	// 1. copy constructor
2051 	// uninitialized
2052 	NextSubTest();
2053 	{
2054 		BEntry entry;
2055 		CPPUNIT_ASSERT( entry.InitCheck() == B_NO_INIT );
2056 		BEntry entry2(entry);
2057 // R5: returns B_BAD_VALUE instead of B_NO_INIT
2058 		CPPUNIT_ASSERT( equals(entry2.InitCheck(), B_BAD_VALUE, B_NO_INIT) );
2059 		CPPUNIT_ASSERT( entry == entry2 );
2060 	}
2061 	// initialized
2062 	TestEntry *testEntries[] = {
2063 		&dir1, &dir2, &file1, &subDir1, &abstractEntry1, &badEntry1,
2064 		&absDirLink1, &absDirLink2, &absDirLink3, &absDirLink4,
2065 		&relDirLink1, &relDirLink2, &relDirLink3, &relDirLink4,
2066 		&absFileLink1, &absFileLink2, &absFileLink3, &absFileLink4,
2067 		&relFileLink1, &relFileLink2, &relFileLink3, &relFileLink4,
2068 		&absBadLink1, &absBadLink2, &absBadLink3, &absBadLink4,
2069 		&relBadLink1, &relBadLink2, &relBadLink3, &relBadLink4,
2070 		&absVeryBadLink1, &absVeryBadLink2, &absVeryBadLink3, &absVeryBadLink4,
2071 		&relVeryBadLink1, &relVeryBadLink2, &relVeryBadLink3, &relVeryBadLink4
2072 	};
2073 	int32 testEntryCount = sizeof(testEntries) / sizeof(TestEntry*);
2074 	for (int32 i = 0; i < testEntryCount; i++) {
2075 		NextSubTest();
2076 		TestEntry *testEntry = testEntries[i];
2077 		BEntry entry(testEntry->cpath);
2078 		BEntry entry2(entry);
2079 		CPPUNIT_ASSERT( entry == entry2 );
2080 		CPPUNIT_ASSERT( entry2 == entry );
2081 		CPPUNIT_ASSERT( !(entry != entry2) );
2082 		CPPUNIT_ASSERT( !(entry2 != entry) );
2083 	}
2084 
2085 	// 2. assignment operator
2086 	// uninitialized
2087 	NextSubTest();
2088 	{
2089 		BEntry entry;
2090 		CPPUNIT_ASSERT( entry.InitCheck() == B_NO_INIT );
2091 		BEntry entry2;
2092 		entry2 = entry;
2093 // R5: returns B_BAD_VALUE instead of B_NO_INIT
2094 		CPPUNIT_ASSERT( equals(entry2.InitCheck(), B_BAD_VALUE, B_NO_INIT) );
2095 		CPPUNIT_ASSERT( entry == entry2 );
2096 	}
2097 	NextSubTest();
2098 	{
2099 		BEntry entry;
2100 		CPPUNIT_ASSERT( entry.InitCheck() == B_NO_INIT );
2101 		BEntry entry2(file1.cpath);
2102 		entry2 = entry;
2103 // R5: returns B_BAD_VALUE instead of B_NO_INIT
2104 		CPPUNIT_ASSERT( equals(entry2.InitCheck(), B_BAD_VALUE, B_NO_INIT) );
2105 		CPPUNIT_ASSERT( entry == entry2 );
2106 	}
2107 	// initialized
2108 	for (int32 i = 0; i < testEntryCount; i++) {
2109 		NextSubTest();
2110 		TestEntry *testEntry = testEntries[i];
2111 		BEntry entry(testEntry->cpath);
2112 		BEntry entry2;
2113 		BEntry entry3(file1.cpath);
2114 		entry2 = entry;
2115 		entry3 = entry;
2116 		CPPUNIT_ASSERT( entry == entry2 );
2117 		CPPUNIT_ASSERT( entry2 == entry );
2118 		CPPUNIT_ASSERT( !(entry != entry2) );
2119 		CPPUNIT_ASSERT( !(entry2 != entry) );
2120 		CPPUNIT_ASSERT( entry == entry3 );
2121 		CPPUNIT_ASSERT( entry3 == entry );
2122 		CPPUNIT_ASSERT( !(entry != entry3) );
2123 		CPPUNIT_ASSERT( !(entry3 != entry) );
2124 	}
2125 }
2126 
2127 // get_entry_ref_for_entry
2128 static
2129 status_t
2130 get_entry_ref_for_entry(const char *dir, const char *leaf, entry_ref *ref)
2131 {
2132 	status_t error = (dir && leaf ? B_OK : B_BAD_VALUE);
2133 	struct stat dirStat;
2134 	if (lstat(dir, &dirStat) == 0) {
2135 		ref->device = dirStat.st_dev;
2136 		ref->directory = dirStat.st_ino;
2137 		ref->set_name(leaf);
2138 	} else
2139 		error = errno;
2140 	return error;
2141 }
2142 
2143 // entry_ref >
2144 bool
2145 operator>(const entry_ref & a, const entry_ref & b)
2146 {
2147 	return (a.device > b.device
2148 		|| (a.device == b.device
2149 			&& (a.directory > b.directory
2150 			|| (a.directory == b.directory
2151 				&& (a.name != NULL && b.name == NULL
2152 				|| (a.name != NULL && b.name != NULL
2153 					&& strcmp(a.name, b.name) > 0))))));
2154 }
2155 
2156 // CFunctionsTest
2157 void
2158 EntryTest::CFunctionsTest()
2159 {
2160 	// get_ref_for_path(), <
2161 	TestEntry *testEntries[] = {
2162 		&dir1, &dir2, &file1, &subDir1, &abstractEntry1, &badEntry1,
2163 		&absDirLink1, &absDirLink2, &absDirLink3, &absDirLink4,
2164 		&relDirLink1, &relDirLink2, &relDirLink3, &relDirLink4,
2165 		&absFileLink1, &absFileLink2, &absFileLink3, &absFileLink4,
2166 		&relFileLink1, &relFileLink2, &relFileLink3, &relFileLink4,
2167 		&absBadLink1, &absBadLink2, &absBadLink3, &absBadLink4,
2168 		&relBadLink1, &relBadLink2, &relBadLink3, &relBadLink4,
2169 		&absVeryBadLink1, &absVeryBadLink2, &absVeryBadLink3, &absVeryBadLink4,
2170 		&relVeryBadLink1, &relVeryBadLink2, &relVeryBadLink3, &relVeryBadLink4
2171 	};
2172 	int32 testEntryCount = sizeof(testEntries) / sizeof(TestEntry*);
2173 	for (int32 i = 0; i < testEntryCount; i++) {
2174 		NextSubTest();
2175 		TestEntry *testEntry = testEntries[i];
2176 		const char *path = testEntry->cpath;
2177 		entry_ref ref;
2178 		if (testEntry->isBad())
2179 			CPPUNIT_ASSERT( get_ref_for_path(path, &ref) == B_ENTRY_NOT_FOUND );
2180 		else {
2181 			CPPUNIT_ASSERT( get_ref_for_path(path, &ref) == B_OK );
2182 			const entry_ref &testEntryRef = testEntry->get_ref();
2183 			CPPUNIT_ASSERT( testEntryRef.device == ref.device );
2184 			CPPUNIT_ASSERT( testEntryRef.directory == ref.directory );
2185 			CPPUNIT_ASSERT( strcmp(testEntryRef.name, ref.name) == 0 );
2186 			CPPUNIT_ASSERT( testEntryRef == ref );
2187 			CPPUNIT_ASSERT( !(testEntryRef != ref) );
2188 			CPPUNIT_ASSERT(  ref == testEntryRef );
2189 			CPPUNIT_ASSERT(  !(ref != testEntryRef) );
2190 			for (int32 k = 0; k < testEntryCount; k++) {
2191 				TestEntry *testEntry2 = testEntries[k];
2192 				const char *path2 = testEntry2->cpath;
2193 				entry_ref ref2;
2194 				if (!testEntry2->isBad()) {
2195 					CPPUNIT_ASSERT( get_ref_for_path(path2, &ref2) == B_OK );
2196 					int cmp = 0;
2197 					if (ref > ref2)
2198 						cmp = 1;
2199 					else if (ref2 > ref)
2200 						cmp = -1;
2201 					CPPUNIT_ASSERT(  (ref == ref2) == (cmp == 0) );
2202 					CPPUNIT_ASSERT(  (ref2 == ref) == (cmp == 0) );
2203 					CPPUNIT_ASSERT(  (ref != ref2) == (cmp != 0) );
2204 					CPPUNIT_ASSERT(  (ref2 != ref) == (cmp != 0) );
2205 					CPPUNIT_ASSERT(  (ref < ref2) == (cmp < 0) );
2206 					CPPUNIT_ASSERT(  (ref2 < ref) == (cmp > 0) );
2207 				}
2208 			}
2209 		}
2210 	}
2211 	// root dir
2212 	NextSubTest();
2213 	entry_ref ref, ref2;
2214 	CPPUNIT_ASSERT( get_ref_for_path("/", &ref) == B_OK );
2215 	CPPUNIT_ASSERT( get_entry_ref_for_entry("/", ".", &ref2) == B_OK );
2216 	CPPUNIT_ASSERT( ref.device == ref2.device );
2217 	CPPUNIT_ASSERT( ref.directory == ref2.directory );
2218 	CPPUNIT_ASSERT( strcmp(ref.name, ref2.name) == 0 );
2219 	CPPUNIT_ASSERT(  ref == ref2 );
2220 	// fs root dir
2221 	NextSubTest();
2222 	CPPUNIT_ASSERT( get_ref_for_path("/boot", &ref) == B_OK );
2223 	CPPUNIT_ASSERT( get_entry_ref_for_entry("/", "boot", &ref2) == B_OK );
2224 	CPPUNIT_ASSERT( ref.device == ref2.device );
2225 	CPPUNIT_ASSERT( ref.directory == ref2.directory );
2226 	CPPUNIT_ASSERT( strcmp(ref.name, ref2.name) == 0 );
2227 	CPPUNIT_ASSERT(  ref == ref2 );
2228 	// uninitialized
2229 	NextSubTest();
2230 	ref = entry_ref();
2231 	ref2 = entry_ref();
2232 	CPPUNIT_ASSERT(  ref == ref2 );
2233 	CPPUNIT_ASSERT(  !(ref != ref2) );
2234 	CPPUNIT_ASSERT(  !(ref < ref2) );
2235 	CPPUNIT_ASSERT(  !(ref2 < ref) );
2236 	CPPUNIT_ASSERT( get_entry_ref_for_entry("/", ".", &ref2) == B_OK );
2237 	CPPUNIT_ASSERT(  !(ref == ref2) );
2238 	CPPUNIT_ASSERT(  ref != ref2 );
2239 	CPPUNIT_ASSERT(  ref < ref2 );
2240 	CPPUNIT_ASSERT(  !(ref2 < ref) );
2241 }
2242 
2243 
2244 // isHarmlessPathname
2245 bool
2246 isHarmlessPathname(const char *path)
2247 {
2248 	bool result = false;
2249 	if (path) {
2250 		const char *harmlessDir = "/tmp/";
2251 		result = (string(path).find(harmlessDir) == 0);
2252 	}
2253 if (!result)
2254 printf("WARNING: `%s' is not a harmless pathname.\n", path);
2255 	return result;
2256 }
2257 
2258 // CreateLink
2259 void
2260 EntryTest::CreateLink(const char *link, const char *target)
2261 {
2262 	if (link && target && isHarmlessPathname(link)) {
2263 		execCommand(string("rm -rf ") + link
2264 					+ " ; ln -s " + target + " " + link);
2265 	}
2266 }
2267 
2268 // CreateFile
2269 void
2270 EntryTest::CreateFile(const char *file)
2271 {
2272 	if (file && isHarmlessPathname(file))
2273 		execCommand(string("rm -rf ") + file + " ; touch " + file);
2274 }
2275 
2276 // CreateDir
2277 void
2278 EntryTest::CreateDir(const char *dir)
2279 {
2280 	if (dir  && isHarmlessPathname(dir))
2281 		execCommand(string("rm -rf ") + dir + " ; mkdir " + dir);
2282 }
2283 
2284 // RemoveFile
2285 void
2286 EntryTest::RemoveFile(const char *file)
2287 {
2288 	if (file && isHarmlessPathname(file))
2289 		execCommand(string("rm -rf ") + file);
2290 }
2291 
2292 // PingFile
2293 bool
2294 EntryTest::PingFile(const char *path, BEntry *entry)
2295 {
2296 	bool result = false;
2297 	// check existence and type
2298 	struct stat st;
2299 	if (lstat(path, &st) == 0)
2300 		result = (S_ISREG(st.st_mode));
2301 	// check entry
2302 	if (result && entry) {
2303 		BPath entryPath;
2304 		result = (entry->GetPath(&entryPath) == B_OK && entryPath == path);
2305 	}
2306 	return result;
2307 }
2308 
2309 // PingDir
2310 bool
2311 EntryTest::PingDir(const char *path, BEntry *entry)
2312 {
2313 	bool result = false;
2314 	// check existence and type
2315 	struct stat st;
2316 	if (lstat(path, &st) == 0)
2317 		result = (S_ISDIR(st.st_mode));
2318 	// check entry
2319 	if (result && entry) {
2320 		BPath entryPath;
2321 		result = (entry->GetPath(&entryPath) == B_OK && entryPath == path);
2322 	}
2323 	return result;
2324 }
2325 
2326 // PingLink
2327 bool
2328 EntryTest::PingLink(const char *path, const char *target, BEntry *entry)
2329 {
2330 	bool result = false;
2331 	// check existence and type
2332 	struct stat st;
2333 	if (lstat(path, &st) == 0)
2334 		result = (S_ISLNK(st.st_mode));
2335 	// check target
2336 	if (result && target) {
2337 		char linkTarget[B_PATH_NAME_LENGTH + 1];
2338 		ssize_t size = readlink(path, linkTarget, B_PATH_NAME_LENGTH);
2339 		result = (size >= 0);
2340 		if (result) {
2341 			linkTarget[size] = 0;
2342 			result = (string(linkTarget) == target);
2343 		}
2344 	}
2345 	// check entry
2346 	if (result && entry) {
2347 		BPath entryPath;
2348 		result = (entry->GetPath(&entryPath) == B_OK && entryPath == path);
2349 	}
2350 	return result;
2351 }
2352 
2353 // MiscTest
2354 void
2355 EntryTest::MiscTest()
2356 {
2357 	BNode node(file1.cpath);
2358 	BEntry entry(file1.cpath);
2359 
2360 	CPPUNIT_ASSERT(node.Lock() == B_OK);
2361 	CPPUNIT_ASSERT( entry.Exists() );
2362 }
2363 
2364 
2365 
2366 // directory name for too long path name (70 characters)
2367 static const char *tooLongDirname =
2368 	"1234567890123456789012345678901234567890123456789012345678901234567890";
2369 
2370 // too long entry name (257 characters)
2371 static const char *tooLongEntryname =
2372 	"1234567890123456789012345678901234567890123456789012345678901234567890"
2373 	"1234567890123456789012345678901234567890123456789012345678901234567890"
2374 	"1234567890123456789012345678901234567890123456789012345678901234567890"
2375 	"12345678901234567890123456789012345678901234567";
2376 
2377 
2378 static void
2379 init_entry_test()
2380 {
2381 	// root dir for testing
2382 	testDir.initDir(badTestEntry, "testDir");
2383 	testDir.initPath((string("/tmp/") + testDir.name).c_str());
2384 	allTestEntries.pop_back();
2385 	// other entries
2386 	dir1.initDir(testDir, "dir1");
2387 	dir2.initDir(testDir, "dir2");
2388 	file1.initFile(dir1, "file1");
2389 	file2.init(dir1, "file2", ABSTRACT_ENTRY);
2390 	file3.init(dir2, "file3", ABSTRACT_ENTRY);
2391 	file4.init(dir1, "file4", ABSTRACT_ENTRY);
2392 	subDir1.initDir(dir1, "subDir1");
2393 	abstractEntry1.init(dir1, "abstractEntry1", ABSTRACT_ENTRY);
2394 	badEntry1.init(abstractEntry1, "badEntry1", BAD_ENTRY);
2395 	absDirLink1.initALink(dir1, "absDirLink1", subDir1);
2396 	absDirLink2.initALink(dir1, "absDirLink2", absDirLink1);
2397 	absDirLink3.initALink(dir2, "absDirLink3", absDirLink2);
2398 	absDirLink4.initALink(testDir, "absDirLink4", absDirLink3);
2399 	relDirLink1.initRLink(dir1, "relDirLink1", subDir1);
2400 	relDirLink2.initRLink(dir1, "relDirLink2", relDirLink1);
2401 	relDirLink3.initRLink(dir2, "relDirLink3", relDirLink2);
2402 	relDirLink4.initRLink(testDir, "relDirLink4", relDirLink3);
2403 	absFileLink1.initALink(dir1, "absFileLink1", file1);
2404 	absFileLink2.initALink(dir1, "absFileLink2", absFileLink1);
2405 	absFileLink3.initALink(dir2, "absFileLink3", absFileLink2);
2406 	absFileLink4.initALink(testDir, "absFileLink4", absFileLink3);
2407 	relFileLink1.initRLink(dir1, "relFileLink1", file1);
2408 	relFileLink2.initRLink(dir1, "relFileLink2", relFileLink1);
2409 	relFileLink3.initRLink(dir2, "relFileLink3", relFileLink2);
2410 	relFileLink4.initRLink(testDir, "relFileLink4", relFileLink3);
2411 	absCyclicLink1.initALink(dir1, "absCyclicLink1", absCyclicLink2);
2412 	absCyclicLink2.initALink(dir1, "absCyclicLink2", absCyclicLink1);
2413 	relCyclicLink1.initRLink(dir1, "relCyclicLink1", relCyclicLink2);
2414 	relCyclicLink2.initRLink(dir1, "relCyclicLink2", relCyclicLink1);
2415 	absBadLink1.initALink(dir1, "absBadLink1", abstractEntry1);
2416 	absBadLink2.initALink(dir1, "absBadLink2", absBadLink1);
2417 	absBadLink3.initALink(dir2, "absBadLink3", absBadLink2);
2418 	absBadLink4.initALink(testDir, "absBadLink4", absBadLink3);
2419 	relBadLink1.initRLink(dir1, "relBadLink1", abstractEntry1);
2420 	relBadLink2.initRLink(dir1, "relBadLink2", relBadLink1);
2421 	relBadLink3.initRLink(dir2, "relBadLink3", relBadLink2);
2422 	relBadLink4.initRLink(testDir, "relBadLink4", relBadLink3);
2423 	absVeryBadLink1.initALink(dir1, "absVeryBadLink1", badEntry1);
2424 	absVeryBadLink2.initALink(dir1, "absVeryBadLink2", absVeryBadLink1);
2425 	absVeryBadLink3.initALink(dir2, "absVeryBadLink3", absVeryBadLink2);
2426 	absVeryBadLink4.initALink(testDir, "absVeryBadLink4", absVeryBadLink3);
2427 	relVeryBadLink1.initRLink(dir1, "relVeryBadLink1", badEntry1);
2428 	relVeryBadLink2.initRLink(dir1, "relVeryBadLink2", relVeryBadLink1);
2429 	relVeryBadLink3.initRLink(dir2, "relVeryBadLink3", relVeryBadLink2);
2430 	relVeryBadLink4.initRLink(testDir, "relVeryBadLink4", relVeryBadLink3);
2431 	tooLongEntry1.init(testDir, tooLongEntryname, ABSTRACT_ENTRY);
2432 	tooLongDir1.initDir(testDir, tooLongDirname);
2433 	tooLongDir2.initDir(tooLongDir1, tooLongDirname);
2434 	tooLongDir3.initDir(tooLongDir2, tooLongDirname);
2435 	tooLongDir4.initDir(tooLongDir3, tooLongDirname);
2436 	tooLongDir5.initDir(tooLongDir4, tooLongDirname);
2437 	tooLongDir6.initDir(tooLongDir5, tooLongDirname);
2438 	tooLongDir7.initDir(tooLongDir6, tooLongDirname);
2439 	tooLongDir8.initDir(tooLongDir7, tooLongDirname);
2440 	tooLongDir9.initDir(tooLongDir8, tooLongDirname);
2441 	tooLongDir10.initDir(tooLongDir9, tooLongDirname);
2442 	tooLongDir11.initDir(tooLongDir10, tooLongDirname);
2443 	tooLongDir12.initDir(tooLongDir11, tooLongDirname);
2444 	tooLongDir13.initDir(tooLongDir12, tooLongDirname);
2445 	tooLongDir14.initDir(tooLongDir13, tooLongDirname);
2446 	tooLongDir15.initDir(tooLongDir14, tooLongDirname);
2447 	tooLongDir16.initDir(tooLongDir15, tooLongDirname);
2448 
2449 	// init paths
2450 	for (list<TestEntry*>::iterator it = allTestEntries.begin();
2451 		 it != allTestEntries.end(); it++) {
2452 		(*it)->initPath();
2453 	}
2454 	// complete initialization
2455 	testDir.completeInit();
2456 	for (list<TestEntry*>::iterator it = allTestEntries.begin();
2457 		 it != allTestEntries.end(); it++) {
2458 		(*it)->completeInit();
2459 	}
2460 	// create the set up command line
2461 	setUpCommandLine = string("mkdir ") + testDir.path;
2462 	for (list<TestEntry*>::iterator it = allTestEntries.begin();
2463 		 it != allTestEntries.end(); it++) {
2464 		TestEntry *entry = *it;
2465 		string command;
2466 		switch (entry->kind) {
2467 			case ABSTRACT_ENTRY:
2468 				break;
2469 			case DIR_ENTRY:
2470 			{
2471 				if (entry->path.length() < B_PATH_NAME_LENGTH) {
2472 					command = string("mkdir ") + entry->path;
2473 				} else {
2474 					command = string("( ")
2475 						+ "cd " + entry->super->super->path + " ; "
2476 						+ " mkdir " + entry->super->name + "/" + entry->name
2477 						+ " )";
2478 				}
2479 				break;
2480 			}
2481 			case FILE_ENTRY:
2482 			{
2483 				command = string("touch ") + entry->path;
2484 				break;
2485 			}
2486 			case LINK_ENTRY:
2487 			{
2488 				command = string("ln -s ") + entry->link + " " + entry->path;
2489 				break;
2490 			}
2491 			default:
2492 				break;
2493 		}
2494 		if (command.length() > 0) {
2495 			if (setUpCommandLine.length() == 0)
2496 				setUpCommandLine = command;
2497 			else
2498 				setUpCommandLine += string(" ; ") + command;
2499 		}
2500 	}
2501 	// create the tear down command line
2502 	tearDownCommandLine = string("rm -rf ") + testDir.path;
2503 }
2504 
2505 struct InitEntryTest {
2506 	InitEntryTest()
2507 	{
2508 		init_entry_test();
2509 	}
2510 } _InitEntryTest;
2511 
2512 
2513 // TestEntry
2514 
2515 // constructor
2516 TestEntry::TestEntry()
2517 		 : super(&badTestEntry),
2518 		   name("badTestEntry"),
2519 		   kind(BAD_ENTRY),
2520 		   path("/tmp/badTestEntry"),
2521 		   target(&badTestEntry),
2522 		   link(),
2523 		   ref(),
2524 		   relative(true),
2525 		   cname(""),
2526 		   cpath(""),
2527 		   clink("")
2528 {
2529 }
2530 
2531 // init
2532 void
2533 TestEntry::init(TestEntry &super, string name, test_entry_kind kind,
2534 				bool relative)
2535 {
2536 	this->super		= &super;
2537 	this->name		= name;
2538 	this->kind		= kind;
2539 	this->relative	= relative;
2540 	allTestEntries.push_back(this);
2541 }
2542 
2543 // initDir
2544 void
2545 TestEntry::initDir(TestEntry &super, string name)
2546 {
2547 	init(super, name, DIR_ENTRY);
2548 }
2549 
2550 // initFile
2551 void
2552 TestEntry::initFile(TestEntry &super, string name)
2553 {
2554 	init(super, name, FILE_ENTRY);
2555 }
2556 
2557 // initRLink
2558 void
2559 TestEntry::initRLink(TestEntry &super, string name, TestEntry &target)
2560 {
2561 	init(super, name, LINK_ENTRY, true);
2562 	this->target = &target;
2563 }
2564 
2565 // initALink
2566 void
2567 TestEntry::initALink(TestEntry &super, string name, TestEntry &target)
2568 {
2569 	init(super, name, LINK_ENTRY, false);
2570 	this->target = &target;
2571 }
2572 
2573 // initPath
2574 void
2575 TestEntry::initPath(const char *pathName)
2576 {
2577 	if (pathName)
2578 		path = pathName;
2579 	else
2580 		path = super->path + "/" + name;
2581 }
2582 
2583 // completeInit
2584 void
2585 TestEntry::completeInit()
2586 {
2587 	// init link
2588 	if (kind == LINK_ENTRY) {
2589 		if (relative)
2590 			link = get_shortest_relative_path(super, target);
2591 		else
2592 			link = target->path;
2593 	}
2594 	// init the C strings
2595 	cname = name.c_str();
2596 	cpath = path.c_str();
2597 	clink = link.c_str();
2598 }
2599 
2600 // get_ref
2601 const entry_ref &
2602 TestEntry::get_ref()
2603 {
2604 	if (isConcrete() || isAbstract())
2605 		get_entry_ref_for_entry(super->cpath, cname, &ref);
2606 	return ref;
2607 }
2608 
2609 // get_shortest_relative_path
2610 static
2611 string
2612 get_shortest_relative_path(TestEntry *dir, TestEntry *entry)
2613 {
2614 	string relPath;
2615 	// put all super directories (including dir itself) of the dir in a set
2616 	map<TestEntry*, int> superDirs;
2617 	int dirSuperLevel = 0;
2618 	for (TestEntry *superDir = dir;
2619 		 superDir != &badTestEntry;
2620 		 superDir = superDir->super, dirSuperLevel++) {
2621 		superDirs[superDir] = dirSuperLevel;
2622 	}
2623 	// find the first super dir that dir and entry have in common
2624 	TestEntry *commonSuperDir = &badTestEntry;
2625 	int targetSuperLevel = 0;
2626 	for (TestEntry *superDir = entry;
2627 		 commonSuperDir == &badTestEntry
2628 		 && superDir != &badTestEntry;
2629 		 superDir = superDir->super, targetSuperLevel++) {
2630 		if (superDirs.find(superDir) != superDirs.end())
2631 			commonSuperDir = superDir;
2632 	}
2633 	// construct the relative path
2634 	if (commonSuperDir != &badTestEntry) {
2635 		dirSuperLevel = superDirs[commonSuperDir];
2636 		if (dirSuperLevel == 0 && targetSuperLevel == 0) {
2637 			// entry == dir
2638 			relPath == ".";
2639 		} else {
2640 			// levels down
2641 			for (TestEntry *superDir = entry;
2642 				 superDir != commonSuperDir;
2643 				 superDir = superDir->super) {
2644 				if (relPath.length() == 0)
2645 					relPath = superDir->name;
2646 				else
2647 					relPath = superDir->name + "/" + relPath;
2648 			}
2649 			// levels up
2650 			for (int i = dirSuperLevel; i > 0; i--) {
2651 				if (relPath.length() == 0)
2652 					relPath = "..";
2653 				else
2654 					relPath = string("../") + relPath;
2655 			}
2656 		}
2657 	}
2658 	return relPath;
2659 }
2660 
2661 // resolve_link
2662 static
2663 TestEntry *
2664 resolve_link(TestEntry *entry)
2665 {
2666 	set<TestEntry*> followedLinks;
2667 	while (entry != &badTestEntry && entry->kind == LINK_ENTRY) {
2668 		if (followedLinks.find(entry) == followedLinks.end()) {
2669 			followedLinks.insert(entry);
2670 			entry = entry->target;
2671 		} else
2672 			entry = &badTestEntry;	// cyclic link
2673 	}
2674 	return entry;
2675 }
2676 
2677 
2678 
2679 
2680