1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
44 // To prevent windows system header files from re-defining min/max
49 #include <sys/types.h>
50 #include <sys/socket.h>
54 #define INVALID_SOCKET -1
57 #include <qplatformdefs.h>
59 #include <QtTest/QtTest>
61 #include <QAuthenticator>
62 #include <QCoreApplication>
65 #include <QHostAddress>
70 #include <QStringList>
76 #include <QTextStream>
81 // RVCT compiles also unused inline methods
82 # include <QNetworkProxy>
91 #include "private/qhostinfo_p.h"
93 #include "../../../network-settings.h"
95 QT_FORWARD_DECLARE_CLASS(QTcpSocket)
98 class tst_QTcpSocket : public QObject
104 virtual ~tst_QTcpSocket();
106 static void enterLoop(int secs)
109 QTestEventLoop::instance().enterLoop(secs);
112 static void exitLoop()
114 // Safe exit - if we aren't in an event loop, don't
117 QTestEventLoop::instance().exitLoop();
119 static bool timeout()
121 return QTestEventLoop::instance().timeout();
125 void initTestCase_data();
130 void socketsConstructedBeforeEventLoop();
134 void setInvalidSocketDescriptor();
135 void setSocketDescriptor();
136 void socketDescriptor();
138 void nonBlockingIMAP();
140 void timeoutConnect_data();
141 void timeoutConnect();
145 void readAllAfterClose();
146 void openCloseOpenClose();
147 void connectDisconnectConnectDisconnect();
148 void disconnectWhileConnecting_data();
149 void disconnectWhileConnecting();
150 void disconnectWhileConnectingNoEventLoop_data();
151 void disconnectWhileConnectingNoEventLoop();
152 void disconnectWhileLookingUp_data();
153 void disconnectWhileLookingUp();
154 void downloadBigFile();
156 void readLineString();
158 void waitForBytesWritten();
159 void waitForBytesWrittenMinusOne();
160 void waitForReadyRead();
161 void waitForReadyReadMinusOne();
163 void synchronousApi();
164 void dontCloseOnTimeout();
165 void recursiveReadyRead();
167 void socketInAThread();
168 void socketsInThreads();
169 void waitForReadyReadInASlot();
170 void remoteCloseError();
171 void nestedEventLoopInErrorSlot();
173 void connectToLocalHostNoService();
175 void waitForConnectedInHostLookupSlot();
176 void waitForConnectedInHostLookupSlot2();
177 void readyReadSignalsAfterWaitForReadyRead();
179 void linuxKernelBugLocalSocket();
181 void abortiveClose();
182 void localAddressEmptyOnBSD();
183 void zeroAndMinusOneReturns();
184 void connectionRefused();
185 void suddenRemoteDisconnect_data();
186 void suddenRemoteDisconnect();
187 void connectToMultiIP();
188 void moveToThread0();
189 void increaseReadBufferSize();
190 void taskQtBug5799ConnectionErrorWaitForConnected();
191 void taskQtBug5799ConnectionErrorEventLoop();
192 void taskQtBug7054TimeoutErrorResetting();
194 void invalidProxy_data();
196 void proxyFactory_data();
199 void qtbug14268_peek();
201 void setSocketOption();
205 void nonBlockingIMAP_hostFound();
206 void nonBlockingIMAP_connected();
207 void nonBlockingIMAP_closed();
208 void nonBlockingIMAP_readyRead();
209 void nonBlockingIMAP_bytesWritten(qint64);
210 void readRegularFile_readyRead();
212 void downloadBigFileSlot();
213 void recursiveReadyReadSlot();
214 void waitForReadyReadInASlotSlot();
215 void enterLoopSlot();
216 void hostLookupSlot();
217 void abortiveClose_abortSlot();
218 void remoteCloseErrorSlot();
219 void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth);
220 void earlySocketBytesSent(qint64 bytes);
221 void earlySocketReadyRead();
224 QByteArray expectedReplyIMAP();
225 void fetchExpectedReplyIMAP();
226 QTcpSocket *newSocket() const;
227 QTcpSocket *nonBlockingIMAP_socket;
228 QStringList nonBlockingIMAP_data;
229 qint64 nonBlockingIMAP_totalWritten;
231 QTcpSocket *tmpSocket;
232 qint64 bytesAvailable;
233 qint64 expectedLength;
237 QByteArray expectedReplyIMAP_cached;
239 mutable int proxyAuthCalled;
241 bool gotClosedSignal;
243 static int loopLevel;
245 SocketPair *earlyConstructedSockets;
246 int earlyBytesWrittenCount;
247 int earlyReadyReadCount;
248 QString stressTestDir;
263 int tst_QTcpSocket::loopLevel = 0;
265 class SocketPair: public QObject
269 QTcpSocket *endPoints[2];
271 SocketPair(QObject *parent = 0)
274 endPoints[0] = endPoints[1] = 0;
282 QTcpSocket *active = new QTcpSocket(this);
283 active->connectToHost("127.0.0.1", server.serverPort());
285 if (!active->waitForConnected(1000))
288 if (!server.waitForNewConnection(1000))
291 QTcpSocket *passive = server.nextPendingConnection();
292 passive->setParent(this);
294 endPoints[0] = active;
295 endPoints[1] = passive;
300 tst_QTcpSocket::tst_QTcpSocket()
304 //This code relates to the socketsConstructedBeforeEventLoop test case
305 earlyConstructedSockets = new SocketPair;
306 QVERIFY(earlyConstructedSockets->create());
307 earlyBytesWrittenCount = 0;
308 earlyReadyReadCount = 0;
309 connect(earlyConstructedSockets->endPoints[0], SIGNAL(readyRead()), this, SLOT(earlySocketReadyRead()));
310 connect(earlyConstructedSockets->endPoints[1], SIGNAL(bytesWritten(qint64)), this, SLOT(earlySocketBytesSent(qint64)));
311 earlyConstructedSockets->endPoints[1]->write("hello work");
314 tst_QTcpSocket::~tst_QTcpSocket()
319 void tst_QTcpSocket::initTestCase_data()
321 QTest::addColumn<bool>("setProxy");
322 QTest::addColumn<int>("proxyType");
323 QTest::addColumn<bool>("ssl");
325 qDebug() << QtNetworkSettings::serverName();
326 QTest::newRow("WithoutProxy") << false << 0 << false;
327 QTest::newRow("WithSocks5Proxy") << true << int(Socks5Proxy) << false;
328 QTest::newRow("WithSocks5ProxyAuth") << true << int(Socks5Proxy | AuthBasic) << false;
330 QTest::newRow("WithHttpProxy") << true << int(HttpProxy) << false;
331 QTest::newRow("WithHttpProxyBasicAuth") << true << int(HttpProxy | AuthBasic) << false;
332 // QTest::newRow("WithHttpProxyNtlmAuth") << true << int(HttpProxy | AuthNtlm) << false;
335 QTest::newRow("WithoutProxy SSL") << false << 0 << true;
336 QTest::newRow("WithSocks5Proxy SSL") << true << int(Socks5Proxy) << true;
337 QTest::newRow("WithSocks5AuthProxy SSL") << true << int(Socks5Proxy | AuthBasic) << true;
339 QTest::newRow("WithHttpProxy SSL") << true << int(HttpProxy) << true;
340 QTest::newRow("WithHttpProxyBasicAuth SSL") << true << int(HttpProxy | AuthBasic) << true;
341 // QTest::newRow("WithHttpProxyNtlmAuth SSL") << true << int(HttpProxy | AuthNtlm) << true;
344 stressTestDir = QFINDTESTDATA("stressTest");
345 QVERIFY2(!stressTestDir.isEmpty(), qPrintable(
346 QString::fromLatin1("Couldn't find stressTest dir starting from %1.").arg(QDir::currentPath())));
349 void tst_QTcpSocket::initTestCase()
351 QVERIFY(QtNetworkSettings::verifyTestNetworkSettings());
354 void tst_QTcpSocket::init()
356 QFETCH_GLOBAL(bool, 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();
366 proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, fluke, 1080);
369 case Socks5Proxy | AuthBasic:
370 proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, fluke, 1081);
373 case HttpProxy | NoAuth:
374 proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3128);
377 case HttpProxy | AuthBasic:
378 proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3129);
381 case HttpProxy | AuthNtlm:
382 proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3130);
385 QNetworkProxy::setApplicationProxy(proxy);
388 qt_qhostinfo_clear_cache();
391 QTcpSocket *tst_QTcpSocket::newSocket() const
395 QFETCH_GLOBAL(bool, ssl);
396 socket = ssl ? new QSslSocket : new QTcpSocket;
398 socket = new QTcpSocket;
402 connect(socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
403 SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
404 Qt::DirectConnection);
408 void tst_QTcpSocket::cleanup()
410 QNetworkProxy::setApplicationProxy(QNetworkProxy::DefaultProxy);
413 void tst_QTcpSocket::proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth)
416 auth->setUser("qsockstest");
417 auth->setPassword("password");
420 //----------------------------------------------------------------------------------
422 void tst_QTcpSocket::socketsConstructedBeforeEventLoop()
424 QFETCH_GLOBAL(bool, setProxy);
425 QFETCH_GLOBAL(bool, ssl);
428 //This test checks that sockets constructed before QCoreApplication::exec() still emit signals
429 //see construction code in the tst_QTcpSocket constructor
431 QCOMPARE(earlyBytesWrittenCount, 1);
432 QCOMPARE(earlyReadyReadCount, 1);
433 earlyConstructedSockets->endPoints[0]->close();
434 earlyConstructedSockets->endPoints[1]->close();
437 void tst_QTcpSocket::earlySocketBytesSent(qint64 /* bytes */)
439 earlyBytesWrittenCount++;
442 void tst_QTcpSocket::earlySocketReadyRead()
444 earlyReadyReadCount++;
447 //----------------------------------------------------------------------------------
449 void tst_QTcpSocket::constructing()
451 QTcpSocket *socket = newSocket();
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);
461 QCOMPARE(socket->getChar(&c), false);
462 QCOMPARE((int) socket->bytesAvailable(), 0);
463 QCOMPARE(socket->canReadLine(), false);
464 QCOMPARE(socket->readLine(), QByteArray());
465 QCOMPARE(socket->socketDescriptor(), (qintptr)-1);
466 QCOMPARE((int) socket->localPort(), 0);
467 QVERIFY(socket->localAddress() == QHostAddress());
468 QCOMPARE((int) socket->peerPort(), 0);
469 QVERIFY(socket->peerAddress() == QHostAddress());
470 QCOMPARE(socket->error(), QTcpSocket::UnknownSocketError);
471 QCOMPARE(socket->errorString(), QString("Unknown error"));
473 // Check the state of the socket layer?
477 //----------------------------------------------------------------------------------
479 void tst_QTcpSocket::bind_data()
481 QTest::addColumn<QString>("stringAddr");
482 QTest::addColumn<bool>("successExpected");
483 QTest::addColumn<QString>("stringExpectedLocalAddress");
485 // iterate all interfaces, add all addresses on them as test data
486 QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
487 foreach (const QNetworkInterface &interface, interfaces) {
488 if (!interface.isValid())
491 foreach (const QNetworkAddressEntry &entry, interface.addressEntries()) {
492 if (entry.ip().isInSubnet(QHostAddress::parseSubnet("fe80::/10"))
493 || entry.ip().isInSubnet(QHostAddress::parseSubnet("169.254/16")))
494 continue; // link-local bind will fail, at least on Linux, so skip it.
496 QString ip(entry.ip().toString());
497 QTest::newRow(ip.toLatin1().constData()) << ip << true << ip;
501 // additionally, try bind to known-bad addresses, and make sure this doesn't work
502 // these ranges are guaranteed to be reserved for 'documentation purposes',
503 // and thus, should be unused in the real world. Not that I'm assuming the
504 // world is full of competent administrators, or anything.
505 QStringList knownBad;
506 knownBad << "198.51.100.1";
507 knownBad << "2001:0DB8::1";
508 foreach (const QString &badAddress, knownBad) {
509 QTest::newRow(badAddress.toLatin1().constData()) << badAddress << false << QString();
513 void tst_QTcpSocket::bind()
515 QFETCH_GLOBAL(bool, setProxy);
517 QSKIP("QTBUG-22964");
518 QFETCH(QString, stringAddr);
519 QFETCH(bool, successExpected);
520 QFETCH(QString, stringExpectedLocalAddress);
522 QHostAddress addr(stringAddr);
523 QHostAddress expectedLocalAddress(stringExpectedLocalAddress);
525 QTcpSocket *socket = newSocket();
526 qDebug() << "Binding " << addr;
528 if (successExpected) {
529 QVERIFY2(socket->bind(addr), qPrintable(socket->errorString()));
531 QVERIFY(!socket->bind(addr));
534 QCOMPARE(socket->localAddress(), expectedLocalAddress);
539 //----------------------------------------------------------------------------------
542 void tst_QTcpSocket::setInvalidSocketDescriptor()
544 QTcpSocket *socket = newSocket();
545 QCOMPARE(socket->socketDescriptor(), (qintptr)-1);
546 QVERIFY(!socket->setSocketDescriptor(-5, QTcpSocket::UnconnectedState));
547 QCOMPARE(socket->socketDescriptor(), (qintptr)-1);
549 QCOMPARE(socket->error(), QTcpSocket::UnsupportedSocketOperationError);
554 //----------------------------------------------------------------------------------
556 void tst_QTcpSocket::setSocketDescriptor()
558 QFETCH_GLOBAL(bool, setProxy);
560 return; // this test doesn't make sense with proxies
563 // need the dummy to ensure winsock is started
564 QTcpSocket *dummy = newSocket();
565 dummy->connectToHost(QtNetworkSettings::serverName(), 143);
566 QVERIFY(dummy->waitForConnected());
568 SOCKET sock = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
569 if (sock == INVALID_SOCKET) {
570 qErrnoWarning(WSAGetLastError(), "INVALID_SOCKET");
573 SOCKET sock = ::socket(AF_INET, SOCK_STREAM, 0);
575 // artificially increase the value of sock
576 SOCKET sock2 = ::fcntl(sock, F_DUPFD, sock + 50);
581 QVERIFY(sock != INVALID_SOCKET);
582 QTcpSocket *socket = newSocket();
583 QVERIFY(socket->setSocketDescriptor(sock, QTcpSocket::UnconnectedState));
584 QCOMPARE(socket->socketDescriptor(), (qintptr)sock);
586 qt_qhostinfo_clear_cache(); //avoid the HostLookupState being skipped due to address being in cache from previous test.
587 socket->connectToHost(QtNetworkSettings::serverName(), 143);
588 QCOMPARE(socket->state(), QTcpSocket::HostLookupState);
589 QCOMPARE(socket->socketDescriptor(), (qintptr)sock);
590 QVERIFY(socket->waitForConnected(10000));
591 // skip this, it has been broken for years, see task 260735
592 // if somebody complains, consider fixing it, but it might break existing applications.
593 QEXPECT_FAIL("", "bug has been around for years, will not fix without need", Continue);
594 QCOMPARE(socket->socketDescriptor(), (qintptr)sock);
601 //----------------------------------------------------------------------------------
603 void tst_QTcpSocket::socketDescriptor()
605 QTcpSocket *socket = newSocket();
607 QCOMPARE(socket->socketDescriptor(), (qintptr)-1);
608 socket->connectToHost(QtNetworkSettings::serverName(), 143);
609 QVERIFY((socket->state() == QAbstractSocket::HostLookupState && socket->socketDescriptor() == -1) ||
610 (socket->state() == QAbstractSocket::ConnectingState && socket->socketDescriptor() != -1));
611 QVERIFY(socket->waitForConnected(10000));
612 QVERIFY(socket->state() == QAbstractSocket::ConnectedState);
613 QVERIFY(socket->socketDescriptor() != -1);
618 //----------------------------------------------------------------------------------
620 void tst_QTcpSocket::blockingIMAP()
622 QTcpSocket *socket = newSocket();
625 socket->connectToHost(QtNetworkSettings::serverName(), 143);
626 QVERIFY(socket->waitForConnected(10000));
627 QCOMPARE(socket->state(), QTcpSocket::ConnectedState);
628 QVERIFY(socket->isValid());
631 QVERIFY(socket->waitForReadyRead(5000));
632 QString s = socket->readLine();
633 // only test if an OK was returned, to make the test compatible between different
634 // IMAP server versions
635 QCOMPARE(s.left(4).toLatin1().constData(), "* OK");
638 QCOMPARE((int) socket->write("1 NOOP\r\n", 8), 8);
639 QCOMPARE((int) socket->write("2 NOOP\r\n", 8), 8);
641 if (!socket->canReadLine())
642 QVERIFY(socket->waitForReadyRead(5000));
645 s = socket->readLine();
646 QCOMPARE(s.toLatin1().constData(), "1 OK Completed\r\n");
648 // Write a third NOOP to verify that write doesn't clear the read buffer
649 QCOMPARE((int) socket->write("3 NOOP\r\n", 8), 8);
651 // Read second response
652 if (!socket->canReadLine())
653 QVERIFY(socket->waitForReadyRead(5000));
654 s = socket->readLine();
655 QCOMPARE(s.toLatin1().constData(), "2 OK Completed\r\n");
657 // Read third response
658 if (!socket->canReadLine())
659 QVERIFY(socket->waitForReadyRead(5000));
660 s = socket->readLine();
661 QCOMPARE(s.toLatin1().constData(), "3 OK Completed\r\n");
665 QCOMPARE((int) socket->write("4 LOGOUT\r\n", 10), 10);
667 if (!socket->canReadLine())
668 QVERIFY(socket->waitForReadyRead(5000));
670 // Read two lines of respose
671 s = socket->readLine();
672 QCOMPARE(s.toLatin1().constData(), "* BYE LOGOUT received\r\n");
674 if (!socket->canReadLine())
675 QVERIFY(socket->waitForReadyRead(5000));
677 s = socket->readLine();
678 QCOMPARE(s.toLatin1().constData(), "4 OK Completed\r\n");
683 // Check that it's closed
684 QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
689 //----------------------------------------------------------------------------------
691 void tst_QTcpSocket::hostNotFound()
693 QTcpSocket *socket = newSocket();
695 socket->connectToHost("nosuchserver.troll.no", 80);
696 QVERIFY(!socket->waitForConnected());
697 QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
698 QCOMPARE(int(socket->error()), int(QTcpSocket::HostNotFoundError));
703 //----------------------------------------------------------------------------------
704 void tst_QTcpSocket::timeoutConnect_data()
706 QTest::addColumn<QString>("address");
707 QTest::newRow("host") << QtNetworkSettings::serverName();
708 QTest::newRow("ip") << QtNetworkSettings::serverIP().toString();
711 void tst_QTcpSocket::timeoutConnect()
713 QFETCH(QString, address);
714 QTcpSocket *socket = newSocket();
719 // Port 1357 is configured to drop packets on the test server
720 socket->connectToHost(address, 1357);
721 QVERIFY(timer.elapsed() < 150);
722 QVERIFY(!socket->waitForConnected(1000)); //200ms is too short when using SOCKS proxy authentication
723 QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
724 QCOMPARE(int(socket->error()), int(QTcpSocket::SocketTimeoutError));
727 socket->connectToHost(address, 1357);
728 QVERIFY(timer.elapsed() < 150);
729 QTimer::singleShot(50, &QTestEventLoop::instance(), SLOT(exitLoop()));
730 QTestEventLoop::instance().enterLoop(5);
731 QVERIFY(!QTestEventLoop::instance().timeout());
732 QVERIFY(socket->state() == QTcpSocket::ConnectingState
733 || socket->state() == QTcpSocket::HostLookupState);
735 QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
736 QCOMPARE(socket->openMode(), QIODevice::NotOpen);
741 //----------------------------------------------------------------------------------
743 void tst_QTcpSocket::nonBlockingIMAP()
745 QTcpSocket *socket = newSocket();
746 connect(socket, SIGNAL(hostFound()), SLOT(nonBlockingIMAP_hostFound()));
747 connect(socket, SIGNAL(connected()), SLOT(nonBlockingIMAP_connected()));
748 connect(socket, SIGNAL(disconnected()), SLOT(nonBlockingIMAP_closed()));
749 connect(socket, SIGNAL(bytesWritten(qint64)), SLOT(nonBlockingIMAP_bytesWritten(qint64)));
750 connect(socket, SIGNAL(readyRead()), SLOT(nonBlockingIMAP_readyRead()));
751 nonBlockingIMAP_socket = socket;
754 socket->connectToHost(QtNetworkSettings::serverName(), 143);
755 QVERIFY(socket->state() == QTcpSocket::HostLookupState ||
756 socket->state() == QTcpSocket::ConnectingState);
763 if (socket->state() == QTcpSocket::ConnectingState) {
770 QCOMPARE(socket->state(), QTcpSocket::ConnectedState);
778 QVERIFY(!nonBlockingIMAP_data.isEmpty());
779 QCOMPARE(nonBlockingIMAP_data.at(0).left(4).toLatin1().constData(), "* OK");
780 nonBlockingIMAP_data.clear();
782 nonBlockingIMAP_totalWritten = 0;
785 QCOMPARE((int) socket->write("1 NOOP\r\n", 8), 8);
793 QVERIFY(nonBlockingIMAP_totalWritten == 8);
803 QVERIFY(!nonBlockingIMAP_data.isEmpty());
804 QCOMPARE(nonBlockingIMAP_data.at(0).toLatin1().constData(), "1 OK Completed\r\n");
805 nonBlockingIMAP_data.clear();
808 nonBlockingIMAP_totalWritten = 0;
811 QCOMPARE((int) socket->write("2 LOGOUT\r\n", 10), 10);
818 QVERIFY(nonBlockingIMAP_totalWritten == 10);
826 // Read two lines of respose
827 QCOMPARE(nonBlockingIMAP_data.at(0).toLatin1().constData(), "* BYE LOGOUT received\r\n");
828 QCOMPARE(nonBlockingIMAP_data.at(1).toLatin1().constData(), "2 OK Completed\r\n");
829 nonBlockingIMAP_data.clear();
834 // Check that it's closed
835 QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
840 void tst_QTcpSocket::nonBlockingIMAP_hostFound()
845 void tst_QTcpSocket::nonBlockingIMAP_connected()
850 void tst_QTcpSocket::nonBlockingIMAP_readyRead()
852 while (nonBlockingIMAP_socket->canReadLine())
853 nonBlockingIMAP_data.append(nonBlockingIMAP_socket->readLine());
858 void tst_QTcpSocket::nonBlockingIMAP_bytesWritten(qint64 written)
860 nonBlockingIMAP_totalWritten += written;
864 void tst_QTcpSocket::nonBlockingIMAP_closed()
868 //----------------------------------------------------------------------------------
870 void tst_QTcpSocket::delayedClose()
872 QTcpSocket *socket = newSocket();
873 connect(socket, SIGNAL(connected()), SLOT(nonBlockingIMAP_connected()));
874 connect(socket, SIGNAL(disconnected()), SLOT(exitLoopSlot()));
876 socket->connectToHost(QtNetworkSettings::serverName(), 143);
882 QCOMPARE(socket->state(), QTcpSocket::ConnectedState);
884 QCOMPARE((int) socket->write("1 LOGOUT\r\n", 10), 10);
886 // Add a huge bulk of data to be written after the logout
887 // command. The server will shut down after receiving the LOGOUT,
888 // so this data will not be read. But our close call should
889 // schedule a delayed close because all the data can not be
890 // written in one go.
891 QCOMPARE((int) socket->write(QByteArray(100000, '\n'), 100000), 100000);
895 QCOMPARE((int) socket->state(), (int) QTcpSocket::ClosingState);
901 QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
907 //----------------------------------------------------------------------------------
909 QByteArray tst_QTcpSocket::expectedReplyIMAP()
911 if (expectedReplyIMAP_cached.isEmpty()) {
912 fetchExpectedReplyIMAP();
915 return expectedReplyIMAP_cached;
918 // Figure out how the current IMAP server responds
919 void tst_QTcpSocket::fetchExpectedReplyIMAP()
921 QTcpSocket *socket = newSocket();
922 socket->connectToHost(QtNetworkSettings::serverName(), 143);
923 QVERIFY2(socket->waitForConnected(10000), qPrintable(socket->errorString()));
924 QVERIFY2(socket->state() == QTcpSocket::ConnectedState, qPrintable(socket->errorString()));
926 QTRY_VERIFY(socket->canReadLine());
928 QByteArray greeting = socket->readLine();
931 QVERIFY2(QtNetworkSettings::compareReplyIMAP(greeting), greeting.constData());
933 expectedReplyIMAP_cached = greeting;
936 //----------------------------------------------------------------------------------
938 void tst_QTcpSocket::partialRead()
940 QTcpSocket *socket = newSocket();
941 socket->connectToHost(QtNetworkSettings::serverName(), 143);
942 QVERIFY(socket->waitForConnected(10000));
943 QVERIFY(socket->state() == QTcpSocket::ConnectedState);
946 QByteArray greeting = expectedReplyIMAP();
947 QVERIFY(!greeting.isEmpty());
949 for (int i = 0; i < 10; i += 2) {
950 while (socket->bytesAvailable() < 2)
951 QVERIFY(socket->waitForReadyRead(5000));
952 QVERIFY(socket->read(buf, 2) == 2);
954 QCOMPARE((char *)buf, greeting.mid(i, 2).data());
960 //----------------------------------------------------------------------------------
962 void tst_QTcpSocket::unget()
964 QTcpSocket *socket = newSocket();
965 socket->connectToHost(QtNetworkSettings::serverName(), 143);
966 QVERIFY(socket->waitForConnected(10000));
967 QVERIFY(socket->state() == QTcpSocket::ConnectedState);
970 QByteArray greeting = expectedReplyIMAP();
971 QVERIFY(!greeting.isEmpty());
973 for (int i = 0; i < 10; i += 2) {
974 while (socket->bytesAvailable() < 2)
975 QVERIFY(socket->waitForReadyRead(10000));
976 int bA = socket->bytesAvailable();
977 QVERIFY(socket->read(buf, 2) == 2);
979 QCOMPARE((char *)buf, greeting.mid(i, 2).data());
980 QCOMPARE((int)socket->bytesAvailable(), bA - 2);
981 socket->ungetChar(buf[1]);
982 socket->ungetChar(buf[0]);
983 QCOMPARE((int)socket->bytesAvailable(), bA);
984 QVERIFY(socket->read(buf, 2) == 2);
986 QCOMPARE((char *)buf, greeting.mid(i, 2).data());
992 //----------------------------------------------------------------------------------
993 void tst_QTcpSocket::readRegularFile_readyRead()
998 //----------------------------------------------------------------------------------
999 void tst_QTcpSocket::readAllAfterClose()
1001 QTcpSocket *socket = newSocket();
1002 socket->connectToHost(QtNetworkSettings::serverName(), 143);
1003 connect(socket, SIGNAL(readyRead()), SLOT(readRegularFile_readyRead()));
1006 QFAIL("Network operation timed out");
1009 QByteArray array = socket->readAll();
1010 QCOMPARE(array.size(), 0);
1015 //----------------------------------------------------------------------------------
1016 void tst_QTcpSocket::openCloseOpenClose()
1018 QTcpSocket *socket = newSocket();
1020 for (int i = 0; i < 3; ++i) {
1021 QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
1022 QCOMPARE(int(socket->openMode()), int(QIODevice::NotOpen));
1023 QVERIFY(socket->isSequential());
1024 QVERIFY(!socket->isOpen());
1025 QVERIFY(socket->socketType() == QTcpSocket::TcpSocket);
1028 QCOMPARE(socket->getChar(&c), false);
1029 QCOMPARE((int) socket->bytesAvailable(), 0);
1030 QCOMPARE(socket->canReadLine(), false);
1031 QCOMPARE(socket->readLine(), QByteArray());
1032 QCOMPARE(socket->socketDescriptor(), (qintptr)-1);
1033 QCOMPARE((int) socket->localPort(), 0);
1034 QVERIFY(socket->localAddress() == QHostAddress());
1035 QCOMPARE((int) socket->peerPort(), 0);
1036 QVERIFY(socket->peerAddress() == QHostAddress());
1037 QCOMPARE(socket->error(), QTcpSocket::UnknownSocketError);
1038 QCOMPARE(socket->errorString(), QString("Unknown error"));
1040 QVERIFY(socket->state() == QTcpSocket::UnconnectedState);
1042 socket->connectToHost(QtNetworkSettings::serverName(), 143);
1043 QVERIFY(socket->waitForConnected(10000));
1050 //----------------------------------------------------------------------------------
1051 void tst_QTcpSocket::connectDisconnectConnectDisconnect()
1053 QTcpSocket *socket = newSocket();
1055 for (int i = 0; i < 3; ++i) {
1056 QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
1057 QVERIFY(socket->socketType() == QTcpSocket::TcpSocket);
1059 socket->connectToHost(QtNetworkSettings::serverName(), 143);
1060 QVERIFY(socket->waitForReadyRead(10000));
1061 QCOMPARE(QString::fromLatin1(socket->read(4)), QString("* OK"));
1063 socket->disconnectFromHost();
1064 if (socket->state() != QTcpSocket::UnconnectedState)
1065 QVERIFY(socket->waitForDisconnected(10000));
1066 QCOMPARE(int(socket->openMode()), int(QIODevice::ReadWrite));
1072 //----------------------------------------------------------------------------------
1073 void tst_QTcpSocket::disconnectWhileConnecting_data()
1075 QTest::addColumn<QByteArray>("data");
1076 QTest::addColumn<bool>("closeDirectly");
1078 QTest::newRow("without-data") << QByteArray() << false;
1079 QTest::newRow("without-data+close") << QByteArray() << true;
1080 QTest::newRow("with-data") << QByteArray("Hello, world!") << false;
1081 QTest::newRow("with-data+close") << QByteArray("Hello, world!") << true;
1083 QByteArray bigData(1024*1024, '@');
1084 QTest::newRow("with-big-data") << bigData << false;
1085 QTest::newRow("with-big-data+close") << bigData << true;
1088 void tst_QTcpSocket::disconnectWhileConnecting()
1090 QFETCH(QByteArray, data);
1091 QFETCH_GLOBAL(bool, setProxy);
1093 return; //proxy not useful for localhost test case
1096 QVERIFY(server.listen(QHostAddress::LocalHost));
1098 // proceed to the connect-write-disconnect
1099 QTcpSocket *socket = newSocket();
1100 socket->connectToHost("127.0.0.1", server.serverPort());
1101 if (!data.isEmpty())
1102 socket->write(data);
1103 if (socket->state() == QAbstractSocket::ConnectedState)
1104 QSKIP("localhost connections are immediate, test case is invalid");
1106 QFETCH(bool, closeDirectly);
1107 if (closeDirectly) {
1109 QCOMPARE(int(socket->openMode()), int(QIODevice::NotOpen));
1111 socket->disconnectFromHost();
1114 connect(socket, SIGNAL(disconnected()), SLOT(exitLoopSlot()));
1116 QVERIFY2(!timeout(), "Network timeout");
1117 QVERIFY(socket->state() == QAbstractSocket::UnconnectedState);
1118 if (!closeDirectly) {
1119 QCOMPARE(int(socket->openMode()), int(QIODevice::ReadWrite));
1122 QCOMPARE(int(socket->openMode()), int(QIODevice::NotOpen));
1124 // accept the other side and verify that it was sent properly:
1125 QVERIFY(server.hasPendingConnections() || server.waitForNewConnection(0));
1126 QTcpSocket *othersocket = server.nextPendingConnection();
1127 if (othersocket->state() != QAbstractSocket::UnconnectedState)
1128 QVERIFY2(othersocket->waitForDisconnected(10000), "Network timeout");
1129 QVERIFY(othersocket->state() == QAbstractSocket::UnconnectedState);
1130 QCOMPARE(othersocket->readAll(), data);
1136 //----------------------------------------------------------------------------------
1137 class ReceiverThread: public QThread
1143 QByteArray receivedData;
1147 : server(0), ok(false), quit(false)
1150 ~ReceiverThread() { }
1154 server = new QTcpServer;
1155 if (!server->listen(QHostAddress::LocalHost))
1157 serverPort = server->serverPort();
1158 server->moveToThread(this);
1162 static void cleanup(void *ptr)
1164 ReceiverThread* self = reinterpret_cast<ReceiverThread*>(ptr);
1173 bool timedOut = false;
1175 if (server->waitForNewConnection(500, &timedOut))
1181 QTcpSocket *socket = server->nextPendingConnection();
1183 if (socket->waitForDisconnected(500))
1185 if (socket->error() != QAbstractSocket::SocketTimeoutError)
1190 receivedData = socket->readAll();
1199 void tst_QTcpSocket::disconnectWhileConnectingNoEventLoop_data()
1201 disconnectWhileConnecting_data();
1204 void tst_QTcpSocket::disconnectWhileConnectingNoEventLoop()
1206 QFETCH(QByteArray, data);
1207 QFETCH_GLOBAL(bool, setProxy);
1209 return; //proxy not useful for localhost test case
1211 QScopedPointer<ReceiverThread, ReceiverThread> thread (new ReceiverThread);
1212 QVERIFY(thread->listen());
1215 // proceed to the connect-write-disconnect
1216 QTcpSocket *socket = newSocket();
1217 socket->connectToHost("127.0.0.1", thread->serverPort);
1218 if (!data.isEmpty())
1219 socket->write(data);
1220 if (socket->state() == QAbstractSocket::ConnectedState)
1221 QSKIP("localhost connections are immediate, test case is invalid");
1223 QFETCH(bool, closeDirectly);
1224 if (closeDirectly) {
1226 QCOMPARE(int(socket->openMode()), int(QIODevice::NotOpen));
1228 socket->disconnectFromHost();
1231 QVERIFY2(socket->waitForDisconnected(10000), "Network timeout");
1232 QVERIFY(socket->state() == QAbstractSocket::UnconnectedState);
1233 if (!closeDirectly) {
1234 QCOMPARE(int(socket->openMode()), int(QIODevice::ReadWrite));
1237 QCOMPARE(int(socket->openMode()), int(QIODevice::NotOpen));
1240 // check if the other side received everything ok
1241 QVERIFY(thread->wait(30000));
1242 QVERIFY(thread->ok);
1243 QCOMPARE(thread->receivedData, data);
1246 //----------------------------------------------------------------------------------
1247 void tst_QTcpSocket::disconnectWhileLookingUp_data()
1249 QTest::addColumn<bool>("doClose");
1251 QTest::newRow("disconnect") << false;
1252 QTest::newRow("close") << true;
1255 void tst_QTcpSocket::disconnectWhileLookingUp()
1257 QFETCH_GLOBAL(bool, setProxy);
1259 return; // we let the proxies do the lookup now
1261 // just connect and disconnect, then make sure nothing weird happened
1262 QTcpSocket *socket = newSocket();
1263 socket->connectToHost(QtNetworkSettings::serverName(), 21);
1265 // check that connect is in progress
1266 QVERIFY(socket->state() != QAbstractSocket::UnconnectedState);
1268 QFETCH(bool, doClose);
1271 QVERIFY(socket->openMode() == QIODevice::NotOpen);
1273 socket->disconnectFromHost();
1274 QVERIFY(socket->openMode() == QIODevice::ReadWrite);
1275 QVERIFY(socket->waitForDisconnected(5000));
1278 // let anything queued happen
1280 QTimer::singleShot(50, &loop, SLOT(quit()));
1285 QVERIFY(socket->openMode() == QIODevice::NotOpen);
1287 QVERIFY(socket->openMode() == QIODevice::ReadWrite);
1290 QVERIFY(socket->state() == QAbstractSocket::UnconnectedState);
1293 //----------------------------------------------------------------------------------
1294 void tst_QTcpSocket::downloadBigFile()
1298 tmpSocket = newSocket();
1300 connect(tmpSocket, SIGNAL(connected()), SLOT(exitLoopSlot()));
1301 connect(tmpSocket, SIGNAL(readyRead()), SLOT(downloadBigFileSlot()));
1302 connect(tmpSocket, SIGNAL(disconnected()), SLOT(exitLoopSlot()));
1304 tmpSocket->connectToHost(QtNetworkSettings::serverName(), 80);
1310 QFAIL("Network operation timed out");
1313 QByteArray hostName = QtNetworkSettings::serverName().toLatin1();
1314 QVERIFY(tmpSocket->state() == QAbstractSocket::ConnectedState);
1315 QVERIFY(tmpSocket->write("GET /qtest/mediumfile HTTP/1.0\r\n") > 0);
1316 QVERIFY(tmpSocket->write("HOST: ") > 0);
1317 QVERIFY(tmpSocket->write(hostName.data()) > 0);
1318 QVERIFY(tmpSocket->write("\r\n") > 0);
1319 QVERIFY(tmpSocket->write("\r\n") > 0);
1323 readingBody = false;
1332 if (bytesAvailable > 0)
1333 qDebug("Slow Connection, only downloaded %ld of %d", long(bytesAvailable), 10000281);
1334 QFAIL("Network operation timed out");
1337 QCOMPARE(bytesAvailable, expectedLength);
1339 qDebug("\t\t%.1fMB/%.1fs: %.1fMB/s",
1340 bytesAvailable / (1024.0 * 1024.0),
1341 stopWatch.elapsed() / 1024.0,
1342 (bytesAvailable / (stopWatch.elapsed() / 1000.0)) / (1024 * 1024));
1348 //----------------------------------------------------------------------------------
1349 void tst_QTcpSocket::exitLoopSlot()
1354 //----------------------------------------------------------------------------------
1355 void tst_QTcpSocket::downloadBigFileSlot()
1358 while (tmpSocket->canReadLine()) {
1359 QByteArray array = tmpSocket->readLine();
1360 if (array.startsWith("Content-Length"))
1361 expectedLength = array.simplified().split(' ').at(1).toInt();
1362 if (array == "\r\n") {
1369 bytesAvailable += tmpSocket->readAll().size();
1370 if (bytesAvailable == expectedLength)
1375 //----------------------------------------------------------------------------------
1376 void tst_QTcpSocket::readLine()
1378 QTcpSocket *socket = newSocket();
1379 socket->connectToHost(QtNetworkSettings::serverName(), 143);
1380 QVERIFY(socket->waitForConnected(5000));
1382 while (!socket->canReadLine())
1383 QVERIFY(socket->waitForReadyRead(10000));
1387 qint64 linelen = socket->readLine(buffer, sizeof(buffer));
1388 QVERIFY(linelen >= 3);
1389 QVERIFY(linelen < 1024);
1391 QByteArray reply = QByteArray::fromRawData(buffer, linelen);
1392 QCOMPARE((int) buffer[linelen-2], (int) '\r');
1393 QCOMPARE((int) buffer[linelen-1], (int) '\n');
1394 QCOMPARE((int) buffer[linelen], (int) '\0');
1396 QVERIFY2(QtNetworkSettings::compareReplyIMAP(reply), reply.constData());
1398 QCOMPARE(socket->write("1 NOOP\r\n"), qint64(8));
1400 while (socket->bytesAvailable() < 10)
1401 QVERIFY(socket->waitForReadyRead(10000));
1403 QCOMPARE(socket->readLine(buffer, 11), qint64(10));
1404 QCOMPARE((const char *)buffer, "1 OK Compl");
1406 while (socket->bytesAvailable() < 6)
1407 QVERIFY(socket->waitForReadyRead(10000));
1409 QCOMPARE(socket->readLine(buffer, 11), qint64(6));
1410 QCOMPARE((const char *)buffer, "eted\r\n");
1412 QVERIFY(!socket->waitForReadyRead(100));
1413 QCOMPARE(socket->readLine(buffer, sizeof(buffer)), qint64(0));
1414 QVERIFY(socket->error() == QAbstractSocket::SocketTimeoutError
1415 || socket->error() == QAbstractSocket::RemoteHostClosedError);
1416 QCOMPARE(socket->bytesAvailable(), qint64(0));
1419 QCOMPARE(socket->readLine(buffer, sizeof(buffer)), qint64(-1));
1424 //----------------------------------------------------------------------------------
1425 void tst_QTcpSocket::readLineString()
1427 QTcpSocket *socket = newSocket();
1428 socket->connectToHost(QtNetworkSettings::serverName(), 143);
1429 QVERIFY(socket->waitForReadyRead(10000));
1431 QByteArray arr = socket->readLine();
1432 QVERIFY2(QtNetworkSettings::compareReplyIMAP(arr), arr.constData());
1437 //----------------------------------------------------------------------------------
1438 void tst_QTcpSocket::readChunks()
1440 QTcpSocket *socket = newSocket();
1441 socket->connectToHost(QtNetworkSettings::serverName(), 143);
1442 QVERIFY(socket->waitForConnected(10000));
1443 QVERIFY(socket->waitForReadyRead(5000));
1446 memset(buf, '@', sizeof(buf));
1447 qint64 dataLength = socket->read(buf, sizeof(buf));
1448 QVERIFY(dataLength > 0);
1450 QCOMPARE(buf[dataLength - 2], '\r');
1451 QCOMPARE(buf[dataLength - 1], '\n');
1452 QCOMPARE(buf[dataLength], '@');
1457 //----------------------------------------------------------------------------------
1458 void tst_QTcpSocket::waitForBytesWritten()
1460 QTcpSocket *socket = newSocket();
1461 socket->connectToHost(QtNetworkSettings::serverName(), 80);
1462 QVERIFY(socket->waitForConnected(10000));
1464 socket->write("GET / HTTP/1.0\r\n\r\n");
1465 qint64 toWrite = socket->bytesToWrite();
1466 QVERIFY(socket->waitForBytesWritten(5000));
1467 QVERIFY(toWrite > socket->bytesToWrite());
1472 //----------------------------------------------------------------------------------
1473 void tst_QTcpSocket::waitForBytesWrittenMinusOne()
1476 QSKIP("QTBUG-24451 - indefinite wait may hang");
1478 QTcpSocket *socket = newSocket();
1479 socket->connectToHost(QtNetworkSettings::serverName(), 80);
1480 QVERIFY(socket->waitForConnected(10000));
1482 socket->write("GET / HTTP/1.0\r\n\r\n");
1483 qint64 toWrite = socket->bytesToWrite();
1484 QVERIFY(socket->waitForBytesWritten(-1));
1485 QVERIFY(toWrite > socket->bytesToWrite());
1490 //----------------------------------------------------------------------------------
1491 void tst_QTcpSocket::waitForReadyRead()
1493 QTcpSocket *socket = newSocket();
1494 socket->connectToHost(QtNetworkSettings::serverName(), 80);
1495 socket->write("GET / HTTP/1.0\r\n\r\n");
1496 QVERIFY(socket->waitForReadyRead(5000));
1500 //----------------------------------------------------------------------------------
1501 void tst_QTcpSocket::waitForReadyReadMinusOne()
1504 QSKIP("QTBUG-24451 - indefinite wait may hang");
1506 QTcpSocket *socket = newSocket();
1507 socket->connectToHost(QtNetworkSettings::serverName(), 80);
1508 socket->write("GET / HTTP/1.0\r\n\r\n");
1509 QVERIFY(socket->waitForReadyRead(-1));
1513 //----------------------------------------------------------------------------------
1514 void tst_QTcpSocket::flush()
1516 QTcpSocket *socket = newSocket();
1519 connect(socket, SIGNAL(connected()), SLOT(exitLoopSlot()));
1520 socket->connectToHost(QtNetworkSettings::serverName(), 143);
1522 QVERIFY(socket->isOpen());
1524 socket->write("1 LOGOUT\r\n");
1525 QCOMPARE(socket->bytesToWrite(), qint64(10));
1527 QCOMPARE(socket->bytesToWrite(), qint64(0));
1533 //----------------------------------------------------------------------------------
1534 void tst_QTcpSocket::synchronousApi()
1536 QTcpSocket *ftpSocket = newSocket();
1537 ftpSocket->connectToHost(QtNetworkSettings::serverName(), 21);
1538 ftpSocket->write("QUIT\r\n");
1539 QVERIFY(ftpSocket->waitForDisconnected(10000));
1540 QVERIFY(ftpSocket->bytesAvailable() > 0);
1541 QByteArray arr = ftpSocket->readAll();
1542 QVERIFY(arr.size() > 0);
1546 //----------------------------------------------------------------------------------
1547 void tst_QTcpSocket::dontCloseOnTimeout()
1550 server.setProxy(QNetworkProxy(QNetworkProxy::NoProxy));
1551 QVERIFY(server.listen());
1553 QHostAddress serverAddress = QHostAddress::LocalHost;
1554 if (!(server.serverAddress() == QHostAddress::AnyIPv4)
1555 && !(server.serverAddress() == QHostAddress::AnyIPv6)
1556 && !(server.serverAddress() == QHostAddress::Any))
1557 serverAddress = server.serverAddress();
1559 QTcpSocket *socket = newSocket();
1560 socket->connectToHost(serverAddress, server.serverPort());
1561 QVERIFY(!socket->waitForReadyRead(100));
1562 QCOMPARE(socket->error(), QTcpSocket::SocketTimeoutError);
1563 QVERIFY(socket->isOpen());
1565 QVERIFY(!socket->waitForDisconnected(100));
1566 QCOMPARE(socket->error(), QTcpSocket::SocketTimeoutError);
1567 QVERIFY(socket->isOpen());
1572 //----------------------------------------------------------------------------------
1573 void tst_QTcpSocket::recursiveReadyRead()
1575 QTcpSocket *smtp = newSocket();
1576 connect(smtp, SIGNAL(connected()), SLOT(exitLoopSlot()));
1577 connect(smtp, SIGNAL(readyRead()), SLOT(recursiveReadyReadSlot()));
1580 QSignalSpy spy(smtp, SIGNAL(readyRead()));
1582 smtp->connectToHost("smtp.trolltech.com", 25);
1584 QVERIFY2(!timeout(),
1585 "Timed out when connecting to smtp.trolltech.com:25");
1588 QVERIFY2(!timeout(),
1589 "Timed out when waiting for the readyRead() signal");
1591 QCOMPARE(spy.count(), 1);
1596 void tst_QTcpSocket::recursiveReadyReadSlot()
1598 // make sure the server spits out more data
1599 tmpSocket->write("NOOP\r\n");
1602 // indiscriminately enter the event loop and start processing
1603 // events again. but oops! future socket notifications will cause
1604 // undesired recursive behavior. Unless QTcpSocket is smart, which
1605 // it of course is. :-)
1607 for (int i = 0; i < 100; ++i)
1608 loop.processEvents();
1610 // all we really wanted to do was process some events, then exit
1615 //----------------------------------------------------------------------------------
1616 void tst_QTcpSocket::atEnd()
1618 QTcpSocket *socket = newSocket();
1619 socket->connectToHost(QtNetworkSettings::serverName(), 21);
1621 QVERIFY(socket->waitForReadyRead(15000));
1622 QTextStream stream(socket);
1623 QVERIFY(!stream.atEnd());
1624 QString greeting = stream.readLine();
1625 QVERIFY(stream.atEnd());
1627 // Test server must use some vsFTPd 2.x.x version
1628 QVERIFY2(greeting.length() == sizeof("220 (vsFTPd 2.x.x)")-1, qPrintable(greeting));
1629 QVERIFY2(greeting.startsWith("220 (vsFTPd 2."), qPrintable(greeting));
1630 QVERIFY2(greeting.endsWith(")"), qPrintable(greeting));
1635 class TestThread : public QThread
1640 inline QByteArray data() const
1649 QFETCH_GLOBAL(bool, ssl);
1651 socket = new QSslSocket;
1654 socket = new QTcpSocket;
1655 connect(socket, SIGNAL(readyRead()), this, SLOT(getData()), Qt::DirectConnection);
1656 connect(socket, SIGNAL(disconnected()), this, SLOT(closed()), Qt::DirectConnection);
1657 connect(socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
1658 SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)), Qt::DirectConnection);
1660 socket->connectToHost(QtNetworkSettings::serverName(), 21);
1661 socket->write("QUIT\r\n");
1668 inline void getData()
1670 socketData += socket->readAll();
1673 inline void closed()
1677 inline void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth)
1679 auth->setUser("qsockstest");
1680 auth->setPassword("password");
1685 QByteArray socketData;
1688 //----------------------------------------------------------------------------------
1689 void tst_QTcpSocket::socketInAThread()
1691 for (int i = 0; i < 3; ++i) {
1694 QVERIFY(thread.wait(15000));
1695 QByteArray data = thread.data();
1696 QVERIFY2(QtNetworkSettings::compareReplyFtp(data), data.constData());
1700 //----------------------------------------------------------------------------------
1701 void tst_QTcpSocket::socketsInThreads()
1703 for (int i = 0; i < 3; ++i) {
1712 QVERIFY(thread2.wait(15000));
1713 QVERIFY(thread3.wait(15000));
1714 QVERIFY(thread1.wait(15000));
1716 QByteArray data1 = thread1.data();
1717 QByteArray data2 = thread2.data();
1718 QByteArray data3 = thread3.data();
1720 QVERIFY2(QtNetworkSettings::compareReplyFtp(data1), data1.constData());
1721 QVERIFY2(QtNetworkSettings::compareReplyFtp(data2), data2.constData());
1722 QVERIFY2(QtNetworkSettings::compareReplyFtp(data3), data3.constData());
1726 //----------------------------------------------------------------------------------
1727 void tst_QTcpSocket::waitForReadyReadInASlot()
1729 QTcpSocket *socket = newSocket();
1731 connect(socket, SIGNAL(connected()), this, SLOT(waitForReadyReadInASlotSlot()));
1733 socket->connectToHost(QtNetworkSettings::serverName(), 80);
1734 socket->write("GET / HTTP/1.0\r\n\r\n");
1737 QVERIFY(!timeout());
1742 void tst_QTcpSocket::waitForReadyReadInASlotSlot()
1744 QVERIFY(tmpSocket->waitForReadyRead(10000));
1748 class RemoteCloseErrorServer : public QTcpServer
1752 RemoteCloseErrorServer()
1754 connect(this, SIGNAL(newConnection()),
1755 this, SLOT(getConnection()));
1759 void getConnection()
1761 tst_QTcpSocket::exitLoop();
1765 //----------------------------------------------------------------------------------
1766 void tst_QTcpSocket::remoteCloseError()
1768 QFETCH_GLOBAL(bool, setProxy);
1770 return; //proxy not useful for localhost test case
1771 RemoteCloseErrorServer server;
1772 QVERIFY(server.listen(QHostAddress::LocalHost));
1774 QCoreApplication::instance()->processEvents();
1776 QTcpSocket *clientSocket = newSocket();
1777 connect(clientSocket, SIGNAL(readyRead()), this, SLOT(exitLoopSlot()));
1779 clientSocket->connectToHost(server.serverAddress(), server.serverPort());
1782 QVERIFY(!timeout());
1784 QVERIFY(server.hasPendingConnections());
1785 QTcpSocket *serverSocket = server.nextPendingConnection();
1786 connect(clientSocket, SIGNAL(disconnected()), this, SLOT(exitLoopSlot()));
1788 serverSocket->write("Hello");
1791 QVERIFY(!timeout());
1793 QCOMPARE(clientSocket->bytesAvailable(), qint64(5));
1795 qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError");
1796 QSignalSpy errorSpy(clientSocket, SIGNAL(error(QAbstractSocket::SocketError)));
1797 QSignalSpy disconnectedSpy(clientSocket, SIGNAL(disconnected()));
1799 clientSocket->write("World");
1800 serverSocket->disconnectFromHost();
1802 tmpSocket = clientSocket;
1803 connect(clientSocket, SIGNAL(error(QAbstractSocket::SocketError)),
1804 this, SLOT(remoteCloseErrorSlot()));
1807 QVERIFY(!timeout());
1809 QCOMPARE(disconnectedSpy.count(), 1);
1810 QCOMPARE(errorSpy.count(), 1);
1811 QCOMPARE(clientSocket->error(), QAbstractSocket::RemoteHostClosedError);
1813 delete serverSocket;
1815 clientSocket->connectToHost(server.serverAddress(), server.serverPort());
1818 QVERIFY(!timeout());
1820 QVERIFY(server.hasPendingConnections());
1821 serverSocket = server.nextPendingConnection();
1822 serverSocket->disconnectFromHost();
1825 QVERIFY(!timeout());
1827 QCOMPARE(clientSocket->state(), QAbstractSocket::UnconnectedState);
1829 delete clientSocket;
1832 void tst_QTcpSocket::remoteCloseErrorSlot()
1834 QCOMPARE(tmpSocket->state(), QAbstractSocket::ConnectedState);
1835 static_cast<QTcpSocket *>(sender())->close();
1838 void tst_QTcpSocket::enterLoopSlot()
1840 QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
1841 socket->deleteLater();
1843 // enter nested event loop
1845 QTimer::singleShot(100, &loop, SLOT(quit()));
1848 // Fire a non-0 singleshot to leave time for the delete
1849 QTimer::singleShot(250, this, SLOT(exitLoopSlot()));
1851 //----------------------------------------------------------------------------------
1852 void tst_QTcpSocket::nestedEventLoopInErrorSlot()
1854 QTcpSocket *socket = newSocket();
1855 QPointer<QTcpSocket> p(socket);
1856 connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(enterLoopSlot()));
1858 socket->connectToHost("hostnotfoundhostnotfound.troll.no", 9999); // Host not found, fyi
1863 //----------------------------------------------------------------------------------
1865 void tst_QTcpSocket::connectToLocalHostNoService()
1867 // This test was created after we received a report that claimed
1868 // QTcpSocket would crash if trying to connect to "localhost" on a random
1869 // port with no service listening.
1870 QTcpSocket *socket = newSocket();
1871 socket->connectToHost("localhost", 31415); // no service running here, one suspects
1873 while(socket->state() == QTcpSocket::HostLookupState || socket->state() == QTcpSocket::ConnectingState) {
1876 QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
1881 //----------------------------------------------------------------------------------
1882 void tst_QTcpSocket::waitForConnectedInHostLookupSlot()
1884 // This test tries to reproduce the problem where waitForConnected() is
1885 // called at a point where the host lookup is already done. QTcpSocket
1886 // will try to abort the "pending lookup", but since it's already done and
1887 // the queued signal is already underway, we will receive the signal after
1888 // waitForConnected() has returned, and control goes back to the event
1889 // loop. When the signal has been received, the connection is torn down,
1890 // then reopened. Yikes. If we reproduce this by calling
1891 // waitForConnected() inside hostLookupSlot(), it will even crash.
1892 tmpSocket = newSocket();
1894 connect(tmpSocket, SIGNAL(connected()), &loop, SLOT(quit()));
1896 connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
1897 QSignalSpy timerSpy(&timer, SIGNAL(timeout()));
1900 connect(tmpSocket, SIGNAL(hostFound()), this, SLOT(hostLookupSlot()));
1901 tmpSocket->connectToHost(QtNetworkSettings::serverName(), 143);
1903 // only execute the loop if not already connected
1904 if (tmpSocket->state() != QAbstractSocket::ConnectedState)
1907 QCOMPARE(timerSpy.count(), 0);
1912 void tst_QTcpSocket::hostLookupSlot()
1914 // This will fail to cancel the pending signal
1915 QVERIFY(tmpSocket->waitForConnected(10000));
1918 class Foo : public QObject
1923 bool attemptedToConnect;
1924 bool networkTimeout;
1927 inline Foo(QObject *parent = 0) : QObject(parent)
1929 attemptedToConnect = false;
1930 networkTimeout = false;
1933 QFETCH_GLOBAL(bool, ssl);
1935 sock = new QSslSocket;
1938 sock = new QTcpSocket;
1939 connect(sock, SIGNAL(connected()), this, SLOT(connectedToIt()));
1940 connect(sock, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
1941 SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
1950 inline void connectedToIt()
1955 attemptedToConnect = true;
1956 sock->connectToHost(QtNetworkSettings::serverName(), 80);
1960 #elif defined Q_OS_LINUX
1963 if (!sock->waitForConnected()) {
1964 networkTimeout = true;
1966 tst_QTcpSocket::exitLoop();
1969 inline void exitLoop()
1971 tst_QTcpSocket::exitLoop();
1974 inline void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth)
1976 auth->setUser("qsockstest");
1977 auth->setPassword("password");
1981 //----------------------------------------------------------------------------------
1982 void tst_QTcpSocket::waitForConnectedInHostLookupSlot2()
1986 QTimer::singleShot(100, &foo, SLOT(doIt()));
1987 QTimer::singleShot(5000, &foo, SLOT(exitLoop()));
1990 if (timeout() || foo.networkTimeout)
1991 QFAIL("Network timeout");
1993 QVERIFY(foo.attemptedToConnect);
1994 QCOMPARE(foo.count, 1);
1997 //----------------------------------------------------------------------------------
1998 void tst_QTcpSocket::readyReadSignalsAfterWaitForReadyRead()
2000 QTcpSocket *socket = newSocket();
2002 QSignalSpy readyReadSpy(socket, SIGNAL(readyRead()));
2005 socket->connectToHost(QtNetworkSettings::serverName(), 143);
2007 // Wait for the read
2008 QVERIFY(socket->waitForReadyRead(10000));
2010 QCOMPARE(readyReadSpy.count(), 1);
2012 QString s = socket->readLine();
2013 QVERIFY2(QtNetworkSettings::compareReplyIMAP(s.toLatin1()), s.toLatin1().constData());
2014 QCOMPARE(socket->bytesAvailable(), qint64(0));
2016 QCoreApplication::instance()->processEvents();
2017 QCOMPARE(socket->bytesAvailable(), qint64(0));
2018 QCOMPARE(readyReadSpy.count(), 1);
2023 class TestThread2 : public QThread
2029 QFile fileWriter("fifo");
2030 QVERIFY(fileWriter.open(QFile::WriteOnly));
2031 QCOMPARE(fileWriter.write(QByteArray(32, '@')), qint64(32));
2032 QCOMPARE(fileWriter.write(QByteArray(32, '@')), qint64(32));
2033 QCOMPARE(fileWriter.write(QByteArray(32, '@')), qint64(32));
2034 QCOMPARE(fileWriter.write(QByteArray(32, '@')), qint64(32));
2038 //----------------------------------------------------------------------------------
2040 void tst_QTcpSocket::linuxKernelBugLocalSocket()
2042 QFile::remove("fifo");
2043 mkfifo("fifo", 0666);
2048 QFile fileReader("fifo");
2049 QVERIFY(fileReader.open(QFile::ReadOnly));
2053 QTcpSocket *socket = newSocket();
2054 socket->setSocketDescriptor(fileReader.handle());
2055 QVERIFY(socket->waitForReadyRead(5000));
2056 QCOMPARE(socket->bytesAvailable(), qint64(128));
2058 QFile::remove("fifo");
2064 //----------------------------------------------------------------------------------
2065 void tst_QTcpSocket::abortiveClose()
2067 QFETCH_GLOBAL(bool, setProxy);
2069 return; //proxy not useful for localhost test case
2071 QVERIFY(server.listen(QHostAddress::LocalHost));
2072 connect(&server, SIGNAL(newConnection()), this, SLOT(exitLoopSlot()));
2074 QTcpSocket *clientSocket = newSocket();
2075 clientSocket->connectToHost(server.serverAddress(), server.serverPort());
2078 QVERIFY(server.hasPendingConnections());
2080 QVERIFY(tmpSocket = server.nextPendingConnection());
2082 qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError");
2083 QSignalSpy readyReadSpy(clientSocket, SIGNAL(readyRead()));
2084 QSignalSpy errorSpy(clientSocket, SIGNAL(error(QAbstractSocket::SocketError)));
2086 connect(clientSocket, SIGNAL(disconnected()), this, SLOT(exitLoopSlot()));
2087 QTimer::singleShot(0, this, SLOT(abortiveClose_abortSlot()));
2091 QCOMPARE(readyReadSpy.count(), 0);
2092 QCOMPARE(errorSpy.count(), 1);
2094 QCOMPARE(*static_cast<const int *>(errorSpy.at(0).at(0).constData()),
2095 int(QAbstractSocket::RemoteHostClosedError));
2097 delete clientSocket;
2100 void tst_QTcpSocket::abortiveClose_abortSlot()
2105 //----------------------------------------------------------------------------------
2106 void tst_QTcpSocket::localAddressEmptyOnBSD()
2109 QSKIP("QTBUG-24451 - indefinite wait may hang");
2111 QFETCH_GLOBAL(bool, setProxy);
2113 return; //proxy not useful for localhost test case
2115 QVERIFY(server.listen(QHostAddress::LocalHost));
2117 QTcpSocket *tcpSocket = 0;
2118 // we try 10 times, but note that this doesn't always provoke the bug
2119 for (int i = 0; i < 10; ++i) {
2121 tcpSocket = newSocket();
2122 tcpSocket->connectToHost(QHostAddress::LocalHost, server.serverPort());
2123 if (!tcpSocket->waitForConnected(0)) {
2124 // to provoke the bug, we need a local socket that connects immediately
2127 if (tcpSocket->state() != QTcpSocket::UnconnectedState)
2128 QVERIFY(tcpSocket->waitForDisconnected(-1));
2131 QCOMPARE(tcpSocket->localAddress(), QHostAddress(QHostAddress::LocalHost));
2136 //----------------------------------------------------------------------------------
2137 void tst_QTcpSocket::zeroAndMinusOneReturns()
2139 QTcpSocket *socket = newSocket();
2140 socket->connectToHost(QtNetworkSettings::serverName(), 80);
2141 socket->write("GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n");
2142 QVERIFY(socket->waitForReadyRead(15000));
2145 QVERIFY(socket->getChar(c));
2146 QCOMPARE(socket->read(c, 16), qint64(16));
2147 QVERIFY(socket->readLine(c, 16) > 0);
2148 QVERIFY(!socket->readAll().isEmpty());
2150 // the last operation emptied the read buffer
2151 // all read operations from this point on should fail
2152 // with return 0 because the socket is still open
2153 QVERIFY(socket->readAll().isEmpty());
2154 QCOMPARE(socket->read(c, 16), qint64(0));
2155 QCOMPARE(socket->readLine(c, 16), qint64(0));
2156 QVERIFY(!socket->getChar(c));
2158 socket->write("GET / HTTP/1.0\r\n\r\n");
2159 QVERIFY(socket->waitForDisconnected(15000));
2160 QCOMPARE(socket->error(), QAbstractSocket::RemoteHostClosedError);
2162 QCOMPARE(socket->write("BLUBBER"), qint64(-1));
2163 QVERIFY(socket->getChar(c));
2164 QCOMPARE(socket->read(c, 16), qint64(16));
2165 QVERIFY(socket->readLine(c, 16) > 0);
2166 QVERIFY(!socket->readAll().isEmpty());
2168 // the last operation emptied the read buffer
2169 // all read operations from this point on should fail
2170 // with return -1 because the socket is not connected
2171 QVERIFY(socket->readAll().isEmpty());
2172 QCOMPARE(socket->read(c, 16), qint64(-1));
2173 QCOMPARE(socket->readLine(c, 16), qint64(-1));
2174 QVERIFY(!socket->getChar(c));
2175 QVERIFY(!socket->putChar('a'));
2179 // now the QIODevice is closed, which means getChar complains
2180 QCOMPARE(socket->write("BLUBBER"), qint64(-1));
2181 QCOMPARE(socket->read(c, 16), qint64(-1));
2182 QCOMPARE(socket->readLine(c, 16), qint64(-1));
2183 QVERIFY(!socket->getChar(c));
2184 QVERIFY(!socket->putChar('a'));
2189 //----------------------------------------------------------------------------------
2190 void tst_QTcpSocket::connectionRefused()
2192 qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError");
2193 qRegisterMetaType<QAbstractSocket::SocketState>("QAbstractSocket::SocketState");
2195 QTcpSocket *socket = newSocket();
2196 QSignalSpy stateSpy(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)));
2197 QSignalSpy errorSpy(socket, SIGNAL(error(QAbstractSocket::SocketError)));
2198 connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
2199 &QTestEventLoop::instance(), SLOT(exitLoop()));
2201 socket->connectToHost(QtNetworkSettings::serverName(), 144);
2204 disconnect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
2205 &QTestEventLoop::instance(), SLOT(exitLoop()));
2206 QVERIFY2(!timeout(), "Network timeout");
2208 QCOMPARE(socket->state(), QAbstractSocket::UnconnectedState);
2209 QCOMPARE(socket->error(), QAbstractSocket::ConnectionRefusedError);
2211 QCOMPARE(stateSpy.count(), 3);
2212 QCOMPARE(qvariant_cast<QAbstractSocket::SocketState>(stateSpy.at(0).at(0)), QAbstractSocket::HostLookupState);
2213 QCOMPARE(qvariant_cast<QAbstractSocket::SocketState>(stateSpy.at(1).at(0)), QAbstractSocket::ConnectingState);
2214 QCOMPARE(qvariant_cast<QAbstractSocket::SocketState>(stateSpy.at(2).at(0)), QAbstractSocket::UnconnectedState);
2215 QCOMPARE(errorSpy.count(), 1);
2220 //----------------------------------------------------------------------------------
2221 void tst_QTcpSocket::suddenRemoteDisconnect_data()
2223 QTest::addColumn<QString>("client");
2224 QTest::addColumn<QString>("server");
2226 QTest::newRow("Qt4 Client <-> Qt4 Server") << QString::fromLatin1("qt4client") << QString::fromLatin1("qt4server");
2229 void tst_QTcpSocket::suddenRemoteDisconnect()
2231 QFETCH(QString, client);
2232 QFETCH(QString, server);
2234 QFETCH_GLOBAL(bool, setProxy);
2237 QFETCH_GLOBAL(bool, ssl);
2241 QString processExe = stressTestDir + "/stressTest";
2244 QProcess serverProcess;
2245 serverProcess.setReadChannel(QProcess::StandardError);
2246 serverProcess.start(processExe, QStringList(server), QIODevice::ReadWrite | QIODevice::Text);
2247 QVERIFY2(serverProcess.waitForStarted(), qPrintable(
2248 QString::fromLatin1("Could not start %1: %2").arg(processExe, serverProcess.errorString())));
2249 while (!serverProcess.canReadLine())
2250 QVERIFY(serverProcess.waitForReadyRead(10000));
2251 QCOMPARE(serverProcess.readLine().data(), QByteArray(server.toLatin1() + "\n").data());
2254 QProcess clientProcess;
2255 clientProcess.setReadChannel(QProcess::StandardError);
2256 clientProcess.start(processExe, QStringList(client), QIODevice::ReadWrite | QIODevice::Text);
2257 QVERIFY2(clientProcess.waitForStarted(), qPrintable(
2258 QString::fromLatin1("Could not start %1: %2").arg(processExe, clientProcess.errorString())));
2259 while (!clientProcess.canReadLine())
2260 QVERIFY(clientProcess.waitForReadyRead(10000));
2261 QCOMPARE(clientProcess.readLine().data(), QByteArray(client.toLatin1() + "\n").data());
2263 // Let them play for a while
2264 qDebug("Running stress test for 5 seconds");
2266 connect(&serverProcess, SIGNAL(finished(int)), &loop, SLOT(quit()));
2267 connect(&clientProcess, SIGNAL(finished(int)), &loop, SLOT(quit()));
2270 QTimer::singleShot(20000, &loop, SLOT(quit()));
2272 while ((serverProcess.state() == QProcess::Running
2273 || clientProcess.state() == QProcess::Running) && stopWatch.elapsed() < 20000)
2276 QVERIFY(stopWatch.elapsed() < 20000);
2278 // Check that both exited normally.
2279 #if defined(UBUNTU_ONEIRIC) && defined(__x86_64__)
2280 QEXPECT_FAIL("", "Fails on this platform", Abort);
2282 QCOMPARE(clientProcess.readAll().constData(), "SUCCESS\n");
2283 QCOMPARE(serverProcess.readAll().constData(), "SUCCESS\n");
2286 //----------------------------------------------------------------------------------
2288 void tst_QTcpSocket::connectToMultiIP()
2290 QSKIP("TODO: setup DNS in the new network");
2291 #if defined(Q_OS_VXWORKS)
2292 QSKIP("VxSim in standard config doesn't even run a DNS resolver");
2294 QFETCH_GLOBAL(bool, ssl);
2297 QFETCH_GLOBAL(bool, setProxy);
2299 QSKIP("This test takes too long if we also add the proxies.");
2301 qDebug("Please wait, this test can take a while...");
2303 QTcpSocket *socket = newSocket();
2304 // rationale: this domain resolves to 3 A-records, 2 of them are
2305 // invalid. QTcpSocket should never spend more than 30 seconds per IP, and
2309 socket->connectToHost("multi.dev.troll.no", 80);
2310 QVERIFY(socket->waitForConnected(60500));
2311 QVERIFY(stopWatch.elapsed() < 70000);
2314 stopWatch.restart();
2315 socket->connectToHost("multi.dev.troll.no", 81);
2316 QVERIFY(!socket->waitForConnected(2000));
2317 QVERIFY(stopWatch.elapsed() < 2000);
2318 QCOMPARE(socket->error(), QAbstractSocket::SocketTimeoutError);
2324 //----------------------------------------------------------------------------------
2325 void tst_QTcpSocket::moveToThread0()
2327 QFETCH_GLOBAL(int, proxyType);
2328 if (proxyType & AuthMask)
2332 // Case 1: Moved after connecting, before waiting for connection.
2333 QTcpSocket *socket = newSocket();;
2334 socket->connectToHost(QtNetworkSettings::serverName(), 143);
2335 socket->moveToThread(0);
2336 QVERIFY(socket->waitForConnected(5000));
2337 socket->write("XXX LOGOUT\r\n");
2338 QVERIFY(socket->waitForBytesWritten(5000));
2339 QVERIFY(socket->waitForDisconnected());
2343 // Case 2: Moved before connecting
2344 QTcpSocket *socket = newSocket();
2345 socket->moveToThread(0);
2346 socket->connectToHost(QtNetworkSettings::serverName(), 143);
2347 QVERIFY(socket->waitForConnected(5000));
2348 socket->write("XXX LOGOUT\r\n");
2349 QVERIFY(socket->waitForBytesWritten(5000));
2350 QVERIFY(socket->waitForDisconnected());
2354 // Case 3: Moved after writing, while waiting for bytes to be written.
2355 QTcpSocket *socket = newSocket();
2356 socket->connectToHost(QtNetworkSettings::serverName(), 143);
2357 QVERIFY(socket->waitForConnected(5000));
2358 socket->write("XXX LOGOUT\r\n");
2359 socket->moveToThread(0);
2360 QVERIFY(socket->waitForBytesWritten(5000));
2361 QVERIFY(socket->waitForDisconnected());
2365 // Case 4: Moved after writing, while waiting for response.
2366 QTcpSocket *socket = newSocket();
2367 socket->connectToHost(QtNetworkSettings::serverName(), 143);
2368 QVERIFY(socket->waitForConnected(5000));
2369 socket->write("XXX LOGOUT\r\n");
2370 QVERIFY(socket->waitForBytesWritten(5000));
2371 socket->moveToThread(0);
2372 QVERIFY(socket->waitForDisconnected());
2377 void tst_QTcpSocket::increaseReadBufferSize()
2379 QFETCH_GLOBAL(bool, setProxy);
2381 return; //proxy not useful for localhost test case
2383 QTcpSocket *active = newSocket();
2384 connect(active, SIGNAL(readyRead()), SLOT(exitLoopSlot()));
2386 // connect two sockets to each other:
2387 QVERIFY(server.listen(QHostAddress::LocalHost));
2388 active->connectToHost("127.0.0.1", server.serverPort());
2389 QVERIFY(active->waitForConnected(5000));
2390 QVERIFY(server.waitForNewConnection(5000));
2392 QTcpSocket *passive = server.nextPendingConnection();
2395 // now write 512 bytes of data on one end
2396 QByteArray data(512, 'a');
2397 passive->write(data);
2398 QVERIFY2(passive->waitForBytesWritten(5000), "Network timeout");
2400 // set the read buffer size to less than what was written and iterate:
2401 active->setReadBufferSize(256);
2403 QVERIFY2(!timeout(), "Network timeout");
2404 QCOMPARE(active->bytesAvailable(), active->readBufferSize());
2406 // increase the buffer size and iterate again:
2407 active->setReadBufferSize(384);
2409 QVERIFY2(!timeout(), "Network timeout");
2410 QCOMPARE(active->bytesAvailable(), active->readBufferSize());
2412 // once more, but now it should read everything there was to read
2413 active->setReadBufferSize(1024);
2415 QVERIFY2(!timeout(), "Network timeout");
2416 QCOMPARE(active->bytesAvailable(), qint64(data.size()));
2418 // drain it and compare
2419 QCOMPARE(active->readAll(), data);
2421 // now one more test by setting the buffer size to unlimited:
2422 passive->write(data);
2423 QVERIFY2(passive->waitForBytesWritten(5000), "Network timeout");
2424 active->setReadBufferSize(256);
2426 QVERIFY2(!timeout(), "Network timeout");
2427 QCOMPARE(active->bytesAvailable(), active->readBufferSize());
2428 active->setReadBufferSize(0);
2430 QVERIFY2(!timeout(), "Network timeout");
2431 QCOMPARE(active->bytesAvailable(), qint64(data.size()));
2432 QCOMPARE(active->readAll(), data);
2437 void tst_QTcpSocket::taskQtBug5799ConnectionErrorWaitForConnected()
2439 QFETCH_GLOBAL(bool, setProxy);
2443 // check that we get a proper error connecting to port 12346
2444 // use waitForConnected, e.g. this should use a synchronous select() on the OS level
2447 socket.connectToHost(QtNetworkSettings::serverName(), 12346);
2450 socket.waitForConnected(10000);
2451 QVERIFY2(timer.elapsed() < 9900, "Connection to closed port timed out instead of refusing, something is wrong");
2452 QVERIFY2(socket.state() == QAbstractSocket::UnconnectedState, "Socket connected unexpectedly!");
2453 QVERIFY2(socket.error() == QAbstractSocket::ConnectionRefusedError,
2454 QString("Could not reach server: %1").arg(socket.errorString()).toLocal8Bit());
2457 void tst_QTcpSocket::taskQtBug5799ConnectionErrorEventLoop()
2459 QFETCH_GLOBAL(bool, setProxy);
2463 // check that we get a proper error connecting to port 12346
2464 // This testcase uses an event loop
2466 connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), &QTestEventLoop::instance(), SLOT(exitLoop()));
2467 socket.connectToHost(QtNetworkSettings::serverName(), 12346);
2469 QTestEventLoop::instance().enterLoop(10);
2470 QVERIFY2(!QTestEventLoop::instance().timeout(), "Connection to closed port timed out instead of refusing, something is wrong");
2471 QVERIFY2(socket.state() == QAbstractSocket::UnconnectedState, "Socket connected unexpectedly!");
2472 QVERIFY2(socket.error() == QAbstractSocket::ConnectionRefusedError,
2473 QString("Could not reach server: %1").arg(socket.errorString()).toLocal8Bit());
2476 void tst_QTcpSocket::taskQtBug7054TimeoutErrorResetting()
2478 QTcpSocket *socket = newSocket();
2480 socket->connectToHost(QtNetworkSettings::serverName(), 443);
2481 QVERIFY(socket->waitForConnected(5*1000));
2482 QVERIFY(socket->error() == QAbstractSocket::UnknownSocketError);
2484 // We connected to the HTTPS port. Wait two seconds to receive data. We will receive
2485 // nothing because we would need to start the SSL handshake
2486 QVERIFY(!socket->waitForReadyRead(2*1000));
2487 QVERIFY(socket->error() == QAbstractSocket::SocketTimeoutError);
2489 // Now write some crap to make the server disconnect us. 4 lines are enough.
2490 socket->write("a\r\nb\r\nc\r\nd\r\n");
2491 socket->waitForBytesWritten(2*1000);
2493 // we try to waitForReadyRead another time, but this time instead of a timeout we
2494 // should get a better error since the server disconnected us
2495 QVERIFY(!socket->waitForReadyRead(2*1000));
2496 // It must NOT be the SocketTimeoutError that had been set before
2497 QVERIFY(socket->error() == QAbstractSocket::RemoteHostClosedError);
2500 void tst_QTcpSocket::invalidProxy_data()
2502 QTest::addColumn<int>("type");
2503 QTest::addColumn<QString>("host");
2504 QTest::addColumn<int>("port");
2505 QTest::addColumn<bool>("failsAtConnect");
2506 QTest::addColumn<int>("expectedError");
2508 QString fluke = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString();
2509 QTest::newRow("ftp-proxy") << int(QNetworkProxy::FtpCachingProxy) << fluke << 21 << true
2510 << int(QAbstractSocket::UnsupportedSocketOperationError);
2511 QTest::newRow("http-caching-proxy") << int(QNetworkProxy::HttpCachingProxy) << fluke << 3128 << true
2512 << int(QAbstractSocket::UnsupportedSocketOperationError);
2513 QTest::newRow("no-such-host-socks5") << int(QNetworkProxy::Socks5Proxy)
2514 << "this-host-will-never-exist.troll.no" << 1080 << false
2515 << int(QAbstractSocket::ProxyNotFoundError);
2516 QTest::newRow("no-such-host-http") << int(QNetworkProxy::HttpProxy)
2517 << "this-host-will-never-exist.troll.no" << 3128 << false
2518 << int(QAbstractSocket::ProxyNotFoundError);
2519 QTest::newRow("http-on-socks5") << int(QNetworkProxy::HttpProxy) << fluke << 1080 << false
2520 << int(QAbstractSocket::ProxyConnectionClosedError);
2521 QTest::newRow("socks5-on-http") << int(QNetworkProxy::Socks5Proxy) << fluke << 3128 << false
2522 << int(QAbstractSocket::SocketTimeoutError);
2525 void tst_QTcpSocket::invalidProxy()
2527 QFETCH_GLOBAL(bool, setProxy);
2532 QFETCH(QString, host);
2534 QFETCH(bool, failsAtConnect);
2535 QNetworkProxy::ProxyType proxyType = QNetworkProxy::ProxyType(type);
2536 QNetworkProxy proxy(proxyType, host, port);
2538 QTcpSocket *socket = newSocket();
2539 socket->setProxy(proxy);
2540 socket->connectToHost(QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString(), 80);
2542 if (failsAtConnect) {
2543 QCOMPARE(socket->state(), QAbstractSocket::UnconnectedState);
2545 QCOMPARE(socket->state(), QAbstractSocket::ConnectingState);
2546 QVERIFY(!socket->waitForConnected(5000));
2548 QVERIFY(!socket->errorString().isEmpty());
2550 // note: the following test is not a hard failure.
2551 // Sometimes, error codes change for the better
2552 QTEST(int(socket->error()), "expectedError");
2557 // copied from tst_qnetworkreply.cpp
2558 class MyProxyFactory: public QNetworkProxyFactory
2562 QList<QNetworkProxy> toReturn;
2563 QNetworkProxyQuery lastQuery;
2564 inline MyProxyFactory() { clear(); }
2569 toReturn = QList<QNetworkProxy>() << QNetworkProxy::DefaultProxy;
2570 lastQuery = QNetworkProxyQuery();
2573 virtual QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query)
2581 void tst_QTcpSocket::proxyFactory_data()
2583 QTest::addColumn<QList<QNetworkProxy> >("proxyList");
2584 QTest::addColumn<QNetworkProxy>("proxyUsed");
2585 QTest::addColumn<bool>("failsAtConnect");
2586 QTest::addColumn<int>("expectedError");
2588 QList<QNetworkProxy> proxyList;
2590 // tests that do connect
2592 proxyList << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3129);
2593 QTest::newRow("http")
2594 << proxyList << proxyList.at(0)
2595 << false << int(QAbstractSocket::UnknownSocketError);
2598 proxyList << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1081);
2599 QTest::newRow("socks5")
2600 << proxyList << proxyList.at(0)
2601 << false << int(QAbstractSocket::UnknownSocketError);
2604 proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129)
2605 << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1081);
2606 QTest::newRow("cachinghttp+socks5")
2607 << proxyList << proxyList.at(1)
2608 << false << int(QAbstractSocket::UnknownSocketError);
2611 proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121)
2612 << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129)
2613 << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1081);
2614 QTest::newRow("ftp+cachinghttp+socks5")
2615 << proxyList << proxyList.at(2)
2616 << false << int(QAbstractSocket::UnknownSocketError);
2618 // tests that fail to connect
2620 proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129);
2621 QTest::newRow("cachinghttp")
2622 << proxyList << QNetworkProxy()
2623 << true << int(QAbstractSocket::UnsupportedSocketOperationError);
2626 proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121);
2627 QTest::newRow("ftp")
2628 << proxyList << QNetworkProxy()
2629 << true << int(QAbstractSocket::UnsupportedSocketOperationError);
2632 proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121)
2633 << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129);
2634 QTest::newRow("ftp+cachinghttp")
2635 << proxyList << QNetworkProxy()
2636 << true << int(QAbstractSocket::UnsupportedSocketOperationError);
2639 void tst_QTcpSocket::proxyFactory()
2641 QFETCH_GLOBAL(bool, setProxy);
2645 QFETCH(QList<QNetworkProxy>, proxyList);
2646 QFETCH(QNetworkProxy, proxyUsed);
2647 QFETCH(bool, failsAtConnect);
2649 MyProxyFactory *factory = new MyProxyFactory;
2650 factory->toReturn = proxyList;
2651 QNetworkProxyFactory::setApplicationProxyFactory(factory);
2653 QTcpSocket *socket = newSocket();
2654 QString host = QtNetworkSettings::serverName();
2655 socket->connectToHost(host, 80);
2657 // Verify that the factory was called properly
2658 QCOMPARE(factory->callCount, 1);
2659 QCOMPARE(factory->lastQuery, QNetworkProxyQuery(host, 80));
2661 if (failsAtConnect) {
2662 QCOMPARE(socket->state(), QAbstractSocket::UnconnectedState);
2664 QCOMPARE(socket->state(), QAbstractSocket::ConnectingState);
2665 QVERIFY(socket->waitForConnected(5000));
2666 QCOMPARE(proxyAuthCalled, 1);
2668 QVERIFY(!socket->errorString().isEmpty());
2670 // note: the following test is not a hard failure.
2671 // Sometimes, error codes change for the better
2672 QTEST(int(socket->error()), "expectedError");
2677 // there is a similar test inside tst_qtcpserver that uses the event loop instead
2678 void tst_QTcpSocket::qtbug14268_peek()
2680 QFETCH_GLOBAL(bool, setProxy);
2684 SocketPair socketPair;
2685 QVERIFY(socketPair.create());
2686 QTcpSocket *outgoing = socketPair.endPoints[0];
2687 QTcpSocket *incoming = socketPair.endPoints[1];
2689 QVERIFY(incoming->state() == QTcpSocket::ConnectedState);
2690 QVERIFY(outgoing->state() == QTcpSocket::ConnectedState);
2692 outgoing->write("abc\n");
2693 QVERIFY(outgoing->waitForBytesWritten(2000));
2694 QVERIFY(incoming->waitForReadyRead(2000));
2695 QVERIFY(incoming->peek(128*1024) == QByteArray("abc\n"));
2697 outgoing->write("def\n");
2698 QVERIFY(outgoing->waitForBytesWritten(2000));
2699 QVERIFY(incoming->waitForReadyRead(2000));
2700 QVERIFY(incoming->peek(128*1024) == QByteArray("abc\ndef\n"));
2702 outgoing->write("ghi\n");
2703 QVERIFY(outgoing->waitForBytesWritten(2000));
2704 QVERIFY(incoming->waitForReadyRead(2000));
2705 QVERIFY(incoming->peek(128*1024) == QByteArray("abc\ndef\nghi\n"));
2707 QVERIFY(incoming->read(128*1024) == QByteArray("abc\ndef\nghi\n"));
2710 void tst_QTcpSocket::setSocketOption()
2712 QFETCH_GLOBAL(bool, setProxy);
2716 SocketPair socketPair;
2717 QVERIFY(socketPair.create());
2718 QTcpSocket *outgoing = socketPair.endPoints[0];
2719 QTcpSocket *incoming = socketPair.endPoints[1];
2721 QVERIFY(incoming->state() == QTcpSocket::ConnectedState);
2722 QVERIFY(outgoing->state() == QTcpSocket::ConnectedState);
2724 outgoing->setSocketOption(QAbstractSocket::LowDelayOption, true);
2725 QVariant v = outgoing->socketOption(QAbstractSocket::LowDelayOption);
2726 QVERIFY(v.isValid() && v.toBool());
2727 outgoing->setSocketOption(QAbstractSocket::KeepAliveOption, true);
2728 v = outgoing->socketOption(QAbstractSocket::KeepAliveOption);
2729 QVERIFY(v.isValid() && v.toBool());
2731 outgoing->setSocketOption(QAbstractSocket::LowDelayOption, false);
2732 v = outgoing->socketOption(QAbstractSocket::LowDelayOption);
2733 QVERIFY(v.isValid() && !v.toBool());
2734 outgoing->setSocketOption(QAbstractSocket::KeepAliveOption, false);
2735 v = outgoing->socketOption(QAbstractSocket::KeepAliveOption);
2736 QVERIFY(v.isValid() && !v.toBool());
2739 QEXPECT_FAIL("", "QTBUG-23323", Abort);
2741 outgoing->setSocketOption(QAbstractSocket::TypeOfServiceOption, 32); //high priority
2742 v = outgoing->socketOption(QAbstractSocket::TypeOfServiceOption);
2743 QVERIFY(v.isValid() && v.toInt() == 32);
2746 QTEST_MAIN(tst_QTcpSocket)
2747 #include "tst_qtcpsocket.moc"