File indexing completed on 2024-05-12 04:39:45

0001 /*
0002     SPDX-FileCopyrightText: 2020 Christoph Roick <chrisito@gmx.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "testfilepaths.h"
0008 
0009 #include "../midebuggerplugin.h"
0010 
0011 #include <interfaces/iplugincontroller.h>
0012 #include <tests/autotestshell.h>
0013 #include <tests/testcore.h>
0014 
0015 #include <KPluginFactory>
0016 
0017 #include <QDBusAbstractAdaptor>
0018 #include <QDBusConnection>
0019 #include <QObject>
0020 #include <QTest>
0021 
0022 class DrKonqiAdaptor;
0023 
0024 class TestMIDBus : public QObject
0025 {
0026     Q_OBJECT
0027 
0028 private Q_SLOTS:
0029     void initTestCase();
0030 
0031     void debug();
0032 
0033     void cleanupTestCase();
0034 
0035 public Q_SLOTS:
0036     void message(KDevelop::IStatus*, const QString &message)
0037     {
0038         m_lastMessage = message;
0039     }
0040 
0041 private:
0042     QString m_lastMessage;
0043 };
0044 
0045 /**
0046  * Copy of DBus-Adaptor interface of DrKonqi that is going to connect with our TestDebugger
0047  */
0048 class DrKonqiAdaptor : public QDBusAbstractAdaptor
0049 {
0050     Q_OBJECT
0051     Q_CLASSINFO("D-Bus Interface", "org.kde.drkonqi")
0052 
0053 public:
0054     DrKonqiAdaptor(QObject* parent) : QDBusAbstractAdaptor(parent)
0055     {
0056         QVERIFY(QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.drkonqi.PID0")));
0057         QVERIFY(QDBusConnection::sessionBus().registerObject(QStringLiteral("/debugger"), parent));
0058     }
0059 
0060     QString registeredName;
0061     qint64 registeredPid = 0;
0062     bool closed = false;
0063     bool finished = false;
0064 
0065 public Q_SLOTS:
0066     int pid()
0067     {
0068         return 123;
0069     }
0070     Q_NOREPLY void registerDebuggingApplication(const QString &name, qint64 pid = 0)
0071     {
0072         if (pid != QCoreApplication::applicationPid()) {
0073             qDebug() << "ignoring other app:" << name << pid;
0074             return;
0075         }
0076         registeredName = name;
0077         registeredPid = pid;
0078     }
0079     Q_NOREPLY void debuggingFinished(const QString&)
0080     {
0081         finished = true;
0082     }
0083     Q_NOREPLY void debuggerClosed(const QString&)
0084     {
0085         closed = true;
0086         finished = false;
0087         registeredPid = 0;
0088     }
0089 
0090 Q_SIGNALS:
0091     void acceptDebuggingApplication(const QString &name);
0092 };
0093 
0094 void TestMIDBus::initTestCase()
0095 {
0096     QCoreApplication::addLibraryPath(QStringLiteral(TEST_PLUGIN_DIR));
0097 
0098     KDevelop::AutoTestShell::init({QStringLiteral("testdebugger")});
0099     KDevelop::TestCore::initialize(KDevelop::Core::NoUi);
0100 }
0101 
0102 void TestMIDBus::debug()
0103 {
0104 #ifdef Q_OS_WIN
0105     QSKIP("somehow, running this test makes Windows CI jobs fail via KeyboardInterrupt (^C)");
0106 #endif
0107 
0108     auto plugin = dynamic_cast<KDevMI::MIDebuggerPlugin*>(KDevelop::ICore::self()->pluginController()->loadPlugin(QStringLiteral("testdebugger")));
0109     QVERIFY(plugin);
0110     connect(plugin, &KDevMI::MIDebuggerPlugin::showMessage, this, &TestMIDBus::message);
0111 
0112     // Start the adaptor (DrKonqi) after KDevelop was started
0113     auto adaptor = new DrKonqiAdaptor(this);
0114 
0115     QTRY_COMPARE(adaptor->registeredPid, QApplication::applicationPid());
0116 
0117     emit adaptor->acceptDebuggingApplication(QStringLiteral("KDevelop (Test) - test-test_midbus"));
0118 
0119     QTRY_VERIFY(!m_lastMessage.isEmpty());
0120     QCOMPARE(m_lastMessage, QStringLiteral("Attaching to process 123"));
0121 
0122     QVERIFY(!adaptor->finished);
0123     QTRY_VERIFY(adaptor->finished);
0124 
0125     QVERIFY(!adaptor->closed);
0126     plugin->unload();
0127     QTRY_VERIFY(adaptor->closed);
0128 
0129     // Shut down KDevelop, but let the adaptor continue.
0130     KDevelop::TestCore::shutdown();
0131     m_lastMessage.clear();
0132 
0133     // Now restart KDevelop with the adaptor (DrKonqi) already running
0134     KDevelop::AutoTestShell::init({QStringLiteral("testdebugger")});
0135     KDevelop::TestCore::initialize(KDevelop::Core::NoUi);
0136 
0137     plugin = dynamic_cast<KDevMI::MIDebuggerPlugin*>(KDevelop::ICore::self()->pluginController()->loadPlugin(QStringLiteral("testdebugger")));
0138     QVERIFY(plugin);
0139     connect(plugin, &KDevMI::MIDebuggerPlugin::showMessage, this, &TestMIDBus::message);
0140 
0141     QTRY_COMPARE(adaptor->registeredPid, QApplication::applicationPid());
0142 
0143     emit adaptor->acceptDebuggingApplication(QStringLiteral("KDevelop (Test) - test-test_midbus"));
0144 
0145     QTRY_VERIFY(!m_lastMessage.isEmpty());
0146     QCOMPARE(m_lastMessage, QStringLiteral("Attaching to process 123"));
0147 
0148     QVERIFY(!adaptor->finished);
0149     QTRY_VERIFY(adaptor->finished);
0150 }
0151 
0152 void TestMIDBus::cleanupTestCase()
0153 {
0154     KDevelop::TestCore::shutdown();
0155     // Wait until the debug session is deleted via event loop. DebugController::debuggerStateChanged(),
0156     // invoked from ~CorePrivate(), calls session->deleteLater(). So an additional processing of
0157     // events is needed after the one in TestCore::shutdown(), in which Core is deleted.
0158     QTest::qWait(1);
0159 }
0160 
0161 
0162 QTEST_GUILESS_MAIN(TestMIDBus)
0163 
0164 #include "test_midbus.moc"