Fix race condition in tst_QDBusConnection::pendingCallWhenDisconnected
The test sent a message and hoped that the "delete server" would cause the server object in the QDBusConnectionManager thread be deleted before it could receive and process the message. That's racy, because on some CI machines, it did and then sent back an error reply indicating the object sought was not found. Instead, let's use a child process that we can kill to make it exit at the right time. I've chosen to use dbus-daemon itself, because that lets us test the actual conditions that triggered the original bug: the daemon getting killed during a desktop session shutdown on Linux. Change-Id: I87e17314d8b24ae983b1fffd1454483aea87c921 Reviewed-by: Tony Sarajärvi <tony.sarajarvi@qt.io>bb10
parent
d5ac97e36f
commit
f8b5142e30
|
|
@ -40,6 +40,11 @@
|
|||
#include <QtTest/QtTest>
|
||||
#include <QtDBus/QtDBus>
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
# include <sys/types.h>
|
||||
# include <signal.h>
|
||||
#endif
|
||||
|
||||
void MyObject::method(const QDBusMessage &msg)
|
||||
{
|
||||
path = msg.path();
|
||||
|
|
@ -1357,23 +1362,39 @@ void tst_QDBusConnection::callVirtualObjectLocal()
|
|||
|
||||
void tst_QDBusConnection::pendingCallWhenDisconnected()
|
||||
{
|
||||
#ifdef QT_NO_PROCESS
|
||||
QSKIP("Test requires QProcess");
|
||||
#else
|
||||
if (!QCoreApplication::instance())
|
||||
QSKIP("Test requires a QCoreApplication");
|
||||
|
||||
QDBusServer *server = new QDBusServer;
|
||||
QDBusConnection con = QDBusConnection::connectToPeer(server->address(), "disconnect");
|
||||
QTestEventLoop::instance().enterLoop(2);
|
||||
QVERIFY(con.isConnected());
|
||||
QDBusMessage message = QDBusMessage::createMethodCall("", "/", QString(), "method");
|
||||
QProcess daemon;
|
||||
daemon.start("dbus-daemon", QStringList() << "--session" << "--nofork" << "--print-address");
|
||||
QVERIFY2(daemon.waitForReadyRead(2000),
|
||||
"Daemon didn't print its address in time; error: \"" + daemon.errorString().toLocal8Bit() +
|
||||
"\"; stderr:\n" + daemon.readAllStandardError());
|
||||
|
||||
QString address = QString::fromLocal8Bit(daemon.readAll().trimmed());
|
||||
QDBusConnection con = QDBusConnection::connectToBus(address, "disconnect");
|
||||
QVERIFY2(con.isConnected(), (con.lastError().name() + ": " + con.lastError().message()).toLocal8Bit());
|
||||
|
||||
// confirm we're connected and we're alone in this bus
|
||||
QCOMPARE(con.baseService(), QString(":1.0"));
|
||||
|
||||
// kill the bus
|
||||
daemon.terminate();
|
||||
daemon.waitForFinished();
|
||||
|
||||
// send something, which we should get an error with
|
||||
QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.DBus", "/", QString(), "ListNames");
|
||||
QDBusPendingCall reply = con.asyncCall(message);
|
||||
|
||||
delete server;
|
||||
|
||||
QTestEventLoop::instance().enterLoop(2);
|
||||
reply.waitForFinished();
|
||||
QVERIFY(!con.isConnected());
|
||||
QVERIFY(reply.isFinished());
|
||||
QVERIFY(reply.isError());
|
||||
QVERIFY(reply.error().type() == QDBusError::Disconnected);
|
||||
QCOMPARE(reply.error().type(), QDBusError::Disconnected);
|
||||
#endif
|
||||
}
|
||||
|
||||
QString MyObject::path;
|
||||
|
|
|
|||
Loading…
Reference in New Issue