1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 package org.eclipse.jgit.merge;
45
46 import static org.junit.Assert.assertEquals;
47
48 import java.io.ByteArrayOutputStream;
49 import java.io.IOException;
50
51 import org.eclipse.jgit.diff.RawText;
52 import org.eclipse.jgit.diff.RawTextComparator;
53 import org.eclipse.jgit.lib.Constants;
54 import org.junit.Assume;
55 import org.junit.Test;
56 import org.junit.experimental.theories.DataPoints;
57 import org.junit.experimental.theories.Theories;
58 import org.junit.runner.RunWith;
59
60 @RunWith(Theories.class)
61 public class MergeAlgorithmTest {
62 MergeFormatter fmt=new MergeFormatter();
63
64 private final boolean newlineAtEnd;
65
66 @DataPoints
67 public static boolean[] newlineAtEndDataPoints = { false, true };
68
69 public MergeAlgorithmTest(boolean newlineAtEnd) {
70 this.newlineAtEnd = newlineAtEnd;
71 }
72
73
74
75
76
77
78
79 @Test
80 public void testTwoConflictingModifications() throws IOException {
81 assertEquals(t("a<b=Z>Zdefghij"),
82 merge("abcdefghij", "abZdefghij", "aZZdefghij"));
83 }
84
85
86
87
88
89
90
91
92 @Test
93 public void testOneAgainstTwoConflictingModifications() throws IOException {
94 assertEquals(t("aZ<Z=c>Zefghij"),
95 merge("abcdefghij", "aZZZefghij", "aZcZefghij"));
96 }
97
98
99
100
101
102
103
104 @Test
105 public void testNoAgainstOneModification() throws IOException {
106 assertEquals(t("aZcZefghij"),
107 merge("abcdefghij", "abcdefghij", "aZcZefghij"));
108 }
109
110
111
112
113
114
115
116 @Test
117 public void testTwoNonConflictingModifications() throws IOException {
118 assertEquals(t("YbZdefghij"),
119 merge("abcdefghij", "abZdefghij", "Ybcdefghij"));
120 }
121
122
123
124
125
126
127
128 @Test
129 public void testTwoComplicatedModifications() throws IOException {
130 assertEquals(t("a<ZZZZfZhZj=bYdYYYYiY>"),
131 merge("abcdefghij", "aZZZZfZhZj", "abYdYYYYiY"));
132 }
133
134
135
136
137
138
139
140
141 @Test
142 public void testTwoModificationsWithSharedDelete() throws IOException {
143 assertEquals(t("Cb}n}"),
144 merge("ab}n}n}", "ab}n}", "Cb}n}"));
145 }
146
147
148
149
150
151
152
153
154 @Test
155 public void testModificationsWithMiddleInsert() throws IOException {
156 assertEquals(t("aBcd123123uvwxPq"),
157 merge("abcd123uvwxpq", "aBcd123123uvwxPq", "abcd123123uvwxpq"));
158 }
159
160
161
162
163
164
165
166
167 @Test
168 public void testModificationsWithMiddleDelete() throws IOException {
169 assertEquals(t("Abz}z123Q"),
170 merge("abz}z}z123q", "Abz}z123Q", "abz}z123q"));
171 }
172
173
174
175
176
177
178 @Test
179 public void testConflictAtStart() throws IOException {
180 assertEquals(t("<Z=Y>bcdefghij"),
181 merge("abcdefghij", "Zbcdefghij", "Ybcdefghij"));
182 }
183
184
185
186
187
188
189 @Test
190 public void testConflictAtEnd() throws IOException {
191 assertEquals(t("abcdefghi<Z=Y>"),
192 merge("abcdefghij", "abcdefghiZ", "abcdefghiY"));
193 }
194
195
196
197
198
199
200
201 @Test
202 public void testSameModification() throws IOException {
203 assertEquals(t("abZdefghij"),
204 merge("abcdefghij", "abZdefghij", "abZdefghij"));
205 }
206
207
208
209
210
211
212
213 @Test
214 public void testDeleteVsModify() throws IOException {
215 assertEquals(t("ab<=Z>defghij"),
216 merge("abcdefghij", "abdefghij", "abZdefghij"));
217 }
218
219 @Test
220 public void testInsertVsModify() throws IOException {
221 assertEquals(t("a<bZ=XY>"), merge("ab", "abZ", "aXY"));
222 }
223
224 @Test
225 public void testAdjacentModifications() throws IOException {
226 assertEquals(t("a<Zc=bY>d"), merge("abcd", "aZcd", "abYd"));
227 }
228
229 @Test
230 public void testSeparateModifications() throws IOException {
231 assertEquals(t("aZcYe"), merge("abcde", "aZcde", "abcYe"));
232 }
233
234 @Test
235 public void testBlankLines() throws IOException {
236 assertEquals(t("aZc\nYe"), merge("abc\nde", "aZc\nde", "abc\nYe"));
237 }
238
239
240
241
242
243
244
245
246
247 @Test
248 public void testTwoSimilarModsAndOneInsert() throws IOException {
249 assertEquals(t("aBcDde"), merge("abcde", "aBcde", "aBcDde"));
250 assertEquals(t("IAAAJCAB"), merge("iACAB", "IACAB", "IAAAJCAB"));
251 assertEquals(t("HIAAAJCAB"), merge("HiACAB", "HIACAB", "HIAAAJCAB"));
252 assertEquals(t("AGADEFHIAAAJCAB"),
253 merge("AGADEFHiACAB", "AGADEFHIACAB", "AGADEFHIAAAJCAB"));
254 }
255
256
257
258
259
260
261
262
263
264 @Test
265 public void testTwoSimilarModsAndOneInsertAtEnd() throws IOException {
266 Assume.assumeTrue(newlineAtEnd);
267 assertEquals(t("IAAJ"), merge("iA", "IA", "IAAJ"));
268 assertEquals(t("IAJ"), merge("iA", "IA", "IAJ"));
269 assertEquals(t("IAAAJ"), merge("iA", "IA", "IAAAJ"));
270 }
271
272 @Test
273 public void testTwoSimilarModsAndOneInsertAtEndNoNewlineAtEnd()
274 throws IOException {
275 Assume.assumeFalse(newlineAtEnd);
276 assertEquals(t("I<A=AAJ>"), merge("iA", "IA", "IAAJ"));
277 assertEquals(t("I<A=AJ>"), merge("iA", "IA", "IAJ"));
278 assertEquals(t("I<A=AAAJ>"), merge("iA", "IA", "IAAAJ"));
279 }
280
281
282
283
284
285
286 @Test
287 public void testEmptyTexts() throws IOException {
288
289 assertEquals(t("<AB=>"), merge("A", "AB", ""));
290 assertEquals(t("<=AB>"), merge("A", "", "AB"));
291
292
293 assertEquals(t(""), merge("AB", "AB", ""));
294 assertEquals(t(""), merge("AB", "", "AB"));
295
296
297 assertEquals(t(""), merge("AB", "", ""));
298 }
299
300 private String merge(String commonBase, String ours, String theirs) throws IOException {
301 MergeResult r = new MergeAlgorithm().merge(RawTextComparator.DEFAULT,
302 T(commonBase), T(ours), T(theirs));
303 ByteArrayOutputStream bo=new ByteArrayOutputStream(50);
304 fmt.formatMerge(bo, r, "B", "O", "T", Constants.CHARACTER_ENCODING);
305 return new String(bo.toByteArray(), Constants.CHARACTER_ENCODING);
306 }
307
308 public String t(String text) {
309 StringBuilder r = new StringBuilder();
310 for (int i = 0; i < text.length(); i++) {
311 char c = text.charAt(i);
312 switch (c) {
313 case '<':
314 r.append("<<<<<<< O\n");
315 break;
316 case '=':
317 r.append("=======\n");
318 break;
319 case '>':
320 r.append(">>>>>>> T\n");
321 break;
322 default:
323 r.append(c);
324 if (newlineAtEnd || i < text.length() - 1)
325 r.append('\n');
326 }
327 }
328 return r.toString();
329 }
330
331 public RawText T(String text) {
332 return new RawText(Constants.encode(t(text)));
333 }
334 }