1 | // Copyright 2019 The Go Authors. All rights reserved. |
---|---|
2 | // Use of this source code is governed by a BSD-style |
3 | // license that can be found in the LICENSE file. |
4 | |
5 | // Package difftest supplies a set of tests that will operate on any |
6 | // implementation of a diff algorithm as exposed by |
7 | // "golang.org/x/tools/internal/diff" |
8 | package difftest |
9 | |
10 | import ( |
11 | "testing" |
12 | |
13 | "golang.org/x/tools/internal/diff" |
14 | ) |
15 | |
16 | const ( |
17 | FileA = "from" |
18 | FileB = "to" |
19 | UnifiedPrefix = "--- " + FileA + "\n+++ " + FileB + "\n" |
20 | ) |
21 | |
22 | var TestCases = []struct { |
23 | Name, In, Out, Unified string |
24 | Edits, LineEdits []diff.Edit |
25 | NoDiff bool |
26 | }{{ |
27 | Name: "empty", |
28 | In: "", |
29 | Out: "", |
30 | }, { |
31 | Name: "no_diff", |
32 | In: "gargantuan\n", |
33 | Out: "gargantuan\n", |
34 | }, { |
35 | Name: "replace_all", |
36 | In: "fruit\n", |
37 | Out: "cheese\n", |
38 | Unified: UnifiedPrefix + ` |
39 | @@ -1 +1 @@ |
40 | -fruit |
41 | +cheese |
42 | `[1:], |
43 | Edits: []diff.Edit{{Start: 0, End: 5, New: "cheese"}}, |
44 | LineEdits: []diff.Edit{{Start: 0, End: 6, New: "cheese\n"}}, |
45 | }, { |
46 | Name: "insert_rune", |
47 | In: "gord\n", |
48 | Out: "gourd\n", |
49 | Unified: UnifiedPrefix + ` |
50 | @@ -1 +1 @@ |
51 | -gord |
52 | +gourd |
53 | `[1:], |
54 | Edits: []diff.Edit{{Start: 2, End: 2, New: "u"}}, |
55 | LineEdits: []diff.Edit{{Start: 0, End: 5, New: "gourd\n"}}, |
56 | }, { |
57 | Name: "delete_rune", |
58 | In: "groat\n", |
59 | Out: "goat\n", |
60 | Unified: UnifiedPrefix + ` |
61 | @@ -1 +1 @@ |
62 | -groat |
63 | +goat |
64 | `[1:], |
65 | Edits: []diff.Edit{{Start: 1, End: 2, New: ""}}, |
66 | LineEdits: []diff.Edit{{Start: 0, End: 6, New: "goat\n"}}, |
67 | }, { |
68 | Name: "replace_rune", |
69 | In: "loud\n", |
70 | Out: "lord\n", |
71 | Unified: UnifiedPrefix + ` |
72 | @@ -1 +1 @@ |
73 | -loud |
74 | +lord |
75 | `[1:], |
76 | Edits: []diff.Edit{{Start: 2, End: 3, New: "r"}}, |
77 | LineEdits: []diff.Edit{{Start: 0, End: 5, New: "lord\n"}}, |
78 | }, { |
79 | Name: "replace_partials", |
80 | In: "blanket\n", |
81 | Out: "bunker\n", |
82 | Unified: UnifiedPrefix + ` |
83 | @@ -1 +1 @@ |
84 | -blanket |
85 | +bunker |
86 | `[1:], |
87 | Edits: []diff.Edit{ |
88 | {Start: 1, End: 3, New: "u"}, |
89 | {Start: 6, End: 7, New: "r"}, |
90 | }, |
91 | LineEdits: []diff.Edit{{Start: 0, End: 8, New: "bunker\n"}}, |
92 | }, { |
93 | Name: "insert_line", |
94 | In: "1: one\n3: three\n", |
95 | Out: "1: one\n2: two\n3: three\n", |
96 | Unified: UnifiedPrefix + ` |
97 | @@ -1,2 +1,3 @@ |
98 | 1: one |
99 | +2: two |
100 | 3: three |
101 | `[1:], |
102 | Edits: []diff.Edit{{Start: 7, End: 7, New: "2: two\n"}}, |
103 | }, { |
104 | Name: "replace_no_newline", |
105 | In: "A", |
106 | Out: "B", |
107 | Unified: UnifiedPrefix + ` |
108 | @@ -1 +1 @@ |
109 | -A |
110 | \ No newline at end of file |
111 | +B |
112 | \ No newline at end of file |
113 | `[1:], |
114 | Edits: []diff.Edit{{Start: 0, End: 1, New: "B"}}, |
115 | }, { |
116 | Name: "append_empty", |
117 | In: "", // GNU diff -u special case: -0,0 |
118 | Out: "AB\nC", |
119 | Unified: UnifiedPrefix + ` |
120 | @@ -0,0 +1,2 @@ |
121 | +AB |
122 | +C |
123 | \ No newline at end of file |
124 | `[1:], |
125 | Edits: []diff.Edit{{Start: 0, End: 0, New: "AB\nC"}}, |
126 | LineEdits: []diff.Edit{{Start: 0, End: 0, New: "AB\nC"}}, |
127 | }, |
128 | // TODO(adonovan): fix this test: GNU diff -u prints "+1,2", Unifies prints "+1,3". |
129 | // { |
130 | // Name: "add_start", |
131 | // In: "A", |
132 | // Out: "B\nCA", |
133 | // Unified: UnifiedPrefix + ` |
134 | // @@ -1 +1,2 @@ |
135 | // -A |
136 | // \ No newline at end of file |
137 | // +B |
138 | // +CA |
139 | // \ No newline at end of file |
140 | // `[1:], |
141 | // Edits: []diff.TextEdit{{Span: newSpan(0, 0), NewText: "B\nC"}}, |
142 | // LineEdits: []diff.TextEdit{{Span: newSpan(0, 0), NewText: "B\nC"}}, |
143 | // }, |
144 | { |
145 | Name: "add_end", |
146 | In: "A", |
147 | Out: "AB", |
148 | Unified: UnifiedPrefix + ` |
149 | @@ -1 +1 @@ |
150 | -A |
151 | \ No newline at end of file |
152 | +AB |
153 | \ No newline at end of file |
154 | `[1:], |
155 | Edits: []diff.Edit{{Start: 1, End: 1, New: "B"}}, |
156 | LineEdits: []diff.Edit{{Start: 0, End: 1, New: "AB"}}, |
157 | }, { |
158 | Name: "add_empty", |
159 | In: "", |
160 | Out: "AB\nC", |
161 | Unified: UnifiedPrefix + ` |
162 | @@ -0,0 +1,2 @@ |
163 | +AB |
164 | +C |
165 | \ No newline at end of file |
166 | `[1:], |
167 | Edits: []diff.Edit{{Start: 0, End: 0, New: "AB\nC"}}, |
168 | LineEdits: []diff.Edit{{Start: 0, End: 0, New: "AB\nC"}}, |
169 | }, { |
170 | Name: "add_newline", |
171 | In: "A", |
172 | Out: "A\n", |
173 | Unified: UnifiedPrefix + ` |
174 | @@ -1 +1 @@ |
175 | -A |
176 | \ No newline at end of file |
177 | +A |
178 | `[1:], |
179 | Edits: []diff.Edit{{Start: 1, End: 1, New: "\n"}}, |
180 | LineEdits: []diff.Edit{{Start: 0, End: 1, New: "A\n"}}, |
181 | }, { |
182 | Name: "delete_front", |
183 | In: "A\nB\nC\nA\nB\nB\nA\n", |
184 | Out: "C\nB\nA\nB\nA\nC\n", |
185 | Unified: UnifiedPrefix + ` |
186 | @@ -1,7 +1,6 @@ |
187 | -A |
188 | -B |
189 | C |
190 | +B |
191 | A |
192 | B |
193 | -B |
194 | A |
195 | +C |
196 | `[1:], |
197 | NoDiff: true, // unified diff is different but valid |
198 | Edits: []diff.Edit{ |
199 | {Start: 0, End: 4, New: ""}, |
200 | {Start: 6, End: 6, New: "B\n"}, |
201 | {Start: 10, End: 12, New: ""}, |
202 | {Start: 14, End: 14, New: "C\n"}, |
203 | }, |
204 | }, { |
205 | Name: "replace_last_line", |
206 | In: "A\nB\n", |
207 | Out: "A\nC\n\n", |
208 | Unified: UnifiedPrefix + ` |
209 | @@ -1,2 +1,3 @@ |
210 | A |
211 | -B |
212 | +C |
213 | + |
214 | `[1:], |
215 | Edits: []diff.Edit{{Start: 2, End: 3, New: "C\n"}}, |
216 | LineEdits: []diff.Edit{{Start: 2, End: 4, New: "C\n\n"}}, |
217 | }, |
218 | { |
219 | Name: "multiple_replace", |
220 | In: "A\nB\nC\nD\nE\nF\nG\n", |
221 | Out: "A\nH\nI\nJ\nE\nF\nK\n", |
222 | Unified: UnifiedPrefix + ` |
223 | @@ -1,7 +1,7 @@ |
224 | A |
225 | -B |
226 | -C |
227 | -D |
228 | +H |
229 | +I |
230 | +J |
231 | E |
232 | F |
233 | -G |
234 | +K |
235 | `[1:], |
236 | Edits: []diff.Edit{ |
237 | {Start: 2, End: 8, New: "H\nI\nJ\n"}, |
238 | {Start: 12, End: 14, New: "K\n"}, |
239 | }, |
240 | NoDiff: true, // diff algorithm produces different delete/insert pattern |
241 | }, |
242 | } |
243 | |
244 | func DiffTest(t *testing.T, compute func(before, after string) []diff.Edit) { |
245 | for _, test := range TestCases { |
246 | t.Run(test.Name, func(t *testing.T) { |
247 | edits := compute(test.In, test.Out) |
248 | got, err := diff.Apply(test.In, edits) |
249 | if err != nil { |
250 | t.Fatalf("Apply failed: %v", err) |
251 | } |
252 | unified, err := diff.ToUnified(FileA, FileB, test.In, edits) |
253 | if err != nil { |
254 | t.Fatalf("ToUnified: %v", err) |
255 | } |
256 | if got != test.Out { |
257 | t.Errorf("Apply: got patched:\n%v\nfrom diff:\n%v\nexpected:\n%v", got, unified, test.Out) |
258 | } |
259 | if !test.NoDiff && unified != test.Unified { |
260 | t.Errorf("Unified: got diff:\n%v\nexpected:\n%v", unified, test.Unified) |
261 | } |
262 | }) |
263 | } |
264 | } |
265 |
Members