// 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; #endif // WITH_TESTS namespace Debugger::Internal { static bool s_testRun = false; bool isTestRun() { return s_testRun; } } // Debugger::Internal #ifdef WITH_TESTS namespace Debugger::Internal { 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 = activeRunConfigForActiveProject(); QVERIFY(rc); auto runControl = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE); runControl->copyDataFromRunConfiguration(rc); DebuggerRunParameters rp = DebuggerRunParameters::fromRunControl(runControl); rp.setInferior(rc->runnable()); rp.setTestCase(TestNoBoundsOfCurrentFunction); auto debugger = createDebuggerWorker(runControl, rp); connect(debugger, &RunWorker::stopped, &QTestEventLoop::instance(), &QTestEventLoop::exitLoop); runControl->start(); 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 // WITH_TESTS