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"