summaryrefslogtreecommitdiff
path: root/subversion/tests/libsvn_repos/repos-test.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/tests/libsvn_repos/repos-test.c')
-rw-r--r--subversion/tests/libsvn_repos/repos-test.c843
1 files changed, 588 insertions, 255 deletions
diff --git a/subversion/tests/libsvn_repos/repos-test.c b/subversion/tests/libsvn_repos/repos-test.c
index 87265f0..8208958 100644
--- a/subversion/tests/libsvn_repos/repos-test.c
+++ b/subversion/tests/libsvn_repos/repos-test.c
@@ -36,13 +36,15 @@
#include "svn_config.h"
#include "svn_props.h"
#include "svn_version.h"
+#include "private/svn_repos_private.h"
+
+/* be able to look into svn_config_t */
+#include "../../libsvn_subr/config_impl.h"
#include "../svn_test_fs.h"
#include "dir-delta-editor.h"
-#include "private/svn_repos_private.h"
-
/* Used to terminate lines in large multi-line string literals. */
#define NL APR_EOL_STR
@@ -486,19 +488,19 @@ print_chrevs(const apr_array_header_t *revs_got,
outstr = apr_pstrcat(pool,
outstr,
apr_psprintf(pool, "%ld ", rev),
- (char *)NULL);
+ SVN_VA_NULL);
}
}
- outstr = apr_pstrcat(pool, outstr, "} Expected: { ", (char *)NULL);
+ outstr = apr_pstrcat(pool, outstr, "} Expected: { ", SVN_VA_NULL);
for (i = 0; i < num_revs_expected; i++)
{
outstr = apr_pstrcat(pool,
outstr,
apr_psprintf(pool, "%ld ",
revs_expected[i]),
- (char *)NULL);
+ SVN_VA_NULL);
}
- return apr_pstrcat(pool, outstr, "}", (char *)NULL);
+ return apr_pstrcat(pool, outstr, "}", SVN_VA_NULL);
}
@@ -1425,8 +1427,8 @@ in_repo_authz(const svn_test_opts_t *opts,
* Create an authz file and put it in the repository.
* Verify it can be read with an relative URL.
* Verify it can be read with an absolute URL.
- * Verify non-existant path does not error out when must_exist is FALSE.
- * Verify non-existant path does error out when must_exist is TRUE.
+ * Verify non-existent path does not error out when must_exist is FALSE.
+ * Verify non-existent path does error out when must_exist is TRUE.
* Verify that an http:// URL produces an error.
* Verify that an svn:// URL produces an error.
*/
@@ -1456,18 +1458,18 @@ in_repo_authz(const svn_test_opts_t *opts,
repos_root = svn_repos_path(repos, pool);
SVN_ERR(svn_uri_get_file_url_from_dirent(&repos_url, repos_root, pool));
- authz_url = apr_pstrcat(pool, repos_url, "/authz", (char *)NULL);
- noent_authz_url = apr_pstrcat(pool, repos_url, "/A/authz", (char *)NULL);
+ authz_url = svn_path_url_add_component2(repos_url, "authz", pool);
+ noent_authz_url = svn_path_url_add_component2(repos_url, "A/authz", pool);
/* absolute file URL. */
SVN_ERR(svn_repos_authz_read2(&authz_cfg, authz_url, NULL, TRUE, pool));
SVN_ERR(authz_check_access(authz_cfg, test_set, pool));
- /* Non-existant path in the repo with must_exist set to FALSE */
+ /* Non-existent path in the repo with must_exist set to FALSE */
SVN_ERR(svn_repos_authz_read2(&authz_cfg, noent_authz_url, NULL,
FALSE, pool));
- /* Non-existant path in the repo with must_exist set to TRUE */
+ /* Non-existent path in the repo with must_exist set to TRUE */
err = svn_repos_authz_read2(&authz_cfg, noent_authz_url, NULL, TRUE, pool);
if (!err || err->apr_err != SVN_ERR_ILLEGAL_TARGET)
return svn_error_createf(SVN_ERR_TEST_FAILED, err,
@@ -1595,15 +1597,14 @@ in_repo_groups_authz(const svn_test_opts_t *opts,
/* Calculate URLs */
repos_root = svn_repos_path(repos, pool);
SVN_ERR(svn_uri_get_file_url_from_dirent(&repos_url, repos_root, pool));
- authz_url = apr_pstrcat(pool, repos_url, "/authz", (char *)NULL);
- empty_authz_url = apr_pstrcat(pool, repos_url, "/empty-authz", (char *)NULL);
- noent_authz_url = apr_pstrcat(pool, repos_url, "/A/authz", (char *)NULL);
- groups_url = apr_pstrcat(pool, repos_url, "/groups", (char *)NULL);
- noent_groups_url = apr_pstrcat(pool, repos_url, "/A/groups", (char *)NULL);
+ authz_url = svn_path_url_add_component2(repos_url, "authz", pool);
+ empty_authz_url = svn_path_url_add_component2(repos_url, "empty-authz", pool);
+ noent_authz_url = svn_path_url_add_component2(repos_url, "A/authz", pool);
+ groups_url = svn_path_url_add_component2(repos_url, "groups", pool);
+ noent_groups_url = svn_path_url_add_component2(repos_url, "A/groups", pool);
/* absolute file URLs. */
- groups_url = apr_pstrcat(pool, repos_url, "/groups", (char *)NULL);
SVN_ERR(svn_repos_authz_read2(&authz_cfg, authz_url, groups_url, TRUE, pool));
SVN_ERR(authz_check_access(authz_cfg, test_set, pool));
@@ -1656,7 +1657,7 @@ in_repo_groups_authz(const svn_test_opts_t *opts,
/* Helper for the groups_authz test. Set *AUTHZ_P to a representation of
- AUTHZ_CONTENTS in conjuction with GROUPS_CONTENTS, using POOL for
+ AUTHZ_CONTENTS in conjunction with GROUPS_CONTENTS, using POOL for
temporary allocation. If DISK is TRUE then write the contents to
temporary files and use svn_repos_authz_read2() to get the data if FALSE
write the data to a buffered stream and use svn_repos_authz_parse(). */
@@ -1771,7 +1772,7 @@ groups_authz(const svn_test_opts_t *opts,
* 2. Verify that access rights written in the global groups file are
* discarded and affect nothing in authorization terms.
* 3. Verify that local groups in the authz file are prohibited in
- * conjuction with global groups (and that a configuration error is
+ * conjunction with global groups (and that a configuration error is
* reported in this scenario).
* 4. Ensure that group cycles in the global groups file are reported.
*
@@ -1827,7 +1828,7 @@ groups_authz(const svn_test_opts_t *opts,
SVN_ERR(authz_check_access(authz_cfg, test_set2, pool));
- /* Local groups cannot be used in conjuction with global groups. */
+ /* Local groups cannot be used in conjunction with global groups. */
groups_contents =
"[groups]" NL
"slaves = maximus" NL
@@ -2460,7 +2461,8 @@ node_location_segments(const svn_test_opts_t *opts,
/* Bail (with success) on known-untestable scenarios */
if ((strcmp(opts->fs_type, "bdb") == 0)
&& (opts->server_minor_version == 4))
- return SVN_NO_ERROR;
+ return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL,
+ "not supported for BDB in SVN 1.4");
/* Create the repository. */
SVN_ERR(svn_test__create_repos(&repos, "test-repo-node-location-segments",
@@ -2886,7 +2888,7 @@ log_receiver(void *baton,
svn_log_entry_t *log_entry,
apr_pool_t *pool)
{
- int *count = baton;
+ svn_revnum_t *count = baton;
(*count)++;
return SVN_NO_ERROR;
}
@@ -2944,13 +2946,18 @@ get_logs(const svn_test_opts_t *opts,
svn_revnum_t end_arg = end ? end : SVN_INVALID_REVNUM;
svn_revnum_t eff_start = start ? start : youngest_rev;
svn_revnum_t eff_end = end ? end : youngest_rev;
- int limit, max_logs =
+ int limit;
+ svn_revnum_t max_logs =
MAX(eff_start, eff_end) + 1 - MIN(eff_start, eff_end);
- int num_logs;
+ svn_revnum_t num_logs;
+ /* this may look like it can get in an infinite loop if max_logs
+ * ended up being larger than the size limit can represent. It
+ * can't because a negative limit will end up failing to match
+ * the existed number of logs. */
for (limit = 0; limit <= max_logs; limit++)
{
- int num_expected = limit ? limit : max_logs;
+ svn_revnum_t num_expected = limit ? limit : max_logs;
svn_pool_clear(subpool);
num_logs = 0;
@@ -2961,9 +2968,9 @@ get_logs(const svn_test_opts_t *opts,
if (num_logs != num_expected)
return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
"Log with start=%ld,end=%ld,limit=%d "
- "returned %d entries (expected %d)",
+ "returned %ld entries (expected %ld)",
start_arg, end_arg, limit,
- num_logs, max_logs);
+ num_logs, num_expected);
}
}
}
@@ -3059,6 +3066,11 @@ test_get_file_revs(const svn_test_opts_t *opts,
apr_hash_set(ht_reverse_results, &trunk_results[i].rev,
sizeof(svn_revnum_t), &trunk_results[i]);
+ /* Check for feature support */
+ if (opts->server_minor_version && (opts->server_minor_version < 5))
+ return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL,
+ "not supported in pre-1.5 SVN");
+
/* Create the repository and verify blame results. */
SVN_ERR(svn_test__create_blame_repository(&repos, "test-repo-get-filerevs",
opts, subpool));
@@ -3167,7 +3179,26 @@ test_delete_repos(const svn_test_opts_t *opts,
return SVN_NO_ERROR;
}
-/* Related to issue 4340, "fs layer should reject filenames with trailing \n" */
+/* Prepare a commit for the filename_with_control_chars() tests */
+static svn_error_t *
+fwcc_prepare(const svn_delta_editor_t **editor_p,
+ void **edit_baton_p,
+ void **root_baton,
+ svn_repos_t *repos,
+ apr_pool_t *scratch_pool)
+{
+ /* Checks for control characters are implemented in the commit editor,
+ * not in the FS API. */
+ SVN_ERR(svn_repos_get_commit_editor4(editor_p, edit_baton_p, repos,
+ NULL, "file://test", "/",
+ "plato", "test commit",
+ dummy_commit_cb, NULL, NULL, NULL,
+ scratch_pool));
+ SVN_ERR((*editor_p)->open_root(*edit_baton_p, 1, scratch_pool, root_baton));
+ return SVN_NO_ERROR;
+}
+
+/* Related to issue 4340, "filenames containing \n corrupt FSFS repositories" */
static svn_error_t *
filename_with_control_chars(const svn_test_opts_t *opts,
apr_pool_t *pool)
@@ -3206,17 +3237,6 @@ filename_with_control_chars(const svn_test_opts_t *opts,
SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(youngest_rev));
svn_pool_clear(subpool);
- /* Checks for control characters are implemented in the commit editor,
- * not in the FS API. */
- SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, pool));
- SVN_ERR(svn_repos_get_commit_editor4(&editor, &edit_baton, repos,
- txn, "file://test", "/",
- "plato", "test commit",
- dummy_commit_cb, NULL, NULL, NULL,
- pool));
-
- SVN_ERR(editor->open_root(edit_baton, 1, pool, &root_baton));
-
/* Attempt to copy /foo to a bad path P. This should fail. */
i = 0;
do
@@ -3225,8 +3245,13 @@ filename_with_control_chars(const svn_test_opts_t *opts,
if (p == NULL)
break;
svn_pool_clear(subpool);
+
+ SVN_ERR(fwcc_prepare(&editor, &edit_baton, &root_baton, repos, subpool));
err = editor->add_directory(p, root_baton, "/foo", 1, subpool,
&out_baton);
+ if (!err)
+ err = editor->close_edit(edit_baton, subpool);
+ svn_error_clear(editor->abort_edit(edit_baton, subpool));
SVN_TEST_ASSERT_ERROR(err, SVN_ERR_FS_PATH_SYNTAX);
} while (p);
@@ -3238,8 +3263,13 @@ filename_with_control_chars(const svn_test_opts_t *opts,
if (p == NULL)
break;
svn_pool_clear(subpool);
+
+ SVN_ERR(fwcc_prepare(&editor, &edit_baton, &root_baton, repos, subpool));
err = editor->add_file(p, root_baton, NULL, SVN_INVALID_REVNUM,
subpool, &out_baton);
+ if (!err)
+ err = editor->close_edit(edit_baton, subpool);
+ svn_error_clear(editor->abort_edit(edit_baton, subpool));
SVN_TEST_ASSERT_ERROR(err, SVN_ERR_FS_PATH_SYNTAX);
} while (p);
@@ -3252,281 +3282,576 @@ filename_with_control_chars(const svn_test_opts_t *opts,
if (p == NULL)
break;
svn_pool_clear(subpool);
+
+ SVN_ERR(fwcc_prepare(&editor, &edit_baton, &root_baton, repos, subpool));
err = editor->add_directory(p, root_baton, NULL, SVN_INVALID_REVNUM,
subpool, &out_baton);
+ if (!err)
+ err = editor->close_edit(edit_baton, subpool);
+ svn_error_clear(editor->abort_edit(edit_baton, subpool));
SVN_TEST_ASSERT_ERROR(err, SVN_ERR_FS_PATH_SYNTAX);
} while (p);
- SVN_ERR(editor->abort_edit(edit_baton, subpool));
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_repos_info(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ svn_repos_t *repos;
+ svn_test_opts_t opts2;
+ apr_hash_t *capabilities;
+ svn_version_t *supports_version;
+ svn_version_t v1_0_0 = {1, 0, 0, ""};
+ svn_version_t v1_4_0 = {1, 4, 0, ""};
+ int repos_format;
+ svn_boolean_t is_fsx = strcmp(opts->fs_type, "fsx") == 0;
+
+ opts2 = *opts;
+
+ /* for repo types that have been around before 1.4 */
+ if (!is_fsx)
+ {
+ opts2.server_minor_version = 3;
+ SVN_ERR(svn_test__create_repos(&repos, "test-repo-info-3",
+ &opts2, pool));
+ SVN_ERR(svn_repos_capabilities(&capabilities, repos, pool, pool));
+ SVN_TEST_ASSERT(apr_hash_count(capabilities) == 0);
+ SVN_ERR(svn_repos_info_format(&repos_format, &supports_version, repos,
+ pool, pool));
+ SVN_TEST_ASSERT(repos_format == 3);
+ SVN_TEST_ASSERT(svn_ver_equal(supports_version, &v1_0_0));
+ }
+
+ opts2.server_minor_version = 9;
+ SVN_ERR(svn_test__create_repos(&repos, "test-repo-info-9",
+ &opts2, pool));
+ SVN_ERR(svn_repos_capabilities(&capabilities, repos, pool, pool));
+ SVN_TEST_ASSERT(apr_hash_count(capabilities) == 1);
+ SVN_TEST_ASSERT(svn_hash_gets(capabilities, SVN_REPOS_CAPABILITY_MERGEINFO));
+ SVN_ERR(svn_repos_info_format(&repos_format, &supports_version, repos,
+ pool, pool));
+ SVN_TEST_ASSERT(repos_format == 5);
+ SVN_TEST_ASSERT(svn_ver_equal(supports_version, &v1_4_0));
return SVN_NO_ERROR;
}
-
-/* Notification receiver for test_dump_bad_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)
+static svn_error_t *
+test_config_pool(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ const char *repo_name = "test-repo-config-pool";
+ svn_repos_t *repos;
+ svn_stringbuf_t *cfg_buffer1, *cfg_buffer2;
+ svn_config_t *cfg;
+ apr_hash_t *sections1, *sections2;
+ int i;
+ svn_fs_txn_t *txn;
+ svn_fs_root_t *root, *rev_root;
+ svn_revnum_t rev;
+ const char *repo_root_url;
+ const char *srcdir;
+ svn_error_t *err;
+
+ svn_repos__config_pool_t *config_pool;
+ apr_pool_t *config_pool_pool;
+ apr_pool_t *subpool = svn_pool_create(pool);
+
+ const char *wrk_dir = svn_test_data_path("config_pool", pool);
+
+ SVN_ERR(svn_io_make_dir_recursively(wrk_dir, pool));
+
+ /* read all config info through a single config pool and we want to be
+ able to control its lifetime. The latter requires a separate pool. */
+ config_pool_pool = svn_pool_create(pool);
+ SVN_ERR(svn_repos__config_pool_create(&config_pool, TRUE,
+ config_pool_pool));
+
+ /* have two different configurations */
+ SVN_ERR(svn_test_get_srcdir(&srcdir, opts, pool));
+ SVN_ERR(svn_stringbuf_from_file2(
+ &cfg_buffer1,
+ svn_dirent_join(srcdir,
+ "../libsvn_subr/config-test.cfg",
+ pool),
+ pool));
+ cfg_buffer2 = svn_stringbuf_dup(cfg_buffer1, pool);
+ svn_stringbuf_appendcstr(cfg_buffer2, "\n[more]\nU=\"X\"\n");
+
+ /* write them to 2x2 files */
+ SVN_ERR(svn_io_write_atomic(svn_dirent_join(wrk_dir,
+ "config-pool-test1.cfg",
+ pool),
+ cfg_buffer1->data, cfg_buffer1->len, NULL,
+ pool));
+ SVN_ERR(svn_io_write_atomic(svn_dirent_join(wrk_dir,
+ "config-pool-test2.cfg",
+ pool),
+ cfg_buffer1->data, cfg_buffer1->len, NULL,
+ pool));
+ SVN_ERR(svn_io_write_atomic(svn_dirent_join(wrk_dir,
+ "config-pool-test3.cfg",
+ pool),
+ cfg_buffer2->data, cfg_buffer2->len, NULL,
+ pool));
+ SVN_ERR(svn_io_write_atomic(svn_dirent_join(wrk_dir,
+ "config-pool-test4.cfg",
+ pool),
+ cfg_buffer2->data, cfg_buffer2->len, NULL,
+ pool));
+
+ /* requesting a config over and over again should return the same
+ (even though it is not being referenced) */
+ sections1 = NULL;
+ for (i = 0; i < 4; ++i)
+ {
+ SVN_ERR(svn_repos__config_pool_get(
+ &cfg, NULL, config_pool,
+ svn_dirent_join(wrk_dir,
+ "config-pool-test1.cfg",
+ pool),
+ TRUE, TRUE, NULL, subpool));
+
+ if (sections1 == NULL)
+ sections1 = cfg->sections;
+ else
+ SVN_TEST_ASSERT(cfg->sections == sections1);
+
+ svn_pool_clear(subpool);
+ }
+
+ /* requesting the same config from another file should return the same
+ (even though it is not being referenced) */
+ for (i = 0; i < 4; ++i)
+ {
+ SVN_ERR(svn_repos__config_pool_get(
+ &cfg, NULL, config_pool,
+ svn_dirent_join(wrk_dir,
+ "config-pool-test2.cfg",
+ pool),
+ TRUE, TRUE, NULL, subpool));
+
+ SVN_TEST_ASSERT(cfg->sections == sections1);
+
+ svn_pool_clear(subpool);
+ }
+
+ /* reading a different configuration should return a different pointer */
+ sections2 = NULL;
+ for (i = 0; i < 2; ++i)
+ {
+ SVN_ERR(svn_repos__config_pool_get(
+ &cfg, NULL, config_pool,
+ svn_dirent_join(wrk_dir,
+ "config-pool-test3.cfg",
+ pool),
+ TRUE, TRUE, NULL, subpool));
+
+ if (sections2 == NULL)
+ sections2 = cfg->sections;
+ else
+ SVN_TEST_ASSERT(cfg->sections == sections2);
+
+ SVN_TEST_ASSERT(sections1 != sections2);
+ svn_pool_clear(subpool);
+ }
+
+ /* create an in-repo config */
+ SVN_ERR(svn_dirent_get_absolute(&repo_root_url, repo_name, pool));
+ SVN_ERR(svn_uri_get_file_url_from_dirent(&repo_root_url, repo_root_url,
+ pool));
+
+ SVN_ERR(svn_test__create_repos(&repos, repo_name, opts, pool));
+ SVN_ERR(svn_fs_begin_txn2(&txn, svn_repos_fs(repos), 0, 0, pool));
+ SVN_ERR(svn_fs_txn_root(&root, txn, pool));
+ SVN_ERR(svn_fs_make_dir(root, "dir", pool));
+ SVN_ERR(svn_fs_make_file(root, "dir/config", pool));
+ SVN_ERR(svn_test__set_file_contents(root, "dir/config",
+ cfg_buffer1->data, pool));
+ SVN_ERR(svn_fs_commit_txn(NULL, &rev, txn, pool));
+
+ /* reading the config from the repo should still give cfg1 */
+ SVN_ERR(svn_repos__config_pool_get(&cfg, NULL, config_pool,
+ svn_path_url_add_component2(
+ repo_root_url,
+ "dir/config", pool),
+ TRUE, TRUE, NULL, subpool));
+ SVN_TEST_ASSERT(cfg->sections == sections1);
+ svn_pool_clear(subpool);
+
+ /* create another in-repo config */
+ SVN_ERR(svn_fs_begin_txn2(&txn, svn_repos_fs(repos), rev, 0, pool));
+ SVN_ERR(svn_fs_txn_root(&root, txn, pool));
+ SVN_ERR(svn_fs_revision_root(&rev_root, svn_repos_fs(repos), rev, pool));
+ SVN_ERR(svn_fs_copy(rev_root, "dir", root, "another-dir", pool));
+ SVN_ERR(svn_test__set_file_contents(root, "dir/config",
+ cfg_buffer2->data, pool));
+ SVN_ERR(svn_fs_commit_txn(NULL, &rev, txn, pool));
+
+ /* reading the config from the repo should give cfg2 now */
+ SVN_ERR(svn_repos__config_pool_get(&cfg, NULL, config_pool,
+ svn_path_url_add_component2(
+ repo_root_url,
+ "dir/config", pool),
+ TRUE, TRUE, NULL, subpool));
+ SVN_TEST_ASSERT(cfg->sections == sections2);
+ svn_pool_clear(subpool);
+
+ /* reading the copied config should still give cfg1 */
+ SVN_ERR(svn_repos__config_pool_get(&cfg, NULL, config_pool,
+ svn_path_url_add_component2(
+ repo_root_url,
+ "another-dir/config",
+ pool),
+ TRUE, TRUE, NULL, subpool));
+ SVN_TEST_ASSERT(cfg->sections == sections1);
+ svn_pool_clear(subpool);
+
+ /* once again: repeated reads. This triggers a different code path. */
+ SVN_ERR(svn_repos__config_pool_get(&cfg, NULL, config_pool,
+ svn_path_url_add_component2(
+ repo_root_url,
+ "dir/config", pool),
+ TRUE, TRUE, NULL, subpool));
+ SVN_TEST_ASSERT(cfg->sections == sections2);
+ SVN_ERR(svn_repos__config_pool_get(&cfg, NULL, config_pool,
+ svn_path_url_add_component2(
+ repo_root_url,
+ "another-dir/config",
+ pool),
+ TRUE, TRUE, NULL, subpool));
+ SVN_TEST_ASSERT(cfg->sections == sections1);
+ svn_pool_clear(subpool);
+
+ /* access paths that don't exist */
+ SVN_TEST_ASSERT_ERROR(svn_repos__config_pool_get(&cfg, NULL, config_pool,
+ svn_path_url_add_component2(repo_root_url, "X",
+ pool),
+ TRUE, TRUE, NULL, subpool),
+ SVN_ERR_ILLEGAL_TARGET);
+ err = svn_repos__config_pool_get(&cfg, NULL, config_pool, "X.cfg",
+ TRUE, TRUE, NULL, subpool);
+ SVN_TEST_ASSERT(err && APR_STATUS_IS_ENOENT(err->apr_err));
+ svn_error_clear(err);
+ svn_pool_clear(subpool);
+
+ return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+test_repos_fs_type(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
{
+ svn_repos_t *repos;
+
+ /* Create test repository. */
+ SVN_ERR(svn_test__create_repos(&repos, "test-repo-repos_fs_type",
+ opts, pool));
+
+ SVN_TEST_STRING_ASSERT(svn_repos_fs_type(repos, pool), opts->fs_type);
+
+ /* Re-open repository and verify fs-type again. */
+ SVN_ERR(svn_repos_open3(&repos, svn_repos_path(repos, pool), NULL,
+ pool, pool));
+
+ SVN_TEST_STRING_ASSERT(svn_repos_fs_type(repos, pool), opts->fs_type);
+
+ return SVN_NO_ERROR;
}
-/* Regression test for part 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)
+deprecated_access_context_api(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
{
svn_repos_t *repos;
- svn_fs_t *fs;
+ svn_fs_access_t *access;
svn_fs_txn_t *txn;
- svn_fs_root_t *txn_root;
- svn_revnum_t youngest_rev = 0;
- const svn_string_t *bad_mergeinfo = svn_string_create("/foo:0", pool);
+ svn_fs_root_t *root;
+ const char *conflict;
+ svn_revnum_t new_rev;
+ const char *hook;
- SVN_ERR(svn_test__create_repos(&repos, "test-repo-dump-r0-mergeinfo",
+ /* Create test repository. */
+ SVN_ERR(svn_test__create_repos(&repos,
+ "test-repo-deprecated-access-context-api",
opts, pool));
- fs = svn_repos_fs(repos);
- /* Revision 1: Any commit will do, here */
- SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, pool));
- SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
- SVN_ERR(svn_fs_make_dir(txn_root, "/bar", pool));
- SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool));
- SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(youngest_rev));
+ /* Set an empty pre-commit hook. */
+#ifdef WIN32
+ hook = apr_pstrcat(pool, svn_repos_pre_commit_hook(repos, pool), ".bat",
+ SVN_VA_NULL);
+ SVN_ERR(svn_io_file_create(hook,
+ "exit 0" APR_EOL_STR,
+ pool));
+#else
+ hook = svn_repos_pre_commit_hook(repos, pool);
+ SVN_ERR(svn_io_file_create(hook,
+ "#!/bin/sh" APR_EOL_STR "exit 0" APR_EOL_STR,
+ pool));
+ SVN_ERR(svn_io_set_file_executable(hook, TRUE, FALSE, pool));
+#endif
- /* Revision 2: Add bad mergeinfo */
- SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, pool));
- SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
- SVN_ERR(svn_fs_change_node_prop(txn_root, "/bar", "svn:mergeinfo", bad_mergeinfo, pool));
- SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool));
- SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(youngest_rev));
+ /* Set some access context using svn_fs_access_add_lock_token(). */
+ SVN_ERR(svn_fs_create_access(&access, "jrandom", pool));
+ SVN_ERR(svn_fs_access_add_lock_token(access, "opaquelocktoken:abc"));
+ SVN_ERR(svn_fs_set_access(svn_repos_fs(repos), access));
- /* Test that a dump completes without error. 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_stringbuf_t *stringbuf = svn_stringbuf_create_empty(pool);
- svn_stream_t *stream = svn_stream_from_stringbuf(stringbuf, pool);
-
- SVN_ERR(svn_repos_dump_fs3(repos, stream, 2, SVN_INVALID_REVNUM,
- FALSE, FALSE,
- dump_r0_mergeinfo_notifier, NULL,
- NULL, NULL,
- pool));
- }
+ /* Commit a new revision. */
+ SVN_ERR(svn_repos_fs_begin_txn_for_commit2(&txn, repos, 0,
+ apr_hash_make(pool), pool));
+ SVN_ERR(svn_fs_txn_root(&root, txn, pool));
+ SVN_ERR(svn_fs_make_dir(root, "/whatever", pool));
+ SVN_ERR(svn_repos_fs_commit_txn(&conflict, repos, &new_rev, txn, pool));
+
+ SVN_TEST_STRING_ASSERT(conflict, NULL);
+ SVN_TEST_ASSERT(new_rev == 1);
return SVN_NO_ERROR;
}
-
-/* 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)
+mkdir_delete_copy(svn_repos_t *repos,
+ const char *src,
+ const char *dst,
+ apr_pool_t *pool)
{
- const char *test_path = "/bar";
svn_fs_t *fs = svn_repos_fs(repos);
+ svn_revnum_t youngest_rev;
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;
+ svn_fs_root_t *txn_root, *rev_root;
- /* Revision 1: Any commit will do, here */
- SVN_ERR(svn_fs_begin_txn2(&txn, fs, youngest_rev, 0, pool));
+ SVN_ERR(svn_fs_youngest_rev(&youngest_rev, fs, pool));
+
+ SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, 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_fs_make_dir(txn_root, "A/T", pool));
+ SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool));
+
+ SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, pool));
+ SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+ SVN_ERR(svn_fs_delete(txn_root, "A/T", 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_begin_txn(&txn, fs, youngest_rev, 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_fs_revision_root(&rev_root, fs, youngest_rev - 1, pool));
+ SVN_ERR(svn_fs_copy(rev_root, src, txn_root, dst, 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.
- */
+struct authz_read_baton_t {
+ apr_hash_t *paths;
+ apr_pool_t *pool;
+ const char *deny;
+};
+
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)
+authz_read_func(svn_boolean_t *allowed,
+ svn_fs_root_t *root,
+ const char *path,
+ void *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_fs4(repos, stream,
- SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
- svn_repos_load_uuid_default,
- parent_fspath,
- FALSE, FALSE, /*use_*_commit_hook*/
- validate_props,
- notify_func, notify_baton,
- NULL, NULL, /*cancellation*/
- pool));
- svn_stream_close(stream);
+ struct authz_read_baton_t *b = baton;
+
+ if (b->deny && !strcmp(b->deny, path))
+ *allowed = FALSE;
+ else
+ *allowed = TRUE;
+
+ svn_hash_sets(b->paths, apr_pstrdup(b->pool, path), (void*)1);
- /* 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;
}
-static void
-load_r0_mergeinfo_notifier(void *baton,
- const svn_repos_notify_t *notify,
- apr_pool_t *scratch_pool)
+static svn_error_t *
+verify_locations(apr_hash_t *actual,
+ apr_hash_t *expected,
+ apr_hash_t *checked,
+ apr_pool_t *pool)
{
- svn_boolean_t *had_mergeinfo_warning = baton;
+ apr_hash_index_t *hi;
- if (notify->action == svn_repos_notify_warning)
+ for (hi = apr_hash_first(pool, expected); hi; hi = apr_hash_next(hi))
{
- if (notify->warning == svn_repos__notify_warning_invalid_mergeinfo)
- {
- *had_mergeinfo_warning = TRUE;
- }
+ const svn_revnum_t *rev = apr_hash_this_key(hi);
+ const char *path = apr_hash_get(actual, rev, sizeof(svn_revnum_t));
+
+ if (!path)
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "expected %s for %d found (null)",
+ (char*)apr_hash_this_val(hi), (int)*rev);
+ else if (strcmp(path, apr_hash_this_val(hi)))
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "expected %s for %d found %s",
+ (char*)apr_hash_this_val(hi), (int)*rev, path);
+
}
+
+ for (hi = apr_hash_first(pool, actual); hi; hi = apr_hash_next(hi))
+ {
+ const svn_revnum_t *rev = apr_hash_this_key(hi);
+ const char *path = apr_hash_get(expected, rev, sizeof(svn_revnum_t));
+
+ if (!path)
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "found %s for %d expected (null)",
+ (char*)apr_hash_this_val(hi), (int)*rev);
+ else if (strcmp(path, apr_hash_this_val(hi)))
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "found %s for %d expected %s",
+ (char*)apr_hash_this_val(hi), (int)*rev, path);
+
+ if (!svn_hash_gets(checked, path))
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "did not check %s", path);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static void
+set_expected(apr_hash_t *expected,
+ svn_revnum_t rev,
+ const char *path,
+ apr_pool_t *pool)
+{
+ svn_revnum_t *rp = apr_palloc(pool, sizeof(svn_revnum_t));
+ *rp = rev;
+ apr_hash_set(expected, rp, sizeof(svn_revnum_t), path);
}
-/* 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)
+trace_node_locations_authz(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);
+ svn_repos_t *repos;
+ svn_fs_t *fs;
+ svn_revnum_t youngest_rev = 0;
+ svn_fs_txn_t *txn;
+ svn_fs_root_t *txn_root;
+ struct authz_read_baton_t arb;
+ apr_array_header_t *revs = apr_array_make(pool, 10, sizeof(svn_revnum_t));
+ apr_hash_t *locations;
+ apr_hash_t *expected = apr_hash_make(pool);
+ int i;
- /* Produce a dump file containing bad mergeinfo */
- {
- svn_repos_t *repos;
+ /* Create test repository. */
+ SVN_ERR(svn_test__create_repos(&repos, "test-repo-trace-node-locations-authz",
+ opts, pool));
+ fs = svn_repos_fs(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));
- }
+ /* r1 create A */
+ SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, pool));
+ SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+ SVN_ERR(svn_fs_make_dir(txn_root, "A", pool));
+ SVN_ERR(svn_fs_make_file(txn_root, "A/f", pool));
+ SVN_ERR(svn_test__set_file_contents(txn_root, "A/f", "foobar", pool));
+ SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, 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);
- }
+ /* r4 copy A to B */
+ SVN_ERR(mkdir_delete_copy(repos, "A", "B", pool));
- /* Test loading with validating properties: should return an error */
- {
- svn_repos_t *repos;
+ /* r7 copy B to C */
+ SVN_ERR(mkdir_delete_copy(repos, "B", "C", pool));
- 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));
- }
+ /* r10 copy C to D */
+ SVN_ERR(mkdir_delete_copy(repos, "C", "D", pool));
+
+ SVN_ERR(svn_fs_youngest_rev(&youngest_rev, fs, pool));
+ SVN_ERR_ASSERT(youngest_rev == 10);
+
+ arb.paths = apr_hash_make(pool);
+ arb.pool = pool;
+ arb.deny = NULL;
+
+ apr_array_clear(revs);
+ for (i = 0; i <= youngest_rev; ++i)
+ APR_ARRAY_PUSH(revs, svn_revnum_t) = i;
+ set_expected(expected, 10, "/D/f", pool);
+ set_expected(expected, 8, "/C/f", pool);
+ set_expected(expected, 7, "/C/f", pool);
+ set_expected(expected, 5, "/B/f", pool);
+ set_expected(expected, 4, "/B/f", pool);
+ set_expected(expected, 2, "/A/f", pool);
+ set_expected(expected, 1, "/A/f", pool);
+ apr_hash_clear(arb.paths);
+ SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs,
+ authz_read_func, &arb, pool));
+ SVN_ERR(verify_locations(locations, expected, arb.paths, pool));
+
+ apr_array_clear(revs);
+ for (i = 1; i <= youngest_rev; ++i)
+ APR_ARRAY_PUSH(revs, svn_revnum_t) = i;
+ apr_hash_clear(arb.paths);
+ SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs,
+ authz_read_func, &arb, pool));
+ SVN_ERR(verify_locations(locations, expected, arb.paths, pool));
+
+ apr_array_clear(revs);
+ for (i = 2; i <= youngest_rev; ++i)
+ APR_ARRAY_PUSH(revs, svn_revnum_t) = i;
+ set_expected(expected, 1, NULL, pool);
+ apr_hash_clear(arb.paths);
+ SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs,
+ authz_read_func, &arb, pool));
+ SVN_ERR(verify_locations(locations, expected, arb.paths, pool));
+
+ apr_array_clear(revs);
+ for (i = 3; i <= youngest_rev; ++i)
+ APR_ARRAY_PUSH(revs, svn_revnum_t) = i;
+ set_expected(expected, 2, NULL, pool);
+ apr_hash_clear(arb.paths);
+ SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs,
+ authz_read_func, &arb, pool));
+ SVN_ERR(verify_locations(locations, expected, arb.paths, pool));
+
+ apr_array_clear(revs);
+ for (i = 6; i <= youngest_rev; ++i)
+ APR_ARRAY_PUSH(revs, svn_revnum_t) = i;
+ set_expected(expected, 5, NULL, pool);
+ set_expected(expected, 4, NULL, pool);
+ apr_hash_clear(arb.paths);
+ SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs,
+ authz_read_func, &arb, pool));
+ SVN_ERR(verify_locations(locations, expected, arb.paths, pool));
+
+ arb.deny = "/B/f";
+ apr_array_clear(revs);
+ for (i = 0; i <= youngest_rev; ++i)
+ APR_ARRAY_PUSH(revs, svn_revnum_t) = i;
+ apr_hash_clear(arb.paths);
+ SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs,
+ authz_read_func, &arb, pool));
+ SVN_ERR(verify_locations(locations, expected, arb.paths, pool));
+
+ apr_array_clear(revs);
+ for (i = 6; i <= youngest_rev; ++i)
+ APR_ARRAY_PUSH(revs, svn_revnum_t) = i;
+ apr_hash_clear(arb.paths);
+ SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs,
+ authz_read_func, &arb, pool));
+ SVN_ERR(verify_locations(locations, expected, arb.paths, pool));
+
+ APR_ARRAY_PUSH(revs, svn_revnum_t) = 0;
+ apr_hash_clear(arb.paths);
+ SVN_ERR(svn_repos_trace_node_locations(fs, &locations, "D/f", 10, revs,
+ authz_read_func, &arb, pool));
+ SVN_ERR(verify_locations(locations, expected, arb.paths, pool));
return SVN_NO_ERROR;
}
/* The test table. */
-struct svn_test_descriptor_t test_funcs[] =
+static int max_threads = 4;
+
+static struct svn_test_descriptor_t test_funcs[] =
{
SVN_TEST_NULL,
SVN_TEST_OPTS_PASS(dir_deltas,
@@ -3569,9 +3894,17 @@ struct svn_test_descriptor_t test_funcs[] =
"test svn_repos_delete"),
SVN_TEST_OPTS_PASS(filename_with_control_chars,
"test filenames with control characters"),
- 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_OPTS_PASS(test_repos_info,
+ "test svn_repos_info_*"),
+ SVN_TEST_OPTS_PASS(test_config_pool,
+ "test svn_repos__config_pool_*"),
+ SVN_TEST_OPTS_PASS(test_repos_fs_type,
+ "test test_repos_fs_type"),
+ SVN_TEST_OPTS_PASS(deprecated_access_context_api,
+ "test deprecated access context api"),
+ SVN_TEST_OPTS_PASS(trace_node_locations_authz,
+ "authz for svn_repos_trace_node_locations"),
SVN_TEST_NULL
};
+
+SVN_TEST_MAIN