File indexing completed on 2024-11-10 04:56:21

0001 /*
0002     SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 // Qt
0007 #include <QSignalSpy>
0008 #include <QTest>
0009 // WaylandServer
0010 #include "wayland/clientconnection.h"
0011 #include "wayland/display.h"
0012 // Wayland
0013 #include <wayland-server.h>
0014 // system
0015 #include <sys/socket.h>
0016 #include <sys/types.h>
0017 #include <unistd.h>
0018 
0019 using namespace KWin;
0020 
0021 class TestWaylandServerDisplay : public QObject
0022 {
0023     Q_OBJECT
0024 private Q_SLOTS:
0025     void testSocketName();
0026     void testStartStop();
0027     void testClientConnection();
0028     void testConnectNoSocket();
0029     void testAutoSocketName();
0030 };
0031 
0032 void TestWaylandServerDisplay::testSocketName()
0033 {
0034     KWin::Display display;
0035     QSignalSpy changedSpy(&display, &KWin::Display::socketNamesChanged);
0036     QCOMPARE(display.socketNames(), QStringList());
0037     const QString testSName = QStringLiteral("fooBar");
0038     display.addSocketName(testSName);
0039     QCOMPARE(display.socketNames(), QStringList{testSName});
0040     QCOMPARE(changedSpy.count(), 1);
0041 
0042     // changing to same name again should not emit signal
0043     display.addSocketName(testSName);
0044     QCOMPARE(changedSpy.count(), 1);
0045 }
0046 
0047 void TestWaylandServerDisplay::testStartStop()
0048 {
0049     const QString testSocketName = QStringLiteral("kwin-wayland-server-display-test-0");
0050     QDir runtimeDir(qgetenv("XDG_RUNTIME_DIR"));
0051     QVERIFY(runtimeDir.exists());
0052     QVERIFY(!runtimeDir.exists(testSocketName));
0053 
0054     std::unique_ptr<KWin::Display> display(new KWin::Display);
0055     QSignalSpy runningSpy(display.get(), &KWin::Display::runningChanged);
0056     display->addSocketName(testSocketName);
0057     QVERIFY(!display->isRunning());
0058     display->start();
0059     //     QVERIFY(runningSpy.wait());
0060     QCOMPARE(runningSpy.count(), 1);
0061     QVERIFY(runningSpy.first().first().toBool());
0062     QVERIFY(display->isRunning());
0063     QVERIFY(runtimeDir.exists(testSocketName));
0064 
0065     display.reset();
0066     QVERIFY(!runtimeDir.exists(testSocketName));
0067 }
0068 
0069 void TestWaylandServerDisplay::testClientConnection()
0070 {
0071     KWin::Display display;
0072     display.addSocketName(QStringLiteral("kwin-wayland-server-display-test-client-connection"));
0073     display.start();
0074     QSignalSpy connectedSpy(&display, &KWin::Display::clientConnected);
0075     QSignalSpy disconnectedSpy(&display, &KWin::Display::clientDisconnected);
0076 
0077     int sv[2];
0078     QVERIFY(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) >= 0);
0079 
0080     auto client = wl_client_create(display, sv[0]);
0081     QVERIFY(client);
0082 
0083     QVERIFY(connectedSpy.isEmpty());
0084     QVERIFY(display.connections().isEmpty());
0085     ClientConnection *connection = display.getConnection(client);
0086     QVERIFY(connection);
0087     QCOMPARE(connection->client(), client);
0088     if (getuid() == 0) {
0089         QEXPECT_FAIL("", "Please don't run test as root", Continue);
0090     }
0091     QVERIFY(connection->userId() != 0);
0092     if (getgid() == 0) {
0093         QEXPECT_FAIL("", "Please don't run test as root", Continue);
0094     }
0095     QVERIFY(connection->groupId() != 0);
0096     QVERIFY(connection->processId() != 0);
0097     QCOMPARE(connection->display(), &display);
0098     QCOMPARE(connection->executablePath(), QCoreApplication::applicationFilePath());
0099     QCOMPARE((wl_client *)*connection, client);
0100     const ClientConnection &constRef = *connection;
0101     QCOMPARE((wl_client *)constRef, client);
0102     QCOMPARE(connectedSpy.count(), 1);
0103     QCOMPARE(connectedSpy.first().first().value<ClientConnection *>(), connection);
0104     QCOMPARE(display.connections().count(), 1);
0105     QCOMPARE(display.connections().first(), connection);
0106 
0107     QCOMPARE(connection, display.getConnection(client));
0108     QCOMPARE(connectedSpy.count(), 1);
0109 
0110     // create a second client
0111     int sv2[2];
0112     QVERIFY(socketpair(AF_UNIX, SOCK_STREAM, 0, sv2) >= 0);
0113     auto client2 = display.createClient(sv2[0]);
0114     QVERIFY(client2);
0115     ClientConnection *connection2 = display.getConnection(client2->client());
0116     QVERIFY(connection2);
0117     QCOMPARE(connection2, client2);
0118     QCOMPARE(connectedSpy.count(), 2);
0119     QCOMPARE(connectedSpy.first().first().value<ClientConnection *>(), connection);
0120     QCOMPARE(connectedSpy.last().first().value<ClientConnection *>(), connection2);
0121     QCOMPARE(connectedSpy.last().first().value<ClientConnection *>(), client2);
0122     QCOMPARE(display.connections().count(), 2);
0123     QCOMPARE(display.connections().first(), connection);
0124     QCOMPARE(display.connections().last(), connection2);
0125     QCOMPARE(display.connections().last(), client2);
0126 
0127     // and destroy
0128     QVERIFY(disconnectedSpy.isEmpty());
0129     wl_client_destroy(client);
0130     QCOMPARE(disconnectedSpy.count(), 1);
0131     QSignalSpy clientDestroyedSpy(client2, &QObject::destroyed);
0132     client2->destroy();
0133     QCOMPARE(clientDestroyedSpy.count(), 1);
0134     QCOMPARE(disconnectedSpy.count(), 2);
0135     close(sv[0]);
0136     close(sv[1]);
0137     close(sv2[0]);
0138     close(sv2[1]);
0139     QVERIFY(display.connections().isEmpty());
0140 }
0141 
0142 void TestWaylandServerDisplay::testConnectNoSocket()
0143 {
0144     KWin::Display display;
0145     display.start();
0146     QVERIFY(display.isRunning());
0147 
0148     // let's try connecting a client
0149     int sv[2];
0150     QVERIFY(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) >= 0);
0151     auto client = display.createClient(sv[0]);
0152     QVERIFY(client);
0153 
0154     wl_client_destroy(client->client());
0155     close(sv[0]);
0156     close(sv[1]);
0157 }
0158 
0159 void TestWaylandServerDisplay::testAutoSocketName()
0160 {
0161     QTemporaryDir runtimeDir;
0162     QVERIFY(runtimeDir.isValid());
0163     QVERIFY(qputenv("XDG_RUNTIME_DIR", runtimeDir.path().toUtf8()));
0164 
0165     KWin::Display display0;
0166     QSignalSpy socketNameChangedSpy0(&display0, &KWin::Display::socketNamesChanged);
0167     QVERIFY(socketNameChangedSpy0.isValid());
0168     QVERIFY(display0.addSocketName());
0169     display0.start();
0170     QVERIFY(display0.isRunning());
0171     QCOMPARE(socketNameChangedSpy0.count(), 1);
0172 
0173     KWin::Display display1;
0174     QSignalSpy socketNameChangedSpy1(&display1, &KWin::Display::socketNamesChanged);
0175     QVERIFY(socketNameChangedSpy1.isValid());
0176     QVERIFY(display1.addSocketName());
0177     display1.start();
0178     QVERIFY(display1.isRunning());
0179     QCOMPARE(socketNameChangedSpy1.count(), 1);
0180 }
0181 
0182 QTEST_GUILESS_MAIN(TestWaylandServerDisplay)
0183 #include "test_display.moc"