This patch doesn't say anything about whether we wanted or now want the design
of *_is_canonical() and *_canonicalize() to be such that
is_canonical(canonicalize(path)) is always true. I present this for interested
parties to play with and make progress.
Sample outputs:
[[[
DBG: dirent_uri-test.c:1191: non-c. dirent: 'O:.' -> 'O:.'
DBG: dirent_uri-test.c:1191: non-c. dirent: './v:' -> 'v:'
DBG: dirent_uri-test.c:1198: non-c. URI: 'u9' -> 'u9'
...
DBG: dirent_uri-test.c:1180: f='/hxDC7/'
lt-dirent_uri-test:
/home/julianfoad/src/subversion-fsrepli/subversion/libsvn_subr/dirent_uri.c:322:
canonicalize: Assertion `*src != '/'' failed.
]]]
To get the dirent failures I forcibly defined SVN_USE_DOS_PATHS in
libsvn_subr/dirent_uri.c.
For whatever invariants we do decide should hold, it would be beneficial to
have such a test in place.
The relpath_* functions do currently seem to obey this invariant, so I suggest
we commit at least the relpath part of this, if we agree that's intended
behaviour.
--
- Julian
Proof of concept: add random testing of is_canonical(canonicalize(path)).
Sample outputs:
[[[
DBG: dirent_uri-test.c:1191: non-c. dirent: 'O:.' -> 'O:.'
DBG: dirent_uri-test.c:1191: non-c. dirent: './v:' -> 'v:'
DBG: dirent_uri-test.c:1198: non-c. URI: 'u9' -> 'u9'
...
DBG: dirent_uri-test.c:1180: f='/hxDC7/'
lt-dirent_uri-test: /home/julianfoad/src/subversion-fsrepli/subversion/libsvn_subr/dirent_uri.c:322: canonicalize: Assertion `*src != '/'' failed.
]]]
* subversion/tests/libsvn_subr/dirent_uri-test.c
(random_filename): New.
(test_dirent_is_canonical_random): New test.
(test_funcs): Run it.
--This line, and those below, will be ignored--
Index: subversion/tests/libsvn_subr/dirent_uri-test.c
===================================================================
--- subversion/tests/libsvn_subr/dirent_uri-test.c (revision 1848853)
+++ subversion/tests/libsvn_subr/dirent_uri-test.c (working copy)
@@ -1129,12 +1129,89 @@ test_dirent_is_canonical(apr_pool_t *poo
canonicalized);
}
return SVN_NO_ERROR;
}
+/* */
+static char *
+random_filename(void)
+{
+ static char s[10];
+ int len = (long)rand() * 9 / RAND_MAX;
+ int i;
+
+ for (i = 0; i < len; ++i)
+ {
+ float r1 = (float)rand() / RAND_MAX;
+ float r2 = (float)rand() / RAND_MAX;
+ char c;
+
+ if (r1 < 0.2) /* about 1 in 5: special path chars */
+ {
+ c = "/:"[(int)(r2 * 1.2)];
+ }
+ else if (r1 < 0.3)
+ {
+ c = (char)(r2 * 32); /* about 1 in 10: control chars */
+ if (c == 0) c = 127;
+ }
+ else
+ {
+ c = (char)(32 + r2 * 95); /* the rest: printable ASCII chars */
+ }
+ s[i] = c;
+ }
+ s[i] = '\0';
+
+ return s;
+}
+
+static svn_error_t *
+test_dirent_is_canonical_random(apr_pool_t *pool)
+{
+ int tries = 1000000;
+ int i;
+
+ for (i = 0; i < tries; ++i)
+ {
+ const char *f = random_filename();
+ const char *ized;
+
+ /*SVN_DBG(("f='%s'", f));*/
+ ized = svn_relpath_canonicalize(f, pool);
+ if (!svn_relpath_is_canonical(ized))
+ {
+ SVN_DBG(("non-c. relpath: '%s' -> '%s'", f, ized));
+ /*SVN_TEST_ASSERT(svn_relpath_is_canonical(
+ svn_relpath_canonicalize(f, pool)));*/
+ }
+ ized = svn_dirent_canonicalize(f, pool);
+ if (!svn_dirent_is_canonical(ized, pool))
+ {
+ SVN_DBG(("non-c. dirent: '%s' -> '%s'", f, ized));
+ /*SVN_TEST_ASSERT(svn_dirent_is_canonical(
+ svn_dirent_canonicalize(f, pool), pool));*/
+ }
+#if 0 /* URI fails in many cases, and svn_uri_canonicalize assertion-fails
+ when input begins with '/' */
+ ized = svn_uri_canonicalize(f, pool);
+ if (!svn_uri_is_canonical(ized, pool))
+ {
+ SVN_DBG(("non-c. URI: '%s' -> '%s'", f, ized));
+ /*SVN_TEST_ASSERT(svn_uri_is_canonical(
+ svn_uri_canonicalize(f, pool), pool));*/
+ }
+#endif
+ }
+
+ return SVN_NO_ERROR;
+}
+
+#undef SVN_USE_DOS_PATHS
+
static svn_error_t *
test_relpath_is_canonical(apr_pool_t *pool)
{
const testcase_is_canonical_t *t;
static const testcase_is_canonical_t tests[] = {
{ "", TRUE },
@@ -3016,10 +3093,12 @@ static struct svn_test_descriptor_t test
SVN_TEST_PASS2(test_fspath_get_longest_ancestor,
"test svn_fspath__get_longest_ancestor"),
SVN_TEST_PASS2(test_cert_match_dns_identity,
"test svn_cert__match_dns_identity"),
SVN_TEST_XFAIL2(test_rule3,
"test match with RFC 6125 s. 6.4.3 Rule 3"),
+ SVN_TEST_PASS2(test_dirent_is_canonical_random,
+ "test dirent_is_canonical random"),
SVN_TEST_NULL
};
SVN_TEST_MAIN