You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2015/11/30 11:24:23 UTC
svn commit: r1717223 [47/50] - in /subversion/branches/ra-git: ./ build/
build/ac-macros/ build/generator/ build/generator/templates/
contrib/hook-scripts/ notes/ notes/api-errata/1.9/ notes/move-tracking/
subversion/ subversion/bindings/ctypes-python/...
Modified: subversion/branches/ra-git/subversion/tests/cmdline/update_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/update_tests.py?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/update_tests.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/update_tests.py Mon Nov 30 10:24:16 2015
@@ -2227,6 +2227,7 @@ def forced_update_failures(sbox):
# Test for issue #2556. The tests maps a virtual drive to a working copy
# and tries some basic update, commit and status actions on the virtual
# drive.
+@SkipUnless(svntest.main.is_os_windows)
def update_wc_on_windows_drive(sbox):
"update wc on the root of a Windows (virtual) drive"
@@ -2253,10 +2254,6 @@ def update_wc_on_windows_drive(sbox):
return None
- # Skip the test if not on Windows
- if not svntest.main.windows:
- raise svntest.Skip
-
# just create an empty folder, we'll checkout later.
sbox.build(create_wc = False)
svntest.main.safe_rmtree(sbox.wc_dir)
@@ -2265,7 +2262,7 @@ def update_wc_on_windows_drive(sbox):
# create a virtual drive to the working copy folder
drive = find_the_next_available_drive_letter()
if drive is None:
- raise svntest.Skip
+ raise svntest.Skip('No drive letter available')
subprocess.call(['subst', drive +':', sbox.wc_dir])
wc_dir = drive + ':/'
@@ -5137,7 +5134,7 @@ def skip_access_denied(sbox):
try:
import msvcrt
except ImportError:
- raise svntest.Skip
+ raise svntest.Skip('python msvcrt library not available')
sbox.build()
wc_dir = sbox.wc_dir
@@ -6626,8 +6623,7 @@ def update_conflict_details(sbox):
{
"Path" : re.escape(sbox.ospath('A/B')),
- "Conflict Properties File" :
- re.escape(sbox.ospath('A/B/dir_conflicts.prej')) + '.*',
+ "Conflicted Properties" : "key",
"Conflict Details": re.escape(
'incoming dir edit upon update' +
' Source left: (dir) ^/A/B@1' +
@@ -6697,6 +6693,128 @@ def update_conflict_details(sbox):
svntest.actions.run_and_verify_info(expected_info, sbox.ospath('A/B'),
'--depth', 'infinity')
+# Keywords should be updated in local file even if text change is shortcut
+# (due to the local change being the same as the incoming change, for example).
+@XFail()
+def update_keywords_on_shortcut(sbox):
+ "update_keywords_on_shortcut"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ # Start with a file with keywords expanded
+ mu_path = sbox.ospath('A/mu')
+ svntest.main.file_append(mu_path, '$LastChangedRevision$\n')
+ svntest.main.run_svn(None, 'ps', 'svn:keywords', 'LastChangedRevision', mu_path)
+ sbox.simple_commit('A/mu')
+
+ # Modify the text, and commit
+ svntest.main.file_append(mu_path, 'New line.\n')
+ sbox.simple_commit('A/mu')
+
+ # Update back to the previous revision
+ sbox.simple_update('A/mu', 2)
+
+ # Make the same change again locally
+ svntest.main.file_append(mu_path, 'New line.\n')
+
+ # Update, so that merging the text change is a short-cut merge
+ text_before_up = open(sbox.ospath('A/mu'), 'r').readlines()
+ sbox.simple_update('A/mu')
+ text_after_up = open(sbox.ospath('A/mu'), 'r').readlines()
+
+ # Check the keywords have been updated
+ if not any(['$LastChangedRevision: 2 $' in line
+ for line in text_before_up]):
+ raise svntest.Failure("keyword not as expected in test set-up phase")
+ if not any(['$LastChangedRevision: 3 $' in line
+ for line in text_after_up]):
+ raise svntest.Failure("update did not update the LastChangedRevision keyword")
+
+def update_add_conflicted_deep(sbox):
+ "deep add conflicted"
+
+ sbox.build()
+ repo_url = sbox.repo_url
+
+ svntest.actions.run_and_verify_svnmucc(
+ None, [], '-U', repo_url, '-m', '',
+ 'mkdir', 'A/z',
+ 'mkdir', 'A/z/z',
+ 'mkdir', 'A/z/z/z')
+
+ svntest.actions.run_and_verify_svnmucc(
+ None, [], '-U', repo_url, '-m', '',
+ 'rm', 'A/z',
+ 'mkdir', 'A/z',
+ 'mkdir', 'A/z/z',
+ 'mkdir', 'A/z/z/z')
+
+ sbox.simple_append('A/z', 'A/z')
+ sbox.simple_add('A/z')
+ sbox.simple_update('A', 2)
+ # This final update used to segfault using 1.9.0 and 1.9.1
+ sbox.simple_update('A/z/z', 3)
+
+def missing_tmp_update(sbox):
+ "missing tmp update caused segfault"
+
+ sbox.build(read_only = True)
+ wc_dir = sbox.wc_dir
+ svntest.actions.run_and_verify_update(wc_dir, None, None, None, [], False,
+ wc_dir, '--set-depth', 'empty')
+
+ os.rmdir(sbox.ospath(svntest.main.get_admin_name() + '/tmp'))
+
+ svntest.actions.run_and_verify_svn(None, '.*Unable to create.*',
+ 'up', wc_dir, '--set-depth', 'infinity')
+
+ svntest.actions.run_and_verify_svn(None, [], 'cleanup', wc_dir)
+
+ svntest.actions.run_and_verify_update(wc_dir, None, None, None, [], False,
+ wc_dir, '--set-depth', 'infinity')
+
+def update_delete_switched(sbox):
+ "update delete switched"
+
+ sbox.build(read_only = True)
+ wc_dir = sbox.wc_dir
+
+ svntest.actions.run_and_verify_switch(wc_dir, sbox.ospath('A/B/E'),
+ sbox.repo_url + '/A/D/G',
+ None, None, None, [], False,
+ '--ignore-ancestry')
+
+ # Introduce some change somewhere...
+ sbox.simple_propset('A', 'A', 'A')
+
+ expected_status = svntest.wc.State(wc_dir, {
+ '' : Item(status=' ', wc_rev='1'),
+ 'A' : Item(status='A ', copied='+', treeconflict='C', wc_rev='-'),
+ 'A/B' : Item(status=' ', copied='+', wc_rev='-'),
+ 'A/B/E' : Item(status='A ', copied='+', wc_rev='-'),
+ 'A/B/E/rho' : Item(status=' ', copied='+', wc_rev='-'),
+ 'A/B/E/pi' : Item(status=' ', copied='+', wc_rev='-'),
+ 'A/B/E/tau' : Item(status=' ', copied='+', wc_rev='-'),
+ 'A/B/lambda' : Item(status=' ', copied='+', wc_rev='-'),
+ 'A/B/F' : Item(status=' ', copied='+', wc_rev='-'),
+ 'A/D' : Item(status=' ', copied='+', wc_rev='-'),
+ 'A/D/G' : Item(status=' ', copied='+', wc_rev='-'),
+ 'A/D/G/pi' : Item(status=' ', copied='+', wc_rev='-'),
+ 'A/D/G/tau' : Item(status=' ', copied='+', wc_rev='-'),
+ 'A/D/G/rho' : Item(status=' ', copied='+', wc_rev='-'),
+ 'A/D/gamma' : Item(status=' ', copied='+', wc_rev='-'),
+ 'A/D/H' : Item(status=' ', copied='+', wc_rev='-'),
+ 'A/D/H/omega' : Item(status=' ', copied='+', wc_rev='-'),
+ 'A/D/H/psi' : Item(status=' ', copied='+', wc_rev='-'),
+ 'A/D/H/chi' : Item(status=' ', copied='+', wc_rev='-'),
+ 'A/mu' : Item(status=' ', copied='+', wc_rev='-'),
+ 'A/C' : Item(status=' ', copied='+', wc_rev='-'),
+ 'iota' : Item(status=' ', wc_rev='1'),
+ })
+ svntest.actions.run_and_verify_update(wc_dir, None, None, expected_status,
+ [], False, sbox.ospath('A'), '-r', 0)
+
#######################################################################
# Run the tests
@@ -6783,6 +6901,10 @@ test_list = [ None,
bump_below_tree_conflict,
update_child_below_add,
update_conflict_details,
+ update_keywords_on_shortcut,
+ update_add_conflicted_deep,
+ missing_tmp_update,
+ update_delete_switched,
]
if __name__ == '__main__':
Modified: subversion/branches/ra-git/subversion/tests/cmdline/upgrade_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/upgrade_tests.py?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/upgrade_tests.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/upgrade_tests.py Mon Nov 30 10:24:16 2015
@@ -1438,6 +1438,132 @@ def upgrade_1_7_dir_external(sbox):
# svn: warning: W200033: sqlite[S5]: database is locked
svntest.actions.run_and_verify_svn(None, [], 'upgrade', sbox.wc_dir)
+@SkipUnless(svntest.wc.python_sqlite_can_read_wc)
+def auto_analyze(sbox):
+ """automatic SQLite ANALYZE"""
+
+ sbox.build(create_wc = False)
+
+ replace_sbox_with_tarfile(sbox, 'wc-without-stat1.tar.bz2')
+ svntest.main.run_svnadmin('setuuid', sbox.repo_dir,
+ '52ec7e4b-e5f0-451d-829f-f05d5571b4ab')
+
+ # Don't use svn to do relocate as that will add the table.
+ svntest.wc.sqlite_exec(sbox.wc_dir,
+ "update repository "
+ "set root ='" + sbox.repo_url + "'")
+ val = svntest.wc.sqlite_stmt(sbox.wc_dir,
+ "select 1 from sqlite_master "
+ "where name = 'sqlite_stat1'")
+ if val != []:
+ raise svntest.Failure("initial state failed")
+
+ # Make working copy read-only (but not wc_dir itself as
+ # svntest.main.chmod_tree will not reset it.)
+ for path, subdirs, files in os.walk(sbox.wc_dir):
+ for d in subdirs:
+ os.chmod(os.path.join(path, d), 0555)
+ for f in files:
+ os.chmod(os.path.join(path, f), 0444)
+
+ state = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
+ svntest.actions.run_and_verify_status(sbox.wc_dir, state)
+
+ svntest.main.chmod_tree(sbox.wc_dir, 0666, 0022)
+
+ state = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
+ svntest.actions.run_and_verify_status(sbox.wc_dir, state)
+
+ val = svntest.wc.sqlite_stmt(sbox.wc_dir,
+ "select 1 from sqlite_master "
+ "where name = 'sqlite_stat1'")
+ if val != [(1,)]:
+ raise svntest.Failure("analyze failed")
+
+def upgrade_1_0_with_externals(sbox):
+ "test upgrading 1.0.0 working copy with externals"
+
+ sbox.build(create_wc = False)
+ replace_sbox_with_tarfile(sbox, 'upgrade_1_0_with_externals.tar.bz2')
+
+ url = sbox.repo_url
+
+ # This is non-canonical by the rules of svn_uri_canonicalize, it gets
+ # written into the entries file and upgrade has to canonicalize.
+ non_canonical_url = url[:-1] + '%%%02x' % ord(url[-1])
+ xml_entries_relocate(sbox.wc_dir, 'file:///1.0.0/repos', non_canonical_url)
+
+ externals_propval = 'exdir_G ' + sbox.repo_url + '/A/D/G' + '\n'
+ adm_name = svntest.main.get_admin_name()
+ dir_props_file = os.path.join(sbox.wc_dir, adm_name, 'dir-props')
+ svntest.main.file_write(dir_props_file,
+ ('K 13\n'
+ 'svn:externals\n'
+ 'V %d\n' % len(externals_propval))
+ + externals_propval + '\nEND\n', 'wb')
+
+ # Attempt to use the working copy, this should give an error
+ expected_stderr = wc_is_too_old_regex
+ svntest.actions.run_and_verify_svn(None, expected_stderr,
+ 'info', sbox.wc_dir)
+
+
+ # Now upgrade the working copy
+ svntest.actions.run_and_verify_svn(None, [],
+ 'upgrade', sbox.wc_dir)
+ # And the separate working copy below COPIED or check_format() fails
+ svntest.actions.run_and_verify_svn(None, [],
+ 'upgrade',
+ os.path.join(sbox.wc_dir, 'COPIED', 'G'))
+
+ # Actually check the format number of the upgraded working copy
+ check_format(sbox, get_current_format())
+
+ # Now check the contents of the working copy
+ # #### This working copy is not just a basic tree,
+ # fix with the right data once we get here
+ expected_status = svntest.wc.State(sbox.wc_dir,
+ {
+ '' : Item(status=' M', wc_rev=7),
+ 'B' : Item(status=' ', wc_rev='7'),
+ 'B/mu' : Item(status=' ', wc_rev='7'),
+ 'B/D' : Item(status=' ', wc_rev='7'),
+ 'B/D/H' : Item(status=' ', wc_rev='7'),
+ 'B/D/H/psi' : Item(status=' ', wc_rev='7'),
+ 'B/D/H/omega' : Item(status=' ', wc_rev='7'),
+ 'B/D/H/zeta' : Item(status='MM', wc_rev='7'),
+ 'B/D/H/chi' : Item(status=' ', wc_rev='7'),
+ 'B/D/gamma' : Item(status=' ', wc_rev='9'),
+ 'B/D/G' : Item(status=' ', wc_rev='7'),
+ 'B/D/G/tau' : Item(status=' ', wc_rev='7'),
+ 'B/D/G/rho' : Item(status=' ', wc_rev='7'),
+ 'B/D/G/pi' : Item(status=' ', wc_rev='7'),
+ 'B/B' : Item(status=' ', wc_rev='7'),
+ 'B/B/lambda' : Item(status=' ', wc_rev='7'),
+ 'MKDIR' : Item(status='A ', wc_rev='0'),
+ 'MKDIR/MKDIR' : Item(status='A ', wc_rev='0'),
+ 'A' : Item(status=' ', wc_rev='7'),
+ 'A/B' : Item(status=' ', wc_rev='7'),
+ 'A/B/lambda' : Item(status=' ', wc_rev='7'),
+ 'A/D' : Item(status=' ', wc_rev='7'),
+ 'A/D/G' : Item(status=' ', wc_rev='7'),
+ 'A/D/G/rho' : Item(status=' ', wc_rev='7'),
+ 'A/D/G/pi' : Item(status=' ', wc_rev='7'),
+ 'A/D/G/tau' : Item(status=' ', wc_rev='7'),
+ 'A/D/H' : Item(status=' ', wc_rev='7'),
+ 'A/D/H/psi' : Item(status=' ', wc_rev='7'),
+ 'A/D/H/omega' : Item(status=' ', wc_rev='7'),
+ 'A/D/H/zeta' : Item(status=' ', wc_rev='7'),
+ 'A/D/H/chi' : Item(status=' ', wc_rev='7'),
+ 'A/D/gamma' : Item(status=' ', wc_rev='7'),
+ 'A/mu' : Item(status=' ', wc_rev='7'),
+ 'iota' : Item(status=' ', wc_rev='7'),
+ 'COPIED' : Item(status=' ', wc_rev='10'),
+ 'DELETED' : Item(status='D ', wc_rev='10'),
+ 'exdir_G' : Item(status='X '),
+ })
+ run_and_verify_status_no_server(sbox.wc_dir, expected_status)
+
########################################################################
# Run the tests
@@ -1494,6 +1620,8 @@ test_list = [ None,
iprops_upgrade1_6,
changelist_upgrade_1_6,
upgrade_1_7_dir_external,
+ auto_analyze,
+ upgrade_1_0_with_externals,
]
Modified: subversion/branches/ra-git/subversion/tests/libsvn_client/client-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_client/client-test.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_client/client-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_client/client-test.c Mon Nov 30 10:24:16 2015
@@ -34,6 +34,7 @@
#include "private/svn_client_mtcc.h"
#include "svn_repos.h"
#include "svn_subst.h"
+#include "private/svn_sorts_private.h"
#include "private/svn_wc_private.h"
#include "svn_props.h"
#include "svn_hash.h"
@@ -740,14 +741,14 @@ test_foreign_repos_copy(const svn_test_o
wc_path = svn_test_data_path("test-foreign-repos-copy", pool);
- wc_path = svn_dirent_join(wc_path, "foreign-wc", pool);
-
/* Remove old test data from the previous run */
SVN_ERR(svn_io_remove_dir2(wc_path, TRUE, NULL, NULL, pool));
SVN_ERR(svn_io_make_dir_recursively(wc_path, pool));
svn_test_add_dir_cleanup(wc_path);
+ wc_path = svn_dirent_join(wc_path, "foreign-wc", pool);
+
rev.kind = svn_opt_revision_head;
peg_rev.kind = svn_opt_revision_unspecified;
SVN_ERR(svn_client_create_context(&ctx, pool));
@@ -953,7 +954,7 @@ test_remote_only_status(const svn_test_o
/* Check out a sparse root @r1 of the repository */
wc_path = svn_test_data_path("test-remote-only-status-wc", pool);
- /*svn_test_add_dir_cleanup(wc_path);*/
+ svn_test_add_dir_cleanup(wc_path);
SVN_ERR(svn_io_remove_dir2(wc_path, TRUE, NULL, NULL, pool));
rev.kind = svn_opt_revision_number;
@@ -1014,8 +1015,7 @@ test_remote_only_status(const svn_test_o
SVN_TEST_ASSERT(results->nelts == i);
if (opts->verbose)
- qsort(results->elts, results->nelts, results->elt_size,
- compare_status_paths);
+ svn_sort__array(results, compare_status_paths);
for (i = 0; i < results->nelts; ++i)
{
@@ -1287,6 +1287,127 @@ test_copy_pin_externals(const svn_test_o
return SVN_NO_ERROR;
}
+/* issue #4560 */
+static svn_error_t *
+test_copy_pin_externals_select_subtree(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_opt_revision_t rev;
+ svn_opt_revision_t peg_rev;
+ const char *repos_url;
+ const char *A_copy_url;
+ const char *B_url;
+ const char *wc_path;
+ svn_client_ctx_t *ctx;
+ apr_hash_t *externals_to_pin;
+ apr_array_header_t *external_items;
+ apr_array_header_t *copy_sources;
+ svn_wc_external_item2_t item;
+ svn_client_copy_source_t copy_source;
+ apr_hash_t *props;
+ int i;
+ struct test_data {
+ const char *subtree_relpath;
+ const char *src_external_desc;
+ const char *expected_dst_external_desc;
+ } test_data[] = {
+ /* Note: these externals definitions contain extra whitespace on
+ purpose, to test that the pinning logic doesn't make
+ whitespace-only changes to values that aren't pinned. */
+
+ /* External on A/B will be pinned. */
+ { "B", "^/A/D/gamma gamma-ext", "^/A/D/gamma@3 gamma-ext" },
+
+ /* External on A/D won't be pinned. */
+ { "D", "^/A/B/F F-ext", "^/A/B/F F-ext" } ,
+
+ { NULL },
+ };
+
+ /* Create a filesytem and repository containing the Greek tree. */
+ SVN_ERR(create_greek_repos(&repos_url, "pin-externals-select-subtree",
+ opts, pool));
+
+ wc_path = svn_test_data_path("pin-externals-select-subtree-wc", pool);
+
+ /* Remove old test data from the previous run */
+ SVN_ERR(svn_io_remove_dir2(wc_path, TRUE, NULL, NULL, pool));
+
+ SVN_ERR(svn_io_make_dir_recursively(wc_path, pool));
+ svn_test_add_dir_cleanup(wc_path);
+
+ rev.kind = svn_opt_revision_head;
+ peg_rev.kind = svn_opt_revision_unspecified;
+ SVN_ERR(svn_client_create_context(&ctx, pool));
+
+ /* Configure externals. */
+ i = 0;
+ while (test_data[i].subtree_relpath)
+ {
+ const char *subtree_relpath;
+ const char *url;
+ const svn_string_t *propval;
+
+ subtree_relpath = test_data[i].subtree_relpath;
+ propval = svn_string_create(test_data[i].src_external_desc, pool);
+
+ url = apr_pstrcat(pool, repos_url, "/A/", subtree_relpath, SVN_VA_NULL);
+ SVN_ERR(svn_client_propset_remote(SVN_PROP_EXTERNALS, propval,
+ url, TRUE, 1, NULL,
+ NULL, NULL, ctx, pool));
+ i++;
+ }
+
+ /* Set up parameters for pinning externals on A/B. */
+ externals_to_pin = apr_hash_make(pool);
+
+ item.url = "^/A/D/gamma";
+ item.target_dir = "gamma-ext";
+
+ external_items = apr_array_make(pool, 2, sizeof(svn_wc_external_item2_t *));
+ APR_ARRAY_PUSH(external_items, svn_wc_external_item2_t *) = &item;
+ B_url = apr_pstrcat(pool, repos_url, "/A/B", SVN_VA_NULL);
+ svn_hash_sets(externals_to_pin, B_url, external_items);
+
+ /* Copy ^/A to ^/A_copy, pinning externals on ^/A/B. */
+ copy_source.path = apr_pstrcat(pool, repos_url, "/A", SVN_VA_NULL);
+ copy_source.revision = &rev;
+ copy_source.peg_revision = &peg_rev;
+ copy_sources = apr_array_make(pool, 1, sizeof(svn_client_copy_source_t *));
+ APR_ARRAY_PUSH(copy_sources, svn_client_copy_source_t *) = ©_source;
+ A_copy_url = apr_pstrcat(pool, repos_url, "/A_copy", SVN_VA_NULL);
+ SVN_ERR(svn_client_copy7(copy_sources, A_copy_url, FALSE, FALSE,
+ FALSE, FALSE, TRUE, externals_to_pin,
+ NULL, NULL, NULL, ctx, pool));
+
+ /* Verify that externals were pinned as expected. */
+ i = 0;
+ while (test_data[i].subtree_relpath)
+ {
+ const char *subtree_relpath;
+ const char *url;
+ const svn_string_t *propval;
+ svn_stringbuf_t *externals_desc;
+ const char *expected_desc;
+
+ subtree_relpath = test_data[i].subtree_relpath;
+ url = apr_pstrcat(pool, A_copy_url, "/", subtree_relpath, SVN_VA_NULL);
+
+ SVN_ERR(svn_client_propget5(&props, NULL, SVN_PROP_EXTERNALS,
+ url, &peg_rev, &rev, NULL,
+ svn_depth_empty, NULL, ctx, pool, pool));
+ propval = svn_hash_gets(props, url);
+ SVN_TEST_ASSERT(propval);
+ externals_desc = svn_stringbuf_create(propval->data, pool);
+ svn_stringbuf_strip_whitespace(externals_desc);
+ expected_desc = test_data[i].expected_dst_external_desc;
+ SVN_TEST_STRING_ASSERT(externals_desc->data, expected_desc);
+
+ i++;
+ }
+
+ return SVN_NO_ERROR;
+}
+
/* ========================================================================== */
@@ -1313,6 +1434,8 @@ static struct svn_test_descriptor_t test
"test svn_client_status6 with ignore_local_mods"),
SVN_TEST_OPTS_PASS(test_copy_pin_externals,
"test svn_client_copy7 with externals_to_pin"),
+ SVN_TEST_OPTS_PASS(test_copy_pin_externals_select_subtree,
+ "pin externals on selected subtrees only"),
SVN_TEST_NULL
};
Modified: subversion/branches/ra-git/subversion/tests/libsvn_delta/svndiff-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_delta/svndiff-test.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_delta/svndiff-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_delta/svndiff-test.c Mon Nov 30 10:24:16 2015
@@ -88,7 +88,7 @@ main(int argc, char **argv)
#ifdef QUOPRINT_SVNDIFFS
encoder = svn_quoprint_encode(stdout_stream, pool);
#else
- encoder = svn_base64_encode(stdout_stream, pool);
+ encoder = svn_base64_encode2(stdout_stream, TRUE, pool);
#endif
/* use maximum compression level */
svn_txdelta_to_svndiff3(&svndiff_handler, &svndiff_baton,
Modified: subversion/branches/ra-git/subversion/tests/libsvn_diff/parse-diff-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_diff/parse-diff-test.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_diff/parse-diff-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_diff/parse-diff-test.c Mon Nov 30 10:24:16 2015
@@ -66,6 +66,8 @@ static const char *git_unidiff =
"Index: A/C/gamma" NL
"===================================================================" NL
"diff --git a/A/C/gamma b/A/C/gamma" NL
+ "old mode 100644" NL
+ "new mode 100755" NL
"--- a/A/C/gamma\t(revision 2)" NL
"+++ b/A/C/gamma\t(working copy)" NL
"@@ -1 +1,2 @@" NL
@@ -86,6 +88,8 @@ static const char *git_tree_and_text_uni
"Index: iota.copied" NL
"===================================================================" NL
"diff --git a/iota b/iota.copied" NL
+ "old mode 100644" NL
+ "new mode 100755" NL
"copy from iota" NL
"copy to iota.copied" NL
"--- a/iota\t(revision 2)" NL
@@ -96,6 +100,8 @@ static const char *git_tree_and_text_uni
"Index: A/mu.moved" NL
"===================================================================" NL
"diff --git a/A/mu b/A/mu.moved" NL
+ "old mode 100644" NL
+ "new mode 100755" NL
"rename from A/mu" NL
"rename to A/mu.moved" NL
"--- a/A/mu\t(revision 2)" NL
@@ -114,7 +120,7 @@ static const char *git_tree_and_text_uni
"Index: A/B/lambda" NL
"===================================================================" NL
"diff --git a/A/B/lambda b/A/B/lambda" NL
- "deleted file mode 100644" NL
+ "deleted file mode 100755" NL
"--- a/A/B/lambda\t(revision 2)" NL
"+++ /dev/null\t(working copy)" NL
"@@ -1 +0,0 @@" NL
@@ -303,6 +309,24 @@ create_patch_file(svn_patch_file_t **pat
return SVN_NO_ERROR;
}
+/* svn_stream_readline() with hunk reader semantics */
+static svn_error_t *
+stream_readline_diff(svn_stream_t *stream,
+ svn_stringbuf_t **buf,
+ const char *eol,
+ svn_boolean_t *eof,
+ apr_pool_t *result_pool)
+{
+ SVN_ERR(svn_stream_readline(stream, buf, eol, eof, result_pool));
+
+ /* Hunks are only at EOF after they are completely read, even if
+ they don't have a final EOL in the text */
+ if (*eof && (*buf)->len)
+ *eof = FALSE;
+
+ return SVN_NO_ERROR;
+}
+
/* Check that reading a line from HUNK equals what's inside EXPECTED.
* If ORIGINAL is TRUE, read the original hunk text; else, read the
* modified hunk text. */
@@ -321,7 +345,7 @@ check_content(svn_diff_hunk_t *hunk, svn
while (TRUE)
{
- SVN_ERR(svn_stream_readline(exp, &exp_buf, NL, &exp_eof, pool));
+ SVN_ERR(stream_readline_diff(exp, &exp_buf, NL, &exp_eof, pool));
if (original)
SVN_ERR(svn_diff_hunk_readline_original_text(hunk, &hunk_buf, NULL,
&hunk_eof, pool, pool));
@@ -447,6 +471,10 @@ test_parse_git_diff(apr_pool_t *pool)
SVN_TEST_STRING_ASSERT(patch->new_filename, "A/C/gamma");
SVN_TEST_ASSERT(patch->operation == svn_diff_op_modified);
SVN_TEST_ASSERT(patch->hunks->nelts == 1);
+ SVN_TEST_ASSERT(patch->old_executable_bit = svn_tristate_false);
+ SVN_TEST_ASSERT(patch->new_executable_bit = svn_tristate_true);
+ SVN_TEST_ASSERT(patch->old_symlink_bit = svn_tristate_false);
+ SVN_TEST_ASSERT(patch->new_symlink_bit = svn_tristate_false);
hunk = APR_ARRAY_IDX(patch->hunks, 0, svn_diff_hunk_t *);
@@ -482,6 +510,10 @@ test_parse_git_diff(apr_pool_t *pool)
SVN_TEST_STRING_ASSERT(patch->new_filename, "new");
SVN_TEST_ASSERT(patch->operation == svn_diff_op_added);
SVN_TEST_ASSERT(patch->hunks->nelts == 0);
+ SVN_TEST_ASSERT(patch->old_executable_bit = svn_tristate_unknown);
+ SVN_TEST_ASSERT(patch->new_executable_bit = svn_tristate_false);
+ SVN_TEST_ASSERT(patch->old_symlink_bit = svn_tristate_unknown);
+ SVN_TEST_ASSERT(patch->new_symlink_bit = svn_tristate_false);
SVN_ERR(svn_diff_close_patch_file(patch_file, pool));
@@ -507,6 +539,10 @@ test_parse_git_tree_and_text_diff(apr_po
SVN_TEST_ASSERT(patch);
SVN_TEST_STRING_ASSERT(patch->old_filename, "iota");
SVN_TEST_STRING_ASSERT(patch->new_filename, "iota.copied");
+ SVN_TEST_ASSERT(patch->old_executable_bit = svn_tristate_false);
+ SVN_TEST_ASSERT(patch->new_executable_bit = svn_tristate_true);
+ SVN_TEST_ASSERT(patch->old_symlink_bit = svn_tristate_false);
+ SVN_TEST_ASSERT(patch->new_symlink_bit = svn_tristate_false);
SVN_TEST_ASSERT(patch->operation == svn_diff_op_copied);
SVN_TEST_ASSERT(patch->hunks->nelts == 1);
@@ -529,6 +565,10 @@ test_parse_git_tree_and_text_diff(apr_po
SVN_TEST_ASSERT(patch);
SVN_TEST_STRING_ASSERT(patch->old_filename, "A/mu");
SVN_TEST_STRING_ASSERT(patch->new_filename, "A/mu.moved");
+ SVN_TEST_ASSERT(patch->old_executable_bit = svn_tristate_false);
+ SVN_TEST_ASSERT(patch->new_executable_bit = svn_tristate_true);
+ SVN_TEST_ASSERT(patch->old_symlink_bit = svn_tristate_false);
+ SVN_TEST_ASSERT(patch->new_symlink_bit = svn_tristate_false);
SVN_TEST_ASSERT(patch->operation == svn_diff_op_moved);
SVN_TEST_ASSERT(patch->hunks->nelts == 1);
@@ -572,6 +612,10 @@ test_parse_git_tree_and_text_diff(apr_po
SVN_TEST_STRING_ASSERT(patch->new_filename, "/dev/null");
SVN_TEST_ASSERT(patch->operation == svn_diff_op_deleted);
SVN_TEST_ASSERT(patch->hunks->nelts == 1);
+ SVN_TEST_ASSERT(patch->old_executable_bit = svn_tristate_true);
+ SVN_TEST_ASSERT(patch->new_executable_bit = svn_tristate_unknown);
+ SVN_TEST_ASSERT(patch->old_symlink_bit = svn_tristate_false);
+ SVN_TEST_ASSERT(patch->new_symlink_bit = svn_tristate_unknown);
hunk = APR_ARRAY_IDX(patch->hunks, 0, svn_diff_hunk_t *);
Propchange: subversion/branches/ra-git/subversion/tests/libsvn_fs/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Mon Nov 30 10:24:16 2015
@@ -1,7 +1,7 @@
.libs
test-*
locks-test
-fs-test
+fs-*test
*.o
*.lo
*~
Modified: subversion/branches/ra-git/subversion/tests/libsvn_fs/fs-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_fs/fs-test.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_fs/fs-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_fs/fs-test.c Mon Nov 30 10:24:16 2015
@@ -24,6 +24,7 @@
#include <string.h>
#include <apr_pools.h>
#include <apr_thread_proc.h>
+#include <apr_poll.h>
#include <assert.h>
#include "../svn_test.h"
@@ -224,6 +225,8 @@ reopen_trivial_transaction(const svn_tes
/* Don't use the subpool, txn_name must persist beyond the current txn */
SVN_ERR(svn_fs_txn_name(&txn_name, txn, pool));
+ SVN_TEST_ASSERT(svn_fs_txn_base_revision(txn) == 0);
+
/* Create a third transaction - we don't want that one to reopen. */
SVN_ERR(svn_fs_begin_txn(&txn, fs, 0, subpool));
@@ -237,7 +240,43 @@ reopen_trivial_transaction(const svn_tes
SVN_ERR(svn_fs_txn_root(&root, txn, subpool));
SVN_TEST_STRING_ASSERT(svn_fs_txn_root_name(root, subpool), txn_name);
+ SVN_TEST_ASSERT(svn_fs_txn_base_revision(txn) == 0);
+
+ {
+ const char *conflict;
+ svn_revnum_t new_rev;
+ SVN_ERR(svn_fs_commit_txn(&conflict, &new_rev, txn, subpool));
+ SVN_TEST_STRING_ASSERT(conflict, NULL);
+ SVN_TEST_ASSERT(new_rev == 1);
+ }
+
+ /* Close the transaction ... again. */
+ svn_pool_clear(subpool);
+
+ /* Begin another transaction that is based on revision 1. */
+ SVN_ERR(svn_fs_begin_txn(&txn, fs, 1, subpool));
+
+ /* Don't use the subpool, txn_name must persist beyond the current txn */
+ SVN_ERR(svn_fs_txn_name(&txn_name, txn, pool));
+
+ SVN_TEST_ASSERT(svn_fs_txn_base_revision(txn) == 1);
+
+ /* Keep the txn name in pool */
+ SVN_ERR(svn_fs_txn_name(&txn_name, txn, pool));
+
/* Close the transaction ... again. */
+ svn_pool_clear(subpool);
+
+ /* Reopen the transaction by name ... again */
+ SVN_ERR(svn_fs_open_txn(&txn, fs, txn_name, subpool));
+
+ /* Does it have the same name? ... */
+ SVN_ERR(svn_fs_txn_root(&root, txn, subpool));
+ SVN_TEST_STRING_ASSERT(svn_fs_txn_root_name(root, subpool), txn_name);
+
+ /* And the same base revision? */
+ SVN_TEST_ASSERT(svn_fs_txn_base_revision(txn) == 1);
+
svn_pool_destroy(subpool);
return SVN_NO_ERROR;
@@ -333,6 +372,7 @@ txn_names_are_not_reused_helper1(apr_has
apr_hash_index_t *hi;
const int N = 10;
int i;
+ apr_pool_t *subpool = svn_pool_create(pool);
*txn_names = apr_hash_make(pool);
@@ -342,7 +382,8 @@ txn_names_are_not_reused_helper1(apr_has
{
svn_fs_txn_t *txn;
const char *name;
- SVN_ERR(svn_fs_begin_txn(&txn, fs, 0, pool));
+
+ SVN_ERR(svn_fs_begin_txn(&txn, fs, 0, subpool));
SVN_ERR(svn_fs_txn_name(&name, txn, pool));
if (apr_hash_get(*txn_names, name, APR_HASH_KEY_STRING) != NULL)
return svn_error_createf(SVN_ERR_FS_GENERAL, NULL,
@@ -366,6 +407,7 @@ txn_names_are_not_reused_helper1(apr_has
"created %d transactions, but only aborted %d",
N, i);
+ svn_pool_destroy(subpool);
return SVN_NO_ERROR;
}
@@ -1017,8 +1059,9 @@ check_entry(svn_fs_root_t *root,
{
apr_hash_t *entries;
svn_fs_dirent_t *ent;
+ apr_pool_t *subpool = svn_pool_create(pool);
- SVN_ERR(svn_fs_dir_entries(&entries, root, path, pool));
+ SVN_ERR(svn_fs_dir_entries(&entries, root, path, subpool));
ent = apr_hash_get(entries, name, APR_HASH_KEY_STRING);
if (ent)
@@ -1026,6 +1069,7 @@ check_entry(svn_fs_root_t *root,
else
*present = FALSE;
+ svn_pool_destroy(subpool);
return SVN_NO_ERROR;
}
@@ -4268,7 +4312,7 @@ check_related(const svn_test_opts_t *opt
if (i == j)
{
/* Identical note. */
- if (!related || relation != svn_fs_node_same)
+ if (!related || relation != svn_fs_node_unchanged)
{
return svn_error_createf
(SVN_ERR_TEST_FAILED, NULL,
@@ -4319,7 +4363,7 @@ check_related(const svn_test_opts_t *opt
rev_root, path, subpool));
/* They shall use the same noderevs */
- if (relation != svn_fs_node_same)
+ if (relation != svn_fs_node_unchanged)
{
return svn_error_createf
(SVN_ERR_TEST_FAILED, NULL,
@@ -4339,6 +4383,209 @@ check_related(const svn_test_opts_t *opt
static svn_error_t *
+check_txn_related(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ apr_pool_t *subpool = svn_pool_create(pool);
+ svn_fs_t *fs;
+ svn_fs_txn_t *txn[3];
+ svn_fs_root_t *root[3];
+ svn_revnum_t youngest_rev = 0;
+
+ /* Create a filesystem and repository. */
+ SVN_ERR(svn_test__create_fs(&fs, "test-repo-check-txn-related",
+ opts, pool));
+
+ /*** Step I: Build up some state in our repository through a series
+ of commits */
+
+ /* This is the node graph we are testing. It contains one revision (r1)
+ and two transactions, T1 and T2 - yet uncommitted.
+
+ A is a file that exists in r1 (A-0) and gets modified in both txns.
+ C is a copy of A-0 made in both txns.
+ B is a new node created in both txns
+ D is a file that exists in r1 (D-0) and never gets modified.
+ / is the root folder, touched in r0, r1 and both txns (root-0)
+ R is a copy of the root-0 made in both txns.
+
+ The edges in the graph connect related noderevs:
+
+ +--A-0--+ D-0 +-root-0-+
+ | | | |
+ +-----+ +-----+ +------+ +------+
+ | | | | | | | |
+ B-1 C-1 A-1 A-2 C-2 B-2 R-1 root-1 root-2 R-2
+ */
+ /* Revision 1 */
+ SVN_ERR(svn_fs_begin_txn(&txn[0], fs, youngest_rev, subpool));
+ SVN_ERR(svn_fs_txn_root(&root[0], txn[0], subpool));
+ SVN_ERR(svn_fs_make_file(root[0], "A", subpool));
+ SVN_ERR(svn_test__set_file_contents(root[0], "A", "1", subpool));
+ SVN_ERR(svn_fs_make_file(root[0], "D", subpool));
+ SVN_ERR(svn_fs_commit_txn(NULL, &youngest_rev, txn[0], subpool));
+ SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(youngest_rev));
+ svn_pool_clear(subpool);
+ SVN_ERR(svn_fs_revision_root(&root[0], fs, youngest_rev, pool));
+
+ /* Transaction 1 */
+ SVN_ERR(svn_fs_begin_txn(&txn[1], fs, youngest_rev, pool));
+ SVN_ERR(svn_fs_txn_root(&root[1], txn[1], pool));
+ SVN_ERR(svn_test__set_file_contents(root[1], "A", "2", pool));
+ SVN_ERR(svn_fs_copy(root[0], "A", root[1], "C", pool));
+ SVN_ERR(svn_fs_copy(root[0], "", root[1], "R", pool));
+ SVN_ERR(svn_fs_make_file(root[1], "B", pool));
+
+ /* Transaction 2 */
+ SVN_ERR(svn_fs_begin_txn(&txn[2], fs, youngest_rev, pool));
+ SVN_ERR(svn_fs_txn_root(&root[2], txn[2], pool));
+ SVN_ERR(svn_test__set_file_contents(root[2], "A", "2", pool));
+ SVN_ERR(svn_fs_copy(root[0], "A", root[2], "C", pool));
+ SVN_ERR(svn_fs_copy(root[0], "", root[2], "R", pool));
+ SVN_ERR(svn_fs_make_file(root[2], "B", pool));
+
+ /*** Step II: Exhaustively verify relationship between all nodes in
+ existence. */
+ {
+ enum { NODE_COUNT = 13 };
+ int i, j;
+
+ struct path_rev_t
+ {
+ const char *path;
+ int root;
+ };
+
+ /* Our 16 existing files/revisions. */
+ struct path_rev_t path_revs[NODE_COUNT] = {
+ { "A", 0 }, { "A", 1 }, { "A", 2 },
+ { "B", 1 }, { "B", 2 },
+ { "C", 1 }, { "C", 2 },
+ { "D", 0 },
+ { "/", 0 }, { "/", 1 }, { "/", 2 },
+ { "R", 1 }, { "R", 2 }
+ };
+
+ int related_matrix[NODE_COUNT][NODE_COUNT] = {
+ /* A-0 ... R-2 across the top here*/
+ { 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 }, /* A-0 */
+ { 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 }, /* A-1 */
+ { 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 }, /* A-2 */
+ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* B-1 */
+ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, /* B-2 */
+ { 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 }, /* C-1 */
+ { 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 }, /* C-2 */
+ { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 }, /* D-0 */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 }, /* root-0 */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 }, /* root-1 */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 }, /* root-2 */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 }, /* R-1 */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 }, /* R-2 */
+ };
+
+ /* Here's the fun part. Running the tests. */
+ for (i = 0; i < NODE_COUNT; i++)
+ {
+ for (j = 0; j < NODE_COUNT; j++)
+ {
+ struct path_rev_t pr1 = path_revs[i];
+ struct path_rev_t pr2 = path_revs[j];
+ const svn_fs_id_t *id1, *id2;
+ int related = 0;
+ svn_fs_node_relation_t relation;
+
+ svn_pool_clear(subpool);
+
+ /* Get the ID for the first path/revision combination. */
+ SVN_ERR(svn_fs_node_id(&id1, root[pr1.root], pr1.path, subpool));
+
+ /* Get the ID for the second path/revision combination. */
+ SVN_ERR(svn_fs_node_id(&id2, root[pr2.root], pr2.path, subpool));
+
+ /* <exciting> Now, run the relationship check! </exciting> */
+ related = svn_fs_check_related(id1, id2) ? 1 : 0;
+ if (related == related_matrix[i][j])
+ {
+ /* xlnt! */
+ }
+ else if ((! related) && related_matrix[i][j])
+ {
+ return svn_error_createf
+ (SVN_ERR_TEST_FAILED, NULL,
+ "expected '%s-%d' to be related to '%s-%d'; it was not",
+ pr1.path, pr1.root, pr2.path, pr2.root);
+ }
+ else if (related && (! related_matrix[i][j]))
+ {
+ return svn_error_createf
+ (SVN_ERR_TEST_FAILED, NULL,
+ "expected '%s-%d' to not be related to '%s-%d'; it was",
+ pr1.path, pr1.root, pr2.path, pr2.root);
+ }
+
+ /* Asking directly, i.e. without involving the noderev IDs as
+ * an intermediate, should yield the same results. */
+ SVN_ERR(svn_fs_node_relation(&relation, root[pr1.root], pr1.path,
+ root[pr2.root], pr2.path, subpool));
+ if (i == j)
+ {
+ /* Identical noderev. */
+ if (!related || relation != svn_fs_node_unchanged)
+ {
+ return svn_error_createf
+ (SVN_ERR_TEST_FAILED, NULL,
+ "expected '%s-%d' to be the same as '%s-%d';"
+ " it was not",
+ pr1.path, pr1.root, pr2.path, pr2.root);
+ }
+ }
+ else if (related && relation != svn_fs_node_common_ancestor)
+ {
+ return svn_error_createf
+ (SVN_ERR_TEST_FAILED, NULL,
+ "expected '%s-%d' to have a common ancestor with '%s-%d';"
+ " it had not",
+ pr1.path, pr1.root, pr2.path, pr2.root);
+ }
+ else if (!related && relation != svn_fs_node_unrelated)
+ {
+ return svn_error_createf
+ (SVN_ERR_TEST_FAILED, NULL,
+ "expected '%s-%d' to not be related to '%s-%d'; it was",
+ pr1.path, pr1.root, pr2.path, pr2.root);
+ }
+ } /* for ... */
+ } /* for ... */
+
+ /* Verify that the noderevs stay the same after their last change.
+ There is only D that is not changed. */
+ for (i = 1; i <= 2; ++i)
+ {
+ svn_fs_node_relation_t relation;
+ svn_pool_clear(subpool);
+
+ /* Query their noderev relationship to the latest change. */
+ SVN_ERR(svn_fs_node_relation(&relation, root[i], "D",
+ root[0], "D", subpool));
+
+ /* They shall use the same noderevs */
+ if (relation != svn_fs_node_unchanged)
+ {
+ return svn_error_createf
+ (SVN_ERR_TEST_FAILED, NULL,
+ "expected 'D-%d' to be the same as 'D-0'; it was not", i);
+ }
+ } /* for ... */
+ }
+
+ /* Destroy the subpool. */
+ svn_pool_destroy(subpool);
+
+ return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
branch_test(const svn_test_opts_t *opts,
apr_pool_t *pool)
{
@@ -4557,6 +4804,7 @@ closest_copy_test(const svn_test_opts_t
SVN_ERR(svn_fs_txn_root(&txn_root, txn, spool));
SVN_ERR(svn_test__create_greek_tree(txn_root, spool));
SVN_ERR(test_commit_txn(&after_rev, txn, NULL, spool));
+ svn_pool_clear(spool);
SVN_ERR(svn_fs_revision_root(&rev_root, fs, after_rev, spool));
/* Copy A to Z, and commit. */
@@ -4564,6 +4812,7 @@ closest_copy_test(const svn_test_opts_t
SVN_ERR(svn_fs_txn_root(&txn_root, txn, spool));
SVN_ERR(svn_fs_copy(rev_root, "A", txn_root, "Z", spool));
SVN_ERR(test_commit_txn(&after_rev, txn, NULL, spool));
+ svn_pool_clear(spool);
SVN_ERR(svn_fs_revision_root(&rev_root, fs, after_rev, spool));
/* Anything under Z should have a closest copy pair of ("/Z", 2), so
@@ -4600,6 +4849,7 @@ closest_copy_test(const svn_test_opts_t
SVN_ERR(svn_fs_make_file(txn_root, "Z/t", pool));
SVN_ERR(svn_fs_make_file(txn_root, "Z2/D/H2/t", pool));
SVN_ERR(test_commit_txn(&after_rev, txn, NULL, spool));
+ svn_pool_clear(spool);
SVN_ERR(svn_fs_revision_root(&rev_root, fs, after_rev, spool));
/* Okay, just for kicks, let's modify Z2/D/H2/t. Shouldn't affect
@@ -4609,6 +4859,7 @@ closest_copy_test(const svn_test_opts_t
SVN_ERR(svn_test__set_file_contents(txn_root, "Z2/D/H2/t",
"Edited text.", spool));
SVN_ERR(test_commit_txn(&after_rev, txn, NULL, spool));
+ svn_pool_clear(spool);
SVN_ERR(svn_fs_revision_root(&rev_root, fs, after_rev, spool));
/* Now, we expect Z2/D/H2 to have a closest copy of ("/Z2/D/H2", 3)
@@ -4709,7 +4960,7 @@ unordered_txn_dirprops(const svn_test_op
svn_fs_root_t *txn_root, *txn_root2;
svn_string_t pval;
svn_revnum_t new_rev, not_rev;
- svn_boolean_t is_bdb = strcmp(opts->fs_type, "bdb") == 0;
+ svn_boolean_t is_bdb = strcmp(opts->fs_type, SVN_FS_TYPE_BDB) == 0;
/* This is a regression test for issue #2751. */
@@ -4766,7 +5017,7 @@ unordered_txn_dirprops(const svn_test_op
/* Commit the first one first. */
SVN_ERR(test_commit_txn(&new_rev, txn, NULL, pool));
- /* Some backends are clever then others. */
+ /* Some backends are cleverer than others. */
if (is_bdb)
{
/* Then commit the second -- but expect an conflict because the
@@ -5142,20 +5393,20 @@ test_fs_info_format(const svn_test_opts_
int fs_format;
svn_version_t *supports_version;
svn_version_t v1_5_0 = {1, 5, 0, ""};
- svn_version_t v1_9_0 = {1, 9, 0, ""};
+ svn_version_t v1_10_0 = {1, 10, 0, ""};
svn_test_opts_t opts2;
svn_boolean_t is_fsx = strcmp(opts->fs_type, "fsx") == 0;
opts2 = *opts;
- opts2.server_minor_version = is_fsx ? 9 : 5;
+ opts2.server_minor_version = is_fsx ? 10 : 5;
SVN_ERR(svn_test__create_fs(&fs, "test-fs-format-info", &opts2, pool));
SVN_ERR(svn_fs_info_format(&fs_format, &supports_version, fs, pool, pool));
if (is_fsx)
{
- SVN_TEST_ASSERT(fs_format == 1);
- SVN_TEST_ASSERT(svn_ver_equal(supports_version, &v1_9_0));
+ SVN_TEST_ASSERT(fs_format == 2);
+ SVN_TEST_ASSERT(svn_ver_equal(supports_version, &v1_10_0));
}
else
{
@@ -5341,7 +5592,7 @@ dir_prop_merge(const svn_test_opts_t *op
svn_revnum_t head_rev;
svn_fs_root_t *root;
svn_fs_txn_t *txn, *mid_txn, *top_txn, *sub_txn, *c_txn;
- svn_boolean_t is_bdb = strcmp(opts->fs_type, "bdb") == 0;
+ svn_boolean_t is_bdb = strcmp(opts->fs_type, SVN_FS_TYPE_BDB) == 0;
/* Create test repository. */
SVN_ERR(svn_test__create_fs(&fs, "test-fs-dir_prop-merge", opts, pool));
@@ -5388,7 +5639,7 @@ dir_prop_merge(const svn_test_opts_t *op
SVN_ERR(svn_fs_abort_txn(c_txn, pool));
/* Changes in a sub-tree should not conflict with prop changes to some
- parent directory but some backends are clever then others. */
+ parent directory but some backends are cleverer than others. */
if (is_bdb)
{
SVN_ERR(test_commit_txn(&head_rev, top_txn, "/A", pool));
@@ -5407,100 +5658,6 @@ dir_prop_merge(const svn_test_opts_t *op
return SVN_NO_ERROR;
}
-#if APR_HAS_THREADS
-struct reopen_modify_baton_t {
- const char *fs_path;
- const char *txn_name;
- apr_pool_t *pool;
- svn_error_t *err;
-};
-
-static void * APR_THREAD_FUNC
-reopen_modify_child(apr_thread_t *tid, void *data)
-{
- struct reopen_modify_baton_t *baton = data;
- svn_fs_t *fs;
- svn_fs_txn_t *txn;
- svn_fs_root_t *root;
-
- baton->err = svn_fs_open(&fs, baton->fs_path, NULL, baton->pool);
- if (!baton->err)
- baton->err = svn_fs_open_txn(&txn, fs, baton->txn_name, baton->pool);
- if (!baton->err)
- baton->err = svn_fs_txn_root(&root, txn, baton->pool);
- if (!baton->err)
- baton->err = svn_fs_change_node_prop(root, "A", "name",
- svn_string_create("value",
- baton->pool),
- baton->pool);
- svn_pool_destroy(baton->pool);
- apr_thread_exit(tid, 0);
- return NULL;
-}
-#endif
-
-static svn_error_t *
-reopen_modify(const svn_test_opts_t *opts,
- apr_pool_t *pool)
-{
-#if APR_HAS_THREADS
- svn_fs_t *fs;
- svn_revnum_t head_rev = 0;
- svn_fs_root_t *root;
- svn_fs_txn_t *txn;
- const char *fs_path, *txn_name;
- svn_string_t *value;
- struct reopen_modify_baton_t baton;
- apr_status_t status, child_status;
- apr_threadattr_t *tattr;
- apr_thread_t *tid;
-
- /* Create test repository with greek tree. */
- fs_path = "test-reopen-modify";
- SVN_ERR(svn_test__create_fs(&fs, fs_path, opts, pool));
- SVN_ERR(svn_fs_begin_txn(&txn, fs, head_rev, pool));
- SVN_ERR(svn_fs_txn_root(&root, txn, pool));
- SVN_ERR(svn_test__create_greek_tree(root, pool));
- SVN_ERR(test_commit_txn(&head_rev, txn, NULL, pool));
-
- /* Create txn with changes. */
- SVN_ERR(svn_fs_begin_txn(&txn, fs, head_rev, pool));
- SVN_ERR(svn_fs_txn_name(&txn_name, txn, pool));
- SVN_ERR(svn_fs_txn_root(&root, txn, pool));
- SVN_ERR(svn_fs_make_dir(root, "X", pool));
-
- /* In another thread: reopen fs and txn, and add more changes. This
- works in BDB and FSX but in FSFS the txn_dir_cache becomes
- out-of-date and the thread's changes don't reach the revision. */
- baton.fs_path = fs_path;
- baton.txn_name = txn_name;
- baton.pool = svn_pool_create(pool);
- status = apr_threadattr_create(&tattr, pool);
- if (status)
- return svn_error_wrap_apr(status, _("Can't create threadattr"));
- status = apr_thread_create(&tid, tattr, reopen_modify_child, &baton, pool);
- if (status)
- return svn_error_wrap_apr(status, _("Can't create thread"));
- status = apr_thread_join(&child_status, tid);
- if (status)
- return svn_error_wrap_apr(status, _("Can't join thread"));
- if (baton.err)
- return svn_error_trace(baton.err);
-
- /* Commit */
- SVN_ERR(test_commit_txn(&head_rev, txn, NULL, pool));
-
- /* Check for change made by thread. */
- SVN_ERR(svn_fs_revision_root(&root, fs, head_rev, pool));
- SVN_ERR(svn_fs_node_prop(&value, root, "A", "name", pool));
- SVN_TEST_ASSERT(value && !strcmp(value->data, "value"));
-
- return SVN_NO_ERROR;
-#else
- return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL, "no thread support");
-#endif
-}
-
static svn_error_t *
upgrade_while_committing(const svn_test_opts_t *opts,
apr_pool_t *pool)
@@ -5606,7 +5763,7 @@ test_paths_changed(const svn_test_opts_t
int i;
/* The "mergeinfo_mod flag will say "unknown" until recently. */
- if ( strcmp(opts->fs_type, "bdb") != 0
+ if ( strcmp(opts->fs_type, SVN_FS_TYPE_BDB) != 0
&& (!opts->server_minor_version || (opts->server_minor_version >= 9)))
has_mergeinfo_mod = TRUE;
@@ -5841,6 +5998,9 @@ purge_txn_test(const svn_test_opts_t *op
return SVN_NO_ERROR;
}
+/* Test svn_fs_{contents,props}_{different,changed}().
+ * ### This currently only tests them on revision roots, not on txn roots.
+ */
static svn_error_t *
compare_contents(const svn_test_opts_t *opts,
apr_pool_t *pool)
@@ -5852,6 +6012,7 @@ compare_contents(const svn_test_opts_t *
svn_revnum_t rev;
int i;
apr_pool_t *iterpool = svn_pool_create(pool);
+ svn_boolean_t changed;
/* Two similar but different texts that yield the same MD5 digest. */
const char *evil_text1
@@ -6034,6 +6195,21 @@ compare_contents(const svn_test_opts_t *
}
}
+ /* Check how svn_fs_contents_different() and svn_fs_contents_changed()
+ handles invalid path.*/
+ SVN_ERR(svn_fs_revision_root(&root1, fs, 1, iterpool));
+ SVN_TEST_ASSERT_ANY_ERROR(
+ svn_fs_contents_changed(&changed, root1, "/", root1, "/", iterpool));
+ SVN_TEST_ASSERT_ANY_ERROR(
+ svn_fs_contents_different(&changed, root1, "/", root1, "/", iterpool));
+
+ SVN_TEST_ASSERT_ANY_ERROR(
+ svn_fs_contents_changed(&changed, root1, "/non-existent", root1,
+ "/non-existent", iterpool));
+ SVN_TEST_ASSERT_ANY_ERROR(
+ svn_fs_contents_different(&changed, root1, "/non-existent", root1,
+ "/non-existent", iterpool));
+
svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
@@ -6190,11 +6366,11 @@ test_print_modules(const svn_test_opts_t
svn_stringbuf_t *modules = svn_stringbuf_create_empty(pool);
/* Name of the providing module */
- if (strcmp(opts->fs_type, "fsx") == 0)
+ if (strcmp(opts->fs_type, SVN_FS_TYPE_FSX) == 0)
module_name = "fs_x";
- else if (strcmp(opts->fs_type, "fsfs") == 0)
+ else if (strcmp(opts->fs_type, SVN_FS_TYPE_FSFS) == 0)
module_name = "fs_fs";
- else if (strcmp(opts->fs_type, "bdb") == 0)
+ else if (strcmp(opts->fs_type, SVN_FS_TYPE_BDB) == 0)
module_name = "fs_base";
else
return svn_error_createf(SVN_ERR_TEST_SKIPPED, NULL,
@@ -6321,7 +6497,7 @@ test_dir_optimal_order(const svn_test_op
/* Call the API function we are interested in. */
SVN_ERR(svn_fs_dir_entries(&unordered, root, "A", pool));
- SVN_ERR(svn_fs_dir_optimal_order(&ordered, root, unordered, pool));
+ SVN_ERR(svn_fs_dir_optimal_order(&ordered, root, unordered, pool, pool));
/* Verify that all entries are returned. */
SVN_TEST_ASSERT(ordered->nelts == apr_hash_count(unordered));
@@ -6386,6 +6562,7 @@ test_delta_file_stream(const svn_test_op
svn_fs_txn_t *txn;
svn_fs_root_t *txn_root, *root1, *root2;
svn_revnum_t rev;
+ apr_pool_t *subpool = svn_pool_create(pool);
const char *old_content = "some content";
const char *new_content = "some more content";
@@ -6417,52 +6594,56 @@ test_delta_file_stream(const svn_test_op
/* Test 1: Get delta against empty target. */
SVN_ERR(svn_fs_get_file_delta_stream(&delta_stream,
- NULL, NULL, root1, "foo", pool));
+ NULL, NULL, root1, "foo", subpool));
svn_stringbuf_setempty(source);
svn_stringbuf_setempty(dest);
- svn_txdelta_apply(svn_stream_from_stringbuf(source, pool),
- svn_stream_from_stringbuf(dest, pool),
- NULL, NULL, pool, &delta_handler, &delta_baton);
+ svn_txdelta_apply(svn_stream_from_stringbuf(source, subpool),
+ svn_stream_from_stringbuf(dest, subpool),
+ NULL, NULL, subpool, &delta_handler, &delta_baton);
SVN_ERR(svn_txdelta_send_txstream(delta_stream,
delta_handler,
delta_baton,
- pool));
+ subpool));
SVN_TEST_STRING_ASSERT(old_content, dest->data);
+ svn_pool_clear(subpool);
/* Test 2: Get delta against previous version. */
SVN_ERR(svn_fs_get_file_delta_stream(&delta_stream,
- root1, "foo", root2, "foo", pool));
+ root1, "foo", root2, "foo", subpool));
svn_stringbuf_set(source, old_content);
svn_stringbuf_setempty(dest);
- svn_txdelta_apply(svn_stream_from_stringbuf(source, pool),
- svn_stream_from_stringbuf(dest, pool),
- NULL, NULL, pool, &delta_handler, &delta_baton);
+ svn_txdelta_apply(svn_stream_from_stringbuf(source, subpool),
+ svn_stream_from_stringbuf(dest, subpool),
+ NULL, NULL, subpool, &delta_handler, &delta_baton);
SVN_ERR(svn_txdelta_send_txstream(delta_stream,
delta_handler,
delta_baton,
- pool));
+ subpool));
SVN_TEST_STRING_ASSERT(new_content, dest->data);
+ svn_pool_clear(subpool);
/* Test 3: Get reverse delta. */
SVN_ERR(svn_fs_get_file_delta_stream(&delta_stream,
- root2, "foo", root1, "foo", pool));
+ root2, "foo", root1, "foo", subpool));
svn_stringbuf_set(source, new_content);
svn_stringbuf_setempty(dest);
- svn_txdelta_apply(svn_stream_from_stringbuf(source, pool),
- svn_stream_from_stringbuf(dest, pool),
- NULL, NULL, pool, &delta_handler, &delta_baton);
+ svn_txdelta_apply(svn_stream_from_stringbuf(source, subpool),
+ svn_stream_from_stringbuf(dest, subpool),
+ NULL, NULL, subpool, &delta_handler, &delta_baton);
SVN_ERR(svn_txdelta_send_txstream(delta_stream,
delta_handler,
delta_baton,
- pool));
+ subpool));
SVN_TEST_STRING_ASSERT(old_content, dest->data);
+ svn_pool_destroy(subpool);
+
return SVN_NO_ERROR;
}
@@ -6521,7 +6702,7 @@ test_fsfs_config_opts(const svn_test_opt
const svn_fs_fsfs_info_t *fsfs_info;
/* Bail (with SKIP) on known-untestable scenarios */
- if (strcmp(opts->fs_type, "fsfs") != 0)
+ if (strcmp(opts->fs_type, SVN_FS_TYPE_FSFS) != 0)
return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL,
"this will test FSFS repositories only");
@@ -6627,9 +6808,9 @@ test_modify_txn_being_written(const svn_
svn_stream_t *bar_contents;
/* Bail (with success) on known-untestable scenarios */
- if (strcmp(opts->fs_type, SVN_FS_TYPE_FSFS) != 0)
+ if (strcmp(opts->fs_type, SVN_FS_TYPE_BDB) == 0)
return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL,
- "this will test FSFS repositories only");
+ "this will not test BDB repositories");
/* Create a new repo. */
SVN_ERR(svn_test__create_fs(&fs, "test-modify-txn-being-written",
@@ -6782,6 +6963,71 @@ test_internal_txn_props(const svn_test_o
return SVN_NO_ERROR;
}
+/* A freeze function that expects an 'svn_error_t *' baton, and returns it. */
+/* This function implements svn_fs_freeze_func_t. */
+static svn_error_t *
+freeze_func(void *baton, apr_pool_t *pool)
+{
+ return baton;
+}
+
+static svn_error_t *
+freeze_and_commit(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ svn_fs_t *fs;
+ svn_fs_txn_t *txn;
+ svn_fs_root_t *txn_root;
+ svn_revnum_t new_rev = 0;
+ apr_pool_t *subpool = svn_pool_create(pool);
+
+ if (!strcmp(opts->fs_type, "bdb"))
+ return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL,
+ "this will not test BDB repositories");
+
+ SVN_ERR(svn_test__create_fs(&fs, "test-freeze-and-commit", opts, subpool));
+
+ /* This test used to FAIL with an SQLite error since svn_fs_freeze()
+ * wouldn't unlock rep-cache.db. Therefore, part of the role of creating
+ * the Greek tree is to create a rep-cache.db, in order to test that
+ * svn_fs_freeze() unlocks it. */
+
+ /* r1: Commit the Greek tree. */
+ SVN_ERR(svn_fs_begin_txn(&txn, fs, new_rev, subpool));
+ SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool));
+ SVN_ERR(svn_test__create_greek_tree(txn_root, subpool));
+ SVN_ERR(test_commit_txn(&new_rev, txn, NULL, subpool));
+
+ /* Freeze and unfreeze. */
+ SVN_ERR(svn_fs_freeze(fs, freeze_func, SVN_NO_ERROR, pool));
+
+ /* Freeze again, but have freeze_func fail. */
+ {
+ svn_error_t *err = svn_error_create(APR_EGENERAL, NULL, NULL);
+ SVN_TEST_ASSERT_ERROR(svn_fs_freeze(fs, freeze_func, err, pool),
+ err->apr_err);
+ }
+
+ /* Make some commit using same FS instance. */
+ SVN_ERR(svn_fs_begin_txn(&txn, fs, new_rev, pool));
+ SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+ SVN_ERR(svn_fs_change_node_prop(txn_root, "", "temperature",
+ svn_string_create("310.05", pool),
+ pool));
+ SVN_ERR(test_commit_txn(&new_rev, txn, NULL, pool));
+
+ /* Re-open FS and make another commit. */
+ SVN_ERR(svn_fs_open(&fs, "test-freeze-and-commit", NULL, subpool));
+ SVN_ERR(svn_fs_begin_txn(&txn, fs, new_rev, pool));
+ SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+ SVN_ERR(svn_fs_change_node_prop(txn_root, "/", "temperature",
+ svn_string_create("451", pool),
+ pool));
+ SVN_ERR(test_commit_txn(&new_rev, txn, NULL, pool));
+
+ return SVN_NO_ERROR;
+}
+
/* ------------------------------------------------------------------------ */
/* The test table. */
@@ -6876,9 +7122,6 @@ static struct svn_test_descriptor_t test
"test svn_fs__compatible_version"),
SVN_TEST_OPTS_PASS(dir_prop_merge,
"test merge directory properties"),
- SVN_TEST_OPTS_XFAIL_OTOH(reopen_modify,
- "test reopen and modify txn",
- SVN_TEST_PASS_IF_FS_TYPE_IS_NOT("fsfs")),
SVN_TEST_OPTS_PASS(upgrade_while_committing,
"upgrade while committing"),
SVN_TEST_OPTS_PASS(test_paths_changed,
@@ -6910,11 +7153,15 @@ static struct svn_test_descriptor_t test
SVN_TEST_OPTS_PASS(test_txn_pool_lifetime,
"test pool lifetime dependencies with txn roots"),
SVN_TEST_OPTS_PASS(test_modify_txn_being_written,
- "test modify txn being written in FSFS"),
+ "test modify txn being written"),
SVN_TEST_OPTS_PASS(test_prop_and_text_rep_sharing_collision,
"test property and text rep-sharing collision"),
SVN_TEST_OPTS_PASS(test_internal_txn_props,
"test setting and getting internal txn props"),
+ SVN_TEST_OPTS_PASS(check_txn_related,
+ "test svn_fs_check_related for transactions"),
+ SVN_TEST_OPTS_PASS(freeze_and_commit,
+ "freeze and commit"),
SVN_TEST_NULL
};
Modified: subversion/branches/ra-git/subversion/tests/libsvn_fs/locks-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_fs/locks-test.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_fs/locks-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_fs/locks-test.c Mon Nov 30 10:24:16 2015
@@ -1101,9 +1101,10 @@ obtain_write_lock_failure(const svn_test
apr_hash_t *lock_paths, *unlock_paths;
/* The test makes sense only for FSFS. */
- if (strcmp(opts->fs_type, SVN_FS_TYPE_FSFS) != 0)
+ if (strcmp(opts->fs_type, SVN_FS_TYPE_FSFS) != 0
+ && strcmp(opts->fs_type, SVN_FS_TYPE_FSX) != 0)
return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL,
- "this will test FSFS repositories only");
+ "this will test FSFS/FSX repositories only");
SVN_ERR(create_greek_fs(&fs, &newrev, "test-obtain-write-lock-failure",
opts, pool));
Modified: subversion/branches/ra-git/subversion/tests/libsvn_fs_fs/fs-fs-fuzzy-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_fs_fs/fs-fs-fuzzy-test.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_fs_fs/fs-fs-fuzzy-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_fs_fs/fs-fs-fuzzy-test.c Mon Nov 30 10:24:16 2015
@@ -117,8 +117,9 @@ fuzzing_1_byte_1_rev(const char *repo_na
svn_fs_set_warning_func(svn_repos_fs(repos), dont_filter_warnings, NULL);
/* This shall detect the corruption and return an error. */
- err = svn_repos_verify_fs3(repos, revision, revision, TRUE, FALSE, FALSE,
- NULL, NULL, NULL, NULL, iterpool);
+ err = svn_repos_verify_fs3(repos, revision, revision, FALSE, FALSE,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ iterpool);
/* Case-only changes in checksum digests are not an error.
* We allow upper case chars to be used in MD5 checksums in all other
Modified: subversion/branches/ra-git/subversion/tests/libsvn_fs_fs/fs-fs-pack-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_fs_fs/fs-fs-pack-test.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_fs_fs/fs-fs-pack-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_fs_fs/fs-fs-pack-test.c Mon Nov 30 10:24:16 2015
@@ -1343,8 +1343,9 @@ plain_0_length(const svn_test_opts_t *op
memcpy(rev_contents->data + offset, noderev_str->data, noderev_str->len);
}
- SVN_ERR(svn_io_write_atomic(rev_path, rev_contents->data,
- rev_contents->len, NULL, pool));
+ SVN_ERR(svn_io_write_atomic2(rev_path, rev_contents->data,
+ rev_contents->len, NULL, FALSE,
+ pool));
if (svn_fs_fs__use_log_addressing(fs))
{
@@ -1372,6 +1373,281 @@ plain_0_length(const svn_test_opts_t *op
#undef REPO_NAME
+/* ------------------------------------------------------------------------ */
+
+#define REPO_NAME "test-repo-rep_sharing_effectiveness"
+
+static int
+count_substring(svn_stringbuf_t *string,
+ const char *needle)
+{
+ int count = 0;
+ apr_size_t len = strlen(needle);
+ apr_size_t pos;
+
+ for (pos = 0; pos + len <= string->len; ++pos)
+ if (memcmp(string->data + pos, needle, len) == 0)
+ ++count;
+
+ return count;
+}
+
+static svn_error_t *
+count_representations(int *count,
+ svn_fs_t *fs,
+ svn_revnum_t revision,
+ apr_pool_t *pool)
+{
+ svn_stringbuf_t *rev_contents;
+ const char *rev_path = svn_fs_fs__path_rev_absolute(fs, revision, pool);
+ SVN_ERR(svn_stringbuf_from_file2(&rev_contents, rev_path, pool));
+
+ *count = count_substring(rev_contents, "PLAIN")
+ + count_substring(rev_contents, "DELTA");
+
+ return SVN_NO_ERROR;
+}
+
+/* Repeat string S many times to make it big enough for deltification etc.
+ to kick in. */
+static const char*
+multiply_string(const char *s,
+ apr_pool_t *pool)
+{
+ svn_stringbuf_t *temp = svn_stringbuf_create(s, pool);
+
+ int i;
+ for (i = 0; i < 7; ++i)
+ svn_stringbuf_insert(temp, temp->len, temp->data, temp->len);
+
+ return temp->data;
+}
+
+static svn_error_t *
+rep_sharing_effectiveness(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ svn_fs_t *fs;
+ fs_fs_data_t *ffd;
+ svn_fs_txn_t *txn;
+ svn_fs_root_t *root;
+ svn_revnum_t rev;
+ const char *hello_str = multiply_string("Hello, ", pool);
+ const char *world_str = multiply_string("World!", pool);
+ const char *goodbye_str = multiply_string("Goodbye!", pool);
+
+ if (strcmp(opts->fs_type, "fsfs") != 0)
+ return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL, NULL);
+
+ /* Create a repo that and explicitly enable rep sharing. */
+ SVN_ERR(svn_test__create_fs(&fs, REPO_NAME, opts, pool));
+
+ ffd = fs->fsap_data;
+ if (ffd->format < SVN_FS_FS__MIN_REP_SHARING_FORMAT)
+ return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL, NULL);
+
+ ffd->rep_sharing_allowed = TRUE;
+
+ /* Revision 1: create 2 files with different content. */
+ SVN_ERR(svn_fs_begin_txn(&txn, fs, 0, pool));
+ SVN_ERR(svn_fs_txn_root(&root, txn, pool));
+ SVN_ERR(svn_fs_make_file(root, "foo", pool));
+ SVN_ERR(svn_test__set_file_contents(root, "foo", hello_str, pool));
+ SVN_ERR(svn_fs_make_file(root, "bar", pool));
+ SVN_ERR(svn_test__set_file_contents(root, "bar", world_str, pool));
+ SVN_ERR(svn_fs_commit_txn(NULL, &rev, txn, pool));
+
+ /* Revision 2: modify a file to match another file's r1 content and
+ add another with the same content.
+ (classic rep-sharing). */
+ SVN_ERR(svn_fs_begin_txn(&txn, fs, rev, pool));
+ SVN_ERR(svn_fs_txn_root(&root, txn, pool));
+ SVN_ERR(svn_test__set_file_contents(root, "foo", world_str, pool));
+ SVN_ERR(svn_fs_make_file(root, "baz", pool));
+ SVN_ERR(svn_test__set_file_contents(root, "baz", hello_str, pool));
+ SVN_ERR(svn_fs_commit_txn(NULL, &rev, txn, pool));
+
+ /* Revision 3: modify all files to some new, identical content and add
+ another with the same content.
+ (in-revision rep-sharing). */
+ SVN_ERR(svn_fs_begin_txn(&txn, fs, rev, pool));
+ SVN_ERR(svn_fs_txn_root(&root, txn, pool));
+ SVN_ERR(svn_test__set_file_contents(root, "foo", goodbye_str, pool));
+ SVN_ERR(svn_test__set_file_contents(root, "bar", goodbye_str, pool));
+ SVN_ERR(svn_test__set_file_contents(root, "baz", goodbye_str, pool));
+ SVN_ERR(svn_fs_make_file(root, "qux", pool));
+ SVN_ERR(svn_test__set_file_contents(root, "qux", goodbye_str, pool));
+ SVN_ERR(svn_fs_commit_txn(NULL, &rev, txn, pool));
+
+ /* Verify revision contents. */
+ {
+ const struct {
+ svn_revnum_t revision;
+ const char *file;
+ const char *contents;
+ } expected[] = {
+ { 1, "foo", "Hello, " },
+ { 1, "bar", "World!" },
+ { 2, "foo", "World!" },
+ { 2, "bar", "World!" },
+ { 2, "baz", "Hello, " },
+ { 3, "foo", "Goodbye!" },
+ { 3, "bar", "Goodbye!" },
+ { 3, "baz", "Goodbye!" },
+ { 3, "qux", "Goodbye!" },
+ { SVN_INVALID_REVNUM, NULL, NULL }
+ };
+
+ int i;
+ apr_pool_t *iterpool = svn_pool_create(pool);
+ for (i = 0; SVN_IS_VALID_REVNUM(expected[i].revision); ++i)
+ {
+ svn_stringbuf_t *str;
+
+ SVN_ERR(svn_fs_revision_root(&root, fs, expected[i].revision,
+ iterpool));
+ SVN_ERR(svn_test__get_file_contents(root, expected[i].file, &str,
+ iterpool));
+
+ SVN_TEST_STRING_ASSERT(str->data,
+ multiply_string(expected[i].contents,
+ iterpool));
+ }
+
+ svn_pool_destroy(iterpool);
+ }
+
+ /* Verify that rep sharing eliminated most reps. */
+ {
+ /* Number of expected representations (including the root directory). */
+ const int expected[] = { 1, 3, 1, 2 } ;
+
+ svn_revnum_t i;
+ apr_pool_t *iterpool = svn_pool_create(pool);
+ for (i = 0; i <= rev; ++i)
+ {
+ int count;
+ SVN_ERR(count_representations(&count, fs, i, iterpool));
+ SVN_TEST_ASSERT(count == expected[i]);
+ }
+
+ svn_pool_destroy(iterpool);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+#undef REPO_NAME
+
+/* ------------------------------------------------------------------------ */
+
+#define REPO_NAME "test-repo-delta_chain_with_plain"
+
+static svn_error_t *
+delta_chain_with_plain(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ svn_fs_t *fs;
+ fs_fs_data_t *ffd;
+ svn_fs_txn_t *txn;
+ svn_fs_root_t *root;
+ svn_revnum_t rev;
+ svn_stringbuf_t *prop_value, *contents, *contents2, *hash_rep;
+ int i;
+ apr_hash_t *fs_config, *props;
+
+ if (strcmp(opts->fs_type, "fsfs") != 0)
+ return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL, NULL);
+
+ /* Reproducing issue #4577 without the r1676667 fix is much harder in 1.9+
+ * than it was in 1.8. The reason is that 1.9+ won't deltify small reps
+ * nor against small reps. So, we must construct relatively large PLAIN
+ * and DELTA reps.
+ *
+ * The idea is to construct a PLAIN prop rep, make a file share that as
+ * its text rep, grow the file considerably (to make the PLAIN rep later
+ * read beyond EOF) and then replace it entirely with another longish
+ * contents.
+ */
+
+ /* Create a repo that and explicitly enable rep sharing. */
+ SVN_ERR(svn_test__create_fs(&fs, REPO_NAME, opts, pool));
+
+ ffd = fs->fsap_data;
+ if (ffd->format < SVN_FS_FS__MIN_REP_SHARING_FORMAT)
+ return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL, NULL);
+
+ ffd->rep_sharing_allowed = TRUE;
+
+ /* Make sure all props are stored as PLAIN reps. */
+ ffd->deltify_properties = FALSE;
+
+ /* Construct various content strings.
+ * Note that props need to be shorter than the file contents. */
+ prop_value = svn_stringbuf_create("prop", pool);
+ for (i = 0; i < 10; ++i)
+ svn_stringbuf_appendstr(prop_value, prop_value);
+
+ contents = svn_stringbuf_create("Some text.", pool);
+ for (i = 0; i < 10; ++i)
+ svn_stringbuf_appendstr(contents, contents);
+
+ contents2 = svn_stringbuf_create("Totally new!", pool);
+ for (i = 0; i < 10; ++i)
+ svn_stringbuf_appendstr(contents2, contents2);
+
+ /* Revision 1: create a property rep. */
+ SVN_ERR(svn_fs_begin_txn(&txn, fs, 0, pool));
+ SVN_ERR(svn_fs_txn_root(&root, txn, pool));
+ SVN_ERR(svn_fs_change_node_prop(root, "/", "p",
+ svn_string_create(prop_value->data, pool),
+ pool));
+ SVN_ERR(svn_fs_commit_txn(NULL, &rev, txn, pool));
+
+ /* Revision 2: create a file that shares the text rep with the PLAIN
+ * property rep from r1. */
+ props = apr_hash_make(pool);
+ svn_hash_sets(props, "p", svn_string_create(prop_value->data, pool));
+
+ hash_rep = svn_stringbuf_create_empty(pool);
+ svn_hash_write2(props, svn_stream_from_stringbuf(hash_rep, pool), "END",
+ pool);
+
+ SVN_ERR(svn_fs_begin_txn(&txn, fs, rev, pool));
+ SVN_ERR(svn_fs_txn_root(&root, txn, pool));
+ SVN_ERR(svn_fs_make_file(root, "foo", pool));
+ SVN_ERR(svn_test__set_file_contents(root, "foo", hash_rep->data, pool));
+ SVN_ERR(svn_fs_commit_txn(NULL, &rev, txn, pool));
+
+ /* Revision 3: modify the file contents to a long-ish full text
+ * (~10kByte, longer than the r1 revision file). */
+ SVN_ERR(svn_fs_begin_txn(&txn, fs, rev, pool));
+ SVN_ERR(svn_fs_txn_root(&root, txn, pool));
+ SVN_ERR(svn_test__set_file_contents(root, "foo", contents->data, pool));
+ SVN_ERR(svn_fs_commit_txn(NULL, &rev, txn, pool));
+
+ /* Revision 4: replace file contents to something disjoint from r3. */
+ SVN_ERR(svn_fs_begin_txn(&txn, fs, rev, pool));
+ SVN_ERR(svn_fs_txn_root(&root, txn, pool));
+ SVN_ERR(svn_test__set_file_contents(root, "foo", contents2->data, pool));
+ SVN_ERR(svn_fs_commit_txn(NULL, &rev, txn, pool));
+
+ /* Getting foo@4 must work. To make sure we actually read from disk,
+ * use a new FS instance with disjoint caches. */
+ fs_config = apr_hash_make(pool);
+ svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_NS,
+ svn_uuid_generate(pool));
+ SVN_ERR(svn_fs_open2(&fs, REPO_NAME, fs_config, pool, pool));
+
+ SVN_ERR(svn_fs_revision_root(&root, fs, rev, pool));
+ SVN_ERR(svn_test__get_file_contents(root, "foo", &contents, pool));
+ SVN_TEST_STRING_ASSERT(contents->data, contents2->data);
+
+ return SVN_NO_ERROR;
+}
+
+#undef REPO_NAME
+
/* The test table. */
@@ -1416,6 +1692,10 @@ static struct svn_test_descriptor_t test
"id parser test"),
SVN_TEST_OPTS_PASS(plain_0_length,
"file with 0 expanded-length, issue #4554"),
+ SVN_TEST_OPTS_PASS(rep_sharing_effectiveness,
+ "rep-sharing effectiveness"),
+ SVN_TEST_OPTS_PASS(delta_chain_with_plain,
+ "delta chains starting with PLAIN, issue #4577"),
SVN_TEST_NULL
};
Modified: subversion/branches/ra-git/subversion/tests/libsvn_fs_fs/fs-fs-private-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_fs_fs/fs-fs-private-test.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_fs_fs/fs-fs-private-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_fs_fs/fs-fs-private-test.c Mon Nov 30 10:24:16 2015
@@ -105,6 +105,10 @@ verify_representation_stats(const svn_fs
SVN_TEST_ASSERT(stats->references == stats->total.count);
SVN_TEST_ASSERT(stats->expanded_size == stats->total.expanded_size);
+ /* Reasonable delta chain lengths */
+ SVN_TEST_ASSERT( stats->chain_len >= stats->total.count
+ && stats->chain_len <= 5 * stats->total.count);
+
return SVN_NO_ERROR;
}
@@ -349,8 +353,6 @@ dump_index(const svn_test_opts_t *opts,
/* ------------------------------------------------------------------------ */
-#define REPO_NAME "test-repo-load-index-test"
-
static svn_error_t *
receive_index(const svn_fs_fs__p2l_entry_t *entry,
void *baton,
@@ -363,9 +365,10 @@ receive_index(const svn_fs_fs__p2l_entry
return SVN_NO_ERROR;
}
+#define REPO_NAME "test-repo-load-index-test"
+
static svn_error_t *
-load_index(const svn_test_opts_t *opts,
- apr_pool_t *pool)
+load_index(const svn_test_opts_t *opts, apr_pool_t *pool)
{
svn_repos_t *repos;
svn_revnum_t rev;
@@ -389,24 +392,25 @@ load_index(const svn_test_opts_t *opts,
SVN_ERR(svn_fs_fs__dump_index(svn_repos_fs(repos), rev, receive_index,
entries, NULL, NULL, pool));
- /* Replace it with an empty index.
- * Note that the API requires at least one entry. Give it a dummy. */
+ /* Replace it with an index that declares the whole revision contents as
+ * "unused". */
+ entry = *APR_ARRAY_IDX(entries, entries->nelts-1, svn_fs_fs__p2l_entry_t *);
+ entry.size += entry.offset;
entry.offset = 0;
- entry.size = 0;
entry.type = SVN_FS_FS__ITEM_TYPE_UNUSED;
entry.item.number = SVN_FS_FS__ITEM_INDEX_UNUSED;
entry.item.revision = SVN_INVALID_REVNUM;
APR_ARRAY_PUSH(alt_entries, svn_fs_fs__p2l_entry_t *) = &entry;
SVN_ERR(svn_fs_fs__load_index(svn_repos_fs(repos), rev, alt_entries, pool));
- SVN_TEST_ASSERT_ERROR(svn_repos_verify_fs3(repos, rev, rev,
- FALSE, FALSE, FALSE,
- NULL, NULL, NULL, NULL, pool),
- SVN_ERR_REPOS_CORRUPTED);
+ SVN_TEST_ASSERT_ERROR(svn_repos_verify_fs3(repos, rev, rev, FALSE, FALSE,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, pool),
+ SVN_ERR_FS_INDEX_CORRUPTION);
/* Restore the original index. */
SVN_ERR(svn_fs_fs__load_index(svn_repos_fs(repos), rev, entries, pool));
- SVN_ERR(svn_repos_verify_fs3(repos, rev, rev, FALSE, FALSE, FALSE,
+ SVN_ERR(svn_repos_verify_fs3(repos, rev, rev, FALSE, FALSE, NULL, NULL,
NULL, NULL, NULL, NULL, pool));
return SVN_NO_ERROR;
@@ -414,6 +418,7 @@ load_index(const svn_test_opts_t *opts,
#undef REPO_NAME
+
/* The test table. */
Propchange: subversion/branches/ra-git/subversion/tests/libsvn_fs_x/
('svn:mergeinfo' removed)
Modified: subversion/branches/ra-git/subversion/tests/libsvn_fs_x/fs-x-pack-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_fs_x/fs-x-pack-test.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_fs_x/fs-x-pack-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_fs_x/fs-x-pack-test.c Mon Nov 30 10:24:16 2015
@@ -25,6 +25,7 @@
#include <apr_pools.h>
#include "../svn_test.h"
+#include "../../libsvn_fs_x/batch_fsync.h"
#include "../../libsvn_fs_x/fs.h"
#include "../../libsvn_fs_x/reps.h"
@@ -60,8 +61,8 @@ write_format(const char *path,
"layout sharded %d\n",
format, max_files_per_dir);
- SVN_ERR(svn_io_write_atomic(path, contents, strlen(contents),
- NULL /* copy perms */, pool));
+ SVN_ERR(svn_io_write_atomic2(path, contents, strlen(contents),
+ NULL /* copy perms */, FALSE, pool));
/* And set the perms to make it read only */
return svn_io_set_file_read_only(path, FALSE, pool);
@@ -657,8 +658,8 @@ recover_fully_packed(const svn_test_opts
/* Now, delete the youngest revprop file, and recover again. This
time we want to see an error! */
SVN_ERR(svn_io_remove_file2(
- svn_dirent_join_many(pool, REPO_NAME, PATH_REVPROPS_DIR,
- apr_psprintf(pool, "%ld/%ld",
+ svn_dirent_join_many(pool, REPO_NAME, PATH_REVS_DIR,
+ apr_psprintf(pool, "%ld/p%ld",
after_rev / SHARD_SIZE,
after_rev),
SVN_VA_NULL),
@@ -844,6 +845,90 @@ pack_shard_size_one(const svn_test_opts_
#undef SHARD_SIZE
#undef MAX_REV
/* ------------------------------------------------------------------------ */
+#define REPO_NAME "test-repo-fsx-batch-fsync"
+static svn_error_t *
+test_batch_fsync(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ const char *abspath;
+ svn_fs_x__batch_fsync_t *batch;
+ int i;
+
+ /* Disable this test for non FSX backends because it has no relevance to
+ * them. */
+ if (strcmp(opts->fs_type, "fsx") != 0)
+ return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL,
+ "this will test FSX repositories only");
+
+ /* Create an empty working directory and let it be cleaned up by the test
+ * harness. */
+ SVN_ERR(svn_dirent_get_absolute(&abspath, REPO_NAME, pool));
+
+ SVN_ERR(svn_io_remove_dir2(abspath, TRUE, NULL, NULL, pool));
+ SVN_ERR(svn_io_make_dir_recursively(abspath, pool));
+ svn_test_add_dir_cleanup(abspath);
+
+ /* Initialize infrastructure with a pool that lives as long as this
+ * application. */
+ SVN_ERR(svn_fs_x__batch_fsync_init());
+
+ /* We use and re-use the same batch object throughout this test. */
+ SVN_ERR(svn_fs_x__batch_fsync_create(&batch, pool));
+
+ /* The working directory is new. */
+ SVN_ERR(svn_fs_x__batch_fsync_new_path(batch, abspath, pool));
+
+ /* 1st run: Has to fire up worker threads etc. */
+ for (i = 0; i < 10; ++i)
+ {
+ apr_file_t *file;
+ const char *path = svn_dirent_join(abspath,
+ apr_psprintf(pool, "file%i", i),
+ pool);
+ apr_size_t len = strlen(path);
+
+ SVN_ERR(svn_fs_x__batch_fsync_open_file(&file, batch, path, pool));
+
+ SVN_ERR(svn_io_file_write(file, path, &len, pool));
+ }
+
+ SVN_ERR(svn_fs_x__batch_fsync_run(batch, pool));
+
+ /* 2nd run: Running a batch must leave the container in an empty,
+ * re-usable state. Hence, try to re-use it. */
+ for (i = 0; i < 10; ++i)
+ {
+ apr_file_t *file;
+ const char *path = svn_dirent_join(abspath,
+ apr_psprintf(pool, "new%i", i),
+ pool);
+ apr_size_t len = strlen(path);
+
+ SVN_ERR(svn_fs_x__batch_fsync_open_file(&file, batch, path, pool));
+
+ SVN_ERR(svn_io_file_write(file, path, &len, pool));
+ }
+
+ SVN_ERR(svn_fs_x__batch_fsync_run(batch, pool));
+
+ /* 3rd run: Schedule but don't execute. POOL cleanup shall not fail. */
+ for (i = 0; i < 10; ++i)
+ {
+ apr_file_t *file;
+ const char *path = svn_dirent_join(abspath,
+ apr_psprintf(pool, "another%i", i),
+ pool);
+ apr_size_t len = strlen(path);
+
+ SVN_ERR(svn_fs_x__batch_fsync_open_file(&file, batch, path, pool));
+
+ SVN_ERR(svn_io_file_write(file, path, &len, pool));
+ }
+
+ return SVN_NO_ERROR;
+}
+#undef REPO_NAME
+/* ------------------------------------------------------------------------ */
/* The test table. */
@@ -876,6 +961,8 @@ static struct svn_test_descriptor_t test
"test representations container"),
SVN_TEST_OPTS_PASS(pack_shard_size_one,
"test packing with shard size = 1"),
+ SVN_TEST_OPTS_PASS(test_batch_fsync,
+ "test batch fsync"),
SVN_TEST_NULL
};