summaryrefslogtreecommitdiffstats
path: root/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp')
-rw-r--r--tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp176
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)