1 /*
2  * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/>
3  *           (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com>
4  *
5  * This file is part of lsp-plugins
6  * Created on: 9 февр. 2019 г.
7  *
8  * lsp-plugins is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * any later version.
12  *
13  * lsp-plugins is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include <test/utest.h>
23 #include <core/status.h>
24 #include <core/io/Path.h>
25 
26 #include <string.h>
27 
28 #ifdef PLATFORM_WINDOWS
29     #define TEST_PATH1      "C:\\Windows\\system32"
30     #define TEST_PATH2      "C:\\Windows\\system\\lib"
31     #define TEST_PATH3      "C:\\Windows\\system\\bin"
32     #define TEST_PATH4      "C:\\Windows\\system"
33     #define TEST_ROOT       "C:\\"
34 #else
35     #define TEST_PATH1      "/usr/local/bin"
36     #define TEST_PATH2      "/usr/share/local/lib"
37     #define TEST_PATH3      "/usr/share/local/bin"
38     #define TEST_PATH4      "/usr/share/local"
39     #define TEST_ROOT       "/"
40 #endif
41 
42 using namespace lsp;
43 using namespace lsp::io;
44 
45 static char *cnull = NULL;
46 static LSPString *snull = NULL;
47 static Path *pnull = NULL;
48 
49 static const char *cpaths[] =
50 {
51 #if !defined(PLATFORM_WINDOWS)
52     ".", "",
53     "./", "",
54     "..", "",
55     "../", "",
56     "./.././a", "a",
57     "a/b/c/../../d/./", "a/d",
58     "a///b/c/.//../../d/./", "a/d",
59     "a/b/c/../../../d/e/./f/", "d/e/f",
60 
61     "//", "/",
62     "/.", "/",
63     "/..", "/",
64     "/./", "/",
65     "/../", "/",
66     "/a/b/c/../../d/./", "/a/d",
67     "/a///b/c/.//../../d/./", "/a/d",
68     "/a/b/c/../../../d/e/./f/", "/d/e/f",
69     "/../a/b/c/../../d/./", "/a/d",
70     "/../a///b/c/.//../../d/./", "/a/d",
71     "/./../a/b/c/../../../d/e/./f/", "/d/e/f",
72 #else
73     ".", "",
74     ".\\", "",
75     "..", "",
76     "..\\", "",
77     ".\\..\\.\\a", "a",
78     "a\\b\\c\\..\\..\\d\\.\\", "a\\d",
79     "a\\\\\\b\\c\\.\\\\..\\..\\d\\.\\", "a\\d",
80     "a\\b\\c\\..\\..\\..\\d\\e\\.\\f\\", "d\\e\\f",
81 
82     "C:\\\\", "C:\\",
83     "C:\\.", "C:\\",
84     "C:\\..", "C:\\",
85     "C:\\.\\", "C:\\",
86     "C:\\..\\", "C:\\",
87     "C:\\a\\b\\c\\..\\..\\d\\.\\", "C:\\a\\d",
88     "C:\\a\\\\\\b\\c\\.\\\\..\\..\\d\\.\\", "C:\\a\\d",
89     "C:\\a\\b\\c\\..\\..\\..\\d\\e\\.\\f\\", "C:\\d\\e\\f",
90     "C:\\..\\a\\b\\c\\..\\..\\d\\.\\", "C:\\a\\d",
91     "C:\\..\\a\\\\\\b\\c\\.\\\\..\\..\\d\\.\\", "C:\\a\\d",
92     "C:\\.\\..\\a\\b\\c\\..\\..\\..\\d\\e\\.\\f\\", "C:\\d\\e\\f",
93 #endif
94 
95     NULL, NULL
96 };
97 
98 UTEST_BEGIN("core.io", path)
99 
100 //    status_t    get_parent(char *path, size_t maxlen) const;
101 //    status_t    set_parent(const char *path);
102 //    status_t    get_parent(LSPString *path) const;
103 //    status_t    get_parent(Path *path) const;
104 //    status_t    set_parent(LSPString *path);
105 //    status_t    set_parent(Path *path);
test_get_set_parent()106     void test_get_set_parent()
107     {
108         Path bp, dp;
109         char path[PATH_MAX];
110         LSPString spath, dpath;
111 
112         UTEST_ASSERT(bp.set(TEST_PATH2) == STATUS_OK);
113         UTEST_ASSERT(bp.get_parent(path, PATH_MAX) == STATUS_OK);
114         UTEST_ASSERT(bp.get_parent(path, 2) == STATUS_TOO_BIG);
115         UTEST_ASSERT(bp.get_parent(cnull, PATH_MAX) == STATUS_BAD_ARGUMENTS);
116         UTEST_ASSERT(strcmp(path, TEST_PATH4) == 0);
117 
118         UTEST_ASSERT(spath.set_utf8(TEST_PATH4));
119         UTEST_ASSERT(bp.get_parent(snull) == STATUS_BAD_ARGUMENTS);
120         UTEST_ASSERT(bp.get_parent(&dpath) == STATUS_OK);
121         UTEST_ASSERT(dpath.equals(&spath));
122         UTEST_ASSERT(bp.get_parent(&dp) == STATUS_OK);
123         UTEST_ASSERT(dp.equals(&spath));
124 
125         UTEST_ASSERT(bp.set(TEST_ROOT) == STATUS_OK);
126         UTEST_ASSERT(bp.get_parent(path, PATH_MAX) == STATUS_NOT_FOUND);
127         UTEST_ASSERT(bp.get_parent(&dpath) == STATUS_NOT_FOUND);
128         UTEST_ASSERT(bp.get_parent(&dp) == STATUS_NOT_FOUND);
129 
130         UTEST_ASSERT(bp.set("bin") == STATUS_OK);
131         UTEST_ASSERT(bp.get_parent(path, PATH_MAX) == STATUS_NOT_FOUND);
132         UTEST_ASSERT(bp.get_parent(&dpath) == STATUS_NOT_FOUND);
133         UTEST_ASSERT(bp.get_parent(&dp) == STATUS_NOT_FOUND);
134     }
135 
136 //    status_t    set_last(const char *path);
137 //    status_t    get_last(char *path, size_t maxlen) const;
138 //    status_t    set_last(const LSPString *path);
139 //    status_t    get_last(LSPString *path) const;
140 //    status_t    set_last(const Path *path);
141 //    status_t    get_last(Path *path) const;
test_get_set_last()142     void test_get_set_last()
143     {
144         Path bp, dp, p;
145         char path[PATH_MAX];
146         LSPString spath, dpath, t1;
147 
148         UTEST_ASSERT(dp.set(TEST_PATH2) == STATUS_OK);
149         UTEST_ASSERT(dp.set_last("bin") == STATUS_OK);
150         UTEST_ASSERT(dp.set_last(cnull) == STATUS_BAD_ARGUMENTS);
151         UTEST_ASSERT(dp.equals(TEST_PATH3));
152         UTEST_ASSERT(dp.get_last(path, PATH_MAX) == STATUS_OK);
153         UTEST_ASSERT(strcmp(path, "bin") == 0);
154         UTEST_ASSERT(dp.set_last("") == STATUS_OK);
155         UTEST_ASSERT(dp.equals(TEST_PATH4));
156 
157         UTEST_ASSERT(bp.set_last("bin") == STATUS_OK);
158         UTEST_ASSERT(bp.set_last(cnull) == STATUS_BAD_ARGUMENTS);
159         UTEST_ASSERT(bp.equals("bin"));
160         UTEST_ASSERT(bp.get_last(cnull, PATH_MAX) == STATUS_BAD_ARGUMENTS);
161         UTEST_ASSERT(bp.get_last(path, PATH_MAX) == STATUS_OK);
162         UTEST_ASSERT(strcmp(path, "bin") == 0);
163         UTEST_ASSERT(bp.set_last("") == STATUS_OK);
164         UTEST_ASSERT(bp.is_empty());
165 
166         UTEST_ASSERT(dpath.set_utf8("bin"));
167         dp.clear();
168         UTEST_ASSERT(spath.set_utf8(TEST_PATH2));
169         UTEST_ASSERT(bp.set(&spath) == STATUS_OK);
170         UTEST_ASSERT(bp.set_last(&dpath) == STATUS_OK);
171         UTEST_ASSERT(bp.equals(TEST_PATH3));
172         UTEST_ASSERT(bp.get_last(&t1) == STATUS_OK);
173         UTEST_ASSERT(bp.get_last(snull) == STATUS_BAD_ARGUMENTS);
174         UTEST_ASSERT(t1.equals(&dpath));
175 
176         UTEST_ASSERT(dp.set_last(&dpath) == STATUS_OK);
177         UTEST_ASSERT(dp.equals("bin"));
178         UTEST_ASSERT(dp.get_last(&spath) == STATUS_OK);
179         UTEST_ASSERT(t1.equals(&spath));
180 
181         UTEST_ASSERT(bp.set(TEST_PATH2) == STATUS_OK);
182         UTEST_ASSERT(dp.set("bin") == STATUS_OK);
183         UTEST_ASSERT(bp.set_last(&dp) == STATUS_OK);
184         UTEST_ASSERT(bp.set_last(pnull) == STATUS_BAD_ARGUMENTS);
185         UTEST_ASSERT(bp.equals(TEST_PATH3));
186         UTEST_ASSERT(bp.get_last(&p) == STATUS_OK);
187         UTEST_ASSERT(p.equals("bin"));
188         UTEST_ASSERT(bp.set(TEST_ROOT) == STATUS_OK);
189         UTEST_ASSERT(bp.get_last(&p) == STATUS_OK);
190         UTEST_ASSERT(p.is_empty());
191     }
192 
193 //    status_t    set(const char *path);
194 //    status_t    set(const LSPString *path);
195 //    status_t    set(const Path *path);
196 //    status_t    get(char *path, size_t maxlen) const;
197 //    status_t    get(LSPString *path) const;
198 //    status_t    get(Path *path) const;
test_get_set()199     void test_get_set()
200     {
201         Path p, dp, bp;
202         char path[PATH_MAX];
203         LSPString spath, dpath;
204 
205         UTEST_ASSERT(p.set(TEST_PATH1) == STATUS_OK);
206         UTEST_ASSERT(p.set(cnull) == STATUS_BAD_ARGUMENTS);
207         UTEST_ASSERT(p.get(cnull, PATH_MAX) == STATUS_BAD_ARGUMENTS);
208         UTEST_ASSERT(p.get(path, PATH_MAX) == STATUS_OK);
209         UTEST_ASSERT(p.get(path, 10) == STATUS_TOO_BIG);
210         UTEST_ASSERT(strcmp(path, TEST_PATH1) == 0);
211 
212         UTEST_ASSERT(spath.set_utf8(TEST_PATH2));
213         UTEST_ASSERT(p.set(&spath) == STATUS_OK);
214         UTEST_ASSERT(p.set(snull) == STATUS_BAD_ARGUMENTS);
215         UTEST_ASSERT(p.get(snull) == STATUS_BAD_ARGUMENTS);
216         UTEST_ASSERT(p.get(&dpath) == STATUS_OK);
217         UTEST_ASSERT(dpath.equals(&spath));
218 
219 
220         UTEST_ASSERT(dp.set(&p) == STATUS_OK);
221         UTEST_ASSERT(dp.set(pnull) == STATUS_BAD_ARGUMENTS);
222         UTEST_ASSERT(dp.get(&bp) == STATUS_OK);
223         UTEST_ASSERT(dp.get(pnull) == STATUS_BAD_ARGUMENTS);
224         UTEST_ASSERT(bp.equals(&dp));
225         UTEST_ASSERT(bp.equals(&p));
226         UTEST_ASSERT(bp.equals(TEST_PATH2));
227         UTEST_ASSERT(bp.equals(&spath));
228     }
229 
230 //    status_t    concat(const char *path);
231 //    status_t    concat(LSPString *path);
232 //    status_t    concat(Path *path);
test_concat()233     void test_concat()
234     {
235         Path p;
236         LSPString sstr;
237         Path spath;
238 
239         UTEST_ASSERT(p.set(TEST_PATH4) == STATUS_OK);
240         UTEST_ASSERT(p.concat(FILE_SEPARATOR_S "bin") == STATUS_OK);
241         UTEST_ASSERT(p.concat(cnull) == STATUS_BAD_ARGUMENTS);
242         UTEST_ASSERT(p.equals(TEST_PATH3));
243 
244         p.clear();
245         UTEST_ASSERT(p.concat(TEST_ROOT) == STATUS_OK);
246         UTEST_ASSERT(p.is_root());
247 
248         p.clear();
249         UTEST_ASSERT(p.set(TEST_PATH4) == STATUS_OK);
250         UTEST_ASSERT(sstr.set_utf8(FILE_SEPARATOR_S "bin"));
251         UTEST_ASSERT(p.concat(&sstr) == STATUS_OK);
252         UTEST_ASSERT(p.concat(snull) == STATUS_BAD_ARGUMENTS);
253         UTEST_ASSERT(p.equals(TEST_PATH3));
254 
255         p.clear();
256         UTEST_ASSERT(p.set(TEST_PATH4) == STATUS_OK);
257         UTEST_ASSERT(spath.set(&sstr) == STATUS_OK);
258         UTEST_ASSERT(p.concat(&spath) == STATUS_OK);
259         UTEST_ASSERT(p.concat(pnull) == STATUS_BAD_ARGUMENTS);
260         UTEST_ASSERT(p.equals(TEST_PATH3));
261 
262         p.clear();
263         UTEST_ASSERT(sstr.set_utf8(TEST_ROOT));
264         UTEST_ASSERT(p.concat(&sstr) == STATUS_OK);
265         UTEST_ASSERT(p.is_root());
266 
267         p.clear();
268         UTEST_ASSERT(spath.set(&sstr) == STATUS_OK);
269         UTEST_ASSERT(p.concat(&spath) == STATUS_OK);
270         UTEST_ASSERT(p.is_root());
271     }
272 
273 //    status_t    append_child(const char *path);
274 //    status_t    append_child(LSPString *path);
275 //    status_t    append_child(Path *path);
test_append_child()276     void test_append_child()
277     {
278         Path p;
279         LSPString sstr;
280         Path spath;
281 
282         UTEST_ASSERT(p.set(TEST_PATH4) == STATUS_OK);
283         UTEST_ASSERT(p.append_child("bin") == STATUS_OK);
284         UTEST_ASSERT(p.append_child(cnull) == STATUS_BAD_ARGUMENTS);
285         UTEST_ASSERT(p.equals(TEST_PATH3));
286 
287         p.clear();
288         UTEST_ASSERT(sstr.set_utf8("bin"));
289         UTEST_ASSERT(p.set(TEST_PATH4) == STATUS_OK);
290         UTEST_ASSERT(p.append_child(&sstr) == STATUS_OK);
291         UTEST_ASSERT(p.append_child(snull) == STATUS_BAD_ARGUMENTS);
292         UTEST_ASSERT(p.equals(TEST_PATH3));
293 
294         p.clear();
295         UTEST_ASSERT(p.set(TEST_PATH4) == STATUS_OK);
296         UTEST_ASSERT(spath.set(&sstr) == STATUS_OK);
297         UTEST_ASSERT(p.append_child(&spath) == STATUS_OK);
298         UTEST_ASSERT(p.append_child(pnull) == STATUS_BAD_ARGUMENTS);
299         UTEST_ASSERT(p.equals(TEST_PATH3));
300 
301         UTEST_ASSERT(sstr.set_utf8(TEST_ROOT));
302         UTEST_ASSERT(spath.set(&sstr) == STATUS_OK);
303         UTEST_ASSERT(p.append_child(TEST_ROOT) == STATUS_INVALID_VALUE);
304         UTEST_ASSERT(p.append_child(&sstr) == STATUS_INVALID_VALUE);
305         UTEST_ASSERT(p.append_child(&spath) == STATUS_INVALID_VALUE);
306 
307         sstr.clear();
308         spath.clear();
309         UTEST_ASSERT(p.append_child("") == STATUS_OK);
310         UTEST_ASSERT(p.append_child(&sstr) == STATUS_OK);
311         UTEST_ASSERT(p.append_child(&spath) == STATUS_OK);
312         UTEST_ASSERT(p.equals(TEST_PATH3));
313     }
314 
315 //    status_t    remove_last();
316 //    status_t    remove_last(char *path, size_t maxlen);
317 //    status_t    remove_last(LSPString *path);
318 //    status_t    remove_last(Path *path);
test_remove_last()319     void test_remove_last()
320     {
321         Path p;
322         char path[PATH_MAX];
323         LSPString sstr, xstr;
324         Path spath;
325 
326         UTEST_ASSERT(p.set(TEST_PATH2) == STATUS_OK);
327         UTEST_ASSERT(p.remove_last(path, PATH_MAX) == STATUS_OK);
328         UTEST_ASSERT(p.remove_last(cnull, PATH_MAX) == STATUS_BAD_ARGUMENTS);
329         UTEST_ASSERT(p.remove_last(path, 3) == STATUS_TOO_BIG);
330         UTEST_ASSERT(p.equals(TEST_PATH2));
331         UTEST_ASSERT(strcmp(path, TEST_PATH4) == 0);
332 
333         UTEST_ASSERT(xstr.set_utf8(TEST_PATH4));
334         UTEST_ASSERT(p.set(TEST_PATH2) == STATUS_OK);
335         UTEST_ASSERT(p.remove_last(&sstr) == STATUS_OK);
336         UTEST_ASSERT(p.remove_last(snull) == STATUS_BAD_ARGUMENTS);
337         UTEST_ASSERT(p.equals(TEST_PATH2));
338         UTEST_ASSERT(sstr.equals(&xstr));
339 
340         UTEST_ASSERT(p.set(TEST_PATH2) == STATUS_OK);
341         UTEST_ASSERT(p.remove_last(&spath) == STATUS_OK);
342         UTEST_ASSERT(p.remove_last(pnull) == STATUS_BAD_ARGUMENTS);
343         UTEST_ASSERT(p.equals(TEST_PATH2));
344         UTEST_ASSERT(spath.equals(&xstr));
345 
346         UTEST_ASSERT(p.set(TEST_PATH2) == STATUS_OK);
347         UTEST_ASSERT(p.remove_last() == STATUS_OK);
348         UTEST_ASSERT(p.equals(TEST_PATH4));
349 
350         UTEST_ASSERT(p.set(TEST_ROOT) == STATUS_OK);
351         UTEST_ASSERT(p.remove_last() == STATUS_OK);
352         UTEST_ASSERT(p.equals(TEST_ROOT));
353     }
354 
355 //    status_t    remove_base(const char *path);
356 //    status_t    remove_base(const LSPString *path);
357 //    status_t    remove_base(const Path *path);
test_remove_base()358     void test_remove_base()
359     {
360         Path p, xp;
361         LSPString xs;
362 
363         UTEST_ASSERT(p.set(TEST_PATH3) == STATUS_OK);
364         UTEST_ASSERT(p.remove_base(TEST_PATH4) == STATUS_OK);
365         UTEST_ASSERT(p.remove_base(cnull) == STATUS_BAD_ARGUMENTS);
366         UTEST_ASSERT(p.equals("bin"));
367 
368         UTEST_ASSERT(p.set(TEST_PATH3) == STATUS_OK);
369         UTEST_ASSERT(p.remove_base(TEST_PATH3) == STATUS_OK);
370         UTEST_ASSERT(p.is_empty());
371 
372         UTEST_ASSERT(xs.set_utf8(TEST_PATH4));
373         UTEST_ASSERT(p.set(TEST_PATH3) == STATUS_OK);
374         UTEST_ASSERT(p.remove_base(&xs) == STATUS_OK);
375         UTEST_ASSERT(p.remove_base(snull) == STATUS_BAD_ARGUMENTS);
376         UTEST_ASSERT(p.equals("bin"));
377 
378         UTEST_ASSERT(xs.set_utf8(TEST_PATH3));
379         UTEST_ASSERT(p.set(TEST_PATH3) == STATUS_OK);
380         UTEST_ASSERT(p.remove_base(&xs) == STATUS_OK);
381         UTEST_ASSERT(p.is_empty());
382 
383         UTEST_ASSERT(xp.set(TEST_PATH4) == STATUS_OK);
384         UTEST_ASSERT(p.set(TEST_PATH3) == STATUS_OK);
385         UTEST_ASSERT(p.remove_base(&xp) == STATUS_OK);
386         UTEST_ASSERT(p.remove_base(pnull) == STATUS_BAD_ARGUMENTS);
387         UTEST_ASSERT(p.equals("bin"));
388 
389         UTEST_ASSERT(xp.set(TEST_PATH3) == STATUS_OK);
390         UTEST_ASSERT(p.set(TEST_PATH3) == STATUS_OK);
391         UTEST_ASSERT(p.remove_base(&xp) == STATUS_OK);
392         UTEST_ASSERT(p.is_empty());
393     }
394 
395 //    void        clear()
396 //    bool        is_absolute() const;
397 //    bool        is_relative() const;
398 //    bool        is_empty() const
399 //    bool        is_root() const;
400 //    status_t    root();
test_flags()401     void test_flags()
402     {
403         Path p;
404 
405         UTEST_ASSERT(!p.is_absolute());
406         UTEST_ASSERT(p.is_relative());
407         UTEST_ASSERT(p.is_empty());
408         UTEST_ASSERT(!p.is_root());
409         UTEST_ASSERT(p.root() == STATUS_BAD_STATE);
410 
411         UTEST_ASSERT(p.set(TEST_ROOT) == STATUS_OK);
412         UTEST_ASSERT(p.is_absolute());
413         UTEST_ASSERT(!p.is_relative());
414         UTEST_ASSERT(!p.is_empty());
415         UTEST_ASSERT(p.is_root());
416         UTEST_ASSERT(p.root() == STATUS_OK);
417         UTEST_ASSERT(p.equals(TEST_ROOT));
418 
419         UTEST_ASSERT(p.set(TEST_PATH1) == STATUS_OK);
420         UTEST_ASSERT(p.is_absolute());
421         UTEST_ASSERT(!p.is_relative());
422         UTEST_ASSERT(!p.is_empty());
423         UTEST_ASSERT(!p.is_root());
424         UTEST_ASSERT(p.root() == STATUS_OK);
425         UTEST_ASSERT(p.equals(TEST_ROOT));
426         UTEST_ASSERT(p.is_root());
427 
428         UTEST_ASSERT(p.set("bin") == STATUS_OK);
429         UTEST_ASSERT(!p.is_absolute());
430         UTEST_ASSERT(p.is_relative());
431         UTEST_ASSERT(!p.is_empty());
432         UTEST_ASSERT(!p.is_root());
433         UTEST_ASSERT(p.root() == STATUS_BAD_STATE);
434         UTEST_ASSERT(!p.equals(TEST_ROOT));
435         UTEST_ASSERT(!p.is_root());
436     }
437 
438 //    status_t    get_canonical(char *path, size_t maxlen) const;
439 //    status_t    get_canonical(LSPString *path) const;
440 //    status_t    get_canonical(Path *path) const;
441 //    bool        is_canonical() const;
442 //    status_t    canonicalize();
test_canonical()443     void test_canonical()
444     {
445         Path p, xp;
446         LSPString xs;
447         char path[PATH_MAX];
448 
449 //        UTEST_ASSERT(p.set(TEST_PATH1) == STATUS_OK);
450 //        UTEST_ASSERT(p.is_canonical());
451 //        UTEST_ASSERT(p.set(TEST_ROOT) == STATUS_OK);
452 //        UTEST_ASSERT(p.is_canonical());
453 //        p.clear();
454 //        UTEST_ASSERT(p.is_canonical());
455 
456         for (const char **cp=cpaths; *cp != NULL; cp += 2)
457         {
458             printf("Testing \"%s\" -> \"%s\"\n", cp[0], cp[1]);
459             UTEST_ASSERT(p.set(cp[0]) == STATUS_OK);
460             UTEST_ASSERT(!p.is_canonical());
461 
462             UTEST_ASSERT(p.get_canonical(path, PATH_MAX) == STATUS_OK);
463             UTEST_ASSERT(p.get_canonical(cnull, PATH_MAX) == STATUS_BAD_ARGUMENTS);
464             UTEST_ASSERT_MSG(strcmp(path, cp[1]) == 0, "canonicalized: \"%s\" -> \"%s\"\n", p.get(), path);
465             UTEST_ASSERT(p.equals(cp[0]));
466 
467             UTEST_ASSERT(p.get_canonical(&xp) == STATUS_OK);
468             UTEST_ASSERT(p.get_canonical(pnull) == STATUS_BAD_ARGUMENTS);
469             UTEST_ASSERT_MSG(xp.equals(cp[1]), "canonicalized: \"%s\" -> \"%s\"\n", p.get(), xp.get());
470             UTEST_ASSERT(p.equals(cp[0]));
471 
472             UTEST_ASSERT(p.get_canonical(&xs) == STATUS_OK);
473             UTEST_ASSERT(p.get_canonical(snull) == STATUS_BAD_ARGUMENTS);
474             UTEST_ASSERT_MSG(xp.equals(&xs), "canonicalized: \"%s\" -> \"%s\"\n", p.get(), xs.get_utf8());
475             UTEST_ASSERT(p.equals(cp[0]));
476 
477             UTEST_ASSERT_MSG(p.canonicalize() == STATUS_OK, "canonicalized: \"%s\" -> \"%s\"\n", cp[0], p.get());
478             UTEST_ASSERT(p.is_canonical());
479             UTEST_ASSERT(p.equals(cp[1]));
480         }
481     }
482 
483     UTEST_MAIN
484     {
485         test_get_set();
486         test_get_set_last();
487         test_get_set_parent();
488         test_concat();
489         test_append_child();
490         test_remove_last();
491         test_remove_base();
492         test_flags();
493         test_canonical();
494     }
495 UTEST_END;
496 
497 
498 
499