📄 repos-test.c
字号:
struct locations_info{ svn_revnum_t rev; const char *path;};/* Check that LOCATIONS contain everything in INFO and nothing more. */static svn_error_t *check_locations_info(apr_hash_t *locations, const struct locations_info *info){ unsigned int i; for (i = 0; info->rev != 0; ++i, ++info) { const char *p = apr_hash_get(locations, &info->rev, sizeof (svn_revnum_t)); if (!p) return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, "Missing path for revision %ld", info->rev); if (strcmp(p, info->path) != 0) return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, "Pth mismatch for rev %ld", info->rev); } if (apr_hash_count(locations) > i) return svn_error_create(SVN_ERR_TEST_FAILED, NULL, "Returned locations contain too many elements."); return SVN_NO_ERROR;}/* Check that all locations in INFO exist in REPOS for PATH and PEG_REVISION. */static svn_error_t *check_locations(svn_fs_t *fs, struct locations_info *info, const char *path, svn_revnum_t peg_revision, apr_pool_t *pool){ apr_array_header_t *a = apr_array_make(pool, 0, sizeof(svn_revnum_t)); apr_hash_t *h; struct locations_info *iter; for (iter = info; iter->rev != 0; ++iter) *(svn_revnum_t *) apr_array_push(a) = iter->rev; SVN_ERR(svn_repos_trace_node_locations(fs, &h, path, peg_revision, a, NULL, NULL, pool)); SVN_ERR(check_locations_info(h, info)); return SVN_NO_ERROR;}static svn_error_t *node_locations(const char **msg, svn_boolean_t msg_only, svn_test_opts_t *opts, apr_pool_t *pool){ apr_pool_t *subpool = svn_pool_create(pool); svn_repos_t *repos; svn_fs_t *fs; svn_fs_txn_t *txn; svn_fs_root_t *txn_root, *root; svn_revnum_t youngest_rev; *msg = "test svn_repos_node_locations"; if (msg_only) return SVN_NO_ERROR; /* Create the repository with a Greek tree. */ SVN_ERR(svn_test__create_repos(&repos, "test-repo-node-locations", opts->fs_type, pool)); fs = svn_repos_fs(repos); SVN_ERR(svn_fs_begin_txn(&txn, fs, 0, subpool)); SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool)); SVN_ERR(svn_test__create_greek_tree(txn_root, subpool)); SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, subpool)); svn_pool_clear(subpool); /* Move a file. Rev 2. */ SVN_ERR(svn_fs_revision_root(&root, fs, youngest_rev, subpool)); SVN_ERR(svn_fs_begin_txn(&txn, fs, 0, subpool)); SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool)); SVN_ERR(svn_fs_copy(root, "/A/mu", txn_root, "/mu.new", subpool)); SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, subpool)); { struct locations_info info[] = { { 1, "/A/mu" }, { 2, "/mu.new" }, { 0 } }; /* Test this twice, once with a leading slash, once without, because we know that the "without" form has caused us trouble in the past. */ SVN_ERR(check_locations(fs, info, "/mu.new", 2, pool)); SVN_ERR(check_locations(fs, info, "mu.new", 2, pool)); } svn_pool_clear(subpool); return SVN_NO_ERROR;}static svn_error_t *node_locations2(const char **msg, svn_boolean_t msg_only, svn_test_opts_t *opts, apr_pool_t *pool){ apr_pool_t *subpool = svn_pool_create(pool); svn_repos_t *repos; svn_fs_t *fs; svn_fs_txn_t *txn; svn_fs_root_t *txn_root, *root; svn_revnum_t youngest_rev = 0; *msg = "test svn_repos_node_locations some more"; if (msg_only) return SVN_NO_ERROR; /* Create the repository. */ SVN_ERR(svn_test__create_repos(&repos, "test-repo-node-locations2", opts->fs_type, pool)); fs = svn_repos_fs(repos); /* Revision 1: Add a directory /foo */ SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, subpool)); SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool)); SVN_ERR(svn_fs_make_dir(txn_root, "/foo", subpool)); SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, subpool)); svn_pool_clear(subpool); /* Revision 2: Move /foo to /bar, and add /bar/baz */ SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, subpool)); SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool)); SVN_ERR(svn_fs_revision_root(&root, fs, youngest_rev, subpool)); SVN_ERR(svn_fs_copy(root, "/foo", txn_root, "/bar", subpool)); SVN_ERR(svn_fs_make_file(txn_root, "/bar/baz", subpool)); SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, subpool)); svn_pool_clear(subpool); /* Revision 3: Modify /bar/baz */ SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, subpool)); SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool)); SVN_ERR(svn_test__set_file_contents(txn_root, "/bar/baz", "brrt", subpool)); SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, subpool)); svn_pool_clear(subpool); /* Revision 4: Modify /bar/baz again */ SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, subpool)); SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool)); SVN_ERR(svn_test__set_file_contents(txn_root, "/bar/baz", "bzzz", subpool)); SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, subpool)); svn_pool_clear(subpool); /* Now, check locations. */ { struct locations_info info[] = { { 3, "/bar/baz" }, { 2, "/bar/baz" }, { 0 } }; SVN_ERR(check_locations(fs, info, "/bar/baz", youngest_rev, pool)); } return SVN_NO_ERROR;}/* Testing the reporter. *//* Functions for an editor that will catch removal of defunct locks. *//* The main editor baton. */typedef struct rmlocks_baton_t { apr_hash_t *removed; apr_pool_t *pool;} rmlocks_baton_t;/* The file baton. */typedef struct rmlocks_file_baton_t { rmlocks_baton_t *main_baton; const char *path;} rmlocks_file_baton_t;/* An svn_delta_editor_t function. */static svn_error_t *rmlocks_open_file(const char *path, void *parent_baton, svn_revnum_t base_revision, apr_pool_t *file_pool, void **file_baton){ rmlocks_file_baton_t *fb = apr_palloc(file_pool, sizeof(*fb)); rmlocks_baton_t *b = parent_baton; fb->main_baton = b; fb->path = apr_pstrdup(b->pool, path); *file_baton = fb; return SVN_NO_ERROR;}/* An svn_delta_editor_t function. */static svn_error_t *rmlocks_change_prop(void *file_baton, const char *name, const svn_string_t *value, apr_pool_t *pool){ rmlocks_file_baton_t *fb = file_baton; if (strcmp(name, SVN_PROP_ENTRY_LOCK_TOKEN) == 0) { if (value != NULL) return svn_error_create(SVN_ERR_TEST_FAILED, NULL, "Value for lock-token property not NULL"); /* We only want it removed once. */ if (apr_hash_get(fb->main_baton->removed, fb->path, APR_HASH_KEY_STRING) != NULL) return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, "Lock token for '%s' already removed", fb->path); /* Mark as removed. */ apr_hash_set(fb->main_baton->removed, fb->path, APR_HASH_KEY_STRING, (void *)1); } return SVN_NO_ERROR;}/* An svn_delta_editor_t function. */static svn_error_t *rmlocks_open_root(void *edit_baton, svn_revnum_t base_revision, apr_pool_t *dir_pool, void **root_baton){ *root_baton = edit_baton; return SVN_NO_ERROR;}/* An svn_delta_editor_t function. */static svn_error_t *rmlocks_open_directory(const char *path, void *parent_baton, svn_revnum_t base_revision, apr_pool_t *pool, void **dir_baton){ *dir_baton = parent_baton; return SVN_NO_ERROR;}/* Create an svn_delta_editor/baton, storing them in EDITOR/EDIT_BATON, that will store paths for which lock tokens were *REMOVED in REMOVED. Allocate the editor and *REMOVED in POOL. */static svn_error_t *create_rmlocks_editor(svn_delta_editor_t **editor, void **edit_baton, apr_hash_t **removed, apr_pool_t *pool){ rmlocks_baton_t *baton = apr_palloc(pool, sizeof(*baton)); /* Create the editor. */ *editor = svn_delta_default_editor(pool); (*editor)->open_root = rmlocks_open_root; (*editor)->open_directory = rmlocks_open_directory; (*editor)->open_file = rmlocks_open_file; (*editor)->change_file_prop = rmlocks_change_prop; /* Initialize the baton. */ baton->removed = apr_hash_make(pool); baton->pool = pool; *edit_baton = baton; *removed = baton->removed; return SVN_NO_ERROR;}/* Check that HASH contains exactly the const char * entries for all entries in the NULL-terminated array SPEC. */static svn_error_t *rmlocks_check(const char **spec, apr_hash_t *hash){ apr_size_t n = 0; for (; *spec; ++spec, ++n) { if (! apr_hash_get(hash, *spec, APR_HASH_KEY_STRING)) return svn_error_createf (SVN_ERR_TEST_FAILED, NULL, "Lock token for '%s' should have been removed", *spec); } if (n < apr_hash_count(hash)) return svn_error_create(SVN_ERR_TEST_FAILED, NULL, "Lock token for one or more paths unexpectedly " "removed"); return SVN_NO_ERROR;}/* Test that defunct locks are removed by the reporter. */static svn_error_t *rmlocks(const char **msg, svn_boolean_t msg_only, svn_test_opts_t *opts, apr_pool_t *pool){ svn_repos_t *repos; svn_fs_t *fs; svn_fs_txn_t *txn; svn_fs_root_t *txn_root; apr_pool_t *subpool = svn_pool_create(pool); svn_revnum_t youngest_rev; svn_delta_editor_t *editor; void *edit_baton, *report_baton; svn_lock_t *l1, *l2, *l3, *l4; svn_fs_access_t *fs_access; apr_hash_t *removed; *msg = "test removal of defunct locks"; if (msg_only) return SVN_NO_ERROR; /* Create a filesystem and repository. */ SVN_ERR(svn_test__create_repos(&repos, "test-repo-rmlocks", opts->fs_type, pool)); fs = svn_repos_fs(repos); /* Prepare a txn to receive the greek tree. */ SVN_ERR(svn_fs_begin_txn(&txn, fs, 0, subpool)); SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool)); SVN_ERR(svn_test__create_greek_tree(txn_root, subpool)); SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, subpool)); svn_pool_clear(subpool); SVN_ERR(svn_fs_create_access(&fs_access, "user1", pool)); SVN_ERR(svn_fs_set_access(fs, fs_access)); /* Lock some files, break a lock, steal another and check that those get removed. */ { const char *expected [] = { "A/mu", "A/D/gamma", NULL };
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -