~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/selftest/testdiff.py

  • Committer: John Arbash Meinel
  • Date: 2005-11-08 18:36:26 UTC
  • mto: This revision was merged to the branch mainline in revision 1727.
  • Revision ID: john@arbash-meinel.com-20051108183626-71f8414338043265
Updating unified_diff to take a factory, using the new diff algorithm in the code.

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
    output.seek(0, 0)
8
8
    return output.readlines()
9
9
 
10
 
def check_patch(lines):
11
 
    assert len(lines) > 1, \
12
 
        "Not enough lines for a file header for patch:\n%s" % "".join(lines)
13
 
    assert lines[0].startswith ('---'), \
14
 
        'No orig line for patch:\n%s' % "".join(lines)
15
 
    assert lines[1].startswith ('+++'), \
16
 
        'No mod line for patch:\n%s' % "".join(lines)
17
 
    assert len(lines) > 2, \
18
 
        "No hunks for patch:\n%s" % "".join(lines)
19
 
    assert lines[2].startswith('@@'),\
20
 
        "No hunk header for patch:\n%s" % "".join(lines)
21
 
    assert '@@' in lines[2][2:], \
22
 
        "Unterminated hunk header for patch:\n%s" % "".join(lines)
23
 
 
24
10
class TestDiff(TestCase):
25
11
    def test_add_nl(self):
26
12
        """diff generates a valid diff for patches that add a newline"""
27
13
        lines = udiff_lines(['boo'], ['boo\n'])
28
 
        check_patch(lines)
29
 
        assert lines[4] == '\\ No newline at end of file\n', \
30
 
            "expected no-nl, got %r" % lines[4]
 
14
        self.check_patch(lines)
 
15
        self.assertEquals(lines[4], '\\ No newline at end of file\n')
 
16
            ## "expected no-nl, got %r" % lines[4]
31
17
 
32
18
    def test_add_nl_2(self):
33
19
        """diff generates a valid diff for patches that change last line and
34
20
        add a newline.
35
21
        """
36
22
        lines = udiff_lines(['boo'], ['goo\n'])
37
 
        check_patch(lines)
38
 
        assert lines[4] == '\\ No newline at end of file\n', \
39
 
            "expected no-nl, got %r" % lines[4]
 
23
        self.check_patch(lines)
 
24
        self.assertEquals(lines[4], '\\ No newline at end of file\n')
 
25
            ## "expected no-nl, got %r" % lines[4]
40
26
 
41
27
    def test_remove_nl(self):
42
28
        """diff generates a valid diff for patches that change last line and
43
29
        add a newline.
44
30
        """
45
31
        lines = udiff_lines(['boo\n'], ['boo'])
46
 
        check_patch(lines)
47
 
        assert lines[5] == '\\ No newline at end of file\n', \
48
 
            "expected no-nl, got %r" % lines[5]
 
32
        self.check_patch(lines)
 
33
        self.assertEquals(lines[5], '\\ No newline at end of file\n')
 
34
            ## "expected no-nl, got %r" % lines[5]
 
35
 
 
36
    def check_patch(self, lines):
 
37
        self.assert_(len(lines) > 1)
 
38
            ## "Not enough lines for a file header for patch:\n%s" % "".join(lines)
 
39
        self.assert_(lines[0].startswith ('---'))
 
40
            ## 'No orig line for patch:\n%s' % "".join(lines)
 
41
        self.assert_(lines[1].startswith ('+++'))
 
42
            ## 'No mod line for patch:\n%s' % "".join(lines)
 
43
        self.assert_(len(lines) > 2)
 
44
            ## "No hunks for patch:\n%s" % "".join(lines)
 
45
        self.assert_(lines[2].startswith('@@'))
 
46
            ## "No hunk header for patch:\n%s" % "".join(lines)
 
47
        self.assert_('@@' in lines[2][2:])
 
48
            ## "Unterminated hunk header for patch:\n%s" % "".join(lines)
 
49
 
 
50
class TestCDVDiffLib(TestCase):
 
51
 
 
52
    def test_matching_blocks(self):
 
53
        from bzrlib.cdvdifflib import SequenceMatcher
 
54
 
 
55
        def chk_blocks(a, b, matching):
 
56
            # difflib always adds a signature of the total
 
57
            # length, with no matching entries at the end
 
58
            matching = matching + [(len(a), len(b), 0)]
 
59
            s = SequenceMatcher(None, a, b)
 
60
            self.assertEquals(matching, s.get_matching_blocks())
 
61
 
 
62
        # Some basic matching tests
 
63
        chk_blocks('', '', [])
 
64
        chk_blocks([], [], [])
 
65
        chk_blocks('abcd', 'abcd', [(0, 0, 4)])
 
66
        chk_blocks('abcd', 'abce', [(0, 0, 3)])
 
67
        chk_blocks('eabc', 'abce', [(1, 0, 3)])
 
68
        chk_blocks('eabce', 'abce', [(1, 0, 4)])
 
69
        chk_blocks('abcde', 'abXde', [(0, 0, 2), (3, 3, 2)])
 
70
        chk_blocks('abcde', 'abXYZde', [(0, 0, 2), (3, 5, 2)])
 
71
        chk_blocks('abde', 'abXYZde', [(0, 0, 2), (2, 5, 2)])
 
72
        # This may check too much, but it checks to see that 
 
73
        # a copied block stays attached to the previous section,
 
74
        # not the later one.
 
75
        # difflib would tend to grab the trailing longest match
 
76
        # which would make the diff not look right
 
77
        chk_blocks('abcdefghijklmnop', 'abcdefxydefghijklmnop', [(0, 0, 6), (6, 11, 10)])
 
78
 
 
79
        # make sure it supports passing in lists
 
80
        chk_blocks(
 
81
                [ 'hello there\n'
 
82
                , 'world\n'
 
83
                , 'how are you today?\n'],
 
84
                [ 'hello there\n'
 
85
                , 'how are you today?\n'],
 
86
                [(0, 0, 1), (2, 1, 1)])
 
87
 
 
88
 
 
89
    def test_opcodes(self):
 
90
        from bzrlib.cdvdifflib import SequenceMatcher
 
91
 
 
92
        def chk_ops(a, b, codes):
 
93
            s = SequenceMatcher(None, a, b)
 
94
            self.assertEquals(codes, s.get_opcodes())
 
95
 
 
96
        chk_ops('', '', [])
 
97
        chk_ops([], [], [])
 
98
        chk_ops('abcd', 'abcd', [('equal', 0, 4, 0, 4)])
 
99
        chk_ops('abcd', 'abce', [ ('equal', 0, 3, 0, 3)
 
100
                                , ('replace', 3, 4, 3, 4)
 
101
                                ])
 
102
        chk_ops('eabc', 'abce', [ ('delete', 0, 1, 0, 0)
 
103
                                , ('equal', 1, 4, 0, 3)
 
104
                                , ('insert', 4, 4, 3, 4)
 
105
                                ])
 
106
        chk_ops('eabce', 'abce', [ ('delete', 0, 1, 0, 0)
 
107
                                 , ('equal', 1, 5, 0, 4)
 
108
                                 ])
 
109
        chk_ops('abcde', 'abXde', [ ('equal', 0, 2, 0, 2)
 
110
                                  , ('replace', 2, 3, 2, 3)
 
111
                                  , ('equal', 3, 5, 3, 5)
 
112
                                  ])
 
113
        chk_ops('abcde', 'abXYZde', [ ('equal', 0, 2, 0, 2)
 
114
                                    , ('replace', 2, 3, 2, 5)
 
115
                                    , ('equal', 3, 5, 5, 7)
 
116
                                    ])
 
117
        chk_ops('abde', 'abXYZde', [ ('equal', 0, 2, 0, 2)
 
118
                                   , ('insert', 2, 2, 2, 5)
 
119
                                   , ('equal', 2, 4, 5, 7)
 
120
                                   ])
 
121
        chk_ops('abcdefghijklmnop', 'abcdefxydefghijklmnop',
 
122
                [ ('equal', 0, 6, 0, 6)
 
123
                , ('insert', 6, 6, 6, 11)
 
124
                , ('equal', 6, 16, 11, 21)
 
125
                ])
 
126
 
 
127
        chk_ops(
 
128
                [ 'hello there\n'
 
129
                , 'world\n'
 
130
                , 'how are you today?\n'],
 
131
                [ 'hello there\n'
 
132
                , 'how are you today?\n'],
 
133
                [ ('equal', 0, 1, 0, 1)
 
134
                , ('delete', 1, 2, 1, 1)
 
135
                , ('equal', 2, 3, 1, 2)
 
136
                ])