diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-08-05 16:22:51 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-08-05 16:22:51 +0000 |
commit | cf46733632c7279a9fd0fe6ce26f9185a4ae82a9 (patch) | |
tree | da27775a2161723ef342e91af41a8b51fedef405 /subversion/tests/libsvn_repos/dump-load-test.c | |
parent | bb0ef45f7c46b0ae221b26265ef98a768c33f820 (diff) | |
download | subversion-tarball-master.tar.gz |
subversion-1.9.7HEADsubversion-1.9.7master
Diffstat (limited to 'subversion/tests/libsvn_repos/dump-load-test.c')
-rw-r--r-- | subversion/tests/libsvn_repos/dump-load-test.c | 289 |
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 |