1 /*
2     SPDX-FileCopyrightText: 2017 Friedrich W. H. Kossebau <kossebau@kde.org>
3 
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "test_vcsdiff.h"
8 
9 #include <QTest>
10 #include <QStandardPaths>
11 
12 #include <vcs/vcslocation.h>
13 
14 using namespace KDevelop;
15 
initTestCase()16 void TestVcsDiff::initTestCase()
17 {
18     QStandardPaths::setTestModeEnabled(true);
19     QString path = QFINDTESTDATA("sample.diff");
20     QFile in(path);
21     QCOMPARE(in.open(QIODevice::ReadOnly), true);
22     sampleDiff = QString::fromUtf8(in.readAll());
23     QCOMPARE(sampleDiff.length(), 6235);
24 }
25 
setDiff(VcsDiff & diff,const QString & diffString,const QUrl & baseDiff,uint depth)26 void TestVcsDiff::setDiff(VcsDiff& diff,
27                           const QString& diffString,
28                           const QUrl& baseDiff,
29                           uint depth)
30 {
31     diff.setDiff(diffString);
32     diff.setBaseDiff(baseDiff);
33     diff.setDepth(depth);
34 }
35 
compareDiff(const VcsDiff & diff,const QString & diffString,const QUrl & baseDiff,uint depth)36 void TestVcsDiff::compareDiff(const VcsDiff& diff,
37                               const QString& diffString,
38                               const QUrl& baseDiff,
39                               uint depth)
40 {
41     QCOMPARE(diff.diff(), diffString);
42     QCOMPARE(diff.baseDiff(), baseDiff);
43     QCOMPARE(diff.depth(), depth);
44 }
45 
testFileNames()46 void TestVcsDiff::testFileNames()
47 {
48     VcsDiff diff;
49     diff.setDiff(sampleDiff);
50     const QVector<VcsDiff::FilePair> expected = {
51         {"kdevplatform/vcs/vcsdiff.cpp", "kdevplatform/vcs/vcsdiff.cpp"},
52         {"kdevplatform/vcs/vcsdiff.h", "kdevplatform/vcs/vcsdiff.h"}
53     };
54     QCOMPARE(diff.fileNames(), expected);
55 }
56 
testSubDiff()57 void TestVcsDiff::testSubDiff()
58 {
59     /**************************
60      * Test a real world diff *
61      **************************/
62     VcsDiff diff;
63     diff.setDiff(sampleDiff);
64     QString expected(R"diff(--- a/kdevplatform/vcs/vcsdiff.cpp
65 +++ b/kdevplatform/vcs/vcsdiff.cpp
66 @@ -39,7 +39,7 @@ public:
67         , oldCount
68         , newStart
69         , newCount
70 -       , firstLineIdx
71 +       , firstLineIdx  /**< The 0-based line number (in the whole diff) of the hunk header line (the one starting with `@@`) */
72         ;
73      QString srcFile    /**< The source filename */
74            , tgtFile    /**< The target filename */
75 )diff");
76     const auto subHunkDiffs = {
77         diff.subDiffHunk(15),
78     };
79     for(auto df: subHunkDiffs) {
80         QVERIFY(df.fileNames().count()>0);
81         QCOMPARE(df.fileNames().front().source, "kdevplatform/vcs/vcsdiff.cpp");
82         QCOMPARE(df.diff(), expected);
83     }
84 
85     VcsDiff subHunkDiff = diff.subDiff(15, 50);
86     QVERIFY(subHunkDiff.fileNames().count()>0);
87     QCOMPARE(subHunkDiff.fileNames().front().source, "kdevplatform/vcs/vcsdiff.cpp");
88 
89     /*********************************
90      * Test start offset computation *
91      *********************************/
92     VcsDiff skipDiff;
93     skipDiff.setDiff(R"diff(--- a/skip
94 +++ b/skip
95 @@ -1,2 +3,2 @@ heading
96 + increase offset
97 
98 + dont increase offset
99 - deletion
100 - second deletion
101 )diff");
102     expected = QStringLiteral(R"diff(--- a/skip
103 +++ b/skip
104 @@ -2,3 +4,2 @@ heading
105 
106 - deletion
107   second deletion
108 )diff");
109     auto subDiff = skipDiff.subDiff(6,6);
110     QCOMPARE(subDiff.diff(), expected);
111 
112 }
113 
testConflicts()114 void TestVcsDiff::testConflicts()
115 {
116     VcsDiff conflictDiff;
117     conflictDiff.setDiff(R"diff(--- a/skip
118 +++ b/skip
119 @@ -1,2 +3,2 @@ conflict
120 + increase offset            3     2
121                              4  0  3
122 + dont increase offset       5     4
123 - deletion                   6  1
124 <<<<<<< HEAD                 7
125 blablabla                    8  2
126 =======                      9
127 yadayadayada                10     5
128 >>>>>>> commit              11
129 - second deletion           12  3
130 )diff");
131     QCOMPARE(conflictDiff.diffLineToSourceLine(8), 2);
132     QCOMPARE(conflictDiff.diffLineToTargetLine(10), 5);
133     QCOMPARE(conflictDiff.diffLineToSourceLine(7), -1);
134     QCOMPARE(conflictDiff.diffLineToSourceLine(9), -1);
135     QCOMPARE(conflictDiff.diffLineToSourceLine(11), -1);
136 }
137 
138 
testLineMapping()139 void TestVcsDiff::testLineMapping()
140 {
141     VcsDiff diff;
142     diff.setDiff(sampleDiff);
143 
144     // We have no way to map the headings
145     QCOMPARE(diff.diffLineToSourceLine(169-1), -1);
146     QCOMPARE(diff.diffLineToTargetLine(169-1), -1);
147 
148     QCOMPARE(diff.diffLineToSourceLine(15-1), 42-1);
149     QCOMPARE(diff.diffLineToTargetLine(15-1), -1);
150 
151     QCOMPARE(diff.diffLineToTargetLine(147-1), 180-1);
152     QCOMPARE(diff.diffLineToSourceLine(147-1), 150-1);
153 }
154 
155 
testCopyConstructor()156  void TestVcsDiff::testCopyConstructor()
157  {
158     // test plain copy
159     const QString diffString("diff");
160     const QUrl baseDiff("git://1");
161     const uint depth = 1;
162     const VcsLocation location("server");
163 
164     {
165         VcsDiff diffA;
166         setDiff(diffA,
167                 diffString, baseDiff, depth);
168 
169         VcsDiff diffB(diffA);
170         compareDiff(diffA,
171                     diffString, baseDiff, depth);
172         compareDiff(diffB,
173                     diffString, baseDiff, depth);
174     }
175 
176     const QString diffStringNew("diffNew");
177 
178     // test detach after changing A
179     {
180         VcsDiff diffA;
181         setDiff(diffA,
182                 diffString, baseDiff, depth);
183 
184         VcsDiff diffB(diffA);
185         // change a property of A
186         diffA.setDiff(diffStringNew);
187 
188         compareDiff(diffA,
189                     diffStringNew, baseDiff, depth);
190         compareDiff(diffB,
191                     diffString, baseDiff, depth);
192     }
193 }
194 
testAssignOperator()195 void TestVcsDiff::testAssignOperator()
196 {
197     // test plain copy
198     const QString diffString("diff");
199     const QUrl baseDiff("git://1");
200     const uint depth = 1;
201     const VcsLocation location("server");
202 
203     {
204         VcsDiff diffA;
205         setDiff(diffA,
206                 diffString, baseDiff, depth);
207 
208         VcsDiff diffB;
209         diffB = diffA;
210         compareDiff(diffA,
211                     diffString, baseDiff, depth);
212         compareDiff(diffB,
213                     diffString, baseDiff, depth);
214     }
215 
216     const QString diffStringNew("diffNew");
217 
218     // test detach after changing A
219     {
220         VcsDiff diffA;
221         setDiff(diffA,
222                 diffString, baseDiff, depth);
223 
224         VcsDiff diffB;
225         diffB = diffA;
226         // change a property of A
227         diffA.setDiff(diffStringNew);
228 
229         compareDiff(diffA,
230                     diffStringNew, baseDiff, depth);
231         compareDiff(diffB,
232                     diffString,    baseDiff, depth);
233     }
234 }
235 
236 QTEST_GUILESS_MAIN(TestVcsDiff)
237