|
1
|
"""Tests for the split-diff view helper (_compute_split_lines).""" |
|
2
|
|
|
3
|
from fossil.views import _compute_split_lines |
|
4
|
|
|
5
|
|
|
6
|
def _make_line(text, line_type, old_num="", new_num=""): |
|
7
|
"""Build a diff-line dict matching the shape produced by checkin_detail.""" |
|
8
|
if line_type in ("add", "del", "context") and text: |
|
9
|
prefix = text[0] |
|
10
|
code = text[1:] |
|
11
|
else: |
|
12
|
prefix = "" |
|
13
|
code = text |
|
14
|
return { |
|
15
|
"text": text, |
|
16
|
"type": line_type, |
|
17
|
"old_num": old_num, |
|
18
|
"new_num": new_num, |
|
19
|
"prefix": prefix, |
|
20
|
"code": code, |
|
21
|
} |
|
22
|
|
|
23
|
|
|
24
|
class TestComputeSplitLines: |
|
25
|
"""Unit tests for _compute_split_lines.""" |
|
26
|
|
|
27
|
def test_context_lines_appear_on_both_sides(self): |
|
28
|
lines = [ |
|
29
|
_make_line(" hello", "context", old_num=1, new_num=1), |
|
30
|
_make_line(" world", "context", old_num=2, new_num=2), |
|
31
|
] |
|
32
|
left, right = _compute_split_lines(lines) |
|
33
|
assert len(left) == 2 |
|
34
|
assert len(right) == 2 |
|
35
|
assert left[0]["text"] == " hello" |
|
36
|
assert right[0]["text"] == " hello" |
|
37
|
assert left[1]["text"] == " world" |
|
38
|
assert right[1]["text"] == " world" |
|
39
|
|
|
40
|
def test_deletion_only_on_left(self): |
|
41
|
lines = [ |
|
42
|
_make_line("-removed", "del", old_num=5), |
|
43
|
] |
|
44
|
left, right = _compute_split_lines(lines) |
|
45
|
assert len(left) == 1 |
|
46
|
assert len(right) == 1 |
|
47
|
assert left[0]["type"] == "del" |
|
48
|
assert left[0]["text"] == "-removed" |
|
49
|
assert right[0]["type"] == "empty" |
|
50
|
assert right[0]["text"] == "" |
|
51
|
|
|
52
|
def test_addition_only_on_right(self): |
|
53
|
lines = [ |
|
54
|
_make_line("+added", "add", new_num=10), |
|
55
|
] |
|
56
|
left, right = _compute_split_lines(lines) |
|
57
|
assert len(left) == 1 |
|
58
|
assert len(right) == 1 |
|
59
|
assert left[0]["type"] == "empty" |
|
60
|
assert right[0]["type"] == "add" |
|
61
|
assert right[0]["text"] == "+added" |
|
62
|
|
|
63
|
def test_paired_del_add_block(self): |
|
64
|
"""Adjacent del+add lines should be paired row-by-row.""" |
|
65
|
lines = [ |
|
66
|
_make_line("-old_a", "del", old_num=1), |
|
67
|
_make_line("-old_b", "del", old_num=2), |
|
68
|
_make_line("+new_a", "add", new_num=1), |
|
69
|
_make_line("+new_b", "add", new_num=2), |
|
70
|
] |
|
71
|
left, right = _compute_split_lines(lines) |
|
72
|
assert len(left) == 2 |
|
73
|
assert len(right) == 2 |
|
74
|
assert left[0]["type"] == "del" |
|
75
|
assert right[0]["type"] == "add" |
|
76
|
assert left[1]["type"] == "del" |
|
77
|
assert right[1]["type"] == "add" |
|
78
|
|
|
79
|
def test_unequal_del_add_pads_with_empty(self): |
|
80
|
"""When there are more dels than adds, right side gets empty placeholders.""" |
|
81
|
lines = [ |
|
82
|
_make_line("-old_a", "del", old_num=1), |
|
83
|
_make_line("-old_b", "del", old_num=2), |
|
84
|
_make_line("-old_c", "del", old_num=3), |
|
85
|
_make_line("+new_a", "add", new_num=1), |
|
86
|
] |
|
87
|
left, right = _compute_split_lines(lines) |
|
88
|
assert len(left) == 3 |
|
89
|
assert len(right) == 3 |
|
90
|
assert left[0]["type"] == "del" |
|
91
|
assert right[0]["type"] == "add" |
|
92
|
assert left[1]["type"] == "del" |
|
93
|
assert right[1]["type"] == "empty" |
|
94
|
assert left[2]["type"] == "del" |
|
95
|
assert right[2]["type"] == "empty" |
|
96
|
|
|
97
|
def test_more_adds_than_dels_pads_left(self): |
|
98
|
"""When there are more adds than dels, left side gets empty placeholders.""" |
|
99
|
lines = [ |
|
100
|
_make_line("-old", "del", old_num=1), |
|
101
|
_make_line("+new_a", "add", new_num=1), |
|
102
|
_make_line("+new_b", "add", new_num=2), |
|
103
|
] |
|
104
|
left, right = _compute_split_lines(lines) |
|
105
|
assert len(left) == 2 |
|
106
|
assert len(right) == 2 |
|
107
|
assert left[0]["type"] == "del" |
|
108
|
assert right[0]["type"] == "add" |
|
109
|
assert left[1]["type"] == "empty" |
|
110
|
assert right[1]["type"] == "add" |
|
111
|
|
|
112
|
def test_hunk_and_header_lines_on_both_sides(self): |
|
113
|
lines = [ |
|
114
|
_make_line("--- a/file.py", "header"), |
|
115
|
_make_line("+++ b/file.py", "header"), |
|
116
|
_make_line("@@ -1,3 +1,3 @@", "hunk"), |
|
117
|
_make_line(" ctx", "context", old_num=1, new_num=1), |
|
118
|
] |
|
119
|
left, right = _compute_split_lines(lines) |
|
120
|
assert len(left) == 4 |
|
121
|
assert len(right) == 4 |
|
122
|
assert left[0]["type"] == "header" |
|
123
|
assert right[0]["type"] == "header" |
|
124
|
assert left[2]["type"] == "hunk" |
|
125
|
assert right[2]["type"] == "hunk" |
|
126
|
assert left[3]["type"] == "context" |
|
127
|
assert right[3]["type"] == "context" |
|
128
|
|
|
129
|
def test_mixed_sequence(self): |
|
130
|
"""Full realistic sequence: header, hunk, context, del, add, context.""" |
|
131
|
lines = [ |
|
132
|
_make_line("--- a/f.py", "header"), |
|
133
|
_make_line("+++ b/f.py", "header"), |
|
134
|
_make_line("@@ -1,4 +1,4 @@", "hunk"), |
|
135
|
_make_line(" line1", "context", old_num=1, new_num=1), |
|
136
|
_make_line("-old2", "del", old_num=2), |
|
137
|
_make_line("+new2", "add", new_num=2), |
|
138
|
_make_line(" line3", "context", old_num=3, new_num=3), |
|
139
|
] |
|
140
|
left, right = _compute_split_lines(lines) |
|
141
|
# header(2) + hunk(1) + context(1) + paired del/add(1) + context(1) = 6 |
|
142
|
assert len(left) == 6 |
|
143
|
assert len(right) == 6 |
|
144
|
# Check paired del/add at index 4 |
|
145
|
assert left[4]["type"] == "del" |
|
146
|
assert right[4]["type"] == "add" |
|
147
|
|
|
148
|
def test_empty_input(self): |
|
149
|
left, right = _compute_split_lines([]) |
|
150
|
assert left == [] |
|
151
|
assert right == [] |
|
152
|
|
|
153
|
def test_orphan_add_without_preceding_del(self): |
|
154
|
"""An add line not preceded by a del should still work.""" |
|
155
|
lines = [ |
|
156
|
_make_line(" ctx", "context", old_num=1, new_num=1), |
|
157
|
_make_line("+new", "add", new_num=2), |
|
158
|
_make_line(" ctx2", "context", old_num=2, new_num=3), |
|
159
|
] |
|
160
|
left, right = _compute_split_lines(lines) |
|
161
|
assert len(left) == 3 |
|
162
|
assert len(right) == 3 |
|
163
|
assert left[1]["type"] == "empty" |
|
164
|
assert right[1]["type"] == "add" |
|
165
|
|