Debugger: Move plugin tests to extra file pair

Change-Id: I1ce7c9e9b2b680ea8f5a80a3b9556916e7d3d180
Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
hjk
2024-01-18 18:30:14 +01:00
parent d234e71643
commit 3f224291e6
5 changed files with 266 additions and 222 deletions

View File

@@ -52,6 +52,7 @@ add_qtc_plugin(Debugger
debuggerrunconfigurationaspect.cpp debuggerrunconfigurationaspect.h
debuggerruncontrol.cpp debuggerruncontrol.h
debuggersourcepathmappingwidget.cpp debuggersourcepathmappingwidget.h
debuggertest.cpp debuggertest.h
debuggertooltipmanager.cpp debuggertooltipmanager.h
debuggertr.h
disassembleragent.cpp disassembleragent.h

View File

@@ -47,6 +47,7 @@ QtcPlugin {
"debuggerrunconfigurationaspect.cpp", "debuggerrunconfigurationaspect.h",
"debuggerruncontrol.cpp", "debuggerruncontrol.h",
"debuggersourcepathmappingwidget.cpp", "debuggersourcepathmappingwidget.h",
"debuggertest.cpp", "debuggertest.h",
"debuggertooltipmanager.cpp", "debuggertooltipmanager.h",
"disassembleragent.cpp", "disassembleragent.h",
"disassemblerlines.cpp", "disassemblerlines.h",

View File

@@ -7,12 +7,12 @@
#include "debuggerdialogs.h"
#include "debuggerengine.h"
#include "debuggericons.h"
#include "debuggeritem.h"
#include "debuggeritemmanager.h"
#include "debuggermainwindow.h"
#include "debuggerrunconfigurationaspect.h"
#include "debuggerruncontrol.h"
#include "debuggerkitaspect.h"
#include "debuggertest.h"
#include "debuggertr.h"
#include "breakhandler.h"
#include "enginemanager.h"
@@ -116,22 +116,6 @@
#include <QVBoxLayout>
#include <QVariant>
#ifdef WITH_TESTS
#include <cppeditor/cpptoolstestcase.h>
#include <cppeditor/projectinfo.h>
#include <QTest>
#include <QSignalSpy>
#include <QTestEventLoop>
//#define WITH_BENCHMARK
#ifdef WITH_BENCHMARK
#include <valgrind/callgrind.h>
#endif
#endif // WITH_TESTS
#include <climits>
#define DEBUG_STATE 1
@@ -2337,210 +2321,6 @@ void showPermanentStatusMessage(const QString &message)
namespace Internal {
static bool s_testRun = false;
bool isTestRun() { return s_testRun; }
#ifdef WITH_TESTS
class DebuggerUnitTests : public QObject
{
Q_OBJECT
public:
DebuggerUnitTests() = default;
private slots:
void initTestCase();
void cleanupTestCase();
void testDebuggerMatching_data();
void testDebuggerMatching();
void testBenchmark();
void testStateMachine();
private:
CppEditor::Tests::TemporaryCopiedDir *m_tmpDir = nullptr;
};
void DebuggerUnitTests::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 = ToolchainKitAspect::toolchain(allKits.first());
// if (!toolchain)
// QSKIP("This test requires that there is a kit with a toolchain.");
// bool hasClangExecutable;
// clangExecutableFromSettings(toolchain->typeId(), &hasClangExecutable);
// if (!hasClangExecutable)
// QSKIP("No clang suitable for analyzing found");
s_testRun = true;
m_tmpDir = new CppEditor::Tests::TemporaryCopiedDir(":/debugger/unit-tests");
QVERIFY(m_tmpDir->isValid());
}
void DebuggerUnitTests::cleanupTestCase()
{
delete m_tmpDir;
}
void DebuggerUnitTests::testStateMachine()
{
FilePath proFile = m_tmpDir->absolutePath("simple/simple.pro");
CppEditor::Tests::ProjectOpenerAndCloser projectManager;
QVERIFY(projectManager.open(proFile, true));
QEventLoop loop;
connect(BuildManager::instance(), &BuildManager::buildQueueFinished,
&loop, &QEventLoop::quit);
BuildManager::buildProjectWithDependencies(ProjectManager::startupProject());
loop.exec();
const QScopeGuard cleanup([] { EditorManager::closeAllEditors(false); });
RunConfiguration *rc = ProjectManager::startupRunConfiguration();
QVERIFY(rc);
auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
runControl->copyDataFromRunConfiguration(rc);
auto debugger = new DebuggerRunTool(runControl);
debugger->setInferior(rc->runnable());
debugger->setTestCase(TestNoBoundsOfCurrentFunction);
connect(debugger, &DebuggerRunTool::stopped,
&QTestEventLoop::instance(), &QTestEventLoop::exitLoop);
debugger->startRunControl();
QTestEventLoop::instance().enterLoop(5);
}
enum FakeEnum { FakeDebuggerCommonSettingsId };
void DebuggerUnitTests::testBenchmark()
{
#ifdef WITH_BENCHMARK
CALLGRIND_START_INSTRUMENTATION;
volatile Id id1 = Id(DEBUGGER_COMMON_SETTINGS_ID);
CALLGRIND_STOP_INSTRUMENTATION;
CALLGRIND_DUMP_STATS;
CALLGRIND_START_INSTRUMENTATION;
volatile FakeEnum id2 = FakeDebuggerCommonSettingsId;
CALLGRIND_STOP_INSTRUMENTATION;
CALLGRIND_DUMP_STATS;
#endif
}
void DebuggerUnitTests::testDebuggerMatching_data()
{
QTest::addColumn<QStringList>("debugger");
QTest::addColumn<QString>("target");
QTest::addColumn<int>("result");
QTest::newRow("Invalid data")
<< QStringList()
<< QString()
<< int(DebuggerItem::DoesNotMatch);
QTest::newRow("Invalid debugger")
<< QStringList()
<< QString::fromLatin1("x86-linux-generic-elf-32bit")
<< int(DebuggerItem::DoesNotMatch);
QTest::newRow("Invalid target")
<< QStringList("x86-linux-generic-elf-32bit")
<< QString()
<< int(DebuggerItem::DoesNotMatch);
QTest::newRow("Fuzzy match 1")
<< QStringList("unknown-unknown-unknown-unknown-0bit")
<< QString::fromLatin1("x86-linux-generic-elf-32bit")
<< int(DebuggerItem::MatchesWell); // Is this the expected behavior?
QTest::newRow("Fuzzy match 2")
<< QStringList("unknown-unknown-unknown-unknown-0bit")
<< QString::fromLatin1("arm-windows-msys-pe-64bit")
<< int(DebuggerItem::MatchesWell); // Is this the expected behavior?
QTest::newRow("Architecture mismatch")
<< QStringList("x86-linux-generic-elf-32bit")
<< QString::fromLatin1("arm-linux-generic-elf-32bit")
<< int(DebuggerItem::DoesNotMatch);
QTest::newRow("OS mismatch")
<< QStringList("x86-linux-generic-elf-32bit")
<< QString::fromLatin1("x86-macosx-generic-elf-32bit")
<< int(DebuggerItem::DoesNotMatch);
QTest::newRow("Format mismatch")
<< QStringList("x86-linux-generic-elf-32bit")
<< QString::fromLatin1("x86-linux-generic-pe-32bit")
<< int(DebuggerItem::DoesNotMatch);
QTest::newRow("Linux perfect match")
<< QStringList("x86-linux-generic-elf-32bit")
<< QString::fromLatin1("x86-linux-generic-elf-32bit")
<< int(DebuggerItem::MatchesWell);
QTest::newRow("Linux match")
<< QStringList("x86-linux-generic-elf-64bit")
<< QString::fromLatin1("x86-linux-generic-elf-32bit")
<< int(DebuggerItem::MatchesSomewhat);
QTest::newRow("Windows perfect match 1")
<< QStringList("x86-windows-msvc2013-pe-64bit")
<< QString::fromLatin1("x86-windows-msvc2013-pe-64bit")
<< int(DebuggerItem::MatchesWell);
QTest::newRow("Windows perfect match 2")
<< QStringList("x86-windows-msvc2013-pe-64bit")
<< QString::fromLatin1("x86-windows-msvc2012-pe-64bit")
<< int(DebuggerItem::MatchesWell);
QTest::newRow("Windows match 1")
<< QStringList("x86-windows-msvc2013-pe-64bit")
<< QString::fromLatin1("x86-windows-msvc2013-pe-32bit")
<< int(DebuggerItem::MatchesSomewhat);
QTest::newRow("Windows match 2")
<< QStringList("x86-windows-msvc2013-pe-64bit")
<< QString::fromLatin1("x86-windows-msvc2012-pe-32bit")
<< int(DebuggerItem::MatchesSomewhat);
QTest::newRow("Windows mismatch on word size")
<< QStringList("x86-windows-msvc2013-pe-32bit")
<< QString::fromLatin1("x86-windows-msvc2013-pe-64bit")
<< int(DebuggerItem::DoesNotMatch);
QTest::newRow("Windows mismatch on osflavor 1")
<< QStringList("x86-windows-msvc2013-pe-32bit")
<< QString::fromLatin1("x86-windows-msys-pe-64bit")
<< int(DebuggerItem::DoesNotMatch);
QTest::newRow("Windows mismatch on osflavor 2")
<< QStringList("x86-windows-msys-pe-32bit")
<< QString::fromLatin1("x86-windows-msvc2010-pe-64bit")
<< int(DebuggerItem::DoesNotMatch);
}
void DebuggerUnitTests::testDebuggerMatching()
{
QFETCH(QStringList, debugger);
QFETCH(QString, target);
QFETCH(int, result);
auto expectedLevel = static_cast<DebuggerItem::MatchLevel>(result);
Abis debuggerAbis;
for (const QString &abi : std::as_const(debugger))
debuggerAbis << Abi::fromString(abi);
DebuggerItem item;
item.setAbis(debuggerAbis);
DebuggerItem::MatchLevel level = item.matchTarget(Abi::fromString(target));
if (level == DebuggerItem::MatchesPerfectly)
level = DebuggerItem::MatchesWell;
QCOMPARE(expectedLevel, level);
}
#endif // ifdef WITH_TESTS
bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMessage)
{
Q_UNUSED(errorMessage)
@@ -2551,7 +2331,7 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess
dd = new DebuggerPluginPrivate(arguments);
#ifdef WITH_TESTS
addTest<DebuggerUnitTests>();
addTestCreator(createDebuggerTest);
#endif
return true;

View File

@@ -0,0 +1,248 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifdef WITH_TESTS
#include "debuggertest.h"
#include "debuggercore.h"
#include "debuggeritem.h"
#include "debuggerruncontrol.h"
#include <coreplugin/editormanager/editormanager.h>
#include <cppeditor/cpptoolstestcase.h>
#include <cppeditor/projectinfo.h>
#include <projectexplorer/buildmanager.h>
#include <projectexplorer/projectmanager.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/runcontrol.h>
#include <utils/filepath.h>
#include <QTest>
#include <QSignalSpy>
#include <QTestEventLoop>
//#define WITH_BENCHMARK
#ifdef WITH_BENCHMARK
#include <valgrind/callgrind.h>
#endif
using namespace Core;
using namespace ProjectExplorer;
using namespace Utils;
namespace Debugger::Internal {
static bool s_testRun = false;
bool isTestRun() { return s_testRun; }
class DebuggerUnitTests : public QObject
{
Q_OBJECT
public:
DebuggerUnitTests() = default;
private slots:
void initTestCase();
void cleanupTestCase();
void testDebuggerMatching_data();
void testDebuggerMatching();
void testBenchmark();
void testStateMachine();
private:
CppEditor::Tests::TemporaryCopiedDir *m_tmpDir = nullptr;
};
void DebuggerUnitTests::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 = ToolchainKitAspect::toolchain(allKits.first());
// if (!toolchain)
// QSKIP("This test requires that there is a kit with a toolchain.");
// bool hasClangExecutable;
// clangExecutableFromSettings(toolchain->typeId(), &hasClangExecutable);
// if (!hasClangExecutable)
// QSKIP("No clang suitable for analyzing found");
s_testRun = true;
m_tmpDir = new CppEditor::Tests::TemporaryCopiedDir(":/debugger/unit-tests");
QVERIFY(m_tmpDir->isValid());
}
void DebuggerUnitTests::cleanupTestCase()
{
delete m_tmpDir;
}
void DebuggerUnitTests::testStateMachine()
{
FilePath proFile = m_tmpDir->absolutePath("simple/simple.pro");
CppEditor::Tests::ProjectOpenerAndCloser projectManager;
QVERIFY(projectManager.open(proFile, true));
QEventLoop loop;
connect(BuildManager::instance(), &BuildManager::buildQueueFinished,
&loop, &QEventLoop::quit);
BuildManager::buildProjectWithDependencies(ProjectManager::startupProject());
loop.exec();
const QScopeGuard cleanup([] { EditorManager::closeAllEditors(false); });
RunConfiguration *rc = ProjectManager::startupRunConfiguration();
QVERIFY(rc);
auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
runControl->copyDataFromRunConfiguration(rc);
auto debugger = new DebuggerRunTool(runControl);
debugger->setInferior(rc->runnable());
debugger->setTestCase(TestNoBoundsOfCurrentFunction);
connect(debugger, &DebuggerRunTool::stopped,
&QTestEventLoop::instance(), &QTestEventLoop::exitLoop);
debugger->startRunControl();
QTestEventLoop::instance().enterLoop(5);
}
enum FakeEnum { FakeDebuggerCommonSettingsId };
void DebuggerUnitTests::testBenchmark()
{
#ifdef WITH_BENCHMARK
CALLGRIND_START_INSTRUMENTATION;
volatile Id id1 = Id(DEBUGGER_COMMON_SETTINGS_ID);
CALLGRIND_STOP_INSTRUMENTATION;
CALLGRIND_DUMP_STATS;
CALLGRIND_START_INSTRUMENTATION;
volatile FakeEnum id2 = FakeDebuggerCommonSettingsId;
CALLGRIND_STOP_INSTRUMENTATION;
CALLGRIND_DUMP_STATS;
#endif
}
void DebuggerUnitTests::testDebuggerMatching_data()
{
QTest::addColumn<QStringList>("debugger");
QTest::addColumn<QString>("target");
QTest::addColumn<int>("result");
QTest::newRow("Invalid data")
<< QStringList()
<< QString()
<< int(DebuggerItem::DoesNotMatch);
QTest::newRow("Invalid debugger")
<< QStringList()
<< QString::fromLatin1("x86-linux-generic-elf-32bit")
<< int(DebuggerItem::DoesNotMatch);
QTest::newRow("Invalid target")
<< QStringList("x86-linux-generic-elf-32bit")
<< QString()
<< int(DebuggerItem::DoesNotMatch);
QTest::newRow("Fuzzy match 1")
<< QStringList("unknown-unknown-unknown-unknown-0bit")
<< QString::fromLatin1("x86-linux-generic-elf-32bit")
<< int(DebuggerItem::MatchesWell); // Is this the expected behavior?
QTest::newRow("Fuzzy match 2")
<< QStringList("unknown-unknown-unknown-unknown-0bit")
<< QString::fromLatin1("arm-windows-msys-pe-64bit")
<< int(DebuggerItem::MatchesWell); // Is this the expected behavior?
QTest::newRow("Architecture mismatch")
<< QStringList("x86-linux-generic-elf-32bit")
<< QString::fromLatin1("arm-linux-generic-elf-32bit")
<< int(DebuggerItem::DoesNotMatch);
QTest::newRow("OS mismatch")
<< QStringList("x86-linux-generic-elf-32bit")
<< QString::fromLatin1("x86-macosx-generic-elf-32bit")
<< int(DebuggerItem::DoesNotMatch);
QTest::newRow("Format mismatch")
<< QStringList("x86-linux-generic-elf-32bit")
<< QString::fromLatin1("x86-linux-generic-pe-32bit")
<< int(DebuggerItem::DoesNotMatch);
QTest::newRow("Linux perfect match")
<< QStringList("x86-linux-generic-elf-32bit")
<< QString::fromLatin1("x86-linux-generic-elf-32bit")
<< int(DebuggerItem::MatchesWell);
QTest::newRow("Linux match")
<< QStringList("x86-linux-generic-elf-64bit")
<< QString::fromLatin1("x86-linux-generic-elf-32bit")
<< int(DebuggerItem::MatchesSomewhat);
QTest::newRow("Windows perfect match 1")
<< QStringList("x86-windows-msvc2013-pe-64bit")
<< QString::fromLatin1("x86-windows-msvc2013-pe-64bit")
<< int(DebuggerItem::MatchesWell);
QTest::newRow("Windows perfect match 2")
<< QStringList("x86-windows-msvc2013-pe-64bit")
<< QString::fromLatin1("x86-windows-msvc2012-pe-64bit")
<< int(DebuggerItem::MatchesWell);
QTest::newRow("Windows match 1")
<< QStringList("x86-windows-msvc2013-pe-64bit")
<< QString::fromLatin1("x86-windows-msvc2013-pe-32bit")
<< int(DebuggerItem::MatchesSomewhat);
QTest::newRow("Windows match 2")
<< QStringList("x86-windows-msvc2013-pe-64bit")
<< QString::fromLatin1("x86-windows-msvc2012-pe-32bit")
<< int(DebuggerItem::MatchesSomewhat);
QTest::newRow("Windows mismatch on word size")
<< QStringList("x86-windows-msvc2013-pe-32bit")
<< QString::fromLatin1("x86-windows-msvc2013-pe-64bit")
<< int(DebuggerItem::DoesNotMatch);
QTest::newRow("Windows mismatch on osflavor 1")
<< QStringList("x86-windows-msvc2013-pe-32bit")
<< QString::fromLatin1("x86-windows-msys-pe-64bit")
<< int(DebuggerItem::DoesNotMatch);
QTest::newRow("Windows mismatch on osflavor 2")
<< QStringList("x86-windows-msys-pe-32bit")
<< QString::fromLatin1("x86-windows-msvc2010-pe-64bit")
<< int(DebuggerItem::DoesNotMatch);
}
void DebuggerUnitTests::testDebuggerMatching()
{
QFETCH(QStringList, debugger);
QFETCH(QString, target);
QFETCH(int, result);
auto expectedLevel = static_cast<DebuggerItem::MatchLevel>(result);
Abis debuggerAbis;
for (const QString &abi : std::as_const(debugger))
debuggerAbis << Abi::fromString(abi);
DebuggerItem item;
item.setAbis(debuggerAbis);
DebuggerItem::MatchLevel level = item.matchTarget(Abi::fromString(target));
if (level == DebuggerItem::MatchesPerfectly)
level = DebuggerItem::MatchesWell;
QCOMPARE(expectedLevel, level);
}
QObject *createDebuggerTest()
{
return new DebuggerUnitTests;
}
} // Debugger::Internal
#include "debuggertest.moc"
#endif

View File

@@ -0,0 +1,14 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
#include <QObject>
namespace Debugger::Internal {
#ifdef WITH_TESTS
QObject *createDebuggerTest();
#endif
} // Debugger::Internal