subversion/subversion-1.6.18-hashorder...

730 lines
29 KiB
Diff

Add APR hashorder fixes from upstream.
--- subversion-1.6.18/subversion/bindings/swig/python/tests/repository.py.hashorder
+++ subversion-1.6.18/subversion/bindings/swig/python/tests/repository.py
@@ -133,9 +133,11 @@ class SubversionRepositoryTestCase(unitt
repos.dir_delta(prev_root, '', '', this_root, '', e_ptr, e_baton,
_authz_callback, 1, 1, 0, 0)
- # Check results
- self.assertEqual(editor.textdeltas[0].new_data, "This is a test.\n")
- self.assertEqual(editor.textdeltas[1].new_data, "A test.\n")
+ # Check results.
+ # Ignore the order in which the editor delivers the two sibling files.
+ self.assertEqual(set([editor.textdeltas[0].new_data,
+ editor.textdeltas[1].new_data]),
+ set(["This is a test.\n", "A test.\n"]))
self.assertEqual(len(editor.textdeltas),2)
def test_retrieve_and_change_rev_prop(self):
--- subversion-1.6.18/subversion/bindings/swig/python/tests/trac/versioncontrol/tests/svn_fs.py.hashorder
+++ subversion-1.6.18/subversion/bindings/swig/python/tests/trac/versioncontrol/tests/svn_fs.py
@@ -224,30 +224,50 @@ class SubversionRepositoryTestCase(unitt
def test_diff_dir_different_revs(self):
diffs = self.repos.get_deltas('trunk', 4, 'trunk', 8)
- self._cmp_diff((None, ('trunk/dir1/dir2', 8),
- (Node.DIRECTORY, Changeset.ADD)), diffs.next())
- self._cmp_diff((None, ('trunk/dir1/dir3', 8),
- (Node.DIRECTORY, Changeset.ADD)), diffs.next())
- self._cmp_diff((None, ('trunk/README2.txt', 6),
- (Node.FILE, Changeset.ADD)), diffs.next())
- self._cmp_diff((('trunk/dir2', 4), None,
- (Node.DIRECTORY, Changeset.DELETE)), diffs.next())
- self._cmp_diff((('trunk/dir3', 4), None,
- (Node.DIRECTORY, Changeset.DELETE)), diffs.next())
+ expected = [
+ (None, ('trunk/README2.txt', 6),
+ (Node.FILE, Changeset.ADD)),
+ (None, ('trunk/dir1/dir2', 8),
+ (Node.DIRECTORY, Changeset.ADD)),
+ (None, ('trunk/dir1/dir3', 8),
+ (Node.DIRECTORY, Changeset.ADD)),
+ (('trunk/dir2', 4), None,
+ (Node.DIRECTORY, Changeset.DELETE)),
+ (('trunk/dir3', 4), None,
+ (Node.DIRECTORY, Changeset.DELETE)),
+ ]
+ actual = [diffs.next() for i in range(5)]
+ actual = sorted(actual,
+ key=lambda diff: ((diff[0] or diff[1]).path,
+ (diff[0] or diff[1]).rev))
+ self.assertEqual(len(expected), len(actual))
+ for e,a in zip(expected, actual):
+ self._cmp_diff(e,a)
self.assertRaises(StopIteration, diffs.next)
def test_diff_dir_different_dirs(self):
diffs = self.repos.get_deltas('trunk', 1, 'branches/v1x', 12)
- self._cmp_diff((None, ('branches/v1x/dir1', 12),
- (Node.DIRECTORY, Changeset.ADD)), diffs.next())
- self._cmp_diff((None, ('branches/v1x/dir1/dir2', 12),
- (Node.DIRECTORY, Changeset.ADD)), diffs.next())
- self._cmp_diff((None, ('branches/v1x/dir1/dir3', 12),
- (Node.DIRECTORY, Changeset.ADD)), diffs.next())
- self._cmp_diff((None, ('branches/v1x/README.txt', 12),
- (Node.FILE, Changeset.ADD)), diffs.next())
- self._cmp_diff((None, ('branches/v1x/README2.txt', 12),
- (Node.FILE, Changeset.ADD)), diffs.next())
+ expected = [
+ (None, ('branches/v1x/README.txt', 12),
+ (Node.FILE, Changeset.ADD)),
+ (None, ('branches/v1x/README2.txt', 12),
+ (Node.FILE, Changeset.ADD)),
+ (None, ('branches/v1x/dir1', 12),
+ (Node.DIRECTORY, Changeset.ADD)),
+ (None, ('branches/v1x/dir1/dir2', 12),
+ (Node.DIRECTORY, Changeset.ADD)),
+ (None, ('branches/v1x/dir1/dir3', 12),
+ (Node.DIRECTORY, Changeset.ADD)),
+ ]
+ actual = [diffs.next() for i in range(5)]
+ actual = sorted(actual, key=lambda diff: (diff[1].path, diff[1].rev))
+ # for e,a in zip(expected, actual):
+ # t.write("%r\n" % (e,))
+ # t.write("%r\n" % ((None, (a[1].path, a[1].rev), (a[2], a[3])),) )
+ # t.write('\n')
+ self.assertEqual(len(expected), len(actual))
+ for e,a in zip(expected, actual):
+ self._cmp_diff(e,a)
self.assertRaises(StopIteration, diffs.next)
def test_diff_dir_no_change(self):
--- subversion-1.6.18/subversion/bindings/swig/python/tests/wc.py.hashorder
+++ subversion-1.6.18/subversion/bindings/swig/python/tests/wc.py
@@ -193,8 +193,9 @@ class SubversionWorkingCopyTestCase(unit
def test_entries_read(self):
entries = wc.entries_read(self.wc, True)
-
- self.assertEqual(['', 'tags', 'branches', 'trunk'], list(entries.keys()))
+ keys = list(entries.keys())
+ keys.sort()
+ self.assertEqual(['', 'branches', 'tags', 'trunk'], keys)
def test_get_ignores(self):
self.assert_(isinstance(wc.get_ignores(None, self.wc), list))
--- subversion-1.6.18/subversion/tests/cmdline/diff_tests.py.hashorder
+++ subversion-1.6.18/subversion/tests/cmdline/diff_tests.py
@@ -1024,8 +1024,10 @@ def diff_base_to_repos(sbox):
if not re_infoline.match(line):
list2.append(line)
- if list1 != list2:
- raise svntest.Failure
+ # Two files in diff may be in any order.
+ list1 = svntest.verify.UnorderedOutput(list1)
+
+ svntest.verify.compare_and_display_lines('', '', list1, list2)
#----------------------------------------------------------------------
--- subversion-1.6.18/subversion/tests/cmdline/lock_tests.py.hashorder
+++ subversion-1.6.18/subversion/tests/cmdline/lock_tests.py
@@ -1164,6 +1164,8 @@ def repos_lock_with_info(sbox):
raise svntest.Failure
#----------------------------------------------------------------------
+@Issue(4126)
+@Skip(svntest.main.is_ra_type_dav_serf) # Issue 4126 unpredictable result
def unlock_already_unlocked_files(sbox):
"(un)lock set of files, one already (un)locked"
--- subversion-1.6.18/subversion/tests/cmdline/stat_tests.py.hashorder
+++ subversion-1.6.18/subversion/tests/cmdline/stat_tests.py
@@ -781,38 +781,13 @@ def status_in_xml(sbox):
else:
raise svntest.Failure
- template = ["<?xml version=\"1.0\"?>\n",
- "<status>\n",
- "<target\n",
- " path=\"%s\">\n" % (file_path),
- "<entry\n",
- " path=\"%s\">\n" % (file_path),
- "<wc-status\n",
- " props=\"none\"\n",
- " item=\"modified\"\n",
- " revision=\"1\">\n",
- "<commit\n",
- " revision=\"1\">\n",
- "<author>%s</author>\n" % svntest.main.wc_author,
- time_str,
- "</commit>\n",
- "</wc-status>\n",
- "</entry>\n",
- "<against\n",
- " revision=\"1\"/>\n",
- "</target>\n",
- "</status>\n",
- ]
+ expected_entries = {file_path : {'wcprops' : 'none',
+ 'wcitem' : 'modified',
+ 'wcrev' : '1',
+ 'crev' : '1',
+ 'author' : svntest.main.wc_author}}
- exit_code, output, error = svntest.actions.run_and_verify_svn(None, None, [],
- 'status',
- file_path,
- '--xml', '-u')
-
- for i in range(0, len(output)):
- if output[i] != template[i]:
- print("ERROR: expected: %s actual: %s" % (template[i], output[i]))
- raise svntest.Failure
+ svntest.actions.run_and_verify_status_xml(expected_entries, file_path, '-u')
#----------------------------------------------------------------------
@@ -1049,53 +1024,23 @@ def status_update_with_incoming_props(sb
else:
raise svntest.Failure
- xout = ["<?xml version=\"1.0\"?>\n",
- "<status>\n",
- "<target\n",
- " path=\"%s\">\n" % (wc_dir),
- "<entry\n",
- " path=\"%s\">\n" % (A_path),
- "<wc-status\n",
- " props=\"none\"\n",
- " item=\"normal\"\n",
- " revision=\"1\">\n",
- "<commit\n",
- " revision=\"1\">\n",
- "<author>%s</author>\n" % svntest.main.wc_author,
- time_str,
- "</commit>\n",
- "</wc-status>\n",
- "<repos-status\n",
- " props=\"modified\"\n",
- " item=\"none\">\n",
- "</repos-status>\n",
- "</entry>\n",
- "<entry\n",
- " path=\"%s\">\n" % (wc_dir),
- "<wc-status\n",
- " props=\"none\"\n",
- " item=\"normal\"\n",
- " revision=\"1\">\n",
- "<commit\n",
- " revision=\"1\">\n",
- "<author>%s</author>\n" % svntest.main.wc_author,
- time_str,
- "</commit>\n",
- "</wc-status>\n",
- "<repos-status\n",
- " props=\"modified\"\n",
- " item=\"none\">\n",
- "</repos-status>\n",
- "</entry>\n",
- "<against\n",
- " revision=\"2\"/>\n",
- "</target>\n",
- "</status>\n",]
-
- exit_code, output, error = svntest.actions.run_and_verify_svn(None, xout, [],
- 'status',
- wc_dir,
- '--xml', '-uN')
+ expected_entries ={wc_dir : {'wcprops' : 'none',
+ 'wcitem' : 'normal',
+ 'wcrev' : '1',
+ 'crev' : '1',
+ 'author' : svntest.main.wc_author,
+ 'rprops' : 'modified',
+ 'ritem' : 'none'},
+ A_path : {'wcprops' : 'none',
+ 'wcitem' : 'normal',
+ 'wcrev' : '1',
+ 'crev' : '1',
+ 'author' : svntest.main.wc_author,
+ 'rprops' : 'modified',
+ 'ritem' : 'none'},
+ }
+
+ svntest.actions.run_and_verify_status_xml(expected_entries, wc_dir, '-uN')
# more incoming prop updates.
def status_update_verbose_with_incoming_props(sbox):
--- subversion-1.6.18/subversion/tests/cmdline/svnlook_tests.py.hashorder
+++ subversion-1.6.18/subversion/tests/cmdline/svnlook_tests.py
@@ -105,35 +105,39 @@ def test_misc(sbox):
# the 'svnlook tree --full-paths' output if demanding the whole repository
treelist = run_svnlook('tree', repo_dir)
treelistfull = run_svnlook('tree', '--full-paths', repo_dir)
+
path = ''
- n = 0
+ treelistexpand = []
for entry in treelist:
len1 = len(entry)
len2 = len(entry.lstrip())
- path = path[0:2*(len1-len2)-1] + entry.strip()
- test = treelistfull[n].rstrip()
- if n != 0:
- test = "/" + test
- if not path == test:
- print("Unexpected result from tree with --full-paths:")
- print(" entry : %s" % entry.rstrip())
- print(" with --full-paths: %s" % treelistfull[n].rstrip())
- raise svntest.Failure
- n = n + 1
+ path = path[0:2*(len1-len2)-1] + entry.strip() + '\n'
+ if path == '/\n':
+ treelistexpand.append(path)
+ else:
+ treelistexpand.append(path[1:])
+
+ treelistexpand = svntest.verify.UnorderedOutput(treelistexpand)
+ svntest.verify.compare_and_display_lines('Unexpected result from tree', '',
+ treelistexpand, treelistfull)
# check if the 'svnlook tree' output is the ending of
# the 'svnlook tree --full-paths' output if demanding
# any part of the repository
- n = 0
treelist = run_svnlook('tree', repo_dir, '/A/B')
treelistfull = run_svnlook('tree', '--full-paths', repo_dir, '/A/B')
+
+ path = ''
+ treelistexpand = []
for entry in treelist:
- if not treelistfull[n].endswith(entry.lstrip()):
- print("Unexpected result from tree with --full-paths:")
- print(" entry : %s" % entry.rstrip())
- print(" with --full-paths: %s" % treelistfull[n].rstrip())
- raise svntest.Failure
- n = n + 1
+ len1 = len(entry)
+ len2 = len(entry.lstrip())
+ path = path[0:2*(len1-len2)] + entry.strip() + '\n'
+ treelistexpand.append('/A/' + path)
+
+ treelistexpand = svntest.verify.UnorderedOutput(treelistexpand)
+ svntest.verify.compare_and_display_lines('Unexpected result from tree', '',
+ treelistexpand, treelistfull)
treelist = run_svnlook('tree', repo_dir, '/')
if treelist[0] != '/\n':
@@ -621,7 +625,7 @@ fp.close()"""
# internal property, not really expected
' svn:check-locks\n',
' bogus_rev_prop\n', ' svn:date\n']
- verify_logfile(logfilepath, expected_data)
+ verify_logfile(logfilepath, svntest.verify.UnorderedOutput(expected_data))
########################################################################
# Run the tests
--- subversion-1.6.18/subversion/tests/cmdline/svnsync_tests.py.hashorder
+++ subversion-1.6.18/subversion/tests/cmdline/svnsync_tests.py
@@ -179,7 +179,7 @@ or another dump file."""
else:
exp_master_dumpfile_contents = master_dumpfile_contents
- svntest.verify.compare_and_display_lines(
+ svntest.verify.compare_dump_files(
"Dump files", "DUMP", exp_master_dumpfile_contents, dest_dump)
--- subversion-1.6.18/subversion/tests/cmdline/svntest/actions.py.hashorder
+++ subversion-1.6.18/subversion/tests/cmdline/svntest/actions.py
@@ -448,7 +448,8 @@ class LogEntry:
self.revprops = revprops
def assert_changed_paths(self, changed_paths):
- """Not implemented, so just raises svntest.Failure.
+ """Assert that changed_paths is the same as this entry's changed_paths
+ Raises svntest.Failure if not.
"""
raise Failure('NOT IMPLEMENTED')
@@ -902,13 +903,21 @@ def run_and_verify_merge2(dir, rev1, rev
if dry_run and out != out_dry:
# Due to the way ra_serf works, it's possible that the dry-run and
# real merge operations did the same thing, but the output came in
- # a different order. Let's see if maybe that's the case.
+ # a different order. Let's see if maybe that's the case by comparing
+ # the outputs as unordered sets rather than as lists.
+ #
+ # This now happens for other RA layers with modern APR because the
+ # hash order now varies.
#
- # NOTE: Would be nice to limit this dance to serf tests only, but...
- out_copy = out[:]
- out_dry_copy = out_dry[:]
- out_copy.sort()
- out_dry_copy.sort()
+ # The different orders of the real and dry-run merges may cause
+ # the "Merging rX through rY into" lines to be duplicated a
+ # different number of times in the two outputs. The list-set
+ # conversion removes duplicates so these differences are ignored.
+ # It also removes "U some/path" duplicate lines. Perhaps we
+ # should avoid that?
+ out_copy = set(merge_diff_out[:])
+ out_dry_copy = set(out_dry[:])
+
if out_copy != out_dry_copy:
print("=============================================================")
print("Merge outputs differ")
@@ -1193,6 +1202,56 @@ def run_and_verify_unquiet_status(wc_dir
tree.dump_tree_script(actual, wc_dir_name + os.sep)
raise
+def run_and_verify_status_xml(expected_entries = [],
+ *args):
+ """ Run 'status --xml' with arguments *ARGS. If successful the output
+ is parsed into an XML document and will be verified by comparing against
+ EXPECTED_ENTRIES.
+ """
+
+ exit_code, output, errput = run_and_verify_svn(None, None, [],
+ 'status', '--xml', *args)
+
+ if len(errput) > 0:
+ raise Failure
+
+ doc = parseString(''.join(output))
+ entries = doc.getElementsByTagName('entry')
+
+ def getText(nodelist):
+ rc = []
+ for node in nodelist:
+ if node.nodeType == node.TEXT_NODE:
+ rc.append(node.data)
+ return ''.join(rc)
+
+ actual_entries = {}
+ for entry in entries:
+ wcstatus = entry.getElementsByTagName('wc-status')[0]
+ commit = entry.getElementsByTagName('commit')
+ author = entry.getElementsByTagName('author')
+ rstatus = entry.getElementsByTagName('repos-status')
+
+ actual_entry = {'wcprops' : wcstatus.getAttribute('props'),
+ 'wcitem' : wcstatus.getAttribute('item'),
+ }
+ if wcstatus.hasAttribute('revision'):
+ actual_entry['wcrev'] = wcstatus.getAttribute('revision')
+ if (commit):
+ actual_entry['crev'] = commit[0].getAttribute('revision')
+ if (author):
+ actual_entry['author'] = getText(author[0].childNodes)
+ if (rstatus):
+ actual_entry['rprops'] = rstatus[0].getAttribute('props')
+ actual_entry['ritem'] = rstatus[0].getAttribute('item')
+
+ actual_entries[entry.getAttribute('path')] = actual_entry
+
+ if expected_entries != actual_entries:
+ raise Failure('\n' + '\n'.join(difflib.ndiff(
+ pprint.pformat(expected_entries).splitlines(),
+ pprint.pformat(actual_entries).splitlines())))
+
def run_and_verify_diff_summarize_xml(error_re_string = [],
expected_prefix = None,
expected_paths = [],
--- subversion-1.6.18/subversion/tests/cmdline/svntest/verify.py.hashorder
+++ subversion-1.6.18/subversion/tests/cmdline/svntest/verify.py
@@ -17,6 +17,8 @@
######################################################################
import re, sys
+from difflib import ndiff
+import pprint
import main, tree, wc # general svntest routines in this module.
from svntest import Failure
@@ -59,6 +61,10 @@ class SVNIncorrectDatatype(SVNUnexpected
run_and_verify_* API"""
pass
+class SVNDumpParseError(Failure):
+ """Exception raised if parsing a dump file fails"""
+ pass
+
######################################################################
# Comparison of expected vs. actual output
@@ -359,3 +365,193 @@ def verify_exit_code(message, actual, ex
display_lines(message, "Exit Code",
str(expected) + '\n', str(actual) + '\n')
raise raisable
+
+# A simple dump file parser. While sufficient for the current
+# testsuite it doesn't cope with all valid dump files.
+class DumpParser:
+ def __init__(self, lines):
+ self.current = 0
+ self.lines = lines
+ self.parsed = {}
+
+ def parse_line(self, regex, required=True):
+ m = re.match(regex, self.lines[self.current])
+ if not m:
+ if required:
+ raise SVNDumpParseError("expected '%s' at line %d\n%s"
+ % (regex, self.current,
+ self.lines[self.current]))
+ else:
+ return None
+ self.current += 1
+ return m.group(1)
+
+ def parse_blank(self, required=True):
+ if self.lines[self.current] != '\n': # Works on Windows
+ if required:
+ raise SVNDumpParseError("expected blank at line %d\n%s"
+ % (self.current, self.lines[self.current]))
+ else:
+ return False
+ self.current += 1
+ return True
+
+ def parse_format(self):
+ return self.parse_line('SVN-fs-dump-format-version: ([0-9]+)$')
+
+ def parse_uuid(self):
+ return self.parse_line('UUID: ([0-9a-z-]+)$')
+
+ def parse_revision(self):
+ return self.parse_line('Revision-number: ([0-9]+)$')
+
+ def parse_prop_length(self, required=True):
+ return self.parse_line('Prop-content-length: ([0-9]+)$', required)
+
+ def parse_content_length(self, required=True):
+ return self.parse_line('Content-length: ([0-9]+)$', required)
+
+ def parse_path(self):
+ path = self.parse_line('Node-path: (.+)$', required=False)
+ if not path and self.lines[self.current] == 'Node-path: \n':
+ self.current += 1
+ path = ''
+ return path
+
+ def parse_kind(self):
+ return self.parse_line('Node-kind: (.+)$', required=False)
+
+ def parse_action(self):
+ return self.parse_line('Node-action: ([0-9a-z-]+)$')
+
+ def parse_copyfrom_rev(self):
+ return self.parse_line('Node-copyfrom-rev: ([0-9]+)$', required=False)
+
+ def parse_copyfrom_path(self):
+ path = self.parse_line('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)
+
+ def parse_copy_sha1(self):
+ return self.parse_line('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)
+
+ def parse_text_sha1(self):
+ return self.parse_line('Text-content-sha1: ([0-9a-z]+)$', required=False)
+
+ def parse_text_length(self):
+ return self.parse_line('Text-content-length: ([0-9]+)$', required=False)
+
+ # One day we may need to parse individual property name/values into a map
+ def get_props(self):
+ props = []
+ while not re.match('PROPS-END$', self.lines[self.current]):
+ props.append(self.lines[self.current])
+ self.current += 1
+ self.current += 1
+ return props
+
+ def get_content(self, length):
+ content = ''
+ while len(content) < length:
+ content += self.lines[self.current]
+ self.current += 1
+ if len(content) == length + 1:
+ content = content[:-1]
+ elif len(content) != length:
+ raise SVNDumpParseError("content length expected %d actual %d at line %d"
+ % (length, len(content), self.current))
+ return content
+
+ def parse_one_node(self):
+ node = {}
+ node['kind'] = self.parse_kind()
+ action = self.parse_action()
+ node['copyfrom_rev'] = self.parse_copyfrom_rev()
+ node['copyfrom_path'] = self.parse_copyfrom_path()
+ node['copy_md5'] = self.parse_copy_md5()
+ node['copy_sha1'] = self.parse_copy_sha1()
+ node['prop_length'] = self.parse_prop_length(required=False)
+ node['text_length'] = self.parse_text_length()
+ node['text_md5'] = self.parse_text_md5()
+ node['text_sha1'] = self.parse_text_sha1()
+ node['content_length'] = self.parse_content_length(required=False)
+ self.parse_blank()
+ if node['prop_length']:
+ node['props'] = self.get_props()
+ if node['text_length']:
+ node['content'] = self.get_content(int(node['text_length']))
+ # Hard to determine how may blanks is 'correct' (a delete that is
+ # followed by an add that is a replace and a copy has one fewer
+ # than expected but that can't be predicted until seeing the add)
+ # so allow arbitrary number
+ blanks = 0
+ while self.current < len(self.lines) and self.parse_blank(required=False):
+ blanks += 1
+ node['blanks'] = blanks
+ return action, node
+
+ def parse_all_nodes(self):
+ nodes = {}
+ while True:
+ if self.current >= len(self.lines):
+ break
+ path = self.parse_path()
+ if not path and not path is '':
+ break
+ if not nodes.get(path):
+ nodes[path] = {}
+ action, node = self.parse_one_node()
+ if nodes[path].get(action):
+ raise SVNDumpParseError("duplicate action '%s' for node '%s' at line %d"
+ % (action, path, self.current))
+ nodes[path][action] = node
+ return nodes
+
+ def parse_one_revision(self):
+ revision = {}
+ number = self.parse_revision()
+ revision['prop_length'] = self.parse_prop_length()
+ revision['content_length'] = self.parse_content_length()
+ self.parse_blank()
+ revision['props'] = self.get_props()
+ self.parse_blank()
+ revision['nodes'] = self.parse_all_nodes()
+ return number, revision
+
+ def parse_all_revisions(self):
+ while self.current < len(self.lines):
+ number, revision = self.parse_one_revision()
+ if self.parsed.get(number):
+ raise SVNDumpParseError("duplicate revision %d at line %d"
+ % (number, self.current))
+ self.parsed[number] = revision
+
+ def parse(self):
+ self.parsed['format'] = self.parse_format()
+ self.parse_blank()
+ self.parsed['uuid'] = self.parse_uuid()
+ self.parse_blank()
+ self.parse_all_revisions()
+ return self.parsed
+
+def compare_dump_files(message, label, expected, actual):
+ """Parse two dump files EXPECTED and ACTUAL, both of which are lists
+ of lines as returned by run_and_verify_dump, and check that the same
+ revisions, nodes, properties, etc. are present in both dumps.
+ """
+
+ parsed_expected = DumpParser(expected).parse()
+ parsed_actual = DumpParser(actual).parse()
+
+ if parsed_expected != parsed_actual:
+ raise svntest.Failure('\n' + '\n'.join(ndiff(
+ pprint.pformat(parsed_expected).splitlines(),
+ pprint.pformat(parsed_actual).splitlines())))
--- subversion-1.6.18/subversion/tests/cmdline/switch_tests.py.hashorder
+++ subversion-1.6.18/subversion/tests/cmdline/switch_tests.py
@@ -1541,33 +1541,29 @@ def mergeinfo_switch_elision(sbox):
beta_path = os.path.join(wc_dir, "A", "B", "E", "beta")
# Make branches A/B_COPY_1 and A/B_COPY_2
- svntest.actions.run_and_verify_svn(
- None,
- ["A " + os.path.join(wc_dir, "A", "B_COPY_1", "lambda") + "\n",
+ expected_stdout = verify.UnorderedOutput([
+ "A " + os.path.join(wc_dir, "A", "B_COPY_1", "lambda") + "\n",
"A " + os.path.join(wc_dir, "A", "B_COPY_1", "E") + "\n",
"A " + os.path.join(wc_dir, "A", "B_COPY_1", "E", "alpha") + "\n",
"A " + os.path.join(wc_dir, "A", "B_COPY_1", "E", "beta") + "\n",
"A " + os.path.join(wc_dir, "A", "B_COPY_1", "F") + "\n",
"Checked out revision 1.\n",
- "A " + B_COPY_1_path + "\n"],
- [],
- 'copy',
- sbox.repo_url + "/A/B",
- B_COPY_1_path)
-
- svntest.actions.run_and_verify_svn(
- None,
- ["A " + os.path.join(wc_dir, "A", "B_COPY_2", "lambda") + "\n",
+ "A " + B_COPY_1_path + "\n",
+ ])
+ svntest.actions.run_and_verify_svn(None, expected_stdout, [], 'copy',
+ sbox.repo_url + "/A/B", B_COPY_1_path)
+
+ expected_stdout = verify.UnorderedOutput([
+ "A " + os.path.join(wc_dir, "A", "B_COPY_2", "lambda") + "\n",
"A " + os.path.join(wc_dir, "A", "B_COPY_2", "E") + "\n",
"A " + os.path.join(wc_dir, "A", "B_COPY_2", "E", "alpha") + "\n",
"A " + os.path.join(wc_dir, "A", "B_COPY_2", "E", "beta") + "\n",
"A " + os.path.join(wc_dir, "A", "B_COPY_2", "F") + "\n",
"Checked out revision 1.\n",
- "A " + B_COPY_2_path + "\n"],
- [],
- 'copy',
- sbox.repo_url + "/A/B",
- B_COPY_2_path)
+ "A " + B_COPY_2_path + "\n",
+ ])
+ svntest.actions.run_and_verify_svn(None, expected_stdout, [], 'copy',
+ sbox.repo_url + "/A/B", B_COPY_2_path)
expected_output = svntest.wc.State(wc_dir, {
'A/B_COPY_1' : Item(verb='Adding'),
--- subversion-1.6.18/subversion/tests/cmdline/update_tests.py.hashorder
+++ subversion-1.6.18/subversion/tests/cmdline/update_tests.py
@@ -1101,6 +1101,7 @@ def another_hudson_problem(sbox):
# Sigh, I can't get run_and_verify_update to work (but not because
# of issue 919 as far as I can tell)
+ expected_output = svntest.verify.UnorderedOutput(expected_output)
svntest.actions.run_and_verify_svn(None,
['D '+G_path+'\n',
'Updated to revision 3.\n',
@@ -2849,19 +2850,17 @@ def mergeinfo_update_elision(sbox):
lambda_path = os.path.join(wc_dir, "A", "B", "lambda")
# Make a branch A/B_COPY
- svntest.actions.run_and_verify_svn(
- None,
- ["A " + os.path.join(wc_dir, "A", "B_COPY", "lambda") + "\n",
+ expected_stdout = verify.UnorderedOutput([
+ "A " + os.path.join(wc_dir, "A", "B_COPY", "lambda") + "\n",
"A " + os.path.join(wc_dir, "A", "B_COPY", "E") + "\n",
"A " + os.path.join(wc_dir, "A", "B_COPY", "E", "alpha") + "\n",
"A " + os.path.join(wc_dir, "A", "B_COPY", "E", "beta") + "\n",
"A " + os.path.join(wc_dir, "A", "B_COPY", "F") + "\n",
"Checked out revision 1.\n",
- "A " + B_COPY_path + "\n"],
- [],
- 'copy',
- sbox.repo_url + "/A/B",
- B_COPY_path)
+ "A " + B_COPY_path + "\n",
+ ])
+ svntest.actions.run_and_verify_svn(None, expected_stdout, [], 'copy',
+ sbox.repo_url + "/A/B", B_COPY_path)
expected_output = wc.State(wc_dir, {'A/B_COPY' : Item(verb='Adding')})
expected_status = svntest.actions.get_virginal_state(wc_dir, 1)