xref: /haiku/src/tests/system/kernel/fs/KPathTest.cpp (revision e8a484b0f6ad5e49b35d660b1974b06309612570)
1 /*
2  * Copyright 2017, Axel Dörfler, axeld@pinc-software.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "KPathTest.h"
8 
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #include <fs/KPath.h>
13 
14 #include <cppunit/TestCaller.h>
15 #include <cppunit/TestSuite.h>
16 
17 
18 typedef void* mutex;
19 
20 
21 // Kernel stubs
22 
23 
24 extern "C" team_id
team_get_kernel_team_id(void)25 team_get_kernel_team_id(void)
26 {
27 	return 0;
28 }
29 
30 
31 extern "C" team_id
team_get_current_team_id(void)32 team_get_current_team_id(void)
33 {
34 	return 0;
35 }
36 
37 
38 extern "C" status_t
vfs_normalize_path(const char * path,char * buffer,size_t bufferSize,bool traverseLink,bool kernel)39 vfs_normalize_path(const char* path, char* buffer, size_t bufferSize,
40 	bool traverseLink, bool kernel)
41 {
42 	return B_NOT_SUPPORTED;
43 }
44 
45 
46 // #pragma mark - DEBUG only
47 
48 
49 extern "C" void*
memalign_etc(size_t alignment,size_t size,uint32 flags)50 memalign_etc(size_t alignment, size_t size, uint32 flags)
51 {
52 	return malloc(size);
53 }
54 
55 
56 extern "C" status_t
_mutex_lock(mutex * lock,void * locker)57 _mutex_lock(mutex* lock, void* locker)
58 {
59 	return B_OK;
60 }
61 
62 
63 extern "C" status_t
_mutex_trylock(mutex * lock)64 _mutex_trylock(mutex* lock)
65 {
66 	return B_OK;
67 }
68 
69 
70 extern "C" void
_mutex_unlock(mutex * lock)71 _mutex_unlock(mutex* lock)
72 {
73 }
74 
75 
76 // #pragma mark -
77 
78 
KPathTest()79 KPathTest::KPathTest()
80 {
81 }
82 
83 
~KPathTest()84 KPathTest::~KPathTest()
85 {
86 }
87 
88 
89 void
TestSetToAndPath()90 KPathTest::TestSetToAndPath()
91 {
92 	KPath path;
93 	status_t status = path.InitCheck();
94 	CPPUNIT_ASSERT_MESSAGE("1. ", status == B_OK);
95 
96 	status = path.SetTo("a/b/c");
97 	CPPUNIT_ASSERT_MESSAGE("2. ", status == B_OK);
98 	CPPUNIT_ASSERT(strcmp(path.Path(), "a/b/c") == 0);
99 	CPPUNIT_ASSERT(path.Length() == 5);
100 	CPPUNIT_ASSERT(path.BufferSize() == B_PATH_NAME_LENGTH + 1);
101 
102 	status = path.SetPath("abc/def");
103 	CPPUNIT_ASSERT_MESSAGE("3. ", status == B_OK);
104 	CPPUNIT_ASSERT(strcmp(path.Path(), "abc/def") == 0);
105 	CPPUNIT_ASSERT(path.Length() == 7);
106 	CPPUNIT_ASSERT(path.BufferSize() == B_PATH_NAME_LENGTH + 1);
107 
108 	status = path.SetTo("a/b/c", false, 10);
109 	CPPUNIT_ASSERT_MESSAGE("4. ", status == B_OK);
110 	CPPUNIT_ASSERT(strcmp(path.Path(), "a/b/c") == 0);
111 	CPPUNIT_ASSERT(path.Length() == 5);
112 	CPPUNIT_ASSERT(path.BufferSize() == 10);
113 
114 	status = path.SetPath("sorry/i'm/too/long");
115 	CPPUNIT_ASSERT(status == B_BUFFER_OVERFLOW);
116 	CPPUNIT_ASSERT(strcmp(path.Path(), "a/b/c") == 0);
117 	CPPUNIT_ASSERT(path.Length() == 5);
118 
119 	status = path.SetTo(NULL, KPath::DEFAULT, SIZE_MAX);
120 	CPPUNIT_ASSERT(status == B_NO_MEMORY);
121 }
122 
123 
124 void
TestLazyAlloc()125 KPathTest::TestLazyAlloc()
126 {
127 	KPath path(NULL, KPath::LAZY_ALLOC);
128 	CPPUNIT_ASSERT(path.Path() == NULL);
129 	CPPUNIT_ASSERT(path.Length() == 0);
130 	CPPUNIT_ASSERT(path.BufferSize() == B_PATH_NAME_LENGTH + 1);
131 	CPPUNIT_ASSERT(path.InitCheck() == B_OK);
132 
133 	path.SetPath("/b");
134 	CPPUNIT_ASSERT(path.Path() != NULL);
135 	CPPUNIT_ASSERT(strcmp(path.Path(), "/b") == 0);
136 	CPPUNIT_ASSERT(path.Length() == 2);
137 	CPPUNIT_ASSERT(path.BufferSize() == B_PATH_NAME_LENGTH + 1);
138 
139 	KPath second("yo", KPath::LAZY_ALLOC);
140 	CPPUNIT_ASSERT(second.Path() != NULL);
141 	CPPUNIT_ASSERT(strcmp(second.Path(), "yo") == 0);
142 	CPPUNIT_ASSERT(second.Length() == 2);
143 	CPPUNIT_ASSERT(second.BufferSize() == B_PATH_NAME_LENGTH + 1);
144 
145 	status_t status = path.SetTo(NULL, KPath::LAZY_ALLOC, SIZE_MAX);
146 	CPPUNIT_ASSERT(status == B_OK);
147 	status = path.SetPath("test");
148 	CPPUNIT_ASSERT(status == B_NO_MEMORY);
149 	CPPUNIT_ASSERT(path.InitCheck() == B_NO_MEMORY);
150 }
151 
152 
153 void
TestLeaf()154 KPathTest::TestLeaf()
155 {
156 	KPath path("a");
157 	CPPUNIT_ASSERT(strcmp(path.Path(), "a") == 0);
158 	CPPUNIT_ASSERT(strcmp(path.Leaf(), "a") == 0);
159 
160 	path.SetTo("");
161 	CPPUNIT_ASSERT(strcmp(path.Path(), "") == 0);
162 	CPPUNIT_ASSERT(strcmp(path.Leaf(), "") == 0);
163 
164 	path.SetTo("/");
165 	CPPUNIT_ASSERT(strcmp(path.Path(), "/") == 0);
166 	CPPUNIT_ASSERT(strcmp(path.Leaf(), "") == 0);
167 
168 	path.SetTo("a/b");
169 	CPPUNIT_ASSERT(strcmp(path.Path(), "a/b") == 0);
170 	CPPUNIT_ASSERT(strcmp(path.Leaf(), "b") == 0);
171 
172 	path.SetTo("a/b/");
173 	CPPUNIT_ASSERT(strcmp(path.Path(), "a/b") == 0);
174 	CPPUNIT_ASSERT(strcmp(path.Leaf(), "b") == 0);
175 
176 	path.SetTo("/a/b//c");
177 	CPPUNIT_ASSERT(strcmp(path.Path(), "/a/b//c") == 0);
178 	CPPUNIT_ASSERT(strcmp(path.Leaf(), "c") == 0);
179 }
180 
181 
182 void
TestReplaceLeaf()183 KPathTest::TestReplaceLeaf()
184 {
185 	KPath path;
186 	status_t status = path.ReplaceLeaf("x");
187 	CPPUNIT_ASSERT(status == B_OK);
188 
189 	path.SetTo("/a/b/c");
190 	CPPUNIT_ASSERT(path.Length() == 6);
191 
192 	status = path.ReplaceLeaf(NULL);
193 	CPPUNIT_ASSERT(status == B_OK);
194 	CPPUNIT_ASSERT(path.Length() == 4);
195 	CPPUNIT_ASSERT(strcmp(path.Path(), "/a/b") == 0);
196 
197 	status = path.ReplaceLeaf("");
198 	CPPUNIT_ASSERT(status == B_OK);
199 	CPPUNIT_ASSERT(path.Length() == 2);
200 	CPPUNIT_ASSERT(strcmp(path.Path(), "/a") == 0);
201 
202 	status = path.ReplaceLeaf("c");
203 	CPPUNIT_ASSERT(status == B_OK);
204 	CPPUNIT_ASSERT(path.Length() == 2);
205 	CPPUNIT_ASSERT(strcmp(path.Path(), "/c") == 0);
206 }
207 
208 
209 void
TestRemoveLeaf()210 KPathTest::TestRemoveLeaf()
211 {
212 	KPath path;
213 	bool removed = path.RemoveLeaf();
214 	CPPUNIT_ASSERT(!removed);
215 
216 	path.SetTo("a//b/c");
217 	removed = path.RemoveLeaf();
218 	CPPUNIT_ASSERT_MESSAGE("1. removed", removed);
219 	CPPUNIT_ASSERT(strcmp(path.Path(), "a//b") == 0);
220 	CPPUNIT_ASSERT(path.Length() == 4);
221 
222 	removed = path.RemoveLeaf();
223 	CPPUNIT_ASSERT_MESSAGE("2. removed", removed);
224 	CPPUNIT_ASSERT(strcmp(path.Path(), "a") == 0);
225 	CPPUNIT_ASSERT(path.Length() == 1);
226 
227 	removed = path.RemoveLeaf();
228 	CPPUNIT_ASSERT_MESSAGE("3. !removed", !removed);
229 	CPPUNIT_ASSERT(strcmp(path.Path(), "a") == 0);
230 	CPPUNIT_ASSERT(path.Length() == 1);
231 
232 	path.SetTo("/a");
233 	removed = path.RemoveLeaf();
234 	CPPUNIT_ASSERT_MESSAGE("4. removed", removed);
235 	CPPUNIT_ASSERT(strcmp(path.Path(), "/") == 0);
236 	CPPUNIT_ASSERT(path.Length() == 1);
237 
238 	removed = path.RemoveLeaf();
239 	CPPUNIT_ASSERT_MESSAGE("5. !removed", !removed);
240 	CPPUNIT_ASSERT(strcmp(path.Path(), "/") == 0);
241 	CPPUNIT_ASSERT(path.Length() == 1);
242 }
243 
244 
245 void
TestAdopt()246 KPathTest::TestAdopt()
247 {
248 	KPath one("first", false, 10);
249 	CPPUNIT_ASSERT(one.InitCheck() == B_OK);
250 	CPPUNIT_ASSERT(one.BufferSize() == 10);
251 	CPPUNIT_ASSERT(one.Length() == 5);
252 	KPath two("second", false, 20);
253 	CPPUNIT_ASSERT(two.InitCheck() == B_OK);
254 	CPPUNIT_ASSERT(two.BufferSize() == 20);
255 
256 	one.Adopt(two);
257 	CPPUNIT_ASSERT(one.InitCheck() == B_OK);
258 	CPPUNIT_ASSERT(one.BufferSize() == 20);
259 	CPPUNIT_ASSERT(one.Length() == 6);
260 	CPPUNIT_ASSERT(strcmp(one.Path(), "second") == 0);
261 	CPPUNIT_ASSERT(two.Length() == 0);
262 	CPPUNIT_ASSERT(two.BufferSize() == 0);
263 	CPPUNIT_ASSERT(two.InitCheck() == B_NO_INIT);
264 
265 	two.SetTo(NULL, KPath::LAZY_ALLOC);
266 	CPPUNIT_ASSERT(two.InitCheck() == B_OK);
267 	CPPUNIT_ASSERT(two.Path() == NULL);
268 	CPPUNIT_ASSERT(two.Length() == 0);
269 	one.Adopt(two);
270 
271 	CPPUNIT_ASSERT(two.InitCheck() == B_OK);
272 	CPPUNIT_ASSERT(one.Path() == NULL);
273 	CPPUNIT_ASSERT(one.Length() == 0);
274 	one.SetPath("test");
275 	CPPUNIT_ASSERT(one.Path() != NULL);
276 	CPPUNIT_ASSERT(strcmp(one.Path(), "test") == 0);
277 	CPPUNIT_ASSERT(one.Length() == 4);
278 }
279 
280 
281 void
TestLockBuffer()282 KPathTest::TestLockBuffer()
283 {
284 	KPath path;
285 	CPPUNIT_ASSERT(path.Path() != NULL);
286 	CPPUNIT_ASSERT(path.Length() == 0);
287 	char* buffer = path.LockBuffer();
288 	CPPUNIT_ASSERT(path.Path() == buffer);
289 	strcpy(buffer, "test");
290 	CPPUNIT_ASSERT(path.Length() == 0);
291 	path.UnlockBuffer();
292 	CPPUNIT_ASSERT(path.Length() == 4);
293 
294 	KPath second(NULL, KPath::LAZY_ALLOC);
295 	CPPUNIT_ASSERT(second.Path() == NULL);
296 	CPPUNIT_ASSERT(second.Length() == 0);
297 	buffer = second.LockBuffer();
298 	CPPUNIT_ASSERT(second.Path() == NULL);
299 	CPPUNIT_ASSERT(buffer == NULL);
300 
301 	KPath third(NULL, KPath::LAZY_ALLOC);
302 	CPPUNIT_ASSERT(third.Path() == NULL);
303 	buffer = third.LockBuffer(true);
304 	CPPUNIT_ASSERT(third.Path() != NULL);
305 	CPPUNIT_ASSERT(buffer != NULL);
306 	strcpy(buffer, "test");
307 	CPPUNIT_ASSERT(third.Length() == 0);
308 	third.UnlockBuffer();
309 	CPPUNIT_ASSERT(third.Length() == 4);
310 }
311 
312 
313 void
TestDetachBuffer()314 KPathTest::TestDetachBuffer()
315 {
316 	KPath path("test");
317 	CPPUNIT_ASSERT(path.InitCheck() == B_OK);
318 
319 	char* buffer = path.DetachBuffer();
320 	CPPUNIT_ASSERT(buffer != NULL);
321 	CPPUNIT_ASSERT(strcmp(buffer, "test") == 0);
322 
323 	CPPUNIT_ASSERT(path.Path() == NULL);
324 	CPPUNIT_ASSERT(path.InitCheck() == B_NO_INIT);
325 }
326 
327 
328 void
TestNormalize()329 KPathTest::TestNormalize()
330 {
331 	// Outside the kernel, we only test the error case.
332 	KPath path("test/../out");
333 	CPPUNIT_ASSERT(path.InitCheck() == B_OK);
334 
335 	status_t status = path.Normalize(true);
336 	CPPUNIT_ASSERT(status == B_NOT_SUPPORTED);
337 	CPPUNIT_ASSERT(path.Path() != NULL);
338 	CPPUNIT_ASSERT(path.Path()[0] == '\0');
339 	CPPUNIT_ASSERT(path.Path() == path.Leaf());
340 
341 	status = path.SetTo("test/../in", KPath::NORMALIZE);
342 	CPPUNIT_ASSERT(status == B_NOT_SUPPORTED);
343 	CPPUNIT_ASSERT(path.Path() != NULL);
344 	CPPUNIT_ASSERT(path.Path()[0] == '\0');
345 	CPPUNIT_ASSERT(path.Path() == path.Leaf());
346 }
347 
348 
349 void
TestAssign()350 KPathTest::TestAssign()
351 {
352 	KPath one("first", false, 10);
353 	CPPUNIT_ASSERT(one.Length() == 5);
354 	KPath two("second", false, 20);
355 
356 	two = one;
357 	CPPUNIT_ASSERT(strcmp(two.Path(), one.Path()) == 0);
358 	CPPUNIT_ASSERT(two.Path() != one.Path());
359 	CPPUNIT_ASSERT(two.BufferSize() == one.BufferSize());
360 	CPPUNIT_ASSERT(two.Length() == one.Length());
361 
362 	one = "/whatever";
363 	CPPUNIT_ASSERT(one.Length() == 9);
364 	CPPUNIT_ASSERT(one.BufferSize() == two.BufferSize());
365 	CPPUNIT_ASSERT(strcmp(one.Path(), "/whatever") == 0);
366 }
367 
368 
369 void
TestEquals()370 KPathTest::TestEquals()
371 {
372 	KPath a("one");
373 	KPath b("two");
374 	CPPUNIT_ASSERT_MESSAGE("1.", !(a == b));
375 
376 	b = a;
377 	CPPUNIT_ASSERT_MESSAGE("2.", a == b);
378 
379 	b = "ones";
380 	CPPUNIT_ASSERT_MESSAGE("3.", !(a == b));
381 }
382 
383 
384 void
TestNotEquals()385 KPathTest::TestNotEquals()
386 {
387 	KPath a("one");
388 	KPath b("two");
389 	CPPUNIT_ASSERT_MESSAGE("1.", a != b);
390 
391 	b = a;
392 	CPPUNIT_ASSERT_MESSAGE("2.", !(a != b));
393 
394 	b = "ones";
395 	CPPUNIT_ASSERT_MESSAGE("3.", a != b);
396 }
397 
398 
399 /*static*/ void
AddTests(BTestSuite & parent)400 KPathTest::AddTests(BTestSuite& parent)
401 {
402 	CppUnit::TestSuite& suite = *new CppUnit::TestSuite("KPathTest");
403 
404 	suite.addTest(new CppUnit::TestCaller<KPathTest>(
405 		"KPathTest::TestSetToAndPath", &KPathTest::TestSetToAndPath));
406 	suite.addTest(new CppUnit::TestCaller<KPathTest>(
407 		"KPathTest::TestLazyAlloc", &KPathTest::TestLazyAlloc));
408 	suite.addTest(new CppUnit::TestCaller<KPathTest>(
409 		"KPathTest::TestLeaf", &KPathTest::TestLeaf));
410 	suite.addTest(new CppUnit::TestCaller<KPathTest>(
411 		"KPathTest::TestReplaceLeaf", &KPathTest::TestReplaceLeaf));
412 	suite.addTest(new CppUnit::TestCaller<KPathTest>(
413 		"KPathTest::TestRemoveLeaf", &KPathTest::TestRemoveLeaf));
414 	suite.addTest(new CppUnit::TestCaller<KPathTest>(
415 		"KPathTest::TestAdopt", &KPathTest::TestAdopt));
416 	suite.addTest(new CppUnit::TestCaller<KPathTest>(
417 		"KPathTest::TestLockBuffer", &KPathTest::TestLockBuffer));
418 	suite.addTest(new CppUnit::TestCaller<KPathTest>(
419 		"KPathTest::TestDetachBuffer", &KPathTest::TestDetachBuffer));
420 	suite.addTest(new CppUnit::TestCaller<KPathTest>(
421 		"KPathTest::TestNormalize", &KPathTest::TestNormalize));
422 	suite.addTest(new CppUnit::TestCaller<KPathTest>(
423 		"KPathTest::TestAssign", &KPathTest::TestAssign));
424 	suite.addTest(new CppUnit::TestCaller<KPathTest>(
425 		"KPathTest::TestEquals", &KPathTest::TestEquals));
426 	suite.addTest(new CppUnit::TestCaller<KPathTest>(
427 		"KPathTest::TestNotEquals", &KPathTest::TestNotEquals));
428 
429 	parent.addTest("KPathTest", &suite);
430 }
431