git-cola v4.0.2
[git-cola.git] / test / diffparse_test.py
blobe4e70074ea9d8e40608d88375a4e044a24b1a113
1 """Tests for the diffparse module"""
2 # pylint: disable=redefined-outer-name
3 from __future__ import absolute_import, division, print_function, unicode_literals
5 import pytest
7 from cola import core
8 from cola import diffparse
10 from . import helper
13 class DiffLinesTestData(object):
14 """Test data used by DiffLines tests"""
16 def __init__(self):
17 self.parser = diffparse.DiffLines()
18 fixture_path = helper.fixture('diff.txt')
19 self.text = core.read(fixture_path)
22 @pytest.fixture
23 def difflines_data():
24 """Return test data for diffparse.DiffLines tests"""
25 return DiffLinesTestData()
28 def test_diff():
29 fixture_path = helper.fixture('diff.txt')
30 parser = diffparse.DiffParser('cola/diffparse.py', core.read(fixture_path))
31 hunks = parser.hunks
33 assert len(hunks) == 3
34 assert hunks[0].first_line_idx == 0
35 assert len(hunks[0].lines) == 23
36 assert hunks[0].lines[0] == '@@ -6,10 +6,21 @@ from cola import gitcmds\n'
37 assert hunks[0].lines[1] == ' from cola import gitcfg\n'
38 assert hunks[0].lines[2] == ' \n'
39 assert hunks[0].lines[3] == ' \n'
40 assert hunks[0].lines[4] == '+class DiffSource(object):\n'
41 assert hunks[0].lines[-1] == (
42 r" self._header_start_re = re.compile('^@@ -(\d+)"
43 r" \+(\d+),(\d+) @@.*')"
44 '\n'
46 assert hunks[1].first_line_idx == 23
47 assert len(hunks[1].lines) == 18
48 assert hunks[1].lines[0] == '@@ -29,13 +40,11 @@ class DiffParser(object):\n'
49 assert hunks[1].lines[1] == ' self.diff_sel = []\n'
50 assert hunks[1].lines[2] == ' self.selected = []\n'
51 assert hunks[1].lines[3] == ' self.filename = filename\n'
52 assert hunks[1].lines[4] == (
53 '+ self.diff_source = diff_source or DiffSource()\n'
55 assert hunks[1].lines[-1] == ' self.header = header\n'
57 assert hunks[2].first_line_idx == 41
58 assert len(hunks[2].lines) == 16
59 assert hunks[2].lines[0] == '@@ -43,11 +52,10 @@ class DiffParser(object):\n'
60 assert hunks[2].lines[-1] == (
61 ' """Writes a new diff corresponding to the user\'s' ' selection."""\n'
65 def test_diff_at_start():
66 fixture_path = helper.fixture('diff-start.txt')
67 parser = diffparse.DiffParser('foo bar/a', core.read(fixture_path))
68 hunks = parser.hunks
70 assert hunks[0].lines[0] == '@@ -1 +1,4 @@\n'
71 assert hunks[-1].lines[-1] == '+c\n'
72 assert hunks[0].old_start == 1
73 assert hunks[0].old_count == 1
74 assert hunks[0].new_start == 1
75 assert hunks[0].new_count == 4
76 assert parser.generate_patch(1, 3) == (
77 '--- a/foo bar/a\n' '+++ b/foo bar/a\n' '@@ -1 +1,3 @@\n' ' bar\n' '+a\n' '+b\n'
79 assert parser.generate_patch(0, 4) == (
80 '--- a/foo bar/a\n'
81 '+++ b/foo bar/a\n'
82 '@@ -1 +1,4 @@\n'
83 ' bar\n'
84 '+a\n'
85 '+b\n'
86 '+c\n'
90 def test_diff_at_end():
91 fixture_path = helper.fixture('diff-end.txt')
92 parser = diffparse.DiffParser('rijndael.js', core.read(fixture_path))
93 hunks = parser.hunks
95 assert hunks[0].lines[0] == '@@ -1,39 +1 @@\n'
96 assert hunks[-1].lines[-1] == (
97 "+module.exports = require('./build/Release/rijndael');\n"
99 assert hunks[0].old_start == 1
100 assert hunks[0].old_count == 39
101 assert hunks[0].new_start == 1
102 assert hunks[0].new_count == 1
105 def test_diff_that_empties_file():
106 fixture_path = helper.fixture('diff-empty.txt')
107 parser = diffparse.DiffParser('filename', core.read(fixture_path))
108 hunks = parser.hunks
110 assert hunks[0].lines[0] == '@@ -1,2 +0,0 @@\n'
111 assert hunks[-1].lines[-1] == '-second\n'
112 assert hunks[0].old_start == 1
113 assert hunks[0].old_count == 2
114 assert hunks[0].new_start == 0
115 assert hunks[0].new_count == 0
116 assert parser.generate_patch(1, 1) == (
117 '--- a/filename\n' '+++ b/filename\n' '@@ -1,2 +1 @@\n' '-first\n' ' second\n'
119 assert parser.generate_patch(0, 2) == (
120 '--- a/filename\n' '+++ b/filename\n' '@@ -1,2 +0,0 @@\n' '-first\n' '-second\n'
124 def test_diff_file_removal():
125 diff_text = """\
126 deleted file mode 100755
127 @@ -1,1 +0,0 @@
128 -#!/bin/sh
130 parser = diffparse.DiffParser('deleted.txt', diff_text)
132 expect = 1
133 actual = len(parser.hunks)
134 assert expect == actual
136 # Selecting the first two lines generate no diff
137 expect = None
138 actual = parser.generate_patch(0, 1)
139 assert expect == actual
141 # Selecting the last line should generate a line removal
142 expect = """\
143 --- a/deleted.txt
144 +++ b/deleted.txt
145 @@ -1 +0,0 @@
146 -#!/bin/sh
148 actual = parser.generate_patch(1, 2)
149 assert expect == actual
151 # All three lines should map to the same hunk diff
152 actual = parser.generate_hunk_patch(0)
153 assert expect == actual
155 actual = parser.generate_hunk_patch(1)
156 assert expect == actual
158 actual = parser.generate_hunk_patch(2)
159 assert expect == actual
162 def test_basic_diff_line_count(difflines_data):
163 """Verify the basic line counts"""
164 lines = difflines_data.parser.parse(difflines_data.text)
165 expect = len(difflines_data.text.splitlines())
166 actual = len(lines)
167 assert expect == actual
170 def test_diff_line_count_ranges(difflines_data):
171 parser = difflines_data.parser
172 lines = parser.parse(difflines_data.text)
174 # Diff header
175 line = 0
176 count = 1
177 assert lines[line][0] == parser.DASH
178 assert lines[line][1] == parser.DASH
179 line += count
181 # 3 lines of context
182 count = 3
183 current_old = 6
184 current_new = 6
185 for i in range(count):
186 assert lines[line + i][0] == current_old + i
187 assert lines[line + i][1] == current_new + i
188 line += count
189 current_old += count
190 current_new += count
192 # 10 lines of new text
193 count = 10
194 for i in range(count):
195 assert lines[line + i][0] == parser.EMPTY
196 assert lines[line + i][1] == current_new + i
198 line += count
199 current_new += count
201 # 3 more lines of context
202 count = 3
203 for i in range(count):
204 assert lines[line + i][0] == current_old + i
205 assert lines[line + i][1] == current_new + i
206 line += count
207 current_new += count
208 current_old += count
210 # 1 line of removal
211 count = 1
212 for i in range(count):
213 assert lines[line + i][0] == current_old + i
214 assert lines[line + i][1] == parser.EMPTY
215 line += count
216 current_old += count
218 # 2 lines of addition
219 count = 2
220 for i in range(count):
221 assert lines[line + i][0] == parser.EMPTY
222 assert lines[line + i][1] == current_new + i
223 line += count
224 current_new += count
226 # 3 more lines of context
227 count = 3
228 for i in range(count):
229 assert lines[line + i][0] == current_old + i
230 assert lines[line + i][1] == current_new + i
231 line += count
232 current_new += count
233 current_old += count
235 # 1 line of header
236 count = 1
237 for i in range(count):
238 assert lines[line + i][0] == parser.DASH
239 assert lines[line + i][1] == parser.DASH
240 line += count
242 # 3 more lines of context
243 current_old = 29
244 current_new = 40
245 count = 3
246 for i in range(count):
247 assert lines[line + i][0] == current_old + i
248 assert lines[line + i][1] == current_new + i
249 line += count
250 current_new += count
251 current_old += count
253 expect_max_old = 53
254 assert expect_max_old == parser.old.max_value
256 expect_max_new = 61
257 assert expect_max_new == parser.new.max_value
259 assert parser.digits() == 2
262 def test_diff_line_for_merge(difflines_data):
263 """Verify the basic line counts"""
264 text = """@@@ -1,23 -1,33 +1,75 @@@
265 ++<<<<<<< upstream
269 parser = difflines_data.parser
270 lines = parser.parse(text)
271 assert len(lines) == 4
272 assert len(lines[0]) == 3
273 assert len(lines[1]) == 3
274 assert len(lines[2]) == 3
275 assert len(lines[3]) == 3
277 assert lines[0][0] == parser.DASH
278 assert lines[0][1] == parser.DASH
279 assert lines[0][2] == parser.DASH
281 assert lines[1][0] == parser.EMPTY
282 assert lines[1][1] == parser.EMPTY
283 assert lines[1][2] == 1
285 assert lines[2][0] == 1
286 assert lines[2][1] == parser.EMPTY
287 assert lines[2][2] == 2
289 assert lines[3][0] == 2
290 assert lines[3][1] == parser.EMPTY
291 assert lines[3][2] == 3
294 def test_diff_line_digits(difflines_data):
295 parser = difflines_data.parser
297 text = """@@ -1,99 +1,99 @@"""
298 parser.parse(text)
299 assert parser.digits() == 2
301 text = """@@ -2,99 +2,99 @@"""
302 parser.parse(text)
303 assert parser.digits() == 3
306 def test_format_basic():
307 fmt = diffparse.FormatDigits()
308 fmt.set_digits(2)
310 expect = '01 99'
311 actual = fmt.value(1, 99)
312 assert expect == actual
315 def test_format_reuse():
316 fmt = diffparse.FormatDigits()
318 fmt.set_digits(3)
319 expect = '001 099'
320 actual = fmt.value(1, 99)
321 assert expect == actual
323 fmt.set_digits(4)
324 expect = '0001 0099'
325 actual = fmt.value(1, 99)
326 assert expect == actual
329 def test_format_special_values():
330 fmt = diffparse.FormatDigits(dash='-')
331 fmt.set_digits(3)
333 expect = ' 099'
334 actual = fmt.value(fmt.EMPTY, 99)
335 assert expect == actual
337 expect = '001 '
338 actual = fmt.value(1, fmt.EMPTY)
339 assert expect == actual
341 expect = ' '
342 actual = fmt.value(fmt.EMPTY, fmt.EMPTY)
343 assert expect == actual
345 expect = '--- 001'
346 actual = fmt.value(fmt.DASH, 1)
347 assert expect == actual
349 expect = '099 ---'
350 actual = fmt.value(99, fmt.DASH)
351 assert expect == actual
353 expect = '--- ---'
354 actual = fmt.value(fmt.DASH, fmt.DASH)
355 assert expect == actual
357 expect = ' ---'
358 actual = fmt.value(fmt.EMPTY, fmt.DASH)
359 assert expect == actual
361 expect = '--- '
362 actual = fmt.value(fmt.DASH, fmt.EMPTY)
363 assert expect == actual
366 def test_parse_range_str():
367 start, count = diffparse.parse_range_str('1,2')
368 assert start == 1
369 assert count == 2
372 def test_parse_range_str_single_line():
373 start, count = diffparse.parse_range_str('2')
374 assert start == 2
375 assert count == 1
378 def test_parse_range_str_empty():
379 start, count = diffparse.parse_range_str('0,0')
380 assert start == 0
381 assert count == 0