summaryrefslogtreecommitdiffstats
path: root/tests/auto/network/socket/qtcpsocket
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/network/socket/qtcpsocket')
-rw-r--r--tests/auto/network/socket/qtcpsocket/qtcpsocket.pro2
-rw-r--r--tests/auto/network/socket/qtcpsocket/stressTest/Test.cpp14
-rw-r--r--tests/auto/network/socket/qtcpsocket/stressTest/Test.h14
-rw-r--r--tests/auto/network/socket/qtcpsocket/stressTest/main.cpp14
-rw-r--r--tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp207
5 files changed, 209 insertions, 42 deletions
diff --git a/tests/auto/network/socket/qtcpsocket/qtcpsocket.pro b/tests/auto/network/socket/qtcpsocket/qtcpsocket.pro
index cdab37bd07..347359f508 100644
--- a/tests/auto/network/socket/qtcpsocket/qtcpsocket.pro
+++ b/tests/auto/network/socket/qtcpsocket/qtcpsocket.pro
@@ -4,6 +4,4 @@ TEMPLATE = subdirs
!wince*: SUBDIRS = test stressTest
wince*|vxworks* : SUBDIRS = test
-linux-*:system(". /etc/lsb-release && [ "$DISTRIB_CODENAME" = oneiric ]"):DEFINES+=UBUNTU_ONEIRIC
-
requires(contains(QT_CONFIG,private_tests))
diff --git a/tests/auto/network/socket/qtcpsocket/stressTest/Test.cpp b/tests/auto/network/socket/qtcpsocket/stressTest/Test.cpp
index 768f122377..ba3ea68d46 100644
--- a/tests/auto/network/socket/qtcpsocket/stressTest/Test.cpp
+++ b/tests/auto/network/socket/qtcpsocket/stressTest/Test.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
diff --git a/tests/auto/network/socket/qtcpsocket/stressTest/Test.h b/tests/auto/network/socket/qtcpsocket/stressTest/Test.h
index 6c075db5fd..b7b1f9775f 100644
--- a/tests/auto/network/socket/qtcpsocket/stressTest/Test.h
+++ b/tests/auto/network/socket/qtcpsocket/stressTest/Test.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
diff --git a/tests/auto/network/socket/qtcpsocket/stressTest/main.cpp b/tests/auto/network/socket/qtcpsocket/stressTest/main.cpp
index e32080ce1d..146161015a 100644
--- a/tests/auto/network/socket/qtcpsocket/stressTest/main.cpp
+++ b/tests/auto/network/socket/qtcpsocket/stressTest/main.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
diff --git a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp
index 684bd0db68..0ba9b6a58c 100644
--- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp
+++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
@@ -10,9 +10,9 @@
** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -23,8 +23,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -73,6 +73,7 @@
// RVCT compiles also unused inline methods
# include <QNetworkProxy>
+#include <time.h>
#ifdef Q_OS_LINUX
#include <stdio.h>
#include <stdlib.h>
@@ -123,6 +124,8 @@ private slots:
void constructing();
void bind_data();
void bind();
+ void bindThenResolveHost_data();
+ void bindThenResolveHost();
void setInvalidSocketDescriptor();
#ifndef Q_OS_WINRT
void setSocketDescriptor();
@@ -196,7 +199,7 @@ private slots:
void qtbug14268_peek();
void setSocketOption();
-
+ void clientSendDataOnDelayedDisconnect();
protected slots:
void nonBlockingIMAP_hostFound();
@@ -245,6 +248,9 @@ private:
int earlyBytesWrittenCount;
int earlyReadyReadCount;
QString stressTestDir;
+
+ QString firstFailName;
+ QHostInfo firstFailInfo;
};
enum ProxyTests {
@@ -297,7 +303,10 @@ public:
};
tst_QTcpSocket::tst_QTcpSocket()
+ : firstFailName("qt-test-server-first-fail")
{
+ qsrand(time(NULL));
+
tmpSocket = 0;
//This code relates to the socketsConstructedBeforeEventLoop test case
@@ -308,6 +317,8 @@ tst_QTcpSocket::tst_QTcpSocket()
connect(earlyConstructedSockets->endPoints[0], SIGNAL(readyRead()), this, SLOT(earlySocketReadyRead()));
connect(earlyConstructedSockets->endPoints[1], SIGNAL(bytesWritten(qint64)), this, SLOT(earlySocketBytesSent(qint64)));
earlyConstructedSockets->endPoints[1]->write("hello work");
+
+ firstFailInfo.setAddresses(QList<QHostAddress>() << QHostAddress("224.0.0.0") << QtNetworkSettings::serverIP());
}
tst_QTcpSocket::~tst_QTcpSocket()
@@ -389,6 +400,7 @@ void tst_QTcpSocket::init()
}
qt_qhostinfo_clear_cache();
+ qt_qhostinfo_cache_inject(firstFailName, firstFailInfo);
}
QTcpSocket *tst_QTcpSocket::newSocket() const
@@ -486,9 +498,12 @@ void tst_QTcpSocket::constructing()
void tst_QTcpSocket::bind_data()
{
QTest::addColumn<QString>("stringAddr");
+ QTest::addColumn<int>("port");
QTest::addColumn<bool>("successExpected");
QTest::addColumn<QString>("stringExpectedLocalAddress");
+ bool testIpv6 = false;
+
// iterate all interfaces, add all addresses on them as test data
QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
foreach (const QNetworkInterface &netinterface, interfaces) {
@@ -501,10 +516,26 @@ void tst_QTcpSocket::bind_data()
continue; // link-local bind will fail, at least on Linux, so skip it.
QString ip(entry.ip().toString());
- QTest::newRow(ip.toLatin1().constData()) << ip << true << ip;
+ QTest::newRow(ip.toLatin1().constData()) << ip << 0 << true << ip;
+
+ if (!testIpv6 && entry.ip().protocol() == QAbstractSocket::IPv6Protocol)
+ testIpv6 = true;
}
}
+ // test binding to localhost
+ QTest::newRow("0.0.0.0") << "0.0.0.0" << 0 << true << "0.0.0.0";
+ if (testIpv6)
+ QTest::newRow("[::]") << "::" << 0 << true << "::";
+
+ // and binding with a port number...
+ // Since we want to test that we got the port number we asked for, we need a random port number.
+ // We use random in case a previous run of the test left the port lingering open.
+ // -1 indicates "random port"
+ QTest::newRow("0.0.0.0:randomport") << "0.0.0.0" << -1 << true << "0.0.0.0";
+ if (testIpv6)
+ QTest::newRow("[::]:randomport") << "::" << -1 << true << "::";
+
// additionally, try bind to known-bad addresses, and make sure this doesn't work
// these ranges are guaranteed to be reserved for 'documentation purposes',
// and thus, should be unused in the real world. Not that I'm assuming the
@@ -513,8 +544,16 @@ void tst_QTcpSocket::bind_data()
knownBad << "198.51.100.1";
knownBad << "2001:0DB8::1";
foreach (const QString &badAddress, knownBad) {
- QTest::newRow(badAddress.toLatin1().constData()) << badAddress << false << QString();
+ QTest::newRow(badAddress.toLatin1().constData()) << badAddress << 0 << false << QString();
}
+
+#ifdef Q_OS_UNIX
+ // try to bind to a privileged ports
+ // we should fail if we're not root (unless the ports are in use!)
+ QTest::newRow("127.0.0.1:1") << "127.0.0.1" << 1 << !geteuid() << (geteuid() ? QString() : "127.0.0.1");
+ if (testIpv6)
+ QTest::newRow("[::]:1") << "::" << 1 << !geteuid() << (geteuid() ? QString() : "::");
+#endif
}
void tst_QTcpSocket::bind()
@@ -523,23 +562,124 @@ void tst_QTcpSocket::bind()
if (setProxy)
return; // QTBUG-22964 for proxies, QTBUG-29972 for QSKIP
QFETCH(QString, stringAddr);
+ QFETCH(int, port);
QFETCH(bool, successExpected);
QFETCH(QString, stringExpectedLocalAddress);
QHostAddress addr(stringAddr);
QHostAddress expectedLocalAddress(stringExpectedLocalAddress);
+ QTcpSocket dummySocket; // used only to "use up" a file descriptor
+ dummySocket.bind();
+
QTcpSocket *socket = newSocket();
- qDebug() << "Binding " << addr;
+ quint16 boundPort;
+ qintptr fd;
if (successExpected) {
- QVERIFY2(socket->bind(addr), qPrintable(socket->errorString()));
+ bool randomPort = port == -1;
+ int attemptsLeft = 5; // only used with randomPort
+ do {
+ if (randomPort) {
+ // try to get a random port number
+ // we do this to ensure we're not trying to bind to the same port as we've just used in
+ // a previous run - race condition with the OS actually freeing the port
+ Q_STATIC_ASSERT(RAND_MAX > 1024);
+ port = qrand() & USHRT_MAX;
+ if (port < 1024)
+ continue;
+ }
+
+ bool bindSuccess = socket->bind(addr, port);
+ if (!bindSuccess && randomPort && socket->error() == QTcpSocket::AddressInUseError) {
+ // we may have been unlucky and hit an already open port, so try another
+ --attemptsLeft;
+ continue;
+ }
+
+ QVERIFY2(bindSuccess, qPrintable(socket->errorString() + ", tried port " + QString::number(port)));
+ break;
+ } while (randomPort && attemptsLeft);
+
+ QCOMPARE(socket->state(), QAbstractSocket::BoundState);
+ boundPort = socket->localPort();
+ if (port)
+ QCOMPARE(int(boundPort), port);
+ fd = socket->socketDescriptor();
+ QVERIFY(fd != INVALID_SOCKET);
} else {
- QVERIFY(!socket->bind(addr));
+ QVERIFY(!socket->bind(addr, port));
+ QCOMPARE(socket->localPort(), quint16(0));
}
QCOMPARE(socket->localAddress(), expectedLocalAddress);
+ if (successExpected) {
+ // try to use the socket and expect it to remain working
+ QTcpServer server;
+ QVERIFY(server.listen(addr));
+
+ // free up the file descriptor
+ dummySocket.close();
+
+ QHostAddress remoteAddr = addr;
+ if (addr == QHostAddress::AnyIPv4)
+ remoteAddr = QHostAddress::LocalHost;
+ else if (addr == QHostAddress::AnyIPv6)
+ remoteAddr = QHostAddress::LocalHostIPv6;
+
+ socket->connectToHost(remoteAddr, server.serverPort());
+ QVERIFY2(socket->waitForConnected(2000), socket->errorString().toLocal8Bit());
+ QVERIFY(server.waitForNewConnection(2000));
+
+ QTcpSocket *acceptedSocket = server.nextPendingConnection();
+ QCOMPARE(socket->localPort(), boundPort);
+ QCOMPARE(acceptedSocket->peerPort(), boundPort);
+ QCOMPARE(socket->localAddress(), remoteAddr);
+ QCOMPARE(socket->socketDescriptor(), fd);
+ }
+
+ delete socket;
+}
+
+//----------------------------------------------------------------------------------
+
+void tst_QTcpSocket::bindThenResolveHost_data()
+{
+ QTest::addColumn<QString>("hostName");
+ QTest::newRow("ip-literal") << QtNetworkSettings::serverIP().toString();
+ QTest::newRow("name") << QtNetworkSettings::serverName();
+ QTest::newRow("first-fail") << firstFailName;
+}
+
+// similar to the previous test, but we'll connect to a host name that needs resolving
+void tst_QTcpSocket::bindThenResolveHost()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return; // doesn't make sense to test binding locally with proxies
+
+ QFETCH(QString, hostName);
+
+ QTcpSocket dummySocket; // used only to "use up" a file descriptor
+ dummySocket.bind();
+
+ QTcpSocket *socket = newSocket();
+
+ QVERIFY2(socket->bind(QHostAddress(QHostAddress::AnyIPv4), 0), socket->errorString().toLocal8Bit());
+ QCOMPARE(socket->state(), QAbstractSocket::BoundState);
+ quint16 boundPort = socket->localPort();
+ qintptr fd = socket->socketDescriptor();
+ QVERIFY(fd != INVALID_SOCKET);
+
+ dummySocket.close();
+
+ socket->connectToHost(hostName, 80);
+ QVERIFY2(socket->waitForConnected(), "Network timeout");
+
+ QCOMPARE(socket->localPort(), boundPort);
+ QCOMPARE(socket->socketDescriptor(), fd);
+
delete socket;
}
@@ -592,13 +732,10 @@ void tst_QTcpSocket::setSocketDescriptor()
QCOMPARE(socket->socketDescriptor(), (qintptr)sock);
qt_qhostinfo_clear_cache(); //avoid the HostLookupState being skipped due to address being in cache from previous test.
- socket->connectToHost(QtNetworkSettings::serverName(), 143);
+ socket->connectToHost(QtNetworkSettings::serverName(), 80);
QCOMPARE(socket->state(), QTcpSocket::HostLookupState);
QCOMPARE(socket->socketDescriptor(), (qintptr)sock);
QVERIFY(socket->waitForConnected(10000));
- // skip this, it has been broken for years, see task 260735
- // if somebody complains, consider fixing it, but it might break existing applications.
- QEXPECT_FAIL("", "bug has been around for years, will not fix without need", Continue);
QCOMPARE(socket->socketDescriptor(), (qintptr)sock);
delete socket;
#ifdef Q_OS_WIN
@@ -615,8 +752,8 @@ void tst_QTcpSocket::socketDescriptor()
QCOMPARE(socket->socketDescriptor(), (qintptr)-1);
socket->connectToHost(QtNetworkSettings::serverName(), 143);
- QVERIFY((socket->state() == QAbstractSocket::HostLookupState && socket->socketDescriptor() == -1) ||
- (socket->state() == QAbstractSocket::ConnectingState && socket->socketDescriptor() != -1));
+ QVERIFY(socket->state() == QAbstractSocket::HostLookupState ||
+ socket->state() == QAbstractSocket::ConnectingState);
QVERIFY(socket->waitForConnected(10000));
QVERIFY(socket->state() == QAbstractSocket::ConnectedState);
QVERIFY(socket->socketDescriptor() != -1);
@@ -2815,5 +2952,37 @@ void tst_QTcpSocket::setSocketOption()
QVERIFY(v.isValid() && v.toInt() == 32);
}
+// Test buffered socket properly send data on delayed disconnect
+void tst_QTcpSocket::clientSendDataOnDelayedDisconnect()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ QTcpServer server;
+ QTcpSocket *socket = newSocket();
+
+ QVERIFY(server.listen(QHostAddress::LocalHost));
+
+ // Connect to server, write data and close socket
+ const QByteArray sendData("GET /\r\n");
+ socket->connectToHost(server.serverAddress(), server.serverPort());
+ QVERIFY(socket->waitForConnected(5000)); // ready for write
+ QCOMPARE(socket->write(sendData), sendData.size());
+ socket->close();
+ QVERIFY(socket->waitForDisconnected(5000)); // flush buffer
+
+ // Check data on server side
+ QByteArray recData;
+ QVERIFY(server.waitForNewConnection(5000));
+ QTcpSocket *newConnection = server.nextPendingConnection();
+ QVERIFY(newConnection != NULL);
+ while (newConnection->waitForReadyRead(5000)) // have data to read
+ recData += newConnection->readAll();
+ QCOMPARE(sendData, recData);
+
+ delete socket;
+}
+
QTEST_MAIN(tst_QTcpSocket)
#include "tst_qtcpsocket.moc"