Warning, file /plasma/kwin/autotests/test_client_machine.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 #include "testutils.h"
0010 // KWin
0011 #include "client_machine.h"
0012 #include "utils/xcbutils.h"
0013 // Qt
0014 #include <QApplication>
0015 #include <QtTest>
0016 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
0017 #include <private/qtx11extras_p.h>
0018 #else
0019 #include <QX11Info>
0020 #endif
0021 // xcb
0022 #include <xcb/xcb.h>
0023 // system
0024 #include <netdb.h>
0025 #include <sys/socket.h>
0026 #include <sys/types.h>
0027 #include <unistd.h>
0028 
0029 Q_LOGGING_CATEGORY(KWIN_CORE, "kwin_core")
0030 
0031 using namespace KWin;
0032 
0033 class TestClientMachine : public QObject
0034 {
0035     Q_OBJECT
0036 private Q_SLOTS:
0037     void initTestCase();
0038     void cleanupTestCase();
0039     void hostName_data();
0040     void hostName();
0041     void emptyHostName();
0042 
0043 private:
0044     void setClientMachineProperty(xcb_window_t window, const QString &hostname);
0045     QString m_hostName;
0046     QString m_fqdn;
0047 };
0048 
0049 void TestClientMachine::setClientMachineProperty(xcb_window_t window, const QString &hostname)
0050 {
0051     xcb_change_property(connection(), XCB_PROP_MODE_REPLACE, window,
0052                         XCB_ATOM_WM_CLIENT_MACHINE, XCB_ATOM_STRING, 8,
0053                         hostname.length(), hostname.toLocal8Bit().constData());
0054 }
0055 
0056 void TestClientMachine::initTestCase()
0057 {
0058 #ifdef HOST_NAME_MAX
0059     char hostnamebuf[HOST_NAME_MAX];
0060 #else
0061     char hostnamebuf[256];
0062 #endif
0063     if (gethostname(hostnamebuf, sizeof hostnamebuf) >= 0) {
0064         hostnamebuf[sizeof(hostnamebuf) - 1] = 0;
0065         m_hostName = hostnamebuf;
0066     }
0067     addrinfo *res;
0068     addrinfo addressHints;
0069     memset(&addressHints, 0, sizeof(addressHints));
0070     addressHints.ai_family = PF_UNSPEC;
0071     addressHints.ai_socktype = SOCK_STREAM;
0072     addressHints.ai_flags |= AI_CANONNAME;
0073     if (getaddrinfo(m_hostName.toLocal8Bit().constData(), nullptr, &addressHints, &res) == 0) {
0074         if (res->ai_canonname) {
0075             m_fqdn = QString::fromLocal8Bit(res->ai_canonname);
0076         }
0077     }
0078     freeaddrinfo(res);
0079 
0080     qApp->setProperty("x11RootWindow", QVariant::fromValue<quint32>(QX11Info::appRootWindow()));
0081     qApp->setProperty("x11Connection", QVariant::fromValue<void *>(QX11Info::connection()));
0082 }
0083 
0084 void TestClientMachine::cleanupTestCase()
0085 {
0086 }
0087 
0088 void TestClientMachine::hostName_data()
0089 {
0090     QTest::addColumn<QString>("hostName");
0091     QTest::addColumn<QString>("expectedHost");
0092     QTest::addColumn<bool>("local");
0093 
0094     QTest::newRow("empty") << QString() << QStringLiteral("localhost") << true;
0095     QTest::newRow("localhost") << QStringLiteral("localhost") << QStringLiteral("localhost") << true;
0096     QTest::newRow("hostname") << m_hostName << m_hostName << true;
0097     QTest::newRow("HOSTNAME") << m_hostName.toUpper() << m_hostName.toUpper() << true;
0098     QString cutted(m_hostName);
0099     cutted.remove(0, 1);
0100     QTest::newRow("ostname") << cutted << cutted << false;
0101     QString domain("random.name.not.exist.tld");
0102     QTest::newRow("domain") << domain << domain << false;
0103     QTest::newRow("fqdn") << m_fqdn << m_fqdn << true;
0104     QTest::newRow("FQDN") << m_fqdn.toUpper() << m_fqdn.toUpper() << true;
0105     cutted = m_fqdn;
0106     cutted.remove(0, 1);
0107     QTest::newRow("qdn") << cutted << cutted << false;
0108 }
0109 
0110 void TestClientMachine::hostName()
0111 {
0112     const QRect geometry(0, 0, 10, 10);
0113     const uint32_t values[] = {true};
0114     Xcb::Window window(geometry, XCB_WINDOW_CLASS_INPUT_ONLY, XCB_CW_OVERRIDE_REDIRECT, values);
0115     QFETCH(QString, hostName);
0116     QFETCH(bool, local);
0117     setClientMachineProperty(window, hostName);
0118 
0119     ClientMachine clientMachine;
0120     QSignalSpy spy(&clientMachine, &ClientMachine::localhostChanged);
0121     clientMachine.resolve(window, XCB_WINDOW_NONE);
0122     QTEST(clientMachine.hostName(), "expectedHost");
0123 
0124     int i = 0;
0125     while (clientMachine.isResolving() && i++ < 50) {
0126         // name is being resolved in an external thread, so let's wait a little bit
0127         QTest::qWait(250);
0128     }
0129 
0130     QCOMPARE(clientMachine.isLocal(), local);
0131     QCOMPARE(spy.isEmpty(), !local);
0132 }
0133 
0134 void TestClientMachine::emptyHostName()
0135 {
0136     const QRect geometry(0, 0, 10, 10);
0137     const uint32_t values[] = {true};
0138     Xcb::Window window(geometry, XCB_WINDOW_CLASS_INPUT_ONLY, XCB_CW_OVERRIDE_REDIRECT, values);
0139     ClientMachine clientMachine;
0140     QSignalSpy spy(&clientMachine, &ClientMachine::localhostChanged);
0141     clientMachine.resolve(window, XCB_WINDOW_NONE);
0142     QCOMPARE(clientMachine.hostName(), ClientMachine::localhost());
0143     QVERIFY(clientMachine.isLocal());
0144     // should be local
0145     QCOMPARE(spy.isEmpty(), false);
0146 }
0147 
0148 Q_CONSTRUCTOR_FUNCTION(forceXcb)
0149 QTEST_MAIN(TestClientMachine)
0150 #include "test_client_machine.moc"