Modified: 
subversion/branches/addremove/subversion/tests/cmdline/svnauthz_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svnauthz_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/svnauthz_tests.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/svnauthz_tests.py 
Sat May 23 14:16:56 2020
@@ -197,9 +197,8 @@ def svnauthz_validate_txn_test(sbox):
   svntest.main.create_python_hook_script(pre_commit_hook, hook_instance)
   svntest.main.file_append(authz_path, 'x')
   expected_status.tweak('A/authz', status='  ', wc_rev=4)
-  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)
   expected_data = svntest.verify.ExpectedOutput("Exit 2\n", match_all=False)
   verify_logfile(logfilepath, expected_data)
 
@@ -275,9 +274,8 @@ def svnauthz_accessof_repo_test(sbox):
   expected_status.add({
     'A/authz'            :  Item(status='  ', 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)
 
   # Anonymous access with no path, and no repository should be rw
   # since it returns the highest level of access granted anywhere.
@@ -898,6 +896,105 @@ def svnauthz_compat_mode_repo_test(sbox)
       repo_url + "/zilch"
   )
 
+
+@Issue(4793)
+def svnauthz_inverted_selector_test(sbox):
+  "test inverted selector rights"
+
+  # build an authz file
+  authz_content = ("[groups]\n"
+                   "grouped = grouper\n"
+
+                   "[aliases]\n"
+                   "aliased = aliaser\n"
+
+                   "[A:/]\n"
+                   "@grouped = r\n"
+                   "~@grouped = rw\n"
+
+                   "[B:/]\n"
+                   "&aliased = r\n"
+                   "~&aliased = rw\n"
+
+                   "[C:/]\n"
+                   "user = r\n"
+                   "~user = rw\n"
+
+                   "[D:/]\n"
+                   "~@grouped = rw\n"
+                   "not-grouper = r\n"
+
+                   "[E:/]\n"
+                   "~&aliased = rw\n"
+                   "not-aliaser = r\n"
+
+                   "[F:/]\n"
+                   "~user = rw\n"
+                   "not-user = r\n")
+
+  (authz_fd, authz_path) = tempfile.mkstemp()
+  svntest.main.file_write(authz_path, authz_content)
+
+  def accessof(repos, user, expected_stdout):
+    return svntest.actions.run_and_verify_svnauthz(
+      expected_stdout, None, 0, False, 'accessof',
+      '--repository', repos, '--username', user, authz_path)
+
+  accessof('A', 'grouper', 'r')
+  accessof('A', 'not-grouper', 'rw')
+
+  accessof('B', 'aliaser', 'r')
+  accessof('B', 'not-aliaser', 'rw')
+
+  accessof('C', 'user', 'r')
+  accessof('C', 'not-user', 'rw')
+
+  accessof('D', 'grouper', 'no')
+  accessof('D', 'not-grouper', 'r')
+  accessof('D', 'other', 'rw')
+
+  accessof('E', 'aliaser', 'no')
+  accessof('E', 'not-aliaser', 'r')
+  accessof('E', 'other', 'rw')
+
+  accessof('F', 'user', 'no')
+  accessof('F', 'not-user', 'r')
+  accessof('F', 'other', 'rw')
+
+  os.close(authz_fd)
+  os.remove(authz_path)
+
+
+@Issues(4802, 4803)
+def svnauthz_empty_group_test(sbox):
+  "test empty group definition"
+
+  # build an authz file
+  authz_content = ("[groups]\n"
+                   "group1 =\n"
+                   "group2 = @group1\n"
+                   "group3 = @group2, user\n"
+
+
+                   "[A:/]\n"
+                   "@group1 = rw\n"
+                   "@group2 = rw\n"
+                   "@group3 = r\n")
+
+  (authz_fd, authz_path) = tempfile.mkstemp()
+  svntest.main.file_write(authz_path, authz_content)
+
+  expected_stderr = svntest.verify.RegexOutput(
+    r".*warning: W220003:.*", match_all=False)
+
+  svntest.actions.run_and_verify_svnauthz(
+    [], expected_stderr, 0, False, 'validate', authz_path)
+
+  svntest.actions.run_and_verify_svnauthz(
+    'r', expected_stderr, 0, False, 'accessof',
+    '--repository', 'A', '--username', 'user', authz_path)
+
+
 ########################################################################
 # Run the tests
 
@@ -916,6 +1013,8 @@ test_list = [ None,
               svnauthz_accessof_txn_test,
               svnauthz_compat_mode_file_test,
               svnauthz_compat_mode_repo_test,
+              svnauthz_inverted_selector_test,
+              svnauthz_empty_group_test,
              ]
 
 if __name__ == '__main__':

Modified: 
subversion/branches/addremove/subversion/tests/cmdline/svndumpfilter_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svndumpfilter_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- 
subversion/branches/addremove/subversion/tests/cmdline/svndumpfilter_tests.py 
(original)
+++ 
subversion/branches/addremove/subversion/tests/cmdline/svndumpfilter_tests.py 
Sat May 23 14:16:56 2020
@@ -83,7 +83,7 @@ def filter_and_return_output(dump, bufsi
 def reflect_dropped_renumbered_revs(sbox):
   "reflect dropped renumbered revs in svn:mergeinfo"
 
-  ## See http://subversion.tigris.org/issues/show_bug.cgi?id=2982. ##
+  ## See https://issues.apache.org/jira/browse/SVN-2982. ##
 
   # Test svndumpfilter with include option
   sbox.build(empty=True)
@@ -134,7 +134,7 @@ def svndumpfilter_loses_mergeinfo(sbox):
   "svndumpfilter loses mergeinfo"
   #svndumpfilter loses mergeinfo if invoked without --renumber-revs
 
-  ## See http://subversion.tigris.org/issues/show_bug.cgi?id=3181. ##
+  ## See https://issues.apache.org/jira/browse/SVN-3181. ##
 
   sbox.build(empty=True)
   dumpfile_location = os.path.join(os.path.dirname(sys.argv[0]),
@@ -217,7 +217,7 @@ def _simple_dumpfilter_test(sbox, dumpfi
 @Issue(2697)
 def dumpfilter_with_targets(sbox):
   "svndumpfilter --targets blah"
-  ## See http://subversion.tigris.org/issues/show_bug.cgi?id=2697. ##
+  ## See https://issues.apache.org/jira/browse/SVN-2697. ##
 
   sbox.build(empty=True)
 
@@ -608,7 +608,7 @@ def match_empty_prefix(sbox):
                                                              '--quiet',
                                                              *dumpargs)
     if filtered_err:
-      raise verify.UnexpectedStderr(filtered_err)
+      raise SVNExpectedStderr(filtered_err)
 
     # Load the filtered dump into a repo and check the result
     sbox.build(empty=True)
@@ -677,7 +677,7 @@ def accepts_deltas(sbox):
 @Issue(4234)
 def dumpfilter_targets_expect_leading_slash_prefixes(sbox):
   "dumpfilter targets expect leading '/' in prefixes"
-  ## See http://subversion.tigris.org/issues/show_bug.cgi?id=4234. ##
+  ## See https://issues.apache.org/jira/browse/SVN-4234. ##
 
   sbox.build(empty=True)
 

Modified: 
subversion/branches/addremove/subversion/tests/cmdline/svnfsfs_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svnfsfs_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/svnfsfs_tests.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/svnfsfs_tests.py Sat 
May 23 14:16:56 2020
@@ -94,7 +94,8 @@ def patch_format(repo_dir, shard_size):
 
   new_contents = b"\n".join(processed_lines)
   os.chmod(format_path, svntest.main.S_ALL_RW)
-  open(format_path, 'wb').write(new_contents)
+  with open(format_path, 'wb') as f:
+    f.write(new_contents)
 
 ######################################################################
 # Tests
@@ -184,7 +185,7 @@ def test_stats(sbox):
                            '.*\d+ bytes in .*\d+ file property 
representations',
                            '.*\d+ average delta chain length',
                            '.*\d+ bytes in header & footer overhead' ],
-    '.* representation statistics:' : 
+    '.* representation statistics:' :
                           ['.*\d+ bytes in .*\d+ reps',
                            '.*\d+ bytes in .*\d+ shared reps',
                            '.*\d+ bytes expanded size',

Modified: 
subversion/branches/addremove/subversion/tests/cmdline/svnmover_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svnmover_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/svnmover_tests.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/svnmover_tests.py 
Sat May 23 14:16:56 2020
@@ -469,7 +469,7 @@ rm A/B/C/Y
     '   D /top0/A/B/C/Y',
   ]))
   expected_output = svntest.verify.UnorderedRegexListOutput(escaped
-                          + ['^-', '^r2', '^-', '^Changed paths:',])
+                          + ['^--*', '^r2.*', '^--*', '^Changed paths:',])
   svntest.actions.run_and_verify_svn(expected_output, [],
                                      'log', '-qvr2', repo_url)
 
@@ -755,7 +755,7 @@ def simple_moves_within_a_branch(sbox):
                 'mv lib/foo/y2 y2')
   # move and rename, dir with children
   test_svnmover2(sbox, '/trunk',
-                 reported_br_diff('') +
+                 reported_br_diff('trunk') +
                  reported_add('subdir') +
                  reported_move('lib', 'subdir/lib2'),
                 'mkdir subdir',
@@ -765,7 +765,7 @@ def simple_moves_within_a_branch(sbox):
   # moves and renames together
   # (put it all back to how it was, in one commit)
   test_svnmover2(sbox, '/trunk',
-                 reported_br_diff('') +
+                 reported_br_diff('trunk') +
                  reported_move('subdir/lib2/README.txt', 'README') +
                  reported_move('subdir/lib2', 'lib') +
                  reported_move('y2', 'lib/foo/y') +
@@ -1545,7 +1545,7 @@ def replace_via_rm_cp(sbox):
   """replace by deleting and copying"""
 
   sbox_build_svnmover(sbox)
-                 
+
   expected_eids = svntest.wc.State('', {
     'B0'     : Item(eid=0),
     'B0/X'   : Item(eid=1),
@@ -1572,7 +1572,7 @@ def replace_via_rm_cp(sbox):
   test_svnmover_verify_log(sbox.repo_url,
                            ['D /top0/X/A',
                             'A /top0/X/A (from /top0/X/A:1)'])
-                 
+
 @XFail()
 # After making a commit, svnmover currently can't (within the same execution)
 # look up paths in the revision it just committed.

Modified: 
subversion/branches/addremove/subversion/tests/cmdline/svnmucc_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svnmucc_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/svnmucc_tests.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/svnmucc_tests.py Sat 
May 23 14:16:56 2020
@@ -458,7 +458,7 @@ rm A/B/C/Y
     '   D /A/B/C/Y',
   ]))
   expected_output = svntest.verify.UnorderedRegexListOutput(excaped
-                    + ['^-', '^r3', '^-', '^Changed paths:',])
+                    + ['^--*', '^r3.*', '^--*', '^Changed paths:',])
   svntest.actions.run_and_verify_svn(expected_output, [],
                                      'log', '-qvr3', repo_url)
 
@@ -534,7 +534,8 @@ def svnmucc_type_errors(sbox):
                 'put', sbox.ospath('file'), 'A')
 
   xtest_svnmucc(sbox.repo_url,
-                ["svnmucc: E160020: Path 'Z' already exists"],
+                ["svnmucc: E160020: Path 'Z' already exists, or was created "
+                 "by an earlier operation"],
                 '-m', '',
                 'mkdir', 'A/Z',
                 'put', sbox.ospath('file'), 'A/Z')
@@ -576,7 +577,8 @@ def svnmucc_propset_and_put(sbox):
 
   # Put same file twice (non existing)
   xtest_svnmucc(sbox.repo_url,
-                ["svnmucc: E160020: Path 't3' already exists"],
+                ["svnmucc: E160020: Path 't3' already exists, or was created "
+                 "by an earlier operation"],
                 '-m', '',
                 'put', sbox.ospath('file'), 't3',
                 'put', sbox.ospath('file'), 't3')

Modified: 
subversion/branches/addremove/subversion/tests/cmdline/svnrdump_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svnrdump_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/svnrdump_tests.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/svnrdump_tests.py 
Sat May 23 14:16:56 2020
@@ -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']:
@@ -982,6 +991,36 @@ def load_non_deltas_with_props(sbox):
     actual = map(str.strip, out)
     svntest.verify.compare_and_display_lines(None, 'PROPS', expected, actual)
 
+def load_invalid_svn_date_revprop_in_r0(sbox):
+  "load: invalid svn:date revprop in r0"
+  svnrdump_tests_dir = os.path.join(os.path.dirname(sys.argv[0]),
+                                    'svnrdump_tests_data')
+  sbox.build(create_wc=False, empty=True)
+  svntest.actions.enable_revprop_changes(sbox.repo_dir)
+  expected_err = svntest.verify.RegexListOutput(
+                   ['.* E125005: Wrong or unexpected property value.*'],
+                   match_all=False)
+  dumpfile = "bad-date-r0.dump"
+  dumpfile_path = os.path.join(svnrdump_tests_dir, dumpfile)
+  run_and_verify_svnrdump_load(dumpfile_path,
+                               [], expected_err, 1,
+                               sbox.repo_url)
+
+def load_invalid_svn_date_revprop_in_r1(sbox):
+  "load: invalid svn:date revprop in r1"
+  svnrdump_tests_dir = os.path.join(os.path.dirname(sys.argv[0]),
+                                    'svnrdump_tests_data')
+  sbox.build(create_wc=False, empty=True)
+  svntest.actions.enable_revprop_changes(sbox.repo_dir)
+  expected_err = svntest.verify.RegexListOutput(
+                   ['.* E125005: Wrong or unexpected property value.*'],
+                   match_all=False)
+  dumpfile = "bad-date-r0.dump"
+  dumpfile_path = os.path.join(svnrdump_tests_dir, dumpfile)
+  run_and_verify_svnrdump_load(dumpfile_path,
+                               [], expected_err, 1,
+                               sbox.repo_url)
+
 ########################################################################
 # Run the tests
 
@@ -1043,6 +1082,8 @@ test_list = [ None,
               load_non_deltas_replace_copy_with_props,
               dump_replace_with_copy,
               load_non_deltas_with_props,
+              load_invalid_svn_date_revprop_in_r0,
+              load_invalid_svn_date_revprop_in_r1,
              ]
 
 if __name__ == '__main__':

Modified: 
subversion/branches/addremove/subversion/tests/cmdline/svnserveautocheck.sh
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svnserveautocheck.sh?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/svnserveautocheck.sh 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/svnserveautocheck.sh 
Sat May 23 14:16:56 2020
@@ -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}
 
@@ -66,6 +74,28 @@ fail() {
   exit 1
 }
 
+query() {
+    printf "%s" "$SCRIPT: $1 (y/n)? [$2] "
+    if [ -n "$BASH_VERSION" ]; then
+        read -n 1 -t 32
+    else
+        #
+        prog="
+import select as s
+import sys
+import tty, termios
+tty.setcbreak(sys.stdin.fileno(), termios.TCSANOW)
+if s.select([sys.stdin.fileno()], [], [], 32)[0]:
+  sys.stdout.write(sys.stdin.read(1))
+"
+        stty_state=`stty -g`
+        REPLY=`$PYTHON -u -c "$prog" "$@"`
+        stty $stty_state
+    fi
+    echo
+    [ "${REPLY:-$2}" = 'y' ]
+}
+
 # Compute ABS_BUILDDIR and ABS_SRCDIR.
 if [ -x subversion/svn/svn ]; then
   # cwd is build tree root
@@ -84,19 +114,27 @@ if [ ! -e $ABS_SRCDIR/subversion/include
   fail "Run this script from the root of Subversion's build tree!"
 fi
 
+# Create a directory for the PID and log files. If you change this, also make
+# sure to change the svn:ignore entry for it and "make check-clean".
+SVNSERVE_ROOT="$ABS_BUILDDIR/subversion/tests/cmdline/svnserve-$(date 
'+%Y%m%d-%H%M%S')"
+mkdir "$SVNSERVE_ROOT" \
+    || fail "couldn't create temporary directory '$SVNSERVE_ROOT'"
+
 # If you change this, also make sure to change the svn:ignore entry
 # for it and "make check-clean".
-SVNSERVE_PID=$ABS_BUILDDIR/subversion/tests/svnserveautocheck.pid
+SVNSERVE_PID=$SVNSERVE_ROOT/svnserve.pid
+SVNSERVE_LOG=$SVNSERVE_ROOT/svnserve.log
 
 SERVER_CMD="$ABS_BUILDDIR/subversion/svnserve/svnserve"
 
 rm -f $SVNSERVE_PID
+rm -f $SVNSERVE_LOG
 
 random_port() {
   if [ -n "$BASH_VERSION" ]; then
     echo $(($RANDOM+1024))
   else
-    $PYTHON -c 'import random; print random.randint(1024, 2**16-1)'
+    $PYTHON -c 'import random; print(random.randint(1024, 2**16-1))'
   fi
 }
 
@@ -124,10 +162,15 @@ 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 \
             --pid-file $SVNSERVE_PID \
+            --log-file $SVNSERVE_LOG \
             $SVNSERVE_ARGS &
 
 BASE_URL=svn://127.0.0.1:$SVNSERVE_PORT
@@ -143,5 +186,11 @@ else
   cd - > /dev/null
 fi
 
+query 'Browse server log' n \
+    && less "$SVNSERVE_LOG"
+
+query 'Delete svnserve root directory' y \
+    && rm -fr "$SVNSERVE_ROOT/"
+
 really_cleanup
 exit $r

Modified: 
subversion/branches/addremove/subversion/tests/cmdline/svnsync_authz_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svnsync_authz_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- 
subversion/branches/addremove/subversion/tests/cmdline/svnsync_authz_tests.py 
(original)
+++ 
subversion/branches/addremove/subversion/tests/cmdline/svnsync_authz_tests.py 
Sat May 23 14:16:56 2020
@@ -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/addremove/subversion/tests/cmdline/svnsync_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svnsync_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/svnsync_tests.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/svnsync_tests.py Sat 
May 23 14:16:56 2020
@@ -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/addremove/subversion/tests/cmdline/svntest/__init__.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svntest/__init__.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/svntest/__init__.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/svntest/__init__.py 
Sat May 23 14:16:56 2020
@@ -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/addremove/subversion/tests/cmdline/svntest/actions.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svntest/actions.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/svntest/actions.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/svntest/actions.py 
Sat May 23 14:16:56 2020
@@ -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,
@@ -391,7 +418,7 @@ def run_and_verify_svnrdump(dumpfile_con
   # Since main.run_svnrdump() uses binary mode, normalize the stderr
   # line endings on Windows ourselves.
   if sys.platform == 'win32':
-    err = map(lambda x : x.replace('\r\n', '\n'), err)
+    err = [x.replace('\r\n', '\n') for x in err]
 
   # Ignore "consider upgrade" warnings to allow regression tests to pass
   # when run against a 1.6 mod_dav_svn.
@@ -1896,7 +1923,7 @@ def _run_and_verify_resolve(cmd, expecte
         "Merge conflicts in '" + path + "' marked as resolved.\n" for path in
         expected_paths]),
       verify.UnorderedRegexListOutput([
-        "Conflict in property.*at '" + path + "' marked as resolved.\n" \
+        "Conflict in property.*at '" + re.escape(path) + "' marked as 
resolved.\n" \
         for path in expected_paths]),
       verify.UnorderedOutput([
         "Tree conflict at '" + path + "' marked as resolved.\n" for path in
@@ -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)
@@ -2139,7 +2181,7 @@ def set_prop(name, value, path, expected
       file = None
   else:
     raise TypeError(value)
- 
+
   if file is None:
     propset += (name, value, path)
   else:

Modified: subversion/branches/addremove/subversion/tests/cmdline/svntest/main.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svntest/main.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/svntest/main.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/svntest/main.py Sat 
May 23 14:16:56 2020
@@ -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 = 15
 
 ######################################################################
 #
@@ -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:]))
@@ -865,8 +902,6 @@ def run_entriesdump(path):
     ### report on this? or continue to just skip it?
     return None
 
-  class Entry(object):
-    pass
   entries = { }
   exec(''.join(filter_dbg(stdout_lines)))
   return entries
@@ -890,8 +925,6 @@ def run_entriesdump_tree(path):
     ### report on this? or continue to just skip it?
     return None
 
-  class Entry(object):
-    pass
   dirs = { }
   exec(''.join(filter_dbg(stdout_lines)))
   return dirs
@@ -978,7 +1011,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 +1024,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 +1044,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 +1072,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)
@@ -1309,30 +1347,29 @@ def create_http_connection(url, debuglev
   h.set_debuglevel(debuglevel)
   return h
 
-def write_restrictive_svnserve_conf(repo_dir, anon_access="none"):
+def write_restrictive_svnserve_conf(repo_dir, anon_access="none",
+                                    separate_groups_db=False):
   "Create a restrictive authz file ( no anynomous access )."
 
   fp = open(get_svnserve_conf_file_path(repo_dir), 'w')
-  fp.write("[general]\nanon-access = %s\nauth-access = write\n"
-           "authz-db = authz\n" % anon_access)
+  fp.write("[general]\n"
+           "anon-access = %s\n"
+           "auth-access = write\n"
+           "authz-db = authz\n" % anon_access);
+  if separate_groups_db:
+    fp.write("groups-db = groups\n")
   if options.enable_sasl:
-    fp.write("realm = svntest\n[sasl]\nuse-sasl = true\n");
+    fp.write("realm = svntest\n"
+             "[sasl]\n",
+             "use-sasl = true\n");
   else:
     fp.write("password-db = passwd\n")
   fp.close()
 
-def write_restrictive_svnserve_conf_with_groups(repo_dir,
-                                                anon_access="none"):
+def write_restrictive_svnserve_conf_with_groups(repo_dir, anon_access="none"):
   "Create a restrictive configuration with groups stored in a separate file."
 
-  fp = open(get_svnserve_conf_file_path(repo_dir), 'w')
-  fp.write("[general]\nanon-access = %s\nauth-access = write\n"
-           "authz-db = authz\ngroups-db = groups\n" % anon_access)
-  if options.enable_sasl:
-    fp.write("realm = svntest\n[sasl]\nuse-sasl = true\n");
-  else:
-    fp.write("password-db = passwd\n")
-  fp.close()
+  return write_restrictive_svnserve_conf(repo_dir, anon_access, True)
 
 # Warning: because mod_dav_svn uses one shared authz file for all
 # repositories, you *cannot* use write_authz_file in any test that
@@ -1574,9 +1611,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 \
@@ -1608,28 +1647,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:
@@ -1642,7 +1690,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([
@@ -1666,6 +1713,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
+
+
 ######################################################################
 
 
@@ -1746,6 +1797,10 @@ class TestSpawningThread(threading.Threa
       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)
@@ -2086,7 +2141,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)')
@@ -2162,6 +2217,8 @@ def _create_parser(usage=None):
                     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(
@@ -2174,6 +2231,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
@@ -2184,6 +2254,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)
@@ -2215,26 +2291,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.fsfs_version in introducing_version:
+      introduced_in = introducing_version[options.fsfs_version]
       if options.server_minor_version \
-        and options.server_minor_version != 8 \
+        and options.server_minor_version != introduced_in \
         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.server_minor_version \
-        and options.server_minor_version != 7 \
-        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):
@@ -2309,6 +2388,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
@@ -2330,6 +2412,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()
@@ -2387,6 +2470,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 = ''
@@ -2479,8 +2572,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,

Modified: 
subversion/branches/addremove/subversion/tests/cmdline/svntest/mergetrees.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svntest/mergetrees.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- 
subversion/branches/addremove/subversion/tests/cmdline/svntest/mergetrees.py 
(original)
+++ 
subversion/branches/addremove/subversion/tests/cmdline/svntest/mergetrees.py 
Sat May 23 14:16:56 2020
@@ -253,69 +253,48 @@ def set_up_branch(sbox, branch_only = Fa
   expected_status = actions.get_virginal_state(wc_dir, 1)
   expected_disk = main.greek_state.copy()
 
+  def path_join(head, tail):
+    if not head: return tail
+    if not tail: return head
+    return head + '/' + tail
+
+  def greek_file_item(path):
+    if path[-1:].islower():
+      basename = re.sub('.*/', '', path)
+      return Item("This is the file '" + basename + "'.\n")
+    return Item()
+
+  A_paths = [
+    "",
+    "B",
+    "B/lambda",
+    "B/E",
+    "B/E/alpha",
+    "B/E/beta",
+    "B/F",
+    "mu",
+    "C",
+    "D",
+    "D/gamma",
+    "D/G",
+    "D/G/pi",
+    "D/G/rho",
+    "D/G/tau",
+    "D/H",
+    "D/H/chi",
+    "D/H/omega",
+    "D/H/psi",
+    ]
   def copy_A(dest_name, rev):
     expected = verify.UnorderedOutput(
-      ["A    " + os.path.join(wc_dir, dest_name, "B") + "\n",
-       "A    " + os.path.join(wc_dir, dest_name, "B", "lambda") + "\n",
-       "A    " + os.path.join(wc_dir, dest_name, "B", "E") + "\n",
-       "A    " + os.path.join(wc_dir, dest_name, "B", "E", "alpha") + "\n",
-       "A    " + os.path.join(wc_dir, dest_name, "B", "E", "beta") + "\n",
-       "A    " + os.path.join(wc_dir, dest_name, "B", "F") + "\n",
-       "A    " + os.path.join(wc_dir, dest_name, "mu") + "\n",
-       "A    " + os.path.join(wc_dir, dest_name, "C") + "\n",
-       "A    " + os.path.join(wc_dir, dest_name, "D") + "\n",
-       "A    " + os.path.join(wc_dir, dest_name, "D", "gamma") + "\n",
-       "A    " + os.path.join(wc_dir, dest_name, "D", "G") + "\n",
-       "A    " + os.path.join(wc_dir, dest_name, "D", "G", "pi") + "\n",
-       "A    " + os.path.join(wc_dir, dest_name, "D", "G", "rho") + "\n",
-       "A    " + os.path.join(wc_dir, dest_name, "D", "G", "tau") + "\n",
-       "A    " + os.path.join(wc_dir, dest_name, "D", "H") + "\n",
-       "A    " + os.path.join(wc_dir, dest_name, "D", "H", "chi") + "\n",
-       "A    " + os.path.join(wc_dir, dest_name, "D", "H", "omega") + "\n",
-       "A    " + os.path.join(wc_dir, dest_name, "D", "H", "psi") + "\n",
-       "Checked out revision " + str(rev - 1) + ".\n",
-       "A         " + os.path.join(wc_dir, dest_name) + "\n"])
-    expected_status.add({
-      dest_name + "/B"         : Item(status='  ', wc_rev=rev),
-      dest_name + "/B/lambda"  : Item(status='  ', wc_rev=rev),
-      dest_name + "/B/E"       : Item(status='  ', wc_rev=rev),
-      dest_name + "/B/E/alpha" : Item(status='  ', wc_rev=rev),
-      dest_name + "/B/E/beta"  : Item(status='  ', wc_rev=rev),
-      dest_name + "/B/F"       : Item(status='  ', wc_rev=rev),
-      dest_name + "/mu"        : Item(status='  ', wc_rev=rev),
-      dest_name + "/C"         : Item(status='  ', wc_rev=rev),
-      dest_name + "/D"         : Item(status='  ', wc_rev=rev),
-      dest_name + "/D/gamma"   : Item(status='  ', wc_rev=rev),
-      dest_name + "/D/G"       : Item(status='  ', wc_rev=rev),
-      dest_name + "/D/G/pi"    : Item(status='  ', wc_rev=rev),
-      dest_name + "/D/G/rho"   : Item(status='  ', wc_rev=rev),
-      dest_name + "/D/G/tau"   : Item(status='  ', wc_rev=rev),
-      dest_name + "/D/H"       : Item(status='  ', wc_rev=rev),
-      dest_name + "/D/H/chi"   : Item(status='  ', wc_rev=rev),
-      dest_name + "/D/H/omega" : Item(status='  ', wc_rev=rev),
-      dest_name + "/D/H/psi"   : Item(status='  ', wc_rev=rev),
-      dest_name                : Item(status='  ', wc_rev=rev)})
-    expected_disk.add({
-      dest_name                : Item(),
-      dest_name + '/B'         : Item(),
-      dest_name + '/B/lambda'  : Item("This is the file 'lambda'.\n"),
-      dest_name + '/B/E'       : Item(),
-      dest_name + '/B/E/alpha' : Item("This is the file 'alpha'.\n"),
-      dest_name + '/B/E/beta'  : Item("This is the file 'beta'.\n"),
-      dest_name + '/B/F'       : Item(),
-      dest_name + '/mu'        : Item("This is the file 'mu'.\n"),
-      dest_name + '/C'         : Item(),
-      dest_name + '/D'         : Item(),
-      dest_name + '/D/gamma'   : Item("This is the file 'gamma'.\n"),
-      dest_name + '/D/G'       : Item(),
-      dest_name + '/D/G/pi'    : Item("This is the file 'pi'.\n"),
-      dest_name + '/D/G/rho'   : Item("This is the file 'rho'.\n"),
-      dest_name + '/D/G/tau'   : Item("This is the file 'tau'.\n"),
-      dest_name + '/D/H'       : Item(),
-      dest_name + '/D/H/chi'   : Item("This is the file 'chi'.\n"),
-      dest_name + '/D/H/omega' : Item("This is the file 'omega'.\n"),
-      dest_name + '/D/H/psi'   : Item("This is the file 'psi'.\n"),
-      })
+      [ "A         " + sbox.ospath(path_join(dest_name, p)) + "\n"
+        for p in A_paths ])
+    expected_status.add(
+      { path_join(dest_name, p) : Item(status='  ', wc_rev=rev)
+        for p in A_paths })
+    expected_disk.add(
+      { path_join(dest_name, p) : greek_file_item(p)
+        for p in A_paths })
 
     # Make a branch A_COPY to merge into.
     actions.run_and_verify_svn(expected, [], 'copy',

Propchange: 
subversion/branches/addremove/subversion/tests/cmdline/svntest/mergetrees.py
            ('svn:executable' removed)

Modified: 
subversion/branches/addremove/subversion/tests/cmdline/svntest/sandbox.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svntest/sandbox.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/svntest/sandbox.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/svntest/sandbox.py 
Sat May 23 14:16:56 2020
@@ -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/addremove/subversion/tests/cmdline/svntest/testcase.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svntest/testcase.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/svntest/testcase.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/svntest/testcase.py 
Sat May 23 14:16:56 2020
@@ -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/addremove/subversion/tests/cmdline/svntest/tree.py
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svntest/tree.py?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/tests/cmdline/svntest/tree.py 
(original)
+++ subversion/branches/addremove/subversion/tests/cmdline/svntest/tree.py Sat 
May 23 14:16:56 2020
@@ -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:


Reply via email to