tests/test-bdiff.py
branchstable
changeset 43306 59338f956109
parent 43076 2372284d9457
child 48875 6000f5b25c9b
equal deleted inserted replaced
43029:c5dc122fdc2b 43306:59338f956109
     1 from __future__ import absolute_import, print_function
     1 from __future__ import absolute_import, print_function
     2 import collections
     2 import collections
     3 import struct
     3 import struct
     4 import unittest
     4 import unittest
     5 
     5 
     6 from mercurial import (
     6 from mercurial import mdiff
     7     mdiff,
       
     8 )
       
     9 
     7 
    10 class diffreplace(
     8 
    11     collections.namedtuple('diffreplace', 'start end from_ to')):
     9 class diffreplace(collections.namedtuple('diffreplace', 'start end from_ to')):
    12     def __repr__(self):
    10     def __repr__(self):
    13         return 'diffreplace(%r, %r, %r, %r)' % self
    11         return 'diffreplace(%r, %r, %r, %r)' % self
    14 
    12 
       
    13 
    15 class BdiffTests(unittest.TestCase):
    14 class BdiffTests(unittest.TestCase):
    16 
       
    17     def assert_bdiff_applies(self, a, b):
    15     def assert_bdiff_applies(self, a, b):
    18         d = mdiff.textdiff(a, b)
    16         d = mdiff.textdiff(a, b)
    19         c = a
    17         c = a
    20         if d:
    18         if d:
    21             c = mdiff.patches(a, [d])
    19             c = mdiff.patches(a, [d])
    22         self.assertEqual(
    20         self.assertEqual(
    23             c, b, ("bad diff+patch result from\n  %r to\n  "
    21             c,
    24                    "%r: \nbdiff: %r\npatched: %r" % (a, b, d, c[:200])))
    22             b,
       
    23             (
       
    24                 "bad diff+patch result from\n  %r to\n  "
       
    25                 "%r: \nbdiff: %r\npatched: %r" % (a, b, d, c[:200])
       
    26             ),
       
    27         )
    25 
    28 
    26     def assert_bdiff(self, a, b):
    29     def assert_bdiff(self, a, b):
    27         self.assert_bdiff_applies(a, b)
    30         self.assert_bdiff_applies(a, b)
    28         self.assert_bdiff_applies(b, a)
    31         self.assert_bdiff_applies(b, a)
    29 
    32 
    56         bin = mdiff.textdiff(a, b)
    59         bin = mdiff.textdiff(a, b)
    57         pos = 0
    60         pos = 0
    58         q = 0
    61         q = 0
    59         actions = []
    62         actions = []
    60         while pos < len(bin):
    63         while pos < len(bin):
    61             p1, p2, l = struct.unpack(">lll", bin[pos:pos + 12])
    64             p1, p2, l = struct.unpack(">lll", bin[pos : pos + 12])
    62             pos += 12
    65             pos += 12
    63             if p1:
    66             if p1:
    64                 actions.append(a[q:p1])
    67                 actions.append(a[q:p1])
    65             actions.append(diffreplace(p1, p2, a[p1:p2], bin[pos:pos + l]))
    68             actions.append(diffreplace(p1, p2, a[p1:p2], bin[pos : pos + l]))
    66             pos += l
    69             pos += l
    67             q = p2
    70             q = p2
    68         if q < len(a):
    71         if q < len(a):
    69             actions.append(a[q:])
    72             actions.append(a[q:])
    70         return actions
    73         return actions
    71 
    74 
    72     def test_issue1295(self):
    75     def test_issue1295(self):
    73         cases = [
    76         cases = [
    74             (b"x\n\nx\n\nx\n\nx\n\nz\n", b"x\n\nx\n\ny\n\nx\n\nx\n\nz\n",
    77             (
    75              [b'x\n\nx\n\n',
    78                 b"x\n\nx\n\nx\n\nx\n\nz\n",
    76               diffreplace(6, 6, b'', b'y\n\n'),
    79                 b"x\n\nx\n\ny\n\nx\n\nx\n\nz\n",
    77               b'x\n\nx\n\nz\n']),
    80                 [
    78             (b"x\n\nx\n\nx\n\nx\n\nz\n", b"x\n\nx\n\ny\n\nx\n\ny\n\nx\n\nz\n",
    81                     b'x\n\nx\n\n',
    79              [b'x\n\nx\n\n',
    82                     diffreplace(6, 6, b'', b'y\n\n'),
    80               diffreplace(6, 6, b'', b'y\n\n'),
    83                     b'x\n\nx\n\nz\n',
    81               b'x\n\n',
    84                 ],
    82               diffreplace(9, 9, b'', b'y\n\n'),
    85             ),
    83               b'x\n\nz\n']),
    86             (
       
    87                 b"x\n\nx\n\nx\n\nx\n\nz\n",
       
    88                 b"x\n\nx\n\ny\n\nx\n\ny\n\nx\n\nz\n",
       
    89                 [
       
    90                     b'x\n\nx\n\n',
       
    91                     diffreplace(6, 6, b'', b'y\n\n'),
       
    92                     b'x\n\n',
       
    93                     diffreplace(9, 9, b'', b'y\n\n'),
       
    94                     b'x\n\nz\n',
       
    95                 ],
       
    96             ),
    84         ]
    97         ]
    85         for old, new, want in cases:
    98         for old, new, want in cases:
    86             self.assertEqual(self.showdiff(old, new), want)
    99             self.assertEqual(self.showdiff(old, new), want)
    87 
   100 
    88     def test_issue1295_varies_on_pure(self):
   101     def test_issue1295_varies_on_pure(self):
    89             # we should pick up abbbc. rather than bc.de as the longest match
   102         # we should pick up abbbc. rather than bc.de as the longest match
    90         got = self.showdiff(b"a\nb\nb\nb\nc\n.\nd\ne\n.\nf\n",
   103         got = self.showdiff(
    91                             b"a\nb\nb\na\nb\nb\nb\nc\n.\nb\nc\n.\nd\ne\nf\n")
   104             b"a\nb\nb\nb\nc\n.\nd\ne\n.\nf\n",
    92         want_c = [b'a\nb\nb\n',
   105             b"a\nb\nb\na\nb\nb\nb\nc\n.\nb\nc\n.\nd\ne\nf\n",
    93                   diffreplace(6, 6, b'', b'a\nb\nb\nb\nc\n.\n'),
   106         )
    94                   b'b\nc\n.\nd\ne\n',
   107         want_c = [
    95                   diffreplace(16, 18, b'.\n', b''),
   108             b'a\nb\nb\n',
    96                   b'f\n']
   109             diffreplace(6, 6, b'', b'a\nb\nb\nb\nc\n.\n'),
    97         want_pure = [diffreplace(0, 0, b'', b'a\nb\nb\n'),
   110             b'b\nc\n.\nd\ne\n',
    98                      b'a\nb\nb\nb\nc\n.\n',
   111             diffreplace(16, 18, b'.\n', b''),
    99                      diffreplace(12, 12, b'', b'b\nc\n.\n'),
   112             b'f\n',
   100                      b'd\ne\n',
   113         ]
   101                      diffreplace(16, 18, b'.\n', b''), b'f\n']
   114         want_pure = [
   102         self.assertTrue(got in (want_c, want_pure),
   115             diffreplace(0, 0, b'', b'a\nb\nb\n'),
   103                         'got: %r, wanted either %r or %r' % (
   116             b'a\nb\nb\nb\nc\n.\n',
   104                             got, want_c, want_pure))
   117             diffreplace(12, 12, b'', b'b\nc\n.\n'),
       
   118             b'd\ne\n',
       
   119             diffreplace(16, 18, b'.\n', b''),
       
   120             b'f\n',
       
   121         ]
       
   122         self.assertTrue(
       
   123             got in (want_c, want_pure),
       
   124             'got: %r, wanted either %r or %r' % (got, want_c, want_pure),
       
   125         )
   105 
   126 
   106     def test_fixws(self):
   127     def test_fixws(self):
   107         cases = [
   128         cases = [
   108             (b" \ta\r b\t\n", b"ab\n", 1),
   129             (b" \ta\r b\t\n", b"ab\n", 1),
   109             (b" \ta\r b\t\n", b" a b\n", 0),
   130             (b" \ta\r b\t\n", b" a b\n", 0),
   111             (b"", b"", 0),
   132             (b"", b"", 0),
   112         ]
   133         ]
   113         for a, b, allws in cases:
   134         for a, b, allws in cases:
   114             c = mdiff.fixws(a, allws)
   135             c = mdiff.fixws(a, allws)
   115             self.assertEqual(
   136             self.assertEqual(
   116                 c, b, 'fixws(%r) want %r got %r (allws=%r)' % (a, b, c, allws))
   137                 c, b, 'fixws(%r) want %r got %r (allws=%r)' % (a, b, c, allws)
       
   138             )
   117 
   139 
   118     def test_nice_diff_for_trivial_change(self):
   140     def test_nice_diff_for_trivial_change(self):
   119         self.assertEqual(self.showdiff(
   141         self.assertEqual(
   120             b''.join(b'<%d\n-\n' % i for i in range(5)),
   142             self.showdiff(
   121             b''.join(b'>%d\n-\n' % i for i in range(5))),
   143                 b''.join(b'<%d\n-\n' % i for i in range(5)),
   122                          [diffreplace(0, 3, b'<0\n', b'>0\n'),
   144                 b''.join(b'>%d\n-\n' % i for i in range(5)),
   123                           b'-\n',
   145             ),
   124                           diffreplace(5, 8, b'<1\n', b'>1\n'),
   146             [
   125                           b'-\n',
   147                 diffreplace(0, 3, b'<0\n', b'>0\n'),
   126                           diffreplace(10, 13, b'<2\n', b'>2\n'),
   148                 b'-\n',
   127                           b'-\n',
   149                 diffreplace(5, 8, b'<1\n', b'>1\n'),
   128                           diffreplace(15, 18, b'<3\n', b'>3\n'),
   150                 b'-\n',
   129                           b'-\n',
   151                 diffreplace(10, 13, b'<2\n', b'>2\n'),
   130                           diffreplace(20, 23, b'<4\n', b'>4\n'),
   152                 b'-\n',
   131                           b'-\n'])
   153                 diffreplace(15, 18, b'<3\n', b'>3\n'),
       
   154                 b'-\n',
       
   155                 diffreplace(20, 23, b'<4\n', b'>4\n'),
       
   156                 b'-\n',
       
   157             ],
       
   158         )
   132 
   159 
   133     def test_prefer_appending(self):
   160     def test_prefer_appending(self):
   134         # 1 line to 3 lines
   161         # 1 line to 3 lines
   135         self.assertEqual(self.showdiff(b'a\n', b'a\n' * 3),
   162         self.assertEqual(
   136                          [b'a\n', diffreplace(2, 2, b'', b'a\na\n')])
   163             self.showdiff(b'a\n', b'a\n' * 3),
       
   164             [b'a\n', diffreplace(2, 2, b'', b'a\na\n')],
       
   165         )
   137         # 1 line to 5 lines
   166         # 1 line to 5 lines
   138         self.assertEqual(self.showdiff(b'a\n', b'a\n' * 5),
   167         self.assertEqual(
   139                          [b'a\n', diffreplace(2, 2, b'', b'a\na\na\na\n')])
   168             self.showdiff(b'a\n', b'a\n' * 5),
       
   169             [b'a\n', diffreplace(2, 2, b'', b'a\na\na\na\n')],
       
   170         )
   140 
   171 
   141     def test_prefer_removing_trailing(self):
   172     def test_prefer_removing_trailing(self):
   142         # 3 lines to 1 line
   173         # 3 lines to 1 line
   143         self.assertEqual(self.showdiff(b'a\n' * 3, b'a\n'),
   174         self.assertEqual(
   144                          [b'a\n', diffreplace(2, 6, b'a\na\n', b'')])
   175             self.showdiff(b'a\n' * 3, b'a\n'),
       
   176             [b'a\n', diffreplace(2, 6, b'a\na\n', b'')],
       
   177         )
   145         # 5 lines to 1 line
   178         # 5 lines to 1 line
   146         self.assertEqual(self.showdiff(b'a\n' * 5, b'a\n'),
   179         self.assertEqual(
   147                          [b'a\n', diffreplace(2, 10, b'a\na\na\na\n', b'')])
   180             self.showdiff(b'a\n' * 5, b'a\n'),
       
   181             [b'a\n', diffreplace(2, 10, b'a\na\na\na\n', b'')],
       
   182         )
       
   183 
   148 
   184 
   149 if __name__ == '__main__':
   185 if __name__ == '__main__':
   150     import silenttestrunner
   186     import silenttestrunner
       
   187 
   151     silenttestrunner.main(__name__)
   188     silenttestrunner.main(__name__)