KWin
Loading...
Searching...
No Matches
test_display.cpp
Go to the documentation of this file.
1/*
2 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5*/
6// Qt
7#include <QSignalSpy>
8#include <QTest>
9// WaylandServer
11#include "wayland/display.h"
12// Wayland
13#include <wayland-server.h>
14// system
15#include <sys/socket.h>
16#include <sys/types.h>
17#include <unistd.h>
18
19using namespace KWin;
20
21class TestWaylandServerDisplay : public QObject
22{
23 Q_OBJECT
24private Q_SLOTS:
25 void testSocketName();
26 void testStartStop();
27 void testClientConnection();
28 void testConnectNoSocket();
29 void testAutoSocketName();
30};
31
32void TestWaylandServerDisplay::testSocketName()
33{
34 KWin::Display display;
35 QSignalSpy changedSpy(&display, &KWin::Display::socketNamesChanged);
36 QCOMPARE(display.socketNames(), QStringList());
37 const QString testSName = QStringLiteral("fooBar");
38 display.addSocketName(testSName);
39 QCOMPARE(display.socketNames(), QStringList{testSName});
40 QCOMPARE(changedSpy.count(), 1);
41
42 // changing to same name again should not emit signal
43 display.addSocketName(testSName);
44 QCOMPARE(changedSpy.count(), 1);
45}
46
47void TestWaylandServerDisplay::testStartStop()
48{
49 const QString testSocketName = QStringLiteral("kwin-wayland-server-display-test-0");
50 QDir runtimeDir(qgetenv("XDG_RUNTIME_DIR"));
51 QVERIFY(runtimeDir.exists());
52 QVERIFY(!runtimeDir.exists(testSocketName));
53
54 std::unique_ptr<KWin::Display> display(new KWin::Display);
55 QSignalSpy runningSpy(display.get(), &KWin::Display::runningChanged);
56 display->addSocketName(testSocketName);
57 QVERIFY(!display->isRunning());
58 display->start();
59 // QVERIFY(runningSpy.wait());
60 QCOMPARE(runningSpy.count(), 1);
61 QVERIFY(runningSpy.first().first().toBool());
62 QVERIFY(display->isRunning());
63 QVERIFY(runtimeDir.exists(testSocketName));
64
65 display.reset();
66 QVERIFY(!runtimeDir.exists(testSocketName));
67}
68
69void TestWaylandServerDisplay::testClientConnection()
70{
71 KWin::Display display;
72 display.addSocketName(QStringLiteral("kwin-wayland-server-display-test-client-connection"));
73 display.start();
74 QSignalSpy connectedSpy(&display, &KWin::Display::clientConnected);
75 QSignalSpy disconnectedSpy(&display, &KWin::Display::clientDisconnected);
76
77 int sv[2];
78 QVERIFY(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) >= 0);
79
80 auto client = wl_client_create(display, sv[0]);
81 QVERIFY(client);
82
83 QVERIFY(connectedSpy.isEmpty());
84 QVERIFY(display.connections().isEmpty());
85 ClientConnection *connection = display.getConnection(client);
86 QVERIFY(connection);
87 QCOMPARE(connection->client(), client);
88 if (getuid() == 0) {
89 QEXPECT_FAIL("", "Please don't run test as root", Continue);
90 }
91 QVERIFY(connection->userId() != 0);
92 if (getgid() == 0) {
93 QEXPECT_FAIL("", "Please don't run test as root", Continue);
94 }
95 QVERIFY(connection->groupId() != 0);
96 QVERIFY(connection->processId() != 0);
97 QCOMPARE(connection->display(), &display);
98 QCOMPARE(connection->executablePath(), QCoreApplication::applicationFilePath());
99 QCOMPARE((wl_client *)*connection, client);
100 const ClientConnection &constRef = *connection;
101 QCOMPARE((wl_client *)constRef, client);
102 QCOMPARE(connectedSpy.count(), 1);
103 QCOMPARE(connectedSpy.first().first().value<ClientConnection *>(), connection);
104 QCOMPARE(display.connections().count(), 1);
105 QCOMPARE(display.connections().first(), connection);
106
107 QCOMPARE(connection, display.getConnection(client));
108 QCOMPARE(connectedSpy.count(), 1);
109
110 // create a second client
111 int sv2[2];
112 QVERIFY(socketpair(AF_UNIX, SOCK_STREAM, 0, sv2) >= 0);
113 auto client2 = display.createClient(sv2[0]);
114 QVERIFY(client2);
115 ClientConnection *connection2 = display.getConnection(client2->client());
116 QVERIFY(connection2);
117 QCOMPARE(connection2, client2);
118 QCOMPARE(connectedSpy.count(), 2);
119 QCOMPARE(connectedSpy.first().first().value<ClientConnection *>(), connection);
120 QCOMPARE(connectedSpy.last().first().value<ClientConnection *>(), connection2);
121 QCOMPARE(connectedSpy.last().first().value<ClientConnection *>(), client2);
122 QCOMPARE(display.connections().count(), 2);
123 QCOMPARE(display.connections().first(), connection);
124 QCOMPARE(display.connections().last(), connection2);
125 QCOMPARE(display.connections().last(), client2);
126
127 // and destroy
128 QVERIFY(disconnectedSpy.isEmpty());
129 wl_client_destroy(client);
130 QCOMPARE(disconnectedSpy.count(), 1);
131 QSignalSpy clientDestroyedSpy(client2, &QObject::destroyed);
132 client2->destroy();
133 QCOMPARE(clientDestroyedSpy.count(), 1);
134 QCOMPARE(disconnectedSpy.count(), 2);
135 close(sv[0]);
136 close(sv[1]);
137 close(sv2[0]);
138 close(sv2[1]);
139 QVERIFY(display.connections().isEmpty());
140}
141
142void TestWaylandServerDisplay::testConnectNoSocket()
143{
144 KWin::Display display;
145 display.start();
146 QVERIFY(display.isRunning());
147
148 // let's try connecting a client
149 int sv[2];
150 QVERIFY(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) >= 0);
151 auto client = display.createClient(sv[0]);
152 QVERIFY(client);
153
154 wl_client_destroy(client->client());
155 close(sv[0]);
156 close(sv[1]);
157}
158
159void TestWaylandServerDisplay::testAutoSocketName()
160{
161 QTemporaryDir runtimeDir;
162 QVERIFY(runtimeDir.isValid());
163 QVERIFY(qputenv("XDG_RUNTIME_DIR", runtimeDir.path().toUtf8()));
164
165 KWin::Display display0;
166 QSignalSpy socketNameChangedSpy0(&display0, &KWin::Display::socketNamesChanged);
167 QVERIFY(socketNameChangedSpy0.isValid());
168 QVERIFY(display0.addSocketName());
169 display0.start();
170 QVERIFY(display0.isRunning());
171 QCOMPARE(socketNameChangedSpy0.count(), 1);
172
173 KWin::Display display1;
174 QSignalSpy socketNameChangedSpy1(&display1, &KWin::Display::socketNamesChanged);
175 QVERIFY(socketNameChangedSpy1.isValid());
176 QVERIFY(display1.addSocketName());
177 display1.start();
178 QVERIFY(display1.isRunning());
179 QCOMPARE(socketNameChangedSpy1.count(), 1);
180}
181
182QTEST_GUILESS_MAIN(TestWaylandServerDisplay)
183#include "test_display.moc"
Convenient Class which represents a wl_client.
Class holding the Wayland server display loop.
Definition display.h:34
ClientConnection * createClient(int fd)
Definition display.cpp:228
QStringList socketNames() const
Definition display.cpp:87
QList< ClientConnection * > connections() const
Definition display.cpp:223
ClientConnection * getConnection(wl_client *client)
Definition display.cpp:200
bool addSocketName(const QString &name=QString())
Definition display.cpp:68
bool isRunning() const
Definition display.cpp:144
bool start()
Definition display.cpp:92
KWIN_EXPORT xcb_connection_t * connection()
Definition xcb.h:19