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/11/27 12:52:46 UTC

svn commit: r1546002 [36/39] - in /subversion/branches/verify-keep-going: ./ build/ build/ac-macros/ build/generator/ build/generator/swig/ build/generator/templates/ build/win32/ contrib/client-side/emacs/ contrib/server-side/ contrib/server-side/svnc...

Modified: subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/entries-compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/entries-compat.c?rev=1546002&r1=1546001&r2=1546002&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/entries-compat.c (original)
+++ subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/entries-compat.c Wed Nov 27 11:52:35 2013
@@ -377,7 +377,7 @@ test_entries_alloc(apr_pool_t *pool)
                                        "fake-wc",
                                        WC_NAME,
                                        "D",
-                                       NULL);
+                                       SVN_VA_NULL);
   SVN_ERR(svn_wc_entry(&entry, local_relpath, adm_access, TRUE, pool));
   SVN_TEST_ASSERT(entry == apr_hash_get(entries, "D", APR_HASH_KEY_STRING));
 
@@ -413,7 +413,7 @@ test_stubs(apr_pool_t *pool)
                                        "fake-wc",
                                        WC_NAME,
                                        "M",
-                                       NULL);
+                                       SVN_VA_NULL);
 
   SVN_ERR(svn_wc_adm_open3(&adm_access,
                            NULL /* associated */,
@@ -638,6 +638,8 @@ test_access_baton_like_locking(apr_pool_
 }
 
 
+int svn_test_max_threads = -1;
+
 struct svn_test_descriptor_t test_funcs[] =
   {
     SVN_TEST_NULL,

Modified: subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/op-depth-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/op-depth-test.c?rev=1546002&r1=1546001&r2=1546002&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/op-depth-test.c (original)
+++ subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/op-depth-test.c Wed Nov 27 11:52:35 2013
@@ -27,7 +27,9 @@
 #include <apr_pools.h>
 #include <apr_general.h>
 
+#include "svn_private_config.h"
 #include "svn_types.h"
+#include "svn_hash.h"
 #include "svn_io.h"
 #include "svn_dirent_uri.h"
 #include "svn_pools.h"
@@ -51,10 +53,6 @@
 
 #include "../svn_test.h"
 
-#ifdef _MSC_VER
-#pragma warning(disable: 4221) /* nonstandard extension used */
-#endif
-
 /* Compare strings, like strcmp but either or both may be NULL which
  * compares equal to NULL and not equal to any non-NULL string. */
 static int
@@ -103,6 +101,14 @@ typedef struct nodes_row_t {
     const char *props;  /* comma-separated list of prop names */
 } nodes_row_t;
 
+/* What conflicts are on a path. */
+typedef struct conflict_info_t {
+    const char *local_relpath;
+    svn_boolean_t text_conflicted;
+    svn_boolean_t prop_conflicted;
+    svn_boolean_t tree_conflicted;
+} conflict_info_t;
+
 /* Macro for filling in the REPO_* fields of a non-base NODES_ROW_T
  * that has no copy-from info. */
 #define NO_COPY_FROM SVN_INVALID_REVNUM, NULL, FALSE
@@ -331,6 +337,146 @@ check_db_rows(svn_test__sandbox_t *b,
 }
 
 
+static const char *
+print_conflict(const conflict_info_t *row,
+               apr_pool_t *result_pool)
+{
+  return apr_psprintf(result_pool, "\"%s\", %s, %s, %s",
+                      row->local_relpath,
+                      row->text_conflicted ? "TRUE" : "FALSE",
+                      row->prop_conflicted ? "TRUE" : "FALSE",
+                      row->tree_conflicted ? "TRUE" : "FALSE");
+}
+
+static svn_error_t *
+compare_conflict_info(const void *key, apr_ssize_t klen,
+                      enum svn_hash_diff_key_status status,
+                      void *baton)
+{
+  comparison_baton_t *b = baton;
+  conflict_info_t *expected = apr_hash_get(b->expected_hash, key, klen);
+  conflict_info_t *found = apr_hash_get(b->found_hash, key, klen);
+
+  if (! expected)
+    {
+      b->errors = svn_error_createf(
+                    SVN_ERR_TEST_FAILED, b->errors,
+                    "found   {%s}",
+                    print_conflict(found, b->scratch_pool));
+    }
+  else if (! found)
+    {
+      b->errors = svn_error_createf(
+                    SVN_ERR_TEST_FAILED, b->errors,
+                    "expected {%s}",
+                    print_conflict(expected, b->scratch_pool));
+    }
+  else if (expected->text_conflicted != found->text_conflicted
+           || expected->prop_conflicted != found->prop_conflicted
+           || expected->tree_conflicted != found->tree_conflicted)
+    {
+      b->errors = svn_error_createf(
+                    SVN_ERR_TEST_FAILED, b->errors,
+                    "expected {%s}; found {%s}",
+                    print_conflict(expected, b->scratch_pool),
+                    print_conflict(found, b->scratch_pool));
+    }
+
+  /* Don't terminate the comparison: accumulate all differences. */
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+check_db_conflicts(svn_test__sandbox_t *b,
+                   const char *root_path,
+                   const conflict_info_t *expected_conflicts)
+{
+  const char *base_relpath = root_path;
+  svn_sqlite__db_t *sdb;
+  int i;
+  svn_sqlite__stmt_t *stmt;
+  static const char *const statements[] = {
+    "SELECT local_relpath"
+    " FROM actual_node "
+    " WHERE conflict_data is NOT NULL "
+    "   AND local_relpath = ?1 OR local_relpath LIKE ?2",
+    NULL };
+#define STMT_SELECT_ACTUAL_INFO 0
+
+  svn_boolean_t have_row;
+  apr_hash_t *found_hash = apr_hash_make(b->pool);
+  apr_hash_t *expected_hash = apr_hash_make(b->pool);
+  apr_pool_t *iterpool = svn_pool_create(b->pool);
+  apr_hash_index_t *hi;
+  comparison_baton_t comparison_baton;
+
+  comparison_baton.expected_hash = expected_hash;
+  comparison_baton.found_hash = found_hash;
+  comparison_baton.scratch_pool = b->pool;
+  comparison_baton.errors = NULL;
+
+  /* Fill ACTUAL_HASH with data from the WC DB. */
+  SVN_ERR(open_wc_db(&sdb, b->wc_abspath, statements, b->pool, b->pool));
+  SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_ACTUAL_INFO));
+  SVN_ERR(svn_sqlite__bindf(stmt, "ss", base_relpath,
+                            (base_relpath[0]
+                             ? apr_psprintf(b->pool, "%s/%%", base_relpath)
+                             : "_%")));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+  while (have_row)
+    {
+      conflict_info_t *row = apr_palloc(b->pool, sizeof(*row));
+
+      row->local_relpath = svn_sqlite__column_text(stmt, 0, b->pool);
+
+      svn_hash_sets(found_hash, row->local_relpath, row);
+
+      SVN_ERR(svn_sqlite__step(&have_row, stmt));
+    }
+  SVN_ERR(svn_sqlite__reset(stmt));
+  SVN_ERR(svn_sqlite__close(sdb));
+
+  for (hi = apr_hash_first(b->pool, found_hash); hi; hi = apr_hash_next(hi))
+    {
+      svn_skel_t *conflict;
+      conflict_info_t *info = svn__apr_hash_index_val(hi);
+      const char *local_abspath;
+
+      svn_pool_clear(iterpool);
+
+      local_abspath = svn_dirent_join(b->wc_abspath, info->local_relpath,
+                                      iterpool);
+
+      SVN_ERR(svn_wc__db_read_conflict(&conflict, b->wc_ctx->db, local_abspath,
+                                       iterpool, iterpool));
+
+      SVN_TEST_ASSERT(conflict != NULL);
+
+      SVN_ERR(svn_wc__conflict_read_info(NULL, NULL,
+                                         &info->text_conflicted,
+                                         &info->prop_conflicted,
+                                         &info->tree_conflicted,
+                                         b->wc_ctx->db, local_abspath,
+                                         conflict,
+                                         iterpool, iterpool));
+    }
+
+  /* Fill EXPECTED_HASH with data from EXPECTED_ROWS. */
+  if (expected_conflicts)
+    for (i = 0; expected_conflicts[i].local_relpath != NULL; i++)
+      {
+        const conflict_info_t *row = &expected_conflicts[i];
+
+        svn_hash_sets(expected_hash, row->local_relpath, row);
+      }
+
+  /* Compare EXPECTED_HASH with ACTUAL_HASH and return any errors. */
+  SVN_ERR(svn_hash_diff(expected_hash, found_hash,
+                        compare_conflict_info, &comparison_baton, b->pool));
+  return comparison_baton.errors;
+}
+
+
 /* ---------------------------------------------------------------------- */
 /* The test functions */
 
@@ -758,7 +904,7 @@ test_adds_change_kind(const svn_test_opt
 {
   svn_test__sandbox_t b;
 
-  SVN_ERR(svn_test__sandbox_create(&b, "adds", opts, pool));
+  SVN_ERR(svn_test__sandbox_create(&b, "test_adds_change_kind", opts, pool));
   SVN_ERR(sbox_add_and_commit_greek_tree(&b));
 
   /* replace dir with file */
@@ -5214,9 +5360,21 @@ update_prop_mod_into_moved(const svn_tes
     SVN_ERR(check_db_rows(&b, "", nodes));
   }
 
+  {
+    conflict_info_t conflicts[] = {
+      { "A", FALSE, FALSE, TRUE },
+      {0}
+    };
+
+    SVN_ERR(check_db_conflicts(&b, "", conflicts));
+  }
+
   /* Resolve should update the move. */
   SVN_ERR(sbox_wc_resolve(&b, "A", svn_depth_empty,
                           svn_wc_conflict_choose_mine_conflict));
+
+  SVN_ERR(check_db_conflicts(&b, "", NULL));
+
   {
     nodes_row_t nodes[] = {
       {0, "",         "normal",       2, ""},
@@ -5299,6 +5457,7 @@ nested_move_update(const svn_test_opts_t
                           svn_wc_conflict_choose_mine_conflict));
   SVN_ERR(sbox_wc_resolve(&b, "A2/B/C", svn_depth_empty,
                           svn_wc_conflict_choose_mine_conflict));
+  SVN_ERR(check_db_conflicts(&b, "", NULL /* no conflicts */));
   {
     nodes_row_t nodes[] = {
       {0, "",          "normal",       2, ""},
@@ -5325,6 +5484,8 @@ nested_move_update(const svn_test_opts_t
 
   /* Update A to r3 brings no changes but updates the revisions. */
   SVN_ERR(sbox_wc_update(&b, "A", 3));
+  SVN_ERR(check_db_conflicts(&b, "", NULL /* no conflicts */));
+
   {
     nodes_row_t nodes[] = {
       {0, "",          "normal",       2, ""},
@@ -5624,7 +5785,9 @@ check_tree_conflict_repos_path(svn_test_
       svn_wc_conflict_version_t *version
         = APR_ARRAY_IDX(locations, 0, svn_wc_conflict_version_t *);
 
-      SVN_ERR_ASSERT(!strcmp(version->path_in_repos, repos_path1));
+      SVN_TEST_ASSERT(version != NULL);
+
+      SVN_TEST_ASSERT(!strcmp(version->path_in_repos, repos_path1));
     }
 
   if (repos_path2)
@@ -5632,7 +5795,9 @@ check_tree_conflict_repos_path(svn_test_
       svn_wc_conflict_version_t *version
         = APR_ARRAY_IDX(locations, 1, svn_wc_conflict_version_t *);
 
-      SVN_ERR_ASSERT(!strcmp(version->path_in_repos, repos_path2));
+      SVN_TEST_ASSERT(version != NULL);
+
+      SVN_TEST_ASSERT(!strcmp(version->path_in_repos, repos_path2));
     }
 
   return SVN_NO_ERROR;
@@ -7084,7 +7249,7 @@ movedto_opdepth(const svn_test_opts_t *o
 {
   svn_test__sandbox_t b;
 
-  SVN_ERR(svn_test__sandbox_create(&b, "moved_to_op_depth",
+  SVN_ERR(svn_test__sandbox_create(&b, "movedto_opdepth",
                                    opts, pool));
 
   SVN_ERR(sbox_wc_mkdir(&b, "A"));
@@ -8206,8 +8371,1091 @@ move_update_parent_replace(const svn_tes
   return SVN_NO_ERROR;
 }
 
-/* ---------------------------------------------------------------------- */
-/* The list of test functions */
+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_delete_intermediate(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+  svn_test__sandbox_t b;
+
+  SVN_ERR(svn_test__sandbox_create(&b, "move_delete_intermediate", 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 delete A */
+  SVN_ERR(sbox_wc_delete(&b, "A"));
+
+  /* AAA_1, AAA_2 and AAA_3 should still be moves after deleting A */
+  {
+    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",          "base-deleted", NO_COPY_FROM},
+      {1, "A/A",        "base-deleted", NO_COPY_FROM},
+      {1, "A/A/A",      "base-deleted", NO_COPY_FROM, "AAA_1"},
+      {1, "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},
+      {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;
+}
+
+static svn_error_t *
+move_revert_intermediate(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+  svn_test__sandbox_t b;
+
+  SVN_ERR(svn_test__sandbox_create(&b, "move_revert_intermediate", 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;
+}
+
+static svn_error_t *
+move_replace_ancestor_with_child(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+    svn_test__sandbox_t b;
+
+    SVN_ERR(svn_test__sandbox_create(&b, "move_replace_ancestor_with_child", opts,
+        pool));
+
+    SVN_ERR(sbox_wc_mkdir(&b, "A"));
+    SVN_ERR(sbox_wc_mkdir(&b, "A/A"));
+
+    SVN_ERR(sbox_wc_commit(&b, ""));
+    SVN_ERR(sbox_wc_update(&b, "", 1));
+
+    SVN_ERR(sbox_wc_move(&b, "A", "A2"));
+
+    {
+      nodes_row_t nodes[] = {
+
+        { 0, "",            "normal",       1, "" },
+
+        { 0, "A",           "normal",       1, "A"},
+        { 0, "A/A",         "normal",       1, "A/A" },
+
+        { 1, "A",           "base-deleted", NO_COPY_FROM , "A2"},
+        { 1, "A/A",         "base-deleted", NO_COPY_FROM },
+
+        { 1, "A2",          "normal",       1, "A",     MOVED_HERE },
+        { 1, "A2/A",        "normal",       1, "A/A",   MOVED_HERE },
+
+        { 0 },
+      };
+      SVN_ERR(check_db_rows(&b, "", nodes));
+    }
+
+    SVN_ERR(sbox_wc_move(&b, "A2/A", "A"));
+
+    {
+      nodes_row_t nodes[] = {
+        { 0, "",            "normal",       1, "" },
+
+        { 0, "A",           "normal",       1, "A"},
+        { 0, "A/A",         "normal",       1, "A/A" },
+
+        { 1, "A",           "normal",       1, "A/A", FALSE, "A2", TRUE },
+        { 1, "A/A",         "base-deleted", NO_COPY_FROM },
+
+        { 1, "A2",          "normal",       1, "A",     MOVED_HERE },
+        { 1, "A2/A",        "normal",       1, "A/A",   MOVED_HERE },
+
+        { 2, "A2/A",        "base-deleted", NO_COPY_FROM, "A" },
+        { 0 },
+      };
+      SVN_ERR(check_db_rows(&b, "", nodes));
+    }
+
+    /* ### This currently fails with an assertion in maintainer mode */
+    SVN_ERR(sbox_wc_delete(&b, "A2"));
+
+    {
+      nodes_row_t nodes[] = {
+        { 0, "",            "normal",       1, "" },
+
+        { 0, "A",           "normal",       1, "A"},
+        { 0, "A/A",         "normal",       1, "A/A" },
+
+        { 1, "A",           "normal",       1, "A/A", MOVED_HERE },
+        { 1, "A/A",         "base-deleted", NO_COPY_FROM, "A" },
+
+        { 0 },
+      };
+      SVN_ERR(check_db_rows(&b, "", nodes));
+    }
+
+    SVN_ERR(sbox_wc_commit(&b, "A"));
+
+    return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_twice_within_delete(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+    svn_test__sandbox_t b;
+
+    SVN_ERR(svn_test__sandbox_create(&b, "move_twice_within_delete", 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_commit(&b, ""));
+    SVN_ERR(sbox_wc_update(&b, "", 1));
+
+    SVN_ERR(sbox_wc_mkdir(&b, "B"));
+    SVN_ERR(sbox_wc_move(&b, "A", "B/A"));
+    SVN_ERR(sbox_wc_move(&b, "B/A/A", "B/AA"));
+    SVN_ERR(sbox_wc_move(&b, "B/AA/A", "AA"));
+
+    {
+      nodes_row_t nodes[] = {
+
+        { 0, "",          "normal",       1, "" },
+                          
+        { 0, "A",         "normal",       1, "A" },
+        { 0, "A/A",       "normal",       1, "A/A" },
+        { 0, "A/A/A",     "normal",       1, "A/A/A" },
+                          
+        { 1, "A",         "base-deleted", NO_COPY_FROM, "B/A" },
+        { 1, "A/A",       "base-deleted", NO_COPY_FROM },
+        { 1, "A/A/A",     "base-deleted", NO_COPY_FROM },
+                          
+        { 1, "AA",        "normal",       1, "A/A/A", MOVED_HERE },
+
+        { 1, "B",         "normal",       NO_COPY_FROM },
+        { 2, "B/A",       "normal",       1, "A",       MOVED_HERE },
+        { 2, "B/A/A",     "normal",       1, "A/A",     MOVED_HERE },
+        { 2, "B/A/A/A",   "normal",       1, "A/A/A",   MOVED_HERE },
+
+        { 3, "B/A/A",     "base-deleted", NO_COPY_FROM, "B/AA" },
+        { 3, "B/A/A/A",   "base-deleted", NO_COPY_FROM },
+
+        { 2, "B/AA",      "normal",       1, "A/A", MOVED_HERE},
+        { 2, "B/AA/A",    "normal",       1, "A/A/A", MOVED_HERE },
+
+        { 3, "B/AA/A",    "base-deleted", NO_COPY_FROM, "AA" },
+
+        { 0 },
+      };
+      SVN_ERR(check_db_rows(&b, "", nodes));
+    }
+
+    SVN_ERR(sbox_wc_delete(&b, "B"));
+
+    {
+      nodes_row_t nodes[] = {
+        { 0, "",        "normal", 1, "" },
+
+        { 0, "A",       "normal", 1, "A" },
+        { 0, "A/A",     "normal", 1, "A/A" },
+        { 0, "A/A/A",   "normal", 1, "A/A/A" },
+
+        { 1, "A",       "base-deleted", NO_COPY_FROM },
+        { 1, "A/A",     "base-deleted", NO_COPY_FROM },
+        { 1, "A/A/A",   "base-deleted", NO_COPY_FROM, "AA" },
+
+        { 1, "AA", "normal", 1, "A/A/A", MOVED_HERE },
+
+        { 0 },
+      };
+        SVN_ERR(check_db_rows(&b, "", nodes));
+    }
+
+    return SVN_NO_ERROR;
+}
+
+/* Helper function for 4 move4 tests */
+static svn_error_t *
+init_move4(svn_test__sandbox_t *sandbox,
+           const char *test_name,
+           const svn_test_opts_t *opts,
+           svn_boolean_t move_away,
+           apr_pool_t *pool)
+{
+  SVN_ERR(svn_test__sandbox_create(sandbox, test_name, opts, pool));
+
+  SVN_ERR(sbox_wc_mkdir(sandbox, "A"));
+  SVN_ERR(sbox_wc_mkdir(sandbox, "A/A"));
+  SVN_ERR(sbox_wc_mkdir(sandbox, "A/A/A"));
+  SVN_ERR(sbox_wc_mkdir(sandbox, "A/A/A/A"));
+
+  SVN_ERR(sbox_wc_mkdir(sandbox, "B"));
+  SVN_ERR(sbox_wc_mkdir(sandbox, "B/A"));
+  SVN_ERR(sbox_wc_mkdir(sandbox, "B/A/A"));
+  SVN_ERR(sbox_wc_mkdir(sandbox, "B/A/A/A"));
+
+  SVN_ERR(sbox_wc_mkdir(sandbox, "C"));
+  SVN_ERR(sbox_wc_mkdir(sandbox, "C/A"));
+  SVN_ERR(sbox_wc_mkdir(sandbox, "C/A/A"));
+  SVN_ERR(sbox_wc_mkdir(sandbox, "C/A/A/A"));
+
+  SVN_ERR(sbox_wc_mkdir(sandbox, "D"));
+  SVN_ERR(sbox_wc_mkdir(sandbox, "D/A"));
+  SVN_ERR(sbox_wc_mkdir(sandbox, "D/A/A"));
+  SVN_ERR(sbox_wc_mkdir(sandbox, "D/A/A/A"));
+
+  SVN_ERR(sbox_wc_commit(sandbox, "")); /* r1 */
+
+  if (strstr(test_name, "_edit_"))
+    {
+      SVN_ERR(sbox_wc_propset(sandbox, "key", "value", "A/A/A"));
+      SVN_ERR(sbox_wc_propset(sandbox, "key", "value", "B/A/A"));
+      SVN_ERR(sbox_wc_propset(sandbox, "key", "value", "C/A/A"));
+      SVN_ERR(sbox_wc_propset(sandbox, "key", "value", "D/A/A"));
+      SVN_ERR(sbox_wc_propset(sandbox, "key", "value", "A/A/A/A"));
+      SVN_ERR(sbox_wc_propset(sandbox, "key", "value", "B/A/A/A"));
+      SVN_ERR(sbox_wc_propset(sandbox, "key", "value", "C/A/A/A"));
+      SVN_ERR(sbox_wc_propset(sandbox, "key", "value", "D/A/A/A"));
+    }
+  else if (strstr(test_name, "_delete_"))
+    {
+      SVN_ERR(sbox_wc_delete(sandbox, "A/A/A/A"));
+      SVN_ERR(sbox_wc_delete(sandbox, "B/A/A/A"));
+      SVN_ERR(sbox_wc_delete(sandbox, "C/A/A/A"));
+      SVN_ERR(sbox_wc_delete(sandbox, "D/A/A/A"));
+    }
+  else if (strstr(test_name, "_add_"))
+    {
+      SVN_ERR(sbox_wc_mkdir(sandbox, "A/A/A/NEW"));
+      SVN_ERR(sbox_wc_mkdir(sandbox, "B/A/A/NEW"));
+      SVN_ERR(sbox_wc_mkdir(sandbox, "C/A/A/NEW"));
+      SVN_ERR(sbox_wc_mkdir(sandbox, "D/A/A/NEW"));
+    }
+  else if (strstr(test_name, "_delself_"))
+    {
+      SVN_ERR(sbox_wc_delete(sandbox, "A/A/A"));
+      SVN_ERR(sbox_wc_delete(sandbox, "B/A/A"));
+      SVN_ERR(sbox_wc_delete(sandbox, "C/A/A"));
+      SVN_ERR(sbox_wc_delete(sandbox, "D/A/A"));
+    }
+
+  SVN_ERR(sbox_wc_commit(sandbox, ""));
+  SVN_ERR(sbox_wc_update(sandbox, "", 1));
+
+  SVN_ERR(sbox_wc_move(sandbox, "A/A/A", "AAA_1"));
+
+  if (move_away)
+    SVN_ERR(sbox_wc_move(sandbox, "A", "A_moved"));
+  else
+    SVN_ERR(sbox_wc_delete(sandbox, "A"));
+
+  SVN_ERR(sbox_wc_move(sandbox, "B", "A"));
+
+  SVN_ERR(sbox_wc_move(sandbox, "A/A/A", "AAA_2"));
+
+  if (move_away)
+    SVN_ERR(sbox_wc_move(sandbox, "A/A", "BA_moved"));
+  else
+    SVN_ERR(sbox_wc_delete(sandbox, "A/A"));
+
+  SVN_ERR(sbox_wc_move(sandbox, "C/A", "A/A"));
+
+  SVN_ERR(sbox_wc_move(sandbox, "A/A/A", "AAA_3"));
+
+  SVN_ERR(sbox_wc_move(sandbox, "D/A/A", "A/A/A"));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+del4_update_edit_AAA(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+  svn_test__sandbox_t b;
+
+  SVN_ERR(init_move4(&b, "del4_update_edit_AAA", opts, FALSE, pool));
+
+  /* Update and resolve via mine strategy */
+  SVN_ERR(sbox_wc_update(&b, "", 2));
+  SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity, svn_wc_conflict_choose_mine_conflict));
+  /* Go back to start position */
+  SVN_ERR(sbox_wc_update(&b, "", 1));
+  SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity, svn_wc_conflict_choose_mine_conflict));
+  /* Update and resolve via their strategy */
+  SVN_ERR(sbox_wc_update(&b, "", 2));
+  SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity, svn_wc_conflict_choose_merged));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+del4_update_delete_AAA(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+  svn_test__sandbox_t b;
+
+  SVN_ERR(init_move4(&b, "del4_update_delete_AAA", opts, FALSE, pool));
+
+  /* Update and resolve via mine strategy */
+  SVN_ERR(sbox_wc_update(&b, "", 2));
+  SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity, svn_wc_conflict_choose_mine_conflict));
+  /* Go back to start position */
+  SVN_ERR(sbox_wc_update(&b, "", 1));
+  SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity, svn_wc_conflict_choose_mine_conflict));
+  /* Update and resolve via their strategy */
+  SVN_ERR(sbox_wc_update(&b, "", 2));
+  SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity, svn_wc_conflict_choose_merged));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+del4_update_add_AAA(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+  svn_test__sandbox_t b;
+
+  SVN_ERR(init_move4(&b, "del4_update_add_AAA", opts, FALSE, pool));
+
+  /* Update and resolve via mine strategy */
+  SVN_ERR(sbox_wc_update(&b, "", 2));
+  SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity, svn_wc_conflict_choose_mine_conflict));
+  /* Go back to start position */
+  SVN_ERR(sbox_wc_update(&b, "", 1));
+  SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity, svn_wc_conflict_choose_mine_conflict));
+  /* Update and resolve via their strategy */
+  SVN_ERR(sbox_wc_update(&b, "", 2));
+  SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity, svn_wc_conflict_choose_merged));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+del4_update_delself_AAA(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+  svn_test__sandbox_t b;
+
+  SVN_ERR(init_move4(&b, "del4_update_delself_AAA", opts, FALSE, pool));
+
+  /* Update and resolve via mine strategy */
+  SVN_ERR(sbox_wc_update(&b, "", 2));
+
+  /* Resolve a few conflicts manually */
+  SVN_ERR(sbox_wc_resolve(&b, "A", svn_depth_empty,
+                          svn_wc_conflict_choose_mine_conflict));
+  SVN_ERR(sbox_wc_resolve(&b, "B", svn_depth_empty,
+                          svn_wc_conflict_choose_mine_conflict));
+  SVN_ERR(sbox_wc_resolve(&b, "C/A", svn_depth_empty,
+                          svn_wc_conflict_choose_mine_conflict));
+
+  /* ### These can currently only be resolved to merged ???? */
+  SVN_ERR(sbox_wc_resolve(&b, "D/A/A", svn_depth_empty,
+                          svn_wc_conflict_choose_merged));
+  SVN_ERR(sbox_wc_resolve(&b, "A/A/A", svn_depth_empty,
+                          svn_wc_conflict_choose_merged));
+
+  SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity, svn_wc_conflict_choose_mine_conflict));
+  /* Go back to start position */
+  SVN_ERR(sbox_wc_update(&b, "", 1));
+  SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity, svn_wc_conflict_choose_mine_conflict));
+  /* Update and resolve via their strategy */
+  SVN_ERR(sbox_wc_update(&b, "", 2));
+  SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity, svn_wc_conflict_choose_merged));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move4_update_edit_AAA(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+    svn_test__sandbox_t b;
+
+    SVN_ERR(init_move4(&b, "move4_update_edit_AAA", opts, TRUE, pool));
+
+    /* Update and resolve via mine strategy */
+    SVN_ERR(sbox_wc_update(&b, "", 2));
+    SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity, svn_wc_conflict_choose_mine_conflict));
+    /* Go back to start position */
+    SVN_ERR(sbox_wc_update(&b, "", 1));
+    SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity, svn_wc_conflict_choose_mine_conflict));
+    /* Update and resolve via their strategy */
+    SVN_ERR(sbox_wc_update(&b, "", 2));
+    SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity, svn_wc_conflict_choose_merged));
+
+    return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move4_update_delete_AAA(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+    svn_test__sandbox_t b;
+
+    SVN_ERR(init_move4(&b, "move4_update_delete_AAA", opts, TRUE, pool));
+
+    /* Update and resolve via mine strategy */
+    SVN_ERR(sbox_wc_update(&b, "", 2));
+    SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity, svn_wc_conflict_choose_mine_conflict));
+    /* Go back to start position */
+    SVN_ERR(sbox_wc_update(&b, "", 1));
+    SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity, svn_wc_conflict_choose_mine_conflict));
+    /* Update and resolve via their strategy */
+    SVN_ERR(sbox_wc_update(&b, "", 2));
+    SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity, svn_wc_conflict_choose_merged));
+
+    return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move4_update_add_AAA(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+    svn_test__sandbox_t b;
+
+    SVN_ERR(init_move4(&b, "move4_update_add_AAA", opts, TRUE, pool));
+
+    /* Update and resolve via mine strategy */
+    SVN_ERR(sbox_wc_update(&b, "", 2));
+    SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity, svn_wc_conflict_choose_mine_conflict));
+    /* Go back to start position */
+    SVN_ERR(sbox_wc_update(&b, "", 1));
+    SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity, svn_wc_conflict_choose_mine_conflict));
+    /* Update and resolve via their strategy */
+    SVN_ERR(sbox_wc_update(&b, "", 2));
+    SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity, svn_wc_conflict_choose_merged));
+
+    return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move4_update_delself_AAA(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+    svn_test__sandbox_t b;
+
+    SVN_ERR(init_move4(&b, "move4_update_delself_AAA", opts, TRUE, pool));
+
+    /* Update and resolve via mine strategy */
+    SVN_ERR(sbox_wc_update(&b, "", 2));
+
+    /* Resolve a few conflicts manually */
+    SVN_ERR(sbox_wc_resolve(&b, "A", svn_depth_empty,
+        svn_wc_conflict_choose_mine_conflict));
+    SVN_ERR(sbox_wc_resolve(&b, "B", svn_depth_empty,
+        svn_wc_conflict_choose_mine_conflict));
+    SVN_ERR(sbox_wc_resolve(&b, "C/A", svn_depth_empty,
+        svn_wc_conflict_choose_mine_conflict));
+
+    /* ### These can currently only be resolved to merged ???? */
+    SVN_ERR(sbox_wc_resolve(&b, "D/A/A", svn_depth_empty,
+                            svn_wc_conflict_choose_merged));
+    SVN_ERR(sbox_wc_resolve(&b, "A/A/A", svn_depth_empty,
+                            svn_wc_conflict_choose_merged));
+    SVN_ERR(sbox_wc_resolve(&b, "A_moved/A/A", svn_depth_empty,
+                            svn_wc_conflict_choose_merged));
+    /*SVN_ERR(check_db_conflicts(&b, "", NULL));*/
+    SVN_ERR(sbox_wc_resolve(&b, "A/A", svn_depth_empty,
+                            svn_wc_conflict_choose_mine_conflict));
+    SVN_ERR(sbox_wc_resolve(&b, "BA_moved/A", svn_depth_empty,
+                            svn_wc_conflict_choose_merged));
+    SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity, svn_wc_conflict_choose_mine_conflict));
+    /* Go back to start position */
+    SVN_ERR(sbox_wc_update(&b, "", 1));
+    SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity, svn_wc_conflict_choose_mine_conflict));
+    /* Update and resolve via their strategy */
+    SVN_ERR(sbox_wc_update(&b, "", 2));
+    SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity, svn_wc_conflict_choose_merged));
+
+    return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+simple_move_bump(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+  svn_test__sandbox_t b;
+
+  SVN_ERR(svn_test__sandbox_create(&b, "simple_move_bump", opts, pool));
+
+  SVN_ERR(sbox_wc_mkdir(&b, "A"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+
+  SVN_ERR(sbox_wc_propset(&b, "old_A", "val", "A"));
+  SVN_ERR(sbox_wc_propset(&b, "old_B", "val", "A/B"));
+
+  SVN_ERR(sbox_wc_commit(&b, ""));
+
+  SVN_ERR(sbox_wc_propset(&b, "new_A", "val", "A"));
+  SVN_ERR(sbox_wc_propset(&b, "new_B", "val", "A/B"));
+
+  SVN_ERR(sbox_wc_commit(&b, ""));
+
+  SVN_ERR(sbox_wc_update(&b, "", 1));
+
+  SVN_ERR(sbox_wc_move(&b, "A/B", "A/B_mv"));
+  SVN_ERR(sbox_wc_move(&b, "A", "A_mv"));
+
+  {
+    nodes_row_t nodes[] = {
+
+      { 0, "",          "normal",       1, ""},
+      { 0, "A",         "normal",       1, "A", NOT_MOVED, "old_A"},
+      { 0, "A/B",       "normal",       1, "A/B", NOT_MOVED, "old_B"},
+
+      { 1, "A",         "base-deleted", NO_COPY_FROM, "A_mv"},
+      { 1, "A/B",       "base-deleted", NO_COPY_FROM},
+
+      { 1, "A_mv",      "normal",       1, "A", MOVED_HERE, "old_A" },
+      { 1, "A_mv/B",    "normal",       1, "A/B", MOVED_HERE, "old_B" },
+
+      { 2, "A_mv/B",    "base-deleted", NO_COPY_FROM, "A_mv/B_mv" },
+      { 2, "A_mv/B_mv", "normal",       1, "A/B", FALSE, NULL, TRUE, "old_B" },
+
+      { 0 },
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+  }
+
+  SVN_ERR(sbox_wc_update(&b, "", 2));
+
+  /* Expect the A tree to be updated */
+  {
+    nodes_row_t nodes[] = {
+
+      { 0, "",          "normal",       2, ""},
+      { 0, "A",         "normal",       2, "A", NOT_MOVED, "new_A,old_A"},
+      { 0, "A/B",       "normal",       2, "A/B", NOT_MOVED, "new_B,old_B"},
+
+      { 1, "A",         "base-deleted", NO_COPY_FROM, "A_mv"},
+      { 1, "A/B",       "base-deleted", NO_COPY_FROM},
+
+      { 1, "A_mv",      "normal",       1, "A", MOVED_HERE, "old_A" },
+      { 1, "A_mv/B",    "normal",       1, "A/B", MOVED_HERE, "old_B" },
+
+      { 2, "A_mv/B",    "base-deleted", NO_COPY_FROM, "A_mv/B_mv" },
+      { 2, "A_mv/B_mv", "normal",       1, "A/B", FALSE, NULL, TRUE, "old_B" },
+
+      { 0 },
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+  }
+
+  SVN_ERR(sbox_wc_resolve(&b, "A", svn_depth_empty,
+                          svn_wc_conflict_choose_mine_conflict));
+
+  {
+    nodes_row_t nodes[] = {
+
+      { 0, "",          "normal",       2, ""},
+      { 0, "A",         "normal",       2, "A", NOT_MOVED, "new_A,old_A"},
+      { 0, "A/B",       "normal",       2, "A/B", NOT_MOVED, "new_B,old_B"},
+
+      { 1, "A",         "base-deleted", NO_COPY_FROM, "A_mv"},
+      { 1, "A/B",       "base-deleted", NO_COPY_FROM},
+
+      { 1, "A_mv",      "normal",       2, "A", MOVED_HERE, "new_A,old_A" },
+      { 1, "A_mv/B",    "normal",       2, "A/B", MOVED_HERE, "new_B,old_B" },
+
+      { 2, "A_mv/B",    "base-deleted", NO_COPY_FROM, "A_mv/B_mv" },
+      { 2, "A_mv/B_mv", "normal",       1, "A/B", FALSE, NULL, TRUE, "old_B" },
+
+      { 0 },
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+  }
+
+  SVN_ERR(sbox_wc_resolve(&b, "A_mv/B", svn_depth_empty,
+                          svn_wc_conflict_choose_mine_conflict));
+
+  {
+    nodes_row_t nodes[] = {
+
+      { 0, "",          "normal",       2, ""},
+      { 0, "A",         "normal",       2, "A", NOT_MOVED, "new_A,old_A"},
+      { 0, "A/B",       "normal",       2, "A/B", NOT_MOVED, "new_B,old_B"},
+
+      { 1, "A",         "base-deleted", NO_COPY_FROM, "A_mv"},
+      { 1, "A/B",       "base-deleted", NO_COPY_FROM},
+
+      { 1, "A_mv",      "normal",       2, "A", MOVED_HERE, "new_A,old_A" },
+      { 1, "A_mv/B",    "normal",       2, "A/B", MOVED_HERE, "new_B,old_B" },
+
+      { 2, "A_mv/B",    "base-deleted", NO_COPY_FROM, "A_mv/B_mv" },
+      { 2, "A_mv/B_mv", "normal",       2, "A/B", FALSE, NULL, TRUE, "new_B,old_B" },
+
+      { 0 },
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+  }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+movedhere_extract_retract(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+  svn_test__sandbox_t b;
+
+  SVN_ERR(svn_test__sandbox_create(&b, "movedhere_extract_retract",
+                                   opts, pool));
+
+  SVN_ERR(sbox_wc_mkdir(&b, "A"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/B1"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/B2"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/B3"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/C1"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/C2"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/C3"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/D1"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/D2"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/D3"));
+
+  SVN_ERR(sbox_wc_commit(&b, ""));
+
+  SVN_ERR(sbox_wc_propset(&b, "k", "v", "A/B1"));
+  SVN_ERR(sbox_wc_propset(&b, "k", "v", "A/B2"));
+  SVN_ERR(sbox_wc_propset(&b, "k", "v", "A/B3"));
+  SVN_ERR(sbox_wc_delete(&b, "A/C1"));
+  SVN_ERR(sbox_wc_delete(&b, "A/C2"));
+  SVN_ERR(sbox_wc_delete(&b, "A/C3"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/E1"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/E2"));
+  SVN_ERR(sbox_wc_mkdir(&b, "A/E3"));
+
+  SVN_ERR(sbox_wc_commit(&b, ""));
+
+  SVN_ERR(sbox_wc_update(&b, "", 1));
+
+  SVN_ERR(sbox_wc_move(&b, "A", "Z"));
+
+  SVN_ERR(sbox_wc_delete(&b, "Z/B1"));
+  SVN_ERR(sbox_wc_delete(&b, "Z/C1"));
+  SVN_ERR(sbox_wc_delete(&b, "Z/D1"));
+
+  SVN_ERR(sbox_wc_move(&b, "Z/B2", "B2"));
+  SVN_ERR(sbox_wc_move(&b, "Z/C2", "C2"));
+  SVN_ERR(sbox_wc_move(&b, "Z/D2", "D2"));
+
+  SVN_ERR(sbox_wc_mkdir(&b, "Z/B2"));
+  SVN_ERR(sbox_wc_mkdir(&b, "Z/C2"));
+  SVN_ERR(sbox_wc_mkdir(&b, "Z/D2"));
+  SVN_ERR(sbox_wc_mkdir(&b, "Z/E2"));
+
+  SVN_ERR(sbox_wc_update(&b, "", 2));
+  SVN_ERR(sbox_wc_resolve(&b, "A", svn_depth_empty,
+                          svn_wc_conflict_choose_mine_conflict));
+  SVN_ERR(sbox_wc_resolve(&b, "Z/B1", svn_depth_empty,
+                          svn_wc_conflict_choose_mine_conflict));
+  SVN_ERR(sbox_wc_resolve(&b, "Z/B2", svn_depth_empty,
+                          svn_wc_conflict_choose_mine_conflict));
+
+  SVN_ERR(sbox_wc_resolve(&b, "Z/C1", svn_depth_empty,
+                          svn_wc_conflict_choose_merged));
+  SVN_ERR(sbox_wc_resolve(&b, "Z/C2", svn_depth_empty,
+                          svn_wc_conflict_choose_merged));
+
+  SVN_ERR(sbox_wc_resolve(&b, "", svn_depth_infinity,
+                          svn_wc_conflict_choose_mine_conflict));
+  {
+    nodes_row_t nodes[] = {
+
+      {0, "",       "normal",       2, ""},
+      {0, "A",      "normal",       2, "A"},
+      {0, "A/B1",   "normal",       2, "A/B1", FALSE, NULL, FALSE, "k"},
+      {0, "A/B2",   "normal",       2, "A/B2", FALSE, NULL, FALSE, "k"},
+      {0, "A/B3",   "normal",       2, "A/B3", FALSE, NULL, FALSE, "k"},
+      {0, "A/D1",   "normal",       2, "A/D1"},
+      {0, "A/D2",   "normal",       2, "A/D2"},
+      {0, "A/D3",   "normal",       2, "A/D3"},
+      {0, "A/E1",   "normal",       2, "A/E1"},
+      {0, "A/E2",   "normal",       2, "A/E2"},
+      {0, "A/E3",   "normal",       2, "A/E3"},
+
+      {1, "A",      "base-deleted", NO_COPY_FROM, "Z"},
+      {1, "A/B1",   "base-deleted", NO_COPY_FROM},
+      {1, "A/B2",   "base-deleted", NO_COPY_FROM},
+      {1, "A/B3",   "base-deleted", NO_COPY_FROM},
+
+      {1, "A/D1",   "base-deleted", NO_COPY_FROM},
+      {1, "A/D2",   "base-deleted", NO_COPY_FROM},
+      {1, "A/D3",   "base-deleted", NO_COPY_FROM},
+
+      {1, "A/E1",   "base-deleted", NO_COPY_FROM},
+      {1, "A/E2",   "base-deleted", NO_COPY_FROM},
+      {1, "A/E3",   "base-deleted", NO_COPY_FROM},
+
+      {1, "B2",     "normal",       2, "A/B2", MOVED_HERE, "k"},
+      {1, "C2",     "normal",       1, "A/C2"},
+      {1, "D2",     "normal",       1, "A/D2", MOVED_HERE},
+
+      {1, "Z",      "normal",       2, "A", MOVED_HERE},
+      {1, "Z/B1",   "normal",       2, "A/B1", MOVED_HERE, "k"},
+      {1, "Z/B2",   "normal",       2, "A/B2", MOVED_HERE, "k"},
+      {1, "Z/B3",   "normal",       2, "A/B3", MOVED_HERE, "k"},
+      {1, "Z/D1",   "normal",       2, "A/D1", MOVED_HERE},
+      {1, "Z/D2",   "normal",       2, "A/D2", MOVED_HERE},
+      {1, "Z/D3",   "normal",       2, "A/D3", MOVED_HERE},
+      {1, "Z/E1",   "normal",       2, "A/E1", MOVED_HERE},
+      {1, "Z/E2",   "normal",       2, "A/E2", MOVED_HERE},
+      {1, "Z/E3",   "normal",       2, "A/E3", MOVED_HERE},
+
+      {2, "Z/B2",   "normal",       NO_COPY_FROM, "B2"},
+      {2, "Z/C2",   "normal",       NO_COPY_FROM},
+      {2, "Z/D2",   "normal",       NO_COPY_FROM, "D2"},
+      {2, "Z/E2",   "normal",       NO_COPY_FROM},
+
+      {2, "Z/B1",   "base-deleted", NO_COPY_FROM},
+      {2, "Z/D1",   "base-deleted", NO_COPY_FROM},
+
+      { 0 },
+    };
+    SVN_ERR(check_db_rows(&b, "", nodes));
+  }
+
+  return SVN_NO_ERROR;
+}
+
+
+/* ---------------------------------------------------------------------- */
+/* The list of test functions */
+
+int svn_test_max_threads = 2;
 
 struct svn_test_descriptor_t test_funcs[] =
   {
@@ -8361,5 +9609,37 @@ struct svn_test_descriptor_t test_funcs[
                        "update with tree conflict (issue 4347)"),
     SVN_TEST_OPTS_PASS(move_update_parent_replace,
                        "move update with replaced parent (issue 4388)"),
+    SVN_TEST_OPTS_PASS(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_PASS(move_delete_intermediate,
+                       "move more than once, delete intermediate"),
+    SVN_TEST_OPTS_XFAIL(move_revert_intermediate,
+                       "move more than once, revert intermediate"),
+    SVN_TEST_OPTS_PASS(move_replace_ancestor_with_child,
+                       "move replace ancestor with child"),
+    SVN_TEST_OPTS_PASS(move_twice_within_delete,
+                       "move twice and then delete"),
+    SVN_TEST_OPTS_PASS(del4_update_edit_AAA,
+                       "del4: edit AAA"),
+    SVN_TEST_OPTS_PASS(del4_update_delete_AAA,
+                       "del4: delete AAA"),
+    SVN_TEST_OPTS_PASS(del4_update_add_AAA,
+                       "del4: add AAA"),
+    SVN_TEST_OPTS_PASS(del4_update_delself_AAA,
+                       "del4: delete self AAA"),
+    SVN_TEST_OPTS_PASS(move4_update_edit_AAA,
+                       "move4: edit AAA"),
+    SVN_TEST_OPTS_PASS(move4_update_delete_AAA,
+                       "move4: delete AAA"),
+    SVN_TEST_OPTS_PASS(move4_update_add_AAA,
+                       "move4: add AAA"),
+    SVN_TEST_OPTS_XFAIL(move4_update_delself_AAA,
+                       "move4: delete self AAA"),
+    SVN_TEST_OPTS_PASS(simple_move_bump,
+                       "simple move bump"),
+    SVN_TEST_OPTS_PASS(movedhere_extract_retract,
+                       "movedhere extract retract"),
     SVN_TEST_NULL
   };

Modified: subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/pristine-store-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/pristine-store-test.c?rev=1546002&r1=1546001&r2=1546002&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/pristine-store-test.c (original)
+++ subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/pristine-store-test.c Wed Nov 27 11:52:35 2013
@@ -319,6 +319,8 @@ reject_mismatching_text(const svn_test_o
 }
 
 
+int svn_test_max_threads = -1;
+
 struct svn_test_descriptor_t test_funcs[] =
   {
     SVN_TEST_NULL,

Modified: subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/utils.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/utils.c?rev=1546002&r1=1546001&r2=1546002&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/utils.c (original)
+++ subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/utils.c Wed Nov 27 11:52:35 2013
@@ -326,8 +326,15 @@ sbox_wc_update_depth(svn_test__sandbox_t
                                              sizeof(const char *));
   svn_opt_revision_t revision;
 
-  revision.kind = svn_opt_revision_number;
-  revision.value.number = revnum;
+  if (SVN_IS_VALID_REVNUM(revnum))
+    {
+      revision.kind = svn_opt_revision_number;
+      revision.value.number = revnum;
+    }
+  else
+    {
+      revision.kind = svn_opt_revision_head;
+    }
 
   APR_ARRAY_PUSH(paths, const char *) = sbox_wc_path(b, path);
   SVN_ERR(svn_client_create_context2(&ctx, NULL, b->pool));
@@ -354,7 +361,7 @@ sbox_wc_switch(svn_test__sandbox_t *b,
   svn_revnum_t result_rev;
   svn_opt_revision_t head_rev = { svn_opt_revision_head, {0} };
 
-  url = apr_pstrcat(b->pool, b->repos_url, url, (char*)NULL);
+  url = apr_pstrcat(b->pool, b->repos_url, url, SVN_VA_NULL);
   SVN_ERR(svn_client_create_context2(&ctx, NULL, b->pool));
   ctx->wc_ctx = b->wc_ctx;
   return svn_client_switch3(&result_rev, sbox_wc_path(b, path), url,

Modified: subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/wc-lock-tester.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/wc-lock-tester.c?rev=1546002&r1=1546001&r2=1546002&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/wc-lock-tester.c (original)
+++ subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/wc-lock-tester.c Wed Nov 27 11:52:35 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/verify-keep-going/subversion/tests/libsvn_wc/wc-queries-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/wc-queries-test.c?rev=1546002&r1=1546001&r2=1546002&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/wc-queries-test.c (original)
+++ subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/wc-queries-test.c Wed Nov 27 11:52:35 2013
@@ -22,6 +22,7 @@
  */
 
 #include "svn_pools.h"
+#include "svn_hash.h"
 #include "svn_ctype.h"
 #include "private/svn_dep_compat.h"
 
@@ -30,22 +31,17 @@
 #include "../svn_test.h"
 
 #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>
+/* Import the sqlite3 API vtable from sqlite3wrapper.c */
+#  define SQLITE_OMIT_DEPRECATED
+#  include <sqlite3ext.h>
+extern const sqlite3_api_routines *const svn_sqlite3__api_funcs;
+extern int (*const svn_sqlite3__api_initialize)(void);
+extern int (*const svn_sqlite3__api_config)(int, ...);
+#  define sqlite3_api svn_sqlite3__api_funcs
+#  define sqlite3_initialize svn_sqlite3__api_initialize
+#  define sqlite3_config svn_sqlite3__api_config
 #else
-  #include <sqlite3.h>
+#  include <sqlite3.h>
 #endif
 
 #include "../../libsvn_wc/wc-queries.h"
@@ -77,6 +73,7 @@ static const int schema_statements[] =
   STMT_CREATE_NODES,
   STMT_CREATE_NODES_TRIGGERS,
   STMT_CREATE_EXTERNALS,
+  STMT_INSTALL_SCHEMA_STATISTICS,
   /* Memory tables */
   STMT_CREATE_TARGETS_LIST,
   STMT_CREATE_CHANGELIST_LIST,
@@ -95,8 +92,8 @@ static const int slow_statements[] =
   /* Operate on the entire WC */
   STMT_SELECT_ALL_NODES,                /* schema validation code */
 
-  /* Is there a record? ### Can we somehow check for LIMIT 1? */
-  STMT_LOOK_FOR_WORK,
+  /* Updates all records for a repository (designed slow) */
+  STMT_UPDATE_LOCK_REPOS_ID,
 
   /* Full temporary table read */
   STMT_INSERT_ACTUAL_EMPTIES,
@@ -114,6 +111,19 @@ static const int slow_statements[] =
   -1 /* final marker */
 };
 
+/* Statements that just read the first record from a table,
+   using the primary key. Specialized as different sqlite
+   versions produce different results */
+static const int primary_key_statements[] =
+{
+  /* Is there a record? ### Can we somehow check for LIMIT 1,
+     and primary key instead of adding a list? */
+  STMT_LOOK_FOR_WORK,
+  STMT_SELECT_WORK_ITEM,
+
+  -1 /* final marker */
+};
+
 /* Helper function to determine if a statement is in a list */
 static svn_boolean_t
 in_list(const int list[], int stmt_idx)
@@ -162,15 +172,15 @@ create_memory_db(sqlite3 **db,
 static svn_error_t *
 test_sqlite_version(apr_pool_t *scratch_pool)
 {
-  printf("DBG: Using Sqlite %s\n", sqlite3_version);
+  printf("DBG: Using Sqlite %s\n", sqlite3_libversion());
 
   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,
             "Compiled against Sqlite %s (at runtime we have Sqlite %s)",
-            SQLITE_VERSION, sqlite3_version);
+            SQLITE_VERSION, sqlite3_libversion());
 
 #if !SQLITE_VERSION_AT_LEAST(3, 7, 9)
   return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
@@ -529,6 +539,7 @@ is_node_table(const char *table_name)
   return (apr_strnatcasecmp(table_name, "nodes") == 0
           || apr_strnatcasecmp(table_name, "actual_node") == 0
           || apr_strnatcasecmp(table_name, "externals") == 0
+          || apr_strnatcasecmp(table_name, "lock") == 0
           || apr_strnatcasecmp(table_name, "wc_lock") == 0
           || FALSE);
 }
@@ -590,7 +601,7 @@ test_query_expectations(apr_pool_t *scra
                              apr_pstrcat(iterpool,
                                          "EXPLAIN QUERY PLAN ",
                                          wc_queries[i],
-                                         NULL),
+                                         SVN_VA_NULL),
                              -1, &stmt, &tail);
 
       if (r != SQLITE_OK)
@@ -651,14 +662,24 @@ test_query_expectations(apr_pool_t *scra
                        || (item->expression_vars < 1))
                    && !is_result_table(item->table))
             {
-              warned = TRUE;
-              if (!is_slow_statement(i))
-                warnings = svn_error_createf(SVN_ERR_TEST_FAILED, warnings,
+              if (in_list(primary_key_statements, i))
+                {
+                  /* Reported as primary key index usage in Sqlite 3.7,
+                     as table scan in 3.8+, while the execution plan is
+                     identical: read first record from table */
+                }
+              else if (!is_slow_statement(i))
+                {
+                  warned = TRUE;
+                  warnings = svn_error_createf(SVN_ERR_TEST_FAILED, warnings,
                                 "%s: "
                                 "Uses %s with only %d index component: (%s)\n%s",
                                 wc_query_info[i][0], item->table,
                                 item->expression_vars, item->expressions,
                                 wc_queries[i]);
+                }
+              else
+                warned = TRUE;
             }
           else if (item->search && !item->index)
             {
@@ -718,6 +739,245 @@ test_query_expectations(apr_pool_t *scra
   return warnings;
 }
 
+static svn_error_t *
+test_query_duplicates(apr_pool_t *scratch_pool)
+{
+  sqlite3 *sdb;
+  int i;
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+  svn_error_t *warnings = NULL;
+  svn_boolean_t supports_query_info;
+  apr_hash_t *sha_to_query = apr_hash_make(scratch_pool);
+
+  SVN_ERR(create_memory_db(&sdb, scratch_pool));
+
+  SVN_ERR(supported_explain_query_plan(&supports_query_info, sdb,
+      scratch_pool));
+  if (!supports_query_info)
+    {
+      SQLITE_ERR(sqlite3_close(sdb));
+      return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL,
+          "Sqlite doesn't support EXPLAIN QUERY PLAN");
+    }
+
+  for (i = 0; i < STMT_SCHEMA_FIRST; i++)
+    {
+      sqlite3_stmt *stmt;
+      const char *tail;
+      int r;
+      svn_stringbuf_t *result;
+      svn_checksum_t *checksum;
+
+      if (is_schema_statement(i))
+        continue;
+
+      /* Prepare statement to find if it is a single statement. */
+      r = sqlite3_prepare_v2(sdb, wc_queries[i], -1, &stmt, &tail);
+
+      if (r != SQLITE_OK)
+        continue; /* Parse failure is already reported by 'test_parable' */
+
+      SQLITE_ERR(sqlite3_finalize(stmt));
+      if (tail[0] != '\0')
+        continue; /* Multi-queries are currently not testable */
+
+      svn_pool_clear(iterpool);
+
+      r = sqlite3_prepare_v2(sdb,
+                             apr_pstrcat(iterpool,
+                             "EXPLAIN ",
+                             wc_queries[i],
+                             SVN_VA_NULL),
+                             -1, &stmt, &tail);
+
+      if (r != SQLITE_OK)
+          continue; /* EXPLAIN not enabled or doesn't support this query */
+
+      result = svn_stringbuf_create_empty(iterpool);
+
+      while (SQLITE_ROW == (r = sqlite3_step(stmt)))
+        {
+          int col;
+
+          for (col = 0; col < sqlite3_column_count(stmt); col++)
+            {
+              const char *txt = (const char*)sqlite3_column_text(stmt, col);
+              if (txt)
+                  svn_stringbuf_appendcstr(result, txt);
+
+              svn_stringbuf_appendcstr(result, "|");
+            }
+
+          svn_stringbuf_appendcstr(result, "\n");
+        }
+
+      SQLITE_ERR(sqlite3_reset(stmt));
+      SQLITE_ERR(sqlite3_finalize(stmt));
+
+      SVN_ERR(svn_checksum(&checksum, svn_checksum_sha1,
+                           result->data, result->len,
+                           iterpool));
+
+      {
+        const char *hex = svn_checksum_to_cstring(checksum, scratch_pool);
+        const char *other;
+
+        other = svn_hash_gets(sha_to_query, hex);
+        if (other)
+          {
+            warnings = svn_error_createf(SVN_ERR_TEST_FAILED, warnings,
+                              "Query %s has an identical execution plan as %s",
+                              wc_query_info[i][0], other);
+          }
+        else
+          svn_hash_sets(sha_to_query, hex, wc_query_info[i][0]);
+      }
+    }
+  SQLITE_ERR(sqlite3_close(sdb)); /* Close the DB if ok; otherwise leaked */
+
+  return warnings;
+}
+
+/* Helper to verify a bit of data in the sqlite3 statistics */
+static int
+parse_stat_data(const char *stat)
+{
+  int n = 0;
+  apr_int64_t last = APR_INT64_MAX;
+  while (*stat)
+    {
+      apr_int64_t v;
+      char *next;
+
+      if (*stat < '0' || *stat > '9')
+        return -2;
+
+      errno = 0;
+      v = apr_strtoi64(stat, &next, 10);
+
+      /* All numbers specify the average number of rows
+         with the same values in all columns left of it,
+         so the value must be >= 1 and lower than or equal
+         to all previous seen numbers */
+      if (v <= 0 || (v > last) || (errno != 0))
+        return -1;
+
+      last = v;
+
+      n++;
+      stat = next;
+
+      if (*stat == ' ')
+        stat++;
+    }
+
+  return n;
+}
+
+static svn_error_t *
+test_schema_statistics(apr_pool_t *scratch_pool)
+{
+  sqlite3 *sdb;
+  sqlite3_stmt *stmt;
+
+  SVN_ERR(create_memory_db(&sdb, scratch_pool));
+
+  SQLITE_ERR(
+      sqlite3_exec(sdb,
+                   "CREATE TABLE shadow_stat1(tbl TEXT, idx TEXT, stat TEXT)",
+                   NULL, NULL, NULL));
+
+  SQLITE_ERR(
+      sqlite3_exec(sdb,
+                   "INSERT INTO shadow_stat1 (tbl, idx, stat) "
+                   "SELECT tbl, idx, stat FROM sqlite_stat1",
+                   NULL, NULL, NULL));
+
+  SQLITE_ERR(
+      sqlite3_exec(sdb,
+                   "DROP TABLE sqlite_stat1",
+                   NULL, NULL, NULL));
+
+  /* Insert statement to give index at least 1 record */
+  SQLITE_ERR(
+      sqlite3_exec(sdb,
+                   "INSERT INTO nodes (wc_id, local_relpath, op_depth,"
+                   "                   presence, kind) "
+                   "VALUES (1, '', 0, 'normal', 'dir')",
+                   NULL, NULL, NULL));
+
+  SQLITE_ERR(
+      sqlite3_exec(sdb,
+                   "INSERT INTO actual_node (wc_id, local_relpath) "
+                   "VALUES (1, '')",
+                   NULL, NULL, NULL));
+
+  SQLITE_ERR(
+      sqlite3_exec(sdb,
+                   "INSERT INTO lock (repos_id, repos_relpath, lock_token) "
+                   "VALUES (1, '', '')",
+                   NULL, NULL, NULL));
+
+  /* These are currently not necessary for query optimization, but it's better
+     to tell Sqlite how we intend to use this table anyway */
+  SQLITE_ERR(
+      sqlite3_exec(sdb,
+                   "INSERT INTO wc_lock (wc_id, local_dir_relpath) "
+                   "VALUES (1, '')",
+                   NULL, NULL, NULL));
+
+  SQLITE_ERR(
+      sqlite3_exec(sdb,
+                   "INSERT INTO WORK_QUEUE (work) "
+                   "VALUES ('')",
+                   NULL, NULL, NULL));
+
+  SQLITE_ERR(
+      sqlite3_exec(sdb,
+                   "ANALYZE",
+                   NULL, NULL, NULL));
+
+  SQLITE_ERR(
+      sqlite3_prepare(sdb, "SELECT s.tbl, s.idx, s.stat, r.stat "
+                           "FROM shadow_stat1 s "
+                           "LEFT JOIN sqlite_stat1 r ON "
+                                "s.tbl=r.tbl and s.idx=r.idx",
+                      -1, &stmt, NULL));
+
+  while (sqlite3_step(stmt) == SQLITE_ROW)
+    {
+      const char *wc_stat       = (const char*)sqlite3_column_text(stmt, 2);
+      const char *sqlite_stat   = (const char*)sqlite3_column_text(stmt, 3);
+
+      if (! sqlite_stat)
+        {
+          return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+                                   "Schema statistic failure:"
+                                   " Refering to unknown index '%s' on '%s'",
+                                   sqlite3_column_text(stmt, 1),
+                                   sqlite3_column_text(stmt, 0));
+        }
+
+      if (parse_stat_data(wc_stat) != parse_stat_data(sqlite_stat))
+        {
+          return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+                                   "Schema statistic failure:"
+                                   " Column mismatch for '%s' on '%s'",
+                                   sqlite3_column_text(stmt, 1),
+                                   sqlite3_column_text(stmt, 0));
+        }
+    }
+
+  SQLITE_ERR(sqlite3_reset(stmt));
+  SQLITE_ERR(sqlite3_finalize(stmt));
+
+  SQLITE_ERR(sqlite3_close(sdb)); /* Close the DB if ok; otherwise leaked */
+
+  return SVN_NO_ERROR;
+}
+
+int svn_test_max_threads = 1;
+
 struct svn_test_descriptor_t test_funcs[] =
   {
     SVN_TEST_NULL,
@@ -727,5 +987,9 @@ struct svn_test_descriptor_t test_funcs[
                    "queries are parsable"),
     SVN_TEST_PASS2(test_query_expectations,
                    "test query expectations"),
+    SVN_TEST_PASS2(test_query_duplicates,
+                   "test query duplicates"),
+    SVN_TEST_PASS2(test_schema_statistics,
+                   "test schema statistics"),
     SVN_TEST_NULL
   };

Modified: subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/wc-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/wc-test.c?rev=1546002&r1=1546001&r2=1546002&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/wc-test.c (original)
+++ subversion/branches/verify-keep-going/subversion/tests/libsvn_wc/wc-test.c Wed Nov 27 11:52:35 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"
@@ -308,6 +309,8 @@ test_externals_parse_erratic(apr_pool_t 
 /* ---------------------------------------------------------------------- */
 /* The list of test functions */
 
+int svn_test_max_threads = 2;
+
 struct svn_test_descriptor_t test_funcs[] =
   {
     SVN_TEST_NULL,

Modified: subversion/branches/verify-keep-going/subversion/tests/svn_test.h
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/tests/svn_test.h?rev=1546002&r1=1546001&r2=1546002&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/tests/svn_test.h (original)
+++ subversion/branches/verify-keep-going/subversion/tests/svn_test.h Wed Nov 27 11:52:35 2013
@@ -104,6 +104,8 @@ typedef struct svn_test_opts_t
   const char *fs_type;
   /* Config file. */
   const char *config_file;
+  /* Source dir. */
+  const char *srcdir;
   /* Minor version to use for servers and FS backends, or zero to use
      the current latest version. */
   int server_minor_version;
@@ -187,6 +189,9 @@ extern struct svn_test_descriptor_t test
 #define SVN_TEST_OPTS_WIMP_COND(func, p, msg, wip) \
   {(p) ? svn_test_xfail : svn_test_pass, NULL, func, msg, wip}
 
+/* Maximum number of concurrent test threads.  Set to 1 if all tests must
+   be executed serially.  Numbers less than 1 mean "unbounded" */
+extern int svn_test_max_threads;
 
 
 /* Return a pseudo-random number based on SEED, and modify SEED.
@@ -222,6 +227,12 @@ svn_test__tree_t;
 extern const svn_test__tree_entry_t svn_test__greek_tree_nodes[21];
 
 
+/* Returns a path to BASENAME within the transient data area for the
+   current test. */
+const char *
+svn_test_data_path(const char* basename, apr_pool_t *result_pool);
+
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/verify-keep-going/subversion/tests/svn_test_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/verify-keep-going/subversion/tests/svn_test_fs.c?rev=1546002&r1=1546001&r2=1546002&view=diff
==============================================================================
--- subversion/branches/verify-keep-going/subversion/tests/svn_test_fs.c (original)
+++ subversion/branches/verify-keep-going/subversion/tests/svn_test_fs.c Wed Nov 27 11:52:35 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"
@@ -144,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;
 }
 
 
@@ -183,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));
@@ -229,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));
@@ -542,13 +558,13 @@ svn_test__validate_changes(svn_fs_root_t
     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",
-                               svn__apr_hash_index_key(hi));
+                               (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",
-                               svn__apr_hash_index_key(hi));
+                               (const char *)svn__apr_hash_index_key(hi));
 
   return SVN_NO_ERROR;
 }