KWin
Loading...
Searching...
No Matches
xwaylandserver_restart_test.cpp
Go to the documentation of this file.
1/*
2 SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "kwin_wayland_test.h"
8
9#include "compositor.h"
10#include "main.h"
12#include "wayland_server.h"
13#include "workspace.h"
14#include "x11window.h"
15#include "xwayland/xwayland.h"
17
18#include <xcb/xcb_icccm.h>
19
20namespace KWin
21{
22
23static const QString s_socketName = QStringLiteral("wayland_test_kwin_xwayland_server_restart-0");
24
25class XwaylandServerRestartTest : public QObject
26{
27 Q_OBJECT
28
29private Q_SLOTS:
30 void initTestCase();
31 void testRestart();
32};
33
34void XwaylandServerRestartTest::initTestCase()
35{
36 QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
37 QVERIFY(waylandServer()->init(s_socketName));
39 QRect(0, 0, 1280, 1024),
40 QRect(1280, 0, 1280, 1024),
41 });
42
43 KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
44 KConfigGroup xwaylandGroup = config->group(QStringLiteral("Xwayland"));
45 xwaylandGroup.writeEntry(QStringLiteral("XwaylandCrashPolicy"), QStringLiteral("Restart"));
46 xwaylandGroup.sync();
47 kwinApp()->setConfig(config);
48
49 kwinApp()->start();
50 QVERIFY(applicationStartedSpy.wait());
51}
52
53static void kwin_safe_kill(QProcess *process)
54{
55 // The SIGKILL signal must be sent when the event loop is spinning.
56 QTimer::singleShot(1, process, &QProcess::kill);
57}
58
59void XwaylandServerRestartTest::testRestart()
60{
61 // This test verifies that the Xwayland server will be restarted after a crash.
62
63 Xwl::Xwayland *xwayland = static_cast<Xwl::Xwayland *>(kwinApp()->xwayland());
64
65 QSignalSpy startedSpy(xwayland, &Xwl::Xwayland::started);
66 QSignalSpy stoppedSpy(xwayland, &Xwl::Xwayland::errorOccurred);
67
68 Test::createX11Connection(); // trigger an X11 start
69 QTRY_COMPARE(startedSpy.count(), 1);
70
71 // Pretend that the Xwayland process has crashed by sending a SIGKILL to it.
72 kwin_safe_kill(xwayland->xwaylandLauncher()->process());
73
74 QTRY_COMPARE(stoppedSpy.count(), 1);
75
76 // Check that the compositor still accepts new X11 clients.
78 QVERIFY(!xcb_connection_has_error(c.get()));
79
80 QTRY_COMPARE(startedSpy.count(), 2);
81 const QRect rect(0, 0, 100, 200);
82 xcb_window_t windowId = xcb_generate_id(c.get());
83 xcb_create_window(c.get(), XCB_COPY_FROM_PARENT, windowId, rootWindow(),
84 rect.x(), rect.y(), rect.width(), rect.height(), 0,
85 XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0, nullptr);
86 xcb_size_hints_t hints;
87 memset(&hints, 0, sizeof(hints));
88 xcb_icccm_size_hints_set_position(&hints, 1, rect.x(), rect.y());
89 xcb_icccm_size_hints_set_size(&hints, 1, rect.width(), rect.height());
90 xcb_icccm_size_hints_set_min_size(&hints, rect.width(), rect.height());
91 xcb_icccm_set_wm_normal_hints(c.get(), windowId, &hints);
92 xcb_map_window(c.get(), windowId);
93 xcb_flush(c.get());
94
95 QSignalSpy windowCreatedSpy(workspace(), &Workspace::windowAdded);
96 QVERIFY(windowCreatedSpy.wait());
97 X11Window *window = windowCreatedSpy.last().first().value<X11Window *>();
98 QVERIFY(window);
99 QCOMPARE(window->window(), windowId);
100 QVERIFY(window->isDecorated());
101
102 // Render a frame to ensure that the compositor doesn't crash.
104 QSignalSpy frameRenderedSpy(Compositor::self()->scene(), &WorkspaceScene::frameRendered);
105 QVERIFY(frameRenderedSpy.wait());
106
107 // Destroy the test window.
108 xcb_destroy_window(c.get(), windowId);
109 xcb_flush(c.get());
110 QVERIFY(Test::waitForWindowClosed(window));
111}
112
113} // namespace KWin
114
116#include "xwaylandserver_restart_test.moc"
WorkspaceScene * scene() const
Definition compositor.h:60
static Compositor * self()
void addRepaintFull()
Definition scene.cpp:81
void windowAdded(KWin::Window *)
#define WAYLANDTEST_MAIN(TestObject)
void setOutputConfig(const QList< QRect > &geometries)
XcbConnectionPtr createX11Connection()
std::unique_ptr< xcb_connection_t, XcbConnectionDeleter > XcbConnectionPtr
bool waitForWindowClosed(Window *window)
KWIN_EXPORT xcb_window_t rootWindow()
Definition xcb.h:24
WaylandServer * waylandServer()
Workspace * workspace()
Definition workspace.h:830