~ubuntu-branches/ubuntu/trusty/subversion/trusty-proposed

« back to all changes in this revision

Viewing changes to subversion/tests/libsvn_subr/dirent_uri-test.c

  • Committer: Package Import Robot
  • Author(s): Andy Whitcroft
  • Date: 2012-06-21 15:36:36 UTC
  • mfrom: (0.4.13 sid)
  • Revision ID: package-import@ubuntu.com-20120621153636-amqqmuidgwgxz1ly
Tags: 1.7.5-1ubuntu1
* Merge from Debian unstable.  Remaining changes:
  - Create pot file on build.
  - Build a python-subversion-dbg package.
  - Build-depend on python-dbg.
  - Build-depend on default-jre-headless/-jdk.
  - Do not apply java-build patch.
  - debian/rules: Manually create the doxygen output directory, otherwise
    we get weird build failures when running parallel builds.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 * dirent_uri-test.c -- test the directory entry and URI functions
3
3
 *
4
4
 * ====================================================================
5
 
 * Copyright (c) 2008 CollabNet.  All rights reserved.
6
 
 *
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.
12
 
 *
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/.
 
5
 *    Licensed to the Apache Software Foundation (ASF) under one
 
6
 *    or more contributor license agreements.  See the NOTICE file
 
7
 *    distributed with this work for additional information
 
8
 *    regarding copyright ownership.  The ASF licenses this file
 
9
 *    to you under the Apache License, Version 2.0 (the
 
10
 *    "License"); you may not use this file except in compliance
 
11
 *    with the License.  You may obtain a copy of the License at
 
12
 *
 
13
 *      http://www.apache.org/licenses/LICENSE-2.0
 
14
 *
 
15
 *    Unless required by applicable law or agreed to in writing,
 
16
 *    software distributed under the License is distributed on an
 
17
 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 
18
 *    KIND, either express or implied.  See the License for the
 
19
 *    specific language governing permissions and limitations
 
20
 *    under the License.
16
21
 * ====================================================================
17
22
 */
18
23
 
19
24
#include <stdio.h>
20
25
#include <string.h>
21
26
 
22
 
#ifdef _MSC_VER
 
27
#if defined(WIN32) || defined(__OS2__)
23
28
#include <direct.h>
24
29
#define getcwd _getcwd
25
30
#define getdcwd _getdcwd
31
36
 
32
37
#include "svn_pools.h"
33
38
#include "svn_dirent_uri.h"
 
39
#include "private/svn_fspath.h"
34
40
 
35
41
#include "../svn_test.h"
36
 
#include "../../libsvn_subr/private_uri.h"
37
42
 
38
43
#define SVN_EMPTY_PATH ""
39
44
 
 
45
/* This check must match the check on top of dirent_uri.c and path-tests.c */
 
46
#if defined(WIN32) || defined(__CYGWIN__) || defined(__OS2__)
 
47
#define SVN_USE_DOS_PATHS
 
48
#endif
 
49
 
40
50
#define COUNT_OF(x) (sizeof(x) / sizeof(x[0]))
41
51
 
42
52
static svn_error_t *
43
 
test_dirent_is_root(const char **msg,
44
 
                    svn_boolean_t msg_only,
45
 
                    svn_test_opts_t *opts,
46
 
                    apr_pool_t *pool)
 
53
test_dirent_is_root(apr_pool_t *pool)
47
54
{
48
55
  apr_size_t i;
49
56
 
52
59
    const char *path;
53
60
    svn_boolean_t result;
54
61
  } tests[] = {
 
62
    { "/",             TRUE  },
55
63
    { "/foo/bar",      FALSE },
56
64
    { "/foo",          FALSE },
57
65
    { "",              FALSE },
58
 
#if defined(WIN32) || defined(__CYGWIN__)
 
66
#ifdef SVN_USE_DOS_PATHS
59
67
    { "X:/foo",        FALSE },
60
68
    { "X:/",           TRUE },
61
 
    { "X:foo",         FALSE },
 
69
    { "X:foo",         FALSE }, /* Based on non absolute root */
62
70
    { "X:",            TRUE },
63
71
    { "//srv/shr",     TRUE },
64
72
    { "//srv/shr/fld", FALSE },
65
 
#else /* WIN32 or Cygwin */
 
73
    { "//srv/s r",     TRUE },
 
74
    { "//srv/s r/fld", FALSE },
 
75
#else /* !SVN_USE_DOS_PATHS */
 
76
    { "/",             TRUE },
66
77
    { "/X:foo",        FALSE },
67
78
    { "/X:",           FALSE },
68
 
#endif /* non-WIN32 */
 
79
#endif /* SVN_USE_DOS_PATHS */
69
80
  };
70
81
 
71
 
  *msg = "test svn_dirent_is_root";
72
 
 
73
 
  if (msg_only)
74
 
    return SVN_NO_ERROR;
75
 
 
76
82
  for (i = 0; i < COUNT_OF(tests); i++)
77
83
    {
78
84
      svn_boolean_t retval;
90
96
}
91
97
 
92
98
static svn_error_t *
93
 
test_uri_is_root(const char **msg,
94
 
                 svn_boolean_t msg_only,
95
 
                 svn_test_opts_t *opts,
96
 
                 apr_pool_t *pool)
 
99
test_uri_is_root(apr_pool_t *pool)
97
100
{
98
101
  apr_size_t i;
99
102
 
102
105
    const char *path;
103
106
    svn_boolean_t result;
104
107
  } tests[] = {
105
 
    { "/foo/bar",      FALSE },
106
 
    { "/foo",          FALSE },
107
 
    { "/",             TRUE },
108
 
    { "",              FALSE },
109
 
    { "X:/foo",        FALSE },
110
 
    { "X:/",           FALSE },
111
 
    { "X:foo",         FALSE },
112
 
    { "X:",            FALSE },
 
108
    { "file://",       TRUE },
 
109
    { "file://a",      FALSE },
 
110
    { "file:///a",     FALSE },
 
111
    { "file:///A:",    FALSE },
 
112
    { "http://server", TRUE },
 
113
    { "http://server/file", FALSE },
 
114
    { "http://",       TRUE },
113
115
  };
114
116
 
115
 
  *msg = "test svn_uri_is_root";
116
 
 
117
 
  if (msg_only)
118
 
    return SVN_NO_ERROR;
119
 
 
120
117
  for (i = 0; i < COUNT_OF(tests); i++)
121
118
    {
122
119
      svn_boolean_t retval;
134
131
}
135
132
 
136
133
static svn_error_t *
137
 
test_dirent_is_absolute(const char **msg,
138
 
                        svn_boolean_t msg_only,
139
 
                        svn_test_opts_t *opts,
140
 
                        apr_pool_t *pool)
 
134
test_dirent_is_absolute(apr_pool_t *pool)
141
135
{
142
136
  apr_size_t i;
143
137
 
146
140
    const char *path;
147
141
    svn_boolean_t result;
148
142
  } tests[] = {
149
 
    { "/foo/bar",      TRUE },
150
 
    { "/foo",          TRUE },
151
 
    { "/",             TRUE },
152
143
    { "foo/bar",       FALSE },
153
144
    { "foo",           FALSE },
154
145
    { "",              FALSE },
155
 
#if defined(WIN32) || defined(__CYGWIN__)
156
 
    { "X:/foo",        TRUE },
157
 
    { "X:/",           TRUE },
 
146
#ifdef SVN_USE_DOS_PATHS
 
147
    { "/foo/bar",      FALSE },
 
148
    { "/foo",          FALSE },
 
149
    { "/",             FALSE },
 
150
    { "C:/foo",        TRUE },
 
151
    { "C:/",           TRUE },
 
152
    { "c:/",           FALSE },
 
153
    { "c:/foo",        FALSE },
158
154
    { "//srv/shr",     TRUE },
159
155
    { "//srv/shr/fld", TRUE },
160
 
#else/* WIN32 or Cygwin */
 
156
    { "//srv/s r",     TRUE },
 
157
    { "//srv/s r/fld", TRUE },
 
158
#else /* !SVN_USE_DOS_PATHS */
 
159
    { "/foo/bar",      TRUE },
 
160
    { "/foo",          TRUE },
 
161
    { "/",             TRUE },
161
162
    { "X:/foo",        FALSE },
162
163
    { "X:/",           FALSE },
163
 
    { "X:foo",         FALSE },
 
164
#endif /* SVN_USE_DOS_PATHS */
 
165
    { "X:foo",         FALSE }, /* Not special on Posix, relative on Windows */
164
166
    { "X:foo/bar",     FALSE },
165
167
    { "X:",            FALSE },
166
 
#endif /* non-WIN32 */
167
168
  };
168
169
 
169
 
  *msg = "test svn_dirent_is_absolute";
170
 
 
171
 
  if (msg_only)
172
 
    return SVN_NO_ERROR;
173
 
 
174
170
  for (i = 0; i < COUNT_OF(tests); i++)
175
171
    {
176
172
      svn_boolean_t retval;
182
178
           "svn_dirent_is_absolute (%s) returned %s instead of %s",
183
179
           tests[i].path, retval ? "TRUE" : "FALSE",
184
180
           tests[i].result ? "TRUE" : "FALSE");
185
 
    }
186
 
 
187
 
  return SVN_NO_ERROR;
188
 
}
189
 
 
190
 
static svn_error_t *
191
 
test_uri_is_absolute(const char **msg,
192
 
                     svn_boolean_t msg_only,
193
 
                     svn_test_opts_t *opts,
194
 
                     apr_pool_t *pool)
195
 
{
196
 
  apr_size_t i;
197
 
 
198
 
  /* Paths to test and their expected results. */
199
 
  struct {
200
 
    const char *path;
201
 
    svn_boolean_t result;
202
 
  } tests[] = {
203
 
    { "/foo/bar",      TRUE },
204
 
    { "/foo",          TRUE },
205
 
    { "/",             TRUE },
206
 
    { "foo/bar",       FALSE },
207
 
    { "foo",           FALSE },
208
 
    { "",              FALSE },
209
 
    { "X:/foo",        FALSE },
210
 
    { "X:foo",         FALSE },
211
 
    { "X:foo/bar",     FALSE },
212
 
    { "X:",            FALSE },
213
 
    { "http://",       TRUE },
214
 
    { "http://test",   TRUE },
215
 
    { "http://foo/bar",TRUE },
216
 
  };
217
 
 
218
 
  *msg = "test svn_uri_is_absolute";
219
 
 
220
 
  if (msg_only)
221
 
    return SVN_NO_ERROR;
222
 
 
223
 
  for (i = 0; i < COUNT_OF(tests); i++)
224
 
    {
225
 
      svn_boolean_t retval;
226
 
 
227
 
      retval = svn_uri_is_absolute(tests[i].path);
228
 
      if (tests[i].result != retval)
229
 
        return svn_error_createf
230
 
          (SVN_ERR_TEST_FAILED, NULL,
231
 
           "svn_uri_is_absolute (%s) returned %s instead of %s",
232
 
           tests[i].path, retval ? "TRUE" : "FALSE",
233
 
           tests[i].result ? "TRUE" : "FALSE");
234
 
    }
235
 
 
236
 
  return SVN_NO_ERROR;
237
 
}
238
 
 
239
 
static svn_error_t *
240
 
test_dirent_join(const char **msg,
241
 
                 svn_boolean_t msg_only,
242
 
                 svn_test_opts_t *opts,
243
 
                 apr_pool_t *pool)
 
181
 
 
182
      /* Don't get absolute paths for the UNC paths, because this will
 
183
         always fail */
 
184
      if (tests[i].result &&
 
185
          strncmp(tests[i].path, "//", 2) != 0)
 
186
        {
 
187
          const char *abspath;
 
188
 
 
189
          SVN_ERR(svn_dirent_get_absolute(&abspath, tests[i].path, pool));
 
190
 
 
191
          if (tests[i].result != (strcmp(tests[i].path, abspath) == 0))
 
192
            return svn_error_createf(
 
193
                          SVN_ERR_TEST_FAILED,
 
194
                          NULL,
 
195
                          "svn_dirent_is_absolute(%s) returned TRUE, but "
 
196
                          "svn_dirent_get_absolute() returned \"%s\"",
 
197
                          tests[i].path,
 
198
                          abspath);
 
199
        }
 
200
    }
 
201
 
 
202
  return SVN_NO_ERROR;
 
203
}
 
204
 
 
205
static svn_error_t *
 
206
test_dirent_join(apr_pool_t *pool)
244
207
{
245
208
  int i;
246
209
  char *result;
255
218
    { "/abc", "/def", "/def" },
256
219
    { "/abc", "/d", "/d" },
257
220
    { "/abc", "/", "/" },
 
221
    { "abc", "/def", "/def" },
258
222
    { SVN_EMPTY_PATH, "/", "/" },
259
223
    { "/", SVN_EMPTY_PATH, "/" },
260
224
    { SVN_EMPTY_PATH, "abc", "abc" },
261
225
    { "abc", SVN_EMPTY_PATH, "abc" },
262
226
    { SVN_EMPTY_PATH, "/abc", "/abc" },
263
227
    { SVN_EMPTY_PATH, SVN_EMPTY_PATH, SVN_EMPTY_PATH },
264
 
#if defined(WIN32) || defined(__CYGWIN__)
265
 
    { "X:/",SVN_EMPTY_PATH, "X:/" },
266
 
    { "X:/","abc", "X:/abc" },
267
 
    { "X:/", "/def", "/def" },
268
 
    { "X:/abc", "/d", "/d" },
269
 
    { "X:/abc", "/", "/" },
 
228
    { "/", "/", "/" },
 
229
#ifdef SVN_USE_DOS_PATHS
 
230
    { "X:/", SVN_EMPTY_PATH, "X:/" },
 
231
    { "X:/", "abc", "X:/abc" },
 
232
    { "X:/", "/def", "X:/def" },
 
233
    { "X:/abc", "/d", "X:/d" },
 
234
    { "X:/abc", "/", "X:/" },
270
235
    { "X:/abc", "X:/", "X:/" },
271
236
    { "X:/abc", "X:/def", "X:/def" },
272
 
    { "X:",SVN_EMPTY_PATH, "X:" },
273
 
    { "X:","abc", "X:abc" },
274
 
    { "X:", "/def", "/def" },
275
 
    { "X:abc", "/d", "/d" },
276
 
    { "X:abc", "/", "/" },
 
237
    { "X:", SVN_EMPTY_PATH, "X:" },
 
238
    { "X:", "abc", "X:abc" },
 
239
    { "X:", "/def", "X:/def" },
 
240
    { "X:abc", "/d", "X:/d" },
 
241
    { "X:abc", "/", "X:/" },
277
242
    { "X:abc", "X:/", "X:/" },
278
243
    { "X:abc", "X:/def", "X:/def" },
279
244
    { "//srv/shr",     "fld",     "//srv/shr/fld" },
280
245
    { "//srv/shr/fld", "subfld",  "//srv/shr/fld/subfld" },
281
246
    { "//srv/shr/fld", "//srv/shr", "//srv/shr" },
282
 
#else /* WIN32 or Cygwin */
 
247
    { "//srv/s r",     "fld",     "//srv/s r/fld" },
 
248
    { "aa", "/dir", "/dir"} ,
 
249
    { "aa", "A:", "A:" },
 
250
    { "aa", "A:file", "A:file"},
 
251
    { "A:", "/", "A:/" },
 
252
#else /* !SVN_USE_DOS_PATHS */
283
253
    { "X:abc", "X:/def", "X:abc/X:/def" },
284
254
    { "X:","abc", "X:/abc" },
285
255
    { "X:/abc", "X:/def", "X:/abc/X:/def" },
286
 
#endif /* non-WIN32 */
 
256
#endif /* SVN_USE_DOS_PATHS */
287
257
  };
288
258
 
289
 
  *msg = "test svn_dirent_join(_many)";
290
 
  if (msg_only)
291
 
    return SVN_NO_ERROR;
292
 
 
293
259
  for (i = 0; i < COUNT_OF(joins); i++ )
294
260
    {
295
261
      const char *base = joins[i][0];
351
317
  TEST_MANY((pool, SVN_EMPTY_PATH, "/", SVN_EMPTY_PATH, NULL), "/");
352
318
  TEST_MANY((pool, SVN_EMPTY_PATH, SVN_EMPTY_PATH, "/", NULL), "/");
353
319
 
354
 
#if defined(WIN32) || defined(__CYGWIN__)
 
320
#ifdef SVN_USE_DOS_PATHS
355
321
  TEST_MANY((pool, "X:/", "def", "ghi", NULL), "X:/def/ghi");
356
322
  TEST_MANY((pool, "abc", "X:/", "ghi", NULL), "X:/ghi");
357
323
  TEST_MANY((pool, "abc", "def", "X:/", NULL), "X:/");
373
339
  TEST_MANY((pool, "//srv/shr", "def", "ghi", NULL), "//srv/shr/def/ghi");
374
340
  TEST_MANY((pool, "//srv/shr/fld", "def", "ghi", NULL), "//srv/shr/fld/def/ghi");
375
341
  TEST_MANY((pool, "//srv/shr/fld", "def", "//srv/shr", NULL), "//srv/shr");
 
342
  TEST_MANY((pool, "//srv/s r/fld", "def", "//srv/s r", NULL), "//srv/s r");
376
343
  TEST_MANY((pool, SVN_EMPTY_PATH, "//srv/shr/fld", "def", "ghi", NULL), "//srv/shr/fld/def/ghi");
377
344
  TEST_MANY((pool, SVN_EMPTY_PATH, "//srv/shr/fld", "def", "//srv/shr", NULL), "//srv/shr");
378
 
#else /* WIN32 or Cygwin */
 
345
 
 
346
  TEST_MANY((pool, "abcd", "/dir", "A:", "file", NULL), "A:file");
 
347
  TEST_MANY((pool, "abcd", "A:", "/dir", "file", NULL), "A:/dir/file");
 
348
 
 
349
#else /* !SVN_USE_DOS_PATHS */
379
350
  TEST_MANY((pool, "X:", "def", "ghi", NULL), "X:/def/ghi");
380
351
  TEST_MANY((pool, "X:", SVN_EMPTY_PATH, "ghi", NULL), "X:/ghi");
381
352
  TEST_MANY((pool, "X:", "def", SVN_EMPTY_PATH, NULL), "X:/def");
382
353
  TEST_MANY((pool, SVN_EMPTY_PATH, "X:", "ghi", NULL), "X:/ghi");
383
 
#endif /* non-WIN32 */
 
354
#endif /* SVN_USE_DOS_PATHS */
384
355
 
385
356
  /* ### probably need quite a few more tests... */
386
357
 
388
359
}
389
360
 
390
361
static svn_error_t *
391
 
test_dirent_dirname(const char **msg,
392
 
                    svn_boolean_t msg_only,
393
 
                    svn_test_opts_t *opts,
394
 
                    apr_pool_t *pool)
 
362
test_relpath_join(apr_pool_t *pool)
 
363
{
 
364
  int i;
 
365
  char *result;
 
366
 
 
367
  static const char * const joins[][3] = {
 
368
    { "abc", "def", "abc/def" },
 
369
    { "a", "def", "a/def" },
 
370
    { "a", "d", "a/d" },
 
371
    { SVN_EMPTY_PATH, "abc", "abc" },
 
372
    { "abc", SVN_EMPTY_PATH, "abc" },
 
373
    { "", "", "" },
 
374
  };
 
375
 
 
376
  for (i = 0; i < COUNT_OF(joins); i++)
 
377
    {
 
378
      const char *base = joins[i][0];
 
379
      const char *comp = joins[i][1];
 
380
      const char *expect = joins[i][2];
 
381
 
 
382
      result = svn_relpath_join(base, comp, pool);
 
383
      if (strcmp(result, expect))
 
384
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
 
385
                                 "svn_relpath_join(\"%s\", \"%s\") returned "
 
386
                                 "\"%s\". expected \"%s\"",
 
387
                                 base, comp, result, expect);
 
388
 
 
389
      /*result = svn_relpath_join_many(pool, base, comp, NULL);
 
390
      if (strcmp(result, expect))
 
391
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
 
392
                                 "svn_relpath_join_many(\"%s\", \"%s\") "
 
393
                                 "returned \"%s\". expected \"%s\"",
 
394
                                 base, comp, result, expect);*/
 
395
    }
 
396
 
 
397
  return SVN_NO_ERROR;
 
398
}
 
399
 
 
400
static svn_error_t *
 
401
test_dirent_basename(apr_pool_t *pool)
 
402
{
 
403
  int i;
 
404
  const char *result;
 
405
 
 
406
  struct {
 
407
    const char *path;
 
408
    const char *result;
 
409
  } tests[] = {
 
410
    { "abc", "abc" },
 
411
    { "/abc", "abc" },
 
412
    { "/abc", "abc" },
 
413
    { "/x/abc", "abc" },
 
414
    { "/xx/abc", "abc" },
 
415
    { "/xx/abc", "abc" },
 
416
    { "/xx/abc", "abc" },
 
417
    { "a", "a" },
 
418
    { "/a", "a" },
 
419
    { "/b/a", "a" },
 
420
    { "/b/a", "a" },
 
421
    { "/", "" },
 
422
    { SVN_EMPTY_PATH, SVN_EMPTY_PATH },
 
423
    { "X:/abc", "abc" },
 
424
#ifdef SVN_USE_DOS_PATHS
 
425
    { "X:", "" },
 
426
    { "X:/", "" },
 
427
    { "X:abc", "abc" },
 
428
    { "//srv/shr", "" },
 
429
    { "//srv/shr/fld", "fld" },
 
430
    { "//srv/shr/fld/subfld", "subfld" },
 
431
    { "//srv/s r/fld", "fld" },
 
432
#else /* !SVN_USE_DOS_PATHS */
 
433
    { "X:", "X:" },
 
434
    { "X:abc", "X:abc" },
 
435
#endif /* SVN_USE_DOS_PATHS */
 
436
  };
 
437
 
 
438
  for (i = 0; i < COUNT_OF(tests); i++)
 
439
    {
 
440
      const char *path = tests[i].path;
 
441
      const char *expect = tests[i].result;
 
442
 
 
443
      result = svn_dirent_basename(path, pool);
 
444
      if (strcmp(result, expect))
 
445
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
 
446
                                 "svn_dirent_basename(\"%s\") returned "
 
447
                                 "\"%s\". expected \"%s\"",
 
448
                                 path, result, expect);
 
449
    }
 
450
 
 
451
  return SVN_NO_ERROR;
 
452
}
 
453
 
 
454
static svn_error_t *
 
455
test_relpath_basename(apr_pool_t *pool)
 
456
{
 
457
  int i;
 
458
  const char *result;
 
459
 
 
460
  struct {
 
461
    const char *path;
 
462
    const char *result;
 
463
  } tests[] = {
 
464
    { "", "" },
 
465
    { " ", " " },
 
466
    { "foo/bar", "bar" },
 
467
    { "foo/bar/bad", "bad" },
 
468
  };
 
469
 
 
470
  for (i = 0; i < COUNT_OF(tests); i++)
 
471
    {
 
472
      const char *path = tests[i].path;
 
473
      const char *expect = tests[i].result;
 
474
 
 
475
      result = svn_relpath_basename(path, pool);
 
476
      if (strcmp(result, expect))
 
477
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
 
478
                                 "svn_relpath_basename(\"%s\") returned "
 
479
                                 "\"%s\". expected \"%s\"",
 
480
                                 path, result, expect);
 
481
    }
 
482
 
 
483
  return SVN_NO_ERROR;
 
484
}
 
485
 
 
486
static svn_error_t *
 
487
test_uri_basename(apr_pool_t *pool)
 
488
{
 
489
  int i;
 
490
  const char *result;
 
491
 
 
492
  struct {
 
493
    const char *path;
 
494
    const char *result;
 
495
  } tests[] = {
 
496
    { "http://s/file", "file" },
 
497
    { "http://s/dir/file", "file" },
 
498
    { "http://s/some%20dir/other%20file", "other file" },
 
499
    { "http://s", "" },
 
500
    { "file://", "" },
 
501
    { "file:///a", "a" },
 
502
    { "file:///a/b", "b" },
 
503
  };
 
504
 
 
505
  for (i = 0; i < COUNT_OF(tests); i++)
 
506
    {
 
507
      const char *path = tests[i].path;
 
508
      const char *expect = tests[i].result;
 
509
 
 
510
      result = svn_uri_basename(path, pool);
 
511
      if (strcmp(result, expect))
 
512
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
 
513
                                 "svn_uri_basename(\"%s\") returned "
 
514
                                 "\"%s\". expected \"%s\"",
 
515
                                 path, result, expect);
 
516
    }
 
517
 
 
518
  return SVN_NO_ERROR;
 
519
}
 
520
 
 
521
static svn_error_t *
 
522
test_dirent_dirname(apr_pool_t *pool)
395
523
{
396
524
  int i;
397
525
  char *result;
410
538
    { "/", "/" },
411
539
    { SVN_EMPTY_PATH, SVN_EMPTY_PATH },
412
540
    { "X:abc/def", "X:abc" },
413
 
#if defined(WIN32) || defined(__CYGWIN__)
 
541
#ifdef SVN_USE_DOS_PATHS
414
542
    { "X:/", "X:/" },
415
543
    { "X:/abc", "X:/" },
416
544
    { "X:abc", "X:" },
418
546
    { "//srv/shr",      "//srv/shr" },
419
547
    { "//srv/shr/fld",  "//srv/shr" },
420
548
    { "//srv/shr/fld/subfld", "//srv/shr/fld" },
421
 
#else  /* WIN32 or Cygwin */
 
549
    { "//srv/s r/fld",  "//srv/s r" },
 
550
#else /* !SVN_USE_DOS_PATHS */
422
551
    /* on non-Windows platforms, ':' is allowed in pathnames */
423
552
    { "X:", "" },
424
553
    { "X:abc", "" },
425
 
#endif /* non-WIN32 */
 
554
#endif /* SVN_USE_DOS_PATHS */
426
555
  };
427
556
 
428
 
  *msg = "test svn_dirent_dirname";
429
 
  if (msg_only)
430
 
    return SVN_NO_ERROR;
431
 
 
432
557
  for (i = 0; i < COUNT_OF(tests); i++)
433
558
    {
434
559
      const char *path = tests[i].path;
446
571
}
447
572
 
448
573
static svn_error_t *
449
 
test_uri_dirname(const char **msg,
450
 
                    svn_boolean_t msg_only,
451
 
                    svn_test_opts_t *opts,
452
 
                    apr_pool_t *pool)
 
574
test_relpath_dirname(apr_pool_t *pool)
 
575
{
 
576
  int i;
 
577
  char *result;
 
578
 
 
579
  struct {
 
580
    const char *path;
 
581
    const char *result;
 
582
  } tests[] = {
 
583
    { "", "" },
 
584
    { " ", "" },
 
585
    { "foo", "" },
 
586
    { "foo/bar", "foo" },
 
587
    { "foo/bar/bad", "foo/bar" },
 
588
  };
 
589
 
 
590
  for (i = 0; i < COUNT_OF(tests); i++)
 
591
    {
 
592
      const char *path = tests[i].path;
 
593
      const char *expect = tests[i].result;
 
594
 
 
595
      result = svn_relpath_dirname(path, pool);
 
596
      if (strcmp(result, expect))
 
597
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
 
598
                                 "svn_relpath_dirname(\"%s\") returned "
 
599
                                 "\"%s\". expected \"%s\"",
 
600
                                 path, result, expect);
 
601
    }
 
602
 
 
603
  return SVN_NO_ERROR;
 
604
}
 
605
 
 
606
static svn_error_t *
 
607
test_uri_dirname(apr_pool_t *pool)
453
608
{
454
609
  int i;
455
610
  char *result;
460
615
  } tests[] = {
461
616
    { "http://server/dir", "http://server" },
462
617
    { "http://server/dir/file", "http://server/dir" },
463
 
    { "http://server", "http:/" }, /* ### Current behavior */
 
618
    { "http://server", "http://server" },
 
619
    { "file:///a/b", "file:///a" },
 
620
    { "file:///a", "file://" },
464
621
  };
465
622
 
466
 
  *msg = "test svn_dirent_dirname";
467
 
  if (msg_only)
468
 
    return SVN_NO_ERROR;
469
 
 
470
623
  for (i = 0; i < COUNT_OF(tests); i++)
471
624
    {
472
625
      const char *path = tests[i].path;
483
636
  return SVN_NO_ERROR;
484
637
}
485
638
 
 
639
/* Paths to test and the expected result, for canonicalize tests. */
 
640
typedef struct testcase_canonicalize_t {
 
641
  const char *path;
 
642
  const char *result;
 
643
} testcase_canonicalize_t;
 
644
 
486
645
static svn_error_t *
487
 
test_dirent_canonicalize(const char **msg,
488
 
                         svn_boolean_t msg_only,
489
 
                         svn_test_opts_t *opts,
490
 
                         apr_pool_t *pool)
 
646
test_dirent_canonicalize(apr_pool_t *pool)
491
647
{
492
 
  struct {
493
 
    const char *path;
494
 
    const char *result;
495
 
  } tests[] = {
 
648
  const testcase_canonicalize_t *t;
 
649
  static const testcase_canonicalize_t tests[] = {
496
650
    { "",                     "" },
497
651
    { ".",                    "" },
498
652
    { "/",                    "/" },
527
681
    { "X:",                   "X:" },
528
682
    { "X:foo",                "X:foo" },
529
683
    { "C:/folder/subfolder/file", "C:/folder/subfolder/file" },
530
 
#if defined(WIN32) || defined(__CYGWIN__)
 
684
#ifdef SVN_USE_DOS_PATHS
531
685
    { "X:/",                  "X:/" },
532
686
    { "X:/./",                "X:/" },
 
687
    { "x:/",                  "X:/" },
 
688
    { "x:",                   "X:" },
 
689
    { "x:AAAAA",              "X:AAAAA" },
533
690
    /* We permit UNC dirents on Windows.  By definition UNC
534
691
     * dirents must have two components so we should remove the
535
692
     * double slash if there is only one component. */
539
696
    { "//server/share/",      "//server/share" },
540
697
    { "//server/SHare/",      "//server/SHare" },
541
698
    { "//SERVER/SHare/",      "//server/SHare" },
542
 
#endif /* WIN32 or Cygwin */
 
699
    { "//srv/s r",            "//srv/s r" },
 
700
    { "//srv/s r/qq",         "//srv/s r/qq" },
 
701
#endif /* SVN_USE_DOS_PATHS */
543
702
  };
544
 
  int i;
545
 
 
546
 
  *msg = "test svn_dirent_canonicalize";
547
 
  if (msg_only)
548
 
    return SVN_NO_ERROR;
549
 
 
550
 
  for (i = 0; i < COUNT_OF(tests); i++)
 
703
 
 
704
  for (t = tests; t < tests + COUNT_OF(tests); t++)
551
705
    {
552
 
      const char *canonical = svn_dirent_canonicalize(tests[i].path, pool);
 
706
      const char *canonical = svn_dirent_canonicalize(t->path, pool);
553
707
 
554
 
      if (strcmp(canonical, tests[i].result))
 
708
      if (strcmp(canonical, t->result))
555
709
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
556
710
                                 "svn_dirent_canonicalize(\"%s\") returned "
557
711
                                 "\"%s\" expected \"%s\"",
558
 
                                 tests[i].path, canonical, tests[i].result);
 
712
                                 t->path, canonical, t->result);
559
713
    }
560
714
 
561
715
  return SVN_NO_ERROR;
562
716
}
563
717
 
564
718
static svn_error_t *
565
 
test_uri_canonicalize(const char **msg,
566
 
                      svn_boolean_t msg_only,
567
 
                      svn_test_opts_t *opts,
568
 
                      apr_pool_t *pool)
 
719
test_relpath_canonicalize(apr_pool_t *pool)
569
720
{
570
 
  struct {
571
 
    const char *path;
572
 
    const char *result;
573
 
  } tests[] = {
 
721
  const testcase_canonicalize_t *t;
 
722
  static const testcase_canonicalize_t tests[] = {
574
723
    { "",                     "" },
575
724
    { ".",                    "" },
576
 
    { "/",                    "/" },
577
 
    { "/.",                   "/" },
 
725
    { "/",                    "" },
 
726
    { "/.",                   "" },
578
727
    { "./",                   "" },
579
728
    { "./.",                  "" },
580
 
    { "//",                   "/" },
581
 
    { "/////",                "/" },
 
729
    { "//",                   "" },
 
730
    { "/////",                "" },
582
731
    { "./././.",              "" },
583
 
    { "////././.",            "/" },
 
732
    { "////././.",            "" },
584
733
    { "foo",                  "foo" },
585
734
    { ".foo",                 ".foo" },
586
735
    { "foo.",                 "foo." },
587
 
    { "/foo",                 "/foo" },
 
736
    { "/foo",                 "foo" },
588
737
    { "foo/",                 "foo" },
589
738
    { "foo./",                "foo." },
590
739
    { "foo./.",               "foo." },
591
740
    { "foo././/.",            "foo." },
592
 
    { "/foo/bar",             "/foo/bar" },
 
741
    { "/foo/bar",             "foo/bar" },
593
742
    { "foo/..",               "foo/.." },
594
743
    { "foo/../",              "foo/.." },
595
744
    { "foo/../.",             "foo/.." },
596
745
    { "foo//.//bar",          "foo/bar" },
597
 
    { "///foo",               "/foo" },
598
 
    { "/.//./.foo",           "/.foo" },
 
746
    { "///foo",               "foo" },
 
747
    { "/.//./.foo",           ".foo" },
599
748
    { ".///.foo",             ".foo" },
600
749
    { "../foo",               "../foo" },
601
750
    { "../../foo/",           "../../foo" },
602
751
    { "../../foo/..",         "../../foo/.." },
603
 
    { "/../../",              "/../.." },
 
752
    { "/../../",              "../.." },
604
753
    { "X:/foo",               "X:/foo" },
605
754
    { "X:",                   "X:" },
606
755
    { "X:foo",                "X:foo" },
607
756
    { "C:/folder/subfolder/file", "C:/folder/subfolder/file" },
 
757
    { "http://hst",           "http:/hst" },
 
758
    { "http://hst/foo/../bar","http:/hst/foo/../bar" },
 
759
    { "http://hst/",          "http:/hst" },
 
760
    { "http:///",             "http:" },
 
761
    { "https://",             "https:" },
 
762
    { "file:///",             "file:" },
 
763
    { "file://",              "file:" },
 
764
    { "svn:///",              "svn:" },
 
765
    { "svn+ssh:///",          "svn+ssh:" },
 
766
    { "http://HST/",          "http:/HST" },
 
767
    { "http://HST/FOO/BaR",   "http:/HST/FOO/BaR" },
 
768
    { "svn+ssh://j.raNDom@HST/BaR", "svn+ssh:/j.raNDom@HST/BaR" },
 
769
    { "svn+SSH://j.random:jRaY@HST/BaR", "svn+SSH:/j.random:jRaY@HST/BaR" },
 
770
    { "SVN+ssh://j.raNDom:jray@HST/BaR", "SVN+ssh:/j.raNDom:jray@HST/BaR" },
 
771
    { "fILe:///Users/jrandom/wc", "fILe:/Users/jrandom/wc" },
 
772
    { "fiLE:///",             "fiLE:" },
 
773
    { "fiLE://",              "fiLE:" },
 
774
    { "file://SRV/shr/repos",  "file:/SRV/shr/repos" },
 
775
    { "file://SRV/SHR/REPOS",  "file:/SRV/SHR/REPOS" },
 
776
    { "http://server////",     "http:/server" },
 
777
    { "http://server/file//",  "http:/server/file" },
 
778
    { "http://server//.//f//", "http:/server/f" },
 
779
    { "file:///c:/temp/repos", "file:/c:/temp/repos" },
 
780
    { "file:///c:/temp/REPOS", "file:/c:/temp/REPOS" },
 
781
    { "file:///C:/temp/REPOS", "file:/C:/temp/REPOS" },
 
782
  };
 
783
 
 
784
  for (t = tests; t < tests + COUNT_OF(tests); t++)
 
785
    {
 
786
      const char *canonical = svn_relpath_canonicalize(t->path, pool);
 
787
 
 
788
      if (strcmp(canonical, t->result))
 
789
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
 
790
                                 "svn_relpath_canonicalize(\"%s\") returned "
 
791
                                 "\"%s\" expected \"%s\"",
 
792
                                 t->path, canonical, t->result);
 
793
    }
 
794
 
 
795
  return SVN_NO_ERROR;
 
796
}
 
797
 
 
798
static const testcase_canonicalize_t uri_canonical_tests[] =
 
799
  {
608
800
    { "http://hst",           "http://hst" },
609
801
    { "http://hst/foo/../bar","http://hst/foo/../bar" },
610
802
    { "http://hst/",          "http://hst" },
616
808
    { "svn+ssh:///",          "svn+ssh://" },
617
809
    { "http://HST/",          "http://hst" },
618
810
    { "http://HST/FOO/BaR",   "http://hst/FOO/BaR" },
 
811
    { "svn+ssh://jens@10.0.1.1",    "svn+ssh://jens@10.0.1.1" },
619
812
    { "svn+ssh://j.raNDom@HST/BaR", "svn+ssh://j.raNDom@hst/BaR" },
620
813
    { "svn+SSH://j.random:jRaY@HST/BaR", "svn+ssh://j.random:jRaY@hst/BaR" },
621
814
    { "SVN+ssh://j.raNDom:jray@HST/BaR", "svn+ssh://j.raNDom:jray@hst/BaR" },
 
815
    { "svn+ssh://j.raNDom:jray@hst/BaR", "svn+ssh://j.raNDom:jray@hst/BaR" },
622
816
    { "fILe:///Users/jrandom/wc", "file:///Users/jrandom/wc" },
623
817
    { "fiLE:///",             "file://" },
624
818
    { "fiLE://",              "file://" },
625
819
    { "file://SRV/shr/repos",  "file://srv/shr/repos" },
626
820
    { "file://SRV/SHR/REPOS",  "file://srv/SHR/REPOS" },
627
 
#if defined(WIN32) || defined(__CYGWIN__)
 
821
    { "http://server////",     "http://server" },
 
822
    { "http://server/file//",  "http://server/file" },
 
823
    { "http://server//.//f//", "http://server/f" },
 
824
    { "http://server/d/.",     "http://server/d" },
 
825
    { "http://server/d/%2E",   "http://server/d" },
 
826
    { "http://server/d/./q",   "http://server/d/q" },
 
827
    { "http://server/d/%2E/q", "http://server/d/q" },
 
828
    { "http://server/%",       "http://server/%25" },
 
829
    { "http://server/%25",     "http://server/%25" },
 
830
    { "http://server/%/d",     "http://server/%25/d" },
 
831
    { "http://server/%25/d",   "http://server/%25/d" },
 
832
    { "http://server/+",       "http://server/+" },
 
833
    { "http://server/%2B",     "http://server/+" },
 
834
    { "http://server/ ",       "http://server/%20" },
 
835
    { "http://server/#",       "http://server/%23" },
 
836
    { "http://server/d/a%2Fb", "http://server/d/a/b" },
 
837
    { "http://server/d/.%2F.", "http://server/d" },
 
838
    { "http://server/d/%2E%2F%2E", "http://server/d" },
 
839
    { "file:///C%3a/temp",     "file:///C:/temp" },
 
840
    { "http://server/cr%AB",   "http://server/cr%AB" },
 
841
    { "http://server/cr%ab",   "http://server/cr%AB" },
 
842
    { "http://hst/foo/bar/",   "http://hst/foo/bar" },
 
843
    { "http://hst/foo/.",      "http://hst/foo" },
 
844
    { "http://hst/foo/%2E",    "http://hst/foo" },
 
845
    { "http://hst/%",          "http://hst/%25" },
 
846
    { "http://hst/+",          "http://hst/+" },
 
847
    { "http://hst/#",          "http://hst/%23" },
 
848
    { "http://hst/ ",          "http://hst/%20" },
 
849
    { "http://hst/%2B",        "http://hst/+" },
 
850
    { "http://HST",            "http://hst" },
 
851
    { "http://hst/foo/./bar",  "http://hst/foo/bar" },
 
852
    { "hTTp://hst/foo/bar",    "http://hst/foo/bar" },
 
853
    { "http://hst/foo/bar/",   "http://hst/foo/bar" },
 
854
    { "file://SRV/share/repo", "file://srv/share/repo" },
 
855
    { "file://srv/SHARE/repo", "file://srv/SHARE/repo" },
 
856
    { "file://srv/share/repo", "file://srv/share/repo" },
 
857
    { "file://srv/share/repo/","file://srv/share/repo" },
 
858
    { "file:///folder/c#",     "file:///folder/c%23" }, /* # needs escaping */
 
859
    { "file:///fld/with space","file:///fld/with%20space" }, /* # needs escaping */
 
860
    { "file:///fld/c%23",      "file:///fld/c%23" }, /* Properly escaped C# */
 
861
    { "file:///%DE%AD%BE%EF",  "file:///%DE%AD%BE%EF" },
 
862
    { "file:///%de%ad%be%ef",  "file:///%DE%AD%BE%EF" },
 
863
    { "file:///%DE%ad%BE%ef",  "file:///%DE%AD%BE%EF" },
 
864
    /* With default port number; these are non-canonical */
 
865
    { "http://server:",        "http://server" },
 
866
    { "http://server:/",       "http://server" },
 
867
    { "http://server:80",      "http://server" },
 
868
    { "http://SERVER:80",      "http://server" },
 
869
    { "http://server:80/",     "http://server" },
 
870
    { "http://server:80/p",    "http://server/p" },
 
871
    { "https://server:",       "https://server" },
 
872
    { "https://Server:443/q",  "https://server/q" },
 
873
    { "svn://server:3690/",    "svn://server" },
 
874
    { "svn://sERVER:3690/r",   "svn://server/r" },
 
875
    { "svn://server:/r",       "svn://server/r" },
 
876
    /* With non-default port number; both canonical and non-c. examples */
 
877
    { "http://server:1",       "http://server:1" },
 
878
    { "http://server:443",     "http://server:443" },
 
879
    { "http://server:81/",     "http://server:81" },
 
880
    { "http://SERVER:3690/",   "http://server:3690" },
 
881
    { "https://server:3690",   "https://server:3690" },
 
882
    { "https://SERVER:80/",    "https://server:80" },
 
883
    { "svn://server:80",       "svn://server:80" },
 
884
    { "svn://SERVER:443/",     "svn://server:443" },
 
885
#ifdef SVN_USE_DOS_PATHS
628
886
    { "file:///c:/temp/repos", "file:///C:/temp/repos" },
629
887
    { "file:///c:/temp/REPOS", "file:///C:/temp/REPOS" },
630
888
    { "file:///C:/temp/REPOS", "file:///C:/temp/REPOS" },
631
 
#else /* WIN32 or Cygwin */
 
889
#else /* !SVN_USE_DOS_PATHS */
632
890
    { "file:///c:/temp/repos", "file:///c:/temp/repos" },
633
891
    { "file:///c:/temp/REPOS", "file:///c:/temp/REPOS" },
634
892
    { "file:///C:/temp/REPOS", "file:///C:/temp/REPOS" },
635
 
#endif /* non-WIN32 */
 
893
#endif /* SVN_USE_DOS_PATHS */
 
894
  /* svn_uri_is_canonical() was a private function in the 1.6 API, and
 
895
     has since taken a MAJOR change of direction, namely that only
 
896
     absolute URLs are considered canonical uris now. */
 
897
    { "",                                NULL },
 
898
    { ".",                               NULL },
 
899
    { "/",                               NULL },
 
900
    { "/.",                              NULL },
 
901
    { "./",                              NULL },
 
902
    { "./.",                             NULL },
 
903
    { "//",                              NULL },
 
904
    { "/////",                           NULL },
 
905
    { "./././.",                         NULL },
 
906
    { "////././.",                       NULL },
 
907
    { "foo",                             NULL },
 
908
    { ".foo",                            NULL },
 
909
    { "foo.",                            NULL },
 
910
    { "/foo",                            NULL },
 
911
    { "foo/",                            NULL },
 
912
    { "foo./",                           NULL },
 
913
    { "foo./.",                          NULL },
 
914
    { "foo././/.",                       NULL },
 
915
    { "/foo/bar",                        NULL },
 
916
    { "foo/..",                          NULL },
 
917
    { "foo/../",                         NULL },
 
918
    { "foo/../.",                        NULL },
 
919
    { "foo//.//bar",                     NULL },
 
920
    { "///foo",                          NULL },
 
921
    { "/.//./.foo",                      NULL },
 
922
    { ".///.foo",                        NULL },
 
923
    { "../foo",                          NULL },
 
924
    { "../../foo/",                      NULL },
 
925
    { "../../foo/..",                    NULL },
 
926
    { "/../../",                         NULL },
 
927
    { "dirA",                            NULL },
 
928
    { "foo/dirA",                        NULL },
 
929
    { "foo/./bar",                       NULL },
 
930
    { "C:/folder/subfolder/file",        NULL },
 
931
    { "X:/foo",                          NULL },
 
932
    { "X:",                              NULL },
 
933
    { "X:foo",                           NULL },
 
934
    { "X:foo/",                          NULL },
 
935
    /* Some people use colons in their filenames. */
 
936
    { ":",                               NULL },
 
937
    { ".:",                              NULL },
 
938
    { "foo/.:",                          NULL },
 
939
    { "//server/share",                  NULL }, /* Only valid as dirent */
 
940
    { "//server",                        NULL },
 
941
    { "//",                              NULL },
 
942
    { "sch://@/",                        NULL },
 
943
    { "sch:///",                         NULL },
 
944
    { "svn://:",                         NULL },
636
945
  };
637
 
  int i;
638
 
 
639
 
  *msg = "test svn_uri_canonicalize";
640
 
  if (msg_only)
641
 
    return SVN_NO_ERROR;
642
 
 
643
 
  for (i = 0; i < COUNT_OF(tests); i++)
644
 
 
 
946
 
 
947
static svn_error_t *
 
948
test_uri_canonicalize(apr_pool_t *pool)
 
949
{
 
950
  const testcase_canonicalize_t *t;
 
951
 
 
952
  for (t = uri_canonical_tests;
 
953
       t < uri_canonical_tests + COUNT_OF(uri_canonical_tests);
 
954
       t++)
645
955
    {
646
 
      const char *canonical = svn_uri_canonicalize(tests[i].path, pool);
647
 
 
648
 
      if (strcmp(canonical, tests[i].result))
 
956
      const char *canonical;
 
957
 
 
958
      if (! t->result)
 
959
        continue;
 
960
 
 
961
      canonical = svn_uri_canonicalize(t->path, pool);
 
962
 
 
963
      if (strcmp(canonical, t->result))
649
964
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
650
965
                                 "svn_uri_canonicalize(\"%s\") returned "
651
966
                                 "\"%s\" expected \"%s\"",
652
 
                                 tests[i].path, canonical, tests[i].result);
 
967
                                 t->path, canonical, t->result);
653
968
    }
654
969
 
655
970
  return SVN_NO_ERROR;
656
971
}
657
972
 
 
973
/* Paths to test and the expected result, for is_canonical tests. */
 
974
typedef struct testcase_is_canonical_t {
 
975
  const char *path;
 
976
  svn_boolean_t canonical;
 
977
} testcase_is_canonical_t;
 
978
 
658
979
static svn_error_t *
659
 
test_dirent_is_canonical(const char **msg,
660
 
                        svn_boolean_t msg_only,
661
 
                        svn_test_opts_t *opts,
662
 
                        apr_pool_t *pool)
 
980
test_dirent_is_canonical(apr_pool_t *pool)
663
981
{
664
 
  struct {
665
 
    const char *path;
666
 
    svn_boolean_t canonical;
667
 
  } tests[] = {
 
982
  const testcase_is_canonical_t *t;
 
983
  static const testcase_is_canonical_t tests[] = {
668
984
    { "",                      TRUE },
669
985
    { ".",                     FALSE },
670
986
    { "/",                     TRUE },
704
1020
    { "X:foo",                 TRUE },
705
1021
    { "X:foo/",                FALSE },
706
1022
    { "file with spaces",      TRUE },
707
 
#if defined(WIN32) || defined(__CYGWIN__)
 
1023
#ifdef SVN_USE_DOS_PATHS
708
1024
    { "X:/",                   TRUE },
 
1025
    { "X:/foo",                TRUE },
 
1026
    { "X:",                    TRUE },
 
1027
    { "X:foo",                 TRUE },
 
1028
    { "x:/",                   FALSE },
 
1029
    { "x:/foo",                FALSE },
 
1030
    { "x:",                    FALSE },
 
1031
    { "x:foo",                 FALSE },
709
1032
    /* We permit UNC dirents on Windows.  By definition UNC
710
1033
     * dirents must have two components so we should remove the
711
1034
     * double slash if there is only one component. */
715
1038
    { "//server/share",        TRUE },
716
1039
    { "//server/SHare",        TRUE },
717
1040
    { "//SERVER/SHare",        FALSE },
718
 
#else /* WIN32 or Cygwin */
 
1041
    { "//srv/SH RE",           TRUE },
 
1042
#else /* !SVN_USE_DOS_PATHS */
719
1043
    { "X:/",                   FALSE },
720
1044
    /* Some people use colons in their filenames. */
721
1045
    { ":", TRUE },
722
1046
    { ".:", TRUE },
723
1047
    { "foo/.:", TRUE },
724
 
#endif /* non-WIN32 */
 
1048
#endif /* SVN_USE_DOS_PATHS */
725
1049
  };
726
 
  int i;
727
 
 
728
 
  *msg = "test svn_dirent_is_canonical";
729
 
  if (msg_only)
730
 
    return SVN_NO_ERROR;
731
 
 
732
 
  for (i = 0; i < COUNT_OF(tests); i++)
 
1050
 
 
1051
  for (t = tests; t < tests + COUNT_OF(tests); t++)
733
1052
    {
734
1053
      svn_boolean_t canonical;
735
1054
      const char* canonicalized;
736
1055
 
737
 
      canonical = svn_dirent_is_canonical(tests[i].path, pool);
738
 
      if (tests[i].canonical != canonical)
 
1056
      canonical = svn_dirent_is_canonical(t->path, pool);
 
1057
      if (t->canonical != canonical)
739
1058
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
740
1059
                                 "svn_dirent_is_canonical(\"%s\") returned "
741
1060
                                 "\"%s\" expected \"%s\"",
742
 
                                 tests[i].path,
 
1061
                                 t->path,
743
1062
                                 canonical ? "TRUE" : "FALSE",
744
 
                                 tests[i].canonical ? "TRUE" : "FALSE");
745
 
 
746
 
      canonicalized = svn_dirent_canonicalize(tests[i].path, pool);
747
 
 
748
 
      if (canonical && (strcmp(tests[i].path, canonicalized) != 0))
 
1063
                                 t->canonical ? "TRUE" : "FALSE");
 
1064
 
 
1065
      canonicalized = svn_dirent_canonicalize(t->path, pool);
 
1066
 
 
1067
      if ((canonical && strcmp(t->path, canonicalized) != 0)
 
1068
          || (!canonical && strcmp(t->path, canonicalized) == 0))
749
1069
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
750
1070
                                 "svn_dirent_canonicalize(\"%s\") returned \"%s\" "
751
1071
                                 "while svn_dirent_is_canonical returned TRUE",
752
 
                                 tests[i].path,
 
1072
                                 t->path,
753
1073
                                 canonicalized);
754
1074
    }
755
1075
 
757
1077
}
758
1078
 
759
1079
static svn_error_t *
760
 
test_uri_is_canonical(const char **msg,
761
 
                      svn_boolean_t msg_only,
762
 
                      svn_test_opts_t *opts,
763
 
                      apr_pool_t *pool)
 
1080
test_relpath_is_canonical(apr_pool_t *pool)
764
1081
{
765
 
  struct {
766
 
    const char *path;
767
 
    svn_boolean_t canonical;
768
 
  } tests[] = {
 
1082
  const testcase_is_canonical_t *t;
 
1083
  static const testcase_is_canonical_t tests[] = {
769
1084
    { "",                      TRUE },
770
1085
    { ".",                     FALSE },
771
 
    { "/",                     TRUE },
 
1086
    { "/",                     FALSE },
772
1087
    { "/.",                    FALSE },
773
1088
    { "./",                    FALSE },
774
1089
    { "./.",                   FALSE },
779
1094
    { "foo",                   TRUE },
780
1095
    { ".foo",                  TRUE },
781
1096
    { "foo.",                  TRUE },
782
 
    { "/foo",                  TRUE },
 
1097
    { "/foo",                  FALSE },
783
1098
    { "foo/",                  FALSE },
784
1099
    { "foo./",                 FALSE },
785
1100
    { "foo./.",                FALSE },
786
1101
    { "foo././/.",             FALSE },
787
 
    { "/foo/bar",              TRUE },
 
1102
    { "/foo/bar",              FALSE },
788
1103
    { "foo/..",                TRUE },
789
1104
    { "foo/../",               FALSE },
790
1105
    { "foo/../.",              FALSE },
799
1114
    { "dirA",                  TRUE },
800
1115
    { "foo/dirA",              TRUE },
801
1116
    { "foo/./bar",             FALSE },
802
 
    { "http://hst",            TRUE },
803
 
    { "http://hst/foo/../bar", TRUE },
804
 
    { "http://hst/",           FALSE },
 
1117
    { "http://hst",            FALSE },
 
1118
    { "http://hst/foo/../bar", FALSE },
805
1119
    { "http://HST/",           FALSE },
806
1120
    { "http://HST/FOO/BaR",    FALSE },
807
 
    { "svn+ssh://jens@10.0.1.1", TRUE },
808
 
    { "svn+ssh://j.raNDom@HST/BaR", FALSE },
809
 
    { "svn+SSH://j.random:jRaY@HST/BaR", FALSE },
810
 
    { "SVN+ssh://j.raNDom:jray@HST/BaR", FALSE },
811
 
    { "svn+ssh://j.raNDom:jray@hst/BaR", TRUE },
 
1121
    { "svn+ssh://jens@10.0.1.1", FALSE },
 
1122
    { "svn+ssh:/jens@10.0.1.1", TRUE },
812
1123
    { "fILe:///Users/jrandom/wc", FALSE },
813
 
    { "fiLE:///",              FALSE },
814
 
    { "fiLE://",               FALSE },
815
 
    { "C:/folder/subfolder/file", TRUE },
 
1124
    { "fILe:/Users/jrandom/wc", TRUE },
816
1125
    { "X:/foo",                TRUE },
817
1126
    { "X:",                    TRUE },
818
1127
    { "X:foo",                 TRUE },
821
1130
    { ":", TRUE },
822
1131
    { ".:", TRUE },
823
1132
    { "foo/.:", TRUE },
824
 
    { "file://SRV/share/repos", FALSE },
825
 
    { "file://srv/SHARE/repos", TRUE },
826
 
    { "file://srv/share/repos", TRUE },
827
1133
    { "//server/share",         FALSE }, /* Only valid as dirent */
828
1134
    { "//server",               FALSE },
829
1135
    { "//",                     FALSE },
830
 
#if defined(WIN32) || defined(__CYGWIN__)
831
1136
    { "file:///c:/temp/repos", FALSE },
832
1137
    { "file:///c:/temp/REPOS", FALSE },
833
 
    { "file:///C:/temp/REPOS", TRUE },
834
 
#else /* WIN32 or Cygwin */
835
 
    { "file:///c:/temp/repos", TRUE },
836
 
    { "file:///c:/temp/REPOS", TRUE },
837
 
    { "file:///C:/temp/REPOS", TRUE },
838
 
#endif /* non-WIN32 */
 
1138
    { "file:///C:/temp/REPOS", FALSE },
839
1139
  };
840
 
  int i;
841
 
 
842
 
  *msg = "test svn_uri_is_canonical";
843
 
  if (msg_only)
844
 
    return SVN_NO_ERROR;
845
 
 
846
 
  for (i = 0; i < COUNT_OF(tests); i++)
 
1140
 
 
1141
  for (t = tests; t < tests + COUNT_OF(tests); t++)
847
1142
    {
848
1143
      svn_boolean_t canonical;
849
1144
      const char* canonicalized;
850
1145
 
851
 
      canonical = svn_uri_is_canonical(tests[i].path, pool);
852
 
      if (tests[i].canonical != canonical)
 
1146
      canonical = svn_relpath_is_canonical(t->path);
 
1147
      if (t->canonical != canonical)
853
1148
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
854
 
                                 "svn_uri_is_canonical(\"%s\") returned "
 
1149
                                 "svn_relpath_is_canonical(\"%s\") returned "
855
1150
                                 "\"%s\" expected \"%s\"",
856
 
                                 tests[i].path,
 
1151
                                 t->path,
857
1152
                                 canonical ? "TRUE" : "FALSE",
858
 
                                 tests[i].canonical ? "TRUE" : "FALSE");
859
 
 
860
 
      canonicalized = svn_uri_canonicalize(tests[i].path, pool);
861
 
 
862
 
      if (canonical && (strcmp(tests[i].path, canonicalized) != 0))
 
1153
                                 t->canonical ? "TRUE" : "FALSE");
 
1154
 
 
1155
      canonicalized = svn_relpath_canonicalize(t->path, pool);
 
1156
 
 
1157
      if ((canonical && strcmp(t->path, canonicalized) != 0)
 
1158
          || (!canonical && strcmp(t->path, canonicalized) == 0))
863
1159
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
864
 
                                 "svn_uri_canonicalize(\"%s\") returned \"%s\" "
865
 
                                 "while svn_uri_is_canonical returned %s",
866
 
                                 tests[i].path,
 
1160
                                 "svn_relpath_canonicalize(\"%s\") returned "
 
1161
                                 "\"%s\"  while svn_relpath_is_canonical "
 
1162
                                 "returned %s",
 
1163
                                 t->path,
867
1164
                                 canonicalized,
868
1165
                                 canonical ? "TRUE" : "FALSE");
869
1166
    }
872
1169
}
873
1170
 
874
1171
static svn_error_t *
875
 
test_dirent_is_ancestor(const char **msg,
876
 
                        svn_boolean_t msg_only,
877
 
                        svn_test_opts_t *opts,
878
 
                        apr_pool_t *pool)
879
 
{
880
 
  apr_size_t i;
881
 
 
882
 
  /* Dirents to test and their expected results. */
883
 
  struct {
884
 
    const char *path1;
885
 
    const char *path2;
886
 
    svn_boolean_t result;
887
 
  } tests[] = {
888
 
    { "/foo",            "/foo/bar",      TRUE},
889
 
    { "/foo/bar",        "/foo/bar/",     TRUE},
890
 
    { "/",               "/foo",          TRUE},
891
 
    { SVN_EMPTY_PATH,    "foo",           TRUE},
892
 
    { SVN_EMPTY_PATH,    ".bar",          TRUE},
893
 
    { SVN_EMPTY_PATH,    "/",             FALSE},
894
 
    { SVN_EMPTY_PATH,    "/foo",          FALSE},
895
 
    { "/.bar",           "/",             FALSE},
896
 
    { "foo/bar",         "foo",           FALSE},
897
 
    { "/foo/bar",        "/foo",          FALSE},
898
 
    { "foo",             "foo/bar",       TRUE},
899
 
    { "foo.",            "foo./.bar",     TRUE},
900
 
 
901
 
    { "../foo",          "..",            FALSE},
902
 
    { SVN_EMPTY_PATH,    SVN_EMPTY_PATH,  TRUE},
903
 
    { "/",               "/",             TRUE},
904
 
    { "X:foo",           "X:bar",         FALSE},
905
 
#if defined(WIN32) || defined(__CYGWIN__)
906
 
    { "//srv/shr",       "//srv",         FALSE},
907
 
    { "//srv/shr",       "//srv/shr/fld", TRUE },
908
 
    { "//srv",           "//srv/shr/fld", TRUE },
909
 
    { "//srv/shr/fld",   "//srv/shr",     FALSE },
910
 
    { "//srv/shr/fld",   "//srv2/shr/fld", FALSE },
911
 
    { "X:/",             "X:/",           TRUE},
912
 
    { "X:/foo",          "X:/",           FALSE},
913
 
    { "X:/",             "X:/foo",        TRUE},
914
 
    { "X:",              "X:foo",         TRUE},
915
 
    { SVN_EMPTY_PATH,    "C:/",           FALSE},
916
 
#else /* WIN32 or Cygwin */
917
 
    { "X:",              "X:foo",         FALSE},
918
 
    { SVN_EMPTY_PATH,    "C:/",           TRUE},
919
 
#endif /* non-WIN32 */
920
 
  };
921
 
 
922
 
  *msg = "test svn_dirent_is_ancestor";
923
 
 
924
 
  if (msg_only)
925
 
    return SVN_NO_ERROR;
926
 
 
927
 
  for (i = 0; i < COUNT_OF(tests); i++)
 
1172
test_uri_is_canonical(apr_pool_t *pool)
 
1173
{
 
1174
  const testcase_canonicalize_t *t;
 
1175
 
 
1176
  for (t = uri_canonical_tests;
 
1177
       t < uri_canonical_tests + COUNT_OF(uri_canonical_tests);
 
1178
       t++)
 
1179
    {
 
1180
      svn_boolean_t canonical;
 
1181
 
 
1182
      canonical = svn_uri_is_canonical(t->path, pool);
 
1183
      if (canonical != (t->result && strcmp(t->path, t->result) == 0))
 
1184
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
 
1185
                                 "svn_uri_is_canonical(\"%s\") returned "
 
1186
                                 "\"%s\"; canonical form is \"%s\"",
 
1187
                                 t->path,
 
1188
                                 canonical ? "TRUE" : "FALSE",
 
1189
                                 t->result);
 
1190
    }
 
1191
 
 
1192
  return SVN_NO_ERROR;
 
1193
}
 
1194
 
 
1195
static svn_error_t *
 
1196
test_dirent_split(apr_pool_t *pool)
 
1197
{
 
1198
  apr_size_t i;
 
1199
 
 
1200
  static const char * const paths[][3] = {
 
1201
    { "/foo/bar",        "/foo",          "bar" },
 
1202
    { "/foo/bar/ ",       "/foo/bar",      " " },
 
1203
    { "/foo",            "/",             "foo" },
 
1204
    { "foo",             SVN_EMPTY_PATH,  "foo" },
 
1205
    { ".bar",            SVN_EMPTY_PATH,  ".bar" },
 
1206
    { "/.bar",           "/",             ".bar" },
 
1207
    { "foo/bar",         "foo",           "bar" },
 
1208
    { "/foo/bar",        "/foo",          "bar" },
 
1209
    { "foo/bar",         "foo",           "bar" },
 
1210
    { "foo./.bar",       "foo.",          ".bar" },
 
1211
    { "../foo",          "..",            "foo" },
 
1212
    { SVN_EMPTY_PATH,   SVN_EMPTY_PATH,   SVN_EMPTY_PATH },
 
1213
    { "/flu\\b/\\blarg", "/flu\\b",       "\\blarg" },
 
1214
    { "/",               "/",             "" },
 
1215
    { "X:/foo/bar",      "X:/foo",        "bar" },
 
1216
    { "X:foo/bar",       "X:foo",         "bar" },
 
1217
#ifdef SVN_USE_DOS_PATHS
 
1218
    { "X:/",             "X:/",           "" },
 
1219
    { "X:/foo",          "X:/",           "foo" },
 
1220
    { "X:foo",           "X:",            "foo" },
 
1221
    { "//srv/shr",       "//srv/shr",     "" },
 
1222
    { "//srv/shr/fld",   "//srv/shr",     "fld" },
 
1223
    { "//srv/s r",       "//srv/s r",     "" },
 
1224
#else /* !SVN_USE_DOS_PATHS */
 
1225
    { "X:foo",           SVN_EMPTY_PATH,  "X:foo" },
 
1226
#endif /* SVN_USE_DOS_PATHS */
 
1227
  };
 
1228
 
 
1229
  for (i = 0; i < COUNT_OF(paths); i++)
 
1230
    {
 
1231
      const char *dir, *base_name;
 
1232
 
 
1233
      svn_dirent_split(&dir, &base_name, paths[i][0], pool);
 
1234
      if (strcmp(dir, paths[i][1]))
 
1235
        {
 
1236
          return svn_error_createf
 
1237
            (SVN_ERR_TEST_FAILED, NULL,
 
1238
             "svn_dirent_split (%s) returned dirname '%s' instead of '%s'",
 
1239
             paths[i][0], dir, paths[i][1]);
 
1240
        }
 
1241
      if (strcmp(base_name, paths[i][2]))
 
1242
        {
 
1243
          return svn_error_createf
 
1244
            (SVN_ERR_TEST_FAILED, NULL,
 
1245
             "svn_dirent_split (%s) returned basename '%s' instead of '%s'",
 
1246
             paths[i][0], base_name, paths[i][2]);
 
1247
        }
 
1248
    }
 
1249
  return SVN_NO_ERROR;
 
1250
}
 
1251
 
 
1252
static svn_error_t *
 
1253
test_relpath_split(apr_pool_t *pool)
 
1254
{
 
1255
  apr_size_t i;
 
1256
 
 
1257
  static const char * const paths[][3] = {
 
1258
    { "", "", "" },
 
1259
    { "bar", "", "bar" },
 
1260
    { "foo/bar", "foo", "bar" },
 
1261
    { "a/b/c", "a/b", "c" },
 
1262
  };
 
1263
 
 
1264
  for (i = 0; i < COUNT_OF(paths); i++)
 
1265
    {
 
1266
      const char *dir, *base_name;
 
1267
 
 
1268
      svn_relpath_split( &dir, &base_name, paths[i][0], pool);
 
1269
      if (strcmp(dir, paths[i][1]))
 
1270
        {
 
1271
          return svn_error_createf
 
1272
            (SVN_ERR_TEST_FAILED, NULL,
 
1273
             "svn_relpath_split (%s) returned dirname '%s' instead of '%s'",
 
1274
             paths[i][0], dir, paths[i][1]);
 
1275
        }
 
1276
      if (strcmp(base_name, paths[i][2]))
 
1277
        {
 
1278
          return svn_error_createf
 
1279
            (SVN_ERR_TEST_FAILED, NULL,
 
1280
             "svn_relpath_split (%s) returned basename '%s' instead of '%s'",
 
1281
             paths[i][0], base_name, paths[i][2]);
 
1282
        }
 
1283
    }
 
1284
  return SVN_NO_ERROR;
 
1285
}
 
1286
 
 
1287
 
 
1288
static svn_error_t *
 
1289
test_uri_split(apr_pool_t *pool)
 
1290
{
 
1291
  apr_size_t i;
 
1292
 
 
1293
  static const char * const paths[][3] = {
 
1294
    { "http://server/foo/bar", "http://server/foo", "bar" },
 
1295
    { "http://server/dir/foo/bar", "http://server/dir/foo", "bar" },
 
1296
    { "http://server/some%20dir/foo%20bar", "http://server/some%20dir", "foo bar" },
 
1297
    { "http://server/foo", "http://server", "foo" },
 
1298
    { "http://server", "http://server", "" },
 
1299
    { "file://", "file://", "" },
 
1300
    { "file:///a", "file://", "a" }
 
1301
  };
 
1302
 
 
1303
  for (i = 0; i < COUNT_OF(paths); i++)
 
1304
    {
 
1305
      const char *dir, *base_name;
 
1306
 
 
1307
      svn_uri_split(&dir, &base_name, paths[i][0], pool);
 
1308
      if (strcmp(dir, paths[i][1]))
 
1309
        {
 
1310
          return svn_error_createf
 
1311
            (SVN_ERR_TEST_FAILED, NULL,
 
1312
             "svn_uri_split (%s) returned dirname '%s' instead of '%s'",
 
1313
             paths[i][0], dir, paths[i][1]);
 
1314
        }
 
1315
      if (strcmp(base_name, paths[i][2]))
 
1316
        {
 
1317
          return svn_error_createf
 
1318
            (SVN_ERR_TEST_FAILED, NULL,
 
1319
             "svn_uri_split (%s) returned basename '%s' instead of '%s'",
 
1320
             paths[i][0], base_name, paths[i][2]);
 
1321
        }
 
1322
    }
 
1323
  return SVN_NO_ERROR;
 
1324
}
 
1325
 
 
1326
/* Paths to test and the expected result, for ancestor tests. */
 
1327
typedef struct testcase_ancestor_t {
 
1328
  const char *path1;
 
1329
  const char *path2;
 
1330
  const char *result;
 
1331
} testcase_ancestor_t;
 
1332
 
 
1333
static const testcase_ancestor_t dirent_ancestor_tests[] =
 
1334
  {
 
1335
    { "",               "",                 "" },
 
1336
    { "",               "foo",              "foo" },
 
1337
    { "",               ".bar",             ".bar" },
 
1338
    { "",               "/",                NULL },
 
1339
    { "",               "/foo",             NULL },
 
1340
    { "/",              "",                 NULL },
 
1341
    { "/",              "foo",              NULL },
 
1342
    { "/",              "/",                "" },
 
1343
    { "/",              "/foo",             "foo" },
 
1344
    { "/",              "bar/bla",          NULL },
 
1345
    { "/foo",           "/foo",             "" },
 
1346
    { "/foo",           "/foot",            NULL },
 
1347
    { "/foo",           "/foo/bar",         "bar" },
 
1348
    { "/foo/bar",       "/foot/bar",        NULL },
 
1349
    { "/foot",          "/foo",             NULL },
 
1350
    { "/foo/bar/bla",   "/foo/bar",         NULL },
 
1351
    { "/foo/bar",       "/foo/bar/bla",     "bla" },
 
1352
    { "foo/bar",        "foo",              NULL },
 
1353
    { "/foo/bar",       "foo",              NULL },
 
1354
    { "/.bar",          "/",                NULL },
 
1355
    { "/foo/bar",       "/foo",             NULL },
 
1356
    { "foo",            "foo/bar",          "bar" },
 
1357
    { "foo.",           "foo./.bar",        ".bar" },
 
1358
    { "X:foo",          "X:bar",            NULL },
 
1359
    { "../foo",         "..",               NULL },
 
1360
#ifdef SVN_USE_DOS_PATHS
 
1361
    { "",               "C:",               NULL },
 
1362
    { "",               "C:foo",            NULL },
 
1363
    { "",               "C:/",              NULL },
 
1364
    { "",               "C:/foo",           NULL },
 
1365
    { "X",              "X:",               NULL },
 
1366
    { "X",              "X:foo",            NULL },
 
1367
    { "X",              "X:/",              NULL },
 
1368
    { "X",              "X:/foo",           NULL },
 
1369
    { "X:",             "X:",               "" },
 
1370
    { "X:",             "X:foo",            "foo" },
 
1371
    { "X:",             "X:/",              NULL },
 
1372
    { "X:",             "X:/foo",           NULL },
 
1373
    { "X:/",            "X:",               NULL },
 
1374
    { "X:/",            "X:foo",            NULL },
 
1375
    { "X:/",            "X:/",              "" },
 
1376
    { "X:/",            "X:/foo",           "foo" },
 
1377
    { "X:/foo",         "X:/",              NULL },
 
1378
    { "A:/foo",         "A:/foo/bar",       "bar" },
 
1379
    { "A:/foo",         "A:/foot",          NULL },
 
1380
    { "//srv",          "//srv/share",      NULL },
 
1381
    { "//srv",          "//srv/shr/fld",    NULL },
 
1382
    { "//srv/shr",      "//srv",            NULL },
 
1383
    { "//srv/share",    "//vrs/share",      NULL },
 
1384
    { "//srv/share",    "//srv/share/foo",  "foo" },
 
1385
    { "//srv/shr",      "//srv/shr/fld",    "fld" },
 
1386
    { "//srv/s r",      "//srv/s r/fld",    "fld" },
 
1387
    { "//srv/shr/fld",  "//srv/shr",        NULL },
 
1388
    { "//srv/shr/fld",  "//srv2/shr/fld",   NULL },
 
1389
    { "/",              "//srv/share",      NULL },
 
1390
#else /* !SVN_USE_DOS_PATHS */
 
1391
    { "",               "C:",               "C:" },
 
1392
    { "",               "C:/foo",           "C:/foo" },
 
1393
    { "X:",             "X:foo",            NULL },
 
1394
#endif
 
1395
  };
 
1396
 
 
1397
static svn_error_t *
 
1398
test_dirent_is_ancestor(apr_pool_t *pool)
 
1399
{
 
1400
  const testcase_ancestor_t *t;
 
1401
 
 
1402
  for (t = dirent_ancestor_tests;
 
1403
       t < dirent_ancestor_tests + COUNT_OF(dirent_ancestor_tests);
 
1404
       t++)
928
1405
    {
929
1406
      svn_boolean_t retval;
930
1407
 
931
 
      retval = svn_dirent_is_ancestor(tests[i].path1, tests[i].path2);
932
 
      if (tests[i].result != retval)
 
1408
      retval = svn_dirent_is_ancestor(t->path1, t->path2);
 
1409
      if (!!t->result != retval)
933
1410
        return svn_error_createf
934
1411
          (SVN_ERR_TEST_FAILED, NULL,
935
1412
           "svn_dirent_is_ancestor (%s, %s) returned %s instead of %s",
936
 
           tests[i].path1, tests[i].path2, retval ? "TRUE" : "FALSE",
937
 
           tests[i].result ? "TRUE" : "FALSE");
938
 
    }
939
 
  return SVN_NO_ERROR;
940
 
}
941
 
 
942
 
static svn_error_t *
943
 
test_uri_is_ancestor(const char **msg,
944
 
                     svn_boolean_t msg_only,
945
 
                     svn_test_opts_t *opts,
946
 
                     apr_pool_t *pool)
947
 
{
948
 
  apr_size_t i;
949
 
 
950
 
  /* URIs to test and their expected results. */
951
 
  struct {
952
 
    const char *path1;
953
 
    const char *path2;
954
 
    svn_boolean_t result;
955
 
  } tests[] = {
956
 
    { "/foo",            "/foo/bar",      TRUE},
957
 
    { "/foo/bar",        "/foo/bar/",     TRUE},
958
 
    { "/",               "/foo",          TRUE},
959
 
    { SVN_EMPTY_PATH,    "foo",           TRUE},
960
 
    { SVN_EMPTY_PATH,    ".bar",          TRUE},
961
 
    { SVN_EMPTY_PATH,    "/",             FALSE},
962
 
    { SVN_EMPTY_PATH,    "/foo",          FALSE},
963
 
    { "/.bar",           "/",             FALSE},
964
 
    { "foo/bar",         "foo",           FALSE},
965
 
    { "/foo/bar",        "/foo",          FALSE},
966
 
    { "foo",             "foo/bar",       TRUE},
967
 
    { "foo.",            "foo./.bar",     TRUE},
968
 
 
969
 
    { "../foo",          "..",            FALSE},
970
 
    { SVN_EMPTY_PATH,    SVN_EMPTY_PATH,  TRUE},
971
 
    { "/",               "/",             TRUE},
972
 
 
973
 
    { "http://test",    "http://test",     TRUE},
974
 
    { "http://test",    "http://taste",    FALSE},
975
 
    { "http://test",    "http://test/foo", TRUE},
976
 
    { "http://test",    "file://test/foo", FALSE},
977
 
    { "http://test",    "http://testF",    FALSE},
978
 
    { "http://",        "http://test",     TRUE},
979
 
    { SVN_EMPTY_PATH,   "http://test",     FALSE},
980
 
    { "X:foo",          "X:bar",           FALSE},
981
 
    { "X:",             "X:foo",           FALSE},
982
 
  };
983
 
 
984
 
  *msg = "test svn_uri_is_ancestor";
985
 
 
986
 
  if (msg_only)
987
 
    return SVN_NO_ERROR;
988
 
 
989
 
  for (i = 0; i < COUNT_OF(tests); i++)
990
 
    {
991
 
      svn_boolean_t retval;
992
 
 
993
 
      retval = svn_uri_is_ancestor(tests[i].path1, tests[i].path2);
994
 
      if (tests[i].result != retval)
 
1413
           t->path1, t->path2, retval ? "TRUE" : "FALSE",
 
1414
           t->result ? "TRUE" : "FALSE");
 
1415
    }
 
1416
  return SVN_NO_ERROR;
 
1417
}
 
1418
 
 
1419
static const testcase_ancestor_t relpath_ancestor_tests[] =
 
1420
  {
 
1421
    { "",               "",                 "" },
 
1422
    { "",               "foo",              "foo" },
 
1423
    { "",               ".bar",             ".bar" },
 
1424
    { "",               "bar/bla",          "bar/bla" },
 
1425
    { "foo",            "foo",              "" },
 
1426
    { "foo",            "foo/bar",          "bar" },
 
1427
    { "foo",            "foot",             NULL },
 
1428
    { "foo.",           "foo./.bar",        ".bar" },
 
1429
    { "foot",           "foo",              NULL },
 
1430
    { "foo/bar",        "foo",              NULL },
 
1431
    { "foo/bar",        "foo/bar/bla",      "bla" },
 
1432
    { "foo/bar",        "foot/bar",         NULL },
 
1433
    { "foo/bar/bla",    "foo/bar",          NULL },
 
1434
    { "food/bar",       "foo/bar",          NULL },
 
1435
    { "http:/server",   "http:/server/q",   "q" },
 
1436
    { "svn:/server",    "http:/server/q",   NULL },
 
1437
    /* These are relpaths so a colon is not special. */
 
1438
    { "",               "C:",               "C:" },
 
1439
    { "X:",             "X:foo",            NULL },
 
1440
    { "X:",             "X:/foo",           "foo" },
 
1441
    { "X:foo",          "X:bar",            NULL },
 
1442
  };
 
1443
 
 
1444
static svn_error_t *
 
1445
test_relpath_is_ancestor(apr_pool_t *pool)
 
1446
{
 
1447
  const testcase_ancestor_t *t;
 
1448
 
 
1449
  for (t = relpath_ancestor_tests;
 
1450
       t < relpath_ancestor_tests + COUNT_OF(relpath_ancestor_tests);
 
1451
       t++)
 
1452
    {
 
1453
      svn_boolean_t retval;
 
1454
 
 
1455
      retval = svn_relpath__is_ancestor(t->path1, t->path2);
 
1456
      if (!!t->result != retval)
 
1457
        return svn_error_createf
 
1458
          (SVN_ERR_TEST_FAILED, NULL,
 
1459
           "svn_relpath_is_ancestor (%s, %s) returned %s instead of %s",
 
1460
           t->path1, t->path2, retval ? "TRUE" : "FALSE",
 
1461
           t->result ? "TRUE" : "FALSE");
 
1462
    }
 
1463
  return SVN_NO_ERROR;
 
1464
}
 
1465
 
 
1466
static const testcase_ancestor_t uri_ancestor_tests[] =
 
1467
  {
 
1468
    { "http://test",    "http://test",      "" },
 
1469
    { "http://test",    "http://taste",     NULL },
 
1470
    { "http://test",    "http://test/foo",  "foo" },
 
1471
    { "http://test",    "file://test/foo",  NULL },
 
1472
    { "http://test",    "http://testf",     NULL },
 
1473
    { "http://",        "http://test",      NULL },
 
1474
    { "http://server",  "http://server/q",  "q" },
 
1475
    { "svn://server",   "http://server/q",  NULL },
 
1476
  };
 
1477
 
 
1478
static svn_error_t *
 
1479
test_uri_is_ancestor(apr_pool_t *pool)
 
1480
{
 
1481
  const testcase_ancestor_t *t;
 
1482
 
 
1483
  for (t = uri_ancestor_tests;
 
1484
       t < uri_ancestor_tests + COUNT_OF(uri_ancestor_tests);
 
1485
       t++)
 
1486
    {
 
1487
      svn_boolean_t retval;
 
1488
 
 
1489
      retval = svn_uri__is_ancestor(t->path1, t->path2);
 
1490
      if (!!t->result != retval)
995
1491
        return svn_error_createf
996
1492
          (SVN_ERR_TEST_FAILED, NULL,
997
1493
           "svn_uri_is_ancestor (%s, %s) returned %s instead of %s",
998
 
           tests[i].path1, tests[i].path2, retval ? "TRUE" : "FALSE",
999
 
           tests[i].result ? "TRUE" : "FALSE");
1000
 
    }
1001
 
  return SVN_NO_ERROR;
1002
 
}
1003
 
 
1004
 
static svn_error_t *
1005
 
test_dirent_get_longest_ancestor(const char **msg,
1006
 
                                 svn_boolean_t msg_only,
1007
 
                                 svn_test_opts_t *opts,
1008
 
                                 apr_pool_t *pool)
1009
 
{
1010
 
  apr_size_t i;
1011
 
 
1012
 
  /* Paths to test and their expected results. */
1013
 
  struct {
1014
 
    const char *path1;
1015
 
    const char *path2;
1016
 
    const char *result;
1017
 
  } tests[] = {
 
1494
           t->path1, t->path2, retval ? "TRUE" : "FALSE",
 
1495
           t->result ? "TRUE" : "FALSE");
 
1496
    }
 
1497
  return SVN_NO_ERROR;
 
1498
}
 
1499
 
 
1500
static svn_error_t *
 
1501
test_dirent_skip_ancestor(apr_pool_t *pool)
 
1502
{
 
1503
  const testcase_ancestor_t *t;
 
1504
 
 
1505
  for (t = dirent_ancestor_tests;
 
1506
       t < dirent_ancestor_tests + COUNT_OF(dirent_ancestor_tests);
 
1507
       t++)
 
1508
    {
 
1509
      const char* retval;
 
1510
 
 
1511
      retval = svn_dirent_skip_ancestor(t->path1, t->path2);
 
1512
      if ((t->result == NULL)
 
1513
          ? (retval != NULL)
 
1514
          : (retval == NULL || strcmp(t->result, retval) != 0))
 
1515
        return svn_error_createf(
 
1516
             SVN_ERR_TEST_FAILED, NULL,
 
1517
             "svn_dirent_skip_ancestor (%s, %s) returned %s instead of %s",
 
1518
             t->path1, t->path2, retval, t->result);
 
1519
    }
 
1520
  return SVN_NO_ERROR;
 
1521
}
 
1522
 
 
1523
static svn_error_t *
 
1524
test_relpath_skip_ancestor(apr_pool_t *pool)
 
1525
{
 
1526
  const testcase_ancestor_t *t;
 
1527
 
 
1528
  for (t = relpath_ancestor_tests;
 
1529
       t < relpath_ancestor_tests + COUNT_OF(relpath_ancestor_tests);
 
1530
       t++)
 
1531
    {
 
1532
      const char* retval;
 
1533
 
 
1534
      retval = svn_relpath_skip_ancestor(t->path1, t->path2);
 
1535
      if ((t->result == NULL)
 
1536
          ? (retval != NULL)
 
1537
          : (retval == NULL || strcmp(t->result, retval) != 0))
 
1538
        return svn_error_createf(
 
1539
             SVN_ERR_TEST_FAILED, NULL,
 
1540
             "svn_relpath_skip_ancestor (%s, %s) returned %s instead of %s",
 
1541
             t->path1, t->path2, retval, t->result);
 
1542
    }
 
1543
  return SVN_NO_ERROR;
 
1544
}
 
1545
 
 
1546
static svn_error_t *
 
1547
test_uri_skip_ancestor(apr_pool_t *pool)
 
1548
{
 
1549
  const testcase_ancestor_t *t;
 
1550
 
 
1551
  for (t = uri_ancestor_tests;
 
1552
       t < uri_ancestor_tests + COUNT_OF(uri_ancestor_tests);
 
1553
       t++)
 
1554
    {
 
1555
      const char* retval;
 
1556
 
 
1557
      retval = svn_uri_skip_ancestor(t->path1, t->path2, pool);
 
1558
      if ((t->result == NULL)
 
1559
          ? (retval != NULL)
 
1560
          : (retval == NULL || strcmp(t->result, retval) != 0))
 
1561
        return svn_error_createf(
 
1562
             SVN_ERR_TEST_FAILED, NULL,
 
1563
             "svn_uri_skip_ancestor (%s, %s) returned %s instead of %s",
 
1564
             t->path1, t->path2, retval, t->result);
 
1565
    }
 
1566
  return SVN_NO_ERROR;
 
1567
}
 
1568
 
 
1569
/* Paths to test and the expected result, for get_longest_ancestor tests. */
 
1570
typedef struct testcase_get_longest_ancestor_t {
 
1571
  const char *path1;
 
1572
  const char *path2;
 
1573
  const char *result;
 
1574
} testcase_get_longest_ancestor_t;
 
1575
 
 
1576
static svn_error_t *
 
1577
test_dirent_get_longest_ancestor(apr_pool_t *pool)
 
1578
{
 
1579
  const testcase_get_longest_ancestor_t *t;
 
1580
  static const testcase_get_longest_ancestor_t tests[] = {
1018
1581
    { "/foo",           "/foo/bar",        "/foo"},
1019
1582
    { "/foo/bar",       "foo/bar",         SVN_EMPTY_PATH},
1020
1583
    { "/",              "/foo",            "/"},
1031
1594
    { "/",              "/",               "/"},
1032
1595
    { "X:foo",          "Y:foo",           SVN_EMPTY_PATH},
1033
1596
    { "X:/folder1",     "Y:/folder2",      SVN_EMPTY_PATH},
1034
 
#if defined(WIN32) || defined(__CYGWIN__)
 
1597
#ifdef SVN_USE_DOS_PATHS
1035
1598
    { "X:/",            "X:/",             "X:/"},
1036
1599
    { "X:/foo/bar/A/D/H/psi", "X:/foo/bar/A/B", "X:/foo/bar/A" },
1037
1600
    { "X:/foo/bar/boo", "X:/foo/bar/baz/boz", "X:/foo/bar"},
1045
1608
    { "X:",             "X:foo",           "X:"},
1046
1609
    { "X:",             "X:/",             SVN_EMPTY_PATH},
1047
1610
    { "X:foo",          "X:bar",           "X:"},
1048
 
#else /* WIN32 or Cygwin */
 
1611
#else /* !SVN_USE_DOS_PATHS */
1049
1612
    { "X:/foo",         "X:",              "X:"},
1050
1613
    { "X:/folder1",     "X:/folder2",      "X:"},
1051
1614
    { "X:",             "X:foo",           SVN_EMPTY_PATH},
1052
1615
    { "X:foo",          "X:bar",           SVN_EMPTY_PATH},
1053
 
#endif /* non-WIN32 */
 
1616
#endif /* SVN_USE_DOS_PATHS */
1054
1617
  };
1055
1618
 
1056
 
  *msg = "test svn_dirent_get_longest_ancestor";
1057
 
 
1058
 
  if (msg_only)
1059
 
    return SVN_NO_ERROR;
1060
 
 
1061
 
  for (i = 0; i < COUNT_OF(tests); i++)
 
1619
  for (t = tests; t < tests + COUNT_OF(tests); t++)
1062
1620
    {
1063
1621
      const char *retval;
1064
1622
 
1065
 
      retval = svn_dirent_get_longest_ancestor(tests[i].path1, tests[i].path2,
1066
 
                                               pool);
 
1623
      retval = svn_dirent_get_longest_ancestor(t->path1, t->path2, pool);
1067
1624
 
1068
 
      if (strcmp(tests[i].result, retval))
 
1625
      if (strcmp(t->result, retval))
1069
1626
        return svn_error_createf
1070
1627
          (SVN_ERR_TEST_FAILED, NULL,
1071
1628
           "svn_dirent_get_longest_ancestor (%s, %s) returned %s instead of %s",
1072
 
           tests[i].path1, tests[i].path2, retval, tests[i].result);
 
1629
           t->path1, t->path2, retval, t->result);
1073
1630
 
1074
1631
      /* changing the order of the paths should return the same results */
1075
 
      retval = svn_dirent_get_longest_ancestor(tests[i].path2, tests[i].path1,
1076
 
                                               pool);
 
1632
      retval = svn_dirent_get_longest_ancestor(t->path2, t->path1, pool);
1077
1633
 
1078
 
      if (strcmp(tests[i].result, retval))
 
1634
      if (strcmp(t->result, retval))
1079
1635
        return svn_error_createf
1080
1636
          (SVN_ERR_TEST_FAILED, NULL,
1081
1637
           "svn_dirent_get_longest_ancestor (%s, %s) returned %s instead of %s",
1082
 
           tests[i].path2, tests[i].path1, retval, tests[i].result);
 
1638
           t->path2, t->path1, retval, t->result);
1083
1639
    }
1084
1640
  return SVN_NO_ERROR;
1085
1641
}
1086
1642
 
1087
1643
static svn_error_t *
1088
 
test_uri_get_longest_ancestor(const char **msg,
1089
 
                              svn_boolean_t msg_only,
1090
 
                              svn_test_opts_t *opts,
1091
 
                              apr_pool_t *pool)
 
1644
test_relpath_get_longest_ancestor(apr_pool_t *pool)
1092
1645
{
1093
 
  apr_size_t i;
1094
 
 
1095
 
  /* Paths to test and their expected results. */
1096
 
  struct {
1097
 
    const char *path1;
1098
 
    const char *path2;
1099
 
    const char *result;
1100
 
  } tests[] = {
1101
 
    { "/foo",           "/foo/bar",        "/foo"},
1102
 
    { "/foo/bar",       "foo/bar",         SVN_EMPTY_PATH},
1103
 
    { "/",              "/foo",            "/"},
1104
 
    { SVN_EMPTY_PATH,   "foo",             SVN_EMPTY_PATH},
1105
 
    { SVN_EMPTY_PATH,   ".bar",            SVN_EMPTY_PATH},
1106
 
    { "/.bar",          "/",               "/"},
1107
 
    { "foo/bar",        "foo",             "foo"},
1108
 
    { "/foo/bar",       "/foo",            "/foo"},
1109
 
    { "/rif",           "/raf",            "/"},
1110
 
    { "foo",            "bar",             SVN_EMPTY_PATH},
 
1646
  const testcase_get_longest_ancestor_t *t;
 
1647
  static const testcase_get_longest_ancestor_t tests[] = {
 
1648
    { "foo",            "foo/bar",         "foo"},
 
1649
    { "foo/bar",        "foo/bar",         "foo/bar"},
 
1650
    { "",               "foo",             ""},
 
1651
    { "",               "foo",             ""},
 
1652
    { "",               ".bar",            ""},
 
1653
    { ".bar",           "",                ""},
 
1654
    { "foo/bar",        "foo",             "foo"},
 
1655
    { "foo/bar",        "foo",             "foo"},
 
1656
    { "rif",            "raf",             ""},
 
1657
    { "foo",            "bar",             ""},
1111
1658
    { "foo",            "foo/bar",         "foo"},
1112
1659
    { "foo.",           "foo./.bar",       "foo."},
1113
 
    { SVN_EMPTY_PATH,   SVN_EMPTY_PATH,    SVN_EMPTY_PATH},
1114
 
    { "/",              "/",               "/"},
 
1660
    { "",               "",                ""},
 
1661
    { "http:/test",     "http:/test",      "http:/test"},
 
1662
    { "http:/test",     "http:/taste",     "http:"},
 
1663
    { "http:/test",     "http:/test/foo",  "http:/test"},
 
1664
    { "http:/test",     "file:/test/foo",  ""},
 
1665
    { "http:/test",     "http:/testF",     "http:"},
 
1666
    { "file:/A/C",      "file:/B/D",       "file:"},
 
1667
    { "file:/A/C",      "file:/A/D",       "file:/A"},
 
1668
    { "X:/foo",         "X:",              "X:"},
 
1669
    { "X:/folder1",     "X:/folder2",      "X:"},
 
1670
    { "X:",             "X:foo",           ""},
 
1671
    { "X:foo",          "X:bar",           ""},
 
1672
  };
 
1673
 
 
1674
  for (t = tests; t < tests + COUNT_OF(tests); t++)
 
1675
    {
 
1676
      const char *retval;
 
1677
 
 
1678
      retval = svn_relpath_get_longest_ancestor(t->path1, t->path2, pool);
 
1679
 
 
1680
      if (strcmp(t->result, retval))
 
1681
        return svn_error_createf
 
1682
          (SVN_ERR_TEST_FAILED, NULL,
 
1683
           "svn_relpath_get_longest_ancestor (%s, %s) returned "
 
1684
           "%s instead of %s",
 
1685
           t->path1, t->path2, retval, t->result);
 
1686
 
 
1687
      /* changing the order of the paths should return the same results */
 
1688
      retval = svn_relpath_get_longest_ancestor(t->path2, t->path1, pool);
 
1689
 
 
1690
      if (strcmp(t->result, retval))
 
1691
        return svn_error_createf
 
1692
          (SVN_ERR_TEST_FAILED, NULL,
 
1693
           "svn_relpath_get_longest_ancestor (%s, %s) returned "
 
1694
           "%s instead of %s",
 
1695
           t->path2, t->path1, retval, t->result);
 
1696
    }
 
1697
  return SVN_NO_ERROR;
 
1698
}
 
1699
 
 
1700
static svn_error_t *
 
1701
test_uri_get_longest_ancestor(apr_pool_t *pool)
 
1702
{
 
1703
  const testcase_get_longest_ancestor_t *t;
 
1704
  static const testcase_get_longest_ancestor_t tests[] = {
1115
1705
    { "http://test",    "http://test",     "http://test"},
1116
1706
    { "http://test",    "http://taste",    SVN_EMPTY_PATH},
1117
1707
    { "http://test",    "http://test/foo", "http://test"},
1118
1708
    { "http://test",    "file://test/foo", SVN_EMPTY_PATH},
1119
 
    { "http://test",    "http://testF",    SVN_EMPTY_PATH},
 
1709
    { "http://test",    "http://testf",    SVN_EMPTY_PATH},
1120
1710
    { "http://",        "http://test",     SVN_EMPTY_PATH},
1121
1711
    { "file:///A/C",    "file:///B/D",     SVN_EMPTY_PATH},
1122
1712
    { "file:///A/C",    "file:///A/D",     "file:///A"},
1123
 
    { "X:/foo",         "X:",              "X:"},
1124
 
    { "X:/folder1",     "X:/folder2",      "X:"},
1125
 
    { "X:",             "X:foo",           SVN_EMPTY_PATH},
1126
 
    { "X:foo",          "X:bar",           SVN_EMPTY_PATH},
1127
1713
  };
1128
1714
 
1129
 
  *msg = "test svn_uri_get_longest_ancestor";
1130
 
 
1131
 
  if (msg_only)
1132
 
    return SVN_NO_ERROR;
1133
 
 
1134
 
  for (i = 0; i < COUNT_OF(tests); i++)
 
1715
  for (t = tests; t < tests + COUNT_OF(tests); t++)
1135
1716
    {
1136
1717
      const char *retval;
1137
1718
 
1138
 
      retval = svn_uri_get_longest_ancestor(tests[i].path1, tests[i].path2,
1139
 
                                             pool);
 
1719
      retval = svn_uri_get_longest_ancestor(t->path1, t->path2, pool);
1140
1720
 
1141
 
      if (strcmp(tests[i].result, retval))
 
1721
      if (strcmp(t->result, retval))
1142
1722
        return svn_error_createf
1143
1723
          (SVN_ERR_TEST_FAILED, NULL,
1144
1724
           "svn_uri_get_longest_ancestor (%s, %s) returned %s instead of %s",
1145
 
           tests[i].path1, tests[i].path2, retval, tests[i].result);
 
1725
           t->path1, t->path2, retval, t->result);
1146
1726
 
1147
1727
      /* changing the order of the paths should return the same results */
1148
 
      retval = svn_uri_get_longest_ancestor(tests[i].path2, tests[i].path1,
1149
 
                                             pool);
 
1728
      retval = svn_uri_get_longest_ancestor(t->path2, t->path1, pool);
1150
1729
 
1151
 
      if (strcmp(tests[i].result, retval))
 
1730
      if (strcmp(t->result, retval))
1152
1731
        return svn_error_createf
1153
1732
          (SVN_ERR_TEST_FAILED, NULL,
1154
1733
           "svn_uri_get_longest_ancestor (%s, %s) returned %s instead of %s",
1155
 
           tests[i].path2, tests[i].path1, retval, tests[i].result);
 
1734
           t->path2, t->path1, retval, t->result);
1156
1735
    }
1157
1736
  return SVN_NO_ERROR;
1158
1737
}
1159
1738
 
1160
1739
static svn_error_t *
1161
 
test_dirent_is_child(const char **msg,
1162
 
                     svn_boolean_t msg_only,
1163
 
                     svn_test_opts_t *opts,
1164
 
                     apr_pool_t *pool)
 
1740
test_dirent_is_child(apr_pool_t *pool)
1165
1741
{
1166
1742
  int i, j;
1167
1743
 
1177
1753
    ".foo",
1178
1754
    "/",
1179
1755
    "foo2",
1180
 
#if defined(WIN32) || defined(__CYGWIN__)
 
1756
#ifdef SVN_USE_DOS_PATHS
1181
1757
    "//srv",
1182
1758
    "//srv2",
1183
1759
    "//srv/shr",
1192
1768
    "H:",
1193
1769
    "H:foo",
1194
1770
    "H:foo/baz",
1195
 
#endif /* Win32 and Cygwin */
 
1771
#endif /* SVN_USE_DOS_PATHS */
1196
1772
    };
1197
1773
 
1198
1774
  /* Maximum number of path[] items for all platforms */
1223
1799
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
1224
1800
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1225
1801
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
1226
 
#if defined(WIN32) || defined(__CYGWIN__)
 
1802
#ifdef SVN_USE_DOS_PATHS
1227
1803
    /* //srv paths */
1228
1804
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1229
1805
      0, 0, "shr", "shr/fld", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
1256
1832
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "baz" },
1257
1833
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1258
1834
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
1259
 
#endif /* Win32 and Cygwin */
 
1835
#endif /* SVN_USE_DOS_PATHS */
1260
1836
  };
1261
1837
 
1262
 
  *msg = "test svn_dirent_is_child";
1263
 
 
1264
 
  if (msg_only)
1265
 
    return SVN_NO_ERROR;
1266
 
 
1267
1838
  for (i = 0; i < COUNT_OF(paths); i++)
1268
1839
    {
1269
1840
      for (j = 0; j < COUNT_OF(paths); j++)
1289
1860
}
1290
1861
 
1291
1862
static svn_error_t *
1292
 
test_uri_is_child(const char **msg,
1293
 
                  svn_boolean_t msg_only,
1294
 
                  svn_test_opts_t *opts,
1295
 
                  apr_pool_t *pool)
 
1863
test_relpath_is_child(apr_pool_t *pool)
1296
1864
{
1297
1865
  int i, j;
1298
1866
 
1299
 
#define NUM_TEST_PATHS 16
1300
 
 
1301
1867
  static const char * const paths[] = {
1302
 
    "/foo/bar",
1303
 
    "/foo/bars",
1304
 
    "/foo/baz",
1305
 
    "/foo/bar/baz",
1306
 
    "/flu/blar/blaz",
1307
 
    "/foo/bar/baz/bing/boom",
1308
 
    SVN_EMPTY_PATH,
 
1868
    "",
1309
1869
    "foo",
 
1870
    "foo/bar",
 
1871
    "foo/bars",
 
1872
    "foo/baz",
 
1873
    "foo/bar/baz",
 
1874
    "flu/blar/blaz",
 
1875
    "foo/bar/baz/bing/boom",
1310
1876
    ".foo",
1311
 
    "/",
 
1877
    ":",
1312
1878
    "foo2",
1313
 
    "H:/foo/bar",
1314
 
    "H:/foo/baz",
1315
 
    "H:",
1316
 
    "H:foo",
1317
 
    "H:foo/baz",
 
1879
    "food",
 
1880
    "bar",
 
1881
    "baz",
 
1882
    "ba",
 
1883
    "bad"
 
1884
    };
 
1885
 
 
1886
  /* Maximum number of path[] items for all platforms */
 
1887
#define MAX_PATHS 32
 
1888
 
 
1889
  static const char * const
 
1890
    remainders[COUNT_OF(paths)][MAX_PATHS] = {
 
1891
    { 0, "foo", "foo/bar", "foo/bars", "foo/baz", "foo/bar/baz",
 
1892
      "flu/blar/blaz", "foo/bar/baz/bing/boom", ".foo", ":", "foo2", "food",
 
1893
      "bar", "baz", "ba", "bad" },
 
1894
    { 0, 0, "bar", "bars", "baz", "bar/baz", 0, "bar/baz/bing/boom", 0, 0, 0,
 
1895
      0, 0, 0, 0, 0 },
 
1896
    { 0, 0, 0, 0, 0, "baz", 0, "baz/bing/boom", 0, 0, 0, 0, 0, 0, 0, 0 },
 
1897
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
1898
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
1899
    { 0, 0, 0, 0, 0, 0, 0, "bing/boom", 0, 0, 0, 0, 0, 0, 0, 0 },
 
1900
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
1901
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
1902
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
1903
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
1904
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
1905
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
1906
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
1907
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
1908
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
 
1909
  };
 
1910
 
 
1911
  for (i = 0; i < COUNT_OF(paths); i++)
 
1912
    {
 
1913
      for (j = 0; j < COUNT_OF(paths); j++)
 
1914
        {
 
1915
          const char *remainder;
 
1916
 
 
1917
          remainder = svn_dirent_is_child(paths[i], paths[j], pool);
 
1918
 
 
1919
          if (strcmp(paths[j], "foodbar") == 0)
 
1920
            SVN_ERR_MALFUNCTION();
 
1921
 
 
1922
          if (((remainder) && (! remainders[i][j]))
 
1923
              || ((! remainder) && (remainders[i][j]))
 
1924
              || (remainder && strcmp(remainder, remainders[i][j])))
 
1925
            return svn_error_createf
 
1926
              (SVN_ERR_TEST_FAILED, NULL,
 
1927
               "svn_relpath_is_child(%s, %s) returned '%s' instead of '%s'",
 
1928
               paths[i], paths[j],
 
1929
               remainder ? remainder : "(null)",
 
1930
               remainders[i][j] ? remainders[i][j] : "(null)" );
 
1931
        }
 
1932
    }
 
1933
 
 
1934
#undef NUM_TEST_PATHS
 
1935
  return SVN_NO_ERROR;
 
1936
}
 
1937
 
 
1938
 
 
1939
static svn_error_t *
 
1940
test_uri_is_child(apr_pool_t *pool)
 
1941
{
 
1942
  int i, j;
 
1943
 
 
1944
  static const char * const paths[] = {
 
1945
    "http://foo/bar",
 
1946
    "http://foo/bar%20bell",
 
1947
    "http://foo/baz",
 
1948
    "http://foo",
 
1949
    "http://f",
 
1950
    "file://foo/bar",
 
1951
    "file://foo/bar/baz%20bol",
1318
1952
    };
1319
1953
 
1320
1954
  static const char * const
1321
1955
    remainders[COUNT_OF(paths)][COUNT_OF(paths)] = {
1322
 
    { 0, 0, 0, "baz", 0, "baz/bing/boom", 0, 0, 0, 0, 0,
1323
 
      0, 0, 0, 0, 0 },
1324
 
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1325
 
      0, 0, 0, 0, 0 },
1326
 
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1327
 
      0, 0, 0, 0, 0 },
1328
 
    { 0, 0, 0, 0, 0, "bing/boom", 0, 0, 0, 0, 0,
1329
 
      0, 0, 0, 0, 0 },
1330
 
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1331
 
      0, 0, 0, 0, 0 },
1332
 
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1333
 
      0, 0, 0, 0, 0 },
1334
 
    { 0, 0, 0, 0, 0, 0, 0, "foo", ".foo", 0, "foo2",
1335
 
      "H:/foo/bar", "H:/foo/baz", "H:", "H:foo", "H:foo/baz" },
1336
 
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1337
 
      0, 0, 0, 0, 0 },
1338
 
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1339
 
      0, 0, 0, 0, 0 },
1340
 
    { "foo/bar", "foo/bars", "foo/baz", "foo/bar/baz", "flu/blar/blaz",
1341
 
      "foo/bar/baz/bing/boom", 0, 0, 0, 0, 0,
1342
 
      0, 0, 0, 0, 0 },
1343
 
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1344
 
      0, 0, 0, 0, 0 },
1345
 
    /* H:/ paths */
1346
 
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1347
 
      0, 0, 0, 0, 0 },
1348
 
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1349
 
      0, 0, 0, 0, 0 },
1350
 
    /* H: paths */
1351
 
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1352
 
      "foo/bar", "foo/baz", 0, 0, 0 },
1353
 
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1354
 
      0, 0, 0, 0, "baz" },
1355
 
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1356
 
      0, 0, 0, 0, 0 },
 
1956
    { 0, 0, 0, 0, 0, 0, 0 },
 
1957
    { 0, 0, 0, 0, 0, 0, 0 },
 
1958
    { 0, 0, 0, 0, 0, 0, 0 },
 
1959
    { "bar", "bar bell", "baz", 0, 0, 0, 0 },
 
1960
    { 0, 0, 0, 0, 0, 0, 0 },
 
1961
    { 0, 0, 0, 0, 0, 0, "baz bol" },
 
1962
    { 0, 0, 0, 0, 0, 0, 0 },
1357
1963
  };
1358
1964
 
1359
 
  *msg = "test svn_uri_is_child";
1360
 
 
1361
 
  if (msg_only)
1362
 
    return SVN_NO_ERROR;
1363
 
 
1364
1965
  for (i = 0; i < COUNT_OF(paths); i++)
1365
1966
    {
1366
1967
      for (j = 0; j < COUNT_OF(paths); j++)
1367
1968
        {
1368
1969
          const char *remainder;
1369
1970
 
1370
 
          remainder = svn_uri_is_child(paths[i], paths[j], pool);
 
1971
          remainder = svn_uri__is_child(paths[i], paths[j], pool);
1371
1972
 
1372
1973
          if (((remainder) && (! remainders[i][j]))
1373
1974
              || ((! remainder) && (remainders[i][j]))
1374
1975
              || (remainder && strcmp(remainder, remainders[i][j])))
1375
1976
            return svn_error_createf
1376
1977
              (SVN_ERR_TEST_FAILED, NULL,
1377
 
               "svn_uri_is_child (%s, %s) returned '%s' instead of '%s'",
1378
 
               paths[i], paths[j],
 
1978
               "svn_uri_is_child (%s, %s) [%d,%d] "
 
1979
               "returned '%s' instead of '%s'",
 
1980
               paths[i], paths[j], i, j,
1379
1981
               remainder ? remainder : "(null)",
1380
1982
               remainders[i][j] ? remainders[i][j] : "(null)" );
1381
1983
        }
1382
1984
    }
1383
1985
 
1384
 
#undef NUM_TEST_PATHS
1385
1986
  return SVN_NO_ERROR;
1386
1987
}
1387
1988
 
1388
1989
static svn_error_t *
1389
 
test_dirent_get_absolute(const char **msg,
1390
 
                         svn_boolean_t msg_only,
1391
 
                         svn_test_opts_t *opts,
1392
 
                         apr_pool_t *pool)
 
1990
test_dirent_get_absolute(apr_pool_t *pool)
1393
1991
{
1394
1992
  int i;
1395
1993
  const char *curdir;
1396
1994
  char buf[8192];
1397
 
#if defined(WIN32) || defined(__CYGWIN__)
 
1995
#ifdef SVN_USE_DOS_PATHS
1398
1996
  const char *curdironc;
1399
1997
  char curdrive[3] = "C:";
1400
 
#endif /* WIN32 */
 
1998
#endif /* SVN_USE_DOS_PATHS */
1401
1999
 
1402
2000
  struct {
1403
2001
    const char *path;
1406
2004
    /* '%' will be replaced by the current working dir. */
1407
2005
    { "abc", "%/abc" },
1408
2006
    { SVN_EMPTY_PATH, "%" },
1409
 
#if defined(WIN32) || defined(__CYGWIN__)
 
2007
#ifdef SVN_USE_DOS_PATHS
1410
2008
    /* '@' will be replaced by the current working dir on C:\. */
1411
2009
    /* '$' will be replaced by the current drive */
1412
2010
    { "C:/", "C:/" },
1415
2013
    { "C:", "@" },
1416
2014
    { "/", "$/" },
1417
2015
    { "/x/abc", "$/x/abc" },
 
2016
    { "c:/", "C:/" },
 
2017
    { "c:/AbC", "C:/AbC" },
 
2018
    { "c:abc", "@/abc" },
1418
2019
    /* svn_dirent_get_absolute will check existence of this UNC shares on the
1419
2020
       test machine, so we can't really test this.
1420
2021
    { "//srv/shr",      "//srv/shr" },
1421
2022
    { "//srv/shr/fld",  "//srv/shr" },
1422
2023
    { "//srv/shr/fld/subfld", "//srv/shr/fld" }, */
1423
 
#else  /* WIN32 or Cygwin */
 
2024
#else /* !SVN_USE_DOS_PATHS */
1424
2025
    { "/abc", "/abc" },
1425
2026
    { "/x/abc", "/x/abc" },
1426
2027
    { "X:", "%/X:" },
1427
2028
    { "X:abc", "%/X:abc" },
1428
 
#endif /* non-WIN32 */
 
2029
#endif /* SVN_USE_DOS_PATHS */
1429
2030
  };
1430
2031
 
1431
 
  *msg = "test svn_dirent_get_absolute";
1432
 
  if (msg_only)
1433
 
    return SVN_NO_ERROR;
1434
 
 
1435
2032
  if (! getcwd(buf, sizeof(buf)))
1436
2033
    return svn_error_create(SVN_ERR_BASE, NULL, "getcwd() failed");
1437
2034
 
1438
2035
  curdir = svn_dirent_internal_style(buf, pool);
1439
2036
 
1440
 
#if defined(WIN32) || defined(__CYGWIN__)
 
2037
#ifdef SVN_USE_DOS_PATHS
1441
2038
  if (! getdcwd(3, buf, sizeof(buf))) /* 3 stands for drive C: */
1442
2039
    return svn_error_create(SVN_ERR_BASE, NULL, "getdcwd() failed");
1443
2040
 
1444
2041
  curdironc = svn_dirent_internal_style(buf, pool);
1445
2042
  curdrive[0] = curdir[0];
1446
 
#endif /* WIN32 */
 
2043
#endif /* SVN_USE_DOS_PATHS */
1447
2044
 
1448
2045
  for (i = 0 ; i < COUNT_OF(tests) ; i++ )
1449
2046
    {
1453
2050
 
1454
2051
      expect_abs = expect;
1455
2052
      if (*expect == '%')
1456
 
        expect_abs = apr_pstrcat(pool, curdir, expect + 1, NULL);
1457
 
#if defined(WIN32) || defined(__CYGWIN__)
 
2053
        expect_abs = apr_pstrcat(pool, curdir, expect + 1, (char *)NULL);
 
2054
#ifdef SVN_USE_DOS_PATHS
1458
2055
      if (*expect == '@')
1459
2056
        expect_abs = apr_pstrcat(pool, curdironc, expect + 1, NULL);
1460
2057
 
1463
2060
 
1464
2061
      /* Remove double '/' when CWD was the root dir (E.g. C:/) */
1465
2062
      expect_abs = svn_dirent_canonicalize(expect_abs, pool);
1466
 
#endif /* WIN32 */
 
2063
#endif /* SVN_USE_DOS_PATHS */
1467
2064
 
1468
2065
      SVN_ERR(svn_dirent_get_absolute(&result, path, pool));
1469
2066
      if (strcmp(result, expect_abs))
1476
2073
  return SVN_NO_ERROR;
1477
2074
}
1478
2075
 
1479
 
static svn_error_t *
1480
 
test_dirent_local_style(const char **msg,
1481
 
                        svn_boolean_t msg_only,
1482
 
                        svn_test_opts_t *opts,
1483
 
                        apr_pool_t *pool)
 
2076
#ifdef WIN32
 
2077
static svn_error_t *
 
2078
test_dirent_get_absolute_from_lc_drive(apr_pool_t *pool)
 
2079
{
 
2080
  char current_dir[1024];
 
2081
  char current_dir_on_C[1024];
 
2082
  char *dir_on_c;
 
2083
  svn_error_t *err;
 
2084
  apr_hash_t *dirents;
 
2085
  apr_hash_index_t *hi;
 
2086
  const char *some_dir_on_C = NULL;
 
2087
 
 
2088
  if (! getcwd(current_dir, sizeof(current_dir)))
 
2089
    return svn_error_create(SVN_ERR_BASE, NULL, "getcwd() failed");
 
2090
 
 
2091
   /* 3 stands for drive C: */
 
2092
  if (! getdcwd(3, current_dir_on_C, sizeof(current_dir_on_C)))
 
2093
    return svn_error_create(SVN_ERR_BASE, NULL, "getdcwd() failed");
 
2094
 
 
2095
  SVN_ERR(svn_io_get_dirents3(&dirents, "C:\\", TRUE, pool, pool));
 
2096
 
 
2097
  /* We need a directory on 'C:\' to switch to lower case and back.
 
2098
     We use the first directory we can find that is not the CWD and
 
2099
     where we can chdir to */
 
2100
 
 
2101
  for (hi = apr_hash_first(pool, dirents); hi; hi = apr_hash_next(hi))
 
2102
    {
 
2103
      const char *dir = svn__apr_hash_index_key(hi);
 
2104
      svn_io_dirent2_t *de = svn__apr_hash_index_val(hi);
 
2105
 
 
2106
      if (de->kind == svn_node_dir &&
 
2107
          strcmp(dir, current_dir_on_C))
 
2108
        {
 
2109
          dir = svn_dirent_join("C:/", dir, pool);
 
2110
          if (!chdir(dir))
 
2111
            {
 
2112
              chdir(current_dir_on_C); /* Switch back to old CWD */
 
2113
              some_dir_on_C = dir;
 
2114
              break;
 
2115
            }
 
2116
        }
 
2117
    }
 
2118
 
 
2119
  if (!some_dir_on_C)
 
2120
    return svn_error_create(SVN_ERR_BASE, NULL,
 
2121
                            "No usable test directory found in C:\\");
 
2122
 
 
2123
  /* Use the test path, but now with a lower case driveletter */
 
2124
  dir_on_c = apr_pstrdup(pool, some_dir_on_C);
 
2125
  dir_on_c[0] = (char)tolower(dir_on_c[0]);
 
2126
 
 
2127
  chdir(dir_on_c);
 
2128
 
 
2129
  err = test_dirent_get_absolute(pool);
 
2130
 
 
2131
  /* Change back to original directory for next tests */
 
2132
  chdir("C:\\"); /* Switch to upper case */
 
2133
  chdir(current_dir_on_C); /* Switch cwd on C: */
 
2134
  chdir(current_dir); /* Switch back to original cwd */
 
2135
  return err;
 
2136
}
 
2137
#endif
 
2138
 
 
2139
static svn_error_t *
 
2140
test_dirent_condense_targets(apr_pool_t *pool)
 
2141
{
 
2142
  int i;
 
2143
  struct {
 
2144
    const char *paths[8];
 
2145
    const char *common;
 
2146
    const char *results[8]; /* must be same size as paths */
 
2147
  } tests[] = {
 
2148
    { { "/dir", "/dir/file", NULL },         NULL,     { "", "file" } },
 
2149
    { { "/dir1", "/dir2", NULL },            NULL,     { "dir1", "dir2" } },
 
2150
    { { "dir1", "dir2", NULL },              NULL,     { "dir1", "dir2" } },
 
2151
#ifdef SVN_USE_DOS_PATHS
 
2152
    { {"C:/", "C:/zeta", NULL},              "C:/",    {"", "zeta"} },
 
2153
    { {"C:/dir", "C:/dir/zeta", NULL},       "C:/dir", {"", "zeta"} },
 
2154
    { {"C:/dir/omega", "C:/dir/zeta", NULL}, "C:/dir", {"omega", "zeta" } },
 
2155
    { {"C:/dir", "D:/dir", NULL},            "",       {"C:/dir", "D:/dir"} },
 
2156
    { {"C:A", "C:dir/b", NULL},              NULL,     {"A", "dir/b"} },
 
2157
#else
 
2158
    { { "/dir", "/dir/file", NULL },        "/dir",    { "", "file" } },
 
2159
    { { "/dir1", "/dir2", NULL },           "/",       { "dir1", "dir2" } },
 
2160
#endif
 
2161
  };
 
2162
 
 
2163
  for (i = 0; i < COUNT_OF(tests); i++)
 
2164
    {
 
2165
      int j;
 
2166
      const char* common;
 
2167
      apr_array_header_t *hdr = apr_array_make(pool, 8, sizeof(const char*));
 
2168
      apr_array_header_t *condensed;
 
2169
 
 
2170
      for (j = 0; j < COUNT_OF(tests[i].paths); j++)
 
2171
        {
 
2172
          if (tests[i].paths[j] != NULL)
 
2173
            APR_ARRAY_PUSH(hdr, const char*) = tests[i].paths[j];
 
2174
          else
 
2175
            break;
 
2176
        }
 
2177
 
 
2178
      SVN_ERR(svn_dirent_condense_targets(&common, &condensed, hdr,
 
2179
                                          FALSE, pool, pool));
 
2180
 
 
2181
      if (tests[i].common != NULL && strcmp(common, tests[i].common))
 
2182
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
 
2183
                                 "svn_dirent_condense_targets returned common "
 
2184
                                 "\"%s\". expected \"%s\"",
 
2185
                                 common, tests[i].common);
 
2186
 
 
2187
      for (j = 0; j < COUNT_OF(tests[i].paths); j++)
 
2188
        {
 
2189
          if (tests[i].paths[j] == NULL || tests[i].results[j] == NULL)
 
2190
            break;
 
2191
 
 
2192
          if (strcmp(APR_ARRAY_IDX(condensed, j, const char*),
 
2193
                     tests[i].results[j]))
 
2194
            return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
 
2195
                           "svn_dirent_condense_targets returned first"
 
2196
                           "\"%s\". expected \"%s\"",
 
2197
                           APR_ARRAY_IDX(condensed, j, const char*),
 
2198
                           tests[i].results[j]);
 
2199
        }
 
2200
    }
 
2201
 
 
2202
 
 
2203
  return SVN_NO_ERROR;
 
2204
}
 
2205
 
 
2206
static svn_error_t *
 
2207
test_uri_condense_targets(apr_pool_t *pool)
 
2208
{
 
2209
  int i;
 
2210
  struct {
 
2211
    const char *paths[8];
 
2212
    const char *common;
 
2213
    const char *results[8]; /* must be same size as paths */
 
2214
  } tests[] = {
 
2215
    /* { { url1, url2, url3 },
 
2216
           common_url,
 
2217
         { relpath1, relpath2, relpath3 } }
 
2218
    */
 
2219
    { { "sc://s/A", "sc://s/B", "sc://s" },
 
2220
        "sc://s",
 
2221
      { "A", "B", "" } },
 
2222
    { { "sc://S/A", "sc://S/B", "sc://S" },
 
2223
        "sc://s",
 
2224
      { "A", "B", "" } },
 
2225
    { { "sc://A/A", "sc://B/B", "sc://s" },
 
2226
        "",
 
2227
      { "sc://a/A", "sc://b/B", "sc://s" } },
 
2228
    { { "sc://A/A", "sc://A/a/B", "sc://a/Q" },
 
2229
        "sc://a",
 
2230
      { "A", "a/B", "Q"} },
 
2231
    { { "sc://server/foo%20bar", "sc://server/baz", "sc://server/blarg" },
 
2232
        "sc://server",
 
2233
      { "foo bar", "baz", "blarg"} },
 
2234
  };
 
2235
 
 
2236
  for (i = 0; i < COUNT_OF(tests); i++)
 
2237
    {
 
2238
      int j;
 
2239
      const char* common;
 
2240
      apr_array_header_t *hdr = apr_array_make(pool, 8, sizeof(const char*));
 
2241
      apr_array_header_t *condensed;
 
2242
 
 
2243
      for (j = 0; j < COUNT_OF(tests[i].paths); j++)
 
2244
        {
 
2245
          if (tests[i].paths[j] != NULL)
 
2246
            APR_ARRAY_PUSH(hdr, const char*) = tests[i].paths[j];
 
2247
          else
 
2248
            break;
 
2249
        }
 
2250
 
 
2251
      SVN_ERR(svn_uri_condense_targets(&common, &condensed, hdr,
 
2252
                                       FALSE, pool, pool));
 
2253
 
 
2254
      if (tests[i].common != NULL && strcmp(common, tests[i].common))
 
2255
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
 
2256
                                 "svn_uri_condense_targets returned common "
 
2257
                                 "\"%s\". expected \"%s\"",
 
2258
                                 common, tests[i].common);
 
2259
 
 
2260
      for (j = 0; j < COUNT_OF(tests[i].paths); j++)
 
2261
        {
 
2262
          if (tests[i].paths[j] == NULL || tests[i].results[j] == NULL)
 
2263
            break;
 
2264
 
 
2265
          if (strcmp(APR_ARRAY_IDX(condensed, j, const char*),
 
2266
                     tests[i].results[j]))
 
2267
            return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
 
2268
                           "svn_uri_condense_targets returned first"
 
2269
                           "\"%s\". expected \"%s\"",
 
2270
                           APR_ARRAY_IDX(condensed, j, const char*),
 
2271
                           tests[i].results[j]);
 
2272
        }
 
2273
    }
 
2274
 
 
2275
 
 
2276
  return SVN_NO_ERROR;
 
2277
}
 
2278
 
 
2279
static svn_error_t *
 
2280
test_dirent_local_style(apr_pool_t *pool)
1484
2281
{
1485
2282
  struct {
1486
2283
    const char *path;
1488
2285
  } tests[] = {
1489
2286
    { "",                     "." },
1490
2287
    { ".",                    "." },
1491
 
#if defined(WIN32) || defined(__CYGWIN__)
1492
 
    { "a:/",                 "a:\\" },
1493
 
    { "a:/file",             "a:\\file" },
 
2288
#ifdef SVN_USE_DOS_PATHS
 
2289
    { "A:/",                 "A:\\" },
 
2290
    { "A:/file",             "A:\\file" },
1494
2291
    { "dir/file",            "dir\\file" },
1495
2292
    { "/",                   "\\" },
1496
2293
    { "//server/share/dir",  "\\\\server\\share\\dir" },
 
2294
    { "//server/sh re/dir",  "\\\\server\\sh re\\dir" },
1497
2295
#else
1498
 
    { "a:/",                 "a:" }, /* Wrong but expected for svn_path_*() */
1499
2296
    { "a:/file",             "a:/file" },
1500
2297
    { "dir/file",            "dir/file" },
1501
2298
    { "/",                   "/" },
1502
 
    { "//server/share/dir",  "/server/share/dir" },
1503
2299
#endif
1504
2300
  };
1505
2301
  int i;
1506
2302
 
1507
 
  *msg = "test svn_dirent_local_style";
1508
 
  if (msg_only)
1509
 
    return SVN_NO_ERROR;
1510
 
 
1511
2303
  for (i = 0; i < COUNT_OF(tests); i++)
1512
2304
    {
1513
2305
      const char *local = svn_dirent_local_style(tests[i].path, pool);
1523
2315
}
1524
2316
 
1525
2317
static svn_error_t *
1526
 
test_uri_local_style(const char **msg,
1527
 
                     svn_boolean_t msg_only,
1528
 
                     svn_test_opts_t *opts,
1529
 
                     apr_pool_t *pool)
1530
 
{
1531
 
  struct {
1532
 
    const char *path;
1533
 
    const char *result;
1534
 
  } tests[] = {
1535
 
    { "",                     "." },
1536
 
    { ".",                    "." },
1537
 
#if defined(WIN32) || defined(__CYGWIN__)
1538
 
    /* Rules are as uri, but paths are shown with local separator */
1539
 
    { "a:/",                 "a:" },
1540
 
    { "a:/file",             "a:\\file" },
1541
 
    { "dir/file",            "dir\\file" },
1542
 
    { "/",                   "\\" },
1543
 
    { "//server/share/dir",  "\\server\\share\\dir" },
1544
 
#else
1545
 
    { "a:/",                 "a:" },
1546
 
    { "a:/file",             "a:/file" },
1547
 
    { "dir/file",            "dir/file" },
1548
 
    { "/",                   "/" },
1549
 
    { "//server/share/dir",  "/server/share/dir" },
1550
 
#endif
1551
 
  };
1552
 
  int i;
1553
 
 
1554
 
  *msg = "test svn_uri_local_style";
1555
 
  if (msg_only)
1556
 
    return SVN_NO_ERROR;
1557
 
 
1558
 
  for (i = 0; i < COUNT_OF(tests); i++)
1559
 
    {
1560
 
      const char *local = svn_uri_local_style(tests[i].path, pool);
1561
 
 
1562
 
      if (strcmp(local, tests[i].result))
1563
 
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
1564
 
                                 "svn_uri_local_style(\"%s\") returned "
1565
 
                                 "\"%s\" expected \"%s\"",
1566
 
                                 tests[i].path, local, tests[i].result);
1567
 
    }
1568
 
 
1569
 
  return SVN_NO_ERROR;
1570
 
}
1571
 
 
1572
 
static svn_error_t *
1573
 
test_dirent_internal_style(const char **msg,
1574
 
                           svn_boolean_t msg_only,
1575
 
                           svn_test_opts_t *opts,
1576
 
                           apr_pool_t *pool)
 
2318
test_dirent_internal_style(apr_pool_t *pool)
1577
2319
{
1578
2320
  struct {
1579
2321
    const char *path;
1584
2326
    { "/",                   "/" },
1585
2327
    { "file",                "file" },
1586
2328
    { "dir/file",            "dir/file" },
1587
 
#if defined(WIN32) || defined(__CYGWIN__)
1588
 
    { "a:\\",                "a:/" },
1589
 
    { "a:\\file",            "a:/file" },
1590
 
    { "a:file",              "a:file" },
 
2329
    { "dir/file/./.",        "dir/file" },
 
2330
#ifdef SVN_USE_DOS_PATHS
 
2331
    { "A:\\",                "A:/" },
 
2332
    { "A:\\file",            "A:/file" },
 
2333
    { "A:file",              "A:file" },
 
2334
    { "a:\\",                "A:/" },
 
2335
    { "a:/",                 "A:/" },
 
2336
    { "a:\\file",            "A:/file" },
 
2337
    { "a:file",              "A:file" },
1591
2338
    { "dir\\file",           "dir/file" },
1592
2339
    { "\\\\srv\\shr\\dir",   "//srv/shr/dir" },
1593
2340
    { "\\\\srv\\shr\\",      "//srv/shr" },
 
2341
    { "\\\\srv\\s r\\",      "//srv/s r" },
1594
2342
    { "//srv/shr",           "//srv/shr" },
 
2343
    { "//srv/s r",           "//srv/s r" },
 
2344
    { "//srv/s r",           "//srv/s r" },
1595
2345
#else
1596
2346
    { "a:/",                 "a:" }, /* Wrong but expected for svn_path_*() */
1597
2347
    { "a:/file",             "a:/file" },
1602
2352
  };
1603
2353
  int i;
1604
2354
 
1605
 
  *msg = "test svn_dirent_internal_style";
1606
 
  if (msg_only)
1607
 
    return SVN_NO_ERROR;
1608
 
 
1609
2355
  for (i = 0; i < COUNT_OF(tests); i++)
1610
2356
    {
1611
2357
      const char *internal = svn_dirent_internal_style(tests[i].path, pool);
1621
2367
}
1622
2368
 
1623
2369
static svn_error_t *
1624
 
test_uri_internal_style(const char **msg,
1625
 
                        svn_boolean_t msg_only,
1626
 
                        svn_test_opts_t *opts,
1627
 
                        apr_pool_t *pool)
 
2370
test_relpath_internal_style(apr_pool_t *pool)
1628
2371
{
1629
2372
  struct {
1630
2373
    const char *path;
1631
2374
    const char *result;
1632
2375
  } tests[] = {
1633
 
    { "",                     "" },
1634
 
    { ".",                    "" },
1635
 
    { "/",                   "/" },
 
2376
    { "",                    "" },
 
2377
    { ".",                   "" },
 
2378
    { "/",                   "" },
1636
2379
    { "file",                "file" },
1637
2380
    { "dir/file",            "dir/file" },
1638
 
#if defined(WIN32) || defined(__CYGWIN__)
1639
 
    /* Rules are as uri, but paths are shown with internal separator */
1640
 
    { "a:\\",                "a:" },
1641
 
    { "a:\\file",            "a:/file" },
1642
 
    { "a:file",              "a:file" },
1643
 
    { "dir\\file",           "dir/file" },
1644
 
    { "//server/share/dir",  "/server/share/dir" },
1645
 
    { "\\\\srv\\shr\\dir",   "/srv/shr/dir" },
1646
 
#else
1647
2381
    { "a:/",                 "a:" },
1648
2382
    { "a:/file",             "a:/file" },
1649
2383
    { "dir/file",            "dir/file" },
1650
 
    { "/",                   "/" },
1651
 
    { "//server/share/dir",  "/server/share/dir" },
1652
 
#endif
 
2384
    { "//server/share/dir",  "server/share/dir" },
 
2385
    { "a/./.",               "a" },
1653
2386
  };
1654
2387
  int i;
1655
2388
 
1656
 
  *msg = "test svn_uri_internal_style";
1657
 
  if (msg_only)
1658
 
    return SVN_NO_ERROR;
1659
 
 
1660
2389
  for (i = 0; i < COUNT_OF(tests); i++)
1661
2390
    {
1662
 
      const char *internal = svn_uri_internal_style(tests[i].path, pool);
 
2391
      const char *internal = svn_relpath__internal_style(tests[i].path, pool);
1663
2392
 
1664
2393
      if (strcmp(internal, tests[i].result))
1665
2394
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
1666
 
                                 "svn_uri_internal_style(\"%s\") returned "
 
2395
                                 "svn_relpath__internal_style(\"%s\") returned "
1667
2396
                                 "\"%s\" expected \"%s\"",
1668
2397
                                 tests[i].path, internal, tests[i].result);
1669
2398
    }
1671
2400
  return SVN_NO_ERROR;
1672
2401
}
1673
2402
 
 
2403
static svn_error_t *
 
2404
test_dirent_from_file_url(apr_pool_t *pool)
 
2405
{
 
2406
  struct {
 
2407
    const char *url;
 
2408
    const char *result;
 
2409
  } tests[] = {
 
2410
    { "file://",                   "/" },
 
2411
    { "file:///dir",               "/dir" },
 
2412
    { "file:///dir/path",          "/dir/path" },
 
2413
    { "file://localhost",          "/" },
 
2414
    { "file://localhost/dir",      "/dir" },
 
2415
    { "file://localhost/dir/path", "/dir/path" },
 
2416
#ifdef SVN_USE_DOS_PATHS
 
2417
    { "file://server/share",       "//server/share" },
 
2418
    { "file://server/share/dir",   "//server/share/dir" },
 
2419
    { "file:///A:",                "A:/" },
 
2420
    { "file:///A:/dir",            "A:/dir" },
 
2421
    { "file:///A:dir",             "A:dir" },
 
2422
    { "file:///A%7C",              "A:/" },
 
2423
    { "file:///A%7C/dir",          "A:/dir" },
 
2424
    { "file:///A%7Cdir",           "A:dir" },
 
2425
#endif
 
2426
  };
 
2427
  int i;
 
2428
 
 
2429
  for (i = 0; i < COUNT_OF(tests); i++)
 
2430
    {
 
2431
      const char *result;
 
2432
 
 
2433
      SVN_ERR(svn_uri_get_dirent_from_file_url(&result, tests[i].url, pool));
 
2434
 
 
2435
      if (strcmp(result, tests[i].result))
 
2436
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
 
2437
                                 "svn_uri_get_dirent_from_file_url(\"%s\") "
 
2438
                                 "returned \"%s\" expected \"%s\"",
 
2439
                                 tests[i].url, result, tests[i].result);
 
2440
    }
 
2441
 
 
2442
  return SVN_NO_ERROR;
 
2443
}
 
2444
 
 
2445
static svn_error_t *
 
2446
test_dirent_from_file_url_errors(apr_pool_t *pool)
 
2447
{
 
2448
  const char *bad_file_urls[] = {
 
2449
    /* error if scheme is not "file" */
 
2450
    "http://localhost/dir",
 
2451
    "file+ssh://localhost/dir",
 
2452
#ifndef SVN_USE_DOS_PATHS
 
2453
    "file://localhostwrongname/dir",  /* error if host name not "localhost" */
 
2454
#endif
 
2455
  };
 
2456
  int i;
 
2457
 
 
2458
  for (i = 0; i < COUNT_OF(bad_file_urls); i++)
 
2459
    {
 
2460
      const char *result;
 
2461
      svn_error_t *err;
 
2462
 
 
2463
      err = svn_uri_get_dirent_from_file_url(&result, bad_file_urls[i],
 
2464
                                             pool);
 
2465
 
 
2466
      if (err == NULL)
 
2467
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
 
2468
                                 "svn_uri_get_dirent_from_file_url(\"%s\") "
 
2469
                                 "didn't return an error.",
 
2470
                                 bad_file_urls[i]);
 
2471
      svn_error_clear(err);
 
2472
    }
 
2473
 
 
2474
  return SVN_NO_ERROR;
 
2475
}
 
2476
 
 
2477
static svn_error_t *
 
2478
test_file_url_from_dirent(apr_pool_t *pool)
 
2479
{
 
2480
  struct {
 
2481
    const char *dirent;
 
2482
    const char *result;
 
2483
  } tests[] = {
 
2484
#ifdef SVN_USE_DOS_PATHS
 
2485
    { "C:/file",                   "file:///C:/file" },
 
2486
    { "C:/",                       "file:///C:/" },
 
2487
    { "C:/File#$",                 "file:///C:/File%23$" },
 
2488
    /* We can't check these as svn_dirent_get_absolute() won't work
 
2489
       on shares that don't exist */
 
2490
    /*{ "//server/share",            "file://server/share" },
 
2491
    { "//server/share/file",       "file://server/share/file" },*/
 
2492
#else
 
2493
    { "/a/b",                      "file:///a/b" },
 
2494
    { "/a",                        "file:///a" },
 
2495
    { "/",                         "file://" },
 
2496
    { "/File#$",                   "file:///File%23$" },
 
2497
#endif
 
2498
  };
 
2499
  int i;
 
2500
 
 
2501
  for (i = 0; i < COUNT_OF(tests); i++)
 
2502
    {
 
2503
      const char *result;
 
2504
 
 
2505
      SVN_ERR(svn_uri_get_file_url_from_dirent(&result, tests[i].dirent,
 
2506
                                               pool));
 
2507
 
 
2508
      if (strcmp(result, tests[i].result))
 
2509
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
 
2510
                                 "svn_uri_get_file_url_from_dirent(\"%s\") "
 
2511
                                 "returned \"%s\" expected \"%s\"",
 
2512
                                 tests[i].dirent, result, tests[i].result);
 
2513
    }
 
2514
 
 
2515
  return SVN_NO_ERROR;
 
2516
}
 
2517
 
 
2518
static svn_error_t *
 
2519
test_dirent_is_under_root(apr_pool_t *pool)
 
2520
{
 
2521
  struct {
 
2522
    const char *base_path;
 
2523
    const char *path;
 
2524
    svn_boolean_t under_root;
 
2525
    const char *result;
 
2526
  } tests[] = {
 
2527
    { "",         "",               TRUE, ""},
 
2528
    { "",         "r",              TRUE, "r"},
 
2529
    { "",         "r/..",           TRUE, ""},
 
2530
    { "",         "r/../..",        FALSE},
 
2531
    { "",         "r/../../b",      FALSE},
 
2532
    { "",         "..",             FALSE},
 
2533
    { "",         "../r",           FALSE},
 
2534
    { "",         "/",              FALSE},
 
2535
    { "",         "/r",             FALSE},
 
2536
    { "",         "/..",            FALSE},
 
2537
    { "b",        "",               TRUE, "b"},
 
2538
    { "b",        "r",              TRUE, "b/r"},
 
2539
    { "b",        "r/..",           TRUE, "b"},
 
2540
    { "b",        "r/../..",        FALSE},
 
2541
    { "b",        "r/../../b",      FALSE},
 
2542
    { "b",        "..",             FALSE},
 
2543
    { "b",        "../r",           FALSE},
 
2544
    { "b",        "../b",           FALSE},
 
2545
    { "b",        "/",              FALSE},
 
2546
    { "b",        "/r",             FALSE},
 
2547
    { "b",        "/..",            FALSE},
 
2548
    { "/",        "",               TRUE, "/"},
 
2549
    { "/",        "r",              TRUE, "/r"},
 
2550
    { "/",        "r/..",           TRUE, "/"},
 
2551
    { "/",        "r/../..",        FALSE},
 
2552
    { "/",        "r/../../b",      FALSE},
 
2553
    { "/",        "..",             FALSE},
 
2554
    { "/",        "../r",           FALSE},
 
2555
    { "/",        "/",              FALSE},
 
2556
    { "/",        "/r",             FALSE},
 
2557
    { "/",        "/..",            FALSE},
 
2558
    { "/b",       "",               TRUE, "/b"},
 
2559
    { "/b",       "r",              TRUE, "/b/r"},
 
2560
    { "/b",       "r/..",           TRUE, "/b"},
 
2561
    { "/b",       "r/../..",        FALSE},
 
2562
    { "/b",       "r/../../b",      FALSE},
 
2563
    { "/b",       "..",             FALSE},
 
2564
    { "/b",       "../r",           FALSE},
 
2565
    { "/b",       "../b",           FALSE},
 
2566
    { "/b",       "/",              FALSE},
 
2567
    { "/b",       "/r",             FALSE},
 
2568
    { "/b",       "/..",            FALSE},
 
2569
    { "/",        "/base",          FALSE},
 
2570
    { "/aa",      "/aa/bb",         FALSE},
 
2571
    { "/base",    "/base2",         FALSE},
 
2572
    { "/b",       "bb",             TRUE, "/b/bb"},
 
2573
    { "/b",       "../bb",          FALSE},
 
2574
    { "/b",       "r/./bb",         TRUE, "/b/r/bb"},
 
2575
    { "/b",       "r/../bb",        TRUE, "/b/bb"},
 
2576
    { "/b",       "r/../../bb",     FALSE},
 
2577
    { "/b",       "./bb",           TRUE, "/b/bb"},
 
2578
    { "/b",       ".",              TRUE, "/b"},
 
2579
    { "/b",       "",               TRUE, "/b"},
 
2580
    { "b",        "b",              TRUE, "b/b"},
 
2581
#ifdef SVN_USE_DOS_PATHS
 
2582
    { "C:/file",  "a\\d",           TRUE, "C:/file/a/d"},
 
2583
    { "C:/file",  "aa\\..\\d",      TRUE, "C:/file/d"},
 
2584
    { "C:/file",  "aa\\..\\..\\d",  FALSE},
 
2585
#else
 
2586
    { "C:/file",  "a\\d",           TRUE, "C:/file/a\\d"},
 
2587
    { "C:/file",  "aa\\..\\d",      TRUE, "C:/file/aa\\..\\d"},
 
2588
    { "C:/file",  "aa\\..\\..\\d",  TRUE, "C:/file/aa\\..\\..\\d"},
 
2589
#endif /* SVN_USE_DOS_PATHS */
 
2590
  };
 
2591
  int i;
 
2592
 
 
2593
  for (i = 0; i < COUNT_OF(tests); i++)
 
2594
    {
 
2595
      svn_boolean_t under_root;
 
2596
      const char *result;
 
2597
 
 
2598
      SVN_ERR(svn_dirent_is_under_root(&under_root,
 
2599
                                       &result,
 
2600
                                       tests[i].base_path,
 
2601
                                       tests[i].path,
 
2602
                                       pool));
 
2603
 
 
2604
      if (under_root != tests[i].under_root)
 
2605
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
 
2606
                                 "svn_dirent_is_under_root(..\"%s\", \"%s\"..)"
 
2607
                                 " returned %s expected %s.",
 
2608
                                 tests[i].base_path,
 
2609
                                 tests[i].path,
 
2610
                                 under_root ? "TRUE" : "FALSE",
 
2611
                                 tests[i].under_root ? "TRUE" : "FALSE");
 
2612
 
 
2613
      if (under_root
 
2614
          && strcmp(result, tests[i].result) != 0)
 
2615
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
 
2616
                                 "svn_dirent_is_under_root(..\"%s\", \"%s\"..)"
 
2617
                                 " found \"%s\" expected \"%s\".",
 
2618
                                 tests[i].base_path,
 
2619
                                 tests[i].path,
 
2620
                                 result,
 
2621
                                 tests[i].result);
 
2622
    }
 
2623
 
 
2624
  return SVN_NO_ERROR;
 
2625
}
 
2626
 
 
2627
static svn_error_t *
 
2628
test_fspath_is_canonical(apr_pool_t *pool)
 
2629
{
 
2630
  const testcase_is_canonical_t *t;
 
2631
  static const testcase_is_canonical_t tests[] = {
 
2632
    { "",                      FALSE },
 
2633
    { ".",                     FALSE },
 
2634
    { "/",                     TRUE },
 
2635
    { "/a",                    TRUE },
 
2636
    { "/a/",                   FALSE },
 
2637
    { "//a",                   FALSE },
 
2638
    { "/a/b",                  TRUE },
 
2639
    { "/a//b",                 FALSE },
 
2640
    { "\\",                    FALSE },
 
2641
    { "\\a",                   FALSE },
 
2642
    { "/\\a",                  TRUE },  /* a single component */
 
2643
    { "/a\\",                  TRUE },  /* a single component */
 
2644
    { "/a\\b",                 TRUE },  /* a single component */
 
2645
  };
 
2646
 
 
2647
  for (t = tests; t < tests + COUNT_OF(tests); t++)
 
2648
    {
 
2649
      svn_boolean_t canonical
 
2650
        = svn_fspath__is_canonical(t->path);
 
2651
 
 
2652
      if (t->canonical != canonical)
 
2653
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
 
2654
                                 "svn_fspath__is_canonical(\"%s\") returned "
 
2655
                                 "\"%s\" expected \"%s\"",
 
2656
                                 t->path,
 
2657
                                 canonical ? "TRUE" : "FALSE",
 
2658
                                 t->canonical ? "TRUE" : "FALSE");
 
2659
    }
 
2660
 
 
2661
  return SVN_NO_ERROR;
 
2662
}
 
2663
 
 
2664
static svn_error_t *
 
2665
test_fspath_join(apr_pool_t *pool)
 
2666
{
 
2667
  int i;
 
2668
 
 
2669
  static const char * const joins[][3] = {
 
2670
    { "/",    "",     "/" },
 
2671
    { "/",    "d",    "/d" },
 
2672
    { "/",    "d/e",  "/d/e" },
 
2673
    { "/abc", "",     "/abc" },
 
2674
    { "/abc", "d",    "/abc/d" },
 
2675
    { "/abc", "d/e",  "/abc/d/e" },
 
2676
  };
 
2677
 
 
2678
  for (i = 0; i < COUNT_OF(joins); i++ )
 
2679
    {
 
2680
      char *result = svn_fspath__join(joins[i][0], joins[i][1], pool);
 
2681
 
 
2682
      SVN_TEST_STRING_ASSERT(result, joins[i][2]);
 
2683
    }
 
2684
 
 
2685
  return SVN_NO_ERROR;
 
2686
}
 
2687
 
 
2688
static svn_error_t *
 
2689
test_fspath_is_child(apr_pool_t *pool)
 
2690
{
 
2691
  int i, j;
 
2692
 
 
2693
  static const char * const paths[] = {
 
2694
    "/",
 
2695
    "/f",
 
2696
    "/foo",
 
2697
    "/foo/bar",
 
2698
    "/foo/bars",
 
2699
    "/foo/bar/baz",
 
2700
    };
 
2701
 
 
2702
  static const char * const
 
2703
    remainders[COUNT_OF(paths)][COUNT_OF(paths)] = {
 
2704
    { 0,  "f",  "foo",  "foo/bar",  "foo/bars", "foo/bar/baz" },
 
2705
    { 0,  0,    0,      0,          0,          0             },
 
2706
    { 0,  0,    0,      "bar",      "bars",     "bar/baz"     },
 
2707
    { 0,  0,    0,      0,          0,          "baz"         },
 
2708
    { 0,  0,    0,      0,          0,          0             },
 
2709
    { 0,  0,    0,      0,          0,          0             },
 
2710
  };
 
2711
 
 
2712
  for (i = 0; i < COUNT_OF(paths); i++)
 
2713
    {
 
2714
      for (j = 0; j < COUNT_OF(paths); j++)
 
2715
        {
 
2716
          const char *remainder
 
2717
            = svn_fspath__is_child(paths[i], paths[j], pool);
 
2718
 
 
2719
          SVN_TEST_STRING_ASSERT(remainder, remainders[i][j]);
 
2720
        }
 
2721
    }
 
2722
 
 
2723
  return SVN_NO_ERROR;
 
2724
}
 
2725
 
 
2726
static svn_error_t *
 
2727
test_fspath_dirname_basename_split(apr_pool_t *pool)
 
2728
{
 
2729
  int i;
 
2730
 
 
2731
  static const struct {
 
2732
    const char *path;
 
2733
    const char *dirname;
 
2734
    const char *basename;
 
2735
  } tests[] = {
 
2736
    { "/", "/", "" },
 
2737
    { "/a", "/", "a" },
 
2738
    { "/abc", "/", "abc" },
 
2739
    { "/x/abc", "/x", "abc" },
 
2740
    { "/x/y/abc", "/x/y", "abc" },
 
2741
  };
 
2742
 
 
2743
  for (i = 0; i < COUNT_OF(tests); i++)
 
2744
    {
 
2745
      const char *result_dirname, *result_basename;
 
2746
 
 
2747
      result_dirname = svn_fspath__dirname(tests[i].path, pool);
 
2748
      SVN_TEST_STRING_ASSERT(result_dirname, tests[i].dirname);
 
2749
 
 
2750
      result_basename = svn_fspath__basename(tests[i].path, pool);
 
2751
      SVN_TEST_STRING_ASSERT(result_basename, tests[i].basename);
 
2752
 
 
2753
      svn_fspath__split(&result_dirname, &result_basename, tests[i].path,
 
2754
                        pool);
 
2755
      SVN_TEST_STRING_ASSERT(result_dirname, tests[i].dirname);
 
2756
      SVN_TEST_STRING_ASSERT(result_basename, tests[i].basename);
 
2757
    }
 
2758
 
 
2759
  return SVN_NO_ERROR;
 
2760
}
 
2761
 
 
2762
static svn_error_t *
 
2763
test_fspath_get_longest_ancestor(apr_pool_t *pool)
 
2764
{
 
2765
  const testcase_get_longest_ancestor_t *t;
 
2766
 
 
2767
  /* Paths to test and their expected results.  Same as in
 
2768
   * test_relpath_get_longest_ancestor() but with '/' prefix. */
 
2769
  static const testcase_get_longest_ancestor_t tests[] = {
 
2770
    { "/foo",            "/foo/bar",         "/foo" },
 
2771
    { "/foo/bar",        "/foo/bar",         "/foo/bar" },
 
2772
    { "/",               "/foo",             "/" },
 
2773
    { "/",               "/foo",             "/" },
 
2774
    { "/",               "/.bar",            "/" },
 
2775
    { "/.bar",           "/",                "/" },
 
2776
    { "/foo/bar",        "/foo",             "/foo" },
 
2777
    { "/foo/bar",        "/foo",             "/foo" },
 
2778
    { "/rif",            "/raf",             "/" },
 
2779
    { "/foo",            "/bar",             "/" },
 
2780
    { "/foo",            "/foo/bar",         "/foo" },
 
2781
    { "/foo.",           "/foo./.bar",       "/foo." },
 
2782
    { "/",               "/",                "/" },
 
2783
    { "/http:/test",     "/http:/test",      "/http:/test" },
 
2784
    { "/http:/test",     "/http:/taste",     "/http:" },
 
2785
    { "/http:/test",     "/http:/test/foo",  "/http:/test" },
 
2786
    { "/http:/test",     "/file:/test/foo",  "/" },
 
2787
    { "/http:/test",     "/http:/testF",     "/http:" },
 
2788
    { "/file:/A/C",      "/file:/B/D",       "/file:" },
 
2789
    { "/file:/A/C",      "/file:/A/D",       "/file:/A" },
 
2790
    { "/X:/foo",         "/X:",              "/X:" },
 
2791
    { "/X:/folder1",     "/X:/folder2",      "/X:" },
 
2792
    { "/X:",             "/X:foo",           "/" },
 
2793
    { "/X:foo",          "/X:bar",           "/" },
 
2794
  };
 
2795
 
 
2796
  for (t = tests; t < tests + COUNT_OF(tests); t++)
 
2797
    {
 
2798
      const char *result;
 
2799
 
 
2800
      result = svn_fspath__get_longest_ancestor(t->path1, t->path2, pool);
 
2801
      SVN_TEST_STRING_ASSERT(t->result, result);
 
2802
 
 
2803
      /* changing the order of the paths should return the same result */
 
2804
      result = svn_fspath__get_longest_ancestor(t->path2, t->path1, pool);
 
2805
      SVN_TEST_STRING_ASSERT(t->result, result);
 
2806
    }
 
2807
  return SVN_NO_ERROR;
 
2808
}
 
2809
 
1674
2810
 
1675
2811
/* The test table.  */
1676
2812
 
1677
2813
struct svn_test_descriptor_t test_funcs[] =
1678
2814
  {
1679
2815
    SVN_TEST_NULL,
1680
 
    SVN_TEST_PASS(test_dirent_is_root),
1681
 
    SVN_TEST_PASS(test_uri_is_root),
1682
 
    SVN_TEST_PASS(test_dirent_is_absolute),
1683
 
    SVN_TEST_PASS(test_uri_is_absolute),
1684
 
    SVN_TEST_PASS(test_dirent_join),
1685
 
    SVN_TEST_PASS(test_dirent_dirname),
1686
 
    SVN_TEST_PASS(test_uri_dirname),
1687
 
    SVN_TEST_PASS(test_dirent_canonicalize),
1688
 
    SVN_TEST_PASS(test_uri_canonicalize),
1689
 
    SVN_TEST_PASS(test_dirent_is_canonical),
1690
 
    SVN_TEST_PASS(test_uri_is_canonical),
1691
 
    SVN_TEST_PASS(test_dirent_get_longest_ancestor),
1692
 
    SVN_TEST_PASS(test_uri_get_longest_ancestor),
1693
 
    SVN_TEST_PASS(test_dirent_is_child),
1694
 
    SVN_TEST_PASS(test_uri_is_child),
1695
 
    SVN_TEST_PASS(test_dirent_is_ancestor),
1696
 
    SVN_TEST_PASS(test_uri_is_ancestor),
1697
 
    SVN_TEST_PASS(test_dirent_get_absolute),
1698
 
    SVN_TEST_PASS(test_dirent_local_style),
1699
 
    SVN_TEST_PASS(test_uri_local_style),
1700
 
    SVN_TEST_PASS(test_dirent_internal_style),
1701
 
    SVN_TEST_PASS(test_uri_internal_style),
 
2816
    SVN_TEST_PASS2(test_dirent_is_root,
 
2817
                   "test svn_dirent_is_root"),
 
2818
    SVN_TEST_PASS2(test_uri_is_root,
 
2819
                   "test svn_uri_is_root"),
 
2820
    SVN_TEST_PASS2(test_dirent_is_absolute,
 
2821
                   "test svn_dirent_is_absolute"),
 
2822
    SVN_TEST_PASS2(test_dirent_join,
 
2823
                   "test svn_dirent_join(_many)"),
 
2824
    SVN_TEST_PASS2(test_relpath_join,
 
2825
                   "test svn_relpath_join"),
 
2826
    SVN_TEST_PASS2(test_dirent_basename,
 
2827
                   "test svn_dirent_basename"),
 
2828
    SVN_TEST_PASS2(test_relpath_basename,
 
2829
                   "test svn_relpath_basename"),
 
2830
    SVN_TEST_PASS2(test_uri_basename,
 
2831
                   "test svn_uri_basename"),
 
2832
    SVN_TEST_PASS2(test_relpath_dirname,
 
2833
                   "test svn_relpath_dirname"),
 
2834
    SVN_TEST_PASS2(test_dirent_dirname,
 
2835
                   "test svn_dirent_dirname"),
 
2836
    SVN_TEST_PASS2(test_uri_dirname,
 
2837
                   "test svn_dirent_dirname"),
 
2838
    SVN_TEST_PASS2(test_dirent_canonicalize,
 
2839
                   "test svn_dirent_canonicalize"),
 
2840
    SVN_TEST_PASS2(test_relpath_canonicalize,
 
2841
                   "test svn_relpath_canonicalize"),
 
2842
    SVN_TEST_PASS2(test_uri_canonicalize,
 
2843
                   "test svn_uri_canonicalize"),
 
2844
    SVN_TEST_PASS2(test_dirent_is_canonical,
 
2845
                   "test svn_dirent_is_canonical"),
 
2846
    SVN_TEST_PASS2(test_relpath_is_canonical,
 
2847
                   "test svn_relpath_is_canonical"),
 
2848
    SVN_TEST_PASS2(test_uri_is_canonical,
 
2849
                   "test svn_uri_is_canonical"),
 
2850
    SVN_TEST_PASS2(test_dirent_split,
 
2851
                   "test svn_dirent_split"),
 
2852
    SVN_TEST_PASS2(test_relpath_split,
 
2853
                   "test svn_relpath_split"),
 
2854
    SVN_TEST_PASS2(test_uri_split,
 
2855
                   "test svn_uri_split"),
 
2856
    SVN_TEST_PASS2(test_dirent_get_longest_ancestor,
 
2857
                   "test svn_dirent_get_longest_ancestor"),
 
2858
    SVN_TEST_PASS2(test_relpath_get_longest_ancestor,
 
2859
                   "test svn_relpath_get_longest_ancestor"),
 
2860
    SVN_TEST_PASS2(test_uri_get_longest_ancestor,
 
2861
                   "test svn_uri_get_longest_ancestor"),
 
2862
    SVN_TEST_PASS2(test_dirent_is_child,
 
2863
                   "test svn_dirent_is_child"),
 
2864
    SVN_TEST_PASS2(test_relpath_is_child,
 
2865
                   "test svn_relpath_is_child"),
 
2866
    SVN_TEST_PASS2(test_uri_is_child,
 
2867
                   "test svn_uri_is_child"),
 
2868
    SVN_TEST_PASS2(test_dirent_is_ancestor,
 
2869
                   "test svn_dirent_is_ancestor"),
 
2870
    SVN_TEST_PASS2(test_relpath_is_ancestor,
 
2871
                   "test svn_relpath_is_ancestor"),
 
2872
    SVN_TEST_PASS2(test_uri_is_ancestor,
 
2873
                   "test svn_uri_is_ancestor"),
 
2874
    SVN_TEST_PASS2(test_dirent_skip_ancestor,
 
2875
                   "test svn_dirent_skip_ancestor"),
 
2876
    SVN_TEST_PASS2(test_relpath_skip_ancestor,
 
2877
                   "test svn_relpath_skip_ancestor"),
 
2878
    SVN_TEST_PASS2(test_uri_skip_ancestor,
 
2879
                   "test svn_uri_skip_ancestor"),
 
2880
    SVN_TEST_PASS2(test_dirent_get_absolute,
 
2881
                   "test svn_dirent_get_absolute"),
 
2882
#ifdef WIN32
 
2883
    SVN_TEST_PASS2(test_dirent_get_absolute_from_lc_drive,
 
2884
                   "test svn_dirent_get_absolute (needs recent apr)"),
 
2885
#endif
 
2886
    SVN_TEST_PASS2(test_dirent_condense_targets,
 
2887
                   "test svn_dirent_condense_targets"),
 
2888
    SVN_TEST_PASS2(test_uri_condense_targets,
 
2889
                   "test svn_uri_condense_targets"),
 
2890
    SVN_TEST_PASS2(test_dirent_local_style,
 
2891
                   "test svn_dirent_local_style"),
 
2892
    SVN_TEST_PASS2(test_dirent_internal_style,
 
2893
                   "test svn_dirent_internal_style"),
 
2894
    SVN_TEST_PASS2(test_relpath_internal_style,
 
2895
                   "test svn_relpath_internal_style"),
 
2896
    SVN_TEST_PASS2(test_dirent_from_file_url,
 
2897
                   "test svn_uri_get_dirent_from_file_url"),
 
2898
    SVN_TEST_PASS2(test_dirent_from_file_url_errors,
 
2899
                   "test svn_uri_get_dirent_from_file_url errors"),
 
2900
    SVN_TEST_PASS2(test_file_url_from_dirent,
 
2901
                   "test svn_uri_get_file_url_from_dirent"),
 
2902
    SVN_TEST_PASS2(test_dirent_is_under_root,
 
2903
                   "test svn_dirent_is_under_root"),
 
2904
    SVN_TEST_PASS2(test_fspath_is_canonical,
 
2905
                   "test svn_fspath__is_canonical"),
 
2906
    SVN_TEST_PASS2(test_fspath_join,
 
2907
                   "test svn_fspath__join"),
 
2908
    SVN_TEST_PASS2(test_fspath_is_child,
 
2909
                   "test svn_fspath__is_child"),
 
2910
    SVN_TEST_PASS2(test_fspath_dirname_basename_split,
 
2911
                   "test svn_fspath__dirname/basename/split"),
 
2912
    SVN_TEST_PASS2(test_fspath_get_longest_ancestor,
 
2913
                   "test svn_fspath__get_longest_ancestor"),
1702
2914
    SVN_TEST_NULL
1703
2915
  };