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