test-simplemerge.py
395 lines
| 11.2 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 | |||
Alexis S. L. Carvalho
|
r4363 | import unittest | ||
Pulkit Goyal
|
r28927 | from mercurial import ( | ||
error, | ||||
simplemerge, | ||||
util, | ||||
) | ||||
Matt Mackall
|
r6002 | |||
Augie Fackler
|
r43346 | from mercurial.utils import stringutil | ||
Yuya Nishihara
|
r37102 | |||
Pulkit Goyal
|
r28927 | TestCase = unittest.TestCase | ||
Raphaël Gomès
|
r52596 | |||
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.""" | ||||
Augie Fackler
|
r43346 | |||
Matt Mackall
|
r6002 | 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'']) | ||||
Augie Fackler
|
r43346 | 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") | ||
Augie Fackler
|
r43346 | simplemerge.Merge3Text.__init__( | ||
self, basetext, atext, btext, base, a, b | ||||
) | ||||
Matt Mackall
|
r6002 | |||
Alexis S. L. Carvalho
|
r4362 | def split_lines(t): | ||
timeless
|
r28861 | return util.stringio(t).readlines() | ||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r43346 | |||
Alexis S. L. Carvalho
|
r4362 | ############################################################ | ||
# test case data from the gnu diffutils manual | ||||
# common base | ||||
Augie Fackler
|
r43346 | 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
|
r43346 | """ | ||
) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r43346 | 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
|
r43346 | """ | ||
) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r43346 | 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
|
r43346 | """ | ||
) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r43346 | 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 | ||||
Augie Fackler
|
r43346 | """ | ||
) | ||||
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
|
r43346 | m3 = Merge3([b'aaa', b'bbb'], [b'aaa', b'bbb'], [b'aaa', b'bbb']) | ||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r43346 | 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
|
r43346 | self.assertEqual(list(m3.merge_regions()), [(b'unchanged', 0, 2)]) | ||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r43346 | self.assertEqual( | ||
list(m3.merge_groups()), [(b'unchanged', [b'aaa', b'bbb'])] | ||||
) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
def test_front_insert(self): | ||||
Augie Fackler
|
r43346 | 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
|
r43346 | 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
|
r43346 | self.assertEqual( | ||
list(m3.merge_regions()), [(b'a', 0, 2), (b'unchanged', 0, 1)] | ||||
) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r43346 | self.assertEqual( | ||
list(m3.merge_groups()), | ||||
[(b'a', [b'aaa', b'bbb']), (b'unchanged', [b'zz'])], | ||||
) | ||||
Thomas Arendsen Hein
|
r4516 | |||
Alexis S. L. Carvalho
|
r4362 | def test_null_insert(self): | ||
Augie Fackler
|
r43346 | m3 = Merge3([], [b'aaa', b'bbb'], []) | ||
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
|
r43346 | self.assertEqual(list(m3.find_sync_regions()), [(0, 0, 2, 2, 0, 0)]) | ||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r43346 | self.assertEqual(list(m3.merge_regions()), [(b'a', 0, 2)]) | ||
Alexis S. L. Carvalho
|
r4362 | |||
Martin von Zweigbergk
|
r49407 | self.assertEqual( | ||
Martin von Zweigbergk
|
r49411 | simplemerge.render_minimized(m3), ([b'aaa', b'bbb'], False) | ||
Martin von Zweigbergk
|
r49407 | ) | ||
Alexis S. L. Carvalho
|
r4362 | |||
def test_no_conflicts(self): | ||||
"""No conflicts because only one side changed""" | ||||
Augie Fackler
|
r43346 | m3 = Merge3( | ||
[b'aaa', b'bbb'], [b'aaa', b'111', b'bbb'], [b'aaa', b'bbb'] | ||||
) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r43346 | 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
|
r43346 | self.assertEqual( | ||
list(m3.merge_regions()), | ||||
[(b'unchanged', 0, 1), (b'a', 1, 2), (b'unchanged', 1, 2)], | ||||
) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
def test_append_a(self): | ||||
Augie Fackler
|
r43346 | 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 | |||
Martin von Zweigbergk
|
r49406 | self.assertEqual( | ||
Martin von Zweigbergk
|
r49411 | b''.join(simplemerge.render_minimized(m3)[0]), b'aaa\nbbb\n222\n' | ||
Martin von Zweigbergk
|
r49406 | ) | ||
Alexis S. L. Carvalho
|
r4362 | |||
def test_append_b(self): | ||||
Augie Fackler
|
r43346 | 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 | |||
Martin von Zweigbergk
|
r49406 | self.assertEqual( | ||
Martin von Zweigbergk
|
r49411 | b''.join(simplemerge.render_minimized(m3)[0]), b'aaa\nbbb\n222\n' | ||
Martin von Zweigbergk
|
r49406 | ) | ||
Alexis S. L. Carvalho
|
r4362 | |||
def test_append_agreement(self): | ||||
Augie Fackler
|
r43346 | 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 | |||
Martin von Zweigbergk
|
r49406 | self.assertEqual( | ||
Martin von Zweigbergk
|
r49411 | b''.join(simplemerge.render_minimized(m3)[0]), b'aaa\nbbb\n222\n' | ||
Martin von Zweigbergk
|
r49406 | ) | ||
Alexis S. L. Carvalho
|
r4362 | |||
def test_append_clash(self): | ||||
Augie Fackler
|
r43346 | 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 | |||
Martin von Zweigbergk
|
r49411 | ml, conflicts = simplemerge.render_minimized( | ||
Martin von Zweigbergk
|
r49406 | m3, | ||
Augie Fackler
|
r43346 | 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', | ||||
) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
def test_insert_agreement(self): | ||||
Augie Fackler
|
r43346 | 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 | |||
Martin von Zweigbergk
|
r49411 | ml, conflicts = simplemerge.render_minimized( | ||
Martin von Zweigbergk
|
r49406 | m3, | ||
Augie Fackler
|
r43346 | name_a=b'a', | ||
name_b=b'b', | ||||
start_marker=b'<<', | ||||
mid_marker=b'--', | ||||
end_marker=b'>>', | ||||
) | ||||
Augie Fackler
|
r37909 | 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
|
r43346 | 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
|
r43346 | 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
|
r43346 | self.assertEqual( | ||
list(m3.merge_regions()), | ||||
[ | ||||
(b'unchanged', 0, 1), | ||||
(b'conflict', 1, 1, 1, 2, 1, 2), | ||||
(b'unchanged', 1, 2), | ||||
], | ||||
) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Augie Fackler
|
r43346 | self.assertEqual( | ||
list(m3.merge_groups()), | ||||
[ | ||||
(b'unchanged', [b'aaa\n']), | ||||
Martin von Zweigbergk
|
r49379 | (b'conflict', ([], [b'111\n'], [b'222\n'])), | ||
Augie Fackler
|
r43346 | (b'unchanged', [b'bbb\n']), | ||
], | ||||
) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
Martin von Zweigbergk
|
r49411 | ml, conflicts = simplemerge.render_minimized( | ||
Martin von Zweigbergk
|
r49406 | m3, | ||
Augie Fackler
|
r43346 | 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 | ||||
Augie Fackler
|
r43346 | ''', | ||
) | ||||
Alexis S. L. Carvalho
|
r4362 | |||
def test_replace_clash(self): | ||||
"""Both try to insert lines in the same place.""" | ||||
Augie Fackler
|
r43346 | 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
|
r43346 | self.assertEqual( | ||
list(m3.find_sync_regions()), | ||||
[(0, 1, 0, 1, 0, 1), (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
|
r43346 | 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
|
r43346 | 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) | ||||
Martin von Zweigbergk
|
r49411 | ml, conflicts = simplemerge.render_minimized(m3, b'LAO', b'TAO') | ||
Augie Fackler
|
r37909 | 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' | ||||
Augie Fackler
|
r43346 | m3 = Merge3( | ||
base_text.splitlines(True), | ||||
other_text.splitlines(True), | ||||
this_text.splitlines(True), | ||||
) | ||||
Martin von Zweigbergk
|
r49411 | m_lines, conflicts = simplemerge.render_minimized(m3, b'OTHER', b'THIS') | ||
Augie Fackler
|
r43346 | self.assertEqual( | ||
b'<<<<<<< OTHER\r\nc\r\n=======\r\nb\r\n' | ||||
b'>>>>>>> THIS\r\n'.splitlines(True), | ||||
Martin von Zweigbergk
|
r49405 | m_lines, | ||
Augie Fackler
|
r43346 | ) | ||
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' | ||||
Augie Fackler
|
r43346 | m3 = Merge3( | ||
base_text.splitlines(True), | ||||
other_text.splitlines(True), | ||||
this_text.splitlines(True), | ||||
) | ||||
Martin von Zweigbergk
|
r49411 | m_lines, conflicts = simplemerge.render_minimized(m3, b'OTHER', b'THIS') | ||
Augie Fackler
|
r43346 | self.assertEqual( | ||
b'<<<<<<< OTHER\rc\r=======\rb\r' | ||||
b'>>>>>>> THIS\r'.splitlines(True), | ||||
Martin von Zweigbergk
|
r49405 | m_lines, | ||
Augie Fackler
|
r43346 | ) | ||
Alexis S. L. Carvalho
|
r4363 | |||
if __name__ == '__main__': | ||||
Gregory Szorc
|
r43280 | import silenttestrunner | ||
Augie Fackler
|
r43346 | |||
Gregory Szorc
|
r43280 | silenttestrunner.main(__name__) | ||