tst_QTcpSocket::connectToHostError - handle possible timeouts

... instead of failing the test. On Ubuntu 20.04 when calling
'connect' with 0.0.0.1 we get EINPROGRESS and nothing else,
since our own internal timer has 30 s. timeout, the event loop
in the test stops before this and no socket error detected yet.
Handle such situation without failing a test.

Fixes: QTBUG-88042
Change-Id: Id6add27fcf9bbbe5fbf83a193652edf08fbad8d6
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
bb10
Timur Pocheptsov 2020-11-16 19:23:53 +01:00
parent 289f909621
commit 4111d8e8e7
2 changed files with 31 additions and 9 deletions

View File

@ -2,7 +2,6 @@
windows
[connectToHostError]
windows-10 gcc developer-build
ubuntu-20.04
# QTBUG-66247
[delayedClose:WithSocks5Proxy]
windows-10 gcc developer-build

View File

@ -83,6 +83,10 @@
#include <memory>
#ifdef Q_OS_LINUX
#include "private/qnativesocketengine_p.h"
#endif // Q_OS_LINUX
#include "private/qhostinfo_p.h"
#include "../../../network-settings.h"
@ -2090,31 +2094,50 @@ void tst_QTcpSocket::nestedEventLoopInErrorSlot()
void tst_QTcpSocket::connectToHostError_data()
{
QTest::addColumn<QString>("host");
QTest::addColumn<int>("port");
QTest::addColumn<quint16>("port");
QTest::addColumn<QAbstractSocket::SocketError>("expectedError");
QTest::newRow("localhost no service") << QStringLiteral("localhost") << 31415 << QAbstractSocket::ConnectionRefusedError;
QTest::newRow("unreachable") << QStringLiteral("0.0.0.1") << 65000 << QAbstractSocket::NetworkError;
QTest::newRow("localhost no service") << QStringLiteral("localhost") << quint16(31415) << QAbstractSocket::ConnectionRefusedError;
QTest::newRow("unreachable") << QStringLiteral("0.0.0.1") << quint16(65000) << QAbstractSocket::NetworkError;
}
void tst_QTcpSocket::connectToHostError()
{
// We are aware of at least one OS in our CI, that would fail
// the test due to timeout - it's Ubuntu 20.04 and 'connect'
// to 0.0.0.1 there return EINPROGRESS, with no other error
// ever received, so only our own internal 30 s. timer can
// detect a connection timeout.
std::unique_ptr<QTcpSocket> socket(newSocket());
QAbstractSocket::SocketError error = QAbstractSocket::UnknownSocketError;
QFETCH(QString, host);
QFETCH(int, port);
QFETCH(const QString, host);
QFETCH(const quint16, port);
QFETCH(QAbstractSocket::SocketError, expectedError);
connect(socket.get(), &QAbstractSocket::errorOccurred, [&](QAbstractSocket::SocketError socketError){
QTestEventLoop eventLoop;
connect(socket.get(), &QAbstractSocket::errorOccurred, socket.get(),
[&](QAbstractSocket::SocketError socketError) {
error = socketError;
QTimer::singleShot(0, &eventLoop, [&]{eventLoop.exitLoop();});
});
socket->connectToHost(host, port); // no service running here, one suspects
QTRY_COMPARE_WITH_TIMEOUT(socket->state(), QTcpSocket::UnconnectedState, 7000);
socket->connectToHost(host, port);
eventLoop.enterLoopMSecs(7000);
if (eventLoop.timeout() && port == 65000) {
// Let's at least verify it's not in connected state:
QVERIFY(socket->state() != QAbstractSocket::ConnectedState);
QSKIP("Connection to unreachable host timed out, skipping the rest of the test");
}
QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
if (error != expectedError && error == QAbstractSocket::ConnectionRefusedError)
QEXPECT_FAIL("unreachable", "CI firewall interfers with this test", Continue);
QCOMPARE(error, expectedError);
}