summaryrefslogtreecommitdiffstats
path: root/tests/auto/qtcpserver
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2009-03-23 10:18:55 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2009-03-23 10:18:55 +0100
commite5fcad302d86d316390c6b0f62759a067313e8a9 (patch)
treec2afbf6f1066b6ce261f14341cf6d310e5595bc1 /tests/auto/qtcpserver
Long live Qt 4.5!
Diffstat (limited to 'tests/auto/qtcpserver')
-rw-r--r--tests/auto/qtcpserver/.gitignore3
-rw-r--r--tests/auto/qtcpserver/crashingServer/crashingServer.pro8
-rw-r--r--tests/auto/qtcpserver/crashingServer/main.cpp70
-rw-r--r--tests/auto/qtcpserver/qtcpserver.pro5
-rw-r--r--tests/auto/qtcpserver/test/test.pro32
-rw-r--r--tests/auto/qtcpserver/tst_qtcpserver.cpp844
6 files changed, 962 insertions, 0 deletions
diff --git a/tests/auto/qtcpserver/.gitignore b/tests/auto/qtcpserver/.gitignore
new file mode 100644
index 0000000000..c00e0a4ca9
--- /dev/null
+++ b/tests/auto/qtcpserver/.gitignore
@@ -0,0 +1,3 @@
+tst_qtcpserver
+crashingServer/crashingServer
+crashingServer/crashingServer.exe
diff --git a/tests/auto/qtcpserver/crashingServer/crashingServer.pro b/tests/auto/qtcpserver/crashingServer/crashingServer.pro
new file mode 100644
index 0000000000..70e42b4456
--- /dev/null
+++ b/tests/auto/qtcpserver/crashingServer/crashingServer.pro
@@ -0,0 +1,8 @@
+SOURCES += main.cpp
+QT = core network
+CONFIG -= app_bundle
+DESTDIR = ./
+
+# This means the auto test works on some machines for MinGW. No dialog stalls
+# the application.
+win32-g++:CONFIG += console
diff --git a/tests/auto/qtcpserver/crashingServer/main.cpp b/tests/auto/qtcpserver/crashingServer/main.cpp
new file mode 100644
index 0000000000..7b9a0d528a
--- /dev/null
+++ b/tests/auto/qtcpserver/crashingServer/main.cpp
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtCore>
+#include <QtNetwork>
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication app(argc, argv);
+
+ QTcpServer server;
+ if (!server.listen(QHostAddress::LocalHost, 49199)) {
+ qDebug("Failed to listen: %s", server.errorString().toLatin1().constData());
+ return 1;
+ }
+
+#if !defined(Q_OS_WINCE)
+ printf("Listening\n");
+ fflush(stdout);
+#else
+ QFile file(QLatin1String("/test_signal.txt"));
+ file.open(QIODevice::WriteOnly);
+ file.write("Listening\n");
+ file.flush();
+ file.close();
+#endif
+
+ server.waitForNewConnection(5000);
+ qFatal("Crash");
+ return 0;
+}
diff --git a/tests/auto/qtcpserver/qtcpserver.pro b/tests/auto/qtcpserver/qtcpserver.pro
new file mode 100644
index 0000000000..fe5ea372d5
--- /dev/null
+++ b/tests/auto/qtcpserver/qtcpserver.pro
@@ -0,0 +1,5 @@
+TEMPLATE = subdirs
+SUBDIRS = test crashingServer
+
+
+
diff --git a/tests/auto/qtcpserver/test/test.pro b/tests/auto/qtcpserver/test/test.pro
new file mode 100644
index 0000000000..3ca854f641
--- /dev/null
+++ b/tests/auto/qtcpserver/test/test.pro
@@ -0,0 +1,32 @@
+load(qttest_p4)
+SOURCES += ../tst_qtcpserver.cpp
+
+win32: {
+wince*: {
+ LIBS += -lws2
+ crashApp.sources = ../crashingServer/crashingServer.exe
+ crashApp.path = crashingServer
+ DEPLOYMENT += crashApp
+} else {
+ LIBS += -lws2_32
+}
+}
+
+TARGET = ../tst_qtcpserver
+
+win32 {
+ CONFIG(debug, debug|release) {
+ TARGET = ../../debug/tst_qtcpserver
+} else {
+ TARGET = ../../release/tst_qtcpserver
+ }
+}
+
+QT = core network
+
+MOC_DIR=tmp
+
+DEFINES += TEST_QNETWORK_PROXY
+
+
+
diff --git a/tests/auto/qtcpserver/tst_qtcpserver.cpp b/tests/auto/qtcpserver/tst_qtcpserver.cpp
new file mode 100644
index 0000000000..50b293d4c3
--- /dev/null
+++ b/tests/auto/qtcpserver/tst_qtcpserver.cpp
@@ -0,0 +1,844 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifdef _WIN32
+#include <winsock2.h>
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#define SOCKET int
+#define INVALID_SOCKET -1
+#endif
+
+#include <QtTest/QtTest>
+
+#ifndef Q_OS_WIN
+#include <unistd.h>
+#include <sys/ioctl.h>
+#endif
+
+#include <qcoreapplication.h>
+#include <qtcpsocket.h>
+#include <qtcpserver.h>
+#include <qhostaddress.h>
+#include <qprocess.h>
+#include <qstringlist.h>
+#include <qplatformdefs.h>
+#include <qhostinfo.h>
+
+#ifdef TEST_QNETWORK_PROXY
+# include <QNetworkProxy>
+Q_DECLARE_METATYPE(QNetworkProxy)
+Q_DECLARE_METATYPE(QList<QNetworkProxy>)
+#endif
+
+#include "../network-settings.h"
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QTcpServer : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QTcpServer();
+ virtual ~tst_QTcpServer();
+
+
+public slots:
+ void initTestCase_data();
+ void init();
+ void cleanup();
+private slots:
+ void getSetCheck();
+ void constructing();
+ void clientServerLoop();
+ void ipv6Server();
+ void ipv4LoopbackPerformanceTest();
+ void ipv6LoopbackPerformanceTest();
+ void ipv4PerformanceTest();
+ void crashTests();
+ void maxPendingConnections();
+ void listenError();
+ void waitForConnectionTest();
+ void setSocketDescriptor();
+ void listenWhileListening();
+ void addressReusable();
+ void setNewSocketDescriptorBlocking();
+#ifdef TEST_QNETWORK_PROXY
+ void invalidProxy_data();
+ void invalidProxy();
+ void proxyFactory_data();
+ void proxyFactory();
+#endif
+};
+
+// Testing get/set functions
+void tst_QTcpServer::getSetCheck()
+{
+ QTcpServer obj1;
+ // int QTcpServer::maxPendingConnections()
+ // void QTcpServer::setMaxPendingConnections(int)
+ obj1.setMaxPendingConnections(0);
+ QCOMPARE(0, obj1.maxPendingConnections());
+ obj1.setMaxPendingConnections(INT_MIN);
+ QCOMPARE(INT_MIN, obj1.maxPendingConnections());
+ obj1.setMaxPendingConnections(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.maxPendingConnections());
+}
+
+tst_QTcpServer::tst_QTcpServer()
+{
+}
+
+tst_QTcpServer::~tst_QTcpServer()
+{
+
+}
+
+void tst_QTcpServer::initTestCase_data()
+{
+ QTest::addColumn<bool>("setProxy");
+ QTest::addColumn<int>("proxyType");
+
+ QTest::newRow("WithoutProxy") << false << 0;
+#ifdef TEST_QNETWORK_PROXY
+ QTest::newRow("WithSocks5Proxy") << true << int(QNetworkProxy::Socks5Proxy);
+#endif
+}
+
+void tst_QTcpServer::init()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy) {
+#ifdef TEST_QNETWORK_PROXY
+ QFETCH_GLOBAL(int, proxyType);
+ if (proxyType == QNetworkProxy::Socks5Proxy) {
+ QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080));
+ }
+#endif
+ }
+}
+
+void tst_QTcpServer::cleanup()
+{
+#ifdef TEST_QNETWORK_PROXY
+ QNetworkProxy::setApplicationProxy(QNetworkProxy::DefaultProxy);
+#endif
+}
+
+//----------------------------------------------------------------------------------
+
+void tst_QTcpServer::constructing()
+{
+ QTcpServer socket;
+
+ // Check the initial state of the QTcpSocket.
+ QCOMPARE(socket.isListening(), false);
+ QCOMPARE((int)socket.serverPort(), 0);
+ QCOMPARE(socket.serverAddress(), QHostAddress());
+ QCOMPARE(socket.maxPendingConnections(), 30);
+ QCOMPARE(socket.hasPendingConnections(), false);
+ QCOMPARE(socket.socketDescriptor(), -1);
+ QCOMPARE(socket.serverError(), QAbstractSocket::UnknownSocketError);
+
+ // Check the state of the socket layer?
+}
+
+//----------------------------------------------------------------------------------
+void tst_QTcpServer::clientServerLoop()
+{
+ QTcpServer server;
+
+ QSignalSpy spy(&server, SIGNAL(newConnection()));
+
+ QVERIFY(!server.isListening());
+ QVERIFY(!server.hasPendingConnections());
+ QVERIFY(server.listen(QHostAddress::Any, 11423));
+ QVERIFY(server.isListening());
+
+ QTcpSocket client;
+
+ QHostAddress serverAddress = QHostAddress::LocalHost;
+ if (!(server.serverAddress() == QHostAddress::Any))
+ serverAddress = server.serverAddress();
+
+ client.connectToHost(serverAddress, server.serverPort());
+ QVERIFY(client.waitForConnected(5000));
+
+ QVERIFY(server.waitForNewConnection(5000));
+ QVERIFY(server.hasPendingConnections());
+
+ QCOMPARE(spy.count(), 1);
+
+ QTcpSocket *serverSocket = server.nextPendingConnection();
+ QVERIFY(serverSocket != 0);
+
+ QVERIFY(serverSocket->write("Greetings, client!\n", 19) == 19);
+ serverSocket->flush();
+
+ QVERIFY(client.waitForReadyRead(5000));
+ QByteArray arr = client.readAll();
+ QCOMPARE(arr.constData(), "Greetings, client!\n");
+
+ QVERIFY(client.write("Well, hello to you!\n", 20) == 20);
+ client.flush();
+
+ QVERIFY(serverSocket->waitForReadyRead(5000));
+ arr = serverSocket->readAll();
+ QCOMPARE(arr.constData(), "Well, hello to you!\n");
+}
+
+//----------------------------------------------------------------------------------
+void tst_QTcpServer::ipv6Server()
+{
+ //### need to enter the event loop for the server to get the connection ?? ( windows)
+ QTcpServer server;
+ if (!server.listen(QHostAddress::LocalHostIPv6, 8944)) {
+ QVERIFY(server.serverError() == QAbstractSocket::UnsupportedSocketOperationError);
+ return;
+ }
+
+ QVERIFY(server.serverPort() == 8944);
+ QVERIFY(server.serverAddress() == QHostAddress::LocalHostIPv6);
+
+ QTcpSocket client;
+ client.connectToHost("::1", 8944);
+ QVERIFY(client.waitForConnected(5000));
+
+ QVERIFY(server.waitForNewConnection());
+ QVERIFY(server.hasPendingConnections());
+
+ QTcpSocket *serverSocket = 0;
+ QVERIFY((serverSocket = server.nextPendingConnection()));
+}
+
+//----------------------------------------------------------------------------------
+void tst_QTcpServer::ipv4LoopbackPerformanceTest()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ QTcpServer server;
+ QVERIFY(server.listen(QHostAddress::LocalHost));
+
+ QVERIFY(server.isListening());
+
+ QTcpSocket clientA;
+ clientA.connectToHost(QHostAddress::LocalHost, server.serverPort());
+ QVERIFY(clientA.waitForConnected(5000));
+ QVERIFY(clientA.state() == QAbstractSocket::ConnectedState);
+
+ QVERIFY(server.waitForNewConnection());
+ QTcpSocket *clientB = server.nextPendingConnection();
+ QVERIFY(clientB);
+
+#if defined(Q_WS_WIN)
+ if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) {
+ QSKIP("Dont run performance tests on QSysInfo::WV_DOS_based systems, overloads the system", SkipAll);
+ } else
+#endif
+ {
+ QByteArray buffer(16384, '@');
+ QTime stopWatch;
+ stopWatch.start();
+ qlonglong totalWritten = 0;
+ while (stopWatch.elapsed() < 5000) {
+ QVERIFY(clientA.write(buffer.data(), buffer.size()) > 0);
+ clientA.flush();
+ totalWritten += buffer.size();
+ while (clientB->waitForReadyRead(100)) {
+ if (clientB->bytesAvailable() == 16384)
+ break;
+ }
+ clientB->read(buffer.data(), buffer.size());
+ clientB->write(buffer.data(), buffer.size());
+ clientB->flush();
+ totalWritten += buffer.size();
+ while (clientA.waitForReadyRead(100)) {
+ if (clientA.bytesAvailable() == 16384)
+ break;
+ }
+ clientA.read(buffer.data(), buffer.size());
+ }
+
+ qDebug("\t\t%s: %.1fMB/%.1fs: %.1fMB/s",
+ server.serverAddress().toString().toLatin1().constData(),
+ totalWritten / (1024.0 * 1024.0),
+ stopWatch.elapsed() / 1000.0,
+ (totalWritten / (stopWatch.elapsed() / 1000.0)) / (1024 * 1024));
+
+ }
+ delete clientB;
+}
+
+//----------------------------------------------------------------------------------
+void tst_QTcpServer::ipv6LoopbackPerformanceTest()
+{
+ QTcpServer server;
+ if (!server.listen(QHostAddress::LocalHostIPv6, 0)) {
+ QVERIFY(server.serverError() == QAbstractSocket::UnsupportedSocketOperationError);
+ } else {
+ QTcpSocket clientA;
+ clientA.connectToHost(server.serverAddress(), server.serverPort());
+ QVERIFY(clientA.waitForConnected(5000));
+
+ QVERIFY(server.waitForNewConnection(5000));
+ QTcpSocket *clientB = server.nextPendingConnection();
+ QVERIFY(clientB);
+
+ QByteArray buffer(16384, '@');
+ QTime stopWatch;
+ stopWatch.start();
+ qlonglong totalWritten = 0;
+ while (stopWatch.elapsed() < 5000) {
+ clientA.write(buffer.data(), buffer.size());
+ clientA.flush();
+ totalWritten += buffer.size();
+ while (clientB->waitForReadyRead(100)) {
+ if (clientB->bytesAvailable() == 16384)
+ break;
+ }
+ clientB->read(buffer.data(), buffer.size());
+ clientB->write(buffer.data(), buffer.size());
+ clientB->flush();
+ totalWritten += buffer.size();
+ while (clientA.waitForReadyRead(100)) {
+ if (clientA.bytesAvailable() == 16384)
+ break;
+ }
+ clientA.read(buffer.data(), buffer.size());
+ }
+
+ qDebug("\t\t%s: %.1fMB/%.1fs: %.1fMB/s",
+ server.serverAddress().toString().toLatin1().constData(),
+ totalWritten / (1024.0 * 1024.0),
+ stopWatch.elapsed() / 1000.0,
+ (totalWritten / (stopWatch.elapsed() / 1000.0)) / (1024 * 1024));
+ delete clientB;
+ }
+}
+
+//----------------------------------------------------------------------------------
+void tst_QTcpServer::ipv4PerformanceTest()
+{
+ QTcpSocket probeSocket;
+ probeSocket.connectToHost("imap.troll.no", 143);
+ QVERIFY(probeSocket.waitForConnected(5000));
+
+ QTcpServer server;
+ QVERIFY(server.listen(probeSocket.localAddress(), 0));
+
+ QTcpSocket clientA;
+ clientA.connectToHost(server.serverAddress(), server.serverPort());
+ QVERIFY(clientA.waitForConnected(5000));
+
+ QVERIFY(server.waitForNewConnection(5000));
+ QTcpSocket *clientB = server.nextPendingConnection();
+ QVERIFY(clientB);
+
+#if defined(Q_WS_WIN)
+ if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) {
+ QSKIP("Dont run performance tests on QSysInfo::WV_DOS_based systems, overloads the system", SkipAll);
+ } else
+#endif
+ {
+
+ QByteArray buffer(16384, '@');
+ QTime stopWatch;
+ stopWatch.start();
+ qlonglong totalWritten = 0;
+ while (stopWatch.elapsed() < 5000) {
+ qlonglong writtenA = clientA.write(buffer.data(), buffer.size());
+ clientA.flush();
+ totalWritten += buffer.size();
+ while (clientB->waitForReadyRead(100)) {
+ if (clientB->bytesAvailable() == writtenA)
+ break;
+ }
+ clientB->read(buffer.data(), buffer.size());
+ qlonglong writtenB = clientB->write(buffer.data(), buffer.size());
+ clientB->flush();
+ totalWritten += buffer.size();
+ while (clientA.waitForReadyRead(100)) {
+ if (clientA.bytesAvailable() == writtenB)
+ break;
+ }
+ clientA.read(buffer.data(), buffer.size());
+ }
+
+ qDebug("\t\t%s: %.1fMB/%.1fs: %.1fMB/s",
+ probeSocket.localAddress().toString().toLatin1().constData(),
+ totalWritten / (1024.0 * 1024.0),
+ stopWatch.elapsed() / 1000.0,
+ (totalWritten / (stopWatch.elapsed() / 1000.0)) / (1024 * 1024));
+ }
+ delete clientB;
+}
+
+//----------------------------------------------------------------------------------
+void tst_QTcpServer::crashTests()
+{
+ QTcpServer server;
+ server.close();
+ QVERIFY(server.listen());
+}
+
+//----------------------------------------------------------------------------------
+void tst_QTcpServer::maxPendingConnections()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy) {
+#ifdef TEST_QNETWORK_PROXY
+ QFETCH_GLOBAL(int, proxyType);
+ if (proxyType == QNetworkProxy::Socks5Proxy) {
+ QSKIP("With socks5 only 1 connection is allowed ever", SkipAll);
+ }
+#endif
+ }
+ //### sees to fail sometimes ... a timing issue with the test on windows
+ QTcpServer server;
+ server.setMaxPendingConnections(2);
+
+ QTcpSocket socket1;
+ QTcpSocket socket2;
+ QTcpSocket socket3;
+
+ QVERIFY(server.listen());
+
+ socket1.connectToHost(QHostAddress::LocalHost, server.serverPort());
+ socket2.connectToHost(QHostAddress::LocalHost, server.serverPort());
+ socket3.connectToHost(QHostAddress::LocalHost, server.serverPort());
+
+ QVERIFY(server.waitForNewConnection(5000));
+
+ QVERIFY(server.hasPendingConnections());
+ QVERIFY(server.nextPendingConnection());
+ QVERIFY(server.hasPendingConnections());
+ QVERIFY(server.nextPendingConnection());
+ QVERIFY(!server.hasPendingConnections());
+ QCOMPARE(server.nextPendingConnection(), (QTcpSocket*)0);
+
+ QVERIFY(server.waitForNewConnection(5000));
+
+ QVERIFY(server.hasPendingConnections());
+ QVERIFY(server.nextPendingConnection());
+}
+
+//----------------------------------------------------------------------------------
+void tst_QTcpServer::listenError()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy) {
+#ifdef TEST_QNETWORK_PROXY
+ QFETCH_GLOBAL(int, proxyType);
+ if (proxyType == QNetworkProxy::Socks5Proxy) {
+ QSKIP("With socks5 we can not make hard requirements on the address or port", SkipAll);
+ }
+#endif
+ }
+ QTcpServer server;
+ QVERIFY(!server.listen(QHostAddress("1.2.3.4"), 0));
+ QCOMPARE(server.serverError(), QAbstractSocket::SocketAddressNotAvailableError);
+ QCOMPARE(server.errorString().toLatin1().constData(), "The address is not available");
+}
+
+class ThreadConnector : public QThread
+{
+public:
+ ThreadConnector(const QHostAddress &host, quint16 port)
+ : host(host), port(port)
+ { }
+
+ ~ThreadConnector()
+ {
+ wait();
+ }
+
+protected:
+ void run()
+ {
+ sleep(2);
+
+ QTcpSocket socket;
+ socket.connectToHost(host, port);
+
+ QEventLoop loop;
+ QTimer::singleShot(5000, &loop, SLOT(quit()));
+ loop.exec();
+ }
+
+private:
+ QHostAddress host;
+ quint16 port;
+};
+
+//----------------------------------------------------------------------------------
+void tst_QTcpServer::waitForConnectionTest()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy) {
+#ifdef TEST_QNETWORK_PROXY
+ QFETCH_GLOBAL(int, proxyType);
+ if (proxyType == QNetworkProxy::Socks5Proxy) {
+ QSKIP("Localhost servers don't work well with SOCKS5", SkipAll);
+ }
+#endif
+ }
+
+ QTcpSocket findLocalIpSocket;
+ findLocalIpSocket.connectToHost(QtNetworkSettings::serverName(), 21);
+ QVERIFY(findLocalIpSocket.waitForConnected(2000));
+
+ QTcpServer server;
+ bool timeout = false;
+ QVERIFY(server.listen(findLocalIpSocket.localAddress()));
+ QVERIFY(!server.waitForNewConnection(1000, &timeout));
+ QCOMPARE(server.serverError(), QAbstractSocket::SocketTimeoutError);
+ QVERIFY(timeout);
+
+ ThreadConnector connector(findLocalIpSocket.localAddress(), server.serverPort());
+ connector.start();
+
+#if !defined(Q_OS_WINCE)
+ QVERIFY(server.waitForNewConnection(3000, &timeout));
+#else
+ QVERIFY(server.waitForNewConnection(9000, &timeout));
+#endif
+ QVERIFY(!timeout);
+}
+
+//----------------------------------------------------------------------------------
+void tst_QTcpServer::setSocketDescriptor()
+{
+ QTcpServer server;
+ QVERIFY(!server.setSocketDescriptor(42));
+ QCOMPARE(server.serverError(), QAbstractSocket::UnsupportedSocketOperationError);
+
+#ifdef Q_OS_WIN
+ // ensure winsock is started
+ WSADATA wsaData;
+ QVERIFY(WSAStartup(MAKEWORD(2,0), &wsaData) == NO_ERROR);
+#endif
+
+ SOCKET sock = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+ QVERIFY(sock != INVALID_SOCKET);
+
+ sockaddr_in sin;
+ memset(&sin, 0, sizeof(sockaddr_in));
+ sin.sin_family = AF_INET;
+ sin.sin_port = 0;
+ sin.sin_addr.s_addr = 0x00000000;
+ QVERIFY(::bind(sock, (sockaddr*)&sin, sizeof(sockaddr_in)) == 0);
+ QVERIFY(::listen(sock, 10) == 0);
+ QVERIFY(server.setSocketDescriptor(sock));
+
+#ifdef Q_OS_WIN
+ WSACleanup();
+#endif
+}
+
+//----------------------------------------------------------------------------------
+void tst_QTcpServer::listenWhileListening()
+{
+ QTcpServer server;
+ QVERIFY(server.listen());
+ QTest::ignoreMessage(QtWarningMsg, "QTcpServer::listen() called when already listening");
+ QVERIFY(!server.listen());
+}
+
+//----------------------------------------------------------------------------------
+
+class SeverWithBlockingSockets : public QTcpServer
+{
+public:
+ SeverWithBlockingSockets()
+ : ok(false) { }
+
+ bool ok;
+
+protected:
+ void incomingConnection(int socketDescriptor)
+ {
+ // how a user woulddo it (qabstractsocketengine is not public)
+ unsigned long arg = 0;
+#ifdef Q_OS_WIN
+ ok = ::ioctlsocket(socketDescriptor, FIONBIO, &arg) == 0;
+ ::closesocket(socketDescriptor);
+#else
+ ok = ::ioctl(socketDescriptor, FIONBIO, &arg) == 0;
+ ::close(socketDescriptor);
+#endif
+ }
+};
+
+void tst_QTcpServer::addressReusable()
+{
+#if defined(QT_NO_PROCESS)
+ QSKIP("Qt was compiled with QT_NO_PROCESS", SkipAll);
+#else
+
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy) {
+#ifdef TEST_QNETWORK_PROXY
+ QFETCH_GLOBAL(int, proxyType);
+ if (proxyType == QNetworkProxy::Socks5Proxy) {
+ QSKIP("With socks5 this test does not make senans at the momment", SkipAll);
+ }
+#endif
+ }
+#if defined(Q_OS_WINCE)
+ QString signalName = QString::fromLatin1("/test_signal.txt");
+ QFile::remove(signalName);
+ // The crashingServer process will crash once it gets a connection.
+ QProcess process;
+ process.start("crashingServer/crashingServer");
+ int waitCount = 5;
+ while (waitCount-- && !QFile::exists(signalName))
+ QTest::qWait(1000);
+ QVERIFY(QFile::exists(signalName));
+ QFile::remove(signalName);
+#else
+ // The crashingServer process will crash once it gets a connection.
+ QProcess process;
+ process.start("crashingServer/crashingServer");
+ QVERIFY(process.waitForReadyRead(5000));
+#endif
+
+ QTcpSocket socket;
+ socket.connectToHost(QHostAddress::LocalHost, 49199);
+ QVERIFY(socket.waitForConnected(5000));
+
+ QVERIFY(process.waitForFinished(5000));
+
+ // Give the system some time.
+ QTest::qSleep(10);
+
+ QTcpServer server;
+ QVERIFY(server.listen(QHostAddress::LocalHost, 49199));
+#endif
+}
+
+void tst_QTcpServer::setNewSocketDescriptorBlocking()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy) {
+#ifdef TEST_QNETWORK_PROXY
+ QFETCH_GLOBAL(int, proxyType);
+ if (proxyType == QNetworkProxy::Socks5Proxy) {
+ QSKIP("With socks5 we can not make the socket descripter blocking", SkipAll);
+ }
+#endif
+ }
+ SeverWithBlockingSockets server;
+ QVERIFY(server.listen());
+
+ QTcpSocket socket;
+ socket.connectToHost(QHostAddress::LocalHost, server.serverPort());
+
+ QVERIFY(server.waitForNewConnection(5000));
+
+ QVERIFY(server.ok);
+}
+
+#ifdef TEST_QNETWORK_PROXY
+void tst_QTcpServer::invalidProxy_data()
+{
+ QTest::addColumn<int>("type");
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<int>("port");
+ QTest::addColumn<int>("expectedError");
+
+ QString fluke = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString();
+ QTest::newRow("ftp-proxy") << int(QNetworkProxy::FtpCachingProxy) << fluke << 21
+ << int(QAbstractSocket::UnsupportedSocketOperationError);
+ QTest::newRow("http-proxy") << int(QNetworkProxy::HttpProxy) << fluke << 3128
+ << int(QAbstractSocket::UnsupportedSocketOperationError);
+
+ QTest::newRow("no-such-host") << int(QNetworkProxy::Socks5Proxy)
+ << "this-host-will-never-exist.troll.no" << 1080
+ << int(QAbstractSocket::ProxyNotFoundError);
+ QTest::newRow("socks5-on-http") << int(QNetworkProxy::Socks5Proxy) << fluke << 3128
+ << int(QAbstractSocket::SocketTimeoutError);
+}
+
+void tst_QTcpServer::invalidProxy()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ QFETCH(int, type);
+ QFETCH(QString, host);
+ QFETCH(int, port);
+ QNetworkProxy::ProxyType proxyType = QNetworkProxy::ProxyType(type);
+ QNetworkProxy proxy(proxyType, host, port);
+
+ QTcpServer server;
+ server.setProxy(proxy);
+ bool listenResult = server.listen();
+
+ QVERIFY(!listenResult);
+ QVERIFY(!server.errorString().isEmpty());
+
+ // note: the following test is not a hard failure.
+ // Sometimes, error codes change for the better
+ QTEST(int(server.serverError()), "expectedError");
+}
+
+// copied from tst_qnetworkreply.cpp
+class MyProxyFactory: public QNetworkProxyFactory
+{
+public:
+ int callCount;
+ QList<QNetworkProxy> toReturn;
+ QNetworkProxyQuery lastQuery;
+ inline MyProxyFactory() { clear(); }
+
+ inline void clear()
+ {
+ callCount = 0;
+ toReturn = QList<QNetworkProxy>() << QNetworkProxy::DefaultProxy;
+ lastQuery = QNetworkProxyQuery();
+ }
+
+ virtual QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query)
+ {
+ lastQuery = query;
+ ++callCount;
+ return toReturn;
+ }
+};
+
+void tst_QTcpServer::proxyFactory_data()
+{
+ QTest::addColumn<QList<QNetworkProxy> >("proxyList");
+ QTest::addColumn<QNetworkProxy>("proxyUsed");
+ QTest::addColumn<bool>("fails");
+ QTest::addColumn<int>("expectedError");
+
+ QList<QNetworkProxy> proxyList;
+
+ // tests that do get to listen
+
+ proxyList << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080);
+ QTest::newRow("socks5")
+ << proxyList << proxyList.at(0)
+ << false << int(QAbstractSocket::UnknownSocketError);
+
+ proxyList.clear();
+ proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3128)
+ << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080);
+ QTest::newRow("cachinghttp+socks5")
+ << proxyList << proxyList.at(1)
+ << false << int(QAbstractSocket::UnknownSocketError);
+
+ proxyList.clear();
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121)
+ << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3128)
+ << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080);
+ QTest::newRow("ftp+cachinghttp+socks5")
+ << proxyList << proxyList.at(2)
+ << false << int(QAbstractSocket::UnknownSocketError);
+
+ // tests that fail to listen
+ proxyList.clear();
+ proxyList << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3128);
+ QTest::newRow("http")
+ << proxyList << proxyList.at(0)
+ << true << int(QAbstractSocket::UnsupportedSocketOperationError);
+
+ proxyList.clear();
+ proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3128);
+ QTest::newRow("cachinghttp")
+ << proxyList << QNetworkProxy()
+ << true << int(QAbstractSocket::UnsupportedSocketOperationError);
+
+ proxyList.clear();
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121);
+ QTest::newRow("ftp")
+ << proxyList << QNetworkProxy()
+ << true << int(QAbstractSocket::UnsupportedSocketOperationError);
+
+ proxyList.clear();
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121)
+ << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3128);
+ QTest::newRow("ftp+cachinghttp")
+ << proxyList << QNetworkProxy()
+ << true << int(QAbstractSocket::UnsupportedSocketOperationError);
+}
+
+void tst_QTcpServer::proxyFactory()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ QFETCH(QList<QNetworkProxy>, proxyList);
+ QFETCH(QNetworkProxy, proxyUsed);
+ QFETCH(bool, fails);
+
+ MyProxyFactory *factory = new MyProxyFactory;
+ factory->toReturn = proxyList;
+ QNetworkProxyFactory::setApplicationProxyFactory(factory);
+
+ QTcpServer server;
+ bool listenResult = server.listen();
+
+ // Verify that the factory was called properly
+ QCOMPARE(factory->callCount, 1);
+ QCOMPARE(factory->lastQuery, QNetworkProxyQuery(0, QString(), QNetworkProxyQuery::TcpServer));
+
+ QCOMPARE(listenResult, !fails);
+ QCOMPARE(server.errorString().isEmpty(), !fails);
+
+ // note: the following test is not a hard failure.
+ // Sometimes, error codes change for the better
+ QTEST(int(server.serverError()), "expectedError");
+}
+#endif
+
+QTEST_MAIN(tst_QTcpServer)
+#include "tst_qtcpserver.moc"