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 08:53:35 UTC
svn commit: r1545955 [14/15] - in /subversion/branches/fsfs-improvements: ./
build/ build/ac-macros/ build/generator/ build/generator/templates/
build/win32/ contrib/server-side/ contrib/server-side/svncutter/ notes/
subversion/bindings/javahl/native/ ...
Modified: subversion/branches/fsfs-improvements/subversion/tests/libsvn_subr/translate-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/tests/libsvn_subr/translate-test.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/tests/libsvn_subr/translate-test.c (original)
+++ subversion/branches/fsfs-improvements/subversion/tests/libsvn_subr/translate-test.c Wed Nov 27 07:53:29 2013
@@ -862,7 +862,7 @@ static svn_error_t *
mixed_to_lf(apr_pool_t *pool)
{
return substitute_and_verify
- ("cr_to_lf", NULL, "\n", 1, NULL, NULL, NULL, NULL, 1, pool);
+ ("mixed_to_lf", NULL, "\n", 1, NULL, NULL, NULL, NULL, 1, pool);
}
@@ -1096,10 +1096,10 @@ static svn_error_t *
unexpand_author(apr_pool_t *pool)
{
SVN_ERR(substitute_and_verify
- ("author", "\n", NULL, 0, NULL, NULL, "jrandom", NULL, 0, pool));
+ ("unexpand_author", "\n", NULL, 0, NULL, NULL, "jrandom", NULL, 0, pool));
SVN_ERR(substitute_and_verify
- ("author", "\r\n", NULL, 0, NULL, NULL, "jrandom", NULL, 0, pool));
+ ("unexpand_author", "\r\n", NULL, 0, NULL, NULL, "jrandom", NULL, 0, pool));
return SVN_NO_ERROR;
}
@@ -1109,11 +1109,11 @@ static svn_error_t *
unexpand_date(apr_pool_t *pool)
{
SVN_ERR(substitute_and_verify
- ("date", "\n", NULL, 0,
+ ("unexpand_date", "\n", NULL, 0,
NULL, "Wed Jan 9 07:49:05 2002", NULL, NULL, 0, pool));
SVN_ERR(substitute_and_verify
- ("date", "\r\n", NULL, 0,
+ ("unexpand_date", "\r\n", NULL, 0,
NULL, "Wed Jan 9 07:49:05 2002", NULL, NULL, 0, pool));
return SVN_NO_ERROR;
@@ -1124,11 +1124,11 @@ static svn_error_t *
unexpand_author_date(apr_pool_t *pool)
{
SVN_ERR(substitute_and_verify
- ("author_date", "\n", NULL, 0,
+ ("unexpand_author_date", "\n", NULL, 0,
NULL, "Wed Jan 9 07:49:05 2002", "jrandom", NULL, 0, pool));
SVN_ERR(substitute_and_verify
- ("author_date", "\r\n", NULL, 0,
+ ("unexpand_author_date", "\r\n", NULL, 0,
NULL, "Wed Jan 9 07:49:05 2002", "jrandom", NULL, 0, pool));
return SVN_NO_ERROR;
@@ -1139,11 +1139,11 @@ static svn_error_t *
unexpand_author_rev(apr_pool_t *pool)
{
SVN_ERR(substitute_and_verify
- ("author_rev", "\n", NULL, 0,
+ ("unexpand_author_rev", "\n", NULL, 0,
"1729", NULL, "jrandom", NULL, 0, pool));
SVN_ERR(substitute_and_verify
- ("author_rev", "\r\n", NULL, 0,
+ ("unexpand_author_rev", "\r\n", NULL, 0,
"1729", NULL, "jrandom", NULL, 0, pool));
return SVN_NO_ERROR;
@@ -1154,11 +1154,11 @@ static svn_error_t *
unexpand_rev(apr_pool_t *pool)
{
SVN_ERR(substitute_and_verify
- ("rev", "\n", NULL, 0,
+ ("unexpand_rev", "\n", NULL, 0,
"1729", NULL, NULL, NULL, 0, pool));
SVN_ERR(substitute_and_verify
- ("rev", "\r\n", NULL, 0,
+ ("unexpand_rev", "\r\n", NULL, 0,
"1729", NULL, NULL, NULL, 0, pool));
return SVN_NO_ERROR;
@@ -1169,11 +1169,11 @@ static svn_error_t *
unexpand_rev_url(apr_pool_t *pool)
{
SVN_ERR(substitute_and_verify
- ("rev_url", "\n", NULL, 0,
+ ("unexpand_rev_url", "\n", NULL, 0,
"1729", NULL, NULL, "http://subversion.tigris.org", 0, pool));
SVN_ERR(substitute_and_verify
- ("rev_url", "\r\n", NULL, 0,
+ ("unexpand_rev_url", "\r\n", NULL, 0,
"1729", NULL, NULL, "http://subversion.tigris.org", 0, pool));
return SVN_NO_ERROR;
@@ -1184,7 +1184,7 @@ static svn_error_t *
unexpand_author_date_rev_url(apr_pool_t *pool)
{
SVN_ERR(substitute_and_verify
- ("author_date_rev_url", "\n", NULL, 0,
+ ("unexpand_author_date_rev_url", "\n", NULL, 0,
"1729",
"Wed Jan 9 07:49:05 2002",
"jrandom",
@@ -1192,7 +1192,7 @@ unexpand_author_date_rev_url(apr_pool_t
1, pool));
SVN_ERR(substitute_and_verify
- ("author_date_rev_url", "\r\n", NULL, 0,
+ ("unexpand_author_date_rev_url", "\r\n", NULL, 0,
"1729",
"Wed Jan 9 07:49:05 2002",
"jrandom",
@@ -1210,7 +1210,7 @@ static svn_error_t *
lf_to_crlf_unexpand_author(apr_pool_t *pool)
{
return substitute_and_verify
- ("lf_to_crlf_author", "\n", "\r\n", 0,
+ ("lf_to_crlf_unexpand_author", "\n", "\r\n", 0,
NULL, NULL, "jrandom", NULL, 0, pool);
}
@@ -1219,7 +1219,7 @@ static svn_error_t *
mixed_to_lf_unexpand_author_date(apr_pool_t *pool)
{
return substitute_and_verify
- ("mixed_to_lf_author_date", NULL, "\n", 1,
+ ("mixed_to_lf_unexpand_author_date", NULL, "\n", 1,
NULL, "Wed Jan 9 07:49:05 2002", "jrandom", NULL, 0, pool);
}
@@ -1228,7 +1228,7 @@ static svn_error_t *
crlf_to_cr_unexpand_author_rev(apr_pool_t *pool)
{
return substitute_and_verify
- ("crlf_to_cr_author_rev", "\r\n", "\r", 0,
+ ("crlf_to_cr_unexpand_author_rev", "\r\n", "\r", 0,
"1729", NULL, "jrandom", NULL, 0, pool);
}
@@ -1237,7 +1237,7 @@ static svn_error_t *
cr_to_crlf_unexpand_rev(apr_pool_t *pool)
{
return substitute_and_verify
- ("cr_to_crlf_rev", "\r", "\r\n", 0,
+ ("cr_to_crlf_unexpand_rev", "\r", "\r\n", 0,
"1729", NULL, NULL, NULL, 0, pool);
}
@@ -1246,7 +1246,7 @@ static svn_error_t *
cr_to_crlf_unexpand_rev_url(apr_pool_t *pool)
{
return substitute_and_verify
- ("cr_to_crlf_rev_url", "\r", "\r\n", 0,
+ ("cr_to_crlf_unexpand_rev_url", "\r", "\r\n", 0,
"1729", NULL, NULL, "http://subversion.tigris.org", 0, pool);
}
@@ -1255,7 +1255,7 @@ static svn_error_t *
mixed_to_crlf_unexpand_author_date_rev_url(apr_pool_t *pool)
{
return substitute_and_verify
- ("mixed_to_crlf_author_date_rev_url", NULL, "\r\n", 1,
+ ("mixed_to_crlf_unexpand_author_date_rev_url", NULL, "\r\n", 1,
"1729",
"Wed Jan 9 07:49:05 2002",
"jrandom",
@@ -1268,6 +1268,8 @@ mixed_to_crlf_unexpand_author_date_rev_u
/* The test table. */
+int svn_test_max_threads = 7;
+
struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
Modified: subversion/branches/fsfs-improvements/subversion/tests/libsvn_subr/utf-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/tests/libsvn_subr/utf-test.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/tests/libsvn_subr/utf-test.c (original)
+++ subversion/branches/fsfs-improvements/subversion/tests/libsvn_subr/utf-test.c Wed Nov 27 07:53:29 2013
@@ -740,6 +740,8 @@ test_utf_is_normalized(apr_pool_t *pool)
/* The test table. */
+int svn_test_max_threads = 1;
+
struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
Modified: subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/conflict-data-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/conflict-data-test.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/conflict-data-test.c (original)
+++ subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/conflict-data-test.c Wed Nov 27 07:53:29 2013
@@ -810,6 +810,8 @@ test_prop_conflicts(const svn_test_opts_
/* The test table. */
+int svn_test_max_threads = 1;
+
struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
Modified: subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/db-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/db-test.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/db-test.c (original)
+++ subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/db-test.c Wed Nov 27 07:53:29 2013
@@ -1521,6 +1521,8 @@ test_externals_store(apr_pool_t *pool)
return SVN_NO_ERROR;
}
+int svn_test_max_threads = 2;
+
struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
Modified: subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/entries-compat.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/entries-compat.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/entries-compat.c (original)
+++ subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/entries-compat.c Wed Nov 27 07:53:29 2013
@@ -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/fsfs-improvements/subversion/tests/libsvn_wc/op-depth-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/op-depth-test.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/op-depth-test.c (original)
+++ subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/op-depth-test.c Wed Nov 27 07:53:29 2013
@@ -29,6 +29,7 @@
#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"
@@ -52,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
@@ -104,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
@@ -332,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 */
@@ -759,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 */
@@ -5215,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, ""},
@@ -5300,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, ""},
@@ -5326,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, ""},
@@ -5625,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)
@@ -5633,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;
@@ -7085,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"));
@@ -8753,9 +8917,546 @@ move_twice_within_delete(const svn_test_
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[] =
{
SVN_TEST_NULL,
@@ -8920,5 +9621,25 @@ struct svn_test_descriptor_t test_funcs[
"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/fsfs-improvements/subversion/tests/libsvn_wc/pristine-store-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/pristine-store-test.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/pristine-store-test.c (original)
+++ subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/pristine-store-test.c Wed Nov 27 07:53:29 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/fsfs-improvements/subversion/tests/libsvn_wc/utils.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/utils.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/utils.c (original)
+++ subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/utils.c Wed Nov 27 07:53:29 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));
Modified: subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/wc-queries-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/wc-queries-test.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/wc-queries-test.c (original)
+++ subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/wc-queries-test.c Wed Nov 27 07:53:29 2013
@@ -22,6 +22,7 @@
*/
#include "svn_pools.h"
+#include "svn_hash.h"
#include "svn_ctype.h"
#include "private/svn_dep_compat.h"
@@ -72,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,
@@ -90,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,
@@ -109,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)
@@ -524,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);
}
@@ -585,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)
@@ -646,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)
{
@@ -713,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,
@@ -722,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/fsfs-improvements/subversion/tests/libsvn_wc/wc-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/wc-test.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/wc-test.c (original)
+++ subversion/branches/fsfs-improvements/subversion/tests/libsvn_wc/wc-test.c Wed Nov 27 07:53:29 2013
@@ -309,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/fsfs-improvements/subversion/tests/svn_test.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/tests/svn_test.h?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/tests/svn_test.h (original)
+++ subversion/branches/fsfs-improvements/subversion/tests/svn_test.h Wed Nov 27 07:53:29 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.
Modified: subversion/branches/fsfs-improvements/subversion/tests/svn_test_main.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/subversion/tests/svn_test_main.c?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/subversion/tests/svn_test_main.c (original)
+++ subversion/branches/fsfs-improvements/subversion/tests/svn_test_main.c Wed Nov 27 07:53:29 2013
@@ -47,9 +47,18 @@
#include "svn_utf.h"
#include "private/svn_cmdline_private.h"
+#include "private/svn_atomic.h"
+#include "private/svn_mutex.h"
#include "svn_private_config.h"
+#if APR_HAS_THREADS && APR_VERSION_AT_LEAST(1,3,0)
+# include <apr_thread_pool.h>
+# define HAVE_THREADPOOLS 1
+#else
+# define HAVE_THREADPOOLS 0
+#endif
+
/* Some Subversion test programs may want to parse options in the
argument list, so we remember it here. */
int test_argc;
@@ -76,6 +85,9 @@ static svn_boolean_t allow_segfaults = F
Pass, All). */
enum svn_test_mode_t mode_filter = svn_test_all;
+/* Test option: Allow concurrent execution of tests */
+static svn_boolean_t parallel = FALSE;
+
/* Option parsing enums and structures */
enum {
help_opt = SVN_OPT_FIRST_LONGOPT_ID,
@@ -88,7 +100,8 @@ enum {
server_minor_version_opt,
allow_segfault_opt,
srcdir_opt,
- mode_filter_opt
+ mode_filter_opt,
+ parallel_opt
};
static const apr_getopt_option_t cl_options[] =
@@ -117,6 +130,8 @@ static const apr_getopt_option_t cl_opti
N_("don't trap seg faults (useful for debugging)")},
{"srcdir", srcdir_opt, 1,
N_("source directory")},
+ {"parallel", parallel_opt, 0,
+ N_("allow concurrent execution of tests")},
{0, 0, 0, 0}
};
@@ -130,6 +145,9 @@ static svn_boolean_t skip_cleanup = FALS
/* All cleanup actions are registered as cleanups on this pool. */
static apr_pool_t *cleanup_pool = NULL;
+/* Used by test_thread to serialize access to stdout. */
+static svn_mutex__t *log_mutex = NULL;
+
static apr_status_t
cleanup_rmtree(void *data)
{
@@ -160,13 +178,34 @@ svn_test_add_dir_cleanup(const char *pat
if (cleanup_mode)
{
const char *abspath;
- svn_error_t *err = svn_path_get_absolute(&abspath, path, cleanup_pool);
+ svn_error_t *err;
+
+ /* All cleanup functions use the *same* pool (not subpools of it).
+ Thus, we need to synchronize. */
+ err = svn_mutex__lock(log_mutex);
+ if (err)
+ {
+ if (verbose_mode)
+ printf("FAILED svn_mutex__lock in svn_test_add_dir_cleanup.\n");
+ svn_error_clear(err);
+ return;
+ }
+
+ err = svn_path_get_absolute(&abspath, path, cleanup_pool);
svn_error_clear(err);
if (!err)
apr_pool_cleanup_register(cleanup_pool, abspath, cleanup_rmtree,
apr_pool_cleanup_null);
else if (verbose_mode)
printf("FAILED ABSPATH: %s\n", path);
+
+ err = svn_mutex__unlock(log_mutex, NULL);
+ if (err)
+ {
+ if (verbose_mode)
+ printf("FAILED svn_mutex__unlock in svn_test_add_dir_cleanup.\n");
+ svn_error_clear(err);
+ }
}
}
@@ -209,6 +248,86 @@ crash_handler(int signum)
longjmp(jump_buffer, 1);
}
+/* Write the result of test number TEST_NUM to stdout. Pretty-print test
+ name and dots according to our test-suite spec, and return TRUE if there
+ has been a test failure.
+
+ The parameters are basically the internal state of do_test_num() and
+ test_thread(). */
+/* */
+static svn_boolean_t
+log_results(const char *progname,
+ int test_num,
+ svn_boolean_t msg_only,
+ svn_boolean_t run_this_test,
+ svn_boolean_t skip,
+ svn_boolean_t xfail,
+ svn_boolean_t wimp,
+ svn_error_t *err,
+ const char *msg,
+ const struct svn_test_descriptor_t *desc)
+{
+ svn_boolean_t test_failed;
+
+ if (err && err->apr_err == SVN_ERR_TEST_SKIPPED)
+ {
+ svn_error_clear(err);
+ err = SVN_NO_ERROR;
+ skip = TRUE;
+ }
+
+ /* Failure means unexpected results -- FAIL or XPASS. */
+ test_failed = (!wimp && ((err != SVN_NO_ERROR) != (xfail != 0)));
+
+ /* If we got an error, print it out. */
+ if (err)
+ {
+ svn_handle_error2(err, stdout, FALSE, "svn_tests: ");
+ svn_error_clear(err);
+ }
+
+ if (msg_only)
+ {
+ if (run_this_test)
+ printf(" %3d %-5s %s%s%s%s\n",
+ test_num,
+ (xfail ? "XFAIL" : (skip ? "SKIP" : "")),
+ msg ? msg : "(test did not provide name)",
+ (wimp && verbose_mode) ? " [[" : "",
+ (wimp && verbose_mode) ? desc->wip : "",
+ (wimp && verbose_mode) ? "]]" : "");
+ }
+ else if (run_this_test && ((! quiet_mode) || test_failed))
+ {
+ printf("%s %s %d: %s%s%s%s\n",
+ (err
+ ? (xfail ? "XFAIL:" : "FAIL: ")
+ : (xfail ? "XPASS:" : (skip ? "SKIP: " : "PASS: "))),
+ progname,
+ test_num,
+ msg ? msg : "(test did not provide name)",
+ wimp ? " [[WIMP: " : "",
+ wimp ? desc->wip : "",
+ wimp ? "]]" : "");
+ }
+
+ if (msg)
+ {
+ size_t len = strlen(msg);
+ if (len > 50)
+ printf("WARNING: Test docstring exceeds 50 characters\n");
+ if (msg[len - 1] == '.')
+ printf("WARNING: Test docstring ends in a period (.)\n");
+ if (svn_ctype_isupper(msg[0]))
+ printf("WARNING: Test docstring is capitalized\n");
+ }
+ if (desc->msg == NULL)
+ printf("WARNING: New-style test descriptor is missing a docstring.\n");
+
+ fflush(stdout);
+
+ return test_failed;
+}
/* Execute a test number TEST_NUM. Pretty-print test name and dots
according to our test-suite spec, and return the result code.
@@ -224,7 +343,6 @@ do_test_num(const char *progname,
{
svn_boolean_t skip, xfail, wimp;
svn_error_t *err = NULL;
- svn_boolean_t test_failed;
const char *msg = NULL; /* the message this individual test prints out */
const struct svn_test_descriptor_t *desc;
const int array_size = get_array_size();
@@ -296,60 +414,147 @@ do_test_num(const char *progname,
}
/* Failure means unexpected results -- FAIL or XPASS. */
- test_failed = (!wimp && ((err != SVN_NO_ERROR) != (xfail != 0)));
+ skip_cleanup = log_results(progname, test_num, msg_only, run_this_test,
+ skip, xfail, wimp, err, msg, desc);
- /* If we got an error, print it out. */
- if (err)
- {
- svn_handle_error2(err, stdout, FALSE, "svn_tests: ");
- svn_error_clear(err);
- }
+ return skip_cleanup;
+}
- if (msg_only)
- {
- if (run_this_test)
- printf(" %3d %-5s %s%s%s%s\n",
- test_num,
- (xfail ? "XFAIL" : (skip ? "SKIP" : "")),
- msg ? msg : "(test did not provide name)",
- (wimp && verbose_mode) ? " [[" : "",
- (wimp && verbose_mode) ? desc->wip : "",
- (wimp && verbose_mode) ? "]]" : "");
- }
- else if (run_this_test && ((! quiet_mode) || test_failed))
+#if HAVE_THREADPOOLS
+
+/* Per-test parameters used by test_thread */
+typedef struct test_params_t
+{
+ /* Name of the application */
+ const char *progname;
+
+ /* Number / index of the test to execute */
+ int test_num;
+
+ /* Global test options as provided by main() */
+ svn_test_opts_t *opts;
+
+ /* Thread-safe parent pool for the test-specific pool. We expect the
+ test thread to create a sub-pool and destroy it after test completion. */
+ apr_pool_t *pool;
+
+ /* Reference to the global failure flag. Set this if any test failed. */
+ svn_atomic_t *got_error;
+
+ /* Reference to the global completed test counter. */
+ svn_atomic_t *run_count;
+} test_params_t;
+
+/* Thread function similar to do_test_num() but with fewer options. We do
+ catch segfaults. All parameters are given as a test_params_t in DATA.
+ */
+static void * APR_THREAD_FUNC
+test_thread(apr_thread_t *tid, void *data)
+{
+ svn_boolean_t skip, xfail, wimp;
+ svn_error_t *err = NULL;
+ const struct svn_test_descriptor_t *desc;
+ svn_boolean_t run_this_test; /* This test's mode matches DESC->MODE. */
+ test_params_t *params = data;
+
+ apr_pool_t *test_pool = svn_pool_create(params->pool);
+
+ desc = &test_funcs[params->test_num];
+ skip = desc->mode == svn_test_skip;
+ xfail = desc->mode == svn_test_xfail;
+ wimp = xfail && desc->wip;
+ run_this_test = mode_filter == svn_test_all || mode_filter == desc->mode;
+
+ /* Do test */
+ if (skip || !run_this_test)
+ ; /* pass */
+ else if (desc->func2)
+ err = (*desc->func2)(test_pool);
+ else
+ err = (*desc->func_opts)(params->opts, test_pool);
+
+ /* Write results to console */
+ svn_error_clear(svn_mutex__lock(log_mutex));
+ if (log_results(params->progname, params->test_num, FALSE, run_this_test,
+ skip, xfail, wimp, err, desc->msg, desc))
+ svn_atomic_set(params->got_error, TRUE);
+ svn_error_clear(svn_mutex__unlock(log_mutex, NULL));
+
+ /* release all test memory */
+ svn_pool_destroy(test_pool);
+
+ /* one more test completed */
+ svn_atomic_inc(params->run_count);
+
+ return NULL;
+}
+
+/* Execute all ARRAY_SIZE tests concurrently using MAX_THREADS threads.
+ Pass PROGNAME and OPTS to the individual tests. Return TRUE if at least
+ one of the tests failed. Allocate all data in POOL.
+
+ Note that cleanups are delayed until all tests have been completed.
+ */
+static svn_boolean_t
+do_tests_concurrently(const char *progname,
+ int array_size,
+ int max_threads,
+ svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ apr_thread_pool_t *threads;
+ apr_status_t status;
+ svn_atomic_t got_error = FALSE;
+ int i;
+ svn_atomic_t run_count = 0;
+
+ /* Create the thread pool. */
+ status = apr_thread_pool_create(&threads, max_threads, max_threads, pool);
+ if (status)
{
- printf("%s %s %d: %s%s%s%s\n",
- (err
- ? (xfail ? "XFAIL:" : "FAIL: ")
- : (xfail ? "XPASS:" : (skip ? "SKIP: " : "PASS: "))),
- progname,
- test_num,
- msg ? msg : "(test did not provide name)",
- wimp ? " [[WIMP: " : "",
- wimp ? desc->wip : "",
- wimp ? "]]" : "");
+ printf("apr_thread_pool_create() failed.\n");
+ return TRUE;
}
- if (msg)
+ /* Don't queue requests unless we reached the worker thread limit. */
+ apr_thread_pool_threshold_set(threads, 0);
+
+ /* Generate one task per test and queue them in the thread pool. */
+ for (i = 1; i <= array_size; i++)
{
- size_t len = strlen(msg);
- if (len > 50)
- printf("WARNING: Test docstring exceeds 50 characters\n");
- if (msg[len - 1] == '.')
- printf("WARNING: Test docstring ends in a period (.)\n");
- if (svn_ctype_isupper(msg[0]))
- printf("WARNING: Test docstring is capitalized\n");
+ test_params_t *params = apr_pcalloc(pool, sizeof(*params));
+ params->got_error = &got_error;
+ params->opts = opts;
+ params->pool = pool;
+ params->progname = progname;
+ params->test_num = i;
+ params->run_count = &run_count;
+
+ apr_thread_pool_push(threads, test_thread, params, 0, NULL);
}
- if (desc->msg == NULL)
- printf("WARNING: New-style test descriptor is missing a docstring.\n");
- fflush(stdout);
+ /* Wait for all tasks (tests) to complete. As it turns out, this is the
+ variant with the least run-time overhead to the test threads. */
+ while ( apr_thread_pool_tasks_count(threads)
+ || apr_thread_pool_busy_count(threads))
+ apr_thread_yield();
+
+ /* For some unknown reason, cleaning POOL (TEST_POOL in main()) does not
+ call the following reliably for all users. */
+ apr_thread_pool_destroy(threads);
- skip_cleanup = test_failed;
+ /* Verify that we didn't skip any tasks. */
+ if (run_count != array_size)
+ {
+ printf("Parallel test failure: only %d of %d tests executed.\n",
+ (int)run_count, array_size);
+ return TRUE;
+ }
- return test_failed;
+ return got_error != FALSE;
}
+#endif
static void help(const char *progname, apr_pool_t *pool)
{
@@ -410,9 +615,9 @@ static svn_error_t *init_test_data(const
}
const char *
-svn_test_data_path(const char *basename, apr_pool_t *result_pool)
+svn_test_data_path(const char *base_name, apr_pool_t *result_pool)
{
- return svn_dirent_join(data_path, basename, result_pool);
+ return svn_dirent_join(data_path, base_name, result_pool);
}
@@ -449,6 +654,12 @@ main(int argc, const char *argv[])
* usage but make it thread-safe to allow for multi-threaded tests.
*/
pool = apr_allocator_owner_get(svn_pool_create_allocator(TRUE));
+ err = svn_mutex__init(&log_mutex, TRUE, pool);
+ if (err)
+ {
+ svn_handle_error2(err, stderr, TRUE, "svn_tests: ");
+ svn_error_clear(err);
+ }
/* Remember the command line */
test_argc = argc;
@@ -538,6 +749,10 @@ main(int argc, const char *argv[])
case fstype_opt:
opts.fs_type = apr_pstrdup(pool, opt_arg);
break;
+ case srcdir_opt:
+ SVN_INT_ERR(svn_utf_cstring_to_utf8(&opts.srcdir, opt_arg, pool));
+ opts.srcdir = svn_dirent_internal_style(opts.srcdir, pool);
+ break;
case list_opt:
list_mode = TRUE;
break;
@@ -581,7 +796,13 @@ main(int argc, const char *argv[])
fprintf(stderr, "FAIL: Invalid minor version given\n");
exit(1);
}
+ break;
}
+#if HAVE_THREADPOOLS
+ case parallel_opt:
+ parallel = TRUE;
+ break;
+#endif
}
}
@@ -652,15 +873,33 @@ main(int argc, const char *argv[])
if (! ran_a_test)
{
/* just run all tests */
- for (i = 1; i <= array_size; i++)
+ if (svn_test_max_threads < 1)
+ svn_test_max_threads = array_size;
+
+ if (svn_test_max_threads == 1 || !parallel)
{
- if (do_test_num(prog_name, i, FALSE, &opts, NULL, test_pool))
- got_error = TRUE;
+ for (i = 1; i <= array_size; i++)
+ {
+ if (do_test_num(prog_name, i, FALSE, &opts, NULL, test_pool))
+ got_error = TRUE;
+
+ /* Clear the per-function pool */
+ svn_pool_clear(test_pool);
+ svn_pool_clear(cleanup_pool);
+ }
+ }
+#if HAVE_THREADPOOLS
+ else
+ {
+ got_error = do_tests_concurrently(prog_name, array_size,
+ svn_test_max_threads,
+ &opts, test_pool);
- /* Clear the per-function pool */
+ /* Execute all cleanups */
svn_pool_clear(test_pool);
svn_pool_clear(cleanup_pool);
}
+#endif
}
/* Clean up APR */
Modified: subversion/branches/fsfs-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-bindings.cmd
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-bindings.cmd?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-bindings.cmd (original)
+++ subversion/branches/fsfs-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-bindings.cmd Wed Nov 27 07:53:29 2013
@@ -22,29 +22,30 @@ SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDE
CALL ..\svn-config.cmd
IF ERRORLEVEL 1 EXIT /B 1
-ECHO ON
IF "%SVN_BRANCH%" LEQ "1.6.x" (
- ECHO --- Building 1.6.x or older: Skipping bindings ---
- EXIT /B 0
+ ECHO --- Building 1.6.x or older: Skipping bindings ---
+ EXIT /B 0
)
-PATH %PATH%;%TESTDIR%\bin
-SET result=0
+IF "%SVN_BRANCH%" LSS "1.9." (
+ IF NOT EXIST "%TESTDIR%\bin" MKDIR "%TESTDIR%\bin"
+ xcopy /y /i ..\deps\release\bin\*.dll "%TESTDIR%\bin"
-python win-tests.py -d -f fsfs --javahl "%TESTDIR%\tests"
-IF ERRORLEVEL 1 (
- echo [python reported error !ERRORLEVEL!]
- SET result=1
+ PATH %TESTDIR%\bin;!PATH!
)
+SET result=0
+
if "%SVN_BRANCH%" GTR "1.9." (
python win-tests.py -r -f fsfs --swig=python "%TESTDIR%\tests"
IF ERRORLEVEL 1 (
- echo [Python tests exited with error !ERRORLEVEL!]
+ echo [Python tests reported error !ERRORLEVEL!] 1>&2
SET result=1
+ ) ELSE (
+ echo Done.
)
) ELSE (
@@ -61,8 +62,10 @@ if "%SVN_BRANCH%" GTR "1.9." (
python subversion\bindings\swig\python\tests\run_all.py
IF ERRORLEVEL 1 (
- echo [Python tests exited with error !ERRORLEVEL!]
+ echo [Python tests reported error !ERRORLEVEL!] 1>&2
SET result=1
+ ) ELSE (
+ echo Done.
)
)
@@ -71,8 +74,10 @@ 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
+ echo [Perl tests reported error !ERRORLEVEL!] 1>&2
+ REM SET result=1
+ ) ELSE (
+ echo Done.
)
) ELSE IF "%SVN_BRANCH%" GTR "1.8." (
@@ -94,19 +99,23 @@ if "%SVN_BRANCH%" GTR "1.9." (
pushd subversion\bindings\swig\perl\native
perl -MExtUtils::Command::MM -e "test_harness()" t\*.t
IF ERRORLEVEL 1 (
- echo [Perl reported error !ERRORLEVEL!]
+ echo [Test runner reported error !ERRORLEVEL!]
SET result=1
)
popd
)
if "%SVN_BRANCH%" GTR "1.9." (
- python win-tests.py -d -f fsfs --swig=ruby "%TESTDIR%\tests"
+ python win-tests.py -d -f fsfs --swig=ruby "%TESTDIR%\tests"
+
+ IF ERRORLEVEL 1 (
+ echo [Ruby tests reported error !ERRORLEVEL!] 1>&2
+ REM SET result=1
+ ) ELSE (
+ echo Done.
+ )
- IF ERRORLEVEL 1 (
- echo [Ruby tests reported error !ERRORLEVEL!] (not fatal)
- REM SET result=1
- )
+ taskkill /im svnserve.exe /f
)
exit /b %result%
Modified: subversion/branches/fsfs-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-build-bindings.cmd
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-build-bindings.cmd?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-build-bindings.cmd (original)
+++ subversion/branches/fsfs-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-build-bindings.cmd Wed Nov 27 07:53:29 2013
@@ -28,7 +28,7 @@ IF "%SVN_BRANCH%" LEQ "1.6.x" (
EXIT /B 0
)
-SET DEBUG_TARGETS=/t:__JAVAHL__ /t:__JAVAHL_TESTS__
+SET DEBUG_TARGETS=/t:__ALL_TESTS__
SET RELEASE_TARGETS=/t:__SWIG_PYTHON__
if "%SVN_BRANCH%" GTR "1.8." (
@@ -39,10 +39,10 @@ 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%
+msbuild subversion_vcnet.sln /m /v: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 %RELEASE_TARGETS%
+msbuild subversion_vcnet.sln /m /v:m /p:Configuration=Release /p:Platform=Win32 %RELEASE_TARGETS%
IF ERRORLEVEL 1 EXIT /B 1
-EXIT /B 0
\ No newline at end of file
+EXIT /B 0
Modified: subversion/branches/fsfs-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-build.cmd
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-build.cmd?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-build.cmd (original)
+++ subversion/branches/fsfs-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-build.cmd Wed Nov 27 07:53:29 2013
@@ -25,10 +25,12 @@ IF ERRORLEVEL 1 EXIT /B 1
PUSHD ..\deps
-nant gen-dev -D:wc=..\build -D:impBase=../deps/build/win32 -D:botBuild=true %NANTARGS%
+nant gen-dev -D:wc=..\build -D:impBase=../deps/build/win32 -D:botBuild=true %SVN_NANT_ARGS%
IF ERRORLEVEL 1 EXIT /B 1
POPD
-msbuild subversion_vcnet.sln /p:Configuration=Debug /p:Platform=win32 /t:__ALL_TESTS__
+msbuild subversion_vcnet.sln /m /v:m /p:Configuration=Debug /p:Platform=Win32 /t:__ALL_TESTS__ %SVN_MSBUILD_ARGS%
IF ERRORLEVEL 1 EXIT /B 1
+
+EXIT /B 0
Modified: subversion/branches/fsfs-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-cleanup.cmd
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-cleanup.cmd?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-cleanup.cmd (original)
+++ subversion/branches/fsfs-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-cleanup.cmd Wed Nov 27 07:53:29 2013
@@ -28,17 +28,17 @@ PUSHD ..\deps
ECHO Checking dependencies in %CD%
IF NOT EXIST "imports\" (
- svn co --username guest --password "" http://sharpsvn.open.collab.net/svn/sharpsvn/trunk/imports imports
+ svn co --username guest --password "" http://sharpsvn.open.collab.net/svn/sharpsvn/trunk/imports imports
)
IF NOT EXIST build\imports.done (
- svn up imports
- copy /y imports\dev-default.build default.build
- nant prep-dev %NANTARGS%
- IF ERRORLEVEL 1 (
- exit /B 1
- )
- del release\bin\*svn* release\bin\_*.* 2>nul:
- echo. > build\imports.done
+ svn up imports
+ copy /y imports\dev-default.build default.build
+ nant prep-dev %NANTARGS%
+ IF ERRORLEVEL 1 (
+ EXIT /B 1
+ )
+ del release\bin\*svn* release\bin\_*.* 2>nul:
+ ECHO. > build\imports.done
)
POPD
@@ -50,6 +50,7 @@ IF NOT ERRORLEVEL 1 (
POPD
+taskkill /im msbuild.exe /f 2> nul:
taskkill /im svn.exe /f 2> nul:
taskkill /im svnlook.exe /f 2> nul:
taskkill /im svnadmin.exe /f 2> nul:
@@ -57,20 +58,23 @@ taskkill /im svnserve.exe /f 2> nul:
taskkill /im svnrdump.exe /f 2> nul:
taskkill /im svnsync.exe /f 2> nul:
taskkill /im httpd.exe /f 2> nul:
+taskkill /im client-test.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 ruby.exe /f 2> nul:
taskkill /im mspdbsrv.exe /f 2> nul:
-IF EXIST "%TESTDIR%\tests\subversion\tests\cmdline\httpd\" (
- rmdir /s /q "%TESTDIR%\tests\subversion\tests\cmdline\httpd"
-)
+
IF EXIST "%TESTDIR%\swig\" (
- rmdir /s /q "%TESTDIR%\swig"
+ rmdir /s /q "%TESTDIR%\swig"
)
-del "%TESTDIR%\tests\*.log" 2> nul:
-
+IF EXIST "%TESTDIR%\tests\" (
+ PUSHD "%TESTDIR%\tests\"
+ rmdir /s /q "%TESTDIR%\tests\" 2> nul:
+ POPD
+)
exit /B 0
Modified: subversion/branches/fsfs-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-test.cmd
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-test.cmd?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-test.cmd (original)
+++ subversion/branches/fsfs-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-test.cmd Wed Nov 27 07:53:29 2013
@@ -65,10 +65,12 @@ IF NOT "%1" == "" GOTO next
taskkill /im svnserve.exe httpd.exe /f 2> nul:
-IF NOT EXIST "%TESTDIR%\bin" MKDIR "%TESTDIR%\bin"
-xcopy /y /i ..\deps\release\bin\*.dll "%TESTDIR%\bin"
+IF "%SVN_BRANCH%" LSS "1.9." (
+ IF NOT EXIST "%TESTDIR%\bin" MKDIR "%TESTDIR%\bin"
+ xcopy /y /i ..\deps\release\bin\*.dll "%TESTDIR%\bin"
-PATH %TESTDIR%\bin;%PATH%
+ PATH %TESTDIR%\bin;!PATH!
+)
IF "%LOCAL%+%FSFS%" == "1+1" (
echo win-tests.py -c %PARALLEL% %MODE% -f fsfs %ARGS% "%TESTDIR%\tests"
Modified: subversion/branches/fsfs-improvements/tools/client-side/svn-bench/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-improvements/tools/client-side/svn-bench/cl.h?rev=1545955&r1=1545954&r2=1545955&view=diff
==============================================================================
--- subversion/branches/fsfs-improvements/tools/client-side/svn-bench/cl.h (original)
+++ subversion/branches/fsfs-improvements/tools/client-side/svn-bench/cl.h Wed Nov 27 07:53:29 2013
@@ -137,7 +137,7 @@ extern const apr_getopt_option_t svn_cl_
*
* Typically, error codes like SVN_ERR_UNVERSIONED_RESOURCE,
* SVN_ERR_ENTRY_NOT_FOUND, etc, are supplied in varargs. Don't
- * forget to terminate the argument list with SVN_NO_ERROR.
+ * forget to terminate the argument list with 0 (or APR_SUCCESS).
*/
svn_error_t *
svn_cl__try(svn_error_t *err,