kwin/src/wayland/autotests/client/test_idle.cpp
Vlad Zahorodnii 09e079b78f Remove factory methods in Display
The main reason why we have factory methods is that up to some point,
kwayland had its own signal to indicate when globals have to be removed.

Now that all globals add destroy listeners for the wl_display object,
we don't have that signal. Most factory methods are equivalent to doing
new T(display).

Besides adding unnecessary boilerplate code, another reason to get rid
of the factory methods is to reduce the amount of merge conflicts. If
several persons work on implementing wayland protocols at the same time,
sooner or later someone will have to resolve merge conflicts in Display.
2020-12-14 13:04:59 +00:00

276 lines
8.6 KiB
C++

/*
SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
// Qt
#include <QtTest>
// client
#include "KWayland/Client/connection_thread.h"
#include "KWayland/Client/event_queue.h"
#include "KWayland/Client/idle.h"
#include "KWayland/Client/registry.h"
#include "KWayland/Client/seat.h"
// server
#include "../../src/server/display.h"
#include "../../src/server/idle_interface.h"
#include "../../src/server/seat_interface.h"
using namespace KWayland::Client;
using namespace KWaylandServer;
class IdleTest : public QObject
{
Q_OBJECT
private Q_SLOTS:
void init();
void cleanup();
void testTimeout();
void testSimulateUserActivity();
void testServerSimulateUserActivity();
void testIdleInhibit();
void testIdleInhibitBlocksTimeout();
private:
Display *m_display = nullptr;
SeatInterface *m_seatInterface = nullptr;
IdleInterface *m_idleInterface = nullptr;
ConnectionThread *m_connection = nullptr;
QThread *m_thread = nullptr;
EventQueue *m_queue = nullptr;
Seat *m_seat = nullptr;
Idle *m_idle = nullptr;
};
static const QString s_socketName = QStringLiteral("kwayland-test-idle-0");
void IdleTest::init()
{
delete m_display;
m_display = new Display(this);
m_display->addSocketName(s_socketName);
m_display->start();
QVERIFY(m_display->isRunning());
m_display->createShm();
m_seatInterface = new SeatInterface(m_display);
m_seatInterface->setName(QStringLiteral("seat0"));
m_seatInterface->create();
m_idleInterface = new IdleInterface(m_display);
// setup connection
m_connection = new KWayland::Client::ConnectionThread;
QSignalSpy connectedSpy(m_connection, &ConnectionThread::connected);
QVERIFY(connectedSpy.isValid());
m_connection->setSocketName(s_socketName);
m_thread = new QThread(this);
m_connection->moveToThread(m_thread);
m_thread->start();
m_connection->initConnection();
QVERIFY(connectedSpy.wait());
m_queue = new EventQueue(this);
m_queue->setup(m_connection);
Registry registry;
QSignalSpy interfacesAnnouncedSpy(&registry, &Registry::interfacesAnnounced);
QVERIFY(interfacesAnnouncedSpy.isValid());
registry.setEventQueue(m_queue);
registry.create(m_connection);
QVERIFY(registry.isValid());
registry.setup();
QVERIFY(interfacesAnnouncedSpy.wait());
m_seat = registry.createSeat(registry.interface(Registry::Interface::Seat).name,
registry.interface(Registry::Interface::Seat).version,
this);
QVERIFY(m_seat->isValid());
m_idle = registry.createIdle(registry.interface(Registry::Interface::Idle).name,
registry.interface(Registry::Interface::Idle).version,
this);
QVERIFY(m_idle->isValid());
}
void IdleTest::cleanup()
{
#define CLEANUP(variable) \
if (variable) { \
delete variable; \
variable = nullptr; \
}
CLEANUP(m_idle)
CLEANUP(m_seat)
CLEANUP(m_queue)
if (m_connection) {
m_connection->deleteLater();
m_connection = nullptr;
}
if (m_thread) {
m_thread->quit();
m_thread->wait();
delete m_thread;
m_thread = nullptr;
}
CLEANUP(m_display)
#undef CLEANUP
// these are the children of the display
m_idleInterface = nullptr;
m_seatInterface = nullptr;
}
void IdleTest::testTimeout()
{
// this test verifies the basic functionality of a timeout, that it gets fired
// and that it resumes from idle, etc.
QScopedPointer<IdleTimeout> timeout(m_idle->getTimeout(1, m_seat));
QVERIFY(timeout->isValid());
QSignalSpy idleSpy(timeout.data(), &IdleTimeout::idle);
QVERIFY(idleSpy.isValid());
QSignalSpy resumedFormIdleSpy(timeout.data(), &IdleTimeout::resumeFromIdle);
QVERIFY(resumedFormIdleSpy.isValid());
// we requested a timeout of 1 msec, but the minimum the server sets is 5 sec
QVERIFY(!idleSpy.wait(500));
// the default of 5 sec will now pass
QVERIFY(idleSpy.wait());
// simulate some activity
QVERIFY(resumedFormIdleSpy.isEmpty());
m_seatInterface->setTimestamp(1);
QVERIFY(resumedFormIdleSpy.wait());
timeout.reset();
m_connection->flush();
m_display->dispatchEvents();
}
void IdleTest::testSimulateUserActivity()
{
// this test verifies that simulate user activity doesn't fire the timer
QScopedPointer<IdleTimeout> timeout(m_idle->getTimeout(6000, m_seat));
QVERIFY(timeout->isValid());
QSignalSpy idleSpy(timeout.data(), &IdleTimeout::idle);
QVERIFY(idleSpy.isValid());
QSignalSpy resumedFormIdleSpy(timeout.data(), &IdleTimeout::resumeFromIdle);
QVERIFY(resumedFormIdleSpy.isValid());
m_connection->flush();
QTest::qWait(4000);
timeout->simulateUserActivity();
// waiting default five sec should fail
QVERIFY(!idleSpy.wait());
// another 2 sec should fire
QVERIFY(idleSpy.wait(2000));
// now simulating user activity should emit a resumedFromIdle
QVERIFY(resumedFormIdleSpy.isEmpty());
timeout->simulateUserActivity();
QVERIFY(resumedFormIdleSpy.wait());
timeout.reset();
m_connection->flush();
m_display->dispatchEvents();
}
void IdleTest::testServerSimulateUserActivity()
{
// this test verifies that simulate user activity doesn't fire the timer
QScopedPointer<IdleTimeout> timeout(m_idle->getTimeout(6000, m_seat));
QVERIFY(timeout->isValid());
QSignalSpy idleSpy(timeout.data(), &IdleTimeout::idle);
QVERIFY(idleSpy.isValid());
QSignalSpy resumedFormIdleSpy(timeout.data(), &IdleTimeout::resumeFromIdle);
QVERIFY(resumedFormIdleSpy.isValid());
m_connection->flush();
QTest::qWait(4000);
m_idleInterface->simulateUserActivity();
// waiting default five sec should fail
QVERIFY(!idleSpy.wait());
// another 2 sec should fire
QVERIFY(idleSpy.wait(2000));
// now simulating user activity should emit a resumedFromIdle
QVERIFY(resumedFormIdleSpy.isEmpty());
m_idleInterface->simulateUserActivity();
QVERIFY(resumedFormIdleSpy.wait());
timeout.reset();
m_connection->flush();
m_display->dispatchEvents();
}
void IdleTest::testIdleInhibit()
{
QCOMPARE(m_idleInterface->isInhibited(), false);
QSignalSpy idleInhibitedSpy(m_idleInterface, &IdleInterface::inhibitedChanged);
QVERIFY(idleInhibitedSpy.isValid());
m_idleInterface->inhibit();
QCOMPARE(m_idleInterface->isInhibited(), true);
QCOMPARE(idleInhibitedSpy.count(), 1);
m_idleInterface->inhibit();
QCOMPARE(m_idleInterface->isInhibited(), true);
QCOMPARE(idleInhibitedSpy.count(), 1);
m_idleInterface->uninhibit();
QCOMPARE(m_idleInterface->isInhibited(), true);
QCOMPARE(idleInhibitedSpy.count(), 1);
m_idleInterface->uninhibit();
QCOMPARE(m_idleInterface->isInhibited(), false);
QCOMPARE(idleInhibitedSpy.count(), 2);
}
void IdleTest::testIdleInhibitBlocksTimeout()
{
// this test verifies that a timeout does not fire when the system is inhibited
// so first inhibit
QCOMPARE(m_idleInterface->isInhibited(), false);
m_idleInterface->inhibit();
QScopedPointer<IdleTimeout> timeout(m_idle->getTimeout(1, m_seat));
QVERIFY(timeout->isValid());
QSignalSpy idleSpy(timeout.data(), &IdleTimeout::idle);
QVERIFY(idleSpy.isValid());
QSignalSpy resumedFormIdleSpy(timeout.data(), &IdleTimeout::resumeFromIdle);
QVERIFY(resumedFormIdleSpy.isValid());
// we requested a timeout of 1 msec, but the minimum the server sets is 5 sec
QVERIFY(!idleSpy.wait(500));
// the default of 5 sec won't pass
QVERIFY(!idleSpy.wait());
// simulate some activity
QVERIFY(resumedFormIdleSpy.isEmpty());
m_seatInterface->setTimestamp(1);
// resume from idle should not fire
QVERIFY(!resumedFormIdleSpy.wait());
// let's uninhibit
m_idleInterface->uninhibit();
QCOMPARE(m_idleInterface->isInhibited(), false);
// we requested a timeout of 1 msec, but the minimum the server sets is 5 sec
QVERIFY(!idleSpy.wait(500));
// the default of 5 sec will now pass
QVERIFY(idleSpy.wait());
// if we inhibit now it will trigger a resume from idle
QVERIFY(resumedFormIdleSpy.isEmpty());
m_idleInterface->inhibit();
QVERIFY(resumedFormIdleSpy.wait());
// let's wait again just to verify that also inhibit for already existing IdleTimeout works
QVERIFY(!idleSpy.wait(500));
QVERIFY(!idleSpy.wait());
QCOMPARE(idleSpy.count(), 1);
timeout.reset();
m_connection->flush();
m_display->dispatchEvents();
}
QTEST_GUILESS_MAIN(IdleTest)
#include "test_idle.moc"