tst_QDnsLookup: check for DNS server sanity

Instead of failing tst_QDnsLookup and blaming the class for problems,
let's first verify that the resolver can resolve an address. If it can't
and we're not in the CI, then just skip the test.

I chose "a-multi" because a) it required the least variability in the
command-line and b) it has more than one RR in the RR set so it may find
more problems than "a-single".

Output when I forced a domain that doesn't exist:

QWARN  : tst_QDnsLookup::initTestCase() Default DNS server in this
system cannot correctly resolve "a-multix.test.qt-project.org"
QWARN  : tst_QDnsLookup::initTestCase() Please check if you are
connected to the Internet.
QDEBUG : tst_QDnsLookup::initTestCase() Output was:
Server:		127.0.0.53
Address:	127.0.0.53#53

** server can't find a-multix.test.qt-project.org: NXDOMAIN

SKIP   : tst_QDnsLookup::initTestCase() DNS server does not appear to
work

Task-number: QTBUG-129335
Change-Id: Id2dcc2ce7cfdd83c556ffffddb88a1f1b4339606
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
(cherry picked from commit 40986460e3f372cdb42ad80377455dc43b7cdb42)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Thiago Macieira 2024-09-28 09:14:35 -07:00 committed by Qt Cherry-pick Bot
parent ea871ee2e2
commit 5ce4677f2e

View File

@ -16,6 +16,9 @@
#if QT_CONFIG(networkproxy)
# include <QtNetwork/QNetworkProxyFactory>
#endif
#if QT_CONFIG(process)
# include <QtCore/QProcess>
#endif
#if QT_CONFIG(ssl)
# include <QtNetwork/QSslSocket>
#endif
@ -245,6 +248,64 @@ void tst_QDnsLookup::initTestCase()
// for DNS-over-TLS
QNetworkProxyFactory::setUseSystemConfiguration(true);
#endif
#if QT_CONFIG(process)
// make sure these match something in lookup_data()
QString checkedDomain = domainName(u"a-multi"_s);
static constexpr QByteArrayView expectedAddresses[] = {
"192.0.2.1", "192.0.2.2", "192.0.2.3"
};
QByteArray output;
auto dnsServerDoesWork = [&]() {
// check if the DNS server is too broken
QProcess nslookup;
#ifdef Q_OS_WIN
nslookup.setProcessChannelMode(QProcess::MergedChannels);
#else
nslookup.setProcessChannelMode(QProcess::ForwardedErrorChannel);
#endif
nslookup.start(u"nslookup"_s, { checkedDomain } );
if (!nslookup.waitForStarted()) {
// executable didn't start, we err on assuming the servers work
return true;
}
// if nslookup is running, then we must have the correct answers
if (!nslookup.waitForFinished(120'000)) {
qWarning() << "nslookup timed out";
return true;
}
output = nslookup.readAll();
bool ok = nslookup.exitCode() == 0;
if (ok)
ok = std::all_of(std::begin(expectedAddresses), std::end(expectedAddresses),
[&](QByteArrayView addr) { return output.contains(addr); });
if (!ok)
return false;
// check a domain that shouldn't exist
nslookup.setArguments({ domainName(u"invalid.invalid"_s) });
nslookup.start();
if (!nslookup.waitForFinished(120'000)) {
qWarning() << "nslookup timed out";
return true;
}
output = nslookup.readAll();
return nslookup.exitCode() != 0
#ifdef Q_OS_WIN
|| output.contains("Non-existent domain")
#endif
;
};
if (!dnsServersMustWork && !dnsServerDoesWork()) {
qWarning() << "Default DNS server in this system cannot correctly resolve" << checkedDomain;
qWarning() << "Please check if you are connected to the Internet.";
qDebug("Output was:\n%s", output.constData());
QSKIP("DNS server does not appear to work");
}
#endif
}
QString tst_QDnsLookup::domainName(const QString &input)