1// SymLinkTest.cpp
2
3#include <stdio.h>
4#include <string.h>
5
6#include <string>
7using std::string;
8
9#include <Directory.h>
10#include <Entry.h>
11#include <Path.h>
12#include <SymLink.h>
13
14#include "SymLinkTest.h"
15
16// Suite
17SymLinkTest::Test*
18SymLinkTest::Suite()
19{
20	CppUnit::TestSuite *suite = new CppUnit::TestSuite();
21	typedef CppUnit::TestCaller<SymLinkTest> TC;
22
23	NodeTest::AddBaseClassTests<SymLinkTest>("BSymLink::", suite);
24
25	suite->addTest( new TC("BSymLink::Init Test 1", &SymLinkTest::InitTest1) );
26	suite->addTest( new TC("BSymLink::Init Test 2", &SymLinkTest::InitTest2) );
27	suite->addTest( new TC("BSymLink::ReadLink Test",
28						   &SymLinkTest::ReadLinkTest) );
29	suite->addTest( new TC("BSymLink::MakeLinkedPath Test",
30						   &SymLinkTest::MakeLinkedPathTest) );
31	suite->addTest( new TC("BSymLink::IsAbsolute Test",
32						   &SymLinkTest::IsAbsoluteTest) );
33	suite->addTest( new TC("BSymLink::Assignment Test",
34						   &SymLinkTest::AssignmentTest) );
35
36	return suite;
37}
38
39// CreateRONodes
40void
41SymLinkTest::CreateRONodes(TestNodes& testEntries)
42{
43	testEntries.clear();
44	const char *filename;
45	filename = "/tmp";
46	testEntries.add(new BSymLink(filename), filename);
47	filename = dirLinkname;
48	testEntries.add(new BSymLink(filename), filename);
49	filename = fileLinkname;
50	testEntries.add(new BSymLink(filename), filename);
51	filename = badLinkname;
52	testEntries.add(new BSymLink(filename), filename);
53	filename = cyclicLinkname1;
54	testEntries.add(new BSymLink(filename), filename);
55}
56
57// CreateRWNodes
58void
59SymLinkTest::CreateRWNodes(TestNodes& testEntries)
60{
61	testEntries.clear();
62	const char *filename;
63	filename = dirLinkname;
64	testEntries.add(new BSymLink(filename), filename);
65	filename = fileLinkname;
66	testEntries.add(new BSymLink(filename), filename);
67}
68
69// CreateUninitializedNodes
70void
71SymLinkTest::CreateUninitializedNodes(TestNodes& testEntries)
72{
73	testEntries.clear();
74	testEntries.add(new BSymLink, "");
75}
76
77// setUp
78void SymLinkTest::setUp()
79{
80	NodeTest::setUp();
81}
82
83// tearDown
84void SymLinkTest::tearDown()
85{
86	NodeTest::tearDown();
87}
88
89// InitTest1
90void
91SymLinkTest::InitTest1()
92{
93	const char *dirLink = dirLinkname;
94	const char *dirSuperLink = dirSuperLinkname;
95	const char *dirRelLink = dirRelLinkname;
96	const char *fileLink = fileLinkname;
97	const char *existingDir = existingDirname;
98	const char *existingSuperDir = existingSuperDirname;
99	const char *existingRelDir = existingRelDirname;
100	const char *existingFile = existingFilename;
101	const char *existingSuperFile = existingSuperFilename;
102	const char *existingRelFile = existingRelFilename;
103	const char *nonExisting = nonExistingDirname;
104	const char *nonExistingSuper = nonExistingSuperDirname;
105	const char *nonExistingRel = nonExistingRelDirname;
106	// 1. default constructor
107	NextSubTest();
108	{
109		BSymLink link;
110		CPPUNIT_ASSERT( link.InitCheck() == B_NO_INIT );
111	}
112
113	// 2. BSymLink(const char*)
114	NextSubTest();
115	{
116		BSymLink link(fileLink);
117		CPPUNIT_ASSERT( link.InitCheck() == B_OK );
118	}
119	NextSubTest();
120	{
121		BSymLink link(nonExisting);
122		CPPUNIT_ASSERT( link.InitCheck() == B_ENTRY_NOT_FOUND );
123	}
124	NextSubTest();
125	{
126		BSymLink link((const char *)NULL);
127		CPPUNIT_ASSERT( equals(link.InitCheck(), B_BAD_VALUE, B_NO_INIT) );
128	}
129	NextSubTest();
130	{
131		BSymLink link("");
132		CPPUNIT_ASSERT( link.InitCheck() == B_ENTRY_NOT_FOUND );
133	}
134	NextSubTest();
135	{
136		BSymLink link(existingFile);
137		CPPUNIT_ASSERT( link.InitCheck() == B_OK );
138	}
139	NextSubTest();
140	{
141		BSymLink link(existingDir);
142		CPPUNIT_ASSERT( link.InitCheck() == B_OK );
143	}
144	NextSubTest();
145	{
146		BSymLink link(tooLongEntryname);
147		CPPUNIT_ASSERT( link.InitCheck() == B_NAME_TOO_LONG );
148	}
149
150	// 3. BSymLink(const BEntry*)
151	NextSubTest();
152	{
153		BEntry entry(dirLink);
154		CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
155		BSymLink link(&entry);
156		CPPUNIT_ASSERT( link.InitCheck() == B_OK );
157	}
158	NextSubTest();
159	{
160		BEntry entry(nonExisting);
161		CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
162		BSymLink link(&entry);
163		CPPUNIT_ASSERT( link.InitCheck() == B_ENTRY_NOT_FOUND );
164	}
165	NextSubTest();
166	{
167		BSymLink link((BEntry *)NULL);
168		CPPUNIT_ASSERT( link.InitCheck() == B_BAD_VALUE );
169	}
170	NextSubTest();
171	{
172		BEntry entry;
173		BSymLink link(&entry);
174		CPPUNIT_ASSERT( equals(link.InitCheck(), B_BAD_ADDRESS, B_BAD_VALUE) );
175	}
176	NextSubTest();
177	{
178		BEntry entry(existingFile);
179		CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
180		BSymLink link(&entry);
181		CPPUNIT_ASSERT( link.InitCheck() == B_OK );
182
183	}
184	NextSubTest();
185	{
186		BEntry entry(existingDir);
187		CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
188		BSymLink link(&entry);
189		CPPUNIT_ASSERT( link.InitCheck() == B_OK );
190
191	}
192	NextSubTest();
193	{
194		BEntry entry(tooLongEntryname);
195		// R5 returns E2BIG instead of B_NAME_TOO_LONG
196		CPPUNIT_ASSERT( equals(entry.InitCheck(), E2BIG, B_NAME_TOO_LONG) );
197		BSymLink link(&entry);
198		CPPUNIT_ASSERT( equals(link.InitCheck(), B_BAD_ADDRESS, B_BAD_VALUE) );
199	}
200
201	// 4. BSymLink(const entry_ref*)
202	NextSubTest();
203	{
204		BEntry entry(dirLink);
205		CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
206		entry_ref ref;
207		CPPUNIT_ASSERT( entry.GetRef(&ref) == B_OK );
208		BSymLink link(&ref);
209		CPPUNIT_ASSERT( link.InitCheck() == B_OK );
210	}
211	NextSubTest();
212	{
213		BEntry entry(nonExisting);
214		CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
215		entry_ref ref;
216		CPPUNIT_ASSERT( entry.GetRef(&ref) == B_OK );
217		BSymLink link(&ref);
218		CPPUNIT_ASSERT( link.InitCheck() == B_ENTRY_NOT_FOUND );
219	}
220	NextSubTest();
221	{
222		BSymLink link((entry_ref *)NULL);
223		CPPUNIT_ASSERT( link.InitCheck() == B_BAD_VALUE );
224	}
225	NextSubTest();
226	{
227		BEntry entry(existingFile);
228		CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
229		entry_ref ref;
230		CPPUNIT_ASSERT( entry.GetRef(&ref) == B_OK );
231		BSymLink link(&ref);
232		CPPUNIT_ASSERT( link.InitCheck() == B_OK );
233	}
234	NextSubTest();
235	{
236		BEntry entry(existingDir);
237		CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
238		entry_ref ref;
239		CPPUNIT_ASSERT( entry.GetRef(&ref) == B_OK );
240		BSymLink link(&ref);
241		CPPUNIT_ASSERT( link.InitCheck() == B_OK );
242	}
243
244	// 5. BSymLink(const BDirectory*, const char*)
245	NextSubTest();
246	{
247		BDirectory pathDir(dirSuperLink);
248		CPPUNIT_ASSERT( pathDir.InitCheck() == B_OK );
249		BSymLink link(&pathDir, dirRelLink);
250		CPPUNIT_ASSERT( link.InitCheck() == B_OK );
251	}
252	NextSubTest();
253	{
254		BDirectory pathDir(dirSuperLink);
255		CPPUNIT_ASSERT( pathDir.InitCheck() == B_OK );
256		BSymLink link(&pathDir, dirLink);
257		CPPUNIT_ASSERT( link.InitCheck() == B_BAD_VALUE );
258	}
259	NextSubTest();
260	{
261		BDirectory pathDir(nonExistingSuper);
262		CPPUNIT_ASSERT( pathDir.InitCheck() == B_OK );
263		BSymLink link(&pathDir, nonExistingRel);
264		CPPUNIT_ASSERT( link.InitCheck() == B_ENTRY_NOT_FOUND );
265	}
266	NextSubTest();
267	{
268		BSymLink link((BDirectory *)NULL, (const char *)NULL);
269		CPPUNIT_ASSERT( link.InitCheck() == B_BAD_VALUE );
270	}
271	NextSubTest();
272	{
273		BSymLink link((BDirectory *)NULL, dirLink);
274		CPPUNIT_ASSERT( link.InitCheck() == B_BAD_VALUE );
275	}
276	NextSubTest();
277	{
278		BDirectory pathDir(dirSuperLink);
279		CPPUNIT_ASSERT( pathDir.InitCheck() == B_OK );
280		BSymLink link(&pathDir, (const char *)NULL);
281		CPPUNIT_ASSERT( link.InitCheck() == B_BAD_VALUE );
282	}
283	NextSubTest();
284	{
285		BDirectory pathDir(dirSuperLink);
286		CPPUNIT_ASSERT( pathDir.InitCheck() == B_OK );
287		BSymLink link(&pathDir, "");
288		CPPUNIT_ASSERT(link.InitCheck() == B_ENTRY_NOT_FOUND);
289	}
290	NextSubTest();
291	{
292		BDirectory pathDir(existingSuperFile);
293		CPPUNIT_ASSERT( pathDir.InitCheck() == B_OK );
294		BSymLink link(&pathDir, existingRelFile);
295		CPPUNIT_ASSERT( link.InitCheck() == B_OK );
296	}
297	NextSubTest();
298	{
299		BDirectory pathDir(existingSuperDir);
300		CPPUNIT_ASSERT( pathDir.InitCheck() == B_OK );
301		BSymLink link(&pathDir, existingRelDir);
302		CPPUNIT_ASSERT( link.InitCheck() == B_OK );
303	}
304	NextSubTest();
305	{
306		BDirectory pathDir(tooLongSuperEntryname);
307		CPPUNIT_ASSERT( pathDir.InitCheck() == B_OK );
308		BSymLink link(&pathDir, tooLongRelEntryname);
309		CPPUNIT_ASSERT( link.InitCheck() == B_NAME_TOO_LONG );
310	}
311	NextSubTest();
312	{
313		BDirectory pathDir(fileSuperDirname);
314		CPPUNIT_ASSERT( pathDir.InitCheck() == B_OK );
315		BSymLink link(&pathDir, fileRelDirname);
316		CPPUNIT_ASSERT( link.InitCheck() == B_ENTRY_NOT_FOUND );
317	}
318}
319
320// InitTest2
321void
322SymLinkTest::InitTest2()
323{
324	const char *dirLink = dirLinkname;
325	const char *dirSuperLink = dirSuperLinkname;
326	const char *dirRelLink = dirRelLinkname;
327	const char *fileLink = fileLinkname;
328	const char *existingDir = existingDirname;
329	const char *existingSuperDir = existingSuperDirname;
330	const char *existingRelDir = existingRelDirname;
331	const char *existingFile = existingFilename;
332	const char *existingSuperFile = existingSuperFilename;
333	const char *existingRelFile = existingRelFilename;
334	const char *nonExisting = nonExistingDirname;
335	const char *nonExistingSuper = nonExistingSuperDirname;
336	const char *nonExistingRel = nonExistingRelDirname;
337	BSymLink link;
338	// 2. BSymLink(const char*)
339	NextSubTest();
340	CPPUNIT_ASSERT( link.SetTo(fileLink) == B_OK );
341	CPPUNIT_ASSERT( link.InitCheck() == B_OK );
342	//
343	NextSubTest();
344	CPPUNIT_ASSERT( link.SetTo(nonExisting) == B_ENTRY_NOT_FOUND );
345	CPPUNIT_ASSERT( link.InitCheck() == B_ENTRY_NOT_FOUND );
346	//
347	NextSubTest();
348	CPPUNIT_ASSERT( equals(link.SetTo((const char *)NULL), B_BAD_VALUE,
349						   B_NO_INIT) );
350	CPPUNIT_ASSERT( equals(link.InitCheck(), B_BAD_VALUE, B_NO_INIT) );
351	//
352	NextSubTest();
353	CPPUNIT_ASSERT( link.SetTo("") == B_ENTRY_NOT_FOUND );
354	CPPUNIT_ASSERT( link.InitCheck() == B_ENTRY_NOT_FOUND );
355	//
356	NextSubTest();
357	CPPUNIT_ASSERT( link.SetTo(existingFile) == B_OK );
358	CPPUNIT_ASSERT( link.InitCheck() == B_OK );
359	//
360	NextSubTest();
361	CPPUNIT_ASSERT( link.SetTo(existingDir) == B_OK );
362	CPPUNIT_ASSERT( link.InitCheck() == B_OK );
363	//
364	NextSubTest();
365	CPPUNIT_ASSERT( link.SetTo(tooLongEntryname) == B_NAME_TOO_LONG );
366	CPPUNIT_ASSERT( link.InitCheck() == B_NAME_TOO_LONG );
367
368	// 3. BSymLink(const BEntry*)
369	NextSubTest();
370	BEntry entry(dirLink);
371	CPPUNIT_ASSERT( entry.InitCheck() == B_OK );
372	CPPUNIT_ASSERT( link.SetTo(&entry) == B_OK );
373	CPPUNIT_ASSERT( link.InitCheck() == B_OK );
374	//
375	NextSubTest();
376	CPPUNIT_ASSERT( entry.SetTo(nonExisting) == B_OK );
377	CPPUNIT_ASSERT( link.SetTo(&entry) == B_ENTRY_NOT_FOUND );
378	CPPUNIT_ASSERT( link.InitCheck() == B_ENTRY_NOT_FOUND );
379	//
380	NextSubTest();
381	CPPUNIT_ASSERT( link.SetTo((BEntry *)NULL) == B_BAD_VALUE );
382	CPPUNIT_ASSERT( link.InitCheck() == B_BAD_VALUE );
383	//
384	NextSubTest();
385	entry.Unset();
386	CPPUNIT_ASSERT( entry.InitCheck() == B_NO_INIT );
387	CPPUNIT_ASSERT( equals(link.SetTo(&entry), B_BAD_ADDRESS, B_BAD_VALUE) );
388	CPPUNIT_ASSERT( equals(link.InitCheck(), B_BAD_ADDRESS, B_BAD_VALUE) );
389	//
390	NextSubTest();
391	CPPUNIT_ASSERT( entry.SetTo(existingFile) == B_OK );
392	CPPUNIT_ASSERT( link.SetTo(&entry) == B_OK );
393	CPPUNIT_ASSERT( link.InitCheck() == B_OK );
394	//
395	NextSubTest();
396	CPPUNIT_ASSERT( entry.SetTo(existingDir) == B_OK );
397	CPPUNIT_ASSERT( link.SetTo(&entry) == B_OK );
398	CPPUNIT_ASSERT( link.InitCheck() == B_OK );
399	//
400	NextSubTest();
401	// R5 returns E2BIG instead of B_NAME_TOO_LONG
402	CPPUNIT_ASSERT( equals(entry.SetTo(tooLongEntryname), E2BIG,
403						   B_NAME_TOO_LONG) );
404	CPPUNIT_ASSERT( equals(link.SetTo(&entry), B_BAD_ADDRESS, B_BAD_VALUE) );
405	CPPUNIT_ASSERT( equals(link.InitCheck(), B_BAD_ADDRESS, B_BAD_VALUE) );
406
407	// 4. BSymLink(const entry_ref*)
408	NextSubTest();
409	CPPUNIT_ASSERT( entry.SetTo(dirLink) == B_OK );
410	entry_ref ref;
411	CPPUNIT_ASSERT( entry.GetRef(&ref) == B_OK );
412	CPPUNIT_ASSERT( link.SetTo(&ref) == B_OK );
413	CPPUNIT_ASSERT( link.InitCheck() == B_OK );
414	//
415	NextSubTest();
416	CPPUNIT_ASSERT( entry.SetTo(nonExisting) == B_OK );
417	CPPUNIT_ASSERT( entry.GetRef(&ref) == B_OK );
418	CPPUNIT_ASSERT( link.SetTo(&ref) == B_ENTRY_NOT_FOUND );
419	CPPUNIT_ASSERT( link.InitCheck() == B_ENTRY_NOT_FOUND );
420	//
421	NextSubTest();
422	CPPUNIT_ASSERT( link.SetTo((entry_ref *)NULL) == B_BAD_VALUE );
423	CPPUNIT_ASSERT( link.InitCheck() == B_BAD_VALUE );
424	//
425	NextSubTest();
426	CPPUNIT_ASSERT( entry.SetTo(existingFile) == B_OK );
427	CPPUNIT_ASSERT( entry.GetRef(&ref) == B_OK );
428	CPPUNIT_ASSERT( link.SetTo(&ref) == B_OK );
429	CPPUNIT_ASSERT( link.InitCheck() == B_OK );
430	//
431	NextSubTest();
432	CPPUNIT_ASSERT( entry.SetTo(existingDir) == B_OK );
433	CPPUNIT_ASSERT( entry.GetRef(&ref) == B_OK );
434	CPPUNIT_ASSERT( link.SetTo(&ref) == B_OK );
435	CPPUNIT_ASSERT( link.InitCheck() == B_OK );
436
437	// 5. BSymLink(const BDirectory*, const char*)
438	NextSubTest();
439	BDirectory pathDir(dirSuperLink);
440	CPPUNIT_ASSERT( pathDir.InitCheck() == B_OK );
441	CPPUNIT_ASSERT( link.SetTo(&pathDir, dirRelLink) == B_OK );
442	CPPUNIT_ASSERT( link.InitCheck() == B_OK );
443	//
444	NextSubTest();
445	CPPUNIT_ASSERT( pathDir.SetTo(dirSuperLink) == B_OK );
446	CPPUNIT_ASSERT( link.SetTo(&pathDir, dirLink) == B_BAD_VALUE );
447	CPPUNIT_ASSERT( link.InitCheck() == B_BAD_VALUE );
448	//
449	NextSubTest();
450	CPPUNIT_ASSERT( pathDir.SetTo(nonExistingSuper) == B_OK );
451	CPPUNIT_ASSERT( link.SetTo(&pathDir, nonExistingRel) == B_ENTRY_NOT_FOUND );
452	CPPUNIT_ASSERT( link.InitCheck() == B_ENTRY_NOT_FOUND );
453	//
454	NextSubTest();
455	CPPUNIT_ASSERT( link.SetTo((BDirectory *)NULL, (const char *)NULL)
456					== B_BAD_VALUE );
457	CPPUNIT_ASSERT( link.InitCheck() == B_BAD_VALUE );
458	//
459	NextSubTest();
460	CPPUNIT_ASSERT( link.SetTo((BDirectory *)NULL, dirLink) == B_BAD_VALUE );
461	CPPUNIT_ASSERT( link.InitCheck() == B_BAD_VALUE );
462	//
463	NextSubTest();
464	CPPUNIT_ASSERT( pathDir.SetTo(dirSuperLink) == B_OK );
465	CPPUNIT_ASSERT( link.SetTo(&pathDir, (const char *)NULL) == B_BAD_VALUE );
466	CPPUNIT_ASSERT( link.InitCheck() == B_BAD_VALUE );
467	//
468	NextSubTest();
469	CPPUNIT_ASSERT( pathDir.SetTo(dirSuperLink) == B_OK );
470	CPPUNIT_ASSERT(link.SetTo(&pathDir, "") == B_ENTRY_NOT_FOUND);
471	CPPUNIT_ASSERT(link.InitCheck() == B_ENTRY_NOT_FOUND);
472	//
473	NextSubTest();
474	CPPUNIT_ASSERT( pathDir.SetTo(existingSuperFile) == B_OK );
475	CPPUNIT_ASSERT( link.SetTo(&pathDir, existingRelFile) == B_OK );
476	CPPUNIT_ASSERT( link.InitCheck() == B_OK );
477	//
478	NextSubTest();
479	CPPUNIT_ASSERT( pathDir.SetTo(existingSuperDir) == B_OK );
480	CPPUNIT_ASSERT( link.SetTo(&pathDir, existingRelDir) == B_OK );
481	CPPUNIT_ASSERT( link.InitCheck() == B_OK );
482	//
483	NextSubTest();
484	CPPUNIT_ASSERT( pathDir.SetTo(tooLongSuperEntryname) == B_OK );
485	CPPUNIT_ASSERT( link.SetTo(&pathDir, tooLongRelEntryname)
486					== B_NAME_TOO_LONG );
487	CPPUNIT_ASSERT( link.InitCheck() == B_NAME_TOO_LONG );
488	//
489	NextSubTest();
490	CPPUNIT_ASSERT( pathDir.SetTo(fileSuperDirname) == B_OK );
491	CPPUNIT_ASSERT( link.SetTo(&pathDir, fileRelDirname) == B_ENTRY_NOT_FOUND );
492	CPPUNIT_ASSERT( link.InitCheck() == B_ENTRY_NOT_FOUND );
493}
494
495// ReadLinkTest
496void
497SymLinkTest::ReadLinkTest()
498{
499	const char *dirLink = dirLinkname;
500	const char *fileLink = fileLinkname;
501	const char *badLink = badLinkname;
502	const char *cyclicLink1 = cyclicLinkname1;
503	const char *cyclicLink2 = cyclicLinkname2;
504	const char *existingDir = existingDirname;
505	const char *existingFile = existingFilename;
506	const char *nonExisting = nonExistingDirname;
507	BSymLink link;
508	char buffer[B_PATH_NAME_LENGTH + 1];
509	// uninitialized
510	// R5: returns B_BAD_ADDRESS instead of (as doc'ed) B_FILE_ERROR
511	NextSubTest();
512	CPPUNIT_ASSERT( link.InitCheck() == B_NO_INIT );
513	CPPUNIT_ASSERT( equals(link.ReadLink(buffer, sizeof(buffer)),
514						   B_BAD_ADDRESS, B_FILE_ERROR) );
515	// existing dir link
516	NextSubTest();
517	CPPUNIT_ASSERT( link.SetTo(dirLink) == B_OK );
518	CPPUNIT_ASSERT( link.ReadLink(buffer, sizeof(buffer))
519					== (ssize_t)strlen(existingDir) );
520	CPPUNIT_ASSERT( strcmp(buffer, existingDir) == 0 );
521	// existing file link
522	NextSubTest();
523	CPPUNIT_ASSERT( link.SetTo(fileLink) == B_OK );
524	CPPUNIT_ASSERT( link.ReadLink(buffer, sizeof(buffer))
525					== (ssize_t)strlen(existingFile) );
526	CPPUNIT_ASSERT( strcmp(buffer, existingFile) == 0 );
527	// existing cyclic link
528	NextSubTest();
529	CPPUNIT_ASSERT( link.SetTo(cyclicLink1) == B_OK );
530	CPPUNIT_ASSERT( link.ReadLink(buffer, sizeof(buffer))
531					== (ssize_t)strlen(cyclicLink2) );
532	CPPUNIT_ASSERT( strcmp(buffer, cyclicLink2) == 0 );
533	// existing link to non-existing entry
534	NextSubTest();
535	CPPUNIT_ASSERT( link.SetTo(badLink) == B_OK );
536	CPPUNIT_ASSERT( link.ReadLink(buffer, sizeof(buffer))
537					== (ssize_t)strlen(nonExisting) );
538	CPPUNIT_ASSERT( strcmp(buffer, nonExisting) == 0 );
539	// non-existing link
540	// R5: returns B_BAD_ADDRESS instead of (as doc'ed) B_FILE_ERROR
541	NextSubTest();
542	CPPUNIT_ASSERT( link.SetTo(nonExisting) == B_ENTRY_NOT_FOUND );
543	CPPUNIT_ASSERT( equals(link.ReadLink(buffer, sizeof(buffer)),
544						   B_BAD_ADDRESS, B_FILE_ERROR) );
545	// dir
546	NextSubTest();
547	CPPUNIT_ASSERT( link.SetTo(existingDir) == B_OK );
548	CPPUNIT_ASSERT( link.ReadLink(buffer, sizeof(buffer)) == B_BAD_VALUE );
549	// file
550	NextSubTest();
551	CPPUNIT_ASSERT( link.SetTo(existingFile) == B_OK );
552	CPPUNIT_ASSERT( link.ReadLink(buffer, sizeof(buffer)) == B_BAD_VALUE );
553	// small buffer
554	// R5: returns the size of the contents, not the number of bytes copied
555	// Haiku: ... so do we
556	NextSubTest();
557	char smallBuffer[2];
558	CPPUNIT_ASSERT( link.SetTo(dirLink) == B_OK );
559	ssize_t linkLength = link.ReadLink(smallBuffer, sizeof(smallBuffer));
560	CPPUNIT_ASSERT(linkLength == static_cast<ssize_t>(strlen(existingDir)));
561	CPPUNIT_ASSERT_EQUAL('/', smallBuffer[0]);
562	CPPUNIT_ASSERT_EQUAL('\0', smallBuffer[1]);
563
564	// Invoke with one extra byte of length to ensure that the result is NULL
565	// terminated.
566	NextSubTest();
567	buffer[17] = 'x';
568	CPPUNIT_ASSERT(link.ReadLink(buffer, 18));
569	CPPUNIT_ASSERT_EQUAL('\0', buffer[17]);
570	CPPUNIT_ASSERT_EQUAL(strcmp(buffer, "/tmp/existing-dir"), 0);
571
572	// bad args
573	NextSubTest();
574	CPPUNIT_ASSERT( link.SetTo(fileLink) == B_OK );
575	CPPUNIT_ASSERT( equals(link.ReadLink(NULL, sizeof(buffer)), B_BAD_ADDRESS,
576						   B_BAD_VALUE) );
577}
578
579// MakeLinkedPathTest
580void
581SymLinkTest::MakeLinkedPathTest()
582{
583	const char *dirLink = dirLinkname;
584	const char *fileLink = fileLinkname;
585	const char *relDirLink = relDirLinkname;
586	const char *relFileLink = relFileLinkname;
587	const char *cyclicLink1 = cyclicLinkname1;
588	const char *cyclicLink2 = cyclicLinkname2;
589	const char *existingDir = existingDirname;
590	const char *existingSuperDir = existingSuperDirname;
591	const char *existingFile = existingFilename;
592	const char *existingSuperFile = existingSuperFilename;
593	const char *nonExisting = nonExistingDirname;
594	BSymLink link;
595	BPath path;
596	// 1. MakeLinkedPath(const char*, BPath*)
597	// uninitialized
598	NextSubTest();
599	CPPUNIT_ASSERT( link.InitCheck() == B_NO_INIT );
600	CPPUNIT_ASSERT( equals(link.MakeLinkedPath("/boot", &path), B_BAD_ADDRESS,
601						   B_FILE_ERROR) );
602	link.Unset();
603	path.Unset();
604	// existing absolute dir link
605	NextSubTest();
606	CPPUNIT_ASSERT( link.SetTo(dirLink) == B_OK );
607	CPPUNIT_ASSERT( link.MakeLinkedPath("/boot", &path)
608					== (ssize_t)strlen(existingDir) );
609	CPPUNIT_ASSERT( path.InitCheck() == B_OK );
610	CPPUNIT_ASSERT( string(existingDir) == path.Path() );
611	link.Unset();
612	path.Unset();
613	// existing absolute file link
614	NextSubTest();
615	CPPUNIT_ASSERT( link.SetTo(fileLink) == B_OK );
616	CPPUNIT_ASSERT( link.MakeLinkedPath("/boot", &path)
617					== (ssize_t)strlen(existingFile) );
618	CPPUNIT_ASSERT( path.InitCheck() == B_OK );
619	CPPUNIT_ASSERT( string(existingFile) == path.Path() );
620	link.Unset();
621	path.Unset();
622	// existing absolute cyclic link
623	NextSubTest();
624	CPPUNIT_ASSERT( link.SetTo(cyclicLink1) == B_OK );
625	CPPUNIT_ASSERT( link.MakeLinkedPath("/boot", &path)
626					== (ssize_t)strlen(cyclicLink2) );
627	CPPUNIT_ASSERT( path.InitCheck() == B_OK );
628	CPPUNIT_ASSERT( string(cyclicLink2) == path.Path() );
629	link.Unset();
630	path.Unset();
631	// existing relative dir link
632	NextSubTest();
633	BEntry entry;
634	BPath entryPath;
635	CPPUNIT_ASSERT( entry.SetTo(existingDir) == B_OK );
636	CPPUNIT_ASSERT( entry.GetPath(&entryPath) == B_OK );
637	CPPUNIT_ASSERT( link.SetTo(relDirLink) == B_OK );
638	CPPUNIT_ASSERT( link.MakeLinkedPath(existingSuperDir, &path)
639					== (ssize_t)strlen(entryPath.Path()) );
640	CPPUNIT_ASSERT( path.InitCheck() == B_OK );
641	CPPUNIT_ASSERT( entryPath == path );
642	link.Unset();
643	path.Unset();
644	entry.Unset();
645	entryPath.Unset();
646	// existing relative file link
647	NextSubTest();
648	CPPUNIT_ASSERT( entry.SetTo(existingFile) == B_OK );
649	CPPUNIT_ASSERT( entry.GetPath(&entryPath) == B_OK );
650	CPPUNIT_ASSERT( link.SetTo(relFileLink) == B_OK );
651	CPPUNIT_ASSERT( link.MakeLinkedPath(existingSuperFile, &path)
652					== (ssize_t)strlen(entryPath.Path()) );
653	CPPUNIT_ASSERT( path.InitCheck() == B_OK );
654	CPPUNIT_ASSERT( entryPath == path );
655	link.Unset();
656	path.Unset();
657	entry.Unset();
658	entryPath.Unset();
659	// bad args
660	NextSubTest();
661	CPPUNIT_ASSERT( link.SetTo(dirLink) == B_OK );
662// R5: crashs, when passing a NULL path
663#if !TEST_R5
664	CPPUNIT_ASSERT( link.MakeLinkedPath("/boot", NULL) == B_BAD_VALUE );
665#endif
666	CPPUNIT_ASSERT( link.MakeLinkedPath((const char*)NULL, &path)
667					== B_BAD_VALUE );
668// R5: crashs, when passing a NULL path
669#if !TEST_R5
670	CPPUNIT_ASSERT( link.MakeLinkedPath((const char*)NULL, NULL)
671					== B_BAD_VALUE );
672#endif
673	link.Unset();
674	path.Unset();
675
676	// 2. MakeLinkedPath(const BDirectory*, BPath*)
677	// uninitialized
678	NextSubTest();
679	link.Unset();
680	CPPUNIT_ASSERT( link.InitCheck() == B_NO_INIT );
681	BDirectory dir;
682	CPPUNIT_ASSERT( dir.SetTo("/boot") == B_OK);
683	CPPUNIT_ASSERT( equals(link.MakeLinkedPath(&dir, &path), B_BAD_ADDRESS,
684						   B_FILE_ERROR) );
685	link.Unset();
686	path.Unset();
687	dir.Unset();
688	// existing absolute dir link
689	NextSubTest();
690	CPPUNIT_ASSERT( link.SetTo(dirLink) == B_OK );
691	CPPUNIT_ASSERT( dir.SetTo("/boot") == B_OK);
692	CPPUNIT_ASSERT( link.MakeLinkedPath(&dir, &path)
693					== (ssize_t)strlen(existingDir) );
694	CPPUNIT_ASSERT( path.InitCheck() == B_OK );
695	CPPUNIT_ASSERT( string(existingDir) == path.Path() );
696	link.Unset();
697	path.Unset();
698	dir.Unset();
699	// existing absolute file link
700	NextSubTest();
701	CPPUNIT_ASSERT( link.SetTo(fileLink) == B_OK );
702	CPPUNIT_ASSERT( dir.SetTo("/boot") == B_OK);
703	CPPUNIT_ASSERT( link.MakeLinkedPath(&dir, &path)
704					== (ssize_t)strlen(existingFile) );
705	CPPUNIT_ASSERT( path.InitCheck() == B_OK );
706	CPPUNIT_ASSERT( string(existingFile) == path.Path() );
707	link.Unset();
708	path.Unset();
709	dir.Unset();
710	// existing absolute cyclic link
711	NextSubTest();
712	CPPUNIT_ASSERT( link.SetTo(cyclicLink1) == B_OK );
713	CPPUNIT_ASSERT( dir.SetTo("/boot") == B_OK);
714	CPPUNIT_ASSERT( link.MakeLinkedPath(&dir, &path)
715					== (ssize_t)strlen(cyclicLink2) );
716	CPPUNIT_ASSERT( path.InitCheck() == B_OK );
717	CPPUNIT_ASSERT( string(cyclicLink2) == path.Path() );
718	link.Unset();
719	path.Unset();
720	dir.Unset();
721	// existing relative dir link
722	NextSubTest();
723	CPPUNIT_ASSERT( entry.SetTo(existingDir) == B_OK );
724	CPPUNIT_ASSERT( entry.GetPath(&entryPath) == B_OK );
725	CPPUNIT_ASSERT( link.SetTo(relDirLink) == B_OK );
726	CPPUNIT_ASSERT( dir.SetTo(existingSuperDir) == B_OK);
727	CPPUNIT_ASSERT( link.MakeLinkedPath(&dir, &path)
728					== (ssize_t)strlen(entryPath.Path()) );
729	CPPUNIT_ASSERT( path.InitCheck() == B_OK );
730	CPPUNIT_ASSERT( entryPath == path );
731	link.Unset();
732	path.Unset();
733	dir.Unset();
734	entry.Unset();
735	entryPath.Unset();
736	// existing relative file link
737	NextSubTest();
738	CPPUNIT_ASSERT( entry.SetTo(existingFile) == B_OK );
739	CPPUNIT_ASSERT( entry.GetPath(&entryPath) == B_OK );
740	CPPUNIT_ASSERT( link.SetTo(relFileLink) == B_OK );
741	CPPUNIT_ASSERT( dir.SetTo(existingSuperFile) == B_OK);
742	CPPUNIT_ASSERT( link.MakeLinkedPath(&dir, &path)
743					== (ssize_t)strlen(entryPath.Path()) );
744	CPPUNIT_ASSERT( path.InitCheck() == B_OK );
745	CPPUNIT_ASSERT( entryPath == path );
746	link.Unset();
747	path.Unset();
748	dir.Unset();
749	entry.Unset();
750	entryPath.Unset();
751	// absolute link, uninitialized dir
752	NextSubTest();
753	CPPUNIT_ASSERT( link.SetTo(dirLink) == B_OK );
754	CPPUNIT_ASSERT( dir.InitCheck() == B_NO_INIT);
755	CPPUNIT_ASSERT( link.MakeLinkedPath(&dir, &path)
756					== (ssize_t)strlen(existingDir) );
757	CPPUNIT_ASSERT( path.InitCheck() == B_OK );
758	CPPUNIT_ASSERT( string(existingDir) == path.Path() );
759	// absolute link, badly initialized dir
760	NextSubTest();
761	CPPUNIT_ASSERT( link.SetTo(dirLink) == B_OK );
762	CPPUNIT_ASSERT( dir.SetTo(nonExisting) == B_ENTRY_NOT_FOUND);
763	CPPUNIT_ASSERT( link.MakeLinkedPath(&dir, &path)
764					== (ssize_t)strlen(existingDir) );
765	CPPUNIT_ASSERT( path.InitCheck() == B_OK );
766	CPPUNIT_ASSERT( string(existingDir) == path.Path() );
767	link.Unset();
768	path.Unset();
769	dir.Unset();
770	// relative link, uninitialized dir
771	NextSubTest();
772	CPPUNIT_ASSERT( link.SetTo(relDirLink) == B_OK );
773	CPPUNIT_ASSERT( dir.InitCheck() == B_NO_INIT);
774	CPPUNIT_ASSERT( equals(link.MakeLinkedPath(&dir, &path), B_NO_INIT,
775						   B_BAD_VALUE) );
776	link.Unset();
777	// relative link, badly initialized dir
778	NextSubTest();
779	CPPUNIT_ASSERT( link.SetTo(relDirLink) == B_OK );
780	CPPUNIT_ASSERT( dir.SetTo(nonExisting) == B_ENTRY_NOT_FOUND);
781	CPPUNIT_ASSERT( equals(link.MakeLinkedPath(&dir, &path), B_NO_INIT,
782						   B_BAD_VALUE) );
783	link.Unset();
784	path.Unset();
785	dir.Unset();
786	// bad args
787	NextSubTest();
788	CPPUNIT_ASSERT( link.SetTo(dirLink) == B_OK );
789	CPPUNIT_ASSERT( dir.SetTo("/boot") == B_OK);
790// R5: crashs, when passing a NULL path
791#if !TEST_R5
792	CPPUNIT_ASSERT( link.MakeLinkedPath(&dir, NULL) == B_BAD_VALUE );
793#endif
794
795	CPPUNIT_ASSERT( link.MakeLinkedPath((const BDirectory*)NULL, &path)
796					== B_BAD_VALUE );
797// R5: crashs, when passing a NULL path
798#if !TEST_R5
799	CPPUNIT_ASSERT( link.MakeLinkedPath((const BDirectory*)NULL, NULL)
800					== B_BAD_VALUE );
801#endif
802	link.Unset();
803	path.Unset();
804	dir.Unset();
805}
806
807// IsAbsoluteTest
808void
809SymLinkTest::IsAbsoluteTest()
810{
811	const char *dirLink = dirLinkname;
812	const char *relFileLink = relFileLinkname;
813	const char *existingDir = existingDirname;
814	const char *existingFile = existingFilename;
815	const char *nonExisting = nonExistingDirname;
816	BSymLink link;
817	// uninitialized
818	NextSubTest();
819	CPPUNIT_ASSERT( link.InitCheck() == B_NO_INIT );
820	CPPUNIT_ASSERT( link.IsAbsolute() == false );
821	link.Unset();
822	// existing absolute dir link
823	NextSubTest();
824	CPPUNIT_ASSERT( link.SetTo(dirLink) == B_OK );
825	CPPUNIT_ASSERT( link.IsAbsolute() == true );
826	link.Unset();
827	// existing relative file link
828	NextSubTest();
829	CPPUNIT_ASSERT( link.SetTo(relFileLink) == B_OK );
830	CPPUNIT_ASSERT( link.IsAbsolute() == false );
831	link.Unset();
832	// non-existing link
833	NextSubTest();
834	CPPUNIT_ASSERT( link.SetTo(nonExisting) == B_ENTRY_NOT_FOUND );
835	CPPUNIT_ASSERT( link.IsAbsolute() == false );
836	link.Unset();
837	// dir
838	NextSubTest();
839	CPPUNIT_ASSERT( link.SetTo(existingDir) == B_OK );
840	CPPUNIT_ASSERT( link.IsAbsolute() == false );
841	link.Unset();
842	// file
843	NextSubTest();
844	CPPUNIT_ASSERT( link.SetTo(existingFile) == B_OK );
845	CPPUNIT_ASSERT( link.IsAbsolute() == false );
846	link.Unset();
847}
848
849// AssignmentTest
850void
851SymLinkTest::AssignmentTest()
852{
853	const char *dirLink = dirLinkname;
854	const char *fileLink = fileLinkname;
855	// 1. copy constructor
856	// uninitialized
857	NextSubTest();
858	{
859		BSymLink link;
860		CPPUNIT_ASSERT( link.InitCheck() == B_NO_INIT );
861		BSymLink link2(link);
862		// R5 returns B_BAD_VALUE instead of B_NO_INIT
863		CPPUNIT_ASSERT( equals(link2.InitCheck(), B_BAD_VALUE, B_NO_INIT) );
864	}
865	// existing dir link
866	NextSubTest();
867	{
868		BSymLink link(dirLink);
869		CPPUNIT_ASSERT( link.InitCheck() == B_OK );
870		BSymLink link2(link);
871		CPPUNIT_ASSERT( link2.InitCheck() == B_OK );
872	}
873	// existing file link
874	NextSubTest();
875	{
876		BSymLink link(fileLink);
877		CPPUNIT_ASSERT( link.InitCheck() == B_OK );
878		BSymLink link2(link);
879		CPPUNIT_ASSERT( link2.InitCheck() == B_OK );
880	}
881
882	// 2. assignment operator
883	// uninitialized
884	NextSubTest();
885	{
886		BSymLink link;
887		BSymLink link2;
888		link2 = link;
889		// R5 returns B_BAD_VALUE instead of B_NO_INIT
890		CPPUNIT_ASSERT( equals(link2.InitCheck(), B_BAD_VALUE, B_NO_INIT) );
891	}
892	NextSubTest();
893	{
894		BSymLink link;
895		BSymLink link2(dirLink);
896		link2 = link;
897		// R5 returns B_BAD_VALUE instead of B_NO_INIT
898		CPPUNIT_ASSERT( equals(link2.InitCheck(), B_BAD_VALUE, B_NO_INIT) );
899	}
900	// existing dir link
901	NextSubTest();
902	{
903		BSymLink link(dirLink);
904		BSymLink link2;
905		link2 = link;
906		CPPUNIT_ASSERT( link2.InitCheck() == B_OK );
907	}
908	// existing file link
909	NextSubTest();
910	{
911		BSymLink link(fileLink);
912		BSymLink link2;
913		link2 = link;
914		CPPUNIT_ASSERT( link2.InitCheck() == B_OK );
915	}
916}
917
918