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 *) = &copy_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
   };