summaryrefslogtreecommitdiff
path: root/subversion/tests/libsvn_repos/dump-load-test.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/tests/libsvn_repos/dump-load-test.c')
-rw-r--r--subversion/tests/libsvn_repos/dump-load-test.c289
1 files changed, 289 insertions, 0 deletions
diff --git a/subversion/tests/libsvn_repos/dump-load-test.c b/subversion/tests/libsvn_repos/dump-load-test.c
new file mode 100644
index 0000000..3b6118d
--- /dev/null
+++ b/subversion/tests/libsvn_repos/dump-load-test.c
@@ -0,0 +1,289 @@
+/* dump-load-test.c --- tests for dumping and loading repositories
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <apr_pools.h>
+
+#include "svn_pools.h"
+#include "svn_error.h"
+#include "svn_fs.h"
+#include "svn_repos.h"
+#include "private/svn_repos_private.h"
+
+#include "../svn_test.h"
+#include "../svn_test_fs.h"
+
+
+
+/* Test dumping in the presence of the property PROP_NAME:PROP_VAL.
+ * Return the dumped data in *DUMP_DATA_P (if DUMP_DATA_P is not null).
+ * REPOS is an empty repository.
+ * See svn_repos_dump_fs3() for START_REV, END_REV, NOTIFY_FUNC, NOTIFY_BATON.
+ */
+static svn_error_t *
+test_dump_bad_props(svn_stringbuf_t **dump_data_p,
+ svn_repos_t *repos,
+ const char *prop_name,
+ const svn_string_t *prop_val,
+ svn_revnum_t start_rev,
+ svn_revnum_t end_rev,
+ svn_repos_notify_func_t notify_func,
+ void *notify_baton,
+ apr_pool_t *pool)
+{
+ const char *test_path = "/bar";
+ svn_fs_t *fs = svn_repos_fs(repos);
+ svn_fs_txn_t *txn;
+ svn_fs_root_t *txn_root;
+ svn_revnum_t youngest_rev = 0;
+ svn_stringbuf_t *dump_data = svn_stringbuf_create_empty(pool);
+ svn_stream_t *stream = svn_stream_from_stringbuf(dump_data, pool);
+ const char *expected_str;
+
+ /* Revision 1: Any commit will do, here */
+ SVN_ERR(svn_fs_begin_txn2(&txn, fs, youngest_rev, 0, pool));
+ SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+ SVN_ERR(svn_fs_make_dir(txn_root, test_path , pool));
+ SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool));
+ SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(youngest_rev));
+
+ /* Revision 2: Add the bad property */
+ SVN_ERR(svn_fs_begin_txn2(&txn, fs, youngest_rev, 0, pool));
+ SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+ SVN_ERR(svn_fs_change_node_prop(txn_root, test_path , prop_name, prop_val,
+ pool));
+ SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool));
+ SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(youngest_rev));
+
+ /* Test that a dump completes without error. */
+ SVN_ERR(svn_repos_dump_fs3(repos, stream, start_rev, end_rev,
+ FALSE, FALSE,
+ notify_func, notify_baton,
+ NULL, NULL,
+ pool));
+ svn_stream_close(stream);
+
+ /* Check that the property appears in the dump data */
+ expected_str = apr_psprintf(pool, "K %d\n%s\n"
+ "V %d\n%s\n"
+ "PROPS-END\n",
+ (int)strlen(prop_name), prop_name,
+ (int)prop_val->len, prop_val->data);
+ SVN_TEST_ASSERT(strstr(dump_data->data, expected_str));
+
+ if (dump_data_p)
+ *dump_data_p = dump_data;
+ return SVN_NO_ERROR;
+}
+
+/* Test loading in the presence of the property PROP_NAME:PROP_VAL.
+ * Load data from DUMP_DATA.
+ * REPOS is an empty repository.
+ */
+static svn_error_t *
+test_load_bad_props(svn_stringbuf_t *dump_data,
+ svn_repos_t *repos,
+ const char *prop_name,
+ const svn_string_t *prop_val,
+ const char *parent_fspath,
+ svn_boolean_t validate_props,
+ svn_repos_notify_func_t notify_func,
+ void *notify_baton,
+ apr_pool_t *pool)
+{
+ const char *test_path = apr_psprintf(pool, "%s%s",
+ parent_fspath ? parent_fspath : "",
+ "/bar");
+ svn_stream_t *stream = svn_stream_from_stringbuf(dump_data, pool);
+ svn_fs_t *fs;
+ svn_fs_root_t *rev_root;
+ svn_revnum_t youngest_rev;
+ svn_string_t *loaded_prop_val;
+
+ SVN_ERR(svn_repos_load_fs5(repos, stream,
+ SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
+ svn_repos_load_uuid_default,
+ parent_fspath,
+ FALSE, FALSE, /*use_*_commit_hook*/
+ validate_props,
+ FALSE /*ignore_dates*/,
+ notify_func, notify_baton,
+ NULL, NULL, /*cancellation*/
+ pool));
+ svn_stream_close(stream);
+
+ /* Check the loaded property */
+ fs = svn_repos_fs(repos);
+ SVN_ERR(svn_fs_youngest_rev(&youngest_rev, fs, pool));
+ SVN_ERR(svn_fs_revision_root(&rev_root, fs, youngest_rev, pool));
+ SVN_ERR(svn_fs_node_prop(&loaded_prop_val,
+ rev_root, test_path, prop_name, pool));
+ SVN_TEST_ASSERT(svn_string_compare(loaded_prop_val, prop_val));
+ return SVN_NO_ERROR;
+}
+
+/* Notification receiver for test_dump_r0_mergeinfo(). This does not
+ need to do anything, it just needs to exist.
+ */
+static void
+dump_r0_mergeinfo_notifier(void *baton,
+ const svn_repos_notify_t *notify,
+ apr_pool_t *scratch_pool)
+{
+}
+
+/* Regression test for the 'dump' part of issue #4476 "Mergeinfo
+ containing r0 makes svnsync and svnadmin dump fail". */
+static svn_error_t *
+test_dump_r0_mergeinfo(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ const char *prop_name = "svn:mergeinfo";
+ const svn_string_t *bad_mergeinfo = svn_string_create("/foo:0", pool);
+ svn_repos_t *repos;
+
+ SVN_ERR(svn_test__create_repos(&repos, "test-repo-dump-r0-mergeinfo",
+ opts, pool));
+ /* In order to exercise the
+ functionality under test -- that is, in order for the dump to try to
+ parse the mergeinfo it is dumping -- the dump must start from a
+ revision greater than 1 and must take a notification callback. */
+ SVN_ERR(test_dump_bad_props(NULL, repos,
+ prop_name, bad_mergeinfo,
+ 2, SVN_INVALID_REVNUM,
+ dump_r0_mergeinfo_notifier, NULL,
+ pool));
+
+ return SVN_NO_ERROR;
+}
+
+static void
+load_r0_mergeinfo_notifier(void *baton,
+ const svn_repos_notify_t *notify,
+ apr_pool_t *scratch_pool)
+{
+ svn_boolean_t *had_mergeinfo_warning = baton;
+
+ if (notify->action == svn_repos_notify_warning)
+ {
+ if (notify->warning == svn_repos_notify_warning_invalid_mergeinfo)
+ {
+ *had_mergeinfo_warning = TRUE;
+ }
+ }
+}
+
+/* Regression test for the 'load' part of issue #4476 "Mergeinfo
+ * containing r0 makes svnsync and svnadmin dump fail".
+ *
+ * Bad mergeinfo should not prevent loading a backup, at least when we do not
+ * require mergeinfo revision numbers or paths to be adjusted during loading.
+ */
+static svn_error_t *
+test_load_r0_mergeinfo(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ const char *prop_name = "svn:mergeinfo";
+ const svn_string_t *prop_val = svn_string_create("/foo:0", pool);
+ svn_stringbuf_t *dump_data = svn_stringbuf_create_empty(pool);
+
+ /* Produce a dump file containing bad mergeinfo */
+ {
+ svn_repos_t *repos;
+
+ SVN_ERR(svn_test__create_repos(&repos, "test-repo-load-r0-mi-1",
+ opts, pool));
+ SVN_ERR(test_dump_bad_props(&dump_data, repos,
+ prop_name, prop_val,
+ SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
+ NULL, NULL, pool));
+ }
+
+ /* Test loading without validating properties: should warn and succeed */
+ {
+ svn_repos_t *repos;
+ svn_boolean_t had_mergeinfo_warning = FALSE;
+
+ SVN_ERR(svn_test__create_repos(&repos, "test-repo-load-r0-mi-2",
+ opts, pool));
+
+ /* Without changing revision numbers or paths */
+ SVN_ERR(test_load_bad_props(dump_data, repos,
+ prop_name, prop_val,
+ NULL /*parent_dir*/, FALSE /*validate_props*/,
+ load_r0_mergeinfo_notifier, &had_mergeinfo_warning,
+ pool));
+ SVN_TEST_ASSERT(had_mergeinfo_warning);
+
+ /* With changing revision numbers and/or paths (by loading the same data
+ again, on top of existing revisions, into subdirectory 'bar') */
+ had_mergeinfo_warning = FALSE;
+ SVN_ERR(test_load_bad_props(dump_data, repos,
+ prop_name, prop_val,
+ "/bar", FALSE /*validate_props*/,
+ load_r0_mergeinfo_notifier, &had_mergeinfo_warning,
+ pool));
+ SVN_TEST_ASSERT(had_mergeinfo_warning);
+ }
+
+ /* Test loading with validating properties: should return an error */
+ {
+ svn_repos_t *repos;
+
+ SVN_ERR(svn_test__create_repos(&repos, "test-repo-load-r0-mi-3",
+ opts, pool));
+
+ /* Without changing revision numbers or paths */
+ SVN_TEST_ASSERT_ANY_ERROR(test_load_bad_props(dump_data, repos,
+ prop_name, prop_val,
+ NULL /*parent_dir*/, TRUE /*validate_props*/,
+ NULL, NULL,
+ pool));
+
+ /* With changing revision numbers and/or paths (by loading the same data
+ again, on top of existing revisions, into subdirectory 'bar') */
+ SVN_TEST_ASSERT_ANY_ERROR(test_load_bad_props(dump_data, repos,
+ prop_name, prop_val,
+ "/bar", TRUE /*validate_props*/,
+ NULL, NULL,
+ pool));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/* The test table. */
+
+static int max_threads = 4;
+
+static struct svn_test_descriptor_t test_funcs[] =
+ {
+ SVN_TEST_NULL,
+ SVN_TEST_OPTS_PASS(test_dump_r0_mergeinfo,
+ "test dumping with r0 mergeinfo"),
+ SVN_TEST_OPTS_PASS(test_load_r0_mergeinfo,
+ "test loading with r0 mergeinfo"),
+ SVN_TEST_NULL
+ };
+
+SVN_TEST_MAIN