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