tst_QDnsLookup: add the ability to specify an alternate default server

For people running this test who are burdened with a broken DNS server
and for whom the check added in the previous commit fails, skipping the
test.

Incidentally, this is useful for developing QDnsLookup itself, because
some otherwise-reasonable servers are known to fail for some queries.
For example, dnsmasq doesn't like queries of type ANY:

SKIP   : tst_QDnsLookup::lookup(any-a-single) Server refused or was unable to answer query; a-single type ANY: Server failure
SKIP   : tst_QDnsLookup::lookup(any-a-plus-aaaa) Server refused or was unable to answer query; a-plus-aaaa type ANY: Server failure
SKIP   : tst_QDnsLookup::lookup(any-multi) Server refused or was unable to answer query; multi type ANY: Server failure

Now I can get it to pass with QTEST_DNS_SERVER='[2001:4860:4860::8888]':

PASS   : tst_QDnsLookup::lookup(any-a-single)
PASS   : tst_QDnsLookup::lookup(any-a-plus-aaaa)
PASS   : tst_QDnsLookup::lookup(any-multi)

Note for the future: setting a non-default server may exercise different
code paths inside QDnsLookup, so this is not a replacement for having
proper DNS servers in the CI.

Fixes: QTBUG-129335
Change-Id: I81dcd4834972efa84c9ffffdd8aaafb68f20560b
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
(cherry picked from commit 10fea78bdcad2086c980fa1c1bbcd5bb543e4366)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Thiago Macieira 2024-09-28 09:49:51 -07:00 committed by Qt Cherry-pick Bot
parent 5ce4677f2e
commit c2df419edf

View File

@ -36,18 +36,21 @@ static const int Timeout = 15000; // 15s
class tst_QDnsLookup: public QObject class tst_QDnsLookup: public QObject
{ {
Q_OBJECT Q_OBJECT
public:
const QString normalDomain = u".test.qt-project.org"_s; const QString normalDomain = u".test.qt-project.org"_s;
const QString idnDomain = u".alqualondë.test.qt-project.org"_s; const QString idnDomain = u".alqualondë.test.qt-project.org"_s;
QHostAddress alternateDnsServer;
quint16 alternateDnsServerPort = 53;
bool usingIdnDomain = false; bool usingIdnDomain = false;
bool dnsServersMustWork = false; bool dnsServersMustWork = false;
private:
QString domainName(const QString &input); QString domainName(const QString &input);
QString domainNameList(const QString &input); QString domainNameList(const QString &input);
QStringList domainNameListAlternatives(const QString &input); QStringList domainNameListAlternatives(const QString &input);
std::unique_ptr<QDnsLookup> lookupCommon(QDnsLookup::Type type, const QString &domain, std::unique_ptr<QDnsLookup> lookupCommon(QDnsLookup::Type type, const QString &domain,
const QHostAddress &server = {}, quint16 port = 0, QHostAddress server = {}, quint16 port = 0,
QDnsLookup::Protocol protocol = QDnsLookup::Standard); QDnsLookup::Protocol protocol = QDnsLookup::Standard);
QStringList formatReply(const QDnsLookup *lookup) const; QStringList formatReply(const QDnsLookup *lookup) const;
@ -94,6 +97,12 @@ static QList<QHostAddress> systemNameservers(QDnsLookup::Protocol protocol)
QList<QHostAddress> result; QList<QHostAddress> result;
if (protocol != QDnsLookup::Standard) if (protocol != QDnsLookup::Standard)
return result; return result;
if (auto tst = static_cast<tst_QDnsLookup *>(QTest::testObject()); !tst->alternateDnsServer.isNull()) {
// if the user provided an alternate server, that's our "system"
if (tst->alternateDnsServerPort == 53)
result.emplaceBack(tst->alternateDnsServer);
return result;
}
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
ULONG infosize = 0; ULONG infosize = 0;
@ -249,6 +258,13 @@ void tst_QDnsLookup::initTestCase()
QNetworkProxyFactory::setUseSystemConfiguration(true); QNetworkProxyFactory::setUseSystemConfiguration(true);
#endif #endif
if (QString alternateDns = qEnvironmentVariable("QTEST_DNS_SERVER"); !alternateDns.isEmpty()) {
// use QUrl to parse host:port, so we get IPv6 too
QUrl u("dns://" + alternateDns);
alternateDnsServer = QHostAddress(u.host());
alternateDnsServerPort = u.port(alternateDnsServerPort);
}
#if QT_CONFIG(process) #if QT_CONFIG(process)
// make sure these match something in lookup_data() // make sure these match something in lookup_data()
QString checkedDomain = domainName(u"a-multi"_s); QString checkedDomain = domainName(u"a-multi"_s);
@ -299,9 +315,10 @@ void tst_QDnsLookup::initTestCase()
#endif #endif
; ;
}; };
if (!dnsServersMustWork && !dnsServerDoesWork()) { if (!dnsServersMustWork && alternateDnsServer.isNull() && !dnsServerDoesWork()) {
qWarning() << "Default DNS server in this system cannot correctly resolve" << checkedDomain; qWarning() << "Default DNS server in this system cannot correctly resolve" << checkedDomain;
qWarning() << "Please check if you are connected to the Internet."; qWarning() << "Please check if you are connected to the Internet or set the "
"QTEST_DNS_SERVER environment variable to a working server.";
qDebug("Output was:\n%s", output.constData()); qDebug("Output was:\n%s", output.constData());
QSKIP("DNS server does not appear to work"); QSKIP("DNS server does not appear to work");
} }
@ -346,9 +363,13 @@ QStringList tst_QDnsLookup::domainNameListAlternatives(const QString &input)
std::unique_ptr<QDnsLookup> std::unique_ptr<QDnsLookup>
tst_QDnsLookup::lookupCommon(QDnsLookup::Type type, const QString &domain, tst_QDnsLookup::lookupCommon(QDnsLookup::Type type, const QString &domain,
const QHostAddress &server, quint16 port, QHostAddress server, quint16 port,
QDnsLookup::Protocol protocol) QDnsLookup::Protocol protocol)
{ {
if (server.isNull()) {
server = alternateDnsServer;
port = alternateDnsServerPort;
}
auto lookup = std::make_unique<QDnsLookup>(type, domainName(domain), protocol, server, port); auto lookup = std::make_unique<QDnsLookup>(type, domainName(domain), protocol, server, port);
QObject::connect(lookup.get(), &QDnsLookup::finished, QObject::connect(lookup.get(), &QDnsLookup::finished,
&QTestEventLoop::instance(), &QTestEventLoop::exitLoop); &QTestEventLoop::instance(), &QTestEventLoop::exitLoop);