diff --git a/src/plugins/debugger/CMakeLists.txt b/src/plugins/debugger/CMakeLists.txt index 45a6e09f73f..8f338dd9819 100644 --- a/src/plugins/debugger/CMakeLists.txt +++ b/src/plugins/debugger/CMakeLists.txt @@ -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 diff --git a/src/plugins/debugger/debugger.qbs b/src/plugins/debugger/debugger.qbs index 3cdd7517e93..3c5825eb627 100644 --- a/src/plugins/debugger/debugger.qbs +++ b/src/plugins/debugger/debugger.qbs @@ -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", diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 66128f25575..e49e429f775 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -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 #include -#ifdef WITH_TESTS - -#include -#include - -#include -#include -#include - -//#define WITH_BENCHMARK -#ifdef WITH_BENCHMARK -#include -#endif - -#endif // WITH_TESTS - #include #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 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("debugger"); - QTest::addColumn("target"); - QTest::addColumn("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(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(); + addTestCreator(createDebuggerTest); #endif return true; diff --git a/src/plugins/debugger/debuggertest.cpp b/src/plugins/debugger/debuggertest.cpp new file mode 100644 index 00000000000..802185d60ea --- /dev/null +++ b/src/plugins/debugger/debuggertest.cpp @@ -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 + +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +//#define WITH_BENCHMARK +#ifdef WITH_BENCHMARK +#include +#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 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("debugger"); + QTest::addColumn("target"); + QTest::addColumn("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(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 diff --git a/src/plugins/debugger/debuggertest.h b/src/plugins/debugger/debuggertest.h new file mode 100644 index 00000000000..994398d2554 --- /dev/null +++ b/src/plugins/debugger/debuggertest.h @@ -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 + +namespace Debugger::Internal { + +#ifdef WITH_TESTS +QObject *createDebuggerTest(); +#endif + +} // Debugger::Internal