You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2012/04/26 19:27:23 UTC
svn commit: r1330982 -
/subversion/trunk/subversion/tests/cmdline/merge_symmetric_tests.py
Author: julianfoad
Date: Thu Apr 26 17:27:23 2012
New Revision: 1330982
URL: http://svn.apache.org/viewvc?rev=1330982&view=rev
Log:
* subversion/tests/cmdline/merge_symmetric_tests.py
New file, making a start on some tests for symmetric merge.
Added:
subversion/trunk/subversion/tests/cmdline/merge_symmetric_tests.py (with props)
Added: subversion/trunk/subversion/tests/cmdline/merge_symmetric_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/merge_symmetric_tests.py?rev=1330982&view=auto
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/merge_symmetric_tests.py (added)
+++ subversion/trunk/subversion/tests/cmdline/merge_symmetric_tests.py Thu Apr 26 17:27:23 2012
@@ -0,0 +1,326 @@
+#!/usr/bin/env python
+#
+# merge_tests.py: testing "symmetric merge" scenarios
+#
+# Subversion is a tool for revision control.
+# See http://subversion.apache.org for more information.
+#
+# ====================================================================
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+######################################################################
+
+# General modules
+import shutil, sys, re, os
+import time
+
+# Our testing module
+import svntest
+from svntest import main, wc, verify, actions
+
+# (abbreviation)
+Item = wc.StateItem
+Skip = svntest.testcase.Skip_deco
+SkipUnless = svntest.testcase.SkipUnless_deco
+XFail = svntest.testcase.XFail_deco
+Issues = svntest.testcase.Issues_deco
+Issue = svntest.testcase.Issue_deco
+Wimp = svntest.testcase.Wimp_deco
+
+from svntest.main import SVN_PROP_MERGEINFO
+from svntest.main import server_has_mergeinfo
+from merge_tests import local_path
+from merge_tests import expected_merge_output
+from merge_tests import svn_merge
+
+#----------------------------------------------------------------------
+
+# Merging scenarios to test
+#
+# Merge once
+#
+# A (--?---
+# ( \
+# B (--?--x
+#
+# Merge twice in same direction
+#
+# A (--o-----?---
+# ( \ \
+# B (--o--x--?--x
+#
+# Merge to and fro
+#
+# A (--o-----?--x
+# ( \ /
+# B (--o--x--?---
+#
+# A (--o-----o-----?--x
+# ( \ \ /
+# B (--o--x--o--x--?---
+#
+# A (--o-----o--x--?--x
+# ( \ / /
+# B (--o--x--o-----?---
+#
+# A (--o-----o--x--?---
+# ( \ / \
+# B (--o--x--o-----?--x
+#
+# Merge with cherry-picks
+#
+# Cherry1, fwd
+# A (--o-----o-[o]----o---
+# ( \ \ \
+# B (--o--x--?-----c-----x
+#
+# Cherry2, fwd
+# A (--o-----?-----c--o---
+# ( \ / \
+# B (--o--x--o-[o]-------x
+#
+# Cherry3, fwd
+# A (--o-----?-------c--o----
+# ( \_____ / \
+# ( \ / \
+# B (--o--o-[o]-x-/---------x
+# \__/
+#
+# Cherry1, back
+# A (--o-----o-[o]-------x
+# ( \ \ /
+# B (--o--x--?-----c--o---
+#
+# Cherry2, back
+# A (--o-----?-----c-----x
+# ( \ / /
+# B (--o--x--o-[o]----o---
+#
+# Cherry3, back
+# A (--o-----?-------c------x
+# ( \_____ / /
+# ( \ / /
+# B (--o--o-[o]-x-/-----o----
+# \__/
+#
+# Criss-cross merge
+#
+# A (--o--?--x--?----
+# ( \ / \
+# ( X \
+# ( / \ \
+# B (--o--?--x--?---x
+#
+# Subtree mergeinfo
+#
+# ...
+#
+# Sparse WC
+#
+# ...
+#
+# Mixed-rev WC
+#
+# ...
+#
+#
+# Key to diagrams:
+#
+# o - an original change
+# ? - an original change or no-op (test both)
+# x - a merge
+# c - a cherry-pick merge
+# [o] - source range of a cherry-pick merge
+
+
+########################################################################
+
+def get_mergeinfo_change(sbox, target):
+ """Return a list of revision numbers representing the mergeinfo change
+ on TARGET (working version against base). Non-recursive."""
+ exit, out, err = actions.run_and_verify_svn(None, None, [],
+ 'diff', '--depth=empty',
+ sbox.ospath(target))
+ merged_revs = []
+ for line in out:
+ match = re.match(r' Merged /(\w+):r([0-9-]+)', line)
+ if match:
+ for r_range in match.group(2).split(','):
+ if '-' in r_range:
+ r_start, r_end = r_range.split('-')
+ else:
+ r_start = r_end = r_range
+ merged_revs += range(int(r_start), int(r_end) + 1)
+ return merged_revs
+
+def make_branches(sbox):
+ """Make branches A and B."""
+ sbox.build()
+ sbox.simple_copy('A', 'B')
+ sbox.simple_commit()
+ os.chdir(sbox.wc_dir)
+ sbox.wc_dir = ''
+
+def modify_branch(sbox, branch, number, conflicting=False):
+ """Commit a modification to branch BRANCH. The actual modification depends
+ on NUMBER. If CONFLICTING=True, the change will be of a kind that
+ conflicts with any other change that has CONFLICTING=True."""
+ uniq = branch + str(number) # something like 'A1' or 'B2'
+ if conflicting:
+ sbox.simple_propset('conflict', uniq, branch + '/C')
+ elif number % 2 == 0:
+ sbox.simple_copy(branch + '/mu', branch + '/mu-' + uniq)
+ else: # number % 2 == 1
+ sbox.simple_propset('prop-' + uniq, uniq, branch + '/D')
+ sbox.simple_commit()
+
+def symmetric_merge(sbox, source, target, lines=None, args=[],
+ expect_mi=None, expect_3ways=None):
+ """Do a complete, automatic merge from path SOURCE to path TARGET, and
+ commit. Verify the output and that there is no error.
+ ### TODO: Verify the changes made.)
+
+ LINES is a list of regular expressions to match other lines of output; if
+ LINES is 'None' then match all normal (non-conflicting) merges.
+
+ ARGS are additional arguments passed to svn merge."""
+
+ source = local_path(source)
+ target = local_path(target)
+
+ # First, update the WC target because mixed-rev is not fully supported.
+ sbox.simple_update(target)
+
+ if lines is None:
+ lines = ["--- Recording mergeinfo for .*\n",
+ "(A |D |[UG] | [UG]|[UG][UG]) " + target + ".*\n"]
+ else:
+ # Expect mergeinfo on the target; caller must supply matches for any
+ # subtree mergeinfo paths.
+ lines.append(" [UG] " + target + "\n")
+ exp_out = expected_merge_output(None, lines, target=target)
+ svntest.actions.run_and_verify_svn(None, exp_out, [],
+ 'merge', '--symmetric',
+ '^/' + source, target,
+ *args)
+ if expect_mi is not None:
+ actual_mi_change = get_mergeinfo_change(sbox, target)
+ assert actual_mi_change == expect_mi
+ if expect_3ways is not None:
+ ### actual_3ways = ...
+ ### assert actual_3ways == expect_3ways
+ pass
+
+ sbox.simple_commit()
+
+def cherry_pick(sbox, rev, source, target):
+ """Cherry-pick merge revision REV from branch SOURCE to branch TARGET
+ (both WC-relative paths), and commit."""
+ sbox.simple_update(target)
+ svn_merge(rev, source, target)
+ sbox.simple_commit()
+
+
+#----------------------------------------------------------------------
+
+# Merge once
+#
+# A (--?---
+# ( \
+# B (--?--x
+
+@SkipUnless(server_has_mergeinfo)
+def merge_once_1(sbox):
+ """merge_once_1"""
+ make_branches(sbox)
+ symmetric_merge(sbox, 'A', 'B')
+
+@SkipUnless(server_has_mergeinfo)
+def merge_once_2(sbox):
+ """merge_once_2"""
+ make_branches(sbox)
+ modify_branch(sbox, 'A', 1)
+ symmetric_merge(sbox, 'A', 'B')
+
+@SkipUnless(server_has_mergeinfo)
+def merge_once_3(sbox):
+ """merge_once_3"""
+ make_branches(sbox)
+ modify_branch(sbox, 'B', 1)
+ symmetric_merge(sbox, 'A', 'B')
+
+@SkipUnless(server_has_mergeinfo)
+def merge_once_4(sbox):
+ """merge_once_4"""
+ make_branches(sbox)
+ modify_branch(sbox, 'A', 3)
+ modify_branch(sbox, 'B', 4)
+
+ expect_mi = [2, 3, 4]
+ symmetric_merge(sbox, 'A', 'B',
+ expect_mi=expect_mi)
+
+#----------------------------------------------------------------------
+
+# Cherry2, fwd
+#
+# A (--o-----?-----c--o---
+# ( \ / \
+# B (--o--x--o-[o]-------x
+# 2 34 5 6 7 8 9
+#
+@SkipUnless(server_has_mergeinfo)
+def cherry2_fwd(sbox):
+ """cherry2-fwd"""
+ make_branches(sbox)
+ modify_branch(sbox, 'A', 3)
+ modify_branch(sbox, 'B', 4)
+ symmetric_merge(sbox, 'A', 'B')
+ modify_branch(sbox, 'B', 6)
+ modify_branch(sbox, 'B', 7)
+ cherry_pick(sbox, 7, 'B', 'A')
+ modify_branch(sbox, 'A', 9)
+
+ # Expected merge:
+ # Logical changes = A9 (and NOT A8)
+ # Mergeinfo += A5-9
+ # 3-way merges: (Base=A8, Source-right=A9)
+ expect_mi = [5, 6, 7, 8, 9]
+ expect_3ways = [('A8', 'A9')]
+ symmetric_merge(sbox, 'A', 'B',
+ expect_mi=expect_mi, expect_3ways=expect_3ways)
+
+
+########################################################################
+# Run the tests
+
+
+# list all tests here, starting with None:
+test_list = [ None,
+ merge_once_1,
+ merge_once_2,
+ merge_once_3,
+ merge_once_4,
+ cherry2_fwd,
+ ]
+
+if __name__ == '__main__':
+ svntest.main.run_tests(test_list)
+ # NOTREACHED
+
+
+### End of file.
Propchange: subversion/trunk/subversion/tests/cmdline/merge_symmetric_tests.py
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: subversion/trunk/subversion/tests/cmdline/merge_symmetric_tests.py
------------------------------------------------------------------------------
svn:executable = *