tests/auto/qtcpserver/tst_qtcpserver.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 // Just to get Q_OS_SYMBIAN
       
    43 #include <qglobal.h>
       
    44 #if defined(_WIN32) && !defined(Q_OS_SYMBIAN)
       
    45 #include <winsock2.h>
       
    46 #else
       
    47 #include <sys/types.h>
       
    48 #include <sys/socket.h>
       
    49 #define SOCKET int
       
    50 #define INVALID_SOCKET -1
       
    51 #endif
       
    52 
       
    53 #include <QtTest/QtTest>
       
    54 
       
    55 #ifndef Q_OS_WIN
       
    56 #include <unistd.h>
       
    57 #include <sys/ioctl.h>
       
    58 #endif
       
    59 
       
    60 #include <qcoreapplication.h>
       
    61 #include <qtcpsocket.h>
       
    62 #include <qtcpserver.h>
       
    63 #include <qhostaddress.h>
       
    64 #include <qprocess.h>
       
    65 #include <qstringlist.h>
       
    66 #include <qplatformdefs.h>
       
    67 #include <qhostinfo.h>
       
    68 
       
    69 #ifdef TEST_QNETWORK_PROXY
       
    70 # include <QNetworkProxy>
       
    71 Q_DECLARE_METATYPE(QNetworkProxy)
       
    72 Q_DECLARE_METATYPE(QList<QNetworkProxy>)
       
    73 #endif
       
    74 
       
    75 #include "../network-settings.h"
       
    76 
       
    77 //TESTED_CLASS=
       
    78 //TESTED_FILES=
       
    79 
       
    80 class tst_QTcpServer : public QObject
       
    81 {
       
    82     Q_OBJECT
       
    83 
       
    84 public:
       
    85     tst_QTcpServer();
       
    86     virtual ~tst_QTcpServer();
       
    87 
       
    88 
       
    89 public slots:
       
    90     void initTestCase_data();
       
    91     void init();
       
    92     void cleanup();
       
    93 private slots:
       
    94     void getSetCheck();
       
    95     void constructing();
       
    96     void clientServerLoop();
       
    97     void ipv6Server();
       
    98     void ipv4LoopbackPerformanceTest();
       
    99     void ipv6LoopbackPerformanceTest();
       
   100     void ipv4PerformanceTest();
       
   101     void crashTests();
       
   102     void maxPendingConnections();
       
   103     void listenError();
       
   104     void waitForConnectionTest();
       
   105     void setSocketDescriptor();
       
   106     void listenWhileListening();
       
   107     void addressReusable();
       
   108     void setNewSocketDescriptorBlocking();
       
   109 #ifdef TEST_QNETWORK_PROXY
       
   110     void invalidProxy_data();
       
   111     void invalidProxy();
       
   112     void proxyFactory_data();
       
   113     void proxyFactory();
       
   114 #endif
       
   115 };
       
   116 
       
   117 // Testing get/set functions
       
   118 void tst_QTcpServer::getSetCheck()
       
   119 {
       
   120     QTcpServer obj1;
       
   121     // int QTcpServer::maxPendingConnections()
       
   122     // void QTcpServer::setMaxPendingConnections(int)
       
   123     obj1.setMaxPendingConnections(0);
       
   124     QCOMPARE(0, obj1.maxPendingConnections());
       
   125     obj1.setMaxPendingConnections(INT_MIN);
       
   126     QCOMPARE(INT_MIN, obj1.maxPendingConnections());
       
   127     obj1.setMaxPendingConnections(INT_MAX);
       
   128     QCOMPARE(INT_MAX, obj1.maxPendingConnections());
       
   129 }
       
   130 
       
   131 tst_QTcpServer::tst_QTcpServer()
       
   132 {
       
   133     Q_SET_DEFAULT_IAP
       
   134 }
       
   135 
       
   136 tst_QTcpServer::~tst_QTcpServer()
       
   137 {
       
   138 }
       
   139 
       
   140 void tst_QTcpServer::initTestCase_data()
       
   141 {
       
   142     QTest::addColumn<bool>("setProxy");
       
   143     QTest::addColumn<int>("proxyType");
       
   144 
       
   145     QTest::newRow("WithoutProxy") << false << 0;
       
   146 #ifdef TEST_QNETWORK_PROXY
       
   147     QTest::newRow("WithSocks5Proxy") << true << int(QNetworkProxy::Socks5Proxy);
       
   148 #endif
       
   149 }
       
   150 
       
   151 void tst_QTcpServer::init()
       
   152 {
       
   153     QFETCH_GLOBAL(bool, setProxy);
       
   154     if (setProxy) {
       
   155 #ifdef TEST_QNETWORK_PROXY
       
   156         QFETCH_GLOBAL(int, proxyType);
       
   157         if (proxyType == QNetworkProxy::Socks5Proxy) {
       
   158             QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080));
       
   159         }
       
   160 #endif
       
   161     }
       
   162 }
       
   163 
       
   164 void tst_QTcpServer::cleanup()
       
   165 {
       
   166 #ifdef TEST_QNETWORK_PROXY
       
   167     QNetworkProxy::setApplicationProxy(QNetworkProxy::DefaultProxy);
       
   168 #endif
       
   169 }
       
   170 
       
   171 //----------------------------------------------------------------------------------
       
   172 
       
   173 void tst_QTcpServer::constructing()
       
   174 {
       
   175     QTcpServer socket;
       
   176 
       
   177     // Check the initial state of the QTcpSocket.
       
   178     QCOMPARE(socket.isListening(), false);
       
   179     QCOMPARE((int)socket.serverPort(), 0);
       
   180     QCOMPARE(socket.serverAddress(), QHostAddress());
       
   181     QCOMPARE(socket.maxPendingConnections(), 30);
       
   182     QCOMPARE(socket.hasPendingConnections(), false);
       
   183     QCOMPARE(socket.socketDescriptor(), -1);
       
   184     QCOMPARE(socket.serverError(), QAbstractSocket::UnknownSocketError);
       
   185 
       
   186     // Check the state of the socket layer?
       
   187 }
       
   188 
       
   189 //----------------------------------------------------------------------------------
       
   190 void tst_QTcpServer::clientServerLoop()
       
   191 {
       
   192     QTcpServer server;
       
   193 
       
   194     QSignalSpy spy(&server, SIGNAL(newConnection()));
       
   195 
       
   196     QVERIFY(!server.isListening());
       
   197     QVERIFY(!server.hasPendingConnections());
       
   198     QVERIFY(server.listen(QHostAddress::Any, 11423));
       
   199     QVERIFY(server.isListening());
       
   200 
       
   201     QTcpSocket client;
       
   202 
       
   203     QHostAddress serverAddress = QHostAddress::LocalHost;
       
   204     if (!(server.serverAddress() == QHostAddress::Any))
       
   205         serverAddress = server.serverAddress();
       
   206 
       
   207     client.connectToHost(serverAddress, server.serverPort());
       
   208     QVERIFY(client.waitForConnected(5000));
       
   209 
       
   210     QVERIFY(server.waitForNewConnection(5000));
       
   211     QVERIFY(server.hasPendingConnections());
       
   212 
       
   213     QCOMPARE(spy.count(), 1);
       
   214 
       
   215     QTcpSocket *serverSocket = server.nextPendingConnection();
       
   216     QVERIFY(serverSocket != 0);
       
   217 
       
   218     QVERIFY(serverSocket->write("Greetings, client!\n", 19) == 19);
       
   219     serverSocket->flush();
       
   220 
       
   221     QVERIFY(client.waitForReadyRead(5000));
       
   222     QByteArray arr = client.readAll();
       
   223     QCOMPARE(arr.constData(), "Greetings, client!\n");
       
   224 
       
   225     QVERIFY(client.write("Well, hello to you!\n", 20) == 20);
       
   226     client.flush();
       
   227 
       
   228     QVERIFY(serverSocket->waitForReadyRead(5000));
       
   229     arr = serverSocket->readAll();
       
   230     QCOMPARE(arr.constData(), "Well, hello to you!\n");
       
   231 }
       
   232 
       
   233 //----------------------------------------------------------------------------------
       
   234 void tst_QTcpServer::ipv6Server()
       
   235 {
       
   236 #if defined(Q_OS_SYMBIAN)
       
   237     QSKIP("Symbian: IPv6 is not yet supported", SkipAll);
       
   238 #endif
       
   239     //### need to enter the event loop for the server to get the connection ?? ( windows)
       
   240     QTcpServer server;
       
   241     if (!server.listen(QHostAddress::LocalHostIPv6, 8944)) {
       
   242         QVERIFY(server.serverError() == QAbstractSocket::UnsupportedSocketOperationError);
       
   243         return;
       
   244     }
       
   245 
       
   246     QVERIFY(server.serverPort() == 8944);
       
   247     QVERIFY(server.serverAddress() == QHostAddress::LocalHostIPv6);
       
   248 
       
   249     QTcpSocket client;
       
   250     client.connectToHost("::1", 8944);
       
   251     QVERIFY(client.waitForConnected(5000));
       
   252 
       
   253     QVERIFY(server.waitForNewConnection());
       
   254     QVERIFY(server.hasPendingConnections());
       
   255 
       
   256     QTcpSocket *serverSocket = 0;
       
   257     QVERIFY((serverSocket = server.nextPendingConnection()));
       
   258 }
       
   259 
       
   260 //----------------------------------------------------------------------------------
       
   261 void tst_QTcpServer::ipv4LoopbackPerformanceTest()
       
   262 {
       
   263     QFETCH_GLOBAL(bool, setProxy);
       
   264     if (setProxy)
       
   265         return;
       
   266 
       
   267     QTcpServer server;
       
   268     QVERIFY(server.listen(QHostAddress::LocalHost));
       
   269 
       
   270     QVERIFY(server.isListening());
       
   271 
       
   272     QTcpSocket clientA;
       
   273     clientA.connectToHost(QHostAddress::LocalHost, server.serverPort());
       
   274     QVERIFY(clientA.waitForConnected(5000));
       
   275     QVERIFY(clientA.state() == QAbstractSocket::ConnectedState);
       
   276 
       
   277     QVERIFY(server.waitForNewConnection());
       
   278     QTcpSocket *clientB = server.nextPendingConnection();
       
   279     QVERIFY(clientB);
       
   280 
       
   281     QByteArray buffer(16384, '@');
       
   282     QTime stopWatch;
       
   283     stopWatch.start();
       
   284     qlonglong totalWritten = 0;
       
   285     while (stopWatch.elapsed() < 5000) {
       
   286         QVERIFY(clientA.write(buffer.data(), buffer.size()) > 0);
       
   287         clientA.flush();
       
   288         totalWritten += buffer.size();
       
   289         while (clientB->waitForReadyRead(100)) {
       
   290             if (clientB->bytesAvailable() == 16384)
       
   291                 break;
       
   292         }
       
   293         clientB->read(buffer.data(), buffer.size());
       
   294         clientB->write(buffer.data(), buffer.size());
       
   295         clientB->flush();
       
   296         totalWritten += buffer.size();
       
   297         while (clientA.waitForReadyRead(100)) {
       
   298             if (clientA.bytesAvailable() == 16384)
       
   299                 break;
       
   300         }
       
   301         clientA.read(buffer.data(), buffer.size());
       
   302     }
       
   303 
       
   304     qDebug("\t\t%s: %.1fMB/%.1fs: %.1fMB/s",
       
   305            server.serverAddress().toString().toLatin1().constData(),
       
   306            totalWritten / (1024.0 * 1024.0),
       
   307            stopWatch.elapsed() / 1000.0,
       
   308            (totalWritten / (stopWatch.elapsed() / 1000.0)) / (1024 * 1024));
       
   309 
       
   310     delete clientB;
       
   311 }
       
   312 
       
   313 //----------------------------------------------------------------------------------
       
   314 void tst_QTcpServer::ipv6LoopbackPerformanceTest()
       
   315 {
       
   316 #if defined(Q_OS_SYMBIAN)
       
   317     QSKIP("Symbian: IPv6 is not yet supported", SkipAll);
       
   318 #endif
       
   319     QTcpServer server;
       
   320     if (!server.listen(QHostAddress::LocalHostIPv6, 0)) {
       
   321         QVERIFY(server.serverError() == QAbstractSocket::UnsupportedSocketOperationError);
       
   322     } else {
       
   323         QTcpSocket clientA;
       
   324         clientA.connectToHost(server.serverAddress(), server.serverPort());
       
   325         QVERIFY(clientA.waitForConnected(5000));
       
   326 
       
   327         QVERIFY(server.waitForNewConnection(5000));
       
   328         QTcpSocket *clientB = server.nextPendingConnection();
       
   329         QVERIFY(clientB);
       
   330 
       
   331         QByteArray buffer(16384, '@');
       
   332         QTime stopWatch;
       
   333         stopWatch.start();
       
   334         qlonglong totalWritten = 0;
       
   335         while (stopWatch.elapsed() < 5000) {
       
   336             clientA.write(buffer.data(), buffer.size());
       
   337             clientA.flush();
       
   338             totalWritten += buffer.size();
       
   339             while (clientB->waitForReadyRead(100)) {
       
   340                 if (clientB->bytesAvailable() == 16384)
       
   341                     break;
       
   342             }
       
   343             clientB->read(buffer.data(), buffer.size());
       
   344             clientB->write(buffer.data(), buffer.size());
       
   345             clientB->flush();
       
   346             totalWritten += buffer.size();
       
   347             while (clientA.waitForReadyRead(100)) {
       
   348                 if (clientA.bytesAvailable() == 16384)
       
   349                    break;
       
   350             }
       
   351             clientA.read(buffer.data(), buffer.size());
       
   352         }
       
   353 
       
   354         qDebug("\t\t%s: %.1fMB/%.1fs: %.1fMB/s",
       
   355                server.serverAddress().toString().toLatin1().constData(),
       
   356                totalWritten / (1024.0 * 1024.0),
       
   357                stopWatch.elapsed() / 1000.0,
       
   358                (totalWritten / (stopWatch.elapsed() / 1000.0)) / (1024 * 1024));
       
   359         delete clientB;
       
   360     }
       
   361 }
       
   362 
       
   363 //----------------------------------------------------------------------------------
       
   364 void tst_QTcpServer::ipv4PerformanceTest()
       
   365 {
       
   366     QTcpSocket probeSocket;
       
   367     probeSocket.connectToHost(QtNetworkSettings::serverName(), 143);
       
   368     QVERIFY(probeSocket.waitForConnected(5000));
       
   369 
       
   370     QTcpServer server;
       
   371     QVERIFY(server.listen(probeSocket.localAddress(), 0));
       
   372 
       
   373     QTcpSocket clientA;
       
   374     clientA.connectToHost(server.serverAddress(), server.serverPort());
       
   375     QVERIFY(clientA.waitForConnected(5000));
       
   376 
       
   377     QVERIFY(server.waitForNewConnection(5000));
       
   378     QTcpSocket *clientB = server.nextPendingConnection();
       
   379     QVERIFY(clientB);
       
   380 
       
   381     QByteArray buffer(16384, '@');
       
   382     QTime stopWatch;
       
   383     stopWatch.start();
       
   384     qlonglong totalWritten = 0;
       
   385     while (stopWatch.elapsed() < 5000) {
       
   386         qlonglong writtenA = clientA.write(buffer.data(), buffer.size());
       
   387         clientA.flush();
       
   388         totalWritten += buffer.size();
       
   389         while (clientB->waitForReadyRead(100)) {
       
   390             if (clientB->bytesAvailable() == writtenA)
       
   391                 break;
       
   392         }
       
   393         clientB->read(buffer.data(), buffer.size());
       
   394         qlonglong writtenB = clientB->write(buffer.data(), buffer.size());
       
   395         clientB->flush();
       
   396         totalWritten += buffer.size();
       
   397         while (clientA.waitForReadyRead(100)) {
       
   398             if (clientA.bytesAvailable() == writtenB)
       
   399                break;
       
   400         }
       
   401         clientA.read(buffer.data(), buffer.size());
       
   402     }
       
   403 
       
   404     qDebug("\t\t%s: %.1fMB/%.1fs: %.1fMB/s",
       
   405            probeSocket.localAddress().toString().toLatin1().constData(),
       
   406            totalWritten / (1024.0 * 1024.0),
       
   407            stopWatch.elapsed() / 1000.0,
       
   408            (totalWritten / (stopWatch.elapsed() / 1000.0)) / (1024 * 1024));
       
   409 
       
   410     delete clientB;
       
   411 }
       
   412 
       
   413 //----------------------------------------------------------------------------------
       
   414 void tst_QTcpServer::crashTests()
       
   415 {
       
   416     QTcpServer server;
       
   417     server.close();
       
   418     QVERIFY(server.listen());
       
   419 }
       
   420 
       
   421 //----------------------------------------------------------------------------------
       
   422 void tst_QTcpServer::maxPendingConnections()
       
   423 {
       
   424     QFETCH_GLOBAL(bool, setProxy);
       
   425     if (setProxy) {
       
   426 #ifdef TEST_QNETWORK_PROXY
       
   427         QFETCH_GLOBAL(int, proxyType);
       
   428         if (proxyType == QNetworkProxy::Socks5Proxy) {
       
   429             QSKIP("With socks5 only 1 connection is allowed ever", SkipAll);
       
   430         }
       
   431 #endif
       
   432     }
       
   433     //### sees to fail sometimes ... a timing issue with the test on windows
       
   434     QTcpServer server;
       
   435     server.setMaxPendingConnections(2);
       
   436 
       
   437     QTcpSocket socket1;
       
   438     QTcpSocket socket2;
       
   439     QTcpSocket socket3;
       
   440 
       
   441     QVERIFY(server.listen());
       
   442 
       
   443     socket1.connectToHost(QHostAddress::LocalHost, server.serverPort());
       
   444     socket2.connectToHost(QHostAddress::LocalHost, server.serverPort());
       
   445     socket3.connectToHost(QHostAddress::LocalHost, server.serverPort());
       
   446 
       
   447     QVERIFY(server.waitForNewConnection(5000));
       
   448 
       
   449     QVERIFY(server.hasPendingConnections());
       
   450     QVERIFY(server.nextPendingConnection());
       
   451     QVERIFY(server.hasPendingConnections());
       
   452     QVERIFY(server.nextPendingConnection());
       
   453     QVERIFY(!server.hasPendingConnections());
       
   454     QCOMPARE(server.nextPendingConnection(), (QTcpSocket*)0);
       
   455 
       
   456     QVERIFY(server.waitForNewConnection(5000));
       
   457 
       
   458     QVERIFY(server.hasPendingConnections());
       
   459     QVERIFY(server.nextPendingConnection());
       
   460 }
       
   461 
       
   462 //----------------------------------------------------------------------------------
       
   463 void tst_QTcpServer::listenError()
       
   464 {
       
   465     QFETCH_GLOBAL(bool, setProxy);
       
   466     if (setProxy) {
       
   467 #ifdef TEST_QNETWORK_PROXY
       
   468         QFETCH_GLOBAL(int, proxyType);
       
   469         if (proxyType == QNetworkProxy::Socks5Proxy) {
       
   470             QSKIP("With socks5 we can not make hard requirements on the address or port", SkipAll);
       
   471         }
       
   472 #endif
       
   473     }
       
   474     QTcpServer server;
       
   475     QVERIFY(!server.listen(QHostAddress("1.2.3.4"), 0));
       
   476     QCOMPARE(server.serverError(), QAbstractSocket::SocketAddressNotAvailableError);
       
   477     QCOMPARE(server.errorString().toLatin1().constData(), "The address is not available");
       
   478 }
       
   479 
       
   480 class ThreadConnector : public QThread
       
   481 {
       
   482 public:
       
   483     ThreadConnector(const QHostAddress &host, quint16 port)
       
   484         : host(host), port(port)
       
   485     { }
       
   486 
       
   487     ~ThreadConnector()
       
   488     {
       
   489         wait();
       
   490     }
       
   491 
       
   492 protected:
       
   493     void run()
       
   494     {
       
   495         sleep(2);
       
   496 
       
   497         QTcpSocket socket;
       
   498         socket.connectToHost(host, port);
       
   499 
       
   500         QEventLoop loop;
       
   501         QTimer::singleShot(5000, &loop, SLOT(quit()));
       
   502         loop.exec();
       
   503     }
       
   504 
       
   505 private:
       
   506     QHostAddress host;
       
   507     quint16 port;
       
   508 };
       
   509 
       
   510 //----------------------------------------------------------------------------------
       
   511 void tst_QTcpServer::waitForConnectionTest()
       
   512 {
       
   513 
       
   514     QFETCH_GLOBAL(bool, setProxy);
       
   515     if (setProxy) {
       
   516 #ifdef TEST_QNETWORK_PROXY
       
   517         QFETCH_GLOBAL(int, proxyType);
       
   518         if (proxyType == QNetworkProxy::Socks5Proxy) {
       
   519             QSKIP("Localhost servers don't work well with SOCKS5", SkipAll);
       
   520         }
       
   521 #endif
       
   522     }
       
   523 
       
   524     QTcpSocket findLocalIpSocket;
       
   525     findLocalIpSocket.connectToHost(QtNetworkSettings::serverName(), 143);
       
   526     QVERIFY(findLocalIpSocket.waitForConnected(2000));
       
   527 
       
   528     QTcpServer server;
       
   529     bool timeout = false;
       
   530     QVERIFY(server.listen(findLocalIpSocket.localAddress()));
       
   531     QVERIFY(!server.waitForNewConnection(1000, &timeout));
       
   532     QCOMPARE(server.serverError(), QAbstractSocket::SocketTimeoutError);
       
   533     QVERIFY(timeout);
       
   534 
       
   535     ThreadConnector connector(findLocalIpSocket.localAddress(), server.serverPort());
       
   536     connector.start();
       
   537 
       
   538 #if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
       
   539     QVERIFY(server.waitForNewConnection(9000, &timeout));
       
   540 #else
       
   541     QVERIFY(server.waitForNewConnection(3000, &timeout));
       
   542 #endif
       
   543     QVERIFY(!timeout);
       
   544 }
       
   545 
       
   546 //----------------------------------------------------------------------------------
       
   547 void tst_QTcpServer::setSocketDescriptor()
       
   548 {
       
   549     QTcpServer server;
       
   550     QVERIFY(!server.setSocketDescriptor(42));
       
   551     QCOMPARE(server.serverError(), QAbstractSocket::UnsupportedSocketOperationError);
       
   552 
       
   553 #ifdef Q_OS_WIN
       
   554     // ensure winsock is started
       
   555     WSADATA wsaData;
       
   556     QVERIFY(WSAStartup(MAKEWORD(2,0), &wsaData) == NO_ERROR);
       
   557 #endif
       
   558 
       
   559     SOCKET sock = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
       
   560 
       
   561     QVERIFY(sock != INVALID_SOCKET);
       
   562 
       
   563     sockaddr_in sin;
       
   564     memset(&sin, 0, sizeof(sockaddr_in));
       
   565     sin.sin_family = AF_INET;
       
   566     sin.sin_port = 0;
       
   567     sin.sin_addr.s_addr = 0x00000000;
       
   568     QVERIFY(::bind(sock, (sockaddr*)&sin, sizeof(sockaddr_in)) == 0);
       
   569     QVERIFY(::listen(sock, 10) == 0);
       
   570     QVERIFY(server.setSocketDescriptor(sock));
       
   571 
       
   572 #ifdef Q_OS_WIN
       
   573     WSACleanup();
       
   574 #endif
       
   575 }
       
   576 
       
   577 //----------------------------------------------------------------------------------
       
   578 void tst_QTcpServer::listenWhileListening()
       
   579 {
       
   580     QTcpServer server;
       
   581     QVERIFY(server.listen());
       
   582     QTest::ignoreMessage(QtWarningMsg, "QTcpServer::listen() called when already listening");
       
   583     QVERIFY(!server.listen());
       
   584 }
       
   585 
       
   586 //----------------------------------------------------------------------------------
       
   587 
       
   588 class SeverWithBlockingSockets : public QTcpServer
       
   589 {
       
   590 public:
       
   591     SeverWithBlockingSockets()
       
   592         : ok(false) { }
       
   593 
       
   594     bool ok;
       
   595 
       
   596 protected:
       
   597     void incomingConnection(int socketDescriptor)
       
   598     {
       
   599         // how a user woulddo it (qabstractsocketengine is not public)
       
   600         unsigned long arg = 0;
       
   601 #if defined(Q_OS_SYMBIAN)
       
   602         arg = fcntl(socketDescriptor, F_GETFL, NULL);
       
   603         arg &= (~O_NONBLOCK);
       
   604         ok = ::fcntl(socketDescriptor, F_SETFL, arg) != -1;
       
   605 #elif defined(Q_OS_WIN)
       
   606         ok = ::ioctlsocket(socketDescriptor, FIONBIO, &arg) == 0;
       
   607         ::closesocket(socketDescriptor);
       
   608 #else
       
   609         ok = ::ioctl(socketDescriptor, FIONBIO, &arg) == 0;
       
   610         ::close(socketDescriptor);
       
   611 #endif
       
   612     }
       
   613 };
       
   614 
       
   615 void tst_QTcpServer::addressReusable()
       
   616 {
       
   617 #if defined(Q_OS_SYMBIAN) && defined(Q_CC_NOKIAX86)
       
   618     QSKIP("Symbian: Emulator does not support process launching", SkipAll );
       
   619 #endif
       
   620 
       
   621 #if defined(QT_NO_PROCESS)
       
   622     QSKIP("Qt was compiled with QT_NO_PROCESS", SkipAll);
       
   623 #else
       
   624 
       
   625     QFETCH_GLOBAL(bool, setProxy);
       
   626     if (setProxy) {
       
   627 #ifdef TEST_QNETWORK_PROXY
       
   628         QFETCH_GLOBAL(int, proxyType);
       
   629         if (proxyType == QNetworkProxy::Socks5Proxy) {
       
   630             QSKIP("With socks5 this test does not make senans at the momment", SkipAll);
       
   631         }
       
   632 #endif
       
   633     }
       
   634 #if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
       
   635     QString signalName = QString::fromLatin1("/test_signal.txt");
       
   636     QFile::remove(signalName);
       
   637     // The crashingServer process will crash once it gets a connection.
       
   638     QProcess process;
       
   639     process.start("crashingServer/crashingServer");
       
   640     int waitCount = 5;
       
   641     while (waitCount-- && !QFile::exists(signalName))
       
   642         QTest::qWait(1000);
       
   643     QVERIFY(QFile::exists(signalName));
       
   644     QFile::remove(signalName);
       
   645 #else
       
   646     // The crashingServer process will crash once it gets a connection.
       
   647     QProcess process;
       
   648     process.start("crashingServer/crashingServer");
       
   649     QVERIFY(process.waitForReadyRead(5000));
       
   650 #endif
       
   651 
       
   652     QTcpSocket socket;
       
   653     socket.connectToHost(QHostAddress::LocalHost, 49199);
       
   654     QVERIFY(socket.waitForConnected(5000));
       
   655 
       
   656     QVERIFY(process.waitForFinished(5000));
       
   657 
       
   658     // Give the system some time.
       
   659     QTest::qSleep(10);
       
   660 
       
   661     QTcpServer server;
       
   662     QVERIFY(server.listen(QHostAddress::LocalHost, 49199));
       
   663 #endif
       
   664 }
       
   665 
       
   666 void tst_QTcpServer::setNewSocketDescriptorBlocking()
       
   667 {
       
   668     QFETCH_GLOBAL(bool, setProxy);
       
   669     if (setProxy) {
       
   670 #ifdef TEST_QNETWORK_PROXY
       
   671         QFETCH_GLOBAL(int, proxyType);
       
   672         if (proxyType == QNetworkProxy::Socks5Proxy) {
       
   673             QSKIP("With socks5 we can not make the socket descripter blocking", SkipAll);
       
   674         }
       
   675 #endif
       
   676     }
       
   677     SeverWithBlockingSockets server;
       
   678     QVERIFY(server.listen());
       
   679 
       
   680     QTcpSocket socket;
       
   681     socket.connectToHost(QHostAddress::LocalHost, server.serverPort());
       
   682     QVERIFY(server.waitForNewConnection(5000));
       
   683     QVERIFY(server.ok);
       
   684 }
       
   685 
       
   686 #ifdef TEST_QNETWORK_PROXY
       
   687 void tst_QTcpServer::invalidProxy_data()
       
   688 {
       
   689     QTest::addColumn<int>("type");
       
   690     QTest::addColumn<QString>("host");
       
   691     QTest::addColumn<int>("port");
       
   692     QTest::addColumn<int>("expectedError");
       
   693 
       
   694     QString fluke = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString();
       
   695     QTest::newRow("ftp-proxy") << int(QNetworkProxy::FtpCachingProxy) << fluke << 143
       
   696                                << int(QAbstractSocket::UnsupportedSocketOperationError);
       
   697     QTest::newRow("http-proxy") << int(QNetworkProxy::HttpProxy) << fluke << 3128
       
   698                                 << int(QAbstractSocket::UnsupportedSocketOperationError);
       
   699 
       
   700     QTest::newRow("no-such-host") << int(QNetworkProxy::Socks5Proxy)
       
   701                                   << "this-host-will-never-exist.troll.no" << 1080
       
   702                                   << int(QAbstractSocket::ProxyNotFoundError);
       
   703     QTest::newRow("socks5-on-http") << int(QNetworkProxy::Socks5Proxy) << fluke << 3128
       
   704                                     << int(QAbstractSocket::SocketTimeoutError);
       
   705 }
       
   706 
       
   707 void tst_QTcpServer::invalidProxy()
       
   708 {
       
   709     QFETCH_GLOBAL(bool, setProxy);
       
   710     if (setProxy)
       
   711         return;
       
   712 
       
   713     QFETCH(int, type);
       
   714     QFETCH(QString, host);
       
   715     QFETCH(int, port);
       
   716     QNetworkProxy::ProxyType proxyType = QNetworkProxy::ProxyType(type);
       
   717     QNetworkProxy proxy(proxyType, host, port);
       
   718 
       
   719     QTcpServer server;
       
   720     server.setProxy(proxy);
       
   721     bool listenResult = server.listen();
       
   722 
       
   723     QVERIFY(!listenResult);
       
   724     QVERIFY(!server.errorString().isEmpty());
       
   725 
       
   726     // note: the following test is not a hard failure.
       
   727     // Sometimes, error codes change for the better
       
   728     QTEST(int(server.serverError()), "expectedError");
       
   729 }
       
   730 
       
   731 // copied from tst_qnetworkreply.cpp
       
   732 class MyProxyFactory: public QNetworkProxyFactory
       
   733 {
       
   734 public:
       
   735     int callCount;
       
   736     QList<QNetworkProxy> toReturn;
       
   737     QNetworkProxyQuery lastQuery;
       
   738     inline MyProxyFactory() { clear(); }
       
   739 
       
   740     inline void clear()
       
   741     {
       
   742         callCount = 0;
       
   743         toReturn = QList<QNetworkProxy>() << QNetworkProxy::DefaultProxy;
       
   744         lastQuery = QNetworkProxyQuery();
       
   745     }
       
   746 
       
   747     virtual QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query)
       
   748     {
       
   749         lastQuery = query;
       
   750         ++callCount;
       
   751         return toReturn;
       
   752     }
       
   753 };
       
   754 
       
   755 void tst_QTcpServer::proxyFactory_data()
       
   756 {
       
   757     QTest::addColumn<QList<QNetworkProxy> >("proxyList");
       
   758     QTest::addColumn<QNetworkProxy>("proxyUsed");
       
   759     QTest::addColumn<bool>("fails");
       
   760     QTest::addColumn<int>("expectedError");
       
   761 
       
   762     QList<QNetworkProxy> proxyList;
       
   763 
       
   764     // tests that do get to listen
       
   765 
       
   766     proxyList << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080);
       
   767     QTest::newRow("socks5")
       
   768         << proxyList << proxyList.at(0)
       
   769         << false << int(QAbstractSocket::UnknownSocketError);
       
   770 
       
   771     proxyList.clear();
       
   772     proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3128)
       
   773               << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080);
       
   774     QTest::newRow("cachinghttp+socks5")
       
   775         << proxyList << proxyList.at(1)
       
   776         << false << int(QAbstractSocket::UnknownSocketError);
       
   777 
       
   778     proxyList.clear();
       
   779     proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121)
       
   780               << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3128)
       
   781               << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080);
       
   782     QTest::newRow("ftp+cachinghttp+socks5")
       
   783         << proxyList << proxyList.at(2)
       
   784         << false << int(QAbstractSocket::UnknownSocketError);
       
   785 
       
   786     // tests that fail to listen
       
   787     proxyList.clear();
       
   788     proxyList << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3128);
       
   789     QTest::newRow("http")
       
   790         << proxyList << proxyList.at(0)
       
   791         << true << int(QAbstractSocket::UnsupportedSocketOperationError);
       
   792 
       
   793     proxyList.clear();
       
   794     proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3128);
       
   795     QTest::newRow("cachinghttp")
       
   796         << proxyList << QNetworkProxy()
       
   797         << true << int(QAbstractSocket::UnsupportedSocketOperationError);
       
   798 
       
   799     proxyList.clear();
       
   800     proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121);
       
   801     QTest::newRow("ftp")
       
   802         << proxyList << QNetworkProxy()
       
   803         << true << int(QAbstractSocket::UnsupportedSocketOperationError);
       
   804 
       
   805     proxyList.clear();
       
   806     proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121)
       
   807               << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3128);
       
   808     QTest::newRow("ftp+cachinghttp")
       
   809         << proxyList << QNetworkProxy()
       
   810         << true << int(QAbstractSocket::UnsupportedSocketOperationError);
       
   811 }
       
   812 
       
   813 void tst_QTcpServer::proxyFactory()
       
   814 {
       
   815     QFETCH_GLOBAL(bool, setProxy);
       
   816     if (setProxy)
       
   817         return;
       
   818 
       
   819     QFETCH(QList<QNetworkProxy>, proxyList);
       
   820     QFETCH(QNetworkProxy, proxyUsed);
       
   821     QFETCH(bool, fails);
       
   822 
       
   823     MyProxyFactory *factory = new MyProxyFactory;
       
   824     factory->toReturn = proxyList;
       
   825     QNetworkProxyFactory::setApplicationProxyFactory(factory);
       
   826 
       
   827     QTcpServer server;
       
   828     bool listenResult = server.listen();
       
   829 
       
   830     // Verify that the factory was called properly
       
   831     QCOMPARE(factory->callCount, 1);
       
   832     QCOMPARE(factory->lastQuery, QNetworkProxyQuery(0, QString(), QNetworkProxyQuery::TcpServer));
       
   833 
       
   834     QCOMPARE(listenResult, !fails);
       
   835     QCOMPARE(server.errorString().isEmpty(), !fails);
       
   836 
       
   837     // note: the following test is not a hard failure.
       
   838     // Sometimes, error codes change for the better
       
   839     QTEST(int(server.serverError()), "expectedError");
       
   840 }
       
   841 #endif
       
   842 
       
   843 QTEST_MAIN(tst_QTcpServer)
       
   844 #include "tst_qtcpserver.moc"