From a3549e5b325e49e3d73ffd0a42d4faa3c7bdc73e Mon Sep 17 00:00:00 2001 From: Pete Woods Date: Tue, 12 Nov 2013 23:34:04 +0000 Subject: [PATCH] Add qdbus-simple-test-runner binary Support running libqtdbustest inside a parent instance --- data/session.conf | 33 +++++++++ data/system.conf | 33 +++++++++ debian/control | 16 +++- debian/libqtdbustest1.symbols | 8 +- debian/qtdbustest-runner.install | 1 + src/CMakeLists.txt | 3 +- src/libqtdbustest/DBusService.h | 2 +- src/libqtdbustest/DBusTestRunner.cpp | 71 +++++++++++------- src/libqtdbustest/QProcessDBusService.cpp | 35 ++++++--- src/libqtdbustest/QProcessDBusService.h | 8 ++ src/qdbus-test-runner/CMakeLists.txt | 20 +++++ .../qdbus-simple-test-runner.cpp | 74 +++++++++++++++++++ tests/libqtdbustest/TestDBusTestRunner.cpp | 10 +-- .../libqtdbustest/TestQProcessDBusService.cpp | 12 +-- 14 files changed, 271 insertions(+), 55 deletions(-) create mode 100644 debian/qtdbustest-runner.install create mode 100644 src/qdbus-test-runner/CMakeLists.txt create mode 100644 src/qdbus-test-runner/qdbus-simple-test-runner.cpp diff --git a/data/session.conf b/data/session.conf index c5d9648..2a00eb5 100644 --- a/data/session.conf +++ b/data/session.conf @@ -1,9 +1,42 @@ + + + + session + unix:tmpdir=/tmp + + + + + + + + + 60000 + + + 1000000000 + 1000000000 + 1000000000 + 120000 + 240000 + 100000 + 10000 + 100000 + 10000 + 50000 + 50000 + 50000 + 300000 + diff --git a/data/system.conf b/data/system.conf index 23105fd..f76602e 100644 --- a/data/system.conf +++ b/data/system.conf @@ -1,9 +1,42 @@ + + + + system + unix:tmpdir=/tmp + + + + + + + + + 60000 + + + 1000000000 + 1000000000 + 1000000000 + 120000 + 240000 + 100000 + 10000 + 100000 + 10000 + 50000 + 50000 + 50000 + 300000 + diff --git a/debian/control b/debian/control index f47f4f4..2d390bb 100644 --- a/debian/control +++ b/debian/control @@ -25,7 +25,7 @@ Pre-Depends: ${misc:Pre-Depends}, Depends: dbus, ${misc:Depends}, ${shlibs:Depends}, -Description: Library for testing DBus interations using Qt +Description: Library for testing DBus interactions using Qt A simple library for testing Qt based DBus services and clients. . This package contains the shared libraries. @@ -36,7 +36,17 @@ Architecture: any Multi-Arch: same Depends: libqtdbustest1 (= ${binary:Version}), ${misc:Depends}, -Description: Library for testing DBus interations using Qt +Description: Library for testing DBus interactions using Qt A simple library for testing Qt based DBus services and clients. . - This package contains files that are needed to build. \ No newline at end of file + This package contains files that are needed to build. + +Package: qtdbustest-runner +Architecture: any +Depends: libqtdbustest1 (= ${binary:Version}), + ${shlibs:Depends}, + ${misc:Depends}, + gvfs-backends, +Description: Library for testing DBus interactions using Qt + Simple executable for running a test script under a private + DBus environment. diff --git a/debian/libqtdbustest1.symbols b/debian/libqtdbustest1.symbols index 792226b..c826de8 100644 --- a/debian/libqtdbustest1.symbols +++ b/debian/libqtdbustest1.symbols @@ -15,13 +15,18 @@ libqtdbustest.so.1 libqtdbustest1 #MINVER# (c++)"QtDBusTest::SuicidalProcess::qt_metacast(char const*)@Base" 0.1 (c++)"QtDBusTest::SuicidalProcess::setSuicidal()@Base" 0.1 (c++)"QtDBusTest::SuicidalProcess::staticMetaObject@Base" 0.1 - (c++)"QtDBusTest::SuicidalProcess::setWatchdogCommand(QString const&)@Base" 0.1+13.10.20130809-0ubuntu1 + (c++)"QtDBusTest::SuicidalProcess::setWatchdogCommand(QString const&)@Base" 0.1 (c++)"QtDBusTest::SuicidalProcess::SuicidalProcess(QObject*)@Base" 0.1 (c++)"QtDBusTest::SuicidalProcess::SuicidalProcess(QObject*)@Base" 0.1 (c++)"QtDBusTest::SuicidalProcess::~SuicidalProcess()@Base" 0.1 (c++)"QtDBusTest::SuicidalProcess::~SuicidalProcess()@Base" 0.1 (c++)"QtDBusTest::SuicidalProcess::~SuicidalProcess()@Base" 0.1 + (c++)"QtDBusTest::QProcessDBusService::qt_metacall(QMetaObject::Call, int, void**)@Base" 0.1 + (c++)"QtDBusTest::QProcessDBusService::qt_metacast(char const*)@Base" 0.1 + (c++)"QtDBusTest::QProcessDBusService::slotFinished(int)@Base" 0.1 + (c++)"QtDBusTest::QProcessDBusService::staticMetaObject@Base" 0.1 (c++)"QtDBusTest::QProcessDBusService::start(QDBusConnection const&)@Base" 0.1 + (c++)"QtDBusTest::QProcessDBusService::finished(int)@Base" 0.1 (c++)"QtDBusTest::QProcessDBusService::QProcessDBusService(QString const&, QDBusConnection::BusType, QString const&, QStringList const&)@Base" 0.1 (c++)"QtDBusTest::QProcessDBusService::QProcessDBusService(QString const&, QDBusConnection::BusType, QString const&, QStringList const&)@Base" 0.1 (c++)"QtDBusTest::QProcessDBusService::~QProcessDBusService()@Base" 0.1 @@ -34,6 +39,7 @@ libqtdbustest.so.1 libqtdbustest1 #MINVER# (c++)"QtDBusTest::DBusTestRunner::sessionConnection() const@Base" 0.1 (c++)"QtDBusTest::DBusTestRunner::systemBus() const@Base" 0.1 (c++)"QtDBusTest::SuicidalProcess::metaObject() const@Base" 0.1 + (c++)"QtDBusTest::QProcessDBusService::metaObject() const@Base" 0.1 (c++)"QtDBusTest::QProcessDBusService::pid() const@Base" 0.1 (c++)"typeinfo for QtDBusTest::DBusService@Base" 0.1 (c++)"typeinfo for QtDBusTest::DBusTestRunner@Base" 0.1 diff --git a/debian/qtdbustest-runner.install b/debian/qtdbustest-runner.install new file mode 100644 index 0000000..1e881ed --- /dev/null +++ b/debian/qtdbustest-runner.install @@ -0,0 +1 @@ +usr/bin \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index adc9071..9f07623 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,4 +2,5 @@ include(GenerateExportHeader) add_compiler_export_flags() add_subdirectory(watchdog) -add_subdirectory(libqtdbustest) \ No newline at end of file +add_subdirectory(libqtdbustest) +add_subdirectory(qdbus-test-runner) \ No newline at end of file diff --git a/src/libqtdbustest/DBusService.h b/src/libqtdbustest/DBusService.h index c9e00dd..550903b 100644 --- a/src/libqtdbustest/DBusService.h +++ b/src/libqtdbustest/DBusService.h @@ -30,7 +30,7 @@ class DBusServicePrivate; typedef QSharedPointer DBusServicePtr; -class Q_DECL_EXPORT DBusService { +class Q_DECL_EXPORT DBusService: public QObject { public: DBusService(const QString &name, QDBusConnection::BusType busType); diff --git a/src/libqtdbustest/DBusTestRunner.cpp b/src/libqtdbustest/DBusTestRunner.cpp index 4b21dc0..618340e 100644 --- a/src/libqtdbustest/DBusTestRunner.cpp +++ b/src/libqtdbustest/DBusTestRunner.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Canonical, Ltd. + l * Copyright (C) 2013 Canonical, Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published @@ -47,47 +47,64 @@ DBusTestRunner::DBusTestRunner(const QString &dbusSessionConfigFile, const QString &dbusSystemConfigFile) : d(new DBusTestRunnerPrivate()) { - // session bus setup + // If we are already running inside a QDBus test environment + if (qEnvironmentVariableIsSet("QDBUS_TEST_RUNNER_PARENT")) { + // session bus setup + d->m_sessionBus = QString::fromUtf8( + qgetenv("DBUS_SESSION_BUS_ADDRESS")); + d->m_sessionConnection = QDBusConnection::sessionBus(); - d->m_sessionDBus.setProcessChannelMode(QProcess::MergedChannels); - d->m_sessionDBus.start("dbus-daemon", - QStringList() << "--config-file" << dbusSessionConfigFile - << "--print-address"); - Q_ASSERT(d->m_sessionDBus.waitForStarted()); + // system bus setup + d->m_systemBus = QString::fromUtf8(qgetenv("DBUS_SYSTEM_BUS_ADDRESS")); + d->m_systemConnection = QDBusConnection::systemBus(); + } else { + // session bus setup - d->m_sessionDBus.waitForReadyRead(); - d->m_sessionBus = d->m_sessionDBus.readAll().trimmed(); + d->m_sessionDBus.setProcessChannelMode(QProcess::MergedChannels); + d->m_sessionDBus.start("dbus-daemon", + QStringList() << "--config-file" << dbusSessionConfigFile + << "--print-address"); + Q_ASSERT(d->m_sessionDBus.waitForStarted()); - qputenv("DBUS_SESSION_BUS_ADDRESS", d->m_sessionBus.toUtf8()); + d->m_sessionDBus.waitForReadyRead(); + d->m_sessionBus = d->m_sessionDBus.readAll().trimmed(); - d->m_sessionConnection = QDBusConnection::connectToBus(d->m_sessionBus, - d->m_sessionBus); + qputenv("DBUS_SESSION_BUS_ADDRESS", d->m_sessionBus.toUtf8()); + qputenv("DBUS_STARTER_ADDRESS", d->m_sessionBus.toUtf8()); + qputenv("DBUS_STARTER_BUS_TYPE", "session"); - // system bus setup + d->m_sessionConnection = QDBusConnection::connectToBus(d->m_sessionBus, + d->m_sessionBus); - d->m_systemDBus.setProcessChannelMode(QProcess::MergedChannels); - d->m_systemDBus.start("dbus-daemon", - QStringList() << "--config-file" << dbusSystemConfigFile - << "--print-address"); - Q_ASSERT(d->m_systemDBus.waitForStarted()); + // system bus setup - d->m_systemDBus.waitForReadyRead(); - d->m_systemBus = d->m_systemDBus.readAll().trimmed(); + d->m_systemDBus.setProcessChannelMode(QProcess::MergedChannels); + d->m_systemDBus.start("dbus-daemon", + QStringList() << "--config-file" << dbusSystemConfigFile + << "--print-address"); + Q_ASSERT(d->m_systemDBus.waitForStarted()); - qputenv("DBUS_SYSTEM_BUS_ADDRESS", d->m_systemBus.toUtf8()); + d->m_systemDBus.waitForReadyRead(); + d->m_systemBus = d->m_systemDBus.readAll().trimmed(); - d->m_systemConnection = QDBusConnection::connectToBus(d->m_systemBus, - d->m_systemBus); + qputenv("DBUS_SYSTEM_BUS_ADDRESS", d->m_systemBus.toUtf8()); + + d->m_systemConnection = QDBusConnection::connectToBus(d->m_systemBus, + d->m_systemBus); + } } DBusTestRunner::~DBusTestRunner() { d->m_services.clear(); - d->m_sessionDBus.terminate(); - Q_ASSERT(d->m_sessionDBus.waitForFinished()); + // If we aren't running inside a QDBus test environment + if (qEnvironmentVariableIsEmpty("QDBUS_TEST_RUNNER_PARENT")) { + d->m_sessionDBus.terminate(); + Q_ASSERT(d->m_sessionDBus.waitForFinished()); - d->m_systemDBus.terminate(); - Q_ASSERT(d->m_systemDBus.waitForFinished()); + d->m_systemDBus.terminate(); + Q_ASSERT(d->m_systemDBus.waitForFinished()); + } } void DBusTestRunner::registerService(DBusServicePtr service) { diff --git a/src/libqtdbustest/QProcessDBusService.cpp b/src/libqtdbustest/QProcessDBusService.cpp index 170c0b1..6a17477 100644 --- a/src/libqtdbustest/QProcessDBusService.cpp +++ b/src/libqtdbustest/QProcessDBusService.cpp @@ -46,15 +46,13 @@ QProcessDBusService::QProcessDBusService(const QString &name, const QStringList &arguments) : DBusService(name, busType), p( new QProcessDBusServicePrivate(program, arguments)) { + connect(&p->m_process, SIGNAL(finished(int)), this, + SLOT(slotFinished(int))); } QProcessDBusService::~QProcessDBusService() { p->m_process.terminate(); p->m_process.waitForFinished(); - - if(qEnvironmentVariableIsSet("QDBUS_TEST_RUNNER_PROCESS_OUTPUT")) { - qDebug() << p->m_process.readAll(); - } } void QProcessDBusService::start(const QDBusConnection &connection) { @@ -63,16 +61,25 @@ void QProcessDBusService::start(const QDBusConnection &connection) { QSignalSpy spy(&watcher, SIGNAL(serviceOwnerChanged(const QString &,const QString &,const QString &))); - p->m_process.setProcessChannelMode(QProcess::MergedChannels); + QProcessEnvironment environment(QProcessEnvironment::systemEnvironment()); + environment.insert("QDBUS_TEST_RUNNER_PARENT", "1"); + p->m_process.setProcessEnvironment(environment); + p->m_process.setProcessChannelMode(QProcess::ForwardedChannels); p->m_process.start(p->m_program, p->m_arguments); - spy.wait(1000); - if (spy.empty()) { - p->m_process.waitForReadyRead(50); - - QString error = "Process [" + p->m_program + "] for service [" + name() - + "] failed to start:\n" + p->m_process.readAll(); - throw std::logic_error(error.toStdString()); + if (name().isEmpty()) { + if (!p->m_process.waitForStarted()) { + QString error = "Process [" + p->m_program + "] for service [" + + name() + "] failed to start"; + throw std::logic_error(error.toStdString()); + } + } else { + spy.wait(); + if (spy.empty()) { + QString error = "Process [" + p->m_program + "] for service [" + + name() + "] failed to appear on bus"; + throw std::logic_error(error.toStdString()); + } } } @@ -80,4 +87,8 @@ Q_PID QProcessDBusService::pid() const { return p->m_process.pid(); } +void QProcessDBusService::slotFinished(int exitCode) { + finished(exitCode); +} + } diff --git a/src/libqtdbustest/QProcessDBusService.h b/src/libqtdbustest/QProcessDBusService.h index 36684f7..1d3a1a1 100644 --- a/src/libqtdbustest/QProcessDBusService.h +++ b/src/libqtdbustest/QProcessDBusService.h @@ -30,6 +30,8 @@ namespace QtDBusTest { class QProcessDBusServicePrivate; class Q_DECL_EXPORT QProcessDBusService: public DBusService { +Q_OBJECT + public: explicit QProcessDBusService(const QString &name, QDBusConnection::BusType busType, const QString &program, @@ -41,6 +43,12 @@ class Q_DECL_EXPORT QProcessDBusService: public DBusService { virtual Q_PID pid() const; +Q_SIGNALS: + void finished(int exitCode); + +protected Q_SLOTS: + virtual void slotFinished(int exitCode); + private: QScopedPointer p; }; diff --git a/src/qdbus-test-runner/CMakeLists.txt b/src/qdbus-test-runner/CMakeLists.txt new file mode 100644 index 0000000..19025ac --- /dev/null +++ b/src/qdbus-test-runner/CMakeLists.txt @@ -0,0 +1,20 @@ + +add_executable( + qdbus-simple-test-runner + qdbus-simple-test-runner.cpp +) + +target_link_libraries( + qdbus-simple-test-runner + qtdbustest +) + +qt5_use_modules( + qdbus-simple-test-runner + Core +) + +install( + TARGETS qdbus-simple-test-runner + RUNTIME DESTINATION "bin" +) diff --git a/src/qdbus-test-runner/qdbus-simple-test-runner.cpp b/src/qdbus-test-runner/qdbus-simple-test-runner.cpp new file mode 100644 index 0000000..2772604 --- /dev/null +++ b/src/qdbus-test-runner/qdbus-simple-test-runner.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2013 Canonical, Ltd. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of version 3 of the GNU Lesser General Public License as published + * by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Author: Pete Woods + */ + +#include +#include +#include +#include + +using namespace QtDBusTest; + +static void exitQt(int sig) { + Q_UNUSED(sig); + QCoreApplication::exit(0); +} + +class ExitListener: public QObject { +Q_OBJECT + +public Q_SLOTS: + void finished(int exitCode) { + QCoreApplication::exit(exitCode); + } +}; + +int main(int argc, char **argv) { + QCoreApplication application(argc, argv); + + signal(SIGINT, &exitQt); + signal(SIGTERM, &exitQt); + + DBusTestRunner runner; + + if (argc < 2) { + qWarning() << "Usage:" << argv[0] << "COMMAND "; + return 1; + } + + QString command(QString::fromUtf8(argv[1])); + + QStringList arguments; + for (int i(2); i < argc; ++i) { + arguments << QString::fromUtf8(argv[i]); + } + + QSharedPointer service( + new QProcessDBusService("", QDBusConnection::SessionBus, command, + arguments)); + + runner.registerService(service); + runner.startServices(); + + ExitListener listener; + QObject::connect(service.data(), SIGNAL(finished(int)), &listener, + SLOT(finished(int))); + + return application.exec(); +} + +#include "qdbus-simple-test-runner.moc" diff --git a/tests/libqtdbustest/TestDBusTestRunner.cpp b/tests/libqtdbustest/TestDBusTestRunner.cpp index 36377a1..beaabbb 100644 --- a/tests/libqtdbustest/TestDBusTestRunner.cpp +++ b/tests/libqtdbustest/TestDBusTestRunner.cpp @@ -32,7 +32,7 @@ class TestDBusTestRunner: public Test { protected: TestDBusTestRunner() : dbusTestRunner(TEST_DBUS_SESSION_CONFIG_FILE, - TEST_DBUS_SYSTEM_CONFIG_FILE) { + TEST_DBUS_SYSTEM_CONFIG_FILE) { } virtual ~TestDBusTestRunner() { @@ -44,7 +44,7 @@ class TestDBusTestRunner: public Test { TEST_F(TestDBusTestRunner, StartsSessionService) { QSharedPointer process( new QProcessDBusService("test.session.name", - QDBusConnection::SessionBus, "python3", + QDBusConnection::SessionBus, "/usr/bin/python3", QStringList() << "-m" << "dbusmock" << "test.session.name" << "/test/object" << "test.Interface")); @@ -59,14 +59,14 @@ TEST_F(TestDBusTestRunner, StartsSessionService) { pgrep.waitForReadyRead(); EXPECT_EQ( - "python3 -m dbusmock test.session.name /test/object test.Interface", + "/usr/bin/python3 -m dbusmock test.session.name /test/object test.Interface", QString::fromUtf8(pgrep.readAll().trimmed()).toStdString()); } TEST_F(TestDBusTestRunner, StartsSystemService) { QSharedPointer process( new QProcessDBusService("test.system.name", - QDBusConnection::SystemBus, "python3", + QDBusConnection::SystemBus, "/usr/bin/python3", QStringList() << "-m" << "dbusmock" << "-s" << "test.system.name" << "/test/object" << "test.Interface")); @@ -82,7 +82,7 @@ TEST_F(TestDBusTestRunner, StartsSystemService) { pgrep.waitForReadyRead(); EXPECT_EQ( - "python3 -m dbusmock -s test.system.name /test/object test.Interface", + "/usr/bin/python3 -m dbusmock -s test.system.name /test/object test.Interface", QString::fromUtf8(pgrep.readAll().trimmed()).toStdString()); } diff --git a/tests/libqtdbustest/TestQProcessDBusService.cpp b/tests/libqtdbustest/TestQProcessDBusService.cpp index e77b60d..e41462a 100644 --- a/tests/libqtdbustest/TestQProcessDBusService.cpp +++ b/tests/libqtdbustest/TestQProcessDBusService.cpp @@ -34,7 +34,7 @@ class TestQProcessDBusService: public Test { protected: TestQProcessDBusService() : dbusTestRunner(TEST_DBUS_SESSION_CONFIG_FILE, - TEST_DBUS_SYSTEM_CONFIG_FILE) { + TEST_DBUS_SYSTEM_CONFIG_FILE) { } virtual ~TestQProcessDBusService() { @@ -45,7 +45,7 @@ class TestQProcessDBusService: public Test { TEST_F(TestQProcessDBusService, WaitsForServiceAppeared) { QProcessDBusService process("test.name", QDBusConnection::SessionBus, - "python3", + "/usr/bin/python3", QStringList() << "-m" << "dbusmock" << "test.name" << "/test/object" << "test.Interface"); @@ -58,17 +58,19 @@ TEST_F(TestQProcessDBusService, WaitsForServiceAppeared) { pgrep.waitForFinished(); pgrep.waitForReadyRead(); - EXPECT_EQ("python3 -m dbusmock test.name /test/object test.Interface", + EXPECT_EQ( + "/usr/bin/python3 -m dbusmock test.name /test/object test.Interface", QString::fromUtf8(pgrep.readAll().trimmed()).toStdString()); } TEST_F(TestQProcessDBusService, ThrowsErrorForFailToStart) { QProcessDBusService process("test.name", QDBusConnection::SessionBus, - "python3", + "/usr/bin/python3", QStringList() << "-m" << "dbusmock" << "not.test.name" << "/test/object" << "test.Interface"); - ASSERT_THROW(process.start(dbusTestRunner.sessionConnection()), std::logic_error); + ASSERT_THROW(process.start(dbusTestRunner.sessionConnection()), + std::logic_error); } } // namespace