File indexing completed on 2024-11-10 04:56:12
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 "compositor.h" 0010 #include "main.h" 0011 #include "scene/workspacescene.h" 0012 #include "wayland_server.h" 0013 #include "workspace.h" 0014 #include "x11window.h" 0015 #include "xwayland/xwayland.h" 0016 #include "xwayland/xwaylandlauncher.h" 0017 0018 #include <xcb/xcb_icccm.h> 0019 0020 namespace KWin 0021 { 0022 0023 static const QString s_socketName = QStringLiteral("wayland_test_kwin_xwayland_server_restart-0"); 0024 0025 class XwaylandServerRestartTest : public QObject 0026 { 0027 Q_OBJECT 0028 0029 private Q_SLOTS: 0030 void initTestCase(); 0031 void testRestart(); 0032 }; 0033 0034 void XwaylandServerRestartTest::initTestCase() 0035 { 0036 QSignalSpy applicationStartedSpy(kwinApp(), &Application::started); 0037 QVERIFY(waylandServer()->init(s_socketName)); 0038 Test::setOutputConfig({ 0039 QRect(0, 0, 1280, 1024), 0040 QRect(1280, 0, 1280, 1024), 0041 }); 0042 0043 KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); 0044 KConfigGroup xwaylandGroup = config->group(QStringLiteral("Xwayland")); 0045 xwaylandGroup.writeEntry(QStringLiteral("XwaylandCrashPolicy"), QStringLiteral("Restart")); 0046 xwaylandGroup.sync(); 0047 kwinApp()->setConfig(config); 0048 0049 kwinApp()->start(); 0050 QVERIFY(applicationStartedSpy.wait()); 0051 } 0052 0053 static void kwin_safe_kill(QProcess *process) 0054 { 0055 // The SIGKILL signal must be sent when the event loop is spinning. 0056 QTimer::singleShot(1, process, &QProcess::kill); 0057 } 0058 0059 void XwaylandServerRestartTest::testRestart() 0060 { 0061 // This test verifies that the Xwayland server will be restarted after a crash. 0062 0063 Xwl::Xwayland *xwayland = static_cast<Xwl::Xwayland *>(kwinApp()->xwayland()); 0064 0065 QSignalSpy startedSpy(xwayland, &Xwl::Xwayland::started); 0066 QSignalSpy stoppedSpy(xwayland, &Xwl::Xwayland::errorOccurred); 0067 0068 Test::createX11Connection(); // trigger an X11 start 0069 QTRY_COMPARE(startedSpy.count(), 1); 0070 0071 // Pretend that the Xwayland process has crashed by sending a SIGKILL to it. 0072 kwin_safe_kill(xwayland->xwaylandLauncher()->process()); 0073 0074 QTRY_COMPARE(stoppedSpy.count(), 1); 0075 0076 // Check that the compositor still accepts new X11 clients. 0077 Test::XcbConnectionPtr c = Test::createX11Connection(); 0078 QVERIFY(!xcb_connection_has_error(c.get())); 0079 0080 QTRY_COMPARE(startedSpy.count(), 2); 0081 const QRect rect(0, 0, 100, 200); 0082 xcb_window_t windowId = xcb_generate_id(c.get()); 0083 xcb_create_window(c.get(), XCB_COPY_FROM_PARENT, windowId, rootWindow(), 0084 rect.x(), rect.y(), rect.width(), rect.height(), 0, 0085 XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0, nullptr); 0086 xcb_size_hints_t hints; 0087 memset(&hints, 0, sizeof(hints)); 0088 xcb_icccm_size_hints_set_position(&hints, 1, rect.x(), rect.y()); 0089 xcb_icccm_size_hints_set_size(&hints, 1, rect.width(), rect.height()); 0090 xcb_icccm_size_hints_set_min_size(&hints, rect.width(), rect.height()); 0091 xcb_icccm_set_wm_normal_hints(c.get(), windowId, &hints); 0092 xcb_map_window(c.get(), windowId); 0093 xcb_flush(c.get()); 0094 0095 QSignalSpy windowCreatedSpy(workspace(), &Workspace::windowAdded); 0096 QVERIFY(windowCreatedSpy.wait()); 0097 X11Window *window = windowCreatedSpy.last().first().value<X11Window *>(); 0098 QVERIFY(window); 0099 QCOMPARE(window->window(), windowId); 0100 QVERIFY(window->isDecorated()); 0101 0102 // Render a frame to ensure that the compositor doesn't crash. 0103 Compositor::self()->scene()->addRepaintFull(); 0104 QSignalSpy frameRenderedSpy(Compositor::self()->scene(), &WorkspaceScene::frameRendered); 0105 QVERIFY(frameRenderedSpy.wait()); 0106 0107 // Destroy the test window. 0108 xcb_destroy_window(c.get(), windowId); 0109 xcb_flush(c.get()); 0110 QVERIFY(Test::waitForWindowClosed(window)); 0111 } 0112 0113 } // namespace KWin 0114 0115 WAYLANDTEST_MAIN(KWin::XwaylandServerRestartTest) 0116 #include "xwaylandserver_restart_test.moc"