📄 changes-test.c
字号:
change->text_mod = 1; change->prop_mod = 0; apr_hash_set(ideal, "/foo", APR_HASH_KEY_STRING, change); } if (strcmp(txn_id, "2") == 0) { change = apr_palloc(pool, sizeof(*change)); change->node_rev_id = svn_fs_parse_id("1.0.2", 5, pool); change->change_kind = svn_fs_path_change_modify; change->text_mod = 0; change->prop_mod = 1; apr_hash_set(ideal, "/foo", APR_HASH_KEY_STRING, change); change = apr_palloc(pool, sizeof(*change)); change->node_rev_id = svn_fs_parse_id("2.0.2", 5, pool); change->change_kind = svn_fs_path_change_modify; change->text_mod = 1; change->prop_mod = 0; apr_hash_set(ideal, "/bar", APR_HASH_KEY_STRING, change); } if (strcmp(txn_id, "3") == 0) { change = apr_palloc(pool, sizeof(*change)); change->node_rev_id = svn_fs_parse_id("3.0.3", 5, pool); change->change_kind = svn_fs_path_change_modify; change->text_mod = 1; change->prop_mod = 0; apr_hash_set(ideal, "/baz", APR_HASH_KEY_STRING, change); } if (strcmp(txn_id, "4") == 0) { change = apr_palloc(pool, sizeof(*change)); change->node_rev_id = svn_fs_parse_id("4.0.4", 5, pool); change->change_kind = svn_fs_path_change_add; change->text_mod = 1; change->prop_mod = 0; apr_hash_set(ideal, "/fob", APR_HASH_KEY_STRING, change); } if (strcmp(txn_id, "5") == 0) { change = apr_palloc(pool, sizeof(*change)); change->node_rev_id = svn_fs_parse_id("5.0.5", 5, pool); change->change_kind = svn_fs_path_change_replace; change->text_mod = 1; change->prop_mod = 1; apr_hash_set(ideal, "/baz", APR_HASH_KEY_STRING, change); } if (strcmp(txn_id, "6") == 0) { change = apr_palloc(pool, sizeof(*change)); change->node_rev_id = svn_fs_parse_id("4.0.6", 5, pool); change->change_kind = svn_fs_path_change_modify; change->text_mod = 0; change->prop_mod = 1; apr_hash_set(ideal, "/fob", APR_HASH_KEY_STRING, change); } return ideal;}static svn_error_t *compare_changes(apr_hash_t *ideals, apr_hash_t *changes, svn_test_opts_t *opts, const char *txn_id, apr_pool_t *pool){ apr_hash_index_t *hi; for (hi = apr_hash_first(pool, ideals); hi; hi = apr_hash_next(hi)) { const void *key; void *val; svn_fs_path_change_t *ideal_change, *change; const char *path; /* KEY will be the path, VAL the change. */ apr_hash_this(hi, &key, NULL, &val); path = (const char *) key; ideal_change = val; /* Now get the change that refers to PATH in the actual changes hash. */ change = apr_hash_get(changes, path, APR_HASH_KEY_STRING); if (! change) return svn_error_createf (SVN_ERR_TEST_FAILED, NULL, "missing expected change for path '%s' in txn_id '%s'", path, txn_id); /* Verify that the NODE-REV-ID matches. */ if (svn_fs_compare_ids(change->node_rev_id, ideal_change->node_rev_id)) return svn_error_createf (SVN_ERR_TEST_FAILED, NULL, "node revision ids differ in change for key '%s'", txn_id); /* Verify that the change KIND matches. */ if (change->change_kind != ideal_change->change_kind) return svn_error_createf (SVN_ERR_TEST_FAILED, NULL, "change kinds differ in change for key '%s'", txn_id); /* Verify that the change TEXT-MOD bit matches. */ if (change->text_mod != ideal_change->text_mod) return svn_error_createf (SVN_ERR_TEST_FAILED, NULL, "change text-mod bits differ in change for key '%s'", txn_id); /* Verify that the change PROP-MOD bit matches. */ if (change->prop_mod != ideal_change->prop_mod) return svn_error_createf (SVN_ERR_TEST_FAILED, NULL, "change prop-mod bits differ in change for key '%s'", txn_id); } return SVN_NO_ERROR;}static svn_error_t *changes_fetch(const char **msg, svn_boolean_t msg_only, svn_test_opts_t *opts, apr_pool_t *pool){ svn_fs_t *fs; int i; int num_txns = sizeof(standard_txns) / sizeof(const char *); struct changes_args args; *msg = "fetch compressed changes from the changes table"; if (msg_only) return SVN_NO_ERROR; /* Create a new fs and repos */ SVN_ERR(svn_test__create_fs(&fs, "test-repo-changes-fetch", "bdb", pool)); /* First, verify that we can request changes for an arbitrary key without error. */ args.fs = fs; args.key = "blahbliggityblah"; SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_changes_fetch, &args, pool)); if ((! args.changes) || (apr_hash_count(args.changes))) return svn_error_create(SVN_ERR_TEST_FAILED, NULL, "expected empty changes hash"); /* Add the standard slew of changes. */ SVN_ERR(add_standard_changes(fs, pool)); /* For each transaction, fetch that transaction's changes, and compare those changes against our ideal compressed changes hash. */ for (i = 0; i < num_txns; i++) { const char *txn_id = standard_txns[i]; apr_hash_t *ideals; /* Get the ideal changes hash. */ ideals = get_ideal_changes(txn_id, pool); /* Setup the trail baton. */ args.fs = fs; args.key = txn_id; /* And get those changes via in the internal interface, and verify that they are accurate. */ SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_changes_fetch, &args, pool)); if (! args.changes) return svn_error_createf (SVN_ERR_TEST_FAILED, NULL, "got no changes for key '%s'", txn_id); if (apr_hash_count(ideals) != apr_hash_count(args.changes)) return svn_error_createf (SVN_ERR_TEST_FAILED, NULL, "unexpected number of changes for key '%s'", txn_id); SVN_ERR(compare_changes(ideals, args.changes, opts, txn_id, pool)); } return SVN_NO_ERROR;}static svn_error_t *changes_fetch_ordering(const char **msg, svn_boolean_t msg_only, svn_test_opts_t *opts, apr_pool_t *pool){ svn_fs_t *fs; svn_revnum_t youngest_rev = 0; const char *txn_name; svn_fs_txn_t *txn; svn_fs_root_t *txn_root, *rev_root; struct changes_args args; apr_pool_t *subpool = svn_pool_create(pool); apr_hash_index_t *hi; *msg = "verify ordered-ness of fetched compressed changes"; if (msg_only) return SVN_NO_ERROR; /* Create a new fs and repos */ SVN_ERR(svn_test__create_fs (&fs, "test-repo-changes-fetch-ordering", "bdb", pool)); /*** REVISION 1: Make some files and dirs. ***/ SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, subpool)); SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool)); { static svn_test__txn_script_command_t script_entries[] = { { 'a', "dir1", 0 }, { 'a', "file1", "This is the file 'file1'.\n" }, { 'a', "dir1/file2", "This is the file 'file2'.\n" }, { 'a', "dir1/file3", "This is the file 'file3'.\n" }, { 'a', "dir1/file4", "This is the file 'file4'.\n" }, }; SVN_ERR(svn_test__txn_script_exec(txn_root, script_entries, 5, subpool)); } SVN_ERR(svn_fs_commit_txn(NULL, &youngest_rev, txn, subpool)); svn_pool_clear(subpool); /*** REVISION 2: Delete and add some stuff, non-depth-first. ***/ SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, subpool)); /* Don't use subpool, txn_name is used after subpool is cleared */ SVN_ERR(svn_fs_txn_name(&txn_name, txn, pool)); SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool)); { static svn_test__txn_script_command_t script_entries[] = { { 'd', "file1", "This is the file 'file1'.\n" }, { 'd', "dir1/file2", "This is the file 'file2'.\n" }, { 'd', "dir1/file3", "This is the file 'file3'.\n" }, { 'a', "dir1/file5", "This is the file 'file4'.\n" }, { 'a', "dir1/dir2", 0 }, { 'd', "dir1", 0 }, { 'a', "dir3", 0 }, }; SVN_ERR(svn_test__txn_script_exec(txn_root, script_entries, 7, subpool)); } SVN_ERR(svn_fs_commit_txn(NULL, &youngest_rev, txn, subpool)); svn_pool_clear(subpool); /*** TEST: We should have only three changes, the deletion of 'file1' the deletion of 'dir1', and the addition of 'dir3'. ***/ args.fs = fs; args.key = txn_name; SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_changes_fetch, &args, subpool)); if ((! args.changes) || (apr_hash_count(args.changes) != 3)) return svn_error_create(SVN_ERR_TEST_FAILED, NULL, "expected changes"); for (hi = apr_hash_first(subpool, args.changes); hi; hi = apr_hash_next(hi)) { const void *key; void *val; svn_fs_path_change_t *change; /* KEY will be the path, VAL the change. */ apr_hash_this(hi, &key, NULL, &val); change = val; if ((change->change_kind == svn_fs_path_change_add) && (strcmp(key, "/dir3") == 0)) ; else if ((change->change_kind == svn_fs_path_change_delete) && ((strcmp(key, "/dir1") == 0) || (strcmp(key, "/file1") == 0))) ; else return svn_error_create(SVN_ERR_TEST_FAILED, NULL, "got wrong changes"); } /*** REVISION 3: Do the same stuff as in revision 1. ***/ SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, subpool)); SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool)); { static svn_test__txn_script_command_t script_entries[] = { { 'a', "dir1", 0 }, { 'a', "file1", "This is the file 'file1'.\n" }, { 'a', "dir1/file2", "This is the file 'file2'.\n" }, { 'a', "dir1/file3", "This is the file 'file3'.\n" }, { 'a', "dir1/file4", "This is the file 'file4'.\n" }, }; SVN_ERR(svn_test__txn_script_exec(txn_root, script_entries, 5, subpool)); } SVN_ERR(svn_fs_commit_txn(NULL, &youngest_rev, txn, subpool)); svn_pool_clear(subpool); /*** REVISION 4: Do the same stuff as in revision 2, but use a copy overwrite of the top directory (instead of a delete) to test that the 'replace' change type works, too. (And add 'dir4' instead of 'dir3', since 'dir3' still exists). ***/ SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, subpool)); /* Don't use subpool, txn_name is used after subpool is cleared */ SVN_ERR(svn_fs_txn_name(&txn_name, txn, pool)); SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool)); SVN_ERR(svn_fs_revision_root(&rev_root, fs, 1, subpool)); { static svn_test__txn_script_command_t script_entries[] = { { 'd', "file1", "This is the file 'file1'.\n" }, { 'd', "dir1/file2", "This is the file 'file2'.\n" }, { 'd', "dir1/file3", "This is the file 'file3'.\n" }, { 'a', "dir1/file5", "This is the file 'file4'.\n" }, { 'a', "dir1/dir2", 0 }, }; SVN_ERR(svn_test__txn_script_exec(txn_root, script_entries, 5, subpool)); SVN_ERR(svn_fs_copy(rev_root, "dir1", txn_root, "dir1", subpool)); SVN_ERR(svn_fs_make_dir(txn_root, "dir4", subpool)); } SVN_ERR(svn_fs_commit_txn(NULL, &youngest_rev, txn, subpool)); svn_pool_clear(subpool); /*** TEST: We should have only three changes, the deletion of 'file1' the replacement of 'dir1', and the addition of 'dir4'. ***/ args.fs = fs; args.key = txn_name; SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_changes_fetch, &args, subpool)); if ((! args.changes) || (apr_hash_count(args.changes) != 3)) return svn_error_create(SVN_ERR_TEST_FAILED, NULL, "expected changes"); for (hi = apr_hash_first(subpool, args.changes); hi; hi = apr_hash_next(hi)) { const void *key; void *val; svn_fs_path_change_t *change; /* KEY will be the path, VAL the change. */ apr_hash_this(hi, &key, NULL, &val); change = val; if ((change->change_kind == svn_fs_path_change_add) && (strcmp(key, "/dir4") == 0)) ; else if ((change->change_kind == svn_fs_path_change_replace) && (strcmp(key, "/dir1") == 0)) ; else if ((change->change_kind == svn_fs_path_change_delete) && (strcmp(key, "/file1") == 0)) ; else return svn_error_create(SVN_ERR_TEST_FAILED, NULL, "got wrong changes"); } return SVN_NO_ERROR;}/* The test table. */struct svn_test_descriptor_t test_funcs[] = { SVN_TEST_NULL, SVN_TEST_PASS(changes_add), SVN_TEST_PASS(changes_fetch_raw), SVN_TEST_PASS(changes_delete), SVN_TEST_PASS(changes_fetch), SVN_TEST_PASS(changes_fetch_ordering), SVN_TEST_NULL };
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -