You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2013/10/15 10:52:18 UTC

svn commit: r1532250 [35/37] - in /subversion/branches/cache-server: ./ build/ build/ac-macros/ build/generator/ build/generator/swig/ build/generator/templates/ contrib/client-side/emacs/ contrib/hook-scripts/ contrib/server-side/fsfsfixer/ contrib/se...

Modified: subversion/branches/cache-server/subversion/tests/libsvn_subr/string-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/tests/libsvn_subr/string-test.c?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/tests/libsvn_subr/string-test.c (original)
+++ subversion/branches/cache-server/subversion/tests/libsvn_subr/string-test.c Tue Oct 15 08:52:06 2013
@@ -38,6 +38,7 @@
 
 #include "svn_io.h"
 #include "svn_error.h"
+#include "svn_sorts.h"    /* MIN / MAX */
 #include "svn_string.h"   /* This includes <apr_*.h> */
 #include "private/svn_string_private.h"
 
@@ -537,7 +538,42 @@ test24(apr_pool_t *pool)
   SVN_TEST_ASSERT(length == 20);
   SVN_TEST_STRING_ASSERT(buffer, "18446744073709551615");
 
-  return test_stringbuf_unequal("abc", "abb", pool);
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+sub_test_base36(apr_uint64_t value, const char *base36)
+{
+  char buffer[SVN_INT64_BUFFER_SIZE];
+  apr_size_t length;
+  apr_size_t expected_length = strlen(base36);
+  const char *end = buffer;
+  apr_uint64_t result;
+
+  length = svn__ui64tobase36(buffer, value);
+  SVN_TEST_ASSERT(length == expected_length);
+  SVN_TEST_STRING_ASSERT(buffer, base36);
+
+  result = svn__base36toui64(&end, buffer);
+  SVN_TEST_ASSERT(end - buffer == length);
+  SVN_TEST_ASSERT(result == value);
+
+  result = svn__base36toui64(NULL, buffer);
+  SVN_TEST_ASSERT(result == value);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_base36(apr_pool_t *pool)
+{
+  SVN_ERR(sub_test_base36(0, "0"));
+  SVN_ERR(sub_test_base36(1234567890ull, "kf12oi"));
+  SVN_ERR(sub_test_base36(0x7fffffffffffffffull, "1y2p0ij32e8e7"));
+  SVN_ERR(sub_test_base36(0x8000000000000000ull, "1y2p0ij32e8e8"));
+  SVN_ERR(sub_test_base36(0xffffffffffffffffull, "3w5e11264sgsf"));
+
+  return SVN_NO_ERROR;
 }
 
 static svn_error_t *
@@ -620,7 +656,7 @@ test_string_similarity(apr_pool_t *pool)
     const char *stra;
     const char *strb;
     apr_size_t lcs;
-    int score;
+    unsigned int score;
   } tests[] =
       {
 #define SCORE(lcs, len) ((2000 * (lcs) + (len)/2) / (len))
@@ -711,6 +747,85 @@ test_string_similarity(apr_pool_t *pool)
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+test_string_matching(apr_pool_t *pool)
+{
+  const struct test_data_t
+    {
+      const char *a;
+      const char *b;
+      apr_size_t match_len;
+      apr_size_t rmatch_len;
+    }
+  tests[] =
+    {
+      /* edge cases */
+      {"", "", 0, 0},
+      {"", "x", 0, 0},
+      {"x", "", 0, 0},
+      {"x", "x", 1, 1},
+      {"", "1234567890abcdef", 0, 0},
+      {"1234567890abcdef", "", 0, 0},
+      {"1234567890abcdef", "1234567890abcdef", 16, 16},
+
+      /* left-side matches */
+      {"x", "y", 0, 0},
+      {"ax", "ay", 1, 0},
+      {"ax", "a", 1, 0},
+      {"a", "ay", 1, 0},
+      {"1234567890abcdef", "1234567890abcdeg", 15, 0},
+      {"1234567890abcdef_", "1234567890abcdefg", 16, 0},
+      {"12345678_0abcdef", "1234567890abcdeg", 8, 0},
+      {"1234567890abcdef", "12345678", 8, 0},
+      {"12345678", "1234567890abcdef", 8, 0},
+      {"12345678_0ab", "1234567890abcdef", 8, 0},
+
+      /* right-side matches */
+      {"xa", "ya", 0, 1},
+      {"xa", "a", 0, 1},
+      {"a", "ya", 0, 1},
+      {"_234567890abcdef", "1234567890abcdef", 0, 15},
+      {"_1234567890abcdef", "x1234567890abcdef", 0, 16},
+      {"1234567_90abcdef", "_1234567890abcdef", 0, 8},
+      {"1234567890abcdef", "90abcdef", 0, 8},
+      {"90abcdef", "1234567890abcdef", 0, 8},
+      {"8_0abcdef", "7890abcdef", 0, 7},
+
+      /* two-side matches */
+      {"bxa", "bya", 1, 1},
+      {"bxa", "ba", 1, 1},
+      {"ba", "bya", 1, 1},
+      {"1234567_90abcdef", "1234567890abcdef", 7, 8},
+      {"12345678_90abcdef", "1234567890abcdef", 8, 8},
+      {"12345678_0abcdef", "1234567890abcdef", 8, 7},
+      {"123456_abcdef", "1234sdffdssdf567890abcdef", 4, 6},
+      {"1234567890abcdef", "12345678ef", 8, 2},
+      {"x_234567890abcdef", "x1234567890abcdef", 1, 15},
+      {"1234567890abcdefx", "1234567890abcdex", 15, 1},
+
+      /* list terminator */
+      {NULL}
+    };
+
+  const struct test_data_t *test;
+  for (test = tests; test->a != NULL; ++test)
+    {
+      apr_size_t a_len = strlen(test->a);
+      apr_size_t b_len = strlen(test->b);
+      apr_size_t max_match = MIN(a_len, b_len);
+      apr_size_t match_len
+        = svn_cstring__match_length(test->a, test->b, max_match);
+      apr_size_t rmatch_len
+        = svn_cstring__reverse_match_length(test->a + a_len, test->b + b_len,
+                                            max_match);
+
+      SVN_TEST_ASSERT(match_len == test->match_len);
+      SVN_TEST_ASSERT(rmatch_len == test->rmatch_len);
+    }
+  
+  return SVN_NO_ERROR;
+}
+
 /*
    ====================================================================
    If you add a new test to this file, update this array.
@@ -770,6 +885,8 @@ struct svn_test_descriptor_t test_funcs[
                    "compare stringbufs; same length, different content"),
     SVN_TEST_PASS2(test24,
                    "verify i64toa"),
+    SVN_TEST_PASS2(test_base36,
+                   "verify base36 conversion"),
     SVN_TEST_PASS2(test_stringbuf_insert,
                    "check inserting into svn_stringbuf_t"),
     SVN_TEST_PASS2(test_stringbuf_remove,
@@ -778,5 +895,7 @@ struct svn_test_descriptor_t test_funcs[
                    "check replacement in svn_stringbuf_t"),
     SVN_TEST_PASS2(test_string_similarity,
                    "test string similarity scores"),
+    SVN_TEST_PASS2(test_string_matching,
+                   "test string matching"),
     SVN_TEST_NULL
   };

Modified: subversion/branches/cache-server/subversion/tests/libsvn_subr/subst_translate-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/tests/libsvn_subr/subst_translate-test.c?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/tests/libsvn_subr/subst_translate-test.c (original)
+++ subversion/branches/cache-server/subversion/tests/libsvn_subr/subst_translate-test.c Tue Oct 15 08:52:06 2013
@@ -27,6 +27,7 @@
 
 #include "../svn_test.h"
 
+#include "svn_private_config.h"
 #include "svn_types.h"
 #include "svn_string.h"
 #include "svn_subst.h"
@@ -269,6 +270,10 @@ test_svn_subst_build_keywords3(apr_pool_
        "trunk/foo.txt stsp foo.txt %",
        "1234", "http://svn.example.com/repos/trunk/foo.txt",
        "http://svn.example.com/repos", "stsp"},
+      {"FOO", "FOO=author%_=%_%a",
+       "author = stsp",
+       "1234", "http://svn.example.com/repos/trunk/foo.txt",
+       "http://svn.example.com/repos", "stsp"},
       {"MyKeyword", "MyKeyword=%r%_%u%_%_%a",
        "4567 http://svn.example.com/svn/branches/myfile  jrandom",
        "4567", "http://svn.example.com/svn/branches/myfile",
@@ -295,6 +300,7 @@ test_svn_subst_build_keywords3(apr_pool_
                                         t->rev, t->url, t->repos_root_url,
                                         0 /* date */, t->author, pool));
       expanded_keyword = svn_hash_gets(kw, t->keyword_name);
+      SVN_TEST_ASSERT(expanded_keyword != NULL);
       SVN_TEST_STRING_ASSERT(expanded_keyword->data, t->expanded_keyword);
     }
 

Modified: subversion/branches/cache-server/subversion/tests/libsvn_subr/utf-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/tests/libsvn_subr/utf-test.c?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/tests/libsvn_subr/utf-test.c (original)
+++ subversion/branches/cache-server/subversion/tests/libsvn_subr/utf-test.c Tue Oct 15 08:52:06 2013
@@ -25,6 +25,7 @@
 #include "svn_utf.h"
 #include "svn_pools.h"
 
+#include "private/svn_string_private.h"
 #include "private/svn_utf_private.h"
 
 /* Random number seed.  Yes, it's global, just pretend you can't see it. */
@@ -294,6 +295,448 @@ test_utf_cstring_from_utf8_ex2(apr_pool_
   return SVN_NO_ERROR;
 }
 
+/* Test normalization-independent UTF-8 string comparison */
+static svn_error_t *
+test_utf_collated_compare(apr_pool_t *pool)
+{
+  /* Normalized: NFC */
+  static const char nfc[] =
+    "\xe1\xb9\xa8"              /* S with dot above and below */
+    "\xc5\xaf"                  /* u with ring */
+    "\xe1\xb8\x87"              /* b with macron below */
+    "\xe1\xb9\xbd"              /* v with tilde */
+    "\xe1\xb8\x9d"              /* e with breve and cedilla */
+    "\xc8\x91"                  /* r with double grave */
+    "\xc5\xa1"                  /* s with caron */
+    "\xe1\xb8\xaf"              /* i with diaeresis and acute */
+    "\xe1\xbb\x9d"              /* o with grave and hook */
+    "\xe1\xb9\x8b";             /* n with circumflex below */
+
+  /* Normalized: NFD */
+  static const char nfd[] =
+    "S\xcc\xa3\xcc\x87"         /* S with dot above and below */
+    "u\xcc\x8a"                 /* u with ring */
+    "b\xcc\xb1"                 /* b with macron below */
+    "v\xcc\x83"                 /* v with tilde */
+    "e\xcc\xa7\xcc\x86"         /* e with breve and cedilla */
+    "r\xcc\x8f"                 /* r with double grave */
+    "s\xcc\x8c"                 /* s with caron */
+    "i\xcc\x88\xcc\x81"         /* i with diaeresis and acute */
+    "o\xcc\x9b\xcc\x80"         /* o with grave and hook */
+    "n\xcc\xad";                /* n with circumflex below */
+
+  /* Mixed, denormalized */
+  static const char mixup[] =
+    "S\xcc\x87\xcc\xa3"         /* S with dot above and below */
+    "\xc5\xaf"                  /* u with ring */
+    "b\xcc\xb1"                 /* b with macron below */
+    "\xe1\xb9\xbd"              /* v with tilde */
+    "e\xcc\xa7\xcc\x86"         /* e with breve and cedilla */
+    "\xc8\x91"                  /* r with double grave */
+    "s\xcc\x8c"                 /* s with caron */
+    "\xe1\xb8\xaf"              /* i with diaeresis and acute */
+    "o\xcc\x80\xcc\x9b"         /* o with grave and hook */
+    "\xe1\xb9\x8b";             /* n with circumflex below */
+
+  static const char longer[] =
+    "\xe1\xb9\xa8"              /* S with dot above and below */
+    "\xc5\xaf"                  /* u with ring */
+    "\xe1\xb8\x87"              /* b with macron below */
+    "\xe1\xb9\xbd"              /* v with tilde */
+    "\xe1\xb8\x9d"              /* e with breve and cedilla */
+    "\xc8\x91"                  /* r with double grave */
+    "\xc5\xa1"                  /* s with caron */
+    "\xe1\xb8\xaf"              /* i with diaeresis and acute */
+    "\xe1\xbb\x9d"              /* o with grave and hook */
+    "\xe1\xb9\x8b"              /* n with circumflex below */
+    "X";
+
+  static const char shorter[] =
+    "\xe1\xb9\xa8"              /* S with dot above and below */
+    "\xc5\xaf"                  /* u with ring */
+    "\xe1\xb8\x87"              /* b with macron below */
+    "\xe1\xb9\xbd"              /* v with tilde */
+    "\xe1\xb8\x9d"              /* e with breve and cedilla */
+    "\xc8\x91"                  /* r with double grave */
+    "\xc5\xa1"                  /* s with caron */
+    "\xe1\xb8\xaf"              /* i with diaeresis and acute */
+    "\xe1\xbb\x9d";             /* o with grave and hook */
+
+  static const char lowcase[] =
+    "s\xcc\x87\xcc\xa3"         /* s with dot above and below */
+    "\xc5\xaf"                  /* u with ring */
+    "b\xcc\xb1"                 /* b with macron below */
+    "\xe1\xb9\xbd"              /* v with tilde */
+    "e\xcc\xa7\xcc\x86"         /* e with breve and cedilla */
+    "\xc8\x91"                  /* r with double grave */
+    "s\xcc\x8c"                 /* s with caron */
+    "\xe1\xb8\xaf"              /* i with diaeresis and acute */
+    "o\xcc\x80\xcc\x9b"         /* o with grave and hook */
+    "\xe1\xb9\x8b";             /* n with circumflex below */
+
+  static const struct utfcmp_test_t {
+    const char *stra;
+    char op;
+    const char *strb;
+    const char *taga;
+    const char *tagb;
+  } utfcmp_tests[] = {
+    /* Empty key */
+    {"",  '=', "",  "empty",    "empty"},
+    {"",  '<', "a", "empty",    "nonempty"},
+    {"a", '>', "",  "nonempty", "empty"},
+
+    /* Deterministic ordering */
+    {"a", '<', "b", "a", "b"},
+    {"b", '<', "c", "b", "c"},
+    {"a", '<', "c", "a", "c"},
+
+    /* Normalized equality */
+    {nfc,   '=', nfd,    "nfc",   "nfd"},
+    {nfd,   '=', nfc,    "nfd",   "nfc"},
+    {nfc,   '=', mixup,  "nfc",   "mixup"},
+    {nfd,   '=', mixup,  "nfd",   "mixup"},
+    {mixup, '=', nfd,    "mixup", "nfd"},
+    {mixup, '=', nfc,    "mixup", "nfc"},
+
+    /* Key length */
+    {nfc,     '<', longer,    "nfc",     "longer"},
+    {longer,  '>', nfc,       "longer",  "nfc"},
+    {nfd,     '>', shorter,   "nfd",     "shorter"},
+    {shorter, '<', nfd,       "shorter", "nfd"},
+    {mixup,   '<', lowcase,   "mixup",   "lowcase"},
+    {lowcase, '>', mixup,     "lowcase",  "mixup"},
+
+    {NULL, 0, NULL, NULL, NULL}
+  };
+
+
+  const struct utfcmp_test_t *ut;
+  svn_membuf_t bufa, bufb;
+  svn_membuf__create(&bufa, 0, pool);
+  svn_membuf__create(&bufb, 0, pool);
+
+  srand(111);
+  for (ut = utfcmp_tests; ut->stra; ++ut)
+    {
+      const svn_boolean_t implicit_size = (rand() % 17) & 1;
+      const apr_size_t lena = (implicit_size
+                               ? SVN_UTF__UNKNOWN_LENGTH : strlen(ut->stra));
+      const apr_size_t lenb = (implicit_size
+                               ? SVN_UTF__UNKNOWN_LENGTH : strlen(ut->strb));
+      int result;
+
+      SVN_ERR(svn_utf__normcmp(&result,
+                               ut->stra, lena, ut->strb, lenb,
+                               &bufa, &bufb));
+
+      /* UCS-4 debugging dump of the decomposed strings
+      {
+        const apr_int32_t *const ucsbufa = bufa.data;
+        const apr_int32_t *const ucsbufb = bufb.data;
+        apr_size_t i;
+
+        printf("(%c)%7s %c %s\n", ut->op,
+               ut->taga, (!result ? '=' : (result < 0 ? '<' : '>')), ut->tagb);
+
+        for (i = 0; i < bufa.size || i < bufb.size; ++i)
+        {
+          if (i < bufa.size && i < bufb.size)
+            printf("    U+%04X   U+%04X\n", ucsbufa[i], ucsbufb[i]);
+          else if (i < bufa.size)
+            printf("    U+%04X\n", ucsbufa[i]);
+          else
+            printf("             U+%04X\n", ucsbufb[i]);
+        }
+      }
+      */
+
+      if (('=' == ut->op && 0 != result)
+          || ('<' == ut->op && 0 <= result)
+          || ('>' == ut->op && 0 >= result))
+        {
+          return svn_error_createf
+            (SVN_ERR_TEST_FAILED, NULL,
+             "Ut->Op '%s' %c '%s' but '%s' %c '%s'",
+             ut->taga, ut->op, ut->tagb,
+             ut->taga, (!result ? '=' : (result < 0 ? '<' : '>')), ut->tagb);
+        }
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
+
+static svn_error_t *
+test_utf_pattern_match(apr_pool_t *pool)
+{
+  static const struct glob_test_t {
+    svn_boolean_t sql_like;
+    svn_boolean_t matches;
+    const char *pattern;
+    const char *string;
+    const char *escape;
+  } glob_tests[] = {
+#define LIKE_MATCH TRUE, TRUE
+#define LIKE_FAIL  TRUE, FALSE
+#define GLOB_MATCH FALSE, TRUE
+#define GLOB_FAIL  FALSE, FALSE
+
+    {LIKE_FAIL,  "",     "test", NULL},
+    {GLOB_FAIL,  "",     "test", NULL},
+    {LIKE_FAIL,  "",     "%",    NULL},
+    {GLOB_FAIL,  "",     "*",    NULL},
+    {LIKE_FAIL,  "test", "%",    NULL},
+    {GLOB_FAIL,  "test", "*",    NULL},
+    {LIKE_MATCH, "test", "test", NULL},
+    {GLOB_MATCH, "test", "test", NULL},
+    {LIKE_MATCH, "t\xe1\xb8\x9dst", "te\xcc\xa7\xcc\x86st", NULL},
+    {GLOB_MATCH, "te\xcc\xa7\xcc\x86st", "t\xe1\xb8\x9dst", NULL},
+
+    {LIKE_FAIL,  "test", "test", "\xe1\xb8\x9d"}, /* escape char not ascii */
+    {LIKE_FAIL,  "test", "test", ""},             /* empty escape string */
+
+    {LIKE_MATCH, "te#st",    "test",   "#"},
+    {LIKE_FAIL,  "te#st",    "test",   NULL},
+    {GLOB_MATCH, "te\\st",   "test",   NULL},
+    {LIKE_MATCH, "te##st",   "te#st",  "#"},
+    {LIKE_FAIL,  "te##st",   "te#st",  NULL},
+    {GLOB_MATCH, "te\\\\st", "te\\st", NULL},
+    {GLOB_FAIL,  "te\\\\st", "te\\st", "\\"}, /* escape char with glob */
+    {LIKE_FAIL,  "te#%t",    "te%t",   NULL},
+    {LIKE_MATCH, "te#%t",    "te%t",   "#"},
+    {GLOB_MATCH, "te\\*t",   "te*t",   NULL},
+    {LIKE_FAIL,  "te#%t",    "test",   NULL},
+    {GLOB_FAIL,  "te\\*t",   "test",   NULL},
+    {LIKE_FAIL,  "te#_t",    "te_t",   NULL},
+    {LIKE_MATCH, "te#_t",    "te_t",   "#"},
+    {GLOB_MATCH, "te\\?t",   "te?t",   NULL},
+    {LIKE_FAIL,  "te#_t",    "test",   NULL},
+    {LIKE_FAIL,  "te#_t",    "test",   "#"},
+    {GLOB_FAIL,  "te\\?t",   "test",   NULL},
+
+    {LIKE_MATCH, "_est",     "test",   NULL},
+    {GLOB_MATCH, "?est",     "test",   NULL},
+    {LIKE_MATCH, "te_t",     "test",   NULL},
+    {GLOB_MATCH, "te?t",     "test",   NULL},
+    {LIKE_MATCH, "tes_",     "test",   NULL},
+    {GLOB_MATCH, "tes?",     "test",   NULL},
+    {LIKE_FAIL,  "test_",    "test",   NULL},
+    {GLOB_FAIL,  "test?",    "test",   NULL},
+
+    {LIKE_MATCH, "[s%n]",   "[subversion]", NULL},
+    {GLOB_FAIL,  "[s*n]",   "[subversion]", NULL},
+    {LIKE_MATCH, "#[s%n]",  "[subversion]", "#"},
+    {GLOB_MATCH, "\\[s*n]", "[subversion]", NULL},
+
+    {GLOB_MATCH, ".[\\-\\t]", ".t",           NULL},
+    {GLOB_MATCH, "test*?*[a-z]*", "testgoop", NULL},
+    {GLOB_MATCH, "te[^x]t", "test",           NULL},
+    {GLOB_MATCH, "te[^abc]t", "test",         NULL},
+    {GLOB_MATCH, "te[^x]t", "test",           NULL},
+    {GLOB_MATCH, "te[!x]t", "test",           NULL},
+    {GLOB_FAIL,  "te[^x]t", "text",           NULL},
+    {GLOB_FAIL,  "te[^\\x]t", "text",         NULL},
+    {GLOB_FAIL,  "te[^x\\", "text",           NULL},
+    {GLOB_FAIL,  "te[/]t", "text",            NULL},
+    {GLOB_MATCH, "te[r-t]t", "test",          NULL},
+    {GLOB_MATCH, "te[r-Tz]t", "tezt",         NULL},
+    {GLOB_FAIL,  "te[R-T]t", "tent",          NULL},
+/*  {GLOB_MATCH, "tes[]t]", "test",           NULL}, */
+    {GLOB_MATCH, "tes[t-]", "test",           NULL},
+    {GLOB_MATCH, "tes[t-]]", "test]",         NULL},
+    {GLOB_FAIL,  "tes[t-]]", "test",          NULL},
+    {GLOB_FAIL,  "tes[u-]", "test",           NULL},
+    {GLOB_FAIL,  "tes[t-]", "tes[t-]",        NULL},
+    {GLOB_MATCH, "test[/-/]", "test/",        NULL},
+    {GLOB_MATCH, "test[\\/-/]", "test/",      NULL},
+    {GLOB_MATCH, "test[/-\\/]", "test/",      NULL},
+
+#undef LIKE_MATCH
+#undef LIKE_FAIL
+#undef GLOB_MATCH
+#undef GLOB_FAIL
+
+    {FALSE, FALSE, NULL, NULL, NULL}
+  };
+
+  const struct glob_test_t *gt;
+  svn_membuf_t bufa, bufb, bufc;
+  svn_membuf__create(&bufa, 0, pool);
+  svn_membuf__create(&bufb, 0, pool);
+  svn_membuf__create(&bufc, 0, pool);
+
+  srand(79);
+  for (gt = glob_tests; gt->pattern; ++gt)
+    {
+      const svn_boolean_t implicit_size = (rand() % 13) & 1;
+      const apr_size_t lenptn = (implicit_size
+                                 ? SVN_UTF__UNKNOWN_LENGTH
+                                 : strlen(gt->pattern));
+      const apr_size_t lenstr = (implicit_size
+                                 ? SVN_UTF__UNKNOWN_LENGTH
+                                 : strlen(gt->string));
+      const apr_size_t lenesc = (implicit_size
+                                 ? SVN_UTF__UNKNOWN_LENGTH
+                                 : (gt->escape ? strlen(gt->escape) : 0));
+      svn_boolean_t match;
+      svn_error_t *err;
+
+
+      err = svn_utf__glob(&match,
+                          gt->pattern, lenptn,
+                          gt->string, lenstr,
+                          gt->escape, lenesc,
+                          gt->sql_like, &bufa, &bufb, &bufc);
+
+      if (!gt->sql_like && gt->escape && !err)
+        return svn_error_create
+          (SVN_ERR_TEST_FAILED, err, "Failed to detect GLOB ESCAPE");
+
+      if ((err && gt->matches)
+          || (!err && !match != !gt->matches))
+        {
+          if (gt->sql_like)
+            return svn_error_createf
+              (SVN_ERR_TEST_FAILED, err,
+               "Wrong result: %s'%s' LIKE '%s'%s%s%s%s",
+               (gt->matches ? "NOT " : ""), gt->string, gt->pattern,
+               (gt->escape ? " ESCAPE " : ""), (gt->escape ? "'" : ""),
+               (gt->escape ? gt->escape : ""), (gt->escape ? "'" : ""));
+          else
+            return svn_error_createf
+              (SVN_ERR_TEST_FAILED, err, "Wrong result: %s%s GLOB %s",
+               (gt->matches ? "NOT " : ""), gt->string, gt->pattern);
+        }
+
+      if (err)
+        svn_error_clear(err);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+test_utf_fuzzy_escape(apr_pool_t *pool)
+{
+
+  /* Accented latin, mixed normalization */
+  static const char mixup[] =
+    "S\xcc\x87\xcc\xa3"         /* S with dot above and below */
+    "\xc5\xaf"                  /* u with ring */
+    "b\xcc\xb1"                 /* b with macron below */
+    "\xe1\xb9\xbd"              /* v with tilde */
+    "e\xcc\xa7\xcc\x86"         /* e with breve and cedilla */
+    "\xc8\x91"                  /* r with double grave */
+    "s\xcc\x8c"                 /* s with caron */
+    "\xe1\xb8\xaf"              /* i with diaeresis and acute */
+    "o\xcc\x80\xcc\x9b"         /* o with grave and hook */
+    "\xe1\xb9\x8b";             /* n with circumflex below */
+
+  /* As above, but latin lowercase 'o' replaced with Greek 'omicron' */
+  static const char greekish[] =
+    "S\xcc\x87\xcc\xa3"         /* S with dot above and below */
+    "\xc5\xaf"                  /* u with ring */
+    "b\xcc\xb1"                 /* b with macron below */
+    "\xe1\xb9\xbd"              /* v with tilde */
+    "e\xcc\xa7\xcc\x86"         /* e with breve and cedilla */
+    "\xc8\x91"                  /* r with double grave */
+    "s\xcc\x8c"                 /* s with caron */
+    "\xe1\xb8\xaf"              /* i with diaeresis and acute */
+    "\xce\xbf\xcc\x80\xcc\x9b"  /* omicron with grave and hook */
+    "\xe1\xb9\x8b";             /* n with circumflex below */
+
+  /* More interesting invalid characters. */
+  static const char invalid[] =
+    "Not Unicode: \xef\xb7\x91;"      /* U+FDD1 */
+    "Out of range: \xf4\x90\x80\x81;" /* U+110001 */
+    "Not UTF-8: \xe6;"
+    "Null byte: \0;";
+
+  const char *fuzzy;
+
+  fuzzy = svn_utf__fuzzy_escape(mixup, strlen(mixup), pool);
+  SVN_TEST_ASSERT(0 == strcmp(fuzzy, "Subversion"));
+
+  fuzzy = svn_utf__fuzzy_escape(greekish, strlen(greekish), pool);
+  SVN_TEST_ASSERT(0 == strcmp(fuzzy, "Subversi{U+03BF}n"));
+
+  fuzzy = svn_utf__fuzzy_escape(invalid, sizeof(invalid) - 1, pool);
+  /*fprintf(stderr, "%s\n", fuzzy);*/
+  SVN_TEST_ASSERT(0 == strcmp(fuzzy,
+                              "Not Unicode: {U?FDD1};"
+                              "Out of range: ?\\F4?\\90?\\80?\\81;"
+                              "Not UTF-8: ?\\E6;"
+                              "Null byte: \\0;"));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_utf_is_normalized(apr_pool_t *pool)
+{
+  /* Normalized: NFC */
+  static const char nfc[] =
+    "\xe1\xb9\xa8"              /* S with dot above and below */
+    "\xc5\xaf"                  /* u with ring */
+    "\xe1\xb8\x87"              /* b with macron below */
+    "\xe1\xb9\xbd"              /* v with tilde */
+    "\xe1\xb8\x9d"              /* e with breve and cedilla */
+    "\xc8\x91"                  /* r with double grave */
+    "\xc5\xa1"                  /* s with caron */
+    "\xe1\xb8\xaf"              /* i with diaeresis and acute */
+    "\xe1\xbb\x9d"              /* o with grave and hook */
+    "\xe1\xb9\x8b";             /* n with circumflex below */
+
+  /* Normalized: NFD */
+  static const char nfd[] =
+    "S\xcc\xa3\xcc\x87"         /* S with dot above and below */
+    "u\xcc\x8a"                 /* u with ring */
+    "b\xcc\xb1"                 /* b with macron below */
+    "v\xcc\x83"                 /* v with tilde */
+    "e\xcc\xa7\xcc\x86"         /* e with breve and cedilla */
+    "r\xcc\x8f"                 /* r with double grave */
+    "s\xcc\x8c"                 /* s with caron */
+    "i\xcc\x88\xcc\x81"         /* i with diaeresis and acute */
+    "o\xcc\x9b\xcc\x80"         /* o with grave and hook */
+    "n\xcc\xad";                /* n with circumflex below */
+
+  /* Mixed, denormalized */
+  static const char mixup[] =
+    "S\xcc\x87\xcc\xa3"         /* S with dot above and below */
+    "\xc5\xaf"                  /* u with ring */
+    "b\xcc\xb1"                 /* b with macron below */
+    "\xe1\xb9\xbd"              /* v with tilde */
+    "e\xcc\xa7\xcc\x86"         /* e with breve and cedilla */
+    "\xc8\x91"                  /* r with double grave */
+    "s\xcc\x8c"                 /* s with caron */
+    "\xe1\xb8\xaf"              /* i with diaeresis and acute */
+    "o\xcc\x80\xcc\x9b"         /* o with grave and hook */
+    "\xe1\xb9\x8b";             /* n with circumflex below */
+
+  /* Invalid UTF-8 */
+  static const char invalid[] =
+    "\xe1\xb9\xa8"              /* S with dot above and below */
+    "\xc5\xaf"                  /* u with ring */
+    "\xe1\xb8\x87"              /* b with macron below */
+    "\xe1\xb9\xbd"              /* v with tilde */
+    "\xe1\xb8\x9d"              /* e with breve and cedilla */
+    "\xc8\x91"                  /* r with double grave */
+    "\xc5\xa1"                  /* s with caron */
+    "\xe1\xb8\xaf"              /* i with diaeresis and acute */
+    "\xe6"                      /* Invalid byte */
+    "\xe1\xb9\x8b";             /* n with circumflex below */
+
+  SVN_ERR_ASSERT(svn_utf__is_normalized(nfc, pool));
+  SVN_ERR_ASSERT(!svn_utf__is_normalized(nfd, pool));
+  SVN_ERR_ASSERT(!svn_utf__is_normalized(mixup, pool));
+  SVN_ERR_ASSERT(!svn_utf__is_normalized(invalid, pool));
+
+  return SVN_NO_ERROR;
+}
+
 
 /* The test table.  */
 
@@ -308,5 +751,13 @@ struct svn_test_descriptor_t test_funcs[
                    "test svn_utf_cstring_to_utf8_ex2"),
     SVN_TEST_PASS2(test_utf_cstring_from_utf8_ex2,
                    "test svn_utf_cstring_from_utf8_ex2"),
+    SVN_TEST_PASS2(test_utf_collated_compare,
+                   "test svn_utf__normcmp"),
+    SVN_TEST_PASS2(test_utf_pattern_match,
+                   "test svn_utf__glob"),
+    SVN_TEST_PASS2(test_utf_fuzzy_escape,
+                   "test svn_utf__fuzzy_escape"),
+    SVN_TEST_PASS2(test_utf_is_normalized,
+                   "test svn_utf__is_normalized"),
     SVN_TEST_NULL
   };

Modified: subversion/branches/cache-server/subversion/tests/libsvn_wc/conflict-data-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/tests/libsvn_wc/conflict-data-test.c?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/tests/libsvn_wc/conflict-data-test.c (original)
+++ subversion/branches/cache-server/subversion/tests/libsvn_wc/conflict-data-test.c Tue Oct 15 08:52:06 2013
@@ -28,6 +28,8 @@
 #include <apr_hash.h>
 #include <apr_tables.h>
 
+#include "svn_private_config.h"
+#include "svn_props.h"
 #include "svn_pools.h"
 #include "svn_hash.h"
 #include "svn_types.h"
@@ -54,47 +56,133 @@ fail(apr_pool_t *pool, const char *fmt, 
   return svn_error_create(SVN_ERR_TEST_FAILED, 0, msg);
 }
 
-/* Raise a test error if EXPECTED and ACTUAL differ. */
+/* Assert that two integers are equal. Return an error if not. */
+#define ASSERT_INT_EQ(a, b) \
+  do { \
+    if ((a) != (b)) \
+      return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, \
+                               "failed: ASSERT_INT_EQ(" #a ", " #b ") " \
+                               "-> (%d == %d)", a, b); \
+  } while (0)
+
+/* Assert that two strings are equal or both null. Return an error if not. */
+#define ASSERT_STR_EQ(a, b) \
+  SVN_TEST_STRING_ASSERT(a, b)
+
+/* Assert that two version_t's are equal or both null. Return an error if not. */
+static svn_error_t *
+compare_version(const svn_wc_conflict_version_t *actual,
+                const svn_wc_conflict_version_t *expected)
+{
+  if (actual == NULL && expected == NULL)
+    return SVN_NO_ERROR;
+
+  SVN_TEST_ASSERT(actual && expected);
+  ASSERT_STR_EQ(actual->repos_url,      expected->repos_url);
+  ASSERT_INT_EQ((int)actual->peg_rev,   (int)expected->peg_rev);
+  ASSERT_STR_EQ(actual->path_in_repos,  expected->path_in_repos);
+  ASSERT_INT_EQ(actual->node_kind,      expected->node_kind);
+  return SVN_NO_ERROR;
+}
+
+/* Assert that two conflict descriptions contain exactly the same data
+ * (including names of temporary files), or are both NULL.  Return an
+ * error if not. */
+static svn_error_t *
+compare_conflict(const svn_wc_conflict_description3_t *actual,
+                 const svn_wc_conflict_description3_t *expected)
+{
+  if (actual == NULL && expected == NULL)
+    return SVN_NO_ERROR;
+
+  SVN_TEST_ASSERT(actual && expected);
+
+  ASSERT_INT_EQ(actual->kind,           expected->kind);
+  ASSERT_STR_EQ(actual->local_abspath,  expected->local_abspath);
+  ASSERT_INT_EQ(actual->node_kind,      expected->node_kind);
+  ASSERT_STR_EQ(actual->property_name,  expected->property_name);
+  ASSERT_INT_EQ(actual->is_binary,      expected->is_binary);
+  ASSERT_STR_EQ(actual->mime_type,      expected->mime_type);
+  ASSERT_INT_EQ(actual->action,         expected->action);
+  ASSERT_INT_EQ(actual->reason,         expected->reason);
+  ASSERT_STR_EQ(actual->base_abspath,   expected->base_abspath);
+  ASSERT_STR_EQ(actual->their_abspath,  expected->their_abspath);
+  ASSERT_STR_EQ(actual->my_abspath,     expected->my_abspath);
+  ASSERT_STR_EQ(actual->merged_file,    expected->merged_file);
+  ASSERT_INT_EQ(actual->operation,      expected->operation);
+  SVN_ERR(compare_version(actual->src_left_version,
+                          expected->src_left_version));
+  SVN_ERR(compare_version(actual->src_right_version,
+                          expected->src_right_version));
+  return SVN_NO_ERROR;
+}
+
+/* Assert that a file contains the expected data.  Return an
+ * error if not. */
 static svn_error_t *
-compare_version(const svn_wc_conflict_version_t *expected,
-                const svn_wc_conflict_version_t *actual)
+compare_file_content(const char *file_abspath,
+                     const char *expected_val,
+                     apr_pool_t *scratch_pool)
 {
-  SVN_TEST_STRING_ASSERT(expected->repos_url, actual->repos_url);
-  SVN_TEST_ASSERT(expected->peg_rev == actual->peg_rev);
-  SVN_TEST_STRING_ASSERT(expected->path_in_repos, actual->path_in_repos);
-  SVN_TEST_ASSERT(expected->node_kind == actual->node_kind);
+  svn_stringbuf_t *actual_val;
+
+  SVN_ERR(svn_stringbuf_from_file2(&actual_val, file_abspath, scratch_pool));
+  ASSERT_STR_EQ(actual_val->data, expected_val);
   return SVN_NO_ERROR;
 }
 
-/* Raise a test error if EXPECTED and ACTUAL differ or if ACTUAL is NULL. */
-static svn_error_t *
-compare_conflict(const svn_wc_conflict_description2_t *expected,
-                 const svn_wc_conflict_description2_t *actual)
-{
-  SVN_TEST_ASSERT(actual != NULL);
-
-  SVN_TEST_STRING_ASSERT(expected->local_abspath, actual->local_abspath);
-  SVN_TEST_ASSERT(expected->node_kind == actual->node_kind);
-  SVN_TEST_ASSERT(expected->kind == actual->kind);
-  SVN_TEST_STRING_ASSERT(expected->property_name, actual->property_name);
-  SVN_TEST_ASSERT(expected->is_binary == actual->is_binary);
-  SVN_TEST_STRING_ASSERT(expected->mime_type, actual->mime_type);
-  SVN_TEST_ASSERT(expected->action == actual->action);
-  SVN_TEST_ASSERT(expected->reason == actual->reason);
-  SVN_TEST_STRING_ASSERT(expected->base_abspath, actual->base_abspath);
-  SVN_TEST_STRING_ASSERT(expected->their_abspath, actual->their_abspath);
-  SVN_TEST_STRING_ASSERT(expected->my_abspath, actual->my_abspath);
-  SVN_TEST_STRING_ASSERT(expected->merged_file, actual->merged_file);
-  SVN_TEST_ASSERT(expected->operation == actual->operation);
-  SVN_ERR(compare_version(expected->src_left_version,
-                          actual->src_left_version));
-  SVN_ERR(compare_version(expected->src_right_version,
-                          actual->src_right_version));
+/* Assert that ACTUAL and EXPECTED both represent the same property
+ * conflict, or are both NULL.  Return an error if not.
+ *
+ * Compare the property values found in files named by
+ * ACTUAL->base_abspath, ACTUAL->my_abspath, ACTUAL->merged_abspath
+ * with EXPECTED_BASE_VAL, EXPECTED_MY_VAL, EXPECTED_THEIR_VAL
+ * respectively, ignoring the corresponding fields in EXPECTED. */
+static svn_error_t *
+compare_prop_conflict(const svn_wc_conflict_description2_t *actual,
+                      const svn_wc_conflict_description2_t *expected,
+                      const char *expected_base_val,
+                      const char *expected_my_val,
+                      const char *expected_their_val,
+                      apr_pool_t *scratch_pool)
+{
+  if (actual == NULL && expected == NULL)
+    return SVN_NO_ERROR;
+
+  SVN_TEST_ASSERT(actual && expected);
+  ASSERT_INT_EQ(actual->kind,   svn_wc_conflict_kind_property);
+  ASSERT_INT_EQ(expected->kind, svn_wc_conflict_kind_property);
+
+  ASSERT_STR_EQ(actual->local_abspath,  expected->local_abspath);
+  ASSERT_INT_EQ(actual->node_kind,      expected->node_kind);
+  ASSERT_STR_EQ(actual->property_name,  expected->property_name);
+  ASSERT_INT_EQ(actual->action,         expected->action);
+  ASSERT_INT_EQ(actual->reason,         expected->reason);
+  ASSERT_INT_EQ(actual->operation,      expected->operation);
+  SVN_ERR(compare_version(actual->src_left_version,
+                          expected->src_left_version));
+  SVN_ERR(compare_version(actual->src_right_version,
+                          expected->src_right_version));
+
+  SVN_ERR(compare_file_content(actual->base_abspath, expected_base_val,
+                               scratch_pool));
+  SVN_ERR(compare_file_content(actual->my_abspath, expected_my_val,
+                               scratch_pool));
+  /* Historical wart: for a prop conflict, 'theirs' is in the 'merged_file'
+   * field, and the conflict artifact file is in the 'theirs_abspath' field. */
+  SVN_ERR(compare_file_content(actual->merged_file, expected_their_val,
+                               scratch_pool));
+  /*ASSERT_STR_EQ(actual->theirs_abspath, conflict_artifact_file));*/
+
+  /* These are 'undefined' for a prop conflict */
+  /*ASSERT_INT_EQ(actual->is_binary, expected->is_binary);*/
+  /*ASSERT_STR_EQ(actual->mime_type, expected->mime_type);*/
+
   return SVN_NO_ERROR;
 }
 
 /* Create and return a tree conflict description */
-static svn_wc_conflict_description2_t *
+static svn_wc_conflict_description3_t *
 tree_conflict_create(const char *local_abspath,
                      svn_node_kind_t node_kind,
                      svn_wc_operation_t operation,
@@ -111,14 +199,14 @@ tree_conflict_create(const char *local_a
                      apr_pool_t *result_pool)
 {
   svn_wc_conflict_version_t *left, *right;
-  svn_wc_conflict_description2_t *conflict;
+  svn_wc_conflict_description3_t *conflict;
 
   left = svn_wc_conflict_version_create2(left_repo, NULL, left_path,
                                          left_revnum, left_kind, result_pool);
   right = svn_wc_conflict_version_create2(right_repo, NULL, right_path,
                                           right_revnum, right_kind,
                                           result_pool);
-  conflict = svn_wc_conflict_description_create_tree2(
+  conflict = svn_wc_conflict_description_create_tree3(
                     local_abspath, node_kind, operation,
                     left, right, result_pool);
   conflict->action = action;
@@ -129,8 +217,8 @@ tree_conflict_create(const char *local_a
 static svn_error_t *
 test_deserialize_tree_conflict(apr_pool_t *pool)
 {
-  const svn_wc_conflict_description2_t *conflict;
-  svn_wc_conflict_description2_t *exp_conflict;
+  const svn_wc_conflict_description3_t *conflict;
+  svn_wc_conflict_description3_t *exp_conflict;
   const char *tree_conflict_data;
   const char *local_abspath;
   const svn_skel_t *skel;
@@ -139,7 +227,7 @@ test_deserialize_tree_conflict(apr_pool_
                         "(version 0  2 -1 0  0 ) (version 0  2 -1 0  0 ))";
 
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, "Foo.c", pool));
-  exp_conflict = svn_wc_conflict_description_create_tree2(
+  exp_conflict = svn_wc_conflict_description_create_tree3(
                         local_abspath, svn_node_file, svn_wc_operation_update,
                         NULL, NULL, pool);
   exp_conflict->action = svn_wc_conflict_action_delete;
@@ -161,7 +249,7 @@ test_deserialize_tree_conflict(apr_pool_
 static svn_error_t *
 test_serialize_tree_conflict_data(apr_pool_t *pool)
 {
-  svn_wc_conflict_description2_t *conflict;
+  svn_wc_conflict_description3_t *conflict;
   const char *tree_conflict_data;
   const char *expected;
   const char *local_abspath;
@@ -169,7 +257,7 @@ test_serialize_tree_conflict_data(apr_po
 
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, "Foo.c", pool));
 
-  conflict = svn_wc_conflict_description_create_tree2(
+  conflict = svn_wc_conflict_description_create_tree3(
                     local_abspath, svn_node_file, svn_wc_operation_update,
                     NULL, NULL, pool);
   conflict->action = svn_wc_conflict_action_delete;
@@ -198,7 +286,7 @@ test_read_write_tree_conflicts(const svn
 
   const char *parent_abspath;
   const char *child1_abspath, *child2_abspath;
-  svn_wc_conflict_description2_t *conflict1, *conflict2;
+  svn_wc_conflict_description3_t *conflict1, *conflict2;
 
   SVN_ERR(svn_test__sandbox_create(&sbox, "read_write_tree_conflicts", opts, pool));
   parent_abspath = svn_dirent_join(sbox.wc_abspath, "A", pool);
@@ -250,15 +338,15 @@ test_read_write_tree_conflicts(const svn
 
   /* Read conflicts back */
   {
-    const svn_wc_conflict_description2_t *read_conflict;
+    const svn_wc_conflict_description3_t *read_conflict;
 
     SVN_ERR(svn_wc__get_tree_conflict(&read_conflict, sbox.wc_ctx,
                                       child1_abspath, pool, pool));
-    SVN_ERR(compare_conflict(conflict1, read_conflict));
+    SVN_ERR(compare_conflict(read_conflict, conflict1));
 
     SVN_ERR(svn_wc__get_tree_conflict(&read_conflict, sbox.wc_ctx,
                                       child2_abspath, pool, pool));
-    SVN_ERR(compare_conflict(conflict2, read_conflict));
+    SVN_ERR(compare_conflict(read_conflict, conflict2));
   }
 
   /* Read many */
@@ -540,6 +628,186 @@ test_serialize_tree_conflict(const svn_t
   return SVN_NO_ERROR;
 }
 
+/* A conflict resolver callback baton for test_prop_conflicts(). */
+typedef struct test_prop_conflict_baton_t
+{
+  /* Sets of properties. */
+  apr_hash_t *mine;
+  apr_hash_t *their_old;
+  apr_hash_t *theirs;
+  /* The set of prop names in conflict. */
+  apr_hash_t *conflicts;
+
+  /* We use all the fields of DESC except the base/theirs/mine/merged paths. */
+  svn_wc_conflict_description2_t *desc;
+
+  int conflicts_seen;
+} test_prop_conflict_baton_t;
+
+/* Set *CONFLICT_SKEL_P to a new property conflict skel reflecting the
+ * conflict details given in B. */
+static svn_error_t *
+create_prop_conflict_skel(svn_skel_t **conflict_skel_p,
+                          svn_wc_context_t *wc_ctx,
+                          const test_prop_conflict_baton_t *b,
+                          apr_pool_t *result_pool,
+                          apr_pool_t *scratch_pool)
+{
+  svn_skel_t *conflict_skel = svn_wc__conflict_skel_create(result_pool);
+  const char *marker_abspath;
+  svn_boolean_t complete;
+
+  SVN_ERR(svn_io_write_unique(&marker_abspath,
+                              b->desc->local_abspath,
+                              "conflict-artifact-file-content\n", 6,
+                              svn_io_file_del_none, scratch_pool));
+
+  SVN_ERR(svn_wc__conflict_skel_add_prop_conflict(conflict_skel,
+                                                  wc_ctx->db,
+                                                  b->desc->local_abspath,
+                                                  marker_abspath,
+                                                  b->mine, b->their_old,
+                                                  b->theirs, b->conflicts,
+                                                  result_pool, scratch_pool));
+
+  switch (b->desc->operation)
+    {
+    case svn_wc_operation_update:
+      SVN_ERR(svn_wc__conflict_skel_set_op_update(
+                conflict_skel,
+                b->desc->src_left_version, b->desc->src_right_version,
+                result_pool, scratch_pool));
+      break;
+    case svn_wc_operation_switch:
+      SVN_ERR(svn_wc__conflict_skel_set_op_switch(
+                conflict_skel,
+                b->desc->src_left_version, b->desc->src_right_version,
+                result_pool, scratch_pool));
+      break;
+    case svn_wc_operation_merge:
+      SVN_ERR(svn_wc__conflict_skel_set_op_merge(
+                conflict_skel,
+                b->desc->src_left_version, b->desc->src_right_version,
+                result_pool, scratch_pool));
+      break;
+    default:
+      SVN_ERR_MALFUNCTION();
+    }
+
+  SVN_ERR(svn_wc__conflict_skel_is_complete(&complete, conflict_skel));
+  SVN_TEST_ASSERT(complete);
+  *conflict_skel_p = conflict_skel;
+  return SVN_NO_ERROR;
+}
+
+/* A conflict resolver callback for test_prop_conflicts(), that checks
+ * that the conflict described to it matches the one described in BATON,
+ * and also counts the number of times it is called. */
+static svn_error_t *
+prop_conflict_cb(svn_wc_conflict_result_t **result_p,
+                 const svn_wc_conflict_description2_t *desc,
+                 void *baton,
+                 apr_pool_t *result_pool,
+                 apr_pool_t *scratch_pool)
+{
+  test_prop_conflict_baton_t *b = baton;
+
+  SVN_ERR(compare_prop_conflict(
+            desc, b->desc,
+            svn_prop_get_value(b->their_old, desc->property_name),
+            svn_prop_get_value(b->mine, desc->property_name),
+            svn_prop_get_value(b->theirs, desc->property_name),
+            scratch_pool));
+  b->conflicts_seen++;
+
+  *result_p = svn_wc_create_conflict_result(svn_wc_conflict_choose_postpone,
+                                            NULL /*merged_file*/, result_pool);
+  return SVN_NO_ERROR;
+}
+
+/* Test for correct retrieval of property conflict descriptions from
+ * the WC DB.
+ *
+ * Presently it tests just one prop conflict, and only during the
+ * 'resolve' operation.  We should also test during the 'update'/
+ * 'switch'/'merge' operations.
+ */
+static svn_error_t *
+test_prop_conflicts(const svn_test_opts_t *opts,
+                    apr_pool_t *pool)
+{
+  svn_test__sandbox_t sbox;
+  svn_skel_t *conflict_skel;
+  svn_error_t *err;
+  const char *lock_abspath;
+  test_prop_conflict_baton_t *b = apr_pcalloc(pool, sizeof(*b));
+  svn_wc_conflict_description2_t *desc = apr_pcalloc(pool, sizeof(*desc));
+
+  SVN_ERR(svn_test__sandbox_create(&sbox, "test_prop_conflicts", opts, pool));
+
+  /* Describe a property conflict */
+  b->mine = apr_hash_make(pool);
+  b->their_old = apr_hash_make(pool);
+  b->theirs = apr_hash_make(pool);
+  b->conflicts = apr_hash_make(pool);
+  svn_hash_sets(b->mine, "prop", svn_string_create("Mine", pool));
+  svn_hash_sets(b->their_old, "prop", svn_string_create("Their-Old", pool));
+  svn_hash_sets(b->theirs, "prop", svn_string_create("Theirs", pool));
+  svn_hash_sets(b->conflicts, "prop", "");
+
+  b->desc = desc;
+  desc->local_abspath = sbox.wc_abspath;
+  desc->kind = svn_wc_conflict_kind_property;
+  desc->node_kind = svn_node_dir;
+  desc->operation = svn_wc_operation_update;
+  desc->action = svn_wc_conflict_action_edit;
+  desc->reason = svn_wc_conflict_reason_edited;
+  desc->mime_type = NULL;
+  desc->is_binary = FALSE;
+  desc->property_name = "prop";
+  desc->src_left_version
+    = svn_wc_conflict_version_create2(sbox.repos_url, "uuid",
+                                      "trunk", 12, svn_node_dir, pool);
+  desc->src_right_version = NULL;  /* WC only */
+
+  b->conflicts_seen = 0;
+
+  /* Record a conflict */
+  {
+    apr_pool_t *subpool = svn_pool_create(pool);
+    SVN_ERR(create_prop_conflict_skel(&conflict_skel, sbox.wc_ctx, b,
+                                      pool, subpool));
+    svn_pool_clear(subpool);
+    SVN_ERR(svn_wc__db_op_mark_conflict(sbox.wc_ctx->db,
+                                        sbox.wc_abspath,
+                                        conflict_skel, NULL, subpool));
+    svn_pool_destroy(subpool);
+  }
+
+  /* Test the API for resolving the conflict: check that correct details
+   * of the conflict are returned. */
+  SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, sbox.wc_ctx,
+                                                 sbox.wc_abspath, pool, pool));
+  err = svn_wc__resolve_conflicts(sbox.wc_ctx, sbox.wc_abspath,
+                                  svn_depth_empty,
+                                  FALSE /* resolve_text */,
+                                  "" /* resolve_prop (ALL props) */,
+                                  FALSE /* resolve_tree */,
+                                  svn_wc_conflict_choose_unspecified,
+                                  prop_conflict_cb, b,
+                                  NULL, NULL, /* cancellation */
+                                  NULL, NULL, /* notification */
+                                  pool);
+
+  SVN_ERR(svn_error_compose_create(err,
+                                   svn_wc__release_write_lock(sbox.wc_ctx,
+                                                              lock_abspath,
+                                                              pool)));
+
+  ASSERT_INT_EQ(b->conflicts_seen, 1);
+  return SVN_NO_ERROR;
+}
+
 /* The test table.  */
 
 struct svn_test_descriptor_t test_funcs[] =
@@ -557,6 +825,8 @@ struct svn_test_descriptor_t test_funcs[
                        "read and write a text conflict"),
     SVN_TEST_OPTS_PASS(test_serialize_tree_conflict,
                        "read and write a tree conflict"),
+    SVN_TEST_OPTS_PASS(test_prop_conflicts,
+                       "test prop conflicts"),
     SVN_TEST_NULL
   };
 

Modified: subversion/branches/cache-server/subversion/tests/libsvn_wc/db-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/tests/libsvn_wc/db-test.c?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/tests/libsvn_wc/db-test.c (original)
+++ subversion/branches/cache-server/subversion/tests/libsvn_wc/db-test.c Tue Oct 15 08:52:06 2013
@@ -343,6 +343,8 @@ create_open(svn_wc__db_t **db,
   SVN_ERR(svn_wc__db_open(db, NULL, FALSE, TRUE, pool, pool));
   SVN_ERR(svn_test__create_fake_wc(*local_abspath, TESTING_DATA, pool, pool));
 
+  svn_test_add_dir_cleanup(*local_abspath);
+
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/cache-server/subversion/tests/libsvn_wc/entries-compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/tests/libsvn_wc/entries-compat.c?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/tests/libsvn_wc/entries-compat.c (original)
+++ subversion/branches/cache-server/subversion/tests/libsvn_wc/entries-compat.c Tue Oct 15 08:52:06 2013
@@ -336,6 +336,8 @@ create_open(svn_wc__db_t **db,
                           TRUE /* enforce_empty_wq */,
                           pool, pool));
 
+  svn_test_add_dir_cleanup(*local_abspath);
+
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/cache-server/subversion/tests/libsvn_wc/op-depth-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/tests/libsvn_wc/op-depth-test.c?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/tests/libsvn_wc/op-depth-test.c (original)
+++ subversion/branches/cache-server/subversion/tests/libsvn_wc/op-depth-test.c Tue Oct 15 08:52:06 2013
@@ -27,6 +27,7 @@
 #include <apr_pools.h>
 #include <apr_general.h>
 
+#include "svn_private_config.h"
 #include "svn_types.h"
 #include "svn_io.h"
 #include "svn_dirent_uri.h"
@@ -1109,6 +1110,7 @@ base_dir_insert_remove(svn_test__sandbox
   SVN_ERR(svn_wc__db_base_remove(b->wc_ctx->db, dir_abspath,
                                  FALSE /* keep_as_Working */,
                                  FALSE /* queue_deletes */,
+                                 FALSE /* remove_locks */,
                                  SVN_INVALID_REVNUM,
                                  NULL, NULL, b->pool));
   SVN_ERR(svn_wc__wq_run(b->wc_ctx->db, dir_abspath,
@@ -1892,7 +1894,7 @@ check_db_actual(svn_test__sandbox_t* b, 
     {
       const char *local_relpath = svn_sqlite__column_text(stmt, 0, b->pool);
       if (!apr_hash_get(path_hash, local_relpath, APR_HASH_KEY_STRING))
-        return svn_error_createf(SVN_ERR_TEST_FAILED, svn_sqlite__close(sdb),
+        return svn_error_createf(SVN_ERR_TEST_FAILED, svn_sqlite__reset(stmt),
                                  "actual '%s' unexpected", local_relpath);
       apr_hash_set(path_hash, local_relpath, APR_HASH_KEY_STRING, NULL);
       SVN_ERR(svn_sqlite__step(&have_row, stmt));
@@ -1902,7 +1904,7 @@ check_db_actual(svn_test__sandbox_t* b, 
     {
       const char *local_relpath
         = svn__apr_hash_index_key(apr_hash_first(b->pool, path_hash));
-      return svn_error_createf(SVN_ERR_TEST_FAILED, svn_sqlite__close(sdb),
+      return svn_error_createf(SVN_ERR_TEST_FAILED, svn_sqlite__reset(stmt),
                                "actual '%s' expected", local_relpath);
     }
 
@@ -8148,6 +8150,309 @@ update_with_tree_conflict(const svn_test
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+move_update_parent_replace(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+  svn_test__sandbox_t b;
+
+  SVN_ERR(svn_test__sandbox_create(&b, "move_update_parent_replace", opts,
+                                   pool));
+
+  SVN_ERR(sbox_wc_mkdir(&b, "A"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+  SVN_ERR(sbox_wc_commit(&b, ""));
+  SVN_ERR(sbox_wc_delete(&b, "A/B"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+  SVN_ERR(sbox_wc_commit(&b, ""));
+  SVN_ERR(sbox_wc_update(&b, "", 1));
+  SVN_ERR(sbox_wc_move(&b, "A/B/C", "A/C"));
+
+  /* Update breaks the move and leaves a conflict. */
+  SVN_ERR(sbox_wc_update(&b, "", 2));
+  {
+    nodes_row_t nodes[] = {
+      {0, "",    "normal",       2, ""},
+      {0, "A",   "normal",       2, "A"},
+      {0, "A/B", "normal",       2, "A/B"},
+      {2, "A/C", "normal",       1, "A/B/C"},
+      {0}
+    };
+    actual_row_t actual[] = {
+      {"A/B", NULL},
+      {0}
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+    SVN_ERR(check_db_actual(&b, actual));
+  }
+
+  SVN_ERR(sbox_wc_resolve(&b, "A/B", svn_depth_infinity,
+                          svn_wc_conflict_choose_mine_conflict));
+
+  {
+    nodes_row_t nodes[] = {
+      {0, "",    "normal",       2, ""},
+      {0, "A",   "normal",       2, "A"},
+      {0, "A/B", "normal",       2, "A/B"},
+      {2, "A/C", "normal",       1, "A/B/C"},
+      {0}
+    };
+    actual_row_t actual[] = {
+      {0}
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+    SVN_ERR(check_db_actual(&b, actual));
+  }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+copy_mixed_rev_mods(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+  svn_test__sandbox_t b;
+
+  SVN_ERR(svn_test__sandbox_create(&b, "copy_mixed_rev_mods", opts,
+                                   pool));
+
+  SVN_ERR(sbox_wc_mkdir(&b, "A"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+  SVN_ERR(sbox_wc_commit(&b, ""));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/B/C"));
+  SVN_ERR(sbox_wc_commit(&b, ""));
+  SVN_ERR(sbox_wc_update(&b, "", 1));
+  SVN_ERR(sbox_wc_update(&b, "A/B", 2));
+  SVN_ERR(sbox_wc_delete(&b, "A/B"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+
+  {
+    nodes_row_t nodes[] = {
+      {0, "",      "normal",       1, ""},
+      {0, "A",     "normal",       1, "A"},
+      {0, "A/B",   "normal",       2, "A/B"},
+      {0, "A/B/C", "normal",       2, "A/B/C"},
+      {2, "A/B",   "normal",       NO_COPY_FROM},
+      {2, "A/B/C", "base-deleted", NO_COPY_FROM},
+      {0}
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+  }
+
+  SVN_ERR(sbox_wc_copy(&b, "A", "X"));
+  {
+    nodes_row_t nodes[] = {
+      {1, "X",   "normal",      1, "A"},
+      {1, "X/B", "not-present", 2, "A/B"},
+      {2, "X/B", "normal",      NO_COPY_FROM},
+      {0}
+    };
+    SVN_ERR(check_db_rows(&b, "X", nodes));
+  }
+
+  SVN_ERR(sbox_wc_commit(&b, "X"));
+  {
+    nodes_row_t nodes[] = {
+      {0, "X",   "normal", 3, "X"},
+      {0, "X/B", "normal", 3, "X/B"},
+      {0}
+    };
+    SVN_ERR(check_db_rows(&b, "X", nodes));
+  }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_child_to_parent_revert(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+  svn_test__sandbox_t b;
+
+  SVN_ERR(svn_test__sandbox_create(&b, "move_child_to_parent_revert", opts,
+                                   pool));
+
+  SVN_ERR(sbox_wc_mkdir(&b, "A"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+  SVN_ERR(sbox_wc_commit(&b, ""));
+
+
+  SVN_ERR(sbox_wc_move(&b, "A/B", "B"));
+  SVN_ERR(sbox_wc_delete(&b, "A"));
+
+  /* Verify that the move is still recorded correctly */
+  {
+    nodes_row_t nodes[] = {
+      {0, "",    "normal", 0, ""},
+      {0, "A",   "normal", 1, "A"},
+      {0, "A/B", "normal", 1, "A/B"},
+
+      {1, "A",   "base-deleted", NO_COPY_FROM},
+      {1, "A/B", "base-deleted", NO_COPY_FROM, "B"},
+
+      {1, "B", "normal", 1, "A/B", MOVED_HERE},
+      {0}
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+  }
+
+  SVN_ERR(sbox_wc_revert(&b, "A", svn_depth_infinity));
+
+  /* Verify that the move is now just a copy */
+  {
+    nodes_row_t nodes[] = {
+      {0, "",    "normal", 0, ""},
+      {0, "A",   "normal", 1, "A"},
+      {0, "A/B", "normal", 1, "A/B"},
+
+      {1, "B", "normal", 1, "A/B"},
+      {0}
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+  }
+
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_abspath_more_than_once(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+  svn_test__sandbox_t b;
+
+  SVN_ERR(svn_test__sandbox_create(&b, "move_child_to_parent_revert", opts,
+                                   pool));
+
+  SVN_ERR(sbox_wc_mkdir(&b, "A"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/A"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/A/A"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/A/A/A"));
+  SVN_ERR(sbox_wc_mkdir(&b, "B"));
+  SVN_ERR(sbox_wc_mkdir(&b, "B/A"));
+  SVN_ERR(sbox_wc_mkdir(&b, "B/A/A"));
+  SVN_ERR(sbox_wc_mkdir(&b, "B/A/A/A"));
+  SVN_ERR(sbox_wc_mkdir(&b, "C"));
+  SVN_ERR(sbox_wc_mkdir(&b, "C/A"));
+  SVN_ERR(sbox_wc_mkdir(&b, "C/A/A"));
+  SVN_ERR(sbox_wc_mkdir(&b, "C/A/A/A"));
+  SVN_ERR(sbox_wc_commit(&b, ""));
+
+  SVN_ERR(sbox_wc_move(&b, "A/A/A", "AAA_1"));
+
+  SVN_ERR(sbox_wc_delete(&b, "A"));
+  SVN_ERR(sbox_wc_move(&b, "B", "A"));
+
+  SVN_ERR(sbox_wc_move(&b, "A/A/A", "AAA_2"));
+
+  SVN_ERR(sbox_wc_delete(&b, "A/A"));
+  SVN_ERR(sbox_wc_move(&b, "C/A", "A/A"));
+
+  SVN_ERR(sbox_wc_move(&b, "A/A/A", "AAA_3"));
+
+  /* Verify that the move is still recorded correctly */
+  {
+    nodes_row_t nodes[] = {
+
+      {0, "",           "normal",       0, ""},
+
+      {1, "AAA_1",      "normal",       1, "A/A/A",             MOVED_HERE},
+      {1, "AAA_1/A",    "normal",       1, "A/A/A/A",           MOVED_HERE},
+      {1, "AAA_2",      "normal",       1, "B/A/A",             MOVED_HERE},
+      {1, "AAA_2/A",    "normal",       1, "B/A/A/A",           MOVED_HERE},
+      {1, "AAA_3",      "normal",       1, "C/A/A",             MOVED_HERE},
+      {1, "AAA_3/A",    "normal",       1, "C/A/A/A",           MOVED_HERE},
+
+      {0, "A",          "normal",       1, "A"},
+      {0, "A/A",        "normal",       1, "A/A"},
+      {0, "A/A/A",      "normal",       1, "A/A/A"},
+      {0, "A/A/A/A",    "normal",       1, "A/A/A/A"},
+
+      {1, "A",          "normal",       1, "B",                 MOVED_HERE},
+      {1, "A/A",        "normal",       1, "B/A",               MOVED_HERE},
+      {1, "A/A/A",      "normal",       1, "B/A/A", FALSE, "AAA_1",   TRUE},
+      {1, "A/A/A/A",    "normal",       1, "B/A/A/A",           MOVED_HERE},
+
+      {2, "A/A",        "normal",       1, "C/A", MOVED_HERE},
+      {2, "A/A/A",      "normal",       1, "C/A/A", FALSE, "AAA_2",   TRUE},
+      {2, "A/A/A/A",    "normal",       1, "C/A/A/A",           MOVED_HERE},
+
+      {3, "A/A/A",      "base-deleted", NO_COPY_FROM,      "AAA_3"},
+      {3, "A/A/A/A",    "base-deleted", NO_COPY_FROM},
+
+      {0, "B",          "normal",       1, "B"},
+      {0, "B/A",        "normal",       1, "B/A"},
+      {0, "B/A/A",      "normal",       1, "B/A/A"},
+      {0, "B/A/A/A",    "normal",       1, "B/A/A/A"},
+
+      {1, "B",          "base-deleted", NO_COPY_FROM, "A"},
+      {1, "B/A",        "base-deleted", NO_COPY_FROM},
+      {1, "B/A/A",      "base-deleted", NO_COPY_FROM},
+      {1, "B/A/A/A",    "base-deleted", NO_COPY_FROM},
+
+      {0, "C",          "normal",       1, "C"},
+      {0, "C/A",        "normal",       1, "C/A"},
+      {0, "C/A/A",      "normal",       1, "C/A/A"},
+      {0, "C/A/A/A",    "normal",       1, "C/A/A/A"},
+
+      {2, "C/A",        "base-deleted", NO_COPY_FROM, "A/A"},
+      {2, "C/A/A",      "base-deleted", NO_COPY_FROM},
+      {2, "C/A/A/A",    "base-deleted", NO_COPY_FROM},
+
+      {0},
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+  }
+
+  /* Ok, now we are in the very ugly case where A/A/A is moved away 3 times */
+
+  /* Let's revert A */
+  SVN_ERR(sbox_wc_revert(&b, "A", svn_depth_infinity));
+
+  /* AAA_1 should now be a copy, but AAA_2 and AAA_3 should still be moves,
+     but now from the original location instead of from "A/A/A" */
+  {
+    nodes_row_t nodes[] = {
+
+      {0, "",           "normal",       0, ""},
+
+      {1, "AAA_1",      "normal",       1, "A/A/A",},
+      {1, "AAA_1/A",    "normal",       1, "A/A/A/A"},
+      {1, "AAA_2",      "normal",       1, "B/A/A",             MOVED_HERE},
+      {1, "AAA_2/A",    "normal",       1, "B/A/A/A",           MOVED_HERE},
+      {1, "AAA_3",      "normal",       1, "C/A/A",             MOVED_HERE},
+      {1, "AAA_3/A",    "normal",       1, "C/A/A/A",           MOVED_HERE},
+
+      {0, "A",          "normal",       1, "A"},
+      {0, "A/A",        "normal",       1, "A/A"},
+      {0, "A/A/A",      "normal",       1, "A/A/A"},
+      {0, "A/A/A/A",    "normal",       1, "A/A/A/A"},
+
+      {0, "B",          "normal",       1, "B"},
+      {0, "B/A",        "normal",       1, "B/A"},
+      {0, "B/A/A",      "normal",       1, "B/A/A"},
+      {0, "B/A/A/A",    "normal",       1, "B/A/A/A"},
+
+      {1, "B",          "base-deleted", NO_COPY_FROM},
+      {1, "B/A",        "base-deleted", NO_COPY_FROM},
+      {1, "B/A/A",      "base-deleted", NO_COPY_FROM, "AAA_2"},
+      {1, "B/A/A/A",    "base-deleted", NO_COPY_FROM},
+
+      {0, "C",          "normal",       1, "C"},
+      {0, "C/A",        "normal",       1, "C/A"},
+      {0, "C/A/A",      "normal",       1, "C/A/A"},
+      {0, "C/A/A/A",    "normal",       1, "C/A/A/A"},
+
+      {2, "C/A",        "base-deleted", NO_COPY_FROM},
+      {2, "C/A/A",      "base-deleted", NO_COPY_FROM, "AAA_3"},
+      {2, "C/A/A/A",    "base-deleted", NO_COPY_FROM},
+
+      {0},
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+  }
+
+  return SVN_NO_ERROR;
+}
+
+
 /* ---------------------------------------------------------------------- */
 /* The list of test functions */
 
@@ -8301,5 +8606,13 @@ struct svn_test_descriptor_t test_funcs[
                        "move/delete file externals (issue 4293)"),
     SVN_TEST_OPTS_PASS(update_with_tree_conflict,
                        "update with tree conflict (issue 4347)"),
+    SVN_TEST_OPTS_PASS(move_update_parent_replace,
+                       "move update with replaced parent (issue 4388)"),
+    SVN_TEST_OPTS_XFAIL(copy_mixed_rev_mods,
+                       "copy mixed-rev with mods"),
+    SVN_TEST_OPTS_PASS(move_child_to_parent_revert,
+                       "move child to parent and revert (issue 4436)"),
+    SVN_TEST_OPTS_XFAIL(move_abspath_more_than_once,
+                       "move one abspath more than once"),
     SVN_TEST_NULL
   };

Modified: subversion/branches/cache-server/subversion/tests/libsvn_wc/wc-lock-tester.c
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/tests/libsvn_wc/wc-lock-tester.c?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/tests/libsvn_wc/wc-lock-tester.c (original)
+++ subversion/branches/cache-server/subversion/tests/libsvn_wc/wc-lock-tester.c Tue Oct 15 08:52:06 2013
@@ -35,16 +35,19 @@
 #include "private/svn_wc_private.h"
 #include "../../libsvn_wc/wc.h"
 #include "../../libsvn_wc/wc_db.h"
+#include "../../libsvn_wc/workqueue.h"
 
 #include "svn_private_config.h"
 
 #define USAGE_MSG \
-  "Usage: %s [-r|-1] DIRNAME\n" \
+  "Usage: %s [-1|-r|-w] DIRNAME\n" \
   "\n" \
-  "Locks one directory (-1), or a tree recursively (-r)\n"
+  "Locks one directory (-1), or a tree recursively (-r), or locks\n" \
+  "recursively and creates an outstanding work queue item (-w)\n"
 
 static svn_error_t *
 obtain_lock(const char *path, svn_boolean_t recursive,
+            svn_boolean_t populate_work_queue,
             apr_pool_t *scratch_pool)
 {
   const char *local_abspath;
@@ -52,9 +55,7 @@ obtain_lock(const char *path, svn_boolea
 
   SVN_ERR(svn_path_cstring_to_utf8(&path, path, scratch_pool));
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));
-
-      SVN_ERR(svn_wc_context_create(&wc_ctx, NULL, scratch_pool,
-                                    scratch_pool));
+  SVN_ERR(svn_wc_context_create(&wc_ctx, NULL, scratch_pool, scratch_pool));
 
   if (recursive)
     {
@@ -68,6 +69,19 @@ obtain_lock(const char *path, svn_boolea
                                        scratch_pool));
     }
 
+  if (populate_work_queue)
+    {
+      svn_skel_t *work_item;
+
+      /* Add an arbitrary work item to the work queue for DB, but don't
+       * run the work queue. */
+      SVN_ERR(svn_wc__wq_build_sync_file_flags(&work_item, wc_ctx->db,
+                                               local_abspath, scratch_pool,
+                                               scratch_pool));
+      SVN_ERR(svn_wc__db_wq_add(wc_ctx->db, local_abspath, work_item,
+                                scratch_pool));
+    }
+
   SVN_ERR(svn_cmdline_printf(scratch_pool, "Lock on '%s' obtained, and we "
                              "are not going to release it.\n",
                              svn_dirent_local_style(local_abspath,
@@ -83,9 +97,11 @@ main(int argc, const char *argv[])
   int exit_code = EXIT_SUCCESS;
   svn_error_t *err;
   svn_boolean_t recursive;
+  svn_boolean_t populate_work_queue;
 
   if (argc != 3
-      || (strcmp(argv[1], "-1") && apr_strnatcmp(argv[1], "-r")))
+      || (strcmp(argv[1], "-1") && apr_strnatcmp(argv[1], "-r") &&
+          apr_strnatcmp(argv[1], "-w")))
     {
       fprintf(stderr, USAGE_MSG, argv[0]);
       exit(EXIT_FAILURE);
@@ -100,9 +116,10 @@ main(int argc, const char *argv[])
   /* set up the global pool */
   pool = svn_pool_create(NULL);
 
-  recursive = (strcmp(argv[1], "-1") != 0);
+  populate_work_queue = (strcmp(argv[1], "-w") == 0);
+  recursive = ((strcmp(argv[1], "-1") != 0) || populate_work_queue);
 
-  err = obtain_lock(argv[2], recursive, pool);
+  err = obtain_lock(argv[2], recursive, populate_work_queue, pool);
 
   if (err)
     {

Modified: subversion/branches/cache-server/subversion/tests/libsvn_wc/wc-queries-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/tests/libsvn_wc/wc-queries-test.c?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/tests/libsvn_wc/wc-queries-test.c (original)
+++ subversion/branches/cache-server/subversion/tests/libsvn_wc/wc-queries-test.c Tue Oct 15 08:52:06 2013
@@ -32,6 +32,17 @@
 #ifdef SVN_SQLITE_INLINE
 /* Include sqlite3 inline, making all symbols private. */
   #define SQLITE_API static
+  #ifdef __APPLE__
+    #include <Availability.h>
+    #if __MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+      /* <libkern/OSAtomic.h> is included on OS X by sqlite3.c, and
+         on old systems (Leopard or older), it cannot be compiled
+         with -std=c89 because it uses inline. This is a work-around. */
+      #define inline __inline__
+      #include <libkern/OSAtomic.h>
+      #undef inline
+    #endif
+  #endif
   #include <sqlite3.c>
 #else
   #include <sqlite3.h>
@@ -154,7 +165,7 @@ test_sqlite_version(apr_pool_t *scratch_
   printf("DBG: Using Sqlite %s\n", sqlite3_version);
 
   if (sqlite3_libversion_number() != SQLITE_VERSION_NUMBER)
-    printf("DBG: Compiled against Sqlite %s", SQLITE_VERSION);
+    printf("DBG: Compiled against Sqlite %s\n", SQLITE_VERSION);
 
   if (sqlite3_libversion_number() < SQLITE_VERSION_NUMBER)
     return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,

Modified: subversion/branches/cache-server/subversion/tests/libsvn_wc/wc-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/tests/libsvn_wc/wc-test.c?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/tests/libsvn_wc/wc-test.c (original)
+++ subversion/branches/cache-server/subversion/tests/libsvn_wc/wc-test.c Tue Oct 15 08:52:06 2013
@@ -24,6 +24,7 @@
 #include <apr_pools.h>
 #include <apr_general.h>
 
+#include "svn_private_config.h"
 #include "svn_types.h"
 #include "svn_io.h"
 #include "svn_dirent_uri.h"

Modified: subversion/branches/cache-server/subversion/tests/svn_test.h
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/tests/svn_test.h?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/tests/svn_test.h (original)
+++ subversion/branches/cache-server/subversion/tests/svn_test.h Tue Oct 15 08:52:06 2013
@@ -63,12 +63,13 @@ extern "C" {
     SVN_ERR_ASSERT((expected));                                           \
     if (err__ == SVN_NO_ERROR || err__->apr_err != (expected))            \
       return err__ ? svn_error_createf(SVN_ERR_TEST_FAILED, err__,        \
-                                       "Expected error %d but got %d",    \
-                                       (expected),                        \
-                                       err__->apr_err)                    \
+                                       "Expected error %s but got %s",    \
+                                       svn_error_symbolic_name(expected), \
+                                       svn_error_symbolic_name(           \
+                                         err__->apr_err))                 \
                    : svn_error_createf(SVN_ERR_TEST_FAILED, err__,        \
-                                        "Expected error %d but got %s",   \
-                                        (expected),                       \
+                                       "Expected error %s but got %s",    \
+                                       svn_error_symbolic_name(expected), \
                                         "SVN_NO_ERROR");                  \
     svn_error_clear(err__);                                               \
   } while (0)

Modified: subversion/branches/cache-server/subversion/tests/svn_test_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/tests/svn_test_fs.c?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/tests/svn_test_fs.c (original)
+++ subversion/branches/cache-server/subversion/tests/svn_test_fs.c Tue Oct 15 08:52:06 2013
@@ -26,6 +26,7 @@
 
 #include "svn_test.h"
 
+#include "svn_private_config.h"
 #include "svn_string.h"
 #include "svn_utf.h"
 #include "svn_pools.h"
@@ -33,6 +34,7 @@
 #include "svn_fs.h"
 #include "svn_path.h"
 #include "svn_delta.h"
+#include "svn_hash.h"
 
 #include "svn_test_fs.h"
 
@@ -81,8 +83,8 @@ make_fs_config(const char *fs_type,
                fs_type);
   if (server_minor_version)
     {
-      if (server_minor_version == 6)
-        /* no SVN_FS_CONFIG_PRE_1_7_COMPATIBLE */;
+      if (server_minor_version == 6 || server_minor_version == 7)
+        svn_hash_sets(fs_config, SVN_FS_CONFIG_PRE_1_8_COMPATIBLE, "1");
       else if (server_minor_version == 5)
         apr_hash_set(fs_config, SVN_FS_CONFIG_PRE_1_6_COMPATIBLE,
                      APR_HASH_KEY_STRING, "1");
@@ -143,21 +145,36 @@ create_fs(svn_fs_t **fs_p,
  * copy that file into the filesystem FS and set *MUST_REOPEN to TRUE, else
  * set *MUST_REOPEN to FALSE. */
 static svn_error_t *
-maybe_install_fsfs_conf(svn_fs_t *fs,
-                        const svn_test_opts_t *opts,
-                        svn_boolean_t *must_reopen,
-                        apr_pool_t *pool)
+maybe_install_fs_conf(svn_fs_t *fs,
+                      const svn_test_opts_t *opts,
+                      svn_boolean_t *must_reopen,
+                      apr_pool_t *pool)
 {
   *must_reopen = FALSE;
-  if (strcmp(opts->fs_type, "fsfs") != 0 || ! opts->config_file)
+  if (! opts->config_file)
     return SVN_NO_ERROR;
 
-  *must_reopen = TRUE;
-  return svn_io_copy_file(opts->config_file,
-                          svn_path_join(svn_fs_path(fs, pool),
-                                        "fsfs.conf", pool),
-                          FALSE /* copy_perms */,
-                          pool);
+  if (strcmp(opts->fs_type, "fsfs") == 0)
+    {
+      *must_reopen = TRUE;
+      return svn_io_copy_file(opts->config_file,
+                              svn_path_join(svn_fs_path(fs, pool),
+                                            "fsfs.conf", pool),
+                              FALSE /* copy_perms */,
+                              pool);
+    }
+
+  if (strcmp(opts->fs_type, "fsx") == 0)
+    {
+      *must_reopen = TRUE;
+      return svn_io_copy_file(opts->config_file,
+                              svn_path_join(svn_fs_path(fs, pool),
+                                            "fsx.conf", pool),
+                              FALSE /* copy_perms */,
+                              pool);
+    }
+
+  return SVN_NO_ERROR;
 }
 
 
@@ -182,7 +199,7 @@ svn_test__create_fs(svn_fs_t **fs_p,
   SVN_ERR(create_fs(fs_p, name, opts->fs_type,
                     opts->server_minor_version, pool));
 
-  SVN_ERR(maybe_install_fsfs_conf(*fs_p, opts, &must_reopen, pool));
+  SVN_ERR(maybe_install_fs_conf(*fs_p, opts, &must_reopen, pool));
   if (must_reopen)
     {
       SVN_ERR(svn_fs_open(fs_p, name, NULL, pool));
@@ -228,8 +245,8 @@ svn_test__create_repos(svn_repos_t **rep
   /* Register this repo for cleanup. */
   svn_test_add_dir_cleanup(name);
 
-  SVN_ERR(maybe_install_fsfs_conf(svn_repos_fs(repos), opts, &must_reopen,
-                                  pool));
+  SVN_ERR(maybe_install_fs_conf(svn_repos_fs(repos), opts, &must_reopen,
+                                pool));
   if (must_reopen)
     {
       SVN_ERR(svn_repos_open2(&repos, name, NULL, pool));
@@ -354,6 +371,8 @@ get_dir_entries(apr_hash_t *tree_entries
 }
 
 
+/* Verify that PATH under ROOT is: a directory if contents is NULL;
+   a file with contents CONTENTS otherwise. */
 static svn_error_t *
 validate_tree_entry(svn_fs_root_t *root,
                     const char *path,
@@ -515,6 +534,42 @@ svn_test__validate_tree(svn_fs_root_t *r
 
 
 svn_error_t *
+svn_test__validate_changes(svn_fs_root_t *root,
+                           apr_hash_t *expected,
+                           apr_pool_t *pool)
+{
+  apr_hash_t *actual;
+  apr_hash_index_t *hi;
+
+  SVN_ERR(svn_fs_paths_changed2(&actual, root, pool));
+
+#if 0
+  /* Print ACTUAL and EXPECTED. */
+  {
+    int i;
+    for (i=0, hi = apr_hash_first(pool, expected); hi; hi = apr_hash_next(hi))
+      SVN_DBG(("expected[%d] = '%s'\n", i++, svn__apr_hash_index_key(hi)));
+    for (i=0, hi = apr_hash_first(pool, actual); hi; hi = apr_hash_next(hi))
+      SVN_DBG(("actual[%d] = '%s'\n", i++, svn__apr_hash_index_key(hi)));
+  }
+#endif
+
+  for (hi = apr_hash_first(pool, expected); hi; hi = apr_hash_next(hi))
+    if (NULL == svn_hash_gets(actual, svn__apr_hash_index_key(hi)))
+      return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+                               "Path '%s' missing from actual changed-paths",
+                               (const char *)svn__apr_hash_index_key(hi));
+
+  for (hi = apr_hash_first(pool, actual); hi; hi = apr_hash_next(hi))
+    if (NULL == svn_hash_gets(expected, svn__apr_hash_index_key(hi)))
+      return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+                               "Path '%s' missing from expected changed-paths",
+                               (const char *)svn__apr_hash_index_key(hi));
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 svn_test__txn_script_exec(svn_fs_root_t *txn_root,
                           svn_test__txn_script_command_t *script,
                           int num_edits,

Modified: subversion/branches/cache-server/subversion/tests/svn_test_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/subversion/tests/svn_test_fs.h?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/subversion/tests/svn_test_fs.h (original)
+++ subversion/branches/cache-server/subversion/tests/svn_test_fs.h Tue Oct 15 08:52:06 2013
@@ -112,6 +112,14 @@ svn_test__validate_tree(svn_fs_root_t *r
                         int num_entries,
                         apr_pool_t *pool);
 
+/* Verify that svn_fs_paths_changed2(ROOT) returns a hash with exactly
+   the same keys as EXPECTED_KEYS.  Values are not currently verified.
+ */
+svn_error_t *
+svn_test__validate_changes(svn_fs_root_t *root,
+                           apr_hash_t *expected_keys,
+                           apr_pool_t *pool);
+
 /* Structure for describing script-ish commands to perform on a
    transaction using svn_test__txn_script_exec().  */
 typedef struct svn_test__txn_script_command_t

Modified: subversion/branches/cache-server/tools/buildbot/slaves/bb-openbsd/svnclean.sh
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/tools/buildbot/slaves/bb-openbsd/svnclean.sh?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/tools/buildbot/slaves/bb-openbsd/svnclean.sh (original)
+++ subversion/branches/cache-server/tools/buildbot/slaves/bb-openbsd/svnclean.sh Tue Oct 15 08:52:06 2013
@@ -24,7 +24,7 @@ set -x
 
 branch="$(basename $(svn info . | grep ^URL  | cut -d' ' -f2))"
 (test -h ../svn-trunk || ln -s build ../svn-trunk)
-for i in 6 7; do
+for i in 6 7 8 9 10; do
   (test -h ../svn-1.${i}.x || ln -s build ../svn-1.${i}.x)
 done
 svn update ../../unix-build

Modified: subversion/branches/cache-server/tools/buildbot/slaves/win32-SharpSvn/svn-config.cmd.template
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/tools/buildbot/slaves/win32-SharpSvn/svn-config.cmd.template?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/tools/buildbot/slaves/win32-SharpSvn/svn-config.cmd.template (original)
+++ subversion/branches/cache-server/tools/buildbot/slaves/win32-SharpSvn/svn-config.cmd.template Tue Oct 15 08:52:06 2013
@@ -29,3 +29,22 @@ SET TMP=%TEMP%
 
 IF NOT EXIST "%TESTDIR%\" MKDIR "%TESTDIR%"
 IF NOT EXIST "%TEMP%\" MKDIR "%TEMP%"
+
+
+
+
+
+SET SVN_URL=
+SET SVN_RELURL=
+for /F "usebackq tokens=1,* delims=:" %%i IN (`svn info .`) do (
+
+  IF "%%i" == "URL" (
+    SET SVN_URL=%%j
+  ) ELSE IF "%%i" == "Relative URL" (
+    SET SVN_RELURL=%%j
+  )
+)
+SET SVN_URL=%SVN_URL:~1%
+SET SVN_RELURL=%SVN_RELURL:~3%
+SET SVN_SUBBRANCH=%SVN_RELURL:~11%
+SET SVN_BRANCH=%SVN_SUBBRANCH:branches/=%

Modified: subversion/branches/cache-server/tools/buildbot/slaves/win32-SharpSvn/svntest-bindings.cmd
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/tools/buildbot/slaves/win32-SharpSvn/svntest-bindings.cmd?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/tools/buildbot/slaves/win32-SharpSvn/svntest-bindings.cmd (original)
+++ subversion/branches/cache-server/tools/buildbot/slaves/win32-SharpSvn/svntest-bindings.cmd Tue Oct 15 08:52:06 2013
@@ -22,10 +22,10 @@ SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDE
 
 CALL ..\svn-config.cmd
 IF ERRORLEVEL 1 EXIT /B 1
+ECHO ON
 
-svnversion . /1.6.x | find "S" > nul:
-IF ERRORLEVEL 1 (
-  ECHO --- Building 1.6.x: Skipping bindings ---
+IF "%SVN_BRANCH%" LEQ "1.6.x" (
+  ECHO --- Building 1.6.x or older: Skipping bindings ---
   EXIT /B 0
 )
 
@@ -34,52 +34,79 @@ SET result=0
 
 python win-tests.py -d -f fsfs --javahl "%TESTDIR%\tests"
 IF ERRORLEVEL 1 (
-  echo [python reported error %ERRORLEVEL%]
-  SET result=1
-)
-
-IF EXIST "%TESTDIR%\swig" rmdir /s /q "%TESTDIR%\swig"
-mkdir "%TESTDIR%\swig\py-release\libsvn"
-mkdir "%TESTDIR%\swig\py-release\svn"
-
-xcopy "release\subversion\bindings\swig\python\*.pyd" "%TESTDIR%\swig\py-release\libsvn\*.pyd" > nul:
-xcopy "release\subversion\bindings\swig\python\libsvn_swig_py\*.dll" "%TESTDIR%\swig\py-release\libsvn\*.dll" > nul:
-xcopy "subversion\bindings\swig\python\*.py" "%TESTDIR%\swig\py-release\libsvn\*.py" > nul:
-xcopy "subversion\bindings\swig\python\svn\*.py" "%TESTDIR%\swig\py-release\svn\*.py" > nul:
-
-SET PYTHONPATH=%TESTDIR%\swig\py-release
-
-python subversion\bindings\swig\python\tests\run_all.py
-IF ERRORLEVEL 1 (
-  echo [Python reported error %ERRORLEVEL%]
+  echo [python reported error !ERRORLEVEL!]
   SET result=1
 )
 
-mkdir "%TESTDIR%\swig\pl-release\SVN"
-mkdir "%TESTDIR%\swig\pl-release\auto\SVN"
-xcopy subversion\bindings\swig\perl\native\*.pm "%TESTDIR%\swig\pl-release\SVN" > nul:
-pushd release\subversion\bindings\swig\perl\native
-for %%i in (*.dll) do (
-  set name=%%i
-  mkdir "%TESTDIR%\swig\pl-release\auto\SVN\!name:~0,-4!"
-  xcopy "!name:~0,-4!.*" "%TESTDIR%\swig\pl-release\auto\SVN\!name:~0,-4!" > nul:
-  xcopy /y "_Core.dll" "%TESTDIR%\swig\pl-release\auto\SVN\!name:~0,-4!" > nul:
-)
-popd
+if "%SVN_BRANCH%" GTR "1.9." (
 
-svnversion . /1.7.x | find "S" > nul:
-IF ERRORLEVEL 1 (
-  ECHO --- Building 1.7.x: Skipping perl tests ---
-  EXIT /B %result%
-)
+    python win-tests.py -r -f fsfs --swig=python "%TESTDIR%\tests"
 
-SET PERL5LIB=%PERL5LIB%;%TESTDIR%\swig\pl-release;
-pushd subversion\bindings\swig\perl\native
-perl -MExtUtils::Command::MM -e test_harness() t\*.t
-IF ERRORLEVEL 1 (
-  echo [Perl reported error %ERRORLEVEL%]
-  SET result=1
+    IF ERRORLEVEL 1 (
+        echo [Python tests exited with error !ERRORLEVEL!]
+        SET result=1
+    )
+
+) ELSE (
+    IF EXIST "%TESTDIR%\swig" rmdir /s /q "%TESTDIR%\swig"
+    mkdir "%TESTDIR%\swig\py-release\libsvn"
+    mkdir "%TESTDIR%\swig\py-release\svn"
+
+    xcopy "release\subversion\bindings\swig\python\*.pyd" "%TESTDIR%\swig\py-release\libsvn\*.pyd" > nul:
+    xcopy "release\subversion\bindings\swig\python\libsvn_swig_py\*.dll" "%TESTDIR%\swig\py-release\libsvn\*.dll" > nul:
+    xcopy "subversion\bindings\swig\python\*.py" "%TESTDIR%\swig\py-release\libsvn\*.py" > nul:
+    xcopy "subversion\bindings\swig\python\svn\*.py" "%TESTDIR%\swig\py-release\svn\*.py" > nul:
+
+    SET PYTHONPATH=%TESTDIR%\swig\py-release
+
+    python subversion\bindings\swig\python\tests\run_all.py
+    IF ERRORLEVEL 1 (
+        echo [Python tests exited with error !ERRORLEVEL!]
+        SET result=1
+    )
+)
+
+if "%SVN_BRANCH%" GTR "1.9." (
+
+    python win-tests.py -d -f fsfs --swig=perl "%TESTDIR%\tests"
+
+    IF ERRORLEVEL 1 (
+        echo [Perl tests exited with error !ERRORLEVEL!]
+        SET result=1
+    )
+
+) ELSE IF "%SVN_BRANCH%" GTR "1.8." (
+
+    mkdir "%TESTDIR%\swig\pl-debug\SVN"
+    mkdir "%TESTDIR%\swig\pl-debug\auto\SVN"
+    xcopy subversion\bindings\swig\perl\native\*.pm "%TESTDIR%\swig\pl-debug\SVN" > nul:
+    pushd debug\subversion\bindings\swig\perl\native
+    for %%i in (*.dll) do (
+        set name=%%i
+        mkdir "%TESTDIR%\swig\pl-debug\auto\SVN\!name:~0,-4!"
+        xcopy "!name:~0,-4!.*" "%TESTDIR%\swig\pl-debug\auto\SVN\!name:~0,-4!" > nul:
+        xcopy /y "_Core.dll" "%TESTDIR%\swig\pl-debug\auto\SVN\!name:~0,-4!" > nul:
+    )
+    popd
+
+
+    SET PERL5LIB=%PERL5LIB%;%TESTDIR%\swig\pl-debug;
+    pushd subversion\bindings\swig\perl\native
+    perl -MExtUtils::Command::MM -e "test_harness()" t\*.t
+    IF ERRORLEVEL 1 (
+        echo [Perl reported error !ERRORLEVEL!]
+        SET result=1
+    )
+    popd
+)
+
+if "%SVN_BRANCH%" GTR "1.9." (
+  python win-tests.py -d -f fsfs --swig=ruby "%TESTDIR%\tests"
+
+  IF ERRORLEVEL 1 (
+    echo [Ruby tests reported error !ERRORLEVEL!] (not fatal)
+    REM SET result=1
+  )
 )
-popd
 
 exit /b %result%

Modified: subversion/branches/cache-server/tools/buildbot/slaves/win32-SharpSvn/svntest-build-bindings.cmd
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/tools/buildbot/slaves/win32-SharpSvn/svntest-build-bindings.cmd?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/tools/buildbot/slaves/win32-SharpSvn/svntest-build-bindings.cmd (original)
+++ subversion/branches/cache-server/tools/buildbot/slaves/win32-SharpSvn/svntest-build-bindings.cmd Tue Oct 15 08:52:06 2013
@@ -23,14 +23,26 @@ SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDE
 CALL ..\svn-config.cmd
 IF ERRORLEVEL 1 EXIT /B 1
 
-svnversion . /1.6.x | find "S" > nul:
-IF ERRORLEVEL 1 (
+IF "%SVN_BRANCH%" LEQ "1.6.x" (
   ECHO --- Building 1.6.x: Skipping bindings ---
   EXIT /B 0
 )
 
-msbuild subversion_vcnet.sln /p:Configuration=Debug /p:Platform=win32 /t:__JAVAHL__ /t:__JAVAHL_TESTS__
+SET DEBUG_TARGETS=/t:__JAVAHL__ /t:__JAVAHL_TESTS__
+SET RELEASE_TARGETS=/t:__SWIG_PYTHON__
+
+if "%SVN_BRANCH%" GTR "1.8." (
+  SET DEBUG_TARGETS=%DEBUG_TARGETS% /t:__SWIG_PERL__
+)
+
+if "%SVN_BRANCH%" GTR "1.9." (
+  SET DEBUG_TARGETS=%DEBUG_TARGETS% /t:__SWIG_RUBY__
+)
+
+msbuild subversion_vcnet.sln /m /p:Configuration=Debug /p:Platform=win32 %DEBUG_TARGETS%
 IF ERRORLEVEL 1 EXIT /B 1
 
-msbuild subversion_vcnet.sln /p:Configuration=Release /p:Platform=win32 /t:__SWIG_PYTHON__ /t:__SWIG_PERL__
+msbuild subversion_vcnet.sln /p:Configuration=Release /p:Platform=win32 %RELEASE_TARGETS%
 IF ERRORLEVEL 1 EXIT /B 1
+
+EXIT /B 0
\ No newline at end of file

Modified: subversion/branches/cache-server/tools/buildbot/slaves/win32-SharpSvn/svntest-cleanup.cmd
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/tools/buildbot/slaves/win32-SharpSvn/svntest-cleanup.cmd?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/tools/buildbot/slaves/win32-SharpSvn/svntest-cleanup.cmd (original)
+++ subversion/branches/cache-server/tools/buildbot/slaves/win32-SharpSvn/svntest-cleanup.cmd Tue Oct 15 08:52:06 2013
@@ -59,6 +59,7 @@ taskkill /im svnsync.exe /f 2> nul:
 taskkill /im httpd.exe /f 2> nul:
 taskkill /im fs-test.exe /f 2> nul:
 taskkill /im op-depth-test.exe /f 2> nul:
+taskkill /im atomic-ra-revprop-change.exe /f 2> nul:
 taskkill /im java.exe /f 2> nul:
 taskkill /im perl.exe /f 2> nul:
 taskkill /im mspdbsrv.exe /f 2> nul:

Modified: subversion/branches/cache-server/tools/client-side/svn-bench/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/tools/client-side/svn-bench/cl.h?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/tools/client-side/svn-bench/cl.h (original)
+++ subversion/branches/cache-server/tools/client-side/svn-bench/cl.h Tue Oct 15 08:52:06 2013
@@ -90,6 +90,7 @@ typedef struct svn_cl__opt_state_t
   svn_boolean_t no_revprops;     /* retrieve no revprops */
   apr_hash_t *revprop_table;     /* table of revision properties to get/set */
   svn_boolean_t use_merge_history; /* use/display extra merge information */
+  svn_boolean_t auto_moves;      /* interpret unique DEL/ADD pairs as moves */
   svn_boolean_t trust_server_cert; /* trust server SSL certs that would
                                       otherwise be rejected as "untrusted" */
 } svn_cl__opt_state_t;
@@ -107,7 +108,8 @@ svn_opt_subcommand_t
   svn_cl__help,
   svn_cl__null_export,
   svn_cl__null_list,
-  svn_cl__null_log;
+  svn_cl__null_log,
+  svn_cl__null_info;
 
 
 /* See definition in main.c for documentation. */

Modified: subversion/branches/cache-server/tools/client-side/svn-bench/help-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/tools/client-side/svn-bench/help-cmd.c?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/tools/client-side/svn-bench/help-cmd.c (original)
+++ subversion/branches/cache-server/tools/client-side/svn-bench/help-cmd.c Tue Oct 15 08:52:06 2013
@@ -80,7 +80,7 @@ svn_cl__help(apr_getopt_t *os,
   SVN_ERR(svn_ra_print_modules(version_footer, pool));
 
   return svn_opt_print_help4(os,
-                             "svn",   /* ### erm, derive somehow? */
+                             "svn-bench",   /* ### erm, derive somehow? */
                              opt_state ? opt_state->version : FALSE,
                              opt_state ? opt_state->quiet : FALSE,
                              opt_state ? opt_state->verbose : FALSE,

Modified: subversion/branches/cache-server/tools/client-side/svn-bench/null-log-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/cache-server/tools/client-side/svn-bench/null-log-cmd.c?rev=1532250&r1=1532249&r2=1532250&view=diff
==============================================================================
--- subversion/branches/cache-server/tools/client-side/svn-bench/null-log-cmd.c (original)
+++ subversion/branches/cache-server/tools/client-side/svn-bench/null-log-cmd.c Tue Oct 15 08:52:06 2013
@@ -140,6 +140,9 @@ svn_cl__null_log(apr_getopt_t *os,
   apr_array_header_t *revprops;
   svn_opt_revision_t target_peg_revision;
   const char *target_path_or_url;
+  svn_move_behavior_t move_behavior = opt_state->auto_moves
+                                    ? svn_move_behavior_auto_moves
+                                    : svn_move_behavior_explicit_moves;
 
   SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
                                                       opt_state->targets,
@@ -202,13 +205,14 @@ svn_cl__null_log(apr_getopt_t *os,
   APR_ARRAY_PUSH(revprops, const char *) = SVN_PROP_REVISION_DATE;
   if (!opt_state->quiet)
     APR_ARRAY_PUSH(revprops, const char *) = SVN_PROP_REVISION_LOG;
-  SVN_ERR(svn_client_log5(targets,
+  SVN_ERR(svn_client_log6(targets,
                           &target_peg_revision,
                           opt_state->revision_ranges,
                           opt_state->limit,
                           opt_state->verbose,
                           opt_state->stop_on_copy,
                           opt_state->use_merge_history,
+                          move_behavior,
                           revprops,
                           log_entry_receiver,
                           &lb,