You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2015/11/30 11:24:23 UTC

svn commit: r1717223 [46/50] - in /subversion/branches/ra-git: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ contrib/hook-scripts/ notes/ notes/api-errata/1.9/ notes/move-tracking/ subversion/ subversion/bindings/ctypes-python/...

Modified: subversion/branches/ra-git/subversion/tests/cmdline/prop_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/prop_tests.py?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/prop_tests.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/prop_tests.py Mon Nov 30 10:24:16 2015
@@ -2666,13 +2666,37 @@ def xml_unsafe_author2(sbox):
   else:
     expected_author = 'foo\bbar'
 
-  expected_output = svntest.verify.UnorderedOutput([
-    '      1 %-8s              Jan 01  2000 ./\n' % expected_author,
-    '      1 %-8s              Jan 01  2000 A/\n' % expected_author,
-    '      1 %-8s           25 Jan 01  2000 iota\n' % expected_author
-  ])
+  # Use svn ls in --xml mode to test locale independent output.
+  expected_output = [
+    '<?xml version="1.0" encoding="UTF-8"?>\n',
+    '<lists>\n',
+    '<list\n',
+    '   path="%s">\n' % sbox.repo_url,
+    '<entry\n',
+    '   kind="dir">\n',
+    '<name>A</name>\n',
+    '<commit\n',
+    '   revision="1">\n',
+    '<author>%s</author>\n' % expected_author,
+    '<date>2000-01-01T12:00:00.000000Z</date>\n',
+    '</commit>\n',
+    '</entry>\n',
+    '<entry\n',
+    '   kind="file">\n',
+    '<name>iota</name>\n',
+    '<size>25</size>\n',
+    '<commit\n',
+    '   revision="1">\n',
+    '<author>%s</author>\n' % expected_author,
+    '<date>2000-01-01T12:00:00.000000Z</date>\n',
+    '</commit>\n',
+    '</entry>\n',
+    '</list>\n',
+    '</lists>\n'
+    ]
+
   svntest.actions.run_and_verify_svn(expected_output, [],
-                                     'ls', '-v', repo_url)
+                                     'ls', '--xml', repo_url)
 
   expected_info = [{
       'Repository Root' : sbox.repo_url,
@@ -2716,11 +2740,8 @@ def dir_prop_conflict_details(sbox):
                                         None,
                                         expected_status,
                                         check_props=True)
-
-  # The conflict properties file line was shown for previous versions, but the
-  # conflict source urls are new since 1.8.
   expected_info = {
-    'Conflict Properties File' : re.escape(sbox.ospath('A/dir_conflicts.prej')),
+    'Conflicted Properties' : 'my-prop',
     'Conflict Details': re.escape('incoming dir edit upon update'
                                            + ' Source  left: (dir) ^/A@1'
                                            + ' Source right: (dir) ^/A@2')
@@ -2783,6 +2804,31 @@ def wc_propop_on_url(sbox):
                                      'pg', 'my:Q', '-r', 'PREV',
                                      sbox.repo_url)
 
+def prop_conflict_root(sbox):
+  """property conflict on wc root"""
+
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  sbox.simple_propset('propname', 'propval1', '')
+  sbox.simple_commit()
+  sbox.simple_propset('propname', 'propval2', '')
+  sbox.simple_commit()
+  sbox.simple_update(revision=2)
+  sbox.simple_propset('propname', 'propvalconflict', '')
+
+  expected_output = svntest.wc.State(wc_dir, {
+    '' : Item(status=' C'),
+  })
+  expected_disk = svntest.main.greek_state.copy()
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 3)
+  expected_status.tweak('', status=' C')
+  extra_files = ['dir_conflicts.prej']
+  svntest.actions.run_and_verify_update(wc_dir,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status,
+                                        extra_files=extra_files)
 
 ########################################################################
 # Run the tests
@@ -2834,6 +2880,7 @@ test_list = [ None,
               dir_prop_conflict_details,
               iprops_list_abspath,
               wc_propop_on_url,
+              prop_conflict_root,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/ra-git/subversion/tests/cmdline/revert_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/revert_tests.py?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/revert_tests.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/revert_tests.py Mon Nov 30 10:24:16 2015
@@ -1630,7 +1630,13 @@ def revert_obstructing_wc(sbox):
   svntest.actions.run_and_verify_svn("Skipped '.*A' -- .*obstruct.*", [],
                                      'revert', '-R', wc_dir)
 
+def revert_moved_dir_partial(sbox):
+  "partial revert moved_dir"
 
+  sbox.build(read_only = True)
+
+  sbox.simple_move('A', 'A_')
+  svntest.actions.run_and_verify_svn(None, [], 'revert', sbox.ospath('A'))
 
 
 ########################################################################
@@ -1673,6 +1679,7 @@ test_list = [ None,
               revert_with_unversioned_targets,
               revert_nonexistent,
               revert_obstructing_wc,
+              revert_moved_dir_partial,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/ra-git/subversion/tests/cmdline/stat_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/stat_tests.py?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/stat_tests.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/stat_tests.py Mon Nov 30 10:24:16 2015
@@ -1598,44 +1598,81 @@ def status_dash_u_deleted_directories(sb
 
   # check status -u of B
   expected = svntest.verify.UnorderedOutput(
-         ["D                1   %s\n" % "B",
-          "D                1   %s\n" % os.path.join("B", "lambda"),
-          "D                1   %s\n" % os.path.join("B", "E"),
-          "D                1   %s\n" % os.path.join("B", "E", "alpha"),
-          "D                1   %s\n" % os.path.join("B", "E", "beta"),
-          "D                1   %s\n" % os.path.join("B", "F"),
+         ["D                1        1 jrandom      %s\n" % \
+                                        "B",
+          "D                1        1 jrandom      %s\n" % \
+                                        os.path.join("B", "lambda"),
+          "D                1        1 jrandom      %s\n" % \
+                                        os.path.join("B", "E"),
+          "D                1        1 jrandom      %s\n" % \
+                                        os.path.join("B", "E", "alpha"),
+          "D                1        1 jrandom      %s\n" % \
+                                        os.path.join("B", "E", "beta"),
+          "D                1        1 jrandom      %s\n" % 
+          os.path.join("B", "F"),
           "Status against revision:      1\n" ])
   svntest.actions.run_and_verify_svn(expected,
                                      [],
+                                     "status", "-u", "-v", "B")
+
+  expected = \
+         ["D                1   %s\n" % "B",
+          "Status against revision:      1\n" ]
+  svntest.actions.run_and_verify_svn(expected,
+                                     [],
                                      "status", "-u", "B")
 
+
   # again, but now from inside B, should give the same output
   if not os.path.exists('B'):
     os.mkdir('B')
   os.chdir("B")
   expected = svntest.verify.UnorderedOutput(
-         ["D                1   %s\n" % ".",
-          "D                1   %s\n" % "lambda",
-          "D                1   %s\n" % "E",
-          "D                1   %s\n" % os.path.join("E", "alpha"),
-          "D                1   %s\n" % os.path.join("E", "beta"),
-          "D                1   %s\n" % "F",
+         ["D                1        1 jrandom      %s\n" % \
+                                        ".",
+          "D                1        1 jrandom      %s\n" % \
+                                        "lambda",
+          "D                1        1 jrandom      %s\n" % \
+                                        "E",
+          "D                1        1 jrandom      %s\n" % \
+                                        os.path.join("E", "alpha"),
+          "D                1        1 jrandom      %s\n" % \
+                                        os.path.join("E", "beta"),
+          "D                1        1 jrandom      %s\n" % \
+                                        "F",
           "Status against revision:      1\n" ])
   svntest.actions.run_and_verify_svn(expected,
                                      [],
+                                     "status", "-u", "-v", ".")
+
+  expected = \
+         ["D                1   %s\n" % ".",
+          "Status against revision:      1\n" ]
+  svntest.actions.run_and_verify_svn(expected,
+                                     [],
                                      "status", "-u", ".")
 
   # check status -u of B/E
   expected = svntest.verify.UnorderedOutput(
-         ["D                1   %s\n" % os.path.join("B", "E"),
-          "D                1   %s\n" % os.path.join("B", "E", "alpha"),
-          "D                1   %s\n" % os.path.join("B", "E", "beta"),
+         ["D                1        1 jrandom      %s\n" % \
+                                        os.path.join("B", "E"),
+          "D                1        1 jrandom      %s\n" % \
+                                        os.path.join("B", "E", "alpha"),
+          "D                1        1 jrandom      %s\n" % \
+                                        os.path.join("B", "E", "beta"),
           "Status against revision:      1\n" ])
 
   os.chdir(was_cwd)
   os.chdir(A_path)
   svntest.actions.run_and_verify_svn(expected,
                                      [],
+                                     "status", "-u", "-v",
+                                     os.path.join("B", "E"))
+
+
+  expected = [ "Status against revision:      1\n" ]
+  svntest.actions.run_and_verify_svn(expected,
+                                     [],
                                      "status", "-u",
                                      os.path.join("B", "E"))
 

Modified: subversion/branches/ra-git/subversion/tests/cmdline/svnadmin_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/svnadmin_tests.py?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/svnadmin_tests.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/svnadmin_tests.py Mon Nov 30 10:24:16 2015
@@ -147,7 +147,7 @@ def check_hotcopy_fsfs_fsx(src, dst):
         # the hotcopy destination (i.e. a fresh cache generation)
         if src_file == 'revprop-generation':
           f2 = open(dst_path, 'r')
-          revprop_gen = int(f2.read().strip().split()[1])
+          revprop_gen = int(f2.read().strip())
           if revprop_gen != 0:
               raise svntest.Failure("Hotcopy destination has non-zero " +
                                     "revprop generation")
@@ -249,6 +249,18 @@ def patch_format(repo_dir, shard_size):
   os.chmod(format_path, 0666)
   open(format_path, 'wb').write(new_contents)
 
+def is_sharded(repo_dir):
+  """Return whether the FSFS repository REPO_DIR is sharded."""
+
+  format_path = os.path.join(repo_dir, "db", "format")
+  contents = open(format_path, 'rb').read()
+
+  for line in contents.split("\n"):
+    if line.startswith("layout sharded"):
+      return True
+
+  return False
+
 def load_and_verify_dumpstream(sbox, expected_stdout, expected_stderr,
                                revs, check_props, dump, *varargs):
   """Load the array of lines passed in DUMP into the current tests'
@@ -589,8 +601,8 @@ def dump_quiet(sbox):
 
   sbox.build(create_wc = False)
 
-  exit_code, output, errput = svntest.main.run_svnadmin("dump", sbox.repo_dir,
-                                                        '--quiet')
+  exit_code, dump, errput = svntest.main.run_svnadmin("dump", sbox.repo_dir,
+                                                      '--quiet')
   svntest.verify.compare_and_display_lines(
     "Output of 'svnadmin dump --quiet' is unexpected.",
     'STDERR', [], errput)
@@ -792,7 +804,7 @@ def verify_incremental_fsfs(sbox):
   # the listing itself is valid.
   r2 = fsfs_file(sbox.repo_dir, 'revs', '2')
   if r2.endswith('pack'):
-    raise svntest.Skip
+    raise svntest.Skip('Test doesn\'t handle packed revisions')
 
   fp = open(r2, 'wb')
   fp.write("""id: 0-2.0.r2/0
@@ -1215,7 +1227,7 @@ def fsfs_recover_handle_missing_revs_or_
 
 #----------------------------------------------------------------------
 
-@Skip(svntest.main.tests_use_prepacakaged_repository)
+@Skip(svntest.main.tests_use_prepackaged_repository)
 def create_in_repo_subdir(sbox):
   "'svnadmin create /path/to/repo/subdir'"
 
@@ -1371,21 +1383,21 @@ def dont_drop_valid_mergeinfo_during_inc
   # PART 2: Load a a series of incremental dumps to an empty repository.
   #
   # Incrementally dump the repository into three dump files:
-  dump_file_r1_10 = svntest.main.temp_dir + "-r1-10.dump"
+  dump_file_r1_10 = sbox.get_tempname("r1-10-dump")
   exit_code, output, errput = svntest.main.run_svnadmin(
     'dump', sbox.repo_dir, '-r1:10')
   dump_fp = open(dump_file_r1_10, 'wb')
   dump_fp.writelines(output)
   dump_fp.close()
 
-  dump_file_r11_13 = svntest.main.temp_dir + "-r11-13.dump"
+  dump_file_r11_13 = sbox.get_tempname("r11-13-dump")
   exit_code, output, errput = svntest.main.run_svnadmin(
     'dump', sbox.repo_dir, '--incremental', '-r11:13')
   dump_fp = open(dump_file_r11_13, 'wb')
   dump_fp.writelines(output)
   dump_fp.close()
 
-  dump_file_r14_15 = svntest.main.temp_dir + "-r14-15.dump"
+  dump_file_r14_15 = sbox.get_tempname("r14-15-dump")
   exit_code, output, errput = svntest.main.run_svnadmin(
     'dump', sbox.repo_dir, '--incremental', '-r14:15')
   dump_fp = open(dump_file_r14_15, 'wb')
@@ -2000,6 +2012,14 @@ def mergeinfo_race(sbox):
   "concurrent mergeinfo commits invalidate pred-count"
   sbox.build()
 
+  # This test exercises two commit-time race condition bugs:
+  #
+  # (a) metadata corruption when concurrent commits change svn:mergeinfo (issue #4129)
+  # (b) false positive SVN_ERR_FS_CONFLICT error with httpv1 commits
+  #     https://mail-archives.apache.org/mod_mbox/subversion-dev/201507.mbox/%3C20150731234536.GA5395@tarsus.local2%3E
+  #
+  # Both bugs are timing-dependent and might not reproduce 100% of the time.
+
   wc_dir = sbox.wc_dir
   wc2_dir = sbox.add_wc_path('2')
 
@@ -2046,6 +2066,10 @@ def recover_old_empty(sbox):
 def verify_keep_going(sbox):
   "svnadmin verify --keep-going test"
 
+  # No support for modifying pack files
+  if svntest.main.options.fsfs_packing:
+    raise svntest.Skip('fsfs packing set')
+
   sbox.build(create_wc = False)
   repo_url = sbox.repo_url
   B_url = sbox.repo_url + '/B'
@@ -2070,20 +2094,28 @@ def verify_keep_going(sbox):
 
   exp_out = svntest.verify.RegexListOutput([".*Verified revision 0.",
                                             ".*Verified revision 1.",
-                                            ".*Error verifying revision 2.",
-                                            ".*Error verifying revision 3.",
                                             ".*",
                                             ".*Summary.*",
                                             ".*r2: E160004:.*",
                                             ".*r2: E160004:.*",
                                             ".*r3: E160004:.*",
                                             ".*r3: E160004:.*"])
-  exp_err = svntest.verify.RegexListOutput(["svnadmin: E160004:.*",
-                                            "svnadmin: E165011:.*"], False)
 
   if (svntest.main.fs_has_rep_sharing()):
     exp_out.insert(0, ".*Verifying.*metadata.*")
 
+  exp_err = svntest.verify.RegexListOutput([".*Error verifying revision 2.",
+                                            "svnadmin: E160004:.*",
+                                            "svnadmin: E160004:.*",
+                                            ".*Error verifying revision 3.",
+                                            "svnadmin: E160004:.*",
+                                            "svnadmin: E160004:.*",
+                                            "svnadmin: E205012:.*"], False)
+
+  if (svntest.main.is_fs_log_addressing()):
+    exp_err.insert(0, ".*Error verifying repository metadata.")
+    exp_err.insert(1, "svnadmin: E160004:.*")
+
   if svntest.verify.verify_outputs("Unexpected error while running 'svnadmin verify'.",
                                    output, errput, exp_out, exp_err):
     raise svntest.Failure
@@ -2095,11 +2127,19 @@ def verify_keep_going(sbox):
     exp_out = svntest.verify.RegexListOutput([".*Verifying metadata at revision 0"])
   else:
     exp_out = svntest.verify.RegexListOutput([".*Verified revision 0.",
-                                             ".*Verified revision 1.",
-                                             ".*Error verifying revision 2."])
+                                              ".*Verified revision 1."])
     if (svntest.main.fs_has_rep_sharing()):
       exp_out.insert(0, ".*Verifying repository metadata.*")
 
+  if (svntest.main.is_fs_log_addressing()):
+    exp_err = svntest.verify.RegexListOutput([
+                                     ".*Error verifying repository metadata.",
+                                     "svnadmin: E160004:.*"], False)
+  else:
+    exp_err = svntest.verify.RegexListOutput([".*Error verifying revision 2.",
+                                              "svnadmin: E160004:.*",
+                                              "svnadmin: E160004:.*"], False)
+
   if svntest.verify.verify_outputs("Unexpected error while running 'svnadmin verify'.",
                                    output, errput, exp_out, exp_err):
     raise svntest.Failure
@@ -2109,17 +2149,85 @@ def verify_keep_going(sbox):
                                                         "--quiet",
                                                         sbox.repo_dir)
 
+  if (svntest.main.is_fs_log_addressing()):
+    exp_err = svntest.verify.RegexListOutput([
+                                      ".*Error verifying repository metadata.",
+                                      "svnadmin: E160004:.*"], False)
+  else:
+    exp_err = svntest.verify.RegexListOutput([".*Error verifying revision 2.",
+                                              "svnadmin: E160004:.*",
+                                              "svnadmin: E160004:.*"], False)
+
   if svntest.verify.verify_outputs("Output of 'svnadmin verify' is unexpected.",
-                                   None, errput, None, "svnadmin: E165011:.*"):
+                                   None, errput, None, exp_err):
     raise svntest.Failure
 
   # Don't leave a corrupt repository
   svntest.main.safe_rmtree(sbox.repo_dir, True)
 
+
+@SkipUnless(svntest.main.is_fs_type_fsfs)
+def verify_keep_going_quiet(sbox):
+  "svnadmin verify --keep-going --quiet test"
+
+  # No support for modifying pack files
+  if svntest.main.options.fsfs_packing:
+    raise svntest.Skip('fsfs packing set')
+
+  sbox.build(create_wc = False)
+  repo_url = sbox.repo_url
+  B_url = sbox.repo_url + '/B'
+  C_url = sbox.repo_url + '/C'
+
+  # Create A/B/E/bravo in r2.
+  svntest.actions.run_and_verify_svn(None, [],
+                                     'mkdir', '-m', 'log_msg',
+                                     B_url)
+
+  svntest.actions.run_and_verify_svn(None, [],
+                                     'mkdir', '-m', 'log_msg',
+                                     C_url)
+
+  r2 = fsfs_file(sbox.repo_dir, 'revs', '2')
+  fp = open(r2, 'r+b')
+  fp.write("""inserting junk to corrupt the rev""")
+  fp.close()
+
+  exit_code, output, errput = svntest.main.run_svnadmin("verify",
+                                                        "--keep-going",
+                                                        "--quiet",
+                                                        sbox.repo_dir)
+
+  exp_err = svntest.verify.RegexListOutput([".*Error verifying revision 2.",
+                                            "svnadmin: E160004:.*",
+                                            "svnadmin: E160004:.*",
+                                            ".*Error verifying revision 3.",
+                                            "svnadmin: E160004:.*",
+                                            "svnadmin: E160004:.*",
+                                            "svnadmin: E205012:.*"], False)
+
+  # Insert another expected error from checksum verification
+  if (svntest.main.is_fs_log_addressing()):
+    exp_err.insert(0, ".*Error verifying repository metadata.")
+    exp_err.insert(1, "svnadmin: E160004:.*")
+
+  if svntest.verify.verify_outputs(
+          "Unexpected error while running 'svnadmin verify'.",
+          output, errput, None, exp_err):
+    raise svntest.Failure
+
+  # Don't leave a corrupt repository
+  svntest.main.safe_rmtree(sbox.repo_dir, True)
+
+
 @SkipUnless(svntest.main.is_fs_type_fsfs)
 def verify_invalid_path_changes(sbox):
   "detect invalid changed path list entries"
 
+  # No support for modifying pack files
+  if svntest.main.options.fsfs_packing:
+    raise svntest.Skip('fsfs packing set')
+
   sbox.build(create_wc = False)
   repo_url = sbox.repo_url
 
@@ -2180,23 +2288,15 @@ def verify_invalid_path_changes(sbox):
 
   exp_out = svntest.verify.RegexListOutput([".*Verified revision 0.",
                                            ".*Verified revision 1.",
-                                           ".*Error verifying revision 2.",
                                            ".*Verified revision 3.",
-                                           ".*Error verifying revision 4.",
                                            ".*Verified revision 5.",
-                                           ".*Error verifying revision 6.",
                                            ".*Verified revision 7.",
                                            ".*Verified revision 8.",
                                            ".*Verified revision 9.",
-                                           ".*Error verifying revision 10.",
                                            ".*Verified revision 11.",
-                                           ".*Error verifying revision 12.",
                                            ".*Verified revision 13.",
-                                           ".*Error verifying revision 14.",
                                            ".*Verified revision 15.",
-                                           ".*Error verifying revision 16.",
                                            ".*Verified revision 17.",
-                                           ".*Error verifying revision 18.",
                                            ".*Verified revision 19.",
                                            ".*",
                                            ".*Summary.*",
@@ -2217,12 +2317,36 @@ def verify_invalid_path_changes(sbox):
                                            ".*r18: E160013:.*"])
   if (svntest.main.fs_has_rep_sharing()):
     exp_out.insert(0, ".*Verifying.*metadata.*")
-    if svntest.main.is_fs_log_addressing():
-      exp_out.insert(1, ".*Verifying.*metadata.*")
+  if svntest.main.options.fsfs_sharding is not None:
+    for x in range(0, 19 / svntest.main.options.fsfs_sharding):
+      exp_out.insert(0, ".*Verifying.*metadata.*")
+  if svntest.main.is_fs_log_addressing():
+    exp_out.insert(0, ".*Verifying.*metadata.*")
 
-  exp_err = svntest.verify.RegexListOutput(["svnadmin: E160020:.*",
+  exp_err = svntest.verify.RegexListOutput([".*Error verifying revision 2.",
+                                            "svnadmin: E160020:.*",
+                                            "svnadmin: E160020:.*",
+                                            ".*Error verifying revision 4.",
+                                            "svnadmin: E160013:.*",
+                                            ".*Error verifying revision 6.",
+                                            "svnadmin: E160013:.*",
+                                            "svnadmin: E160013:.*",
+                                            ".*Error verifying revision 10.",
+                                            "svnadmin: E160013:.*",
+                                            "svnadmin: E160013:.*",
+                                            ".*Error verifying revision 12.",
+                                            "svnadmin: E145001:.*",
+                                            "svnadmin: E145001:.*",
+                                            ".*Error verifying revision 14.",
+                                            "svnadmin: E160013:.*",
+                                            "svnadmin: E160013:.*",
+                                            ".*Error verifying revision 16.",
                                             "svnadmin: E145001:.*",
-                                            "svnadmin: E160013:.*"], False)
+                                            "svnadmin: E145001:.*",
+                                            ".*Error verifying revision 18.",
+                                            "svnadmin: E160013:.*",
+                                            "svnadmin: E160013:.*",
+                                            "svnadmin: E205012:.*"], False)
 
 
   if svntest.verify.verify_outputs("Unexpected error while running 'svnadmin verify'.",
@@ -2233,15 +2357,19 @@ def verify_invalid_path_changes(sbox):
                                                         sbox.repo_dir)
 
   exp_out = svntest.verify.RegexListOutput([".*Verified revision 0.",
-                                            ".*Verified revision 1.",
-                                            ".*Error verifying revision 2."])
-  exp_err = svntest.verify.RegexListOutput(["svnadmin: E160020:.*",
-                                            "svnadmin: E165011:.*"], False)
+                                            ".*Verified revision 1."])
+  exp_err = svntest.verify.RegexListOutput([".*Error verifying revision 2.",
+                                            "svnadmin: E160020:.*",
+                                            "svnadmin: E160020:.*"], False)
 
   if (svntest.main.fs_has_rep_sharing()):
     exp_out.insert(0, ".*Verifying.*metadata.*")
-    if svntest.main.is_fs_log_addressing():
-      exp_out.insert(1, ".*Verifying.*metadata.*")
+  if svntest.main.options.fsfs_sharding is not None:
+    for x in range(0, 19 / svntest.main.options.fsfs_sharding):
+      exp_out.insert(0, ".*Verifying.*metadata.*")
+  if svntest.main.is_fs_log_addressing():
+    exp_out.insert(0, ".*Verifying.*metadata.*")
+
   if svntest.verify.verify_outputs("Unexpected error while running 'svnadmin verify'.",
                                    output, errput, exp_out, exp_err):
     raise svntest.Failure
@@ -2251,8 +2379,13 @@ def verify_invalid_path_changes(sbox):
                                                         "--quiet",
                                                         sbox.repo_dir)
 
+  exp_out = []
+  exp_err = svntest.verify.RegexListOutput([".*Error verifying revision 2.",
+                                            "svnadmin: E160020:.*",
+                                            "svnadmin: E160020:.*"], False)
+
   if svntest.verify.verify_outputs("Output of 'svnadmin verify' is unexpected.",
-                                   None, errput, None, "svnadmin: E165011:.*"):
+                                   output, errput, exp_out, exp_err):
     raise svntest.Failure
 
   # Don't leave a corrupt repository
@@ -2292,6 +2425,10 @@ def verify_denormalized_names(sbox):
   if (svntest.main.fs_has_rep_sharing()):
     expected_output_regex_list.insert(0, ".*Verifying repository metadata.*")
 
+  if svntest.main.options.fsfs_sharding is not None:
+    for x in range(0, 7 / svntest.main.options.fsfs_sharding):
+      expected_output_regex_list.insert(0, ".*Verifying.*metadata.*")
+
   if svntest.main.is_fs_log_addressing():
     expected_output_regex_list.insert(0, ".* Verifying metadata at revision 0.*")
 
@@ -2606,7 +2743,10 @@ def verify_quickly(sbox):
   "verify quickly using metadata"
 
   sbox.build(create_wc = False)
-  rev_file = open(fsfs_file(sbox.repo_dir, 'revs', '1'), 'r+b')
+  if svntest.main.is_fs_type_fsfs():
+    rev_file = open(fsfs_file(sbox.repo_dir, 'revs', '1'), 'r+b')
+  else:
+    rev_file = open(fsfs_file(sbox.repo_dir, 'revs', 'r1'), 'r+b')
 
   # set new contents
   rev_file.seek(8)
@@ -2621,8 +2761,7 @@ def verify_quickly(sbox):
   # resulting in different progress output
   if svntest.main.is_fs_log_addressing():
     exp_out = svntest.verify.RegexListOutput([])
-    exp_err = svntest.verify.RegexListOutput(["svnadmin: E160004:.*",
-                                              "svnadmin: E165011:.*"], False)
+    exp_err = svntest.verify.RegexListOutput(["svnadmin: E160004:.*"], False)
   else:
     exp_out = svntest.verify.RegexListOutput([])
     exp_err = svntest.verify.RegexListOutput([])
@@ -2646,7 +2785,7 @@ def fsfs_hotcopy_progress(sbox):
   # and incremental scenarios.  The progress output can be affected by
   # the --fsfs-packing option, so skip the test if that is the case.
   if svntest.main.options.fsfs_packing:
-    raise svntest.Skip
+    raise svntest.Skip('fsfs packing set')
 
   # Create an empty repository, configure three files per shard.
   sbox.build(create_wc=False, empty=True)
@@ -2760,7 +2899,7 @@ def fsfs_hotcopy_progress_with_revprop_c
   # The progress output can be affected by the --fsfs-packing
   # option, so skip the test if that is the case.
   if svntest.main.options.fsfs_packing:
-    raise svntest.Skip
+    raise svntest.Skip('fsfs packing set')
 
   # Create an empty repository, commit several revisions and hotcopy it.
   sbox.build(create_wc=False, empty=True)
@@ -2954,6 +3093,206 @@ def load_no_svndate_r0(sbox):
                                          'proplist', '--revprop', '-r0',
                                          sbox.repo_dir)
 
+# This is only supported for FSFS
+# The port to FSX is still pending, BDB won't support it.
+@SkipUnless(svntest.main.is_fs_type_fsfs)
+def hotcopy_read_only(sbox):
+  "'svnadmin hotcopy' a read-only source repository"
+  sbox.build()
+  svntest.main.chmod_tree(sbox.repo_dir, 0, 0222)
+
+  backup_dir, backup_url = sbox.add_repo_path('backup')
+  exit_code, output, errput = svntest.main.run_svnadmin("hotcopy",
+                                                        sbox.repo_dir,
+                                                        backup_dir)
+
+  # r/o repos are hard to clean up. Make it writable again.
+  svntest.main.chmod_tree(sbox.repo_dir, 0222, 0222)
+  if errput:
+    logger.warn("Error: hotcopy failed")
+    raise SVNUnexpectedStderr(errput)
+
+@SkipUnless(svntest.main.is_fs_type_fsfs)
+@SkipUnless(svntest.main.fs_has_pack)
+def fsfs_pack_non_sharded(sbox):
+  "'svnadmin pack' on a non-sharded repository"
+
+  # Configure two files per shard to trigger packing.
+  sbox.build(create_wc = False,
+             minor_version = min(svntest.main.options.server_minor_version,3))
+
+  # Skip for pre-cooked sharded repositories
+  if is_sharded(sbox.repo_dir):
+    raise svntest.Skip('sharded pre-cooked repository')
+
+  svntest.actions.run_and_verify_svnadmin(
+      None, [], "upgrade", sbox.repo_dir)
+  svntest.actions.run_and_verify_svnadmin(
+      ['svnadmin: Warning - this repository is not sharded. Packing has no effect.\n'],
+      [], "pack", sbox.repo_dir)
+
+def load_revprops(sbox):
+  "svnadmin load-revprops"
+
+  sbox.build(create_wc=False, empty=True)
+
+  dump_path = os.path.join(os.path.dirname(sys.argv[0]),
+                                           'svnadmin_tests_data',
+                                           'skeleton_repos.dump')
+  dump_contents = open(dump_path, 'rb').readlines()
+  load_and_verify_dumpstream(sbox, None, [], None, False, dump_contents)
+
+  svntest.actions.run_and_verify_svnlook(['Initial setup...\n', '\n'],
+                                         [], 'log', '-r1', sbox.repo_dir)
+
+  # After loading the dump, amend one of the log message in the repository.
+  input_file = sbox.get_tempname()
+  svntest.main.file_write(input_file, 'Modified log message...\n')
+
+  svntest.actions.run_and_verify_svnadmin([], [], 'setlog', '--bypass-hooks',
+                                          '-r1', sbox.repo_dir, input_file)
+  svntest.actions.run_and_verify_svnlook(['Modified log message...\n', '\n'],
+                                         [], 'log', '-r1', sbox.repo_dir)
+
+  # Load the same dump, but with 'svnadmin load-revprops'.  Doing so should
+  # restore the log message to its original state.
+  svntest.main.run_command_stdin(svntest.main.svnadmin_binary, None, 0,
+                                 True, dump_contents, 'load-revprops',
+                                 sbox.repo_dir)
+
+  svntest.actions.run_and_verify_svnlook(['Initial setup...\n', '\n'],
+                                         [], 'log', '-r1', sbox.repo_dir)
+
+def dump_revprops(sbox):
+  "svnadmin dump-revprops"
+
+  sbox.build(create_wc=False)
+
+  # Dump revprops only.
+  exit_code, dump_contents, errput = \
+    svntest.actions.run_and_verify_svnadmin(None, [], "dump-revprops", "-q",
+                                            sbox.repo_dir)
+
+  # We expect the dump to contain no path changes
+  for line in dump_contents:
+    if line.find("Node-path: ") > -1:
+      logger.warn("Error: path change found in revprops-only dump.")
+      raise svntest.Failure
+
+  # Remember the current log message for r1
+  exit_code, log_msg, errput = \
+    svntest.actions.run_and_verify_svnlook(None, [], 'log', '-r1',
+                                           sbox.repo_dir)
+
+  # Now, change the log message in the repository.
+  input_file = sbox.get_tempname()
+  svntest.main.file_write(input_file, 'Modified log message...\n')
+
+  svntest.actions.run_and_verify_svnadmin([], [], 'setlog', '--bypass-hooks',
+                                          '-r1', sbox.repo_dir, input_file)
+  svntest.actions.run_and_verify_svnlook(['Modified log message...\n', '\n'],
+                                         [], 'log', '-r1', sbox.repo_dir)
+
+  # Load the same dump with 'svnadmin load-revprops'.  Doing so should
+  # restore the log message to its original state.
+  svntest.main.run_command_stdin(svntest.main.svnadmin_binary, None, 0,
+                                 True, dump_contents, 'load-revprops',
+                                 sbox.repo_dir)
+
+  svntest.actions.run_and_verify_svnlook(log_msg, [], 'log', '-r1',
+                                         sbox.repo_dir)
+
+@XFail(svntest.main.is_fs_type_fsx)
+@Issue(4598)
+def dump_no_op_change(sbox):
+  "svnadmin dump with no-op changes"
+
+  sbox.build(create_wc=False, empty=True)
+  empty_file = sbox.get_tempname()
+  svntest.main.file_write(empty_file, '')
+
+  svntest.actions.run_and_verify_svnmucc(None, [],
+                                         '-U', sbox.repo_url,
+                                         '-m', svntest.main.make_log_msg(),
+                                         'put', empty_file, 'bar')
+  # Commit a no-op change.
+  svntest.actions.run_and_verify_svnmucc(None, [],
+                                         '-U', sbox.repo_url,
+                                         '-m', svntest.main.make_log_msg(),
+                                         'put', empty_file, 'bar')
+  # Dump and load the repository.
+  _, dump, _ = svntest.actions.run_and_verify_svnadmin(None, [],
+                                                       'dump', '-q',
+                                                       sbox.repo_dir)
+  sbox2 = sbox.clone_dependent()
+  sbox2.build(create_wc=False, empty=True)
+  load_and_verify_dumpstream(sbox2, None, [], None, False, dump)
+
+  # We expect svn log -v to yield identical results for both original and
+  # reconstructed repositories.  This used to fail as described in the
+  # Issue 4598 (https://issues.apache.org/jira/browse/SVN-4598), at least
+  # around r1706415.
+  #
+  # Test svn log -v for r2:
+  _, expected, _ = svntest.actions.run_and_verify_svn(None, [], 'log', '-v',
+                                                      '-r2', sbox.repo_url)
+  found = [True for line in expected if line.find('M /bar\n') != -1]
+  if not found:
+    raise svntest.Failure
+  svntest.actions.run_and_verify_svn(expected, [], 'log',  '-v',
+                                     '-r2', sbox2.repo_url)
+  # Test svn log -v for /bar:
+  _, expected, _ = svntest.actions.run_and_verify_svn(None, [], 'log', '-v',
+                                                      sbox.repo_url + '/bar')
+  found = [True for line in expected if line.find('M /bar\n') != -1]
+  if not found:
+    raise svntest.Failure
+  svntest.actions.run_and_verify_svn(expected, [], 'log',  '-v',
+                                     sbox2.repo_url + '/bar')
+
+@XFail()
+def dump_no_op_prop_change(sbox):
+  "svnadmin dump with no-op property change"
+
+  sbox.build(create_wc=False, empty=True)
+  empty_file = sbox.get_tempname()
+  svntest.main.file_write(empty_file, '')
+
+  svntest.actions.run_and_verify_svnmucc(None, [],
+                                         '-U', sbox.repo_url,
+                                         '-m', svntest.main.make_log_msg(),
+                                         'put', empty_file, 'bar',
+                                         'propset', 'pname', 'pval', 'bar')
+  # Commit a no-op property change.
+  svntest.actions.run_and_verify_svnmucc(None, [],
+                                         '-U', sbox.repo_url,
+                                         '-m', svntest.main.make_log_msg(),
+                                         'propset', 'pname', 'pval', 'bar')
+  # Dump and load the repository.
+  _, dump, _ = svntest.actions.run_and_verify_svnadmin(None, [],
+                                                       'dump', '-q',
+                                                       sbox.repo_dir)
+  sbox2 = sbox.clone_dependent()
+  sbox2.build(create_wc=False, empty=True)
+  load_and_verify_dumpstream(sbox2, None, [], None, False, dump)
+
+  # Test svn log -v for r2:
+  _, expected, _ = svntest.actions.run_and_verify_svn(None, [], 'log', '-v',
+                                                      '-r2', sbox.repo_url)
+  found = [True for line in expected if line.find('M /bar\n') != -1]
+  if not found:
+    raise svntest.Failure
+  svntest.actions.run_and_verify_svn(expected, [], 'log',  '-v',
+                                     '-r2', sbox2.repo_url)
+  # Test svn log -v for /bar:
+  _, expected, _ = svntest.actions.run_and_verify_svn(None, [], 'log', '-v',
+                                                      sbox.repo_url + '/bar')
+  found = [True for line in expected if line.find('M /bar\n') != -1]
+  if not found:
+    raise svntest.Failure
+  svntest.actions.run_and_verify_svn(expected, [], 'log',  '-v',
+                                     sbox2.repo_url + '/bar')
+
 ########################################################################
 # Run the tests
 
@@ -2992,6 +3331,7 @@ test_list = [ None,
               mergeinfo_race,
               recover_old_empty,
               verify_keep_going,
+              verify_keep_going_quiet,
               verify_invalid_path_changes,
               verify_denormalized_names,
               fsfs_recover_old_non_empty,
@@ -3009,6 +3349,12 @@ test_list = [ None,
               upgrade,
               load_txdelta,
               load_no_svndate_r0,
+              hotcopy_read_only,
+              fsfs_pack_non_sharded,
+              load_revprops,
+              dump_revprops,
+              dump_no_op_change,
+              dump_no_op_prop_change
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/ra-git/subversion/tests/cmdline/svnmucc_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/svnmucc_tests.py?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/svnmucc_tests.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/svnmucc_tests.py Mon Nov 30 10:24:16 2015
@@ -106,7 +106,9 @@ def basic_svnmucc(sbox):
 
   sbox.build()
   empty_file = sbox.ospath('empty')
+  file = sbox.ospath('file')
   svntest.main.file_append(empty_file, '')
+  svntest.main.file_append(file, 'file')
 
   # revision 2
   test_svnmucc(sbox.repo_url,
@@ -301,6 +303,14 @@ def basic_svnmucc(sbox):
                'propsetf', 'testprop', empty_file, 'foo/z.c',
                'propsetf', 'testprop', empty_file, 'foo/foo')
 
+  # revision 21
+  test_svnmucc(sbox.repo_url,
+               ['M /foo/z.c',
+                ], #---------
+               '-m', 'log msg',
+               'propset', 'testprop', 'false', 'foo/z.c',
+               'put', file, 'foo/z.c')
+
   # Expected missing revision error
   xtest_svnmucc(sbox.repo_url,
                 ["svnmucc: E200004: 'a' is not a revision"
@@ -453,6 +463,132 @@ rm A/B/C/Y
                                      'log', '-qvr3', repo_url)
 
 
+def prohibited_deletes_and_moves(sbox):
+  "test prohibited delete and move operations"
+
+  # These action sequences were allowed in 1.8.13, but are prohibited in 1.9.x
+  # and later.  Most of them probably indicate an inadvertent user mistake.
+  # See dev@, 2015-05-11, "Re: Issue 4579 / svnmucc fails to process certain
+  # deletes", <http://svn.haxx.se/dev/archive-2015-05/0038.shtml>
+
+  sbox.build(read_only = True)
+  svntest.main.file_write(sbox.ospath('file'), "New contents")
+
+  xtest_svnmucc(sbox.repo_url,
+                ["svnmucc: E200009: Can't delete node at 'iota'",
+                 ], #---------
+                '-m', 'r2: modify and delete /iota',
+                'put', sbox.ospath('file'), 'iota',
+                'rm', 'iota')
+
+  xtest_svnmucc(sbox.repo_url,
+                ["svnmucc: E200009: Can't delete node at 'iota'",
+                 ], #---------
+                '-m', 'r2: propset and delete /iota',
+                'propset', 'prop', 'val', 'iota',
+                'rm', 'iota')
+
+  xtest_svnmucc(sbox.repo_url,
+                ["svnmucc: E160013: Can't delete node at 'iota' as it does "
+                 "not exist",
+                 ], #---------
+                '-m', 'r2: delete and delete /iota',
+                'rm', 'iota',
+                'rm', 'iota')
+
+  # Subversion 1.8.13 used to move /iota without applying the text change.
+  xtest_svnmucc(sbox.repo_url,
+                ["svnmucc: E200009: Can't delete node at 'iota'",
+                 ], #---------
+                '-m', 'r2: modify and move /iota',
+                'put', sbox.ospath('file'), 'iota',
+                'mv', 'iota', 'iota2')
+
+  # Subversion 1.8.13 used to move /A without applying the inner remove.
+  xtest_svnmucc(sbox.repo_url,
+                ["svnmucc: E200009: Can't delete node at 'A'",
+                 ], #---------
+                '-m', 'r2: delete /A/B and move /A',
+                'rm', 'A/B',
+                'mv', 'A', 'A1')
+
+def svnmucc_type_errors(sbox):
+  "test type errors"
+
+  sbox.build(read_only=True)
+
+  sbox.simple_append('file', 'New contents')
+
+  xtest_svnmucc(sbox.repo_url,
+                ["svnmucc: E160016: Can't operate on 'B' "
+                "because 'A' is not a directory"],
+                '-m', '',
+                'put', sbox.ospath('file'), 'A',
+                'mkdir', 'A/B',
+                'propset', 'iota', 'iota', 'iota')
+
+  xtest_svnmucc(sbox.repo_url,
+                ["svnmucc: E200009: Can't delete node at 'A'"],
+                '-m', '',
+                'mkdir', 'A/Z',
+                'put', sbox.ospath('file'), 'A')
+
+  xtest_svnmucc(sbox.repo_url,
+                ["svnmucc: E160020: Path 'Z' already exists"],
+                '-m', '',
+                'mkdir', 'A/Z',
+                'put', sbox.ospath('file'), 'A/Z')
+
+def svnmucc_propset_and_put(sbox):
+  "propset and put"
+
+  sbox.build()
+
+  sbox.simple_append('file', 'New contents')
+
+  # First in the sane order: put, then propset
+  xtest_svnmucc(sbox.repo_url,
+                [],
+                '-m', '',
+                'put', sbox.ospath('file'), 't1',
+                'propset', 't1', 't1', 't1')
+
+  # And now in an impossible order: propset, then put
+  xtest_svnmucc(sbox.repo_url,
+                ["svnmucc: E200009: Can't set properties at not existing 't2'"],
+                '-m', '',
+                'propset', 't2', 't2', 't2',
+                'put', sbox.ospath('file'), 't2')
+
+  # And if the target already exists (dir)
+  xtest_svnmucc(sbox.repo_url,
+                ["svnmucc: E200009: Can't delete node at 'A'"],
+                '-m', '',
+                'propset', 'A', 'A', 'A',
+                'put', sbox.ospath('file'), 'A')
+
+  # And if the target already exists (file) # fixed in r1702467
+  xtest_svnmucc(sbox.repo_url,
+                [],
+                '-m', '',
+                'propset', 'iota', 'iota', 'iota',
+                'put', sbox.ospath('file'), 'iota')
+
+  # Put same file twice (non existing)
+  xtest_svnmucc(sbox.repo_url,
+                ["svnmucc: E160020: Path 't3' already exists"],
+                '-m', '',
+                'put', sbox.ospath('file'), 't3',
+                'put', sbox.ospath('file'), 't3')
+
+  # Put same file twice (existing)
+  xtest_svnmucc(sbox.repo_url,
+                ["svnmucc: E200009: Can't update file at 't1'"],
+                '-m', '',
+                'put', sbox.ospath('file'), 't1',
+                'put', sbox.ospath('file'), 't1')
+
+
 ######################################################################
 
 test_list = [ None,
@@ -462,6 +598,9 @@ test_list = [ None,
               too_many_log_messages,
               no_log_msg_non_interactive,
               nested_replaces,
+              prohibited_deletes_and_moves,
+              svnmucc_type_errors,
+              svnmucc_propset_and_put,
             ]
 
 if __name__ == '__main__':

Modified: subversion/branches/ra-git/subversion/tests/cmdline/svnrdump_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/svnrdump_tests.py?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/svnrdump_tests.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/svnrdump_tests.py Mon Nov 30 10:24:16 2015
@@ -541,7 +541,7 @@ def dont_drop_valid_mergeinfo_during_inc
   # PART 2: Load a series of incremental dumps to an empty repository.
   #
   # Incrementally dump the repository into three dump files:
-  dump_file_r1_10 = svntest.main.temp_dir + "-r1-10.dump"
+  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',
@@ -550,7 +550,7 @@ def dont_drop_valid_mergeinfo_during_inc
   dump_fp.writelines(output)
   dump_fp.close()
 
-  dump_file_r11_13 = svntest.main.temp_dir + "-r11-13.dump"
+  dump_file_r11_13 = sbox.get_tempname("r11-13-dump")
   output = svntest.actions.run_and_verify_svnrdump(None,
                                                    svntest.verify.AnyOutput,
                                                    [], 0, '-q', 'dump',
@@ -560,7 +560,7 @@ def dont_drop_valid_mergeinfo_during_inc
   dump_fp.writelines(output)
   dump_fp.close()
 
-  dump_file_r14_15 = svntest.main.temp_dir + "-r14-15.dump"
+  dump_file_r14_15 = sbox.get_tempname("r14-15-dump")
   output = svntest.actions.run_and_verify_svnrdump(None,
                                                    svntest.verify.AnyOutput,
                                                    [], 0, '-q', 'dump',
@@ -571,6 +571,7 @@ def dont_drop_valid_mergeinfo_during_inc
   dump_fp.close()
 
   # 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
   sbox.build(empty=True)
 
   # Create the revprop-change hook for this test
@@ -606,6 +607,7 @@ def dont_drop_valid_mergeinfo_during_inc
   # PART 3: Load a full dump to an non-empty repository.
   #
   # Reset our sandbox.
+  svntest.main.safe_rmtree(sbox.repo_dir, True) # Fix race with bdb in svnserve
   sbox.build(empty=True)
 
   # Create the revprop-change hook for this test
@@ -667,6 +669,7 @@ def dont_drop_valid_mergeinfo_during_inc
   # PART 4: Load a a series of incremental dumps to an non-empty repository.
   #
   # Reset our sandbox.
+  svntest.main.safe_rmtree(sbox.repo_dir, True) # Fix race with bdb in svnserve
   sbox.build(empty=True)
 
   # Create the revprop-change hook for this test

Modified: subversion/branches/ra-git/subversion/tests/cmdline/svnserveautocheck.sh
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/svnserveautocheck.sh?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/svnserveautocheck.sh (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/svnserveautocheck.sh Mon Nov 30 10:24:16 2015
@@ -92,16 +92,19 @@ random_port() {
   fi
 }
 
-if type time > /dev/null; then
-  TIME_CMD=time
-else
-  TIME_CMD=""
-fi
+if type time > /dev/null ; then TIME_CMD() { time "$@"; } ; else TIME_CMD() { "$@"; } ; fi
 
 MAKE=${MAKE:-make}
+PATH="$PATH:/usr/sbin/:/usr/local/sbin/"
+
+ss > /dev/null 2>&1 || netstat > /dev/null 2>&1 || fail "unable to find ss or netstat required to find a free port"
 
 SVNSERVE_PORT=$(random_port)
-while netstat -an | grep $SVNSERVE_PORT | grep 'LISTEN'; do
+while \
+  (ss -ltn sport = :$SVNSERVE_PORT 2>&1 | grep :$SVNSERVE_PORT > /dev/null ) \
+  || \
+  (netstat -an 2>&1 | grep $SVNSERVE_PORT | grep 'LISTEN' > /dev/null ) \
+  do
   SVNSERVE_PORT=$(random_port)
 done
 
@@ -121,13 +124,13 @@ fi
 
 BASE_URL=svn://127.0.0.1:$SVNSERVE_PORT
 if [ $# = 0 ]; then
-  $TIME_CMD "$MAKE" check "BASE_URL=$BASE_URL"
+  TIME_CMD "$MAKE" check "BASE_URL=$BASE_URL"
   r=$?
 else
   cd "$ABS_BUILDDIR/subversion/tests/cmdline/"
   TEST="$1"
   shift
-  $TIME_CMD "./${TEST}_tests.py" "--url=$BASE_URL" $*
+  TIME_CMD "./${TEST}_tests.py" "--url=$BASE_URL" $*
   r=$?
   cd - > /dev/null
 fi

Modified: subversion/branches/ra-git/subversion/tests/cmdline/svnsync_authz_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/svnsync_authz_tests.py?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/svnsync_authz_tests.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/svnsync_authz_tests.py Mon Nov 30 10:24:16 2015
@@ -30,7 +30,7 @@
 import sys, os
 
 # Test suite-specific modules
-import locale, re, urllib
+import locale, re
 
 # Our testing module
 import svntest
@@ -383,7 +383,7 @@ def identity_copy(sbox):
     except:
       pass
   if locale.setlocale(locale.LC_ALL) != other_locale:
-    raise svntest.Skip
+    raise svntest.Skip('Setting test locale failed')
 
   try:
     run_test(sbox, "copy-bad-encoding.expected.dump",
@@ -471,8 +471,7 @@ def copy_delete_unreadable_child(sbox):
                        src_authz + ':/A': '* =',
                        })
 
-  dest_url = svntest.main.file_scheme_prefix \
-                    + urllib.pathname2url(os.path.abspath(dest_sbox.repo_dir))
+  dest_url = dest_sbox.file_protocol_repo_url()
   run_init(dest_url, sbox.repo_url)
   run_sync(dest_url)
 

Modified: subversion/branches/ra-git/subversion/tests/cmdline/svnsync_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/svnsync_tests.py?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/svnsync_tests.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/svnsync_tests.py Mon Nov 30 10:24:16 2015
@@ -28,7 +28,7 @@
 import sys, os
 
 # Test suite-specific modules
-import re, urllib
+import re
 
 # Our testing module
 import svntest
@@ -131,16 +131,14 @@ def setup_and_sync(sbox, dump_file_conte
   repo_url = sbox.repo_url
   cwd = os.getcwd()
   if is_src_ra_local:
-    repo_url = svntest.main.file_scheme_prefix + \
-                        urllib.pathname2url(os.path.join(cwd, sbox.repo_dir))
+    repo_url = sbox.file_protocol_repo_url()
 
   if subdir:
     repo_url = repo_url + subdir
 
   dest_repo_url = dest_sbox.repo_url
   if is_dest_ra_local:
-    dest_repo_url = svntest.main.file_scheme_prefix + \
-                    urllib.pathname2url(os.path.join(cwd, dest_sbox.repo_dir))
+    dest_repo_url = dest_sbox.file_protocol_repo_url()
   run_init(dest_repo_url, repo_url, source_prop_encoding)
 
   run_sync(dest_repo_url, repo_url,

Modified: subversion/branches/ra-git/subversion/tests/cmdline/svntest/__init__.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/svntest/__init__.py?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/svntest/__init__.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/svntest/__init__.py Mon Nov 30 10:24:16 2015
@@ -23,11 +23,11 @@
 __all__ = [ ]
 
 import sys
-if sys.hexversion < 0x2050000:
-  sys.stderr.write('[SKIPPED] at least Python 2.5 is required\n')
+if sys.hexversion < 0x2070000:
+  sys.stderr.write('[SKIPPED] at least Python 2.7 is required\n')
 
   # note: exiting is a bit harsh for a library module, but we really do
-  # require Python 2.5. this package isn't going to work otherwise.
+  # require Python 2.7. this package isn't going to work otherwise.
 
   # we're skipping this test, not failing, so exit with 0
   sys.exit(0)

Modified: subversion/branches/ra-git/subversion/tests/cmdline/svntest/actions.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/svntest/actions.py?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/svntest/actions.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/svntest/actions.py Mon Nov 30 10:24:16 2015
@@ -249,6 +249,28 @@ def run_and_verify_svnadmin2(expected_st
   return exit_code, out, err
 
 
+def run_and_verify_svnfsfs(expected_stdout,
+                           expected_stderr, *varargs):
+  """Like run_and_verify_svnfsfs2, but the expected exit code is
+  assumed to be 0 if no output is expected on stderr, and 1 otherwise."""
+
+  expected_exit = 0
+  if expected_stderr is not None and expected_stderr != []:
+    expected_exit = 1
+  return run_and_verify_svnfsfs2(expected_stdout, expected_stderr,
+                                 expected_exit, *varargs)
+
+def run_and_verify_svnfsfs2(expected_stdout, expected_stderr,
+                            expected_exit, *varargs):
+  """Run svnfsfs command and check its output and exit code."""
+
+  exit_code, out, err = main.run_svnfsfs(*varargs)
+  verify.verify_outputs("Unexpected output", out, err,
+                        expected_stdout, expected_stderr)
+  verify.verify_exit_code("Unexpected return code", exit_code, expected_exit)
+  return exit_code, out, err
+
+
 def run_and_verify_svnversion(wc_dir, trail_url,
                               expected_stdout, expected_stderr, *varargs):
   """like run_and_verify_svnversion2, but the expected exit code is
@@ -380,6 +402,27 @@ def run_and_verify_svnrdump(dumpfile_con
   return output
 
 
+def run_and_verify_svnmover(expected_stdout, expected_stderr,
+                            *varargs):
+  """Run svnmover command and check its output"""
+
+  expected_exit = 0
+  if expected_stderr is not None and expected_stderr != []:
+    expected_exit = 1
+  return run_and_verify_svnmover2(expected_stdout, expected_stderr,
+                                  expected_exit, *varargs)
+
+def run_and_verify_svnmover2(expected_stdout, expected_stderr,
+                             expected_exit, *varargs):
+  """Run svnmover command and check its output and exit code."""
+
+  exit_code, out, err = main.run_svnmover(*varargs)
+  verify.verify_outputs("Unexpected output", out, err,
+                        expected_stdout, expected_stderr)
+  verify.verify_exit_code("Unexpected return code", exit_code, expected_exit)
+  return exit_code, out, err
+
+
 def run_and_verify_svnmucc(expected_stdout, expected_stderr,
                            *varargs):
   """Run svnmucc command and check its output"""
@@ -1646,7 +1689,7 @@ def run_and_verify_diff_summarize_xml(er
   for path in paths:
     modified_path = path.childNodes[0].data
 
-    if (expected_prefix is not None
+    if (expected_prefix
         and modified_path.find(expected_prefix) == 0):
       modified_path = modified_path.replace(expected_prefix, '')[1:].strip()
 

Modified: subversion/branches/ra-git/subversion/tests/cmdline/svntest/main.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/svntest/main.py?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/svntest/main.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/svntest/main.py Mon Nov 30 10:24:16 2015
@@ -112,7 +112,7 @@ class SVNRepositoryCreateFailure(Failure
 # Windows specifics
 if sys.platform == 'win32':
   windows = True
-  file_scheme_prefix = 'file:'
+  file_scheme_prefix = 'file:///'
   _exe = '.exe'
   _bat = '.bat'
   os.environ['SVN_DBG_STACKTRACES_TO_STDERR'] = 'y'
@@ -179,6 +179,7 @@ svnauthz_binary = os.path.abspath('../..
 svnauthz_validate_binary = os.path.abspath(
     '../../../tools/server-side/svnauthz-validate' + _exe
 )
+svnmover_binary = os.path.abspath('../../../tools/dev/svnmover/svnmover' + _exe)
 
 # Location to the pristine repository, will be calculated from test_area_url
 # when we know what the user specified for --url.
@@ -680,8 +681,7 @@ V %d
 %s
 END
 """ % (len(cert_rep), cert_rep, len(netloc_url), netloc_url)
-
-  file_write(md5_file, md5_file_contents)
+  file_write(md5_file, md5_file_contents, mode='wb')
 
 def copy_trust(dst_cfgdir, src_cfgdir):
   """Copy svn.ssl.server files from one config dir to another.
@@ -774,6 +774,12 @@ def run_svnversion(*varargs):
   as list of lines (including line terminators)."""
   return run_command(svnversion_binary, 1, False, *varargs)
 
+def run_svnmover(*varargs):
+  """Run svnmover with VARARGS, returns exit code as int; stdout, stderr as
+  list of lines (including line terminators)."""
+  return run_command(svnmover_binary, 1, False,
+                     *(_with_auth(_with_config_dir(varargs))))
+
 def run_svnmucc(*varargs):
   """Run svnmucc with VARARGS, returns exit code as int; stdout, stderr as
   list of lines (including line terminators).  Use binary mode for output."""
@@ -881,6 +887,8 @@ def youngest(repos_path):
 
 # Chmod recursively on a whole subtree
 def chmod_tree(path, mode, mask):
+  """For each node in the OS filesystem tree PATH, subtract MASK from its
+  permissions and add MODE to them."""
   for dirpath, dirs, files in os.walk(path):
     for name in dirs + files:
       fullname = os.path.join(dirpath, name)
@@ -1192,6 +1200,30 @@ def create_python_hook_script(hook_path,
     file_write(hook_path, "#!%s\n%s" % (sys.executable, hook_script_code))
     os.chmod(hook_path, 0755)
 
+def create_http_connection(url, debuglevel=9):
+  """Create an http(s) connection to the host specified by URL.
+     Set the debugging level (the amount of debugging output printed when
+     working with this connection) to DEBUGLEVEL.  By default, all debugging
+     output is printed. """
+
+  import httplib
+  from urlparse import urlparse
+
+  loc = urlparse(url)
+  if loc.scheme == 'http':
+    h = httplib.HTTPConnection(loc.hostname, loc.port)
+  else:
+    try:
+      import ssl # new in python 2.6
+      c = ssl.create_default_context()
+      c.check_hostname = False
+      c.verify_mode = ssl.CERT_NONE
+      h = httplib.HTTPSConnection(loc.hostname, loc.port, context=c)
+    except:
+      h = httplib.HTTPSConnection(loc.hostname, loc.port)
+  h.set_debuglevel(debuglevel)
+  return h
+
 def write_restrictive_svnserve_conf(repo_dir, anon_access="none"):
   "Create a restrictive authz file ( no anynomous access )."
 
@@ -1414,7 +1446,7 @@ def make_log_msg():
 # Functions which check the test configuration
 # (useful for conditional XFails)
 
-def tests_use_prepacakaged_repository():
+def tests_use_prepackaged_repository():
   return options.fsfs_version is not None
 
 def tests_verify_dump_load_cross_check():
@@ -1527,15 +1559,28 @@ def is_plaintext_password_storage_disabl
 
 
 # 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([
+    '2.2.27',
     '2.2.26',
+    '2.2.25',
     '2.4.9',
+    '2.4.8',
+    '2.4.7',
+    '2.4.6',
+    '2.4.5',
 ])
 def is_mod_dav_url_quoting_broken():
     if is_ra_type_dav():
         return (options.httpd_version in __mod_dav_url_quoting_broken_versions)
     return None
 
+def is_httpd_authz_provider_enabled():
+    if is_ra_type_dav():
+      v = options.httpd_version.split('.')
+      return (v[0] == '2' and int(v[1]) >= 3) or int(v[0]) > 2
+    return None
+
 ######################################################################
 
 
@@ -1570,13 +1615,12 @@ class TestSpawningThread(threading.Threa
     args = []
     args.append(str(index))
     args.append('-c')
+    args.append('--set-log-level=%s' % logger.getEffectiveLevel())
     # add some startup arguments from this process
     if options.fs_type:
       args.append('--fs-type=' + options.fs_type)
     if options.test_area_url:
       args.append('--url=' + options.test_area_url)
-    if logger.getEffectiveLevel() <= logging.DEBUG:
-      args.append('-v')
     if options.cleanup:
       args.append('--cleanup')
     if options.enable_sasl:
@@ -1870,14 +1914,48 @@ def _internal_run_tests(test_list, testn
   return exit_code
 
 
-def create_default_options():
-  """Set the global options to the defaults, as provided by the argument
-     parser."""
-  _parse_options([])
+class AbbreviatedFormatter(logging.Formatter):
+  """A formatter with abbreviated loglevel indicators in the output.
+
+  Use %(levelshort)s in the format string to get a single character
+  representing the loglevel..
+  """
+
+  _level_short = {
+    logging.CRITICAL : 'C',
+    logging.ERROR : 'E',
+    logging.WARNING : 'W',
+    logging.INFO : 'I',
+    logging.DEBUG : 'D',
+    logging.NOTSET : '-',
+    }
 
+  def format(self, record):
+    record.levelshort = self._level_short[record.levelno]
+    return logging.Formatter.format(self, record)
 
-def _create_parser():
+def _create_parser(usage=None):
   """Return a parser for our test suite."""
+
+  global logger
+
+  # Initialize the LOGGER global variable so the option parsing can set
+  # its loglevel, as appropriate.
+  logger = logging.getLogger()
+
+  # Did some chucklehead log something before we configured it? If they
+  # did, then a default handler/formatter would get installed. We want
+  # to be the one to install the first (and only) handler.
+  for handler in logger.handlers:
+    if not isinstance(handler.formatter, AbbreviatedFormatter):
+      raise Exception('Logging occurred before configuration. Some code'
+                      ' path needs to be fixed. Examine the log output'
+                      ' to find what/where logged something.')
+
+  # Set a sane default log level
+  if logger.getEffectiveLevel() == logging.NOTSET:
+    logger.setLevel(logging.WARN)
+
   def set_log_level(option, opt, value, parser, level=None):
     if level:
       # called from --verbose
@@ -1886,9 +1964,18 @@ def _create_parser():
       # called from --set-log-level
       logger.setLevel(getattr(logging, value, None) or int(value))
 
-  # set up the parser
+  # Set up the parser.
+  # If you add new options, consider adding them in
+  #
+  #     .../build/run_tests.py:main()
+  #
+  # and handling them in
+  #
+  #     .../build/run_tests.py:TestHarness._init_py_tests()
+  #
   _default_http_library = 'serf'
-  usage = 'usage: %prog [options] [<test> ...]'
+  if usage is None:
+    usage = 'usage: %prog [options] [<test> ...]'
   parser = optparse.OptionParser(usage=usage)
   parser.add_option('-l', '--list', action='store_true', dest='list_tests',
                     help='Print test doc strings instead of running them')
@@ -1903,6 +1990,9 @@ def _create_parser():
   parser.add_option('-p', '--parallel', action='store_const',
                     const=default_num_threads, dest='parallel',
                     help='Run the tests in parallel')
+  parser.add_option('--parallel-instances', action='store',
+                    type='int', dest='parallel',
+                    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')
@@ -1980,37 +2070,54 @@ def _create_parser():
   parser.set_defaults(
         server_minor_version=SVN_VER_MINOR,
         url=file_scheme_prefix + \
-                        urllib.pathname2url(os.path.abspath(os.getcwd())),
+                        svntest.wc.svn_uri_quote(
+                           os.path.abspath(
+                               os.getcwd()).replace(os.path.sep, '/')),
         http_library=_default_http_library)
 
   return parser
 
 
-def _parse_options(arglist=sys.argv[1:]):
+def parse_options(arglist=sys.argv[1:], usage=None):
   """Parse the arguments in arg_list, and set the global options object with
      the results"""
 
   global options
 
-  parser = _create_parser()
+  parser = _create_parser(usage)
   (options, args) = parser.parse_args(arglist)
 
-  # some sanity checking
+  # 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)
+  if not logger.handlers:
+    # Now that we have some options, let's get the logger configured before
+    # doing anything more
+    if options.log_with_timestamps:
+      formatter = AbbreviatedFormatter('%(levelshort)s:'
+                                       ' [%(asctime)s] %(message)s',
+                                       datefmt='%Y-%m-%d %H:%M:%S')
+    else:
+      formatter = AbbreviatedFormatter('%(levelshort)s: %(message)s')
+    handler = logging.StreamHandler(sys.stdout)
+    handler.setFormatter(formatter)
+    logger.addHandler(handler)
+
+  # Normalize url to have no trailing slash
+  if options.url:
+    if options.url[-1:] == '/':
+      options.test_area_url = options.url[:-1]
+    else:
+      options.test_area_url = options.url
+
+  # Some sanity checking
   if options.fsfs_packing and not options.fsfs_sharding:
     parser.error("--fsfs-packing requires --fsfs-sharding")
 
-  # If you change the below condition then change
-  # ../../../../build/run_tests.py too.
   if options.server_minor_version not in range(3, SVN_VER_MINOR+1):
     parser.error("test harness only supports server minor versions 3-%d"
                  % SVN_VER_MINOR)
 
-  if options.url:
-    if options.url[-1:] == '/': # Normalize url to have no trailing slash
-      options.test_area_url = options.url[:-1]
-    else:
-      options.test_area_url = options.url
-
   # Make sure the server-minor-version matches the fsfs-version parameter.
   if options.fsfs_version:
     if options.fsfs_version == 6:
@@ -2093,27 +2200,6 @@ def get_issue_details(issue_numbers):
   return issue_dict
 
 
-class AbbreviatedFormatter(logging.Formatter):
-  """A formatter with abbreviated loglevel indicators in the output.
-
-  Use %(levelshort)s in the format string to get a single character
-  representing the loglevel..
-  """
-
-  _level_short = {
-    logging.CRITICAL : 'C',
-    logging.ERROR : 'E',
-    logging.WARNING : 'W',
-    logging.INFO : 'I',
-    logging.DEBUG : 'D',
-    logging.NOTSET : '-',
-    }
-
-  def format(self, record):
-    record.levelshort = self._level_short[record.levelno]
-    return logging.Formatter.format(self, record)
-
-
 # Main func.  This is the "entry point" that all the test scripts call
 # to run their list of tests.
 #
@@ -2124,7 +2210,6 @@ def execute_tests(test_list, serial_only
   exiting the process.  This function can be used when a caller doesn't
   want the process to die."""
 
-  global logger
   global pristine_url
   global pristine_greek_repos_url
   global svn_binary
@@ -2134,6 +2219,7 @@ def execute_tests(test_list, serial_only
   global svnsync_binary
   global svndumpfilter_binary
   global svnversion_binary
+  global svnmover_binary
   global svnmucc_binary
   global svnauthz_binary
   global svnauthz_validate_binary
@@ -2144,42 +2230,13 @@ def execute_tests(test_list, serial_only
 
   testnums = []
 
-  # Initialize the LOGGER global variable so the option parsing can set
-  # its loglevel, as appropriate.
-  logger = logging.getLogger()
-
-  # Did some chucklehead log something before we configured it? If they
-  # did, then a default handler/formatter would get installed. We want
-  # to be the one to install the first (and only) handler.
-  for handler in logger.handlers:
-    if not isinstance(handler.formatter, AbbreviatedFormatter):
-      raise Exception('Logging occurred before configuration. Some code'
-                      ' path needs to be fixed. Examine the log output'
-                      ' to find what/where logged something.')
-
   if not options:
     # Override which tests to run from the commandline
-    (parser, args) = _parse_options()
+    (parser, args) = parse_options()
     test_selection = args
   else:
     parser = _create_parser()
 
-  # If there are no handlers registered yet, then install our own with
-  # our custom formatter. (anything currently installed *is* our handler
-  # as tested above)
-  if not logger.handlers:
-    # Now that we have some options, let's get the logger configured before
-    # doing anything more
-    if options.log_with_timestamps:
-      formatter = AbbreviatedFormatter('%(levelshort)s:'
-                                       ' [%(asctime)s] %(message)s',
-                                       datefmt='%Y-%m-%d %H:%M:%S')
-    else:
-      formatter = AbbreviatedFormatter('%(levelshort)s: %(message)s')
-    handler = logging.StreamHandler(sys.stdout)
-    handler.setFormatter(formatter)
-    logger.addHandler(handler)
-
   # parse the positional arguments (test nums, names)
   for arg in test_selection:
     appended = False
@@ -2229,7 +2286,9 @@ def execute_tests(test_list, serial_only
 
   # Calculate pristine_greek_repos_url from test_area_url.
   pristine_greek_repos_url = options.test_area_url + '/' + \
-                                urllib.pathname2url(pristine_greek_repos_dir)
+                                svntest.wc.svn_uri_quote(
+                                  pristine_greek_repos_dir.replace(
+                                      os.path.sep, '/'))
 
   if options.use_jsvn:
     if options.svn_bin is None:
@@ -2259,6 +2318,7 @@ def execute_tests(test_list, serial_only
     svnauthz_binary = os.path.join(options.tools_bin, 'svnauthz' + _exe)
     svnauthz_validate_binary = os.path.join(options.tools_bin,
                                             'svnauthz-validate' + _exe)
+    svnmover_binary = os.path.join(options.tools_bin, 'svnmover' + _exe)
 
   ######################################################################
 
@@ -2307,25 +2367,29 @@ def execute_tests(test_list, serial_only
     # We are simply listing the tests so always exit with success.
     return 0
 
-  # don't run tests in parallel when the tests don't support it or there
-  # are only a few tests to run.
+  # don't run tests in parallel when the tests don't support it or
+  # there are only a few tests to run.
+  options_parallel = options.parallel
   if serial_only or len(testnums) < 2:
     options.parallel = 0
 
-  if not options.is_child_process:
-    # Build out the default configuration directory
-    create_config_dir(default_config_dir,
-                      ssl_cert=options.ssl_cert,
-                      ssl_url=options.test_area_url,
-                      http_proxy=options.http_proxy,
-                      exclusive_wc_locks=options.exclusive_wc_locks)
-
-    # Setup the pristine repository
-    svntest.actions.setup_pristine_greek_repository()
-
-  # Run the tests.
-  exit_code = _internal_run_tests(test_list, testnums, options.parallel,
-                                  options.srcdir, progress_func)
+  try:
+    if not options.is_child_process:
+      # Build out the default configuration directory
+      create_config_dir(default_config_dir,
+                        ssl_cert=options.ssl_cert,
+                        ssl_url=options.test_area_url,
+                        http_proxy=options.http_proxy,
+                        exclusive_wc_locks=options.exclusive_wc_locks)
+
+      # Setup the pristine repository
+      svntest.actions.setup_pristine_greek_repository()
+
+    # Run the tests.
+    exit_code = _internal_run_tests(test_list, testnums, options.parallel,
+                                    options.srcdir, progress_func)
+  finally:
+    options.parallel = options_parallel
 
   # Remove all scratchwork: the 'pristine' repository, greek tree, etc.
   # This ensures that an 'import' will happen the next time we run.

Modified: subversion/branches/ra-git/subversion/tests/cmdline/svntest/sandbox.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/svntest/sandbox.py?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/svntest/sandbox.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/svntest/sandbox.py Mon Nov 30 10:24:16 2015
@@ -24,7 +24,6 @@
 import os
 import shutil
 import copy
-import urllib
 import logging
 import re
 
@@ -114,7 +113,8 @@ class Sandbox:
     if empty or not read_only:  # use a local repo
       self.repo_dir = os.path.join(svntest.main.general_repo_dir, self.name)
       self.repo_url = (svntest.main.options.test_area_url + '/'
-                       + urllib.pathname2url(self.repo_dir))
+                       + svntest.wc.svn_uri_quote(
+                                self.repo_dir.replace(os.path.sep, '/')))
       self.add_test_path(self.repo_dir)
     else:
       self.repo_dir = svntest.main.pristine_greek_repos_dir
@@ -195,7 +195,8 @@ class Sandbox:
     path = (os.path.join(svntest.main.general_repo_dir, self.name)
             + '.' + suffix)
     url = svntest.main.options.test_area_url + \
-                                        '/' + urllib.pathname2url(path)
+                                        '/' + svntest.wc.svn_uri_quote(
+                                                path.replace(os.path.sep, '/'))
     self.add_test_path(path, remove)
     return path, url
 
@@ -276,6 +277,12 @@ class Sandbox:
                                   temporary and 'TEMP' or 'PERM',
                                   parts[1])
 
+  def file_protocol_repo_url(self):
+    """get a file:// url pointing to the repository"""
+    return svntest.main.file_scheme_prefix + \
+           svntest.wc.svn_uri_quote(
+                os.path.abspath(self.repo_dir).replace(os.path.sep, '/'))
+
   def simple_update(self, target=None, revision='HEAD'):
     """Update the WC or TARGET.
        TARGET is a relpath relative to the WC."""

Modified: subversion/branches/ra-git/subversion/tests/cmdline/svntest/tree.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/svntest/tree.py?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/svntest/tree.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/svntest/tree.py Mon Nov 30 10:24:16 2015
@@ -285,16 +285,7 @@ class SVNTreeNode:
     if self.props:
       if comma:
         line += ", "
-      line += "props={"
-      comma = False
-
-      for name in self.props:
-        if comma:
-          line += ", "
-        line += "'%s':'%s'" % (name, self.props[name])
-        comma = True
-
-      line += "}"
+      line += ("props=%s" % self.props)
       comma = True
 
     for name in self.atts:

Modified: subversion/branches/ra-git/subversion/tests/cmdline/svntest/verify.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/svntest/verify.py?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/svntest/verify.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/svntest/verify.py Mon Nov 30 10:24:16 2015
@@ -853,7 +853,7 @@ def make_git_diff_header(target_path, re
   if add:
     output.extend([
       "diff --git a/" + repos_relpath + " b/" + repos_relpath + "\n",
-      "new file mode 10644\n",
+      "new file mode 100644\n",
     ])
     if text_changes:
       output.extend([
@@ -863,7 +863,7 @@ def make_git_diff_header(target_path, re
   elif delete:
     output.extend([
       "diff --git a/" + repos_relpath + " b/" + repos_relpath + "\n",
-      "deleted file mode 10644\n",
+      "deleted file mode 100644\n",
     ])
     if text_changes:
       output.extend([

Modified: subversion/branches/ra-git/subversion/tests/cmdline/svntest/wc.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/svntest/wc.py?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/svntest/wc.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/svntest/wc.py Mon Nov 30 10:24:16 2015
@@ -116,6 +116,15 @@ _re_parse_co_restored = re.compile('^(Re
 _re_parse_commit_ext = re.compile('^(([A-Za-z]+( [a-z]+)*)) \'(.+)\'( --.*)?')
 _re_parse_commit = re.compile('^(\w+(  \(bin\))?)\s+(.+)')
 
+#rN: eids 0 15 branches 4
+_re_parse_eid_header = re.compile('^r(-1|[0-9]+): eids ([0-9]+) ([0-9]+) '
+                                  'branches ([0-9]+)$')
+# B0.2 root-eid 3
+_re_parse_eid_branch = re.compile('^(B[0-9.]+) root-eid ([0-9]+) num-eids ([0-9]+)( from [^ ]*)?$')
+_re_parse_eid_merge_history = re.compile('merge-history: merge-ancestors ([0-9]+)')
+# e4: normal 6 C
+_re_parse_eid_ele = re.compile('^e([0-9]+): (none|normal|subbranch) '
+                               '(-1|[0-9]+) (.*)$')
 
 class State:
   """Describes an existing or expected state of a working copy.
@@ -206,6 +215,30 @@ class State:
       if list(filter(path, item)):
         item.tweak(**kw)
 
+  def rename(self, moves):
+    """Change the path of some items.
+
+    MOVES is a dictionary mapping source path to destination
+    path. Children move with moved parents.  All subtrees are moved in
+    reverse depth order to temporary storage before being moved in
+    depth order to the final location.  This allows nested moves.
+
+    """
+    temp = {}
+    for src, dst in sorted(moves.items(), key=lambda (src, dst): src)[::-1]:
+      temp[src] = {}
+      for path, item in self.desc.items():
+        if path == src or path[:len(src) + 1] == src + '/':
+          temp[src][path] = item;
+          del self.desc[path]
+    for src, dst in sorted(moves.items(), key=lambda (src, dst): dst):
+      for path, item in temp[src].items():
+        if path == src:
+          new_path = dst
+        else:
+          new_path = dst + path[len(src):]
+        self.desc[new_path] = item
+
   def subtree(self, subtree_path):
     """Return a State object which is a deep copy of the sub-tree
     beneath SUBTREE_PATH (which is assumed to be rooted at the tree of
@@ -750,6 +783,63 @@ class State:
 
     return cls('', desc)
 
+  @classmethod
+  def from_eids(cls, lines):
+
+    # Need to read all elements in a branch before we can construct
+    # the full path to an element.
+    # For the full path we use <branch-id>/<path-within-branch>.
+
+    def eid_path(eids, eid):
+      ele = eids[eid]
+      if ele[0] == '-1':
+        return ele[1]
+      parent_path = eid_path(eids, ele[0])
+      if parent_path == '':
+        return ele[1]
+      return parent_path + '/' + ele[1]
+
+    def eid_full_path(eids, eid, branch_id):
+      path = eid_path(eids, eid)
+      if path == '':
+        return branch_id
+      return branch_id + '/' + path
+
+    def add_to_desc(eids, desc, branch_id):
+      for k, v in eids.items():
+        desc[eid_full_path(eids, k, branch_id)] = StateItem(eid=k)
+
+    branch_id = None
+    eids = {}
+    desc = {}
+    for line in lines:
+
+      match = _re_parse_eid_ele.search(line)
+      if match and match.group(2) != 'none':
+        eid = match.group(1)
+        parent_eid = match.group(3) 
+        path = match.group(4)
+        if path == '.':
+          path = ''
+        eids[eid] = [parent_eid, path]
+
+      match = _re_parse_eid_branch.search(line)
+      if match:
+        if branch_id:
+          add_to_desc(eids, desc, branch_id)
+          eids = {}
+        branch_id = match.group(1)
+        root_eid = match.group(2)
+
+      match = _re_parse_eid_merge_history.search(line)
+      if match:
+        ### TODO: store the merge history
+        pass
+
+    add_to_desc(eids, desc, branch_id)
+
+    return cls('', desc)
+  
 
 class StateItem:
   """Describes an individual item within a working copy.
@@ -764,7 +854,8 @@ class StateItem:
                entry_rev=None, entry_status=None, entry_copied=None,
                locked=None, copied=None, switched=None, writelocked=None,
                treeconflict=None, moved_from=None, moved_to=None,
-               prev_status=None, prev_verb=None, prev_treeconflict=None):
+               prev_status=None, prev_verb=None, prev_treeconflict=None,
+               eid=None):
     # provide an empty prop dict if it wasn't provided
     if props is None:
       props = { }
@@ -772,6 +863,8 @@ class StateItem:
     ### keep/make these ints one day?
     if wc_rev is not None:
       wc_rev = str(wc_rev)
+    if eid is not None:
+      eid = str(eid)
 
     # Any attribute can be None if not relevant, unless otherwise stated.
 
@@ -807,6 +900,7 @@ class StateItem:
     # Relative paths to the move locations
     self.moved_from = moved_from
     self.moved_to = moved_to
+    self.eid = eid
 
   def copy(self):
     "Make a deep copy of self."
@@ -820,6 +914,8 @@ class StateItem:
       # Refine the revision args (for now) to ensure they are strings.
       if value is not None and name == 'wc_rev':
         value = str(value)
+      if value is not None and name == 'eid':
+        value = str(value)
       setattr(self, name, value)
 
   def __eq__(self, other):
@@ -867,6 +963,8 @@ class StateItem:
       atts['moved_from'] = self.moved_from
     if self.moved_to is not None:
       atts['moved_to'] = self.moved_to
+    if self.eid is not None:
+      atts['eid'] = self.eid
 
     return (os.path.normpath(path), self.contents, self.props, atts)
 
@@ -980,6 +1078,20 @@ 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
+
 def open_wc_db(local_path):
   """Open the SQLite DB for the WC path LOCAL_PATH.
      Return (DB object, WC root path, WC relpath of LOCAL_PATH)."""
@@ -1035,6 +1147,16 @@ def sqlite_stmt(wc_root_path, stmt):
   c.execute(stmt)
   return c.fetchall()
 
+def sqlite_exec(wc_root_path, stmt):
+  """Execute STMT on the SQLite wc.db in WC_ROOT_PATH and return the
+     results."""
+
+  db = open_wc_db(wc_root_path)[0]
+  c = db.cursor()
+  c.execute(stmt)
+  db.commit()
+
+
 # ------------
 ### probably toss these at some point. or major rework. or something.
 ### just bootstrapping some changes for now.

Modified: subversion/branches/ra-git/subversion/tests/cmdline/switch_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/switch_tests.py?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/switch_tests.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/switch_tests.py Mon Nov 30 10:24:16 2015
@@ -771,7 +771,7 @@ def refresh_read_only_attribute(sbox):
   # behavior, just skip the test.
   if os.name == 'posix':
     if os.geteuid() == 0:
-      raise svntest.Skip
+      raise svntest.Skip('Test doesn\'t work as uid 0')
 
   sbox.build()
   wc_dir = sbox.wc_dir