diff options
author | Christian Kandeler <christian.kandeler@theqtcompany.com> | 2015-02-04 15:19:30 +0100 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@theqtcompany.com> | 2015-02-09 16:48:26 +0200 |
commit | 2946364ce6ad760f732d1042e3206a0fe0a456d6 (patch) | |
tree | dab96a6e578d00d1a749a332cc2bdad7e208687c | |
parent | c632be5c924bbef9619e79af645edadca88e0b94 (diff) |
Add unit tests.
These test the complete workflow as the user experiences it when
clicking "Start".
Intended usage:
(1) Run sdktool to set up a kit with the toolchain you want
to test against (using a temporary directory).
The tests assume exactly one Kit to be present.
(2) Start Creator with a matching settings path and
"-load ClangStaticAnalyzer -test ClangStaticAnalyzer".
(3) Repeat until all toolchains have been tested.
The initial implementation tests one trivial source file
with both qbs and qmake.
Change-Id: I810f23e2990a789a4dd9f1dd16335fbcf5c5f39f
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com>
13 files changed, 227 insertions, 0 deletions
diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzer.pro b/plugins/clangstaticanalyzer/clangstaticanalyzer.pro index 5c7e91c599..df939e9f36 100644 --- a/plugins/clangstaticanalyzer/clangstaticanalyzer.pro +++ b/plugins/clangstaticanalyzer/clangstaticanalyzer.pro @@ -37,5 +37,11 @@ HEADERS += \ FORMS += \ clangstaticanalyzerconfigwidget.ui +equals(TEST, 1) { + HEADERS += clangstaticanalyzerunittests.h + SOURCES += clangstaticanalyzerunittests.cpp + RESOURCES += clangstaticanalyzerunittests.qrc +} + DISTFILES += \ tests/tests.pri diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzer.qbs b/plugins/clangstaticanalyzer/clangstaticanalyzer.qbs index 6c2612a69c..78c7decc5d 100644 --- a/plugins/clangstaticanalyzer/clangstaticanalyzer.qbs +++ b/plugins/clangstaticanalyzer/clangstaticanalyzer.qbs @@ -44,4 +44,15 @@ QtcPlugin { "clangstaticanalyzerutils.h", "clangstaticanalyzer_global.h", ] + + Group { + name: "Unit tests" + condition: project.testsEnabled + files: [ + "clangstaticanalyzerunittests.cpp", + "clangstaticanalyzerunittests.h", + "clangstaticanalyzerunittests.qrc", + "unit-tests/**/*", + ] + } } diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticmodel.h b/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticmodel.h index beccf89a84..d3af814982 100644 --- a/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticmodel.h +++ b/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticmodel.h @@ -34,6 +34,7 @@ public: ClangStaticAnalyzerDiagnosticModel(QObject *parent = 0); void addDiagnostics(const QList<Diagnostic> &diagnostics); + QList<Diagnostic> diagnostics() const { return m_diagnostics; } void clear(); // QAbstractListModel interface diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerplugin.cpp b/plugins/clangstaticanalyzer/clangstaticanalyzerplugin.cpp index e635305b97..943d7ac7e5 100644 --- a/plugins/clangstaticanalyzer/clangstaticanalyzerplugin.cpp +++ b/plugins/clangstaticanalyzer/clangstaticanalyzerplugin.cpp @@ -22,6 +22,10 @@ #include "clangstaticanalyzerruncontrolfactory.h" #include "clangstaticanalyzertool.h" +#ifdef WITH_TESTS +#include "clangstaticanalyzerunittests.h" +#endif + #include <analyzerbase/analyzermanager.h> #include <coreplugin/icore.h> #include <coreplugin/icontext.h> @@ -156,5 +160,14 @@ ExtensionSystem::IPlugin::ShutdownFlag ClangStaticAnalyzerPlugin::aboutToShutdow return SynchronousShutdown; } +QList<QObject *> ClangStaticAnalyzerPlugin::createTestObjects() const +{ + QList<QObject *> tests; +#ifdef WITH_TESTS + tests << new ClangStaticAnalyzerUnitTests(m_analyzerTool); +#endif + return tests; +} + } // namespace Internal } // namespace ClangStaticAnalyzerPlugin diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerplugin.h b/plugins/clangstaticanalyzer/clangstaticanalyzerplugin.h index d96611a16f..c0a6a247fb 100644 --- a/plugins/clangstaticanalyzer/clangstaticanalyzerplugin.h +++ b/plugins/clangstaticanalyzer/clangstaticanalyzerplugin.h @@ -42,6 +42,8 @@ public: ShutdownFlag aboutToShutdown(); private: + QList<QObject *> createTestObjects() const override; + ClangStaticAnalyzerTool *m_analyzerTool; }; diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzertool.cpp b/plugins/clangstaticanalyzer/clangstaticanalyzertool.cpp index ffec5af1a7..93579781a0 100644 --- a/plugins/clangstaticanalyzer/clangstaticanalyzertool.cpp +++ b/plugins/clangstaticanalyzer/clangstaticanalyzertool.cpp @@ -54,6 +54,7 @@ ClangStaticAnalyzerTool::ClangStaticAnalyzerTool(QObject *parent) , m_diagnosticView(0) , m_goBack(0) , m_goNext(0) + , m_running(false) { setObjectName(QLatin1String("ClangStaticAnalyzerTool")); setRunMode(ProjectExplorer::ClangStaticAnalyzerMode); @@ -206,6 +207,7 @@ void ClangStaticAnalyzerTool::startTool(StartMode mode) QTC_ASSERT(project, return); m_projectInfoBeforeBuild = CppTools::CppModelManager::instance()->projectInfo(project); QTC_ASSERT(m_projectInfoBeforeBuild.isValid(), return); + m_running = true; ProjectExplorerPlugin::instance()->runProject(project, runMode()); } @@ -220,6 +222,11 @@ void ClangStaticAnalyzerTool::resetCursorAndProjectInfoBeforeBuild() m_projectInfoBeforeBuild = CppTools::ProjectInfo(); } +QList<Diagnostic> ClangStaticAnalyzerTool::diagnostics() const +{ + return m_diagnosticModel->diagnostics(); +} + void ClangStaticAnalyzerTool::onEngineIsStarting() { QTC_ASSERT(m_diagnosticModel, return); @@ -246,6 +253,8 @@ void ClangStaticAnalyzerTool::onEngineFinished() AnalyzerManager::showStatusMessage(issuesFound > 0 ? AnalyzerManager::tr("Clang Static Analyzer finished, %n issues were found.", 0, issuesFound) : AnalyzerManager::tr("Clang Static Analyzer finished, no issues were found.")); + m_running = false; + emit finished(); } void ClangStaticAnalyzerTool::setBusyCursor(bool busy) diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzertool.h b/plugins/clangstaticanalyzer/clangstaticanalyzertool.h index 8f3bb1f196..4b61ae0fda 100644 --- a/plugins/clangstaticanalyzer/clangstaticanalyzertool.h +++ b/plugins/clangstaticanalyzer/clangstaticanalyzertool.h @@ -40,6 +40,13 @@ public: CppTools::ProjectInfo projectInfoBeforeBuild() const; void resetCursorAndProjectInfoBeforeBuild(); + // For testing. + bool isRunning() const { return m_running; } + QList<Diagnostic> diagnostics() const; + +signals: + void finished(); // For testing. + private: QWidget *createWidgets(); Analyzer::AnalyzerRunControl *createRunControl(const Analyzer::AnalyzerStartParameters &sp, @@ -60,6 +67,7 @@ private: QAction *m_goBack; QAction *m_goNext; + bool m_running; }; } // namespace Internal diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerunittests.cpp b/plugins/clangstaticanalyzer/clangstaticanalyzerunittests.cpp new file mode 100644 index 0000000000..82c5ac1b29 --- /dev/null +++ b/plugins/clangstaticanalyzer/clangstaticanalyzerunittests.cpp @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com <http://qt.digia.com/> +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com <http://qt.digia.com/> +** +****************************************************************************/ + +#include "clangstaticanalyzerunittests.h" + +#include "clangstaticanalyzerdiagnostic.h" +#include "clangstaticanalyzertool.h" +#include "clangstaticanalyzerutils.h" + +#include <analyzerbase/analyzermanager.h> +#include <cpptools/cppmodelmanager.h> +#include <cpptools/cpptoolstestcase.h> +#include <projectexplorer/kitinformation.h> +#include <projectexplorer/kitmanager.h> +#include <projectexplorer/projectexplorer.h> +#include <projectexplorer/toolchain.h> +#include <utils/fileutils.h> + +#include <QEventLoop> +#include <QSignalSpy> +#include <QTemporaryDir> +#include <QTimer> +#include <QtTest> + +using namespace Analyzer; +using namespace ProjectExplorer; +using namespace Utils; + +namespace ClangStaticAnalyzer { +namespace Internal { + +ClangStaticAnalyzerUnitTests::ClangStaticAnalyzerUnitTests(ClangStaticAnalyzerTool *analyzerTool, + QObject *parent) + : QObject(parent) + , m_analyzerTool(analyzerTool) + , m_tmpDir(0) +{ +} + +void ClangStaticAnalyzerUnitTests::initTestCase() +{ + const QList<Kit *> allKits = KitManager::kits(); + if (allKits.count() != 1) + QSKIP("This test requires exactly one kit to be present"); + const ToolChain * const toolchain = ToolChainKitInformation::toolChain(allKits.first()); + if (!toolchain) + QSKIP("This test requires that there is a kit with a toolchain."); + bool hasClangExecutable; + clangExecutableFromSettings(toolchain->type(), &hasClangExecutable); + if (!hasClangExecutable) + QSKIP("No clang suitable for analyzing found"); + + m_tmpDir = new CppTools::Tests::TemporaryCopiedDir(QLatin1String(":/unit-tests")); +} + +void ClangStaticAnalyzerUnitTests::cleanupTestCase() +{ + delete m_tmpDir; +} + +void ClangStaticAnalyzerUnitTests::testProject() +{ + QFETCH(QString, projectFilePath); + QFETCH(int, expectedDiagCount); + + CppTools::Tests::ProjectOpenerAndCloser projectManager; + const CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePath, true); + QVERIFY(projectInfo.isValid()); + AnalyzerManager::selectTool(m_analyzerTool, Analyzer::StartLocal); + AnalyzerManager::startTool(); + if (m_analyzerTool->isRunning()) { + QSignalSpy waiter(m_analyzerTool, SIGNAL(finished())); + QVERIFY(waiter.wait(30000)); + } + QCOMPARE(m_analyzerTool->diagnostics().count(), expectedDiagCount); +} + +void ClangStaticAnalyzerUnitTests::testProject_data() +{ + QTest::addColumn<QString>("projectFilePath"); + QTest::addColumn<int>("expectedDiagCount"); + QTest::newRow("qbs project") + << QString(m_tmpDir->path() + QLatin1String("/simple/simple.qbs")) << 1; + QTest::newRow("qbs project") + << QString(m_tmpDir->path() + QLatin1String("/simple/simple.pro")) << 1; +} + +} // namespace Internal +} // namespace ClangStaticAnalyzerPlugin diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerunittests.h b/plugins/clangstaticanalyzer/clangstaticanalyzerunittests.h new file mode 100644 index 0000000000..bbf9cc88f6 --- /dev/null +++ b/plugins/clangstaticanalyzer/clangstaticanalyzerunittests.h @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com <http://qt.digia.com/> +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com <http://qt.digia.com/> +** +****************************************************************************/ + +#ifndef CLANGSTATICANALYZERUNITTESTS_H +#define CLANGSTATICANALYZERUNITTESTS_H + +#include <QObject> +#include <QTemporaryDir> + +namespace CppTools { namespace Tests { class TemporaryCopiedDir; } } + +namespace ClangStaticAnalyzer { +namespace Internal { +class ClangStaticAnalyzerTool; + +class ClangStaticAnalyzerUnitTests : public QObject +{ + Q_OBJECT + +public: + ClangStaticAnalyzerUnitTests(ClangStaticAnalyzerTool *analyzerTool, QObject *parent = 0); + +private slots: + void initTestCase(); + void cleanupTestCase(); + void testProject(); + void testProject_data(); + +private: + ClangStaticAnalyzerTool * const m_analyzerTool; + CppTools::Tests::TemporaryCopiedDir *m_tmpDir; +}; + +} // namespace Internal +} // namespace ClangStaticAnalyzerPlugin + +#endif // Include guard + diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerunittests.qrc b/plugins/clangstaticanalyzer/clangstaticanalyzerunittests.qrc new file mode 100644 index 0000000000..0de4936d20 --- /dev/null +++ b/plugins/clangstaticanalyzer/clangstaticanalyzerunittests.qrc @@ -0,0 +1,7 @@ +<RCC> + <qresource prefix="/"> + <file>unit-tests/simple/main.cpp</file> + <file>unit-tests/simple/simple.qbs</file> + <file>unit-tests/simple/simple.pro</file> + </qresource> +</RCC> diff --git a/plugins/clangstaticanalyzer/unit-tests/simple/main.cpp b/plugins/clangstaticanalyzer/unit-tests/simple/main.cpp new file mode 100644 index 0000000000..af917a3a33 --- /dev/null +++ b/plugins/clangstaticanalyzer/unit-tests/simple/main.cpp @@ -0,0 +1,5 @@ +int main() +{ + int *i = 0; + *i = 42; +} diff --git a/plugins/clangstaticanalyzer/unit-tests/simple/simple.pro b/plugins/clangstaticanalyzer/unit-tests/simple/simple.pro new file mode 100644 index 0000000000..fb560c2af6 --- /dev/null +++ b/plugins/clangstaticanalyzer/unit-tests/simple/simple.pro @@ -0,0 +1,3 @@ +CONFIG -= QT + +SOURCES = main.cpp diff --git a/plugins/clangstaticanalyzer/unit-tests/simple/simple.qbs b/plugins/clangstaticanalyzer/unit-tests/simple/simple.qbs new file mode 100644 index 0000000000..f6ae698a0c --- /dev/null +++ b/plugins/clangstaticanalyzer/unit-tests/simple/simple.qbs @@ -0,0 +1,5 @@ +import qbs + +CppApplication { + files: ["main.cpp"] +} |