diff options
Diffstat (limited to 'tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp')
-rw-r--r-- | tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp | 176 |
1 files changed, 122 insertions, 54 deletions
diff --git a/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp b/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp index 4759ac292a..c03076d98e 100644 --- a/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp +++ b/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp @@ -1,34 +1,7 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** 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. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <qglobal.h> -// To prevent windows system header files from re-defining min/max -#define NOMINMAX 1 #if defined(_WIN32) #include <winsock2.h> #else @@ -60,6 +33,8 @@ #include <qnetworkinterface.h> #include <QNetworkProxy> +#include <QSet> +#include <QList> #include "../../../network-settings.h" @@ -117,6 +92,9 @@ private slots: void pauseAccepting(); + void pendingConnectionAvailable_data(); + void pendingConnectionAvailable(); + private: bool shouldSkipIpv6TestsForBrokenGetsockopt(); #ifdef SHOULD_CHECK_SYSCALL_SUPPORT @@ -160,7 +138,8 @@ void tst_QTcpServer::initTestCase() #ifdef QT_TEST_SERVER QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1080)); QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3128)); - QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::ftpProxyServerName(), 2121)); + // FTP currently not supported: + // QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::ftpProxyServerName(), 2121)); QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::imapServerName(), 143)); #else if (!QtNetworkSettings::verifyTestNetworkSettings()) @@ -268,7 +247,7 @@ void tst_QTcpServer::clientServerLoop() QVERIFY(server.waitForNewConnection(5000)); QVERIFY(server.hasPendingConnections()); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QTcpSocket *serverSocket = server.nextPendingConnection(); QVERIFY(serverSocket != 0); @@ -429,9 +408,9 @@ void tst_QTcpServer::maxPendingConnections() // two connections have been made. The second compare makes sure no // more are accepted. Creating connections happens multithreaded so // qWait must be used for that. - QTRY_COMPARE(spy.count(), 2); + QTRY_COMPARE(spy.size(), 2); QTest::qWait(100); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); QVERIFY(server.hasPendingConnections()); QVERIFY(server.nextPendingConnection()); @@ -480,7 +459,7 @@ public: protected: void run() override { - sleep(2); + sleep(std::chrono::seconds{2}); QTcpSocket socket; socket.connectToHost(host, port); @@ -598,9 +577,6 @@ void tst_QTcpServer::addressReusable() #if !QT_CONFIG(process) QSKIP("No qprocess support", SkipAll); #else -#ifdef Q_OS_LINUX - QSKIP("The addressReusable test is unstable on Linux. See QTBUG-39985."); -#endif QFETCH_GLOBAL(bool, setProxy); if (setProxy) { #ifndef QT_NO_NETWORKPROXY @@ -611,16 +587,25 @@ void tst_QTcpServer::addressReusable() QSKIP("No proxy support"); #endif // QT_NO_NETWORKPROXY } + + QTcpServer server; + QVERIFY(server.listen(QHostAddress::LocalHost, 0)); + quint16 serverPort = server.serverPort(); + qDebug() << "Got port" << serverPort; + server.close(); // cleanly close + + QTest::qSleep(10); + // The crashingServer process will crash once it gets a connection. QProcess process; QString processExe = crashingServerDir + "/crashingServer"; - process.start(processExe); + process.start(processExe, { QString::number(serverPort) }); QVERIFY2(process.waitForStarted(), qPrintable( QString::fromLatin1("Could not start %1: %2").arg(processExe, process.errorString()))); - QVERIFY(process.waitForReadyRead(5000)); + QVERIFY2(process.waitForReadyRead(5000), qPrintable(process.readAllStandardError())); QTcpSocket socket; - socket.connectToHost(QHostAddress::LocalHost, 49199); + socket.connectToHost(QHostAddress::LocalHost, serverPort); QVERIFY(socket.waitForConnected(5000)); QVERIFY(process.waitForFinished(30000)); @@ -628,8 +613,9 @@ void tst_QTcpServer::addressReusable() // Give the system some time. QTest::qSleep(10); - QTcpServer server; - QVERIFY(server.listen(QHostAddress::LocalHost, 49199)); + // listen again + QVERIFY2(server.listen(QHostAddress::LocalHost, serverPort), + qPrintable(server.errorString())); #endif } @@ -748,6 +734,7 @@ void tst_QTcpServer::proxyFactory_data() << proxyList << proxyList.at(1) << false << int(QAbstractSocket::UnknownSocketError); +#if 0 // ftp not currently supported proxyList.clear(); proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121) << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3128) @@ -755,6 +742,7 @@ void tst_QTcpServer::proxyFactory_data() QTest::newRow("ftp+cachinghttp+socks5") << proxyList << proxyList.at(2) << false << int(QAbstractSocket::UnknownSocketError); +#endif // tests that fail to listen proxyList.clear(); @@ -769,6 +757,7 @@ void tst_QTcpServer::proxyFactory_data() << proxyList << QNetworkProxy() << true << int(QAbstractSocket::UnsupportedSocketOperationError); +#if 0 // ftp not currently supported proxyList.clear(); proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121); QTest::newRow("ftp") @@ -781,6 +770,7 @@ void tst_QTcpServer::proxyFactory_data() QTest::newRow("ftp+cachinghttp") << proxyList << QNetworkProxy() << true << int(QAbstractSocket::UnsupportedSocketOperationError); +#endif } void tst_QTcpServer::proxyFactory() @@ -875,10 +865,12 @@ void tst_QTcpServer::serverAddress_data() QTest::newRow("AnyIPv4") << QHostAddress(QHostAddress::AnyIPv4) << QHostAddress(QHostAddress::AnyIPv4); if (QtNetworkSettings::hasIPv6()) QTest::newRow("AnyIPv6") << QHostAddress(QHostAddress::AnyIPv6) << QHostAddress(QHostAddress::AnyIPv6); - foreach (const QNetworkInterface &iface, QNetworkInterface::allInterfaces()) { + const auto ifaces = QNetworkInterface::allInterfaces(); + for (const QNetworkInterface &iface : ifaces) { if ((iface.flags() & QNetworkInterface::IsUp) == 0) continue; - foreach (const QNetworkAddressEntry &entry, iface.addressEntries()) { + const auto entries = iface.addressEntries(); + for (const QNetworkAddressEntry &entry : entries) { QTest::newRow(qPrintable(entry.ip().toString())) << entry.ip() << entry.ip(); } } @@ -932,7 +924,8 @@ void tst_QTcpServer::linkLocal() QSet <QString> scopes; QHostAddress localMaskv4("169.254.0.0"); QHostAddress localMaskv6("fe80::"); - foreach (const QNetworkInterface& iface, QNetworkInterface::allInterfaces()) { + const auto ifaces = QNetworkInterface::allInterfaces(); + for (const QNetworkInterface &iface : ifaces) { //Windows preallocates link local addresses to interfaces that are down. //These may or may not work depending on network driver (they do not work for the Bluetooth PAN driver) if (iface.flags() & QNetworkInterface::IsUp) { @@ -945,8 +938,15 @@ void tst_QTcpServer::linkLocal() // (we don't know why) if (iface.name().startsWith("utun")) continue; + // Do not use the iBridge interfae + if (iface.hardwareAddress() == "AC:DE:48:00:11:22") + continue; + // Do no use the Apple Wireless Direct Link interfaces + if (iface.name().startsWith("awdl")) + continue; #endif - foreach (QNetworkAddressEntry addressEntry, iface.addressEntries()) { + const auto entries = iface.addressEntries(); + for (const QNetworkAddressEntry &addressEntry : entries) { QHostAddress addr = addressEntry.ip(); if (addr.isInSubnet(localMaskv4, 16)) { addresses << addr; @@ -965,7 +965,7 @@ void tst_QTcpServer::linkLocal() QList<QTcpServer*> servers; quint16 port = 0; - foreach (const QHostAddress& addr, addresses) { + for (const QHostAddress &addr : std::as_const(addresses)) { QTcpServer *server = new QTcpServer; QVERIFY(server->listen(addr, port)); port = server->serverPort(); //listen to same port on different interfaces @@ -973,7 +973,7 @@ void tst_QTcpServer::linkLocal() } QList<QTcpSocket*> clients; - foreach (const QHostAddress& addr, addresses) { + for (const QHostAddress &addr : std::as_const(addresses)) { //unbound socket QTcpSocket *socket = new QTcpSocket; socket->connectToHost(addr, port); @@ -988,7 +988,7 @@ void tst_QTcpServer::linkLocal() } //each server should have two connections - foreach (QTcpServer* server, servers) { + for (QTcpServer *server : std::as_const(servers)) { //qDebug() << "checking for connections" << server->serverAddress() << ":" << server->serverPort(); QVERIFY(server->waitForNewConnection(5000)); QTcpSocket* remote = server->nextPendingConnection(); @@ -1023,12 +1023,12 @@ void tst_QTcpServer::eagainBlockingAccept() QTcpSocket s; s.connectToHost(QHostAddress::LocalHost, 7896); QSignalSpy spy(&server, SIGNAL(newConnection())); - QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 1, 500); + QTRY_COMPARE_WITH_TIMEOUT(spy.size(), 1, 500); s.close(); // To test try again, should connect just fine. s.connectToHost(QHostAddress::LocalHost, 7896); - QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 2, 500); + QTRY_COMPARE_WITH_TIMEOUT(spy.size(), 2, 500); s.close(); server.close(); } @@ -1064,13 +1064,13 @@ void tst_QTcpServer::pauseAccepting() QTcpSocket sockets[NumSockets]; sockets[0].connectToHost(address, server.serverPort()); QVERIFY(spy.wait()); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); server.pauseAccepting(); for (int i = 1; i < NumSockets; ++i) sockets[i].connectToHost(address, server.serverPort()); QVERIFY(!spy.wait(400)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); server.resumeAccepting(); if (setProxy) { @@ -1078,7 +1078,75 @@ void tst_QTcpServer::pauseAccepting() Abort); } QVERIFY(spy.wait()); - QCOMPARE(spy.count(), 6); + QCOMPARE(spy.size(), 6); +} + + +// Only adds the socket to the pending connections list after emitNextSocket is +// called. It's very artificial, but it allows us to test the behavior of +// the pendingConnectionAvailable signal when a server doesn't add the socket +// during the incomingConnection virtual function. +class DerivedServer : public QTcpServer +{ +public: + explicit DerivedServer(QObject *parent = nullptr) + : QTcpServer(parent) + { + } + + void emitNextSocket() + { + if (m_socketDescriptors.isEmpty()) + return; + auto *socket = new QTcpSocket(this); + socket->setSocketDescriptor(m_socketDescriptors.back()); + m_socketDescriptors.pop_back(); + addPendingConnection(socket); + } +protected: + void incomingConnection(qintptr socketDescriptor) override + { + m_socketDescriptors.push_back(socketDescriptor); + } +private: + QList<qintptr> m_socketDescriptors; +}; + +void tst_QTcpServer::pendingConnectionAvailable_data() +{ + QTest::addColumn<bool>("useDerivedServer"); + QTest::newRow("QTcpServer") << false; + QTest::newRow("DerivedServer") << true; +} + +void tst_QTcpServer::pendingConnectionAvailable() +{ + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + QSKIP("This feature does not differentiate with or without proxy"); + QFETCH(bool, useDerivedServer); + + QTcpServer *server = useDerivedServer ? new DerivedServer : new QTcpServer; + if (!server->listen(QHostAddress::LocalHost, 0)) { + qWarning() << "Server failed to listen:" << server->errorString(); + QSKIP("Server failed to listen"); + } + QSignalSpy newConnectionSpy(server, &QTcpServer::newConnection); + QSignalSpy pendingConnectionSpy(server, &QTcpServer::pendingConnectionAvailable); + + QTcpSocket socket; + socket.connectToHost(QHostAddress::LocalHost, server->serverPort()); + + QVERIFY(newConnectionSpy.wait()); + QVERIFY(socket.waitForConnected()); + QCOMPARE(socket.state(), QTcpSocket::ConnectedState); + + int expectedPendingConnections = useDerivedServer ? 0 : 1; + QCOMPARE(pendingConnectionSpy.size(), expectedPendingConnections); + + if (useDerivedServer) + static_cast<DerivedServer *>(server)->emitNextSocket(); + QCOMPARE(pendingConnectionSpy.size(), 1); } QTEST_MAIN(tst_QTcpServer) |