diff --git a/projectmanagers/cmake/cmakeutils.cpp b/projectmanagers/cmake/cmakeutils.cpp --- a/projectmanagers/cmake/cmakeutils.cpp +++ b/projectmanagers/cmake/cmakeutils.cpp @@ -643,7 +643,6 @@ const auto contents = CMakeListsParser::readCMakeFile(buildDir.toLocalFile() + "/CTestTestfile.cmake"); QVector tests; - QVector subdirs; for (const auto& entry: contents) { if (entry.name == QLatin1String("add_test")) { auto args = entry.arguments; @@ -655,11 +654,29 @@ tests += test; } else if (entry.name == QLatin1String("subdirs")) { tests += importTestSuites(Path(buildDir, entry.arguments.constFirst().value)); + } else if (entry.name == QLatin1String("set_tests_properties")) { + if(entry.arguments.count() < 4 || entry.arguments.count() % 2) { + qCWarning(CMAKE) << "found set_tests_properties() with unexpected number of arguments:" + << entry.arguments.count(); + continue; + } + if (tests.isEmpty() || entry.arguments.constFirst().value != tests.constLast().name) { + qCWarning(CMAKE) << "found set_tests_properties(" << entry.arguments.constFirst().value + << " ...), but expected test " << tests.constLast().name; + continue; + } + if (entry.arguments[1].value != QLatin1String("PROPERTIES")) { + qCWarning(CMAKE) << "found set_tests_properties(" << entry.arguments.constFirst().value + << entry.arguments.at(1).value << "...), but expected PROPERTIES as second argument"; + continue; + } + Test &test = tests.last(); + for (int i = 2; i < entry.arguments.count(); i += 2) + test.properties[entry.arguments[i].value] = entry.arguments[i + 1].value; } } return tests; } } - diff --git a/projectmanagers/cmake/testing/ctestrunjob.h b/projectmanagers/cmake/testing/ctestrunjob.h --- a/projectmanagers/cmake/testing/ctestrunjob.h +++ b/projectmanagers/cmake/testing/ctestrunjob.h @@ -30,7 +30,7 @@ { Q_OBJECT public: - CTestRunJob(CTestSuite* suite, const QStringList& cases, KDevelop::OutputJob::OutputJobVerbosity verbosity, bool expectFail, QObject* parent = nullptr); + CTestRunJob(CTestSuite* suite, const QStringList& cases, KDevelop::OutputJob::OutputJobVerbosity verbosity, QObject* parent = nullptr); void start() override; protected: @@ -47,7 +47,6 @@ KJob* m_job; KDevelop::OutputJob* m_outputJob; KDevelop::OutputJob::OutputJobVerbosity m_verbosity; - bool m_expectFail; }; #endif // CTESTRUNJOB_H diff --git a/projectmanagers/cmake/testing/ctestrunjob.cpp b/projectmanagers/cmake/testing/ctestrunjob.cpp --- a/projectmanagers/cmake/testing/ctestrunjob.cpp +++ b/projectmanagers/cmake/testing/ctestrunjob.cpp @@ -36,14 +36,13 @@ using namespace KDevelop; -CTestRunJob::CTestRunJob(CTestSuite* suite, const QStringList& cases, OutputJob::OutputJobVerbosity verbosity, bool expectFail, QObject* parent) +CTestRunJob::CTestRunJob(CTestSuite* suite, const QStringList& cases, OutputJob::OutputJobVerbosity verbosity, QObject* parent) : KJob(parent) , m_suite(suite) , m_cases(cases) , m_job(nullptr) , m_outputJob(nullptr) , m_verbosity(verbosity) -, m_expectFail(expectFail) { foreach (const QString& testCase, cases) { @@ -188,13 +187,14 @@ if (prevResult == TestResult::Passed || prevResult == TestResult::NotRun) { TestResult::TestCaseResult result = TestResult::NotRun; + const bool expectFail = m_suite->properties().value(QStringLiteral("WILL_FAIL"), QStringLiteral("FALSE")) == QLatin1String("TRUE"); if (line.startsWith(QLatin1String("PASS :"))) { - result = m_expectFail ? TestResult::UnexpectedPass : TestResult::Passed; + result = expectFail ? TestResult::UnexpectedPass : TestResult::Passed; } else if (line.startsWith(QLatin1String("FAIL! :"))) { - result = m_expectFail ? TestResult::ExpectedFail : TestResult::Failed; + result = expectFail ? TestResult::ExpectedFail : TestResult::Failed; } else if (line.startsWith(QLatin1String("XFAIL :"))) { diff --git a/projectmanagers/cmake/testing/ctestsuite.h b/projectmanagers/cmake/testing/ctestsuite.h --- a/projectmanagers/cmake/testing/ctestsuite.h +++ b/projectmanagers/cmake/testing/ctestsuite.h @@ -32,38 +32,39 @@ class CTestSuite : public KDevelop::ITestSuite { public: - CTestSuite(const QString& name, const KDevelop::Path &executable, const QList& files, KDevelop::IProject* project, const QStringList& args, bool expectFail); + CTestSuite(const QString& name, const KDevelop::Path &executable, const QList& files, KDevelop::IProject* project, const QStringList& args, const QHash& properties); virtual ~CTestSuite(); - + virtual KJob* launchCase(const QString& testCase, TestJobVerbosity verbosity); virtual KJob* launchCases(const QStringList& testCases, TestJobVerbosity verbosity); virtual KJob* launchAllCases(TestJobVerbosity verbosity); - + virtual KDevelop::Path executable() const; virtual QStringList cases() const; virtual QString name() const; virtual KDevelop::IProject* project() const; - + virtual KDevelop::IndexedDeclaration declaration() const; virtual KDevelop::IndexedDeclaration caseDeclaration(const QString& testCase) const; - + + virtual QHash properties() const; + QStringList arguments() const; void setTestCases(const QStringList& cases); QList sourceFiles() const; void loadDeclarations(const KDevelop::IndexedString& document, const KDevelop::ReferencedTopDUContext& context); - + private: KDevelop::Path m_executable; QString m_name; QStringList m_cases; QStringList m_args; QList m_files; KDevelop::IProject* m_project; - + QHash m_declarations; + QHash m_properties; KDevelop::IndexedDeclaration m_suiteDeclaration; - - bool m_expectFail; }; #endif // CTESTSUITE_H diff --git a/projectmanagers/cmake/testing/ctestsuite.cpp b/projectmanagers/cmake/testing/ctestsuite.cpp --- a/projectmanagers/cmake/testing/ctestsuite.cpp +++ b/projectmanagers/cmake/testing/ctestsuite.cpp @@ -38,13 +38,13 @@ using namespace KDevelop; -CTestSuite::CTestSuite(const QString& name, const KDevelop::Path &executable, const QList& files, IProject* project, const QStringList& args, bool expectFail): +CTestSuite::CTestSuite(const QString& name, const KDevelop::Path &executable, const QList& files, IProject* project, const QStringList& args, const QHash& properties): m_executable(executable), m_name(name), m_args(args), m_files(files), m_project(project), -m_expectFail(expectFail) +m_properties(properties) { Q_ASSERT(project); qCDebug(CMAKE) << m_name << m_executable << m_project->name(); @@ -139,7 +139,7 @@ qCDebug(CMAKE) << "Launching test run" << m_name << "with cases" << testCases; OutputJob::OutputJobVerbosity outputVerbosity = (verbosity == Verbose) ? OutputJob::Verbose : OutputJob::Silent; - return new CTestRunJob(this, testCases, outputVerbosity, m_expectFail); + return new CTestRunJob(this, testCases, outputVerbosity); } KJob* CTestSuite::launchAllCases(TestJobVerbosity verbosity) @@ -192,5 +192,7 @@ return m_files; } - - +QHash CTestSuite::properties() const +{ + return m_properties; +} diff --git a/projectmanagers/cmake/testing/ctestutils.cpp b/projectmanagers/cmake/testing/ctestutils.cpp --- a/projectmanagers/cmake/testing/ctestutils.cpp +++ b/projectmanagers/cmake/testing/ctestutils.cpp @@ -63,8 +63,7 @@ executablePath = target.artifacts.constFirst(); } - const bool willFail = test.properties.value(QStringLiteral("WILL_FAIL"), QStringLiteral("FALSE")) == QLatin1String("TRUE"); - CTestSuite* suite = new CTestSuite(test.name, executablePath, {}, project, test.arguments, willFail); + CTestSuite* suite = new CTestSuite(test.name, executablePath, {}, project, test.arguments, test.properties); ICore::self()->runController()->registerJob(new CTestFindJob(suite)); } } diff --git a/projectmanagers/cmake/tests/manual/unit_tests/CMakeLists.txt b/projectmanagers/cmake/tests/manual/unit_tests/CMakeLists.txt --- a/projectmanagers/cmake/tests/manual/unit_tests/CMakeLists.txt +++ b/projectmanagers/cmake/tests/manual/unit_tests/CMakeLists.txt @@ -7,9 +7,18 @@ add_executable(test_fail fail.cpp) set_target_properties(test_fail PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) add_test(fail test_fail) +set_tests_properties(fail PROPERTIES + FOO "foo" + BAR TRUE + MULTILINE "this is +a multi +line property" + QUOTES "\"\\\\\"\\\\\\" + WORKING_DIRECTORY "/bar/baz" + WILL_FAIL TRUE) add_executable(four_test math_test.cpp) -add_test(test_three four_test 3) +add_test(NAME test_three COMMAND four_test 3 WORKING_DIRECTORY "/foo") add_test(test_four four_test 4) add_subdirectory(five) diff --git a/projectmanagers/cmake/tests/manual/unit_tests/five/CMakeLists.txt b/projectmanagers/cmake/tests/manual/unit_tests/five/CMakeLists.txt --- a/projectmanagers/cmake/tests/manual/unit_tests/five/CMakeLists.txt +++ b/projectmanagers/cmake/tests/manual/unit_tests/five/CMakeLists.txt @@ -1 +1,2 @@ add_test(test_five four_test 5) +set_property(TEST test_five PROPERTY WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/bin") diff --git a/projectmanagers/cmake/tests/manual/unit_tests/math_test.cpp b/projectmanagers/cmake/tests/manual/unit_tests/math_test.cpp --- a/projectmanagers/cmake/tests/manual/unit_tests/math_test.cpp +++ b/projectmanagers/cmake/tests/manual/unit_tests/math_test.cpp @@ -1,11 +1,13 @@ +#include + int main(int argc, char** argv) { if (argc < 2) { return 1; } - - if (atoi(argv[1]) == 4) + + if (std::atoi(argv[1]) == 4) { return 0; } diff --git a/projectmanagers/cmake/tests/test_ctestfindsuites.cpp b/projectmanagers/cmake/tests/test_ctestfindsuites.cpp --- a/projectmanagers/cmake/tests/test_ctestfindsuites.cpp +++ b/projectmanagers/cmake/tests/test_ctestfindsuites.cpp @@ -87,10 +87,11 @@ { QCOMPARE(suite->cases(), QStringList()); QVERIFY(!suite->declaration().isValid()); - CTestSuite* ctestSuite = (CTestSuite*)(suite); + CTestSuite* ctestSuite = static_cast(suite); const auto buildDir = Path(CMake::allBuildDirs(project).at(0)); QString exeSubdir = buildDir.relativePath(ctestSuite->executable().parent()); QCOMPARE(exeSubdir, ctestSuite->name() == "fail" ? QStringLiteral("bin") : QString() ); + QVERIFY(ctestSuite->properties().isEmpty()); } }