~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_patches.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2008-04-07 07:52:50 UTC
  • mfrom: (3340.1.1 208418-1.4)
  • Revision ID: pqm@pqm.ubuntu.com-20080407075250-phs53xnslo8boaeo
Return the correct knit serialisation method in _StreamAccess.
        (Andrew Bennetts, Martin Pool, Robert Collins)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2004 - 2006 Aaron Bentley, Canonical Ltd
 
2
# <aaron.bentley@utoronto.ca>
 
3
#
 
4
# This program is free software; you can redistribute it and/or modify
 
5
# it under the terms of the GNU General Public License as published by
 
6
# the Free Software Foundation; either version 2 of the License, or
 
7
# (at your option) any later version.
 
8
#
 
9
# This program is distributed in the hope that it will be useful,
 
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
# GNU General Public License for more details.
 
13
#
 
14
# You should have received a copy of the GNU General Public License
 
15
# along with this program; if not, write to the Free Software
 
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
17
 
 
18
 
 
19
import unittest
 
20
import os.path
 
21
 
 
22
from bzrlib.iterablefile import IterableFile
 
23
from bzrlib.patches import (MalformedLine, 
 
24
                            MalformedHunkHeader, 
 
25
                            MalformedPatchHeader, 
 
26
                            ContextLine, 
 
27
                            InsertLine,
 
28
                            RemoveLine, 
 
29
                            difference_index, 
 
30
                            get_patch_names,
 
31
                            hunk_from_header, 
 
32
                            iter_patched, 
 
33
                            parse_line,
 
34
                            parse_patch,
 
35
                            parse_patches)
 
36
 
 
37
 
 
38
class PatchesTester(unittest.TestCase):
 
39
    def datafile(self, filename):
 
40
        data_path = os.path.join(os.path.dirname(__file__), 
 
41
                                 "test_patches_data", filename)
 
42
        return file(data_path, "rb")
 
43
 
 
44
    def testValidPatchHeader(self):
 
45
        """Parse a valid patch header"""
 
46
        lines = "--- orig/commands.py\n+++ mod/dommands.py\n".split('\n')
 
47
        (orig, mod) = get_patch_names(lines.__iter__())
 
48
        assert(orig == "orig/commands.py")
 
49
        assert(mod == "mod/dommands.py")
 
50
 
 
51
    def testInvalidPatchHeader(self):
 
52
        """Parse an invalid patch header"""
 
53
        lines = "-- orig/commands.py\n+++ mod/dommands.py".split('\n')
 
54
        self.assertRaises(MalformedPatchHeader, get_patch_names,
 
55
                          lines.__iter__())
 
56
 
 
57
    def testValidHunkHeader(self):
 
58
        """Parse a valid hunk header"""
 
59
        header = "@@ -34,11 +50,6 @@\n"
 
60
        hunk = hunk_from_header(header);
 
61
        assert (hunk.orig_pos == 34)
 
62
        assert (hunk.orig_range == 11)
 
63
        assert (hunk.mod_pos == 50)
 
64
        assert (hunk.mod_range == 6)
 
65
        assert (str(hunk) == header)
 
66
 
 
67
    def testValidHunkHeader2(self):
 
68
        """Parse a tricky, valid hunk header"""
 
69
        header = "@@ -1 +0,0 @@\n"
 
70
        hunk = hunk_from_header(header);
 
71
        assert (hunk.orig_pos == 1)
 
72
        assert (hunk.orig_range == 1)
 
73
        assert (hunk.mod_pos == 0)
 
74
        assert (hunk.mod_range == 0)
 
75
        assert (str(hunk) == header)
 
76
 
 
77
    def testPDiff(self):
 
78
        """Parse a hunk header produced by diff -p"""
 
79
        header = "@@ -407,7 +292,7 @@ bzr 0.18rc1  2007-07-10\n"
 
80
        hunk = hunk_from_header(header)
 
81
        self.assertEqual('bzr 0.18rc1  2007-07-10', hunk.tail)
 
82
        self.assertEqual(header, str(hunk))
 
83
 
 
84
    def makeMalformed(self, header):
 
85
        self.assertRaises(MalformedHunkHeader, hunk_from_header, header)
 
86
 
 
87
    def testInvalidHeader(self):
 
88
        """Parse an invalid hunk header"""
 
89
        self.makeMalformed(" -34,11 +50,6 \n")
 
90
        self.makeMalformed("@@ +50,6 -34,11 @@\n")
 
91
        self.makeMalformed("@@ -34,11 +50,6 @@")
 
92
        self.makeMalformed("@@ -34.5,11 +50,6 @@\n")
 
93
        self.makeMalformed("@@-34,11 +50,6@@\n")
 
94
        self.makeMalformed("@@ 34,11 50,6 @@\n")
 
95
        self.makeMalformed("@@ -34,11 @@\n")
 
96
        self.makeMalformed("@@ -34,11 +50,6.5 @@\n")
 
97
        self.makeMalformed("@@ -34,11 +50,-6 @@\n")
 
98
 
 
99
    def lineThing(self,text, type):
 
100
        line = parse_line(text)
 
101
        assert(isinstance(line, type))
 
102
        assert(str(line)==text)
 
103
 
 
104
    def makeMalformedLine(self, text):
 
105
        self.assertRaises(MalformedLine, parse_line, text)
 
106
 
 
107
    def testValidLine(self):
 
108
        """Parse a valid hunk line"""
 
109
        self.lineThing(" hello\n", ContextLine)
 
110
        self.lineThing("+hello\n", InsertLine)
 
111
        self.lineThing("-hello\n", RemoveLine)
 
112
    
 
113
    def testMalformedLine(self):
 
114
        """Parse invalid valid hunk lines"""
 
115
        self.makeMalformedLine("hello\n")
 
116
    
 
117
    def compare_parsed(self, patchtext):
 
118
        lines = patchtext.splitlines(True)
 
119
        patch = parse_patch(lines.__iter__())
 
120
        pstr = str(patch)
 
121
        i = difference_index(patchtext, pstr)
 
122
        if i is not None:
 
123
            print "%i: \"%s\" != \"%s\"" % (i, patchtext[i], pstr[i])
 
124
        self.assertEqual (patchtext, str(patch))
 
125
 
 
126
    def testAll(self):
 
127
        """Test parsing a whole patch"""
 
128
        patchtext = self.datafile("patchtext.patch").read()
 
129
        self.compare_parsed(patchtext)
 
130
 
 
131
    def testInit(self):
 
132
        """Handle patches missing half the position, range tuple"""
 
133
        patchtext = \
 
134
"""--- orig/__vavg__.cl
 
135
+++ mod/__vavg__.cl
 
136
@@ -1 +1,2 @@
 
137
 __qbpsbezng__ = "erfgehpgherqgrkg ra"
 
138
+__qbp__ = Na nygreangr Nepu pbzznaqyvar vagresnpr
 
139
"""
 
140
        self.compare_parsed(patchtext)
 
141
 
 
142
    def testLineLookup(self):
 
143
        import sys
 
144
        """Make sure we can accurately look up mod line from orig"""
 
145
        patch = parse_patch(self.datafile("diff"))
 
146
        orig = list(self.datafile("orig"))
 
147
        mod = list(self.datafile("mod"))
 
148
        removals = []
 
149
        for i in range(len(orig)):
 
150
            mod_pos = patch.pos_in_mod(i)
 
151
            if mod_pos is None:
 
152
                removals.append(orig[i])
 
153
                continue
 
154
            assert(mod[mod_pos]==orig[i])
 
155
        rem_iter = removals.__iter__()
 
156
        for hunk in patch.hunks:
 
157
            for line in hunk.lines:
 
158
                if isinstance(line, RemoveLine):
 
159
                    next = rem_iter.next()
 
160
                    if line.contents != next:
 
161
                        sys.stdout.write(" orig:%spatch:%s" % (next,
 
162
                                         line.contents))
 
163
                    assert(line.contents == next)
 
164
        self.assertRaises(StopIteration, rem_iter.next)
 
165
 
 
166
    def testPatching(self):
 
167
        """Test a few patch files, and make sure they work."""
 
168
        files = [
 
169
            ('diff-2', 'orig-2', 'mod-2'),
 
170
            ('diff-3', 'orig-3', 'mod-3'),
 
171
            ('diff-4', 'orig-4', 'mod-4'),
 
172
            ('diff-5', 'orig-5', 'mod-5'),
 
173
            ('diff-6', 'orig-6', 'mod-6'),
 
174
        ]
 
175
        for diff, orig, mod in files:
 
176
            patch = self.datafile(diff)
 
177
            orig_lines = list(self.datafile(orig))
 
178
            mod_lines = list(self.datafile(mod))
 
179
 
 
180
            patched_file = IterableFile(iter_patched(orig_lines, patch))
 
181
            lines = []
 
182
            count = 0
 
183
            for patch_line in patched_file:
 
184
                self.assertEqual(patch_line, mod_lines[count])
 
185
                count += 1
 
186
            self.assertEqual(count, len(mod_lines))
 
187
 
 
188
    def testFirstLineRenumber(self):
 
189
        """Make sure we handle lines at the beginning of the hunk"""
 
190
        patch = parse_patch(self.datafile("insert_top.patch"))
 
191
        assert (patch.pos_in_mod(0)==1)
 
192
 
 
193
    def testParsePatches(self):
 
194
        """Make sure file names can be extracted from tricky unified diffs"""
 
195
        patchtext = \
 
196
"""--- orig-7
 
197
+++ mod-7
 
198
@@ -1,10 +1,10 @@
 
199
 -- a
 
200
--- b
 
201
+++ c
 
202
 xx d
 
203
 xx e
 
204
 ++ f
 
205
-++ g
 
206
+-- h
 
207
 xx i
 
208
 xx j
 
209
 -- k
 
210
--- l
 
211
+++ m
 
212
--- orig-8
 
213
+++ mod-8
 
214
@@ -1 +1 @@
 
215
--- A
 
216
+++ B
 
217
@@ -1 +1 @@
 
218
--- C
 
219
+++ D
 
220
"""
 
221
        filenames = [('orig-7', 'mod-7'),
 
222
                     ('orig-8', 'mod-8')]
 
223
        patches = parse_patches(patchtext.splitlines(True))
 
224
        patch_files = []
 
225
        for patch in patches:
 
226
            patch_files.append((patch.oldname, patch.newname))
 
227
        assert (patch_files == filenames)
 
228
            
 
229
def test():
 
230
    patchesTestSuite = unittest.makeSuite(PatchesTester,'test')
 
231
    runner = unittest.TextTestRunner(verbosity=0)
 
232
    return runner.run(patchesTestSuite)
 
233
 
 
234
 
 
235
if __name__ == "__main__":
 
236
    test()