Warning, file /frameworks/kwindowsystem/autotests/kstartupinfo_unittest.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* This file is part of the KDE libraries 0002 0003 SPDX-FileCopyrightText: 2012, 2019 David Faure <faure@kde.org> 0004 SPDX-FileCopyrightText: 2012 Kai Dombrowe <just89@gmx.de> 0005 0006 SPDX-License-Identifier: LGPL-2.1-or-later 0007 */ 0008 0009 #include "netwm.h" 0010 #include <QSignalSpy> 0011 #include <QWidget> 0012 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) 0013 #include <private/qtx11extras_p.h> 0014 #else 0015 #include <QX11Info> 0016 #endif 0017 0018 #include <kstartupinfo.h> 0019 #include <qtest_widgets.h> 0020 0021 #include <xcb/xcb.h> 0022 0023 #include "cptr_p.h" 0024 0025 Q_DECLARE_METATYPE(KStartupInfoId) 0026 Q_DECLARE_METATYPE(KStartupInfoData) 0027 0028 class KStartupInfo_UnitTest : public QObject 0029 { 0030 Q_OBJECT 0031 public: 0032 KStartupInfo_UnitTest() 0033 : m_listener(KStartupInfo::CleanOnCantDetect, this) 0034 , m_receivedCount(0) 0035 { 0036 qRegisterMetaType<KStartupInfoId>(); 0037 qRegisterMetaType<KStartupInfoData>(); 0038 connect(&m_listener, &KStartupInfo::gotNewStartup, this, &KStartupInfo_UnitTest::slotNewStartup); 0039 } 0040 0041 protected Q_SLOTS: 0042 void slotNewStartup(const KStartupInfoId &id, const KStartupInfoData &data) 0043 { 0044 ++m_receivedCount; 0045 m_receivedId = id; 0046 m_receivedData = data; 0047 Q_EMIT ready(); 0048 } 0049 Q_SIGNALS: 0050 void ready(); 0051 0052 private Q_SLOTS: 0053 void testStart(); 0054 void dontCrashCleanup_data(); 0055 void dontCrashCleanup(); 0056 void checkCleanOnCantDetectTest(); 0057 void checkStartupTest_data(); 0058 void checkStartupTest(); 0059 void createNewStartupIdTest(); 0060 void createNewStartupIdForTimestampTest(); 0061 void setNewStartupIdTest(); 0062 0063 private: 0064 KStartupInfo m_listener; 0065 0066 int m_receivedCount; 0067 KStartupInfoId m_receivedId; 0068 KStartupInfoData m_receivedData; 0069 }; 0070 0071 void KStartupInfo_UnitTest::testStart() 0072 { 0073 KStartupInfoId id; 0074 id.initId(KStartupInfo::createNewStartupId()); 0075 0076 KStartupInfoData data; 0077 const QString appId = "/dir with space/kstartupinfo_unittest.desktop"; 0078 data.setApplicationId(appId); 0079 const QString iconPath = "/dir with space/kstartupinfo_unittest.png"; 0080 data.setIcon(iconPath); 0081 const QString description = "A description"; 0082 data.setDescription(description); 0083 const QString name = "A name"; 0084 data.setName(name); 0085 const int pid = 12345; 0086 data.addPid(pid); 0087 const QString bin = "dir with space/kstartupinfo_unittest"; 0088 data.setBin(bin); 0089 0090 QSignalSpy removedSpy(&m_listener, &KStartupInfo::gotRemoveStartup); 0091 QVERIFY(removedSpy.isValid()); 0092 0093 KStartupInfo::sendStartup(id, data); 0094 KStartupInfo::sendFinish(id, data); 0095 0096 QSignalSpy spy(this, &KStartupInfo_UnitTest::ready); 0097 spy.wait(5000); 0098 0099 QCOMPARE(m_receivedCount, 1); 0100 // qDebug() << m_receivedId.id(); // something like "$HOSTNAME;1342544979;490718;8602_TIME0" 0101 QCOMPARE(m_receivedData.name(), name); 0102 QCOMPARE(m_receivedData.description(), description); 0103 QCOMPARE(m_receivedData.applicationId(), appId); 0104 QCOMPARE(m_receivedData.icon(), iconPath); 0105 QCOMPARE(m_receivedData.bin(), bin); 0106 // qDebug() << m_receivedData.bin() << m_receivedData.name() << m_receivedData.description() << m_receivedData.icon() << m_receivedData.pids() << 0107 // m_receivedData.hostname() << m_receivedData.applicationId(); 0108 0109 int waitTime = 0; 0110 while (waitTime < 5000 && removedSpy.count() < 1) { 0111 QTest::qWait(200); 0112 waitTime += 200; 0113 } 0114 QCOMPARE(removedSpy.count(), 1); 0115 } 0116 0117 static void doSync() 0118 { 0119 auto *c = QX11Info::connection(); 0120 const auto cookie = xcb_get_input_focus(c); 0121 xcb_generic_error_t *error = nullptr; 0122 UniqueCPointer<xcb_get_input_focus_reply_t> sync(xcb_get_input_focus_reply(c, cookie, &error)); 0123 if (error) { 0124 free(error); 0125 } 0126 } 0127 0128 void KStartupInfo_UnitTest::dontCrashCleanup_data() 0129 { 0130 QTest::addColumn<bool>("silent"); 0131 QTest::addColumn<bool>("change"); 0132 QTest::addColumn<int>("countRemoveStartup"); 0133 0134 QTest::newRow("normal") << false << false << 2; 0135 QTest::newRow("silent") << true << false << 0; 0136 QTest::newRow("uninited") << false << true << 0; 0137 } 0138 0139 void KStartupInfo_UnitTest::dontCrashCleanup() 0140 { 0141 qputenv("KSTARTUPINFO_TIMEOUT", QByteArrayLiteral("1")); 0142 0143 KStartupInfoId id; 0144 KStartupInfoId id2; 0145 id.initId(QByteArrayLiteral("somefancyidwhichisrandom_kstartupinfo_unittest_0")); 0146 id2.initId(QByteArrayLiteral("somefancyidwhichisrandom_kstartupinfo_unittest_1")); 0147 0148 KStartupInfoData data; 0149 data.setApplicationId(QStringLiteral("/dir with space/kstartupinfo_unittest.desktop")); 0150 data.setIcon(QStringLiteral("/dir with space/kstartupinfo_unittest.png")); 0151 data.setDescription(QStringLiteral("A description")); 0152 data.setName(QStringLiteral("A name")); 0153 data.addPid(12345); 0154 data.setBin(QStringLiteral("dir with space/kstartupinfo_unittest")); 0155 QFETCH(bool, silent); 0156 if (silent) { 0157 data.setSilent(KStartupInfoData::Yes); 0158 } 0159 0160 QSignalSpy spy(&m_listener, &KStartupInfo::gotRemoveStartup); 0161 QFETCH(bool, change); 0162 if (change) { 0163 KStartupInfo::sendChange(id, data); 0164 KStartupInfo::sendChange(id2, data); 0165 } else { 0166 KStartupInfo::sendStartup(id, data); 0167 KStartupInfo::sendStartup(id2, data); 0168 } 0169 0170 // let's do a roundtrip to the X server 0171 doSync(); 0172 0173 QFETCH(int, countRemoveStartup); 0174 int waitTime = 1900; 0175 QTest::qWait(1900); 0176 while (waitTime <= 5000) { 0177 QTest::qWait(200); 0178 waitTime += 200; 0179 if (spy.count() == countRemoveStartup) { 0180 break; 0181 } 0182 } 0183 QCOMPARE(spy.count(), countRemoveStartup); 0184 } 0185 0186 void KStartupInfo_UnitTest::checkCleanOnCantDetectTest() 0187 { 0188 KStartupInfoId id; 0189 KStartupInfoId id2; 0190 id.initId(QByteArrayLiteral("somefancyidwhichisrandom_kstartupinfo_unittest_0")); 0191 id2.initId(QByteArrayLiteral("somefancyidwhichisrandom_kstartupinfo_unittest_1")); 0192 0193 KStartupInfoData data; 0194 data.setApplicationId(QStringLiteral("/dir with space/kstartupinfo_unittest.desktop")); 0195 data.setIcon(QStringLiteral("/dir with space/kstartupinfo_unittest.png")); 0196 data.setDescription(QStringLiteral("A description")); 0197 data.setName(QStringLiteral("A name")); 0198 data.setBin(QStringLiteral("dir with space/kstartupinfo_unittest")); 0199 data.setWMClass(QByteArrayLiteral("0")); 0200 0201 xcb_connection_t *c = QX11Info::connection(); 0202 xcb_window_t window = xcb_generate_id(c); 0203 uint32_t values[] = {XCB_EVENT_MASK_PROPERTY_CHANGE}; 0204 xcb_create_window(c, 0205 XCB_COPY_FROM_PARENT, 0206 window, 0207 QX11Info::appRootWindow(), 0208 0, 0209 0, 0210 100, 0211 100, 0212 0, 0213 XCB_COPY_FROM_PARENT, 0214 XCB_COPY_FROM_PARENT, 0215 XCB_CW_EVENT_MASK, 0216 values); 0217 0218 KStartupInfo::sendStartup(id, data); 0219 KStartupInfo::sendStartup(id2, data); 0220 0221 int previousCount = m_receivedCount; 0222 0223 doSync(); 0224 QTest::qWait(10); 0225 0226 xcb_map_window(c, window); 0227 xcb_flush(c); 0228 QTest::qWait(10); 0229 0230 xcb_unmap_window(c, window); 0231 xcb_flush(c); 0232 QTest::qWait(100); 0233 xcb_map_window(c, window); 0234 xcb_flush(c); 0235 0236 QCOMPARE(m_receivedCount, previousCount + 2); 0237 QCOMPARE(m_receivedId, id2); 0238 } 0239 0240 void KStartupInfo_UnitTest::checkStartupTest_data() 0241 { 0242 QTest::addColumn<QByteArray>("wmClass"); 0243 QTest::addColumn<int>("pid"); 0244 0245 QTest::newRow("wmClass") << QByteArrayLiteral("kstartupinfotest") << 0; 0246 QTest::newRow("pid") << QByteArray() << 12345; 0247 } 0248 0249 void KStartupInfo_UnitTest::checkStartupTest() 0250 { 0251 KStartupInfoId id; 0252 KStartupInfoId id2; 0253 id.initId(QByteArrayLiteral("somefancyidwhichisrandom_kstartupinfo_unittest_0")); 0254 id2.initId(QByteArrayLiteral("somefancyidwhichisrandom_kstartupinfo_unittest_1")); 0255 0256 KStartupInfoData data; 0257 data.setApplicationId(QStringLiteral("/dir with space/kstartupinfo_unittest.desktop")); 0258 data.setIcon(QStringLiteral("/dir with space/kstartupinfo_unittest.png")); 0259 data.setDescription(QStringLiteral("A description")); 0260 data.setName(QStringLiteral("A name")); 0261 data.setBin(QStringLiteral("dir with space/kstartupinfo_unittest")); 0262 QFETCH(int, pid); 0263 data.addPid(pid); 0264 data.setHostname(QByteArrayLiteral("localhost")); 0265 0266 // important for this test: WMClass 0267 QFETCH(QByteArray, wmClass); 0268 data.setWMClass(wmClass); 0269 0270 xcb_connection_t *c = QX11Info::connection(); 0271 xcb_window_t window = xcb_generate_id(c); 0272 uint32_t values[] = {XCB_EVENT_MASK_PROPERTY_CHANGE}; 0273 xcb_create_window(c, 0274 XCB_COPY_FROM_PARENT, 0275 window, 0276 QX11Info::appRootWindow(), 0277 0, 0278 0, 0279 100, 0280 100, 0281 0, 0282 XCB_COPY_FROM_PARENT, 0283 XCB_COPY_FROM_PARENT, 0284 XCB_CW_EVENT_MASK, 0285 values); 0286 0287 xcb_change_property(c, 0288 XCB_PROP_MODE_REPLACE, 0289 window, 0290 XCB_ATOM_WM_CLASS, 0291 XCB_ATOM_STRING, 0292 8, 0293 wmClass.length() * 2 + 1, 0294 "kstartupinfotest\0kstartupinfotest"); 0295 xcb_change_property(c, XCB_PROP_MODE_REPLACE, window, XCB_ATOM_WM_CLIENT_MACHINE, XCB_ATOM_STRING, 8, 9, "localhost"); 0296 NETWinInfo winInfo(QX11Info::connection(), window, QX11Info::appRootWindow(), NET::Properties(), NET::Properties2()); 0297 winInfo.setPid(pid); 0298 0299 KStartupInfo info(KStartupInfo::DisableKWinModule | KStartupInfo::AnnounceSilenceChanges, this); 0300 KStartupInfo::sendStartup(id, data); 0301 KStartupInfo::sendStartup(id2, data); 0302 0303 doSync(); 0304 QTest::qWait(100); 0305 0306 QCOMPARE(info.checkStartup(window), KStartupInfo::Match); 0307 QCOMPARE(info.checkStartup(window), KStartupInfo::Match); 0308 } 0309 0310 void KStartupInfo_UnitTest::createNewStartupIdTest() 0311 { 0312 const QByteArray &id = KStartupInfo::createNewStartupId(); 0313 QVERIFY(!id.isEmpty()); 0314 const int index = id.indexOf(QByteArrayLiteral("TIME")); 0315 QVERIFY(index != -1); 0316 const QByteArray time = id.mid(index + 4); 0317 QVERIFY(time.toULongLong() != 0u); 0318 } 0319 0320 void KStartupInfo_UnitTest::createNewStartupIdForTimestampTest() 0321 { 0322 const QByteArray &id = KStartupInfo::createNewStartupIdForTimestamp(5); 0323 QVERIFY(!id.isEmpty()); 0324 const int index = id.indexOf(QByteArrayLiteral("TIME")); 0325 QVERIFY(index != -1); 0326 QCOMPARE(id.mid(index + 4).toULongLong(), 5u); 0327 } 0328 0329 void KStartupInfo_UnitTest::setNewStartupIdTest() 0330 { 0331 #if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(5, 102) 0332 { 0333 QWindow window; 0334 const QByteArray str = "somefancyidwhichisrandom_kstartupinfo_unittest_2"; 0335 KStartupInfo::setNewStartupId(&window, str); 0336 QCOMPARE(KStartupInfo::startupId(), str); 0337 } 0338 #endif 0339 0340 #if KWINDOWSYSTEM_ENABLE_DEPRECATED_SINCE(5, 62) 0341 { 0342 QWidget widget; 0343 const QByteArray str = "somefancyidwhichisrandom_kstartupinfo_unittest_3"; 0344 KStartupInfo::setNewStartupId(&widget, str); // deprecated 0345 QCOMPARE(KStartupInfo::startupId(), str); 0346 } 0347 #endif 0348 } 0349 0350 QTEST_MAIN(KStartupInfo_UnitTest) 0351 0352 #include "kstartupinfo_unittest.moc"