Warning, file /plasma/kwin/autotests/integration/xwaylandserver_restart_test.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kwin_wayland_test.h" 0008 0009 #include "composite.h" 0010 #include "core/outputbackend.h" 0011 #include "main.h" 0012 #include "scene/workspacescene.h" 0013 #include "wayland_server.h" 0014 #include "workspace.h" 0015 #include "x11window.h" 0016 #include "xwayland/xwayland.h" 0017 #include "xwayland/xwaylandlauncher.h" 0018 0019 #include <xcb/xcb_icccm.h> 0020 0021 namespace KWin 0022 { 0023 0024 struct XcbConnectionDeleter 0025 { 0026 void operator()(xcb_connection_t *pointer) 0027 { 0028 xcb_disconnect(pointer); 0029 } 0030 }; 0031 0032 static const QString s_socketName = QStringLiteral("wayland_test_kwin_xwayland_server_restart-0"); 0033 0034 class XwaylandServerRestartTest : public QObject 0035 { 0036 Q_OBJECT 0037 0038 private Q_SLOTS: 0039 void initTestCase(); 0040 void testRestart(); 0041 }; 0042 0043 void XwaylandServerRestartTest::initTestCase() 0044 { 0045 QSignalSpy applicationStartedSpy(kwinApp(), &Application::started); 0046 QVERIFY(waylandServer()->init(s_socketName)); 0047 QMetaObject::invokeMethod(kwinApp()->outputBackend(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(QVector<QRect>, QVector<QRect>() << QRect(0, 0, 1280, 1024) << QRect(1280, 0, 1280, 1024))); 0048 0049 KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); 0050 KConfigGroup xwaylandGroup = config->group("Xwayland"); 0051 xwaylandGroup.writeEntry(QStringLiteral("XwaylandCrashPolicy"), QStringLiteral("Restart")); 0052 xwaylandGroup.sync(); 0053 kwinApp()->setConfig(config); 0054 0055 kwinApp()->start(); 0056 QVERIFY(applicationStartedSpy.wait()); 0057 } 0058 0059 static void kwin_safe_kill(QProcess *process) 0060 { 0061 // The SIGKILL signal must be sent when the event loop is spinning. 0062 QTimer::singleShot(1, process, &QProcess::kill); 0063 } 0064 0065 void XwaylandServerRestartTest::testRestart() 0066 { 0067 // This test verifies that the Xwayland server will be restarted after a crash. 0068 0069 Xwl::Xwayland *xwayland = static_cast<Xwl::Xwayland *>(kwinApp()->xwayland()); 0070 0071 // Pretend that the Xwayland process has crashed by sending a SIGKILL to it. 0072 QSignalSpy startedSpy(xwayland, &Xwl::Xwayland::started); 0073 kwin_safe_kill(xwayland->xwaylandLauncher()->process()); 0074 QVERIFY(startedSpy.wait()); 0075 QCOMPARE(startedSpy.count(), 1); 0076 0077 // Check that the compositor still accepts new X11 clients. 0078 std::unique_ptr<xcb_connection_t, XcbConnectionDeleter> c(xcb_connect(nullptr, nullptr)); 0079 QVERIFY(!xcb_connection_has_error(c.get())); 0080 const QRect rect(0, 0, 100, 200); 0081 xcb_window_t windowId = xcb_generate_id(c.get()); 0082 xcb_create_window(c.get(), XCB_COPY_FROM_PARENT, windowId, rootWindow(), 0083 rect.x(), rect.y(), rect.width(), rect.height(), 0, 0084 XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0, nullptr); 0085 xcb_size_hints_t hints; 0086 memset(&hints, 0, sizeof(hints)); 0087 xcb_icccm_size_hints_set_position(&hints, 1, rect.x(), rect.y()); 0088 xcb_icccm_size_hints_set_size(&hints, 1, rect.width(), rect.height()); 0089 xcb_icccm_size_hints_set_min_size(&hints, rect.width(), rect.height()); 0090 xcb_icccm_set_wm_normal_hints(c.get(), windowId, &hints); 0091 xcb_map_window(c.get(), windowId); 0092 xcb_flush(c.get()); 0093 0094 QSignalSpy windowCreatedSpy(workspace(), &Workspace::windowAdded); 0095 QVERIFY(windowCreatedSpy.wait()); 0096 X11Window *window = windowCreatedSpy.last().first().value<X11Window *>(); 0097 QVERIFY(window); 0098 QCOMPARE(window->window(), windowId); 0099 QVERIFY(window->isDecorated()); 0100 0101 // Render a frame to ensure that the compositor doesn't crash. 0102 Compositor::self()->scene()->addRepaintFull(); 0103 QSignalSpy frameRenderedSpy(Compositor::self()->scene(), &WorkspaceScene::frameRendered); 0104 QVERIFY(frameRenderedSpy.wait()); 0105 0106 // Destroy the test window. 0107 xcb_destroy_window(c.get(), windowId); 0108 xcb_flush(c.get()); 0109 QVERIFY(Test::waitForWindowDestroyed(window)); 0110 } 0111 0112 } // namespace KWin 0113 0114 WAYLANDTEST_MAIN(KWin::XwaylandServerRestartTest) 0115 #include "xwaylandserver_restart_test.moc"