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