File indexing completed on 2024-04-14 05:21:16
0001 /* 0002 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 // own 0007 #include "../ksldapp.h" 0008 // KDE Frameworks 0009 #include <KIdleTime> 0010 // Qt 0011 #include <QProcess> 0012 #include <private/qtx11extras_p.h> 0013 #include <QSignalSpy> 0014 #include <QTest> 0015 // xcb 0016 #include <xcb/xcb.h> 0017 #include <xcb/xtest.h> 0018 0019 class KSldTest : public QObject 0020 { 0021 Q_OBJECT 0022 private Q_SLOTS: 0023 void initTestCase(); 0024 void testEstablishGrab(); 0025 void testActivateOnTimeout(); 0026 void testGraceTimeUnlocking(); 0027 }; 0028 0029 void KSldTest::initTestCase() 0030 { 0031 QCoreApplication::setAttribute(Qt::AA_ForceRasterWidgets); 0032 // change to the build bin dir 0033 QDir::setCurrent(QCoreApplication::applicationDirPath()); 0034 } 0035 0036 void KSldTest::testEstablishGrab() 0037 { 0038 ScreenLocker::KSldApp ksld; 0039 ksld.initialize(); 0040 QVERIFY(ksld.establishGrab()); 0041 // grab is established, trying again should succeed as well 0042 QVERIFY(ksld.establishGrab()); 0043 0044 // let's ungrab 0045 ksld.doUnlock(); 0046 0047 // to get the grab to fail we need another X client 0048 // we start another process to perform our grab 0049 QProcess keyboardGrabber; 0050 keyboardGrabber.start(QStringLiteral("./keyboardGrabber"), QStringList()); 0051 QVERIFY(keyboardGrabber.waitForStarted()); 0052 0053 // let's add some delay to be sure that keyboardGrabber has it's X stuff done 0054 QTest::qWait(100); 0055 0056 // now grabbing should fail 0057 QVERIFY(!ksld.establishGrab()); 0058 0059 // let's terminate again 0060 keyboardGrabber.terminate(); 0061 QVERIFY(keyboardGrabber.waitForFinished()); 0062 0063 // now grabbing should succeed again 0064 QVERIFY(ksld.establishGrab()); 0065 0066 ksld.doUnlock(); 0067 0068 // now the same with pointer 0069 QProcess pointerGrabber; 0070 pointerGrabber.start(QStringLiteral("./pointerGrabber"), QStringList()); 0071 QVERIFY(pointerGrabber.waitForStarted()); 0072 0073 // let's add some delay to be sure that pointerGrabber has it's X stuff done 0074 QTest::qWait(100); 0075 0076 // now grabbing should fail 0077 QVERIFY(!ksld.establishGrab()); 0078 0079 // let's terminate again 0080 pointerGrabber.terminate(); 0081 QVERIFY(pointerGrabber.waitForFinished()); 0082 0083 // now grabbing should succeed again 0084 QVERIFY(ksld.establishGrab()); 0085 } 0086 0087 void KSldTest::testActivateOnTimeout() 0088 { 0089 // this time verifies that the screen gets locked on idle timeout, requires the system to be idle 0090 ScreenLocker::KSldApp ksld; 0091 ksld.initialize(); 0092 0093 // we need to modify the idle timeout of KSLD, it's in minutes we cannot wait that long 0094 if (ksld.idleId() != 0) { 0095 // remove old Idle id 0096 KIdleTime::instance()->removeIdleTimeout(ksld.idleId()); 0097 } 0098 ksld.setIdleId(KIdleTime::instance()->addIdleTimeout(5000)); 0099 0100 QSignalSpy lockStateChangedSpy(&ksld, &ScreenLocker::KSldApp::lockStateChanged); 0101 QVERIFY(lockStateChangedSpy.isValid()); 0102 0103 // let's wait the double of the idle timeout 0104 QVERIFY(lockStateChangedSpy.wait(10000)); 0105 QCOMPARE(ksld.lockState(), ScreenLocker::KSldApp::AcquiringLock); 0106 0107 // let's simulate unlock to get rid of started greeter process 0108 const auto children = ksld.children(); 0109 for (auto it = children.begin(); it != children.end(); ++it) { 0110 if (qstrcmp((*it)->metaObject()->className(), "LogindIntegration") != 0) { 0111 continue; 0112 } 0113 QMetaObject::invokeMethod(*it, "requestUnlock"); 0114 break; 0115 } 0116 QVERIFY(lockStateChangedSpy.wait()); 0117 0118 KIdleTime::instance()->removeIdleTimeout(ksld.idleId()); 0119 } 0120 0121 void KSldTest::testGraceTimeUnlocking() 0122 { 0123 // this time verifies that the screen gets unlocked during grace time by simulated user activity 0124 ScreenLocker::KSldApp ksld(this); 0125 ksld.initialize(); 0126 0127 // we need to modify the idle timeout of KSLD, it's in minutes we cannot wait that long 0128 if (ksld.idleId() != 0) { 0129 // remove old Idle id 0130 KIdleTime::instance()->removeIdleTimeout(ksld.idleId()); 0131 } 0132 ksld.setIdleId(KIdleTime::instance()->addIdleTimeout(5000)); 0133 // infinite 0134 ksld.setGraceTime(-1); 0135 0136 QSignalSpy lockedSpy(&ksld, &ScreenLocker::KSldApp::locked); 0137 QVERIFY(lockedSpy.isValid()); 0138 QSignalSpy unlockedSpy(&ksld, &ScreenLocker::KSldApp::unlocked); 0139 QVERIFY(unlockedSpy.isValid()); 0140 0141 // let's wait quite some time to give the greeter a chance to come up 0142 QVERIFY(lockedSpy.wait(30000)); 0143 QCOMPARE(ksld.lockState(), ScreenLocker::KSldApp::Locked); 0144 0145 // let's simulate unlock by faking input 0146 const QPoint cursorPos = QCursor::pos(); 0147 xcb_test_fake_input(QX11Info::connection(), XCB_MOTION_NOTIFY, 0, XCB_TIME_CURRENT_TIME, XCB_WINDOW_NONE, cursorPos.x() + 1, cursorPos.y() + 1, 0); 0148 xcb_flush(QX11Info::connection()); 0149 QVERIFY(unlockedSpy.wait()); 0150 0151 // now let's test again without grace time 0152 ksld.setGraceTime(0); 0153 QVERIFY(lockedSpy.wait(30000)); 0154 QCOMPARE(ksld.lockState(), ScreenLocker::KSldApp::Locked); 0155 0156 xcb_test_fake_input(QX11Info::connection(), XCB_MOTION_NOTIFY, 0, XCB_TIME_CURRENT_TIME, XCB_WINDOW_NONE, cursorPos.x(), cursorPos.y(), 0); 0157 xcb_flush(QX11Info::connection()); 0158 QVERIFY(!unlockedSpy.wait()); 0159 0160 // and unlock 0161 const auto children = ksld.children(); 0162 for (auto it = children.begin(); it != children.end(); ++it) { 0163 if (qstrcmp((*it)->metaObject()->className(), "LogindIntegration") != 0) { 0164 continue; 0165 } 0166 QMetaObject::invokeMethod(*it, "requestUnlock"); 0167 break; 0168 } 0169 QVERIFY(unlockedSpy.wait()); 0170 } 0171 0172 QTEST_MAIN(KSldTest) 0173 #include "ksldtest.moc"