d8df5d344df57ac691621cfc0bc2d5338da5d23a
[profile/ivi/qtbase.git] / tests / auto / network / socket / qtcpsocket / tst_qtcpsocket.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <qglobal.h>
43
44 // To prevent windows system header files from re-defining min/max
45 #define NOMINMAX
46 #if defined(_WIN32)
47 #include <winsock2.h>
48 #else
49 #include <sys/types.h>
50 #include <sys/socket.h>
51 #include <fcntl.h>
52 #include <unistd.h>
53 #define SOCKET int
54 #define INVALID_SOCKET -1
55 #endif
56
57 #include <qplatformdefs.h>
58
59 #include <QtTest/QtTest>
60
61 #include <QAuthenticator>
62 #include <QCoreApplication>
63 #include <QEventLoop>
64 #include <QFile>
65 #include <QHostAddress>
66 #include <QHostInfo>
67 #include <QMap>
68 #include <QPointer>
69 #include <QProcess>
70 #include <QStringList>
71 #include <QTcpServer>
72 #include <QTcpSocket>
73 #ifndef QT_NO_SSL
74 #include <QSslSocket>
75 #endif
76 #include <QTextStream>
77 #include <QThread>
78 #include <QTime>
79 #include <QTimer>
80 #include <QDebug>
81 // RVCT compiles also unused inline methods
82 # include <QNetworkProxy>
83
84 #ifdef Q_OS_LINUX
85 #include <stdio.h>
86 #include <stdlib.h>
87 #include <sys/stat.h>
88 #include <unistd.h>
89 #endif
90
91 #include "private/qhostinfo_p.h"
92
93 #include "../../../network-settings.h"
94
95 QT_FORWARD_DECLARE_CLASS(QTcpSocket)
96 class SocketPair;
97
98 class tst_QTcpSocket : public QObject
99 {
100     Q_OBJECT
101
102 public:
103     tst_QTcpSocket();
104     virtual ~tst_QTcpSocket();
105
106     static void enterLoop(int secs)
107     {
108         ++loopLevel;
109         QTestEventLoop::instance().enterLoop(secs);
110         --loopLevel;
111     }
112     static void exitLoop()
113     {
114         // Safe exit - if we aren't in an event loop, don't
115         // exit one.
116         if (loopLevel > 0)
117             QTestEventLoop::instance().exitLoop();
118     }
119     static bool timeout()
120     {
121         return QTestEventLoop::instance().timeout();
122     }
123
124 public slots:
125     void initTestCase_data();
126     void initTestCase();
127     void init();
128     void cleanup();
129 private slots:
130     void socketsConstructedBeforeEventLoop();
131     void constructing();
132     void bind_data();
133     void bind();
134     void setInvalidSocketDescriptor();
135     void setSocketDescriptor();
136     void socketDescriptor();
137     void blockingIMAP();
138     void nonBlockingIMAP();
139     void hostNotFound();
140     void timeoutConnect_data();
141     void timeoutConnect();
142     void delayedClose();
143     void partialRead();
144     void unget();
145     void readAllAfterClose();
146     void openCloseOpenClose();
147     void connectDisconnectConnectDisconnect();
148     void disconnectWhileConnecting_data();
149     void disconnectWhileConnecting();
150     void disconnectWhileConnectingNoEventLoop_data();
151     void disconnectWhileConnectingNoEventLoop();
152     void disconnectWhileLookingUp_data();
153     void disconnectWhileLookingUp();
154     void downloadBigFile();
155     void readLine();
156     void readLineString();
157     void readChunks();
158     void waitForBytesWritten();
159     void waitForBytesWrittenMinusOne();
160     void waitForReadyRead();
161     void waitForReadyReadMinusOne();
162     void flush();
163     void synchronousApi();
164     void dontCloseOnTimeout();
165     void recursiveReadyRead();
166     void atEnd();
167     void socketInAThread();
168     void socketsInThreads();
169     void waitForReadyReadInASlot();
170     void remoteCloseError();
171     void nestedEventLoopInErrorSlot();
172 #ifndef Q_OS_WIN
173     void connectToLocalHostNoService();
174 #endif
175     void waitForConnectedInHostLookupSlot();
176     void waitForConnectedInHostLookupSlot2();
177     void readyReadSignalsAfterWaitForReadyRead();
178 #ifdef Q_OS_LINUX
179     void linuxKernelBugLocalSocket();
180 #endif
181     void abortiveClose();
182     void localAddressEmptyOnBSD();
183     void zeroAndMinusOneReturns();
184     void connectionRefused();
185     void suddenRemoteDisconnect_data();
186     void suddenRemoteDisconnect();
187     void connectToMultiIP();
188     void moveToThread0();
189     void increaseReadBufferSize();
190     void taskQtBug5799ConnectionErrorWaitForConnected();
191     void taskQtBug5799ConnectionErrorEventLoop();
192     void taskQtBug7054TimeoutErrorResetting();
193
194     void invalidProxy_data();
195     void invalidProxy();
196     void proxyFactory_data();
197     void proxyFactory();
198
199     void qtbug14268_peek();
200
201     void setSocketOption();
202
203
204 protected slots:
205     void nonBlockingIMAP_hostFound();
206     void nonBlockingIMAP_connected();
207     void nonBlockingIMAP_closed();
208     void nonBlockingIMAP_readyRead();
209     void nonBlockingIMAP_bytesWritten(qint64);
210     void readRegularFile_readyRead();
211     void exitLoopSlot();
212     void downloadBigFileSlot();
213     void recursiveReadyReadSlot();
214     void waitForReadyReadInASlotSlot();
215     void enterLoopSlot();
216     void hostLookupSlot();
217     void abortiveClose_abortSlot();
218     void remoteCloseErrorSlot();
219     void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth);
220     void earlySocketBytesSent(qint64 bytes);
221     void earlySocketReadyRead();
222
223 private:
224     QByteArray expectedReplyIMAP();
225     void fetchExpectedReplyIMAP();
226     QTcpSocket *newSocket() const;
227     QTcpSocket *nonBlockingIMAP_socket;
228     QStringList nonBlockingIMAP_data;
229     qint64 nonBlockingIMAP_totalWritten;
230
231     QTcpSocket *tmpSocket;
232     qint64 bytesAvailable;
233     qint64 expectedLength;
234     bool readingBody;
235     QTime timer;
236
237     QByteArray expectedReplyIMAP_cached;
238
239     mutable int proxyAuthCalled;
240
241     bool gotClosedSignal;
242     int numConnections;
243     static int loopLevel;
244
245     SocketPair *earlyConstructedSockets;
246     int earlyBytesWrittenCount;
247     int earlyReadyReadCount;
248     QString stressTestDir;
249 };
250
251 enum ProxyTests {
252     NoProxy = 0x00,
253     Socks5Proxy = 0x01,
254     HttpProxy = 0x02,
255     TypeMask = 0x0f,
256
257     NoAuth = 0x00,
258     AuthBasic = 0x10,
259     AuthNtlm = 0x20,
260     AuthMask = 0xf0
261 };
262
263 int tst_QTcpSocket::loopLevel = 0;
264
265 class SocketPair: public QObject
266 {
267     Q_OBJECT
268 public:
269     QTcpSocket *endPoints[2];
270
271     SocketPair(QObject *parent = 0)
272         : QObject(parent)
273     {
274         endPoints[0] = endPoints[1] = 0;
275     }
276
277     bool create()
278     {
279         QTcpServer server;
280         server.listen();
281
282         QTcpSocket *active = new QTcpSocket(this);
283         active->connectToHost("127.0.0.1", server.serverPort());
284
285         if (!active->waitForConnected(1000))
286             return false;
287
288         if (!server.waitForNewConnection(1000))
289             return false;
290
291         QTcpSocket *passive = server.nextPendingConnection();
292         passive->setParent(this);
293
294         endPoints[0] = active;
295         endPoints[1] = passive;
296         return true;
297     }
298 };
299
300 tst_QTcpSocket::tst_QTcpSocket()
301 {
302     tmpSocket = 0;
303
304     //This code relates to the socketsConstructedBeforeEventLoop test case
305     earlyConstructedSockets = new SocketPair;
306     QVERIFY(earlyConstructedSockets->create());
307     earlyBytesWrittenCount = 0;
308     earlyReadyReadCount = 0;
309     connect(earlyConstructedSockets->endPoints[0], SIGNAL(readyRead()), this, SLOT(earlySocketReadyRead()));
310     connect(earlyConstructedSockets->endPoints[1], SIGNAL(bytesWritten(qint64)), this, SLOT(earlySocketBytesSent(qint64)));
311     earlyConstructedSockets->endPoints[1]->write("hello work");
312 }
313
314 tst_QTcpSocket::~tst_QTcpSocket()
315 {
316
317 }
318
319 void tst_QTcpSocket::initTestCase_data()
320 {
321     QTest::addColumn<bool>("setProxy");
322     QTest::addColumn<int>("proxyType");
323     QTest::addColumn<bool>("ssl");
324
325     qDebug() << QtNetworkSettings::serverName();
326     QTest::newRow("WithoutProxy") << false << 0 << false;
327     QTest::newRow("WithSocks5Proxy") << true << int(Socks5Proxy) << false;
328     QTest::newRow("WithSocks5ProxyAuth") << true << int(Socks5Proxy | AuthBasic) << false;
329
330     QTest::newRow("WithHttpProxy") << true << int(HttpProxy) << false;
331     QTest::newRow("WithHttpProxyBasicAuth") << true << int(HttpProxy | AuthBasic) << false;
332 //    QTest::newRow("WithHttpProxyNtlmAuth") << true << int(HttpProxy | AuthNtlm) << false;
333
334 #ifndef QT_NO_SSL
335     QTest::newRow("WithoutProxy SSL") << false << 0 << true;
336     QTest::newRow("WithSocks5Proxy SSL") << true << int(Socks5Proxy) << true;
337     QTest::newRow("WithSocks5AuthProxy SSL") << true << int(Socks5Proxy | AuthBasic) << true;
338
339     QTest::newRow("WithHttpProxy SSL") << true << int(HttpProxy) << true;
340     QTest::newRow("WithHttpProxyBasicAuth SSL") << true << int(HttpProxy | AuthBasic) << true;
341 //    QTest::newRow("WithHttpProxyNtlmAuth SSL") << true << int(HttpProxy | AuthNtlm) << true;
342 #endif
343
344     stressTestDir = QFINDTESTDATA("stressTest");
345     QVERIFY2(!stressTestDir.isEmpty(), qPrintable(
346         QString::fromLatin1("Couldn't find stressTest dir starting from %1.").arg(QDir::currentPath())));
347 }
348
349 void tst_QTcpSocket::initTestCase()
350 {
351     QVERIFY(QtNetworkSettings::verifyTestNetworkSettings());
352 }
353
354 void tst_QTcpSocket::init()
355 {
356     QFETCH_GLOBAL(bool, setProxy);
357     if (setProxy) {
358         QFETCH_GLOBAL(int, proxyType);
359         QList<QHostAddress> addresses = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses();
360         QVERIFY2(addresses.count() > 0, "failed to get ip address for test server");
361         QString fluke = addresses.first().toString();
362         QNetworkProxy proxy;
363
364         switch (proxyType) {
365         case Socks5Proxy:
366             proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, fluke, 1080);
367             break;
368
369         case Socks5Proxy | AuthBasic:
370             proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, fluke, 1081);
371             break;
372
373         case HttpProxy | NoAuth:
374             proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3128);
375             break;
376
377         case HttpProxy | AuthBasic:
378             proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3129);
379             break;
380
381         case HttpProxy | AuthNtlm:
382             proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3130);
383             break;
384         }
385         QNetworkProxy::setApplicationProxy(proxy);
386     }
387
388     qt_qhostinfo_clear_cache();
389 }
390
391 QTcpSocket *tst_QTcpSocket::newSocket() const
392 {
393     QTcpSocket *socket;
394 #ifndef QT_NO_SSL
395     QFETCH_GLOBAL(bool, ssl);
396     socket = ssl ? new QSslSocket : new QTcpSocket;
397 #else
398     socket = new QTcpSocket;
399 #endif
400
401     proxyAuthCalled = 0;
402     connect(socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
403             SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
404             Qt::DirectConnection);
405     return socket;
406 }
407
408 void tst_QTcpSocket::cleanup()
409 {
410     QNetworkProxy::setApplicationProxy(QNetworkProxy::DefaultProxy);
411 }
412
413 void tst_QTcpSocket::proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth)
414 {
415     ++proxyAuthCalled;
416     auth->setUser("qsockstest");
417     auth->setPassword("password");
418 }
419
420 //----------------------------------------------------------------------------------
421
422 void tst_QTcpSocket::socketsConstructedBeforeEventLoop()
423 {
424     QFETCH_GLOBAL(bool, setProxy);
425     QFETCH_GLOBAL(bool, ssl);
426     if (setProxy || ssl)
427         return;
428     //This test checks that sockets constructed before QCoreApplication::exec() still emit signals
429     //see construction code in the tst_QTcpSocket constructor
430     enterLoop(3);
431     QCOMPARE(earlyBytesWrittenCount, 1);
432     QCOMPARE(earlyReadyReadCount, 1);
433     earlyConstructedSockets->endPoints[0]->close();
434     earlyConstructedSockets->endPoints[1]->close();
435 }
436
437 void tst_QTcpSocket::earlySocketBytesSent(qint64 /* bytes */)
438 {
439     earlyBytesWrittenCount++;
440 }
441
442 void tst_QTcpSocket::earlySocketReadyRead()
443 {
444     earlyReadyReadCount++;
445 }
446
447 //----------------------------------------------------------------------------------
448
449 void tst_QTcpSocket::constructing()
450 {
451     QTcpSocket *socket = newSocket();
452
453     // Check the initial state of the QTcpSocket.
454     QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
455     QVERIFY(socket->isSequential());
456     QVERIFY(!socket->isOpen());
457     QVERIFY(!socket->isValid());
458     QCOMPARE(socket->socketType(), QTcpSocket::TcpSocket);
459
460     char c;
461     QCOMPARE(socket->getChar(&c), false);
462     QCOMPARE((int) socket->bytesAvailable(), 0);
463     QCOMPARE(socket->canReadLine(), false);
464     QCOMPARE(socket->readLine(), QByteArray());
465     QCOMPARE(socket->socketDescriptor(), (qintptr)-1);
466     QCOMPARE((int) socket->localPort(), 0);
467     QVERIFY(socket->localAddress() == QHostAddress());
468     QCOMPARE((int) socket->peerPort(), 0);
469     QVERIFY(socket->peerAddress() == QHostAddress());
470     QCOMPARE(socket->error(), QTcpSocket::UnknownSocketError);
471     QCOMPARE(socket->errorString(), QString("Unknown error"));
472
473     // Check the state of the socket layer?
474     delete socket;
475 }
476
477 //----------------------------------------------------------------------------------
478
479 void tst_QTcpSocket::bind_data()
480 {
481     QTest::addColumn<QString>("stringAddr");
482     QTest::addColumn<bool>("successExpected");
483     QTest::addColumn<QString>("stringExpectedLocalAddress");
484
485     // iterate all interfaces, add all addresses on them as test data
486     QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
487     foreach (const QNetworkInterface &interface, interfaces) {
488         if (!interface.isValid())
489             continue;
490
491         foreach (const QNetworkAddressEntry &entry, interface.addressEntries()) {
492             if (entry.ip().isInSubnet(QHostAddress::parseSubnet("fe80::/10"))
493                 || entry.ip().isInSubnet(QHostAddress::parseSubnet("169.254/16")))
494                 continue; // link-local bind will fail, at least on Linux, so skip it.
495
496             QString ip(entry.ip().toString());
497             QTest::newRow(ip.toLatin1().constData()) << ip << true << ip;
498         }
499     }
500
501     // additionally, try bind to known-bad addresses, and make sure this doesn't work
502     // these ranges are guaranteed to be reserved for 'documentation purposes',
503     // and thus, should be unused in the real world. Not that I'm assuming the
504     // world is full of competent administrators, or anything.
505     QStringList knownBad;
506     knownBad << "198.51.100.1";
507     knownBad << "2001:0DB8::1";
508     foreach (const QString &badAddress, knownBad) {
509         QTest::newRow(badAddress.toLatin1().constData()) << badAddress << false << QString();
510     }
511 }
512
513 void tst_QTcpSocket::bind()
514 {
515     QFETCH_GLOBAL(bool, setProxy);
516     if (setProxy)
517         QSKIP("QTBUG-22964");
518     QFETCH(QString, stringAddr);
519     QFETCH(bool, successExpected);
520     QFETCH(QString, stringExpectedLocalAddress);
521
522     QHostAddress addr(stringAddr);
523     QHostAddress expectedLocalAddress(stringExpectedLocalAddress);
524
525     QTcpSocket *socket = newSocket();
526     qDebug() << "Binding " << addr;
527
528     if (successExpected) {
529         QVERIFY2(socket->bind(addr), qPrintable(socket->errorString()));
530     } else {
531         QVERIFY(!socket->bind(addr));
532     }
533
534     QCOMPARE(socket->localAddress(), expectedLocalAddress);
535
536     delete socket;
537 }
538
539 //----------------------------------------------------------------------------------
540
541
542 void tst_QTcpSocket::setInvalidSocketDescriptor()
543 {
544     QTcpSocket *socket = newSocket();
545     QCOMPARE(socket->socketDescriptor(), (qintptr)-1);
546     QVERIFY(!socket->setSocketDescriptor(-5, QTcpSocket::UnconnectedState));
547     QCOMPARE(socket->socketDescriptor(), (qintptr)-1);
548
549     QCOMPARE(socket->error(), QTcpSocket::UnsupportedSocketOperationError);
550
551     delete socket;
552 }
553
554 //----------------------------------------------------------------------------------
555
556 void tst_QTcpSocket::setSocketDescriptor()
557 {
558     QFETCH_GLOBAL(bool, setProxy);
559     if (setProxy)
560         return;                 // this test doesn't make sense with proxies
561
562 #ifdef Q_OS_WIN
563     // need the dummy to ensure winsock is started
564     QTcpSocket *dummy = newSocket();
565     dummy->connectToHost(QtNetworkSettings::serverName(), 143);
566     QVERIFY(dummy->waitForConnected());
567
568     SOCKET sock = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
569     if (sock == INVALID_SOCKET) {
570         qErrnoWarning(WSAGetLastError(), "INVALID_SOCKET");
571     }
572 #else
573     SOCKET sock = ::socket(AF_INET, SOCK_STREAM, 0);
574
575     // artificially increase the value of sock
576     SOCKET sock2 = ::fcntl(sock, F_DUPFD, sock + 50);
577     ::close(sock);
578     sock = sock2;
579 #endif
580
581     QVERIFY(sock != INVALID_SOCKET);
582     QTcpSocket *socket = newSocket();
583     QVERIFY(socket->setSocketDescriptor(sock, QTcpSocket::UnconnectedState));
584     QCOMPARE(socket->socketDescriptor(), (qintptr)sock);
585
586     qt_qhostinfo_clear_cache(); //avoid the HostLookupState being skipped due to address being in cache from previous test.
587     socket->connectToHost(QtNetworkSettings::serverName(), 143);
588     QCOMPARE(socket->state(), QTcpSocket::HostLookupState);
589     QCOMPARE(socket->socketDescriptor(), (qintptr)sock);
590     QVERIFY(socket->waitForConnected(10000));
591     // skip this, it has been broken for years, see task 260735
592     // if somebody complains, consider fixing it, but it might break existing applications.
593     QEXPECT_FAIL("", "bug has been around for years, will not fix without need", Continue);
594     QCOMPARE(socket->socketDescriptor(), (qintptr)sock);
595     delete socket;
596 #ifdef Q_OS_WIN
597     delete dummy;
598 #endif
599 }
600
601 //----------------------------------------------------------------------------------
602
603 void tst_QTcpSocket::socketDescriptor()
604 {
605     QTcpSocket *socket = newSocket();
606
607     QCOMPARE(socket->socketDescriptor(), (qintptr)-1);
608     socket->connectToHost(QtNetworkSettings::serverName(), 143);
609     QVERIFY((socket->state() == QAbstractSocket::HostLookupState && socket->socketDescriptor() == -1) ||
610             (socket->state() == QAbstractSocket::ConnectingState && socket->socketDescriptor() != -1));
611     QVERIFY(socket->waitForConnected(10000));
612     QVERIFY(socket->state() == QAbstractSocket::ConnectedState);
613     QVERIFY(socket->socketDescriptor() != -1);
614
615     delete socket;
616 }
617
618 //----------------------------------------------------------------------------------
619
620 void tst_QTcpSocket::blockingIMAP()
621 {
622     QTcpSocket *socket = newSocket();
623
624     // Connect
625     socket->connectToHost(QtNetworkSettings::serverName(), 143);
626     QVERIFY(socket->waitForConnected(10000));
627     QCOMPARE(socket->state(), QTcpSocket::ConnectedState);
628     QVERIFY(socket->isValid());
629
630     // Read greeting
631     QVERIFY(socket->waitForReadyRead(5000));
632     QString s = socket->readLine();
633     // only test if an OK was returned, to make the test compatible between different
634     // IMAP server versions
635     QCOMPARE(s.left(4).toLatin1().constData(), "* OK");
636
637     // Write NOOP
638     QCOMPARE((int) socket->write("1 NOOP\r\n", 8), 8);
639     QCOMPARE((int) socket->write("2 NOOP\r\n", 8), 8);
640
641     if (!socket->canReadLine())
642         QVERIFY(socket->waitForReadyRead(5000));
643
644     // Read response
645     s = socket->readLine();
646     QCOMPARE(s.toLatin1().constData(), "1 OK Completed\r\n");
647
648     // Write a third NOOP to verify that write doesn't clear the read buffer
649     QCOMPARE((int) socket->write("3 NOOP\r\n", 8), 8);
650
651     // Read second response
652     if (!socket->canReadLine())
653         QVERIFY(socket->waitForReadyRead(5000));
654     s = socket->readLine();
655     QCOMPARE(s.toLatin1().constData(), "2 OK Completed\r\n");
656
657     // Read third response
658     if (!socket->canReadLine())
659         QVERIFY(socket->waitForReadyRead(5000));
660     s = socket->readLine();
661     QCOMPARE(s.toLatin1().constData(), "3 OK Completed\r\n");
662
663
664     // Write LOGOUT
665     QCOMPARE((int) socket->write("4 LOGOUT\r\n", 10), 10);
666
667     if (!socket->canReadLine())
668         QVERIFY(socket->waitForReadyRead(5000));
669
670     // Read two lines of respose
671     s = socket->readLine();
672     QCOMPARE(s.toLatin1().constData(), "* BYE LOGOUT received\r\n");
673
674     if (!socket->canReadLine())
675         QVERIFY(socket->waitForReadyRead(5000));
676
677     s = socket->readLine();
678     QCOMPARE(s.toLatin1().constData(), "4 OK Completed\r\n");
679
680     // Close the socket
681     socket->close();
682
683     // Check that it's closed
684     QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
685
686     delete socket;
687 }
688
689 //----------------------------------------------------------------------------------
690
691 void tst_QTcpSocket::hostNotFound()
692 {
693     QTcpSocket *socket = newSocket();
694
695     socket->connectToHost("nosuchserver.troll.no", 80);
696     QVERIFY(!socket->waitForConnected());
697     QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
698     QCOMPARE(int(socket->error()), int(QTcpSocket::HostNotFoundError));
699
700     delete socket;
701 }
702
703 //----------------------------------------------------------------------------------
704 void tst_QTcpSocket::timeoutConnect_data()
705 {
706     QTest::addColumn<QString>("address");
707     QTest::newRow("host") << QtNetworkSettings::serverName();
708     QTest::newRow("ip") << QtNetworkSettings::serverIP().toString();
709 }
710
711 void tst_QTcpSocket::timeoutConnect()
712 {
713     QFETCH(QString, address);
714     QTcpSocket *socket = newSocket();
715
716     QElapsedTimer timer;
717     timer.start();
718
719     // Port 1357 is configured to drop packets on the test server
720     socket->connectToHost(address, 1357);
721     QVERIFY(timer.elapsed() < 150);
722     QVERIFY(!socket->waitForConnected(1000)); //200ms is too short when using SOCKS proxy authentication
723     QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
724     QCOMPARE(int(socket->error()), int(QTcpSocket::SocketTimeoutError));
725
726     timer.start();
727     socket->connectToHost(address, 1357);
728     QVERIFY(timer.elapsed() < 150);
729     QTimer::singleShot(50, &QTestEventLoop::instance(), SLOT(exitLoop()));
730     QTestEventLoop::instance().enterLoop(5);
731     QVERIFY(!QTestEventLoop::instance().timeout());
732     QVERIFY(socket->state() == QTcpSocket::ConnectingState
733             || socket->state() == QTcpSocket::HostLookupState);
734     socket->abort();
735     QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
736     QCOMPARE(socket->openMode(), QIODevice::NotOpen);
737
738     delete socket;
739 }
740
741 //----------------------------------------------------------------------------------
742
743 void tst_QTcpSocket::nonBlockingIMAP()
744 {
745     QTcpSocket *socket = newSocket();
746     connect(socket, SIGNAL(hostFound()), SLOT(nonBlockingIMAP_hostFound()));
747     connect(socket, SIGNAL(connected()), SLOT(nonBlockingIMAP_connected()));
748     connect(socket, SIGNAL(disconnected()), SLOT(nonBlockingIMAP_closed()));
749     connect(socket, SIGNAL(bytesWritten(qint64)), SLOT(nonBlockingIMAP_bytesWritten(qint64)));
750     connect(socket, SIGNAL(readyRead()), SLOT(nonBlockingIMAP_readyRead()));
751     nonBlockingIMAP_socket = socket;
752
753     // Connect
754     socket->connectToHost(QtNetworkSettings::serverName(), 143);
755     QVERIFY(socket->state() == QTcpSocket::HostLookupState ||
756             socket->state() == QTcpSocket::ConnectingState);
757
758     enterLoop(30);
759     if (timeout()) {
760         QFAIL("Timed out");
761     }
762
763     if (socket->state() == QTcpSocket::ConnectingState) {
764         enterLoop(30);
765         if (timeout()) {
766             QFAIL("Timed out");
767         }
768     }
769
770     QCOMPARE(socket->state(), QTcpSocket::ConnectedState);
771
772     enterLoop(30);
773     if (timeout()) {
774         QFAIL("Timed out");
775     }
776
777     // Read greeting
778     QVERIFY(!nonBlockingIMAP_data.isEmpty());
779     QCOMPARE(nonBlockingIMAP_data.at(0).left(4).toLatin1().constData(), "* OK");
780     nonBlockingIMAP_data.clear();
781
782     nonBlockingIMAP_totalWritten = 0;
783
784     // Write NOOP
785     QCOMPARE((int) socket->write("1 NOOP\r\n", 8), 8);
786
787
788     enterLoop(30);
789     if (timeout()) {
790         QFAIL("Timed out");
791     }
792
793     QVERIFY(nonBlockingIMAP_totalWritten == 8);
794
795
796     enterLoop(30);
797     if (timeout()) {
798         QFAIL("Timed out");
799     }
800
801
802     // Read response
803     QVERIFY(!nonBlockingIMAP_data.isEmpty());
804     QCOMPARE(nonBlockingIMAP_data.at(0).toLatin1().constData(), "1 OK Completed\r\n");
805     nonBlockingIMAP_data.clear();
806
807
808     nonBlockingIMAP_totalWritten = 0;
809
810     // Write LOGOUT
811     QCOMPARE((int) socket->write("2 LOGOUT\r\n", 10), 10);
812
813     enterLoop(30);
814     if (timeout()) {
815         QFAIL("Timed out");
816     }
817
818     QVERIFY(nonBlockingIMAP_totalWritten == 10);
819
820     // Wait for greeting
821     enterLoop(30);
822     if (timeout()) {
823         QFAIL("Timed out");
824     }
825
826     // Read two lines of respose
827     QCOMPARE(nonBlockingIMAP_data.at(0).toLatin1().constData(), "* BYE LOGOUT received\r\n");
828     QCOMPARE(nonBlockingIMAP_data.at(1).toLatin1().constData(), "2 OK Completed\r\n");
829     nonBlockingIMAP_data.clear();
830
831     // Close the socket
832     socket->close();
833
834     // Check that it's closed
835     QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
836
837     delete socket;
838 }
839
840 void tst_QTcpSocket::nonBlockingIMAP_hostFound()
841 {
842     exitLoop();
843 }
844
845 void tst_QTcpSocket::nonBlockingIMAP_connected()
846 {
847     exitLoop();
848 }
849
850 void tst_QTcpSocket::nonBlockingIMAP_readyRead()
851 {
852     while (nonBlockingIMAP_socket->canReadLine())
853         nonBlockingIMAP_data.append(nonBlockingIMAP_socket->readLine());
854
855     exitLoop();
856 }
857
858 void tst_QTcpSocket::nonBlockingIMAP_bytesWritten(qint64 written)
859 {
860     nonBlockingIMAP_totalWritten += written;
861     exitLoop();
862 }
863
864 void tst_QTcpSocket::nonBlockingIMAP_closed()
865 {
866 }
867
868 //----------------------------------------------------------------------------------
869
870 void tst_QTcpSocket::delayedClose()
871 {
872     QTcpSocket *socket = newSocket();
873     connect(socket, SIGNAL(connected()), SLOT(nonBlockingIMAP_connected()));
874     connect(socket, SIGNAL(disconnected()), SLOT(exitLoopSlot()));
875
876     socket->connectToHost(QtNetworkSettings::serverName(), 143);
877
878     enterLoop(30);
879     if (timeout())
880         QFAIL("Timed out");
881
882     QCOMPARE(socket->state(), QTcpSocket::ConnectedState);
883
884     QCOMPARE((int) socket->write("1 LOGOUT\r\n", 10), 10);
885
886     // Add a huge bulk of data to be written after the logout
887     // command. The server will shut down after receiving the LOGOUT,
888     // so this data will not be read. But our close call should
889     // schedule a delayed close because all the data can not be
890     // written in one go.
891     QCOMPARE((int) socket->write(QByteArray(100000, '\n'), 100000), 100000);
892
893     socket->close();
894
895     QCOMPARE((int) socket->state(), (int) QTcpSocket::ClosingState);
896
897     enterLoop(10);
898     if (timeout())
899         QFAIL("Timed out");
900
901     QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
902
903     delete socket;
904 }
905
906
907 //----------------------------------------------------------------------------------
908
909 QByteArray tst_QTcpSocket::expectedReplyIMAP()
910 {
911     if (expectedReplyIMAP_cached.isEmpty()) {
912         fetchExpectedReplyIMAP();
913     }
914
915     return expectedReplyIMAP_cached;
916 }
917
918 // Figure out how the current IMAP server responds
919 void tst_QTcpSocket::fetchExpectedReplyIMAP()
920 {
921     QTcpSocket *socket = newSocket();
922     socket->connectToHost(QtNetworkSettings::serverName(), 143);
923     QVERIFY2(socket->waitForConnected(10000), qPrintable(socket->errorString()));
924     QVERIFY2(socket->state() == QTcpSocket::ConnectedState, qPrintable(socket->errorString()));
925
926     QTRY_VERIFY(socket->canReadLine());
927
928     QByteArray greeting = socket->readLine();
929     delete socket;
930
931     QVERIFY2(QtNetworkSettings::compareReplyIMAP(greeting), greeting.constData());
932
933     expectedReplyIMAP_cached = greeting;
934 }
935
936 //----------------------------------------------------------------------------------
937
938 void tst_QTcpSocket::partialRead()
939 {
940     QTcpSocket *socket = newSocket();
941     socket->connectToHost(QtNetworkSettings::serverName(), 143);
942     QVERIFY(socket->waitForConnected(10000));
943     QVERIFY(socket->state() == QTcpSocket::ConnectedState);
944     char buf[512];
945
946     QByteArray greeting = expectedReplyIMAP();
947     QVERIFY(!greeting.isEmpty());
948
949     for (int i = 0; i < 10; i += 2) {
950         while (socket->bytesAvailable() < 2)
951             QVERIFY(socket->waitForReadyRead(5000));
952         QVERIFY(socket->read(buf, 2) == 2);
953         buf[2] = '\0';
954         QCOMPARE((char *)buf, greeting.mid(i, 2).data());
955     }
956
957     delete socket;
958 }
959
960 //----------------------------------------------------------------------------------
961
962 void tst_QTcpSocket::unget()
963 {
964     QTcpSocket *socket = newSocket();
965     socket->connectToHost(QtNetworkSettings::serverName(), 143);
966     QVERIFY(socket->waitForConnected(10000));
967     QVERIFY(socket->state() == QTcpSocket::ConnectedState);
968     char buf[512];
969
970     QByteArray greeting = expectedReplyIMAP();
971     QVERIFY(!greeting.isEmpty());
972
973     for (int i = 0; i < 10; i += 2) {
974         while (socket->bytesAvailable() < 2)
975             QVERIFY(socket->waitForReadyRead(10000));
976         int bA = socket->bytesAvailable();
977         QVERIFY(socket->read(buf, 2) == 2);
978         buf[2] = '\0';
979         QCOMPARE((char *)buf, greeting.mid(i, 2).data());
980         QCOMPARE((int)socket->bytesAvailable(), bA - 2);
981         socket->ungetChar(buf[1]);
982         socket->ungetChar(buf[0]);
983         QCOMPARE((int)socket->bytesAvailable(), bA);
984         QVERIFY(socket->read(buf, 2) == 2);
985         buf[2] = '\0';
986         QCOMPARE((char *)buf, greeting.mid(i, 2).data());
987     }
988
989     delete socket;
990 }
991
992 //----------------------------------------------------------------------------------
993 void tst_QTcpSocket::readRegularFile_readyRead()
994 {
995     exitLoop();
996 }
997
998 //----------------------------------------------------------------------------------
999 void tst_QTcpSocket::readAllAfterClose()
1000 {
1001     QTcpSocket *socket = newSocket();
1002     socket->connectToHost(QtNetworkSettings::serverName(), 143);
1003     connect(socket, SIGNAL(readyRead()), SLOT(readRegularFile_readyRead()));
1004     enterLoop(10);
1005     if (timeout())
1006         QFAIL("Network operation timed out");
1007
1008     socket->close();
1009     QByteArray array = socket->readAll();
1010     QCOMPARE(array.size(), 0);
1011
1012     delete socket;
1013 }
1014
1015 //----------------------------------------------------------------------------------
1016 void tst_QTcpSocket::openCloseOpenClose()
1017 {
1018     QTcpSocket *socket = newSocket();
1019
1020     for (int i = 0; i < 3; ++i) {
1021         QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
1022         QCOMPARE(int(socket->openMode()), int(QIODevice::NotOpen));
1023         QVERIFY(socket->isSequential());
1024         QVERIFY(!socket->isOpen());
1025         QVERIFY(socket->socketType() == QTcpSocket::TcpSocket);
1026
1027         char c;
1028         QCOMPARE(socket->getChar(&c), false);
1029         QCOMPARE((int) socket->bytesAvailable(), 0);
1030         QCOMPARE(socket->canReadLine(), false);
1031         QCOMPARE(socket->readLine(), QByteArray());
1032         QCOMPARE(socket->socketDescriptor(), (qintptr)-1);
1033         QCOMPARE((int) socket->localPort(), 0);
1034         QVERIFY(socket->localAddress() == QHostAddress());
1035         QCOMPARE((int) socket->peerPort(), 0);
1036         QVERIFY(socket->peerAddress() == QHostAddress());
1037         QCOMPARE(socket->error(), QTcpSocket::UnknownSocketError);
1038         QCOMPARE(socket->errorString(), QString("Unknown error"));
1039
1040         QVERIFY(socket->state() == QTcpSocket::UnconnectedState);
1041
1042         socket->connectToHost(QtNetworkSettings::serverName(), 143);
1043         QVERIFY(socket->waitForConnected(10000));
1044         socket->close();
1045     }
1046
1047     delete socket;
1048 }
1049
1050 //----------------------------------------------------------------------------------
1051 void tst_QTcpSocket::connectDisconnectConnectDisconnect()
1052 {
1053     QTcpSocket *socket = newSocket();
1054
1055     for (int i = 0; i < 3; ++i) {
1056         QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
1057         QVERIFY(socket->socketType() == QTcpSocket::TcpSocket);
1058
1059         socket->connectToHost(QtNetworkSettings::serverName(), 143);
1060         QVERIFY(socket->waitForReadyRead(10000));
1061         QCOMPARE(QString::fromLatin1(socket->read(4)), QString("* OK"));
1062
1063         socket->disconnectFromHost();
1064         if (socket->state() != QTcpSocket::UnconnectedState)
1065             QVERIFY(socket->waitForDisconnected(10000));
1066         QCOMPARE(int(socket->openMode()), int(QIODevice::ReadWrite));
1067     }
1068
1069     delete socket;
1070 }
1071
1072 //----------------------------------------------------------------------------------
1073 void tst_QTcpSocket::disconnectWhileConnecting_data()
1074 {
1075     QTest::addColumn<QByteArray>("data");
1076     QTest::addColumn<bool>("closeDirectly");
1077
1078     QTest::newRow("without-data") << QByteArray() << false;
1079     QTest::newRow("without-data+close") << QByteArray() << true;
1080     QTest::newRow("with-data") << QByteArray("Hello, world!") << false;
1081     QTest::newRow("with-data+close") << QByteArray("Hello, world!") << true;
1082
1083     QByteArray bigData(1024*1024, '@');
1084     QTest::newRow("with-big-data") << bigData << false;
1085     QTest::newRow("with-big-data+close") << bigData << true;
1086 }
1087
1088 void tst_QTcpSocket::disconnectWhileConnecting()
1089 {
1090     QFETCH(QByteArray, data);
1091     QFETCH_GLOBAL(bool, setProxy);
1092     if (setProxy)
1093         return; //proxy not useful for localhost test case
1094
1095     QTcpServer server;
1096     QVERIFY(server.listen(QHostAddress::LocalHost));
1097
1098     // proceed to the connect-write-disconnect
1099     QTcpSocket *socket = newSocket();
1100     socket->connectToHost("127.0.0.1", server.serverPort());
1101     if (!data.isEmpty())
1102         socket->write(data);
1103     if (socket->state() == QAbstractSocket::ConnectedState)
1104         QSKIP("localhost connections are immediate, test case is invalid");
1105
1106     QFETCH(bool, closeDirectly);
1107     if (closeDirectly) {
1108         socket->close();
1109         QCOMPARE(int(socket->openMode()), int(QIODevice::NotOpen));
1110     } else {
1111         socket->disconnectFromHost();
1112     }
1113
1114     connect(socket, SIGNAL(disconnected()), SLOT(exitLoopSlot()));
1115     enterLoop(10);
1116     QVERIFY2(!timeout(), "Network timeout");
1117     QVERIFY(socket->state() == QAbstractSocket::UnconnectedState);
1118     if (!closeDirectly) {
1119         QCOMPARE(int(socket->openMode()), int(QIODevice::ReadWrite));
1120         socket->close();
1121     }
1122     QCOMPARE(int(socket->openMode()), int(QIODevice::NotOpen));
1123
1124     // accept the other side and verify that it was sent properly:
1125     QVERIFY(server.hasPendingConnections() || server.waitForNewConnection(0));
1126     QTcpSocket *othersocket = server.nextPendingConnection();
1127     if (othersocket->state() != QAbstractSocket::UnconnectedState)
1128         QVERIFY2(othersocket->waitForDisconnected(10000), "Network timeout");
1129     QVERIFY(othersocket->state() == QAbstractSocket::UnconnectedState);
1130     QCOMPARE(othersocket->readAll(), data);
1131
1132     delete socket;
1133     delete othersocket;
1134 }
1135
1136 //----------------------------------------------------------------------------------
1137 class ReceiverThread: public QThread
1138 {
1139     QTcpServer *server;
1140 public:
1141     int serverPort;
1142     bool ok;
1143     QByteArray receivedData;
1144     volatile bool quit;
1145
1146     ReceiverThread()
1147         : server(0), ok(false), quit(false)
1148     { }
1149
1150     ~ReceiverThread() { }
1151
1152     bool listen()
1153     {
1154         server = new QTcpServer;
1155         if (!server->listen(QHostAddress::LocalHost))
1156             return false;
1157         serverPort = server->serverPort();
1158         server->moveToThread(this);
1159         return true;
1160     }
1161
1162     static void cleanup(void *ptr)
1163     {
1164         ReceiverThread* self = reinterpret_cast<ReceiverThread*>(ptr);
1165         self->quit = true;
1166         self->wait(30000);
1167         delete self;
1168     }
1169
1170 protected:
1171     void run()
1172     {
1173         bool timedOut = false;
1174         while (!quit) {
1175             if (server->waitForNewConnection(500, &timedOut))
1176                 break;
1177             if (!timedOut)
1178                 return;
1179         }
1180
1181         QTcpSocket *socket = server->nextPendingConnection();
1182         while (!quit) {
1183             if (socket->waitForDisconnected(500))
1184                 break;
1185             if (socket->error() != QAbstractSocket::SocketTimeoutError)
1186                 return;
1187         }
1188
1189         if (!quit) {
1190             receivedData = socket->readAll();
1191             ok = true;
1192         }
1193         delete socket;
1194         delete server;
1195         server = 0;
1196     }
1197 };
1198
1199 void tst_QTcpSocket::disconnectWhileConnectingNoEventLoop_data()
1200 {
1201     disconnectWhileConnecting_data();
1202 }
1203
1204 void tst_QTcpSocket::disconnectWhileConnectingNoEventLoop()
1205 {
1206     QFETCH(QByteArray, data);
1207     QFETCH_GLOBAL(bool, setProxy);
1208     if (setProxy)
1209         return; //proxy not useful for localhost test case
1210
1211     QScopedPointer<ReceiverThread, ReceiverThread> thread (new ReceiverThread);
1212     QVERIFY(thread->listen());
1213     thread->start();
1214
1215     // proceed to the connect-write-disconnect
1216     QTcpSocket *socket = newSocket();
1217     socket->connectToHost("127.0.0.1", thread->serverPort);
1218     if (!data.isEmpty())
1219         socket->write(data);
1220     if (socket->state() == QAbstractSocket::ConnectedState)
1221         QSKIP("localhost connections are immediate, test case is invalid");
1222
1223     QFETCH(bool, closeDirectly);
1224     if (closeDirectly) {
1225         socket->close();
1226         QCOMPARE(int(socket->openMode()), int(QIODevice::NotOpen));
1227     } else {
1228         socket->disconnectFromHost();
1229     }
1230
1231     QVERIFY2(socket->waitForDisconnected(10000), "Network timeout");
1232     QVERIFY(socket->state() == QAbstractSocket::UnconnectedState);
1233     if (!closeDirectly) {
1234         QCOMPARE(int(socket->openMode()), int(QIODevice::ReadWrite));
1235         socket->close();
1236     }
1237     QCOMPARE(int(socket->openMode()), int(QIODevice::NotOpen));
1238     delete socket;
1239
1240     // check if the other side received everything ok
1241     QVERIFY(thread->wait(30000));
1242     QVERIFY(thread->ok);
1243     QCOMPARE(thread->receivedData, data);
1244 }
1245
1246 //----------------------------------------------------------------------------------
1247 void tst_QTcpSocket::disconnectWhileLookingUp_data()
1248 {
1249     QTest::addColumn<bool>("doClose");
1250
1251     QTest::newRow("disconnect") << false;
1252     QTest::newRow("close") << true;
1253 }
1254
1255 void tst_QTcpSocket::disconnectWhileLookingUp()
1256 {
1257     QFETCH_GLOBAL(bool, setProxy);
1258     if (setProxy)
1259         return;                 // we let the proxies do the lookup now
1260
1261     // just connect and disconnect, then make sure nothing weird happened
1262     QTcpSocket *socket = newSocket();
1263     socket->connectToHost(QtNetworkSettings::serverName(), 21);
1264
1265     // check that connect is in progress
1266     QVERIFY(socket->state() != QAbstractSocket::UnconnectedState);
1267
1268     QFETCH(bool, doClose);
1269     if (doClose) {
1270         socket->close();
1271         QVERIFY(socket->openMode() == QIODevice::NotOpen);
1272     } else {
1273         socket->disconnectFromHost();
1274         QVERIFY(socket->openMode() == QIODevice::ReadWrite);
1275         QVERIFY(socket->waitForDisconnected(5000));
1276     }
1277
1278     // let anything queued happen
1279     QEventLoop loop;
1280     QTimer::singleShot(50, &loop, SLOT(quit()));
1281     loop.exec();
1282
1283     // recheck
1284     if (doClose) {
1285         QVERIFY(socket->openMode() == QIODevice::NotOpen);
1286     } else {
1287         QVERIFY(socket->openMode() == QIODevice::ReadWrite);
1288     }
1289
1290     QVERIFY(socket->state() == QAbstractSocket::UnconnectedState);
1291 }
1292
1293 //----------------------------------------------------------------------------------
1294 void tst_QTcpSocket::downloadBigFile()
1295 {
1296     if (tmpSocket)
1297         delete tmpSocket;
1298     tmpSocket = newSocket();
1299
1300     connect(tmpSocket, SIGNAL(connected()), SLOT(exitLoopSlot()));
1301     connect(tmpSocket, SIGNAL(readyRead()), SLOT(downloadBigFileSlot()));
1302     connect(tmpSocket, SIGNAL(disconnected()), SLOT(exitLoopSlot()));
1303
1304     tmpSocket->connectToHost(QtNetworkSettings::serverName(), 80);
1305
1306     enterLoop(30);
1307     if (timeout()) {
1308         delete tmpSocket;
1309         tmpSocket = 0;
1310         QFAIL("Network operation timed out");
1311     }
1312
1313     QByteArray hostName = QtNetworkSettings::serverName().toLatin1();
1314     QVERIFY(tmpSocket->state() == QAbstractSocket::ConnectedState);
1315     QVERIFY(tmpSocket->write("GET /qtest/mediumfile HTTP/1.0\r\n") > 0);
1316     QVERIFY(tmpSocket->write("HOST: ") > 0);
1317     QVERIFY(tmpSocket->write(hostName.data()) > 0);
1318     QVERIFY(tmpSocket->write("\r\n") > 0);
1319     QVERIFY(tmpSocket->write("\r\n") > 0);
1320
1321     bytesAvailable = 0;
1322     expectedLength = 0;
1323     readingBody = false;
1324
1325     QTime stopWatch;
1326     stopWatch.start();
1327
1328     enterLoop(600);
1329     if (timeout()) {
1330         delete tmpSocket;
1331         tmpSocket = 0;
1332         if (bytesAvailable > 0)
1333             qDebug("Slow Connection, only downloaded %ld of %d", long(bytesAvailable), 10000281);
1334         QFAIL("Network operation timed out");
1335     }
1336
1337     QCOMPARE(bytesAvailable, expectedLength);
1338
1339     qDebug("\t\t%.1fMB/%.1fs: %.1fMB/s",
1340            bytesAvailable / (1024.0 * 1024.0),
1341            stopWatch.elapsed() / 1024.0,
1342            (bytesAvailable / (stopWatch.elapsed() / 1000.0)) / (1024 * 1024));
1343
1344     delete tmpSocket;
1345     tmpSocket = 0;
1346 }
1347
1348 //----------------------------------------------------------------------------------
1349 void tst_QTcpSocket::exitLoopSlot()
1350 {
1351     exitLoop();
1352 }
1353
1354 //----------------------------------------------------------------------------------
1355 void tst_QTcpSocket::downloadBigFileSlot()
1356 {
1357     if (!readingBody) {
1358         while (tmpSocket->canReadLine()) {
1359             QByteArray array = tmpSocket->readLine();
1360             if (array.startsWith("Content-Length"))
1361                 expectedLength = array.simplified().split(' ').at(1).toInt();
1362             if (array == "\r\n") {
1363                 readingBody = true;
1364                 break;
1365             }
1366         }
1367     }
1368     if (readingBody) {
1369         bytesAvailable += tmpSocket->readAll().size();
1370         if (bytesAvailable == expectedLength)
1371             exitLoop();
1372     }
1373 }
1374
1375 //----------------------------------------------------------------------------------
1376 void tst_QTcpSocket::readLine()
1377 {
1378     QTcpSocket *socket = newSocket();
1379     socket->connectToHost(QtNetworkSettings::serverName(), 143);
1380     QVERIFY(socket->waitForConnected(5000));
1381
1382     while (!socket->canReadLine())
1383         QVERIFY(socket->waitForReadyRead(10000));
1384
1385     char buffer[1024];
1386
1387     qint64 linelen = socket->readLine(buffer, sizeof(buffer));
1388     QVERIFY(linelen >= 3);
1389     QVERIFY(linelen < 1024);
1390
1391     QByteArray reply = QByteArray::fromRawData(buffer, linelen);
1392     QCOMPARE((int) buffer[linelen-2], (int) '\r');
1393     QCOMPARE((int) buffer[linelen-1], (int) '\n');
1394     QCOMPARE((int) buffer[linelen],   (int) '\0');
1395
1396     QVERIFY2(QtNetworkSettings::compareReplyIMAP(reply), reply.constData());
1397
1398     QCOMPARE(socket->write("1 NOOP\r\n"), qint64(8));
1399
1400     while (socket->bytesAvailable() < 10)
1401         QVERIFY(socket->waitForReadyRead(10000));
1402
1403     QCOMPARE(socket->readLine(buffer, 11), qint64(10));
1404     QCOMPARE((const char *)buffer, "1 OK Compl");
1405
1406     while (socket->bytesAvailable() < 6)
1407         QVERIFY(socket->waitForReadyRead(10000));
1408
1409     QCOMPARE(socket->readLine(buffer, 11), qint64(6));
1410     QCOMPARE((const char *)buffer, "eted\r\n");
1411
1412     QVERIFY(!socket->waitForReadyRead(100));
1413     QCOMPARE(socket->readLine(buffer, sizeof(buffer)), qint64(0));
1414     QVERIFY(socket->error() == QAbstractSocket::SocketTimeoutError
1415             || socket->error() == QAbstractSocket::RemoteHostClosedError);
1416     QCOMPARE(socket->bytesAvailable(), qint64(0));
1417
1418     socket->close();
1419     QCOMPARE(socket->readLine(buffer, sizeof(buffer)), qint64(-1));
1420
1421     delete socket;
1422 }
1423
1424 //----------------------------------------------------------------------------------
1425 void tst_QTcpSocket::readLineString()
1426 {
1427     QTcpSocket *socket = newSocket();
1428     socket->connectToHost(QtNetworkSettings::serverName(), 143);
1429     QVERIFY(socket->waitForReadyRead(10000));
1430
1431     QByteArray arr = socket->readLine();
1432     QVERIFY2(QtNetworkSettings::compareReplyIMAP(arr), arr.constData());
1433
1434     delete socket;
1435 }
1436
1437 //----------------------------------------------------------------------------------
1438 void tst_QTcpSocket::readChunks()
1439 {
1440     QTcpSocket *socket = newSocket();
1441     socket->connectToHost(QtNetworkSettings::serverName(), 143);
1442     QVERIFY(socket->waitForConnected(10000));
1443     QVERIFY(socket->waitForReadyRead(5000));
1444
1445     char buf[4096];
1446     memset(buf, '@', sizeof(buf));
1447     qint64 dataLength = socket->read(buf, sizeof(buf));
1448     QVERIFY(dataLength > 0);
1449
1450     QCOMPARE(buf[dataLength - 2], '\r');
1451     QCOMPARE(buf[dataLength - 1], '\n');
1452     QCOMPARE(buf[dataLength], '@');
1453
1454     delete socket;
1455 }
1456
1457 //----------------------------------------------------------------------------------
1458 void tst_QTcpSocket::waitForBytesWritten()
1459 {
1460     QTcpSocket *socket = newSocket();
1461     socket->connectToHost(QtNetworkSettings::serverName(), 80);
1462     QVERIFY(socket->waitForConnected(10000));
1463
1464     socket->write("GET / HTTP/1.0\r\n\r\n");
1465     qint64 toWrite = socket->bytesToWrite();
1466     QVERIFY(socket->waitForBytesWritten(5000));
1467     QVERIFY(toWrite > socket->bytesToWrite());
1468
1469     delete socket;
1470 }
1471
1472 //----------------------------------------------------------------------------------
1473 void tst_QTcpSocket::waitForBytesWrittenMinusOne()
1474 {
1475 #ifdef Q_OS_WIN
1476     QSKIP("QTBUG-24451 - indefinite wait may hang");
1477 #endif
1478     QTcpSocket *socket = newSocket();
1479     socket->connectToHost(QtNetworkSettings::serverName(), 80);
1480     QVERIFY(socket->waitForConnected(10000));
1481
1482     socket->write("GET / HTTP/1.0\r\n\r\n");
1483     qint64 toWrite = socket->bytesToWrite();
1484     QVERIFY(socket->waitForBytesWritten(-1));
1485     QVERIFY(toWrite > socket->bytesToWrite());
1486
1487     delete socket;
1488 }
1489
1490 //----------------------------------------------------------------------------------
1491 void tst_QTcpSocket::waitForReadyRead()
1492 {
1493     QTcpSocket *socket = newSocket();
1494     socket->connectToHost(QtNetworkSettings::serverName(), 80);
1495     socket->write("GET / HTTP/1.0\r\n\r\n");
1496     QVERIFY(socket->waitForReadyRead(5000));
1497     delete socket;
1498 }
1499
1500 //----------------------------------------------------------------------------------
1501 void tst_QTcpSocket::waitForReadyReadMinusOne()
1502 {
1503 #ifdef Q_OS_WIN
1504     QSKIP("QTBUG-24451 - indefinite wait may hang");
1505 #endif
1506     QTcpSocket *socket = newSocket();
1507     socket->connectToHost(QtNetworkSettings::serverName(), 80);
1508     socket->write("GET / HTTP/1.0\r\n\r\n");
1509     QVERIFY(socket->waitForReadyRead(-1));
1510     delete socket;
1511 }
1512
1513 //----------------------------------------------------------------------------------
1514 void tst_QTcpSocket::flush()
1515 {
1516     QTcpSocket *socket = newSocket();
1517     socket->flush();
1518
1519     connect(socket, SIGNAL(connected()), SLOT(exitLoopSlot()));
1520     socket->connectToHost(QtNetworkSettings::serverName(), 143);
1521     enterLoop(60);
1522     QVERIFY(socket->isOpen());
1523
1524     socket->write("1 LOGOUT\r\n");
1525     QCOMPARE(socket->bytesToWrite(), qint64(10));
1526     socket->flush();
1527     QCOMPARE(socket->bytesToWrite(), qint64(0));
1528     socket->close();
1529
1530     delete socket;
1531 }
1532
1533 //----------------------------------------------------------------------------------
1534 void tst_QTcpSocket::synchronousApi()
1535 {
1536     QTcpSocket *ftpSocket = newSocket();
1537     ftpSocket->connectToHost(QtNetworkSettings::serverName(), 21);
1538     ftpSocket->write("QUIT\r\n");
1539     QVERIFY(ftpSocket->waitForDisconnected(10000));
1540     QVERIFY(ftpSocket->bytesAvailable() > 0);
1541     QByteArray arr = ftpSocket->readAll();
1542     QVERIFY(arr.size() > 0);
1543     delete ftpSocket;
1544 }
1545
1546 //----------------------------------------------------------------------------------
1547 void tst_QTcpSocket::dontCloseOnTimeout()
1548 {
1549     QTcpServer server;
1550     server.setProxy(QNetworkProxy(QNetworkProxy::NoProxy));
1551     QVERIFY(server.listen());
1552
1553     QHostAddress serverAddress = QHostAddress::LocalHost;
1554     if (!(server.serverAddress() == QHostAddress::AnyIPv4)
1555         && !(server.serverAddress() == QHostAddress::AnyIPv6)
1556         && !(server.serverAddress() == QHostAddress::Any))
1557         serverAddress = server.serverAddress();
1558
1559     QTcpSocket *socket = newSocket();
1560     socket->connectToHost(serverAddress, server.serverPort());
1561     QVERIFY(!socket->waitForReadyRead(100));
1562     QCOMPARE(socket->error(), QTcpSocket::SocketTimeoutError);
1563     QVERIFY(socket->isOpen());
1564
1565     QVERIFY(!socket->waitForDisconnected(100));
1566     QCOMPARE(socket->error(), QTcpSocket::SocketTimeoutError);
1567     QVERIFY(socket->isOpen());
1568
1569     delete socket;
1570 }
1571
1572 //----------------------------------------------------------------------------------
1573 void tst_QTcpSocket::recursiveReadyRead()
1574 {
1575     QTcpSocket *smtp = newSocket();
1576     connect(smtp, SIGNAL(connected()), SLOT(exitLoopSlot()));
1577     connect(smtp, SIGNAL(readyRead()), SLOT(recursiveReadyReadSlot()));
1578     tmpSocket = smtp;
1579
1580     QSignalSpy spy(smtp, SIGNAL(readyRead()));
1581
1582     smtp->connectToHost("smtp.trolltech.com", 25);
1583     enterLoop(30);
1584     QVERIFY2(!timeout(),
1585             "Timed out when connecting to smtp.trolltech.com:25");
1586
1587     enterLoop(30);
1588     QVERIFY2(!timeout(),
1589             "Timed out when waiting for the readyRead() signal");
1590
1591     QCOMPARE(spy.count(), 1);
1592
1593     delete smtp;
1594 }
1595
1596 void tst_QTcpSocket::recursiveReadyReadSlot()
1597 {
1598     // make sure the server spits out more data
1599     tmpSocket->write("NOOP\r\n");
1600     tmpSocket->flush();
1601
1602     // indiscriminately enter the event loop and start processing
1603     // events again. but oops! future socket notifications will cause
1604     // undesired recursive behavior. Unless QTcpSocket is smart, which
1605     // it of course is. :-)
1606     QEventLoop loop;
1607     for (int i = 0; i < 100; ++i)
1608         loop.processEvents();
1609
1610     // all we really wanted to do was process some events, then exit
1611     // the loop
1612     exitLoop();
1613 }
1614
1615 //----------------------------------------------------------------------------------
1616 void tst_QTcpSocket::atEnd()
1617 {
1618     QTcpSocket *socket = newSocket();
1619     socket->connectToHost(QtNetworkSettings::serverName(), 21);
1620
1621     QVERIFY(socket->waitForReadyRead(15000));
1622     QTextStream stream(socket);
1623     QVERIFY(!stream.atEnd());
1624     QString greeting = stream.readLine();
1625     QVERIFY(stream.atEnd());
1626
1627     // Test server must use some vsFTPd 2.x.x version
1628     QVERIFY2(greeting.length() == sizeof("220 (vsFTPd 2.x.x)")-1, qPrintable(greeting));
1629     QVERIFY2(greeting.startsWith("220 (vsFTPd 2."), qPrintable(greeting));
1630     QVERIFY2(greeting.endsWith(")"), qPrintable(greeting));
1631
1632     delete socket;
1633 }
1634
1635 class TestThread : public QThread
1636 {
1637     Q_OBJECT
1638
1639 public:
1640     inline QByteArray data() const
1641     {
1642         return socketData;
1643     }
1644
1645 protected:
1646     inline void run()
1647     {
1648 #ifndef QT_NO_SSL
1649         QFETCH_GLOBAL(bool, ssl);
1650         if (ssl)
1651             socket = new QSslSocket;
1652         else
1653 #endif
1654         socket = new QTcpSocket;
1655         connect(socket, SIGNAL(readyRead()), this, SLOT(getData()), Qt::DirectConnection);
1656         connect(socket, SIGNAL(disconnected()), this, SLOT(closed()), Qt::DirectConnection);
1657         connect(socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
1658                 SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)), Qt::DirectConnection);
1659
1660         socket->connectToHost(QtNetworkSettings::serverName(), 21);
1661         socket->write("QUIT\r\n");
1662         exec();
1663
1664         delete socket;
1665     }
1666
1667 private slots:
1668     inline void getData()
1669     {
1670         socketData += socket->readAll();
1671     }
1672
1673     inline void closed()
1674     {
1675         quit();
1676     }
1677     inline void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth)
1678     {
1679         auth->setUser("qsockstest");
1680         auth->setPassword("password");
1681     }
1682 private:
1683     int exitCode;
1684     QTcpSocket *socket;
1685     QByteArray socketData;
1686 };
1687
1688 //----------------------------------------------------------------------------------
1689 void tst_QTcpSocket::socketInAThread()
1690 {
1691     for (int i = 0; i < 3; ++i) {
1692         TestThread thread;
1693         thread.start();
1694         QVERIFY(thread.wait(15000));
1695         QByteArray data = thread.data();
1696         QVERIFY2(QtNetworkSettings::compareReplyFtp(data), data.constData());
1697     }
1698 }
1699
1700 //----------------------------------------------------------------------------------
1701 void tst_QTcpSocket::socketsInThreads()
1702 {
1703     for (int i = 0; i < 3; ++i) {
1704         TestThread thread1;
1705         TestThread thread2;
1706         TestThread thread3;
1707
1708         thread1.start();
1709         thread2.start();
1710         thread3.start();
1711
1712         QVERIFY(thread2.wait(15000));
1713         QVERIFY(thread3.wait(15000));
1714         QVERIFY(thread1.wait(15000));
1715
1716         QByteArray data1 = thread1.data();
1717         QByteArray data2 = thread2.data();
1718         QByteArray data3 = thread3.data();
1719
1720         QVERIFY2(QtNetworkSettings::compareReplyFtp(data1), data1.constData());
1721         QVERIFY2(QtNetworkSettings::compareReplyFtp(data2), data2.constData());
1722         QVERIFY2(QtNetworkSettings::compareReplyFtp(data3), data3.constData());
1723     }
1724 }
1725
1726 //----------------------------------------------------------------------------------
1727 void tst_QTcpSocket::waitForReadyReadInASlot()
1728 {
1729     QTcpSocket *socket = newSocket();
1730     tmpSocket = socket;
1731     connect(socket, SIGNAL(connected()), this, SLOT(waitForReadyReadInASlotSlot()));
1732
1733     socket->connectToHost(QtNetworkSettings::serverName(), 80);
1734     socket->write("GET / HTTP/1.0\r\n\r\n");
1735
1736     enterLoop(30);
1737     QVERIFY(!timeout());
1738
1739     delete socket;
1740 }
1741
1742 void tst_QTcpSocket::waitForReadyReadInASlotSlot()
1743 {
1744     QVERIFY(tmpSocket->waitForReadyRead(10000));
1745     exitLoop();
1746 }
1747
1748 class RemoteCloseErrorServer : public QTcpServer
1749 {
1750     Q_OBJECT
1751 public:
1752     RemoteCloseErrorServer()
1753     {
1754         connect(this, SIGNAL(newConnection()),
1755                 this, SLOT(getConnection()));
1756     }
1757
1758 private slots:
1759     void getConnection()
1760     {
1761         tst_QTcpSocket::exitLoop();
1762     }
1763 };
1764
1765 //----------------------------------------------------------------------------------
1766 void tst_QTcpSocket::remoteCloseError()
1767 {
1768     QFETCH_GLOBAL(bool, setProxy);
1769     if (setProxy)
1770         return; //proxy not useful for localhost test case
1771     RemoteCloseErrorServer server;
1772     QVERIFY(server.listen(QHostAddress::LocalHost));
1773
1774     QCoreApplication::instance()->processEvents();
1775
1776     QTcpSocket *clientSocket = newSocket();
1777     connect(clientSocket, SIGNAL(readyRead()), this, SLOT(exitLoopSlot()));
1778
1779     clientSocket->connectToHost(server.serverAddress(), server.serverPort());
1780
1781     enterLoop(30);
1782     QVERIFY(!timeout());
1783
1784     QVERIFY(server.hasPendingConnections());
1785     QTcpSocket *serverSocket = server.nextPendingConnection();
1786     connect(clientSocket, SIGNAL(disconnected()), this, SLOT(exitLoopSlot()));
1787
1788     serverSocket->write("Hello");
1789
1790     enterLoop(30);
1791     QVERIFY(!timeout());
1792
1793     QCOMPARE(clientSocket->bytesAvailable(), qint64(5));
1794
1795     qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError");
1796     QSignalSpy errorSpy(clientSocket, SIGNAL(error(QAbstractSocket::SocketError)));
1797     QSignalSpy disconnectedSpy(clientSocket, SIGNAL(disconnected()));
1798
1799     clientSocket->write("World");
1800     serverSocket->disconnectFromHost();
1801
1802     tmpSocket = clientSocket;
1803     connect(clientSocket, SIGNAL(error(QAbstractSocket::SocketError)),
1804             this, SLOT(remoteCloseErrorSlot()));
1805
1806     enterLoop(30);
1807     QVERIFY(!timeout());
1808
1809     QCOMPARE(disconnectedSpy.count(), 1);
1810     QCOMPARE(errorSpy.count(), 1);
1811     QCOMPARE(clientSocket->error(), QAbstractSocket::RemoteHostClosedError);
1812
1813     delete serverSocket;
1814
1815     clientSocket->connectToHost(server.serverAddress(), server.serverPort());
1816
1817     enterLoop(30);
1818     QVERIFY(!timeout());
1819
1820     QVERIFY(server.hasPendingConnections());
1821     serverSocket = server.nextPendingConnection();
1822     serverSocket->disconnectFromHost();
1823
1824     enterLoop(30);
1825     QVERIFY(!timeout());
1826
1827     QCOMPARE(clientSocket->state(), QAbstractSocket::UnconnectedState);
1828
1829     delete clientSocket;
1830 }
1831
1832 void tst_QTcpSocket::remoteCloseErrorSlot()
1833 {
1834     QCOMPARE(tmpSocket->state(), QAbstractSocket::ConnectedState);
1835     static_cast<QTcpSocket *>(sender())->close();
1836 }
1837
1838 void tst_QTcpSocket::enterLoopSlot()
1839 {
1840     QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
1841     socket->deleteLater();
1842
1843     // enter nested event loop
1844     QEventLoop loop;
1845     QTimer::singleShot(100, &loop, SLOT(quit()));
1846     loop.exec();
1847
1848     // Fire a non-0 singleshot to leave time for the delete
1849     QTimer::singleShot(250, this, SLOT(exitLoopSlot()));
1850 }
1851 //----------------------------------------------------------------------------------
1852 void tst_QTcpSocket::nestedEventLoopInErrorSlot()
1853 {
1854     QTcpSocket *socket = newSocket();
1855     QPointer<QTcpSocket> p(socket);
1856     connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(enterLoopSlot()));
1857
1858     socket->connectToHost("hostnotfoundhostnotfound.troll.no", 9999); // Host not found, fyi
1859     enterLoop(30);
1860     QVERIFY(!p);
1861 }
1862
1863 //----------------------------------------------------------------------------------
1864 #ifndef Q_OS_WIN
1865 void tst_QTcpSocket::connectToLocalHostNoService()
1866 {
1867     // This test was created after we received a report that claimed
1868     // QTcpSocket would crash if trying to connect to "localhost" on a random
1869     // port with no service listening.
1870     QTcpSocket *socket = newSocket();
1871     socket->connectToHost("localhost", 31415); // no service running here, one suspects
1872
1873     while(socket->state() == QTcpSocket::HostLookupState || socket->state() == QTcpSocket::ConnectingState) {
1874         QTest::qWait(100);
1875     }
1876     QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
1877     delete socket;
1878 }
1879 #endif
1880
1881 //----------------------------------------------------------------------------------
1882 void tst_QTcpSocket::waitForConnectedInHostLookupSlot()
1883 {
1884     // This test tries to reproduce the problem where waitForConnected() is
1885     // called at a point where the host lookup is already done. QTcpSocket
1886     // will try to abort the "pending lookup", but since it's already done and
1887     // the queued signal is already underway, we will receive the signal after
1888     // waitForConnected() has returned, and control goes back to the event
1889     // loop. When the signal has been received, the connection is torn down,
1890     // then reopened. Yikes. If we reproduce this by calling
1891     // waitForConnected() inside hostLookupSlot(), it will even crash.
1892     tmpSocket = newSocket();
1893     QEventLoop loop;
1894     connect(tmpSocket, SIGNAL(connected()), &loop, SLOT(quit()));
1895     QTimer timer;
1896     connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
1897     QSignalSpy timerSpy(&timer, SIGNAL(timeout()));
1898     timer.start(15000);
1899
1900     connect(tmpSocket, SIGNAL(hostFound()), this, SLOT(hostLookupSlot()));
1901     tmpSocket->connectToHost(QtNetworkSettings::serverName(), 143);
1902
1903     // only execute the loop if not already connected
1904     if (tmpSocket->state() != QAbstractSocket::ConnectedState)
1905         loop.exec();
1906
1907     QCOMPARE(timerSpy.count(), 0);
1908
1909     delete tmpSocket;
1910 }
1911
1912 void tst_QTcpSocket::hostLookupSlot()
1913 {
1914     // This will fail to cancel the pending signal
1915     QVERIFY(tmpSocket->waitForConnected(10000));
1916 }
1917
1918 class Foo : public QObject
1919 {
1920     Q_OBJECT
1921     QTcpSocket *sock;
1922 public:
1923     bool attemptedToConnect;
1924     bool networkTimeout;
1925     int count;
1926
1927     inline Foo(QObject *parent = 0) : QObject(parent)
1928     {
1929         attemptedToConnect = false;
1930         networkTimeout = false;
1931         count = 0;
1932 #ifndef QT_NO_SSL
1933         QFETCH_GLOBAL(bool, ssl);
1934         if (ssl)
1935             sock = new QSslSocket;
1936         else
1937 #endif
1938         sock = new QTcpSocket;
1939         connect(sock, SIGNAL(connected()), this, SLOT(connectedToIt()));
1940         connect(sock, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
1941                 SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
1942     }
1943
1944     inline ~Foo()
1945     {
1946         delete sock;
1947     }
1948
1949 public slots:
1950     inline void connectedToIt()
1951     { count++; }
1952
1953     inline void doIt()
1954     {
1955         attemptedToConnect = true;
1956         sock->connectToHost(QtNetworkSettings::serverName(), 80);
1957
1958 #ifdef Q_OS_MAC
1959         pthread_yield_np();
1960 #elif defined Q_OS_LINUX
1961         pthread_yield();
1962 #endif
1963         if (!sock->waitForConnected()) {
1964             networkTimeout = true;
1965         }
1966         tst_QTcpSocket::exitLoop();
1967     }
1968
1969     inline void exitLoop()
1970     {
1971         tst_QTcpSocket::exitLoop();
1972     }
1973
1974     inline void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth)
1975     {
1976         auth->setUser("qsockstest");
1977         auth->setPassword("password");
1978     }
1979 };
1980
1981 //----------------------------------------------------------------------------------
1982 void tst_QTcpSocket::waitForConnectedInHostLookupSlot2()
1983 {
1984     Foo foo;
1985
1986     QTimer::singleShot(100, &foo, SLOT(doIt()));
1987     QTimer::singleShot(5000, &foo, SLOT(exitLoop()));
1988
1989     enterLoop(30);
1990     if (timeout() || foo.networkTimeout)
1991         QFAIL("Network timeout");
1992
1993     QVERIFY(foo.attemptedToConnect);
1994     QCOMPARE(foo.count, 1);
1995 }
1996
1997 //----------------------------------------------------------------------------------
1998 void tst_QTcpSocket::readyReadSignalsAfterWaitForReadyRead()
1999 {
2000     QTcpSocket *socket = newSocket();
2001
2002     QSignalSpy readyReadSpy(socket, SIGNAL(readyRead()));
2003
2004     // Connect
2005     socket->connectToHost(QtNetworkSettings::serverName(), 143);
2006
2007     // Wait for the read
2008     QVERIFY(socket->waitForReadyRead(10000));
2009
2010     QCOMPARE(readyReadSpy.count(), 1);
2011
2012     QString s = socket->readLine();
2013     QVERIFY2(QtNetworkSettings::compareReplyIMAP(s.toLatin1()), s.toLatin1().constData());
2014     QCOMPARE(socket->bytesAvailable(), qint64(0));
2015
2016     QCoreApplication::instance()->processEvents();
2017     QCOMPARE(socket->bytesAvailable(), qint64(0));
2018     QCOMPARE(readyReadSpy.count(), 1);
2019
2020     delete socket;
2021 }
2022
2023 class TestThread2 : public QThread
2024 {
2025     Q_OBJECT
2026 public:
2027     void run()
2028     {
2029         QFile fileWriter("fifo");
2030         QVERIFY(fileWriter.open(QFile::WriteOnly));
2031         QCOMPARE(fileWriter.write(QByteArray(32, '@')), qint64(32));
2032         QCOMPARE(fileWriter.write(QByteArray(32, '@')), qint64(32));
2033         QCOMPARE(fileWriter.write(QByteArray(32, '@')), qint64(32));
2034         QCOMPARE(fileWriter.write(QByteArray(32, '@')), qint64(32));
2035     }
2036 };
2037
2038 //----------------------------------------------------------------------------------
2039 #ifdef Q_OS_LINUX
2040 void tst_QTcpSocket::linuxKernelBugLocalSocket()
2041 {
2042     QFile::remove("fifo");
2043     mkfifo("fifo", 0666);
2044
2045     TestThread2 test;
2046     test.start();
2047
2048     QFile fileReader("fifo");
2049     QVERIFY(fileReader.open(QFile::ReadOnly));
2050
2051     test.wait();
2052
2053     QTcpSocket *socket = newSocket();
2054     socket->setSocketDescriptor(fileReader.handle());
2055     QVERIFY(socket->waitForReadyRead(5000));
2056     QCOMPARE(socket->bytesAvailable(), qint64(128));
2057
2058     QFile::remove("fifo");
2059
2060     delete socket;
2061 }
2062 #endif
2063
2064 //----------------------------------------------------------------------------------
2065 void tst_QTcpSocket::abortiveClose()
2066 {
2067     QFETCH_GLOBAL(bool, setProxy);
2068     if (setProxy)
2069         return; //proxy not useful for localhost test case
2070     QTcpServer server;
2071     QVERIFY(server.listen(QHostAddress::LocalHost));
2072     connect(&server, SIGNAL(newConnection()), this, SLOT(exitLoopSlot()));
2073
2074     QTcpSocket *clientSocket = newSocket();
2075     clientSocket->connectToHost(server.serverAddress(), server.serverPort());
2076
2077     enterLoop(10);
2078     QVERIFY(server.hasPendingConnections());
2079
2080     QVERIFY(tmpSocket = server.nextPendingConnection());
2081
2082     qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError");
2083     QSignalSpy readyReadSpy(clientSocket, SIGNAL(readyRead()));
2084     QSignalSpy errorSpy(clientSocket, SIGNAL(error(QAbstractSocket::SocketError)));
2085
2086     connect(clientSocket, SIGNAL(disconnected()), this, SLOT(exitLoopSlot()));
2087     QTimer::singleShot(0, this, SLOT(abortiveClose_abortSlot()));
2088
2089     enterLoop(5);
2090
2091     QCOMPARE(readyReadSpy.count(), 0);
2092     QCOMPARE(errorSpy.count(), 1);
2093
2094     QCOMPARE(*static_cast<const int *>(errorSpy.at(0).at(0).constData()),
2095              int(QAbstractSocket::RemoteHostClosedError));
2096
2097     delete clientSocket;
2098 }
2099
2100 void tst_QTcpSocket::abortiveClose_abortSlot()
2101 {
2102     tmpSocket->abort();
2103 }
2104
2105 //----------------------------------------------------------------------------------
2106 void tst_QTcpSocket::localAddressEmptyOnBSD()
2107 {
2108 #ifdef Q_OS_WIN
2109     QSKIP("QTBUG-24451 - indefinite wait may hang");
2110 #endif
2111     QFETCH_GLOBAL(bool, setProxy);
2112     if (setProxy)
2113         return; //proxy not useful for localhost test case
2114     QTcpServer server;
2115     QVERIFY(server.listen(QHostAddress::LocalHost));
2116
2117     QTcpSocket *tcpSocket = 0;
2118     // we try 10 times, but note that this doesn't always provoke the bug
2119     for (int i = 0; i < 10; ++i) {
2120         delete tcpSocket;
2121         tcpSocket = newSocket();
2122         tcpSocket->connectToHost(QHostAddress::LocalHost, server.serverPort());
2123         if (!tcpSocket->waitForConnected(0)) {
2124             // to provoke the bug, we need a local socket that connects immediately
2125             // --i;
2126             tcpSocket->abort();
2127             if (tcpSocket->state() != QTcpSocket::UnconnectedState)
2128                 QVERIFY(tcpSocket->waitForDisconnected(-1));
2129             continue;
2130         }
2131         QCOMPARE(tcpSocket->localAddress(), QHostAddress(QHostAddress::LocalHost));
2132     }
2133     delete tcpSocket;
2134 }
2135
2136 //----------------------------------------------------------------------------------
2137 void tst_QTcpSocket::zeroAndMinusOneReturns()
2138 {
2139     QTcpSocket *socket = newSocket();
2140     socket->connectToHost(QtNetworkSettings::serverName(), 80);
2141     socket->write("GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n");
2142     QVERIFY(socket->waitForReadyRead(15000));
2143
2144     char c[16];
2145     QVERIFY(socket->getChar(c));
2146     QCOMPARE(socket->read(c, 16), qint64(16));
2147     QVERIFY(socket->readLine(c, 16) > 0);
2148     QVERIFY(!socket->readAll().isEmpty());
2149
2150     // the last operation emptied the read buffer
2151     // all read operations from this point on should fail
2152     // with return 0 because the socket is still open
2153     QVERIFY(socket->readAll().isEmpty());
2154     QCOMPARE(socket->read(c, 16), qint64(0));
2155     QCOMPARE(socket->readLine(c, 16), qint64(0));
2156     QVERIFY(!socket->getChar(c));
2157
2158     socket->write("GET / HTTP/1.0\r\n\r\n");
2159     QVERIFY(socket->waitForDisconnected(15000));
2160     QCOMPARE(socket->error(), QAbstractSocket::RemoteHostClosedError);
2161
2162     QCOMPARE(socket->write("BLUBBER"), qint64(-1));
2163     QVERIFY(socket->getChar(c));
2164     QCOMPARE(socket->read(c, 16), qint64(16));
2165     QVERIFY(socket->readLine(c, 16) > 0);
2166     QVERIFY(!socket->readAll().isEmpty());
2167
2168     // the last operation emptied the read buffer
2169     // all read operations from this point on should fail
2170     // with return -1 because the socket is not connected
2171     QVERIFY(socket->readAll().isEmpty());
2172     QCOMPARE(socket->read(c, 16), qint64(-1));
2173     QCOMPARE(socket->readLine(c, 16), qint64(-1));
2174     QVERIFY(!socket->getChar(c));
2175     QVERIFY(!socket->putChar('a'));
2176
2177     socket->close();
2178
2179     // now the QIODevice is closed, which means getChar complains
2180     QCOMPARE(socket->write("BLUBBER"), qint64(-1));
2181     QCOMPARE(socket->read(c, 16), qint64(-1));
2182     QCOMPARE(socket->readLine(c, 16), qint64(-1));
2183     QVERIFY(!socket->getChar(c));
2184     QVERIFY(!socket->putChar('a'));
2185
2186     delete socket;
2187 }
2188
2189 //----------------------------------------------------------------------------------
2190 void tst_QTcpSocket::connectionRefused()
2191 {
2192     qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError");
2193     qRegisterMetaType<QAbstractSocket::SocketState>("QAbstractSocket::SocketState");
2194
2195     QTcpSocket *socket = newSocket();
2196     QSignalSpy stateSpy(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)));
2197     QSignalSpy errorSpy(socket, SIGNAL(error(QAbstractSocket::SocketError)));
2198     connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
2199             &QTestEventLoop::instance(), SLOT(exitLoop()));
2200
2201     socket->connectToHost(QtNetworkSettings::serverName(), 144);
2202
2203     enterLoop(10);
2204     disconnect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
2205                &QTestEventLoop::instance(), SLOT(exitLoop()));
2206     QVERIFY2(!timeout(), "Network timeout");
2207
2208     QCOMPARE(socket->state(), QAbstractSocket::UnconnectedState);
2209     QCOMPARE(socket->error(), QAbstractSocket::ConnectionRefusedError);
2210
2211     QCOMPARE(stateSpy.count(), 3);
2212     QCOMPARE(qvariant_cast<QAbstractSocket::SocketState>(stateSpy.at(0).at(0)), QAbstractSocket::HostLookupState);
2213     QCOMPARE(qvariant_cast<QAbstractSocket::SocketState>(stateSpy.at(1).at(0)), QAbstractSocket::ConnectingState);
2214     QCOMPARE(qvariant_cast<QAbstractSocket::SocketState>(stateSpy.at(2).at(0)), QAbstractSocket::UnconnectedState);
2215     QCOMPARE(errorSpy.count(), 1);
2216
2217     delete socket;
2218 }
2219
2220 //----------------------------------------------------------------------------------
2221 void tst_QTcpSocket::suddenRemoteDisconnect_data()
2222 {
2223     QTest::addColumn<QString>("client");
2224     QTest::addColumn<QString>("server");
2225
2226     QTest::newRow("Qt4 Client <-> Qt4 Server") << QString::fromLatin1("qt4client") << QString::fromLatin1("qt4server");
2227 }
2228
2229 void tst_QTcpSocket::suddenRemoteDisconnect()
2230 {
2231     QFETCH(QString, client);
2232     QFETCH(QString, server);
2233
2234     QFETCH_GLOBAL(bool, setProxy);
2235     if (setProxy)
2236         return;
2237     QFETCH_GLOBAL(bool, ssl);
2238     if (ssl)
2239         return;
2240
2241     QString processExe = stressTestDir + "/stressTest";
2242
2243     // Start server
2244     QProcess serverProcess;
2245     serverProcess.setReadChannel(QProcess::StandardError);
2246     serverProcess.start(processExe, QStringList(server), QIODevice::ReadWrite | QIODevice::Text);
2247     QVERIFY2(serverProcess.waitForStarted(), qPrintable(
2248         QString::fromLatin1("Could not start %1: %2").arg(processExe, serverProcess.errorString())));
2249     while (!serverProcess.canReadLine())
2250         QVERIFY(serverProcess.waitForReadyRead(10000));
2251     QCOMPARE(serverProcess.readLine().data(), QByteArray(server.toLatin1() + "\n").data());
2252
2253     // Start client
2254     QProcess clientProcess;
2255     clientProcess.setReadChannel(QProcess::StandardError);
2256     clientProcess.start(processExe, QStringList(client), QIODevice::ReadWrite | QIODevice::Text);
2257     QVERIFY2(clientProcess.waitForStarted(), qPrintable(
2258         QString::fromLatin1("Could not start %1: %2").arg(processExe, clientProcess.errorString())));
2259     while (!clientProcess.canReadLine())
2260         QVERIFY(clientProcess.waitForReadyRead(10000));
2261     QCOMPARE(clientProcess.readLine().data(), QByteArray(client.toLatin1() + "\n").data());
2262
2263     // Let them play for a while
2264     qDebug("Running stress test for 5 seconds");
2265     QEventLoop loop;
2266     connect(&serverProcess, SIGNAL(finished(int)), &loop, SLOT(quit()));
2267     connect(&clientProcess, SIGNAL(finished(int)), &loop, SLOT(quit()));
2268     QTime stopWatch;
2269     stopWatch.start();
2270     QTimer::singleShot(20000, &loop, SLOT(quit()));
2271
2272     while ((serverProcess.state() == QProcess::Running
2273            || clientProcess.state() == QProcess::Running) && stopWatch.elapsed() < 20000)
2274         loop.exec();
2275
2276     QVERIFY(stopWatch.elapsed() < 20000);
2277
2278     // Check that both exited normally.
2279 #if defined(UBUNTU_ONEIRIC) && defined(__x86_64__)
2280     QEXPECT_FAIL("", "Fails on this platform", Abort);
2281 #endif
2282     QCOMPARE(clientProcess.readAll().constData(), "SUCCESS\n");
2283     QCOMPARE(serverProcess.readAll().constData(), "SUCCESS\n");
2284 }
2285
2286 //----------------------------------------------------------------------------------
2287
2288 void tst_QTcpSocket::connectToMultiIP()
2289 {
2290     QSKIP("TODO: setup DNS in the new network");
2291 #if defined(Q_OS_VXWORKS)
2292     QSKIP("VxSim in standard config doesn't even run a DNS resolver");
2293 #else
2294     QFETCH_GLOBAL(bool, ssl);
2295     if (ssl)
2296         return;
2297     QFETCH_GLOBAL(bool, setProxy);
2298     if (setProxy)
2299         QSKIP("This test takes too long if we also add the proxies.");
2300
2301     qDebug("Please wait, this test can take a while...");
2302
2303     QTcpSocket *socket = newSocket();
2304     // rationale: this domain resolves to 3 A-records, 2 of them are
2305     // invalid. QTcpSocket should never spend more than 30 seconds per IP, and
2306     // 30s*2 = 60s.
2307     QTime stopWatch;
2308     stopWatch.start();
2309     socket->connectToHost("multi.dev.troll.no", 80);
2310     QVERIFY(socket->waitForConnected(60500));
2311     QVERIFY(stopWatch.elapsed() < 70000);
2312     socket->abort();
2313
2314     stopWatch.restart();
2315     socket->connectToHost("multi.dev.troll.no", 81);
2316     QVERIFY(!socket->waitForConnected(2000));
2317     QVERIFY(stopWatch.elapsed() < 2000);
2318     QCOMPARE(socket->error(), QAbstractSocket::SocketTimeoutError);
2319
2320     delete socket;
2321 #endif
2322 }
2323
2324 //----------------------------------------------------------------------------------
2325 void tst_QTcpSocket::moveToThread0()
2326 {
2327     QFETCH_GLOBAL(int, proxyType);
2328     if (proxyType & AuthMask)
2329         return;
2330
2331     {
2332         // Case 1: Moved after connecting, before waiting for connection.
2333         QTcpSocket *socket = newSocket();;
2334         socket->connectToHost(QtNetworkSettings::serverName(), 143);
2335         socket->moveToThread(0);
2336         QVERIFY(socket->waitForConnected(5000));
2337         socket->write("XXX LOGOUT\r\n");
2338         QVERIFY(socket->waitForBytesWritten(5000));
2339         QVERIFY(socket->waitForDisconnected());
2340         delete socket;
2341     }
2342     {
2343         // Case 2: Moved before connecting
2344         QTcpSocket *socket = newSocket();
2345         socket->moveToThread(0);
2346         socket->connectToHost(QtNetworkSettings::serverName(), 143);
2347         QVERIFY(socket->waitForConnected(5000));
2348         socket->write("XXX LOGOUT\r\n");
2349         QVERIFY(socket->waitForBytesWritten(5000));
2350         QVERIFY(socket->waitForDisconnected());
2351         delete socket;
2352     }
2353     {
2354         // Case 3: Moved after writing, while waiting for bytes to be written.
2355         QTcpSocket *socket = newSocket();
2356         socket->connectToHost(QtNetworkSettings::serverName(), 143);
2357         QVERIFY(socket->waitForConnected(5000));
2358         socket->write("XXX LOGOUT\r\n");
2359         socket->moveToThread(0);
2360         QVERIFY(socket->waitForBytesWritten(5000));
2361         QVERIFY(socket->waitForDisconnected());
2362         delete socket;
2363     }
2364     {
2365         // Case 4: Moved after writing, while waiting for response.
2366         QTcpSocket *socket = newSocket();
2367         socket->connectToHost(QtNetworkSettings::serverName(), 143);
2368         QVERIFY(socket->waitForConnected(5000));
2369         socket->write("XXX LOGOUT\r\n");
2370         QVERIFY(socket->waitForBytesWritten(5000));
2371         socket->moveToThread(0);
2372         QVERIFY(socket->waitForDisconnected());
2373         delete socket;
2374     }
2375 }
2376
2377 void tst_QTcpSocket::increaseReadBufferSize()
2378 {
2379     QFETCH_GLOBAL(bool, setProxy);
2380     if (setProxy)
2381         return; //proxy not useful for localhost test case
2382     QTcpServer server;
2383     QTcpSocket *active = newSocket();
2384     connect(active, SIGNAL(readyRead()), SLOT(exitLoopSlot()));
2385
2386     // connect two sockets to each other:
2387     QVERIFY(server.listen(QHostAddress::LocalHost));
2388     active->connectToHost("127.0.0.1", server.serverPort());
2389     QVERIFY(active->waitForConnected(5000));
2390     QVERIFY(server.waitForNewConnection(5000));
2391
2392     QTcpSocket *passive = server.nextPendingConnection();
2393     QVERIFY(passive);
2394
2395     // now write 512 bytes of data on one end
2396     QByteArray data(512, 'a');
2397     passive->write(data);
2398     QVERIFY2(passive->waitForBytesWritten(5000), "Network timeout");
2399
2400     // set the read buffer size to less than what was written and iterate:
2401     active->setReadBufferSize(256);
2402     enterLoop(10);
2403     QVERIFY2(!timeout(), "Network timeout");
2404     QCOMPARE(active->bytesAvailable(), active->readBufferSize());
2405
2406     // increase the buffer size and iterate again:
2407     active->setReadBufferSize(384);
2408     enterLoop(10);
2409     QVERIFY2(!timeout(), "Network timeout");
2410     QCOMPARE(active->bytesAvailable(), active->readBufferSize());
2411
2412     // once more, but now it should read everything there was to read
2413     active->setReadBufferSize(1024);
2414     enterLoop(10);
2415     QVERIFY2(!timeout(), "Network timeout");
2416     QCOMPARE(active->bytesAvailable(), qint64(data.size()));
2417
2418     // drain it and compare
2419     QCOMPARE(active->readAll(), data);
2420
2421     // now one more test by setting the buffer size to unlimited:
2422     passive->write(data);
2423     QVERIFY2(passive->waitForBytesWritten(5000), "Network timeout");
2424     active->setReadBufferSize(256);
2425     enterLoop(10);
2426     QVERIFY2(!timeout(), "Network timeout");
2427     QCOMPARE(active->bytesAvailable(), active->readBufferSize());
2428     active->setReadBufferSize(0);
2429     enterLoop(10);
2430     QVERIFY2(!timeout(), "Network timeout");
2431     QCOMPARE(active->bytesAvailable(), qint64(data.size()));
2432     QCOMPARE(active->readAll(), data);
2433
2434     delete active;
2435 }
2436
2437 void tst_QTcpSocket::taskQtBug5799ConnectionErrorWaitForConnected()
2438 {
2439     QFETCH_GLOBAL(bool, setProxy);
2440     if (setProxy)
2441         return;
2442
2443     // check that we get a proper error connecting to port 12346
2444     // use waitForConnected, e.g. this should use a synchronous select() on the OS level
2445
2446     QTcpSocket socket;
2447     socket.connectToHost(QtNetworkSettings::serverName(), 12346);
2448     QTime timer;
2449     timer.start();
2450     socket.waitForConnected(10000);
2451     QVERIFY2(timer.elapsed() < 9900, "Connection to closed port timed out instead of refusing, something is wrong");
2452     QVERIFY2(socket.state() == QAbstractSocket::UnconnectedState, "Socket connected unexpectedly!");
2453     QVERIFY2(socket.error() == QAbstractSocket::ConnectionRefusedError,
2454              QString("Could not reach server: %1").arg(socket.errorString()).toLocal8Bit());
2455 }
2456
2457 void tst_QTcpSocket::taskQtBug5799ConnectionErrorEventLoop()
2458 {
2459     QFETCH_GLOBAL(bool, setProxy);
2460     if (setProxy)
2461         return;
2462
2463     // check that we get a proper error connecting to port 12346
2464     // This testcase uses an event loop
2465     QTcpSocket socket;
2466     connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), &QTestEventLoop::instance(), SLOT(exitLoop()));
2467     socket.connectToHost(QtNetworkSettings::serverName(), 12346);
2468
2469     QTestEventLoop::instance().enterLoop(10);
2470     QVERIFY2(!QTestEventLoop::instance().timeout(), "Connection to closed port timed out instead of refusing, something is wrong");
2471     QVERIFY2(socket.state() == QAbstractSocket::UnconnectedState, "Socket connected unexpectedly!");
2472     QVERIFY2(socket.error() == QAbstractSocket::ConnectionRefusedError,
2473              QString("Could not reach server: %1").arg(socket.errorString()).toLocal8Bit());
2474 }
2475
2476 void tst_QTcpSocket::taskQtBug7054TimeoutErrorResetting()
2477 {
2478     QTcpSocket *socket = newSocket();
2479
2480     socket->connectToHost(QtNetworkSettings::serverName(), 443);
2481     QVERIFY(socket->waitForConnected(5*1000));
2482     QVERIFY(socket->error() == QAbstractSocket::UnknownSocketError);
2483
2484     // We connected to the HTTPS port. Wait two seconds to receive data. We will receive
2485     // nothing because we would need to start the SSL handshake
2486     QVERIFY(!socket->waitForReadyRead(2*1000));
2487     QVERIFY(socket->error() == QAbstractSocket::SocketTimeoutError);
2488
2489     // Now write some crap to make the server disconnect us. 4 lines are enough.
2490     socket->write("a\r\nb\r\nc\r\nd\r\n");
2491     socket->waitForBytesWritten(2*1000);
2492
2493     // we try to waitForReadyRead another time, but this time instead of a timeout we
2494     // should get a better error since the server disconnected us
2495     QVERIFY(!socket->waitForReadyRead(2*1000));
2496     // It must NOT be the SocketTimeoutError that had been set before
2497     QVERIFY(socket->error() == QAbstractSocket::RemoteHostClosedError);
2498 }
2499
2500 void tst_QTcpSocket::invalidProxy_data()
2501 {
2502     QTest::addColumn<int>("type");
2503     QTest::addColumn<QString>("host");
2504     QTest::addColumn<int>("port");
2505     QTest::addColumn<bool>("failsAtConnect");
2506     QTest::addColumn<int>("expectedError");
2507
2508     QString fluke = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString();
2509     QTest::newRow("ftp-proxy") << int(QNetworkProxy::FtpCachingProxy) << fluke << 21 << true
2510                                << int(QAbstractSocket::UnsupportedSocketOperationError);
2511     QTest::newRow("http-caching-proxy") << int(QNetworkProxy::HttpCachingProxy) << fluke << 3128 << true
2512                                         << int(QAbstractSocket::UnsupportedSocketOperationError);
2513     QTest::newRow("no-such-host-socks5") << int(QNetworkProxy::Socks5Proxy)
2514                                          << "this-host-will-never-exist.troll.no" << 1080 << false
2515                                          << int(QAbstractSocket::ProxyNotFoundError);
2516     QTest::newRow("no-such-host-http") << int(QNetworkProxy::HttpProxy)
2517                                        << "this-host-will-never-exist.troll.no" << 3128 << false
2518                                        << int(QAbstractSocket::ProxyNotFoundError);
2519     QTest::newRow("http-on-socks5") << int(QNetworkProxy::HttpProxy) << fluke << 1080 << false
2520                                     << int(QAbstractSocket::ProxyConnectionClosedError);
2521     QTest::newRow("socks5-on-http") << int(QNetworkProxy::Socks5Proxy) << fluke << 3128 << false
2522                                     << int(QAbstractSocket::SocketTimeoutError);
2523 }
2524
2525 void tst_QTcpSocket::invalidProxy()
2526 {
2527     QFETCH_GLOBAL(bool, setProxy);
2528     if (setProxy)
2529         return;
2530
2531     QFETCH(int, type);
2532     QFETCH(QString, host);
2533     QFETCH(int, port);
2534     QFETCH(bool, failsAtConnect);
2535     QNetworkProxy::ProxyType proxyType = QNetworkProxy::ProxyType(type);
2536     QNetworkProxy proxy(proxyType, host, port);
2537
2538     QTcpSocket *socket = newSocket();
2539     socket->setProxy(proxy);
2540     socket->connectToHost(QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString(), 80);
2541
2542     if (failsAtConnect) {
2543         QCOMPARE(socket->state(), QAbstractSocket::UnconnectedState);
2544     } else {
2545         QCOMPARE(socket->state(), QAbstractSocket::ConnectingState);
2546         QVERIFY(!socket->waitForConnected(5000));
2547     }
2548     QVERIFY(!socket->errorString().isEmpty());
2549
2550     // note: the following test is not a hard failure.
2551     // Sometimes, error codes change for the better
2552     QTEST(int(socket->error()), "expectedError");
2553
2554     delete socket;
2555 }
2556
2557 // copied from tst_qnetworkreply.cpp
2558 class MyProxyFactory: public QNetworkProxyFactory
2559 {
2560 public:
2561     int callCount;
2562     QList<QNetworkProxy> toReturn;
2563     QNetworkProxyQuery lastQuery;
2564     inline MyProxyFactory() { clear(); }
2565
2566     inline void clear()
2567     {
2568         callCount = 0;
2569         toReturn = QList<QNetworkProxy>() << QNetworkProxy::DefaultProxy;
2570         lastQuery = QNetworkProxyQuery();
2571     }
2572
2573     virtual QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query)
2574     {
2575         lastQuery = query;
2576         ++callCount;
2577         return toReturn;
2578     }
2579 };
2580
2581 void tst_QTcpSocket::proxyFactory_data()
2582 {
2583     QTest::addColumn<QList<QNetworkProxy> >("proxyList");
2584     QTest::addColumn<QNetworkProxy>("proxyUsed");
2585     QTest::addColumn<bool>("failsAtConnect");
2586     QTest::addColumn<int>("expectedError");
2587
2588     QList<QNetworkProxy> proxyList;
2589
2590     // tests that do connect
2591
2592     proxyList << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3129);
2593     QTest::newRow("http")
2594         << proxyList << proxyList.at(0)
2595         << false << int(QAbstractSocket::UnknownSocketError);
2596
2597     proxyList.clear();
2598     proxyList << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1081);
2599     QTest::newRow("socks5")
2600         << proxyList << proxyList.at(0)
2601         << false << int(QAbstractSocket::UnknownSocketError);
2602
2603     proxyList.clear();
2604     proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129)
2605               << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1081);
2606     QTest::newRow("cachinghttp+socks5")
2607         << proxyList << proxyList.at(1)
2608         << false << int(QAbstractSocket::UnknownSocketError);
2609
2610     proxyList.clear();
2611     proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121)
2612               << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129)
2613               << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1081);
2614     QTest::newRow("ftp+cachinghttp+socks5")
2615         << proxyList << proxyList.at(2)
2616         << false << int(QAbstractSocket::UnknownSocketError);
2617
2618     // tests that fail to connect
2619     proxyList.clear();
2620     proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129);
2621     QTest::newRow("cachinghttp")
2622         << proxyList << QNetworkProxy()
2623         << true << int(QAbstractSocket::UnsupportedSocketOperationError);
2624
2625     proxyList.clear();
2626     proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121);
2627     QTest::newRow("ftp")
2628         << proxyList << QNetworkProxy()
2629         << true << int(QAbstractSocket::UnsupportedSocketOperationError);
2630
2631     proxyList.clear();
2632     proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121)
2633               << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129);
2634     QTest::newRow("ftp+cachinghttp")
2635         << proxyList << QNetworkProxy()
2636         << true << int(QAbstractSocket::UnsupportedSocketOperationError);
2637 }
2638
2639 void tst_QTcpSocket::proxyFactory()
2640 {
2641     QFETCH_GLOBAL(bool, setProxy);
2642     if (setProxy)
2643         return;
2644
2645     QFETCH(QList<QNetworkProxy>, proxyList);
2646     QFETCH(QNetworkProxy, proxyUsed);
2647     QFETCH(bool, failsAtConnect);
2648
2649     MyProxyFactory *factory = new MyProxyFactory;
2650     factory->toReturn = proxyList;
2651     QNetworkProxyFactory::setApplicationProxyFactory(factory);
2652
2653     QTcpSocket *socket = newSocket();
2654     QString host = QtNetworkSettings::serverName();
2655     socket->connectToHost(host, 80);
2656
2657     // Verify that the factory was called properly
2658     QCOMPARE(factory->callCount, 1);
2659     QCOMPARE(factory->lastQuery, QNetworkProxyQuery(host, 80));
2660
2661     if (failsAtConnect) {
2662         QCOMPARE(socket->state(), QAbstractSocket::UnconnectedState);
2663     } else {
2664         QCOMPARE(socket->state(), QAbstractSocket::ConnectingState);
2665         QVERIFY(socket->waitForConnected(5000));
2666         QCOMPARE(proxyAuthCalled, 1);
2667     }
2668     QVERIFY(!socket->errorString().isEmpty());
2669
2670     // note: the following test is not a hard failure.
2671     // Sometimes, error codes change for the better
2672     QTEST(int(socket->error()), "expectedError");
2673
2674     delete socket;
2675 }
2676
2677 // there is a similar test inside tst_qtcpserver that uses the event loop instead
2678 void tst_QTcpSocket::qtbug14268_peek()
2679 {
2680     QFETCH_GLOBAL(bool, setProxy);
2681     if (setProxy)
2682         return;
2683
2684     SocketPair socketPair;
2685     QVERIFY(socketPair.create());
2686     QTcpSocket *outgoing = socketPair.endPoints[0];
2687     QTcpSocket *incoming = socketPair.endPoints[1];
2688
2689     QVERIFY(incoming->state() == QTcpSocket::ConnectedState);
2690     QVERIFY(outgoing->state() == QTcpSocket::ConnectedState);
2691
2692     outgoing->write("abc\n");
2693     QVERIFY(outgoing->waitForBytesWritten(2000));
2694     QVERIFY(incoming->waitForReadyRead(2000));
2695     QVERIFY(incoming->peek(128*1024) == QByteArray("abc\n"));
2696
2697     outgoing->write("def\n");
2698     QVERIFY(outgoing->waitForBytesWritten(2000));
2699     QVERIFY(incoming->waitForReadyRead(2000));
2700     QVERIFY(incoming->peek(128*1024) == QByteArray("abc\ndef\n"));
2701
2702     outgoing->write("ghi\n");
2703     QVERIFY(outgoing->waitForBytesWritten(2000));
2704     QVERIFY(incoming->waitForReadyRead(2000));
2705     QVERIFY(incoming->peek(128*1024) == QByteArray("abc\ndef\nghi\n"));
2706
2707     QVERIFY(incoming->read(128*1024) == QByteArray("abc\ndef\nghi\n"));
2708 }
2709
2710 void tst_QTcpSocket::setSocketOption()
2711 {
2712     QFETCH_GLOBAL(bool, setProxy);
2713     if (setProxy)
2714         return;
2715
2716     SocketPair socketPair;
2717     QVERIFY(socketPair.create());
2718     QTcpSocket *outgoing = socketPair.endPoints[0];
2719     QTcpSocket *incoming = socketPair.endPoints[1];
2720
2721     QVERIFY(incoming->state() == QTcpSocket::ConnectedState);
2722     QVERIFY(outgoing->state() == QTcpSocket::ConnectedState);
2723
2724     outgoing->setSocketOption(QAbstractSocket::LowDelayOption, true);
2725     QVariant v = outgoing->socketOption(QAbstractSocket::LowDelayOption);
2726     QVERIFY(v.isValid() && v.toBool());
2727     outgoing->setSocketOption(QAbstractSocket::KeepAliveOption, true);
2728     v = outgoing->socketOption(QAbstractSocket::KeepAliveOption);
2729     QVERIFY(v.isValid() && v.toBool());
2730
2731     outgoing->setSocketOption(QAbstractSocket::LowDelayOption, false);
2732     v = outgoing->socketOption(QAbstractSocket::LowDelayOption);
2733     QVERIFY(v.isValid() && !v.toBool());
2734     outgoing->setSocketOption(QAbstractSocket::KeepAliveOption, false);
2735     v = outgoing->socketOption(QAbstractSocket::KeepAliveOption);
2736     QVERIFY(v.isValid() && !v.toBool());
2737
2738 #ifdef Q_OS_WIN
2739     QEXPECT_FAIL("", "QTBUG-23323", Abort);
2740 #endif
2741     outgoing->setSocketOption(QAbstractSocket::TypeOfServiceOption, 32); //high priority
2742     v = outgoing->socketOption(QAbstractSocket::TypeOfServiceOption);
2743     QVERIFY(v.isValid() && v.toInt() == 32);
2744 }
2745
2746 QTEST_MAIN(tst_QTcpSocket)
2747 #include "tst_qtcpsocket.moc"