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

svn commit: r1764214 [19/21] - in /subversion/branches/ra-git: ./ build/ build/ac-macros/ build/generator/ build/win32/ contrib/client-side/ contrib/client-side/svnmerge/ contrib/hook-scripts/ contrib/server-side/ contrib/server-side/fsfsfixer/fixer/ c...

Modified: subversion/branches/ra-git/subversion/tests/cmdline/svntest/mergetrees.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/svntest/mergetrees.py?rev=1764214&r1=1764213&r2=1764214&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/svntest/mergetrees.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/svntest/mergetrees.py Tue Oct 11 09:11:50 2016
@@ -29,7 +29,7 @@ import shutil, sys, re, os
 import time
 
 # Our testing module
-import main, wc, verify, actions, testcase
+from svntest import main, wc, verify, actions, testcase
 
 from prop_tests import binary_mime_type_on_text_file_warning
 

Modified: subversion/branches/ra-git/subversion/tests/cmdline/svntest/objects.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/svntest/objects.py?rev=1764214&r1=1764213&r2=1764214&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/svntest/objects.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/svntest/objects.py Tue Oct 11 09:11:50 2016
@@ -127,7 +127,7 @@ def locate_db_dump():
     try:
       if subprocess.Popen([db_dump_name, "-V"]).wait() == 0:
         return db_dump_name
-    except OSError, e:
+    except OSError as e:
       pass
   return 'none'
 

Modified: subversion/branches/ra-git/subversion/tests/cmdline/svntest/sandbox.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/svntest/sandbox.py?rev=1764214&r1=1764213&r2=1764214&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/svntest/sandbox.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/svntest/sandbox.py Tue Oct 11 09:11:50 2016
@@ -434,7 +434,8 @@ class Sandbox:
   def simple_append(self, dest, contents, truncate=False):
     """Append CONTENTS to file DEST, optionally truncating it first.
        DEST is a relpath relative to the WC."""
-    open(self.ospath(dest), truncate and 'wb' or 'ab').write(contents)
+    svntest.main.file_write(self.ospath(dest), contents,
+                            truncate and 'wb' or 'ab')
 
   def simple_lock(self, *targets):
     """Lock TARGETS in the WC.

Modified: subversion/branches/ra-git/subversion/tests/cmdline/svntest/testcase.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/svntest/testcase.py?rev=1764214&r1=1764213&r2=1764214&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/svntest/testcase.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/svntest/testcase.py Tue Oct 11 09:11:50 2016
@@ -141,9 +141,9 @@ class FunctionTestCase(TestCase):
     # docstring on it.
     assert isinstance(func, types.FunctionType)
 
-    name = func.func_name
+    name = func.__name__
 
-    assert func.func_code.co_argcount == 1, \
+    assert func.__code__.co_argcount == 1, \
         '%s must take an sbox argument' % name
 
     doc = func.__doc__.strip()
@@ -165,13 +165,13 @@ class FunctionTestCase(TestCase):
     self.skip_cross_check = skip_cross_check
 
   def get_function_name(self):
-    return self.func.func_name
+    return self.func.__name__
 
   def get_sandbox_name(self):
     """Base the sandbox's name on the name of the file in which the
     function was defined."""
 
-    filename = self.func.func_code.co_filename
+    filename = self.func.__code__.co_filename
     return os.path.splitext(os.path.basename(filename))[0]
 
   def run(self, sandbox):

Modified: subversion/branches/ra-git/subversion/tests/cmdline/svntest/tree.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/svntest/tree.py?rev=1764214&r1=1764213&r2=1764214&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/svntest/tree.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/svntest/tree.py Tue Oct 11 09:11:50 2016
@@ -499,6 +499,7 @@ def create_from_path(path, contents=None
 
 
 eol_re = re.compile(r'(\r\n|\r)')
+eol_re_binary = re.compile(br'(\r\n|\r)')
 
 # helper for build_tree_from_wc()
 def get_props(paths):
@@ -544,7 +545,10 @@ def get_props(paths):
       # contains a CR character XML-encoded as '
'.  The XML
       # parser converts it back into a CR character.  So again convert
       # all end-of-line variants into a single LF:
-      value = eol_re.sub('\n', value)
+      if isinstance(value, str):
+        value = eol_re.sub('\n', value)
+      else:
+        value = eol_re_binary.sub(b'\n', value)
       file_props[name] = value
     files[filename] = file_props
 
@@ -715,7 +719,7 @@ def _dump_tree(n,indent="",stream=sys.st
   the SVNTreeNode N. Prefix each line with the string INDENT."""
 
   # Code partially stolen from Dave Beazley
-  tmp_children = sorted(n.children or [])
+  tmp_children = sorted(n.children or [], key=SVNTreeNode.get_printable_path)
 
   if n.name == root_node_name:
     stream.write("%s%s\n" % (indent, "ROOT"))
@@ -862,10 +866,16 @@ def build_tree_from_diff_summarize(lines
 #   process for every file and dir in the working copy!
 
 
-def build_tree_from_wc(wc_path, load_props=0, ignore_svn=1):
+def build_tree_from_wc(wc_path, load_props=0, ignore_svn=1, keep_eol_style=False):
     """Takes WC_PATH as the path to a working copy.  Walks the tree below
     that path, and creates the tree based on the actual found
     files.  If IGNORE_SVN is true, then exclude SVN admin dirs from the tree.
-    If LOAD_PROPS is true, the props will be added to the tree."""
+    If LOAD_PROPS is true, the props will be added to the tree.
+
+    If KEEP_EOL_STYLE is set, don't let Python normalize the EOL when
+    reading working copy contents as text files.  It has no effect on
+    binary files.
+    """
 
-    return svntest.wc.State.from_wc(wc_path, load_props, ignore_svn).old_tree()
+    return svntest.wc.State.from_wc(wc_path, load_props, ignore_svn,
+                                    keep_eol_style).old_tree()

Modified: subversion/branches/ra-git/subversion/tests/cmdline/svntest/verify.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/svntest/verify.py?rev=1764214&r1=1764213&r2=1764214&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/svntest/verify.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/svntest/verify.py Tue Oct 11 09:11:50 2016
@@ -189,7 +189,7 @@ class RegexOutput(ExpectedOutput):
 
   def __init__(self, expected, match_all=True):
     "EXPECTED is a regular expression string."
-    assert isinstance(expected, str)
+    assert isinstance(expected, str) or isinstance(expected, bytes)
     ExpectedOutput.__init__(self, expected, match_all)
     self.expected_re = re.compile(expected)
 
@@ -416,9 +416,10 @@ def compare_and_display_lines(message, l
   if not isinstance(expected, ExpectedOutput):
     expected = ExpectedOutput(expected)
 
-  if isinstance(actual, str):
-    actual = [actual]
-  actual = svntest.main.filter_dbg(actual)
+  actual = svntest.main.ensure_list(actual)
+  if len(actual) > 0:
+    is_binary = not isinstance(actual[0], str)
+    actual = svntest.main.filter_dbg(actual, is_binary)
 
   if not expected.matches(actual):
     expected.display_differences(message, label, actual)
@@ -484,7 +485,7 @@ class DumpParser:
     return m.group(1)
 
   def parse_blank(self, required=True):
-    if self.lines[self.current] != '\n':  # Works on Windows
+    if self.lines[self.current] != b'\n':  # Works on Windows
       if required:
         raise SVNDumpParseError("expected blank at line %d\n%s"
                                 % (self.current, self.lines[self.current]))
@@ -494,7 +495,7 @@ class DumpParser:
     return True
 
   def parse_header(self, header):
-    regex = '([^:]*): (.*)$'
+    regex = b'([^:]*): (.*)$'
     m = re.match(regex, self.lines[self.current])
     if not m:
       raise SVNDumpParseError("expected a header at line %d, but found:\n%s"
@@ -504,80 +505,80 @@ class DumpParser:
 
   def parse_headers(self):
     headers = []
-    while self.lines[self.current] != '\n':
+    while self.lines[self.current] != b'\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)
+    return self.parse_line(header + b': (false|true)$', required)
 
   def parse_format(self):
-    return self.parse_line('SVN-fs-dump-format-version: ([0-9]+)$')
+    return self.parse_line(b'SVN-fs-dump-format-version: ([0-9]+)$')
 
   def parse_uuid(self):
-    return self.parse_line('UUID: ([0-9a-z-]+)$')
+    return self.parse_line(b'UUID: ([0-9a-z-]+)$')
 
   def parse_revision(self):
-    return self.parse_line('Revision-number: ([0-9]+)$')
+    return self.parse_line(b'Revision-number: ([0-9]+)$')
 
   def parse_prop_delta(self):
-    return self.parse_line('Prop-delta: (false|true)$', required=False)
+    return self.parse_line(b'Prop-delta: (false|true)$', required=False)
 
   def parse_prop_length(self, required=True):
-    return self.parse_line('Prop-content-length: ([0-9]+)$', required)
+    return self.parse_line(b'Prop-content-length: ([0-9]+)$', required)
 
   def parse_content_length(self, required=True):
-    return self.parse_line('Content-length: ([0-9]+)$', required)
+    return self.parse_line(b'Content-length: ([0-9]+)$', required)
 
   def parse_path(self):
-    path = self.parse_line('Node-path: (.*)$', required=False)
+    path = self.parse_line(b'Node-path: (.*)$', required=False)
     return path
 
   def parse_kind(self):
-    return self.parse_line('Node-kind: (.+)$', required=False)
+    return self.parse_line(b'Node-kind: (.+)$', required=False)
 
   def parse_action(self):
-    return self.parse_line('Node-action: ([0-9a-z-]+)$')
+    return self.parse_line(b'Node-action: ([0-9a-z-]+)$')
 
   def parse_copyfrom_rev(self):
-    return self.parse_line('Node-copyfrom-rev: ([0-9]+)$', required=False)
+    return self.parse_line(b'Node-copyfrom-rev: ([0-9]+)$', required=False)
 
   def parse_copyfrom_path(self):
-    path = self.parse_line('Node-copyfrom-path: (.+)$', required=False)
+    path = self.parse_line(b'Node-copyfrom-path: (.+)$', required=False)
     if not path and self.lines[self.current] == 'Node-copyfrom-path: \n':
       self.current += 1
       path = ''
     return path
 
   def parse_copy_md5(self):
-    return self.parse_line('Text-copy-source-md5: ([0-9a-z]+)$', required=False)
+    return self.parse_line(b'Text-copy-source-md5: ([0-9a-z]+)$', required=False)
 
   def parse_copy_sha1(self):
-    return self.parse_line('Text-copy-source-sha1: ([0-9a-z]+)$', required=False)
+    return self.parse_line(b'Text-copy-source-sha1: ([0-9a-z]+)$', required=False)
 
   def parse_text_md5(self):
-    return self.parse_line('Text-content-md5: ([0-9a-z]+)$', required=False)
+    return self.parse_line(b'Text-content-md5: ([0-9a-z]+)$', required=False)
 
   def parse_text_sha1(self):
-    return self.parse_line('Text-content-sha1: ([0-9a-z]+)$', required=False)
+    return self.parse_line(b'Text-content-sha1: ([0-9a-z]+)$', required=False)
 
   def parse_text_delta(self):
-    return self.parse_line('Text-delta: (false|true)$', required=False)
+    return self.parse_line(b'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)
+    return self.parse_line(b'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)
+    return self.parse_line(b'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)
+    return self.parse_line(b'Text-content-length: ([0-9]+)$', required=False)
 
   def get_props(self):
     props = []
-    while not re.match('PROPS-END$', self.lines[self.current]):
+    while not re.match(b'PROPS-END$', self.lines[self.current]):
       props.append(self.lines[self.current])
       self.current += 1
     self.current += 1
@@ -593,7 +594,7 @@ class DumpParser:
         curprop[0] += 1
 
         # key / value
-        key = ''
+        key = b''
         while len(key) != klen + 1:
           key += props[curprop[0]]
           curprop[0] += 1
@@ -601,10 +602,10 @@ class DumpParser:
 
         return key
 
-      if props[curprop[0]].startswith('K'):
+      if props[curprop[0]].startswith(b'K'):
         key = read_key_or_value(curprop)
         value = read_key_or_value(curprop)
-      elif props[curprop[0]].startswith('D'):
+      elif props[curprop[0]].startswith(b'D'):
         key = read_key_or_value(curprop)
         value = None
       else:
@@ -614,7 +615,7 @@ class DumpParser:
     return prophash
 
   def get_content(self, length):
-    content = ''
+    content = b''
     while len(content) < length:
       content += self.lines[self.current]
       self.current += 1
@@ -637,22 +638,22 @@ class DumpParser:
     headers = dict(headers_list)
 
     # Content-length must be last, if present
-    if 'Content-length' in headers and headers_list[-1][0] != 'Content-length':
+    if b'Content-length' in headers and headers_list[-1][0] != b'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]+)$'),
+        ('copyfrom_rev',    b'Node-copyfrom-rev',    b'([0-9]+)$'),
+        ('copyfrom_path',   b'Node-copyfrom-path',   b'(.*)$'),
+        ('copy_md5',        b'Text-copy-source-md5', b'([0-9a-z]+)$'),
+        ('copy_sha1',       b'Text-copy-source-sha1',b'([0-9a-z]+)$'),
+        ('prop_length',     b'Prop-content-length',  b'([0-9]+)$'),
+        ('text_length',     b'Text-content-length',  b'([0-9]+)$'),
+        ('text_md5',        b'Text-content-md5',     b'([0-9a-z]+)$'),
+        ('text_sha1',       b'Text-content-sha1',    b'([0-9a-z]+)$'),
+        ('content_length',  b'Content-length',       b'([0-9]+)$'),
         ]:
       if not header in headers:
         node[key] = None
@@ -743,7 +744,7 @@ def compare_dump_files(message, label, e
   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:
+      if b'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)
@@ -765,8 +766,8 @@ def compare_dump_files(message, label, e
               action_record['blanks'] = 0
 
   if parsed_expected != parsed_actual:
-    print 'DIFF of raw dumpfiles (including expected differences)'
-    print ''.join(ndiff(expected, actual))
+    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(),

Modified: subversion/branches/ra-git/subversion/tests/cmdline/svntest/wc.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/svntest/wc.py?rev=1764214&r1=1764213&r2=1764214&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/svntest/wc.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/svntest/wc.py Tue Oct 11 09:11:50 2016
@@ -26,16 +26,17 @@
 import os
 import sys
 import re
-import urllib
 import logging
 import pprint
 
 if sys.version_info[0] >= 3:
   # Python >=3.0
   from io import StringIO
+  from urllib.parse import quote as urllib_quote
 else:
   # Python <3.0
   from cStringIO import StringIO
+  from urllib import quote as urllib_quote
 
 import svntest
 
@@ -172,7 +173,7 @@ class State:
     "Remove PATHS recursively from the state (the paths must exist)."
     for subtree_path in paths:
       subtree_path = to_relpath(subtree_path)
-      for path, item in self.desc.items():
+      for path, item in svntest.main.ensure_list(self.desc.items()):
         if path == subtree_path or path[:len(subtree_path) + 1] == subtree_path + '/':
           del self.desc[path]
 
@@ -201,7 +202,7 @@ class State:
       for path in args:
         try:
           path_ref = self.desc[to_relpath(path)]
-        except KeyError, e:
+        except KeyError as e:
           e.args = ["Path '%s' not present in WC state descriptor" % path]
           raise
         path_ref.tweak(**kw)
@@ -225,13 +226,13 @@ class State:
 
     """
     temp = {}
-    for src, dst in sorted(moves.items(), key=lambda (src, dst): src)[::-1]:
+    for src, dst in sorted(moves.items(), key=lambda pair: pair[0])[::-1]:
       temp[src] = {}
-      for path, item in self.desc.items():
+      for path, item in svntest.main.ensure_list(self.desc.items()):
         if path == src or path[:len(src) + 1] == src + '/':
           temp[src][path] = item;
           del self.desc[path]
-    for src, dst in sorted(moves.items(), key=lambda (src, dst): dst):
+    for src, dst in sorted(moves.items(), key=lambda pair: pair[1]):
       for path, item in temp[src].items():
         if path == src:
           new_path = dst
@@ -273,7 +274,7 @@ class State:
           os.makedirs(dirpath)
 
         # write out the file contents now
-        open(fullpath, 'wb').write(item.contents)
+        svntest.main.file_write(fullpath, item.contents, 'wb')
 
   def normalize(self):
     """Return a "normalized" version of self.
@@ -380,7 +381,7 @@ class State:
 
   def tweak_for_entries_compare(self):
     for path, item in self.desc.copy().items():
-      if item.status:
+      if item.status and path in self.desc:
         # If this is an unversioned tree-conflict, remove it.
         # These are only in their parents' THIS_DIR, they don't have entries.
         if item.status[0] in '!?' and item.treeconflict == 'C' and \
@@ -656,13 +657,18 @@ class State:
     return cls('', desc)
 
   @classmethod
-  def from_wc(cls, base, load_props=False, ignore_svn=True):
+  def from_wc(cls, base, load_props=False, ignore_svn=True,
+              keep_eol_style=False):
     """Create a State object from a working copy.
 
     Walks the tree at PATH, building a State based on the actual files
     and directories found. If LOAD_PROPS is True, then the properties
     will be loaded for all nodes (Very Expensive!). If IGNORE_SVN is
     True, then the .svn subdirectories will be excluded from the State.
+
+    If KEEP_EOL_STYLE is set, don't let Python normalize the EOL when
+    reading working copy contents as text files.  It has no effect on
+    binary files.
     """
     if not base:
       # we're going to walk the base, and the OS wants "."
@@ -678,7 +684,13 @@ class State:
       for name in dirs + files:
         node = os.path.join(dirpath, name)
         if os.path.isfile(node):
-          contents = open(node, 'r').read()
+          try:
+            if keep_eol_style:
+              contents = open(node, 'r', newline='').read()
+            else:
+              contents = open(node, 'r').read()
+          except:
+            contents = open(node, 'rb').read()
         else:
           contents = None
         desc[repos_join(parent, name)] = StateItem(contents=contents)
@@ -1073,7 +1085,7 @@ def repos_join(base, path):
 def svn_uri_quote(url):
   # svn defines a different set of "safe" characters than Python does, so
   # we need to avoid escaping them. see subr/path.c:uri_char_validity[]
-  return urllib.quote(url, "!$&'()*+,-./:=@_~")
+  return urllib_quote(url, "!$&'()*+,-./:=@_~")
 
 
 # ------------

Modified: subversion/branches/ra-git/subversion/tests/cmdline/trans_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/trans_tests.py?rev=1764214&r1=1764213&r2=1764214&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/trans_tests.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/trans_tests.py Tue Oct 11 09:11:50 2016
@@ -562,9 +562,9 @@ def eol_change_is_text_mod(sbox):
   foo_path = os.path.join(wc_dir, 'foo')
   f = open(foo_path, 'wb')
   if svntest.main.windows:
-    f.write("1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n")
+    f.write(b"1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n")
   else:
-    f.write("1\n2\n3\n4\n5\n6\n7\n8\n9\n")
+    f.write(b"1\n2\n3\n4\n5\n6\n7\n8\n9\n")
   f.close()
 
   # commit the file
@@ -591,10 +591,10 @@ def eol_change_is_text_mod(sbox):
   # check 2: do the files have the right contents now?
   contents = open(foo_path, 'rb').read()
   if svntest.main.windows:
-    if contents != "1\n2\n3\n4\n5\n6\n7\n8\n9\n":
+    if contents != b"1\n2\n3\n4\n5\n6\n7\n8\n9\n":
       raise svntest.Failure
   else:
-    if contents != "1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n":
+    if contents != b"1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n":
       raise svntest.Failure
 
   foo_base_path = svntest.wc.text_base_path(foo_path)

Modified: subversion/branches/ra-git/subversion/tests/cmdline/tree_conflict_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/tree_conflict_tests.py?rev=1764214&r1=1764213&r2=1764214&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/tree_conflict_tests.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/tree_conflict_tests.py Tue Oct 11 09:11:50 2016
@@ -1339,7 +1339,7 @@ def actual_only_node_behaviour(sbox):
                      "relocate", A_copy_url + "/foo", foo_path)
 
   # resolve
-  expected_stdout = "Resolved conflicted state of.*foo.*"
+  expected_stdout = "Tree conflict at.*foo.*marked as resolved"
   expected_stderr = []
   run_and_verify_svn(expected_stdout, expected_stderr,
                      "resolve", "--accept", "working", foo_path)

Modified: subversion/branches/ra-git/subversion/tests/cmdline/update_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/update_tests.py?rev=1764214&r1=1764213&r2=1764214&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/update_tests.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/update_tests.py Tue Oct 11 09:11:50 2016
@@ -92,7 +92,7 @@ def update_binary_file(sbox):
 
   # Make a change to the binary file in the original working copy
   svntest.main.file_append(theta_path, "revision 3 text")
-  theta_contents_r3 = theta_contents + "revision 3 text"
+  theta_contents_r3 = theta_contents + b"revision 3 text"
 
   # Created expected output tree for 'svn ci'
   expected_output = svntest.wc.State(wc_dir, {
@@ -113,7 +113,7 @@ def update_binary_file(sbox):
 
   # Make a local mod to theta
   svntest.main.file_append(theta_backup_path, "extra theta text")
-  theta_contents_local = theta_contents + "extra theta text"
+  theta_contents_local = theta_contents + b"extra theta text"
 
   # Create expected output tree for an update of wc_backup.
   expected_output = svntest.wc.State(wc_backup, {
@@ -196,9 +196,9 @@ def update_binary_file_2(sbox):
 
   # Make some mods to the binary files.
   svntest.main.file_append(theta_path, "foobar")
-  new_theta_contents = theta_contents + "foobar"
+  new_theta_contents = theta_contents + b"foobar"
   svntest.main.file_append(zeta_path, "foobar")
-  new_zeta_contents = zeta_contents + "foobar"
+  new_zeta_contents = zeta_contents + b"foobar"
 
   # Created expected output tree for 'svn ci'
   expected_output = svntest.wc.State(wc_dir, {
@@ -286,7 +286,7 @@ def update_binary_file_3(sbox):
 
   # Make some mods to the binary files.
   svntest.main.file_append(theta_path, "foobar")
-  new_theta_contents = theta_contents + "foobar"
+  new_theta_contents = theta_contents + b"foobar"
 
   # Created expected output tree for 'svn ci'
   expected_output = svntest.wc.State(wc_dir, {
@@ -1657,6 +1657,9 @@ def conflict_markers_matching_eol(sbox):
   else:
     crlf = '\r\n'
 
+  # Strict EOL style matching breaks Windows tests at least with Python 2
+  keep_eol_style = not svntest.main.is_os_windows()
+
   # Checkout a second working copy
   wc_backup = sbox.add_wc_path('backup')
   svntest.actions.run_and_verify_svn(None, [], 'checkout',
@@ -1757,10 +1760,11 @@ def conflict_markers_matching_eol(sbox):
     expected_backup_status.tweak(wc_rev = cur_rev)
 
     # Do the update and check the results in three ways.
-    svntest.actions.run_and_verify_update(wc_backup,
-                                          expected_backup_output,
-                                          expected_backup_disk,
-                                          expected_backup_status)
+    svntest.actions.run_and_verify_update2(wc_backup,
+                                           expected_backup_output,
+                                           expected_backup_disk,
+                                           expected_backup_status,
+                                           keep_eol_style=keep_eol_style)
 
     # cleanup for next run
     svntest.main.run_svn(None, 'revert', '-R', wc_backup)
@@ -1788,6 +1792,9 @@ def update_eolstyle_handling(sbox):
   else:
     crlf = '\r\n'
 
+  # Strict EOL style matching breaks Windows tests at least with Python 2
+  keep_eol_style = not svntest.main.is_os_windows()
+
   # Checkout a second working copy
   wc_backup = sbox.add_wc_path('backup')
   svntest.actions.run_and_verify_svn(None, [], 'checkout',
@@ -1814,10 +1821,11 @@ def update_eolstyle_handling(sbox):
   expected_backup_status = svntest.actions.get_virginal_state(wc_backup, 2)
   expected_backup_status.tweak('A/mu', status='M ')
 
-  svntest.actions.run_and_verify_update(wc_backup,
-                                        expected_backup_output,
-                                        expected_backup_disk,
-                                        expected_backup_status)
+  svntest.actions.run_and_verify_update2(wc_backup,
+                                         expected_backup_output,
+                                         expected_backup_disk,
+                                         expected_backup_status,
+                                         keep_eol_style=keep_eol_style)
 
   # Test 2: now change the eol-style property to another value and commit,
   # update the still changed mu in the second working copy; there should be
@@ -1839,10 +1847,11 @@ def update_eolstyle_handling(sbox):
   expected_backup_status = svntest.actions.get_virginal_state(wc_backup, 3)
   expected_backup_status.tweak('A/mu', status='M ')
 
-  svntest.actions.run_and_verify_update(wc_backup,
-                                        expected_backup_output,
-                                        expected_backup_disk,
-                                        expected_backup_status)
+  svntest.actions.run_and_verify_update2(wc_backup,
+                                         expected_backup_output,
+                                         expected_backup_disk,
+                                         expected_backup_status,
+                                         keep_eol_style=keep_eol_style)
 
   # Test 3: now delete the eol-style property and commit, update the still
   # changed mu in the second working copy; there should be no conflict!
@@ -1863,10 +1872,11 @@ def update_eolstyle_handling(sbox):
 
   expected_backup_status = svntest.actions.get_virginal_state(wc_backup, 4)
   expected_backup_status.tweak('A/mu', status='M ')
-  svntest.actions.run_and_verify_update(wc_backup,
-                                        expected_backup_output,
-                                        expected_backup_disk,
-                                        expected_backup_status)
+  svntest.actions.run_and_verify_update2(wc_backup,
+                                         expected_backup_output,
+                                         expected_backup_disk,
+                                         expected_backup_status,
+                                         keep_eol_style=keep_eol_style)
 
 # Bug in which "update" put a bogus revision number on a schedule-add file,
 # causing the wrong version of it to be committed.
@@ -2710,6 +2720,7 @@ def update_with_obstructing_additions(sb
                                         expected_disk,
                                         expected_status,
                                         [], True,
+                                        '--adds-as-modification', wc_backup,
                                         extra_files=extra_files)
 
   # Some obstructions are still not permitted:
@@ -2820,6 +2831,7 @@ def update_with_obstructing_additions(sb
   svntest.actions.run_and_verify_update(wc_dir, expected_output,
                                         expected_disk, expected_status,
                                         [], False,
+                                        '--adds-as-modification',
                                         A_path)
 
   # Resolve the tree conflict.
@@ -2839,7 +2851,7 @@ def update_with_obstructing_additions(sb
   svntest.actions.run_and_verify_update(wc_dir, expected_output,
                                         expected_disk, expected_status,
                                         [], False,
-                                        wc_dir, '-N')
+                                        wc_dir, '-N', '--adds-as-modification')
 
   # Resolve the tree conflict.
   svntest.main.run_svn(None, 'resolved', omicron_path)
@@ -3610,7 +3622,7 @@ def update_output_with_conflicts(rev, ta
   lines += ['Updated to revision %d.\n' % rev]
   if resolved:
     for path in paths:
-      lines += ["Resolved conflicted state of '%s'\n" % path]
+      lines += ["Merge conflicts in '%s' marked as resolved.\n" % path]
     lines += svntest.main.summary_of_conflicts(text_resolved=len(paths))
   else:
     lines += svntest.main.summary_of_conflicts(text_conflicts=len(paths))
@@ -6343,28 +6355,37 @@ def windows_update_backslash(sbox):
                     'mkdir', 'A/completely\\unusable\\dir')
 
   # No error and a proper skip + recording in the working copy would also
-  # be a good result. This just verifies current behavior.
-
-  if sbox.repo_url.startswith('http'):
-    # Apache Httpd doesn't allow paths with '\\' in them on Windows, so the
-    # test if a user is allowed to read them returns a failure. This makes
-    # mod_dav_svn report the path as server excluded (aka absent), which
-    # doesn't produce output when updating.
-    expected_output = [
-      "Updating '%s':\n" % wc_dir,
-      "At revision 2.\n"
-    ]
-    expected_err = []
-  else:
-    expected_output = None
-    expected_err = 'svn: E155000: .* is not valid.*'
-
-  svntest.actions.run_and_verify_svn(expected_output, expected_err,
-                                     'up', wc_dir)
-
-  if sbox.repo_url.startswith('http'):
+  # be a good result. This just verifies current behavior:
+  #
+  # - Error via file://, svn:// or http:// with SVNPathAuthz short_circuit
+  #
+  # - No error via http:// with SVNPathAuthz on
+  #   (The reason is that Apache Httpd doesn't allow paths with '\\' in
+  #    them on Windows, and a subrequest-based access check returns 404.
+  #    This makes mod_dav_svn report the path as server excluded (aka
+  #    absent), which doesn't produce output when updating.)
+  #
+  # Since https://issues.apache.org/jira/browse/SVN-3288 is about a crash,
+  # we're fine with either result -- that is, if `svn update' finished
+  # without an error, we expect specific stdout and proper wc state.
+  # If it failed, we expect to get the following error:
+  #
+  #  svn: E155000: 'completely\unusable\dir' is not valid as filename
+  #  in directory [...]
+  #
+  exit_code, output, errput = svntest.main.run_svn(1, 'up', wc_dir)
+  if exit_code == 0:
+    verify.verify_outputs("Unexpected output", output, errput, [
+                           "Updating '%s':\n" % wc_dir,
+                           "At revision 2.\n"
+                          ], [])
     expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
     svntest.actions.run_and_verify_status(wc_dir, expected_status)
+  elif exit_code == 1:
+    verify.verify_outputs("Unexpected output", output, errput,
+                          None, 'svn: E155000: .* is not valid.*')
+  else:
+    raise verify.SVNUnexpectedExitCode(exit_code)
 
 def update_moved_away(sbox):
   "update subtree of moved away"
@@ -6614,7 +6635,9 @@ def update_conflict_details(sbox):
                                prev_status='  ', prev_treeconflict='C'),
   })
   svntest.actions.run_and_verify_update(wc_dir, expected_output,
-                                        None, expected_status)
+                                        None, expected_status,
+                                        [], False,
+                                        '--adds-as-modification', wc_dir)
 
   # Update can't pass source as none at a specific URL@revision,
   # because it doesn't know... the working copy could be mixed

Modified: subversion/branches/ra-git/subversion/tests/cmdline/upgrade_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/upgrade_tests.py?rev=1764214&r1=1764213&r2=1764214&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/upgrade_tests.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/upgrade_tests.py Tue Oct 11 09:11:50 2016
@@ -36,6 +36,7 @@ import sys
 import tarfile
 import tempfile
 import logging
+import stat
 
 logger = logging.getLogger()
 
@@ -63,7 +64,7 @@ def replace_sbox_with_tarfile(sbox, tar_
                               dir=None):
   try:
     svntest.main.safe_rmtree(sbox.wc_dir)
-  except OSError, e:
+  except OSError as e:
     pass
 
   if not dir:
@@ -81,7 +82,7 @@ def replace_sbox_with_tarfile(sbox, tar_
 def replace_sbox_repo_with_tarfile(sbox, tar_filename, dir=None):
   try:
     svntest.main.safe_rmtree(sbox.repo_dir)
-  except OSError, e:
+  except OSError as e:
     pass
 
   if not dir:
@@ -130,7 +131,7 @@ def check_dav_cache(dir_path, wc_id, exp
 
   # Check if python's sqlite can read our db
   c.execute('select sqlite_version()')
-  sqlite_ver = map(int, c.fetchone()[0].split('.'))
+  sqlite_ver = svntest.main.ensure_list(map(int, c.fetchone()[0].split('.')))
 
   # SQLite versions have 3 or 4 number groups
   major = sqlite_ver[0]
@@ -157,7 +158,7 @@ def check_dav_cache(dir_path, wc_id, exp
     if row is None:
       raise svntest.Failure("no dav cache for '%s'" % (local_relpath))
     dav_cache = str(row[0])
-    if dav_cache != expected_dav_cache:
+    if dav_cache != str(expected_dav_cache):
       raise svntest.Failure(
               "wrong dav cache for '%s'\n  Found:    '%s'\n  Expected: '%s'" %
                 (local_relpath, dav_cache, expected_dav_cache))
@@ -378,9 +379,9 @@ def upgrade_wcprops(sbox):
   # to be.  (This could be smarter.)
   expected_dav_caches = {
    '' :
-    '(svn:wc:ra_dav:version-url 41 /svn-test-work/local_tmp/repos/!svn/ver/1)',
+    b'(svn:wc:ra_dav:version-url 41 /svn-test-work/local_tmp/repos/!svn/ver/1)',
    'iota' :
-    '(svn:wc:ra_dav:version-url 46 /svn-test-work/local_tmp/repos/!svn/ver/1/iota)',
+    b'(svn:wc:ra_dav:version-url 46 /svn-test-work/local_tmp/repos/!svn/ver/1/iota)',
   }
   check_dav_cache(sbox.wc_dir, 1, expected_dav_caches)
 
@@ -390,7 +391,7 @@ def xml_entries_relocate(path, from_url,
   adm_name = svntest.main.get_admin_name()
   entries = os.path.join(path, adm_name, 'entries')
   txt = open(entries).read().replace('url="' + from_url, 'url="' + to_url)
-  os.chmod(entries, 0777)
+  os.chmod(entries, svntest.main.S_ALL_RWX)
   open(entries, 'w').write(txt)
 
   for dirent in os.listdir(path):
@@ -408,8 +409,8 @@ def simple_entries_replace(path, from_ur
   adm_name = svntest.main.get_admin_name()
   entries = os.path.join(path, adm_name, 'entries')
   txt = open(entries).read().replace(from_url, to_url)
-  os.chmod(entries, 0777)
-  open(entries, 'wb').write(txt)
+  os.chmod(entries, svntest.main.S_ALL_RWX)
+  open(entries, 'wb').write(txt.encode())
 
   for dirent in os.listdir(path):
     item_path = os.path.join(path, dirent)
@@ -1143,21 +1144,21 @@ def upgrade_file_externals(sbox):
   svntest.main.run_svnadmin('setuuid', sbox.repo_dir,
                             '07146bbd-0b64-4aaf-ab70-cd76a0df2d41')
 
-  expected_output = svntest.verify.RegexOutput('r2 committed.*')
+  expected_output = svntest.verify.RegexOutput(b'r2 committed.*')
   svntest.actions.run_and_verify_svnmucc(expected_output, [],
                                          '-m', 'r2',
                                          'propset', 'svn:externals',
                                          '^/A/B/E EX\n^/A/mu muX',
                                          sbox.repo_url + '/A/B/F')
 
-  expected_output = svntest.verify.RegexOutput('r3 committed.*')
+  expected_output = svntest.verify.RegexOutput(b'r3 committed.*')
   svntest.actions.run_and_verify_svnmucc(expected_output, [],
                                          '-m', 'r3',
                                          'propset', 'svn:externals',
                                          '^/A/B/F FX\n^/A/B/lambda lambdaX',
                                          sbox.repo_url + '/A/C')
 
-  expected_output = svntest.verify.RegexOutput('r4 committed.*')
+  expected_output = svntest.verify.RegexOutput(b'r4 committed.*')
   svntest.actions.run_and_verify_svnmucc(expected_output, [],
                                          '-m', 'r4',
                                          'propset', 'pname1', 'pvalue1',
@@ -1260,12 +1261,17 @@ def upgrade_not_present_replaced(sbox):
                                      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 '),
+      'A/B/E'         : Item(status='  ', treeconflict='C'),
+      'A/B/E/beta'    : Item(status='  ', treeconflict='A'),
+      'A/B/E/alpha'   : Item(status='  ', treeconflict='A'),
+      'A/B/lambda'    : Item(status='  ', treeconflict='C'),
       })
   expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
+  expected_status.tweak('A/B/E', status='R ', treeconflict='C'),
+  expected_status.tweak('A/B/E/beta', status='D '),
+  expected_status.tweak('A/B/E/alpha', status='D '),
+  expected_status.tweak('A/B/lambda', status='R ', treeconflict='C'),
+
   svntest.actions.run_and_verify_update(sbox.wc_dir, expected_output,
                                         None, expected_status)
 
@@ -1462,14 +1468,15 @@ def auto_analyze(sbox):
   # svntest.main.chmod_tree will not reset it.)
   for path, subdirs, files in os.walk(sbox.wc_dir):
     for d in subdirs:
-      os.chmod(os.path.join(path, d), 0555)
+      os.chmod(os.path.join(path, d), svntest.main.S_ALL_RX)
     for f in files:
-      os.chmod(os.path.join(path, f), 0444)
+      os.chmod(os.path.join(path, f), svntest.main.S_ALL_READ)
 
   state = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
   svntest.actions.run_and_verify_status(sbox.wc_dir, state)
 
-  svntest.main.chmod_tree(sbox.wc_dir, 0666, 0022)
+  svntest.main.chmod_tree(sbox.wc_dir, svntest.main.S_ALL_RW,
+                          stat.S_IWGRP | stat.S_IWOTH)
 
   state = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
   svntest.actions.run_and_verify_status(sbox.wc_dir, state)

Modified: subversion/branches/ra-git/subversion/tests/cmdline/wc_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/wc_tests.py?rev=1764214&r1=1764213&r2=1764214&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/cmdline/wc_tests.py (original)
+++ subversion/branches/ra-git/subversion/tests/cmdline/wc_tests.py Tue Oct 11 09:11:50 2016
@@ -142,7 +142,7 @@ def status_with_corrupt_wc_db(sbox):
 
   sbox.build(read_only = True)
   with open(sbox.ospath(".svn/wc.db"), 'wb') as fd:
-    fd.write('\0' * 17)
+    fd.write(b'\0' * 17)
   svntest.actions.run_and_verify_svn(
     None,
     r"[^ ]+ E155016: The working copy database at '.*' is corrupt",
@@ -189,7 +189,7 @@ def status_with_missing_wc_db_and_maybe_
 
   sbox.build(read_only = True)
   with open(sbox.ospath(".svn/entries"), 'ab') as fd:
-    fd.write('something\n')
+    fd.write(b'something\n')
     os.remove(sbox.ospath(".svn/wc.db"))
   svntest.actions.run_and_verify_svn(
     None,

Propchange: subversion/branches/ra-git/subversion/tests/libsvn_client/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Tue Oct 11 09:11:50 2016
@@ -1,3 +1,4 @@
 .libs
 *-test
 *.lo
+svn-test-work

Modified: subversion/branches/ra-git/subversion/tests/libsvn_diff/diff-diff3-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_diff/diff-diff3-test.c?rev=1764214&r1=1764213&r2=1764214&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_diff/diff-diff3-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_diff/diff-diff3-test.c Tue Oct 11 09:11:50 2016
@@ -2407,6 +2407,8 @@ merge_with_part_already_present(apr_pool
 /* Merge is more "aggressive" about resolving conflicts than traditional
  * patch or diff3.  Some people consider this behaviour to be a bug, see
  * http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=35014
+ *
+ * The original behavior of this test (added in 2003) was tweaked in 2016.
  */
 static svn_error_t *
 merge_adjacent_changes(apr_pool_t *pool)
@@ -2428,8 +2430,13 @@ merge_adjacent_changes(apr_pool_t *pool)
 
                           "zig\n"
                           "foo\n"
+                          "<<<<<<< adj2\n"
                           "new_bar\n"
-                          "new_baz\n",
+                          "baz\n"
+                          "=======\n"
+                          "bar\n"
+                          "new_baz\n"
+                          ">>>>>>> adj3\n",
 
                           NULL,
                           svn_diff_conflict_display_modified_latest,
@@ -2952,6 +2959,124 @@ two_way_issue_3362_v2(apr_pool_t *pool)
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+three_way_double_add(apr_pool_t *pool)
+{
+  SVN_ERR(three_way_merge("doubleadd1", "doubleadd2", "doubleadd3",
+                          "A\n"
+                          "B\n"
+                          "C\n"
+                          "J\n"
+                          "K\n"
+                          "L",
+
+                          "A\n"
+                          "B\n"
+                          "C\n"
+                          "D\n" /* New line 1a */
+                          "E\n" /* New line 2a */
+                          "F\n" /* New line 3a*/
+                          "J\n"
+                          "K\n"
+                          "L",
+
+                          "A\n"
+                          "B\n"
+                          "O\n" /* Change C to O */
+                          "P\n" /* New line 1b */
+                          "Q\n" /* New line 2b */
+                          "R\n" /* New line 3b */
+                          "J\n"
+                          "K\n"
+                          "L",
+
+                          /* With s/C/O/ we expect something like this,
+                             but the current (1.9/trunk) result is a
+                             succeeded merge to a combined result.
+
+                             ### I'm guessing this result needs tweaks before it
+                                 will be a PASS. */
+                          "A\n"
+                          "B\n"
+                          "<<<<<<< doubleadd2\n"
+                          "C\n"
+                          "D\n" /* New line 1a */
+                          "E\n" /* New line 2a */
+                          "F\n" /* New line 3a*/
+                          "||||||| doubleadd1\n"
+                          "C\n"
+                          "=======\n"
+                          "O\n"
+                          "P\n" /* New line 1b */
+                          "Q\n" /* New line 2b */
+                          "R\n" /* New line 3b */
+                          ">>>>>>> doubleadd3\n"
+                          "J\n"
+                          "K\n"
+                          "L",
+                          NULL,
+                          svn_diff_conflict_display_modified_original_latest,
+                          pool));
+
+  SVN_ERR(three_way_merge("doubleadd4", "doubleadd5", "doubleadd6",
+                          "A\n"
+                          "B\n"
+                          "C\n"
+                          "J\n"
+                          "K\n"
+                          "L",
+
+                          "A\n"
+                          "B\n"
+                          "C\n"
+                          "D\n" /* New line 1a */
+                          "E\n" /* New line 2a */
+                          "F\n" /* New line 3a*/
+                          "K\n"
+                          "L",
+
+                          "A\n"
+                          "B\n"
+                          "O\n" /* Change C to O */
+                          "P\n" /* New line 1b */
+                          "Q\n" /* New line 2b */
+                          "R\n" /* New line 3b */
+                          "J\n"
+                          "K\n"
+                          "L",
+
+                          /* With s/C/O/ we expect something like this,
+                          but the current (1.9/trunk) result is a
+                          succeeded merge to a combined result.
+
+                          ### I'm guessing this result needs tweaks before it
+                          will be a PASS. */
+                          "A\n"
+                          "B\n"
+                          "<<<<<<< doubleadd5\n"
+                          "C\n"
+                          "D\n" /* New line 1a */
+                          "E\n" /* New line 2a */
+                          "F\n" /* New line 3a*/
+                          "||||||| doubleadd4\n"
+                          "C\n"
+                          "J\n"
+                          "=======\n"
+                          "O\n"
+                          "P\n" /* New line 1b */
+                          "Q\n" /* New line 2b */
+                          "R\n" /* New line 3b */
+                          "J\n"
+                          ">>>>>>> doubleadd6\n"
+                          "K\n"
+                          "L",
+                          NULL,
+                          svn_diff_conflict_display_modified_original_latest,
+                          pool));
+
+  return SVN_NO_ERROR;
+}
+
 /* ========================================================================== */
 
 
@@ -2994,6 +3119,8 @@ static struct svn_test_descriptor_t test
                    "2-way issue #3362 test v1"),
     SVN_TEST_PASS2(two_way_issue_3362_v2,
                    "2-way issue #3362 test v2"),
+    SVN_TEST_PASS2(three_way_double_add,
+                   "3-way merge, double add"),
     SVN_TEST_NULL
   };
 

Modified: subversion/branches/ra-git/subversion/tests/libsvn_diff/parse-diff-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_diff/parse-diff-test.c?rev=1764214&r1=1764213&r2=1764214&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_diff/parse-diff-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_diff/parse-diff-test.c Tue Oct 11 09:11:50 2016
@@ -471,10 +471,10 @@ test_parse_git_diff(apr_pool_t *pool)
   SVN_TEST_STRING_ASSERT(patch->new_filename, "A/C/gamma");
   SVN_TEST_ASSERT(patch->operation == svn_diff_op_modified);
   SVN_TEST_ASSERT(patch->hunks->nelts == 1);
-  SVN_TEST_ASSERT(patch->old_executable_bit = svn_tristate_false);
-  SVN_TEST_ASSERT(patch->new_executable_bit = svn_tristate_true);
-  SVN_TEST_ASSERT(patch->old_symlink_bit = svn_tristate_false);
-  SVN_TEST_ASSERT(patch->new_symlink_bit = svn_tristate_false);
+  SVN_TEST_ASSERT(patch->old_executable_bit == svn_tristate_false);
+  SVN_TEST_ASSERT(patch->new_executable_bit == svn_tristate_true);
+  SVN_TEST_ASSERT(patch->old_symlink_bit == svn_tristate_false);
+  SVN_TEST_ASSERT(patch->new_symlink_bit == svn_tristate_false);
 
   hunk = APR_ARRAY_IDX(patch->hunks, 0, svn_diff_hunk_t *);
 
@@ -510,10 +510,10 @@ test_parse_git_diff(apr_pool_t *pool)
   SVN_TEST_STRING_ASSERT(patch->new_filename, "new");
   SVN_TEST_ASSERT(patch->operation == svn_diff_op_added);
   SVN_TEST_ASSERT(patch->hunks->nelts == 0);
-  SVN_TEST_ASSERT(patch->old_executable_bit = svn_tristate_unknown);
-  SVN_TEST_ASSERT(patch->new_executable_bit = svn_tristate_false);
-  SVN_TEST_ASSERT(patch->old_symlink_bit = svn_tristate_unknown);
-  SVN_TEST_ASSERT(patch->new_symlink_bit = svn_tristate_false);
+  SVN_TEST_ASSERT(patch->old_executable_bit == svn_tristate_unknown);
+  SVN_TEST_ASSERT(patch->new_executable_bit == svn_tristate_false);
+  SVN_TEST_ASSERT(patch->old_symlink_bit == svn_tristate_unknown);
+  SVN_TEST_ASSERT(patch->new_symlink_bit == svn_tristate_false);
 
   SVN_ERR(svn_diff_close_patch_file(patch_file, pool));
 
@@ -539,10 +539,10 @@ test_parse_git_tree_and_text_diff(apr_po
   SVN_TEST_ASSERT(patch);
   SVN_TEST_STRING_ASSERT(patch->old_filename, "iota");
   SVN_TEST_STRING_ASSERT(patch->new_filename, "iota.copied");
-  SVN_TEST_ASSERT(patch->old_executable_bit = svn_tristate_false);
-  SVN_TEST_ASSERT(patch->new_executable_bit = svn_tristate_true);
-  SVN_TEST_ASSERT(patch->old_symlink_bit = svn_tristate_false);
-  SVN_TEST_ASSERT(patch->new_symlink_bit = svn_tristate_false);
+  SVN_TEST_ASSERT(patch->old_executable_bit == svn_tristate_false);
+  SVN_TEST_ASSERT(patch->new_executable_bit == svn_tristate_true);
+  SVN_TEST_ASSERT(patch->old_symlink_bit == svn_tristate_false);
+  SVN_TEST_ASSERT(patch->new_symlink_bit == svn_tristate_false);
   SVN_TEST_ASSERT(patch->operation == svn_diff_op_copied);
   SVN_TEST_ASSERT(patch->hunks->nelts == 1);
 
@@ -565,10 +565,10 @@ test_parse_git_tree_and_text_diff(apr_po
   SVN_TEST_ASSERT(patch);
   SVN_TEST_STRING_ASSERT(patch->old_filename, "A/mu");
   SVN_TEST_STRING_ASSERT(patch->new_filename, "A/mu.moved");
-  SVN_TEST_ASSERT(patch->old_executable_bit = svn_tristate_false);
-  SVN_TEST_ASSERT(patch->new_executable_bit = svn_tristate_true);
-  SVN_TEST_ASSERT(patch->old_symlink_bit = svn_tristate_false);
-  SVN_TEST_ASSERT(patch->new_symlink_bit = svn_tristate_false);
+  SVN_TEST_ASSERT(patch->old_executable_bit == svn_tristate_false);
+  SVN_TEST_ASSERT(patch->new_executable_bit == svn_tristate_true);
+  SVN_TEST_ASSERT(patch->old_symlink_bit == svn_tristate_false);
+  SVN_TEST_ASSERT(patch->new_symlink_bit == svn_tristate_false);
   SVN_TEST_ASSERT(patch->operation == svn_diff_op_moved);
   SVN_TEST_ASSERT(patch->hunks->nelts == 1);
 
@@ -612,10 +612,10 @@ test_parse_git_tree_and_text_diff(apr_po
   SVN_TEST_STRING_ASSERT(patch->new_filename, "/dev/null");
   SVN_TEST_ASSERT(patch->operation == svn_diff_op_deleted);
   SVN_TEST_ASSERT(patch->hunks->nelts == 1);
-  SVN_TEST_ASSERT(patch->old_executable_bit = svn_tristate_true);
-  SVN_TEST_ASSERT(patch->new_executable_bit = svn_tristate_unknown);
-  SVN_TEST_ASSERT(patch->old_symlink_bit = svn_tristate_false);
-  SVN_TEST_ASSERT(patch->new_symlink_bit = svn_tristate_unknown);
+  SVN_TEST_ASSERT(patch->old_executable_bit == svn_tristate_true);
+  SVN_TEST_ASSERT(patch->new_executable_bit == svn_tristate_unknown);
+  SVN_TEST_ASSERT(patch->old_symlink_bit == svn_tristate_false);
+  SVN_TEST_ASSERT(patch->new_symlink_bit == svn_tristate_unknown);
 
   hunk = APR_ARRAY_IDX(patch->hunks, 0, svn_diff_hunk_t *);
 

Modified: subversion/branches/ra-git/subversion/tests/libsvn_fs/fs-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_fs/fs-test.c?rev=1764214&r1=1764213&r2=1764214&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_fs/fs-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_fs/fs-test.c Tue Oct 11 09:11:50 2016
@@ -43,6 +43,7 @@
 #include "private/svn_fs_util.h"
 #include "private/svn_fs_private.h"
 #include "private/svn_fspath.h"
+#include "private/svn_sqlite.h"
 
 #include "../svn_test_fs.h"
 
@@ -3592,17 +3593,11 @@ get_file_checksum(svn_checksum_t **check
                   apr_pool_t *pool)
 {
   svn_stream_t *stream;
-  svn_stream_t *checksum_stream;
 
   /* Get a stream for the file contents. */
   SVN_ERR(svn_fs_file_contents(&stream, root, path, pool));
-
-  /* Get a checksummed stream for the contents. */
-  checksum_stream = svn_stream_checksummed2(stream, checksum, NULL,
-                                            checksum_kind, TRUE, pool);
-
-  /* Close the stream, forcing a complete read and copy the digest. */
-  SVN_ERR(svn_stream_close(checksum_stream));
+  SVN_ERR(svn_stream_contents_checksum(checksum, stream, checksum_kind,
+                                       pool, pool));
 
   return SVN_NO_ERROR;
 }
@@ -6701,6 +6696,9 @@ test_fsfs_config_opts(const svn_test_opt
   svn_fs_t *fs;
   const svn_fs_info_placeholder_t *fs_info;
   const svn_fs_fsfs_info_t *fsfs_info;
+  const char *dir_name = "test-repo-fsfs-config-opts";
+  const char *repo_name_default = "test-repo-fsfs-config-opts/default";
+  const char *repo_name_custom = "test-repo-fsfs-config-opts/custom";
 
   /* Bail (with SKIP) on known-untestable scenarios */
   if (strcmp(opts->fs_type, SVN_FS_TYPE_FSFS) != 0)
@@ -6708,20 +6706,19 @@ test_fsfs_config_opts(const svn_test_opt
                             "this will test FSFS repositories only");
 
   /* Remove the test directory from previous runs. */
-  SVN_ERR(svn_io_remove_dir2("test-repo-fsfs-config-opts", TRUE, NULL, NULL,
-                             pool));
+  SVN_ERR(svn_io_remove_dir2(dir_name, TRUE, NULL, NULL, pool));
 
   /* Create the test directory and add it to the test cleanup list. */
-  SVN_ERR(svn_io_dir_make("test-fsfs-config-opts", APR_OS_DEFAULT, pool));
-  svn_test_add_dir_cleanup("test-fsfs-config-opts");
+  SVN_ERR(svn_io_dir_make(dir_name, APR_OS_DEFAULT, pool));
+  svn_test_add_dir_cleanup(dir_name);
 
   /* Create an FSFS filesystem with default config.*/
   fs_config = apr_hash_make(pool);
   svn_hash_sets(fs_config, SVN_FS_CONFIG_FS_TYPE, SVN_FS_TYPE_FSFS);
-  SVN_ERR(svn_fs_create(&fs, "test-fsfs-config-opts/default", fs_config, pool));
+  SVN_ERR(svn_fs_create(&fs, repo_name_default, fs_config, pool));
 
   /* Re-open FS to test the data on disk. */
-  SVN_ERR(svn_fs_open2(&fs, "test-fsfs-config-opts/default", NULL, pool, pool));
+  SVN_ERR(svn_fs_open2(&fs, repo_name_default, NULL, pool, pool));
 
   SVN_ERR(svn_fs_info(&fs_info, fs, pool, pool));
   SVN_TEST_STRING_ASSERT(fs_info->fs_type, SVN_FS_TYPE_FSFS);
@@ -6738,10 +6735,10 @@ test_fsfs_config_opts(const svn_test_opt
   svn_hash_sets(fs_config, SVN_FS_CONFIG_FS_TYPE, SVN_FS_TYPE_FSFS);
   svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_LOG_ADDRESSING, "false");
   svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_SHARD_SIZE, "123");
-  SVN_ERR(svn_fs_create(&fs, "test-fsfs-config-opts/custom", fs_config, pool));
+  SVN_ERR(svn_fs_create(&fs, repo_name_custom, fs_config, pool));
 
   /* Re-open FS to test the data on disk. */
-  SVN_ERR(svn_fs_open2(&fs, "test-fsfs-config-opts/custom", NULL, pool, pool));
+  SVN_ERR(svn_fs_open2(&fs, repo_name_custom, NULL, pool, pool));
 
   SVN_ERR(svn_fs_info(&fs_info, fs, pool, pool));
   SVN_TEST_STRING_ASSERT(fs_info->fs_type, SVN_FS_TYPE_FSFS);
@@ -6982,13 +6979,13 @@ freeze_and_commit(const svn_test_opts_t
   svn_fs_root_t *txn_root;
   svn_revnum_t new_rev = 0;
   apr_pool_t *subpool = svn_pool_create(pool);
+  const char *repo_name = "test-repo-freeze-and-commit";
 
   if (!strcmp(opts->fs_type, "bdb"))
     return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL,
                             "this will not test BDB repositories");
 
-  SVN_ERR(svn_test__create_fs(&fs, "test-repo-freeze-and-commit", opts,
-                              subpool));
+  SVN_ERR(svn_test__create_fs(&fs, repo_name, opts, subpool));
 
   /* This test used to FAIL with an SQLite error since svn_fs_freeze()
    * wouldn't unlock rep-cache.db.  Therefore, part of the role of creating
@@ -7020,7 +7017,7 @@ freeze_and_commit(const svn_test_opts_t
   SVN_ERR(test_commit_txn(&new_rev, txn, NULL, pool));
 
   /* Re-open FS and make another commit. */
-  SVN_ERR(svn_fs_open(&fs, "test-freeze-and-commit", NULL, subpool));
+  SVN_ERR(svn_fs_open(&fs, repo_name, NULL, subpool));
   SVN_ERR(svn_fs_begin_txn(&txn, fs, new_rev, pool));
   SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
   SVN_ERR(svn_fs_change_node_prop(txn_root, "/", "temperature",
@@ -7031,6 +7028,165 @@ freeze_and_commit(const svn_test_opts_t
   return SVN_NO_ERROR;
 }
 
+/* Number of changes in a revision.
+ * Should be > 100 to span multiple blocks. */
+#define CHANGES_COUNT 1017
+
+/* Check that REVISION in FS reports the expected changes. */
+static svn_error_t *
+verify_added_files_list(svn_fs_t *fs,
+                        svn_revnum_t revision,
+                        apr_pool_t *scratch_pool)
+{
+  int i;
+  svn_fs_root_t *root;
+  apr_hash_t *changed_paths;
+  svn_fs_path_change_iterator_t *iterator;
+  svn_fs_path_change3_t *change;
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+
+  /* Collect changes and test that no path gets reported twice. */
+  SVN_ERR(svn_fs_revision_root(&root, fs, revision, scratch_pool));
+  SVN_ERR(svn_fs_paths_changed3(&iterator, root, scratch_pool, scratch_pool));
+
+  changed_paths = apr_hash_make(scratch_pool);
+  SVN_ERR(svn_fs_path_change_get(&change, iterator));
+  while (change)
+    {
+      const char *path = apr_pstrmemdup(scratch_pool, change->path.data,
+                                        change->path.len);
+      SVN_TEST_ASSERT(change->change_kind == svn_fs_path_change_add);
+      SVN_TEST_ASSERT(!apr_hash_get(changed_paths, path, change->path.len));
+
+      apr_hash_set(changed_paths, path, change->path.len, path);
+      SVN_ERR(svn_fs_path_change_get(&change, iterator));
+    }
+
+  /* Verify that we've got exactly all paths that we added. */
+  SVN_TEST_ASSERT(CHANGES_COUNT == apr_hash_count(changed_paths));
+  for (i = 0; i < CHANGES_COUNT; ++i)
+    {
+      const char *file_name;
+      svn_pool_clear(iterpool);
+
+      file_name = apr_psprintf(iterpool, "/file-%d", i);
+      SVN_TEST_ASSERT(svn_hash_gets(changed_paths, file_name));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_large_changed_paths_list(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;
+  int i;
+  svn_revnum_t rev = 0;
+  apr_pool_t *iterpool = svn_pool_create(pool);
+  const char *repo_name = "test-repo-changed-paths-list";
+
+  SVN_ERR(svn_test__create_fs(&fs, repo_name, opts, pool));
+
+  /* r1: Add many empty files - just to amass a long list of changes. */
+  SVN_ERR(svn_fs_begin_txn(&txn, fs, rev, pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+
+  for (i = 0; i < CHANGES_COUNT; ++i)
+    {
+      const char *file_name;
+      svn_pool_clear(iterpool);
+
+      file_name = apr_psprintf(iterpool, "/file-%d", i);
+      SVN_ERR(svn_fs_make_file(txn_root, file_name, iterpool));
+    }
+
+  SVN_ERR(test_commit_txn(&rev, txn, NULL, pool));
+
+  /* Now, read the change list.
+   * Do it twice to cover cached data as well. */
+  svn_pool_clear(iterpool);
+  SVN_ERR(verify_added_files_list(fs, rev, iterpool));
+  svn_pool_clear(iterpool);
+  SVN_ERR(verify_added_files_list(fs, rev, iterpool));
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+
+#undef CHANGES_COUNT
+
+static svn_error_t *
+commit_with_locked_rep_cache(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 new_rev;
+  svn_sqlite__db_t *sdb;
+  svn_error_t *err;
+  const char *fs_path;
+  const char *statements[] = { "SELECT MAX(revision) FROM rep_cache", NULL };
+
+  if (strcmp(opts->fs_type, SVN_FS_TYPE_BDB) == 0)
+    return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL,
+                            "this will not test BDB repositories");
+
+  if (opts->server_minor_version && (opts->server_minor_version < 6))
+    return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL,
+                            "pre-1.6 SVN doesn't support FSFS rep-sharing");
+
+  fs_path = "test-repo-commit-with-locked-rep-cache";
+  SVN_ERR(svn_test__create_fs(&fs, fs_path, opts, pool));
+
+  /* r1: Add a file. */
+  SVN_ERR(svn_fs_begin_txn2(&txn, fs, 0, 0, pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+  SVN_ERR(svn_fs_make_file(txn_root, "/foo", pool));
+  SVN_ERR(svn_test__set_file_contents(txn_root, "/foo", "a", pool));
+  SVN_ERR(test_commit_txn(&new_rev, txn, NULL, pool));
+  SVN_TEST_INT_ASSERT(new_rev, 1);
+
+  /* Begin a new transaction based on r1. */
+  SVN_ERR(svn_fs_begin_txn2(&txn, fs, 1, 0, pool));
+  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
+  SVN_ERR(svn_test__set_file_contents(txn_root, "/foo", "b", pool));
+
+  /* Obtain a shared lock on the rep-cache.db by starting a new read
+   * transaction. */
+  SVN_ERR(svn_sqlite__open(&sdb,
+                           svn_dirent_join(fs_path, "rep-cache.db", pool),
+                           svn_sqlite__mode_readonly, statements, 0, NULL,
+                           0, pool, pool));
+  SVN_ERR(svn_sqlite__begin_transaction(sdb));
+  SVN_ERR(svn_sqlite__exec_statements(sdb, 0));
+
+  /* Attempt to commit fs transaction.  This should result in a commit
+   * post-processing error due to us still holding the shared lock on the
+   * rep-cache.db. */
+  err = svn_fs_commit_txn(NULL, &new_rev, txn, pool);
+  SVN_TEST_ASSERT_ERROR(err, SVN_ERR_SQLITE_BUSY);
+  SVN_TEST_INT_ASSERT(new_rev, 2);
+
+  /* Release the shared lock. */
+  SVN_ERR(svn_sqlite__finish_transaction(sdb, SVN_NO_ERROR));
+  SVN_ERR(svn_sqlite__close(sdb));
+
+  /* Try an operation that reads from rep-cache.db.
+   *
+   * XFAIL: Around r1740802, this call was producing an error due to the
+   * svn_fs_t keeping an unusable db connection (and associated file
+   * locks) within it.
+   */
+  SVN_ERR(svn_fs_verify(fs_path, NULL, 0, SVN_INVALID_REVNUM, NULL, NULL,
+                        NULL, NULL, pool));
+
+  return SVN_NO_ERROR;
+}
+
 /* ------------------------------------------------------------------------ */
 
 /* The test table.  */
@@ -7165,6 +7321,10 @@ static struct svn_test_descriptor_t test
                        "test svn_fs_check_related for transactions"),
     SVN_TEST_OPTS_PASS(freeze_and_commit,
                        "freeze and commit"),
+    SVN_TEST_OPTS_PASS(test_large_changed_paths_list,
+                       "test reading a large changed paths list"),
+    SVN_TEST_OPTS_PASS(commit_with_locked_rep_cache,
+                       "test commit with locked rep-cache"),
     SVN_TEST_NULL
   };
 

Modified: subversion/branches/ra-git/subversion/tests/libsvn_fs_fs/fs-fs-fuzzy-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_fs_fs/fs-fs-fuzzy-test.c?rev=1764214&r1=1764213&r2=1764214&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_fs_fs/fs-fs-fuzzy-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_fs_fs/fs-fs-fuzzy-test.c Tue Oct 11 09:11:50 2016
@@ -86,6 +86,7 @@ fuzzing_1_byte_1_rev(const char *repo_na
   fs_config = apr_hash_make(pool);
   svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_DELTAS, "1");
   svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS, "1");
+  svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_NODEPROPS, "1");
   svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_REVPROPS, "2");
   svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_BLOCK_READ, "0");
 

Modified: subversion/branches/ra-git/subversion/tests/libsvn_fs_fs/fs-fs-pack-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_fs_fs/fs-fs-pack-test.c?rev=1764214&r1=1764213&r2=1764214&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_fs_fs/fs-fs-pack-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_fs_fs/fs-fs-pack-test.c Tue Oct 11 09:11:50 2016
@@ -29,6 +29,7 @@
 #include "../../libsvn_fs_fs/fs.h"
 #include "../../libsvn_fs_fs/fs_fs.h"
 #include "../../libsvn_fs_fs/low_level.h"
+#include "../../libsvn_fs_fs/pack.h"
 #include "../../libsvn_fs_fs/util.h"
 
 #include "svn_hash.h"
@@ -101,17 +102,16 @@ pack_notify(void *baton,
 
 #define R1_LOG_MSG "Let's serf"
 
-/* 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
-   completes, the filesystem's youngest revision number will be the
-   same as NUM_REVS.  */
-static svn_error_t *
-create_packed_filesystem(const char *dir,
-                         const svn_test_opts_t *opts,
-                         svn_revnum_t num_revs,
-                         int shard_size,
-                         apr_pool_t *pool)
+/* Create a 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 completes, the filesystem's
+   youngest revision number will be NUM_REVS.  */
+static svn_error_t *
+create_non_packed_filesystem(const char *dir,
+                             const svn_test_opts_t *opts,
+                             svn_revnum_t num_revs,
+                             int shard_size,
+                             apr_pool_t *pool)
 {
   svn_fs_t *fs;
   svn_fs_txn_t *txn;
@@ -119,7 +119,6 @@ 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;
   apr_hash_t *fs_config;
 
@@ -166,6 +165,28 @@ create_packed_filesystem(const char *dir
   svn_pool_destroy(iterpool);
   svn_pool_destroy(subpool);
 
+  /* Done */
+  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
+   completes, the filesystem's youngest revision number will be the
+   same as NUM_REVS.  */
+static svn_error_t *
+create_packed_filesystem(const char *dir,
+                         const svn_test_opts_t *opts,
+                         svn_revnum_t num_revs,
+                         int shard_size,
+                         apr_pool_t *pool)
+{
+  struct pack_notify_baton pnb;
+
+  /* Create the repo and fill it. */
+  SVN_ERR(create_non_packed_filesystem(dir, opts, num_revs, shard_size,
+                                       pool));
+
   /* Now pack the FS */
   pnb.expected_shard = 0;
   pnb.expected_action = svn_fs_pack_notify_start;
@@ -669,7 +690,7 @@ recover_fully_packed(const svn_test_opts
 
 /* ------------------------------------------------------------------------ */
 /* Regression test for issue #4320 (fsfs file-hinting fails when reading a rep
-   from the transaction that is commiting rev = SHARD_SIZE). */
+   from the transaction that is committing rev = SHARD_SIZE). */
 #define REPO_NAME "test-repo-file-hint-at-shard-boundary"
 #define SHARD_SIZE 4
 #define MAX_REV (SHARD_SIZE - 1)
@@ -1672,7 +1693,7 @@ compare_0_length_rep(const svn_test_opts
 
   enum { COUNT = 5 };
   const char *file_names[COUNT] = { no_rep_file,
-                                    empty_delta_file, 
+                                    empty_plain_file, 
                                     plain_file,
                                     empty_delta_file,
                                     delta_file };
@@ -1740,6 +1761,56 @@ compare_0_length_rep(const svn_test_opts
 
 #undef REPO_NAME
 
+/* ------------------------------------------------------------------------ */
+/* Verify that the format 7 pack logic works even if we can't fit all index
+   metadata into memory. */
+#define REPO_NAME "test-repo-pack-with-limited-memory"
+#define SHARD_SIZE 4
+#define MAX_REV (2 * SHARD_SIZE - 1)
+static svn_error_t *
+pack_with_limited_memory(const svn_test_opts_t *opts,
+                         apr_pool_t *pool)
+{
+  apr_size_t max_mem;
+  apr_pool_t *iterpool = svn_pool_create(pool);
+
+  /* Bail (with success) on known-untestable scenarios */
+  if (opts->server_minor_version && (opts->server_minor_version < 9))
+    return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL,
+                            "pre-1.9 SVN doesn't support reordering packs");
+
+  /* Run with an increasing memory allowance such that we cover all
+     splitting scenarios. */
+  for (max_mem = 350; max_mem < 8000; max_mem += max_mem / 2)
+    {
+      const char *dir;
+      svn_fs_t *fs;
+
+      svn_pool_clear(iterpool);
+
+      /* Create a filesystem. */
+      dir = apr_psprintf(iterpool, "%s-%d", REPO_NAME, (int)max_mem);
+      SVN_ERR(create_non_packed_filesystem(dir, opts, MAX_REV, SHARD_SIZE,
+                                           iterpool));
+
+      /* Pack it with a narrow memory budget. */
+      SVN_ERR(svn_fs_open2(&fs, dir, NULL, iterpool, iterpool));
+      SVN_ERR(svn_fs_fs__pack(fs, max_mem, NULL, NULL, NULL, NULL,
+                              iterpool));
+
+      /* To be sure: Verify that we didn't break the repo. */
+      SVN_ERR(svn_fs_verify(dir, NULL, 0, MAX_REV, NULL, NULL, NULL, NULL,
+                            iterpool));
+    }
+
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+#undef REPO_NAME
+#undef MAX_REV
+#undef SHARD_SIZE
+
 
 /* The test table.  */
 
@@ -1790,6 +1861,8 @@ static struct svn_test_descriptor_t test
                        "delta chains starting with PLAIN, issue #4577"),
     SVN_TEST_OPTS_PASS(compare_0_length_rep,
                        "compare empty PLAIN and non-existent reps"),
+    SVN_TEST_OPTS_PASS(pack_with_limited_memory,
+                       "pack with limited memory for metadata"),
     SVN_TEST_NULL
   };
 

Modified: subversion/branches/ra-git/subversion/tests/libsvn_fs_x/fs-x-pack-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_fs_x/fs-x-pack-test.c?rev=1764214&r1=1764213&r2=1764214&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_fs_x/fs-x-pack-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_fs_x/fs-x-pack-test.c Tue Oct 11 09:11:50 2016
@@ -737,7 +737,7 @@ test_info(const svn_test_opts_t *opts,
           apr_pool_t *pool)
 {
   svn_fs_t *fs;
-  const svn_fs_fsfs_info_t *fsfs_info;
+  const svn_fs_fsx_info_t *fsx_info;
   const svn_fs_info_placeholder_t *info;
 
   SVN_ERR(create_packed_filesystem(REPO_NAME, opts, MAX_REV, SHARD_SIZE,
@@ -753,9 +753,9 @@ test_info(const svn_test_opts_t *opts,
   if (strcmp(opts->fs_type, "fsx") != 0)
     return SVN_NO_ERROR;
 
-  fsfs_info = (const void *)info;
-  SVN_TEST_ASSERT(fsfs_info->shard_size == SHARD_SIZE);
-  SVN_TEST_ASSERT(fsfs_info->min_unpacked_rev
+  fsx_info = (const void *)info;
+  SVN_TEST_ASSERT(fsx_info->shard_size == SHARD_SIZE);
+  SVN_TEST_ASSERT(fsx_info->min_unpacked_rev
                   == (MAX_REV + 1) / SHARD_SIZE * SHARD_SIZE);
 
   return SVN_NO_ERROR;
@@ -873,7 +873,7 @@ test_batch_fsync(const svn_test_opts_t *
   SVN_ERR(svn_fs_x__batch_fsync_init());
 
   /* We use and re-use the same batch object throughout this test. */
-  SVN_ERR(svn_fs_x__batch_fsync_create(&batch, pool));
+  SVN_ERR(svn_fs_x__batch_fsync_create(&batch, TRUE, pool));
 
   /* The working directory is new. */
   SVN_ERR(svn_fs_x__batch_fsync_new_path(batch, abspath, pool));

Modified: subversion/branches/ra-git/subversion/tests/libsvn_ra/ra-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_ra/ra-test.c?rev=1764214&r1=1764213&r2=1764214&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_ra/ra-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_ra/ra-test.c Tue Oct 11 09:11:50 2016
@@ -603,6 +603,7 @@ get_dir_test(const svn_test_opts_t *opts
 {
   svn_ra_session_t *session;
   apr_hash_t *dirents;
+  svn_dirent_t *ent;
 
   SVN_ERR(make_and_open_repos(&session, "test-get-dir", opts, pool));
   SVN_ERR(commit_tree(session, pool));
@@ -613,6 +614,19 @@ get_dir_test(const svn_test_opts_t *opts
                                         SVN_DIRENT_KIND, pool),
                         SVN_ERR_FS_NOT_FOUND);
 
+  /* Test fetching SVN_DIRENT_SIZE without SVN_DIRENT_KIND. */
+  SVN_ERR(svn_ra_get_dir2(session, &dirents, NULL, NULL, "", 1,
+                          SVN_DIRENT_SIZE, pool));
+  SVN_TEST_INT_ASSERT(apr_hash_count(dirents), 1);
+  ent = svn_hash_gets(dirents, "A");
+  SVN_TEST_ASSERT(ent);
+
+#if 0
+  /* ra_serf has returns SVN_INVALID_SIZE instead of documented zero for
+   * for directories. */
+  SVN_TEST_INT_ASSERT(ent->size, 0);
+#endif
+
   return SVN_NO_ERROR;
 }
 
@@ -1632,12 +1646,9 @@ commit_empty_last_change(const svn_test_
       SVN_TEST_ASSERT(dirent != NULL);
       SVN_TEST_STRING_ASSERT(dirent->last_author, "jrandom");
       
-      /* BDB only updates last_changed on the repos_root when there is an
-         actual change. Our other filesystems handle this differently */
-      if (!opts->fs_type || !strcasecmp(opts->fs_type, "BDB"))
-        SVN_TEST_INT_ASSERT(dirent->created_rev, 1);
-      else
-        SVN_TEST_INT_ASSERT(dirent->created_rev, 2+i);
+      /* BDB used to only updates last_changed on the repos_root when there
+         was an actual change. Now all filesystems behave in the same way */
+      SVN_TEST_INT_ASSERT(dirent->created_rev, 2+i);
     }
 
   svn_pool_clear(tmp_pool);

Modified: subversion/branches/ra-git/subversion/tests/libsvn_subr/io-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_subr/io-test.c?rev=1764214&r1=1764213&r2=1764214&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_subr/io-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_subr/io-test.c Tue Oct 11 09:11:50 2016
@@ -674,6 +674,68 @@ test_file_readline(apr_pool_t *pool)
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+test_open_uniquely_named(apr_pool_t *pool)
+{
+  const char *tmp_dir;
+  apr_file_t *file;
+  const char *path;
+  svn_error_t *err;
+
+  SVN_ERR(svn_test_make_sandbox_dir(&tmp_dir, "test_open_uniquely_named",
+                                    pool));
+
+  /* Test #1: File 'foo.tmp' doesn't exist. */
+  SVN_ERR(svn_io_open_uniquely_named(&file, &path, tmp_dir, "foo", ".tmp",
+                                     svn_io_file_del_none, pool, pool));
+  SVN_TEST_STRING_ASSERT(path, svn_dirent_join(tmp_dir, "foo.tmp", pool));
+  SVN_ERR(svn_io_file_close(file, pool));
+
+  /* Test #2: File 'foo.tmp' is already exist. */
+  SVN_ERR(svn_io_open_uniquely_named(NULL, &path, tmp_dir, "foo", ".tmp",
+                                     svn_io_file_del_none, pool, pool));
+  SVN_TEST_STRING_ASSERT(path, svn_dirent_join(tmp_dir, "foo.2.tmp", pool));
+
+  /* Test #3: Directory named 'bar.tmp' is already exist. */
+  SVN_ERR(svn_io_dir_make(svn_dirent_join(tmp_dir, "bar.tmp", pool),
+                          APR_OS_DEFAULT, pool));
+  SVN_ERR(svn_io_open_uniquely_named(NULL, &path, tmp_dir, "bar", ".tmp",
+                                     svn_io_file_del_none, pool, pool));
+  SVN_TEST_STRING_ASSERT(path, svn_dirent_join(tmp_dir, "bar.2.tmp", pool));
+
+
+  /* Test #4: Attempt create file in non-existing directory. */
+  err = svn_io_open_uniquely_named(NULL, &path,
+                                   svn_dirent_join(tmp_dir, "non-existing", pool),
+                                   NULL, NULL, svn_io_file_del_none, pool, pool);
+  if (err && APR_STATUS_IS_ENOENT(err->apr_err))
+    {
+      svn_error_clear(err);
+    }
+  else if (err)
+    {
+      return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+                               "Expected error APR_STATUS_IS_ENOTDIR() but "
+                               "got %s",
+                               svn_error_symbolic_name(err->apr_err));
+    }
+  else
+    {
+      SVN_TEST_ASSERT_ANY_ERROR(err);
+    }
+
+  /* Test #5: File 'yota.tmp' is already exist and readonly. */
+  SVN_ERR(svn_io_file_create_empty(svn_dirent_join(tmp_dir, "yota.tmp", pool),
+                                   pool));
+  SVN_ERR(svn_io_set_file_read_only(svn_dirent_join(tmp_dir, "yota.tmp", pool),
+                                    FALSE, pool));
+  SVN_ERR(svn_io_open_uniquely_named(NULL, &path, tmp_dir, "yota", ".tmp",
+                                    svn_io_file_del_none, pool, pool));
+  SVN_TEST_STRING_ASSERT(path, svn_dirent_join(tmp_dir, "yota.2.tmp", pool));
+
+  return SVN_NO_ERROR;
+}
+
 /* Move the read pointer in FILE to absolute position OFFSET and align
  * the read buffer to multiples of BLOCK_SIZE.  BUFFERED is set only if
  * FILE actually uses a read buffer.  Use POOL for allocations.
@@ -803,7 +865,7 @@ aligned_seek_test(apr_pool_t *pool)
   SVN_ERR(svn_io_file_close(f, pool));
 
   /* now, try read data with buffering disabled.
-     That are a special case because APR reports a buffer size of 0. */
+     That is a special case because APR reports a buffer size of 0. */
   SVN_ERR(svn_io_file_open(&f, tmp_file, APR_READ, APR_OS_DEFAULT, pool));
   SVN_ERR(aligned_read(f, contents,   0x1000, FALSE, pool));
   SVN_ERR(aligned_read(f, contents,   0x8000, FALSE, pool));
@@ -1040,6 +1102,51 @@ test_file_rename2(apr_pool_t *pool)
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+test_apr_trunc_workaround(apr_pool_t *pool)
+{
+  const char *tmp_dir;
+  const char *tmp_file;
+  apr_file_t *f;
+  apr_size_t len;
+  apr_off_t offset;
+  char dummy;
+
+  /* create a temp folder & schedule it for automatic cleanup */
+  SVN_ERR(svn_dirent_get_absolute(&tmp_dir, "test_apr_trunc_workaround",
+                                  pool));
+  SVN_ERR(svn_io_remove_dir2(tmp_dir, TRUE, NULL, NULL, pool));
+  SVN_ERR(svn_io_make_dir_recursively(tmp_dir, pool));
+  svn_test_add_dir_cleanup(tmp_dir);
+
+  /* create an r/w file */
+  tmp_file = svn_dirent_join(tmp_dir, "file", pool);
+  SVN_ERR(svn_io_file_open(&f, tmp_file,
+                           APR_READ | APR_WRITE | APR_BUFFERED | APR_CREATE |
+                              APR_TRUNCATE,
+                           APR_OS_DEFAULT, pool));
+
+  /* write some content and put it internally into read mode */
+  len = 10;
+  SVN_ERR(svn_io_file_write(f, "0123456789", &len, pool));
+
+  offset = 0;
+  SVN_ERR(svn_io_file_seek(f, APR_SET, &offset, pool));
+  SVN_ERR(svn_io_file_getc(&dummy, f, pool));
+
+  /* clear the file and write some new content */
+  SVN_ERR(svn_io_file_trunc(f, 0, pool));
+  len = 3;
+  SVN_ERR(svn_io_file_write(f, "abc", &len, pool));
+
+  /* we should now be positioned at the end of the new content */
+  offset = 0;
+  SVN_ERR(svn_io_file_seek(f, APR_CUR, &offset, pool));
+  SVN_TEST_ASSERT(offset == (int)len);
+
+  return SVN_NO_ERROR;  
+}
+
 /* The test table.  */
 
 static int max_threads = 3;
@@ -1073,6 +1180,10 @@ static struct svn_test_descriptor_t test
                    "test svn_io_read_length_line()"),
     SVN_TEST_PASS2(test_file_readline,
                    "test svn_io_file_readline()"),
+    SVN_TEST_PASS2(test_open_uniquely_named,
+                   "test svn_io_open_uniquely_named()"),
+    SVN_TEST_PASS2(test_apr_trunc_workaround,
+                   "test workaround for APR in svn_io_file_trunc"),
     SVN_TEST_NULL
   };
 

Modified: subversion/branches/ra-git/subversion/tests/libsvn_subr/packed-data-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_subr/packed-data-test.c?rev=1764214&r1=1764213&r2=1764214&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_subr/packed-data-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_subr/packed-data-test.c Tue Oct 11 09:11:50 2016
@@ -222,6 +222,7 @@ test_byte_stream(apr_pool_t *pool)
 
   /* the stream shall contain exactly the items we put into it */
   SVN_TEST_ASSERT(svn_packed__byte_count(stream) == 20);
+  SVN_TEST_ASSERT(svn_packed__byte_block_count(stream) == COUNT);
   for (i = 0; i < COUNT; ++i)
     {
       svn_string_t string;

Modified: subversion/branches/ra-git/subversion/tests/libsvn_subr/sqlite-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/libsvn_subr/sqlite-test.c?rev=1764214&r1=1764213&r2=1764214&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/tests/libsvn_subr/sqlite-test.c (original)
+++ subversion/branches/ra-git/subversion/tests/libsvn_subr/sqlite-test.c Tue Oct 11 09:11:50 2016
@@ -26,8 +26,10 @@
 
 static svn_error_t *
 open_db(svn_sqlite__db_t **sdb,
+        const char **db_abspath_p,
         const char *db_name,
         const char *const *statements,
+        apr_int32_t timeout,
         apr_pool_t *pool)
 {
   const char *db_dir, *db_abspath;
@@ -40,8 +42,10 @@ open_db(svn_sqlite__db_t **sdb,
   db_abspath = svn_dirent_join(db_dir, db_name, pool);
 
   SVN_ERR(svn_sqlite__open(sdb, db_abspath, svn_sqlite__mode_rwcreate,
-                           statements, 0, NULL, 0, pool, pool));
+                           statements, 0, NULL, timeout, pool, pool));
 
+  if (db_abspath_p)
+    *db_abspath_p = db_abspath;
   return SVN_NO_ERROR;
 }
 
@@ -83,7 +87,7 @@ test_sqlite_reset(apr_pool_t *pool)
     NULL
   };
 
-  SVN_ERR(open_db(&sdb, "reset", statements, pool));
+  SVN_ERR(open_db(&sdb, NULL, "reset", statements, 0, pool));
   SVN_ERR(svn_sqlite__create_scalar_function(sdb, "error_second",
                                              1, FALSE /* deterministic */,
                                              error_second, NULL));
@@ -113,6 +117,59 @@ test_sqlite_reset(apr_pool_t *pool)
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+test_sqlite_txn_commit_busy(apr_pool_t *pool)
+{
+  svn_sqlite__db_t *sdb1;
+  svn_sqlite__db_t *sdb2;
+  const char *db_abspath;
+  svn_error_t *err;
+
+  static const char *const statements[] = {
+    "CREATE TABLE test (one TEXT NOT NULL PRIMARY KEY)",
+
+    "INSERT INTO test(one) VALUES ('foo')",
+
+    "SELECT one from test",
+
+    NULL
+  };
+
+  /* Open two db connections.
+
+     Use a small busy_timeout of 250ms, since we're about to receive an
+     SVN_ERR_SQLITE_BUSY error, and retrying for the default 10 seconds
+     would be a waste of time. */
+  SVN_ERR(open_db(&sdb1, &db_abspath, "txn_commit_busy",
+                  statements, 250, pool));
+  SVN_ERR(svn_sqlite__open(&sdb2, db_abspath, svn_sqlite__mode_readwrite,
+                           statements, 0, NULL, 250, pool, pool));
+  SVN_ERR(svn_sqlite__exec_statements(sdb1, 0));
+
+  /* Begin two deferred transactions. */
+  SVN_ERR(svn_sqlite__begin_transaction(sdb1));
+  SVN_ERR(svn_sqlite__exec_statements(sdb1, 1 /* INSERT */));
+  SVN_ERR(svn_sqlite__begin_transaction(sdb2));
+  SVN_ERR(svn_sqlite__exec_statements(sdb2, 2 /* SELECT */));
+
+  /* Try to COMMIT the first write transaction; this should fail due to
+     the concurrent read transaction that holds a shared lock on the db. */
+  err = svn_sqlite__finish_transaction(sdb1, SVN_NO_ERROR);
+  SVN_TEST_ASSERT_ERROR(err, SVN_ERR_SQLITE_BUSY);
+
+  /* We failed to COMMIT the first transaction, but COMMIT-ting the
+     second transaction through a different db connection should succeed.
+     Upgrade it to a write transaction by executing the INSERT statement,
+     and then commit. */
+  SVN_ERR(svn_sqlite__exec_statements(sdb2, 1 /* INSERT */));
+  SVN_ERR(svn_sqlite__finish_transaction(sdb2, SVN_NO_ERROR));
+
+  SVN_ERR(svn_sqlite__close(sdb2));
+  SVN_ERR(svn_sqlite__close(sdb1));
+
+  return SVN_NO_ERROR;
+}
+
 
 static int max_threads = 1;
 
@@ -121,6 +178,8 @@ static struct svn_test_descriptor_t test
     SVN_TEST_NULL,
     SVN_TEST_PASS2(test_sqlite_reset,
                    "sqlite reset"),
+    SVN_TEST_PASS2(test_sqlite_txn_commit_busy,
+                   "sqlite busy on transaction commit"),
     SVN_TEST_NULL
   };