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