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