From 898f35f2982e86f95c7fe061aa5e697c771a0d47 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Wed, 25 Jul 2018 17:21:22 +0200 Subject: Avoid the socket probing and move the shutdown logic into resourceaccess. The problem was (as excercised by the last test in resourcecontroltest), that in this scenario we would: * trigger a synchronization that starts the resource, and then goes into a loop trying to connecting (KAsync::wait -> singleshot timer) * trigger a shutdown that would probe for the socket, not find it, and thus do nothing. * exit the testfunction, which somehow stops qtimer processing, meaning we are stuck in KAsync::wait. For now this is fixed by simply not probing for the socket. --- tests/CMakeLists.txt | 1 + tests/resourcecontroltest.cpp | 83 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 tests/resourcecontroltest.cpp (limited to 'tests') diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2706d5b..3bbbe37 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -55,6 +55,7 @@ auto_tests ( notificationtest entitystoretest upgradetest + resourcecontroltest ) if (WIN32) diff --git a/tests/resourcecontroltest.cpp b/tests/resourcecontroltest.cpp new file mode 100644 index 0000000..e66f444 --- /dev/null +++ b/tests/resourcecontroltest.cpp @@ -0,0 +1,83 @@ +#include + +#include "dummyresource/resourcefactory.h" +#include "resourcecontrol.h" +#include "store.h" +#include "testutils.h" +#include "test.h" +#include "resourceconfig.h" + +/** + * Test starting and stopping of resources. + */ +class ResourceControlTest : public QObject +{ + Q_OBJECT + + KAsync::Job socketIsAvailable(const QByteArray &identifier) + { + return Sink::ResourceAccess::connectToServer(identifier) + .then>( + [&](const KAsync::Error &error, QSharedPointer socket) { + if (error) { + return KAsync::value(false); + } + socket->close(); + return KAsync::value(true); + }); + + } + + bool blockingSocketIsAvailable(const QByteArray &identifier) + { + auto job = socketIsAvailable(identifier); + auto future = job.exec(); + future.waitForFinished(); + return future.value(); + } + +private slots: + + void initTestCase() + { + Sink::Test::initTest(); + auto factory = Sink::ResourceFactory::load("sink.dummy"); + QVERIFY(factory); + ::DummyResource::removeFromDisk("sink.dummy.instance1"); + ResourceConfig::addResource("sink.dummy.instance1", "sink.dummy"); + ::DummyResource::removeFromDisk("sink.dummy.instance2"); + ResourceConfig::addResource("sink.dummy.instance2", "sink.dummy"); + } + + void testResourceStart() + { + VERIFYEXEC(Sink::ResourceControl::start("sink.dummy.instance1")); + QVERIFY(blockingSocketIsAvailable("sink.dummy.instance1")); + } + + void testResourceShutdown() + { + QVERIFY(!blockingSocketIsAvailable("sink.dummy.instance2")); + VERIFYEXEC(Sink::ResourceControl::start("sink.dummy.instance2")); + QVERIFY(blockingSocketIsAvailable("sink.dummy.instance2")); + VERIFYEXEC(Sink::ResourceControl::shutdown("sink.dummy.instance2")); + QVERIFY(!blockingSocketIsAvailable("sink.dummy.instance2")); + } + + //This will produce a race where the synchronize command starts the resource, + //the shutdown command doesn't shutdown because it doesn't realize that the resource is up, + //and the resource ends up getting started, but doing nothing. + void testResourceShutdownAfterStartByCommand() + { + QVERIFY(!blockingSocketIsAvailable("sink.dummy.instance2")); + auto future = Sink::Store::synchronize(Sink::SyncScope{}.resourceFilter("sink.dummy.instance2")).exec(); + + VERIFYEXEC(Sink::ResourceControl::shutdown("sink.dummy.instance2")); + + QVERIFY(!blockingSocketIsAvailable("sink.dummy.instance2")); + } + +}; + +QTEST_MAIN(ResourceControlTest) +#include "resourcecontroltest.moc" -- cgit v1.2.3