diff options
author | axis <qt-info@nokia.com> | 2009-04-24 11:34:15 (GMT) |
---|---|---|
committer | axis <qt-info@nokia.com> | 2009-04-24 11:34:15 (GMT) |
commit | 8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76 (patch) | |
tree | a17e1a767a89542ab59907462206d7dcf2e504b2 /tests/auto/qtcpserver | |
download | Qt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.zip Qt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.tar.gz Qt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.tar.bz2 |
Long live Qt for S60!
Diffstat (limited to 'tests/auto/qtcpserver')
-rw-r--r-- | tests/auto/qtcpserver/.gitignore | 3 | ||||
-rw-r--r-- | tests/auto/qtcpserver/crashingServer/crashingServer.pro | 8 | ||||
-rw-r--r-- | tests/auto/qtcpserver/crashingServer/main.cpp | 70 | ||||
-rw-r--r-- | tests/auto/qtcpserver/qtcpserver.pro | 5 | ||||
-rw-r--r-- | tests/auto/qtcpserver/test/test.pro | 38 | ||||
-rw-r--r-- | tests/auto/qtcpserver/tst_qtcpserver.cpp | 858 |
6 files changed, 982 insertions, 0 deletions
diff --git a/tests/auto/qtcpserver/.gitignore b/tests/auto/qtcpserver/.gitignore new file mode 100644 index 0000000..c00e0a4 --- /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 0000000..70e42b4 --- /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 0000000..d632eb78 --- /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) || defined(Q_OS_SYMBIAN) + QFile file(QLatin1String("/test_signal.txt")); + file.open(QIODevice::WriteOnly); + file.write("Listening\n"); + file.flush(); + file.close(); +#else + printf("Listening\n"); + fflush(stdout); +#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 0000000..fe5ea37 --- /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 0000000..bdeaa92 --- /dev/null +++ b/tests/auto/qtcpserver/test/test.pro @@ -0,0 +1,38 @@ +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 +} +} + +symbian { + crashApp.sources = $$QT_BUILD_TREE/examples/widgets/wiggly/$${BUILD_DIR}/crashingServer.exe + crashApp.path = . + DEPLOYMENT += crashApp +} + +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 0000000..199886b --- /dev/null +++ b/tests/auto/qtcpserver/tst_qtcpserver.cpp @@ -0,0 +1,858 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +// Just to get Q_OS_SYMBIAN +#include <qglobal.h> +#if defined(_WIN32) && !defined(Q_OS_SYMBIAN) +#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() +{ + Q_SET_DEFAULT_IAP +} + +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() +{ +#if defined(Q_OS_SYMBIAN) + QSKIP("Symbian: IPv6 is not yet supported", SkipAll); +#endif + //### 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() +{ +#if defined(Q_OS_SYMBIAN) + QSKIP("Symbian: IPv6 is not yet supported", SkipAll); +#endif + 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(QtNetworkSettings::serverName(), 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(), 143); + 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) || defined(Q_OS_SYMBIAN) + QVERIFY(server.waitForNewConnection(9000, &timeout)); +#else + QVERIFY(server.waitForNewConnection(3000, &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; +#if defined(Q_OS_SYMBIAN) + arg = fcntl(socketDescriptor, F_GETFL, NULL); + arg &= (~O_NONBLOCK); + ok = ::fcntl(socketDescriptor, F_SETFL, arg) != -1; +#elif defined(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(Q_OS_SYMBIAN) && defined(Q_CC_NOKIAX86) + QSKIP("Symbian: Emulator does not support process launching", SkipAll ); +#endif + +#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) || defined(Q_OS_SYMBIAN) + 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 << 143 + << 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" |