File indexing completed on 2024-04-21 05:44:11

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