9e3cd3bf7b
Reviewers: #plasma Subscribers: plasma-devel Projects: #plasma Differential Revision: https://phabricator.kde.org/D1400
321 lines
11 KiB
C++
321 lines
11 KiB
C++
/********************************************************************
|
|
Copyright 2016 Martin Gräßlin <mgraesslin@kde.org>
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) version 3, or any
|
|
later version accepted by the membership of KDE e.V. (or its
|
|
successor approved by the membership of KDE e.V.), which shall
|
|
act as a proxy defined in Section 6 of version 3 of the license.
|
|
|
|
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 library. If not, see <http://www.gnu.org/licenses/>.
|
|
*********************************************************************/
|
|
// Qt
|
|
#include <QtTest/QtTest>
|
|
// client
|
|
#include "../../src/client/connection_thread.h"
|
|
#include "../../src/client/event_queue.h"
|
|
#include "../../src/client/fakeinput.h"
|
|
#include "../../src/client/registry.h"
|
|
// server
|
|
#include "../../src/server/display.h"
|
|
#include "../../src/server/fakeinput_interface.h"
|
|
|
|
#include <linux/input.h>
|
|
|
|
using namespace KWayland::Client;
|
|
using namespace KWayland::Server;
|
|
|
|
Q_DECLARE_METATYPE(Qt::MouseButton)
|
|
|
|
class FakeInputTest : public QObject
|
|
{
|
|
Q_OBJECT
|
|
private Q_SLOTS:
|
|
void init();
|
|
void cleanup();
|
|
|
|
void testAuthenticate();
|
|
void testMotion();
|
|
void testPointerButtonQt_data();
|
|
void testPointerButtonQt();
|
|
void testPointerButtonLinux_data();
|
|
void testPointerButtonLinux();
|
|
void testAxis_data();
|
|
void testAxis();
|
|
|
|
private:
|
|
Display *m_display = nullptr;
|
|
FakeInputInterface *m_fakeInputInterface = nullptr;
|
|
FakeInputDevice *m_device = nullptr;
|
|
ConnectionThread *m_connection = nullptr;
|
|
QThread *m_thread = nullptr;
|
|
EventQueue *m_queue = nullptr;
|
|
FakeInput *m_fakeInput = nullptr;
|
|
};
|
|
|
|
static const QString s_socketName = QStringLiteral("kwayland-test-fake-input-0");
|
|
|
|
void FakeInputTest::init()
|
|
{
|
|
delete m_display;
|
|
m_display = new Display(this);
|
|
m_display->setSocketName(s_socketName);
|
|
m_display->start();
|
|
QVERIFY(m_display->isRunning());
|
|
m_display->createShm();
|
|
m_fakeInputInterface = m_display->createFakeInput();
|
|
m_fakeInputInterface->create();
|
|
QSignalSpy deviceCreatedSpy(m_fakeInputInterface, &FakeInputInterface::deviceCreated);
|
|
QVERIFY(deviceCreatedSpy.isValid());
|
|
|
|
// 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(®istry, &Registry::interfacesAnnounced);
|
|
QVERIFY(interfacesAnnouncedSpy.isValid());
|
|
registry.setEventQueue(m_queue);
|
|
registry.create(m_connection);
|
|
QVERIFY(registry.isValid());
|
|
registry.setup();
|
|
QVERIFY(interfacesAnnouncedSpy.wait());
|
|
|
|
m_fakeInput = registry.createFakeInput(registry.interface(Registry::Interface::FakeInput).name,
|
|
registry.interface(Registry::Interface::FakeInput).version,
|
|
this);
|
|
QVERIFY(m_fakeInput->isValid());
|
|
|
|
QVERIFY(deviceCreatedSpy.wait());
|
|
m_device = deviceCreatedSpy.first().first().value<FakeInputDevice*>();
|
|
QVERIFY(m_device);
|
|
}
|
|
|
|
void FakeInputTest::cleanup()
|
|
{
|
|
#define CLEANUP(variable) \
|
|
if (variable) { \
|
|
delete variable; \
|
|
variable = nullptr; \
|
|
}
|
|
CLEANUP(m_fakeInput)
|
|
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_device)
|
|
CLEANUP(m_fakeInputInterface)
|
|
CLEANUP(m_display)
|
|
#undef CLEANUP
|
|
}
|
|
|
|
void FakeInputTest::testAuthenticate()
|
|
{
|
|
// this test verifies that an authenticate request is passed to the Server
|
|
QVERIFY(!m_device->isAuthenticated());
|
|
QSignalSpy authenticationRequestedSpy(m_device, &FakeInputDevice::authenticationRequested);
|
|
QVERIFY(authenticationRequestedSpy.isValid());
|
|
|
|
m_fakeInput->authenticate(QStringLiteral("test-case"), QStringLiteral("to test"));
|
|
QVERIFY(authenticationRequestedSpy.wait());
|
|
QCOMPARE(authenticationRequestedSpy.count(), 1);
|
|
QCOMPARE(authenticationRequestedSpy.first().at(0).toString(), QStringLiteral("test-case"));
|
|
QCOMPARE(authenticationRequestedSpy.first().at(1).toString(), QStringLiteral("to test"));
|
|
m_device->setAuthentication(true);
|
|
QVERIFY(m_device->isAuthenticated());
|
|
}
|
|
|
|
void FakeInputTest::testMotion()
|
|
{
|
|
// this test verifies that motion is properly passed to the server
|
|
QVERIFY(!m_device->isAuthenticated());
|
|
QSignalSpy motionSpy(m_device, &FakeInputDevice::pointerMotionRequested);
|
|
QVERIFY(motionSpy.isValid());
|
|
|
|
// without an authentication we shouldn't get the signals
|
|
m_fakeInput->requestPointerMove(QSizeF(1, 2));
|
|
QVERIFY(!motionSpy.wait(100));
|
|
|
|
// now let's authenticate the interface
|
|
m_device->setAuthentication(true);
|
|
m_fakeInput->requestPointerMove(QSizeF(1, 2));
|
|
QVERIFY(motionSpy.wait());
|
|
QCOMPARE(motionSpy.count(), 1);
|
|
QCOMPARE(motionSpy.last().first().toSizeF(), QSizeF(1, 2));
|
|
|
|
// just for the fun: once more
|
|
m_fakeInput->requestPointerMove(QSizeF(0, 0));
|
|
QVERIFY(motionSpy.wait());
|
|
QCOMPARE(motionSpy.count(), 2);
|
|
QCOMPARE(motionSpy.last().first().toSizeF(), QSizeF(0, 0));
|
|
}
|
|
|
|
void FakeInputTest::testPointerButtonQt_data()
|
|
{
|
|
QTest::addColumn<Qt::MouseButton>("qtButton");
|
|
QTest::addColumn<quint32>("linuxButton");
|
|
|
|
QTest::newRow("left") << Qt::LeftButton << quint32(BTN_LEFT);
|
|
QTest::newRow("right") << Qt::RightButton << quint32(BTN_RIGHT);
|
|
QTest::newRow("middle") << Qt::MiddleButton << quint32(BTN_MIDDLE);
|
|
}
|
|
|
|
void FakeInputTest::testPointerButtonQt()
|
|
{
|
|
// this test verifies that pointer button events are properly passed to the server with Qt button codes
|
|
QVERIFY(!m_device->isAuthenticated());
|
|
QSignalSpy pressedSpy(m_device, &FakeInputDevice::pointerButtonPressRequested);
|
|
QVERIFY(pressedSpy.isValid());
|
|
QSignalSpy releasedSpy(m_device, &FakeInputDevice::pointerButtonReleaseRequested);
|
|
QVERIFY(releasedSpy.isValid());
|
|
|
|
// without an authentication we shouldn't get the signals
|
|
QFETCH(Qt::MouseButton, qtButton);
|
|
m_fakeInput->requestPointerButtonClick(qtButton);
|
|
QVERIFY(!pressedSpy.wait(100));
|
|
QVERIFY(pressedSpy.isEmpty());
|
|
QVERIFY(releasedSpy.isEmpty());
|
|
|
|
// now authenticate
|
|
m_device->setAuthentication(true);
|
|
// now our click should work
|
|
m_fakeInput->requestPointerButtonClick(qtButton);
|
|
QVERIFY(releasedSpy.wait());
|
|
QCOMPARE(pressedSpy.count(), 1);
|
|
QCOMPARE(releasedSpy.count(), 1);
|
|
QTEST(pressedSpy.last().first().value<quint32>(), "linuxButton");
|
|
QTEST(releasedSpy.last().first().value<quint32>(), "linuxButton");
|
|
|
|
// and a press/release "manually"
|
|
m_fakeInput->requestPointerButtonPress(qtButton);
|
|
QVERIFY(pressedSpy.wait());
|
|
QCOMPARE(pressedSpy.count(), 2);
|
|
QCOMPARE(releasedSpy.count(), 1);
|
|
QTEST(pressedSpy.last().first().value<quint32>(), "linuxButton");
|
|
// and release
|
|
m_fakeInput->requestPointerButtonRelease(qtButton);
|
|
QVERIFY(releasedSpy.wait());
|
|
QCOMPARE(pressedSpy.count(), 2);
|
|
QCOMPARE(releasedSpy.count(), 2);
|
|
QTEST(releasedSpy.last().first().value<quint32>(), "linuxButton");
|
|
}
|
|
|
|
void FakeInputTest::testPointerButtonLinux_data()
|
|
{
|
|
QTest::addColumn<quint32>("linuxButton");
|
|
|
|
QTest::newRow("left") << quint32(BTN_LEFT);
|
|
QTest::newRow("right") << quint32(BTN_RIGHT);
|
|
QTest::newRow("middle") << quint32(BTN_MIDDLE);
|
|
QTest::newRow("side") << quint32(BTN_SIDE);
|
|
QTest::newRow("extra") << quint32(BTN_EXTRA);
|
|
QTest::newRow("forward") << quint32(BTN_FORWARD);
|
|
QTest::newRow("back") << quint32(BTN_BACK);
|
|
QTest::newRow("task") << quint32(BTN_TASK);
|
|
}
|
|
|
|
void FakeInputTest::testPointerButtonLinux()
|
|
{
|
|
// this test verifies that pointer button events are properly passed to the server with Qt button codes
|
|
QVERIFY(!m_device->isAuthenticated());
|
|
QSignalSpy pressedSpy(m_device, &FakeInputDevice::pointerButtonPressRequested);
|
|
QVERIFY(pressedSpy.isValid());
|
|
QSignalSpy releasedSpy(m_device, &FakeInputDevice::pointerButtonReleaseRequested);
|
|
QVERIFY(releasedSpy.isValid());
|
|
|
|
// without an authentication we shouldn't get the signals
|
|
QFETCH(quint32, linuxButton);
|
|
m_fakeInput->requestPointerButtonClick(linuxButton);
|
|
QVERIFY(!pressedSpy.wait(100));
|
|
QVERIFY(pressedSpy.isEmpty());
|
|
QVERIFY(releasedSpy.isEmpty());
|
|
|
|
// now authenticate
|
|
m_device->setAuthentication(true);
|
|
// now our click should work
|
|
m_fakeInput->requestPointerButtonClick(linuxButton);
|
|
QVERIFY(releasedSpy.wait());
|
|
QCOMPARE(pressedSpy.count(), 1);
|
|
QCOMPARE(releasedSpy.count(), 1);
|
|
QTEST(pressedSpy.last().first().value<quint32>(), "linuxButton");
|
|
QTEST(releasedSpy.last().first().value<quint32>(), "linuxButton");
|
|
|
|
// and a press/release "manually"
|
|
m_fakeInput->requestPointerButtonPress(linuxButton);
|
|
QVERIFY(pressedSpy.wait());
|
|
QCOMPARE(pressedSpy.count(), 2);
|
|
QCOMPARE(releasedSpy.count(), 1);
|
|
QTEST(pressedSpy.last().first().value<quint32>(), "linuxButton");
|
|
// and release
|
|
m_fakeInput->requestPointerButtonRelease(linuxButton);
|
|
QVERIFY(releasedSpy.wait());
|
|
QCOMPARE(pressedSpy.count(), 2);
|
|
QCOMPARE(releasedSpy.count(), 2);
|
|
QTEST(releasedSpy.last().first().value<quint32>(), "linuxButton");
|
|
}
|
|
|
|
void FakeInputTest::testAxis_data()
|
|
{
|
|
QTest::addColumn<Qt::Orientation>("orientation");
|
|
QTest::addColumn<qreal>("delta");
|
|
|
|
QTest::newRow("horizontal/1") << Qt::Horizontal << 1.0;
|
|
QTest::newRow("horizontal/-2") << Qt::Horizontal << -2.0;
|
|
QTest::newRow("vertical/10") << Qt::Vertical << 10.0;
|
|
QTest::newRow("vertical/-20") << Qt::Vertical << -22.0;
|
|
}
|
|
|
|
void FakeInputTest::testAxis()
|
|
{
|
|
// this test verifies that pointer axis events are properly passed to the server
|
|
QVERIFY(!m_device->isAuthenticated());
|
|
QSignalSpy axisSpy(m_device, &FakeInputDevice::pointerAxisRequested);
|
|
QVERIFY(axisSpy.isValid());
|
|
|
|
QFETCH(Qt::Orientation, orientation);
|
|
QFETCH(qreal, delta);
|
|
// without an authentication we shouldn't get the signals
|
|
m_fakeInput->requestPointerAxis(orientation, delta);
|
|
QVERIFY(!axisSpy.wait(100));
|
|
|
|
// now authenticate
|
|
m_device->setAuthentication(true);
|
|
|
|
// now we can properly test
|
|
m_fakeInput->requestPointerAxis(orientation, delta);
|
|
QVERIFY(axisSpy.wait());
|
|
QCOMPARE(axisSpy.count(), 1);
|
|
QCOMPARE(axisSpy.first().at(0).value<Qt::Orientation>(), orientation);
|
|
QCOMPARE(axisSpy.first().at(1).value<qreal>(), delta);
|
|
}
|
|
|
|
QTEST_GUILESS_MAIN(FakeInputTest)
|
|
#include "test_fake_input.moc"
|