You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2018/11/13 07:49:08 UTC

svn commit: r1846488 [20/23] - in /subversion/branches/mod-dav-svn-expressions: ./ build/ build/ac-macros/ build/generator/ build/generator/swig/ build/generator/templates/ build/generator/util/ build/win32/ contrib/client-side/ contrib/client-side/svn...

Modified: subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svnrdump_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svnrdump_tests.py?rev=1846488&r1=1846487&r2=1846488&view=diff
==============================================================================
--- subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svnrdump_tests.py (original)
+++ subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svnrdump_tests.py Tue Nov 13 07:49:04 2018
@@ -80,7 +80,54 @@ def compare_repos_dumps(sbox, other_dump
 
   ### This call kind-of assumes EXPECTED is first and ACTUAL is second.
   svntest.verify.compare_dump_files(
-    "Dump files", "DUMP", other_dumpfile, sbox_dumpfile)
+    None, None, other_dumpfile, sbox_dumpfile)
+
+def run_and_verify_svnrdump_dump(dumpfile,
+                                 expected_stdout,
+                                 expected_stderr,
+                                 expected_exit,
+                                 *varargs):
+  """Run 'svnrdump dump'.
+     Verify the results against EXPECTED_*.
+     DUMPFILE is a filename to write to, or None to return the dump as a
+     list of strings.
+  """
+  if dumpfile:
+    varargs += ('--file=' + dumpfile,)
+    exp_stdout = None
+  else:
+    exp_stdout = expected_stdout
+  output = svntest.actions.run_and_verify_svnrdump(
+                                None,
+                                exp_stdout,
+                                expected_stderr,
+                                expected_exit,
+                                'dump',
+                                *varargs)
+  if not dumpfile:
+    return output
+
+def run_and_verify_svnrdump_load(dumpfile,
+                                 expected_stdout,
+                                 expected_stderr,
+                                 expected_exit,
+                                 *varargs):
+  """Run 'svnrdump load' to load a dumpfile.
+     Verify the results against EXPECTED_*.
+     DUMPFILE is a filename or the dump content as a list of strings.
+  """
+  if isinstance(dumpfile, list):
+    dumpfile_content = dumpfile
+  else:
+    dumpfile_content = None
+    varargs += ('--file=' + dumpfile,)
+  svntest.actions.run_and_verify_svnrdump(
+                                dumpfile_content,
+                                expected_stdout,
+                                expected_stderr,
+                                expected_exit,
+                                'load',
+                                *varargs)
 
 def run_dump_test(sbox, dumpfile_name, expected_dumpfile_name = None,
                   subdir = None, bypass_prop_validation = False,
@@ -112,10 +159,11 @@ def run_dump_test(sbox, dumpfile_name, e
     repo_url = repo_url + subdir
 
   # Create a dump file using svnrdump
-  opts = extra_options + ['-q', 'dump', repo_url]
+  opts = extra_options + ['-q', repo_url]
   svnrdump_dumpfile = \
-      svntest.actions.run_and_verify_svnrdump(None, svntest.verify.AnyOutput,
-                                              [], 0, *opts)
+      run_and_verify_svnrdump_dump(None,
+                                   svntest.verify.AnyOutput, [], 0,
+                                   *opts)
 
   if expected_dumpfile_name:
     expected_dumpfile = open(os.path.join(svnrdump_tests_dir,
@@ -170,9 +218,9 @@ def run_load_test(sbox, dumpfile_name, e
                                            'setuuid', sbox.repo_dir,
                                            uuid)
 
-  svntest.actions.run_and_verify_svnrdump(original_dumpfile,
-                                          svntest.verify.AnyOutput,
-                                          [], 0, 'load', sbox.repo_url)
+  run_and_verify_svnrdump_load(original_dumpfile,
+                               svntest.verify.AnyOutput,
+                               [], 0, sbox.repo_url)
 
   # Re-dump the rdump-loaded repo using svnadmin dump
   resulted_dumpfile = svntest.actions.run_and_verify_dump(sbox.repo_dir,
@@ -199,9 +247,9 @@ def basic_dump(sbox):
   sbox.build(read_only = True, create_wc = False)
 
   out = \
-      svntest.actions.run_and_verify_svnrdump(None, svntest.verify.AnyOutput,
-                                              [], 0, '-q', 'dump',
-                                              sbox.repo_url)
+      run_and_verify_svnrdump_dump(None,
+                                   svntest.verify.AnyOutput, [], 0,
+                                   '-q', sbox.repo_url)
 
   if not out[0].startswith(b'SVN-fs-dump-format-version:'):
     raise svntest.Failure('No valid output')
@@ -408,17 +456,14 @@ def reflect_dropped_renumbered_revs(sbox
 
   # Load the specified dump file into the sbox repository using
   # svnrdump load
-  dump_file = open(os.path.join(os.path.dirname(sys.argv[0]),
-                                                'svnrdump_tests_data',
-                                                'with_merges.dump'),
-                   'rb')
-  svnrdump_dumpfile = dump_file.readlines()
-  dump_file.close()
+  dump_file = os.path.join(os.path.dirname(sys.argv[0]),
+                           'svnrdump_tests_data',
+                           'with_merges.dump')
 
   # svnrdump load the dump file.
-  svntest.actions.run_and_verify_svnrdump(svnrdump_dumpfile,
-                                          svntest.verify.AnyOutput,
-                                          [], 0, 'load', sbox.repo_url)
+  run_and_verify_svnrdump_load(dump_file,
+                               svntest.verify.AnyOutput, [], 0,
+                               sbox.repo_url)
 
   # Create the 'toplevel' directory in repository and then load the same
   # dumpfile into that subtree.
@@ -426,10 +471,9 @@ def reflect_dropped_renumbered_revs(sbox
                                             'Committed revision 10.\n'],
                                     [], "mkdir", sbox.repo_url + "/toplevel",
                                      "-m", "Create toplevel dir to load into")
-  svntest.actions.run_and_verify_svnrdump(svnrdump_dumpfile,
-                                          svntest.verify.AnyOutput,
-                                          [], 0, 'load',
-                                          sbox.repo_url + "/toplevel")
+  run_and_verify_svnrdump_load(dump_file,
+                               svntest.verify.AnyOutput, [], 0,
+                               sbox.repo_url + "/toplevel")
   # Verify the svn:mergeinfo properties
   url = sbox.repo_url
   expected_output = svntest.verify.UnorderedOutput([
@@ -455,7 +499,7 @@ def reflect_dropped_renumbered_revs(sbox
 #   2) Dump 'SOURCE-REPOS' in a series of incremental dumps and load
 #      each of them to 'TARGET-REPOS'.
 #
-# See http://subversion.tigris.org/issues/show_bug.cgi?id=3020#desc13
+# See https://issues.apache.org/jira/browse/SVN-3020#desc13
 #
 # This test replicates svnadmin_tests.py 20 'don't filter mergeinfo revs
 # from incremental dump' but uses 'svnrdump [dump|load]' in place of
@@ -515,16 +559,13 @@ def dont_drop_valid_mergeinfo_during_inc
   #   Properties on 'branches/B2':
   #     svn:mergeinfo
   #       /trunk:9
-  dump_fp = open(os.path.join(os.path.dirname(sys.argv[0]),
-                              'svnrdump_tests_data',
-                              'mergeinfo_included_full.dump'),
-                 'rb')
-  dumpfile_full = dump_fp.readlines()
-  dump_fp.close()
-
-  svntest.actions.run_and_verify_svnrdump(dumpfile_full,
-                                          svntest.verify.AnyOutput,
-                                          [], 0, 'load', sbox.repo_url)
+  dumpfile_full = os.path.join(os.path.dirname(sys.argv[0]),
+                               'svnrdump_tests_data',
+                               'mergeinfo_included_full.dump')
+
+  run_and_verify_svnrdump_load(dumpfile_full,
+                               svntest.verify.AnyOutput, [], 0,
+                               sbox.repo_url)
 
   # Check that the mergeinfo is as expected.
   url = sbox.repo_url + '/branches/'
@@ -542,33 +583,22 @@ def dont_drop_valid_mergeinfo_during_inc
   #
   # Incrementally dump the repository into three dump files:
   dump_file_r1_10 = sbox.get_tempname("r1-10-dump")
-  output = svntest.actions.run_and_verify_svnrdump(None,
-                                                   svntest.verify.AnyOutput,
-                                                   [], 0, '-q', 'dump', '-r1:10',
-                                                   sbox.repo_url)
-  dump_fp = open(dump_file_r1_10, 'wb')
-  dump_fp.writelines(output)
-  dump_fp.close()
+  run_and_verify_svnrdump_dump(dump_file_r1_10,
+                               svntest.verify.AnyOutput, [], 0,
+                               '-q', '-r1:10',
+                               sbox.repo_url)
 
   dump_file_r11_13 = sbox.get_tempname("r11-13-dump")
-  output = svntest.actions.run_and_verify_svnrdump(None,
-                                                   svntest.verify.AnyOutput,
-                                                   [], 0, '-q', 'dump',
-                                                   '--incremental', '-r11:13',
-                                                   sbox.repo_url)
-  dump_fp = open(dump_file_r11_13, 'wb')
-  dump_fp.writelines(output)
-  dump_fp.close()
+  run_and_verify_svnrdump_dump(dump_file_r11_13,
+                               svntest.verify.AnyOutput, [], 0,
+                               '-q', '--incremental', '-r11:13',
+                               sbox.repo_url)
 
   dump_file_r14_15 = sbox.get_tempname("r14-15-dump")
-  output = svntest.actions.run_and_verify_svnrdump(None,
-                                                   svntest.verify.AnyOutput,
-                                                   [], 0, '-q', 'dump',
-                                                   '--incremental', '-r14:15',
-                                                   sbox.repo_url)
-  dump_fp = open(dump_file_r14_15, 'wb')
-  dump_fp.writelines(output)
-  dump_fp.close()
+  run_and_verify_svnrdump_dump(dump_file_r14_15,
+                               svntest.verify.AnyOutput, [], 0,
+                               '-q', '--incremental', '-r14:15',
+                               sbox.repo_url)
 
   # Blow away the current repos and create an empty one in its place.
   svntest.main.safe_rmtree(sbox.repo_dir, True) # Fix race with bdb in svnserve
@@ -578,21 +608,15 @@ def dont_drop_valid_mergeinfo_during_inc
   svntest.actions.enable_revprop_changes(sbox.repo_dir)
 
   # Load the three incremental dump files in sequence.
-  dump_fp = open(dump_file_r1_10, 'rb')
-  svntest.actions.run_and_verify_svnrdump(dump_fp.readlines(),
-                                          svntest.verify.AnyOutput,
-                                          [], 0, 'load', sbox.repo_url)
-  dump_fp.close()
-  dump_fp = open(dump_file_r11_13, 'rb')
-  svntest.actions.run_and_verify_svnrdump(dump_fp.readlines(),
-                                          svntest.verify.AnyOutput,
-                                          [], 0, 'load', sbox.repo_url)
-  dump_fp.close()
-  dump_fp = open(dump_file_r14_15, 'rb')
-  svntest.actions.run_and_verify_svnrdump(dump_fp.readlines(),
-                                          svntest.verify.AnyOutput,
-                                          [], 0, 'load', sbox.repo_url)
-  dump_fp.close()
+  run_and_verify_svnrdump_load(dump_file_r1_10,
+                               svntest.verify.AnyOutput, [], 0,
+                               sbox.repo_url)
+  run_and_verify_svnrdump_load(dump_file_r11_13,
+                               svntest.verify.AnyOutput, [], 0,
+                               sbox.repo_url)
+  run_and_verify_svnrdump_load(dump_file_r14_15,
+                               svntest.verify.AnyOutput, [], 0,
+                               sbox.repo_url)
 
   # Check the mergeinfo, we use the same expected output as before,
   # as it (duh!) should be exactly the same as when we loaded the
@@ -622,21 +646,17 @@ def dont_drop_valid_mergeinfo_during_inc
   #     Project-Z     (Added r5)
   #     docs/         (Added r6)
   #       README      (Added r6)
-  dump_fp = open(os.path.join(os.path.dirname(sys.argv[0]),
-                              'svnrdump_tests_data',
-                              'skeleton.dump'),
-                 'rb')
-  dumpfile_skeleton = dump_fp.readlines()
-  dump_fp.close()
-  svntest.actions.run_and_verify_svnrdump(dumpfile_skeleton,
-                                          svntest.verify.AnyOutput,
-                                          [], 0, 'load', sbox.repo_url)
+  dumpfile_skeleton = os.path.join(os.path.dirname(sys.argv[0]),
+                                   'svnrdump_tests_data',
+                                   'skeleton.dump')
+  run_and_verify_svnrdump_load(dumpfile_skeleton,
+                               svntest.verify.AnyOutput, [], 0,
+                               sbox.repo_url)
 
   # Load 'svnadmin_tests_data/mergeinfo_included_full.dump' in one shot:
-  svntest.actions.run_and_verify_svnrdump(dumpfile_full,
-                                          svntest.verify.AnyOutput,
-                                          [], 0, 'load',
-                                          sbox.repo_url + '/Projects/Project-X')
+  run_and_verify_svnrdump_load(dumpfile_full,
+                               svntest.verify.AnyOutput, [], 0,
+                               sbox.repo_url + '/Projects/Project-X')
 
   # Check that the mergeinfo is as expected.  This is exactly the
   # same expected mergeinfo we previously checked, except that the
@@ -676,35 +696,26 @@ def dont_drop_valid_mergeinfo_during_inc
   svntest.actions.enable_revprop_changes(sbox.repo_dir)
 
   # Load the skeleton repos into the empty target:
-  svntest.actions.run_and_verify_svnrdump(dumpfile_skeleton,
-                                          svntest.verify.AnyOutput,
-                                          [], 0, 'load', sbox.repo_url)
+  run_and_verify_svnrdump_load(dumpfile_skeleton,
+                               svntest.verify.AnyOutput, [], 0,
+                               sbox.repo_url)
 
   # Load the three incremental dump files in sequence.
   #
   # The first load fails the same as PART 3.
-  dump_fp = open(dump_file_r1_10, 'rb')
-  svntest.actions.run_and_verify_svnrdump(dump_fp.readlines(),
-                                          svntest.verify.AnyOutput,
-                                          [], 0, 'load',
-                                          sbox.repo_url + '/Projects/Project-X')
-  dump_fp.close()
-  dump_fp = open(dump_file_r11_13, 'rb')
-  svntest.actions.run_and_verify_svnrdump(dump_fp.readlines(),
-                                          svntest.verify.AnyOutput,
-                                          [], 0, 'load',
-                                          sbox.repo_url + '/Projects/Project-X')
-  dump_fp.close()
-  dump_fp = open(dump_file_r14_15, 'rb')
-  svntest.actions.run_and_verify_svnrdump(dump_fp.readlines(),
-                                          svntest.verify.AnyOutput,
-                                          [], 0, 'load',
-                                          sbox.repo_url + '/Projects/Project-X')
-  dump_fp.close()
+  run_and_verify_svnrdump_load(dump_file_r1_10,
+                               svntest.verify.AnyOutput, [], 0,
+                               sbox.repo_url + '/Projects/Project-X')
+  run_and_verify_svnrdump_load(dump_file_r11_13,
+                               svntest.verify.AnyOutput, [], 0,
+                               sbox.repo_url + '/Projects/Project-X')
+  run_and_verify_svnrdump_load(dump_file_r14_15,
+                               svntest.verify.AnyOutput, [], 0,
+                               sbox.repo_url + '/Projects/Project-X')
 
   # Check the resulting mergeinfo.  We expect the exact same results
   # as Part 3.
-  # See http://subversion.tigris.org/issues/show_bug.cgi?id=3020#desc16.
+  # See https://issues.apache.org/jira/browse/SVN-3020#desc16.
   svntest.actions.run_and_verify_svn(expected_output, [],
                                      'propget', 'svn:mergeinfo', '-R',
                                      sbox.repo_url)
@@ -729,15 +740,12 @@ def svnrdump_load_partial_incremental_du
 
   # Load the specified dump file into the sbox repository using
   # svnrdump load
-  dump_file = open(os.path.join(os.path.dirname(sys.argv[0]),
-                                                'svnrdump_tests_data',
-                                                'partial_incremental.dump'),
-                   'rb')
-  svnrdump_dumpfile = dump_file.readlines()
-  dump_file.close()
-  svntest.actions.run_and_verify_svnrdump(svnrdump_dumpfile,
-                                          svntest.verify.AnyOutput,
-                                          [], 0, 'load', sbox.repo_url)
+  dump_file = os.path.join(os.path.dirname(sys.argv[0]),
+                           'svnrdump_tests_data',
+                           'partial_incremental.dump')
+  run_and_verify_svnrdump_load(dump_file,
+                               svntest.verify.AnyOutput, [], 0,
+                               sbox.repo_url)
 
 
 #----------------------------------------------------------------------
@@ -789,9 +797,9 @@ def load_prop_change_in_non_deltas_dump(
   # Try to load that dump.
   sbox.build(create_wc=False, empty=True)
   svntest.actions.enable_revprop_changes(sbox.repo_dir)
-  svntest.actions.run_and_verify_svnrdump(dump,
-                                          [], [], 0,
-                                          '-q', 'load', sbox.repo_url)
+  run_and_verify_svnrdump_load(dump,
+                               [], [], 0,
+                               '-q', sbox.repo_url)
 
 #----------------------------------------------------------------------
 
@@ -852,9 +860,9 @@ def load_non_deltas_copy_with_props(sbox
   new_repo_dir, new_repo_url = sbox.add_repo_path('new_repo')
   svntest.main.create_repos(new_repo_dir)
   svntest.actions.enable_revprop_changes(new_repo_dir)
-  svntest.actions.run_and_verify_svnrdump(dumpfile,
-                                          svntest.verify.AnyOutput,
-                                          [], 0, 'load', new_repo_url)
+  run_and_verify_svnrdump_load(dumpfile,
+                               svntest.verify.AnyOutput, [], 0,
+                               new_repo_url)
 
   # Check that property 'p' really was deleted on each copied node
   for tgt_path in ['A/mu_COPY', 'A/B_COPY', 'A/B_COPY/E',
@@ -899,9 +907,9 @@ def load_non_deltas_replace_copy_with_pr
   new_repo_dir, new_repo_url = sbox.add_repo_path('new_repo')
   svntest.main.create_repos(new_repo_dir)
   svntest.actions.enable_revprop_changes(new_repo_dir)
-  svntest.actions.run_and_verify_svnrdump(dumpfile,
-                                          svntest.verify.AnyOutput,
-                                          [], 0, 'load', new_repo_url)
+  run_and_verify_svnrdump_load(dumpfile,
+                               svntest.verify.AnyOutput, [], 0,
+                               new_repo_url)
 
   # Check that property 'p' really was deleted on each copied node
   # This used to fail, finding that property 'p' was still present
@@ -928,9 +936,10 @@ def dump_replace_with_copy(sbox):
   sbox.simple_commit()
 
   # Dump with 'svnrdump'
-  dumpfile = svntest.actions.run_and_verify_svnrdump(
-                               None, svntest.verify.AnyOutput, [], 0,
-                               'dump', '--quiet', '--incremental', '-r2',
+  dumpfile = run_and_verify_svnrdump_dump(
+                               None,
+                               svntest.verify.AnyOutput, [], 0,
+                               '--quiet', '--incremental', '-r2',
                                sbox.repo_url)
 
   # Check the 'delete' record headers: expect this parse to fail if headers
@@ -969,9 +978,9 @@ def load_non_deltas_with_props(sbox):
   new_repo_dir, new_repo_url = sbox.add_repo_path('new_repo')
   svntest.main.create_repos(new_repo_dir)
   svntest.actions.enable_revprop_changes(new_repo_dir)
-  svntest.actions.run_and_verify_svnrdump(dumpfile,
-                                          svntest.verify.AnyOutput,
-                                          [], 0, 'load', new_repo_url)
+  run_and_verify_svnrdump_load(dumpfile,
+                               svntest.verify.AnyOutput, [], 0,
+                               new_repo_url)
 
   # Check that property 'q' remains on each modified node
   for tgt_path in ['A/mu', 'A/B']:

Modified: subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svnserveautocheck.sh
URL: http://svn.apache.org/viewvc/subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svnserveautocheck.sh?rev=1846488&r1=1846487&r2=1846488&view=diff
==============================================================================
--- subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svnserveautocheck.sh (original)
+++ subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svnserveautocheck.sh Tue Nov 13 07:49:04 2018
@@ -31,6 +31,14 @@
 # distribution; it's easiest to just run it as "make svnserveautocheck".
 # Like "make check", you can specify further options like
 # "make svnserveautocheck FS_TYPE=bdb TESTS=subversion/tests/cmdline/basic.py".
+#
+# Other environment variables that can be passed:
+#
+#  make svnserveautocheck CACHE_REVPROPS=1   # run svnserve --cache-revprops
+#
+#  make svnserveautocheck BLOCK_READ=1       # run svnserve --block-read on
+#
+#  make svnserveautocheck THREADED=1         # run svnserve -T
 
 PYTHON=${PYTHON:-python}
 
@@ -124,6 +132,10 @@ if [ ${CACHE_REVPROPS:+set} ]; then
   SVNSERVE_ARGS="$SVNSERVE_ARGS --cache-revprops on"
 fi
 
+if [ ${BLOCK_READ:+set} ]; then
+  SVNSERVE_ARGS="$SVNSERVE_ARGS --block-read on"
+fi
+
 "$SERVER_CMD" -d -r "$ABS_BUILDDIR/subversion/tests/cmdline" \
             --listen-host 127.0.0.1 \
             --listen-port $SVNSERVE_PORT \

Modified: subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svnsync_authz_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svnsync_authz_tests.py?rev=1846488&r1=1846487&r2=1846488&view=diff
==============================================================================
--- subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svnsync_authz_tests.py (original)
+++ subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svnsync_authz_tests.py Tue Nov 13 07:49:04 2018
@@ -415,7 +415,7 @@ def specific_deny_authz(sbox):
 
   # For mod_dav_svn's parent path setup we need per-repos permissions in
   # the authz file...
-  if sbox.repo_url.startswith('http'):
+  if svntest.main.is_ra_type_dav():
     src_authz = sbox.authz_name()
     dst_authz = dest_sbox.authz_name()
     write_authz_file(sbox, None,

Modified: subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svnsync_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svnsync_tests.py?rev=1846488&r1=1846487&r2=1846488&view=diff
==============================================================================
--- subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svnsync_tests.py (original)
+++ subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svnsync_tests.py Tue Nov 13 07:49:04 2018
@@ -167,7 +167,7 @@ def verify_mirror(dest_sbox, exp_dump_fi
   dest_dump = svntest.actions.run_and_verify_dump(dest_sbox.repo_dir)
 
   svntest.verify.compare_dump_files(
-    "Dump files", "DUMP", exp_dump_file_contents, dest_dump)
+    None, None, exp_dump_file_contents, dest_dump)
 
 def run_test(sbox, dump_file_name, subdir=None, exp_dump_file_name=None,
              bypass_prop_validation=False, source_prop_encoding=None,

Modified: subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/__init__.py
URL: http://svn.apache.org/viewvc/subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/__init__.py?rev=1846488&r1=1846487&r2=1846488&view=diff
==============================================================================
--- subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/__init__.py (original)
+++ subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/__init__.py Tue Nov 13 07:49:04 2018
@@ -35,11 +35,8 @@ if sys.hexversion < 0x2070000:
 try:
   import sqlite3
 except ImportError:
-  try:
-    from pysqlite2 import dbapi2 as sqlite3
-  except ImportError:
-    sys.stderr.write('[SKIPPED] Python sqlite3 module required\n')
-    sys.exit(0)
+  sys.stderr.write('[SKIPPED] Python sqlite3 module required\n')
+  sys.exit(0)
 
 # don't export this name
 del sys

Modified: subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/actions.py
URL: http://svn.apache.org/viewvc/subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/actions.py?rev=1846488&r1=1846487&r2=1846488&view=diff
==============================================================================
--- subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/actions.py (original)
+++ subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/actions.py Tue Nov 13 07:49:04 2018
@@ -64,22 +64,15 @@ def no_relocate_validation():
 def do_relocate_validation():
   os.environ['SVN_I_LOVE_CORRUPTED_WORKING_COPIES_SO_DISABLE_RELOCATE_VALIDATION'] = 'no'
 
-def setup_pristine_greek_repository():
-  """Create the pristine repository and 'svn import' the greek tree"""
-
-  # these directories don't exist out of the box, so we may have to create them
-  if not os.path.exists(main.general_wc_dir):
-    os.makedirs(main.general_wc_dir)
-
-  if not os.path.exists(main.general_repo_dir):
-    os.makedirs(main.general_repo_dir) # this also creates all the intermediate dirs
-
+def _setup_pristine_repo(tree_state,
+                         repos_dir, dump_dir, repos_url,
+                         use_precooked=True):
   # If there's no pristine repos, create one.
-  if not os.path.exists(main.pristine_greek_repos_dir):
-    if main.options.fsfs_version is not None:
-      main.unpack_greek_repos(main.pristine_greek_repos_dir)
+  if not os.path.exists(repos_dir):
+    if use_precooked and main.options.fsfs_version is not None:
+      main.unpack_greek_repos(repos_dir)
     else:
-      main.create_repos(main.pristine_greek_repos_dir)
+      main.create_repos(repos_dir)
 
       # if this is dav, gives us access rights to import the greek tree.
       if main.is_ra_type_dav():
@@ -87,15 +80,14 @@ def setup_pristine_greek_repository():
         main.file_write(authz_file, "[/]\n* = rw\n")
 
       # dump the greek tree to disk.
-      main.greek_state.write_to_disk(main.greek_dump_dir)
+      tree_state.write_to_disk(dump_dir)
 
       # import the greek tree, using l:foo/p:bar
       ### todo: svn should not be prompting for auth info when using
       ### repositories with no auth/auth requirements
       _, output, _ = main.run_svn(None, 'import', '-m',
                                   'Log message for revision 1.',
-                                  main.greek_dump_dir,
-                                  main.pristine_greek_repos_url)
+                                  dump_dir, repos_url)
 
       # verify the printed output of 'svn import'.
       lastline = output.pop().strip()
@@ -107,7 +99,7 @@ def setup_pristine_greek_repository():
         sys.exit(1)
       output_tree = wc.State.from_commit(output)
 
-      expected_output_tree = main.greek_state.copy(main.greek_dump_dir)
+      expected_output_tree = tree_state.copy(dump_dir)
       expected_output_tree.tweak(verb='Adding',
                                  contents=None)
 
@@ -122,9 +114,36 @@ def setup_pristine_greek_repository():
 
     # Finally, disallow any changes to the "pristine" repos.
     error_msg = "Don't modify the pristine repository"
-    create_failing_hook(main.pristine_greek_repos_dir, 'start-commit', error_msg)
-    create_failing_hook(main.pristine_greek_repos_dir, 'pre-lock', error_msg)
-    create_failing_hook(main.pristine_greek_repos_dir, 'pre-revprop-change', error_msg)
+    create_failing_hook(repos_dir, 'start-commit', error_msg)
+    create_failing_hook(repos_dir, 'pre-lock', error_msg)
+    create_failing_hook(repos_dir, 'pre-revprop-change', error_msg)
+
+def setup_pristine_repositories():
+  """Create the pristine repository and 'svn import' the greek tree"""
+
+  # these directories don't exist out of the box, so we may have to create them
+  if not os.path.exists(main.general_wc_dir):
+    os.makedirs(main.general_wc_dir)
+
+  if not os.path.exists(main.general_repo_dir):
+    os.makedirs(main.general_repo_dir) # this also creates all the intermediate dirs
+
+  if not os.path.exists(main.other_dav_root_dir):
+    os.makedirs(main.other_dav_root_dir)
+  if not os.path.exists(main.non_dav_root_dir):
+    os.makedirs(main.non_dav_root_dir)
+
+  _setup_pristine_repo(main.greek_state,
+                       main.pristine_greek_repos_dir,
+                       main.greek_dump_dir,
+                       main.pristine_greek_repos_url)
+
+  # NOTE: We don't use precooked trojan repositories.
+  _setup_pristine_repo(main.trojan_state,
+                       main.pristine_trojan_repos_dir,
+                       main.trojan_dump_dir,
+                       main.pristine_trojan_repos_url,
+                       use_precooked=False)
 
 
 ######################################################################
@@ -144,23 +163,19 @@ def guarantee_empty_repository(path, min
 # Used by every test, so that they can run independently of  one
 # another. Every time this routine is called, it recursively copies
 # the `pristine repos' to a new location.
-# Note: make sure setup_pristine_greek_repository was called once before
-# using this function.
-def guarantee_greek_repository(path, minor_version):
-  """Guarantee that a local svn repository exists at PATH, containing
-  nothing but the greek-tree at revision 1."""
-
-  if path == main.pristine_greek_repos_dir:
+# Note: make sure setup_pristine_repositories was called once before
+# using these functions.
+def _guarantee_repos(path, repos_dir, minor_version, use_precooked=True):
+  if path == repos_dir:
     logger.error("attempt to overwrite the pristine repos!  Aborting.")
     sys.exit(1)
 
   # copy the pristine repository to PATH.
   main.safe_rmtree(path)
-  if (main.options.fsfs_version is not None):
+  if (use_precooked and main.options.fsfs_version is not None):
     failed = main.unpack_greek_repos(path)
   else:
-    failed = main.copy_repos(main.pristine_greek_repos_dir,
-                             path, 1, 1, minor_version)
+    failed = main.copy_repos(repos_dir, path, 1, 1, minor_version)
   if failed:
     logger.error("copying repository failed.")
     sys.exit(1)
@@ -171,6 +186,18 @@ def guarantee_greek_repository(path, min
   # give the repository a unique UUID
   run_and_verify_svnadmin([], [], 'setuuid', path)
 
+def guarantee_greek_repository(path, minor_version):
+  """Guarantee that a local svn repository exists at PATH, containing
+  nothing but the greek-tree at revision 1."""
+
+  _guarantee_repos(path, main.pristine_greek_repos_dir, minor_version)
+
+def guarantee_trojan_repository(path, minor_version):
+  """Guarantee that a local svn repository exists at PATH, containing
+  nothing but the trojan-tree at revision 1."""
+
+  _guarantee_repos(path, main.pristine_trojan_repos_dir, minor_version, False)
+
 def run_and_verify_atomic_ra_revprop_change(expected_stdout,
                                             expected_stderr,
                                             expected_exit,
@@ -1937,7 +1964,7 @@ def run_and_verify_revert(expected_paths
 
 # This allows a test to *quickly* bootstrap itself.
 def make_repo_and_wc(sbox, create_wc=True, read_only=False, empty=False,
-                     minor_version=None):
+                     minor_version=None, tree=None):
   """Create a fresh repository and check out a WC from it.  If EMPTY is
   True, the repository and WC will be empty and at revision 0,
   otherwise they will contain the 'Greek Tree' at revision 1.
@@ -1962,9 +1989,17 @@ def make_repo_and_wc(sbox, create_wc=Tru
     guarantee_empty_repository(sbox.repo_dir, minor_version)
     expected_state = svntest.wc.State('', {})
   else:
-    if not read_only:
-      guarantee_greek_repository(sbox.repo_dir, minor_version)
-    expected_state = main.greek_state
+    if tree == 'greek':
+      if not read_only:
+        guarantee_greek_repository(sbox.repo_dir, minor_version)
+      expected_state = main.greek_state
+    elif tree == 'trojan':
+      if not read_only:
+        guarantee_trojan_repository(sbox.repo_dir, minor_version)
+      expected_state = main.trojan_state
+    else:
+      raise ValueError("'tree' must be 'greek' or 'trojan'"
+                       " but was '%s'" % str(tree))
 
   if create_wc:
     # Generate the expected output tree.
@@ -1998,14 +2033,21 @@ def duplicate_dir(wc_name, wc_copy_name)
 
 
 
-def get_virginal_state(wc_dir, rev):
+def get_virginal_state(wc_dir, rev, tree='greek'):
   "Return a virginal greek tree state for a WC and repos at revision REV."
 
   rev = str(rev) ### maybe switch rev to an integer?
 
   # copy the greek tree, shift it to the new wc_dir, insert a root elem,
   # then tweak all values
-  state = main.greek_state.copy()
+  if tree == 'greek':
+    state = main.greek_state.copy()
+  elif tree == 'trojan':
+    state = main.trojan_state.copy()
+  else:
+    raise ValueError("'tree' must be 'greek' or 'trojan'"
+                     " but was '%s'" % str(tree))
+
   state.wc_dir = wc_dir
   state.desc[''] = wc.StateItem()
   state.tweak(contents=None, status='  ', wc_rev=rev)

Modified: subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/main.py
URL: http://svn.apache.org/viewvc/subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/main.py?rev=1846488&r1=1846487&r2=1846488&view=diff
==============================================================================
--- subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/main.py (original)
+++ subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/main.py Tue Nov 13 07:49:04 2018
@@ -55,8 +55,9 @@ except ImportError:
 import svntest
 from svntest import Failure
 from svntest import Skip
+from svntest.wc import StateItem as Item
 
-SVN_VER_MINOR = 10
+SVN_VER_MINOR = 12
 
 ######################################################################
 #
@@ -199,6 +200,7 @@ svnmover_binary = os.path.abspath('../..
 # Location to the pristine repository, will be calculated from test_area_url
 # when we know what the user specified for --url.
 pristine_greek_repos_url = None
+pristine_trojan_repos_url = None
 
 # Global variable to track all of our options
 options = None
@@ -224,6 +226,10 @@ SVN_PROP_INHERITABLE_IGNORES = "svn:glob
 general_repo_dir = os.path.join(work_dir, "repositories")
 general_wc_dir = os.path.join(work_dir, "working_copies")
 
+# Directories used for DAV tests
+other_dav_root_dir = os.path.join(work_dir, "fsdavroot")
+non_dav_root_dir = os.path.join(work_dir, "nodavroot")
+
 # temp directory in which we will create our 'pristine' local
 # repository and other scratch data.  This should be removed when we
 # quit and when we startup.
@@ -231,7 +237,9 @@ temp_dir = os.path.join(work_dir, 'local
 
 # (derivatives of the tmp dir.)
 pristine_greek_repos_dir = os.path.join(temp_dir, "repos")
+pristine_trojan_repos_dir = os.path.join(temp_dir, "trojan")
 greek_dump_dir = os.path.join(temp_dir, "greekfiles")
+trojan_dump_dir = os.path.join(temp_dir, "trojanfiles")
 default_config_dir = os.path.abspath(os.path.join(temp_dir, "config"))
 
 #
@@ -241,28 +249,57 @@ default_config_dir = os.path.abspath(os.
 # call main.greek_state.copy().  That method will return a copy of this
 # State object which can then be edited.
 #
-_item = svntest.wc.StateItem
 greek_state = svntest.wc.State('', {
-  'iota'        : _item("This is the file 'iota'.\n"),
-  'A'           : _item(),
-  'A/mu'        : _item("This is the file 'mu'.\n"),
-  'A/B'         : _item(),
-  'A/B/lambda'  : _item("This is the file 'lambda'.\n"),
-  'A/B/E'       : _item(),
-  'A/B/E/alpha' : _item("This is the file 'alpha'.\n"),
-  'A/B/E/beta'  : _item("This is the file 'beta'.\n"),
-  'A/B/F'       : _item(),
-  'A/C'         : _item(),
-  'A/D'         : _item(),
-  'A/D/gamma'   : _item("This is the file 'gamma'.\n"),
-  'A/D/G'       : _item(),
-  'A/D/G/pi'    : _item("This is the file 'pi'.\n"),
-  'A/D/G/rho'   : _item("This is the file 'rho'.\n"),
-  'A/D/G/tau'   : _item("This is the file 'tau'.\n"),
-  'A/D/H'       : _item(),
-  'A/D/H/chi'   : _item("This is the file 'chi'.\n"),
-  'A/D/H/psi'   : _item("This is the file 'psi'.\n"),
-  'A/D/H/omega' : _item("This is the file 'omega'.\n"),
+  'iota'        : Item("This is the file 'iota'.\n"),
+  'A'           : Item(),
+  'A/mu'        : Item("This is the file 'mu'.\n"),
+  'A/B'         : Item(),
+  'A/B/lambda'  : Item("This is the file 'lambda'.\n"),
+  'A/B/E'       : Item(),
+  'A/B/E/alpha' : Item("This is the file 'alpha'.\n"),
+  'A/B/E/beta'  : Item("This is the file 'beta'.\n"),
+  'A/B/F'       : Item(),
+  'A/C'         : Item(),
+  'A/D'         : Item(),
+  'A/D/gamma'   : Item("This is the file 'gamma'.\n"),
+  'A/D/G'       : Item(),
+  'A/D/G/pi'    : Item("This is the file 'pi'.\n"),
+  'A/D/G/rho'   : Item("This is the file 'rho'.\n"),
+  'A/D/G/tau'   : Item("This is the file 'tau'.\n"),
+  'A/D/H'       : Item(),
+  'A/D/H/chi'   : Item("This is the file 'chi'.\n"),
+  'A/D/H/psi'   : Item("This is the file 'psi'.\n"),
+  'A/D/H/omega' : Item("This is the file 'omega'.\n"),
+  })
+
+# Likewise our pristine trojan-tree state (for peg revision parsing tests)
+# NOTE: We don't use precooked trojan repositories.
+trojan_state = svntest.wc.State('', {
+  'iota'        : Item("This is the file 'iota'.\n"),
+  '@zeta'       : Item("This is the file 'zeta'.\n"),
+  '_@theta'     : Item("This is the file 'theta'.\n"),
+  '.@kappa'     : Item("This is the file 'kappa'.\n"),
+  'lambda@'     : Item("This is the file 'lambda'.\n"),
+  '@omicron@'   : Item("This is the file 'omicron'.\n"),
+  '@'           : Item(),
+  '@@'          : Item(),
+  '_@'          : Item(),
+  '.@'          : Item(),
+  'A'           : Item(),
+  'A/@@'        : Item("This is the file 'A/@@'.\n"),
+  'A/alpha'     : Item("This is the file 'alpha'.\n"),
+  'A/@omega@'   : Item("This is the file 'omega'.\n"),
+  'B'           : Item(),
+  'B/@'         : Item("This is the file 'B/@'.\n"),
+  'B/@beta'     : Item("This is the file 'beta'.\n"),
+  'B/pi@'       : Item("This is the file 'pi'.\n"),
+  'G'           : Item(),
+  'G/_@'        : Item("This is the file 'G/_@'.\n"),
+  'G/_@gamma'   : Item("This is the file 'gamma'.\n"),
+  'D'           : Item(),
+  'D/.@'        : Item("This is the file 'D/.@'.\n"),
+  'D/.@delta'   : Item("This is the file 'delta'.\n"),
+  'E'           : Item(),
   })
 
 
@@ -452,9 +489,9 @@ def open_pipe(command, bufsize=-1, stdin
   should be passed to wait_on_pipe."""
   command = [str(x) for x in command]
 
-  # On Windows subprocess.Popen() won't accept a Python script as
-  # a valid program to execute, rather it wants the Python executable.
-  if (sys.platform == 'win32') and (command[0].endswith('.py')):
+  # Always run python scripts under the same Python executable as used
+  # for the test suite.
+  if command[0].endswith('.py'):
     command.insert(0, sys.executable)
 
   command_string = command[0] + ' ' + ' '.join(map(_quote_arg, command[1:]))
@@ -978,7 +1015,8 @@ def file_write(path, contents, mode='w')
   which is (w)rite by default."""
 
   if sys.version_info < (3, 0):
-    open(path, mode).write(contents)
+    with open(path, mode) as f:
+      f.write(contents)
   else:
     # Python 3:  Write data in the format required by MODE, i.e. byte arrays
     #            to 'b' files, utf-8 otherwise."""
@@ -990,9 +1028,11 @@ def file_write(path, contents, mode='w')
         contents = contents.decode("utf-8")
 
     if isinstance(contents, str):
-      codecs.open(path, mode, "utf-8").write(contents)
+      with codecs.open(path, mode, "utf-8") as f:
+        f.write(contents)
     else:
-      open(path, mode).write(contents)
+      with open(path, mode) as f:
+        f.write(contents)
 
 # For making local mods to files
 def file_append(path, new_text):
@@ -1008,7 +1048,8 @@ def file_append_binary(path, new_text):
 def file_substitute(path, contents, new_contents):
   """Replace the CONTENTS in the file at PATH using the NEW_CONTENTS"""
   fcontent = open(path, 'r').read().replace(contents, new_contents)
-  open(path, 'w').write(fcontent)
+  with open(path, 'w') as f:
+    f.write(fcontent)
 
 # For setting up authz, hooks and making other tweaks to created repos
 def _post_create_repos(path, minor_version = None):
@@ -1035,7 +1076,8 @@ def _post_create_repos(path, minor_versi
       users += (crosscheck_username + " = " + crosscheck_password + "\n")
     file_append(os.path.join(path, "conf", "passwd"), users)
 
-  if options.fs_type is None or options.fs_type == 'fsfs':
+  if options.fs_type is None or options.fs_type == 'fsfs' or \
+     options.fs_type == 'fsx':
     # fsfs.conf file
     if (minor_version is None or minor_version >= 6):
       confpath = get_fsfs_conf_file_path(path)
@@ -1043,7 +1085,8 @@ def _post_create_repos(path, minor_versi
         shutil.copy(options.config_file, confpath)
 
       if options.memcached_server is not None or \
-         options.fsfs_compression is not None and \
+         options.fsfs_compression is not None or \
+         options.fsfs_dir_deltification is not None and \
          os.path.exists(confpath):
         with open(confpath, 'r') as conffile:
           newlines = []
@@ -1051,6 +1094,10 @@ def _post_create_repos(path, minor_versi
             if line.startswith('# compression ') and \
                options.fsfs_compression is not None:
               line = 'compression = %s\n' % options.fsfs_compression
+            if line.startswith('# enable-dir-deltification ') and \
+               options.fsfs_dir_deltification is not None:
+              line = 'enable-dir-deltification = %s\n' % \
+                options.fsfs_dir_deltification
             newlines += line
             if options.memcached_server is not None and \
                line == '[memcached-servers]\n':
@@ -1569,9 +1616,11 @@ def is_fs_log_addressing():
   return is_fs_type_fsx() or \
         (is_fs_type_fsfs() and options.server_minor_version >= 9)
 
+def fs_has_sha1():
+  return fs_has_rep_sharing()
+
 def fs_has_rep_sharing():
-  return is_fs_type_fsx() or \
-        (is_fs_type_fsfs() and options.server_minor_version >= 6)
+  return options.server_minor_version >= 6
 
 def fs_has_pack():
   return is_fs_type_fsx() or \
@@ -1603,28 +1652,37 @@ def server_has_mergeinfo():
   return options.server_minor_version >= 5
 
 def server_has_revprop_commit():
-  return options.server_minor_version >= 5
+  return options.server_caps.has_revprop_commit
 
 def server_authz_has_aliases():
-  return options.server_minor_version >= 5
+  return options.server_caps.authz_has_aliases
 
 def server_gets_client_capabilities():
-  return options.server_minor_version >= 5
+  return options.server_caps.gets_client_capabilities
 
 def server_has_partial_replay():
-  return options.server_minor_version >= 5
+  return options.server_caps.has_partial_replay
 
 def server_enforces_UTF8_fspaths_in_verify():
-  return options.server_minor_version >= 6
+  return options.server_caps.enforces_UTF8_fspaths_in_verify
 
 def server_enforces_date_syntax():
-  return options.server_minor_version >= 5
+  return options.server_caps.enforces_date_syntax
 
 def server_has_atomic_revprop():
-  return options.server_minor_version >= 7
+  return options.server_caps.has_atomic_revprop
 
 def server_has_reverse_get_file_revs():
-  return options.server_minor_version >= 8
+  return options.server_caps.has_reverse_get_file_revs
+
+def python_sqlite_can_read_our_wc_db():
+  """Check if the Python builtin is capable enough to peek into wc.db"""
+  # Currently enough (1.7-1.9)
+  return svntest.sqlite3.sqlite_version_info >= (3, 6, 18)
+
+def python_sqlite_can_read_without_rowid():
+  """Check if the Python builtin is capable enough to read new rep-cache"""
+  return svntest.sqlite3.sqlite_version_info >= (3, 8, 2)
 
 def is_plaintext_password_storage_disabled():
   try:
@@ -1637,7 +1695,6 @@ def is_plaintext_password_storage_disabl
     return False
   return True
 
-
 # https://issues.apache.org/bugzilla/show_bug.cgi?id=56480
 # https://issues.apache.org/bugzilla/show_bug.cgi?id=55397
 __mod_dav_url_quoting_broken_versions = frozenset([
@@ -1661,6 +1718,10 @@ def is_httpd_authz_provider_enabled():
       return (v[0] == '2' and int(v[1]) >= 3) or int(v[0]) > 2
     return None
 
+def is_remote_http_connection_allowed():
+  return options.allow_remote_http_connection
+
+
 ######################################################################
 
 
@@ -1739,6 +1800,12 @@ class TestSpawningThread(threading.Threa
       args.append('--dump-load-cross-check')
     if options.fsfs_compression:
       args.append('--fsfs-compression=' + options.fsfs_compression)
+    if options.fsfs_dir_deltification:
+      args.append('--fsfs-dir-deltification=' + options.fsfs_dir_deltification)
+    if options.allow_remote_http_connection:
+      args.append('--allow-remote-http-connection')
+    if options.svn_bin:
+      args.append('--bin=' + options.svn_bin)
 
     result, stdout_lines, stderr_lines = spawn_process(command, 0, False, None,
                                                        *args)
@@ -2079,7 +2146,7 @@ def _create_parser(usage=None):
                     help='Run the given number of tests in parallel')
   parser.add_option('-c', action='store_true', dest='is_child_process',
                     help='Flag if we are running this python test as a ' +
-                         'child process')
+                    'child process; used by build/run_tests.py:334')
   parser.add_option('--mode-filter', action='store', dest='mode_filter',
                     default='ALL',
                     help='Limit tests to those with type specified (e.g. XFAIL)')
@@ -2153,6 +2220,10 @@ def _create_parser(usage=None):
                     help='Use memcached server at specified URL (FSFS only)')
   parser.add_option('--fsfs-compression', action='store', type='str',
                     help='Set compression type (for fsfs)')
+  parser.add_option('--fsfs-dir-deltification', action='store', type='str',
+                    help='Set directory deltification option (for fsfs)')
+  parser.add_option('--allow-remote-http-connection', action='store_true',
+                    help='Run tests that connect to remote HTTP(S) servers')
 
   # most of the defaults are None, but some are other values, set them here
   parser.set_defaults(
@@ -2165,6 +2236,19 @@ def _create_parser(usage=None):
 
   return parser
 
+class ServerCaps():
+  """A simple struct that contains the actual server capabilities that don't
+     depend on other settings like FS versions."""
+
+  def __init__(self, options):
+    self.has_revprop_commit = options.server_minor_version >= 5
+    self.authz_has_aliases = options.server_minor_version >= 5
+    self.gets_client_capabilities = options.server_minor_version >= 5
+    self.has_partial_replay = options.server_minor_version >= 5
+    self.enforces_UTF8_fspaths_in_verify = options.server_minor_version >= 6
+    self.enforces_date_syntax = options.server_minor_version >= 5
+    self.has_atomic_revprop = options.server_minor_version >= 7
+    self.has_reverse_get_file_revs = options.server_minor_version >= 8
 
 def parse_options(arglist=sys.argv[1:], usage=None):
   """Parse the arguments in arg_list, and set the global options object with
@@ -2175,6 +2259,12 @@ def parse_options(arglist=sys.argv[1:],
   parser = _create_parser(usage)
   (options, args) = parser.parse_args(arglist)
 
+  # Peg the actual server capabilities.
+  # We tweak the server_minor_version later to accommodate FS restrictions,
+  # but we don't want them to interfere with expectations towards the "pure"
+  # server code.
+  options.server_caps = ServerCaps(options)
+
   # If there are no logging handlers registered yet, then install our
   # own with our custom formatter. (anything currently installed *is*
   # our handler as tested above, in _create_parser)
@@ -2206,26 +2296,29 @@ def parse_options(arglist=sys.argv[1:],
     parser.error("test harness only supports server minor versions 3-%d"
                  % SVN_VER_MINOR)
 
-  # Make sure the server-minor-version matches the fsfs-version parameter.
+  pass
+
+  return (parser, args)
+
+def tweak_options_for_precooked_repos():
+  """Make sure the server-minor-version matches the fsfs-version parameter
+     for pre-cooked repositories."""
+
+  global options
+
+  # Server versions that introduced the respective FSFS formats:
+  introducing_version = { 1:1, 2:4, 3:5, 4:6, 6:8, 7:9 }
   if options.fsfs_version:
-    if options.fsfs_version == 6:
-      if options.server_minor_version \
-        and options.server_minor_version != 8 \
-        and options.server_minor_version != SVN_VER_MINOR:
-        parser.error("--fsfs-version=6 requires --server-minor-version=8")
-      options.server_minor_version = 8
-    if options.fsfs_version == 4:
+    if options.fsfs_version in introducing_version:
+      introduced_in = introducing_version[options.fsfs_version]
       if options.server_minor_version \
-        and options.server_minor_version != 7 \
+        and options.server_minor_version != introduced_in \
         and options.server_minor_version != SVN_VER_MINOR:
-        parser.error("--fsfs-version=4 requires --server-minor-version=7")
-      options.server_minor_version = 7
-    pass
+        parser.error("--fsfs-version=%d requires --server-minor-version=%d" \
+                     % (options.fsfs_version, introduced_in))
+      options.server_minor_version = introduced_in
     # ### Add more tweaks here if and when we support pre-cooked versions
     # ### of FSFS repositories.
-  pass
-
-  return (parser, args)
 
 
 def run_tests(test_list, serial_only = False):
@@ -2300,6 +2393,9 @@ def execute_tests(test_list, serial_only
 
   global pristine_url
   global pristine_greek_repos_url
+  global pristine_trojan_repos_url
+  global other_dav_root_url
+  global non_dav_root_url
   global svn_binary
   global svnadmin_binary
   global svnlook_binary
@@ -2321,6 +2417,7 @@ def execute_tests(test_list, serial_only
   if not options:
     # Override which tests to run from the commandline
     (parser, args) = parse_options()
+    tweak_options_for_precooked_repos()
     test_selection = args
   else:
     parser = _create_parser()
@@ -2378,6 +2475,16 @@ def execute_tests(test_list, serial_only
                                   pristine_greek_repos_dir.replace(
                                       os.path.sep, '/'))
 
+  # Calculate pristine_trojan_repos_url from test_area_url.
+  pristine_trojan_repos_url = options.test_area_url + '/' + \
+                                svntest.wc.svn_uri_quote(
+                                  pristine_trojan_repos_dir.replace(
+                                      os.path.sep, '/'))
+
+  other_dav_root_url = options.test_area_url + '/fsdavroot'
+  non_dav_root_url = options.test_area_url + '/nodavroot'
+
+
   if options.use_jsvn:
     if options.svn_bin is None:
       options.svn_bin = ''
@@ -2470,8 +2577,8 @@ def execute_tests(test_list, serial_only
                         http_proxy=options.http_proxy,
                         exclusive_wc_locks=options.exclusive_wc_locks)
 
-      # Setup the pristine repository
-      svntest.actions.setup_pristine_greek_repository()
+      # Setup the pristine repositories
+      svntest.actions.setup_pristine_repositories()
 
     # Run the tests.
     exit_code = _internal_run_tests(test_list, testnums, options.parallel,

Propchange: subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/mergetrees.py
            ('svn:executable' removed)

Modified: subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/sandbox.py
URL: http://svn.apache.org/viewvc/subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/sandbox.py?rev=1846488&r1=1846487&r2=1846488&view=diff
==============================================================================
--- subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/sandbox.py (original)
+++ subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/sandbox.py Tue Nov 13 07:49:04 2018
@@ -102,7 +102,7 @@ class Sandbox:
 
     self.was_cwd = os.getcwd()
 
-  def _set_name(self, name, read_only=False, empty=False):
+  def _set_name(self, name, read_only=False, empty=False, tree=None):
     """A convenience method for renaming a sandbox, useful when
     working with multiple repositories in the same unit test."""
     if not name is None:
@@ -117,8 +117,15 @@ class Sandbox:
                                 self.repo_dir.replace(os.path.sep, '/')))
       self.add_test_path(self.repo_dir)
     else:
-      self.repo_dir = svntest.main.pristine_greek_repos_dir
-      self.repo_url = svntest.main.pristine_greek_repos_url
+      if tree == 'greek':
+        self.repo_dir = svntest.main.pristine_greek_repos_dir
+        self.repo_url = svntest.main.pristine_greek_repos_url
+      elif tree == 'trojan':
+        self.repo_dir = svntest.main.pristine_trojan_repos_dir
+        self.repo_url = svntest.main.pristine_trojan_repos_url
+      else:
+        raise ValueError("'tree' must be 'greek' or 'trojan'"
+                         " but was '%s'" % str(tree))
 
     if self.repo_url.startswith("http"):
       self.authz_file = os.path.join(svntest.main.work_dir, "authz")
@@ -146,15 +153,15 @@ class Sandbox:
     return clone
 
   def build(self, name=None, create_wc=True, read_only=False, empty=False,
-            minor_version=None):
-    """Make a 'Greek Tree' repo (or refer to the central one if READ_ONLY),
-       or make an empty repo if EMPTY is true,
+            minor_version=None, tree='greek'):
+    """Make a 'Greek Tree' or 'Trojan Tree' repo (or refer to the central
+       one if READ_ONLY), or make an empty repo if EMPTY is true,
        and check out a WC from it (unless CREATE_WC is false). Change the
        sandbox's name to NAME. See actions.make_repo_and_wc() for details."""
-    self._set_name(name, read_only, empty)
+    self._set_name(name, read_only, empty, tree)
     self._ensure_authz()
     svntest.actions.make_repo_and_wc(self, create_wc, read_only, empty,
-                                     minor_version)
+                                     minor_version, tree)
     self._is_built = True
 
   def _ensure_authz(self):
@@ -168,7 +175,8 @@ class Sandbox:
                or open(self.authz_file,'r').read() != default_authz)):
 
         tmp_authz_file = os.path.join(svntest.main.work_dir, "authz-" + self.name)
-        open(tmp_authz_file, 'w').write(default_authz)
+        with open(tmp_authz_file, 'w') as f:
+          f.write(default_authz)
         shutil.move(tmp_authz_file, self.authz_file)
 
   def authz_name(self, repo_dir=None):
@@ -492,7 +500,8 @@ class Sandbox:
                        if not svnrdump_headers_always.match(l)]
     # Ignore differences in number of blank lines between node records,
     # as svnrdump puts 3 whereas svnadmin puts 2 after a replace-with-copy.
-    svntest.verify.compare_dump_files(None, None,
+    svntest.verify.compare_dump_files('svnadmin dump, tweaked',
+                                      'svnrdump dump, tweaked',
                                       dumpfile_a_d_cmp,
                                       dumpfile_r_d_cmp,
                                       ignore_number_of_blank_lines=True)
@@ -523,20 +532,22 @@ class Sandbox:
     reloaded_dumpfile_a_n = svntest.actions.run_and_verify_dump(repo_dir_a_n)
     reloaded_dumpfile_a_d = svntest.actions.run_and_verify_dump(repo_dir_a_d)
     reloaded_dumpfile_r_d = svntest.actions.run_and_verify_dump(repo_dir_r_d)
-    svntest.verify.compare_dump_files(None, None,
+    svntest.verify.compare_dump_files('svnadmin dump no delta, loaded, dumped',
+                                      'svnadmin dump --deltas, loaded, dumped',
                                       reloaded_dumpfile_a_n,
                                       reloaded_dumpfile_a_d,
                                       ignore_uuid=True)
-    svntest.verify.compare_dump_files(None, None,
+    svntest.verify.compare_dump_files('svnadmin dump, loaded, dumped',
+                                      'svnrdump dump, loaded, dumped',
                                       reloaded_dumpfile_a_d,
                                       reloaded_dumpfile_r_d,
                                       ignore_uuid=True)
 
     # Run each dump through svndumpfilter and check for no further change.
-    for dumpfile in [dumpfile_a_n,
-                     dumpfile_a_d,
-                     dumpfile_r_d
-                     ]:
+    for dumpfile, dumpfile_desc in [(dumpfile_a_n, 'svnadmin dump'),
+                                    (dumpfile_a_d, 'svnadmin dump --deltas'),
+                                    (dumpfile_r_d, 'svnrdump dump'),
+                                    ]:
       ### No buffer size seems to work for update_tests-2. So skip that test?
       ### (Its dumpfile size is ~360 KB non-delta, ~180 KB delta.)
       if len(''.join(dumpfile)) > 100000:
@@ -550,7 +561,9 @@ class Sandbox:
       # svndumpfilter strips them.
       # Ignore differences in number of blank lines between node records,
       # as svndumpfilter puts 3 instead of 2 after an add or delete record.
-      svntest.verify.compare_dump_files(None, None, dumpfile, dumpfile2,
+      svntest.verify.compare_dump_files(dumpfile_desc,
+                                        'after svndumpfilter include /',
+                                        dumpfile, dumpfile2,
                                         expect_content_length_always=True,
                                         ignore_empty_prop_sections=True,
                                         ignore_number_of_blank_lines=True)

Modified: subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/testcase.py
URL: http://svn.apache.org/viewvc/subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/testcase.py?rev=1846488&r1=1846487&r2=1846488&view=diff
==============================================================================
--- subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/testcase.py (original)
+++ subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/testcase.py Tue Nov 13 07:49:04 2018
@@ -222,8 +222,8 @@ class _Wimp(_XFail):
     RESULT_SKIP: (2, TextColors.success('SKIP: '), True),
     }
 
-  def __init__(self, wip, test_case, cond_func=lambda: True):
-    _XFail.__init__(self, test_case, cond_func, wip)
+  def __init__(self, wip, test_case, cond_func=lambda: True, issues=None):
+    _XFail.__init__(self, test_case, cond_func, wip, issues)
 
 
 class _Skip(TestCase):

Modified: subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/tree.py
URL: http://svn.apache.org/viewvc/subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/tree.py?rev=1846488&r1=1846487&r2=1846488&view=diff
==============================================================================
--- subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/tree.py (original)
+++ subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/tree.py Tue Nov 13 07:49:04 2018
@@ -267,19 +267,8 @@ class SVNTreeNode:
     line += "%-20s: Item(" % ("'%s'" % path.replace(os.sep, '/'))
     comma = False
 
-    mime_type = self.props.get("svn:mime-type")
-    if not mime_type or mime_type.startswith("text/"):
-      if self.contents is not None:
-        # Escape some characters for nicer script and readability.
-        # (This is error output. I guess speed is no consideration here.)
-        line += "contents=\"%s\"" % (self.contents
-                                     .replace('\n','\\n')
-                                     .replace('"','\\"')
-                                     .replace('\r','\\r')
-                                     .replace('\t','\\t'))
-        comma = True
-    else:
-      line += 'content is binary data'
+    if self.contents is not None:
+      line += "contents=" + repr(self.contents)
       comma = True
 
     if self.props:

Modified: subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/verify.py
URL: http://svn.apache.org/viewvc/subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/verify.py?rev=1846488&r1=1846487&r2=1846488&view=diff
==============================================================================
--- subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/verify.py (original)
+++ subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/verify.py Tue Nov 13 07:49:04 2018
@@ -150,8 +150,9 @@ class ExpectedOutput(object):
        MESSAGE unless it is None, the expected lines, the ACTUAL lines,
        and a diff, all labeled with LABEL.
     """
-    display_lines(message, self.expected, actual, label, label)
-    display_lines_diff(self.expected, actual, label, label)
+    e_label = label + ' (match_all=%s)' % (self.match_all,)
+    display_lines(message, self.expected, actual, e_label, label)
+    display_lines_diff(self.expected, actual, e_label, label)
 
 
 class AnyOutput(ExpectedOutput):
@@ -181,12 +182,36 @@ class AnyOutput(ExpectedOutput):
       logger.warn(message)
 
 
+def re_fullmatch(pattern, string, flags=0):
+  """If the whole STRING matches the regular expression PATTERN,
+     return a corresponding match object.
+     Based on re.fullmatch() in Python 3.4.
+  """
+  if pattern.endswith('$'):
+    return re.match(pattern, string, flags)
+
+  return re.match(pattern + '$', string, flags)
+
+def regex_fullmatch(rx, string):
+  """If the whole STRING matches the compiled regular expression RX,
+     return a corresponding match object.
+     Based on regex.fullmatch() in Python 3.4.
+  """
+  if rx.pattern.endswith('$'):
+    return rx.match(string)
+
+  return re_fullmatch(rx.pattern, string, rx.flags)
+
 class RegexOutput(ExpectedOutput):
   """Matches a single regular expression.
 
      If MATCH_ALL is true, every actual line must match the RE.  If
      MATCH_ALL is false, at least one actual line must match the RE.  In
      any case, there must be at least one line of actual output.
+
+     The RE must match a prefix of the actual line, in contrast to the
+     RegexListOutput and UnorderedRegexListOutput classes which match
+     whole lines.
   """
 
   def __init__(self, expected, match_all=True):
@@ -212,7 +237,8 @@ class RegexOutput(ExpectedOutput):
       return any(self.expected_re.match(line) for line in actual)
 
   def display_differences(self, message, label, actual):
-    display_lines(message, self.expected, actual, label + ' (regexp)', label)
+    e_label = label + ' (regexp, match_all=%s)' % (self.match_all,)
+    display_lines(message, self.expected, actual, e_label, label)
 
   def insert(self, index, line):
     self.expected.insert(index, line)
@@ -228,6 +254,9 @@ class RegexListOutput(ExpectedOutput):
      ones.
 
      In any case, there must be at least one line of actual output.
+
+     The REs must match whole actual lines, in contrast to the RegexOutput
+     class which matches a prefix of the actual line.
   """
 
   def __init__(self, expected, match_all=True):
@@ -243,18 +272,37 @@ class RegexListOutput(ExpectedOutput):
 
     if self.match_all:
       return (len(self.expected_res) == len(actual) and
-              all(e.match(a) for e, a in zip(self.expected_res, actual)))
+              all(regex_fullmatch(e, a) for e, a in zip(self.expected_res, actual)))
 
     i_expected = 0
     for actual_line in actual:
-      if self.expected_res[i_expected].match(actual_line):
+      if regex_fullmatch(self.expected_res[i_expected], actual_line):
         i_expected += 1
         if i_expected == len(self.expected_res):
           return True
     return False
 
   def display_differences(self, message, label, actual):
-    display_lines(message, self.expected, actual, label + ' (regexp)', label)
+    e_label = label + ' (regexp, match_all=%s)' % (self.match_all,)
+    display_lines(message, self.expected, actual, e_label, label)
+
+    assert actual is not None
+    if not isinstance(actual, list):
+      actual = [actual]
+
+    if self.match_all:
+      logger.warn('DIFF ' + label + ':')
+      if len(self.expected) != len(actual):
+        logger.warn('# Expected %d lines; actual %d lines' %
+                    (len(self.expected), len(actual)))
+      for e, a in map(None, self.expected_res, actual):
+        if e is not None and a is not None and regex_fullmatch(e, a):
+          logger.warn("|  " + a.rstrip())
+        else:
+          if e is not None:
+            logger.warn("| -" + repr(e.pattern))
+          if a is not None:
+            logger.warn("| +" + repr(a))
 
   def insert(self, index, line):
     self.expected.insert(index, line)
@@ -279,8 +327,9 @@ class UnorderedOutput(ExpectedOutput):
     return sorted(self.expected) == sorted(actual)
 
   def display_differences(self, message, label, actual):
-    display_lines(message, self.expected, actual, label + ' (unordered)', label)
-    display_lines_diff(self.expected, actual, label + ' (unordered)', label)
+    e_label = label + ' (unordered)'
+    display_lines(message, self.expected, actual, e_label, label)
+    display_lines_diff(sorted(self.expected), sorted(actual), e_label, label)
 
 
 class UnorderedRegexListOutput(ExpectedOutput):
@@ -295,6 +344,9 @@ class UnorderedRegexListOutput(ExpectedO
      expressions.  The implementation matches each expression in turn to
      the first unmatched actual line that it can match, and does not try
      all the permutations when there are multiple possible matches.
+
+     The REs must match whole actual lines, in contrast to the RegexOutput
+     class which matches a prefix of the actual line.
   """
 
   def __init__(self, expected):
@@ -305,13 +357,16 @@ class UnorderedRegexListOutput(ExpectedO
     assert actual is not None
     if not isinstance(actual, list):
       actual = [actual]
+    else:
+      # copy the list so we can remove elements without affecting caller
+      actual = actual[:]
 
     if len(self.expected) != len(actual):
       return False
     for e in self.expected:
       expect_re = re.compile(e)
       for actual_line in actual:
-        if expect_re.match(actual_line):
+        if regex_fullmatch(expect_re, actual_line):
           actual.remove(actual_line)
           break
       else:
@@ -320,9 +375,30 @@ class UnorderedRegexListOutput(ExpectedO
     return True
 
   def display_differences(self, message, label, actual):
-    display_lines(message, self.expected, actual,
-                  label + ' (regexp) (unordered)', label)
+    e_label = label + ' (regexp) (unordered)'
+    display_lines(message, self.expected, actual, e_label, label)
 
+    assert actual is not None
+    if not isinstance(actual, list):
+      actual = [actual]
+    else:
+      # copy the list so we can remove elements without affecting caller
+      actual = actual[:]
+
+    logger.warn('DIFF ' + label + ':')
+    if len(self.expected) != len(actual):
+      logger.warn('# Expected %d lines; actual %d lines' %
+                  (len(self.expected), len(actual)))
+    for e in self.expected:
+      expect_re = re.compile(e)
+      for actual_line in actual:
+        if regex_fullmatch(expect_re, actual_line):
+          actual.remove(actual_line)
+          break
+      else:
+        logger.warn("| -" + expect_re.pattern.rstrip())
+    for a in actual:
+      logger.warn("| +" + a.rstrip())
 
 class AlternateOutput(ExpectedOutput):
   """Matches any one of a list of ExpectedOutput instances.
@@ -467,10 +543,11 @@ def verify_exit_code(message, actual, ex
 # A simple dump file parser.  While sufficient for the current
 # testsuite it doesn't cope with all valid dump files.
 class DumpParser:
-  def __init__(self, lines):
+  def __init__(self, lines, ignore_sha1=False):
     self.current = 0
     self.lines = lines
     self.parsed = {}
+    self.ignore_sha1 = ignore_sha1
 
   def parse_line(self, regex, required=True):
     m = re.match(regex, self.lines[self.current])
@@ -660,6 +737,9 @@ class DumpParser:
       if not header in headers:
         node[key] = None
         continue
+      if self.ignore_sha1 and (key in ['copy_sha1', 'text_sha1']):
+        node[key] = None
+        continue
       m = re.match(regex, headers[header])
       if not m:
         raise SVNDumpParseError("expected '%s' at line %d\n%s"
@@ -726,7 +806,8 @@ class DumpParser:
     self.parse_all_revisions()
     return self.parsed
 
-def compare_dump_files(message, label, expected, actual,
+def compare_dump_files(label_expected, label_actual,
+                       expected, actual,
                        ignore_uuid=False,
                        expect_content_length_always=False,
                        ignore_empty_prop_sections=False,
@@ -735,8 +816,7 @@ def compare_dump_files(message, label, e
   of lines as returned by run_and_verify_dump, and check that the same
   revisions, nodes, properties, etc. are present in both dumps.
   """
-
-  parsed_expected = DumpParser(expected).parse()
+  parsed_expected = DumpParser(expected, not svntest.main.fs_has_sha1()).parse()
   parsed_actual = DumpParser(actual).parse()
 
   if ignore_uuid:
@@ -769,6 +849,8 @@ def compare_dump_files(message, label, e
 
   if parsed_expected != parsed_actual:
     print('DIFF of raw dumpfiles (including expected differences)')
+    print('--- ' + (label_expected or 'expected'))
+    print('+++ ' + (label_actual or 'actual'))
     print(''.join(ndiff(expected, actual)))
     raise svntest.Failure('DIFF of parsed dumpfiles (ignoring expected differences)\n'
                           + '\n'.join(ndiff(
@@ -860,7 +942,7 @@ def make_git_diff_header(target_path, re
     ])
     if text_changes:
       output.extend([
-        "--- /dev/null\t(" + old_tag + ")\n",
+        "--- a/" + repos_relpath + src_label + "\t(" + old_tag + ")\n",
         "+++ b/" + repos_relpath + dst_label + "\t(" + new_tag + ")\n"
       ])
   elif delete:
@@ -871,7 +953,7 @@ def make_git_diff_header(target_path, re
     if text_changes:
       output.extend([
         "--- a/" + repos_relpath + src_label + "\t(" + old_tag + ")\n",
-        "+++ /dev/null\t(" + new_tag + ")\n"
+        "+++ b/" + repos_relpath + dst_label + "\t(" + new_tag + ")\n"
       ])
   elif cp:
     if copyfrom_rev:

Modified: subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/wc.py
URL: http://svn.apache.org/viewvc/subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/wc.py?rev=1846488&r1=1846487&r2=1846488&view=diff
==============================================================================
--- subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/wc.py (original)
+++ subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svntest/wc.py Tue Nov 13 07:49:04 2018
@@ -1092,17 +1092,7 @@ def svn_uri_quote(url):
 
 def python_sqlite_can_read_wc():
   """Check if the Python builtin is capable enough to peek into wc.db"""
-
-  try:
-    db = svntest.sqlite3.connect('')
-
-    c = db.cursor()
-    c.execute('select sqlite_version()')
-    ver = tuple(map(int, c.fetchall()[0][0].split('.')))
-
-    return ver >= (3, 6, 18) # Currently enough (1.7-1.9)
-  except:
-    return False
+  return svntest.main.python_sqlite_can_read_our_wc_db()
 
 def open_wc_db(local_path):
   """Open the SQLite DB for the WC path LOCAL_PATH.

Modified: subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svnversion_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svnversion_tests.py?rev=1846488&r1=1846487&r2=1846488&view=diff
==============================================================================
--- subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svnversion_tests.py (original)
+++ subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/svnversion_tests.py Tue Nov 13 07:49:04 2018
@@ -71,9 +71,8 @@ def svnversion_test(sbox):
   expected_output = wc.State(wc_dir, {'A/mu' : Item(verb='Sending')})
   expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
   expected_status.tweak('A/mu', wc_rev=2)
-  if svntest.actions.run_and_verify_commit(wc_dir,
-                                           expected_output, expected_status):
-    raise svntest.Failure
+  svntest.actions.run_and_verify_commit(wc_dir,
+                                        expected_output, expected_status)
 
   # Unmodified, mixed
   svntest.actions.run_and_verify_svnversion(wc_dir, repo_url,
@@ -98,13 +97,12 @@ def svnversion_test(sbox):
                       + 'appended mu text')
   expected_disk.tweak('iota',
                       contents=expected_disk.desc['A/D/gamma'].contents)
-  if svntest.actions.run_and_verify_switch(wc_dir, iota_path, gamma_url,
-                                           expected_output,
-                                           expected_disk,
-                                           expected_status,
-                                           [],
-                                           False, '--ignore-ancestry'):
-    raise svntest.Failure
+  svntest.actions.run_and_verify_switch(wc_dir, iota_path, gamma_url,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status,
+                                        [],
+                                        False, '--ignore-ancestry')
 
   # Prop modified, mixed, part wc switched
   svntest.actions.run_and_verify_svnversion(wc_dir, repo_url,

Modified: subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/trans_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/trans_tests.py?rev=1846488&r1=1846487&r2=1846488&view=diff
==============================================================================
--- subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/trans_tests.py (original)
+++ subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/trans_tests.py Tue Nov 13 07:49:04 2018
@@ -814,7 +814,8 @@ def props_only_file_update(sbox):
                       ]
 
   # Create r2 with iota's contents and svn:keywords modified
-  open(iota_path, 'w').writelines(content)
+  with open(iota_path, 'w') as f:
+    f.writelines(content)
   svntest.main.run_svn(None, 'propset', 'svn:keywords', 'Author', iota_path)
 
   expected_output = wc.State(wc_dir, {
@@ -831,7 +832,8 @@ def props_only_file_update(sbox):
   # Create r3 that drops svn:keywords
 
   # put the content back to its untranslated form
-  open(iota_path, 'w').writelines(content)
+  with open(iota_path, 'w') as f:
+    f.writelines(content)
 
   svntest.main.run_svn(None, 'propdel', 'svn:keywords', iota_path)
 

Modified: subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/tree_conflict_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/tree_conflict_tests.py?rev=1846488&r1=1846487&r2=1846488&view=diff
==============================================================================
--- subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/tree_conflict_tests.py (original)
+++ subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/tree_conflict_tests.py Tue Nov 13 07:49:04 2018
@@ -473,6 +473,7 @@ def ensure_tree_conflict(sbox, operation
         run_and_verify_svn(expected_stdout, [],
                            'merge',
                            '--allow-mixed-revisions',
+                           '--accept=postpone',
                            '-r', str(source_left_rev) + ':' + str(source_right_rev),
                            source_url, target_path)
       else:
@@ -1096,13 +1097,15 @@ def at_directory_external(sbox):
   svntest.main.run_svn(None, 'update', wc_dir)
 
   # r3: modify ^/A/B/E/alpha
-  open(sbox.ospath('A/B/E/alpha'), 'a').write('This is still A/B/E/alpha.\n')
+  with open(sbox.ospath('A/B/E/alpha'), 'a') as f:
+    f.write('This is still A/B/E/alpha.\n')
   svntest.main.run_svn(None, 'commit', '-m', 'file mod', wc_dir)
   svntest.main.run_svn(None, 'update', wc_dir)
   merge_rev = svntest.main.youngest(sbox.repo_dir)
 
   # r4: create ^/A/B/E/alpha2
-  open(sbox.ospath('A/B/E/alpha2'), 'a').write("This is the file 'alpha2'.\n")
+  with open(sbox.ospath('A/B/E/alpha2'), 'a') as f:
+    f.write("This is the file 'alpha2'.\n")
   svntest.main.run_svn(None, 'add', sbox.ospath('A/B/E/alpha2'))
   svntest.main.run_svn(None, 'commit', '-m', 'file add', wc_dir)
   svntest.main.run_svn(None, 'update', wc_dir)
@@ -1503,6 +1506,47 @@ def update_delete_mixed_rev(sbox):
   }
   run_and_verify_info([expected_info], sbox.repo_url + '/A/B/E/alpha2')
 
+# NB: This test will run forever if the bug it is testing for is present!
+def local_missing_dir_endless_loop(sbox):
+  "endless loop when resolving local-missing dir"
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  sbox.simple_copy('A', 'A1')
+  sbox.simple_commit()
+  sbox.simple_update()
+  sbox.simple_move('A/B', 'A/B2')
+  sbox.simple_commit()
+  sbox.simple_update()
+  main.file_append_binary(sbox.ospath("A/B2/lambda"), "This is more content.\n")
+  sbox.simple_commit()
+  sbox.simple_update()
+
+  # Create a config which enables the interactive conflict resolver
+  config_contents = '''\
+[auth]
+password-stores =
+
+[miscellany]
+interactive-conflicts = true
+'''
+  config_dir = sbox.create_config_dir(config_contents)
+
+  # Bug: 'svn' keeps retrying interactive conflict resolution while the library
+  # keeps signalling 'SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE' -> endless loop
+  main.run_svn("Tree conflict on '%s'" % sbox.ospath("A1/B2"),
+      'merge', '-c4', '^/A', sbox.ospath('A1'),
+      '--config-dir', config_dir, '--force-interactive')
+
+  # If everything works as expected the resolver will recommended a
+  # resolution option and 'svn' will resolve the conflict automatically.
+  # Verify that 'A1/B/lambda' contains the merged content:
+  contents = open(sbox.ospath('A1/B/lambda'), 'rb').readlines()
+  svntest.verify.compare_and_display_lines(
+    "A1/B/lambda has unexpectected contents", sbox.ospath("A1/B/lambda"),
+    [ "This is the file 'lambda'.\n", "This is more content.\n"], contents)
+
+
 #######################################################################
 # Run the tests
 
@@ -1534,6 +1578,7 @@ test_list = [ None,
               actual_only_node_behaviour,
               update_dir_with_not_present,
               update_delete_mixed_rev,
+              local_missing_dir_endless_loop,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/update_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/update_tests.py?rev=1846488&r1=1846487&r2=1846488&view=diff
==============================================================================
--- subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/update_tests.py (original)
+++ subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/update_tests.py Tue Nov 13 07:49:04 2018
@@ -480,7 +480,7 @@ def update_to_rev_zero(sbox):
 def receive_overlapping_same_change(sbox):
   "overlapping identical changes should not conflict"
 
-  ### (See http://subversion.tigris.org/issues/show_bug.cgi?id=682.)
+  ### (See https://issues.apache.org/jira/browse/SVN-682.)
   ###
   ### How this test works:
   ###
@@ -6719,6 +6719,7 @@ def update_conflict_details(sbox):
 # 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()
+@Issue(4585)
 def update_keywords_on_shortcut(sbox):
   "update_keywords_on_shortcut"
 
@@ -6840,6 +6841,21 @@ def update_delete_switched(sbox):
   svntest.actions.run_and_verify_update(wc_dir, None, None, expected_status,
                                         [], False, sbox.ospath('A'), '-r', 0)
 
+@XFail()
+def update_add_missing_local_add(sbox):
+  "update adds missing local addition"
+  
+  sbox.build(read_only=True)
+  
+  # Note that updating 'A' to r0 doesn't reproduce this issue...
+  sbox.simple_update('', revision='0')
+  sbox.simple_mkdir('A')
+  sbox.simple_add_text('mumumu', 'A/mu')
+  os.unlink(sbox.ospath('A/mu'))
+  os.rmdir(sbox.ospath('A'))
+  
+  sbox.simple_update()
+
 #######################################################################
 # Run the tests
 
@@ -6930,6 +6946,7 @@ test_list = [ None,
               update_add_conflicted_deep,
               missing_tmp_update,
               update_delete_switched,
+              update_add_missing_local_add,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/upgrade_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/upgrade_tests.py?rev=1846488&r1=1846487&r2=1846488&view=diff
==============================================================================
--- subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/upgrade_tests.py (original)
+++ subversion/branches/mod-dav-svn-expressions/subversion/tests/cmdline/upgrade_tests.py Tue Nov 13 07:49:04 2018
@@ -392,7 +392,8 @@ def xml_entries_relocate(path, from_url,
   entries = os.path.join(path, adm_name, 'entries')
   txt = open(entries).read().replace('url="' + from_url, 'url="' + to_url)
   os.chmod(entries, svntest.main.S_ALL_RWX)
-  open(entries, 'w').write(txt)
+  with open(entries, 'w') as f:
+    f.write(txt)
 
   for dirent in os.listdir(path):
     item_path = os.path.join(path, dirent)
@@ -410,7 +411,8 @@ def simple_entries_replace(path, from_ur
   entries = os.path.join(path, adm_name, 'entries')
   txt = open(entries).read().replace(from_url, to_url)
   os.chmod(entries, svntest.main.S_ALL_RWX)
-  open(entries, 'wb').write(txt.encode())
+  with open(entries, 'wb') as f:
+    f.write(txt.encode())
 
   for dirent in os.listdir(path):
     item_path = os.path.join(path, dirent)

Modified: subversion/branches/mod-dav-svn-expressions/subversion/tests/libsvn_client/client-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/mod-dav-svn-expressions/subversion/tests/libsvn_client/client-test.c?rev=1846488&r1=1846487&r2=1846488&view=diff
==============================================================================
--- subversion/branches/mod-dav-svn-expressions/subversion/tests/libsvn_client/client-test.c (original)
+++ subversion/branches/mod-dav-svn-expressions/subversion/tests/libsvn_client/client-test.c Tue Nov 13 07:49:04 2018
@@ -756,19 +756,22 @@ test_foreign_repos_copy(const svn_test_o
   SVN_ERR(svn_client_checkout3(NULL, repos_url, wc_path, &peg_rev, &rev,
                                svn_depth_infinity, FALSE, FALSE, ctx, pool));
 
-  SVN_ERR(svn_client__copy_foreign(svn_path_url_add_component2(repos2_url, "A",
-                                                               pool),
-                                   svn_dirent_join(wc_path, "A-copied", pool),
-                                   &peg_rev, &rev, svn_depth_infinity, FALSE, FALSE,
-                                   ctx, pool));
+  SVN_WC__CALL_WITH_WRITE_LOCK(
+    svn_client__copy_foreign(svn_path_url_add_component2(repos2_url, "A",
+                                                         pool),
+                             svn_dirent_join(wc_path, "A-copied", pool),
+                             &peg_rev, &rev, svn_depth_infinity, FALSE,
+                             ctx, pool),
+    ctx->wc_ctx, wc_path, FALSE, pool);
 
 
-  SVN_ERR(svn_client__copy_foreign(svn_path_url_add_component2(repos2_url,
-                                                               "iota",
-                                                               pool),
-                                   svn_dirent_join(wc_path, "iota-copied", pool),
-                                   &peg_rev, &rev, svn_depth_infinity, FALSE, FALSE,
-                                   ctx, pool));
+  SVN_WC__CALL_WITH_WRITE_LOCK(
+    svn_client__copy_foreign(svn_path_url_add_component2(repos2_url, "iota",
+                                                         pool),
+                             svn_dirent_join(wc_path, "iota-copied", pool),
+                             &peg_rev, &rev, svn_depth_infinity, FALSE,
+                             ctx, pool),
+    ctx->wc_ctx, wc_path, FALSE, pool);
 
   return SVN_NO_ERROR;
 }