File indexing completed on 2024-05-12 04:38:09

0001 /*
0002     SPDX-FileCopyrightText: 2012 Milian Wolff <mail@milianw.de>
0003     SPDX-FileCopyrightText: 2012 Morten Danielsen Volden <mvolden2@gmail.com>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "test_filteringstrategy.h"
0009 #include "testlinebuilderfunctions.h"
0010 
0011 #include <outputview/outputfilteringstrategies.h>
0012 #include <outputview/filtereditem.h>
0013 #include <util/path.h>
0014 
0015 #include <QStandardPaths>
0016 
0017 using namespace KDevelop;
0018 
0019 QTEST_GUILESS_MAIN(TestFilteringStrategy)
0020 
0021 namespace QTest {
0022 
0023 template<>
0024 inline char* toString(const FilteredItem::FilteredOutputItemType& type)
0025 {
0026     switch (type) {
0027         case FilteredItem::ActionItem:
0028             return qstrdup("ActionItem");
0029         case FilteredItem::CustomItem:
0030             return qstrdup("CustomItem");
0031         case FilteredItem::ErrorItem:
0032             return qstrdup("ErrorItem");
0033         case FilteredItem::InformationItem:
0034             return qstrdup("InformationItem");
0035         case FilteredItem::InvalidItem:
0036             return qstrdup("InvalidItem");
0037         case FilteredItem::StandardItem:
0038             return qstrdup("StandardItem");
0039         case FilteredItem::WarningItem:
0040             return qstrdup("WarningItem");
0041     }
0042     return qstrdup("unknown");
0043 }
0044 
0045 inline QTestData& newRowForPathType(const char *dataTag, TestPathType pathType)
0046 {
0047     switch (pathType)
0048     {
0049         case UnixFilePathNoSpaces:
0050             return QTest::newRow(QString(QLatin1String(dataTag)+QLatin1String("-unix-ns")).toUtf8().constData());
0051         case UnixFilePathWithSpaces:
0052             return QTest::newRow(QString(QLatin1String(dataTag)+QLatin1String("-unix-ws")).toUtf8().constData());
0053         case WindowsFilePathNoSpaces:
0054             return QTest::newRow(QString(QLatin1String(dataTag)+QLatin1String("-windows-ns")).toUtf8().constData());
0055         case WindowsFilePathWithSpaces:
0056             return QTest::newRow(QString(QLatin1String(dataTag)+QLatin1String("-windows-ws")).toUtf8().constData());
0057     }
0058     Q_UNREACHABLE();
0059 }
0060 
0061 }
0062 
0063 void TestFilteringStrategy::initTestCase()
0064 {
0065     QStandardPaths::setTestModeEnabled(true);
0066 }
0067 
0068 void TestFilteringStrategy::testNoFilterStrategy_data()
0069 {
0070     QTest::addColumn<QString>("line");
0071     QTest::addColumn<FilteredItem::FilteredOutputItemType>("expected");
0072 
0073     for (TestPathType pathType :
0074 #ifdef Q_OS_WIN
0075         {WindowsFilePathNoSpaces, WindowsFilePathWithSpaces}
0076 
0077 #else
0078         {UnixFilePathNoSpaces, UnixFilePathWithSpaces}
0079 #endif
0080     ) {
0081         QTest::newRowForPathType("cppcheck-error-line", pathType)
0082         << buildCppCheckErrorLine(pathType) << FilteredItem::InvalidItem;
0083         QTest::newRowForPathType("compiler-line", pathType)
0084         << buildCompilerLine(pathType) << FilteredItem::InvalidItem;
0085         QTest::newRowForPathType("compiler-error-line", pathType)
0086         << buildCompilerErrorLine(pathType) << FilteredItem::InvalidItem;
0087         QTest::newRowForPathType("compiler-information-line", pathType)
0088         << buildCompilerInformationLine(pathType) << FilteredItem::InvalidItem;
0089         QTest::newRowForPathType("python-error-line", pathType)
0090         << buildPythonErrorLine(pathType) << FilteredItem::InvalidItem;
0091     }
0092     QTest::newRow("cppcheck-info-line")
0093     << buildCppCheckInformationLine() << FilteredItem::InvalidItem;
0094     QTest::newRow("compiler-action-line")
0095     << buildCompilerActionLine() << FilteredItem::InvalidItem;
0096 }
0097 
0098 void TestFilteringStrategy::testNoFilterStrategy()
0099 {
0100     QFETCH(QString, line);
0101     QFETCH(FilteredItem::FilteredOutputItemType, expected);
0102     NoFilterStrategy testee;
0103     FilteredItem item1 = testee.errorInLine(line);
0104     QCOMPARE(item1.type, expected);
0105     item1 = testee.actionInLine(line);
0106     QCOMPARE(item1.type, expected);
0107 }
0108 
0109 void TestFilteringStrategy::testCompilerFilterStrategy_data()
0110 {
0111     QTest::addColumn<QString>("line");
0112     QTest::addColumn<FilteredItem::FilteredOutputItemType>("expectedError");
0113     QTest::addColumn<FilteredItem::FilteredOutputItemType>("expectedAction");
0114     QTest::addColumn<TestPathType>("pathType");
0115 
0116     QTest::newRow("cppcheck-info-line")
0117     << buildCppCheckInformationLine() << FilteredItem::InvalidItem << FilteredItem::InvalidItem << UnixFilePathNoSpaces;
0118     for (TestPathType pathType :
0119 #ifdef Q_OS_WIN
0120         {WindowsFilePathNoSpaces, WindowsFilePathWithSpaces}
0121 #else
0122         {UnixFilePathNoSpaces, UnixFilePathWithSpaces}
0123 #endif
0124     ) {
0125         QTest::newRowForPathType("cppcheck-error-line", pathType)
0126         << buildCppCheckErrorLine(pathType) << FilteredItem::InvalidItem << FilteredItem::InvalidItem << pathType;
0127         QTest::newRowForPathType("compiler-line", pathType)
0128         << buildCompilerLine(pathType) << FilteredItem::InvalidItem << FilteredItem::InvalidItem << pathType;
0129         QTest::newRowForPathType("compiler-error-line", pathType)
0130         << buildCompilerErrorLine(pathType) << FilteredItem::ErrorItem << FilteredItem::InvalidItem << pathType;
0131         QTest::newRowForPathType("compiler-information-line", pathType)
0132         << buildCompilerInformationLine(pathType) << FilteredItem::InformationItem << FilteredItem::InvalidItem << pathType;
0133         QTest::newRowForPathType("compiler-information-line2", pathType)
0134         << buildInfileIncludedFromFirstLine(pathType) << FilteredItem::InformationItem << FilteredItem::InvalidItem << pathType;
0135         QTest::newRowForPathType("compiler-information-line3", pathType)
0136         << buildInfileIncludedFromSecondLine(pathType) << FilteredItem::InformationItem << FilteredItem::InvalidItem << pathType;
0137         QTest::newRow("cmake-error-line1")
0138         << "CMake Error at CMakeLists.txt:2 (cmake_minimum_required):" << FilteredItem::ErrorItem << FilteredItem::InvalidItem << pathType;
0139         QTest::newRow("cmake-error-multiline1")
0140         << "CMake Error: Error in cmake code at" << FilteredItem::InvalidItem << FilteredItem::InvalidItem << pathType;
0141         QTest::newRowForPathType("cmake-error-multiline2", pathType)
0142         << buildCmakeConfigureMultiLine(pathType) << FilteredItem::ErrorItem << FilteredItem::InvalidItem << pathType;
0143         QTest::newRowForPathType("cmake-warning-line", pathType)
0144         << "CMake Warning (dev) in CMakeLists.txt:" << FilteredItem::WarningItem << FilteredItem::InvalidItem << pathType;
0145         QTest::newRowForPathType("cmake-automoc-error", pathType)
0146         << buildAutoMocLine(pathType) << FilteredItem::ErrorItem << FilteredItem::InvalidItem << pathType;
0147         QTest::newRowForPathType("cmake-automoc4-error", pathType)
0148         << buildOldAutoMocLine(pathType) << FilteredItem::InformationItem << FilteredItem::InvalidItem << pathType;
0149         QTest::newRowForPathType("cmake-autogen-error", pathType)
0150         << buildAutoMocLine(pathType, false) << FilteredItem::ErrorItem << FilteredItem::InvalidItem << pathType;
0151         QTest::newRowForPathType("linker-action-line", pathType)
0152         << "linking testCustombuild (g++)" << FilteredItem::InvalidItem << FilteredItem::ActionItem << pathType;
0153         QTest::newRowForPathType("linker-error-line", pathType)
0154         << buildLinkerErrorLine(pathType) << FilteredItem::ErrorItem << FilteredItem::InvalidItem << pathType;
0155         QTest::newRowForPathType("python-error-line", pathType)
0156         << buildPythonErrorLine(pathType) << FilteredItem::InvalidItem << FilteredItem::InvalidItem << pathType;
0157     }
0158 }
0159 
0160 void TestFilteringStrategy::testCompilerFilterStrategy()
0161 {
0162     QFETCH(QString, line);
0163     QFETCH(FilteredItem::FilteredOutputItemType, expectedError);
0164     QFETCH(FilteredItem::FilteredOutputItemType, expectedAction);
0165     QFETCH(TestPathType, pathType);
0166 
0167     QUrl projecturl = QUrl::fromLocalFile( projectPath(pathType) );
0168     CompilerFilterStrategy testee(projecturl);
0169     FilteredItem item1 = testee.errorInLine(line);
0170     QCOMPARE(item1.type, expectedError);
0171     item1 = testee.actionInLine(line);
0172     QCOMPARE(item1.type, expectedAction);
0173 }
0174 
0175 void TestFilteringStrategy::testCompilerFilterstrategyMultipleKeywords_data()
0176 {
0177     QTest::addColumn<QString>("line");
0178     QTest::addColumn<FilteredItem::FilteredOutputItemType>("expectedError");
0179     QTest::addColumn<FilteredItem::FilteredOutputItemType>("expectedAction");
0180 
0181     QTest::newRow("warning-containing-error-word")
0182     << "RingBuffer.cpp:64:6: warning: unused parameter ‘errorItem’ [-Wunused-parameter]"
0183     << FilteredItem::WarningItem << FilteredItem::InvalidItem;
0184     QTest::newRow("error-containing-info-word")
0185     << "NodeSet.hpp:89:27: error: ‘Info’ was not declared in this scope"
0186     << FilteredItem::ErrorItem << FilteredItem::InvalidItem;
0187     QTest::newRow("warning-in-filename-containing-error-word")
0188     << "ErrorHandling.cpp:100:56: warning: unused parameter ‘item’ [-Wunused-parameter]"
0189     << FilteredItem::WarningItem << FilteredItem::InvalidItem;
0190     QTest::newRow("error-in-filename-containing-warning-word")
0191     << "WarningHandling.cpp:100:56: error: ‘Item’ was not declared in this scope"
0192     << FilteredItem::ErrorItem << FilteredItem::InvalidItem;
0193 }
0194 
0195 void TestFilteringStrategy::testCompilerFilterstrategyMultipleKeywords()
0196 {
0197 #ifdef Q_OS_WIN
0198     TestPathType pathTypeToUse = WindowsFilePathNoSpaces;
0199 #else
0200     TestPathType pathTypeToUse = UnixFilePathNoSpaces;
0201 #endif
0202     QFETCH(QString, line);
0203     QFETCH(FilteredItem::FilteredOutputItemType, expectedError);
0204     QFETCH(FilteredItem::FilteredOutputItemType, expectedAction);
0205     QUrl projecturl = QUrl::fromLocalFile( projectPath(pathTypeToUse) );
0206     CompilerFilterStrategy testee(projecturl);
0207     FilteredItem item1 = testee.errorInLine(line);
0208     QCOMPARE(item1.type, expectedError);
0209     item1 = testee.actionInLine(line);
0210     QCOMPARE(item1.type, expectedAction);
0211 }
0212 
0213 void TestFilteringStrategy::testScriptErrorFilterStrategy_data()
0214 {
0215     QTest::addColumn<QString>("line");
0216     QTest::addColumn<FilteredItem::FilteredOutputItemType>("expectedError");
0217     QTest::addColumn<FilteredItem::FilteredOutputItemType>("expectedAction");
0218 
0219     QTest::newRow("cppcheck-info-line")
0220     << buildCppCheckInformationLine() << FilteredItem::InvalidItem << FilteredItem::InvalidItem;
0221     for (TestPathType pathType : {UnixFilePathNoSpaces, UnixFilePathWithSpaces}) {
0222         QTest::newRowForPathType("cppcheck-error-line", pathType)
0223         << buildCppCheckErrorLine(pathType) << FilteredItem::ErrorItem << FilteredItem::InvalidItem;
0224         QTest::newRowForPathType("compiler-line", pathType)
0225         << buildCompilerLine(pathType) << FilteredItem::InvalidItem << FilteredItem::InvalidItem;
0226         QTest::newRowForPathType("compiler-error-line", pathType)
0227         << buildCompilerErrorLine(pathType) << FilteredItem::ErrorItem << FilteredItem::InvalidItem;
0228     }
0229     QTest::newRow("compiler-action-line")
0230     << "linking testCustombuild (g++)" << FilteredItem::InvalidItem << FilteredItem::InvalidItem;
0231     for (TestPathType pathType : {UnixFilePathNoSpaces, UnixFilePathWithSpaces}) {
0232         QTest::newRowForPathType("python-error-line", pathType)
0233         << buildPythonErrorLine(pathType) << FilteredItem::InvalidItem << FilteredItem::InvalidItem;
0234     }
0235 }
0236 
0237 void TestFilteringStrategy::testScriptErrorFilterStrategy()
0238 {
0239     QFETCH(QString, line);
0240     QFETCH(FilteredItem::FilteredOutputItemType, expectedError);
0241     QFETCH(FilteredItem::FilteredOutputItemType, expectedAction);
0242     ScriptErrorFilterStrategy testee;
0243     FilteredItem item1 = testee.errorInLine(line);
0244     QCOMPARE(item1.type, expectedError);
0245     item1 = testee.actionInLine(line);
0246     QCOMPARE(item1.type, expectedAction);
0247 }
0248 
0249 void TestFilteringStrategy::testNativeAppErrorFilterStrategy_data()
0250 {
0251     QTest::addColumn<QString>("line");
0252     QTest::addColumn<QString>("file");
0253     QTest::addColumn<int>("lineNo");
0254     QTest::addColumn<int>("column");
0255     QTest::addColumn<FilteredItem::FilteredOutputItemType>("itemtype");
0256 
0257     // BEGIN: C++
0258     QTest::newRow("cassert")
0259         << "a.out: /foo/bar/test.cpp:5: int main(): Assertion `false' failed."
0260         << "/foo/bar/test.cpp"
0261         << 4 << 0 << FilteredItem::ErrorItem;
0262 
0263     // same filter, may also may match on custom assert messages
0264     QTest::newRow("custom-assert")
0265         << "code at: /osm2go/tests/osm_edit.cpp:47: int main(): Assertion foo = bar failed: foo = 5, bar = 4"
0266         << "/osm2go/tests/osm_edit.cpp"
0267         << 46 << 0 << FilteredItem::ErrorItem;
0268 
0269     QTest::newRow("glibc assert_perror()")
0270         << "a.out: /foo/bar/test.cpp:2009: int void {anonymous}::main(): Unexpected error: Broken pipe."
0271         << "/foo/bar/test.cpp"
0272         << 2008 << 0 << FilteredItem::ErrorItem;
0273     // END: C++
0274 
0275     // BEGIN: Qt
0276     // TODO: qt-connect-* and friends shouldn't be error items but warnings items instead
0277     // this needs refactoring in outputfilteringstrategies, though...
0278     QTest::newRow("qt-connect-nosuch-slot")
0279         << "QObject::connect: No such slot Foo::bar() in /foo/bar.cpp:313"
0280         << "/foo/bar.cpp"
0281         << 312 << 0 << FilteredItem::ErrorItem;
0282     QTest::newRow("qt-connect-nosuch-signal")
0283         << "QObject::connect: No such signal Foo::bar() in /foo/bar.cpp:313"
0284         << "/foo/bar.cpp"
0285         << 312 << 0 << FilteredItem::ErrorItem;
0286     QTest::newRow("qt-connect-parentheses-slot")
0287         << "QObject::connect: Parentheses expected, slot Foo::bar() in /foo/bar.cpp:313"
0288         << "/foo/bar.cpp"
0289         << 312 << 0 << FilteredItem::ErrorItem;
0290     QTest::newRow("qt-connect-parentheses-signal")
0291         << "QObject::connect: Parentheses expected, signal Foo::bar() in /foo/bar.cpp:313"
0292         << "/foo/bar.cpp"
0293         << 312 << 0 << FilteredItem::ErrorItem;
0294     QTest::newRow("qt-assert")
0295         << "ASSERT: \"errors().isEmpty()\" in file /tmp/foo/bar.cpp, line 49"
0296         << "/tmp/foo/bar.cpp"
0297         << 48 << 0 << FilteredItem::ErrorItem;
0298     QTest::newRow("qttest-assert")
0299         << "QFATAL : FooTest::testBar() ASSERT: \"index.isValid()\" in file /foo/bar.cpp, line 32"
0300         << "/foo/bar.cpp"
0301         << 31 << 0 << FilteredItem::ErrorItem;
0302     QTest::newRow("qttest-loc")
0303         << "   Loc: [/foo/bar.cpp(33)]"
0304         << "/foo/bar.cpp"
0305         << 32 << 0 << FilteredItem::ErrorItem;
0306     QTest::newRow("qttest-loc-nocatch")
0307         << "   Loc: [Unknown file(0)]"
0308         << ""
0309         << -1 << -1 << FilteredItem::InvalidItem;
0310     QTest::newRow("qml-import-unix")
0311         << "file:///path/to/foo.qml:7:1: Bar is not a type"
0312         << "/path/to/foo.qml"
0313         << 6 << 0 << FilteredItem::ErrorItem;
0314     QTest::newRow("qml-import-unix1")
0315         << "file:///path/to/foo.qml:7:1: Bar is ambiguous. Found in A and in B"
0316         << "/path/to/foo.qml"
0317         << 6 << 0 << FilteredItem::ErrorItem;
0318     QTest::newRow("qml-import-unix2")
0319         << "file:///path/to/foo.qml:7:1: Bar is instantiated recursively"
0320         << "/path/to/foo.qml"
0321         << 6 << 0 << FilteredItem::ErrorItem;
0322     QTest::newRow("qml-typeerror")
0323         << "file:///path/to/foo.qml:7: TypeError: Cannot read property 'height' of null"
0324         << "/path/to/foo.qml"
0325         << 6 << 0 << FilteredItem::ErrorItem;
0326     QTest::newRow("qml-referenceerror")
0327         << "file:///path/to/foo.qml:7: ReferenceError: readOnly is not defined"
0328         << "/path/to/foo.qml"
0329         << 6 << 0 << FilteredItem::ErrorItem;
0330     QTest::newRow("qml-bindingloop")
0331         << "file:///path/to/foo.qml:7:5: QML Row: Binding loop detected for property \"height\""
0332         << "/path/to/foo.qml"
0333         << 6 << 4 << FilteredItem::ErrorItem;
0334     // END: Qt
0335 
0336     // BEGIN: glib
0337     QTest::newRow("g_assert(0) with domain")
0338         << "GIO:ERROR:/foo/test.cpp:46:int main(): assertion failed: (0)"
0339         << "/foo/test.cpp"
0340         << 45 << 0 << FilteredItem::ErrorItem;
0341 
0342     QTest::newRow("g_assert(0) without domain")
0343         << "ERROR:/foo/test.cpp:46:int main(): assertion failed: (0)"
0344         << "/foo/test.cpp"
0345         << 45 << 0 << FilteredItem::ErrorItem;
0346 
0347     QTest::newRow("g_assert_cmpint(1, ==, 2) with domain")
0348         << "GIO:ERROR:/foo/test.cpp:2024: assertion failed (1 == 2): (1 == 2)"
0349         << "/foo/test.cpp"
0350         << 2023 << 0 << FilteredItem::ErrorItem;
0351 
0352     QTest::newRow("g_assert_cmpint(1, ==, 2) without domain")
0353         << "ERROR:/foo/test.cpp:2024:int main(): assertion failed (1 == 2): (1 == 2)"
0354         << "/foo/test.cpp"
0355         << 2023 << 0 << FilteredItem::ErrorItem;
0356 
0357     QTest::newRow("g_assert_not_reached() with domain")
0358         << "GIO:ERROR:/foo/test.cpp:2024:int main(): code should not be reached"
0359         << "/foo/test.cpp"
0360         << 2023 << 0 << FilteredItem::ErrorItem;
0361 
0362     QTest::newRow("g_assert_not_reached() without domain")
0363         << "ERROR:/foo/test.cpp:2024: code should not be reached"
0364         << "/foo/test.cpp"
0365         << 2023 << 0 << FilteredItem::ErrorItem;
0366 
0367     // with prefix, but without function name
0368     QTest::newRow("g_assert_null() C")
0369         << "GIO:ERROR:/foo/test.c:18: 'bar' should be NULL"
0370         << "/foo/test.c"
0371         << 17 << 0 << FilteredItem::ErrorItem;
0372 
0373     QTest::newRow("g_assert_null() C++")
0374         << "ERROR:/foo/test.c:18:int main(): 'bar' should be NULL"
0375         << "/foo/test.c"
0376         << 17 << 0 << FilteredItem::ErrorItem;
0377 
0378     QTest::newRow("g_assert_nonnull() C")
0379         << "ERROR:/foo/test.cpp:18:int main(): 'bar' should be nullptr"
0380         << "/foo/test.cpp"
0381         << 17 << 0 << FilteredItem::ErrorItem;
0382 
0383     QTest::newRow("g_assert_nonnull() C++")
0384         << "GIO:ERROR:/foo/test.cpp:18:int main(): 'bar' should be nullptr"
0385         << "/foo/test.cpp"
0386         << 17 << 0 << FilteredItem::ErrorItem;
0387 
0388     QTest::newRow("g_assert_true()")
0389         << "GIO:ERROR:/foo/test.cpp:42:int main(): 'bar' should be TRUE"
0390         << "/foo/test.cpp"
0391         << 41 << 0 << FilteredItem::ErrorItem;
0392 
0393     QTest::newRow("g_assert_false()")
0394         << "ERROR:/foo/test.c:42:int main(): 'bar' should be FALSE"
0395         << "/foo/test.c"
0396         << 41 << 0 << FilteredItem::ErrorItem;
0397     // END: glib
0398 }
0399 
0400 void TestFilteringStrategy::testNativeAppErrorFilterStrategy()
0401 {
0402     QFETCH(QString, line);
0403     QFETCH(QString, file);
0404     QFETCH(int, lineNo);
0405     QFETCH(int, column);
0406     QFETCH(FilteredItem::FilteredOutputItemType, itemtype);
0407     NativeAppErrorFilterStrategy testee;
0408     FilteredItem item = testee.errorInLine(line);
0409     QCOMPARE(item.url.path(), file);
0410     QCOMPARE(item.lineNo , lineNo);
0411     QCOMPARE(item.columnNo , column);
0412     QCOMPARE(item.type , itemtype);
0413 }
0414 
0415 void TestFilteringStrategy::testStaticAnalysisFilterStrategy_data()
0416 {
0417     QTest::addColumn<QString>("line");
0418     QTest::addColumn<FilteredItem::FilteredOutputItemType>("expectedError");
0419     QTest::addColumn<FilteredItem::FilteredOutputItemType>("expectedAction");
0420     QTest::addColumn<TestPathType>("pathType");
0421 
0422     QTest::newRow("cppcheck-info-line")
0423     << buildCppCheckInformationLine() << FilteredItem::InvalidItem << FilteredItem::InvalidItem << UnixFilePathNoSpaces;
0424     for (TestPathType pathType : {UnixFilePathNoSpaces, UnixFilePathWithSpaces}) {
0425         QTest::newRowForPathType("cppcheck-error-line", pathType)
0426         << buildCppCheckErrorLine(pathType) << FilteredItem::ErrorItem << FilteredItem::InvalidItem << pathType;
0427         QTest::newRowForPathType("krazy2-error-line", pathType)
0428         << buildKrazyErrorLine(pathType) << FilteredItem::ErrorItem << FilteredItem::InvalidItem << pathType;
0429         QTest::newRowForPathType("krazy2-error-line-two-colons", pathType)
0430         << buildKrazyErrorLine2(pathType) << FilteredItem::ErrorItem << FilteredItem::InvalidItem << pathType;
0431         QTest::newRowForPathType("krazy2-error-line-error-description", pathType)
0432         << buildKrazyErrorLine3(pathType) << FilteredItem::ErrorItem << FilteredItem::InvalidItem << pathType;
0433         QTest::newRowForPathType("krazy2-error-line-wo-line-info", pathType)
0434         << buildKrazyErrorLineNoLineInfo(pathType) << FilteredItem::ErrorItem << FilteredItem::InvalidItem << pathType;
0435         QTest::newRowForPathType("compiler-line", pathType)
0436         << buildCompilerLine(pathType) << FilteredItem::InvalidItem << FilteredItem::InvalidItem << pathType;
0437         QTest::newRowForPathType("compiler-error-line", pathType)
0438         << buildCompilerErrorLine(pathType) << FilteredItem::InvalidItem << FilteredItem::InvalidItem << pathType;
0439     }
0440     QTest::newRow("compiler-action-line")
0441     << "linking testCustombuild (g++)" << FilteredItem::InvalidItem << FilteredItem::InvalidItem << UnixFilePathNoSpaces;
0442     for (TestPathType pathType : {UnixFilePathNoSpaces, UnixFilePathWithSpaces}) {
0443         QTest::newRowForPathType("python-error-line", pathType)
0444         << buildPythonErrorLine(pathType) << FilteredItem::InvalidItem << FilteredItem::InvalidItem << pathType;
0445     }
0446 }
0447 
0448 void TestFilteringStrategy::testStaticAnalysisFilterStrategy()
0449 {
0450     QFETCH(QString, line);
0451     QFETCH(FilteredItem::FilteredOutputItemType, expectedError);
0452     QFETCH(FilteredItem::FilteredOutputItemType, expectedAction);
0453     QFETCH(TestPathType, pathType);
0454 
0455     // Test that url's are extracted correctly as well
0456     QString referencePath = projectPath(pathType) + "main.cpp";
0457 
0458     StaticAnalysisFilterStrategy testee;
0459     FilteredItem item1 = testee.errorInLine(line);
0460     QString extractedPath = item1.url.toLocalFile();
0461     QVERIFY((item1.type != FilteredItem::ErrorItem) || ( extractedPath == referencePath));
0462     QCOMPARE(item1.type, expectedError);
0463     item1 = testee.actionInLine(line);
0464     QCOMPARE(item1.type, expectedAction);
0465 }
0466 
0467 void TestFilteringStrategy::testCompilerFilterstrategyUrlFromAction_data()
0468 {
0469     QTest::addColumn<QString>("line");
0470     QTest::addColumn<QString>("expectedLastDir");
0471     QTest::addColumn<TestPathType>("pathType");
0472 
0473     for (TestPathType pathType :
0474 #ifdef Q_OS_WIN
0475         {WindowsFilePathNoSpaces, WindowsFilePathWithSpaces}
0476 
0477 #else
0478         {UnixFilePathNoSpaces, UnixFilePathWithSpaces}
0479 #endif
0480     ) {
0481         const QString basepath = projectPath(pathType);
0482         QTest::newRowForPathType("cmake-line1", pathType)
0483         << "[ 25%] Building CXX object path/to/one/CMakeFiles/file.o" << QString( basepath + "/path/to/one" ) << pathType;
0484         QTest::newRowForPathType("cmake-line2", pathType)
0485         << "[ 26%] Building CXX object path/to/two/CMakeFiles/file.o" << QString( basepath + "/path/to/two") << pathType;
0486         QTest::newRowForPathType("cmake-line3", pathType)
0487         << "[ 26%] Building CXX object path/to/three/CMakeFiles/file.o" << QString( basepath + "/path/to/three") << pathType;
0488         QTest::newRowForPathType("cmake-line4", pathType)
0489         << "[ 26%] Building CXX object path/to/four/CMakeFiles/file.o" << QString( basepath + "/path/to/four") << pathType;
0490         QTest::newRowForPathType("cmake-line5", pathType)
0491         << "[ 26%] Building CXX object path/to/two/CMakeFiles/file.o" << QString( basepath + "/path/to/two") << pathType;
0492         QTest::newRowForPathType("cd-line6", pathType)
0493         << QString("make[4]: Entering directory '" + basepath + "/path/to/one/'") << QString( basepath + "/path/to/one") << pathType;
0494         QTest::newRowForPathType("waf-cd", pathType)
0495         << QString("Waf: Entering directory `" + basepath + "/path/to/two/'") << QString( basepath + "/path/to/two") << pathType;
0496         QTest::newRowForPathType("cmake-line7", pathType)
0497         << QStringLiteral("[ 50%] Building CXX object CMakeFiles/testdeque.dir/RingBuffer.cpp.o") << QString( basepath) << pathType;
0498         QTest::newRowForPathType("cmake-cd-line8", pathType)
0499         << QString("> /usr/bin/cmake -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=Debug " + basepath) << QString( basepath ) << pathType;
0500     }
0501 }
0502 
0503 void TestFilteringStrategy::testCompilerFilterstrategyUrlFromAction()
0504 {
0505     QFETCH(QString, line);
0506     QFETCH(QString, expectedLastDir);
0507     QFETCH(TestPathType, pathType);
0508 
0509     QUrl projecturl = QUrl::fromLocalFile( projectPath(pathType) );
0510     CompilerFilterStrategy testee(projecturl);
0511     FilteredItem item1 = testee.actionInLine(line);
0512     int last = testee.currentDirs().size() - 1;
0513     QCOMPARE(testee.currentDirs().at(last), expectedLastDir);
0514 }
0515 
0516 void TestFilteringStrategy::benchMarkCompilerFilterAction()
0517 {
0518     QString projecturl = projectPath();
0519     QStringList outputlines;
0520     const int numLines(10000);
0521     int j(0), k(0), l(0), m(0);
0522     do {
0523         ++j; ++k; ++l;
0524         QString tmp;
0525         if(m % 2 == 0) {
0526             tmp = QStringLiteral( "[ 26%] Building CXX object /this/is/the/path/to/the/files/%1/%2/%3/CMakeFiles/file.o").arg( j ).arg( k ).arg( l );
0527         } else {
0528             tmp = QString( "make[4]: Entering directory '" + projecturl + "/this/is/the/path/to/the/files/%1/%2/%3/").arg( j ).arg( k ).arg( l );
0529         }
0530         outputlines << tmp;
0531         if(j % 6 == 0) {
0532             j = 0; ++m;
0533         }
0534         if(k % 9 == 0) {
0535             k = 0; ++m;
0536         }
0537         if(l % 13 == 0) {
0538             l = 0; ++m;
0539         }
0540     }
0541     while(outputlines.size() < numLines ); // gives us numLines (-ish)
0542 
0543     QElapsedTimer totalTime;
0544     totalTime.start();
0545 
0546     static CompilerFilterStrategy testee(QUrl::fromLocalFile(projecturl));
0547     FilteredItem item1(QStringLiteral("dummyline"), FilteredItem::InvalidItem);
0548     QBENCHMARK {
0549         for(int i = 0; i < outputlines.size(); ++i) {
0550             item1 = testee.actionInLine(outputlines.at(i));
0551         }
0552     }
0553 
0554     const qint64 elapsed = totalTime.elapsed();
0555 
0556     qDebug() << "ms elapsed to add directories: " << elapsed;
0557     qDebug() << "total number of directories: " << outputlines.count();
0558     const double avgDirectoryInsertion = double(elapsed) / outputlines.count();
0559     qDebug() << "average ms spend pr. dir: " << avgDirectoryInsertion;
0560 
0561     QVERIFY(avgDirectoryInsertion < 2);
0562 }
0563 
0564 void TestFilteringStrategy::testExtractionOfLineAndColumn_data()
0565 {
0566     QTest::addColumn<QString>("line");
0567     QTest::addColumn<QString>("file");
0568     QTest::addColumn<int>("lineNr");
0569     QTest::addColumn<int>("column");
0570     QTest::addColumn<FilteredItem::FilteredOutputItemType>("itemtype");
0571 
0572 #ifdef Q_OS_WIN
0573     QTest::newRow("msvc-compiler-error-line")
0574         << "Z:\\kderoot\\download\\git\\kcoreaddons\\src\\lib\\jobs\\kjob.cpp(3): error C2065: 'dadsads': undeclared identifier"
0575         << "Z:/kderoot/download/git/kcoreaddons/src/lib/jobs/kjob.cpp" << 2 << 0 << FilteredItem::ErrorItem;
0576     QTest::newRow("msvc-compiler-warning-line")
0577         << "c:\\program files\\microsoft visual studio 10.0\\vc\\include\\crtdefs.h(527): warning C4229: anachronism used : modifiers on data are ignored"
0578         << "c:/program files/microsoft visual studio 10.0/vc/include/crtdefs.h" << 526 << 0 << FilteredItem::WarningItem;
0579 #else
0580     QTest::newRow("gcc-with-col")
0581         << "/path/to/file.cpp:123:45: fatal error: ..."
0582         << "/path/to/file.cpp" << 122 << 44 << FilteredItem::ErrorItem;
0583     QTest::newRow("gcc-no-col")
0584         << "/path/to/file.cpp:123: error ..."
0585         << "/path/to/file.cpp" << 122 << 0 << FilteredItem::ErrorItem;
0586     QTest::newRow("gcc-app-gives-invalid-column")
0587     << "/path/to/file.h:60:0:\
0588 warning: \"SOME_MACRO\" redefined" << "/path/to/file.h" << 59 << 0 << FilteredItem::WarningItem;
0589     QTest::newRow("fortcom")
0590         << "fortcom: Error: Ogive8.f90, line 123: ..."
0591         << QString(projectPath() + "/Ogive8.f90") << 122 << 0 << FilteredItem::ErrorItem;
0592     QTest::newRow("fortcomError")
0593         << "fortcom: Error: ./Ogive8.f90, line 123: ..."
0594         << QString(projectPath() + "/Ogive8.f90") << 122 << 0 << FilteredItem::ErrorItem;
0595     QTest::newRow("fortcomWarning")
0596         << "fortcom: Warning: /path/Ogive8.f90, line 123: ..."
0597         << "/path/Ogive8.f90" << 122 << 0 << FilteredItem::WarningItem;
0598     QTest::newRow("fortcomInfo")
0599         << "fortcom: Info: Ogive8.f90, line 123: ..."
0600         << QString(projectPath() + "/Ogive8.f90") << 122 << 0 << FilteredItem::InformationItem;
0601     QTest::newRow("libtool")
0602         << "libtool: link: warning: ..."
0603         << "" << -1 << 0  << FilteredItem::WarningItem;
0604     QTest::newRow("gfortranError1")
0605         << "/path/to/file.f90:123.456:Error: ...."
0606         << "/path/to/file.f90" << 122 << 455  << FilteredItem::ErrorItem;
0607     QTest::newRow("gfortranError2")
0608         << "/path/flib.f90:3567.22:"
0609         << "/path/flib.f90" << 3566 << 21 << FilteredItem::ErrorItem;
0610     QTest::newRow("ant-javac-Warning")
0611         << "    [javac] /path/class.java:383: warning: [deprecation] ..."
0612         << "/path/class.java" << 382 << 0 << FilteredItem::WarningItem;
0613     QTest::newRow("ant-javac-Error")
0614         << "    [javac] /path/class.java:447: error: cannot find symbol"
0615         << "/path/class.java" << 446 << 0 << FilteredItem::ErrorItem;
0616     QTest::newRow("cmake-error")
0617         << "CMake Error at somesubdir/CMakeLists.txt:214:"
0618         << "/some/path/to/a/somesubdir/CMakeLists.txt" << 213 << 0 << FilteredItem::ErrorItem;
0619 #endif
0620 }
0621 
0622 void TestFilteringStrategy::testExtractionOfLineAndColumn()
0623 {
0624     QFETCH(QString, line);
0625     QFETCH(QString, file);
0626     QFETCH(int, lineNr);
0627     QFETCH(int, column);
0628     QFETCH(FilteredItem::FilteredOutputItemType, itemtype);
0629     QUrl projecturl = QUrl::fromLocalFile( projectPath() );
0630     CompilerFilterStrategy testee(projecturl);
0631     FilteredItem item1 = testee.errorInLine(line);
0632     QCOMPARE(item1.type , itemtype);
0633     QCOMPARE(KDevelop::toUrlOrLocalFile(item1.url), file);
0634     QCOMPARE(item1.lineNo , lineNr);
0635     QCOMPARE(item1.columnNo , column);
0636 }
0637 
0638 #include "moc_test_filteringstrategy.cpp"