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