File indexing completed on 2024-05-12 05:38:09
0001 /* 0002 SPDX-FileCopyrightText: 2023 Fushan Wen <qydwhotmail@gmail.com> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #define QT_FORCE_ASSERTS 1 0008 0009 #include <QProcess> 0010 #include <qpa/qplatformnativeinterface.h> 0011 0012 #include <wayland-client-core.h> 0013 0014 #include "common.h" 0015 #include "waylandtasksmodel.h" 0016 0017 using namespace TaskManager; 0018 using namespace Qt::StringLiterals; 0019 0020 class WaylandTasksModelTest : public QObject 0021 { 0022 Q_OBJECT 0023 0024 private Q_SLOTS: 0025 void initTestCase(); 0026 void cleanupTestCase(); 0027 0028 void test_openCloseWindow(); 0029 void test_modelData(); 0030 void test_fullscreen(); 0031 void test_geometry(); 0032 void test_stackingOrder(); 0033 void test_modelDataFromDesktopFile(); 0034 0035 void test_request(); 0036 0037 // plasmashell runs out of file descriptors when emacs visits lots of files 0038 void test_bug478831(); 0039 0040 private: 0041 WaylandTasksModel m_model; 0042 }; 0043 0044 void WaylandTasksModelTest::initTestCase() 0045 { 0046 TestUtils::initTestCase(); 0047 0048 if (!KWindowSystem::isPlatformWayland()) { 0049 QSKIP("Test is not running on Wayland."); 0050 } 0051 0052 QGuiApplication::setQuitOnLastWindowClosed(false); 0053 0054 QStandardPaths::setTestModeEnabled(true); 0055 0056 const QString applicationDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QDir::separator() + QStringLiteral("applications"); 0057 QDir dir; 0058 if (!dir.exists(applicationDir)) { 0059 dir.mkpath(applicationDir); 0060 } 0061 0062 QPlatformNativeInterface *const native = qGuiApp->platformNativeInterface(); 0063 wl_display_roundtrip(static_cast<struct wl_display *>(native->nativeResourceForIntegration("wl_display"))); 0064 } 0065 0066 void WaylandTasksModelTest::cleanupTestCase() 0067 { 0068 TestUtils::cleanupTestCase(); 0069 } 0070 0071 void WaylandTasksModelTest::test_openCloseWindow() 0072 { 0073 TestUtils::testOpenCloseWindow(m_model); 0074 } 0075 0076 void WaylandTasksModelTest::test_modelData() 0077 { 0078 const QString title = QStringLiteral("__testwindow__%1").arg(QDateTime::currentDateTime().toString()); 0079 QModelIndex index; 0080 auto window = TestUtils::createSingleWindow(m_model, title, index); 0081 0082 // See WaylandTasksModel::data for available roles 0083 // Icon is unavailable on Wayland 0084 0085 QTRY_COMPARE(index.data(AbstractTasksModel::WinIdList).toList().size(), 1); 0086 QVERIFY(index.data(AbstractTasksModel::MimeType).toString().startsWith(QLatin1String("windowsystem/winid"))); 0087 0088 QTRY_VERIFY(index.data(AbstractTasksModel::IsWindow).toBool()); 0089 QTRY_VERIFY(index.data(AbstractTasksModel::IsActive).toBool()); 0090 0091 QTRY_VERIFY(index.data(AbstractTasksModel::IsClosable).toBool()); 0092 QTRY_VERIFY(index.data(AbstractTasksModel::IsMovable).toBool()); 0093 QTRY_VERIFY(index.data(AbstractTasksModel::IsResizable).toBool()); 0094 QTRY_VERIFY(index.data(AbstractTasksModel::IsMaximizable).toBool()); 0095 QTRY_VERIFY(!index.data(AbstractTasksModel::IsMaximized).toBool()); 0096 QTRY_VERIFY(index.data(AbstractTasksModel::IsMinimizable).toBool()); 0097 QTRY_VERIFY(!index.data(AbstractTasksModel::IsKeepAbove).toBool()); 0098 QTRY_VERIFY(!index.data(AbstractTasksModel::IsKeepBelow).toBool()); 0099 QTRY_VERIFY(index.data(AbstractTasksModel::IsFullScreenable).toBool()); 0100 QTRY_VERIFY(!index.data(AbstractTasksModel::IsFullScreen).toBool()); 0101 QTRY_VERIFY(!index.data(AbstractTasksModel::IsShadeable).toBool()); // It's intentionally not implemented on wayland 0102 QTRY_VERIFY(!index.data(AbstractTasksModel::IsShaded).toBool()); 0103 QTRY_VERIFY(index.data(AbstractTasksModel::IsVirtualDesktopsChangeable).toBool()); 0104 QTRY_VERIFY(!index.data(AbstractTasksModel::IsOnAllVirtualDesktops).toBool()); 0105 0106 // Due to window decoration, the size of a window can't be determined accurately 0107 const QRect screenGeometry = index.data(AbstractTasksModel::ScreenGeometry).toRect(); 0108 QVERIFY(screenGeometry.width() > 0 && screenGeometry.height() > 0); 0109 0110 QTRY_VERIFY(!index.data(AbstractTasksModel::IsDemandingAttention).toBool()); 0111 QTRY_VERIFY(!index.data(AbstractTasksModel::SkipTaskbar).toBool()); 0112 QTRY_VERIFY(!index.data(AbstractTasksModel::SkipPager).toBool()); 0113 // AbstractTasksModel::AppPid 0114 0115 QVERIFY(index.data(AbstractTasksModel::CanLaunchNewInstance).toBool()); 0116 } 0117 0118 void WaylandTasksModelTest::test_fullscreen() 0119 { 0120 TestUtils::testFullscreen(m_model); 0121 } 0122 0123 void WaylandTasksModelTest::test_geometry() 0124 { 0125 TestUtils::testGeometry(m_model); 0126 } 0127 0128 void WaylandTasksModelTest::test_stackingOrder() 0129 { 0130 TestUtils::testStackingOrder(m_model); 0131 } 0132 0133 void WaylandTasksModelTest::test_modelDataFromDesktopFile() 0134 { 0135 TestUtils::testModelDataFromDesktopFile(m_model); 0136 } 0137 0138 void WaylandTasksModelTest::test_request() 0139 { 0140 TestUtils::testRequest(m_model); 0141 } 0142 0143 void WaylandTasksModelTest::test_bug478831() 0144 { 0145 QProcess lsof; 0146 lsof.setProgram(u"lsof"_s); 0147 lsof.setArguments({u"-p"_s, QString::number(getpid())}); 0148 lsof.setReadChannel(QProcess::StandardOutput); 0149 lsof.start(QIODeviceBase::ReadOnly); 0150 lsof.waitForFinished(); 0151 const QByteArray fdCountBeforeBA = lsof.readAllStandardOutput(); 0152 const int fdCountBefore = fdCountBeforeBA.count('\n'); 0153 0154 QSignalSpy rowsInsertedSpy(&m_model, &AbstractWindowTasksModel::rowsInserted); 0155 0156 QProcess gtkWindow; 0157 gtkWindow.setProgram(u"python3"_s); 0158 QProcessEnvironment newEnv = QProcessEnvironment::systemEnvironment(); 0159 newEnv.insert(u"GDK_BACKEND"_s, u"x11"_s); 0160 newEnv.insert(u"NO_AT_BRIDGE"_s, u"1"_s); // Otherwise following tests will fail 0161 gtkWindow.setProcessEnvironment(newEnv); 0162 gtkWindow.setArguments({QFINDTESTDATA(u"data/windows/bug478831.py"_s)}); 0163 gtkWindow.start(QIODeviceBase::ReadOnly); 0164 0165 if (rowsInsertedSpy.empty()) { 0166 QVERIFY(rowsInsertedSpy.wait()); 0167 } 0168 const auto results = m_model.match(m_model.index(0, 0), Qt::DisplayRole, u"flash"_s); 0169 QCOMPARE(results.size(), 1); 0170 QTest::qWait(10000); 0171 0172 lsof.start(QIODeviceBase::ReadOnly); 0173 lsof.waitForFinished(); 0174 const QByteArray fdCountAfterBA = lsof.readAllStandardOutput(); 0175 const int fdCountAfter = fdCountAfterBA.count('\n'); 0176 0177 gtkWindow.terminate(); 0178 gtkWindow.waitForFinished(); 0179 qDebug() << fdCountBefore << fdCountAfter << getpid(); 0180 QVERIFY(fdCountBefore > 10); 0181 QVERIFY(fdCountAfter > 10); 0182 QVERIFY(fdCountAfter - fdCountBefore < 10); 0183 } 0184 0185 QTEST_MAIN(WaylandTasksModelTest) 0186 0187 #include "waylandtasksmodeltest.moc"