tests/test-simplemerge.py
changeset 37892 c1bc196e021d
parent 37891 a3ed6e7217c1
child 38645 02850baddadd
equal deleted inserted replaced
37891:a3ed6e7217c1 37892:c1bc196e021d
    33 
    33 
    34     Given BASE, OTHER, THIS, tries to produce a combined text
    34     Given BASE, OTHER, THIS, tries to produce a combined text
    35     incorporating the changes from both BASE->OTHER and BASE->THIS.
    35     incorporating the changes from both BASE->OTHER and BASE->THIS.
    36     All three will typically be sequences of lines."""
    36     All three will typically be sequences of lines."""
    37     def __init__(self, base, a, b):
    37     def __init__(self, base, a, b):
    38         basetext = '\n'.join([i.strip('\n') for i in base] + [''])
    38         basetext = b'\n'.join([i.strip(b'\n') for i in base] + [b''])
    39         atext = '\n'.join([i.strip('\n') for i in a] + [''])
    39         atext = b'\n'.join([i.strip(b'\n') for i in a] + [b''])
    40         btext = '\n'.join([i.strip('\n') for i in b] + [''])
    40         btext = b'\n'.join([i.strip(b'\n') for i in b] + [b''])
    41         if (stringutil.binary(basetext) or stringutil.binary(atext)
    41         if (stringutil.binary(basetext) or stringutil.binary(atext)
    42             or stringutil.binary(btext)):
    42             or stringutil.binary(btext)):
    43             raise error.Abort("don't know how to merge binary files")
    43             raise error.Abort(b"don't know how to merge binary files")
    44         simplemerge.Merge3Text.__init__(self, basetext, atext, btext,
    44         simplemerge.Merge3Text.__init__(self, basetext, atext, btext,
    45                                         base, a, b)
    45                                         base, a, b)
    46 
    46 
    47 CantReprocessAndShowBase = simplemerge.CantReprocessAndShowBase
    47 CantReprocessAndShowBase = simplemerge.CantReprocessAndShowBase
    48 
    48 
    50     return util.stringio(t).readlines()
    50     return util.stringio(t).readlines()
    51 
    51 
    52 ############################################################
    52 ############################################################
    53 # test case data from the gnu diffutils manual
    53 # test case data from the gnu diffutils manual
    54 # common base
    54 # common base
    55 TZU = split_lines("""     The Nameless is the origin of Heaven and Earth;
    55 TZU = split_lines(b"""     The Nameless is the origin of Heaven and Earth;
    56      The named is the mother of all things.
    56      The named is the mother of all things.
    57 
    57 
    58      Therefore let there always be non-being,
    58      Therefore let there always be non-being,
    59        so we may see their subtlety,
    59        so we may see their subtlety,
    60      And let there always be being,
    60      And let there always be being,
    65      They both may be called deep and profound.
    65      They both may be called deep and profound.
    66      Deeper and more profound,
    66      Deeper and more profound,
    67      The door of all subtleties!
    67      The door of all subtleties!
    68 """)
    68 """)
    69 
    69 
    70 LAO = split_lines("""     The Way that can be told of is not the eternal Way;
    70 LAO = split_lines(b"""     The Way that can be told of is not the eternal Way;
    71      The name that can be named is not the eternal name.
    71      The name that can be named is not the eternal name.
    72      The Nameless is the origin of Heaven and Earth;
    72      The Nameless is the origin of Heaven and Earth;
    73      The Named is the mother of all things.
    73      The Named is the mother of all things.
    74      Therefore let there always be non-being,
    74      Therefore let there always be non-being,
    75        so we may see their subtlety,
    75        so we may see their subtlety,
    79      But after they are produced,
    79      But after they are produced,
    80        they have different names.
    80        they have different names.
    81 """)
    81 """)
    82 
    82 
    83 
    83 
    84 TAO = split_lines("""     The Way that can be told of is not the eternal Way;
    84 TAO = split_lines(b"""     The Way that can be told of is not the eternal Way;
    85      The name that can be named is not the eternal name.
    85      The name that can be named is not the eternal name.
    86      The Nameless is the origin of Heaven and Earth;
    86      The Nameless is the origin of Heaven and Earth;
    87      The named is the mother of all things.
    87      The named is the mother of all things.
    88 
    88 
    89      Therefore let there always be non-being,
    89      Therefore let there always be non-being,
    96 
    96 
    97        -- The Way of Lao-Tzu, tr. Wing-tsit Chan
    97        -- The Way of Lao-Tzu, tr. Wing-tsit Chan
    98 
    98 
    99 """)
    99 """)
   100 
   100 
   101 MERGED_RESULT = split_lines("""\
   101 MERGED_RESULT = split_lines(b"""\
   102      The Way that can be told of is not the eternal Way;
   102      The Way that can be told of is not the eternal Way;
   103      The name that can be named is not the eternal name.
   103      The name that can be named is not the eternal name.
   104      The Nameless is the origin of Heaven and Earth;
   104      The Nameless is the origin of Heaven and Earth;
   105      The Named is the mother of all things.
   105      The Named is the mother of all things.
   106      Therefore let there always be non-being,
   106      Therefore let there always be non-being,
   122     def log(self, msg):
   122     def log(self, msg):
   123         pass
   123         pass
   124 
   124 
   125     def test_no_changes(self):
   125     def test_no_changes(self):
   126         """No conflicts because nothing changed"""
   126         """No conflicts because nothing changed"""
   127         m3 = Merge3(['aaa', 'bbb'],
   127         m3 = Merge3([b'aaa', b'bbb'],
   128                     ['aaa', 'bbb'],
   128                     [b'aaa', b'bbb'],
   129                     ['aaa', 'bbb'])
   129                     [b'aaa', b'bbb'])
   130 
   130 
   131         self.assertEqual(m3.find_unconflicted(),
   131         self.assertEqual(m3.find_unconflicted(),
   132                          [(0, 2)])
   132                          [(0, 2)])
   133 
   133 
   134         self.assertEqual(list(m3.find_sync_regions()),
   134         self.assertEqual(list(m3.find_sync_regions()),
   136                            0, 2,
   136                            0, 2,
   137                            0, 2),
   137                            0, 2),
   138                           (2, 2,  2, 2,  2, 2)])
   138                           (2, 2,  2, 2,  2, 2)])
   139 
   139 
   140         self.assertEqual(list(m3.merge_regions()),
   140         self.assertEqual(list(m3.merge_regions()),
   141                          [('unchanged', 0, 2)])
   141                          [(b'unchanged', 0, 2)])
   142 
   142 
   143         self.assertEqual(list(m3.merge_groups()),
   143         self.assertEqual(list(m3.merge_groups()),
   144                          [('unchanged', ['aaa', 'bbb'])])
   144                          [(b'unchanged', [b'aaa', b'bbb'])])
   145 
   145 
   146     def test_front_insert(self):
   146     def test_front_insert(self):
   147         m3 = Merge3(['zz'],
   147         m3 = Merge3([b'zz'],
   148                     ['aaa', 'bbb', 'zz'],
   148                     [b'aaa', b'bbb', b'zz'],
   149                     ['zz'])
   149                     [b'zz'])
   150 
   150 
   151         # todo: should use a sentinel at end as from get_matching_blocks
   151         # todo: should use a sentinel at end as from get_matching_blocks
   152         # to match without zz
   152         # to match without zz
   153         self.assertEqual(list(m3.find_sync_regions()),
   153         self.assertEqual(list(m3.find_sync_regions()),
   154                          [(0, 1,  2, 3,  0, 1),
   154                          [(0, 1,  2, 3,  0, 1),
   155                           (1, 1,  3, 3,  1, 1)])
   155                           (1, 1,  3, 3,  1, 1)])
   156 
   156 
   157         self.assertEqual(list(m3.merge_regions()),
   157         self.assertEqual(list(m3.merge_regions()),
   158                          [('a', 0, 2),
   158                          [(b'a', 0, 2),
   159                           ('unchanged', 0, 1)])
   159                           (b'unchanged', 0, 1)])
   160 
   160 
   161         self.assertEqual(list(m3.merge_groups()),
   161         self.assertEqual(list(m3.merge_groups()),
   162                          [('a', ['aaa', 'bbb']),
   162                          [(b'a', [b'aaa', b'bbb']),
   163                           ('unchanged', ['zz'])])
   163                           (b'unchanged', [b'zz'])])
   164 
   164 
   165     def test_null_insert(self):
   165     def test_null_insert(self):
   166         m3 = Merge3([],
   166         m3 = Merge3([],
   167                     ['aaa', 'bbb'],
   167                     [b'aaa', b'bbb'],
   168                     [])
   168                     [])
   169         # todo: should use a sentinel at end as from get_matching_blocks
   169         # todo: should use a sentinel at end as from get_matching_blocks
   170         # to match without zz
   170         # to match without zz
   171         self.assertEqual(list(m3.find_sync_regions()),
   171         self.assertEqual(list(m3.find_sync_regions()),
   172                          [(0, 0,  2, 2,  0, 0)])
   172                          [(0, 0,  2, 2,  0, 0)])
   173 
   173 
   174         self.assertEqual(list(m3.merge_regions()),
   174         self.assertEqual(list(m3.merge_regions()),
   175                          [('a', 0, 2)])
   175                          [(b'a', 0, 2)])
   176 
   176 
   177         self.assertEqual(list(m3.merge_lines()),
   177         self.assertEqual(list(m3.merge_lines()),
   178                          ['aaa', 'bbb'])
   178                          [b'aaa', b'bbb'])
   179 
   179 
   180     def test_no_conflicts(self):
   180     def test_no_conflicts(self):
   181         """No conflicts because only one side changed"""
   181         """No conflicts because only one side changed"""
   182         m3 = Merge3(['aaa', 'bbb'],
   182         m3 = Merge3([b'aaa', b'bbb'],
   183                     ['aaa', '111', 'bbb'],
   183                     [b'aaa', b'111', b'bbb'],
   184                     ['aaa', 'bbb'])
   184                     [b'aaa', b'bbb'])
   185 
   185 
   186         self.assertEqual(m3.find_unconflicted(),
   186         self.assertEqual(m3.find_unconflicted(),
   187                          [(0, 1), (1, 2)])
   187                          [(0, 1), (1, 2)])
   188 
   188 
   189         self.assertEqual(list(m3.find_sync_regions()),
   189         self.assertEqual(list(m3.find_sync_regions()),
   190                          [(0, 1,  0, 1,  0, 1),
   190                          [(0, 1,  0, 1,  0, 1),
   191                           (1, 2,  2, 3,  1, 2),
   191                           (1, 2,  2, 3,  1, 2),
   192                           (2, 2,  3, 3,  2, 2)])
   192                           (2, 2,  3, 3,  2, 2)])
   193 
   193 
   194         self.assertEqual(list(m3.merge_regions()),
   194         self.assertEqual(list(m3.merge_regions()),
   195                          [('unchanged', 0, 1),
   195                          [(b'unchanged', 0, 1),
   196                           ('a', 1, 2),
   196                           (b'a', 1, 2),
   197                           ('unchanged', 1, 2)])
   197                           (b'unchanged', 1, 2)])
   198 
   198 
   199     def test_append_a(self):
   199     def test_append_a(self):
   200         m3 = Merge3(['aaa\n', 'bbb\n'],
   200         m3 = Merge3([b'aaa\n', b'bbb\n'],
   201                     ['aaa\n', 'bbb\n', '222\n'],
   201                     [b'aaa\n', b'bbb\n', b'222\n'],
   202                     ['aaa\n', 'bbb\n'])
   202                     [b'aaa\n', b'bbb\n'])
   203 
   203 
   204         self.assertEqual(''.join(m3.merge_lines()),
   204         self.assertEqual(b''.join(m3.merge_lines()),
   205                          'aaa\nbbb\n222\n')
   205                          b'aaa\nbbb\n222\n')
   206 
   206 
   207     def test_append_b(self):
   207     def test_append_b(self):
   208         m3 = Merge3(['aaa\n', 'bbb\n'],
   208         m3 = Merge3([b'aaa\n', b'bbb\n'],
   209                     ['aaa\n', 'bbb\n'],
   209                     [b'aaa\n', b'bbb\n'],
   210                     ['aaa\n', 'bbb\n', '222\n'])
   210                     [b'aaa\n', b'bbb\n', b'222\n'])
   211 
   211 
   212         self.assertEqual(''.join(m3.merge_lines()),
   212         self.assertEqual(b''.join(m3.merge_lines()),
   213                          'aaa\nbbb\n222\n')
   213                          b'aaa\nbbb\n222\n')
   214 
   214 
   215     def test_append_agreement(self):
   215     def test_append_agreement(self):
   216         m3 = Merge3(['aaa\n', 'bbb\n'],
   216         m3 = Merge3([b'aaa\n', b'bbb\n'],
   217                     ['aaa\n', 'bbb\n', '222\n'],
   217                     [b'aaa\n', b'bbb\n', b'222\n'],
   218                     ['aaa\n', 'bbb\n', '222\n'])
   218                     [b'aaa\n', b'bbb\n', b'222\n'])
   219 
   219 
   220         self.assertEqual(''.join(m3.merge_lines()),
   220         self.assertEqual(b''.join(m3.merge_lines()),
   221                          'aaa\nbbb\n222\n')
   221                          b'aaa\nbbb\n222\n')
   222 
   222 
   223     def test_append_clash(self):
   223     def test_append_clash(self):
   224         m3 = Merge3(['aaa\n', 'bbb\n'],
   224         m3 = Merge3([b'aaa\n', b'bbb\n'],
   225                     ['aaa\n', 'bbb\n', '222\n'],
   225                     [b'aaa\n', b'bbb\n', b'222\n'],
   226                     ['aaa\n', 'bbb\n', '333\n'])
   226                     [b'aaa\n', b'bbb\n', b'333\n'])
   227 
   227 
   228         ml = m3.merge_lines(name_a='a',
   228         ml = m3.merge_lines(name_a=b'a',
   229                             name_b='b',
   229                             name_b=b'b',
   230                             start_marker='<<',
   230                             start_marker=b'<<',
   231                             mid_marker='--',
   231                             mid_marker=b'--',
   232                             end_marker='>>')
   232                             end_marker=b'>>')
   233         self.assertEqual(''.join(ml),
   233         self.assertEqual(b''.join(ml),
   234                          'aaa\n'
   234                          b'aaa\n'
   235                          'bbb\n'
   235                          b'bbb\n'
   236                          '<< a\n'
   236                          b'<< a\n'
   237                          '222\n'
   237                          b'222\n'
   238                          '--\n'
   238                          b'--\n'
   239                          '333\n'
   239                          b'333\n'
   240                          '>> b\n'
   240                          b'>> b\n'
   241                          )
   241                          )
   242 
   242 
   243     def test_insert_agreement(self):
   243     def test_insert_agreement(self):
   244         m3 = Merge3(['aaa\n', 'bbb\n'],
   244         m3 = Merge3([b'aaa\n', b'bbb\n'],
   245                     ['aaa\n', '222\n', 'bbb\n'],
   245                     [b'aaa\n', b'222\n', b'bbb\n'],
   246                     ['aaa\n', '222\n', 'bbb\n'])
   246                     [b'aaa\n', b'222\n', b'bbb\n'])
   247 
   247 
   248         ml = m3.merge_lines(name_a='a',
   248         ml = m3.merge_lines(name_a=b'a',
   249                             name_b='b',
   249                             name_b=b'b',
   250                             start_marker='<<',
   250                             start_marker=b'<<',
   251                             mid_marker='--',
   251                             mid_marker=b'--',
   252                             end_marker='>>')
   252                             end_marker=b'>>')
   253         self.assertEqual(''.join(ml), 'aaa\n222\nbbb\n')
   253         self.assertEqual(b''.join(ml), b'aaa\n222\nbbb\n')
   254 
   254 
   255 
   255 
   256     def test_insert_clash(self):
   256     def test_insert_clash(self):
   257         """Both try to insert lines in the same place."""
   257         """Both try to insert lines in the same place."""
   258         m3 = Merge3(['aaa\n', 'bbb\n'],
   258         m3 = Merge3([b'aaa\n', b'bbb\n'],
   259                     ['aaa\n', '111\n', 'bbb\n'],
   259                     [b'aaa\n', b'111\n', b'bbb\n'],
   260                     ['aaa\n', '222\n', 'bbb\n'])
   260                     [b'aaa\n', b'222\n', b'bbb\n'])
   261 
   261 
   262         self.assertEqual(m3.find_unconflicted(),
   262         self.assertEqual(m3.find_unconflicted(),
   263                          [(0, 1), (1, 2)])
   263                          [(0, 1), (1, 2)])
   264 
   264 
   265         self.assertEqual(list(m3.find_sync_regions()),
   265         self.assertEqual(list(m3.find_sync_regions()),
   266                          [(0, 1,  0, 1,  0, 1),
   266                          [(0, 1,  0, 1,  0, 1),
   267                           (1, 2,  2, 3,  2, 3),
   267                           (1, 2,  2, 3,  2, 3),
   268                           (2, 2,  3, 3,  3, 3)])
   268                           (2, 2,  3, 3,  3, 3)])
   269 
   269 
   270         self.assertEqual(list(m3.merge_regions()),
   270         self.assertEqual(list(m3.merge_regions()),
   271                          [('unchanged', 0, 1),
   271                          [(b'unchanged', 0, 1),
   272                           ('conflict', 1, 1,  1, 2,  1, 2),
   272                           (b'conflict', 1, 1,  1, 2,  1, 2),
   273                           ('unchanged', 1, 2)])
   273                           (b'unchanged', 1, 2)])
   274 
   274 
   275         self.assertEqual(list(m3.merge_groups()),
   275         self.assertEqual(list(m3.merge_groups()),
   276                          [('unchanged', ['aaa\n']),
   276                          [(b'unchanged', [b'aaa\n']),
   277                           ('conflict', [], ['111\n'], ['222\n']),
   277                           (b'conflict', [], [b'111\n'], [b'222\n']),
   278                           ('unchanged', ['bbb\n']),
   278                           (b'unchanged', [b'bbb\n']),
   279                           ])
   279                           ])
   280 
   280 
   281         ml = m3.merge_lines(name_a='a',
   281         ml = m3.merge_lines(name_a=b'a',
   282                             name_b='b',
   282                             name_b=b'b',
   283                             start_marker='<<',
   283                             start_marker=b'<<',
   284                             mid_marker='--',
   284                             mid_marker=b'--',
   285                             end_marker='>>')
   285                             end_marker=b'>>')
   286         self.assertEqual(''.join(ml),
   286         self.assertEqual(b''.join(ml),
   287 '''aaa
   287 b'''aaa
   288 << a
   288 << a
   289 111
   289 111
   290 --
   290 --
   291 222
   291 222
   292 >> b
   292 >> b
   293 bbb
   293 bbb
   294 ''')
   294 ''')
   295 
   295 
   296     def test_replace_clash(self):
   296     def test_replace_clash(self):
   297         """Both try to insert lines in the same place."""
   297         """Both try to insert lines in the same place."""
   298         m3 = Merge3(['aaa', '000', 'bbb'],
   298         m3 = Merge3([b'aaa', b'000', b'bbb'],
   299                     ['aaa', '111', 'bbb'],
   299                     [b'aaa', b'111', b'bbb'],
   300                     ['aaa', '222', 'bbb'])
   300                     [b'aaa', b'222', b'bbb'])
   301 
   301 
   302         self.assertEqual(m3.find_unconflicted(),
   302         self.assertEqual(m3.find_unconflicted(),
   303                          [(0, 1), (2, 3)])
   303                          [(0, 1), (2, 3)])
   304 
   304 
   305         self.assertEqual(list(m3.find_sync_regions()),
   305         self.assertEqual(list(m3.find_sync_regions()),
   306                          [(0, 1,  0, 1,  0, 1),
   306                          [(0, 1,  0, 1,  0, 1),
   307                           (2, 3,  2, 3,  2, 3),
   307                            (2, 3,  2, 3,  2, 3),
   308                           (3, 3,  3, 3,  3, 3)])
   308                            (3, 3,  3, 3,  3, 3)])
   309 
   309 
   310     def test_replace_multi(self):
   310     def test_replace_multi(self):
   311         """Replacement with regions of different size."""
   311         """Replacement with regions of different size."""
   312         m3 = Merge3(['aaa', '000', '000', 'bbb'],
   312         m3 = Merge3([b'aaa', b'000', b'000', b'bbb'],
   313                     ['aaa', '111', '111', '111', 'bbb'],
   313                     [b'aaa', b'111', b'111', b'111', b'bbb'],
   314                     ['aaa', '222', '222', '222', '222', 'bbb'])
   314                     [b'aaa', b'222', b'222', b'222', b'222', b'bbb'])
   315 
   315 
   316         self.assertEqual(m3.find_unconflicted(),
   316         self.assertEqual(m3.find_unconflicted(),
   317                          [(0, 1), (3, 4)])
   317                          [(0, 1), (3, 4)])
   318 
   318 
   319 
   319 
   323                           (4, 4,  5, 5,  6, 6)])
   323                           (4, 4,  5, 5,  6, 6)])
   324 
   324 
   325     def test_merge_poem(self):
   325     def test_merge_poem(self):
   326         """Test case from diff3 manual"""
   326         """Test case from diff3 manual"""
   327         m3 = Merge3(TZU, LAO, TAO)
   327         m3 = Merge3(TZU, LAO, TAO)
   328         ml = list(m3.merge_lines('LAO', 'TAO'))
   328         ml = list(m3.merge_lines(b'LAO', b'TAO'))
   329         self.log('merge result:')
   329         self.log(b'merge result:')
   330         self.log(''.join(ml))
   330         self.log(b''.join(ml))
   331         self.assertEqual(ml, MERGED_RESULT)
   331         self.assertEqual(ml, MERGED_RESULT)
   332 
   332 
   333     def test_binary(self):
   333     def test_binary(self):
   334         with self.assertRaises(error.Abort):
   334         with self.assertRaises(error.Abort):
   335             Merge3(['\x00'], ['a'], ['b'])
   335             Merge3([b'\x00'], [b'a'], [b'b'])
   336 
   336 
   337     def test_dos_text(self):
   337     def test_dos_text(self):
   338         base_text = 'a\r\n'
   338         base_text = b'a\r\n'
   339         this_text = 'b\r\n'
   339         this_text = b'b\r\n'
   340         other_text = 'c\r\n'
   340         other_text = b'c\r\n'
   341         m3 = Merge3(base_text.splitlines(True), other_text.splitlines(True),
   341         m3 = Merge3(base_text.splitlines(True), other_text.splitlines(True),
   342                     this_text.splitlines(True))
   342                     this_text.splitlines(True))
   343         m_lines = m3.merge_lines('OTHER', 'THIS')
   343         m_lines = m3.merge_lines(b'OTHER', b'THIS')
   344         self.assertEqual('<<<<<<< OTHER\r\nc\r\n=======\r\nb\r\n'
   344         self.assertEqual(b'<<<<<<< OTHER\r\nc\r\n=======\r\nb\r\n'
   345                          '>>>>>>> THIS\r\n'.splitlines(True), list(m_lines))
   345                          b'>>>>>>> THIS\r\n'.splitlines(True), list(m_lines))
   346 
   346 
   347     def test_mac_text(self):
   347     def test_mac_text(self):
   348         base_text = 'a\r'
   348         base_text = b'a\r'
   349         this_text = 'b\r'
   349         this_text = b'b\r'
   350         other_text = 'c\r'
   350         other_text = b'c\r'
   351         m3 = Merge3(base_text.splitlines(True), other_text.splitlines(True),
   351         m3 = Merge3(base_text.splitlines(True), other_text.splitlines(True),
   352                     this_text.splitlines(True))
   352                     this_text.splitlines(True))
   353         m_lines = m3.merge_lines('OTHER', 'THIS')
   353         m_lines = m3.merge_lines(b'OTHER', b'THIS')
   354         self.assertEqual('<<<<<<< OTHER\rc\r=======\rb\r'
   354         self.assertEqual(b'<<<<<<< OTHER\rc\r=======\rb\r'
   355                          '>>>>>>> THIS\r'.splitlines(True), list(m_lines))
   355                          b'>>>>>>> THIS\r'.splitlines(True), list(m_lines))
   356 
   356 
   357 if __name__ == '__main__':
   357 if __name__ == '__main__':
   358     # hide the timer
   358     # hide the timer
   359     import time
   359     import time
   360     orig = time.time
   360     orig = time.time