dev: format code using "garden fmt" (black)
[git-cola.git] / test / diffparse_test.py
blob48b83934ad97f02fe6100e8cc0ee0d37b37dff75
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 patch = diffparse.Patch.parse('cola/diffparse.py', core.read(fixture_path))
31 hunks = patch.hunks
33 assert len(hunks) == 3
34 assert len(hunks[0].lines) == 23
35 assert hunks[0].lines[0] == '@@ -6,10 +6,21 @@ from cola import gitcmds\n'
36 assert hunks[0].lines[1] == ' from cola import gitcfg\n'
37 assert hunks[0].lines[2] == ' \n'
38 assert hunks[0].lines[3] == ' \n'
39 assert hunks[0].lines[4] == '+class DiffSource(object):\n'
40 assert hunks[0].lines[-1] == (
41 r" self._header_start_re = re.compile('^@@ -(\d+)"
42 r" \+(\d+),(\d+) @@.*')"
43 '\n'
45 assert len(hunks[1].lines) == 18
46 assert hunks[1].lines[0] == '@@ -29,13 +40,11 @@ class DiffParser(object):\n'
47 assert hunks[1].lines[1] == ' self.diff_sel = []\n'
48 assert hunks[1].lines[2] == ' self.selected = []\n'
49 assert hunks[1].lines[3] == ' self.filename = filename\n'
50 assert hunks[1].lines[4] == (
51 '+ self.diff_source = diff_source or DiffSource()\n'
53 assert hunks[1].lines[-1] == ' self.header = header\n'
55 assert len(hunks[2].lines) == 16
56 assert hunks[2].lines[0] == '@@ -43,11 +52,10 @@ class DiffParser(object):\n'
57 assert hunks[2].lines[-1] == (
58 ' """Writes a new diff corresponding to the user\'s' ' selection."""\n'
62 def test_diff_at_start():
63 fixture_path = helper.fixture('diff-start.txt')
64 patch = diffparse.Patch.parse('foo bar/a', core.read(fixture_path))
65 hunks = patch.hunks
67 assert hunks[0].lines[0] == '@@ -1 +1,4 @@\n'
68 assert hunks[-1].lines[-1] == '+c\n'
69 assert hunks[0].old_start == 1
70 assert hunks[0].old_count == 1
71 assert hunks[0].new_start == 1
72 assert hunks[0].new_count == 4
73 assert patch.extract_subset(1, 3).as_text() == (
74 '--- a/foo bar/a\n' '+++ b/foo bar/a\n' '@@ -1 +1,3 @@\n' ' bar\n' '+a\n' '+b\n'
76 assert patch.extract_subset(0, 4).as_text() == (
77 '--- a/foo bar/a\n'
78 '+++ b/foo bar/a\n'
79 '@@ -1 +1,4 @@\n'
80 ' bar\n'
81 '+a\n'
82 '+b\n'
83 '+c\n'
87 def test_diff_at_end():
88 fixture_path = helper.fixture('diff-end.txt')
89 patch = diffparse.Patch.parse('rijndael.js', core.read(fixture_path))
90 hunks = patch.hunks
92 assert hunks[0].lines[0] == '@@ -1,39 +1 @@\n'
93 assert hunks[-1].lines[-1] == (
94 "+module.exports = require('./build/Release/rijndael');\n"
96 assert hunks[0].old_start == 1
97 assert hunks[0].old_count == 39
98 assert hunks[0].new_start == 1
99 assert hunks[0].new_count == 1
102 def test_diff_that_empties_file():
103 fixture_path = helper.fixture('diff-empty.txt')
104 patch = diffparse.Patch.parse('filename', core.read(fixture_path))
105 hunks = patch.hunks
107 assert hunks[0].lines[0] == '@@ -1,2 +0,0 @@\n'
108 assert hunks[-1].lines[-1] == '-second\n'
109 assert hunks[0].old_start == 1
110 assert hunks[0].old_count == 2
111 assert hunks[0].new_start == 0
112 assert hunks[0].new_count == 0
113 assert patch.extract_subset(1, 1).as_text() == (
114 '--- a/filename\n' '+++ b/filename\n' '@@ -1,2 +1 @@\n' '-first\n' ' second\n'
116 assert patch.extract_subset(0, 2).as_text() == (
117 '--- a/filename\n' '+++ b/filename\n' '@@ -1,2 +0,0 @@\n' '-first\n' '-second\n'
121 def test_diff_file_removal():
122 diff_text = """\
123 deleted file mode 100755
124 @@ -1,1 +0,0 @@
125 -#!/bin/sh
127 patch = diffparse.Patch.parse('deleted.txt', diff_text)
129 expect = 1
130 actual = len(patch.hunks)
131 assert expect == actual
133 # Selecting the first two lines generate no diff
134 expect = ''
135 actual = patch.extract_subset(0, 1).as_text()
136 assert expect == actual
138 # Selecting the last line should generate a line removal
139 expect = """\
140 --- a/deleted.txt
141 +++ b/deleted.txt
142 @@ -1 +0,0 @@
143 -#!/bin/sh
145 actual = patch.extract_subset(1, 2).as_text()
146 assert expect == actual
148 # All three lines should map to the same hunk diff
149 actual = patch.extract_hunk(0).as_text()
150 assert expect == actual
152 actual = patch.extract_hunk(1).as_text()
153 assert expect == actual
155 actual = patch.extract_hunk(2).as_text()
156 assert expect == actual
159 def test_basic_diff_line_count(difflines_data):
160 """Verify the basic line counts"""
161 lines = difflines_data.parser.parse(difflines_data.text)
162 expect = len(difflines_data.text.splitlines())
163 actual = len(lines)
164 assert expect == actual
167 def test_diff_line_count_ranges(difflines_data):
168 parser = difflines_data.parser
169 lines = parser.parse(difflines_data.text)
171 # Diff header
172 line = 0
173 count = 1
174 assert lines[line][0] == parser.DASH
175 assert lines[line][1] == parser.DASH
176 line += count
178 # 3 lines of context
179 count = 3
180 current_old = 6
181 current_new = 6
182 for i in range(count):
183 assert lines[line + i][0] == current_old + i
184 assert lines[line + i][1] == current_new + i
185 line += count
186 current_old += count
187 current_new += count
189 # 10 lines of new text
190 count = 10
191 for i in range(count):
192 assert lines[line + i][0] == parser.EMPTY
193 assert lines[line + i][1] == current_new + i
195 line += count
196 current_new += count
198 # 3 more lines of context
199 count = 3
200 for i in range(count):
201 assert lines[line + i][0] == current_old + i
202 assert lines[line + i][1] == current_new + i
203 line += count
204 current_new += count
205 current_old += count
207 # 1 line of removal
208 count = 1
209 for i in range(count):
210 assert lines[line + i][0] == current_old + i
211 assert lines[line + i][1] == parser.EMPTY
212 line += count
213 current_old += count
215 # 2 lines of addition
216 count = 2
217 for i in range(count):
218 assert lines[line + i][0] == parser.EMPTY
219 assert lines[line + i][1] == current_new + i
220 line += count
221 current_new += count
223 # 3 more lines of context
224 count = 3
225 for i in range(count):
226 assert lines[line + i][0] == current_old + i
227 assert lines[line + i][1] == current_new + i
228 line += count
229 current_new += count
230 current_old += count
232 # 1 line of header
233 count = 1
234 for i in range(count):
235 assert lines[line + i][0] == parser.DASH
236 assert lines[line + i][1] == parser.DASH
237 line += count
239 # 3 more lines of context
240 current_old = 29
241 current_new = 40
242 count = 3
243 for i in range(count):
244 assert lines[line + i][0] == current_old + i
245 assert lines[line + i][1] == current_new + i
246 line += count
247 current_new += count
248 current_old += count
250 expect_max_old = 53
251 assert expect_max_old == parser.old.max_value
253 expect_max_new = 61
254 assert expect_max_new == parser.new.max_value
256 assert parser.digits() == 2
259 def test_diff_line_for_merge(difflines_data):
260 """Verify the basic line counts"""
261 text = """@@@ -1,23 -1,33 +1,75 @@@
262 ++<<<<<<< upstream
266 parser = difflines_data.parser
267 lines = parser.parse(text)
268 assert len(lines) == 4
269 assert len(lines[0]) == 3
270 assert len(lines[1]) == 3
271 assert len(lines[2]) == 3
272 assert len(lines[3]) == 3
274 assert lines[0][0] == parser.DASH
275 assert lines[0][1] == parser.DASH
276 assert lines[0][2] == parser.DASH
278 assert lines[1][0] == parser.EMPTY
279 assert lines[1][1] == parser.EMPTY
280 assert lines[1][2] == 1
282 assert lines[2][0] == 1
283 assert lines[2][1] == parser.EMPTY
284 assert lines[2][2] == 2
286 assert lines[3][0] == 2
287 assert lines[3][1] == parser.EMPTY
288 assert lines[3][2] == 3
291 def test_diff_line_digits(difflines_data):
292 parser = difflines_data.parser
294 text = """@@ -1,99 +1,99 @@"""
295 parser.parse(text)
296 assert parser.digits() == 2
298 text = """@@ -2,99 +2,99 @@"""
299 parser.parse(text)
300 assert parser.digits() == 3
303 def test_format_basic():
304 fmt = diffparse.FormatDigits()
305 fmt.set_digits(2)
307 expect = '01 99'
308 actual = fmt.value(1, 99)
309 assert expect == actual
312 def test_format_reuse():
313 fmt = diffparse.FormatDigits()
315 fmt.set_digits(3)
316 expect = '001 099'
317 actual = fmt.value(1, 99)
318 assert expect == actual
320 fmt.set_digits(4)
321 expect = '0001 0099'
322 actual = fmt.value(1, 99)
323 assert expect == actual
326 def test_format_special_values():
327 fmt = diffparse.FormatDigits(dash='-')
328 fmt.set_digits(3)
330 expect = ' 099'
331 actual = fmt.value(fmt.EMPTY, 99)
332 assert expect == actual
334 expect = '001 '
335 actual = fmt.value(1, fmt.EMPTY)
336 assert expect == actual
338 expect = ' '
339 actual = fmt.value(fmt.EMPTY, fmt.EMPTY)
340 assert expect == actual
342 expect = '--- 001'
343 actual = fmt.value(fmt.DASH, 1)
344 assert expect == actual
346 expect = '099 ---'
347 actual = fmt.value(99, fmt.DASH)
348 assert expect == actual
350 expect = '--- ---'
351 actual = fmt.value(fmt.DASH, fmt.DASH)
352 assert expect == actual
354 expect = ' ---'
355 actual = fmt.value(fmt.EMPTY, fmt.DASH)
356 assert expect == actual
358 expect = '--- '
359 actual = fmt.value(fmt.DASH, fmt.EMPTY)
360 assert expect == actual
363 def test_parse_range_str():
364 start, count = diffparse.parse_range_str('1,2')
365 assert start == 1
366 assert count == 2
369 def test_parse_range_str_single_line():
370 start, count = diffparse.parse_range_str('2')
371 assert start == 2
372 assert count == 1
375 def test_parse_range_str_empty():
376 start, count = diffparse.parse_range_str('0,0')
377 assert start == 0
378 assert count == 0