1 /*
2 SPDX-FileCopyrightText: 2011 Dmitry Risenberg <dmitry.risenberg@gmail.com>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6
7 #include "interactivedifftest.h"
8
9 #include <QTest>
10 #include "diffmodel.h"
11 #include "diffmodellist.h"
12 #include "parser.h"
13
14 using namespace Diff2;
15
16 typedef QHash<int, QPair<QStringList, QStringList> > DifferenceHash;
17 Q_DECLARE_METATYPE(DifferenceHash);
18 typedef QHash<int, QPair<int, int> > LineNumberHash;
19 Q_DECLARE_METATYPE(LineNumberHash);
20
CompareDifferenceStringList(const DifferenceStringList & actual,const QStringList & expected)21 void InteractiveDiffTest::CompareDifferenceStringList(const DifferenceStringList& actual, const QStringList& expected)
22 {
23 DifferenceStringListConstIterator actualIter;
24 QStringList::const_iterator expectedIter;
25 for (actualIter = actual.constBegin(), expectedIter = expected.constBegin(); actualIter != actual.constEnd() && expectedIter != expected.constEnd(); ++actualIter, ++expectedIter) {
26 QCOMPARE((*actualIter)->string(), *expectedIter);
27 }
28 if (actualIter != actual.constEnd()) {
29 QFAIL(QStringLiteral("Actual has too many items, starting with '%1', line %2").arg((*actualIter)->string()).arg(actualIter - actual.constBegin()).toLatin1().constData());
30 }
31 if (expectedIter != expected.constEnd()) {
32 QFAIL(QStringLiteral("Actual has too few items, no match for '%1', line %2").arg(*expectedIter).arg(expectedIter - expected.constBegin()).toLatin1().constData());
33 }
34 }
35
36 // The most basic test - something is actually working
testOneLineChange()37 void InteractiveDiffTest::testOneLineChange()
38 {
39 DiffModel* model = new DiffModel();
40 QStringList newLines;
41 newLines << "newline\n";
42 QStringList oldLines;
43 oldLines << "oldline\n";
44 model->linesChanged(oldLines, newLines, 2);
45 QCOMPARE(model->differences()->size(), 1);
46
47 QCOMPARE(model->differenceCount(), 1);
48 const Difference* diff = model->differenceAt(0);
49 CompareDifferenceStringList(diff->sourceLines(), oldLines);
50 CompareDifferenceStringList(diff->destinationLines(), newLines);
51 QCOMPARE(diff->type(), int(Difference::Change));
52 }
53
testSameLine()54 void InteractiveDiffTest::testSameLine()
55 {
56 DiffModel* model = new DiffModel();
57 QStringList newLines;
58 newLines << "oldline2\n";
59 QStringList oldLines;
60 oldLines << "oldline1\n" << "oldline2\n";
61 model->linesChanged(oldLines, newLines, 2);
62
63 QCOMPARE(model->differenceCount(), 1);
64 const Difference* diff = model->differenceAt(0);
65 CompareDifferenceStringList(diff->sourceLines(), QStringList() << "oldline1\n");
66 CompareDifferenceStringList(diff->destinationLines(), QStringList());
67 QCOMPARE(diff->type(), int(Difference::Delete));
68 }
69
testDifferenceContents()70 void InteractiveDiffTest::testDifferenceContents()
71 {
72 QFETCH(QStringList, patch);
73 Parser parser(nullptr);
74 bool malformed;
75 DiffModelList* models = parser.parse(patch, &malformed);
76 QVERIFY(!malformed);
77 QCOMPARE(models->size(), 1);
78 DiffModel* model = models->at(0);
79
80 QFETCH(QStringList, oldLines);
81 QFETCH(QStringList, newLines);
82 QFETCH(int, editLineNumber);
83 QFETCH(bool, isAlreadyApplied);
84 model->applyAllDifferences(isAlreadyApplied);
85 model->linesChanged(oldLines, newLines, editLineNumber);
86 QFETCH(int, expectedDifferenceCount);
87 QCOMPARE(model->differenceCount(), expectedDifferenceCount);
88
89 QFETCH(DifferenceHash, expectedDifferences);
90 for (DifferenceHash::ConstIterator iter = expectedDifferences.constBegin(); iter != expectedDifferences.constEnd(); ++iter) {
91 const Difference* diff = model->differenceAt(iter.key());
92 CompareDifferenceStringList(diff->sourceLines(), iter.value().first);
93 CompareDifferenceStringList(diff->destinationLines(), iter.value().second);
94 }
95 }
96
testDifferenceContents_data()97 void InteractiveDiffTest::testDifferenceContents_data()
98 {
99 QTest::addColumn<QStringList>("patch");
100 QTest::addColumn<QStringList>("oldLines"); // lines that are replaced
101 QTest::addColumn<QStringList>("newLines"); // replacement lines
102 QTest::addColumn<int>("editLineNumber");
103 QTest::addColumn<bool>("isAlreadyApplied");
104 QTest::addColumn<int>("expectedDifferenceCount");
105 QTest::addColumn<DifferenceHash>("expectedDifferences");
106
107 {
108 QStringList patch;
109 patch <<
110 "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
111 "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
112 "@@ -1,5 +1,5 @@\n" <<
113 " abcd\n" <<
114 "-delete1\n" <<
115 "+insert1\n" <<
116 " efgh\n" <<
117 "-delete2\n" <<
118 "+insert2\n" <<
119 " ijkl\n";
120
121 QStringList newLines;
122 newLines << "newline1\n" << "newline2\n";
123 QStringList oldLines;
124 oldLines << "efgh\n";
125 QStringList sourceLines;
126 sourceLines << "delete1\n" << "efgh\n" << "delete2\n";
127 QStringList destinationLines;
128 destinationLines << "insert1\n" << "newline1\n" << "newline2\n" << "insert2\n";
129 DifferenceHash expectedDifferences;
130 expectedDifferences.insert(0, qMakePair(sourceLines, destinationLines));
131
132 QTest::newRow("Merge adjacent differences") << patch << oldLines << newLines << 3 << true << 1 << expectedDifferences;
133 }
134 {
135 QStringList patch;
136 patch <<
137 "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
138 "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
139 "@@ -1,4 +1,4 @@\n" <<
140 " abcd\n" <<
141 "-delete1\n" <<
142 "-delete2\n" <<
143 "+insert1\n" <<
144 "+insert2\n" <<
145 " efgh\n";
146
147 QStringList newLines;
148 newLines << "newline1\n";
149 QStringList oldLines;
150 oldLines << "efgh\n";
151 QStringList sourceLines;
152 sourceLines << "delete1\n" << "delete2\n" << "efgh\n";
153 QStringList destinationLines;
154 destinationLines << "insert1\n" << "insert2\n" << "newline1\n";
155 DifferenceHash expectedDifferences;
156 expectedDifferences.insert(0, qMakePair(sourceLines, destinationLines));
157
158 // Append a line to a multiline diff
159 QTest::newRow("Append multiline") << patch << oldLines << newLines << 4 << true << 1 << expectedDifferences;
160 }
161 {
162 QStringList patch;
163 patch <<
164 "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
165 "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
166 "@@ -1,3 +1,3 @@\n" <<
167 " abcd\n" <<
168 "-delete1\n" <<
169 "+insert1\n" <<
170 " efgh\n";
171
172 QStringList newLines;
173 newLines << "delete1\n";
174 QStringList oldLines;
175 oldLines << "insert1\n";
176 QTest::newRow("Revert existing difference") << patch << oldLines << newLines << 2 << true << 0 << DifferenceHash();
177 }
178 {
179 QStringList patch;
180 patch <<
181 "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
182 "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
183 "@@ -1,3 +1,2 @@\n" <<
184 " abcd\n" <<
185 "-delete1\n" <<
186 " efgh\n";
187
188 QStringList newLines;
189 newLines << "abcd\n" << "delete1\n";
190 QStringList oldLines;
191 oldLines << "abcd\n";
192 QTest::newRow("Revert deletion") << patch << oldLines << newLines << 1 << true << 0 << DifferenceHash();
193 }
194 {
195 QStringList patch;
196 patch <<
197 "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
198 "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
199 "@@ -1,4 +1,5 @@\n" <<
200 " abcd\n" <<
201 "-delete1\n" <<
202 "-delete2\n" <<
203 "+insert1\n" <<
204 "+insert2\n" <<
205 "+insert3\n" <<
206 " efgh\n";
207
208 QStringList newLines;
209 newLines << "delete2\n";
210 QStringList oldLines;
211 oldLines << "insert2\n";
212 DifferenceHash expectedDifferences;
213 expectedDifferences.insert(0, qMakePair(QStringList() << "delete1\n", QStringList() << "insert1\n"));
214 expectedDifferences.insert(1, qMakePair(QStringList(), QStringList() << "insert3\n"));
215
216 QTest::newRow("Partial reversion") << patch << oldLines << newLines << 3 << true << 2 << expectedDifferences;
217 }
218 {
219 QStringList patch;
220 patch <<
221 "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
222 "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
223 "@@ -1,4 +1,4 @@\n" <<
224 " abcd\n" <<
225 "-delete1\n" <<
226 "-delete2\n" <<
227 "+insert1\n" <<
228 "+insert2\n" <<
229 " efgh\n";
230
231 QStringList newLines;
232 newLines << "newline1\n" << "newline2\n";
233 QStringList oldLines;
234 oldLines << "abcd\n" << "insert1\n" << "insert2\n" << "efgh\n";
235 QStringList sourceLines;
236 sourceLines << "abcd\n" << "delete1\n" << "delete2\n" << "efgh\n";
237 QStringList destinationLines;
238 destinationLines << "newline1\n" << "newline2\n";
239 DifferenceHash expectedDifferences;
240 expectedDifferences.insert(0, qMakePair(sourceLines, destinationLines));
241
242 // The first existing difference inside the edit
243 QTest::newRow("First inside") << patch << oldLines << newLines << 1 << true << 1 << expectedDifferences;
244 }
245 {
246 QStringList patch;
247 patch <<
248 "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
249 "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
250 "@@ -1,4 +1,4 @@\n" <<
251 " abcd\n" <<
252 "-delete1\n" <<
253 "-delete2\n" <<
254 "+insert1\n" <<
255 "+insert2\n" <<
256 " efgh\n";
257
258 QStringList newLines;
259 newLines << "newline1\n" << "newline2\n";
260 QStringList oldLines;
261 oldLines << "insert2\n" << "efgh\n";
262 QStringList sourceLines;
263 sourceLines << "delete1\n" << "delete2\n" << "efgh\n";
264 QStringList destinationLines;
265 destinationLines << "insert1\n" << "newline1\n" << "newline2\n";
266 DifferenceHash expectedDifferences;
267 expectedDifferences.insert(0, qMakePair(sourceLines, destinationLines));
268
269 // The first existing difference intersects with the edit
270 QTest::newRow("First intersects") << patch << oldLines << newLines << 3 << true << 1 << expectedDifferences;
271 }
272 {
273 QStringList patch;
274 patch <<
275 "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
276 "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
277 "@@ -1,2 +1,3 @@\n" <<
278 " abcd\n" <<
279 "+\n" <<
280 " efgh\n";
281
282 QStringList newLines;
283 newLines << "a\n";
284 QStringList oldLines;
285 oldLines << "\n";
286 DifferenceHash expectedDifferences;
287 expectedDifferences.insert(0, qMakePair(QStringList(), QStringList() << "a\n"));
288
289 QTest::newRow("Replace empty line") << patch << oldLines << newLines << 2 << true << 1 << expectedDifferences;
290 }
291 {
292 QStringList patch;
293 patch <<
294 "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
295 "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
296 "@@ -1,3 +1,3 @@\n" <<
297 " abcd\n" <<
298 "+insert1\n" <<
299 "+insert2\n" <<
300 "+insert3\n" <<
301 "+insert4\n" <<
302 "+insert5\n" <<
303 " efgh\n" <<
304 "@@ -10,3 +15,3 @@\n" <<
305 " abcd\n" <<
306 "-delete1\n" <<
307 "+insert1\n" <<
308 " efgh\n";
309
310 QStringList newLines;
311 newLines << "newline1\n";
312 QStringList oldLines;
313 oldLines << "delete1\n";
314 DifferenceHash expectedDifferences;
315 expectedDifferences.insert(1, qMakePair(QStringList() << "delete1\n", QStringList() << "newline1\n"));
316
317 QTest::newRow("Replace line in source") << patch << oldLines << newLines << 11 << false << 2 << expectedDifferences;
318 }
319 }
320
testLineNumbers_data()321 void InteractiveDiffTest::testLineNumbers_data()
322 {
323 QTest::addColumn<QStringList>("patch");
324 QTest::addColumn<QStringList>("oldLines"); // lines that are replaced
325 QTest::addColumn<QStringList>("newLines"); // replacement lines
326 QTest::addColumn<int>("editLineNumber");
327 QTest::addColumn<int>("expectedDifferenceCount");
328 QTest::addColumn<LineNumberHash>("expectedLineNumbers");
329
330 {
331 QStringList patch;
332 patch <<
333 "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
334 "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
335 "@@ -1,4 +1,6 @@\n" <<
336 " abcd\n" <<
337 "-delete1\n" <<
338 "-delete2\n" <<
339 "+insert1\n" <<
340 "+insert2\n" <<
341 "+insert3\n" <<
342 "+insert4\n" <<
343 " efgh\n" <<
344 "@@ -15,3 +17,4 @@\n" <<
345 " abcd\n" <<
346 "-delete1\n" <<
347 "+insert1\n" <<
348 "+insert2\n" <<
349 " efgh\n";
350
351 QStringList newLines;
352 newLines << "newline1\n" << "newline2\n" << "newline2\n";
353 QStringList oldLines;
354 oldLines << "oldline1\n";
355 LineNumberHash expectedLineNumbers;
356 expectedLineNumbers.insert(0, qMakePair(2, 2));
357 expectedLineNumbers.insert(2, qMakePair(16, 20));
358 QTest::newRow("Update existing line numbers") << patch << oldLines << newLines << 10 << 3 << expectedLineNumbers;
359 }
360 {
361 QStringList patch;
362 patch <<
363 "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
364 "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
365 "@@ -1,4 +1,6 @@\n" <<
366 " abcd\n" <<
367 "-delete1\n" <<
368 "-delete2\n" <<
369 "+insert1\n" <<
370 "+insert2\n" <<
371 "+insert3\n" <<
372 "+insert4\n" <<
373 " efgh\n" <<
374 "@@ -15,3 +17,4 @@\n" <<
375 " abcd\n" <<
376 "-delete1\n" <<
377 "+insert1\n" <<
378 "+insert2\n" <<
379 " efgh\n";
380
381 QStringList newLines;
382 newLines << "newline1\n";
383 QStringList oldLines;
384 oldLines << "oldline1\n";
385 LineNumberHash expectedLineNumbers;
386 expectedLineNumbers.insert(2, qMakePair(22, 25));
387
388 // Line numbers assigned to new difference when it is inserted after all existing differences
389 QTest::newRow("Last edit line number") << patch << oldLines << newLines << 25 << 3 << expectedLineNumbers;
390 }
391 {
392 QStringList patch;
393 patch <<
394 "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
395 "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
396 "@@ -1,4 +1,6 @@\n" <<
397 " abcd\n" <<
398 "-delete1\n" <<
399 "-delete2\n" <<
400 "+insert1\n" <<
401 "+insert2\n" <<
402 "+insert3\n" <<
403 "+insert4\n" <<
404 " efgh\n" <<
405 "@@ -15,3 +17,4 @@\n" <<
406 " abcd\n" <<
407 "-delete1\n" <<
408 "+insert1\n" <<
409 "+insert2\n" <<
410 " efgh\n";
411
412 QStringList newLines;
413 newLines << "newline1\n";
414 QStringList oldLines;
415 oldLines << "oldline1\n";
416 LineNumberHash expectedLineNumbers;
417 expectedLineNumbers.insert(1, qMakePair(11, 13));
418
419 // Line numbers assigned to new difference when it is inserted between existing differences
420 QTest::newRow("Middle edit line number") << patch << oldLines << newLines << 13 << 3 << expectedLineNumbers;
421 }
422 {
423 QStringList patch;
424 patch <<
425 "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
426 "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
427 "@@ -10,4 +10,4 @@\n" <<
428 " abcd\n" <<
429 "-delete1\n" <<
430 "-delete2\n" <<
431 "+insert1\n" <<
432 "+insert2\n" <<
433 " efgh\n";
434
435 QStringList newLines;
436 newLines << "newline1\n";
437 QStringList oldLines;
438 oldLines << "oldline1\n";
439 LineNumberHash expectedLineNumbers;
440 expectedLineNumbers.insert(0, qMakePair(5, 5));
441
442 // Line numbers assigned to new difference when it is inserted before all existing differences
443 QTest::newRow("First edit line number") << patch << oldLines << newLines << 5 << 2 << expectedLineNumbers;
444 }
445 {
446 QStringList patch;
447 patch <<
448 "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
449 "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
450 "@@ -1,3 +1,4 @@\n" <<
451 " abcd\n" <<
452 "-delete1\n" <<
453 "+insert1\n" <<
454 "+insert2\n" <<
455 " efgh\n" <<
456 "@@ -11,4 +12,5 @@\n" <<
457 " abcd\n" <<
458 "-delete2\n" <<
459 "-delete3\n" <<
460 "+insert3\n" <<
461 "+insert4\n" <<
462 "+insert5\n" <<
463 " efgh\n" <<
464 "@@ -21,4 +23,3 @@\n" <<
465 " abcd\n" <<
466 "-delete4\n" <<
467 "-delete5\n" <<
468 "+insert6\n" <<
469 " efgh\n";
470
471 QStringList newLines;
472 newLines << "delete2\n";
473 QStringList oldLines;
474 oldLines << "insert4\n";
475 LineNumberHash expectedLineNumbers;
476 expectedLineNumbers.insert(0, qMakePair(2, 2));
477 expectedLineNumbers.insert(1, qMakePair(12, 13));
478 expectedLineNumbers.insert(2, qMakePair(13, 15));
479 expectedLineNumbers.insert(3, qMakePair(22, 24));
480
481 QTest::newRow("Partial reversion") << patch << oldLines << newLines << 14 << 4 << expectedLineNumbers;
482 }
483 }
484
testLineNumbers()485 void InteractiveDiffTest::testLineNumbers()
486 {
487 QFETCH(QStringList, patch);
488 Parser parser(nullptr);
489 bool malformed;
490 DiffModelList* models = parser.parse(patch, &malformed);
491 QVERIFY(!malformed);
492 QCOMPARE(models->size(), 1);
493 DiffModel* model = models->at(0);
494 model->applyAllDifferences(true);
495
496 QFETCH(QStringList, oldLines);
497 QFETCH(QStringList, newLines);
498 QFETCH(int, editLineNumber);
499 model->linesChanged(oldLines, newLines, editLineNumber);
500 QFETCH(int, expectedDifferenceCount);
501 QCOMPARE(model->differenceCount(), expectedDifferenceCount);
502
503 QFETCH(LineNumberHash, expectedLineNumbers);
504 for (LineNumberHash::ConstIterator iter = expectedLineNumbers.constBegin(); iter != expectedLineNumbers.constEnd(); ++iter) {
505 const Difference* diff = model->differenceAt(iter.key());
506 QCOMPARE(diff->sourceLineNumber(), iter.value().first);
507 QCOMPARE(diff->trackingDestinationLineNumber(), iter.value().second);
508 }
509 }
510
511 // When the new diff and an existing unapplied one are on neighbour lines, do not merge the unapplied with the new.
testAppliedTouch()512 void InteractiveDiffTest::testAppliedTouch()
513 {
514 Difference* first = new Difference(2, 2);
515 first->addSourceLine(QString("delete1"));
516 first->addDestinationLine(QString("insert1"));
517 first->apply(false);
518 Difference* second = new Difference(4, 4);
519 second->addSourceLine(QString("delete2"));
520 second->addDestinationLine(QString("insert2"));
521 second->apply(false);
522 DiffModel model;
523 model.addDiff(first);
524 model.addDiff(second);
525 model.linesChanged(QStringList() << "oldline\n", QStringList() << "newline\n", 3);
526 QCOMPARE(model.differenceCount(), 3);
527 QCOMPARE(model.differenceAt(0), first);
528 QCOMPARE(model.differenceAt(2), second);
529 }
530
531 // When the new diff and an existing unapplied one intersect, the unapplied one should be removed
testAppliedIntersect()532 void InteractiveDiffTest::testAppliedIntersect()
533 {
534 Difference* first = new Difference(2, 2);
535 first->addSourceLine(QString("delete1"));
536 first->addSourceLine(QString("delete2"));
537 first->addDestinationLine(QString("insert1"));
538 first->addDestinationLine(QString("insert2"));
539 first->apply(false);
540 Difference* second = new Difference(5, 5);
541 second->addSourceLine(QString("delete3"));
542 second->addSourceLine(QString("delete4"));
543 second->addDestinationLine(QString("insert3"));
544 second->addDestinationLine(QString("insert4"));
545 second->apply(false);
546 DiffModel model;
547 model.addDiff(first);
548 model.addDiff(second);
549 QStringList removedLines;
550 removedLines << "delete2\n" << "oldline1\n" << "delete3\n";
551 QStringList insertedLines;
552 insertedLines << "newline1\n";
553 model.linesChanged(removedLines, insertedLines, 3);
554 QCOMPARE(model.differenceCount(), 1);
555 const Difference* newDiff = model.differenceAt(0);
556 QCOMPARE(newDiff->applied(), true);
557 QCOMPARE(newDiff->sourceLineNumber(), 3);
558 QCOMPARE(newDiff->trackingDestinationLineNumber(), 3);
559 CompareDifferenceStringList(newDiff->sourceLines(), removedLines);
560 CompareDifferenceStringList(newDiff->destinationLines(), insertedLines);
561 }
562
testExistingAndApplied()563 void InteractiveDiffTest::testExistingAndApplied()
564 {
565 Difference* first = new Difference(2, 2);
566 first->addSourceLine(QString("delete1"));
567 first->addDestinationLine(QString("insert1"));
568 first->apply(true);
569 Difference* second = new Difference(3, 3);
570 second->addSourceLine(QString("delete2"));
571 second->addDestinationLine(QString("insert2"));
572 second->apply(false);
573 DiffModel model;
574 model.addDiff(first);
575 model.addDiff(second);
576 QStringList removedLines;
577 removedLines << "delete1\n";
578 QStringList insertedLines;
579 insertedLines << "newline1\n";
580 model.linesChanged(removedLines, insertedLines, 2);
581 QCOMPARE(model.differenceCount(), 2);
582 QVERIFY(model.differenceAt(0)->applied());
583 QVERIFY(!model.differenceAt(1)->applied());
584 }
585
testOneLineDeletionUnapplied()586 void InteractiveDiffTest::testOneLineDeletionUnapplied()
587 {
588 Difference* unappliedDeletion = new Difference(1, 1);
589 unappliedDeletion->addSourceLine("delete1\n");
590 unappliedDeletion->apply(false);
591 DiffModel model;
592 model.addDiff(unappliedDeletion);
593 QStringList removedLines;
594 removedLines << "delete1\n";
595 QStringList insertedLines;
596 insertedLines << "newline1\n";
597 model.linesChanged(removedLines, insertedLines, 1);
598 QCOMPARE(model.differenceCount(), 1);
599 const Difference* actual = model.differenceAt(0);
600 CompareDifferenceStringList(actual->sourceLines(), removedLines);
601 CompareDifferenceStringList(actual->destinationLines(), insertedLines);
602 }
603
testApplyUnapply()604 void InteractiveDiffTest::testApplyUnapply()
605 {
606 QStringList patch;
607 patch <<
608 "--- file1\t2011-01-01 20:23:45 +0300\n" <<
609 "+++ file2\t2011-01-01 20:24:02 +0300\n" <<
610 "@@ -1,3 +1,4 @@\n" <<
611 " line1\n" <<
612 "-delete1\n" <<
613 "+insert1\n" <<
614 "+insert2\n" <<
615 " line2\n" <<
616 "@@ -11,4 +12,5 @@\n" <<
617 " line3\n" <<
618 "-delete2\n" <<
619 "-delete3\n" <<
620 "+insert3\n" <<
621 "+insert4\n" <<
622 "+insert5\n" <<
623 " line4\n" <<
624 "@@ -21,4 +23,2 @@\n" <<
625 " line5\n" <<
626 "-delete4\n" <<
627 "-delete5\n" <<
628 " line6\n" <<
629 "@@ -31,3 +31,3 @@\n" <<
630 " line7\n" <<
631 "-delete6\n" <<
632 "+insert6\n" <<
633 " line8\n";
634 Parser parser(nullptr);
635 bool malformed;
636 DiffModelList* models = parser.parse(patch, &malformed);
637 QVERIFY(!malformed);
638 QCOMPARE(models->size(), 1);
639 DiffModel* model = models->at(0);
640 QCOMPARE(model->differenceCount(), 4);
641 model->applyAllDifferences(true);
642
643 const auto differences = *model->differences();
644 for (Difference* diff : differences) {
645 QVERIFY(diff->applied());
646 }
647 model->applyAllDifferences(false);
648 QVERIFY(!model->differenceAt(0)->applied());
649 QCOMPARE(model->differenceAt(0)->sourceLineNumber(), 2);
650 QCOMPARE(model->differenceAt(0)->trackingDestinationLineNumber(), 2);
651 QVERIFY(!model->differenceAt(1)->applied());
652 QCOMPARE(model->differenceAt(1)->sourceLineNumber(), 12);
653 QCOMPARE(model->differenceAt(1)->trackingDestinationLineNumber(), 12);
654 QVERIFY(!model->differenceAt(2)->applied());
655 QCOMPARE(model->differenceAt(2)->sourceLineNumber(), 22);
656 QCOMPARE(model->differenceAt(2)->trackingDestinationLineNumber(), 22);
657 QVERIFY(!model->differenceAt(3)->applied());
658 QCOMPARE(model->differenceAt(3)->sourceLineNumber(), 32);
659 QCOMPARE(model->differenceAt(3)->trackingDestinationLineNumber(), 32);
660
661 model->differenceAt(1)->apply(true);
662 QVERIFY(model->differenceAt(1)->applied());
663 QCOMPARE(model->differenceAt(1)->sourceLineNumber(), 12);
664 QCOMPARE(model->differenceAt(1)->trackingDestinationLineNumber(), 12);
665 QVERIFY(!model->differenceAt(2)->applied());
666 QCOMPARE(model->differenceAt(2)->sourceLineNumber(), 22);
667 QCOMPARE(model->differenceAt(2)->trackingDestinationLineNumber(), 23);
668 QVERIFY(!model->differenceAt(3)->applied());
669 QCOMPARE(model->differenceAt(3)->sourceLineNumber(), 32);
670 QCOMPARE(model->differenceAt(3)->trackingDestinationLineNumber(), 33);
671
672 model->differenceAt(1)->apply(true);
673 QVERIFY(model->differenceAt(1)->applied());
674 QCOMPARE(model->differenceAt(1)->sourceLineNumber(), 12);
675 QCOMPARE(model->differenceAt(1)->trackingDestinationLineNumber(), 12);
676 QVERIFY(!model->differenceAt(2)->applied());
677 QCOMPARE(model->differenceAt(2)->sourceLineNumber(), 22);
678 QCOMPARE(model->differenceAt(2)->trackingDestinationLineNumber(), 23);
679 QVERIFY(!model->differenceAt(3)->applied());
680 QCOMPARE(model->differenceAt(3)->sourceLineNumber(), 32);
681 QCOMPARE(model->differenceAt(3)->trackingDestinationLineNumber(), 33);
682
683 model->differenceAt(2)->apply(true);
684 QVERIFY(model->differenceAt(2)->applied());
685 QCOMPARE(model->differenceAt(2)->sourceLineNumber(), 22);
686 QCOMPARE(model->differenceAt(2)->trackingDestinationLineNumber(), 23);
687 QVERIFY(!model->differenceAt(3)->applied());
688 QCOMPARE(model->differenceAt(3)->sourceLineNumber(), 32);
689 QCOMPARE(model->differenceAt(3)->trackingDestinationLineNumber(), 31);
690
691 model->applyAllDifferences(true);
692 QVERIFY(model->differenceAt(0)->applied());
693 QCOMPARE(model->differenceAt(0)->sourceLineNumber(), 2);
694 QCOMPARE(model->differenceAt(0)->trackingDestinationLineNumber(), 2);
695 QVERIFY(model->differenceAt(1)->applied());
696 QCOMPARE(model->differenceAt(1)->sourceLineNumber(), 12);
697 QCOMPARE(model->differenceAt(1)->trackingDestinationLineNumber(), 13);
698 QVERIFY(model->differenceAt(2)->applied());
699 QCOMPARE(model->differenceAt(2)->sourceLineNumber(), 22);
700 QCOMPARE(model->differenceAt(2)->trackingDestinationLineNumber(), 24);
701 QVERIFY(model->differenceAt(3)->applied());
702 QCOMPARE(model->differenceAt(3)->sourceLineNumber(), 32);
703 QCOMPARE(model->differenceAt(3)->trackingDestinationLineNumber(), 32);
704
705 model->applyAllDifferences(true);
706 QVERIFY(model->differenceAt(0)->applied());
707 QCOMPARE(model->differenceAt(0)->sourceLineNumber(), 2);
708 QCOMPARE(model->differenceAt(0)->trackingDestinationLineNumber(), 2);
709 QVERIFY(model->differenceAt(1)->applied());
710 QCOMPARE(model->differenceAt(1)->sourceLineNumber(), 12);
711 QCOMPARE(model->differenceAt(1)->trackingDestinationLineNumber(), 13);
712 QVERIFY(model->differenceAt(2)->applied());
713 QCOMPARE(model->differenceAt(2)->sourceLineNumber(), 22);
714 QCOMPARE(model->differenceAt(2)->trackingDestinationLineNumber(), 24);
715 QVERIFY(model->differenceAt(3)->applied());
716 QCOMPARE(model->differenceAt(3)->sourceLineNumber(), 32);
717 QCOMPARE(model->differenceAt(3)->trackingDestinationLineNumber(), 32);
718 }
719
720 static void
contextDiff1()721 contextDiff1()
722 {
723 QStringList patch;
724 patch <<
725 "commit 7377fcc682e85ef9784adb2a2da2c8c6756f9018 (HEAD, KDE/4.11)\n" <<
726 "Author: Dr. Chocholoušek <bla@zin.ec>\n" <<
727 "AuthorDate: Sat Jan 25 17:30:01 2014 +0100\n" <<
728 "\n" <<
729 " Fake diff.\n" <<
730 "\n" <<
731 "diff --git a/libdiff2/diffmodel.cpp b/libdiff2/diffmodel.cpp\n" <<
732 "new file mode 100644\n" <<
733 "index a42e82d..a8da0c9\n" <<
734 "*** a/libdiff2/diffmodel.cpp\n" << // note the missing timestamps
735 "--- b/libdiff2/diffmodel.cpp\n" <<
736 "*************** DiffModel::DiffModel() :\n" <<
737 "*** 58,64 ****\n" <<
738 " m_sourceFile( "" ),\n" <<
739 " m_destinationFile( "" ),\n" <<
740 " m_sourceTimestamp( "" ),\n" <<
741 "! m_destinationTimestamp( "" ),\n" <<
742 " m_sourceRevision( "" ),\n" <<
743 " m_destinationRevision( "" ),\n" <<
744 " m_appliedCount( 0 ),\n" <<
745 "--- 58,64 ----\n" <<
746 " m_sourceFile( "" ),\n" <<
747 " m_destinationFile( "" ),\n" <<
748 " m_sourceTimestamp( "" ),\n" <<
749 "! m_destinationTimestamp( \"doh\" ),\n" <<
750 " m_sourceRevision( "" ),\n" <<
751 " m_destinationRevision( "" ),\n" <<
752 " m_appliedCount( 0 ),\n" <<
753 "*************** void DiffModel::splitSourceInPathAndFile\n" <<
754 "*** 84,89 ****\n" <<
755 "--- 84,91 ----\n" <<
756 " if( ( pos = m_source.lastIndexOf( \"/\" ) ) >= 0 )\n" <<
757 " m_sourcePath = m_source.mid( 0, pos+1 );\n" <<
758 " \n" <<
759 "+ add_this;\n" <<
760 "+ \n" <<
761 " if( ( pos = m_source.lastIndexOf( \"/\" ) ) >= 0 )\n" <<
762 " m_sourceFile = m_source.mid( pos+1, m_source.length() - pos );\n" <<
763 " else\n";
764 Parser parser(nullptr);
765 bool malformed;
766 DiffModelList* models = parser.parse(patch, &malformed);
767 QVERIFY(!malformed);
768 QCOMPARE(models->size(), 1);
769 DiffModel* model = models->at(0);
770 QCOMPARE(model->differenceCount(), 2);
771 model->applyAllDifferences(true);
772 QVERIFY(model->differenceAt(0)->applied());
773 QCOMPARE(model->differenceAt(0)->sourceLineNumber(), 61);
774 QCOMPARE(model->differenceAt(0)->trackingDestinationLineNumber(), 61);
775 QCOMPARE(model->differenceAt(1)->sourceLineNumber(), 87);
776 QCOMPARE(model->differenceAt(1)->trackingDestinationLineNumber(), 87);
777 }
778
779 static void
contextDiff2()780 contextDiff2()
781 {
782 QStringList patch;
783 patch <<
784 "*** a/libdiff2/diffmodel.cpp\n" <<
785 "--- b/libdiff2/diffmodel.cpp\n" <<
786 "***************\n" <<
787 "*** 55,60 **** DiffModel::DiffModel() :\n" << // note the context here
788 "--- 55,61 ----\n" <<
789 " m_destination( "" ),\n" <<
790 " m_sourcePath( "" ),\n" <<
791 " m_destinationPath( "" ),\n" <<
792 "+ m_hoh ( "" );\n" <<
793 " m_sourceFile( "" ),\n" <<
794 " m_destinationFile( "" ),\n" <<
795 " m_sourceTimestamp( "" ),\n";
796
797 Parser parser(nullptr);
798 bool malformed;
799 DiffModelList* models = parser.parse(patch, &malformed);
800 QVERIFY(!malformed);
801 QCOMPARE(models->size(), 1);
802 DiffModel* model = models->at(0);
803 QCOMPARE(model->differenceCount(), 1);
804 model->applyAllDifferences(true);
805 QVERIFY(model->differenceAt(0)->applied());
806 QCOMPARE(model->differenceAt(0)->sourceLineNumber(), 58);
807 QCOMPARE(model->differenceAt(0)->trackingDestinationLineNumber(), 58);
808 }
809
testContextDiff()810 void InteractiveDiffTest::testContextDiff()
811 {
812 contextDiff1();
813 contextDiff2();
814 }
815
testNormalDiff()816 void InteractiveDiffTest::testNormalDiff()
817 {
818 QStringList patch;
819 patch <<
820 "1c1\n" <<
821 "< a\n" <<
822 "---\n" <<
823 "> b\n";
824 Parser parser(nullptr);
825 bool malformed;
826 DiffModelList* models = parser.parse(patch, &malformed);
827 QVERIFY(!malformed);
828 QCOMPARE(models->size(), 1);
829 DiffModel* model = models->at(0);
830 QCOMPARE(model->differenceCount(), 1);
831 model->applyAllDifferences(true);
832 QVERIFY(model->differenceAt(0)->applied());
833 QCOMPARE(model->differenceAt(0)->sourceLineNumber(), 1);
834 QCOMPARE(model->differenceAt(0)->trackingDestinationLineNumber(), 1);
835 }
836
837 QTEST_GUILESS_MAIN(InteractiveDiffTest);
838