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"