~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-03-11 16:16:00 UTC
  • mto: (2323.6.9 0.15-integration)
  • mto: This revision was merged to the branch mainline in revision 2342.
  • Revision ID: aaron.bentley@utoronto.ca-20070311161600-hvtsmkf3d2z72562
Allow leading junk before merge directive header

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