test-simplemerge.py
365 lines
| 12.3 KiB
| text/x-python
|
PythonLexer
/ tests / test-simplemerge.py
Alexis S. L. Carvalho
|
r4362 | # Copyright (C) 2004, 2005 Canonical Ltd | ||
# | ||||
# This program is free software; you can redistribute it and/or modify | ||||
# it under the terms of the GNU General Public License as published by | ||||
# the Free Software Foundation; either version 2 of the License, or | ||||
# (at your option) any later version. | ||||
# | ||||
# This program is distributed in the hope that it will be useful, | ||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
# GNU General Public License for more details. | ||||
# | ||||
# You should have received a copy of the GNU General Public License | ||||
Martin Geisler
|
r15782 | # along with this program; if not, see <http://www.gnu.org/licenses/>. | ||
Alexis S. L. Carvalho
|
r4362 | |||
Pulkit Goyal
|
r28927 | from __future__ import absolute_import | ||
Alexis S. L. Carvalho
|
r4363 | import unittest | ||
Pulkit Goyal
|
r28927 | from mercurial import ( | ||
error, | ||||
simplemerge, | ||||
util, | ||||
) | ||||
Matt Mackall
|
r6002 | |||
Yuya Nishihara
|
r37102 | from mercurial.utils import ( | ||
stringutil, | ||||
) | ||||
Pulkit Goyal
|
r28927 | TestCase = unittest.TestCase | ||
Matt Mackall
|
r6002 | # bzr compatible interface, for the tests | ||
class Merge3(simplemerge.Merge3Text): | ||||
"""3-way merge of texts. | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Matt Mackall
|
r6002 | Given BASE, OTHER, THIS, tries to produce a combined text | ||
incorporating the changes from both BASE->OTHER and BASE->THIS. | ||||
All three will typically be sequences of lines.""" | ||||
def __init__(self, base, a, b): | ||||
Augie Fackler
|
r37909 | basetext = b'\n'.join([i.strip(b'\n') for i in base] + [b'']) | ||
atext = b'\n'.join([i.strip(b'\n') for i in a] + [b'']) | ||||
btext = b'\n'.join([i.strip(b'\n') for i in b] + [b'']) | ||||
Yuya Nishihara
|
r37102 | if (stringutil.binary(basetext) or stringutil.binary(atext) | ||
or stringutil.binary(btext)): | ||||
Augie Fackler
|
r37909 | raise error.Abort(b"don't know how to merge binary files") | ||
Matt Mackall
|
r6002 | simplemerge.Merge3Text.__init__(self, basetext, atext, btext, | ||
base, a, b) | ||||
Alexis S. L. Carvalho
|
r4363 | CantReprocessAndShowBase = simplemerge.CantReprocessAndShowBase | ||
Alexis S. L. Carvalho
|
r4362 | |||
def split_lines(t): | ||||
timeless
|
r28861 | return util.stringio(t).readlines() | ||
Alexis S. L. Carvalho
|
r4362 | |||
############################################################ | ||||
# test case data from the gnu diffutils manual | ||||
# common base | ||||
Augie Fackler
|
r37909 | TZU = split_lines(b""" The Nameless is the origin of Heaven and Earth; | ||
Alexis S. L. Carvalho
|
r4362 | The named is the mother of all things. | ||
Thomas Arendsen Hein
|
r4516 | |||
Alexis S. L. Carvalho
|
r4362 | Therefore let there always be non-being, | ||
so we may see their subtlety, | ||||
And let there always be being, | ||||
so we may see their outcome. | ||||
The two are the same, | ||||
But after they are produced, | ||||
they have different names. | ||||
They both may be called deep and profound. | ||||
Deeper and more profound, | ||||
The door of all subtleties! | ||||
""") | ||||
Augie Fackler
|
r37909 | LAO = split_lines(b""" The Way that can be told of is not the eternal Way; | ||
Alexis S. L. Carvalho
|
r4362 | The name that can be named is not the eternal name. | ||
The Nameless is the origin of Heaven and Earth; | ||||
The Named is the mother of all things. | ||||
Therefore let there always be non-being, | ||||
so we may see their subtlety, | ||||
And let there always be being, | ||||
so we may see their outcome. | ||||
The two are the same, | ||||
But after they are produced, | ||||
they have different names. | ||||
""") | ||||
Augie Fackler
|
r37909 | TAO = split_lines(b""" The Way that can be told of is not the eternal Way; | ||
Alexis S. L. Carvalho
|
r4362 | The name that can be named is not the eternal name. | ||
The Nameless is the origin of Heaven and Earth; | ||||
The named is the mother of all things. | ||||
Thomas Arendsen Hein
|
r4516 | |||
Alexis S. L. Carvalho
|
r4362 | Therefore let there always be non-being, | ||
so we may see their subtlety, | ||||
And let there always be being, | ||||
so we may see their result. | ||||
The two are the same, | ||||
But after they are produced, | ||||
they have different names. | ||||
Thomas Arendsen Hein
|
r4516 | |||
Alexis S. L. Carvalho
|
r4362 | -- The Way of Lao-Tzu, tr. Wing-tsit Chan | ||
""") | ||||
Augie Fackler
|
r37909 | MERGED_RESULT = split_lines(b"""\ | ||
Matt Mackall
|
r10282 | The Way that can be told of is not the eternal Way; | ||
Alexis S. L. Carvalho
|
r4362 | The name that can be named is not the eternal name. | ||
The Nameless is the origin of Heaven and Earth; | ||||
The Named is the mother of all things. | ||||
Therefore let there always be non-being, | ||||
so we may see their subtlety, | ||||
And let there always be being, | ||||
so we may see their result. | ||||
The two are the same, | ||||
But after they are produced, | ||||
Danny Hooper
|
r38667 | they have different names.\ | ||
\n<<<<<<< LAO\ | ||||
\n======= | ||||
Thomas Arendsen Hein
|
r4516 | |||
Alexis S. L. Carvalho
|
r4362 | -- The Way of Lao-Tzu, tr. Wing-tsit Chan | ||
Danny Hooper
|
r38667 | \ | ||
\n>>>>>>> TAO | ||||
Alexis S. L. Carvalho
|
r4362 | """) | ||
class TestMerge3(TestCase): | ||||
Alexis S. L. Carvalho
|
r4363 | def log(self, msg): | ||
pass | ||||
Alexis S. L. Carvalho
|
r4362 | |||
def test_no_changes(self): | ||||
"""No conflicts because nothing changed""" | ||||
Augie Fackler
|
r37909 | m3 = Merge3([b'aaa', b'bbb'], | ||
[b'aaa', b'bbb'], | ||||
[b'aaa', b'bbb']) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37908 | self.assertEqual(m3.find_unconflicted(), | ||
[(0, 2)]) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37908 | self.assertEqual(list(m3.find_sync_regions()), | ||
[(0, 2, | ||||
0, 2, | ||||
0, 2), | ||||
(2, 2, 2, 2, 2, 2)]) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37908 | self.assertEqual(list(m3.merge_regions()), | ||
Augie Fackler
|
r37909 | [(b'unchanged', 0, 2)]) | ||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37908 | self.assertEqual(list(m3.merge_groups()), | ||
Augie Fackler
|
r37909 | [(b'unchanged', [b'aaa', b'bbb'])]) | ||
Alexis S. L. Carvalho
|
r4362 | |||
def test_front_insert(self): | ||||
Augie Fackler
|
r37909 | m3 = Merge3([b'zz'], | ||
[b'aaa', b'bbb', b'zz'], | ||||
[b'zz']) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
timeless@mozdev.org
|
r17513 | # todo: should use a sentinel at end as from get_matching_blocks | ||
Alexis S. L. Carvalho
|
r4362 | # to match without zz | ||
Augie Fackler
|
r37908 | self.assertEqual(list(m3.find_sync_regions()), | ||
[(0, 1, 2, 3, 0, 1), | ||||
(1, 1, 3, 3, 1, 1)]) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37908 | self.assertEqual(list(m3.merge_regions()), | ||
Augie Fackler
|
r37909 | [(b'a', 0, 2), | ||
(b'unchanged', 0, 1)]) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37908 | self.assertEqual(list(m3.merge_groups()), | ||
Augie Fackler
|
r37909 | [(b'a', [b'aaa', b'bbb']), | ||
(b'unchanged', [b'zz'])]) | ||||
Thomas Arendsen Hein
|
r4516 | |||
Alexis S. L. Carvalho
|
r4362 | def test_null_insert(self): | ||
m3 = Merge3([], | ||||
Augie Fackler
|
r37909 | [b'aaa', b'bbb'], | ||
Alexis S. L. Carvalho
|
r4362 | []) | ||
timeless@mozdev.org
|
r17513 | # todo: should use a sentinel at end as from get_matching_blocks | ||
Alexis S. L. Carvalho
|
r4362 | # to match without zz | ||
Augie Fackler
|
r37908 | self.assertEqual(list(m3.find_sync_regions()), | ||
[(0, 0, 2, 2, 0, 0)]) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37908 | self.assertEqual(list(m3.merge_regions()), | ||
Augie Fackler
|
r37909 | [(b'a', 0, 2)]) | ||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37908 | self.assertEqual(list(m3.merge_lines()), | ||
Augie Fackler
|
r37909 | [b'aaa', b'bbb']) | ||
Alexis S. L. Carvalho
|
r4362 | |||
def test_no_conflicts(self): | ||||
"""No conflicts because only one side changed""" | ||||
Augie Fackler
|
r37909 | m3 = Merge3([b'aaa', b'bbb'], | ||
[b'aaa', b'111', b'bbb'], | ||||
[b'aaa', b'bbb']) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37908 | self.assertEqual(m3.find_unconflicted(), | ||
[(0, 1), (1, 2)]) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37908 | self.assertEqual(list(m3.find_sync_regions()), | ||
[(0, 1, 0, 1, 0, 1), | ||||
(1, 2, 2, 3, 1, 2), | ||||
(2, 2, 3, 3, 2, 2)]) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37908 | self.assertEqual(list(m3.merge_regions()), | ||
Augie Fackler
|
r37909 | [(b'unchanged', 0, 1), | ||
(b'a', 1, 2), | ||||
(b'unchanged', 1, 2)]) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
def test_append_a(self): | ||||
Augie Fackler
|
r37909 | m3 = Merge3([b'aaa\n', b'bbb\n'], | ||
[b'aaa\n', b'bbb\n', b'222\n'], | ||||
[b'aaa\n', b'bbb\n']) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37909 | self.assertEqual(b''.join(m3.merge_lines()), | ||
b'aaa\nbbb\n222\n') | ||||
Alexis S. L. Carvalho
|
r4362 | |||
def test_append_b(self): | ||||
Augie Fackler
|
r37909 | m3 = Merge3([b'aaa\n', b'bbb\n'], | ||
[b'aaa\n', b'bbb\n'], | ||||
[b'aaa\n', b'bbb\n', b'222\n']) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37909 | self.assertEqual(b''.join(m3.merge_lines()), | ||
b'aaa\nbbb\n222\n') | ||||
Alexis S. L. Carvalho
|
r4362 | |||
def test_append_agreement(self): | ||||
Augie Fackler
|
r37909 | m3 = Merge3([b'aaa\n', b'bbb\n'], | ||
[b'aaa\n', b'bbb\n', b'222\n'], | ||||
[b'aaa\n', b'bbb\n', b'222\n']) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37909 | self.assertEqual(b''.join(m3.merge_lines()), | ||
b'aaa\nbbb\n222\n') | ||||
Alexis S. L. Carvalho
|
r4362 | |||
def test_append_clash(self): | ||||
Augie Fackler
|
r37909 | m3 = Merge3([b'aaa\n', b'bbb\n'], | ||
[b'aaa\n', b'bbb\n', b'222\n'], | ||||
[b'aaa\n', b'bbb\n', b'333\n']) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37909 | ml = m3.merge_lines(name_a=b'a', | ||
name_b=b'b', | ||||
start_marker=b'<<', | ||||
mid_marker=b'--', | ||||
end_marker=b'>>') | ||||
self.assertEqual(b''.join(ml), | ||||
b'aaa\n' | ||||
b'bbb\n' | ||||
b'<< a\n' | ||||
b'222\n' | ||||
b'--\n' | ||||
b'333\n' | ||||
b'>> b\n' | ||||
Thomas Arendsen Hein
|
r4633 | ) | ||
Alexis S. L. Carvalho
|
r4362 | |||
def test_insert_agreement(self): | ||||
Augie Fackler
|
r37909 | m3 = Merge3([b'aaa\n', b'bbb\n'], | ||
[b'aaa\n', b'222\n', b'bbb\n'], | ||||
[b'aaa\n', b'222\n', b'bbb\n']) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37909 | ml = m3.merge_lines(name_a=b'a', | ||
name_b=b'b', | ||||
start_marker=b'<<', | ||||
mid_marker=b'--', | ||||
end_marker=b'>>') | ||||
self.assertEqual(b''.join(ml), b'aaa\n222\nbbb\n') | ||||
Thomas Arendsen Hein
|
r4516 | |||
Alexis S. L. Carvalho
|
r4362 | |||
def test_insert_clash(self): | ||||
"""Both try to insert lines in the same place.""" | ||||
Augie Fackler
|
r37909 | m3 = Merge3([b'aaa\n', b'bbb\n'], | ||
[b'aaa\n', b'111\n', b'bbb\n'], | ||||
[b'aaa\n', b'222\n', b'bbb\n']) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37908 | self.assertEqual(m3.find_unconflicted(), | ||
[(0, 1), (1, 2)]) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37908 | self.assertEqual(list(m3.find_sync_regions()), | ||
[(0, 1, 0, 1, 0, 1), | ||||
(1, 2, 2, 3, 2, 3), | ||||
(2, 2, 3, 3, 3, 3)]) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37908 | self.assertEqual(list(m3.merge_regions()), | ||
Augie Fackler
|
r37909 | [(b'unchanged', 0, 1), | ||
(b'conflict', 1, 1, 1, 2, 1, 2), | ||||
(b'unchanged', 1, 2)]) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37908 | self.assertEqual(list(m3.merge_groups()), | ||
Augie Fackler
|
r37909 | [(b'unchanged', [b'aaa\n']), | ||
(b'conflict', [], [b'111\n'], [b'222\n']), | ||||
(b'unchanged', [b'bbb\n']), | ||||
Augie Fackler
|
r37908 | ]) | ||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37909 | ml = m3.merge_lines(name_a=b'a', | ||
name_b=b'b', | ||||
start_marker=b'<<', | ||||
mid_marker=b'--', | ||||
end_marker=b'>>') | ||||
self.assertEqual(b''.join(ml), | ||||
b'''aaa | ||||
Alexis S. L. Carvalho
|
r4362 | << a | ||
111 | ||||
-- | ||||
222 | ||||
>> b | ||||
bbb | ||||
''') | ||||
def test_replace_clash(self): | ||||
"""Both try to insert lines in the same place.""" | ||||
Augie Fackler
|
r37909 | m3 = Merge3([b'aaa', b'000', b'bbb'], | ||
[b'aaa', b'111', b'bbb'], | ||||
[b'aaa', b'222', b'bbb']) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37908 | self.assertEqual(m3.find_unconflicted(), | ||
[(0, 1), (2, 3)]) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37908 | self.assertEqual(list(m3.find_sync_regions()), | ||
[(0, 1, 0, 1, 0, 1), | ||||
Augie Fackler
|
r37909 | (2, 3, 2, 3, 2, 3), | ||
(3, 3, 3, 3, 3, 3)]) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
def test_replace_multi(self): | ||||
"""Replacement with regions of different size.""" | ||||
Augie Fackler
|
r37909 | m3 = Merge3([b'aaa', b'000', b'000', b'bbb'], | ||
[b'aaa', b'111', b'111', b'111', b'bbb'], | ||||
[b'aaa', b'222', b'222', b'222', b'222', b'bbb']) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37908 | self.assertEqual(m3.find_unconflicted(), | ||
[(0, 1), (3, 4)]) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r37908 | self.assertEqual(list(m3.find_sync_regions()), | ||
[(0, 1, 0, 1, 0, 1), | ||||
(3, 4, 4, 5, 5, 6), | ||||
(4, 4, 5, 5, 6, 6)]) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
def test_merge_poem(self): | ||||
"""Test case from diff3 manual""" | ||||
m3 = Merge3(TZU, LAO, TAO) | ||||
Augie Fackler
|
r37909 | ml = list(m3.merge_lines(b'LAO', b'TAO')) | ||
self.log(b'merge result:') | ||||
self.log(b''.join(ml)) | ||||
Augie Fackler
|
r37908 | self.assertEqual(ml, MERGED_RESULT) | ||
Alexis S. L. Carvalho
|
r4362 | |||
def test_binary(self): | ||||
Gregory Szorc
|
r32279 | with self.assertRaises(error.Abort): | ||
Augie Fackler
|
r37909 | Merge3([b'\x00'], [b'a'], [b'b']) | ||
Alexis S. L. Carvalho
|
r4362 | |||
def test_dos_text(self): | ||||
Augie Fackler
|
r37909 | base_text = b'a\r\n' | ||
this_text = b'b\r\n' | ||||
other_text = b'c\r\n' | ||||
Alexis S. L. Carvalho
|
r4362 | m3 = Merge3(base_text.splitlines(True), other_text.splitlines(True), | ||
this_text.splitlines(True)) | ||||
Augie Fackler
|
r37909 | m_lines = m3.merge_lines(b'OTHER', b'THIS') | ||
self.assertEqual(b'<<<<<<< OTHER\r\nc\r\n=======\r\nb\r\n' | ||||
b'>>>>>>> THIS\r\n'.splitlines(True), list(m_lines)) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
def test_mac_text(self): | ||||
Augie Fackler
|
r37909 | base_text = b'a\r' | ||
this_text = b'b\r' | ||||
other_text = b'c\r' | ||||
Alexis S. L. Carvalho
|
r4362 | m3 = Merge3(base_text.splitlines(True), other_text.splitlines(True), | ||
this_text.splitlines(True)) | ||||
Augie Fackler
|
r37909 | m_lines = m3.merge_lines(b'OTHER', b'THIS') | ||
self.assertEqual(b'<<<<<<< OTHER\rc\r=======\rb\r' | ||||
b'>>>>>>> THIS\r'.splitlines(True), list(m_lines)) | ||||
Alexis S. L. Carvalho
|
r4363 | |||
if __name__ == '__main__': | ||||
# hide the timer | ||||
import time | ||||
orig = time.time | ||||
try: | ||||
time.time = lambda: 0 | ||||
unittest.main() | ||||
finally: | ||||
time.time = orig | ||||