summaryrefslogtreecommitdiffstats
path: root/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp')
-rw-r--r--tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp396
1 files changed, 152 insertions, 244 deletions
diff --git a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp
index d907ea34aa..bd4bb7ef81 100644
--- a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp
+++ b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp
@@ -1,76 +1,52 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// When using WinSock2 on Windows, it's the first thing that can be included
// (except qglobal.h), or else you'll get tons of compile errors
#include <qglobal.h>
-// To prevent windows system header files from re-defining min/max
-#define NOMINMAX 1
-
#if defined(Q_OS_WIN)
# include <winsock2.h>
# include <ws2tcpip.h>
#endif
-#include <QTest>
-#include <QTestEventLoop>
-#include <QProcess>
+#include <qhostinfo.h>
+#include "private/qhostinfo_p.h"
+#include "private/qnativesocketengine_p.h"
+
#include <QCoreApplication>
#include <QDebug>
-#include <QTcpSocket>
#include <QTcpServer>
+#include <QTcpSocket>
+#include <QTest>
+#include <QTestEventLoop>
#include <private/qthread_p.h>
-#include <time.h>
+#include <sys/types.h>
+
#if defined(Q_OS_WIN)
-#include <windows.h>
+# include <qt_windows.h>
+# ifdef gai_strerror
+# undef gai_strerror
+# define gai_strerror gai_strerrorA
+# endif
#else
-#include <unistd.h>
-#include <signal.h>
-#endif
-
-#include <qhostinfo.h>
-#include "private/qhostinfo_p.h"
-
-#include <sys/types.h>
-#if defined(Q_OS_UNIX)
-# include <sys/socket.h>
# include <netdb.h>
+# include <sys/socket.h>
+# include <unistd.h>
+#endif
+#ifndef NI_MAXHOST
+# define NI_MAXHOST 1025
#endif
#include "../../../network-settings.h"
#define TEST_DOMAIN ".test.qt-project.org"
+using namespace std::chrono_literals;
class tst_QHostInfo : public QObject
{
@@ -109,15 +85,55 @@ private slots:
void cache();
void abortHostLookup();
-protected slots:
- void resultsReady(const QHostInfo &);
private:
bool ipv6LookupsAvailable;
bool ipv6Available;
- bool lookupDone;
- int lookupsDoneCounter;
+};
+
+class tst_QHostInfo_Helper : public QObject
+{
+ Q_OBJECT
+protected slots:
+ void resultsReady(const QHostInfo &);
+public:
+ tst_QHostInfo_Helper(const QString &hostname)
+ : hostname(hostname)
+ {}
+
+ QString hostname;
+ bool lookupDone = false;
+ int lookupsDoneCounter = 0;
QHostInfo lookupResults;
+
+ void blockingLookup()
+ {
+ lookupResults = QHostInfo::fromName(hostname);
+ lookupDone = true;
+ ++lookupsDoneCounter;
+ }
+ void lookupHostOldStyle()
+ {
+ QHostInfo::lookupHost(hostname, this, SLOT(resultsReady(QHostInfo)));
+ }
+ void lookupHostNewStyle()
+ {
+ QHostInfo::lookupHost(hostname, this, &tst_QHostInfo_Helper::resultsReady);
+ }
+ void lookupHostLambda()
+ {
+ QHostInfo::lookupHost(hostname, this, [this](const QHostInfo &hostInfo) {
+ resultsReady(hostInfo);
+ });
+ }
+
+ bool waitForResults(std::chrono::milliseconds timeout = 15s)
+ {
+ QTestEventLoop::instance().enterLoop(timeout);
+ return !QTestEventLoop::instance().timeout() && lookupDone;
+ }
+
+ void checkResults(QHostInfo::HostInfoError err, const QString &addresses);
};
void tst_QHostInfo::swapFunction()
@@ -233,26 +249,15 @@ void tst_QHostInfo::lookupIPv4_data()
QTest::newRow("idn-unicode") << QString::fromLatin1("a-single.alqualond\353" TEST_DOMAIN) << "192.0.2.1" << int(QHostInfo::NoError);
}
-void tst_QHostInfo::lookupIPv4()
+void tst_QHostInfo_Helper::checkResults(QHostInfo::HostInfoError err, const QString &addresses)
{
- QFETCH(QString, hostname);
- QFETCH(int, err);
- QFETCH(QString, addresses);
-
- lookupDone = false;
- QHostInfo::lookupHost(hostname, this, SLOT(resultsReady(QHostInfo)));
-
- QTestEventLoop::instance().enterLoop(10);
- QVERIFY(!QTestEventLoop::instance().timeout());
- QVERIFY(lookupDone);
-
if ((int)lookupResults.error() != (int)err) {
qWarning() << hostname << "=>" << lookupResults.errorString();
}
- QCOMPARE((int)lookupResults.error(), (int)err);
+ QCOMPARE(lookupResults.error(), err);
QStringList tmp;
- for (int i = 0; i < lookupResults.addresses().count(); ++i)
+ for (int i = 0; i < lookupResults.addresses().size(); ++i)
tmp.append(lookupResults.addresses().at(i).toString());
tmp.sort();
@@ -262,6 +267,18 @@ void tst_QHostInfo::lookupIPv4()
QCOMPARE(tmp.join(' '), expected.join(' '));
}
+void tst_QHostInfo::lookupIPv4()
+{
+ QFETCH(QString, hostname);
+ QFETCH(int, err);
+ QFETCH(QString, addresses);
+
+ tst_QHostInfo_Helper helper(hostname);
+ helper.lookupHostOldStyle();
+ QVERIFY(helper.waitForResults());
+ helper.checkResults(QHostInfo::HostInfoError(err), addresses);
+}
+
void tst_QHostInfo::lookupIPv6_data()
{
QTest::addColumn<QString>("hostname");
@@ -287,24 +304,10 @@ void tst_QHostInfo::lookupIPv6()
if (!ipv6LookupsAvailable)
QSKIP("This platform does not support IPv6 lookups");
- lookupDone = false;
- QHostInfo::lookupHost(hostname, this, SLOT(resultsReady(QHostInfo)));
-
- QTestEventLoop::instance().enterLoop(10);
- QVERIFY(!QTestEventLoop::instance().timeout());
- QVERIFY(lookupDone);
-
- QCOMPARE((int)lookupResults.error(), (int)err);
-
- QStringList tmp;
- for (int i = 0; i < lookupResults.addresses().count(); ++i)
- tmp.append(lookupResults.addresses().at(i).toString());
- tmp.sort();
-
- QStringList expected = addresses.split(' ');
- expected.sort();
-
- QCOMPARE(tmp.join(' ').toLower(), expected.join(' ').toLower());
+ tst_QHostInfo_Helper helper(hostname);
+ helper.lookupHostOldStyle();
+ QVERIFY(helper.waitForResults());
+ helper.checkResults(QHostInfo::HostInfoError(err), addresses);
}
void tst_QHostInfo::lookupConnectToFunctionPointer_data()
@@ -318,26 +321,10 @@ void tst_QHostInfo::lookupConnectToFunctionPointer()
QFETCH(int, err);
QFETCH(QString, addresses);
- lookupDone = false;
- QHostInfo::lookupHost(hostname, this, &tst_QHostInfo::resultsReady);
-
- QTestEventLoop::instance().enterLoop(10);
- QVERIFY(!QTestEventLoop::instance().timeout());
- QVERIFY(lookupDone);
-
- if (int(lookupResults.error()) != int(err))
- qWarning() << hostname << "=>" << lookupResults.errorString();
- QCOMPARE(int(lookupResults.error()), int(err));
-
- QStringList tmp;
- for (const auto &result : lookupResults.addresses())
- tmp.append(result.toString());
- tmp.sort();
-
- QStringList expected = addresses.split(' ');
- expected.sort();
-
- QCOMPARE(tmp.join(' '), expected.join(' '));
+ tst_QHostInfo_Helper helper(hostname);
+ helper.lookupHostNewStyle();
+ QVERIFY(helper.waitForResults());
+ helper.checkResults(QHostInfo::HostInfoError(err), addresses);
}
void tst_QHostInfo::lookupConnectToFunctionPointerDeleted()
@@ -362,89 +349,38 @@ void tst_QHostInfo::lookupConnectToLambda()
QFETCH(int, err);
QFETCH(QString, addresses);
- lookupDone = false;
- QHostInfo::lookupHost(hostname, [this](const QHostInfo &hostInfo) {
- resultsReady(hostInfo);
- });
-
- QTestEventLoop::instance().enterLoop(10);
- QVERIFY(!QTestEventLoop::instance().timeout());
- QVERIFY(lookupDone);
-
- if (int(lookupResults.error()) != int(err))
- qWarning() << hostname << "=>" << lookupResults.errorString();
- QCOMPARE(int(lookupResults.error()), int(err));
-
- QStringList tmp;
- for (int i = 0; i < lookupResults.addresses().count(); ++i)
- tmp.append(lookupResults.addresses().at(i).toString());
- tmp.sort();
-
- QStringList expected = addresses.split(' ');
- expected.sort();
-
- QCOMPARE(tmp.join(' '), expected.join(' '));
+ tst_QHostInfo_Helper helper(hostname);
+ helper.lookupHostLambda();
+ QVERIFY(helper.waitForResults());
+ helper.checkResults(QHostInfo::HostInfoError(err), addresses);
}
static QStringList reverseLookupHelper(const QString &ip)
{
QStringList results;
-
- const QString pythonCode =
- "import socket;"
- "import sys;"
- "print (socket.getnameinfo((sys.argv[1], 0), 0)[0]);";
-
- QList<QByteArray> lines;
- QProcess python;
- python.setProcessChannelMode(QProcess::ForwardedErrorChannel);
- python.start("python", QStringList() << QString("-c") << pythonCode << ip);
- if (python.waitForFinished()) {
- if (python.exitStatus() == QProcess::NormalExit && python.exitCode() == 0)
- lines = python.readAllStandardOutput().split('\n');
- for (QByteArray line : lines) {
- if (!line.isEmpty())
- results << line.trimmed();
- }
- if (!results.isEmpty())
- return results;
- }
-
- qDebug() << "Python failed, falling back to nslookup";
- QProcess lookup;
- lookup.setProcessChannelMode(QProcess::ForwardedErrorChannel);
- lookup.start("nslookup", QStringList(ip));
- if (!lookup.waitForFinished()) {
- results << "nslookup failure";
- qDebug() << "nslookup failure";
+ union qt_sockaddr {
+ sockaddr a;
+ sockaddr_in a4;
+ sockaddr_in6 a6;
+ } sa = {};
+
+ QHostAddress addr(ip);
+ if (addr.isNull()) {
+ qWarning("Could not parse IP address: %ls", qUtf16Printable(ip));
return results;
}
- lines = lookup.readAllStandardOutput().split('\n');
-
- QByteArray name;
-
- const QByteArray nameMarkerNix("name =");
- const QByteArray nameMarkerWin("Name:");
- const QByteArray addressMarkerWin("Address:");
-
- for (QByteArray line : lines) {
- int index = -1;
- if ((index = line.indexOf(nameMarkerNix)) != -1) { // Linux and macOS
- name = line.mid(index + nameMarkerNix.length()).chopped(1).trimmed();
- results << name;
- } else if (line.startsWith(nameMarkerWin)) { // Windows formatting
- name = line.mid(line.lastIndexOf(" ")).trimmed();
- } else if (line.startsWith(addressMarkerWin)) {
- QByteArray address = line.mid(addressMarkerWin.length()).trimmed();
- if (address == ip.toUtf8()) {
- results << name;
- }
- }
- }
- if (results.isEmpty()) {
- qDebug() << "Failure to parse nslookup output: " << lines;
+ // from qnativesocketengine_p.h:
+ QT_SOCKLEN_T len = setSockaddr(&sa.a, addr, /*port = */ 0);
+
+ QByteArray name(NI_MAXHOST, Qt::Uninitialized);
+ int ni_flags = NI_NAMEREQD | NI_NUMERICSERV;
+ if (int r = getnameinfo(&sa.a, len, name.data(), name.size(), nullptr, 0, ni_flags)) {
+ qWarning("Failed to reverse look up '%ls': %s", qUtf16Printable(ip), gai_strerror(r));
+ } else {
+ results << QString::fromLatin1(name, qstrnlen(name, name.size()));
}
+
return results;
}
@@ -457,8 +393,10 @@ void tst_QHostInfo::reverseLookup_data()
QTest::newRow("dns.google") << QString("8.8.8.8") << reverseLookupHelper("8.8.8.8") << 0 << false;
QTest::newRow("one.one.one.one") << QString("1.1.1.1") << reverseLookupHelper("1.1.1.1") << 0 << false;
- QTest::newRow("dns.google IPv6") << QString("2001:4860:4860::8888") << reverseLookupHelper("2001:4860:4860::8888") << 0 << true;
- QTest::newRow("cloudflare IPv6") << QString("2606:4700:4700::1111") << reverseLookupHelper("2606:4700:4700::1111") << 0 << true;
+ if (QStringList hostNames = reverseLookupHelper("2001:4860:4860::8888"); !hostNames.isEmpty())
+ QTest::newRow("dns.google IPv6") << QString("2001:4860:4860::8888") << std::move(hostNames) << 0 << true;
+ if (QStringList hostNames = reverseLookupHelper("2606:4700:4700::1111"); !hostNames.isEmpty())
+ QTest::newRow("cloudflare IPv6") << QString("2606:4700:4700::1111") << std::move(hostNames) << 0 << true;
QTest::newRow("bogus-name IPv6") << QString("1::2::3::4") << QStringList() << 1 << true;
}
@@ -467,11 +405,6 @@ void tst_QHostInfo::reverseLookup()
QFETCH(QString, address);
QFETCH(QStringList, hostNames);
QFETCH(int, err);
- QFETCH(bool, ipv6);
-
- if (ipv6 && !ipv6LookupsAvailable) {
- QSKIP("IPv6 reverse lookups are not supported on this platform");
- }
QHostInfo info = QHostInfo::fromName(address);
@@ -479,7 +412,7 @@ void tst_QHostInfo::reverseLookup()
if (!hostNames.contains(info.hostName()))
qDebug() << "Failure: expecting" << hostNames << ",got " << info.hostName();
QVERIFY(hostNames.contains(info.hostName()));
- QCOMPARE(info.addresses().first(), QHostAddress(address));
+ QCOMPARE(info.addresses().constFirst(), QHostAddress(address));
} else {
QCOMPARE(info.hostName(), address);
QCOMPARE(info.error(), QHostInfo::HostNotFound);
@@ -500,21 +433,9 @@ void tst_QHostInfo::blockingLookup()
QFETCH(int, err);
QFETCH(QString, addresses);
- QHostInfo hostInfo = QHostInfo::fromName(hostname);
- QStringList tmp;
- for (int i = 0; i < hostInfo.addresses().count(); ++i)
- tmp.append(hostInfo.addresses().at(i).toString());
- tmp.sort();
-
- if ((int)hostInfo.error() != (int)err) {
- qWarning() << hostname << "=>" << lookupResults.errorString();
- }
- QCOMPARE((int)hostInfo.error(), (int)err);
-
- QStringList expected = addresses.split(' ');
- expected.sort();
-
- QCOMPARE(tmp.join(' ').toUpper(), expected.join(' ').toUpper());
+ tst_QHostInfo_Helper helper(hostname);
+ helper.blockingLookup();
+ helper.checkResults(QHostInfo::HostInfoError(err), addresses);
}
void tst_QHostInfo::raceCondition()
@@ -531,8 +452,9 @@ protected:
inline void run() override
{
QHostInfo info = QHostInfo::fromName("a-single" TEST_DOMAIN);
+ QCOMPARE(info.errorString(), "Unknown error"); // no error
QCOMPARE(info.error(), QHostInfo::NoError);
- QVERIFY(info.addresses().count() > 0);
+ QVERIFY(info.addresses().size() > 0);
QCOMPARE(info.addresses().at(0).toString(), QString("192.0.2.1"));
}
};
@@ -579,24 +501,22 @@ void tst_QHostInfo::threadSafetyAsynchronousAPI()
{
const int nattempts = 10;
const int lookupsperthread = 10;
- QList<QThread*> threads;
- QList<LookupReceiver*> receivers;
+ QThread threads[nattempts];
+ LookupReceiver receivers[nattempts];
for (int i = 0; i < nattempts; ++i) {
- QThread* thread = new QThread;
- LookupReceiver* receiver = new LookupReceiver;
+ QThread *thread = &threads[i];
+ LookupReceiver *receiver = &receivers[i];
receiver->numrequests = lookupsperthread;
- receivers.append(receiver);
receiver->moveToThread(thread);
connect(thread, SIGNAL(started()), receiver, SLOT(start()));
thread->start();
- threads.append(thread);
}
- for (int k = threads.count() - 1; k >= 0; --k)
- QVERIFY(threads.at(k)->wait(60000));
- foreach (LookupReceiver* receiver, receivers) {
- QCOMPARE(receiver->result.error(), QHostInfo::NoError);
- QCOMPARE(receiver->result.addresses().at(0).toString(), QString("192.0.2.1"));
- QCOMPARE(receiver->numrequests, 0);
+ for (int k = nattempts - 1; k >= 0; --k)
+ QVERIFY(threads[k].wait(60000));
+ for (LookupReceiver &receiver : receivers) {
+ QCOMPARE(receiver.result.error(), QHostInfo::NoError);
+ QCOMPARE(receiver.result.addresses().at(0).toString(), QString("192.0.2.1"));
+ QCOMPARE(receiver.numrequests, 0);
}
}
@@ -605,17 +525,11 @@ void tst_QHostInfo::threadSafetyAsynchronousAPI()
void tst_QHostInfo::multipleSameLookups()
{
const int COUNT = 10;
- lookupsDoneCounter = 0;
-
+ tst_QHostInfo_Helper helper("localhost");
for (int i = 0; i < COUNT; i++)
- QHostInfo::lookupHost("localhost", this, SLOT(resultsReady(QHostInfo)));
+ helper.lookupHostOldStyle();
- QElapsedTimer timer;
- timer.start();
- while (timer.elapsed() < 10000 && lookupsDoneCounter < COUNT) {
- QTestEventLoop::instance().enterLoop(2);
- }
- QCOMPARE(lookupsDoneCounter, COUNT);
+ QTRY_COMPARE_WITH_TIMEOUT(helper.lookupsDoneCounter, COUNT, 10s);
}
// this test is for the multi-threaded QHostInfo rewrite. It is about getting results at all,
@@ -644,19 +558,15 @@ void tst_QHostInfo::multipleDifferentLookups()
QFETCH(int, repeats);
const int COUNT = hostnameList.size();
- lookupsDoneCounter = 0;
+ tst_QHostInfo_Helper helper(QString{});
for (int i = 0; i < hostnameList.size(); i++)
- for (int j = 0; j < repeats; ++j)
- QHostInfo::lookupHost(hostnameList.at(i), this, SLOT(resultsReady(QHostInfo)));
-
- QElapsedTimer timer;
- timer.start();
- while (timer.elapsed() < 60000 && lookupsDoneCounter < repeats*COUNT) {
- QTestEventLoop::instance().enterLoop(2);
- //qDebug() << "t:" << timer.elapsed();
- }
- QCOMPARE(lookupsDoneCounter, repeats*COUNT);
+ for (int j = 0; j < repeats; ++j) {
+ helper.hostname = hostnameList.at(i);
+ helper.lookupHostOldStyle();
+ }
+
+ QTRY_COMPARE_WITH_TIMEOUT(helper.lookupsDoneCounter, repeats*COUNT, 60s);
}
void tst_QHostInfo::cache()
@@ -665,13 +575,12 @@ void tst_QHostInfo::cache()
if (!cache)
return; // test makes only sense when cache enabled
- // reset slot counter
- lookupsDoneCounter = 0;
+ tst_QHostInfo_Helper helper("localhost");
// lookup once, wait in event loop, result should not come directly.
bool valid = true;
int id = -1;
- QHostInfo result = qt_qhostinfo_lookup("localhost", this, SLOT(resultsReady(QHostInfo)), &valid, &id);
+ QHostInfo result = qt_qhostinfo_lookup(helper.hostname, &helper, SLOT(resultsReady(QHostInfo)), &valid, &id);
QTestEventLoop::instance().enterLoop(5);
QVERIFY(!QTestEventLoop::instance().timeout());
QVERIFY(!valid);
@@ -679,7 +588,7 @@ void tst_QHostInfo::cache()
// loopkup second time, result should come directly
valid = false;
- result = qt_qhostinfo_lookup("localhost", this, SLOT(resultsReady(QHostInfo)), &valid, &id);
+ result = qt_qhostinfo_lookup(helper.hostname, &helper, SLOT(resultsReady(QHostInfo)), &valid, &id);
QVERIFY(valid);
QVERIFY(!result.addresses().isEmpty());
@@ -688,17 +597,17 @@ void tst_QHostInfo::cache()
// lookup third time, result should not come directly.
valid = true;
- result = qt_qhostinfo_lookup("localhost", this, SLOT(resultsReady(QHostInfo)), &valid, &id);
+ result = qt_qhostinfo_lookup(helper.hostname, &helper, SLOT(resultsReady(QHostInfo)), &valid, &id);
QTestEventLoop::instance().enterLoop(5);
QVERIFY(!QTestEventLoop::instance().timeout());
QVERIFY(!valid);
QVERIFY(result.addresses().isEmpty());
// the slot should have been called 2 times.
- QCOMPARE(lookupsDoneCounter, 2);
+ QCOMPARE(helper.lookupsDoneCounter, 2);
}
-void tst_QHostInfo::resultsReady(const QHostInfo &hi)
+void tst_QHostInfo_Helper::resultsReady(const QHostInfo &hi)
{
QVERIFY(QThread::currentThread() == thread());
lookupDone = true;
@@ -709,16 +618,15 @@ void tst_QHostInfo::resultsReady(const QHostInfo &hi)
void tst_QHostInfo::abortHostLookup()
{
- //reset counter
- lookupsDoneCounter = 0;
+ tst_QHostInfo_Helper helper("a-single" TEST_DOMAIN);
bool valid = false;
int id = -1;
- QHostInfo result = qt_qhostinfo_lookup("a-single" TEST_DOMAIN, this, SLOT(resultsReady(QHostInfo)), &valid, &id);
+ QHostInfo result = qt_qhostinfo_lookup(helper.hostname, &helper, SLOT(resultsReady(QHostInfo)), &valid, &id);
QVERIFY(!valid);
//it is assumed that the DNS request/response in the backend is slower than it takes to call abort
QHostInfo::abortHostLookup(id);
QTestEventLoop::instance().enterLoop(5);
- QCOMPARE(lookupsDoneCounter, 0);
+ QCOMPARE(helper.lookupsDoneCounter, 0);
}
class LookupAborter : public QObject