subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From julianf...@apache.org
Subject svn commit: r1658462 [27/31] - in /subversion/branches/move-tracking-2: ./ build/ build/generator/ build/generator/templates/ notes/ subversion/ subversion/bindings/cxxhl/include/svncxxhl/ subversion/bindings/javahl/native/ subversion/bindings/javahl/n...
Date Mon, 09 Feb 2015 16:46:21 GMT
Modified: subversion/branches/move-tracking-2/subversion/tests/cmdline/svnsync_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/cmdline/svnsync_tests.py?rev=1658462&r1=1658461&r2=1658462&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/tests/cmdline/svnsync_tests.py (original)
+++ subversion/branches/move-tracking-2/subversion/tests/cmdline/svnsync_tests.py Mon Feb  9 16:46:16 2015
@@ -34,6 +34,7 @@ import re, urllib
 import svntest
 from svntest.verify import SVNUnexpectedStdout, SVNUnexpectedStderr
 from svntest.verify import SVNExpectedStderr
+from svntest.verify import AnyOutput
 from svntest.main import server_has_partial_replay
 
 # (abbreviation)
@@ -49,117 +50,57 @@ Item = svntest.wc.StateItem
 # Helper routines
 
 
-def build_repos(sbox):
-  """Avoid the use sbox.build() because we're working with a repos
-  other than the Greek tree."""
-  # Cleanup after the last run by removing any left-over repository.
-  svntest.main.safe_rmtree(sbox.repo_dir)
-
-  # Create an empty repository.
-  svntest.main.create_repos(sbox.repo_dir)
-
-
-def run_sync(url, source_url=None, expected_error=None,
-             source_prop_encoding=None):
+def run_sync(url, source_url=None,
+             source_prop_encoding=None,
+             expected_output=AnyOutput, expected_error=[]):
   "Synchronize the mirror repository with the master"
   if source_url is not None:
-    args = ["synchronize", url, source_url,
-      "--username", svntest.main.wc_author,
-      "--password", svntest.main.wc_passwd]
+    args = ["synchronize", url, source_url]
   else: # Allow testing of old source-URL-less syntax
-    args = ["synchronize", url,
-      "--username", svntest.main.wc_author,
-      "--password", svntest.main.wc_passwd]
+    args = ["synchronize", url]
   if source_prop_encoding:
     args.append("--source-prop-encoding")
     args.append(source_prop_encoding)
 
-  exit_code, output, errput = svntest.main.run_svnsync(*args)
-  for index, line in enumerate(errput[:]):
-    if re.search("warning: W200007", line):
-      del errput[index]
-  if errput:
-    if expected_error is None:
-      raise SVNUnexpectedStderr(errput)
-    else:
-      expected_error = svntest.verify.RegexOutput(expected_error,
-                                                  match_all=False)
-      svntest.verify.compare_and_display_lines(None, "STDERR",
-                                               expected_error, errput)
-  elif expected_error is not None:
-    raise SVNExpectedStderr
-  if not output and not expected_error:
-    # should be: ['Committed revision 1.\n', 'Committed revision 2.\n']
-    raise SVNUnexpectedStdout("Missing stdout")
-
-def run_copy_revprops(url, source_url, expected_error=None,
-                      source_prop_encoding=None):
+  # Normal expected output is of the form:
+  #            ['Transmitting file data .......\n',  # optional
+  #             'Committed revision 1.\n',
+  #             'Copied properties for revision 1.\n', ...]
+  svntest.actions.run_and_verify_svnsync(expected_output, expected_error,
+                                         *args)
+
+def run_copy_revprops(url, source_url,
+                      source_prop_encoding=None,
+                      expected_output=AnyOutput, expected_error=[]):
   "Copy revprops to the mirror repository from the master"
-  args = ["copy-revprops", url, source_url,
-    "--username", svntest.main.wc_author,
-    "--password", svntest.main.wc_passwd]
+  args = ["copy-revprops", url, source_url]
   if source_prop_encoding:
     args.append("--source-prop-encoding")
     args.append(source_prop_encoding)
 
-  exit_code, output, errput = svntest.main.run_svnsync(*args)
-  for index, line in enumerate(errput[:]):
-    if re.search("warning: W200007", line):
-      del errput[index]
-  if errput:
-    if expected_error is None:
-      raise SVNUnexpectedStderr(errput)
-    else:
-      expected_error = svntest.verify.RegexOutput(expected_error,
-                                                  match_all=False)
-      svntest.verify.compare_and_display_lines(None, "STDERR",
-                                               expected_error, errput)
-  elif expected_error is not None:
-    raise SVNExpectedStderr
-  if not output and not expected_error:
-    # should be: ['Copied properties for revision 1.\n',
-    #             'Copied properties for revision 2.\n']
-    raise SVNUnexpectedStdout("Missing stdout")
+  # Normal expected output is of the form:
+  #            ['Copied properties for revision 1.\n', ...]
+  svntest.actions.run_and_verify_svnsync(expected_output, expected_error,
+                                         *args)
 
 def run_init(dst_url, src_url, source_prop_encoding=None):
   "Initialize the mirror repository from the master"
-  args = ["initialize", dst_url, src_url,
-    "--username", svntest.main.wc_author,
-    "--password", svntest.main.wc_passwd]
+  args = ["initialize", dst_url, src_url]
   if source_prop_encoding:
     args.append("--source-prop-encoding")
     args.append(source_prop_encoding)
 
-  exit_code, output, errput = svntest.main.run_svnsync(*args)
-  for index, line in enumerate(errput[:]):
-    if re.search("warning: W200007", line):
-      del errput[index]
-  if errput:
-    raise SVNUnexpectedStderr(errput)
-  if output != ['Copied properties for revision 0.\n']:
-    raise SVNUnexpectedStdout(output)
+  expected_output = ['Copied properties for revision 0.\n']
+  svntest.actions.run_and_verify_svnsync(expected_output, [], *args)
 
-def run_info(url, expected_error=None):
+def run_info(url, expected_output=AnyOutput, expected_error=[]):
   "Print synchronization information of the repository"
-  exit_code, output, errput = svntest.main.run_svnsync(
-    "info", url,
-    "--username", svntest.main.wc_author,
-    "--password", svntest.main.wc_passwd)
-  if errput:
-    if expected_error is None:
-      raise SVNUnexpectedStderr(errput)
-    else:
-      expected_error = svntest.verify.RegexOutput(expected_error,
-                                                  match_all=False)
-      svntest.verify.compare_and_display_lines(None, "STDERR",
-                                               expected_error, errput)
-  elif expected_error is not None:
-    raise SVNExpectedStderr
-  if not output and not expected_error:
-    # should be: ['From URL: http://....\n',
-    #             'From UUID: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\n',
-    #             'Last Merged Revision: XXX\n']
-    raise SVNUnexpectedStdout("Missing stdout")
+  # Normal expected output is of the form:
+  #            ['From URL: http://....\n',
+  #             'From UUID: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\n',
+  #             'Last Merged Revision: XXX\n']
+  svntest.actions.run_and_verify_svnsync(expected_output, expected_error,
+                                         "info", url)
 
 
 def setup_and_sync(sbox, dump_file_contents, subdir=None,
@@ -168,7 +109,7 @@ def setup_and_sync(sbox, dump_file_conte
   """Create a repository for SBOX, load it with DUMP_FILE_CONTENTS, then create a mirror repository and sync it with SBOX. If is_src_ra_local or is_dest_ra_local is True, then run_init, run_sync, and run_copy_revprops will use the file:// scheme for the source and destination URLs.  Return the mirror sandbox."""
 
   # Create the empty master repository.
-  build_repos(sbox)
+  sbox.build(create_wc=False, empty=True)
 
   # Load the repository from DUMP_FILE_PATH.
   svntest.actions.run_and_verify_load(sbox.repo_dir, dump_file_contents,
@@ -176,11 +117,11 @@ def setup_and_sync(sbox, dump_file_conte
 
   # Create the empty destination repository.
   dest_sbox = sbox.clone_dependent()
-  build_repos(dest_sbox)
+  dest_sbox.build(create_wc=False, empty=True)
 
   # Setup the mirror repository.  Feed it the UUID of the source repository.
   exit_code, output, errput = svntest.main.run_svnlook("uuid", sbox.repo_dir)
-  svntest.actions.run_and_verify_svnadmin2("Setting UUID", None, None, 0,
+  svntest.actions.run_and_verify_svnadmin2(None, None, 0,
                                            'setuuid', dest_sbox.repo_dir,
                                            output[0][:-1])
 
@@ -221,7 +162,7 @@ def verify_mirror(dest_sbox, exp_dump_fi
   for prop_name in ("svn:sync-from-url", "svn:sync-from-uuid",
                     "svn:sync-last-merged-rev"):
     svntest.actions.run_and_verify_svn(
-      None, None, [], "propdel", "--revprop", "-r", "0",
+      None, [], "propdel", "--revprop", "-r", "0",
       prop_name, dest_sbox.repo_url)
 
   # Create a dump file from the mirror repository.
@@ -346,14 +287,13 @@ def detect_meddling(sbox):
   sbox.build("svnsync-meddling")
 
   dest_sbox = sbox.clone_dependent()
-  build_repos(dest_sbox)
+  dest_sbox.build(create_wc=False, empty=True)
 
   # Make our own destination checkout (have to do it ourself because
   # it is not greek).
 
   svntest.main.safe_rmtree(dest_sbox.wc_dir)
   svntest.actions.run_and_verify_svn(None,
-                                     None,
                                      [],
                                      'co',
                                      dest_sbox.repo_url,
@@ -365,7 +305,6 @@ def detect_meddling(sbox):
   run_sync(dest_sbox.repo_url)
 
   svntest.actions.run_and_verify_svn(None,
-                                     None,
                                      [],
                                      'up',
                                      dest_sbox.wc_dir)
@@ -374,14 +313,14 @@ def detect_meddling(sbox):
   svntest.main.file_append(os.path.join(dest_sbox.wc_dir, 'A', 'B', 'lambda'),
                            'new lambda text')
   svntest.actions.run_and_verify_svn(None,
-                                     None,
                                      [],
                                      'ci',
                                      '-m', 'msg',
                                      dest_sbox.wc_dir)
 
+  expected_error = r".*Destination HEAD \(2\) is not the last merged revision \(1\).*"
   run_sync(dest_sbox.repo_url, None,
-           ".*Destination HEAD \\(2\\) is not the last merged revision \\(1\\).*")
+           expected_output=[], expected_error=expected_error)
 
 def url_encoding(sbox):
   "test url encoding issues"
@@ -427,28 +366,18 @@ def info_synchronized(sbox):
   src_uuid = output[0].strip()
 
   dest_sbox = sbox.clone_dependent()
-  build_repos(dest_sbox)
+  dest_sbox.build(create_wc=False, empty=True)
 
   svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)
   run_init(dest_sbox.repo_url, sbox.repo_url)
   run_sync(dest_sbox.repo_url)
 
-  exit_code, output, errput = svntest.main.run_svnsync(
-    "info", dest_sbox.repo_url,
-    "--username", svntest.main.wc_author,
-    "--password", svntest.main.wc_passwd)
-  if errput:
-      raise SVNUnexpectedStderr(errput)
-
   expected_out = ['Source URL: %s\n' % sbox.repo_url,
                   'Source Repository UUID: %s\n' % src_uuid,
                   'Last Merged Revision: 1\n',
                   ]
-
-  svntest.verify.compare_and_display_lines(None,
-                                           'INFO',
-                                           expected_out,
-                                           output)
+  svntest.actions.run_and_verify_svnsync(expected_out, [],
+                                         "info", dest_sbox.repo_url)
 
 def info_not_synchronized(sbox):
   "test info cmd on an un-synchronized repo"
@@ -456,7 +385,7 @@ def info_not_synchronized(sbox):
   sbox.build("svnsync-info-not-syncd", False)
 
   run_info(sbox.repo_url,
-           ".*Repository '%s' is not initialized.*" % sbox.repo_url)
+           [], ".*Repository '%s' is not initialized.*" % sbox.repo_url)
 
 #----------------------------------------------------------------------
 
@@ -578,9 +507,72 @@ def fd_leak_sync_from_serf_to_local(sbox
 @Issue(4476)
 def mergeinfo_contains_r0(sbox):
   "mergeinfo contains r0"
-  run_test(sbox, "mergeinfo-contains-r0.dump",
-           exp_dump_file_name="mergeinfo-contains-r0.expected.dump",
-           bypass_prop_validation=True)
+
+  def make_node_record(node_name, mi):
+    """Return a dumpfile node-record for adding a (directory) node named
+       NODE_NAME with mergeinfo MI. Return it as a list of newline-terminated
+       lines.
+    """
+    headers_tmpl = """\
+Node-path: %s
+Node-kind: dir
+Node-action: add
+Prop-content-length: %d
+Content-length: %d
+"""
+    content_tmpl = """\
+K 13
+svn:mergeinfo
+V %d
+%s
+PROPS-END
+"""
+    content = content_tmpl % (len(mi), mi)
+    headers = headers_tmpl % (node_name, len(content), len(content))
+    record = headers + '\n' + content + '\n\n'
+    return record.splitlines(True)
+
+  # The test case mergeinfo (before, after) syncing, separated here with
+  # spaces instead of newlines
+  test_mi = [
+    ("",            ""),  # unchanged
+    ("/a:1",        "/a:1"),
+    ("/a:1 /b:1*,2","/a:1 /b:1*,2"),
+    ("/:0:1",       "/:0:1"),  # unchanged; colon-zero in filename
+    ("/a:0",        ""),  # dropped entirely
+    ("/a:0*",       ""),
+    ("/a:0 /b:0*",  ""),
+    ("/a:1 /b:0",   "/a:1"),  # one kept, one dropped
+    ("/a:0 /b:1",   "/b:1"),
+    ("/a:0,1 /b:1", "/a:1 /b:1"),  # one kept, one changed
+    ("/a:1 /b:0,1", "/a:1 /b:1"),
+    ("/a:0,1 /b:0*,1 /c:0,2 /d:0-1 /e:0-1,3 /f:0-2 /g:0-3",
+     "/a:1 /b:1 /c:2 /d:1 /e:1,3 /f:1-2 /g:1-3"),  # all changed
+    ("/a:0:0-1",    "/a:0:1"),  # changed; colon-zero in filename
+    ]
+
+  # Get the constant prefix for each dumpfile
+  dump_file_name = "mergeinfo-contains-r0.dump"
+  svnsync_tests_dir = os.path.join(os.path.dirname(sys.argv[0]),
+                                   'svnsync_tests_data')
+  dump_in = open(os.path.join(svnsync_tests_dir, dump_file_name),
+                 'rb').readlines()
+  dump_out = list(dump_in)  # duplicate the list
+
+  # Add dumpfile node records containing the test mergeinfo
+  for n, mi in enumerate(test_mi):
+    node_name = "D" + str(n)
+
+    mi_in = mi[0].replace(' ', '\n')
+    mi_out = mi[1].replace(' ', '\n')
+    dump_in.extend(make_node_record(node_name, mi_in))
+    dump_out.extend(make_node_record(node_name, mi_out))
+
+  # Run the sync
+  dest_sbox = setup_and_sync(sbox, dump_in, bypass_prop_validation=True)
+
+  # Compare the dump produced by the mirror repository with expected
+  verify_mirror(dest_sbox, dump_out)
 
 
 ########################################################################

Modified: subversion/branches/move-tracking-2/subversion/tests/cmdline/svnsync_tests_data/mergeinfo-contains-r0.dump
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/cmdline/svnsync_tests_data/mergeinfo-contains-r0.dump?rev=1658462&r1=1658461&r2=1658462&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/tests/cmdline/svnsync_tests_data/mergeinfo-contains-r0.dump (original)
+++ subversion/branches/move-tracking-2/subversion/tests/cmdline/svnsync_tests_data/mergeinfo-contains-r0.dump Mon Feb  9 16:46:16 2015
@@ -13,8 +13,8 @@ V 27
 PROPS-END
 
 Revision-number: 1
-Prop-content-length: 101
-Content-length: 101
+Prop-content-length: 84
+Content-length: 84
 
 K 10
 svn:author
@@ -24,62 +24,5 @@ K 8
 svn:date
 V 27
 2000-01-01T00:00:00.000000Z
-K 7
-svn:log
-V 0
-
 PROPS-END
 
-Node-path: 
-Node-kind: dir
-Node-action: change
-Prop-content-length: 22
-Content-length: 22
-
-K 1
-p
-V 1
-v
-PROPS-END
-
-
-Revision-number: 2
-Prop-content-length: 113
-Content-length: 113
-
-K 10
-svn:author
-V 7
-jrandom
-K 8
-svn:date
-V 27
-2005-11-07T23:37:17.705159Z
-K 7
-svn:log
-V 11
-add foo.txt
-PROPS-END
-
-Node-path: foo.txt
-Node-kind: file
-Node-action: add
-Prop-content-length: 86
-Text-content-length: 0
-Text-content-md5: d41d8cd98f00b204e9800998ecf8427e
-Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709
-Content-length: 86
-
-K 13
-svn:mergeinfo
-V 51
-/a:0,1
-/b:0*,1
-/c:0,2
-/d:0-1
-/e:0-1,3
-/f:0-2
-/g:0-3
-PROPS-END
-
-

Modified: subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/actions.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/actions.py?rev=1658462&r1=1658461&r2=1658462&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/actions.py (original)
+++ subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/actions.py Mon Feb  9 16:46:16 2015
@@ -129,7 +129,7 @@ def setup_pristine_greek_repository():
 
 ######################################################################
 
-def guarantee_empty_repository(path):
+def guarantee_empty_repository(path, minor_version):
   """Guarantee that a local svn repository exists at PATH, containing
   nothing."""
 
@@ -139,7 +139,7 @@ def guarantee_empty_repository(path):
 
   # create an empty repository at PATH.
   main.safe_rmtree(path)
-  main.create_repos(path)
+  main.create_repos(path, minor_version)
 
 # Used by every test, so that they can run independently of  one
 # another. Every time this routine is called, it recursively copies
@@ -169,10 +169,9 @@ def guarantee_greek_repository(path, min
   main.chmod_tree(path, 0666, 0666)
 
   # give the repository a unique UUID
-  run_and_verify_svnadmin("could not set uuid", [], [], 'setuuid', path)
+  run_and_verify_svnadmin([], [], 'setuuid', path)
 
-def run_and_verify_atomic_ra_revprop_change(message,
-                                            expected_stdout,
+def run_and_verify_atomic_ra_revprop_change(expected_stdout,
                                             expected_stderr,
                                             expected_exit,
                                             url, revision, propname,
@@ -202,11 +201,11 @@ def run_and_verify_atomic_ra_revprop_cha
                                                           want_error)
   verify.verify_outputs("Unexpected output", out, err,
                         expected_stdout, expected_stderr)
-  verify.verify_exit_code(message, exit_code, expected_exit)
+  verify.verify_exit_code("Unexpected return code", exit_code, expected_exit)
   return exit_code, out, err
 
 
-def run_and_verify_svnlook(message, expected_stdout,
+def run_and_verify_svnlook(expected_stdout,
                            expected_stderr, *varargs):
   """Like run_and_verify_svnlook2, but the expected exit code is
   assumed to be 0 if no output is expected on stderr, and 1 otherwise."""
@@ -214,21 +213,21 @@ def run_and_verify_svnlook(message, expe
   expected_exit = 0
   if expected_stderr is not None and expected_stderr != []:
     expected_exit = 1
-  return run_and_verify_svnlook2(message, expected_stdout, expected_stderr,
+  return run_and_verify_svnlook2(expected_stdout, expected_stderr,
                                  expected_exit, *varargs)
 
-def run_and_verify_svnlook2(message, expected_stdout, expected_stderr,
+def run_and_verify_svnlook2(expected_stdout, expected_stderr,
                             expected_exit, *varargs):
   """Run svnlook command and check its output and exit code."""
 
   exit_code, out, err = main.run_svnlook(*varargs)
   verify.verify_outputs("Unexpected output", out, err,
                         expected_stdout, expected_stderr)
-  verify.verify_exit_code(message, exit_code, expected_exit)
+  verify.verify_exit_code("Unexpected return code", exit_code, expected_exit)
   return exit_code, out, err
 
 
-def run_and_verify_svnadmin(message, expected_stdout,
+def run_and_verify_svnadmin(expected_stdout,
                             expected_stderr, *varargs):
   """Like run_and_verify_svnadmin2, but the expected exit code is
   assumed to be 0 if no output is expected on stderr, and 1 otherwise."""
@@ -236,21 +235,21 @@ def run_and_verify_svnadmin(message, exp
   expected_exit = 0
   if expected_stderr is not None and expected_stderr != []:
     expected_exit = 1
-  return run_and_verify_svnadmin2(message, expected_stdout, expected_stderr,
+  return run_and_verify_svnadmin2(expected_stdout, expected_stderr,
                                   expected_exit, *varargs)
 
-def run_and_verify_svnadmin2(message, expected_stdout, expected_stderr,
+def run_and_verify_svnadmin2(expected_stdout, expected_stderr,
                              expected_exit, *varargs):
   """Run svnadmin command and check its output and exit code."""
 
   exit_code, out, err = main.run_svnadmin(*varargs)
   verify.verify_outputs("Unexpected output", out, err,
                         expected_stdout, expected_stderr)
-  verify.verify_exit_code(message, exit_code, expected_exit)
+  verify.verify_exit_code("Unexpected return code", exit_code, expected_exit)
   return exit_code, out, err
 
 
-def run_and_verify_svnversion(message, wc_dir, trail_url,
+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
   assumed to be 0 if no output is expected on stderr, and 1 otherwise."""
@@ -258,11 +257,11 @@ def run_and_verify_svnversion(message, w
   expected_exit = 0
   if expected_stderr is not None and expected_stderr != []:
     expected_exit = 1
-  return run_and_verify_svnversion2(message, wc_dir, trail_url,
+  return run_and_verify_svnversion2(wc_dir, trail_url,
                                     expected_stdout, expected_stderr,
                                     expected_exit, *varargs)
 
-def run_and_verify_svnversion2(message, wc_dir, trail_url,
+def run_and_verify_svnversion2(wc_dir, trail_url,
                                expected_stdout, expected_stderr,
                                expected_exit, *varargs):
   """Run svnversion command and check its output and exit code."""
@@ -274,10 +273,10 @@ def run_and_verify_svnversion2(message,
 
   verify.verify_outputs("Unexpected output", out, err,
                         expected_stdout, expected_stderr)
-  verify.verify_exit_code(message, exit_code, expected_exit)
+  verify.verify_exit_code("Unexpected return code", exit_code, expected_exit)
   return exit_code, out, err
 
-def run_and_verify_svn(message, expected_stdout, expected_stderr, *varargs):
+def run_and_verify_svn(expected_stdout, expected_stderr, *varargs):
   """like run_and_verify_svn2, but the expected exit code is assumed to
   be 0 if no output is expected on stderr, and 1 otherwise."""
 
@@ -288,10 +287,10 @@ def run_and_verify_svn(message, expected
         expected_exit = 1
     elif expected_stderr != []:
       expected_exit = 1
-  return run_and_verify_svn2(message, expected_stdout, expected_stderr,
+  return run_and_verify_svn2(expected_stdout, expected_stderr,
                              expected_exit, *varargs)
 
-def run_and_verify_svn2(message, expected_stdout, expected_stderr,
+def run_and_verify_svn2(expected_stdout, expected_stderr,
                         expected_exit, *varargs):
   """Invoke main.run_svn() with *VARARGS. Return exit code as int; stdout,
   stderr as lists of lines (including line terminators).  For both
@@ -306,7 +305,7 @@ def run_and_verify_svn2(message, expecte
      - If it is already an instance of ExpectedOutput
        (e.g. UnorderedOutput), leave it alone.
 
-  ...and invoke compare_and_display_lines() on MESSAGE, a label based
+  ...and invoke compare_and_display_lines() on a label based
   on the name of the stream being compared (e.g. STDOUT), the
   ExpectedOutput instance, and the actual output.
 
@@ -328,8 +327,9 @@ def run_and_verify_svn2(message, expecte
     want_err = True
 
   exit_code, out, err = main.run_svn(want_err, *varargs)
-  verify.verify_outputs(message, out, err, expected_stdout, expected_stderr)
-  verify.verify_exit_code(message, exit_code, expected_exit)
+  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_load(repo_dir, dump_file_content,
@@ -338,28 +338,22 @@ def run_and_verify_load(repo_dir, dump_f
   if not isinstance(dump_file_content, list):
     raise TypeError("dump_file_content argument should have list type")
   expected_stderr = []
+  args = ()
   if bypass_prop_validation:
-    exit_code, output, errput = main.run_command_stdin(
-      main.svnadmin_binary, expected_stderr, 0, True, dump_file_content,
-      'load', '--force-uuid', '--quiet', '--bypass-prop-validation', repo_dir)
-  else:
-    exit_code, output, errput = main.run_command_stdin(
-      main.svnadmin_binary, expected_stderr, 0, True, dump_file_content,
-      'load', '--force-uuid', '--quiet', repo_dir)
-
-  verify.verify_outputs("Unexpected stderr output", None, errput,
-                        None, expected_stderr)
+    args += ('--bypass-prop-validation',)
+  main.run_command_stdin(
+    main.svnadmin_binary, expected_stderr, 0, True, dump_file_content,
+    'load', '--force-uuid', '--quiet', repo_dir, *args)
 
 
 def run_and_verify_dump(repo_dir, deltas=False):
   "Runs 'svnadmin dump' and reports any errors, returning the dump content."
+  args = ()
   if deltas:
-    exit_code, output, errput = main.run_svnadmin('dump', '--deltas',
-                                                  repo_dir)
-  else:
-    exit_code, output, errput = main.run_svnadmin('dump', repo_dir)
-  verify.verify_outputs("Missing expected output(s)", output, errput,
-                        verify.AnyOutput, verify.AnyOutput)
+    args += ('--deltas',)
+  exit_code, output, errput = run_and_verify_svnadmin(
+                                verify.AnyOutput, [],
+                                'dump', '--quiet', repo_dir, *args)
   return output
 
 
@@ -374,6 +368,8 @@ def run_and_verify_svnrdump(dumpfile_con
   if sys.platform == 'win32':
     err = map(lambda x : x.replace('\r\n', '\n'), err)
 
+  # Ignore "consider upgrade" warnings to allow regression tests to pass
+  # when run against a 1.6 mod_dav_svn.
   for index, line in enumerate(err[:]):
     if re.search("warning: W200007", line):
       del err[index]
@@ -384,45 +380,73 @@ def run_and_verify_svnrdump(dumpfile_con
   return output
 
 
-def run_and_verify_svnmover(message, expected_stdout, expected_stderr,
+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(message, expected_stdout, expected_stderr,
+  return run_and_verify_svnmover2(expected_stdout, expected_stderr,
                                   expected_exit, *varargs)
 
-def run_and_verify_svnmover2(message, expected_stdout, expected_stderr,
+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(message, exit_code, expected_exit)
+  verify.verify_exit_code("Unexpected return code", exit_code, expected_exit)
   return exit_code, out, err
 
 
-def run_and_verify_svnmucc(message, expected_stdout, expected_stderr,
+def run_and_verify_svnmucc(expected_stdout, expected_stderr,
                            *varargs):
   """Run svnmucc command and check its output"""
 
   expected_exit = 0
   if expected_stderr is not None and expected_stderr != []:
     expected_exit = 1
-  return run_and_verify_svnmucc2(message, expected_stdout, expected_stderr,
+  return run_and_verify_svnmucc2(expected_stdout, expected_stderr,
                                  expected_exit, *varargs)
 
-def run_and_verify_svnmucc2(message, expected_stdout, expected_stderr,
+def run_and_verify_svnmucc2(expected_stdout, expected_stderr,
                             expected_exit, *varargs):
   """Run svnmucc command and check its output and exit code."""
 
   exit_code, out, err = main.run_svnmucc(*varargs)
   verify.verify_outputs("Unexpected output", out, err,
                         expected_stdout, expected_stderr)
-  verify.verify_exit_code(message, exit_code, expected_exit)
+  verify.verify_exit_code("Unexpected return code", exit_code, expected_exit)
+  return exit_code, out, err
+
+
+def run_and_verify_svnsync(expected_stdout, expected_stderr,
+                           *varargs):
+  """Run svnsync command and check its output"""
+
+  expected_exit = 0
+  if expected_stderr is not None and expected_stderr != []:
+    expected_exit = 1
+  return run_and_verify_svnsync2(expected_stdout, expected_stderr,
+                                 expected_exit, *varargs)
+
+def run_and_verify_svnsync2(expected_stdout, expected_stderr,
+                            expected_exit, *varargs):
+  """Run svnmucc command and check its output and exit code."""
+
+  exit_code, out, err = main.run_svnsync(*varargs)
+
+  # Ignore "consider upgrade" warnings to allow regression tests to pass
+  # when run against a 1.6 mod_dav_svn.
+  for index, line in enumerate(err[:]):
+    if re.search("warning: W200007", line):
+      del err[index]
+
+  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
 
 
@@ -440,7 +464,7 @@ def load_repo(sbox, dumpfile_path = None
   # Load the mergetracking dumpfile into the repos, and check it out the repo
   run_and_verify_load(sbox.repo_dir, dump_str.splitlines(True),
                       bypass_prop_validation)
-  run_and_verify_svn(None, None, [], "co", sbox.repo_url, sbox.wc_dir)
+  run_and_verify_svn(None, [], "co", sbox.repo_url, sbox.wc_dir)
 
   return dump_str
 
@@ -452,7 +476,7 @@ def expected_noop_update_output(rev):
                                      % (rev),
                                      "no-op update")
 
-def run_and_verify_svnauthz(message, expected_stdout, expected_stderr,
+def run_and_verify_svnauthz(expected_stdout, expected_stderr,
                             expected_exit, compat_mode, *varargs):
   """Run svnauthz command and check its output and exit code.
      If COMPAT_MODE is True then run the command in pre-1.8
@@ -465,7 +489,7 @@ def run_and_verify_svnauthz(message, exp
 
   verify.verify_outputs("Unexpected output", out, err,
                         expected_stdout, expected_stderr)
-  verify.verify_exit_code(message, exit_code, expected_exit)
+  verify.verify_exit_code("Unexpected return code", exit_code, expected_exit)
   return exit_code, out, err
 
 ######################################################################
@@ -714,14 +738,12 @@ class LogParser:
     self.entries[-1].changed_paths[self.use_cdata()] = [{'kind': self.kind,
                                                          'action': self.action}]
 
-def run_and_verify_log_xml(message=None, expected_log_attrs=None,
+def run_and_verify_log_xml(expected_log_attrs=None,
                            expected_paths=None, expected_revprops=None,
                            expected_stdout=None, expected_stderr=None,
                            args=[]):
   """Call run_and_verify_svn with log --xml and args (optional) as command
-  arguments, and pass along message, expected_stdout, and expected_stderr.
-
-  If message is None, pass the svn log command as message.
+  arguments, and pass along expected_stdout, and expected_stderr.
 
   expected_paths checking is not yet implemented.
 
@@ -737,8 +759,7 @@ def run_and_verify_log_xml(message=None,
   expected_paths and expected_revprops are ignored if expected_stdout or
   expected_stderr is specified.
   """
-  if message == None:
-    message = ' '.join(args)
+  message = ' '.join(args)
 
   # We'll parse the output unless the caller specifies expected_stderr or
   # expected_stdout for run_and_verify_svn.
@@ -755,7 +776,7 @@ def run_and_verify_log_xml(message=None,
     log_args.append('-v')
 
   (exit_code, stdout, stderr) = run_and_verify_svn(
-    message, expected_stdout, expected_stderr,
+    expected_stdout, expected_stderr,
     'log', '--xml', *log_args)
   if not parse:
     return
@@ -1594,7 +1615,7 @@ def run_and_verify_status_xml(expected_e
   EXPECTED_ENTRIES.
   """
 
-  exit_code, output, errput = run_and_verify_svn(None, None, [],
+  exit_code, output, errput = run_and_verify_svn(None, [],
                                                  'status', '--xml', *args)
 
   if len(errput) > 0:
@@ -1666,11 +1687,11 @@ def run_and_verify_inherited_prop_xml(pa
 
   if (propname):
     exit_code, output, errput = svntest.actions.run_and_verify_svn(
-      None, None, [], 'propget', propname, '--xml',
+      None, [], 'propget', propname, '--xml',
       '--show-inherited-props', path_or_url, *args)
   else:
     exit_code, output, errput = svntest.actions.run_and_verify_svn(
-      None, None, [], 'proplist', '-v', '--xml', '--show-inherited-props',
+      None, [], 'proplist', '-v', '--xml', '--show-inherited-props',
       path_or_url, *args)
 
   if len(errput) > 0:
@@ -1743,7 +1764,7 @@ def run_and_verify_diff_summarize_xml(er
   EXPECTED_PROPS and EXPECTED_KINDS. Returns on success, raises
   on failure."""
 
-  exit_code, output, errput = run_and_verify_svn(None, None, error_re_string,
+  exit_code, output, errput = run_and_verify_svn(None, error_re_string,
                                                  'diff', '--summarize',
                                                  '--xml', *args)
 
@@ -1827,12 +1848,12 @@ def run_and_validate_lock(path, username
   comment = "Locking path:%s." % path
 
   # lock the path
-  run_and_verify_svn(None, ".*locked by user", [], 'lock',
+  run_and_verify_svn(".*locked by user", [], 'lock',
                      '--username', username,
                      '-m', comment, path)
 
   # Run info and check that we get the lock fields.
-  exit_code, output, err = run_and_verify_svn(None, None, [],
+  exit_code, output, err = run_and_verify_svn(None, [],
                                               'info','-R',
                                               path)
 
@@ -1870,7 +1891,7 @@ def _run_and_verify_resolve(cmd, expecte
         expected_paths]),
     ],
     match_all=False)
-  run_and_verify_svn(None, expected_output, [],
+  run_and_verify_svn(expected_output, [],
                      cmd, *args)
 
 def run_and_verify_resolve(expected_paths, *args):
@@ -1894,7 +1915,7 @@ def run_and_verify_revert(expected_paths
   expected_output = verify.UnorderedOutput([
     "Reverted '" + path + "'\n" for path in
     expected_paths])
-  run_and_verify_svn(None, expected_output, [],
+  run_and_verify_svn(expected_output, [],
                      "revert", *args)
 
 
@@ -1903,32 +1924,44 @@ 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,
-                     minor_version = None):
-  """Create a fresh 'Greek Tree' repository and check out a WC from it.
+def make_repo_and_wc(sbox, create_wc=True, read_only=False, empty=False,
+                     minor_version=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.
 
   If READ_ONLY is False, a dedicated repository will be created, at the path
-  SBOX.repo_dir.  If READ_ONLY is True, the pristine repository will be used.
+  SBOX.repo_dir.  If READ_ONLY is True, a shared pristine repository may be
+  used or a dedicated repository may be created.  (Currently we use a shared
+  pristine 'Greek tree' repo but we create a dedicated empty repo.)
   In either case, SBOX.repo_url is assumed to point to the repository that
   will be used.
 
-  If create_wc is True, a dedicated working copy will be checked out from
+  If CREATE_WC is True, a dedicated working copy will be checked out from
   the repository, at the path SBOX.wc_dir.
 
   Returns on success, raises on failure."""
 
-  # Create (or copy afresh) a new repos with a greek tree in it.
-  if not read_only:
-    guarantee_greek_repository(sbox.repo_dir, minor_version)
+  # Create or copy or reference the appropriate kind of repository:
+  # if we want a non-empty, Greek repo, refer to the shared one; else
+  # if we want an empty repo or a writable Greek repo, create one.
+  # (We could have a shared empty repo for read-only use, but we don't.)
+  if empty:
+    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 create_wc:
     # Generate the expected output tree.
-    expected_output = main.greek_state.copy()
+    expected_output = expected_state.copy()
     expected_output.wc_dir = sbox.wc_dir
     expected_output.tweak(status='A ', contents=None)
 
     # Generate an expected wc tree.
-    expected_wc = main.greek_state
+    expected_wc = expected_state
 
     # Do a checkout, and verify the resulting output and disk contents.
     run_and_verify_checkout(sbox.repo_url,
@@ -2278,6 +2311,6 @@ def build_greek_tree_conflicts(sbox):
   # Update, receiving the incoming changes on top of the local changes,
   # causing tree conflicts.  Don't check for any particular result: that is
   # the job of other tests.
-  run_and_verify_svn(None, verify.AnyOutput, [], 'update', wc_dir)
+  run_and_verify_svn(verify.AnyOutput, [], 'update', wc_dir)
 
 

Modified: subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/deeptrees.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/deeptrees.py?rev=1658462&r1=1658461&r2=1658462&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/deeptrees.py (original)
+++ subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/deeptrees.py Mon Feb  9 16:46:16 2015
@@ -123,13 +123,13 @@ def deep_trees_leaf_edit(base):
   main.file_append(F, "More text for file alpha.\n")
   main.file_append(DF, "More text for file beta.\n")
   main.file_append(DDF, "More text for file gamma.\n")
-  run_and_verify_svn(None, verify.AnyOutput, [],
+  run_and_verify_svn(verify.AnyOutput, [],
                      'propset', 'prop1', '1', F, DF, DDF)
 
   D   = j(base, 'D', 'D1')
   DD  = j(base, 'DD', 'D1', 'D2')
   DDD = j(base, 'DDD', 'D1', 'D2', 'D3')
-  run_and_verify_svn(None, verify.AnyOutput, [],
+  run_and_verify_svn(verify.AnyOutput, [],
                      'propset', 'prop1', '1', D, DD, DDD)
   D   = j(base, 'D', 'D1', 'delta')
   DD  = j(base, 'DD', 'D1', 'D2', 'epsilon')
@@ -137,7 +137,7 @@ def deep_trees_leaf_edit(base):
   main.file_append(D, "This is the file 'delta'.\n")
   main.file_append(DD, "This is the file 'epsilon'.\n")
   main.file_append(DDD, "This is the file 'zeta'.\n")
-  run_and_verify_svn(None, verify.AnyOutput, [],
+  run_and_verify_svn(verify.AnyOutput, [],
                      'add', D, DD, DDD)
 
 # deep trees state after a call to deep_trees_leaf_edit

Modified: subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/factory.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/factory.py?rev=1658462&r1=1658461&r2=1658462&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/factory.py (original)
+++ subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/factory.py Mon Feb  9 16:46:16 2015
@@ -500,7 +500,7 @@ class TestFactory:
       else:
         py = "expected_stdout = verify.UnorderedOutput(" + pylist + ")\n\n"
       py += pychdir
-      py += "actions.run_and_verify_svn2('OUTPUT', expected_stdout, [], 0"
+      py += "actions.run_and_verify_svn2(expected_stdout, [], 0"
     else:
       # write a test that expects failure
       pylist = self.strlist2py(err)
@@ -509,8 +509,7 @@ class TestFactory:
       else:
         py = "expected_stderr = verify.UnorderedOutput(" + pylist + ")\n\n"
       py += pychdir
-      py += ("actions.run_and_verify_svn2('OUTPUT', " +
-             "[], expected_stderr, " + str(code))
+      py += ("actions.run_and_verify_svn2([], expected_stderr, " + str(code))
 
     if len(pyargs) > 0:
       py += ", " + ", ".join(pyargs)
@@ -775,8 +774,7 @@ class TestFactory:
       else:
         py += "expected_stderr = verify.UnorderedOutput(" + pylist + ")\n\n"
       py += pychdir
-      py += ("actions.run_and_verify_svn2('OUTPUT', " +
-             "[], expected_stderr, " + str(code) +
+      py += ("actions.run_and_verify_svn2([], expected_stderr, " + str(code) +
              ", " + url_arg.pyarg + ", " + wc_arg.pyarg)
 
     # Append the remaining args

Modified: subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/main.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/main.py?rev=1658462&r1=1658461&r2=1658462&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/main.py (original)
+++ subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/main.py Mon Feb  9 16:46:16 2015
@@ -132,6 +132,10 @@ else:
 wc_author = 'jrandom'
 wc_passwd = 'rayjandom'
 
+# Username and password used by svnrdump in dump/load cross-checks
+crosscheck_username = '__dumpster__'
+crosscheck_password = '__loadster__'
+
 # Username and password used by the working copies for "second user"
 # scenarios
 wc_author2 = 'jconstant' # use the same password as wc_author
@@ -694,14 +698,25 @@ def _with_config_dir(args):
   else:
     return args + ('--config-dir', default_config_dir)
 
+class svnrdump_crosscheck_authentication:
+  pass
+
 def _with_auth(args):
   assert '--password' not in args
-  args = args + ('--password', wc_passwd,
+  if svnrdump_crosscheck_authentication in args:
+    args = filter(lambda x: x is not svnrdump_crosscheck_authentication, args)
+    auth_username = crosscheck_username
+    auth_password = crosscheck_password
+  else:
+    auth_username = wc_author
+    auth_password = wc_passwd
+
+  args = args + ('--password', auth_password,
                  '--no-auth-cache' )
   if '--username' in args:
     return args
   else:
-    return args + ('--username', wc_author )
+    return args + ('--username', auth_username )
 
 # For running subversion and returning the output
 def run_svn(error_expected, *varargs):
@@ -749,7 +764,8 @@ def run_svnrdump(stdin_input, *varargs):
 def run_svnsync(*varargs):
   """Run svnsync with VARARGS, returns exit code as int; stdout, stderr as
   list of lines (including line terminators)."""
-  return run_command(svnsync_binary, 1, False, *(_with_config_dir(varargs)))
+  return run_command(svnsync_binary, 1, False,
+                     *(_with_auth(_with_config_dir(varargs))))
 
 def run_svnversion(*varargs):
   """Run svnversion with VARARGS, returns exit code as int; stdout, stderr
@@ -941,8 +957,13 @@ def _post_create_repos(path, minor_versi
     # This actually creates TWO [users] sections in the file (one of them is
     # uncommented in `svnadmin create`'s template), so we exercise the .ini
     # files reading code's handling of duplicates, too. :-)
-    file_append(os.path.join(path, "conf", "passwd"),
-                "[users]\njrandom = rayjandom\njconstant = rayjandom\n");
+    users = ("[users]\n"
+             "jrandom = rayjandom\n"
+             "jconstant = rayjandom\n")
+    if tests_verify_dump_load_cross_check():
+      # Insert a user for the dump/load cross-check.
+      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':
     # fsfs.conf file
@@ -1208,7 +1229,7 @@ def write_restrictive_svnserve_conf_with
 # parallel execution at the bottom like so
 #   if __name__ == '__main__':
 #     svntest.main.run_tests(test_list, serial_only = True)
-def write_authz_file(sbox, rules, sections=None):
+def write_authz_file(sbox, rules, sections=None, prefixed_rules=None):
   """Write an authz file to SBOX, appropriate for the RA method used,
 with authorizations rules RULES mapping paths to strings containing
 the rules. You can add sections SECTIONS (ex. groups, aliases...) with
@@ -1216,23 +1237,37 @@ an appropriate list of mappings.
 """
   fp = open(sbox.authz_file, 'w')
 
-  # When the sandbox repository is read only it's name will be different from
+  # When the sandbox repository is read only its name will be different from
   # the repository name.
-  repo_name = sbox.repo_dir
-  while repo_name[-1] == '/':
-    repo_name = repo_name[:-1]
-  repo_name = os.path.basename(repo_name)
+  repo_name = os.path.basename(sbox.repo_dir.rstrip('/'))
 
   if sbox.repo_url.startswith("http"):
-    prefix = repo_name + ":"
+    default_prefix = repo_name + ":"
   else:
-    prefix = ""
+    default_prefix = ""
+
   if sections:
     for p, r in sections.items():
       fp.write("[%s]\n%s\n" % (p, r))
 
-  for p, r in rules.items():
-    fp.write("[%s%s]\n%s\n" % (prefix, p, r))
+  if not prefixed_rules:
+    prefixed_rules = dict()
+
+  if rules:
+    for p, r in rules.items():
+      prefixed_rules[default_prefix + p] = r
+
+  for p, r in prefixed_rules.items():
+    fp.write("[%s]\n%s\n" % (p, r))
+    if tests_verify_dump_load_cross_check():
+      # Insert an ACE that lets the dump/load cross-check bypass
+      # authz restrictions.
+      fp.write(crosscheck_username + " = rw\n")
+
+  if tests_verify_dump_load_cross_check() and '/' not in prefixed_rules:
+    # We need a repository-root ACE for the dump/load cross-check
+    fp.write("[/]\n" + crosscheck_username + " = rw\n")
+
   fp.close()
 
 # See the warning about parallel test execution in write_authz_file
@@ -1386,6 +1421,9 @@ def make_log_msg():
 def tests_use_prepacakaged_repository():
   return options.fsfs_version is not None
 
+def tests_verify_dump_load_cross_check():
+  return options.dump_load_cross_check
+
 def is_ra_type_dav():
   return options.test_area_url.startswith('http')
 
@@ -1575,6 +1613,8 @@ class TestSpawningThread(threading.Threa
       args.append('--fsfs-packing')
     if options.fsfs_version:
       args.append('--fsfs-version=' + str(options.fsfs_version))
+    if options.dump_load_cross_check:
+      args.append('--dump-load-cross-check')
 
     result, stdout_lines, stderr_lines = spawn_process(command, 0, False, None,
                                                        *args)
@@ -1899,6 +1939,11 @@ def _create_parser():
                     help='Default shard size (for fsfs)')
   parser.add_option('--fsfs-version', type='int', action='store',
                     help='FSFS version (fsfs)')
+  parser.add_option('--dump-load-cross-check', action='store_true',
+                    help="After every test, run a series of dump and load " +
+                         "tests with svnadmin, svnrdump and svndumpfilter " +
+                         " on the testcase repositories to cross-check " +
+                         " dump file compatibility.")
   parser.add_option('--config-file', action='store',
                     help="Configuration file for tests.")
   parser.add_option('--set-log-level', action='callback', type='str',

Modified: subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/mergetrees.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/mergetrees.py?rev=1658462&r1=1658461&r2=1658462&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/mergetrees.py (original)
+++ subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/mergetrees.py Mon Feb  9 16:46:16 2015
@@ -122,7 +122,7 @@ def check_mergeinfo_recursively(root_pat
   expected = verify.UnorderedOutput(
     [path + ' - ' + subpaths_mergeinfo[path] + '\n'
      for path in subpaths_mergeinfo])
-  actions.run_and_verify_svn(None, expected, [],
+  actions.run_and_verify_svn(expected, [],
                                      'propget', '-R', SVN_PROP_MERGEINFO,
                                      root_path)
 
@@ -146,7 +146,7 @@ def set_up_dir_replace(sbox):
   new_file2 = os.path.join(foo_path, "new file 2")
 
   # Make directory foo in F, and add some files within it.
-  actions.run_and_verify_svn(None, None, [], 'mkdir', foo_path)
+  actions.run_and_verify_svn(None, [], 'mkdir', foo_path)
   main.file_append(new_file, "Initial text in new file.\n")
   main.file_append(new_file2, "Initial text in new file 2.\n")
   main.run_svn(None, "add", new_file)
@@ -223,7 +223,7 @@ def set_up_dir_replace(sbox):
                                         None, wc_dir)
 
   # Delete foo on F, creating r4.
-  actions.run_and_verify_svn(None, None, [], 'rm', foo_path)
+  actions.run_and_verify_svn(None, [], 'rm', foo_path)
   expected_output = wc.State(wc_dir, {
     'A/B/F/foo'   : Item(verb='Deleting'),
     })
@@ -327,7 +327,7 @@ def set_up_branch(sbox, branch_only = Fa
       })
 
     # Make a branch A_COPY to merge into.
-    actions.run_and_verify_svn(None, expected, [], 'copy',
+    actions.run_and_verify_svn(expected, [], 'copy',
                                        sbox.repo_url + "/A",
                                        os.path.join(wc_dir,
                                                     dest_name))
@@ -400,22 +400,22 @@ def svn_mkfile(path):
   dirname, filename = os.path.split(path)
   main.file_write(path, "This is the file '" + filename + "'.\n" +
                                 "Last changed in '$Revision$'.\n")
-  actions.run_and_verify_svn(None, None, [], 'add', path)
-  actions.run_and_verify_svn(None, None, [], 'propset',
+  actions.run_and_verify_svn(None, [], 'add', path)
+  actions.run_and_verify_svn(None, [], 'propset',
                                      'svn:keywords', 'Revision', path)
 
 def svn_modfile(path):
   "Make text and property mods to a WC file."
   path = local_path(path)
   main.file_append(path, "An extra line.\n")
-  actions.run_and_verify_svn(None, None, [], 'propset',
+  actions.run_and_verify_svn(None, [], 'propset',
                                      'newprop', 'v', path)
 
 def svn_copy(s_rev, path1, path2):
   "Copy a WC path locally."
   path1 = local_path(path1)
   path2 = local_path(path2)
-  actions.run_and_verify_svn(None, None, [], 'copy', '--parents',
+  actions.run_and_verify_svn(None, [], 'copy', '--parents',
                                      '-r', s_rev, path1, path2)
 
 def svn_merge(rev_range, source, target, lines=None, elides=[],
@@ -462,7 +462,7 @@ def svn_merge(rev_range, source, target,
                                   text_resolved=text_resolved,
                                   prop_resolved=prop_resolved,
                                   tree_resolved=tree_resolved)
-  actions.run_and_verify_svn(None, exp_out, [],
+  actions.run_and_verify_svn(exp_out, [],
                                      'merge', rev_arg, source, target, *args)
 
 #----------------------------------------------------------------------

Modified: subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/objects.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/objects.py?rev=1658462&r1=1658461&r2=1658462&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/objects.py (original)
+++ subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/objects.py Mon Feb  9 16:46:16 2015
@@ -156,7 +156,7 @@ class SvnRepository:
 
     """Run 'svnadmin dump' on the repository."""
     exit_code, stdout, stderr = \
-      actions.run_and_verify_svnadmin(None, None, None,
+      actions.run_and_verify_svnadmin(None, None,
                                       'dump', self.repo_absdir)
     ldumpfile = local_path(output_dir + "/svnadmin.dump")
     main.file_write(ldumpfile, ''.join(stderr))
@@ -167,7 +167,7 @@ class SvnRepository:
     make, and each directory is a path relative to the repository root,
     neither starting nor ending with a slash."""
     urls = [self.repo_url + '/' + dir for dir in dirs]
-    actions.run_and_verify_svn(None, None, [],
+    actions.run_and_verify_svn(None, [],
                                'mkdir', '-m', 'svn_mkdirs()', '--parents',
                                *urls)
     self.head_rev += 1
@@ -207,7 +207,7 @@ class SvnWC:
 
   def svn_mkdir(self, rpath):
     lpath = local_path(rpath)
-    actions.run_and_verify_svn(None, None, [], 'mkdir', lpath)
+    actions.run_and_verify_svn(None, [], 'mkdir', lpath)
 
     self.state.add({
       rpath : wc.StateItem(status='A ')
@@ -216,7 +216,7 @@ class SvnWC:
 #  def propset(self, pname, pvalue, *rpaths):
 #    "Set property 'pname' to value 'pvalue' on each path in 'rpaths'"
 #    local_paths = tuple([local_path(rpath) for rpath in rpaths])
-#    actions.run_and_verify_svn(None, None, [], 'propset', pname, pvalue,
+#    actions.run_and_verify_svn(None, [], 'propset', pname, pvalue,
 #                               *local_paths)
 
   def svn_set_props(self, rpath, props):
@@ -224,10 +224,10 @@ class SvnWC:
     """
     lpath = local_path(rpath)
     #for prop in path's existing props:
-    #  actions.run_and_verify_svn(None, None, [], 'propdel',
+    #  actions.run_and_verify_svn(None, [], 'propdel',
     #                             prop, lpath)
     for prop in props:
-      actions.run_and_verify_svn(None, None, [], 'propset',
+      actions.run_and_verify_svn(None, [], 'propset',
                                  prop, props[prop], lpath)
     self.state.tweak(rpath, props=props)
 
@@ -240,7 +240,7 @@ class SvnWC:
       content = "This is the file '" + filename + "'.\n" + \
                 "Last changed in '$Revision$'.\n"
     main.file_write(lpath, content)
-    actions.run_and_verify_svn(None, None, [], 'add', lpath)
+    actions.run_and_verify_svn(None, [], 'add', lpath)
 
     self.state.add({
       rpath : wc.StateItem(status='A ')
@@ -257,7 +257,7 @@ class SvnWC:
     lpath = local_path(rpath)
     if content is not None:
       #main.file_append(lpath, "An extra line.\n")
-      #actions.run_and_verify_svn(None, None, [], 'propset',
+      #actions.run_and_verify_svn(None, [], 'propset',
       #                           'newprop', 'v', lpath)
       main.file_write(lpath, content)
       self.state.tweak(rpath, content=content)
@@ -274,7 +274,7 @@ class SvnWC:
     args = [lpath1, lpath2]
     if parents:
       args += ['--parents']
-    actions.run_and_verify_svn(None, None, [], 'copy', *args)
+    actions.run_and_verify_svn(None, [], 'copy', *args)
     self.state.add({
       rpath2: self.state.desc[rpath1]
     })
@@ -292,7 +292,7 @@ class SvnWC:
       args += ['-r', rev]
     if parents:
       args += ['--parents']
-    actions.run_and_verify_svn(None, None, [], 'copy', *args)
+    actions.run_and_verify_svn(None, [], 'copy', *args)
     self.state.add({
       rpath2: self.state.desc[rpath1]
     })
@@ -303,12 +303,12 @@ class SvnWC:
     args = []
     if even_if_modified:
       args += ['--force']
-    actions.run_and_verify_svn(None, None, [], 'delete', lpath, *args)
+    actions.run_and_verify_svn(None, [], 'delete', lpath, *args)
 
   def svn_commit(self, rpath='', log=''):
     "Commit a WC path (recursively). Return the new revision number."
     lpath = local_path(rpath)
-    actions.run_and_verify_svn(None, verify.AnyOutput, [],
+    actions.run_and_verify_svn(verify.AnyOutput, [],
                                'commit', '-m', log, lpath)
     actions.run_and_verify_update(lpath, None, None, None)
     self.repo.head_rev += 1
@@ -332,6 +332,6 @@ class SvnWC:
 #      exp_1 = "--- Merging r.* into '" + target_re + ".*':"
 #      exp_2 = "(A |D |[UG] | [UG]|[UG][UG])   " + target_re + ".*"
 #      exp_out = verify.RegexOutput(exp_1 + "|" + exp_2)
-#    actions.run_and_verify_svn(None, exp_out, [],
+#    actions.run_and_verify_svn(exp_out, [],
 #                               'merge', rev_spec, lsource, ltarget)
 

Modified: subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/sandbox.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/sandbox.py?rev=1658462&r1=1658461&r2=1658462&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/sandbox.py (original)
+++ subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/sandbox.py Mon Feb  9 16:46:16 2015
@@ -26,12 +26,67 @@ import shutil
 import copy
 import urllib
 import logging
+import re
 
 import svntest
 
 logger = logging.getLogger()
 
 
+def make_mirror(sbox, source_prop_encoding=None):
+  """Make a mirror of the repository in SBOX.
+  """
+  # Set up the mirror repository.
+  dest_sbox = sbox.clone_dependent()
+  dest_sbox.build(create_wc=False, empty=True)
+  exit_code, output, errput = svntest.main.run_svnlook("uuid", sbox.repo_dir)
+  svntest.actions.run_and_verify_svnadmin2(None, None, 0,
+                                           'setuuid', dest_sbox.repo_dir,
+                                           output[0][:-1])
+  svntest.actions.enable_revprop_changes(dest_sbox.repo_dir)
+
+  repo_url = sbox.repo_url
+  dest_repo_url = dest_sbox.repo_url
+
+  # Synchronize it.
+  args = (svntest.main.svnrdump_crosscheck_authentication,)
+  if source_prop_encoding:
+    args = args + ("--source-prop-encoding=" + source_prop_encoding,)
+  svntest.actions.run_and_verify_svnsync(svntest.verify.AnyOutput, [],
+                                         "initialize",
+                                         dest_repo_url, repo_url, *args)
+  svntest.actions.run_and_verify_svnsync(None, [],
+                                         "synchronize",
+                                         dest_repo_url, repo_url, *args)
+
+  return dest_sbox
+
+def verify_mirror(repo_url, repo_dir, expected_dumpfile):
+  """Compare the repository content at REPO_URL/REPO_DIR with that in
+     EXPECTED_DUMPFILE (which is a non-delta dump).
+  """
+  # Remove some SVNSync-specific housekeeping properties from the
+  # mirror repository in preparation for the comparison dump.
+  for prop_name in ("svn:sync-from-url", "svn:sync-from-uuid",
+                    "svn:sync-last-merged-rev"):
+    svntest.actions.run_and_verify_svn(
+      None, [], "propdel", "--revprop", "-r", "0",
+      prop_name, repo_url)
+  # Create a dump file from the mirror repository.
+  dumpfile_s_n = svntest.actions.run_and_verify_dump(repo_dir)
+  # Compare the mirror's dumpfile, ignoring any expected differences:
+  # The original dumpfile in some cases lacks 'Text-content-sha1' headers;
+  # the mirror dump always has them -- ### Why?
+  svnsync_headers_always = re.compile("Text-content-sha1: ")
+  dumpfile_a_n_cmp = [l for l in expected_dumpfile
+                      if not svnsync_headers_always.match(l)]
+  dumpfile_s_n_cmp = [l for l in dumpfile_s_n
+                      if not svnsync_headers_always.match(l)]
+  svntest.verify.compare_dump_files(None, None,
+                                    dumpfile_a_n_cmp,
+                                    dumpfile_s_n_cmp)
+
+
 class Sandbox:
   """Manages a sandbox (one or more repository/working copy pairs) for
   a test to operate within."""
@@ -46,7 +101,9 @@ class Sandbox:
     # This flag is set to True by build() and returned by is_built()
     self._is_built = False
 
-  def _set_name(self, name, read_only=False):
+    self.was_cwd = os.getcwd()
+
+  def _set_name(self, name, read_only=False, empty=False):
     """A convenience method for renaming a sandbox, useful when
     working with multiple repositories in the same unit test."""
     if not name is None:
@@ -54,7 +111,7 @@ class Sandbox:
     self.read_only = read_only
     self.wc_dir = os.path.join(svntest.main.general_wc_dir, self.name)
     self.add_test_path(self.wc_dir)
-    if not read_only:
+    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))
@@ -88,14 +145,16 @@ class Sandbox:
       shutil.copytree(self.wc_dir, clone.wc_dir, symlinks=True)
     return clone
 
-  def build(self, name=None, create_wc=True, read_only=False,
+  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,
        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)
+    self._set_name(name, read_only, empty)
     self._ensure_authz()
-    svntest.actions.make_repo_and_wc(self, create_wc, read_only, minor_version)
+    svntest.actions.make_repo_and_wc(self, create_wc, read_only, empty,
+                                     minor_version)
     self._is_built = True
 
   def _ensure_authz(self):
@@ -376,11 +435,128 @@ class Sandbox:
 
   def youngest(self):
     _, output, _ = svntest.actions.run_and_verify_svnlook(
-                     None, svntest.verify.AnyOutput, [],
+                     svntest.verify.AnyOutput, [],
                      'youngest', self.repo_dir)
     youngest = int(output[0])
     return youngest
 
+  def verify_repo(self):
+    """
+    """
+    svnrdump_headers_missing = re.compile(
+        "Text-content-sha1: .*|Text-copy-source-md5: .*|"
+        "Text-copy-source-sha1: .*|Text-delta-base-sha1: .*"
+    )
+    svnrdump_headers_always = re.compile(
+        "Prop-delta: .*"
+    )
+
+    dumpfile_a_n = svntest.actions.run_and_verify_dump(self.repo_dir,
+                                                       deltas=False)
+    dumpfile_a_d = svntest.actions.run_and_verify_dump(self.repo_dir,
+                                                       deltas=True)
+    dumpfile_r_d = svntest.actions.run_and_verify_svnrdump(
+      None, svntest.verify.AnyOutput, [], 0, 'dump', '-q', self.repo_url,
+      svntest.main.svnrdump_crosscheck_authentication)
+
+    # Compare the two deltas dumpfiles, ignoring expected differences
+    dumpfile_a_d_cmp = [l for l in dumpfile_a_d
+                       if not svnrdump_headers_missing.match(l)
+                                and not svnrdump_headers_always.match(l)]
+    dumpfile_r_d_cmp = [l for l in dumpfile_r_d
+                       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,
+                                      dumpfile_a_d_cmp,
+                                      dumpfile_r_d_cmp,
+                                      ignore_number_of_blank_lines=True)
+
+    # Try loading the dump files.
+    # For extra points, load each with the other tool:
+    #   svnadmin dump | svnrdump load
+    #   svnrdump dump | svnadmin load
+    repo_dir_a_n, repo_url_a_n = self.add_repo_path('load_a_n')
+    svntest.main.create_repos(repo_dir_a_n)
+    svntest.actions.enable_revprop_changes(repo_dir_a_n)
+    svntest.actions.run_and_verify_svnrdump(
+      dumpfile_a_n, svntest.verify.AnyOutput, [], 0, 'load', repo_url_a_n,
+      svntest.main.svnrdump_crosscheck_authentication)
+
+    repo_dir_a_d, repo_url_a_d = self.add_repo_path('load_a_d')
+    svntest.main.create_repos(repo_dir_a_d)
+    svntest.actions.enable_revprop_changes(repo_dir_a_d)
+    svntest.actions.run_and_verify_svnrdump(
+      dumpfile_a_d, svntest.verify.AnyOutput, [], 0, 'load', repo_url_a_d,
+      svntest.main.svnrdump_crosscheck_authentication)
+
+    repo_dir_r_d, repo_url_r_d = self.add_repo_path('load_r_d')
+    svntest.main.create_repos(repo_dir_r_d)
+    svntest.actions.run_and_verify_load(repo_dir_r_d, dumpfile_r_d)
+
+    # Dump the loaded repositories in the same way; expect exact equality
+    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,
+                                      reloaded_dumpfile_a_n,
+                                      reloaded_dumpfile_a_d,
+                                      ignore_uuid=True)
+    svntest.verify.compare_dump_files(None, None,
+                                      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
+                     ]:
+      ### 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:
+        continue
+
+      exit_code, dumpfile2, errput = svntest.main.run_command_stdin(
+        svntest.main.svndumpfilter_binary, None, -1, True,
+        dumpfile, '--quiet', 'include', '/')
+      assert not exit_code and not errput
+      # Ignore empty prop sections in the input file during comparison, as
+      # 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,
+                                        expect_content_length_always=True,
+                                        ignore_empty_prop_sections=True,
+                                        ignore_number_of_blank_lines=True)
+
+    # Run the repository through 'svnsync' and check that this does not
+    # change the repository content. (Don't bother if it's already been
+    # created by svnsync.)
+    if "svn:sync-from-url\n" not in dumpfile_a_n:
+      dest_sbox = make_mirror(self)
+      verify_mirror(dest_sbox.repo_url, dest_sbox.repo_dir, dumpfile_a_n)
+
+  def verify(self, skip_cross_check=False):
+    """Do additional testing that should hold for any sandbox, such as
+       verifying that the repository can be dumped.
+    """
+    if (not skip_cross_check
+        and svntest.main.tests_verify_dump_load_cross_check()):
+      if self.is_built() and not self.read_only:
+        # verify that we can in fact dump the repo
+        # (except for the few tests that deliberately corrupt the repo)
+        os.chdir(self.was_cwd)
+        if os.path.exists(self.repo_dir):
+          logger.info("VERIFY: running dump/load cross-check")
+          self.verify_repo()
+      else:
+        logger.info("VERIFY: WARNING: skipping dump/load cross-check:"
+                    " is-built=%s, read-only=%s"
+                    % (self.is_built() and "true" or "false",
+                       self.read_only and "true" or "false"))
+    pass
+
 def is_url(target):
   return (target.startswith('^/')
           or target.startswith('file://')

Modified: subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/testcase.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/testcase.py?rev=1658462&r1=1658461&r2=1658462&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/testcase.py (original)
+++ subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/testcase.py Mon Feb  9 16:46:16 2015
@@ -28,7 +28,8 @@ import os, types, sys
 import svntest
 
 # if somebody does a "from testcase import *", they only get these names
-__all__ = ['_XFail', '_Wimp', '_Skip', '_SkipUnless']
+__all__ = ['_XFail', '_Wimp', '_Skip', '_SkipUnless',
+           '_SkipDumpLoadCrossCheck']
 
 RESULT_OK = 'ok'
 RESULT_FAIL = 'fail'
@@ -135,7 +136,7 @@ class FunctionTestCase(TestCase):
   is derived from the file name in which FUNC was defined)
   """
 
-  def __init__(self, func, issues=None):
+  def __init__(self, func, issues=None, skip_cross_check=False):
     # it better be a function that accepts an sbox parameter and has a
     # docstring on it.
     assert isinstance(func, types.FunctionType)
@@ -161,6 +162,7 @@ class FunctionTestCase(TestCase):
 
     TestCase.__init__(self, doc=doc, issues=issues)
     self.func = func
+    self.skip_cross_check = skip_cross_check
 
   def get_function_name(self):
     return self.func.func_name
@@ -173,7 +175,9 @@ class FunctionTestCase(TestCase):
     return os.path.splitext(os.path.basename(filename))[0]
 
   def run(self, sandbox):
-    return self.func(sandbox)
+    result = self.func(sandbox)
+    sandbox.verify(skip_cross_check = self.skip_cross_check)
+    return result
 
 
 class _XFail(TestCase):
@@ -261,11 +265,22 @@ class _SkipUnless(_Skip):
     _Skip.__init__(self, test_case, lambda c=cond_func: not c())
 
 
-def create_test_case(func, issues=None):
+class _SkipDumpLoadCrossCheck(TestCase):
+  """A test that will skip the post-test dump/load cross-check."""
+
+  def __init__(self, test_case, cond_func=lambda: True, wip=None,
+               issues=None):
+    TestCase.__init__(self,
+                      create_test_case(test_case, skip_cross_check=True),
+                      cond_func, wip=wip, issues=issues)
+
+
+def create_test_case(func, issues=None, skip_cross_check=False):
   if isinstance(func, TestCase):
     return func
   else:
-    return FunctionTestCase(func, issues=issues)
+    return FunctionTestCase(func, issues=issues,
+                            skip_cross_check=skip_cross_check)
 
 
 # Various decorators to make declaring tests as such simpler
@@ -322,5 +337,15 @@ def Issues_deco(*issues):
 
   return _second
 
+def SkipDumpLoadCrossCheck_deco(cond_func = lambda: True):
+  def _second(func):
+    if isinstance(func, TestCase):
+      return _SkipDumpLoadCrossCheck(func, cond_func, issues=func.issues)
+    else:
+      return _SkipDumpLoadCrossCheck(func, cond_func)
+
+  return _second
+
+
 # Create a singular alias, for linguistic correctness
 Issue_deco = Issues_deco

Modified: subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/verify.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/verify.py?rev=1658462&r1=1658461&r2=1658462&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/verify.py (original)
+++ subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/verify.py Mon Feb  9 16:46:16 2015
@@ -474,8 +474,10 @@ class DumpParser:
     if not m:
       if required:
         raise SVNDumpParseError("expected '%s' at line %d\n%s"
+                                "\nPrevious lines:\n%s"
                                 % (regex, self.current,
-                                   self.lines[self.current]))
+                                   self.lines[self.current],
+                                   ''.join(self.lines[max(0,self.current - 10):self.current])))
       else:
         return None
     self.current += 1
@@ -491,6 +493,26 @@ class DumpParser:
     self.current += 1
     return True
 
+  def parse_header(self, header):
+    regex = '([^:]*): (.*)$'
+    m = re.match(regex, self.lines[self.current])
+    if not m:
+      raise SVNDumpParseError("expected a header at line %d, but found:\n%s"
+                              % (self.current, self.lines[self.current]))
+    self.current += 1
+    return m.groups()
+
+  def parse_headers(self):
+    headers = []
+    while self.lines[self.current] != '\n':
+      key, val = self.parse_header(self)
+      headers.append((key, val))
+    return headers
+
+
+  def parse_boolean(self, header, required):
+    return self.parse_line(header + ': (false|true)$', required)
+
   def parse_format(self):
     return self.parse_line('SVN-fs-dump-format-version: ([0-9]+)$')
 
@@ -500,6 +522,9 @@ class DumpParser:
   def parse_revision(self):
     return self.parse_line('Revision-number: ([0-9]+)$')
 
+  def parse_prop_delta(self):
+    return self.parse_line('Prop-delta: (false|true)$', required=False)
+
   def parse_prop_length(self, required=True):
     return self.parse_line('Prop-content-length: ([0-9]+)$', required)
 
@@ -507,10 +532,7 @@ class DumpParser:
     return self.parse_line('Content-length: ([0-9]+)$', required)
 
   def parse_path(self):
-    path = self.parse_line('Node-path: (.+)$', required=False)
-    if not path and self.lines[self.current] == 'Node-path: \n':
-      self.current += 1
-      path = ''
+    path = self.parse_line('Node-path: (.*)$', required=False)
     return path
 
   def parse_kind(self):
@@ -541,6 +563,15 @@ class DumpParser:
   def parse_text_sha1(self):
     return self.parse_line('Text-content-sha1: ([0-9a-z]+)$', required=False)
 
+  def parse_text_delta(self):
+    return self.parse_line('Text-delta: (false|true)$', required=False)
+
+  def parse_text_delta_base_md5(self):
+    return self.parse_line('Text-delta-base-md5: ([0-9a-f]+)$', required=False)
+
+  def parse_text_delta_base_sha1(self):
+    return self.parse_line('Text-delta-base-sha1: ([0-9a-f]+)$', required=False)
+
   def parse_text_length(self):
     return self.parse_line('Text-content-length: ([0-9]+)$', required=False)
 
@@ -570,8 +601,14 @@ class DumpParser:
 
         return key
 
-      key = read_key_or_value(curprop)
-      value = read_key_or_value(curprop)
+      if props[curprop[0]].startswith('K'):
+        key = read_key_or_value(curprop)
+        value = read_key_or_value(curprop)
+      elif props[curprop[0]].startswith('D'):
+        key = read_key_or_value(curprop)
+        value = None
+      else:
+        raise
       prophash[key] = value
 
     return prophash
@@ -590,17 +627,43 @@ class DumpParser:
 
   def parse_one_node(self):
     node = {}
+
+    # optional 'kind' and required 'action' must be next
     node['kind'] = self.parse_kind()
     action = self.parse_action()
-    node['copyfrom_rev'] = self.parse_copyfrom_rev()
-    node['copyfrom_path'] = self.parse_copyfrom_path()
-    node['copy_md5'] = self.parse_copy_md5()
-    node['copy_sha1'] = self.parse_copy_sha1()
-    node['prop_length'] = self.parse_prop_length(required=False)
-    node['text_length'] = self.parse_text_length()
-    node['text_md5'] = self.parse_text_md5()
-    node['text_sha1'] = self.parse_text_sha1()
-    node['content_length'] = self.parse_content_length(required=False)
+
+    # read any remaining headers
+    headers_list = self.parse_headers()
+    headers = dict(headers_list)
+
+    # Content-length must be last, if present
+    if 'Content-length' in headers and headers_list[-1][0] != 'Content-length':
+      raise SVNDumpParseError("'Content-length' header is not last, "
+                              "in header block ending at line %d"
+                              % (self.current,))
+
+    # parse the remaining optional headers and store in specific keys in NODE
+    for key, header, regex in [
+        ('copyfrom_rev',    'Node-copyfrom-rev',    '([0-9]+)$'),
+        ('copyfrom_path',   'Node-copyfrom-path',   '(.*)$'),
+        ('copy_md5',        'Text-copy-source-md5', '([0-9a-z]+)$'),
+        ('copy_sha1',       'Text-copy-source-sha1','([0-9a-z]+)$'),
+        ('prop_length',     'Prop-content-length',  '([0-9]+)$'),
+        ('text_length',     'Text-content-length',  '([0-9]+)$'),
+        ('text_md5',        'Text-content-md5',     '([0-9a-z]+)$'),
+        ('text_sha1',       'Text-content-sha1',    '([0-9a-z]+)$'),
+        ('content_length',  'Content-length',       '([0-9]+)$'),
+        ]:
+      if not header in headers:
+        node[key] = None
+        continue
+      m = re.match(regex, headers[header])
+      if not m:
+        raise SVNDumpParseError("expected '%s' at line %d\n%s"
+                                % (regex, self.current,
+                                   self.lines[self.current]))
+      node[key] = m.group(1)
+
     self.parse_blank()
     if node['prop_length']:
       node['props'] = self.get_props()
@@ -622,7 +685,7 @@ class DumpParser:
       if self.current >= len(self.lines):
         break
       path = self.parse_path()
-      if not path and not path is '':
+      if path is None:
         break
       if not nodes.get(path):
         nodes[path] = {}
@@ -660,7 +723,11 @@ class DumpParser:
     self.parse_all_revisions()
     return self.parsed
 
-def compare_dump_files(message, label, expected, actual):
+def compare_dump_files(message, label, expected, actual,
+                       ignore_uuid=False,
+                       expect_content_length_always=False,
+                       ignore_empty_prop_sections=False,
+                       ignore_number_of_blank_lines=False):
   """Parse two dump files EXPECTED and ACTUAL, both of which are lists
   of lines as returned by run_and_verify_dump, and check that the same
   revisions, nodes, properties, etc. are present in both dumps.
@@ -669,8 +736,39 @@ def compare_dump_files(message, label, e
   parsed_expected = DumpParser(expected).parse()
   parsed_actual = DumpParser(actual).parse()
 
+  if ignore_uuid:
+    parsed_expected['uuid'] = '<ignored>'
+    parsed_actual['uuid'] = '<ignored>'
+
+  for parsed in [parsed_expected, parsed_actual]:
+    for rev_name, rev_record in parsed.items():
+      #print "Found %s" % (rev_name,)
+      if 'nodes' in rev_record:
+        #print "Found %s.%s" % (rev_name, 'nodes')
+        for path_name, path_record in rev_record['nodes'].items():
+          #print "Found %s.%s.%s" % (rev_name, 'nodes', path_name)
+          for action_name, action_record in path_record.items():
+            #print "Found %s.%s.%s.%s" % (rev_name, 'nodes', path_name, action_name)
+
+            if expect_content_length_always:
+              if action_record.get('content_length') == None:
+                #print 'Adding: %s.%s.%s.%s.%s' % (rev_name, 'nodes', path_name, action_name, 'content_length=0')
+                action_record['content_length'] = '0'
+            if ignore_empty_prop_sections:
+              if action_record.get('prop_length') == '10':
+                #print 'Removing: %s.%s.%s.%s.%s' % (rev_name, 'nodes', path_name, action_name, 'prop_length')
+                action_record['prop_length'] = None
+                del action_record['props']
+                old_content_length = int(action_record['content_length'])
+                action_record['content_length'] = str(old_content_length - 10)
+            if ignore_number_of_blank_lines:
+              action_record['blanks'] = 0
+
   if parsed_expected != parsed_actual:
-    raise svntest.Failure('\n' + '\n'.join(ndiff(
+    print 'DIFF of raw dumpfiles (including expected differences)'
+    print ''.join(ndiff(expected, actual))
+    raise svntest.Failure('DIFF of parsed dumpfiles (ignoring expected differences)\n'
+                          + '\n'.join(ndiff(
           pprint.pformat(parsed_expected).splitlines(),
           pprint.pformat(parsed_actual).splitlines())))
 



Mime
View raw message