2 * path-test.c -- test the path functions
4 * ====================================================================
5 * Copyright (c) 2000-2006 CollabNet. All rights reserved.
7 * This software is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at http://subversion.tigris.org/license-1.html.
10 * If newer versions of this license are posted there, you may use a
11 * newer version instead, at your option.
13 * This software consists of voluntary contributions made by many
14 * individuals. For exact contribution history, see the revision
15 * history and logs, available at http://subversion.tigris.org/.
16 * ====================================================================
21 #include "svn_pools.h"
23 #include <apr_general.h>
25 #include "../svn_test.h"
27 /* Using a symbol, because I tried experimenting with different
29 #define SVN_EMPTY_PATH ""
32 test_path_is_child(const char **msg
,
33 svn_boolean_t msg_only
,
34 svn_test_opts_t
*opts
,
39 /* The path checking code is platform specific, so we shouldn't run
40 the Windows path handling testcases on non-Windows platforms.
42 #define NUM_TEST_PATHS 11
44 static const char * const paths
[NUM_TEST_PATHS
] = {
50 "/foo/bar/baz/bing/boom",
58 static const char * const remainders
[NUM_TEST_PATHS
][NUM_TEST_PATHS
] = {
59 { 0, 0, 0, "baz", 0, "baz/bing/boom", 0, 0, 0, 0, 0 },
60 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
61 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
62 { 0, 0, 0, 0, 0, "bing/boom", 0, 0, 0, 0, 0 },
63 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
64 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
65 { 0, 0, 0, 0, 0, 0, 0, "foo", ".foo", 0, "foo2" },
66 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
67 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
68 { "foo/bar", "foo/bars", "foo/baz", "foo/bar/baz", "flu/blar/blaz",
69 "foo/bar/baz/bing/boom", 0, 0, 0, 0, 0 },
70 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
73 *msg
= "test svn_path_is_child";
78 for (i
= 0; i
< NUM_TEST_PATHS
; i
++)
80 for (j
= 0; j
< NUM_TEST_PATHS
; j
++)
82 const char *remainder
;
84 remainder
= svn_path_is_child(paths
[i
], paths
[j
], pool
);
86 if (((remainder
) && (! remainders
[i
][j
]))
87 || ((! remainder
) && (remainders
[i
][j
]))
88 || (remainder
&& strcmp(remainder
, remainders
[i
][j
])))
89 return svn_error_createf
90 (SVN_ERR_TEST_FAILED
, NULL
,
91 "svn_path_is_child (%s, %s) returned '%s' instead of '%s'",
93 remainder
? remainder
: "(null)",
94 remainders
[i
][j
] ? remainders
[i
][j
] : "(null)" );
103 test_path_split(const char **msg
,
104 svn_boolean_t msg_only
,
105 svn_test_opts_t
*opts
,
110 static const char * const paths
[][3] = {
111 { "/foo/bar", "/foo", "bar" },
112 { "/foo/bar/ ", "/foo/bar", " " },
113 { "/foo", "/", "foo" },
114 { "foo", SVN_EMPTY_PATH
, "foo" },
115 { ".bar", SVN_EMPTY_PATH
, ".bar" },
116 { "/.bar", "/", ".bar" },
117 { "foo/bar", "foo", "bar" },
118 { "/foo/bar", "/foo", "bar" },
119 { "foo/bar", "foo", "bar" },
120 { "foo./.bar", "foo.", ".bar" },
121 { "../foo", "..", "foo" },
122 { SVN_EMPTY_PATH
, SVN_EMPTY_PATH
, SVN_EMPTY_PATH
},
123 { "/flu\\b/\\blarg", "/flu\\b", "\\blarg" },
127 *msg
= "test svn_path_split";
132 for (i
= 0; i
< sizeof(paths
) / sizeof(paths
[0]); i
++)
134 const char *dir
, *base_name
;
136 svn_path_split(paths
[i
][0], &dir
, &base_name
, pool
);
137 if (strcmp(dir
, paths
[i
][1]))
139 return svn_error_createf
140 (SVN_ERR_TEST_FAILED
, NULL
,
141 "svn_path_split (%s) returned dirname '%s' instead of '%s'",
142 paths
[i
][0], dir
, paths
[i
][1]);
144 if (strcmp(base_name
, paths
[i
][2]))
146 return svn_error_createf
147 (SVN_ERR_TEST_FAILED
, NULL
,
148 "svn_path_split (%s) returned basename '%s' instead of '%s'",
149 paths
[i
][0], base_name
, paths
[i
][2]);
157 test_is_url(const char **msg
,
158 svn_boolean_t msg_only
,
159 svn_test_opts_t
*opts
,
164 /* Paths to test and their expected results. */
167 svn_boolean_t result
;
170 { "/blah/blah", FALSE
},
171 { "//blah/blah", FALSE
},
172 { "://blah/blah", FALSE
},
173 { "a:abb://boo/", FALSE
},
174 { "http://svn.collab.net/repos/svn", TRUE
},
175 { "scheme/with", FALSE
},
176 { "scheme/with:", FALSE
},
177 { "scheme/with:/", FALSE
},
178 { "scheme/with://", FALSE
},
179 { "scheme/with://slash/", FALSE
},
180 { "file:///path/to/repository", TRUE
},
187 *msg
= "test svn_path_is_url";
192 for (i
= 0; i
< sizeof(tests
) / sizeof(tests
[0]); i
++)
194 svn_boolean_t retval
;
196 retval
= svn_path_is_url(tests
[i
].path
);
197 if (tests
[i
].result
!= retval
)
198 return svn_error_createf
199 (SVN_ERR_TEST_FAILED
, NULL
,
200 "svn_path_is_url (%s) returned %s instead of %s",
201 tests
[i
].path
, retval
? "TRUE" : "FALSE",
202 tests
[i
].result
? "TRUE" : "FALSE");
210 test_is_uri_safe(const char **msg
,
211 svn_boolean_t msg_only
,
212 svn_test_opts_t
*opts
,
217 /* Paths to test and their expected results. */
220 svn_boolean_t result
;
222 { "http://svn.collab.net/repos", TRUE
},
223 { "http://svn.collab.net/repos%", FALSE
},
224 { "http://svn.collab.net/repos%/svn", FALSE
},
225 { "http://svn.collab.net/repos%2g", FALSE
},
226 { "http://svn.collab.net/repos%2g/svn", FALSE
},
227 { "http://svn.collab.net/repos%%", FALSE
},
228 { "http://svn.collab.net/repos%%/svn", FALSE
},
229 { "http://svn.collab.net/repos%2a", TRUE
},
230 { "http://svn.collab.net/repos%2a/svn", TRUE
},
233 *msg
= "test svn_path_is_uri_safe";
238 for (i
= 0; i
< (sizeof(tests
) / sizeof(tests
[0])); i
++)
240 svn_boolean_t retval
;
242 retval
= svn_path_is_uri_safe(tests
[i
].path
);
243 if (tests
[i
].result
!= retval
)
244 return svn_error_createf
245 (SVN_ERR_TEST_FAILED
, NULL
,
246 "svn_path_is_uri_safe (%s) returned %s instead of %s",
247 tests
[i
].path
, retval
? "TRUE" : "FALSE",
248 tests
[i
].result
? "TRUE" : "FALSE");
256 test_uri_encode(const char **msg
,
257 svn_boolean_t msg_only
,
258 svn_test_opts_t
*opts
,
267 { "http://subversion.tigris.org",
268 "http://subversion.tigris.org"},
269 { " special_at_beginning",
270 "%20special_at_beginning" },
272 "special_at_end%20" },
273 { "special in middle",
274 "special%20in%20middle" },
275 { "\"Ouch!\" \"Did that hurt?\"",
276 "%22Ouch!%22%20%20%22Did%20that%20hurt%3F%22" }
279 *msg
= "test svn_path_uri_[en/de]code";
284 for (i
= 0; i
< 5; i
++)
286 const char *en_path
, *de_path
;
288 /* URI-encode the path, and verify the results. */
289 en_path
= svn_path_uri_encode(tests
[i
].path
, pool
);
290 if (strcmp(en_path
, tests
[i
].result
))
292 return svn_error_createf
293 (SVN_ERR_TEST_FAILED
, NULL
,
294 "svn_path_uri_encode ('%s') returned '%s' instead of '%s'",
295 tests
[i
].path
, en_path
, tests
[i
].result
);
298 /* URI-decode the path, and make sure we're back where we started. */
299 de_path
= svn_path_uri_decode(en_path
, pool
);
300 if (strcmp(de_path
, tests
[i
].path
))
302 return svn_error_createf
303 (SVN_ERR_TEST_FAILED
, NULL
,
304 "svn_path_uri_decode ('%s') returned '%s' instead of '%s'",
305 tests
[i
].result
, de_path
, tests
[i
].path
);
313 test_uri_decode(const char **msg
,
314 svn_boolean_t msg_only
,
315 svn_test_opts_t
*opts
,
324 { "http://c.r.a/s%\0008me",
326 { "http://c.r.a/s%6\000me",
327 "http://c.r.a/s%6" },
328 { "http://c.r.a/s%68me",
329 "http://c.r.a/shme" },
332 *msg
= "test svn_path_uri_decode with invalid escape";
337 for (i
= 0; i
< 3; i
++)
341 /* URI-decode the path, and verify the results. */
342 de_path
= svn_path_uri_decode(tests
[i
].path
, pool
);
343 if (strcmp(de_path
, tests
[i
].result
))
345 return svn_error_createf
346 (SVN_ERR_TEST_FAILED
, NULL
,
347 "svn_path_uri_decode ('%s') returned '%s' instead of '%s'",
348 tests
[i
].path
, de_path
, tests
[i
].result
);
356 test_uri_autoescape(const char **msg
,
357 svn_boolean_t msg_only
,
358 svn_test_opts_t
*opts
,
365 { "http://svn.collab.net/", "http://svn.collab.net/" },
366 { "file:///<>\" {}|\\^`", "file:///%3C%3E%22%20%7B%7D%7C%5C%5E%60" },
367 { "http://[::1]", "http://[::1]" }
371 *msg
= "test svn_path_uri_autoescape";
376 for (i
= 0; i
< 3; ++i
)
378 const char* uri
= svn_path_uri_autoescape(tests
[i
].path
, pool
);
379 if (strcmp(uri
, tests
[i
].result
) != 0)
380 return svn_error_createf
381 (SVN_ERR_TEST_FAILED
, NULL
,
382 "svn_path_uri_autoescape on '%s' returned '%s' instead of '%s'",
383 tests
[i
].path
, uri
, tests
[i
].result
);
384 if (strcmp(tests
[i
].path
, tests
[i
].result
) == 0
385 && tests
[i
].path
!= uri
)
386 return svn_error_createf
387 (SVN_ERR_TEST_FAILED
, NULL
,
388 "svn_path_uri_autoescape on '%s' returned identical but not same"
389 " string", tests
[i
].path
);
396 test_uri_from_iri(const char **msg
,
397 svn_boolean_t msg_only
,
398 svn_test_opts_t
*opts
,
401 /* We have to code the IRIs like this because the compiler might translate
402 character and string literals outside of ASCII to some character set,
403 but here we are hard-coding UTF-8. But we all read UTF-8 codes like
405 static const char p1
[] = {
406 '\x66', '\x69', '\x6C', '\x65', '\x3A', '\x2F', '\x2F', '\x2F',
407 '\x72', '\xC3', '\xA4', '\x6B', '\x73', '\x6D', '\xC3', '\xB6', '\x72',
408 '\x67', '\xC3', '\xA5', '\x73', '\0' };
409 static const char p2
[] = {
410 '\x66', '\x69', '\x6C', '\x65', '\x3A', '\x2F', '\x2F', '\x2F',
411 '\x61', '\x62', '\x25', '\x32', '\x30', '\x63', '\x64', '\0' };
412 static const char *paths
[2][2] = {
414 "file:///r%C3%A4ksm%C3%B6rg%C3%A5s" },
420 *msg
= "test svn_path_uri_from_iri";
425 for (i
= 0; i
< 2; ++i
)
427 const char *uri
= svn_path_uri_from_iri(paths
[i
][0], pool
);
428 if (strcmp(paths
[i
][1], uri
) != 0)
429 return svn_error_createf
430 (SVN_ERR_TEST_FAILED
, NULL
,
431 "svn_path_uri_from_iri on '%s' returned '%s' instead of '%s'",
432 paths
[i
][0], uri
, paths
[i
][1]);
433 if (strcmp(paths
[i
][0], uri
) == 0
434 && paths
[i
][0] != uri
)
435 return svn_error_createf
436 (SVN_ERR_TEST_FAILED
, NULL
,
437 "svn_path_uri_from_iri on '%s' returned identical but not same"
438 " string", paths
[i
][0]);
445 test_join(const char **msg
,
446 svn_boolean_t msg_only
,
447 svn_test_opts_t
*opts
,
453 static const char * const joins
[][3] = {
454 { "abc", "def", "abc/def" },
455 { "a", "def", "a/def" },
458 { "/abc", "d", "/abc/d" },
459 { "/abc", "def", "/abc/def" },
460 { "/abc", "/def", "/def" },
461 { "/abc", "/d", "/d" },
462 { "/abc", "/", "/" },
463 { SVN_EMPTY_PATH
, "/", "/" },
464 { "/", SVN_EMPTY_PATH
, "/" },
465 { SVN_EMPTY_PATH
, "abc", "abc" },
466 { "abc", SVN_EMPTY_PATH
, "abc" },
467 { SVN_EMPTY_PATH
, "/abc", "/abc" },
468 { SVN_EMPTY_PATH
, SVN_EMPTY_PATH
, SVN_EMPTY_PATH
},
471 *msg
= "test svn_path_join(_many)";
475 for (i
= sizeof(joins
) / sizeof(joins
[0]); i
--; )
477 const char *base
= joins
[i
][0];
478 const char *comp
= joins
[i
][1];
479 const char *expect
= joins
[i
][2];
481 result
= svn_path_join(base
, comp
, pool
);
482 if (strcmp(result
, expect
))
483 return svn_error_createf(SVN_ERR_TEST_FAILED
, NULL
,
484 "svn_path_join(\"%s\", \"%s\") returned "
485 "\"%s\". expected \"%s\"",
486 base
, comp
, result
, expect
);
488 result
= svn_path_join_many(pool
, base
, comp
, NULL
);
489 if (strcmp(result
, expect
))
490 return svn_error_createf(SVN_ERR_TEST_FAILED
, NULL
,
491 "svn_path_join_many(\"%s\", \"%s\") returned "
492 "\"%s\". expected \"%s\"",
493 base
, comp
, result
, expect
);
496 #define TEST_MANY(args, expect) \
497 result = svn_path_join_many args ; \
498 if (strcmp(result, expect) != 0) \
499 return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, \
500 "svn_path_join_many" #args " returns \"%s\". " \
505 TEST_MANY((pool
, "abc", NULL
), "abc");
506 TEST_MANY((pool
, "/abc", NULL
), "/abc");
507 TEST_MANY((pool
, "/", NULL
), "/");
509 TEST_MANY((pool
, "abc", "def", "ghi", NULL
), "abc/def/ghi");
510 TEST_MANY((pool
, "abc", "/def", "ghi", NULL
), "/def/ghi");
511 TEST_MANY((pool
, "/abc", "def", "ghi", NULL
), "/abc/def/ghi");
512 TEST_MANY((pool
, "abc", "def", "/ghi", NULL
), "/ghi");
513 TEST_MANY((pool
, "/", "def", "/ghi", NULL
), "/ghi");
514 TEST_MANY((pool
, "/", "/def", "/ghi", NULL
), "/ghi");
516 TEST_MANY((pool
, SVN_EMPTY_PATH
, "def", "ghi", NULL
), "def/ghi");
517 TEST_MANY((pool
, "abc", SVN_EMPTY_PATH
, "ghi", NULL
), "abc/ghi");
518 TEST_MANY((pool
, "abc", "def", SVN_EMPTY_PATH
, NULL
), "abc/def");
519 TEST_MANY((pool
, SVN_EMPTY_PATH
, "def", SVN_EMPTY_PATH
, NULL
), "def");
520 TEST_MANY((pool
, SVN_EMPTY_PATH
, SVN_EMPTY_PATH
, "ghi", NULL
), "ghi");
521 TEST_MANY((pool
, "abc", SVN_EMPTY_PATH
, SVN_EMPTY_PATH
, NULL
), "abc");
522 TEST_MANY((pool
, SVN_EMPTY_PATH
, "def", "/ghi", NULL
), "/ghi");
523 TEST_MANY((pool
, SVN_EMPTY_PATH
, SVN_EMPTY_PATH
, "/ghi", NULL
), "/ghi");
525 TEST_MANY((pool
, "/", "def", "ghi", NULL
), "/def/ghi");
526 TEST_MANY((pool
, "abc", "/", "ghi", NULL
), "/ghi");
527 TEST_MANY((pool
, "abc", "def", "/", NULL
), "/");
528 TEST_MANY((pool
, "/", "/", "ghi", NULL
), "/ghi");
529 TEST_MANY((pool
, "/", "/", "/", NULL
), "/");
530 TEST_MANY((pool
, "/", SVN_EMPTY_PATH
, "ghi", NULL
), "/ghi");
531 TEST_MANY((pool
, "/", "def", SVN_EMPTY_PATH
, NULL
), "/def");
532 TEST_MANY((pool
, SVN_EMPTY_PATH
, "/", "ghi", NULL
), "/ghi");
533 TEST_MANY((pool
, "/", SVN_EMPTY_PATH
, SVN_EMPTY_PATH
, NULL
), "/");
534 TEST_MANY((pool
, SVN_EMPTY_PATH
, "/", SVN_EMPTY_PATH
, NULL
), "/");
535 TEST_MANY((pool
, SVN_EMPTY_PATH
, SVN_EMPTY_PATH
, "/", NULL
), "/");
537 /* ### probably need quite a few more tests... */
544 test_basename(const char **msg
,
545 svn_boolean_t msg_only
,
546 svn_test_opts_t
*opts
,
560 { "/xx/abc", "abc" },
561 { "/xx/abc", "abc" },
562 { "/xx/abc", "abc" },
568 { SVN_EMPTY_PATH
, SVN_EMPTY_PATH
},
571 *msg
= "test svn_path_basename";
575 for (i
= sizeof(tests
) / sizeof(tests
[0]); i
--; )
577 const char *path
= tests
[i
].path
;
578 const char *expect
= tests
[i
].result
;
580 result
= svn_path_basename(path
, pool
);
581 if (strcmp(result
, expect
))
582 return svn_error_createf(SVN_ERR_TEST_FAILED
, NULL
,
583 "svn_path_basename(\"%s\") returned "
584 "\"%s\". expected \"%s\"",
585 path
, result
, expect
);
593 test_dirname(const char **msg
,
594 svn_boolean_t msg_only
,
595 svn_test_opts_t
*opts
,
608 { "/xx/abc", "/xx" },
613 { SVN_EMPTY_PATH
, SVN_EMPTY_PATH
},
616 *msg
= "test svn_path_dirname";
620 for (i
= sizeof(tests
) / sizeof(tests
[0]); i
--; )
622 const char *path
= tests
[i
].path
;
623 const char *expect
= tests
[i
].result
;
625 result
= svn_path_dirname(path
, pool
);
626 if (strcmp(result
, expect
))
627 return svn_error_createf(SVN_ERR_TEST_FAILED
, NULL
,
628 "svn_path_dirname(\"%s\") returned "
629 "\"%s\". expected \"%s\"",
630 path
, result
, expect
);
638 test_decompose(const char **msg
,
639 svn_boolean_t msg_only
,
640 svn_test_opts_t
*opts
,
643 static const char * const paths
[] = {
646 "/foo", "/", "foo", NULL
,
647 "/foo/bar", "/", "foo", "bar", NULL
,
648 "foo/bar", "foo", "bar", NULL
,
650 /* Are these canonical? Should the middle bits produce SVN_EMPTY_PATH? */
651 "foo/bar", "foo", "bar", NULL
,
656 *msg
= "test svn_path_decompose";
666 apr_array_header_t
*components
= svn_path_decompose(paths
[i
], pool
);
668 for (j
= 0; j
< components
->nelts
; ++j
)
670 const char *component
= APR_ARRAY_IDX(components
,
674 return svn_error_createf(SVN_ERR_TEST_FAILED
, NULL
,
675 "svn_path_decompose(\"%s\") returned "
676 "unexpected component \"%s\"",
677 paths
[i
], component
);
678 if (strcmp(component
, paths
[i
+j
+1]))
679 return svn_error_createf(SVN_ERR_TEST_FAILED
, NULL
,
680 "svn_path_decompose(\"%s\") returned "
681 "\"%s\" expected \"%s\"",
682 paths
[i
], component
, paths
[i
+j
+1]);
685 return svn_error_createf(SVN_ERR_TEST_FAILED
, NULL
,
686 "svn_path_decompose(\"%s\") failed "
688 paths
[i
], paths
[i
+j
+1]);
689 i
+= components
->nelts
+ 2;
697 test_canonicalize(const char **msg
,
698 svn_boolean_t msg_only
,
699 svn_test_opts_t
*opts
,
715 { "////././.", "/" },
722 { "foo./.", "foo." },
723 { "foo././/.", "foo." },
724 { "/foo/bar", "/foo/bar" },
725 { "foo/..", "foo/.." },
726 { "foo/../", "foo/.." },
727 { "foo/../.", "foo/.." },
728 { "foo//.//bar", "foo/bar" },
729 { "///foo", "/foo" },
730 { "/.//./.foo", "/.foo" },
731 { ".///.foo", ".foo" },
732 { "../foo", "../foo" },
733 { "../../foo/", "../../foo" },
734 { "../../foo/..", "../../foo/.." },
735 { "/../../", "/../.." },
736 { "http://hst", "http://hst" },
737 { "http://hst/foo/../bar","http://hst/foo/../bar" },
738 { "http://hst/", "http://hst" },
743 *msg
= "test svn_path_canonicalize";
748 while (tests
[i
].path
)
750 const char *canonical
= svn_path_canonicalize(tests
[i
].path
, pool
);
752 if (strcmp(canonical
, tests
[i
].result
))
753 return svn_error_createf(SVN_ERR_TEST_FAILED
, NULL
,
754 "svn_path_canonicalize(\"%s\") returned "
755 "\"%s\" expected \"%s\"",
756 tests
[i
].path
, canonical
, tests
[i
].result
);
764 test_remove_component(const char **msg
,
765 svn_boolean_t msg_only
,
766 svn_test_opts_t
*opts
,
776 { "foo/bar", "foo" },
777 { "/foo/bar", "/foo" },
782 svn_stringbuf_t
*buf
;
784 *msg
= "test svn_path_remove_component";
788 buf
= svn_stringbuf_create("", pool
);
791 while (tests
[i
].path
)
793 svn_stringbuf_set(buf
, tests
[i
].path
);
795 svn_path_remove_component(buf
);
797 if (strcmp(buf
->data
, tests
[i
].result
))
798 return svn_error_createf(SVN_ERR_TEST_FAILED
, NULL
,
799 "svn_path_remove_component(\"%s\") returned "
800 "\"%s\" expected \"%s\"",
801 tests
[i
].path
, buf
->data
, tests
[i
].result
);
809 test_is_root(const char **msg
,
810 svn_boolean_t msg_only
,
811 svn_test_opts_t
*opts
,
816 /* Paths to test and their expected results. */
819 svn_boolean_t result
;
821 { "/foo/bar", FALSE
},
825 #if defined(WIN32) || defined(__CYGWIN__)
830 { "//srv/shr", TRUE
},
832 { "//srv/shr/fld", FALSE
},
833 #else /* WIN32 or Cygwin */
836 #endif /* non-WIN32 */
839 *msg
= "test svn_dirent_is_root";
844 for (i
= 0; i
< sizeof(tests
) / sizeof(tests
[0]); i
++)
846 svn_boolean_t retval
;
848 retval
= svn_dirent_is_root(tests
[i
].path
, strlen(tests
[i
].path
));
849 if (tests
[i
].result
!= retval
)
850 return svn_error_createf
851 (SVN_ERR_TEST_FAILED
, NULL
,
852 "svn_dirent_is_root (%s) returned %s instead of %s",
853 tests
[i
].path
, retval
? "TRUE" : "FALSE",
854 tests
[i
].result
? "TRUE" : "FALSE");
861 test_path_check_valid(const char **msg
,
862 svn_boolean_t msg_only
,
863 svn_test_opts_t
*opts
,
868 /* Paths to test and their expected results. */
871 svn_boolean_t result
;
873 { "/foo/bar", TRUE
},
878 { "foo\7bar", FALSE
},
879 { "foo\31bar", FALSE
},
880 { "\7foo\31bar", FALSE
},
885 *msg
= "test svn_path_check_valid";
890 for (i
= 0; i
< sizeof(tests
) / sizeof(tests
[0]); i
++)
892 svn_error_t
*err
= svn_path_check_valid(tests
[i
].path
, pool
);
893 svn_boolean_t retval
= (err
== SVN_NO_ERROR
);
895 svn_error_clear(err
);
896 if (tests
[i
].result
!= retval
)
897 return svn_error_createf
898 (SVN_ERR_TEST_FAILED
, NULL
,
899 "svn_path_check_valid (%s) returned %s instead of %s",
900 tests
[i
].path
, retval
? "TRUE" : "FALSE",
901 tests
[i
].result
? "TRUE" : "FALSE");
908 test_path_is_ancestor(const char **msg
,
909 svn_boolean_t msg_only
,
910 svn_test_opts_t
*opts
,
915 /* Paths to test and their expected results. */
919 svn_boolean_t result
;
921 { "/foo", "/foo/bar", TRUE
},
922 { "/foo/bar", "/foo/bar/", TRUE
},
923 { "/", "/foo", TRUE
},
924 { SVN_EMPTY_PATH
, "foo", TRUE
},
925 { SVN_EMPTY_PATH
, ".bar", TRUE
},
927 { "/.bar", "/", FALSE
},
928 { "foo/bar", "foo", FALSE
},
929 { "/foo/bar", "/foo", FALSE
},
930 { "foo", "foo/bar", TRUE
},
931 { "foo.", "foo./.bar", TRUE
},
933 { "../foo", "..", FALSE
},
934 { SVN_EMPTY_PATH
, SVN_EMPTY_PATH
, TRUE
},
937 { "http://test", "http://test", TRUE
},
938 { "http://test", "http://taste", FALSE
},
939 { "http://test", "http://test/foo", TRUE
},
940 { "http://test", "file://test/foo", FALSE
},
941 { "http://test", "http://testF", FALSE
},
943 TODO: this testcase fails, showing that svn_path_is_ancestor
944 shouldn't be used on urls. This is related to issue #1711.
946 { "http://", "http://test", FALSE},
950 *msg
= "test svn_path_is_ancestor";
955 for (i
= 0; i
< sizeof(tests
) / sizeof(tests
[0]); i
++)
957 svn_boolean_t retval
;
959 retval
= svn_path_is_ancestor(tests
[i
].path1
, tests
[i
].path2
);
960 if (tests
[i
].result
!= retval
)
961 return svn_error_createf
962 (SVN_ERR_TEST_FAILED
, NULL
,
963 "svn_path_is_ancestor (%s, %s) returned %s instead of %s",
964 tests
[i
].path1
, tests
[i
].path2
, retval
? "TRUE" : "FALSE",
965 tests
[i
].result
? "TRUE" : "FALSE");
971 test_is_single_path_component(const char **msg
,
972 svn_boolean_t msg_only
,
973 svn_test_opts_t
*opts
,
978 /* Paths to test and their expected results. */
981 svn_boolean_t result
;
983 { "/foo/bar", FALSE
},
986 { "foo/bar", FALSE
},
993 *msg
= "test svn_path_is_single_path_component";
998 for (i
= 0; i
< sizeof(tests
) / sizeof(tests
[0]); i
++)
1000 svn_boolean_t retval
;
1002 retval
= svn_path_is_single_path_component(tests
[i
].path
);
1003 if (tests
[i
].result
!= retval
)
1004 return svn_error_createf
1005 (SVN_ERR_TEST_FAILED
, NULL
,
1006 "svn_path_is_single_path_component (%s) returned %s instead of %s",
1007 tests
[i
].path
, retval
? "TRUE" : "FALSE",
1008 tests
[i
].result
? "TRUE" : "FALSE");
1011 return SVN_NO_ERROR
;
1014 static svn_error_t
*
1015 test_compare_paths(const char **msg
,
1016 svn_boolean_t msg_only
,
1017 svn_test_opts_t
*opts
,
1022 /* Paths to test and their expected results. */
1028 { "/foo", "/foo", 0},
1029 { "/foo/bar", "/foo/bar", 0},
1031 { SVN_EMPTY_PATH
, SVN_EMPTY_PATH
, 0},
1033 { "foo", "foo/bar", -1},
1034 { "foo/bar", "foo/boo", -1},
1035 { "boo", "foo", -1},
1037 { "foo/bar", "foo", 1},
1039 { "/foo", "/foo/bar", -1},
1040 { "/foo", "/foo/bar/boo", -1},
1041 { "foo", "/foo", 1},
1042 { "foo\xe0""bar", "foo", 1},
1045 *msg
= "test svn_path_compare_paths";
1048 return SVN_NO_ERROR
;
1050 for (i
= 0; i
< sizeof(tests
) / sizeof(tests
[0]); i
++)
1054 retval
= svn_path_compare_paths(tests
[i
].path1
, tests
[i
].path2
);
1055 /* tests if expected and actual result are both < 0,
1056 equal to 0 or greater than 0. */
1057 if (! (tests
[i
].result
* retval
> 0 ||
1058 (tests
[i
].result
== 0 && retval
== 0)) )
1059 return svn_error_createf
1060 (SVN_ERR_TEST_FAILED
, NULL
,
1061 "svn_path_compare_paths (%s, %s) returned %d instead of %d",
1062 tests
[i
].path1
, tests
[i
].path2
, retval
, tests
[i
].result
);
1064 return SVN_NO_ERROR
;
1067 static svn_error_t
*
1068 test_get_longest_ancestor(const char **msg
,
1069 svn_boolean_t msg_only
,
1070 svn_test_opts_t
*opts
,
1075 /* Paths to test and their expected results. */
1081 { "/foo", "/foo/bar", "/foo"},
1082 { "/foo/bar", "foo/bar", ""},
1083 { "/", "/foo", "/"},
1084 { SVN_EMPTY_PATH
, "foo", SVN_EMPTY_PATH
},
1085 { SVN_EMPTY_PATH
, ".bar", SVN_EMPTY_PATH
},
1086 { "/.bar", "/", "/"},
1087 { "foo/bar", "foo", "foo"},
1088 { "/foo/bar", "/foo", "/foo"},
1089 { "/rif", "/raf", "/"},
1090 { "foo", "foo/bar", "foo"},
1091 { "foo.", "foo./.bar", "foo."},
1092 { SVN_EMPTY_PATH
, SVN_EMPTY_PATH
, SVN_EMPTY_PATH
},
1094 { "http://test", "http://test", "http://test"},
1095 { "http://test", "http://taste", ""},
1096 { "http://test", "http://test/foo", "http://test"},
1097 { "http://test", "file://test/foo", ""},
1098 { "http://test", "http://testF", ""},
1099 { "http://", "http://test", ""},
1102 *msg
= "test svn_path_get_longest_ancestor";
1105 return SVN_NO_ERROR
;
1107 for (i
= 0; i
< sizeof(tests
) / sizeof(tests
[0]); i
++)
1111 retval
= svn_path_get_longest_ancestor(tests
[i
].path1
, tests
[i
].path2
,
1114 if (strcmp(tests
[i
].result
, retval
))
1115 return svn_error_createf
1116 (SVN_ERR_TEST_FAILED
, NULL
,
1117 "svn_path_get_longest_ancestor (%s, %s) returned %s instead of %s",
1118 tests
[i
].path1
, tests
[i
].path2
, retval
, tests
[i
].result
);
1120 /* changing the order of the paths should return the same results */
1121 retval
= svn_path_get_longest_ancestor(tests
[i
].path2
, tests
[i
].path1
,
1124 if (strcmp(tests
[i
].result
, retval
))
1125 return svn_error_createf
1126 (SVN_ERR_TEST_FAILED
, NULL
,
1127 "svn_path_get_longest_ancestor (%s, %s) returned %s instead of %s",
1128 tests
[i
].path2
, tests
[i
].path1
, retval
, tests
[i
].result
);
1130 return SVN_NO_ERROR
;
1134 static svn_error_t
*
1135 test_splitext(const char **msg
,
1136 svn_boolean_t msg_only
,
1137 svn_test_opts_t
*opts
,
1141 apr_pool_t
*subpool
= svn_pool_create(pool
);
1143 /* Paths to test and their expected results. */
1146 const char *path_root
;
1147 const char *path_ext
;
1148 svn_boolean_t result
;
1150 { "no-ext", "no-ext", "" },
1151 { "test-file.py", "test-file.", "py" },
1152 { "period.file.ext", "period.file.", "ext" },
1153 { "multi-component/file.txt", "multi-component/file.", "txt" },
1154 { "yep.still/no-ext", "yep.still/no-ext", "" },
1155 { "folder.with/period.log", "folder.with/period.", "log" },
1156 { "period.", "period.", "" },
1157 { "file.ends-with/period.", "file.ends-with/period.", "" },
1158 { "two-periods..txt", "two-periods..", "txt" },
1159 { ".dot-file", ".dot-file", "" },
1160 { "sub/.dot-file", "sub/.dot-file", "" },
1161 { ".dot-file.withext", ".dot-file.", "withext" },
1162 { "sub/.dot-file.withext", "sub/.dot-file.", "withext" },
1166 *msg
= "test svn_path_splitext";
1169 return SVN_NO_ERROR
;
1171 for (i
= 0; i
< sizeof(tests
) / sizeof(tests
[0]); i
++)
1173 const char *path
= tests
[i
].path
;
1174 const char *path_root
;
1175 const char *path_ext
;
1177 svn_pool_clear(subpool
);
1179 /* First, we'll try splitting and fetching both root and
1180 extension to see if they match our expected results. */
1181 svn_path_splitext(&path_root
, &path_ext
, path
, subpool
);
1182 if ((strcmp(tests
[i
].path_root
, path_root
))
1183 || (strcmp(tests
[i
].path_ext
, path_ext
)))
1184 return svn_error_createf
1185 (SVN_ERR_TEST_FAILED
, NULL
,
1186 "svn_path_splitext (%s) returned ('%s', '%s') "
1187 "instead of ('%s', '%s')",
1188 tests
[i
].path
, path_root
, path_ext
,
1189 tests
[i
].path_root
, tests
[i
].path_ext
);
1191 /* Now, let's only fetch the root. */
1192 svn_path_splitext(&path_root
, NULL
, path
, subpool
);
1193 if (strcmp(tests
[i
].path_root
, path_root
))
1194 return svn_error_createf
1195 (SVN_ERR_TEST_FAILED
, NULL
,
1196 "svn_path_splitext (%s) with a NULL path_ext returned '%s' "
1197 "for the path_root instead of '%s'",
1198 tests
[i
].path
, path_root
, tests
[i
].path_root
);
1200 /* Next, let's only fetch the extension. */
1201 svn_path_splitext(NULL
, &path_ext
, path
, subpool
);
1202 if ((strcmp(tests
[i
].path_root
, path_root
))
1203 || (strcmp(tests
[i
].path_ext
, path_ext
)))
1204 return svn_error_createf
1205 (SVN_ERR_TEST_FAILED
, NULL
,
1206 "svn_path_splitext (%s) with a NULL path_root returned '%s' "
1207 "for the path_ext instead of '%s'",
1208 tests
[i
].path
, path_ext
, tests
[i
].path_ext
);
1210 svn_pool_destroy(subpool
);
1211 return SVN_NO_ERROR
;
1215 static svn_error_t
*
1216 test_compose(const char **msg
,
1217 svn_boolean_t msg_only
,
1218 svn_test_opts_t
*opts
,
1221 static const char * const paths
[] = {
1232 const char * const *path_ptr
= paths
;
1233 const char *input_path
;
1235 *msg
= "test svn_path_decompose";
1237 return SVN_NO_ERROR
;
1239 for (input_path
= *path_ptr
; *path_ptr
; input_path
= *++path_ptr
)
1241 apr_array_header_t
*components
= svn_path_decompose(input_path
, pool
);
1242 const char *output_path
= svn_path_compose(components
, pool
);
1244 if (strcmp(input_path
, output_path
))
1245 return svn_error_createf(SVN_ERR_TEST_FAILED
, NULL
,
1247 "svn_path_decompose(\"%s\")) "
1248 "returned \"%s\" expected \"%s\"",
1249 input_path
, output_path
, input_path
);
1252 return SVN_NO_ERROR
;
1255 /* local define to support XFail-ing tests on Windows/Cygwin only */
1256 #if defined(WIN32) || defined(__CYGWIN__)
1257 #define WINDOWS_OR_CYGWIN TRUE
1259 #define WINDOWS_OR_CYGWIN FALSE
1260 #endif /* WIN32 or Cygwin */
1263 /* The test table. */
1265 struct svn_test_descriptor_t test_funcs
[] =
1268 SVN_TEST_PASS(test_path_is_child
),
1269 SVN_TEST_PASS(test_path_split
),
1270 SVN_TEST_PASS(test_is_url
),
1271 SVN_TEST_PASS(test_is_uri_safe
),
1272 SVN_TEST_PASS(test_uri_encode
),
1273 SVN_TEST_PASS(test_uri_decode
),
1274 SVN_TEST_PASS(test_uri_autoescape
),
1275 SVN_TEST_PASS(test_uri_from_iri
),
1276 SVN_TEST_PASS(test_join
),
1277 SVN_TEST_PASS(test_basename
),
1278 SVN_TEST_PASS(test_dirname
),
1279 SVN_TEST_PASS(test_decompose
),
1280 SVN_TEST_PASS(test_canonicalize
),
1281 SVN_TEST_PASS(test_remove_component
),
1282 SVN_TEST_PASS(test_is_root
),
1283 SVN_TEST_PASS(test_path_is_ancestor
),
1284 SVN_TEST_PASS(test_path_check_valid
),
1285 SVN_TEST_PASS(test_is_single_path_component
),
1286 SVN_TEST_PASS(test_compare_paths
),
1287 SVN_TEST_PASS(test_get_longest_ancestor
),
1288 SVN_TEST_PASS(test_splitext
),
1289 SVN_TEST_PASS(test_compose
),