File indexing completed on 2024-04-28 17:01:43

0001 /*
0002 SPDX-FileCopyrightText: 2011 Dmitry Risenberg <dmitry.risenberg@gmail.com>
0003 
0004 SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "interactivedifftest.h"
0008 
0009 #include <QTest>
0010 #include "diffmodel.h"
0011 #include "diffmodellist.h"
0012 #include "parser.h"
0013 
0014 using namespace Diff2;
0015 
0016 typedef QHash<int, QPair<QStringList, QStringList> > DifferenceHash;
0017 Q_DECLARE_METATYPE(DifferenceHash);
0018 typedef QHash<int, QPair<int, int> > LineNumberHash;
0019 Q_DECLARE_METATYPE(LineNumberHash);
0020 
0021 void InteractiveDiffTest::CompareDifferenceStringList(const DifferenceStringList& actual, const QStringList& expected)
0022 {
0023     DifferenceStringListConstIterator actualIter;
0024     QStringList::const_iterator expectedIter;
0025     for (actualIter = actual.constBegin(), expectedIter = expected.constBegin(); actualIter != actual.constEnd() && expectedIter != expected.constEnd(); ++actualIter, ++expectedIter) {
0026         QCOMPARE((*actualIter)->string(), *expectedIter);
0027     }
0028     if (actualIter != actual.constEnd()) {
0029         QFAIL(QStringLiteral("Actual has too many items, starting with '%1', line %2").arg((*actualIter)->string()).arg(actualIter - actual.constBegin()).toLatin1().constData());
0030     }
0031     if (expectedIter != expected.constEnd()) {
0032         QFAIL(QStringLiteral("Actual has too few items, no match for '%1', line %2").arg(*expectedIter).arg(expectedIter - expected.constBegin()).toLatin1().constData());
0033     }
0034 }
0035 
0036 // The most basic test - something is actually working
0037 void InteractiveDiffTest::testOneLineChange()
0038 {
0039     DiffModel* model = new DiffModel();
0040     QStringList newLines;
0041     newLines << "newline\n";
0042     QStringList oldLines;
0043     oldLines << "oldline\n";
0044     model->linesChanged(oldLines, newLines, 2);
0045     QCOMPARE(model->differences()->size(), 1);
0046 
0047     QCOMPARE(model->differenceCount(), 1);
0048     const Difference* diff = model->differenceAt(0);
0049     CompareDifferenceStringList(diff->sourceLines(), oldLines);
0050     CompareDifferenceStringList(diff->destinationLines(), newLines);
0051     QCOMPARE(diff->type(), int(Difference::Change));
0052 }
0053 
0054 void InteractiveDiffTest::testSameLine()
0055 {
0056     DiffModel* model = new DiffModel();
0057     QStringList newLines;
0058     newLines << "oldline2\n";
0059     QStringList oldLines;
0060     oldLines << "oldline1\n" << "oldline2\n";
0061     model->linesChanged(oldLines, newLines, 2);
0062 
0063     QCOMPARE(model->differenceCount(), 1);
0064     const Difference* diff = model->differenceAt(0);
0065     CompareDifferenceStringList(diff->sourceLines(), QStringList() << "oldline1\n");
0066     CompareDifferenceStringList(diff->destinationLines(), QStringList());
0067     QCOMPARE(diff->type(), int(Difference::Delete));
0068 }
0069 
0070 void InteractiveDiffTest::testDifferenceContents()
0071 {
0072     QFETCH(QStringList, patch);
0073     Parser parser(nullptr);
0074     bool malformed;
0075     DiffModelList* models = parser.parse(patch, &malformed);
0076     QVERIFY(!malformed);
0077     QCOMPARE(models->size(), 1);
0078     DiffModel* model = models->at(0);
0079 
0080     QFETCH(QStringList, oldLines);
0081     QFETCH(QStringList, newLines);
0082     QFETCH(int, editLineNumber);
0083     QFETCH(bool, isAlreadyApplied);
0084     model->applyAllDifferences(isAlreadyApplied);
0085     model->linesChanged(oldLines, newLines, editLineNumber);
0086     QFETCH(int, expectedDifferenceCount);
0087     QCOMPARE(model->differenceCount(), expectedDifferenceCount);
0088 
0089     QFETCH(DifferenceHash, expectedDifferences);
0090     for (DifferenceHash::ConstIterator iter = expectedDifferences.constBegin(); iter != expectedDifferences.constEnd(); ++iter) {
0091         const Difference* diff = model->differenceAt(iter.key());
0092         CompareDifferenceStringList(diff->sourceLines(), iter.value().first);
0093         CompareDifferenceStringList(diff->destinationLines(), iter.value().second);
0094     }
0095 }
0096 
0097 void InteractiveDiffTest::testDifferenceContents_data()
0098 {
0099     QTest::addColumn<QStringList>("patch");
0100     QTest::addColumn<QStringList>("oldLines");     // lines that are replaced
0101     QTest::addColumn<QStringList>("newLines");     // replacement lines
0102     QTest::addColumn<int>("editLineNumber");
0103     QTest::addColumn<bool>("isAlreadyApplied");
0104     QTest::addColumn<int>("expectedDifferenceCount");
0105     QTest::addColumn<DifferenceHash>("expectedDifferences");
0106 
0107     {
0108         QStringList patch;
0109         patch <<
0110               "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
0111               "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
0112               "@@ -1,5 +1,5 @@\n" <<
0113               " abcd\n" <<
0114               "-delete1\n" <<
0115               "+insert1\n" <<
0116               " efgh\n" <<
0117               "-delete2\n" <<
0118               "+insert2\n" <<
0119               " ijkl\n";
0120 
0121         QStringList newLines;
0122         newLines << "newline1\n" << "newline2\n";
0123         QStringList oldLines;
0124         oldLines << "efgh\n";
0125         QStringList sourceLines;
0126         sourceLines << "delete1\n" << "efgh\n" << "delete2\n";
0127         QStringList destinationLines;
0128         destinationLines << "insert1\n" << "newline1\n" << "newline2\n" << "insert2\n";
0129         DifferenceHash expectedDifferences;
0130         expectedDifferences.insert(0, qMakePair(sourceLines, destinationLines));
0131 
0132         QTest::newRow("Merge adjacent differences") << patch << oldLines << newLines << 3 << true << 1 << expectedDifferences;
0133     }
0134     {
0135         QStringList patch;
0136         patch <<
0137               "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
0138               "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
0139               "@@ -1,4 +1,4 @@\n" <<
0140               " abcd\n" <<
0141               "-delete1\n" <<
0142               "-delete2\n" <<
0143               "+insert1\n" <<
0144               "+insert2\n" <<
0145               " efgh\n";
0146 
0147         QStringList newLines;
0148         newLines << "newline1\n";
0149         QStringList oldLines;
0150         oldLines << "efgh\n";
0151         QStringList sourceLines;
0152         sourceLines << "delete1\n" << "delete2\n" << "efgh\n";
0153         QStringList destinationLines;
0154         destinationLines << "insert1\n" << "insert2\n" << "newline1\n";
0155         DifferenceHash expectedDifferences;
0156         expectedDifferences.insert(0, qMakePair(sourceLines, destinationLines));
0157 
0158         // Append a line to a multiline diff
0159         QTest::newRow("Append multiline") << patch << oldLines << newLines << 4 << true << 1 << expectedDifferences;
0160     }
0161     {
0162         QStringList patch;
0163         patch <<
0164               "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
0165               "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
0166               "@@ -1,3 +1,3 @@\n" <<
0167               " abcd\n" <<
0168               "-delete1\n" <<
0169               "+insert1\n" <<
0170               " efgh\n";
0171 
0172         QStringList newLines;
0173         newLines << "delete1\n";
0174         QStringList oldLines;
0175         oldLines << "insert1\n";
0176         QTest::newRow("Revert existing difference") << patch << oldLines << newLines << 2 << true << 0 << DifferenceHash();
0177     }
0178     {
0179         QStringList patch;
0180         patch <<
0181               "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
0182               "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
0183               "@@ -1,3 +1,2 @@\n" <<
0184               " abcd\n" <<
0185               "-delete1\n" <<
0186               " efgh\n";
0187 
0188         QStringList newLines;
0189         newLines << "abcd\n" << "delete1\n";
0190         QStringList oldLines;
0191         oldLines << "abcd\n";
0192         QTest::newRow("Revert deletion") << patch << oldLines << newLines << 1 << true << 0 << DifferenceHash();
0193     }
0194     {
0195         QStringList patch;
0196         patch <<
0197               "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
0198               "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
0199               "@@ -1,4 +1,5 @@\n" <<
0200               " abcd\n" <<
0201               "-delete1\n" <<
0202               "-delete2\n" <<
0203               "+insert1\n" <<
0204               "+insert2\n" <<
0205               "+insert3\n" <<
0206               " efgh\n";
0207 
0208         QStringList newLines;
0209         newLines << "delete2\n";
0210         QStringList oldLines;
0211         oldLines << "insert2\n";
0212         DifferenceHash expectedDifferences;
0213         expectedDifferences.insert(0, qMakePair(QStringList() << "delete1\n", QStringList() << "insert1\n"));
0214         expectedDifferences.insert(1, qMakePair(QStringList(), QStringList() << "insert3\n"));
0215 
0216         QTest::newRow("Partial reversion") << patch << oldLines << newLines << 3 << true << 2 << expectedDifferences;
0217     }
0218     {
0219         QStringList patch;
0220         patch <<
0221               "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
0222               "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
0223               "@@ -1,4 +1,4 @@\n" <<
0224               " abcd\n" <<
0225               "-delete1\n" <<
0226               "-delete2\n" <<
0227               "+insert1\n" <<
0228               "+insert2\n" <<
0229               " efgh\n";
0230 
0231         QStringList newLines;
0232         newLines << "newline1\n" << "newline2\n";
0233         QStringList oldLines;
0234         oldLines << "abcd\n" << "insert1\n" << "insert2\n" << "efgh\n";
0235         QStringList sourceLines;
0236         sourceLines << "abcd\n" << "delete1\n" << "delete2\n" << "efgh\n";
0237         QStringList destinationLines;
0238         destinationLines << "newline1\n" << "newline2\n";
0239         DifferenceHash expectedDifferences;
0240         expectedDifferences.insert(0, qMakePair(sourceLines, destinationLines));
0241 
0242         // The first existing difference inside the edit
0243         QTest::newRow("First inside") << patch << oldLines << newLines << 1 << true << 1 << expectedDifferences;
0244     }
0245     {
0246         QStringList patch;
0247         patch <<
0248               "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
0249               "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
0250               "@@ -1,4 +1,4 @@\n" <<
0251               " abcd\n" <<
0252               "-delete1\n" <<
0253               "-delete2\n" <<
0254               "+insert1\n" <<
0255               "+insert2\n" <<
0256               " efgh\n";
0257 
0258         QStringList newLines;
0259         newLines << "newline1\n" << "newline2\n";
0260         QStringList oldLines;
0261         oldLines << "insert2\n" << "efgh\n";
0262         QStringList sourceLines;
0263         sourceLines << "delete1\n" << "delete2\n" << "efgh\n";
0264         QStringList destinationLines;
0265         destinationLines << "insert1\n" << "newline1\n" << "newline2\n";
0266         DifferenceHash expectedDifferences;
0267         expectedDifferences.insert(0, qMakePair(sourceLines, destinationLines));
0268 
0269         // The first existing difference intersects with the edit
0270         QTest::newRow("First intersects") << patch << oldLines << newLines << 3 << true << 1 << expectedDifferences;
0271     }
0272     {
0273         QStringList patch;
0274         patch <<
0275               "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
0276               "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
0277               "@@ -1,2 +1,3 @@\n" <<
0278               " abcd\n" <<
0279               "+\n" <<
0280               " efgh\n";
0281 
0282         QStringList newLines;
0283         newLines << "a\n";
0284         QStringList oldLines;
0285         oldLines << "\n";
0286         DifferenceHash expectedDifferences;
0287         expectedDifferences.insert(0, qMakePair(QStringList(), QStringList() << "a\n"));
0288 
0289         QTest::newRow("Replace empty line") << patch << oldLines << newLines << 2 << true << 1 << expectedDifferences;
0290     }
0291     {
0292         QStringList patch;
0293         patch <<
0294               "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
0295               "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
0296               "@@ -1,3 +1,3 @@\n" <<
0297               " abcd\n" <<
0298               "+insert1\n" <<
0299               "+insert2\n" <<
0300               "+insert3\n" <<
0301               "+insert4\n" <<
0302               "+insert5\n" <<
0303               " efgh\n" <<
0304               "@@ -10,3 +15,3 @@\n" <<
0305               " abcd\n" <<
0306               "-delete1\n" <<
0307               "+insert1\n" <<
0308               " efgh\n";
0309 
0310         QStringList newLines;
0311         newLines << "newline1\n";
0312         QStringList oldLines;
0313         oldLines << "delete1\n";
0314         DifferenceHash expectedDifferences;
0315         expectedDifferences.insert(1, qMakePair(QStringList() << "delete1\n", QStringList() << "newline1\n"));
0316 
0317         QTest::newRow("Replace line in source") << patch << oldLines << newLines << 11 << false << 2 << expectedDifferences;
0318     }
0319 }
0320 
0321 void InteractiveDiffTest::testLineNumbers_data()
0322 {
0323     QTest::addColumn<QStringList>("patch");
0324     QTest::addColumn<QStringList>("oldLines");     // lines that are replaced
0325     QTest::addColumn<QStringList>("newLines");     // replacement lines
0326     QTest::addColumn<int>("editLineNumber");
0327     QTest::addColumn<int>("expectedDifferenceCount");
0328     QTest::addColumn<LineNumberHash>("expectedLineNumbers");
0329 
0330     {
0331         QStringList patch;
0332         patch <<
0333               "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
0334               "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
0335               "@@ -1,4 +1,6 @@\n" <<
0336               " abcd\n" <<
0337               "-delete1\n" <<
0338               "-delete2\n" <<
0339               "+insert1\n" <<
0340               "+insert2\n" <<
0341               "+insert3\n" <<
0342               "+insert4\n" <<
0343               " efgh\n" <<
0344               "@@ -15,3 +17,4 @@\n" <<
0345               " abcd\n" <<
0346               "-delete1\n" <<
0347               "+insert1\n" <<
0348               "+insert2\n" <<
0349               " efgh\n";
0350 
0351         QStringList newLines;
0352         newLines << "newline1\n" << "newline2\n" << "newline2\n";
0353         QStringList oldLines;
0354         oldLines << "oldline1\n";
0355         LineNumberHash expectedLineNumbers;
0356         expectedLineNumbers.insert(0, qMakePair(2, 2));
0357         expectedLineNumbers.insert(2, qMakePair(16, 20));
0358         QTest::newRow("Update existing line numbers") << patch << oldLines << newLines << 10 << 3 << expectedLineNumbers;
0359     }
0360     {
0361         QStringList patch;
0362         patch <<
0363               "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
0364               "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
0365               "@@ -1,4 +1,6 @@\n" <<
0366               " abcd\n" <<
0367               "-delete1\n" <<
0368               "-delete2\n" <<
0369               "+insert1\n" <<
0370               "+insert2\n" <<
0371               "+insert3\n" <<
0372               "+insert4\n" <<
0373               " efgh\n" <<
0374               "@@ -15,3 +17,4 @@\n" <<
0375               " abcd\n" <<
0376               "-delete1\n" <<
0377               "+insert1\n" <<
0378               "+insert2\n" <<
0379               " efgh\n";
0380 
0381         QStringList newLines;
0382         newLines << "newline1\n";
0383         QStringList oldLines;
0384         oldLines << "oldline1\n";
0385         LineNumberHash expectedLineNumbers;
0386         expectedLineNumbers.insert(2, qMakePair(22, 25));
0387 
0388         // Line numbers assigned to new difference when it is inserted after all existing differences
0389         QTest::newRow("Last edit line number") << patch << oldLines << newLines << 25 << 3 << expectedLineNumbers;
0390     }
0391     {
0392         QStringList patch;
0393         patch <<
0394               "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
0395               "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
0396               "@@ -1,4 +1,6 @@\n" <<
0397               " abcd\n" <<
0398               "-delete1\n" <<
0399               "-delete2\n" <<
0400               "+insert1\n" <<
0401               "+insert2\n" <<
0402               "+insert3\n" <<
0403               "+insert4\n" <<
0404               " efgh\n" <<
0405               "@@ -15,3 +17,4 @@\n" <<
0406               " abcd\n" <<
0407               "-delete1\n" <<
0408               "+insert1\n" <<
0409               "+insert2\n" <<
0410               " efgh\n";
0411 
0412         QStringList newLines;
0413         newLines << "newline1\n";
0414         QStringList oldLines;
0415         oldLines << "oldline1\n";
0416         LineNumberHash expectedLineNumbers;
0417         expectedLineNumbers.insert(1, qMakePair(11, 13));
0418 
0419         // Line numbers assigned to new difference when it is inserted between existing differences
0420         QTest::newRow("Middle edit line number") << patch << oldLines << newLines << 13 << 3 << expectedLineNumbers;
0421     }
0422     {
0423         QStringList patch;
0424         patch <<
0425               "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
0426               "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
0427               "@@ -10,4 +10,4 @@\n" <<
0428               " abcd\n" <<
0429               "-delete1\n" <<
0430               "-delete2\n" <<
0431               "+insert1\n" <<
0432               "+insert2\n" <<
0433               " efgh\n";
0434 
0435         QStringList newLines;
0436         newLines << "newline1\n";
0437         QStringList oldLines;
0438         oldLines << "oldline1\n";
0439         LineNumberHash expectedLineNumbers;
0440         expectedLineNumbers.insert(0, qMakePair(5, 5));
0441 
0442         // Line numbers assigned to new difference when it is inserted before all existing differences
0443         QTest::newRow("First edit line number") << patch << oldLines << newLines << 5 << 2 << expectedLineNumbers;
0444     }
0445     {
0446         QStringList patch;
0447         patch <<
0448               "--- file1\t2011-01-01 20:23:45.000000000 +0300\n" <<
0449               "+++ file2\t2011-01-01 20:24:02.000000000 +0300\n" <<
0450               "@@ -1,3 +1,4 @@\n" <<
0451               " abcd\n" <<
0452               "-delete1\n" <<
0453               "+insert1\n" <<
0454               "+insert2\n" <<
0455               " efgh\n" <<
0456               "@@ -11,4 +12,5 @@\n" <<
0457               " abcd\n" <<
0458               "-delete2\n" <<
0459               "-delete3\n" <<
0460               "+insert3\n" <<
0461               "+insert4\n" <<
0462               "+insert5\n" <<
0463               " efgh\n" <<
0464               "@@ -21,4 +23,3 @@\n" <<
0465               " abcd\n" <<
0466               "-delete4\n" <<
0467               "-delete5\n" <<
0468               "+insert6\n" <<
0469               " efgh\n";
0470 
0471         QStringList newLines;
0472         newLines << "delete2\n";
0473         QStringList oldLines;
0474         oldLines << "insert4\n";
0475         LineNumberHash expectedLineNumbers;
0476         expectedLineNumbers.insert(0, qMakePair(2, 2));
0477         expectedLineNumbers.insert(1, qMakePair(12, 13));
0478         expectedLineNumbers.insert(2, qMakePair(13, 15));
0479         expectedLineNumbers.insert(3, qMakePair(22, 24));
0480 
0481         QTest::newRow("Partial reversion") << patch << oldLines << newLines << 14 << 4 << expectedLineNumbers;
0482     }
0483 }
0484 
0485 void InteractiveDiffTest::testLineNumbers()
0486 {
0487     QFETCH(QStringList, patch);
0488     Parser parser(nullptr);
0489     bool malformed;
0490     DiffModelList* models = parser.parse(patch, &malformed);
0491     QVERIFY(!malformed);
0492     QCOMPARE(models->size(), 1);
0493     DiffModel* model = models->at(0);
0494     model->applyAllDifferences(true);
0495 
0496     QFETCH(QStringList, oldLines);
0497     QFETCH(QStringList, newLines);
0498     QFETCH(int, editLineNumber);
0499     model->linesChanged(oldLines, newLines, editLineNumber);
0500     QFETCH(int, expectedDifferenceCount);
0501     QCOMPARE(model->differenceCount(), expectedDifferenceCount);
0502 
0503     QFETCH(LineNumberHash, expectedLineNumbers);
0504     for (LineNumberHash::ConstIterator iter = expectedLineNumbers.constBegin(); iter != expectedLineNumbers.constEnd(); ++iter) {
0505         const Difference* diff = model->differenceAt(iter.key());
0506         QCOMPARE(diff->sourceLineNumber(), iter.value().first);
0507         QCOMPARE(diff->trackingDestinationLineNumber(), iter.value().second);
0508     }
0509 }
0510 
0511 // When the new diff and an existing unapplied one are on neighbour lines, do not merge the unapplied with the new.
0512 void InteractiveDiffTest::testAppliedTouch()
0513 {
0514     Difference* first = new Difference(2, 2);
0515     first->addSourceLine(QString("delete1"));
0516     first->addDestinationLine(QString("insert1"));
0517     first->apply(false);
0518     Difference* second = new Difference(4, 4);
0519     second->addSourceLine(QString("delete2"));
0520     second->addDestinationLine(QString("insert2"));
0521     second->apply(false);
0522     DiffModel model;
0523     model.addDiff(first);
0524     model.addDiff(second);
0525     model.linesChanged(QStringList() << "oldline\n", QStringList() << "newline\n", 3);
0526     QCOMPARE(model.differenceCount(), 3);
0527     QCOMPARE(model.differenceAt(0), first);
0528     QCOMPARE(model.differenceAt(2), second);
0529 }
0530 
0531 // When the new diff and an existing unapplied one intersect, the unapplied one should be removed
0532 void InteractiveDiffTest::testAppliedIntersect()
0533 {
0534     Difference* first = new Difference(2, 2);
0535     first->addSourceLine(QString("delete1"));
0536     first->addSourceLine(QString("delete2"));
0537     first->addDestinationLine(QString("insert1"));
0538     first->addDestinationLine(QString("insert2"));
0539     first->apply(false);
0540     Difference* second = new Difference(5, 5);
0541     second->addSourceLine(QString("delete3"));
0542     second->addSourceLine(QString("delete4"));
0543     second->addDestinationLine(QString("insert3"));
0544     second->addDestinationLine(QString("insert4"));
0545     second->apply(false);
0546     DiffModel model;
0547     model.addDiff(first);
0548     model.addDiff(second);
0549     QStringList removedLines;
0550     removedLines << "delete2\n" << "oldline1\n" << "delete3\n";
0551     QStringList insertedLines;
0552     insertedLines << "newline1\n";
0553     model.linesChanged(removedLines, insertedLines, 3);
0554     QCOMPARE(model.differenceCount(), 1);
0555     const Difference* newDiff = model.differenceAt(0);
0556     QCOMPARE(newDiff->applied(), true);
0557     QCOMPARE(newDiff->sourceLineNumber(), 3);
0558     QCOMPARE(newDiff->trackingDestinationLineNumber(), 3);
0559     CompareDifferenceStringList(newDiff->sourceLines(), removedLines);
0560     CompareDifferenceStringList(newDiff->destinationLines(), insertedLines);
0561 }
0562 
0563 void InteractiveDiffTest::testExistingAndApplied()
0564 {
0565     Difference* first = new Difference(2, 2);
0566     first->addSourceLine(QString("delete1"));
0567     first->addDestinationLine(QString("insert1"));
0568     first->apply(true);
0569     Difference* second = new Difference(3, 3);
0570     second->addSourceLine(QString("delete2"));
0571     second->addDestinationLine(QString("insert2"));
0572     second->apply(false);
0573     DiffModel model;
0574     model.addDiff(first);
0575     model.addDiff(second);
0576     QStringList removedLines;
0577     removedLines << "delete1\n";
0578     QStringList insertedLines;
0579     insertedLines << "newline1\n";
0580     model.linesChanged(removedLines, insertedLines, 2);
0581     QCOMPARE(model.differenceCount(), 2);
0582     QVERIFY(model.differenceAt(0)->applied());
0583     QVERIFY(!model.differenceAt(1)->applied());
0584 }
0585 
0586 void InteractiveDiffTest::testOneLineDeletionUnapplied()
0587 {
0588     Difference* unappliedDeletion = new Difference(1, 1);
0589     unappliedDeletion->addSourceLine("delete1\n");
0590     unappliedDeletion->apply(false);
0591     DiffModel model;
0592     model.addDiff(unappliedDeletion);
0593     QStringList removedLines;
0594     removedLines << "delete1\n";
0595     QStringList insertedLines;
0596     insertedLines << "newline1\n";
0597     model.linesChanged(removedLines, insertedLines, 1);
0598     QCOMPARE(model.differenceCount(), 1);
0599     const Difference* actual = model.differenceAt(0);
0600     CompareDifferenceStringList(actual->sourceLines(), removedLines);
0601     CompareDifferenceStringList(actual->destinationLines(), insertedLines);
0602 }
0603 
0604 void InteractiveDiffTest::testApplyUnapply()
0605 {
0606     QStringList patch;
0607     patch <<
0608           "--- file1\t2011-01-01 20:23:45 +0300\n" <<
0609           "+++ file2\t2011-01-01 20:24:02 +0300\n" <<
0610           "@@ -1,3 +1,4 @@\n" <<
0611           " line1\n" <<
0612           "-delete1\n" <<
0613           "+insert1\n" <<
0614           "+insert2\n" <<
0615           " line2\n" <<
0616           "@@ -11,4 +12,5 @@\n" <<
0617           " line3\n" <<
0618           "-delete2\n" <<
0619           "-delete3\n" <<
0620           "+insert3\n" <<
0621           "+insert4\n" <<
0622           "+insert5\n" <<
0623           " line4\n" <<
0624           "@@ -21,4 +23,2 @@\n" <<
0625           " line5\n" <<
0626           "-delete4\n" <<
0627           "-delete5\n" <<
0628           " line6\n" <<
0629           "@@ -31,3 +31,3 @@\n" <<
0630           " line7\n" <<
0631           "-delete6\n" <<
0632           "+insert6\n" <<
0633           " line8\n";
0634     Parser parser(nullptr);
0635     bool malformed;
0636     DiffModelList* models = parser.parse(patch, &malformed);
0637     QVERIFY(!malformed);
0638     QCOMPARE(models->size(), 1);
0639     DiffModel* model = models->at(0);
0640     QCOMPARE(model->differenceCount(), 4);
0641     model->applyAllDifferences(true);
0642 
0643     const auto differences = *model->differences();
0644     for (Difference* diff : differences) {
0645         QVERIFY(diff->applied());
0646     }
0647     model->applyAllDifferences(false);
0648     QVERIFY(!model->differenceAt(0)->applied());
0649     QCOMPARE(model->differenceAt(0)->sourceLineNumber(), 2);
0650     QCOMPARE(model->differenceAt(0)->trackingDestinationLineNumber(), 2);
0651     QVERIFY(!model->differenceAt(1)->applied());
0652     QCOMPARE(model->differenceAt(1)->sourceLineNumber(), 12);
0653     QCOMPARE(model->differenceAt(1)->trackingDestinationLineNumber(), 12);
0654     QVERIFY(!model->differenceAt(2)->applied());
0655     QCOMPARE(model->differenceAt(2)->sourceLineNumber(), 22);
0656     QCOMPARE(model->differenceAt(2)->trackingDestinationLineNumber(), 22);
0657     QVERIFY(!model->differenceAt(3)->applied());
0658     QCOMPARE(model->differenceAt(3)->sourceLineNumber(), 32);
0659     QCOMPARE(model->differenceAt(3)->trackingDestinationLineNumber(), 32);
0660 
0661     model->differenceAt(1)->apply(true);
0662     QVERIFY(model->differenceAt(1)->applied());
0663     QCOMPARE(model->differenceAt(1)->sourceLineNumber(), 12);
0664     QCOMPARE(model->differenceAt(1)->trackingDestinationLineNumber(), 12);
0665     QVERIFY(!model->differenceAt(2)->applied());
0666     QCOMPARE(model->differenceAt(2)->sourceLineNumber(), 22);
0667     QCOMPARE(model->differenceAt(2)->trackingDestinationLineNumber(), 23);
0668     QVERIFY(!model->differenceAt(3)->applied());
0669     QCOMPARE(model->differenceAt(3)->sourceLineNumber(), 32);
0670     QCOMPARE(model->differenceAt(3)->trackingDestinationLineNumber(), 33);
0671 
0672     model->differenceAt(1)->apply(true);
0673     QVERIFY(model->differenceAt(1)->applied());
0674     QCOMPARE(model->differenceAt(1)->sourceLineNumber(), 12);
0675     QCOMPARE(model->differenceAt(1)->trackingDestinationLineNumber(), 12);
0676     QVERIFY(!model->differenceAt(2)->applied());
0677     QCOMPARE(model->differenceAt(2)->sourceLineNumber(), 22);
0678     QCOMPARE(model->differenceAt(2)->trackingDestinationLineNumber(), 23);
0679     QVERIFY(!model->differenceAt(3)->applied());
0680     QCOMPARE(model->differenceAt(3)->sourceLineNumber(), 32);
0681     QCOMPARE(model->differenceAt(3)->trackingDestinationLineNumber(), 33);
0682 
0683     model->differenceAt(2)->apply(true);
0684     QVERIFY(model->differenceAt(2)->applied());
0685     QCOMPARE(model->differenceAt(2)->sourceLineNumber(), 22);
0686     QCOMPARE(model->differenceAt(2)->trackingDestinationLineNumber(), 23);
0687     QVERIFY(!model->differenceAt(3)->applied());
0688     QCOMPARE(model->differenceAt(3)->sourceLineNumber(), 32);
0689     QCOMPARE(model->differenceAt(3)->trackingDestinationLineNumber(), 31);
0690 
0691     model->applyAllDifferences(true);
0692     QVERIFY(model->differenceAt(0)->applied());
0693     QCOMPARE(model->differenceAt(0)->sourceLineNumber(), 2);
0694     QCOMPARE(model->differenceAt(0)->trackingDestinationLineNumber(), 2);
0695     QVERIFY(model->differenceAt(1)->applied());
0696     QCOMPARE(model->differenceAt(1)->sourceLineNumber(), 12);
0697     QCOMPARE(model->differenceAt(1)->trackingDestinationLineNumber(), 13);
0698     QVERIFY(model->differenceAt(2)->applied());
0699     QCOMPARE(model->differenceAt(2)->sourceLineNumber(), 22);
0700     QCOMPARE(model->differenceAt(2)->trackingDestinationLineNumber(), 24);
0701     QVERIFY(model->differenceAt(3)->applied());
0702     QCOMPARE(model->differenceAt(3)->sourceLineNumber(), 32);
0703     QCOMPARE(model->differenceAt(3)->trackingDestinationLineNumber(), 32);
0704 
0705     model->applyAllDifferences(true);
0706     QVERIFY(model->differenceAt(0)->applied());
0707     QCOMPARE(model->differenceAt(0)->sourceLineNumber(), 2);
0708     QCOMPARE(model->differenceAt(0)->trackingDestinationLineNumber(), 2);
0709     QVERIFY(model->differenceAt(1)->applied());
0710     QCOMPARE(model->differenceAt(1)->sourceLineNumber(), 12);
0711     QCOMPARE(model->differenceAt(1)->trackingDestinationLineNumber(), 13);
0712     QVERIFY(model->differenceAt(2)->applied());
0713     QCOMPARE(model->differenceAt(2)->sourceLineNumber(), 22);
0714     QCOMPARE(model->differenceAt(2)->trackingDestinationLineNumber(), 24);
0715     QVERIFY(model->differenceAt(3)->applied());
0716     QCOMPARE(model->differenceAt(3)->sourceLineNumber(), 32);
0717     QCOMPARE(model->differenceAt(3)->trackingDestinationLineNumber(), 32);
0718 }
0719 
0720 static void
0721 contextDiff1()
0722 {
0723     QStringList patch;
0724     patch <<
0725           "commit 7377fcc682e85ef9784adb2a2da2c8c6756f9018 (HEAD, KDE/4.11)\n" <<
0726           "Author:     Dr. ChocholouĊĦek <bla@zin.ec>\n" <<
0727           "AuthorDate: Sat Jan 25 17:30:01 2014 +0100\n" <<
0728           "\n" <<
0729           "    Fake diff.\n" <<
0730           "\n" <<
0731           "diff --git a/libdiff2/diffmodel.cpp b/libdiff2/diffmodel.cpp\n" <<
0732           "new file mode 100644\n" <<
0733           "index a42e82d..a8da0c9\n" <<
0734           "*** a/libdiff2/diffmodel.cpp\n" <<  // note the missing timestamps
0735           "--- b/libdiff2/diffmodel.cpp\n" <<
0736           "*************** DiffModel::DiffModel() :\n" <<
0737           "*** 58,64 ****\n" <<
0738           "     m_sourceFile( "" ),\n" <<
0739           "     m_destinationFile( "" ),\n" <<
0740           "     m_sourceTimestamp( "" ),\n" <<
0741           "!    m_destinationTimestamp( "" ),\n" <<
0742           "     m_sourceRevision( "" ),\n" <<
0743           "     m_destinationRevision( "" ),\n" <<
0744           "     m_appliedCount( 0 ),\n" <<
0745           "--- 58,64 ----\n" <<
0746           "     m_sourceFile( "" ),\n" <<
0747           "     m_destinationFile( "" ),\n" <<
0748           "     m_sourceTimestamp( "" ),\n" <<
0749           "!    m_destinationTimestamp( \"doh\" ),\n" <<
0750           "     m_sourceRevision( "" ),\n" <<
0751           "     m_destinationRevision( "" ),\n" <<
0752           "     m_appliedCount( 0 ),\n" <<
0753           "*************** void DiffModel::splitSourceInPathAndFile\n" <<
0754           "*** 84,89 ****\n" <<
0755           "--- 84,91 ----\n" <<
0756           "     if( ( pos = m_source.lastIndexOf( \"/\" ) ) >= 0 )\n" <<
0757           "         m_sourcePath = m_source.mid( 0, pos+1 );\n" <<
0758           "  \n" <<
0759           "+    add_this;\n" <<
0760           "+ \n" <<
0761           "     if( ( pos = m_source.lastIndexOf( \"/\" ) ) >= 0 )\n" <<
0762           "         m_sourceFile = m_source.mid( pos+1, m_source.length() - pos );\n" <<
0763           "     else\n";
0764     Parser parser(nullptr);
0765     bool malformed;
0766     DiffModelList* models = parser.parse(patch, &malformed);
0767     QVERIFY(!malformed);
0768     QCOMPARE(models->size(), 1);
0769     DiffModel* model = models->at(0);
0770     QCOMPARE(model->differenceCount(), 2);
0771     model->applyAllDifferences(true);
0772     QVERIFY(model->differenceAt(0)->applied());
0773     QCOMPARE(model->differenceAt(0)->sourceLineNumber(), 61);
0774     QCOMPARE(model->differenceAt(0)->trackingDestinationLineNumber(), 61);
0775     QCOMPARE(model->differenceAt(1)->sourceLineNumber(), 87);
0776     QCOMPARE(model->differenceAt(1)->trackingDestinationLineNumber(), 87);
0777 }
0778 
0779 static void
0780 contextDiff2()
0781 {
0782     QStringList patch;
0783     patch <<
0784           "*** a/libdiff2/diffmodel.cpp\n" <<
0785           "--- b/libdiff2/diffmodel.cpp\n" <<
0786           "***************\n" <<
0787           "*** 55,60 **** DiffModel::DiffModel() :\n" << // note the  context here
0788           "--- 55,61 ----\n" <<
0789           "     m_destination( "" ),\n" <<
0790           "     m_sourcePath( "" ),\n" <<
0791           "     m_destinationPath( "" ),\n" <<
0792           "+    m_hoh ( "" );\n" <<
0793           "     m_sourceFile( "" ),\n" <<
0794           "     m_destinationFile( "" ),\n" <<
0795           "     m_sourceTimestamp( "" ),\n";
0796 
0797     Parser parser(nullptr);
0798     bool malformed;
0799     DiffModelList* models = parser.parse(patch, &malformed);
0800     QVERIFY(!malformed);
0801     QCOMPARE(models->size(), 1);
0802     DiffModel* model = models->at(0);
0803     QCOMPARE(model->differenceCount(), 1);
0804     model->applyAllDifferences(true);
0805     QVERIFY(model->differenceAt(0)->applied());
0806     QCOMPARE(model->differenceAt(0)->sourceLineNumber(), 58);
0807     QCOMPARE(model->differenceAt(0)->trackingDestinationLineNumber(), 58);
0808 }
0809 
0810 void InteractiveDiffTest::testContextDiff()
0811 {
0812     contextDiff1();
0813     contextDiff2();
0814 }
0815 
0816 void InteractiveDiffTest::testNormalDiff()
0817 {
0818     QStringList patch;
0819     patch <<
0820           "1c1\n" <<
0821           "< a\n" <<
0822           "---\n" <<
0823           "> b\n";
0824     Parser parser(nullptr);
0825     bool malformed;
0826     DiffModelList* models = parser.parse(patch, &malformed);
0827     QVERIFY(!malformed);
0828     QCOMPARE(models->size(), 1);
0829     DiffModel* model = models->at(0);
0830     QCOMPARE(model->differenceCount(), 1);
0831     model->applyAllDifferences(true);
0832     QVERIFY(model->differenceAt(0)->applied());
0833     QCOMPARE(model->differenceAt(0)->sourceLineNumber(), 1);
0834     QCOMPARE(model->differenceAt(0)->trackingDestinationLineNumber(), 1);
0835 }
0836 
0837 QTEST_GUILESS_MAIN(InteractiveDiffTest);
0838 
0839 #include "moc_interactivedifftest.cpp"