~bzr-pqm/bzr/bzr.dev

2052.3.3 by John Arbash Meinel
Add (c) Canonical to files that Aaron has approved
1
# Copyright (C) 2004 - 2006 Aaron Bentley, Canonical Ltd
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
2
# <aaron.bentley@utoronto.ca>
3
#
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
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
1185.82.127 by Aaron Bentley
PEP8 updates
17
18
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
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,
2298.6.1 by Johan Dahlberg
Fix bzrtools shelve command for removed lines beginning with "--"
34
                            parse_patch,
35
                            parse_patches)
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
36
1185.82.127 by Aaron Bentley
PEP8 updates
37
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
38
class PatchesTester(unittest.TestCase):
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
39
    def datafile(self, filename):
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
40
        data_path = os.path.join(os.path.dirname(__file__), 
41
                                 "test_patches_data", filename)
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
42
        return file(data_path, "rb")
43
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
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 makeMalformed(self, header):
78
        self.assertRaises(MalformedHunkHeader, hunk_from_header, header)
79
80
    def testInvalidHeader(self):
81
        """Parse an invalid hunk header"""
82
        self.makeMalformed(" -34,11 +50,6 \n")
83
        self.makeMalformed("@@ +50,6 -34,11 @@\n")
84
        self.makeMalformed("@@ -34,11 +50,6 @@")
85
        self.makeMalformed("@@ -34.5,11 +50,6 @@\n")
86
        self.makeMalformed("@@-34,11 +50,6@@\n")
87
        self.makeMalformed("@@ 34,11 50,6 @@\n")
88
        self.makeMalformed("@@ -34,11 @@\n")
89
        self.makeMalformed("@@ -34,11 +50,6.5 @@\n")
90
        self.makeMalformed("@@ -34,11 +50,-6 @@\n")
91
92
    def lineThing(self,text, type):
93
        line = parse_line(text)
94
        assert(isinstance(line, type))
95
        assert(str(line)==text)
96
97
    def makeMalformedLine(self, text):
98
        self.assertRaises(MalformedLine, parse_line, text)
99
100
    def testValidLine(self):
101
        """Parse a valid hunk line"""
102
        self.lineThing(" hello\n", ContextLine)
103
        self.lineThing("+hello\n", InsertLine)
104
        self.lineThing("-hello\n", RemoveLine)
105
    
106
    def testMalformedLine(self):
107
        """Parse invalid valid hunk lines"""
108
        self.makeMalformedLine("hello\n")
109
    
110
    def compare_parsed(self, patchtext):
111
        lines = patchtext.splitlines(True)
112
        patch = parse_patch(lines.__iter__())
113
        pstr = str(patch)
114
        i = difference_index(patchtext, pstr)
115
        if i is not None:
116
            print "%i: \"%s\" != \"%s\"" % (i, patchtext[i], pstr[i])
117
        self.assertEqual (patchtext, str(patch))
118
119
    def testAll(self):
120
        """Test parsing a whole patch"""
1185.82.129 by Aaron Bentley
Removed confusing text from the test module
121
        patchtext = self.datafile("patchtext.patch").read()
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
122
        self.compare_parsed(patchtext)
123
124
    def testInit(self):
125
        """Handle patches missing half the position, range tuple"""
126
        patchtext = \
1185.82.129 by Aaron Bentley
Removed confusing text from the test module
127
"""--- orig/__vavg__.cl
128
+++ mod/__vavg__.cl
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
129
@@ -1 +1,2 @@
1185.82.129 by Aaron Bentley
Removed confusing text from the test module
130
 __qbpsbezng__ = "erfgehpgherqgrkg ra"
131
+__qbp__ = Na nygreangr Nepu pbzznaqyvar vagresnpr
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
132
"""
133
        self.compare_parsed(patchtext)
134
135
    def testLineLookup(self):
136
        import sys
137
        """Make sure we can accurately look up mod line from orig"""
138
        patch = parse_patch(self.datafile("diff"))
139
        orig = list(self.datafile("orig"))
140
        mod = list(self.datafile("mod"))
141
        removals = []
142
        for i in range(len(orig)):
143
            mod_pos = patch.pos_in_mod(i)
144
            if mod_pos is None:
145
                removals.append(orig[i])
146
                continue
147
            assert(mod[mod_pos]==orig[i])
148
        rem_iter = removals.__iter__()
149
        for hunk in patch.hunks:
150
            for line in hunk.lines:
151
                if isinstance(line, RemoveLine):
152
                    next = rem_iter.next()
153
                    if line.contents != next:
154
                        sys.stdout.write(" orig:%spatch:%s" % (next,
155
                                         line.contents))
156
                    assert(line.contents == next)
157
        self.assertRaises(StopIteration, rem_iter.next)
158
159
    def testPatching(self):
160
        """Test a few patch files, and make sure they work."""
161
        files = [
162
            ('diff-2', 'orig-2', 'mod-2'),
163
            ('diff-3', 'orig-3', 'mod-3'),
164
            ('diff-4', 'orig-4', 'mod-4'),
165
            ('diff-5', 'orig-5', 'mod-5'),
166
            ('diff-6', 'orig-6', 'mod-6'),
167
        ]
168
        for diff, orig, mod in files:
169
            patch = self.datafile(diff)
170
            orig_lines = list(self.datafile(orig))
171
            mod_lines = list(self.datafile(mod))
172
173
            patched_file = IterableFile(iter_patched(orig_lines, patch))
174
            lines = []
175
            count = 0
176
            for patch_line in patched_file:
177
                self.assertEqual(patch_line, mod_lines[count])
178
                count += 1
179
            self.assertEqual(count, len(mod_lines))
180
181
    def testFirstLineRenumber(self):
182
        """Make sure we handle lines at the beginning of the hunk"""
183
        patch = parse_patch(self.datafile("insert_top.patch"))
184
        assert (patch.pos_in_mod(0)==1)
185
2298.6.1 by Johan Dahlberg
Fix bzrtools shelve command for removed lines beginning with "--"
186
    def testParsePatches(self):
187
        """Make sure file names can be extracted from tricky unified diffs"""
188
        patchtext = \
189
"""--- orig-7
190
+++ mod-7
191
@@ -1,10 +1,10 @@
192
 -- a
193
--- b
194
+++ c
195
 xx d
196
 xx e
197
 ++ f
198
-++ g
199
+-- h
200
 xx i
201
 xx j
202
 -- k
203
--- l
204
+++ m
205
--- orig-8
206
+++ mod-8
207
@@ -1 +1 @@
208
--- A
209
+++ B
210
@@ -1 +1 @@
211
--- C
212
+++ D
213
"""
214
        filenames = [('orig-7', 'mod-7'),
215
                     ('orig-8', 'mod-8')]
216
        patches = parse_patches(patchtext.splitlines(True))
217
        patch_files = []
218
        for patch in patches:
219
            patch_files.append((patch.oldname, patch.newname))
220
        assert (patch_files == filenames)
221
            
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
222
def test():
223
    patchesTestSuite = unittest.makeSuite(PatchesTester,'test')
224
    runner = unittest.TextTestRunner(verbosity=0)
225
    return runner.run(patchesTestSuite)
226
227
228
if __name__ == "__main__":
229
    test()