subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ar...@apache.org
Subject svn commit: r1204374 [27/29] - in /subversion/branches/svn-bisect: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/client-side/ contrib/client-side/emacs/ notes/ notes/wc-ng/ subversion/bindings/javahl/native...
Date Mon, 21 Nov 2011 07:08:07 GMT
Modified: subversion/branches/svn-bisect/subversion/tests/cmdline/svnmucc_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/cmdline/svnmucc_tests.py?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/cmdline/svnmucc_tests.py (original)
+++ subversion/branches/svn-bisect/subversion/tests/cmdline/svnmucc_tests.py Mon Nov 21 07:07:56 2011
@@ -25,6 +25,7 @@
 ######################################################################
 
 import svntest
+import re
 
 XFail = svntest.testcase.XFail_deco
 Issues = svntest.testcase.Issues_deco
@@ -46,10 +47,276 @@ def reject_bogus_mergeinfo(sbox):
                                          'propset', 'svn:mergeinfo', '/B:0',
                                          sbox.repo_url + '/A')
 
+_svnmucc_re = re.compile('^(r[0-9]+) committed by jrandom at (.*)$')
+_log_re = re.compile('^   ([ADRM] /[^\(]+($| \(from .*:[0-9]+\)$))')
+_err_re = re.compile('^svnmucc: (.*)$')
+
+def test_svnmucc(repo_url, expected_path_changes, *varargs):
+  """Run svnmucc with the list of SVNMUCC_ARGS arguments.  Verify that
+  its run results in a new commit with 'svn log -rHEAD' changed paths
+  that match the list of EXPECTED_PATH_CHANGES."""
+
+  # First, run svnmucc.
+  exit_code, outlines, errlines = svntest.main.run_svnmucc('-U', repo_url,
+                                                           *varargs)
+  if errlines:
+    raise svntest.main.SVNCommitFailure(str(errlines))
+  if len(outlines) != 1 or not _svnmucc_re.match(outlines[0]):
+    raise svntest.main.SVNLineUnequal(str(outlines))
+
+  # Now, run 'svn log -vq -rHEAD'
+  changed_paths = []
+  exit_code, outlines, errlines = \
+    svntest.main.run_svn(None, 'log', '-vqrHEAD', repo_url)
+  if errlines:
+    raise svntest.Failure("Unable to verify commit with 'svn log': %s"
+                          % (str(errlines)))
+  for line in outlines:
+    match = _log_re.match(line)
+    if match:
+      changed_paths.append(match.group(1).rstrip('\n\r'))
+
+  expected_path_changes.sort()
+  changed_paths.sort()
+  if changed_paths != expected_path_changes:
+    raise svntest.Failure("Logged path changes differ from expectations\n"
+                          "   expected: %s\n"
+                          "     actual: %s" % (str(expected_path_changes),
+                                               str(changed_paths)))
+
+def xtest_svnmucc(repo_url, expected_errors, *varargs):
+  """Run svnmucc with the list of SVNMUCC_ARGS arguments.  Verify that
+  its run results match the list of EXPECTED_ERRORS."""
+
+  # First, run svnmucc.
+  exit_code, outlines, errlines = svntest.main.run_svnmucc('-U', repo_url,
+                                                           *varargs)
+  errors = []
+  for line in errlines:
+    match = _err_re.match(line)
+    if match:
+      errors.append(line.rstrip('\n\r'))
+  if errors != expected_errors:
+    raise svntest.main.SVNUnmatchedError(str(errors))
+
+
+def basic_svnmucc(sbox):
+  "basic svnmucc tests"
+
+  sbox.build()
+  empty_file = sbox.ospath('empty')
+  svntest.main.file_append(empty_file, '')
+
+  # revision 2
+  test_svnmucc(sbox.repo_url,
+               ['A /foo'
+                ], # ---------
+               'mkdir', 'foo')
+
+  # revision 3
+  test_svnmucc(sbox.repo_url,
+               ['A /z.c',
+                ], # ---------
+               'put', empty_file, 'z.c')
+
+  # revision 4
+  test_svnmucc(sbox.repo_url,
+               ['A /foo/z.c (from /z.c:3)',
+                'A /foo/bar (from /foo:3)',
+                ], # ---------
+               'cp', '3', 'z.c', 'foo/z.c',
+               'cp', '3', 'foo', 'foo/bar')
+
+  # revision 5
+  test_svnmucc(sbox.repo_url,
+               ['A /zig (from /foo:4)',
+                'D /zig/bar',
+                'D /foo',
+                'A /zig/zag (from /foo:4)',
+                ], # ---------
+               'cp', '4', 'foo', 'zig',
+               'rm',             'zig/bar',
+               'mv',      'foo', 'zig/zag')
+
+  # revision 6
+  test_svnmucc(sbox.repo_url,
+               ['D /z.c',
+                'A /zig/zag/bar/y.c (from /z.c:5)',
+                'A /zig/zag/bar/x.c (from /z.c:3)',
+                ], # ---------
+               'mv',      'z.c', 'zig/zag/bar/y.c',
+               'cp', '3', 'z.c', 'zig/zag/bar/x.c')
+
+  # revision 7
+  test_svnmucc(sbox.repo_url,
+               ['D /zig/zag/bar/y.c',
+                'A /zig/zag/bar/y y.c (from /zig/zag/bar/y.c:6)',
+                'A /zig/zag/bar/y%20y.c (from /zig/zag/bar/y.c:6)',
+                ], # ---------
+               'mv',         'zig/zag/bar/y.c', 'zig/zag/bar/y%20y.c',
+               'cp', 'HEAD', 'zig/zag/bar/y.c', 'zig/zag/bar/y%2520y.c')
+
+  # revision 8
+  test_svnmucc(sbox.repo_url,
+               ['D /zig/zag/bar/y y.c',
+                'A /zig/zag/bar/z z1.c (from /zig/zag/bar/y y.c:7)',
+                'A /zig/zag/bar/z%20z.c (from /zig/zag/bar/y%20y.c:7)',
+                'A /zig/zag/bar/z z2.c (from /zig/zag/bar/y y.c:7)',
+                ], #---------
+               'mv',         'zig/zag/bar/y%20y.c',   'zig/zag/bar/z z1.c',
+               'cp', 'HEAD', 'zig/zag/bar/y%2520y.c', 'zig/zag/bar/z%2520z.c',
+               'cp', 'HEAD', 'zig/zag/bar/y y.c',     'zig/zag/bar/z z2.c')
+
+
+  # revision 9
+  test_svnmucc(sbox.repo_url,
+               ['D /zig/zag',
+                'A /zig/foo (from /zig/zag:8)',
+                'D /zig/foo/bar/z%20z.c',
+                'D /zig/foo/bar/z z2.c',
+                'R /zig/foo/bar/z z1.c (from /zig/zag/bar/x.c:6)',
+                ], #---------
+               'mv',      'zig/zag',         'zig/foo',
+               'rm',                         'zig/foo/bar/z z1.c',
+               'rm',                         'zig/foo/bar/z%20z2.c',
+               'rm',                         'zig/foo/bar/z%2520z.c',
+               'cp', '6', 'zig/zag/bar/x.c', 'zig/foo/bar/z%20z1.c')
+
+  # revision 10
+  test_svnmucc(sbox.repo_url,
+               ['R /zig/foo/bar (from /zig/z.c:9)',
+                ], #---------
+               'rm',                 'zig/foo/bar',
+               'cp', '9', 'zig/z.c', 'zig/foo/bar')
+
+  # revision 11
+  test_svnmucc(sbox.repo_url,
+               ['R /zig/foo/bar (from /zig/foo/bar:9)',
+                'D /zig/foo/bar/z z1.c',
+                ], #---------
+               'rm',                     'zig/foo/bar',
+               'cp', '9', 'zig/foo/bar', 'zig/foo/bar',
+               'rm',                     'zig/foo/bar/z%20z1.c')
+
+  # revision 12
+  test_svnmucc(sbox.repo_url,
+               ['R /zig/foo (from /zig/foo/bar:11)',
+                ], #---------
+               'rm',                        'zig/foo',
+               'cp', 'head', 'zig/foo/bar', 'zig/foo')
+
+  # revision 13
+  test_svnmucc(sbox.repo_url,
+               ['D /zig',
+                'A /foo (from /foo:4)',
+                'A /foo/foo (from /foo:4)',
+                'A /foo/foo/foo (from /foo:4)',
+                'D /foo/foo/bar',
+                'R /foo/foo/foo/bar (from /foo:4)',
+                ], #---------
+               'rm',             'zig',
+               'cp', '4', 'foo', 'foo',
+               'cp', '4', 'foo', 'foo/foo',
+               'cp', '4', 'foo', 'foo/foo/foo',
+               'rm',             'foo/foo/bar',
+               'rm',             'foo/foo/foo/bar',
+               'cp', '4', 'foo', 'foo/foo/foo/bar')
+
+  # revision 14
+  test_svnmucc(sbox.repo_url,
+               ['A /boozle (from /foo:4)',
+                'A /boozle/buz',
+                'A /boozle/buz/nuz',
+                ], #---------
+               'cp',    '4', 'foo', 'boozle',
+               'mkdir',             'boozle/buz',
+               'mkdir',             'boozle/buz/nuz')
+
+  # revision 15
+  test_svnmucc(sbox.repo_url,
+               ['A /boozle/buz/svnmucc-test.py',
+                'A /boozle/guz (from /boozle/buz:14)',
+                'A /boozle/guz/svnmucc-test.py',
+                ], #---------
+               'put',      empty_file,   'boozle/buz/svnmucc-test.py',
+               'cp', '14', 'boozle/buz', 'boozle/guz',
+               'put',      empty_file,   'boozle/guz/svnmucc-test.py')
+
+  # revision 16
+  test_svnmucc(sbox.repo_url,
+               ['M /boozle/buz/svnmucc-test.py',
+                'R /boozle/guz/svnmucc-test.py',
+                ], #---------
+               'put', empty_file, 'boozle/buz/svnmucc-test.py',
+               'rm',              'boozle/guz/svnmucc-test.py',
+               'put', empty_file, 'boozle/guz/svnmucc-test.py')
+
+  # revision 17
+  test_svnmucc(sbox.repo_url,
+               ['R /foo/bar (from /foo/foo:16)'], #---------
+               'rm',                            'foo/bar',
+               'cp', '16', 'foo/foo',           'foo/bar',
+               'propset',  'testprop',  'true', 'foo/bar')
+
+  # revision 18
+  test_svnmucc(sbox.repo_url,
+               ['M /foo/bar'], #---------
+               'propdel', 'testprop', 'foo/bar')
+
+  # revision 19
+  test_svnmucc(sbox.repo_url,
+               ['M /foo/z.c',
+                'M /foo/foo',
+                ], #---------
+               'propset', 'testprop', 'true', 'foo/z.c',
+               'propset', 'testprop', 'true', 'foo/foo')
+
+  # revision 20
+  test_svnmucc(sbox.repo_url,
+               ['M /foo/z.c',
+                'M /foo/foo',
+                ], #---------
+               'propsetf', 'testprop', empty_file, 'foo/z.c',
+               'propsetf', 'testprop', empty_file, 'foo/foo')
+
+  # Expected missing revision error
+  xtest_svnmucc(sbox.repo_url,
+                ["svnmucc: E200004: 'a' is not a revision"
+                 ], #---------
+                'cp', 'a', 'b')
+
+  # Expected cannot be younger error
+  xtest_svnmucc(sbox.repo_url,
+                ['svnmucc: E205000: Copy source revision cannot be younger ' +
+                 'than base revision',
+                 ], #---------
+                'cp', '42', 'a', 'b')
+
+  # Expected already exists error
+  xtest_svnmucc(sbox.repo_url,
+                ["svnmucc: E125002: 'foo' already exists",
+                 ], #---------
+                'cp', '17', 'a', 'foo')
+
+  # Expected copy_src already exists error
+  xtest_svnmucc(sbox.repo_url,
+                ["svnmucc: E125002: 'a/bar' (from 'foo/bar:17') already exists",
+                 ], #---------
+                'cp', '17', 'foo', 'a',
+                'cp', '17', 'foo/foo', 'a/bar')
+
+  # Expected not found error
+  xtest_svnmucc(sbox.repo_url,
+                ["svnmucc: E125002: 'a' not found",
+                 ], #---------
+                'cp', '17', 'a', 'b')
+
+
 ######################################################################
 
 test_list = [ None,
               reject_bogus_mergeinfo,
+              basic_svnmucc,
             ]
 
 if __name__ == '__main__':

Modified: subversion/branches/svn-bisect/subversion/tests/cmdline/svntest/actions.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/cmdline/svntest/actions.py?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/cmdline/svntest/actions.py (original)
+++ subversion/branches/svn-bisect/subversion/tests/cmdline/svntest/actions.py Mon Nov 21 07:07:56 2011
@@ -1258,7 +1258,7 @@ def run_and_verify_mergeinfo(error_re_st
     verify.verify_outputs(None, None, err, None, expected_err)
     return
 
-  out = sorted([_f for _f in [x.rstrip()[1:] for x in out] if _f])
+  out = [_f for _f in [x.rstrip()[1:] for x in out] if _f]
   expected_output.sort()
   extra_out = []
   if out != expected_output:
@@ -1398,8 +1398,9 @@ def run_and_verify_commit(wc_dir_name, o
     status_tree = status_tree.old_tree()
 
   # Commit.
+  if '-m' not in args and '-F' not in args:
+    args = list(args) + ['-m', 'log msg']
   exit_code, output, errput = main.run_svn(error_re_string, 'ci',
-                                           '-m', 'log msg',
                                            *args)
 
   if error_re_string:
@@ -1747,6 +1748,11 @@ def lock_admin_dir(wc_dir, recursive=Fal
 
   svntest.main.run_wc_lock_tester(recursive, wc_dir)
 
+def set_incomplete(wc_dir, revision):
+  "Make wc_dir incomplete at revision"
+
+  svntest.main.run_wc_incomplete_tester(wc_dir, revision)
+
 def get_wc_uuid(wc_dir):
   "Return the UUID of the working copy at WC_DIR."
   return run_and_parse_info(wc_dir)[0]['Repository UUID']

Modified: subversion/branches/svn-bisect/subversion/tests/cmdline/svntest/factory.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/cmdline/svntest/factory.py?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/cmdline/svntest/factory.py (original)
+++ subversion/branches/svn-bisect/subversion/tests/cmdline/svntest/factory.py Mon Nov 21 07:07:56 2011
@@ -288,7 +288,9 @@ class TestFactory:
     # Any expected_disk still there from a previous verification
     self.prev_disk = None
     if prev_disk:
-      self.prev_disk = [None, prev_disk]      # svntest.wc.State
+      reparented_prev_disk = svntest.wc.State(prev_disk.wc_dir, {});
+      reparented_prev_disk.add_state(sbox.wc_dir, prev_disk);
+      self.prev_disk = [None, reparented_prev_disk]
 
     # Those command line options that expect an argument following
     # which is not a path. (don't expand args following these)

Modified: subversion/branches/svn-bisect/subversion/tests/cmdline/svntest/main.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/cmdline/svntest/main.py?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/cmdline/svntest/main.py (original)
+++ subversion/branches/svn-bisect/subversion/tests/cmdline/svntest/main.py Mon Nov 21 07:07:56 2011
@@ -165,6 +165,7 @@ entriesdump_binary = os.path.abspath('en
 atomic_ra_revprop_change_binary = os.path.abspath('atomic-ra-revprop-change' + \
                                                   _exe)
 wc_lock_tester_binary = os.path.abspath('../libsvn_wc/wc-lock-tester' + _exe)
+wc_incomplete_tester_binary = os.path.abspath('../libsvn_wc/wc-incomplete-tester' + _exe)
 svnmucc_binary=os.path.abspath('../../../tools/client-side/svnmucc/svnmucc' + \
                                _exe)
 
@@ -683,6 +684,10 @@ def run_wc_lock_tester(recursive, path):
     option = "-1"
   return run_command(wc_lock_tester_binary, False, False, option, path)
 
+def run_wc_incomplete_tester(wc_dir, revision):
+  "Run the wc-incomplete tool, returning its exit code, stdout and stderr"
+  return run_command(wc_incomplete_tester_binary, False, False,
+                     wc_dir, revision)
 
 def youngest(repos_path):
   "run 'svnlook youngest' on REPOS_PATH, returns revision as int"
@@ -705,11 +710,16 @@ def chmod_tree(path, mode, mask):
 
 # For clearing away working copies
 def safe_rmtree(dirname, retry=0):
-  "Remove the tree at DIRNAME, making it writable first"
+  """Remove the tree at DIRNAME, making it writable first.
+     If DIRNAME is a symlink, only remove the symlink, not its target."""
   def rmtree(dirname):
     chmod_tree(dirname, 0666, 0666)
     shutil.rmtree(dirname)
 
+  if os.path.islink(dirname):
+    os.unlink(dirname)
+    return
+
   if not os.path.exists(dirname):
     return
 
@@ -988,51 +998,60 @@ def use_editor(func):
   os.environ['SVNTEST_EDITOR_FUNC'] = func
   os.environ['SVN_TEST_PYTHON'] = sys.executable
 
-def mergeinfo_notify_line(revstart, revend):
+def mergeinfo_notify_line(revstart, revend, target=None):
   """Return an expected output line that describes the beginning of a
   mergeinfo recording notification on revisions REVSTART through REVEND."""
+  if target:
+    target_re = re.escape(target)
+  else:
+    target_re = ".+"
   if (revend is None):
     if (revstart < 0):
       revstart = abs(revstart)
-      return "--- Recording mergeinfo for reverse merge of r%ld .*:\n" \
-             % (revstart)
+      return "--- Recording mergeinfo for reverse merge of r%ld into '%s':\n" \
+             % (revstart, target_re)
     else:
-      return "--- Recording mergeinfo for merge of r%ld .*:\n" % (revstart)
+      return "--- Recording mergeinfo for merge of r%ld into '%s':\n" \
+             % (revstart, target_re)
   elif (revstart < revend):
-    return "--- Recording mergeinfo for merge of r%ld through r%ld .*:\n" \
-           % (revstart, revend)
+    return "--- Recording mergeinfo for merge of r%ld through r%ld into '%s':\n" \
+           % (revstart, revend, target_re)
   else:
     return "--- Recording mergeinfo for reverse merge of r%ld through " \
-           "r%ld .*:\n" % (revstart, revend)
+           "r%ld into '%s':\n" % (revstart, revend, target_re)
 
 def merge_notify_line(revstart=None, revend=None, same_URL=True,
-                      foreign=False):
+                      foreign=False, target=None):
   """Return an expected output line that describes the beginning of a
   merge operation on revisions REVSTART through REVEND.  Omit both
   REVSTART and REVEND for the case where the left and right sides of
   the merge are from different URLs."""
   from_foreign_phrase = foreign and "\(from foreign repository\) " or ""
+  if target:
+    target_re = re.escape(target)
+  else:
+    target_re = ".+"
   if not same_URL:
-    return "--- Merging differences between %srepository URLs into '.+':\n" \
-           % (foreign and "foreign " or "")
+    return "--- Merging differences between %srepository URLs into '%s':\n" \
+           % (foreign and "foreign " or "", target_re)
   if revend is None:
     if revstart is None:
       # The left and right sides of the merge are from different URLs.
-      return "--- Merging differences between %srepository URLs into '.+':\n" \
-             % (foreign and "foreign " or "")
+      return "--- Merging differences between %srepository URLs into '%s':\n" \
+             % (foreign and "foreign " or "", target_re)
     elif revstart < 0:
-      return "--- Reverse-merging %sr%ld into '.+':\n" \
-             % (from_foreign_phrase, abs(revstart))
+      return "--- Reverse-merging %sr%ld into '%s':\n" \
+             % (from_foreign_phrase, abs(revstart), target_re)
     else:
-      return "--- Merging %sr%ld into '.+':\n" \
-             % (from_foreign_phrase, revstart)
+      return "--- Merging %sr%ld into '%s':\n" \
+             % (from_foreign_phrase, revstart, target_re)
   else:
     if revstart > revend:
-      return "--- Reverse-merging %sr%ld through r%ld into '.+':\n" \
-             % (from_foreign_phrase, revstart, revend)
+      return "--- Reverse-merging %sr%ld through r%ld into '%s':\n" \
+             % (from_foreign_phrase, revstart, revend, target_re)
     else:
-      return "--- Merging %sr%ld through r%ld into '.+':\n" \
-             % (from_foreign_phrase, revstart, revend)
+      return "--- Merging %sr%ld through r%ld into '%s':\n" \
+             % (from_foreign_phrase, revstart, revend, target_re)
 
 
 def make_log_msg():

Modified: subversion/branches/svn-bisect/subversion/tests/cmdline/svnversion_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/cmdline/svnversion_tests.py?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/cmdline/svnversion_tests.py (original)
+++ subversion/branches/svn-bisect/subversion/tests/cmdline/svnversion_tests.py Mon Nov 21 07:07:56 2011
@@ -147,7 +147,8 @@ def svnversion_test(sbox):
   X_path = os.path.join(wc_dir, 'Q', 'X')
   svntest.actions.run_and_verify_svnversion("Nonexistent file or directory",
                                             X_path, repo_url,
-                                            None, [ "'%s' doesn't exist\n" % X_path ])
+                                            None, [ "'%s' doesn't exist\n"
+                                                   % os.path.abspath(X_path) ])
 
   # Perform a sparse checkout of under the existing WC, and confirm that
   # svnversion detects it as a "partial" WC.
@@ -287,9 +288,8 @@ def svnversion_with_structural_changes(s
   svntest.actions.run_and_verify_svnversion("Deleted file",
                                             sbox.ospath('iota'),
                                             repo_url + '/iota',
+                                            ["1M\n"],
                                             [],
-                                            [ "'%s' doesn't exist\n" % \
-                                              sbox.ospath('iota')],
                                             )
   svntest.actions.run_and_verify_svnversion("Deleted file", wc_dir, repo_url,
                                             [ "1:2M\n" ], [])

Modified: subversion/branches/svn-bisect/subversion/tests/cmdline/tree_conflict_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/cmdline/tree_conflict_tests.py?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/cmdline/tree_conflict_tests.py (original)
+++ subversion/branches/svn-bisect/subversion/tests/cmdline/tree_conflict_tests.py Mon Nov 21 07:07:56 2011
@@ -254,8 +254,10 @@ d_adds = [
 # Scenarios that start with an existing versioned item
 #
 # GO-AWAY: node is no longer at the path where it was.
-# file-del(F) = del(F) or move(F,F2)
+# file-del(F) = del(F)
+# file-move(F) = move(F,F2)
 # dir-del(D)  = del(D) or move(D,D2)
+# Note: file-move(F) does not conflict with incoming edit
 #
 # REPLACE: node is no longer at the path where it was, but another node is.
 # file-rpl(F) = file-del(F) + file-add(F)
@@ -268,10 +270,17 @@ d_adds = [
 
 f_dels = [
   ( create_f, ['fD'] ),
+]
+
+f_moves = [
   ( create_f, ['fM'] ),
 ]
+
 d_dels = [
   ( create_d, ['dD'] ),
+]
+
+d_moves = [
   ( create_d, ['dM'] ),
 ]
 
@@ -562,7 +571,7 @@ def test_tc_merge(sbox, incoming_scen, b
 # WC state: as scheduled (no obstruction)
 
 def up_sw_file_mod_onto_del(sbox):
-  "up/sw file: modify onto del/rpl/mv"
+  "up/sw file: modify onto del/rpl"
   test_tc_up_sw(sbox, f_mods, f_dels + f_rpls)
   # Note: See UC1 in notes/tree-conflicts/use-cases.txt.
 
@@ -573,12 +582,12 @@ def up_sw_file_del_onto_mod(sbox):
   #          ### OR (see Nico's email <>):
   #          schedule-delete but leave F on disk (can only apply with
   #            text-mod; prop-mod can't be preserved in this way)
-  test_tc_up_sw(sbox, f_dels + f_rpls, f_mods)
+  test_tc_up_sw(sbox, f_dels + f_moves + f_rpls, f_mods)
   # Note: See UC2 in notes/tree-conflicts/use-cases.txt.
 
 def up_sw_file_del_onto_del(sbox):
   "up/sw file: del/rpl/mv onto del/rpl/mv"
-  test_tc_up_sw(sbox, f_dels + f_rpls, f_dels + f_rpls)
+  test_tc_up_sw(sbox, f_dels + f_moves + f_rpls, f_dels + f_rpls)
   # Note: See UC3 in notes/tree-conflicts/use-cases.txt.
 
 def up_sw_file_add_onto_add(sbox):
@@ -598,12 +607,12 @@ def up_sw_dir_mod_onto_del(sbox):
 def up_sw_dir_del_onto_mod(sbox):
   "up/sw dir: del/rpl/mv onto modify"
   # WC state: any (D necessarily exists; children may have any state)
-  test_tc_up_sw(sbox, d_dels + d_rpls, d_mods)
+  test_tc_up_sw(sbox, d_dels + d_moves + d_rpls, d_mods)
 
 def up_sw_dir_del_onto_del(sbox):
   "up/sw dir: del/rpl/mv onto del/rpl/mv"
   # WC state: any (D necessarily exists; children may have any state)
-  test_tc_up_sw(sbox, d_dels + d_rpls, d_dels + d_rpls)
+  test_tc_up_sw(sbox, d_dels + d_moves + d_rpls, d_dels + d_rpls)
 
 # This is currently set as XFail over ra_dav because it hits
 # issue #3314 'DAV can overwrite directories during copy'
@@ -650,22 +659,24 @@ def up_sw_dir_add_onto_add(sbox):
 def merge_file_mod_onto_not_file(sbox):
   "merge file: modify onto not-file"
   sbox2 = sbox.clone_dependent()
-  test_tc_merge(sbox, f_mods, br_scen = f_dels + f_rpl_d)
+  test_tc_merge(sbox, f_mods, br_scen = f_dels + f_moves + f_rpl_d)
   test_tc_merge(sbox2, f_mods, wc_scen = f_dels)
   # Note: See UC4 in notes/tree-conflicts/use-cases.txt.
 
 def merge_file_del_onto_not_same(sbox):
   "merge file: del/rpl/mv onto not-same"
   sbox2 = sbox.clone_dependent()
-  test_tc_merge(sbox, f_dels + f_rpls, br_scen = f_mods)
-  test_tc_merge(sbox2, f_dels + f_rpls, wc_scen = f_mods)
+  test_tc_merge(sbox, f_dels + f_moves + f_rpls, br_scen = f_mods)
+  test_tc_merge(sbox2, f_dels + f_moves + f_rpls, wc_scen = f_mods)
   # Note: See UC5 in notes/tree-conflicts/use-cases.txt.
 
 def merge_file_del_onto_not_file(sbox):
   "merge file: del/rpl/mv onto not-file"
   sbox2 = sbox.clone_dependent()
-  test_tc_merge(sbox, f_dels + f_rpls, br_scen = f_dels + f_rpl_d)
-  test_tc_merge(sbox2, f_dels + f_rpls, wc_scen = f_dels)
+  test_tc_merge(sbox, f_dels + f_moves + f_rpls,
+                br_scen = f_dels + f_moves + f_rpl_d)
+  test_tc_merge(sbox2, f_dels + f_moves + f_rpls,
+                wc_scen = f_dels + f_moves)
   # Note: See UC6 in notes/tree-conflicts/use-cases.txt.
 
 def merge_file_add_onto_not_none(sbox):
@@ -682,8 +693,8 @@ def merge_file_add_onto_not_none(sbox):
 def merge_dir_mod_onto_not_dir(sbox):
   "merge dir: modify onto not-dir"
   sbox2 = sbox.clone_dependent()
-  test_tc_merge(sbox, d_mods, br_scen = d_dels + d_rpl_f)
-  test_tc_merge(sbox2, d_mods, wc_scen = d_dels)
+  test_tc_merge(sbox, d_mods, br_scen = d_dels + d_moves + d_rpl_f)
+  test_tc_merge(sbox2, d_mods, wc_scen = d_dels + d_moves)
 
 # Test for issue #3150 'tree conflicts with directories as victims'.
 @XFail()
@@ -691,14 +702,14 @@ def merge_dir_mod_onto_not_dir(sbox):
 def merge_dir_del_onto_not_same(sbox):
   "merge dir: del/rpl/mv onto not-same"
   sbox2 = sbox.clone_dependent()
-  test_tc_merge(sbox, d_dels + d_rpls, br_scen = d_mods)
-  test_tc_merge(sbox2, d_dels + d_rpls, wc_scen = d_mods)
+  test_tc_merge(sbox, d_dels + d_moves + d_rpls, br_scen = d_mods)
+  test_tc_merge(sbox2, d_dels + d_moves + d_rpls, wc_scen = d_mods)
 
 def merge_dir_del_onto_not_dir(sbox):
   "merge dir: del/rpl/mv onto not-dir"
   sbox2 = sbox.clone_dependent()
-  test_tc_merge(sbox, d_dels + d_rpls, br_scen = d_dels + d_rpl_f)
-  test_tc_merge(sbox2, d_dels + d_rpls, wc_scen = d_dels)
+  test_tc_merge(sbox, d_dels + d_moves + d_rpls, br_scen = d_dels + d_moves + d_rpl_f)
+  test_tc_merge(sbox2, d_dels + d_moves + d_rpls, wc_scen = d_dels + d_moves)
 
 def merge_dir_add_onto_not_none(sbox):
   "merge dir: add onto not-none"

Modified: subversion/branches/svn-bisect/subversion/tests/cmdline/update_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/cmdline/update_tests.py?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/cmdline/update_tests.py (original)
+++ subversion/branches/svn-bisect/subversion/tests/cmdline/update_tests.py Mon Nov 21 07:07:56 2011
@@ -5404,6 +5404,212 @@ def update_to_HEAD_plus_1(sbox):
                                         None, None,
                                         None, None, None, wc_dir, '-r', '2')
 
+def update_moved_dir_leaf_del(sbox):
+  "update locally moved dir with leaf del"
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  svntest.main.run_svn(False, 'rm', '-m', 'remove /A/B/E/alpha',
+                       sbox.repo_url + "/A/B/E/alpha")
+  sbox.simple_move("A/B/E", "A/B/E2")
+
+  # since alpha isn't locally modified, the incoming delete should auto-merge
+  expected_output = svntest.wc.State(wc_dir, {
+    'A/B/E2/alpha' : Item(status='D '),
+  })
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.remove('A/B/E/alpha', 'A/B/E/beta', 'A/B/E')
+  expected_disk.add({
+    'A/B/E2'           : Item(),
+    'A/B/E2/beta'      : Item(contents="This is the file 'beta'.\n"),
+  })
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
+  expected_status.add({
+    'A/B/E2'            : Item(status='A ', copied='+', wc_rev='-'),
+    'A/B/E2/beta'       : Item(status='  ', copied='+', wc_rev='-'),
+    'A/B/E2/alpha'      : Item(status='D ', copied='+', wc_rev='-'),
+  })
+  expected_status.remove('A/B/E/alpha')
+  expected_status.tweak('A/B/E', 'A/B/E/beta', status='D ')
+  svntest.actions.run_and_verify_update(wc_dir,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status,
+                                        None, None, None,
+                                        None, None, 1)
+
+def update_moved_dir_edited_leaf_del(sbox):
+  "update locally moved dir with edited leaf del"
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  svntest.main.run_svn(False, 'rm', '-m', 'remove /A/B/E/alpha',
+                       sbox.repo_url + "/A/B/E/alpha")
+  sbox.simple_move("A/B/E", "A/B/E2")
+  svntest.main.file_write(sbox.ospath('A/B/E2/alpha'),
+                          "This is a changed 'alpha'.\n")
+
+  # since alpha was modified post-move, the incoming delete should conflict
+  expected_output = svntest.wc.State(wc_dir, {
+    'A/B/E/alpha'       : Item(status='  ', treeconflict='C'),
+  })
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.remove('A/B/E/alpha', 'A/B/E/beta', 'A/B/E')
+  expected_disk.add({
+    'A/B/E2'           : Item(),
+    'A/B/E2/alpha'     : Item(contents="This is a changed 'alpha'.\n"),
+    'A/B/E2/beta'      : Item(contents="This is the file 'beta'.\n"),
+  })
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
+  expected_status.tweak('A/B/E', 'A/B/E/beta', status='D ')
+  expected_status.remove('A/B/E/alpha')
+  expected_status.add({
+    'A/B/E/alpha'       : Item(status='! ', treeconflict='C'),
+    'A/B/E2'            : Item(status='A ', copied='+', wc_rev='-'),
+    'A/B/E2/beta'       : Item(status='  ', copied='+', wc_rev='-'),
+    'A/B/E2/alpha'      : Item(status='M ', copied='+', wc_rev='-'),
+  })
+  svntest.actions.run_and_verify_update(wc_dir,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status,
+                                        None, None, None,
+                                        None, None, 1)
+
+def update_moved_dir_file_add(sbox):
+  "update locally moved dir with incoming file"
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  foo_path = "A/B/E/foo"
+  foo_content = "This is the file 'foo'.\n"
+
+  svntest.main.file_write(sbox.ospath(foo_path), foo_content, 'wb')
+  sbox.simple_add(foo_path)
+  sbox.simple_commit()
+  # update to go back in time, before the last commit
+  svntest.main.run_svn(False, 'update', '-r', '1', wc_dir)
+  sbox.simple_move("A/B/E", "A/B/E2")
+
+  # the incoming file should auto-merge
+  expected_output = svntest.wc.State(wc_dir, {
+    'A/B/E2/foo' : Item(status='A '),
+  })
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.remove('A/B/E/alpha', 'A/B/E/beta', 'A/B/E')
+  expected_disk.add({
+    'A/B/E2'           : Item(),
+    'A/B/E2/alpha'     : Item(contents="This is the file 'alpha'.\n"),
+    'A/B/E2/beta'      : Item(contents="This is the file 'beta'.\n"),
+    'A/B/E2/foo'       : Item(contents=foo_content),
+  })
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
+  expected_status.tweak('A/B/E', 'A/B/E/alpha', 'A/B/E/beta', status='D ')
+  expected_status.add({
+    'A/B/E/foo'         : Item(status='D ', wc_rev='2'),
+    'A/B/E2'            : Item(status='A ', copied='+', wc_rev='-'),
+    'A/B/E2/beta'       : Item(status='  ', copied='+', wc_rev='-'),
+    'A/B/E2/alpha'      : Item(status='  ', copied='+', wc_rev='-'),
+    'A/B/E2/foo'        : Item(status='A ', copied='+', wc_rev='-'),
+  })
+  svntest.actions.run_and_verify_update(wc_dir,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status,
+                                        None, None, None,
+                                        None, None, 1)
+
+def update_moved_dir_dir_add(sbox):
+  "update locally moved dir with incoming dir"
+  sbox.build()
+  wc_dir = sbox.wc_dir
+  foo_path = "A/B/E/foo"
+  bar_path = "A/B/E/foo/bar"
+  bar_content = "This is the file 'bar'.\n"
+
+  sbox.simple_mkdir(foo_path)
+  svntest.main.file_write(sbox.ospath(bar_path), bar_content, 'wb')
+  sbox.simple_add(bar_path)
+  sbox.simple_commit()
+  # update to go back in time, before the last commit
+  svntest.main.run_svn(False, 'update', '-r', '1', wc_dir)
+  sbox.simple_move("A/B/E", "A/B/E2")
+
+  # the incoming file should auto-merge
+  expected_output = svntest.wc.State(wc_dir, {
+    'A/B/E2/foo'      : Item(status='A '),
+    'A/B/E2/foo/bar'  : Item(status='A '),
+  })
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.remove('A/B/E/alpha', 'A/B/E/beta', 'A/B/E')
+  expected_disk.add({
+    'A/B/E2'           : Item(),
+    'A/B/E2/alpha'     : Item(contents="This is the file 'alpha'.\n"),
+    'A/B/E2/beta'      : Item(contents="This is the file 'beta'.\n"),
+    'A/B/E2/foo'       : Item(),
+    'A/B/E2/foo/bar'   : Item(contents=bar_content),
+  })
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
+  expected_status.tweak('A/B/E', 'A/B/E/alpha', 'A/B/E/beta', status='D ')
+  expected_status.add({
+    'A/B/E/foo'         : Item(status='D ', wc_rev='2'),
+    'A/B/E/foo/bar'     : Item(status='D ', wc_rev='2'),
+    'A/B/E2'            : Item(status='A ', copied='+', wc_rev='-'),
+    'A/B/E2/beta'       : Item(status='  ', copied='+', wc_rev='-'),
+    'A/B/E2/alpha'      : Item(status='  ', copied='+', wc_rev='-'),
+    'A/B/E2/foo'        : Item(status='A ', copied='+', wc_rev='-'),
+    'A/B/E2/foo/bar'    : Item(status='A ', copied='+', wc_rev='-'),
+  })
+  svntest.actions.run_and_verify_update(wc_dir,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status,
+                                        None, None, None,
+                                        None, None, 1)
+
+@XFail()
+@Issue(4037)
+def update_moved_dir_file_move(sbox):
+  "update locally moved dir with incoming file move"
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  sbox.simple_move("A/B/E/alpha", "A/B/F/alpha")
+  sbox.simple_commit()
+  # update to go back in time, before the previous commit
+  svntest.main.run_svn(False, 'update', '-r', '1', wc_dir)
+  sbox.simple_move("A/B/E", "A/B/E2")
+
+  # The incoming move should auto-merge such that A/B/F/alpha appears
+  # as moved to A/B/E2/alpha -- this strategy prefers the local user's
+  # change as the solution to the conflict.
+  # ### Ideally, the user should be offered a set of alternative solutions.
+  # ### E.g. the user might prefer if A/B/E2/alpha disappeared and A/B/E/alpha
+  # ### appeared as moved to A/B/F/alpha. But the --accept option does not yet
+  # ### support tree conflicts.
+  expected_output = svntest.wc.State(wc_dir, {
+    'A/B/E2/alpha' : Item(status='A '),
+  })
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.remove('A/B/E/alpha', 'A/B/E/beta', 'A/B/E')
+  expected_disk.add({
+    'A/B/E2'           : Item(),
+    'A/B/E2/alpha'     : Item(contents="This is the file 'alpha'.\n"),
+    'A/B/E2/beta'      : Item(contents="This is the file 'beta'.\n"),
+  })
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
+  expected_status.tweak('A/B/E', 'A/B/E/alpha', 'A/B/E/beta', status='D ')
+  expected_status.add({
+    'A/B/F/alpha'       : Item(status='D '),
+    'A/B/E2'            : Item(status='A ', copied='+', wc_rev='-'),
+    'A/B/E2/alpha'      : Item(status='A ', copied='+', wc_rev='-'),
+    'A/B/E2/beta'       : Item(status='  ', copied='+', wc_rev='-'),
+  })
+  svntest.actions.run_and_verify_update(wc_dir,
+                                        expected_output,
+                                        expected_disk,
+                                        expected_status,
+                                        None, None, None,
+                                        None, None, 1)
 
 #######################################################################
 # Run the tests
@@ -5471,6 +5677,11 @@ test_list = [ None,
               revive_children_of_copy,
               skip_access_denied,
               update_to_HEAD_plus_1,
+              update_moved_dir_leaf_del,
+              update_moved_dir_edited_leaf_del,
+              update_moved_dir_file_add,
+              update_moved_dir_dir_add,
+              update_moved_dir_file_move,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/svn-bisect/subversion/tests/cmdline/upgrade_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/cmdline/upgrade_tests.py?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/cmdline/upgrade_tests.py (original)
+++ subversion/branches/svn-bisect/subversion/tests/cmdline/upgrade_tests.py Mon Nov 21 07:07:56 2011
@@ -75,6 +75,23 @@ def replace_sbox_with_tarfile(sbox, tar_
 
   shutil.move(os.path.join(extract_dir, dir), sbox.wc_dir)
 
+def replace_sbox_repo_with_tarfile(sbox, tar_filename, dir=None):
+  try:
+    svntest.main.safe_rmtree(sbox.repo_dir)
+  except OSError, e:
+    pass
+
+  if not dir:
+    dir = tar_filename.split('.')[0]
+    
+  tarpath = os.path.join(os.path.dirname(sys.argv[0]), 'upgrade_tests_data',
+                         tar_filename)
+  t = tarfile.open(tarpath, 'r:bz2')
+  extract_dir = tempfile.mkdtemp(dir=svntest.main.temp_dir)
+  for member in t.getmembers():
+    t.extract(member, extract_dir)
+
+  shutil.move(os.path.join(extract_dir, dir), sbox.repo_dir)
 
 def check_format(sbox, expected_format):
   dot_svn = svntest.main.get_admin_name()
@@ -1093,6 +1110,148 @@ def upgrade_with_missing_subdir(sbox):
                                         expected_disk,
                                         expected_status)
 
+@Issue(3994)
+def upgrade_locked(sbox):
+  "upgrade working copy with locked files"
+
+  replace_sbox_with_tarfile(sbox, 'upgrade_locked.tar.bz2')
+
+  svntest.actions.run_and_verify_svn(None, None, [], 'upgrade', sbox.wc_dir)
+
+  expected_status = svntest.wc.State(sbox.wc_dir,
+    {
+      ''                  : Item(status='  ', wc_rev=1),
+      'A'                 : Item(status='D ', wc_rev=2),
+      'A/third'           : Item(status='D ', writelocked='K', wc_rev=2),
+      'other'             : Item(status='D ', writelocked='K', wc_rev=4),
+      'iota'              : Item(status='  ', writelocked='K', wc_rev=3),
+    })
+
+  run_and_verify_status_no_server(sbox.wc_dir, expected_status)
+
+@Issue(4015)
+def upgrade_file_externals(sbox):
+  "upgrade with file externals"
+
+  sbox.build()
+  replace_sbox_with_tarfile(sbox, 'upgrade_file_externals.tar.bz2')
+  svntest.main.run_svnadmin('setuuid', sbox.repo_dir,
+                            '07146bbd-0b64-4aaf-ab70-cd76a0df2d41')
+
+  expected_output = svntest.verify.RegexOutput('r2 committed.*')
+  svntest.actions.run_and_verify_svnmucc(None, expected_output, [],
+                                         'propset', 'svn:externals',
+                                         '^/A/B/E EX\n^/A/mu muX',
+                                         sbox.repo_url + '/A/B/F')
+
+  expected_output = svntest.verify.RegexOutput('r3 committed.*')
+  svntest.actions.run_and_verify_svnmucc(None, expected_output, [],
+                                         'propset', 'svn:externals',
+                                         '^/A/B/F FX\n^/A/B/lambda lambdaX',
+                                         sbox.repo_url + '/A/C')
+
+  expected_output = svntest.verify.RegexOutput('r4 committed.*')
+  svntest.actions.run_and_verify_svnmucc(None, expected_output, [],
+                                         'propset', 'pname1', 'pvalue1',
+                                         sbox.repo_url + '/A/mu',
+                                         'propset', 'pname2', 'pvalue2',
+                                         sbox.repo_url + '/A/B/lambda',
+                                         'propset', 'pname3', 'pvalue3',
+                                         sbox.repo_url + '/A/B/E/alpha')
+
+  svntest.actions.run_and_verify_svn(None, None, [], 'upgrade', sbox.wc_dir)
+  svntest.actions.run_and_verify_svn(None, None, [], 'relocate',
+                                     'file:///tmp/repo', sbox.repo_url,
+                                     sbox.wc_dir)
+  
+  expected_output = svntest.wc.State(sbox.wc_dir, {
+      'A/mu'            : Item(status=' U'),
+      'A/B/lambda'      : Item(status=' U'),
+      'A/B/E/alpha'     : Item(status=' U'),
+      'A/C/FX/EX/alpha' : Item(status=' U'),
+      'A/C/FX/muX'      : Item(status=' U'),
+      'A/C/lambdaX'     : Item(status=' U'),
+      'A/B/F/EX/alpha'  : Item(status=' U'),
+      'A/B/F/muX'       : Item(status=' U'),
+      })
+  svntest.actions.run_and_verify_update(sbox.wc_dir, expected_output,
+                                        None, None)
+
+  ### simple_property_verify only sees last line of multi-line
+  ### property values such as svn:externals
+  simple_property_verify(sbox.wc_dir, {
+      'A/mu'          : {'pname1' : 'pvalue1' },
+      'A/B/lambda'    : {'pname2' : 'pvalue2' },
+      'A/B/E/alpha'   : {'pname3' : 'pvalue3' },
+      'A/B/F'         : {'svn:externals' : '^/A/mu muX'},
+      'A/C'           : {'svn:externals' : '^/A/B/lambda lambdaX'},
+      'A/B/F/muX'     : {'pname1' : 'pvalue1' },
+      'A/C/lambdaX'   : {'pname2' : 'pvalue2' },
+      })
+
+  simple_property_verify(sbox.ospath('A/C/FX'), {
+      ''    : {'svn:externals' : '^/A/mu muX'},
+      'muX' : {'pname1' : 'pvalue1' },
+      })
+
+  simple_property_verify(sbox.ospath('A/C/FX/EX'), {
+      'alpha' : {'pname3' : 'pvalue3' },
+      })
+
+
+@Issue(4035)
+def upgrade_missing_replaced(sbox):
+  "upgrade with missing replaced dir"
+
+  sbox.build(create_wc=False)
+  replace_sbox_with_tarfile(sbox, 'upgrade_missing_replaced.tar.bz2')
+
+  svntest.actions.run_and_verify_svn(None, None, [], 'upgrade', sbox.wc_dir)
+  svntest.main.run_svnadmin('setuuid', sbox.repo_dir,
+                            'd7130b12-92f6-45c9-9217-b9f0472c3fab')
+  svntest.actions.run_and_verify_svn(None, None, [], 'relocate',
+                                     'file:///tmp/repo', sbox.repo_url,
+                                     sbox.wc_dir)
+
+  expected_output = svntest.wc.State(sbox.wc_dir, {
+      'A/B/E'         : Item(status='  ', treeconflict='C'),
+      'A/B/E/alpha'   : Item(status='  ', treeconflict='A'),
+      'A/B/E/beta'    : Item(status='  ', treeconflict='A'),
+      })
+  expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
+  expected_status.tweak('A/B/E', status='! ', treeconflict='C', wc_rev='-')
+  expected_status.tweak('A/B/E/alpha', 'A/B/E/beta', status='D ')
+  svntest.actions.run_and_verify_update(sbox.wc_dir, expected_output,
+                                        None, expected_status)
+
+  svntest.actions.run_and_verify_svn(None, 'Reverted.*', [], 'revert', '-R',
+                                     sbox.wc_dir)
+  expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
+  svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status)
+
+@Issue(4033)
+def upgrade_not_present_replaced(sbox):
+  "upgrade with not-present replaced nodes"
+
+  sbox.build(create_wc=False)
+  replace_sbox_with_tarfile(sbox, 'upgrade_not_present_replaced.tar.bz2')
+
+  svntest.actions.run_and_verify_svn(None, None, [], 'upgrade', sbox.wc_dir)
+  svntest.main.run_svnadmin('setuuid', sbox.repo_dir,
+                            'd7130b12-92f6-45c9-9217-b9f0472c3fab')
+  svntest.actions.run_and_verify_svn(None, None, [], 'relocate',
+                                     'file:///tmp/repo', sbox.repo_url,
+                                     sbox.wc_dir)
+
+  expected_output = svntest.wc.State(sbox.wc_dir, {
+      'A/B/E'         : Item(status='E '),
+      'A/B/E/alpha'   : Item(status='A '),
+      'A/B/E/beta'    : Item(status='A '),
+      'A/B/lambda'    : Item(status='E '),
+      })
+  expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
+  svntest.actions.run_and_verify_update(sbox.wc_dir, expected_output,
+                                        None, expected_status)
 
 ########################################################################
 # Run the tests
@@ -1141,6 +1300,10 @@ test_list = [ None,
               add_add_del_del_tc,
               add_add_x2,
               upgrade_with_missing_subdir,
+              upgrade_locked,
+              upgrade_file_externals,
+              upgrade_missing_replaced,
+              upgrade_not_present_replaced,
              ]
 
 

Propchange: subversion/branches/svn-bisect/subversion/tests/libsvn_delta/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Mon Nov 21 07:07:56 2011
@@ -1,6 +1,7 @@
 Debug
 Release
 .libs
+ev2-from-delta-editor-test
 deltaparse-test
 delta-combine-test
 vdelta-test
@@ -8,6 +9,7 @@ random-test
 xml-output-test
 svndiff-test
 window-test
+editor-test
 combined
 *.o
 *.lo

Modified: subversion/branches/svn-bisect/subversion/tests/libsvn_diff/diff-diff3-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/libsvn_diff/diff-diff3-test.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/libsvn_diff/diff-diff3-test.c (original)
+++ subversion/branches/svn-bisect/subversion/tests/libsvn_diff/diff-diff3-test.c Mon Nov 21 07:07:56 2011
@@ -175,7 +175,7 @@ three_way_merge(const char *filename1,
   SVN_ERR(svn_diff_mem_string_diff3(&diff,
                                     original, modified, latest, options, pool));
 
-  actual = svn_stringbuf_create("", pool);
+  actual = svn_stringbuf_create_empty(pool);
   ostream = svn_stream_from_stringbuf(actual, pool);
 
   SVN_ERR(svn_diff_mem_string_output_merge2
@@ -265,7 +265,7 @@ two_way_diff(const char *filename1,
 
   SVN_ERR(svn_diff_mem_string_diff(&diff, original, modified, options, pool));
 
-  actual = svn_stringbuf_create("", pool);
+  actual = svn_stringbuf_create_empty(pool);
   ostream = svn_stream_from_stringbuf(actual, pool);
 
   SVN_ERR(svn_diff_mem_string_output_unified(ostream, diff,

Modified: subversion/branches/svn-bisect/subversion/tests/libsvn_diff/parse-diff-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/libsvn_diff/parse-diff-test.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/libsvn_diff/parse-diff-test.c (original)
+++ subversion/branches/svn-bisect/subversion/tests/libsvn_diff/parse-diff-test.c Mon Nov 21 07:07:56 2011
@@ -246,6 +246,15 @@ static const char *bad_git_diff_header =
   "diff --git a/ b/path 1 b/ b/path 1"                                  NL
   "new file mode 100644"                                                NL;
 
+static const char *unidiff_lacking_trailing_eol =
+  "Index: A/C/gamma"                                                    NL
+  "===================================================================" NL
+  "--- A/C/gamma\t(revision 2)"                                         NL
+  "+++ A/C/gamma\t(working copy)"                                       NL
+  "@@ -1 +1,2 @@"                                                       NL
+  " This is the file 'gamma'."                                          NL
+  "+some more bytes to 'gamma'"; /* Don't add NL after this line */
+
 
 /* Create a PATCH_FILE containing the contents of DIFF. */
 static svn_error_t *
@@ -900,6 +909,57 @@ test_git_diffs_with_spaces_diff(apr_pool
   SVN_ERR(svn_diff_close_patch_file(patch_file, pool));
   return SVN_NO_ERROR;
 }
+
+static svn_error_t *
+test_parse_unidiff_lacking_trailing_eol(apr_pool_t *pool)
+{
+  svn_patch_file_t *patch_file;
+  svn_boolean_t reverse;
+  svn_boolean_t ignore_whitespace;
+  int i;
+  apr_pool_t *iterpool;
+
+  reverse = FALSE;
+  ignore_whitespace = FALSE;
+  iterpool = svn_pool_create(pool);
+  for (i = 0; i < 2; i++)
+    {
+      svn_patch_t *patch;
+      svn_diff_hunk_t *hunk;
+
+      svn_pool_clear(iterpool);
+
+      SVN_ERR(create_patch_file(&patch_file, unidiff_lacking_trailing_eol,
+                                pool));
+
+      /* We have one patch with one hunk. Parse it. */
+      SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file, reverse,
+                                        ignore_whitespace, iterpool,
+                                        iterpool));
+      SVN_TEST_ASSERT(patch);
+      SVN_TEST_STRING_ASSERT(patch->old_filename, "A/C/gamma");
+      SVN_TEST_STRING_ASSERT(patch->new_filename, "A/C/gamma");
+      SVN_TEST_ASSERT(patch->hunks->nelts == 1);
+
+      hunk = APR_ARRAY_IDX(patch->hunks, 0, svn_diff_hunk_t *);
+      SVN_ERR(check_content(hunk, ! reverse,
+                            "This is the file 'gamma'." NL,
+                            pool));
+
+      /* Verify that the contents are as expected, with a NL appended.
+         TODO: test for notification about the NL silently appended */
+      SVN_ERR(check_content(hunk, reverse,
+                            "This is the file 'gamma'." NL
+                            "some more bytes to 'gamma'" NL,
+                            pool));
+
+      reverse = !reverse;
+      SVN_ERR(svn_diff_close_patch_file(patch_file, pool));
+    }
+  svn_pool_destroy(iterpool);
+  return SVN_NO_ERROR;
+}
+
 /* ========================================================================== */
 
 struct svn_test_descriptor_t test_funcs[] =
@@ -921,5 +981,7 @@ struct svn_test_descriptor_t test_funcs[
                    "test property diffs with odd symbols"),
     SVN_TEST_PASS2(test_git_diffs_with_spaces_diff,
                    "test git diffs with spaces in paths"),
+    SVN_TEST_XFAIL2(test_parse_unidiff_lacking_trailing_eol,
+                   "test parsing unidiffs lacking trailing eol"),
     SVN_TEST_NULL
   };

Modified: subversion/branches/svn-bisect/subversion/tests/libsvn_fs/fs-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/libsvn_fs/fs-test.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/libsvn_fs/fs-test.c (original)
+++ subversion/branches/svn-bisect/subversion/tests/libsvn_fs/fs-test.c Mon Nov 21 07:07:56 2011
@@ -658,6 +658,7 @@ revision_props(const svn_test_opts_t *op
 
   /* Copy a property's value into a new property. */
   SVN_ERR(svn_fs_revision_prop(&value, fs, 0, "color", pool));
+  SVN_TEST_ASSERT(value);
 
   s1.data = value->data;
   s1.len = value->len;
@@ -694,6 +695,7 @@ revision_props(const svn_test_opts_t *op
   /* Obtain a list of all current properties, and make sure it matches
      the expected values. */
   SVN_ERR(svn_fs_revision_proplist(&proplist, fs, 0, pool));
+  SVN_TEST_ASSERT(proplist);
   {
     svn_string_t *prop_value;
 
@@ -4799,6 +4801,102 @@ node_origin_rev(const svn_test_opts_t *o
   return SVN_NO_ERROR;
 }
 
+
+/* Helper: call svn_fs_history_location() and check the results. */
+static svn_error_t *
+check_history_location(const char *expected_path,
+                       svn_revnum_t expected_revision,
+                       svn_fs_history_t *history,
+                       apr_pool_t *pool)
+{
+  const char *actual_path;
+  svn_revnum_t actual_revision;
+
+  SVN_ERR(svn_fs_history_location(&actual_path, &actual_revision,
+                                  history, pool));
+
+  /* Validate the location against our expectations. */
+  if (actual_revision != expected_revision
+      || (actual_path && expected_path && strcmp(actual_path, expected_path))
+      || (actual_path != NULL) != (expected_path != NULL))
+    {
+      return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+                               "svn_fs_history_location() failed:\n"
+                               "  expected '%s@%ld'\n"
+                               "     found '%s@%ld",
+                               expected_path ? expected_path : "(null)",
+                               expected_revision,
+                               actual_path ? actual_path : "(null)",
+                               actual_revision);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+/* Test svn_fs_history_*(). */
+static svn_error_t *
+node_history(const svn_test_opts_t *opts,
+             apr_pool_t *pool)
+{
+  svn_fs_t *fs;
+  svn_fs_txn_t *txn;
+  svn_fs_root_t *txn_root;
+  svn_revnum_t after_rev;
+
+  /* Prepare a txn to receive the greek tree. */
+  SVN_ERR(svn_test__create_fs(&fs, "test-repo-node-history",
+                              opts, pool));
+  SVN_ERR(svn_fs_begin_txn(&txn, fs, 0, pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+
+  /* Create and verify the greek tree. */
+  SVN_ERR(svn_test__create_greek_tree(txn_root, pool));
+  SVN_ERR(test_commit_txn(&after_rev, txn, NULL, pool));
+
+  /* Make some changes, following copy_test() above. */
+
+  /* r2: copy pi to pi2, with textmods. */
+  {
+    svn_fs_root_t *rev_root;
+
+    SVN_ERR(svn_fs_revision_root(&rev_root, fs, after_rev, pool));
+    SVN_ERR(svn_fs_begin_txn(&txn, fs, after_rev, pool));
+    SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+    SVN_ERR(svn_fs_copy(rev_root, "A/D/G/pi",
+                        txn_root, "A/D/H/pi2",
+                        pool));
+    SVN_ERR(svn_test__set_file_contents
+            (txn_root, "A/D/H/pi2", "This is the file 'pi2'.\n", pool));
+    SVN_ERR(test_commit_txn(&after_rev, txn, NULL, pool));
+  }
+
+  /* Go back in history: pi2@r2 -> pi@r1 */
+  {
+    svn_fs_history_t *history;
+    svn_fs_root_t *rev_root;
+
+    SVN_ERR(svn_fs_revision_root(&rev_root, fs, after_rev, pool));
+
+    /* Fetch a history object, and walk it until its start. */
+
+    SVN_ERR(svn_fs_node_history(&history, rev_root, "A/D/H/pi2", pool));
+    SVN_ERR(check_history_location("/A/D/H/pi2", 2, history, pool));
+
+    SVN_ERR(svn_fs_history_prev(&history, history, TRUE, pool));
+    SVN_ERR(check_history_location("/A/D/H/pi2", 2, history, pool));
+
+    SVN_ERR(svn_fs_history_prev(&history, history, TRUE, pool));
+    SVN_ERR(check_history_location("/A/D/G/pi", 1, history, pool));
+
+    SVN_ERR(svn_fs_history_prev(&history, history, TRUE, pool));
+    SVN_TEST_ASSERT(history == NULL);
+  }
+
+  return SVN_NO_ERROR;
+}
+
+
+
 /* ------------------------------------------------------------------------ */
 
 /* The test table.  */
@@ -4878,5 +4976,7 @@ struct svn_test_descriptor_t test_funcs[
                        "test svn_fs_node_origin_rev"),
     SVN_TEST_OPTS_PASS(small_file_integrity,
                        "create and modify small file"),
+    SVN_TEST_OPTS_PASS(node_history,
+                       "test svn_fs_node_history"),
     SVN_TEST_NULL
   };

Modified: subversion/branches/svn-bisect/subversion/tests/libsvn_fs_base/strings-reps-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/libsvn_fs_base/strings-reps-test.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/libsvn_fs_base/strings-reps-test.c (original)
+++ subversion/branches/svn-bisect/subversion/tests/libsvn_fs_base/strings-reps-test.c Mon Nov 21 07:07:56 2011
@@ -360,7 +360,7 @@ verify_expected_record(svn_fs_t *fs,
                              size, expected_len);
 
   /* Read the string back in 100-byte chunks. */
-  text = svn_stringbuf_create("", trail->pool);
+  text = svn_stringbuf_create_empty(trail->pool);
   while (1)
     {
       size = sizeof(buf);

Modified: subversion/branches/svn-bisect/subversion/tests/libsvn_fs_fs/fs-pack-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/libsvn_fs_fs/fs-pack-test.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/libsvn_fs_fs/fs-pack-test.c (original)
+++ subversion/branches/svn-bisect/subversion/tests/libsvn_fs_fs/fs-pack-test.c Mon Nov 21 07:07:56 2011
@@ -95,6 +95,43 @@ get_rev_contents(svn_revnum_t rev, apr_p
   return apr_psprintf(pool, "%" APR_INT64_T_FMT "\n", num);
 }
 
+struct pack_notify_baton
+{
+  apr_int64_t expected_shard;
+  svn_fs_pack_notify_action_t expected_action;
+};
+
+static svn_error_t *
+pack_notify(void *baton,
+            apr_int64_t shard,
+            svn_fs_pack_notify_action_t action,
+            apr_pool_t *pool)
+{
+  struct pack_notify_baton *pnb = baton;
+
+  SVN_TEST_ASSERT(shard == pnb->expected_shard);
+  SVN_TEST_ASSERT(action == pnb->expected_action);
+
+  /* Update expectations. */
+  switch (action)
+    {
+      case svn_fs_pack_notify_start:
+        pnb->expected_action = svn_fs_pack_notify_end;
+        break;
+
+      case svn_fs_pack_notify_end:
+        pnb->expected_action = svn_fs_pack_notify_start;
+        pnb->expected_shard++;
+        break;
+
+      default:
+        return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
+                                "Unknown notification action when packing");
+    }
+
+  return SVN_NO_ERROR;
+}
+
 /* Create a packed filesystem in DIR.  Set the shard size to
    SHARD_SIZE and create NUM_REVS number of revisions (in addition to
    r0).  Use POOL for allocations.  After this function successfully
@@ -113,6 +150,7 @@ create_packed_filesystem(const char *dir
   const char *conflict;
   svn_revnum_t after_rev;
   apr_pool_t *subpool = svn_pool_create(pool);
+  struct pack_notify_baton pnb;
   apr_pool_t *iterpool;
   int version;
 
@@ -156,7 +194,9 @@ create_packed_filesystem(const char *dir
   svn_pool_destroy(subpool);
 
   /* Now pack the FS */
-  return svn_fs_pack(dir, NULL, NULL, NULL, NULL, pool);
+  pnb.expected_shard = 0;
+  pnb.expected_action = svn_fs_pack_notify_start;
+  return svn_fs_pack(dir, pack_notify, &pnb, NULL, NULL, pool);
 }
 
 

Modified: subversion/branches/svn-bisect/subversion/tests/libsvn_repos/repos-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/libsvn_repos/repos-test.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/libsvn_repos/repos-test.c (original)
+++ subversion/branches/svn-bisect/subversion/tests/libsvn_repos/repos-test.c Mon Nov 21 07:07:56 2011
@@ -1314,6 +1314,14 @@ authz(apr_pool_t *pool)
                             "Regression: incomplete ancestry test "
                             "for recursive access lookup.");
 
+  /* The authz rules for the phase 4 tests */
+  contents =
+    "[greek:/dir2//secret]"                                                  NL
+    "* ="                                                                    NL;
+  err = authz_get_handle(&authz_cfg, contents, subpool);
+  SVN_TEST_ASSERT_ERROR(err, SVN_ERR_AUTHZ_INVALID_CONFIG);
+  svn_error_clear(err);
+
   /* That's a wrap! */
   svn_pool_destroy(subpool);
   return SVN_NO_ERROR;
@@ -1340,6 +1348,149 @@ commit_authz_cb(svn_repos_authz_access_t
 
 
 
+enum action_t {
+  A_DELETE,
+  A_ADD_FILE,
+  A_ADD_DIR,
+  A_CHANGE_FILE_PROP
+};
+struct authz_path_action_t
+{
+  enum action_t action;
+  const char *path;
+  svn_boolean_t authz_error_expected;
+  const char *copyfrom_path;
+};
+
+/* Return the appropriate dir baton for the parent of PATH in *DIR_BATON,
+   allocated in POOL. */
+static svn_error_t *
+get_dir_baton(void **dir_baton,
+              const char *path,
+              const svn_delta_editor_t *editor,
+              void *root_baton,
+              apr_pool_t *pool)
+{
+  int i;
+  apr_array_header_t *path_bits = svn_path_decompose(path, pool);
+  const char *path_so_far = "";
+
+  *dir_baton = root_baton;
+  for (i = 0; i < (path_bits->nelts - 1); i++)
+    {
+      const char *path_bit = APR_ARRAY_IDX(path_bits, i, const char *);
+      path_so_far = svn_path_join(path_so_far, path_bit, pool);
+      SVN_ERR(editor->open_directory(path_so_far, *dir_baton,
+                                     SVN_INVALID_REVNUM, pool, dir_baton));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+/* Return the appropriate file baton for PATH in *FILE_BATON, allocated in
+   POOL. */
+static svn_error_t *
+get_file_baton(void **file_baton,
+               const char *path,
+               const svn_delta_editor_t *editor,
+               void *root_baton,
+               apr_pool_t *pool)
+{
+  void *dir_baton;
+
+  SVN_ERR(get_dir_baton(&dir_baton, path, editor, root_baton, pool));
+
+  SVN_ERR(editor->open_file(path, dir_baton, SVN_INVALID_REVNUM, pool,
+                            file_baton));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_path_authz(svn_repos_t *repos,
+                struct authz_path_action_t *path_action,
+                svn_authz_t *authz_file,
+                svn_revnum_t youngest_rev,
+                apr_pool_t *scratch_pool)
+{
+  void *edit_baton;
+  void *root_baton;
+  void *dir_baton;
+  void *file_baton;
+  void *out_baton;
+  const svn_delta_editor_t *editor;
+  svn_error_t *err;
+  svn_error_t *err2;
+
+  /* Create a new commit editor in which we're going to play with
+     authz */
+  SVN_ERR(svn_repos_get_commit_editor4(&editor, &edit_baton, repos,
+                                       NULL, "file://test", "/",
+                                       "plato", "test commit", NULL,
+                                       NULL, commit_authz_cb, authz_file,
+                                       scratch_pool));
+
+  /* Start fiddling.  First get the root, which is readonly. */
+  SVN_ERR(editor->open_root(edit_baton, 1, scratch_pool, &root_baton));
+
+  /* Fetch the appropriate baton for our action.  This may involve opening
+     intermediate batons, but we only care about the final one for the
+     cooresponding action. */
+  if (path_action->action == A_CHANGE_FILE_PROP)
+    SVN_ERR(get_file_baton(&file_baton, path_action->path, editor, root_baton,
+                           scratch_pool));
+  else
+    SVN_ERR(get_dir_baton(&dir_baton, path_action->path, editor, root_baton,
+                          scratch_pool));
+
+  /* Test the appropriate action. */
+  switch (path_action->action)
+    {
+      case A_DELETE:
+        err = editor->delete_entry(path_action->path, SVN_INVALID_REVNUM,
+                                   dir_baton, scratch_pool);
+        break;
+
+      case A_CHANGE_FILE_PROP:
+        err = editor->change_file_prop(file_baton, "svn:test",
+                                       svn_string_create("test", scratch_pool),
+                                       scratch_pool);
+        break;
+
+      case A_ADD_FILE:
+        err = editor->add_file(path_action->path, dir_baton,
+                               path_action->copyfrom_path, youngest_rev,
+                               scratch_pool, &out_baton);
+        break;
+
+      case A_ADD_DIR:
+        err = editor->add_directory(path_action->path, dir_baton,
+                                    path_action->copyfrom_path, youngest_rev,
+                                    scratch_pool, &out_baton);
+        break;
+    }
+
+  /* Don't worry about closing batons, just abort the edit.  Since errors
+     may be delayed, we need to capture results of the abort as well. */
+  err2 = editor->abort_edit(edit_baton, scratch_pool);
+  if (!err)
+    err = err2;
+  else
+    svn_error_clear(err2);
+
+  /* Check for potential errors. */
+  if (path_action->authz_error_expected)
+    {
+      SVN_TEST_ASSERT_ERROR(err, SVN_ERR_AUTHZ_UNWRITABLE);
+      svn_error_clear(err);
+    }
+  else
+    SVN_ERR(err);
+
+  return SVN_NO_ERROR;
+}
+
+
 /* Test that the commit editor is taking authz into account
    properly */
 static svn_error_t *
@@ -1351,13 +1502,26 @@ commit_editor_authz(const svn_test_opts_
   svn_fs_txn_t *txn;
   svn_fs_root_t *txn_root;
   svn_revnum_t youngest_rev;
-  void *edit_baton;
-  void *root_baton, *dir_baton, *dir2_baton, *file_baton;
-  svn_error_t *err;
-  const svn_delta_editor_t *editor;
   svn_authz_t *authz_file;
-  apr_pool_t *subpool = svn_pool_create(pool);
+  apr_pool_t *iterpool;
   const char *authz_contents;
+  int i;
+  struct authz_path_action_t path_actions[] = {
+      { A_DELETE,             "/iota",      TRUE },
+      { A_CHANGE_FILE_PROP,   "/iota",      TRUE },
+      { A_ADD_FILE,           "/alpha",     TRUE },
+      { A_ADD_FILE,           "/alpha",     TRUE,   "file://test/A/B/lambda" },
+      { A_ADD_DIR,            "/I",         TRUE },
+      { A_ADD_DIR,            "/J",         TRUE,   "file://test/A/D" },
+      { A_ADD_FILE,           "/A/alpha",   TRUE },
+      { A_ADD_FILE,           "/A/B/theta", FALSE },
+      { A_DELETE,             "/A/mu",      FALSE },
+      { A_ADD_DIR,            "/A/E",       FALSE },
+      { A_ADD_DIR,            "/A/J",       FALSE,  "file://test/A/D" },
+      { A_DELETE,             "A/D/G",      TRUE },
+      { A_DELETE,             "A/D/H",      FALSE },
+      { A_CHANGE_FILE_PROP,   "A/D/gamma",  FALSE }
+    };
 
   /* The Test Plan
    *
@@ -1367,25 +1531,24 @@ commit_editor_authz(const svn_test_opts_
    * authorized/denied when necessary.  We don't try to be exhaustive
    * in the kinds of authz lookups.  We just make sure that the editor
    * replies to the calls in a way that proves it is doing authz
-   * lookups.
+   * lookups.  Some actions are tested implicitly (such as open_file being
+   * required for change_file_props).
    *
-   * Note that this use of the commit editor is not kosher according
-   * to the generic editor API (we aren't allowed to continue editing
-   * after an error, nor are we allowed to assume that errors are
-   * returned by the operations which caused them).  But it should
-   * work fine with this particular editor implementation.
+   * Note that because of the error handling requirements of the generic
+   * editor API, each operation needs its own editor, which is handled by
+   * a helper function above.
    */
 
   /* Create a filesystem and repository. */
   SVN_ERR(svn_test__create_repos(&repos, "test-repo-commit-authz",
-                                 opts, subpool));
+                                 opts, pool));
   fs = svn_repos_fs(repos);
 
   /* Prepare a txn to receive the greek tree. */
-  SVN_ERR(svn_fs_begin_txn(&txn, fs, 0, subpool));
-  SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool));
-  SVN_ERR(svn_test__create_greek_tree(txn_root, subpool));
-  SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, subpool));
+  SVN_ERR(svn_fs_begin_txn(&txn, fs, 0, pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+  SVN_ERR(svn_test__create_greek_tree(txn_root, pool));
+  SVN_ERR(svn_repos_fs_commit_txn(NULL, repos, &youngest_rev, txn, pool));
   SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(youngest_rev));
 
   /* Load the authz rules for the greek tree. */
@@ -1411,147 +1574,18 @@ commit_editor_authz(const svn_test_opts_
     "[/A/D/G]"                                                               NL
     "plato = r"; /* No newline at end of file. */
 
-  SVN_ERR(authz_get_handle(&authz_file, authz_contents, subpool));
-
-  /* Create a new commit editor in which we're going to play with
-     authz */
-  SVN_ERR(svn_repos_get_commit_editor4(&editor, &edit_baton, repos,
-                                       NULL, "file://test", "/",
-                                       "plato", "test commit", NULL,
-                                       NULL, commit_authz_cb, authz_file,
-                                       subpool));
-
-  /* Start fiddling.  First get the root, which is readonly.  All
-     write operations fail because of the root's permissions. */
-  SVN_ERR(editor->open_root(edit_baton, 1, subpool, &root_baton));
-
-  /* Test denied file deletion. */
-  err = editor->delete_entry("/iota", SVN_INVALID_REVNUM, root_baton, subpool);
-  if (err == SVN_NO_ERROR || err->apr_err != SVN_ERR_AUTHZ_UNWRITABLE)
-    return svn_error_createf(SVN_ERR_TEST_FAILED, err,
-                             "Got %s error instead of expected "
-                             "SVN_ERR_AUTHZ_UNWRITABLE",
-                             err ? "unexpected" : "no");
-  svn_error_clear(err);
-
-  /* Test authorized file open. */
-  SVN_ERR(editor->open_file("/iota", root_baton, SVN_INVALID_REVNUM,
-                            subpool, &file_baton));
-
-  /* Test unauthorized file prop set. */
-  err = editor->change_file_prop(file_baton, "svn:test",
-                                 svn_string_create("test", subpool),
-                                 subpool);
-  if (err == SVN_NO_ERROR || err->apr_err != SVN_ERR_AUTHZ_UNWRITABLE)
-    return svn_error_createf(SVN_ERR_TEST_FAILED, err,
-                             "Got %s error instead of expected "
-                             "SVN_ERR_AUTHZ_UNWRITABLE",
-                             err ? "unexpected" : "no");
-  svn_error_clear(err);
-
-  /* Test denied file addition. */
-  err = editor->add_file("/alpha", root_baton, NULL, SVN_INVALID_REVNUM,
-                         subpool, &file_baton);
-  if (err == SVN_NO_ERROR || err->apr_err != SVN_ERR_AUTHZ_UNWRITABLE)
-    return svn_error_createf(SVN_ERR_TEST_FAILED, err,
-                             "Got %s error instead of expected "
-                             "SVN_ERR_AUTHZ_UNWRITABLE",
-                             err ? "unexpected" : "no");
-  svn_error_clear(err);
-
-  /* Test denied file copy. */
-  err = editor->add_file("/alpha", root_baton, "file://test/A/B/lambda",
-                         youngest_rev, subpool, &file_baton);
-  if (err == SVN_NO_ERROR || err->apr_err != SVN_ERR_AUTHZ_UNWRITABLE)
-    return svn_error_createf(SVN_ERR_TEST_FAILED, err,
-                             "Got %s error instead of expected "
-                             "SVN_ERR_AUTHZ_UNWRITABLE",
-                             err ? "unexpected" : "no");
-  svn_error_clear(err);
-
-  /* Test denied directory addition. */
-  err = editor->add_directory("/I", root_baton, NULL,
-                              SVN_INVALID_REVNUM, subpool, &dir_baton);
-  if (err == SVN_NO_ERROR || err->apr_err != SVN_ERR_AUTHZ_UNWRITABLE)
-    return svn_error_createf(SVN_ERR_TEST_FAILED, err,
-                             "Got %s error instead of expected "
-                             "SVN_ERR_AUTHZ_UNWRITABLE",
-                             err ? "unexpected" : "no");
-  svn_error_clear(err);
-
-  /* Test denied directory copy. */
-  err = editor->add_directory("/J", root_baton, "file://test/A/D",
-                              youngest_rev, subpool, &dir_baton);
-  if (err == SVN_NO_ERROR || err->apr_err != SVN_ERR_AUTHZ_UNWRITABLE)
-    return svn_error_createf(SVN_ERR_TEST_FAILED, err,
-                             "Got %s error instead of expected "
-                             "SVN_ERR_AUTHZ_UNWRITABLE",
-                             err ? "unexpected" : "no");
-  svn_error_clear(err);
-
-  /* Open directory /A, to which we have read/write access. */
-  SVN_ERR(editor->open_directory("/A", root_baton,
-                                 SVN_INVALID_REVNUM,
-                                 subpool, &dir_baton));
-
-  /* Test denied file addition.  Denied because of a conflicting rule
-     on the file path itself. */
-  err = editor->add_file("/A/alpha", dir_baton, NULL,
-                         SVN_INVALID_REVNUM, subpool, &file_baton);
-  if (err == SVN_NO_ERROR || err->apr_err != SVN_ERR_AUTHZ_UNWRITABLE)
-    return svn_error_createf(SVN_ERR_TEST_FAILED, err,
-                             "Got %s error instead of expected "
-                             "SVN_ERR_AUTHZ_UNWRITABLE",
-                             err ? "unexpected" : "no");
-  svn_error_clear(err);
-
-  /* Test authorized file addition. */
-  SVN_ERR(editor->add_file("/A/B/theta", dir_baton, NULL,
-                           SVN_INVALID_REVNUM, subpool,
-                           &file_baton));
+  SVN_ERR(authz_get_handle(&authz_file, authz_contents, pool));
 
-  /* Test authorized file deletion. */
-  SVN_ERR(editor->delete_entry("/A/mu", SVN_INVALID_REVNUM, dir_baton,
-                               subpool));
-
-  /* Test authorized directory creation. */
-  SVN_ERR(editor->add_directory("/A/E", dir_baton, NULL,
-                                SVN_INVALID_REVNUM, subpool,
-                                &dir2_baton));
-
-  /* Test authorized copy of a tree. */
-  SVN_ERR(editor->add_directory("/A/J", dir_baton, "file://test/A/D",
-                                youngest_rev, subpool,
-                                &dir2_baton));
-
-  /* Open /A/D.  This should be granted. */
-  SVN_ERR(editor->open_directory("/A/D", dir_baton, SVN_INVALID_REVNUM,
-                                 subpool, &dir_baton));
-
-  /* Test denied recursive deletion. */
-  err = editor->delete_entry("/A/D/G", SVN_INVALID_REVNUM, dir_baton,
-                             subpool);
-  if (err == SVN_NO_ERROR || err->apr_err != SVN_ERR_AUTHZ_UNWRITABLE)
-    return svn_error_createf(SVN_ERR_TEST_FAILED, err,
-                             "Got %s error instead of expected "
-                             "SVN_ERR_AUTHZ_UNWRITABLE",
-                             err ? "unexpected" : "no");
-  svn_error_clear(err);
-
-  /* Test authorized recursive deletion. */
-  SVN_ERR(editor->delete_entry("/A/D/H", SVN_INVALID_REVNUM,
-                               dir_baton, subpool));
-
-  /* Test authorized propset (open the file first). */
-  SVN_ERR(editor->open_file("/A/D/gamma", dir_baton, SVN_INVALID_REVNUM,
-                            subpool, &file_baton));
-  SVN_ERR(editor->change_file_prop(file_baton, "svn:test",
-                                   svn_string_create("test", subpool),
-                                   subpool));
+  iterpool = svn_pool_create(pool);
+  for (i = 0; i < (sizeof(path_actions) / sizeof(struct authz_path_action_t));
+        i++)
+    {
+      svn_pool_clear(iterpool);
+      SVN_ERR(test_path_authz(repos, &path_actions[i], authz_file,
+                              youngest_rev, iterpool));
+    }
 
-  /* Done. */
-  SVN_ERR(editor->abort_edit(edit_baton, subpool));
-  svn_pool_destroy(subpool);
+  svn_pool_destroy(iterpool);
 
   return SVN_NO_ERROR;
 }
@@ -2487,6 +2521,45 @@ test_get_file_revs(const svn_test_opts_t
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+issue_4060(const svn_test_opts_t *opts,
+           apr_pool_t *pool)
+{
+  apr_pool_t *subpool = svn_pool_create(pool);
+  svn_authz_t *authz_cfg;
+  svn_boolean_t allowed;
+  const char *authz_contents =
+    "[/A/B]"                                                               NL
+    "ozymandias = rw"                                                      NL
+    "[/]"                                                                  NL
+    "ozymandias = r"                                                       NL
+    ""                                                                     NL;
+
+  SVN_ERR(authz_get_handle(&authz_cfg, authz_contents, subpool));
+
+  SVN_ERR(svn_repos_authz_check_access(authz_cfg, "babylon",
+                                       "/A/B/C", "ozymandias",
+                                       svn_authz_write | svn_authz_recursive,
+                                       &allowed, subpool));
+  SVN_TEST_ASSERT(allowed);
+
+  SVN_ERR(svn_repos_authz_check_access(authz_cfg, "",
+                                       "/A/B/C", "ozymandias",
+                                       svn_authz_write | svn_authz_recursive,
+                                       &allowed, subpool));
+  SVN_TEST_ASSERT(allowed);
+
+  SVN_ERR(svn_repos_authz_check_access(authz_cfg, NULL,
+                                       "/A/B/C", "ozymandias",
+                                       svn_authz_write | svn_authz_recursive,
+                                       &allowed, subpool));
+  SVN_TEST_ASSERT(allowed);
+
+  svn_pool_destroy(subpool);
+
+  return SVN_NO_ERROR;
+}
+
 
 /* The test table.  */
 
@@ -2521,5 +2594,7 @@ struct svn_test_descriptor_t test_funcs[
                        "test svn_repos_get_logs ranges and limits"),
     SVN_TEST_OPTS_PASS(test_get_file_revs,
                        "test svn_repos_get_file_revsN"),
+    SVN_TEST_OPTS_PASS(issue_4060,
+                       "test issue 4060"),
     SVN_TEST_NULL
   };

Propchange: subversion/branches/svn-bisect/subversion/tests/libsvn_subr/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Mon Nov 21 07:07:56 2011
@@ -34,3 +34,4 @@ dirent_uri-test
 auth-test
 eol-test
 subst_translate-test
+spillbuf-test

Modified: subversion/branches/svn-bisect/subversion/tests/libsvn_subr/cache-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/libsvn_subr/cache-test.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/libsvn_subr/cache-test.c (original)
+++ subversion/branches/svn-bisect/subversion/tests/libsvn_subr/cache-test.c Mon Nov 21 07:07:56 2011
@@ -182,16 +182,9 @@ test_membuffer_cache_basic(apr_pool_t *p
 {
   svn_cache__t *cache;
   svn_membuffer_t *membuffer;
-  svn_boolean_t thread_safe;
-
-#if APR_HAS_THREADS
-  thread_safe = TRUE;
-#else
-  thread_safe = FALSE;
-#endif
 
   SVN_ERR(svn_cache__membuffer_cache_create(&membuffer, 10*1024, 1,
-                                            thread_safe, pool));
+                                            TRUE, pool));
 
   /* Create a cache with just one entry. */
   SVN_ERR(svn_cache__create_membuffer_cache(&cache,

Modified: subversion/branches/svn-bisect/subversion/tests/libsvn_subr/dirent_uri-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/tests/libsvn_subr/dirent_uri-test.c?rev=1204374&r1=1204373&r2=1204374&view=diff
==============================================================================
--- subversion/branches/svn-bisect/subversion/tests/libsvn_subr/dirent_uri-test.c (original)
+++ subversion/branches/svn-bisect/subversion/tests/libsvn_subr/dirent_uri-test.c Mon Nov 21 07:07:56 2011
@@ -1441,28 +1441,6 @@ static const testcase_ancestor_t relpath
     { "X:foo",          "X:bar",            NULL },
   };
 
-static svn_error_t *
-test_relpath_is_ancestor(apr_pool_t *pool)
-{
-  const testcase_ancestor_t *t;
-
-  for (t = relpath_ancestor_tests;
-       t < relpath_ancestor_tests + COUNT_OF(relpath_ancestor_tests);
-       t++)
-    {
-      svn_boolean_t retval;
-
-      retval = svn_relpath__is_ancestor(t->path1, t->path2);
-      if (!!t->result != retval)
-        return svn_error_createf
-          (SVN_ERR_TEST_FAILED, NULL,
-           "svn_relpath_is_ancestor (%s, %s) returned %s instead of %s",
-           t->path1, t->path2, retval ? "TRUE" : "FALSE",
-           t->result ? "TRUE" : "FALSE");
-    }
-  return SVN_NO_ERROR;
-}
-
 static const testcase_ancestor_t uri_ancestor_tests[] =
   {
     { "http://test",    "http://test",      "" },
@@ -1860,133 +1838,6 @@ test_dirent_is_child(apr_pool_t *pool)
 }
 
 static svn_error_t *
-test_relpath_is_child(apr_pool_t *pool)
-{
-  int i, j;
-
-  static const char * const paths[] = {
-    "",
-    "foo",
-    "foo/bar",
-    "foo/bars",
-    "foo/baz",
-    "foo/bar/baz",
-    "flu/blar/blaz",
-    "foo/bar/baz/bing/boom",
-    ".foo",
-    ":",
-    "foo2",
-    "food",
-    "bar",
-    "baz",
-    "ba",
-    "bad"
-    };
-
-  /* Maximum number of path[] items for all platforms */
-#define MAX_PATHS 32
-
-  static const char * const
-    remainders[COUNT_OF(paths)][MAX_PATHS] = {
-    { 0, "foo", "foo/bar", "foo/bars", "foo/baz", "foo/bar/baz",
-      "flu/blar/blaz", "foo/bar/baz/bing/boom", ".foo", ":", "foo2", "food",
-      "bar", "baz", "ba", "bad" },
-    { 0, 0, "bar", "bars", "baz", "bar/baz", 0, "bar/baz/bing/boom", 0, 0, 0,
-      0, 0, 0, 0, 0 },
-    { 0, 0, 0, 0, 0, "baz", 0, "baz/bing/boom", 0, 0, 0, 0, 0, 0, 0, 0 },
-    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-    { 0, 0, 0, 0, 0, 0, 0, "bing/boom", 0, 0, 0, 0, 0, 0, 0, 0 },
-    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-  };
-
-  for (i = 0; i < COUNT_OF(paths); i++)
-    {
-      for (j = 0; j < COUNT_OF(paths); j++)
-        {
-          const char *remainder;
-
-          remainder = svn_dirent_is_child(paths[i], paths[j], pool);
-
-          if (strcmp(paths[j], "foodbar") == 0)
-            SVN_ERR_MALFUNCTION();
-
-          if (((remainder) && (! remainders[i][j]))
-              || ((! remainder) && (remainders[i][j]))
-              || (remainder && strcmp(remainder, remainders[i][j])))
-            return svn_error_createf
-              (SVN_ERR_TEST_FAILED, NULL,
-               "svn_relpath_is_child(%s, %s) returned '%s' instead of '%s'",
-               paths[i], paths[j],
-               remainder ? remainder : "(null)",
-               remainders[i][j] ? remainders[i][j] : "(null)" );
-        }
-    }
-
-#undef NUM_TEST_PATHS
-  return SVN_NO_ERROR;
-}
-
-
-static svn_error_t *
-test_uri_is_child(apr_pool_t *pool)
-{
-  int i, j;
-
-  static const char * const paths[] = {
-    "http://foo/bar",
-    "http://foo/bar%20bell",
-    "http://foo/baz",
-    "http://foo",
-    "http://f",
-    "file://foo/bar",
-    "file://foo/bar/baz%20bol",
-    };
-
-  static const char * const
-    remainders[COUNT_OF(paths)][COUNT_OF(paths)] = {
-    { 0, 0, 0, 0, 0, 0, 0 },
-    { 0, 0, 0, 0, 0, 0, 0 },
-    { 0, 0, 0, 0, 0, 0, 0 },
-    { "bar", "bar bell", "baz", 0, 0, 0, 0 },
-    { 0, 0, 0, 0, 0, 0, 0 },
-    { 0, 0, 0, 0, 0, 0, "baz bol" },
-    { 0, 0, 0, 0, 0, 0, 0 },
-  };
-
-  for (i = 0; i < COUNT_OF(paths); i++)
-    {
-      for (j = 0; j < COUNT_OF(paths); j++)
-        {
-          const char *remainder;
-
-          remainder = svn_uri__is_child(paths[i], paths[j], pool);
-
-          if (((remainder) && (! remainders[i][j]))
-              || ((! remainder) && (remainders[i][j]))
-              || (remainder && strcmp(remainder, remainders[i][j])))
-            return svn_error_createf
-              (SVN_ERR_TEST_FAILED, NULL,
-               "svn_uri_is_child (%s, %s) [%d,%d] "
-               "returned '%s' instead of '%s'",
-               paths[i], paths[j], i, j,
-               remainder ? remainder : "(null)",
-               remainders[i][j] ? remainders[i][j] : "(null)" );
-        }
-    }
-
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
 test_dirent_get_absolute(apr_pool_t *pool)
 {
   int i;
@@ -2686,7 +2537,7 @@ test_fspath_join(apr_pool_t *pool)
 }
 
 static svn_error_t *
-test_fspath_is_child(apr_pool_t *pool)
+test_fspath_skip_ancestor(apr_pool_t *pool)
 {
   int i, j;
 
@@ -2701,12 +2552,12 @@ test_fspath_is_child(apr_pool_t *pool)
 
   static const char * const
     remainders[COUNT_OF(paths)][COUNT_OF(paths)] = {
-    { 0,  "f",  "foo",  "foo/bar",  "foo/bars", "foo/bar/baz" },
-    { 0,  0,    0,      0,          0,          0             },
-    { 0,  0,    0,      "bar",      "bars",     "bar/baz"     },
-    { 0,  0,    0,      0,          0,          "baz"         },
-    { 0,  0,    0,      0,          0,          0             },
-    { 0,  0,    0,      0,          0,          0             },
+    { "", "f",  "foo",  "foo/bar",  "foo/bars", "foo/bar/baz" },
+    { 0,  "",   0,      0,          0,          0             },
+    { 0,  0,    "",     "bar",      "bars",     "bar/baz"     },
+    { 0,  0,    0,      "",         0,          "baz"         },
+    { 0,  0,    0,      0,          "",         0             },
+    { 0,  0,    0,      0,          0,          ""            },
   };
 
   for (i = 0; i < COUNT_OF(paths); i++)
@@ -2714,7 +2565,7 @@ test_fspath_is_child(apr_pool_t *pool)
       for (j = 0; j < COUNT_OF(paths); j++)
         {
           const char *remainder
-            = svn_fspath__is_child(paths[i], paths[j], pool);
+            = svn_fspath__skip_ancestor(paths[i], paths[j]);
 
           SVN_TEST_STRING_ASSERT(remainder, remainders[i][j]);
         }
@@ -2861,14 +2712,8 @@ struct svn_test_descriptor_t test_funcs[
                    "test svn_uri_get_longest_ancestor"),
     SVN_TEST_PASS2(test_dirent_is_child,
                    "test svn_dirent_is_child"),
-    SVN_TEST_PASS2(test_relpath_is_child,
-                   "test svn_relpath_is_child"),
-    SVN_TEST_PASS2(test_uri_is_child,
-                   "test svn_uri_is_child"),
     SVN_TEST_PASS2(test_dirent_is_ancestor,
                    "test svn_dirent_is_ancestor"),
-    SVN_TEST_PASS2(test_relpath_is_ancestor,
-                   "test svn_relpath_is_ancestor"),
     SVN_TEST_PASS2(test_uri_is_ancestor,
                    "test svn_uri_is_ancestor"),
     SVN_TEST_PASS2(test_dirent_skip_ancestor,
@@ -2905,8 +2750,8 @@ struct svn_test_descriptor_t test_funcs[
                    "test svn_fspath__is_canonical"),
     SVN_TEST_PASS2(test_fspath_join,
                    "test svn_fspath__join"),
-    SVN_TEST_PASS2(test_fspath_is_child,
-                   "test svn_fspath__is_child"),
+    SVN_TEST_PASS2(test_fspath_skip_ancestor,
+                   "test svn_fspath__skip_ancestor"),
     SVN_TEST_PASS2(test_fspath_dirname_basename_split,
                    "test svn_fspath__dirname/basename/split"),
     SVN_TEST_PASS2(test_fspath_get_longest_ancestor,



Mime
View raw message