/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
4763.2.4 by John Arbash Meinel
merge bzr.2.1 in preparation for NEWS entry.
1
# Copyright (C) 2005-2010 Aaron Bentley, Canonical Ltd
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
2
#
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1185.82.127 by Aaron Bentley
PEP8 updates
16
17
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
18
import os.path
19
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
20
from breezy.tests import TestCase
3376.2.6 by Martin Pool
Make PatchesTester use bzrlib TestCase base
21
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
22
from breezy.iterablefile import IterableFile
23
from breezy.patches import (MalformedLine,
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
24
                            MalformedHunkHeader,
25
                            MalformedPatchHeader,
4634.80.1 by Aaron Bentley
Parse binary files.
26
                            BinaryPatch,
4634.80.3 by Aaron Bentley
Clean up tests, test iter_patched.
27
                            BinaryFiles,
4634.80.1 by Aaron Bentley
Parse binary files.
28
                            Patch,
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
29
                            ContextLine,
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
30
                            InsertLine,
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
31
                            RemoveLine,
32
                            difference_index,
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
33
                            get_patch_names,
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
34
                            hunk_from_header,
35
                            iter_patched,
3363.18.3 by Aaron Bentley
Add tests for iter_patched_from_hunks
36
                            iter_patched_from_hunks,
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
37
                            parse_line,
2298.6.1 by Johan Dahlberg
Fix bzrtools shelve command for removed lines beginning with "--"
38
                            parse_patch,
3873.1.2 by Benoît Pierre
Add patches test for 'No newline at end of file' in the middle of hunk lines.
39
                            parse_patches,
40
                            NO_NL)
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
41
1185.82.127 by Aaron Bentley
PEP8 updates
42
3376.2.6 by Martin Pool
Make PatchesTester use bzrlib TestCase base
43
class PatchesTester(TestCase):
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
44
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
45
    def datafile(self, filename):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
46
        data_path = os.path.join(os.path.dirname(__file__),
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
47
                                 "test_patches_data", filename)
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
48
        return file(data_path, "rb")
49
4634.80.3 by Aaron Bentley
Clean up tests, test iter_patched.
50
    def data_lines(self, filename):
51
        datafile = self.datafile(filename)
52
        try:
53
            return datafile.readlines()
54
        finally:
55
            datafile.close()
56
5016.3.2 by Martin Pool
Add test that parse_patches(.. allow_dirty=True) works
57
    def test_parse_patches_leading_noise(self):
5243.1.2 by Martin
Point launchpad links in comments at production server rather than edge
58
        # https://bugs.launchpad.net/bzr/+bug/502076
59
        # https://code.launchpad.net/~toshio/bzr/allow-dirty-patches/+merge/18854
5016.3.2 by Martin Pool
Add test that parse_patches(.. allow_dirty=True) works
60
        lines = ["diff -pruN commands.py",
6601.1.5 by Kit Randel
linting
61
                 "--- orig/commands.py",
62
                 "+++ mod/dommands.py"]
5016.3.2 by Martin Pool
Add test that parse_patches(.. allow_dirty=True) works
63
        bits = parse_patches(iter(lines), allow_dirty=True)
64
6601.1.6 by Kit Randel
change of plan, don't track modified state, just preserve dirty_heads if requested in parse_patches
65
    def test_preserve_dirty_head(self):
66
        """Parse a patch containing a dirty header, and preserve lines"""
67
        lines = ["=== added directory 'foo/bar'\n",
68
                 "=== modified file 'orig/commands.py'\n",
6601.1.2 by Kit Randel
added modified prop to Patch/BinaryPatch, and get_patch_names logic
69
                 "--- orig/commands.py\n",
6603.2.1 by Colin Watson
Avoid associating dirty patch headers with the previous file in the patch.
70
                 "+++ mod/dommands.py\n",
71
                 "=== modified file 'orig/another.py'\n",
72
                 "--- orig/another.py\n",
73
                 "+++ mod/another.py\n"]
6601.1.7 by Kit Randel
fixed dirty_head logic in iter_file_patch
74
        patches = parse_patches(
75
            lines.__iter__(), allow_dirty=True, keep_dirty=True)
6603.2.2 by Colin Watson
Use assertLength.
76
        self.assertLength(2, patches)
6601.1.6 by Kit Randel
change of plan, don't track modified state, just preserve dirty_heads if requested in parse_patches
77
        self.assertEqual(patches[0]['dirty_head'],
78
                         ["=== added directory 'foo/bar'\n",
79
                          "=== modified file 'orig/commands.py'\n"])
80
        self.assertEqual(patches[0]['patch'].get_header().splitlines(True),
81
                         ["--- orig/commands.py\n", "+++ mod/dommands.py\n"])
6603.2.1 by Colin Watson
Avoid associating dirty patch headers with the previous file in the patch.
82
        self.assertEqual(patches[1]['dirty_head'],
83
                         ["=== modified file 'orig/another.py'\n"])
84
        self.assertEqual(patches[1]['patch'].get_header().splitlines(True),
85
                         ["--- orig/another.py\n", "+++ mod/another.py\n"])
6601.1.1 by Kit Randel
added failing test: test_parse_patches_file_modified_header
86
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
87
    def testValidPatchHeader(self):
88
        """Parse a valid patch header"""
89
        lines = "--- orig/commands.py\n+++ mod/dommands.py\n".split('\n')
6601.1.6 by Kit Randel
change of plan, don't track modified state, just preserve dirty_heads if requested in parse_patches
90
        (orig, mod) = get_patch_names(lines.__iter__())
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
91
        self.assertEqual(orig, "orig/commands.py")
92
        self.assertEqual(mod, "mod/dommands.py")
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
93
94
    def testInvalidPatchHeader(self):
95
        """Parse an invalid patch header"""
96
        lines = "-- orig/commands.py\n+++ mod/dommands.py".split('\n')
97
        self.assertRaises(MalformedPatchHeader, get_patch_names,
98
                          lines.__iter__())
99
100
    def testValidHunkHeader(self):
101
        """Parse a valid hunk header"""
102
        header = "@@ -34,11 +50,6 @@\n"
6601.1.5 by Kit Randel
linting
103
        hunk = hunk_from_header(header)
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
104
        self.assertEqual(hunk.orig_pos, 34)
105
        self.assertEqual(hunk.orig_range, 11)
106
        self.assertEqual(hunk.mod_pos, 50)
107
        self.assertEqual(hunk.mod_range, 6)
108
        self.assertEqual(str(hunk), header)
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
109
110
    def testValidHunkHeader2(self):
111
        """Parse a tricky, valid hunk header"""
112
        header = "@@ -1 +0,0 @@\n"
6601.1.5 by Kit Randel
linting
113
        hunk = hunk_from_header(header)
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
114
        self.assertEqual(hunk.orig_pos, 1)
115
        self.assertEqual(hunk.orig_range, 1)
116
        self.assertEqual(hunk.mod_pos, 0)
117
        self.assertEqual(hunk.mod_range, 0)
118
        self.assertEqual(str(hunk), header)
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
119
1551.18.6 by Aaron Bentley
Add support for diff -p-style diffs to patch parser
120
    def testPDiff(self):
121
        """Parse a hunk header produced by diff -p"""
122
        header = "@@ -407,7 +292,7 @@ bzr 0.18rc1  2007-07-10\n"
123
        hunk = hunk_from_header(header)
124
        self.assertEqual('bzr 0.18rc1  2007-07-10', hunk.tail)
125
        self.assertEqual(header, str(hunk))
126
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
127
    def makeMalformed(self, header):
128
        self.assertRaises(MalformedHunkHeader, hunk_from_header, header)
129
130
    def testInvalidHeader(self):
131
        """Parse an invalid hunk header"""
132
        self.makeMalformed(" -34,11 +50,6 \n")
133
        self.makeMalformed("@@ +50,6 -34,11 @@\n")
134
        self.makeMalformed("@@ -34,11 +50,6 @@")
135
        self.makeMalformed("@@ -34.5,11 +50,6 @@\n")
136
        self.makeMalformed("@@-34,11 +50,6@@\n")
137
        self.makeMalformed("@@ 34,11 50,6 @@\n")
138
        self.makeMalformed("@@ -34,11 @@\n")
139
        self.makeMalformed("@@ -34,11 +50,6.5 @@\n")
140
        self.makeMalformed("@@ -34,11 +50,-6 @@\n")
141
6601.1.5 by Kit Randel
linting
142
    def lineThing(self, text, type):
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
143
        line = parse_line(text)
3376.2.5 by Martin Pool
Remove a few more elusive assert statements
144
        self.assertIsInstance(line, type)
145
        self.assertEqual(str(line), text)
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
146
147
    def makeMalformedLine(self, text):
148
        self.assertRaises(MalformedLine, parse_line, text)
149
150
    def testValidLine(self):
151
        """Parse a valid hunk line"""
152
        self.lineThing(" hello\n", ContextLine)
153
        self.lineThing("+hello\n", InsertLine)
154
        self.lineThing("-hello\n", RemoveLine)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
155
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
156
    def testMalformedLine(self):
157
        """Parse invalid valid hunk lines"""
158
        self.makeMalformedLine("hello\n")
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
159
3873.1.2 by Benoît Pierre
Add patches test for 'No newline at end of file' in the middle of hunk lines.
160
    def testMalformedLineNO_NL(self):
3873.1.4 by Benoît Pierre
Add another test for patches to check we correctly handle '\ No newline
161
        """Parse invalid '\ No newline at end of file' in hunk lines"""
3873.1.2 by Benoît Pierre
Add patches test for 'No newline at end of file' in the middle of hunk lines.
162
        self.makeMalformedLine(NO_NL)
163
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
164
    def compare_parsed(self, patchtext):
165
        lines = patchtext.splitlines(True)
166
        patch = parse_patch(lines.__iter__())
167
        pstr = str(patch)
168
        i = difference_index(patchtext, pstr)
169
        if i is not None:
6619.3.3 by Jelmer Vernooij
Apply 2to3 print fix.
170
            print("%i: \"%s\" != \"%s\"" % (i, patchtext[i], pstr[i]))
6601.1.5 by Kit Randel
linting
171
        self.assertEqual(patchtext, str(patch))
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
172
173
    def testAll(self):
174
        """Test parsing a whole patch"""
1185.82.129 by Aaron Bentley
Removed confusing text from the test module
175
        patchtext = self.datafile("patchtext.patch").read()
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
176
        self.compare_parsed(patchtext)
177
4634.80.2 by Aaron Bentley
Ensure patch roundtripping.
178
    def test_parse_binary(self):
4634.80.1 by Aaron Bentley
Parse binary files.
179
        """Test parsing a whole patch"""
4634.80.3 by Aaron Bentley
Clean up tests, test iter_patched.
180
        patches = parse_patches(self.data_lines("binary.patch"))
4634.80.1 by Aaron Bentley
Parse binary files.
181
        self.assertIs(BinaryPatch, patches[0].__class__)
182
        self.assertIs(Patch, patches[1].__class__)
183
        self.assertContainsRe(patches[0].oldname, '^bar\t')
184
        self.assertContainsRe(patches[0].newname, '^qux\t')
185
        self.assertContainsRe(str(patches[0]),
6601.1.5 by Kit Randel
linting
186
                              'Binary files bar\t.* and qux\t.* differ\n')
4634.80.2 by Aaron Bentley
Ensure patch roundtripping.
187
4634.98.1 by Aaron Bentley
Improve patch binary section handling.
188
    def test_parse_binary_after_normal(self):
189
        patches = parse_patches(self.data_lines("binary-after-normal.patch"))
190
        self.assertIs(BinaryPatch, patches[1].__class__)
191
        self.assertIs(Patch, patches[0].__class__)
192
        self.assertContainsRe(patches[1].oldname, '^bar\t')
193
        self.assertContainsRe(patches[1].newname, '^qux\t')
194
        self.assertContainsRe(str(patches[1]),
6601.1.5 by Kit Randel
linting
195
                              'Binary files bar\t.* and qux\t.* differ\n')
4634.98.1 by Aaron Bentley
Improve patch binary section handling.
196
4634.80.2 by Aaron Bentley
Ensure patch roundtripping.
197
    def test_roundtrip_binary(self):
4634.80.3 by Aaron Bentley
Clean up tests, test iter_patched.
198
        patchtext = ''.join(self.data_lines("binary.patch"))
4634.80.2 by Aaron Bentley
Ensure patch roundtripping.
199
        patches = parse_patches(patchtext.splitlines(True))
200
        self.assertEqual(patchtext, ''.join(str(p) for p in patches))
4634.80.1 by Aaron Bentley
Parse binary files.
201
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
202
    def testInit(self):
203
        """Handle patches missing half the position, range tuple"""
204
        patchtext = \
1185.82.129 by Aaron Bentley
Removed confusing text from the test module
205
"""--- orig/__vavg__.cl
206
+++ mod/__vavg__.cl
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
207
@@ -1 +1,2 @@
1185.82.129 by Aaron Bentley
Removed confusing text from the test module
208
 __qbpsbezng__ = "erfgehpgherqgrkg ra"
209
+__qbp__ = Na nygreangr Nepu pbzznaqyvar vagresnpr
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
210
"""
211
        self.compare_parsed(patchtext)
212
213
    def testLineLookup(self):
214
        """Make sure we can accurately look up mod line from orig"""
215
        patch = parse_patch(self.datafile("diff"))
216
        orig = list(self.datafile("orig"))
217
        mod = list(self.datafile("mod"))
218
        removals = []
219
        for i in range(len(orig)):
220
            mod_pos = patch.pos_in_mod(i)
221
            if mod_pos is None:
222
                removals.append(orig[i])
223
                continue
3376.2.5 by Martin Pool
Remove a few more elusive assert statements
224
            self.assertEqual(mod[mod_pos], orig[i])
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
225
        rem_iter = removals.__iter__()
226
        for hunk in patch.hunks:
227
            for line in hunk.lines:
228
                if isinstance(line, RemoveLine):
6634.2.2 by Martin
Fix and unbogofy PatchesTester.testLineLookup
229
                    self.assertEqual(line.contents, next(rem_iter))
6634.2.1 by Martin
Apply 2to3 next fixer and make compatible
230
        self.assertRaises(StopIteration, next, rem_iter)
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
231
232
    def testPatching(self):
233
        """Test a few patch files, and make sure they work."""
234
        files = [
235
            ('diff-2', 'orig-2', 'mod-2'),
236
            ('diff-3', 'orig-3', 'mod-3'),
237
            ('diff-4', 'orig-4', 'mod-4'),
238
            ('diff-5', 'orig-5', 'mod-5'),
239
            ('diff-6', 'orig-6', 'mod-6'),
3873.1.4 by Benoît Pierre
Add another test for patches to check we correctly handle '\ No newline
240
            ('diff-7', 'orig-7', 'mod-7'),
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
241
        ]
242
        for diff, orig, mod in files:
243
            patch = self.datafile(diff)
244
            orig_lines = list(self.datafile(orig))
245
            mod_lines = list(self.datafile(mod))
246
247
            patched_file = IterableFile(iter_patched(orig_lines, patch))
248
            count = 0
249
            for patch_line in patched_file:
250
                self.assertEqual(patch_line, mod_lines[count])
251
                count += 1
252
            self.assertEqual(count, len(mod_lines))
253
4634.80.3 by Aaron Bentley
Clean up tests, test iter_patched.
254
    def test_iter_patched_binary(self):
255
        binary_lines = self.data_lines('binary.patch')
256
        e = self.assertRaises(BinaryFiles, iter_patched, [], binary_lines)
257
3363.18.3 by Aaron Bentley
Add tests for iter_patched_from_hunks
258
    def test_iter_patched_from_hunks(self):
259
        """Test a few patch files, and make sure they work."""
260
        files = [
261
            ('diff-2', 'orig-2', 'mod-2'),
262
            ('diff-3', 'orig-3', 'mod-3'),
263
            ('diff-4', 'orig-4', 'mod-4'),
264
            ('diff-5', 'orig-5', 'mod-5'),
265
            ('diff-6', 'orig-6', 'mod-6'),
3873.1.4 by Benoît Pierre
Add another test for patches to check we correctly handle '\ No newline
266
            ('diff-7', 'orig-7', 'mod-7'),
3363.18.3 by Aaron Bentley
Add tests for iter_patched_from_hunks
267
        ]
268
        for diff, orig, mod in files:
269
            parsed = parse_patch(self.datafile(diff))
270
            orig_lines = list(self.datafile(orig))
271
            mod_lines = list(self.datafile(mod))
272
            iter_patched = iter_patched_from_hunks(orig_lines, parsed.hunks)
273
            patched_file = IterableFile(iter_patched)
274
            count = 0
275
            for patch_line in patched_file:
276
                self.assertEqual(patch_line, mod_lines[count])
277
                count += 1
278
            self.assertEqual(count, len(mod_lines))
279
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
280
    def testFirstLineRenumber(self):
281
        """Make sure we handle lines at the beginning of the hunk"""
282
        patch = parse_patch(self.datafile("insert_top.patch"))
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
283
        self.assertEqual(patch.pos_in_mod(0), 1)
1185.82.126 by Aaron Bentley
Split the patch testing out into a separate file
284
2298.6.1 by Johan Dahlberg
Fix bzrtools shelve command for removed lines beginning with "--"
285
    def testParsePatches(self):
286
        """Make sure file names can be extracted from tricky unified diffs"""
287
        patchtext = \
288
"""--- orig-7
289
+++ mod-7
290
@@ -1,10 +1,10 @@
291
 -- a
292
--- b
293
+++ c
294
 xx d
295
 xx e
296
 ++ f
297
-++ g
298
+-- h
299
 xx i
300
 xx j
301
 -- k
302
--- l
303
+++ m
304
--- orig-8
305
+++ mod-8
306
@@ -1 +1 @@
307
--- A
308
+++ B
309
@@ -1 +1 @@
310
--- C
311
+++ D
312
"""
313
        filenames = [('orig-7', 'mod-7'),
314
                     ('orig-8', 'mod-8')]
315
        patches = parse_patches(patchtext.splitlines(True))
316
        patch_files = []
317
        for patch in patches:
318
            patch_files.append((patch.oldname, patch.newname))
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
319
        self.assertEqual(patch_files, filenames)
3946.4.1 by Tim Penhey
Extract out the counting of the stats values.
320
321
    def testStatsValues(self):
322
        """Test the added, removed and hunks values for stats_values."""
323
        patch = parse_patch(self.datafile("diff"))
324
        self.assertEqual((299, 407, 48), patch.stats_values())