~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_patches.py

  • Committer: Aaron Bentley
  • Date: 2007-06-21 23:43:17 UTC
  • mto: (2520.5.2 bzr.mpbundle)
  • mto: This revision was merged to the branch mainline in revision 2631.
  • Revision ID: abentley@panoramicfeedback.com-20070621234317-5w3h8h36oe90sups
Implement new merge directive format

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Aaron Bentley, Canonical Ltd
 
1
# Copyright (C) 2004 - 2006 Aaron Bentley, Canonical Ltd
2
2
# <aaron.bentley@utoronto.ca>
3
3
#
4
4
# This program is free software; you can redistribute it and/or modify
13
13
#
14
14
# You should have received a copy of the GNU General Public License
15
15
# along with this program; if not, write to the Free Software
16
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
 
 
18
 
 
 
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
17
 
 
18
 
 
19
import unittest
19
20
import os.path
20
21
 
21
 
from bzrlib.tests import TestCase
22
 
 
23
22
from bzrlib.iterablefile import IterableFile
24
 
from bzrlib.patches import (MalformedLine,
25
 
                            MalformedHunkHeader,
26
 
                            MalformedPatchHeader,
27
 
                            BinaryPatch,
28
 
                            BinaryFiles,
29
 
                            Patch,
30
 
                            ContextLine,
 
23
from bzrlib.patches import (MalformedLine, 
 
24
                            MalformedHunkHeader, 
 
25
                            MalformedPatchHeader, 
 
26
                            ContextLine, 
31
27
                            InsertLine,
32
 
                            RemoveLine,
33
 
                            difference_index,
 
28
                            RemoveLine, 
 
29
                            difference_index, 
34
30
                            get_patch_names,
35
 
                            hunk_from_header,
36
 
                            iter_patched,
37
 
                            iter_patched_from_hunks,
 
31
                            hunk_from_header, 
 
32
                            iter_patched, 
38
33
                            parse_line,
39
34
                            parse_patch,
40
 
                            parse_patches,
41
 
                            NO_NL)
42
 
 
43
 
 
44
 
class PatchesTester(TestCase):
45
 
 
 
35
                            parse_patches)
 
36
 
 
37
 
 
38
class PatchesTester(unittest.TestCase):
46
39
    def datafile(self, filename):
47
 
        data_path = os.path.join(os.path.dirname(__file__),
 
40
        data_path = os.path.join(os.path.dirname(__file__), 
48
41
                                 "test_patches_data", filename)
49
42
        return file(data_path, "rb")
50
43
 
51
 
    def data_lines(self, filename):
52
 
        datafile = self.datafile(filename)
53
 
        try:
54
 
            return datafile.readlines()
55
 
        finally:
56
 
            datafile.close()
57
 
 
58
44
    def testValidPatchHeader(self):
59
45
        """Parse a valid patch header"""
60
46
        lines = "--- orig/commands.py\n+++ mod/dommands.py\n".split('\n')
61
47
        (orig, mod) = get_patch_names(lines.__iter__())
62
 
        self.assertEqual(orig, "orig/commands.py")
63
 
        self.assertEqual(mod, "mod/dommands.py")
 
48
        assert(orig == "orig/commands.py")
 
49
        assert(mod == "mod/dommands.py")
64
50
 
65
51
    def testInvalidPatchHeader(self):
66
52
        """Parse an invalid patch header"""
72
58
        """Parse a valid hunk header"""
73
59
        header = "@@ -34,11 +50,6 @@\n"
74
60
        hunk = hunk_from_header(header);
75
 
        self.assertEqual(hunk.orig_pos, 34)
76
 
        self.assertEqual(hunk.orig_range, 11)
77
 
        self.assertEqual(hunk.mod_pos, 50)
78
 
        self.assertEqual(hunk.mod_range, 6)
79
 
        self.assertEqual(str(hunk), 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)
80
66
 
81
67
    def testValidHunkHeader2(self):
82
68
        """Parse a tricky, valid hunk header"""
83
69
        header = "@@ -1 +0,0 @@\n"
84
70
        hunk = hunk_from_header(header);
85
 
        self.assertEqual(hunk.orig_pos, 1)
86
 
        self.assertEqual(hunk.orig_range, 1)
87
 
        self.assertEqual(hunk.mod_pos, 0)
88
 
        self.assertEqual(hunk.mod_range, 0)
89
 
        self.assertEqual(str(hunk), header)
90
 
 
91
 
    def testPDiff(self):
92
 
        """Parse a hunk header produced by diff -p"""
93
 
        header = "@@ -407,7 +292,7 @@ bzr 0.18rc1  2007-07-10\n"
94
 
        hunk = hunk_from_header(header)
95
 
        self.assertEqual('bzr 0.18rc1  2007-07-10', hunk.tail)
96
 
        self.assertEqual(header, str(hunk))
 
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)
97
76
 
98
77
    def makeMalformed(self, header):
99
78
        self.assertRaises(MalformedHunkHeader, hunk_from_header, header)
112
91
 
113
92
    def lineThing(self,text, type):
114
93
        line = parse_line(text)
115
 
        self.assertIsInstance(line, type)
116
 
        self.assertEqual(str(line), text)
 
94
        assert(isinstance(line, type))
 
95
        assert(str(line)==text)
117
96
 
118
97
    def makeMalformedLine(self, text):
119
98
        self.assertRaises(MalformedLine, parse_line, text)
123
102
        self.lineThing(" hello\n", ContextLine)
124
103
        self.lineThing("+hello\n", InsertLine)
125
104
        self.lineThing("-hello\n", RemoveLine)
126
 
 
 
105
    
127
106
    def testMalformedLine(self):
128
107
        """Parse invalid valid hunk lines"""
129
108
        self.makeMalformedLine("hello\n")
130
 
 
131
 
    def testMalformedLineNO_NL(self):
132
 
        """Parse invalid '\ No newline at end of file' in hunk lines"""
133
 
        self.makeMalformedLine(NO_NL)
134
 
 
 
109
    
135
110
    def compare_parsed(self, patchtext):
136
111
        lines = patchtext.splitlines(True)
137
112
        patch = parse_patch(lines.__iter__())
146
121
        patchtext = self.datafile("patchtext.patch").read()
147
122
        self.compare_parsed(patchtext)
148
123
 
149
 
    def test_parse_binary(self):
150
 
        """Test parsing a whole patch"""
151
 
        patches = parse_patches(self.data_lines("binary.patch"))
152
 
        self.assertIs(BinaryPatch, patches[0].__class__)
153
 
        self.assertIs(Patch, patches[1].__class__)
154
 
        self.assertContainsRe(patches[0].oldname, '^bar\t')
155
 
        self.assertContainsRe(patches[0].newname, '^qux\t')
156
 
        self.assertContainsRe(str(patches[0]),
157
 
                                  'Binary files bar\t.* and qux\t.* differ\n')
158
 
 
159
 
    def test_parse_binary_after_normal(self):
160
 
        patches = parse_patches(self.data_lines("binary-after-normal.patch"))
161
 
        self.assertIs(BinaryPatch, patches[1].__class__)
162
 
        self.assertIs(Patch, patches[0].__class__)
163
 
        self.assertContainsRe(patches[1].oldname, '^bar\t')
164
 
        self.assertContainsRe(patches[1].newname, '^qux\t')
165
 
        self.assertContainsRe(str(patches[1]),
166
 
                                  'Binary files bar\t.* and qux\t.* differ\n')
167
 
 
168
 
    def test_roundtrip_binary(self):
169
 
        patchtext = ''.join(self.data_lines("binary.patch"))
170
 
        patches = parse_patches(patchtext.splitlines(True))
171
 
        self.assertEqual(patchtext, ''.join(str(p) for p in patches))
172
 
 
173
124
    def testInit(self):
174
125
        """Handle patches missing half the position, range tuple"""
175
126
        patchtext = \
193
144
            if mod_pos is None:
194
145
                removals.append(orig[i])
195
146
                continue
196
 
            self.assertEqual(mod[mod_pos], orig[i])
 
147
            assert(mod[mod_pos]==orig[i])
197
148
        rem_iter = removals.__iter__()
198
149
        for hunk in patch.hunks:
199
150
            for line in hunk.lines:
202
153
                    if line.contents != next:
203
154
                        sys.stdout.write(" orig:%spatch:%s" % (next,
204
155
                                         line.contents))
205
 
                    self.assertEqual(line.contents, next)
 
156
                    assert(line.contents == next)
206
157
        self.assertRaises(StopIteration, rem_iter.next)
207
158
 
208
159
    def testPatching(self):
213
164
            ('diff-4', 'orig-4', 'mod-4'),
214
165
            ('diff-5', 'orig-5', 'mod-5'),
215
166
            ('diff-6', 'orig-6', 'mod-6'),
216
 
            ('diff-7', 'orig-7', 'mod-7'),
217
167
        ]
218
168
        for diff, orig, mod in files:
219
169
            patch = self.datafile(diff)
228
178
                count += 1
229
179
            self.assertEqual(count, len(mod_lines))
230
180
 
231
 
    def test_iter_patched_binary(self):
232
 
        binary_lines = self.data_lines('binary.patch')
233
 
        e = self.assertRaises(BinaryFiles, iter_patched, [], binary_lines)
234
 
 
235
 
 
236
 
    def test_iter_patched_from_hunks(self):
237
 
        """Test a few patch files, and make sure they work."""
238
 
        files = [
239
 
            ('diff-2', 'orig-2', 'mod-2'),
240
 
            ('diff-3', 'orig-3', 'mod-3'),
241
 
            ('diff-4', 'orig-4', 'mod-4'),
242
 
            ('diff-5', 'orig-5', 'mod-5'),
243
 
            ('diff-6', 'orig-6', 'mod-6'),
244
 
            ('diff-7', 'orig-7', 'mod-7'),
245
 
        ]
246
 
        for diff, orig, mod in files:
247
 
            parsed = parse_patch(self.datafile(diff))
248
 
            orig_lines = list(self.datafile(orig))
249
 
            mod_lines = list(self.datafile(mod))
250
 
            iter_patched = iter_patched_from_hunks(orig_lines, parsed.hunks)
251
 
            patched_file = IterableFile(iter_patched)
252
 
            lines = []
253
 
            count = 0
254
 
            for patch_line in patched_file:
255
 
                self.assertEqual(patch_line, mod_lines[count])
256
 
                count += 1
257
 
            self.assertEqual(count, len(mod_lines))
258
 
 
259
181
    def testFirstLineRenumber(self):
260
182
        """Make sure we handle lines at the beginning of the hunk"""
261
183
        patch = parse_patch(self.datafile("insert_top.patch"))
262
 
        self.assertEqual(patch.pos_in_mod(0), 1)
 
184
        assert (patch.pos_in_mod(0)==1)
263
185
 
264
186
    def testParsePatches(self):
265
187
        """Make sure file names can be extracted from tricky unified diffs"""
295
217
        patch_files = []
296
218
        for patch in patches:
297
219
            patch_files.append((patch.oldname, patch.newname))
298
 
        self.assertEqual(patch_files, filenames)
299
 
 
300
 
    def testStatsValues(self):
301
 
        """Test the added, removed and hunks values for stats_values."""
302
 
        patch = parse_patch(self.datafile("diff"))
303
 
        self.assertEqual((299, 407, 48), patch.stats_values())
 
220
        assert (patch_files == filenames)
 
221
            
 
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()