1// FindDirectoryTest.cpp
2
3#include <errno.h>
4#include <stdio.h>
5#include <string>
6#include <unistd.h>
7
8#include "FindDirectoryTest.h"
9
10#include <FindDirectory.h>
11#include <fs_info.h>
12#include <Entry.h>
13#include <Path.h>
14#include <Volume.h>
15
16
17
18const directory_which directories[] = {
19	B_DESKTOP_DIRECTORY,
20	B_TRASH_DIRECTORY,
21	// BeOS directories.  These are mostly accessed read-only.
22	B_BEOS_DIRECTORY,
23	B_BEOS_SYSTEM_DIRECTORY,
24	B_BEOS_ADDONS_DIRECTORY,
25	B_BEOS_BOOT_DIRECTORY,
26	B_BEOS_FONTS_DIRECTORY,
27	B_BEOS_LIB_DIRECTORY,
28 	B_BEOS_SERVERS_DIRECTORY,
29	B_BEOS_APPS_DIRECTORY,
30	B_BEOS_BIN_DIRECTORY,
31	B_BEOS_ETC_DIRECTORY,
32	B_BEOS_DOCUMENTATION_DIRECTORY,
33	B_BEOS_PREFERENCES_DIRECTORY,
34	B_BEOS_TRANSLATORS_DIRECTORY,
35	B_BEOS_MEDIA_NODES_DIRECTORY,
36	B_BEOS_SOUNDS_DIRECTORY,
37	// Common directories, shared among all users.
38	B_COMMON_DIRECTORY,
39	B_COMMON_SYSTEM_DIRECTORY,
40	B_COMMON_ADDONS_DIRECTORY,
41	B_COMMON_BOOT_DIRECTORY,
42	B_COMMON_FONTS_DIRECTORY,
43	B_COMMON_LIB_DIRECTORY,
44	B_COMMON_SERVERS_DIRECTORY,
45	B_COMMON_BIN_DIRECTORY,
46	B_COMMON_ETC_DIRECTORY,
47	B_COMMON_DOCUMENTATION_DIRECTORY,
48	B_COMMON_SETTINGS_DIRECTORY,
49	B_COMMON_DEVELOP_DIRECTORY,
50	B_COMMON_LOG_DIRECTORY,
51	B_COMMON_SPOOL_DIRECTORY,
52	B_COMMON_TEMP_DIRECTORY,
53	B_COMMON_VAR_DIRECTORY,
54	B_COMMON_TRANSLATORS_DIRECTORY,
55	B_COMMON_MEDIA_NODES_DIRECTORY,
56	B_COMMON_SOUNDS_DIRECTORY,
57	// User directories.  These are interpreted in the context
58	// of the user making the find_directory call.
59	B_USER_DIRECTORY,
60	B_USER_CONFIG_DIRECTORY,
61	B_USER_ADDONS_DIRECTORY,
62	B_USER_BOOT_DIRECTORY,
63	B_USER_FONTS_DIRECTORY,
64	B_USER_LIB_DIRECTORY,
65	B_USER_SETTINGS_DIRECTORY,
66	B_USER_DESKBAR_DIRECTORY,
67	B_USER_PRINTERS_DIRECTORY,
68	B_USER_TRANSLATORS_DIRECTORY,
69	B_USER_MEDIA_NODES_DIRECTORY,
70	B_USER_SOUNDS_DIRECTORY,
71	// Global directories.
72	B_APPS_DIRECTORY,
73	B_PREFERENCES_DIRECTORY,
74	B_UTILITIES_DIRECTORY
75};
76
77const int32 directoryCount = sizeof(directories) / sizeof(directory_which);
78
79const char *testFile		= "/tmp/testFile";
80const char *testMountPoint	= "/non-existing-mount-point";
81
82
83// Suite
84CppUnit::Test*
85FindDirectoryTest::Suite() {
86	CppUnit::TestSuite *suite = new CppUnit::TestSuite();
87	typedef CppUnit::TestCaller<FindDirectoryTest> TC;
88
89	suite->addTest( new TC("find_directory() Test",
90						   &FindDirectoryTest::Test) );
91
92	return suite;
93}
94
95// setUp
96void
97FindDirectoryTest::setUp()
98{
99	BasicTest::setUp();
100	createVolume(testFile, testMountPoint, 1);
101}
102
103// tearDown
104void
105FindDirectoryTest::tearDown()
106{
107	deleteVolume(testFile, testMountPoint);
108	BasicTest::tearDown();
109}
110
111// print_directories
112/*static
113void
114print_directories(dev_t device)
115{
116	printf("device id: %ld\n", device);
117	BVolume volume;
118	status_t error = volume.SetTo(device);
119	if (error != B_OK)
120		printf("Failed to init volume\n");
121	for (int32 i = 0; error == B_OK && i < directoryCount; i++) {
122		BPath path;
123		error = find_directory(directories[i], &path, false, &volume);
124		if (error == B_OK)
125			printf("%4d: `%s'\n", directories[i], path.Path());
126		else
127			printf("Failed to find directory: %s\n", strerror(error));
128	}
129}*/
130
131// test_find_directory
132static
133status_t
134test_find_directory(directory_which dir, BPath &path, dev_t device)
135{
136	status_t error = B_BAD_VALUE;
137	switch (dir) {
138		// volume relative dirs
139		case B_DESKTOP_DIRECTORY:
140		{
141			if (device < 0)
142				device = dev_for_path("/boot");
143			fs_info info;
144			if (fs_stat_dev(device, &info) == 0) {
145				if (!strcmp(info.fsh_name, "bfs")) {
146					entry_ref ref(device, info.root, "home");
147					BPath homePath(&ref);
148					error = homePath.InitCheck();
149					if (error == B_OK)
150						path.SetTo(homePath.Path(), "Desktop");
151				} else
152					error = B_ENTRY_NOT_FOUND;
153			} else
154				error = errno;
155			break;
156		}
157		case B_TRASH_DIRECTORY:
158		{
159			if (device < 0)
160				device = dev_for_path("/boot");
161			fs_info info;
162			if (fs_stat_dev(device, &info) == 0) {
163				if (!strcmp(info.fsh_name, "bfs")) {
164					entry_ref ref(device, info.root, "home");
165					BPath homePath(&ref);
166					error = homePath.InitCheck();
167					if (error == B_OK)
168						path.SetTo(homePath.Path(), "Desktop/Trash");
169				} else if (!strcmp(info.fsh_name, "dos")) {
170					entry_ref ref(device, info.root, "RECYCLED");
171					BPath recycledPath(&ref);
172					error = recycledPath.InitCheck();
173					if (error == B_OK)
174						path.SetTo(recycledPath.Path(), "_BEOS_");
175				} else
176					error = B_ENTRY_NOT_FOUND;
177			} else
178				error = errno;
179			break;
180		}
181		// BeOS directories.  These are mostly accessed read-only.
182		case B_BEOS_DIRECTORY:
183			error = path.SetTo("/boot/beos");
184			break;
185		case B_BEOS_SYSTEM_DIRECTORY:
186			error = path.SetTo("/boot/beos/system");
187			break;
188		case B_BEOS_ADDONS_DIRECTORY:
189			error = path.SetTo("/boot/beos/system/add-ons");
190			break;
191		case B_BEOS_BOOT_DIRECTORY:
192			error = path.SetTo("/boot/beos/system/boot");
193			break;
194		case B_BEOS_FONTS_DIRECTORY:
195			error = path.SetTo("/boot/beos/etc/fonts");
196			break;
197		case B_BEOS_LIB_DIRECTORY:
198			error = path.SetTo("/boot/beos/system/lib");
199			break;
200 		case B_BEOS_SERVERS_DIRECTORY:
201			error = path.SetTo("/boot/beos/system/servers");
202			break;
203		case B_BEOS_APPS_DIRECTORY:
204			error = path.SetTo("/boot/beos/apps");
205			break;
206		case B_BEOS_BIN_DIRECTORY:
207			error = path.SetTo("/boot/beos/bin");
208			break;
209		case B_BEOS_ETC_DIRECTORY:
210			error = path.SetTo("/boot/beos/etc");
211			break;
212		case B_BEOS_DOCUMENTATION_DIRECTORY:
213			error = path.SetTo("/boot/beos/documentation");
214			break;
215		case B_BEOS_PREFERENCES_DIRECTORY:
216			error = path.SetTo("/boot/beos/preferences");
217			break;
218		case B_BEOS_TRANSLATORS_DIRECTORY:
219			error = path.SetTo("/boot/beos/system/add-ons/Translators");
220			break;
221		case B_BEOS_MEDIA_NODES_DIRECTORY:
222			error = path.SetTo("/boot/beos/system/add-ons/media");
223			break;
224		case B_BEOS_SOUNDS_DIRECTORY:
225			error = path.SetTo("/boot/beos/etc/sounds");
226			break;
227		// Common directories, shared among all users.
228		case B_COMMON_DIRECTORY:
229			error = path.SetTo("/boot/home");
230			break;
231		case B_COMMON_SYSTEM_DIRECTORY:
232			error = path.SetTo("/boot/home/config");
233			break;
234		case B_COMMON_ADDONS_DIRECTORY:
235			error = path.SetTo("/boot/home/config/add-ons");
236			break;
237		case B_COMMON_BOOT_DIRECTORY:
238			error = path.SetTo("/boot/home/config/boot");
239			break;
240		case B_COMMON_FONTS_DIRECTORY:
241			error = path.SetTo("/boot/home/config/fonts");
242			break;
243		case B_COMMON_LIB_DIRECTORY:
244			error = path.SetTo("/boot/home/config/lib");
245			break;
246		case B_COMMON_SERVERS_DIRECTORY:
247			error = path.SetTo("/boot/home/config/servers");
248			break;
249		case B_COMMON_BIN_DIRECTORY:
250			error = path.SetTo("/boot/home/config/bin");
251			break;
252		case B_COMMON_ETC_DIRECTORY:
253			error = path.SetTo("/boot/home/config/etc");
254			break;
255		case B_COMMON_DOCUMENTATION_DIRECTORY:
256			error = path.SetTo("/boot/home/config/documentation");
257			break;
258		case B_COMMON_SETTINGS_DIRECTORY:
259			error = path.SetTo("/boot/home/config/settings");
260			break;
261		case B_COMMON_DEVELOP_DIRECTORY:
262			error = path.SetTo("/boot/develop");
263			break;
264		case B_COMMON_LOG_DIRECTORY:
265			error = path.SetTo("/boot/var/log");
266			break;
267		case B_COMMON_SPOOL_DIRECTORY:
268			error = path.SetTo("/boot/var/spool");
269			break;
270		case B_COMMON_TEMP_DIRECTORY:
271			error = path.SetTo("/boot/var/tmp");
272			break;
273		case B_COMMON_VAR_DIRECTORY:
274			error = path.SetTo("/boot/var");
275			break;
276		case B_COMMON_TRANSLATORS_DIRECTORY:
277			error = path.SetTo("/boot/home/config/add-ons/Translators");
278			break;
279		case B_COMMON_MEDIA_NODES_DIRECTORY:
280			error = path.SetTo("/boot/home/config/add-ons/media");
281			break;
282		case B_COMMON_SOUNDS_DIRECTORY:
283			error = path.SetTo("/boot/home/config/sounds");
284			break;
285		// User directories.  These are interpreted in the context
286		// of the user making the find_directory call.
287		case B_USER_DIRECTORY:
288			error = path.SetTo("/boot/home");
289			break;
290		case B_USER_CONFIG_DIRECTORY:
291			error = path.SetTo("/boot/home/config");
292			break;
293		case B_USER_ADDONS_DIRECTORY:
294			error = path.SetTo("/boot/home/config/add-ons");
295			break;
296		case B_USER_BOOT_DIRECTORY:
297			error = path.SetTo("/boot/home/config/boot");
298			break;
299		case B_USER_FONTS_DIRECTORY:
300			error = path.SetTo("/boot/home/config/fonts");
301			break;
302		case B_USER_LIB_DIRECTORY:
303			error = path.SetTo("/boot/home/config/lib");
304			break;
305		case B_USER_SETTINGS_DIRECTORY:
306			error = path.SetTo("/boot/home/config/settings");
307			break;
308		case B_USER_DESKBAR_DIRECTORY:
309			error = path.SetTo("/boot/home/config/be");
310			break;
311		case B_USER_PRINTERS_DIRECTORY:
312			error = path.SetTo("/boot/home/config/settings/printers");
313			break;
314		case B_USER_TRANSLATORS_DIRECTORY:
315			error = path.SetTo("/boot/home/config/add-ons/Translators");
316			break;
317		case B_USER_MEDIA_NODES_DIRECTORY:
318			error = path.SetTo("/boot/home/config/add-ons/media");
319			break;
320		case B_USER_SOUNDS_DIRECTORY:
321			error = path.SetTo("/boot/home/config/sounds");
322			break;
323		// Global directories.
324		case B_APPS_DIRECTORY:
325			error = path.SetTo("/boot/apps");
326			break;
327		case B_PREFERENCES_DIRECTORY:
328			error = path.SetTo("/boot/preferences");
329			break;
330		case B_UTILITIES_DIRECTORY:
331			error = path.SetTo("/boot/utilities");
332			break;
333	}
334	return error;
335}
336
337// TestDirectories
338static
339void
340TestDirectories(dev_t device)
341{
342	BVolume volume;
343	if (device >= 0)
344		CPPUNIT_ASSERT( volume.SetTo(device) == B_OK );
345	for (int32 i = 0; i < directoryCount; i++) {
346		BPath path;
347		BPath path2;
348		char path3[B_PATH_NAME_LENGTH + 1];
349		status_t result = test_find_directory(directories[i], path, device);
350		status_t result2 = find_directory(directories[i], &path2, false,
351										  &volume);
352		status_t result3 = find_directory(directories[i], device, false,
353										  path3, B_PATH_NAME_LENGTH + 1);
354		CPPUNIT_ASSERT( result == result2 && result == result3 );
355		if (result == B_OK)
356			CPPUNIT_ASSERT( path == path2 && path == path3 );
357	}
358}
359
360// Test
361void
362FindDirectoryTest::Test()
363{
364	// /boot
365	NextSubTest();
366	dev_t device = dev_for_path("/boot");
367	CPPUNIT_ASSERT( device > 0 );
368	TestDirectories(device);
369	// /dev
370	NextSubTest();
371	device = dev_for_path("/dev");
372	CPPUNIT_ASSERT( device > 0 );
373	TestDirectories(device);
374	// /
375	NextSubTest();
376	device = dev_for_path("/");
377	CPPUNIT_ASSERT( device > 0 );
378	TestDirectories(device);
379	// test image
380	NextSubTest();
381	device = dev_for_path(testMountPoint);
382	CPPUNIT_ASSERT( device > 0 );
383	TestDirectories(device);
384	// invalid device ID
385	NextSubTest();
386	TestDirectories(-1);
387	// NULL BVolume
388	NextSubTest();
389	for (int32 i = 0; i < directoryCount; i++) {
390		BPath path;
391		BPath path2;
392		status_t result = test_find_directory(directories[i], path, -1);
393		status_t result2 = find_directory(directories[i], &path2, false, NULL);
394		CPPUNIT_ASSERT( result == result2 );
395		if (result == B_OK)
396			CPPUNIT_ASSERT( path == path2 );
397	}
398	// no such volume
399	NextSubTest();
400	device = 213;
401	fs_info info;
402	while (fs_stat_dev(device, &info) == 0)
403		device++;
404	for (int32 i = 0; i < directoryCount; i++) {
405		BPath path;
406		char path3[B_PATH_NAME_LENGTH + 1];
407		status_t result = test_find_directory(directories[i], path, device);
408		status_t result3 = find_directory(directories[i], device, false,
409										  path3, B_PATH_NAME_LENGTH + 1);
410		// Our test_find_directory() returns rather strange errors instead
411		// of B_ENTRY_NOT_FOUND.
412		CPPUNIT_ASSERT( result == B_OK && result3 == B_OK
413						|| result != B_OK && result3 != B_OK );
414		if (result == B_OK)
415			CPPUNIT_ASSERT( path == path3 );
416	}
417	// bad args
418	// R5: crashes
419	NextSubTest();
420	device = dev_for_path("/boot");
421	CPPUNIT_ASSERT( device > 0 );
422#if !TEST_R5
423	CPPUNIT_ASSERT( find_directory(B_BEOS_DIRECTORY, NULL, false, NULL)
424					== B_BAD_VALUE );
425	CPPUNIT_ASSERT( find_directory(B_BEOS_DIRECTORY, device, false, NULL, 50)
426					== B_BAD_VALUE );
427#endif
428	// small buffer
429	NextSubTest();
430	char path3[7];
431	CPPUNIT_ASSERT( find_directory(B_BEOS_DIRECTORY, device, false, path3, 7)
432					== E2BIG );
433}
434
435
436
437
438
439