/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_patches.py

  • Committer: Robert Collins
  • Date: 2010-05-06 11:08:10 UTC
  • mto: This revision was merged to the branch mainline in revision 5223.
  • Revision ID: robertc@robertcollins.net-20100506110810-h3j07fh5gmw54s25
Cleaner matcher matching revised unlocking protocol.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 
18
18
import os.path
19
19
 
20
 
from breezy.tests import TestCase
 
20
from bzrlib.tests import TestCase
21
21
 
22
 
from breezy.iterablefile import IterableFile
23
 
from breezy.patches import (MalformedLine,
 
22
from bzrlib.iterablefile import IterableFile
 
23
from bzrlib.patches import (MalformedLine,
24
24
                            MalformedHunkHeader,
25
25
                            MalformedPatchHeader,
26
26
                            BinaryPatch,
45
45
    def datafile(self, filename):
46
46
        data_path = os.path.join(os.path.dirname(__file__),
47
47
                                 "test_patches_data", filename)
48
 
        return open(data_path, "rb")
 
48
        return file(data_path, "rb")
49
49
 
50
50
    def data_lines(self, filename):
51
 
        with self.datafile(filename) as datafile:
 
51
        datafile = self.datafile(filename)
 
52
        try:
52
53
            return datafile.readlines()
 
54
        finally:
 
55
            datafile.close()
53
56
 
54
57
    def test_parse_patches_leading_noise(self):
55
 
        # https://bugs.launchpad.net/bzr/+bug/502076
56
 
        # https://code.launchpad.net/~toshio/bzr/allow-dirty-patches/+merge/18854
57
 
        lines = [b"diff -pruN commands.py",
58
 
                 b"--- orig/commands.py",
59
 
                 b"+++ mod/dommands.py"]
60
 
        bits = list(parse_patches(iter(lines), allow_dirty=True))
61
 
 
62
 
    def test_preserve_dirty_head(self):
63
 
        """Parse a patch containing a dirty header, and preserve lines"""
64
 
        lines = [b"=== added directory 'foo/bar'\n",
65
 
                 b"=== modified file 'orig/commands.py'\n",
66
 
                 b"--- orig/commands.py\n",
67
 
                 b"+++ mod/dommands.py\n",
68
 
                 b"=== modified file 'orig/another.py'\n",
69
 
                 b"--- orig/another.py\n",
70
 
                 b"+++ mod/another.py\n"]
71
 
        patches = list(parse_patches(
72
 
            lines.__iter__(), allow_dirty=True, keep_dirty=True))
73
 
        self.assertLength(2, patches)
74
 
        self.assertEqual(patches[0]['dirty_head'],
75
 
                         [b"=== added directory 'foo/bar'\n",
76
 
                          b"=== modified file 'orig/commands.py'\n"])
77
 
        self.assertEqual(patches[0]['patch'].get_header().splitlines(True),
78
 
                         [b"--- orig/commands.py\n", b"+++ mod/dommands.py\n"])
79
 
        self.assertEqual(patches[1]['dirty_head'],
80
 
                         [b"=== modified file 'orig/another.py'\n"])
81
 
        self.assertEqual(patches[1]['patch'].get_header().splitlines(True),
82
 
                         [b"--- orig/another.py\n", b"+++ mod/another.py\n"])
 
58
        # https://bugs.edge.launchpad.net/bzr/+bug/502076
 
59
        # https://code.edge.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)
83
64
 
84
65
    def testValidPatchHeader(self):
85
66
        """Parse a valid patch header"""
86
 
        lines = b"--- orig/commands.py\n+++ mod/dommands.py\n".split(b'\n')
 
67
        lines = "--- orig/commands.py\n+++ mod/dommands.py\n".split('\n')
87
68
        (orig, mod) = get_patch_names(lines.__iter__())
88
 
        self.assertEqual(orig, b"orig/commands.py")
89
 
        self.assertEqual(mod, b"mod/dommands.py")
 
69
        self.assertEqual(orig, "orig/commands.py")
 
70
        self.assertEqual(mod, "mod/dommands.py")
90
71
 
91
72
    def testInvalidPatchHeader(self):
92
73
        """Parse an invalid patch header"""
93
 
        lines = b"-- orig/commands.py\n+++ mod/dommands.py".split(b'\n')
 
74
        lines = "-- orig/commands.py\n+++ mod/dommands.py".split('\n')
94
75
        self.assertRaises(MalformedPatchHeader, get_patch_names,
95
76
                          lines.__iter__())
96
77
 
97
78
    def testValidHunkHeader(self):
98
79
        """Parse a valid hunk header"""
99
 
        header = b"@@ -34,11 +50,6 @@\n"
100
 
        hunk = hunk_from_header(header)
 
80
        header = "@@ -34,11 +50,6 @@\n"
 
81
        hunk = hunk_from_header(header);
101
82
        self.assertEqual(hunk.orig_pos, 34)
102
83
        self.assertEqual(hunk.orig_range, 11)
103
84
        self.assertEqual(hunk.mod_pos, 50)
104
85
        self.assertEqual(hunk.mod_range, 6)
105
 
        self.assertEqual(hunk.as_bytes(), header)
 
86
        self.assertEqual(str(hunk), header)
106
87
 
107
88
    def testValidHunkHeader2(self):
108
89
        """Parse a tricky, valid hunk header"""
109
 
        header = b"@@ -1 +0,0 @@\n"
110
 
        hunk = hunk_from_header(header)
 
90
        header = "@@ -1 +0,0 @@\n"
 
91
        hunk = hunk_from_header(header);
111
92
        self.assertEqual(hunk.orig_pos, 1)
112
93
        self.assertEqual(hunk.orig_range, 1)
113
94
        self.assertEqual(hunk.mod_pos, 0)
114
95
        self.assertEqual(hunk.mod_range, 0)
115
 
        self.assertEqual(hunk.as_bytes(), header)
 
96
        self.assertEqual(str(hunk), header)
116
97
 
117
98
    def testPDiff(self):
118
99
        """Parse a hunk header produced by diff -p"""
119
 
        header = b"@@ -407,7 +292,7 @@ bzr 0.18rc1  2007-07-10\n"
 
100
        header = "@@ -407,7 +292,7 @@ bzr 0.18rc1  2007-07-10\n"
120
101
        hunk = hunk_from_header(header)
121
 
        self.assertEqual(b'bzr 0.18rc1  2007-07-10', hunk.tail)
122
 
        self.assertEqual(header, hunk.as_bytes())
 
102
        self.assertEqual('bzr 0.18rc1  2007-07-10', hunk.tail)
 
103
        self.assertEqual(header, str(hunk))
123
104
 
124
105
    def makeMalformed(self, header):
125
106
        self.assertRaises(MalformedHunkHeader, hunk_from_header, header)
126
107
 
127
108
    def testInvalidHeader(self):
128
109
        """Parse an invalid hunk header"""
129
 
        self.makeMalformed(b" -34,11 +50,6 \n")
130
 
        self.makeMalformed(b"@@ +50,6 -34,11 @@\n")
131
 
        self.makeMalformed(b"@@ -34,11 +50,6 @@")
132
 
        self.makeMalformed(b"@@ -34.5,11 +50,6 @@\n")
133
 
        self.makeMalformed(b"@@-34,11 +50,6@@\n")
134
 
        self.makeMalformed(b"@@ 34,11 50,6 @@\n")
135
 
        self.makeMalformed(b"@@ -34,11 @@\n")
136
 
        self.makeMalformed(b"@@ -34,11 +50,6.5 @@\n")
137
 
        self.makeMalformed(b"@@ -34,11 +50,-6 @@\n")
 
110
        self.makeMalformed(" -34,11 +50,6 \n")
 
111
        self.makeMalformed("@@ +50,6 -34,11 @@\n")
 
112
        self.makeMalformed("@@ -34,11 +50,6 @@")
 
113
        self.makeMalformed("@@ -34.5,11 +50,6 @@\n")
 
114
        self.makeMalformed("@@-34,11 +50,6@@\n")
 
115
        self.makeMalformed("@@ 34,11 50,6 @@\n")
 
116
        self.makeMalformed("@@ -34,11 @@\n")
 
117
        self.makeMalformed("@@ -34,11 +50,6.5 @@\n")
 
118
        self.makeMalformed("@@ -34,11 +50,-6 @@\n")
138
119
 
139
 
    def lineThing(self, text, type):
 
120
    def lineThing(self,text, type):
140
121
        line = parse_line(text)
141
122
        self.assertIsInstance(line, type)
142
 
        self.assertEqual(line.as_bytes(), text)
 
123
        self.assertEqual(str(line), text)
143
124
 
144
125
    def makeMalformedLine(self, text):
145
126
        self.assertRaises(MalformedLine, parse_line, text)
146
127
 
147
128
    def testValidLine(self):
148
129
        """Parse a valid hunk line"""
149
 
        self.lineThing(b" hello\n", ContextLine)
150
 
        self.lineThing(b"+hello\n", InsertLine)
151
 
        self.lineThing(b"-hello\n", RemoveLine)
 
130
        self.lineThing(" hello\n", ContextLine)
 
131
        self.lineThing("+hello\n", InsertLine)
 
132
        self.lineThing("-hello\n", RemoveLine)
152
133
 
153
134
    def testMalformedLine(self):
154
135
        """Parse invalid valid hunk lines"""
155
 
        self.makeMalformedLine(b"hello\n")
 
136
        self.makeMalformedLine("hello\n")
156
137
 
157
138
    def testMalformedLineNO_NL(self):
158
 
        """Parse invalid '\\ No newline at end of file' in hunk lines"""
 
139
        """Parse invalid '\ No newline at end of file' in hunk lines"""
159
140
        self.makeMalformedLine(NO_NL)
160
141
 
161
142
    def compare_parsed(self, patchtext):
162
143
        lines = patchtext.splitlines(True)
163
144
        patch = parse_patch(lines.__iter__())
164
 
        pstr = patch.as_bytes()
 
145
        pstr = str(patch)
165
146
        i = difference_index(patchtext, pstr)
166
147
        if i is not None:
167
 
            print("%i: \"%s\" != \"%s\"" % (i, patchtext[i], pstr[i]))
168
 
        self.assertEqual(patchtext, patch.as_bytes())
 
148
            print "%i: \"%s\" != \"%s\"" % (i, patchtext[i], pstr[i])
 
149
        self.assertEqual (patchtext, str(patch))
169
150
 
170
151
    def testAll(self):
171
152
        """Test parsing a whole patch"""
172
 
        with self.datafile("patchtext.patch") as f:
173
 
            patchtext = f.read()
 
153
        patchtext = self.datafile("patchtext.patch").read()
174
154
        self.compare_parsed(patchtext)
175
155
 
176
156
    def test_parse_binary(self):
177
157
        """Test parsing a whole patch"""
178
 
        patches = list(parse_patches(self.data_lines("binary.patch")))
 
158
        patches = parse_patches(self.data_lines("binary.patch"))
179
159
        self.assertIs(BinaryPatch, patches[0].__class__)
180
160
        self.assertIs(Patch, patches[1].__class__)
181
 
        self.assertContainsRe(patches[0].oldname, b'^bar\t')
182
 
        self.assertContainsRe(patches[0].newname, b'^qux\t')
183
 
        self.assertContainsRe(patches[0].as_bytes(),
184
 
                              b'Binary files bar\t.* and qux\t.* differ\n')
 
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')
185
165
 
186
166
    def test_parse_binary_after_normal(self):
187
 
        patches = list(parse_patches(
188
 
            self.data_lines("binary-after-normal.patch")))
 
167
        patches = parse_patches(self.data_lines("binary-after-normal.patch"))
189
168
        self.assertIs(BinaryPatch, patches[1].__class__)
190
169
        self.assertIs(Patch, patches[0].__class__)
191
 
        self.assertContainsRe(patches[1].oldname, b'^bar\t')
192
 
        self.assertContainsRe(patches[1].newname, b'^qux\t')
193
 
        self.assertContainsRe(patches[1].as_bytes(),
194
 
                              b'Binary files bar\t.* and qux\t.* differ\n')
 
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')
195
174
 
196
175
    def test_roundtrip_binary(self):
197
 
        patchtext = b''.join(self.data_lines("binary.patch"))
 
176
        patchtext = ''.join(self.data_lines("binary.patch"))
198
177
        patches = parse_patches(patchtext.splitlines(True))
199
 
        self.assertEqual(patchtext, b''.join(p.as_bytes() for p in patches))
 
178
        self.assertEqual(patchtext, ''.join(str(p) for p in patches))
200
179
 
201
180
    def testInit(self):
202
181
        """Handle patches missing half the position, range tuple"""
203
182
        patchtext = \
204
 
            b"""--- orig/__vavg__.cl
 
183
"""--- orig/__vavg__.cl
205
184
+++ mod/__vavg__.cl
206
185
@@ -1 +1,2 @@
207
186
 __qbpsbezng__ = "erfgehpgherqgrkg ra"
210
189
        self.compare_parsed(patchtext)
211
190
 
212
191
    def testLineLookup(self):
 
192
        import sys
213
193
        """Make sure we can accurately look up mod line from orig"""
214
194
        patch = parse_patch(self.datafile("diff"))
215
195
        orig = list(self.datafile("orig"))
225
205
        for hunk in patch.hunks:
226
206
            for line in hunk.lines:
227
207
                if isinstance(line, RemoveLine):
228
 
                    self.assertEqual(line.contents, next(rem_iter))
229
 
        self.assertRaises(StopIteration, next, rem_iter)
 
208
                    next = rem_iter.next()
 
209
                    if line.contents != next:
 
210
                        sys.stdout.write(" orig:%spatch:%s" % (next,
 
211
                                         line.contents))
 
212
                    self.assertEqual(line.contents, next)
 
213
        self.assertRaises(StopIteration, rem_iter.next)
230
214
 
231
215
    def testPatching(self):
232
216
        """Test a few patch files, and make sure they work."""
244
228
            mod_lines = list(self.datafile(mod))
245
229
 
246
230
            patched_file = IterableFile(iter_patched(orig_lines, patch))
 
231
            lines = []
247
232
            count = 0
248
233
            for patch_line in patched_file:
249
234
                self.assertEqual(patch_line, mod_lines[count])
254
239
        binary_lines = self.data_lines('binary.patch')
255
240
        e = self.assertRaises(BinaryFiles, iter_patched, [], binary_lines)
256
241
 
 
242
 
257
243
    def test_iter_patched_from_hunks(self):
258
244
        """Test a few patch files, and make sure they work."""
259
245
        files = [
270
256
            mod_lines = list(self.datafile(mod))
271
257
            iter_patched = iter_patched_from_hunks(orig_lines, parsed.hunks)
272
258
            patched_file = IterableFile(iter_patched)
 
259
            lines = []
273
260
            count = 0
274
261
            for patch_line in patched_file:
275
262
                self.assertEqual(patch_line, mod_lines[count])
284
271
    def testParsePatches(self):
285
272
        """Make sure file names can be extracted from tricky unified diffs"""
286
273
        patchtext = \
287
 
            b"""--- orig-7
 
274
"""--- orig-7
288
275
+++ mod-7
289
276
@@ -1,10 +1,10 @@
290
277
 -- a
309
296
--- C
310
297
+++ D
311
298
"""
312
 
        filenames = [(b'orig-7', b'mod-7'),
313
 
                     (b'orig-8', b'mod-8')]
 
299
        filenames = [('orig-7', 'mod-7'),
 
300
                     ('orig-8', 'mod-8')]
314
301
        patches = parse_patches(patchtext.splitlines(True))
315
302
        patch_files = []
316
303
        for patch in patches: