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