forked from qt-creator/qt-creator
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>
This commit is contained in:
@@ -37,5 +37,11 @@ HEADERS += \
|
|||||||
FORMS += \
|
FORMS += \
|
||||||
clangstaticanalyzerconfigwidget.ui
|
clangstaticanalyzerconfigwidget.ui
|
||||||
|
|
||||||
|
equals(TEST, 1) {
|
||||||
|
HEADERS += clangstaticanalyzerunittests.h
|
||||||
|
SOURCES += clangstaticanalyzerunittests.cpp
|
||||||
|
RESOURCES += clangstaticanalyzerunittests.qrc
|
||||||
|
}
|
||||||
|
|
||||||
DISTFILES += \
|
DISTFILES += \
|
||||||
tests/tests.pri
|
tests/tests.pri
|
||||||
|
@@ -44,4 +44,15 @@ QtcPlugin {
|
|||||||
"clangstaticanalyzerutils.h",
|
"clangstaticanalyzerutils.h",
|
||||||
"clangstaticanalyzer_global.h",
|
"clangstaticanalyzer_global.h",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
Group {
|
||||||
|
name: "Unit tests"
|
||||||
|
condition: project.testsEnabled
|
||||||
|
files: [
|
||||||
|
"clangstaticanalyzerunittests.cpp",
|
||||||
|
"clangstaticanalyzerunittests.h",
|
||||||
|
"clangstaticanalyzerunittests.qrc",
|
||||||
|
"unit-tests/**/*",
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -34,6 +34,7 @@ public:
|
|||||||
ClangStaticAnalyzerDiagnosticModel(QObject *parent = 0);
|
ClangStaticAnalyzerDiagnosticModel(QObject *parent = 0);
|
||||||
|
|
||||||
void addDiagnostics(const QList<Diagnostic> &diagnostics);
|
void addDiagnostics(const QList<Diagnostic> &diagnostics);
|
||||||
|
QList<Diagnostic> diagnostics() const { return m_diagnostics; }
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
// QAbstractListModel interface
|
// QAbstractListModel interface
|
||||||
|
@@ -22,6 +22,10 @@
|
|||||||
#include "clangstaticanalyzerruncontrolfactory.h"
|
#include "clangstaticanalyzerruncontrolfactory.h"
|
||||||
#include "clangstaticanalyzertool.h"
|
#include "clangstaticanalyzertool.h"
|
||||||
|
|
||||||
|
#ifdef WITH_TESTS
|
||||||
|
#include "clangstaticanalyzerunittests.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <analyzerbase/analyzermanager.h>
|
#include <analyzerbase/analyzermanager.h>
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <coreplugin/icontext.h>
|
#include <coreplugin/icontext.h>
|
||||||
@@ -156,5 +160,14 @@ ExtensionSystem::IPlugin::ShutdownFlag ClangStaticAnalyzerPlugin::aboutToShutdow
|
|||||||
return SynchronousShutdown;
|
return SynchronousShutdown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<QObject *> ClangStaticAnalyzerPlugin::createTestObjects() const
|
||||||
|
{
|
||||||
|
QList<QObject *> tests;
|
||||||
|
#ifdef WITH_TESTS
|
||||||
|
tests << new ClangStaticAnalyzerUnitTests(m_analyzerTool);
|
||||||
|
#endif
|
||||||
|
return tests;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace ClangStaticAnalyzerPlugin
|
} // namespace ClangStaticAnalyzerPlugin
|
||||||
|
@@ -42,6 +42,8 @@ public:
|
|||||||
ShutdownFlag aboutToShutdown();
|
ShutdownFlag aboutToShutdown();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QList<QObject *> createTestObjects() const override;
|
||||||
|
|
||||||
ClangStaticAnalyzerTool *m_analyzerTool;
|
ClangStaticAnalyzerTool *m_analyzerTool;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -54,6 +54,7 @@ ClangStaticAnalyzerTool::ClangStaticAnalyzerTool(QObject *parent)
|
|||||||
, m_diagnosticView(0)
|
, m_diagnosticView(0)
|
||||||
, m_goBack(0)
|
, m_goBack(0)
|
||||||
, m_goNext(0)
|
, m_goNext(0)
|
||||||
|
, m_running(false)
|
||||||
{
|
{
|
||||||
setObjectName(QLatin1String("ClangStaticAnalyzerTool"));
|
setObjectName(QLatin1String("ClangStaticAnalyzerTool"));
|
||||||
setRunMode(ProjectExplorer::ClangStaticAnalyzerMode);
|
setRunMode(ProjectExplorer::ClangStaticAnalyzerMode);
|
||||||
@@ -206,6 +207,7 @@ void ClangStaticAnalyzerTool::startTool(StartMode mode)
|
|||||||
QTC_ASSERT(project, return);
|
QTC_ASSERT(project, return);
|
||||||
m_projectInfoBeforeBuild = CppTools::CppModelManager::instance()->projectInfo(project);
|
m_projectInfoBeforeBuild = CppTools::CppModelManager::instance()->projectInfo(project);
|
||||||
QTC_ASSERT(m_projectInfoBeforeBuild.isValid(), return);
|
QTC_ASSERT(m_projectInfoBeforeBuild.isValid(), return);
|
||||||
|
m_running = true;
|
||||||
ProjectExplorerPlugin::instance()->runProject(project, runMode());
|
ProjectExplorerPlugin::instance()->runProject(project, runMode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,6 +222,11 @@ void ClangStaticAnalyzerTool::resetCursorAndProjectInfoBeforeBuild()
|
|||||||
m_projectInfoBeforeBuild = CppTools::ProjectInfo();
|
m_projectInfoBeforeBuild = CppTools::ProjectInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<Diagnostic> ClangStaticAnalyzerTool::diagnostics() const
|
||||||
|
{
|
||||||
|
return m_diagnosticModel->diagnostics();
|
||||||
|
}
|
||||||
|
|
||||||
void ClangStaticAnalyzerTool::onEngineIsStarting()
|
void ClangStaticAnalyzerTool::onEngineIsStarting()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(m_diagnosticModel, return);
|
QTC_ASSERT(m_diagnosticModel, return);
|
||||||
@@ -246,6 +253,8 @@ void ClangStaticAnalyzerTool::onEngineFinished()
|
|||||||
AnalyzerManager::showStatusMessage(issuesFound > 0
|
AnalyzerManager::showStatusMessage(issuesFound > 0
|
||||||
? AnalyzerManager::tr("Clang Static Analyzer finished, %n issues were found.", 0, issuesFound)
|
? AnalyzerManager::tr("Clang Static Analyzer finished, %n issues were found.", 0, issuesFound)
|
||||||
: AnalyzerManager::tr("Clang Static Analyzer finished, no issues were found."));
|
: AnalyzerManager::tr("Clang Static Analyzer finished, no issues were found."));
|
||||||
|
m_running = false;
|
||||||
|
emit finished();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangStaticAnalyzerTool::setBusyCursor(bool busy)
|
void ClangStaticAnalyzerTool::setBusyCursor(bool busy)
|
||||||
|
@@ -40,6 +40,13 @@ public:
|
|||||||
CppTools::ProjectInfo projectInfoBeforeBuild() const;
|
CppTools::ProjectInfo projectInfoBeforeBuild() const;
|
||||||
void resetCursorAndProjectInfoBeforeBuild();
|
void resetCursorAndProjectInfoBeforeBuild();
|
||||||
|
|
||||||
|
// For testing.
|
||||||
|
bool isRunning() const { return m_running; }
|
||||||
|
QList<Diagnostic> diagnostics() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void finished(); // For testing.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QWidget *createWidgets();
|
QWidget *createWidgets();
|
||||||
Analyzer::AnalyzerRunControl *createRunControl(const Analyzer::AnalyzerStartParameters &sp,
|
Analyzer::AnalyzerRunControl *createRunControl(const Analyzer::AnalyzerStartParameters &sp,
|
||||||
@@ -60,6 +67,7 @@ private:
|
|||||||
|
|
||||||
QAction *m_goBack;
|
QAction *m_goBack;
|
||||||
QAction *m_goNext;
|
QAction *m_goNext;
|
||||||
|
bool m_running;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
104
plugins/clangstaticanalyzer/clangstaticanalyzerunittests.cpp
Normal file
104
plugins/clangstaticanalyzer/clangstaticanalyzerunittests.cpp
Normal file
@@ -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
|
53
plugins/clangstaticanalyzer/clangstaticanalyzerunittests.h
Normal file
53
plugins/clangstaticanalyzer/clangstaticanalyzerunittests.h
Normal file
@@ -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
|
||||||
|
|
@@ -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>
|
5
plugins/clangstaticanalyzer/unit-tests/simple/main.cpp
Normal file
5
plugins/clangstaticanalyzer/unit-tests/simple/main.cpp
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
int main()
|
||||||
|
{
|
||||||
|
int *i = 0;
|
||||||
|
*i = 42;
|
||||||
|
}
|
3
plugins/clangstaticanalyzer/unit-tests/simple/simple.pro
Normal file
3
plugins/clangstaticanalyzer/unit-tests/simple/simple.pro
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
CONFIG -= QT
|
||||||
|
|
||||||
|
SOURCES = main.cpp
|
5
plugins/clangstaticanalyzer/unit-tests/simple/simple.qbs
Normal file
5
plugins/clangstaticanalyzer/unit-tests/simple/simple.qbs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import qbs
|
||||||
|
|
||||||
|
CppApplication {
|
||||||
|
files: ["main.cpp"]
|
||||||
|
}
|
Reference in New Issue
Block a user