1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
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 https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29
30#include <QtTest/QTest>
31#include <QtTest/QTestEventLoop>
32#include <QtCore/QQueue>
33#include <QtCore/QString>
34#include <QtCore/QCoreApplication>
35
36#include <private/qhttpsocketengine_p.h>
37#include <qhostinfo.h>
38#include <qhostaddress.h>
39#include <qtcpsocket.h>
40#include <qdebug.h>
41#include <qelapsedtimer.h>
42#include <qtcpserver.h>
43
44#include "../../../network-settings.h"
45
46class tst_QHttpSocketEngine : public QObject
47{
48 Q_OBJECT
49
50private slots:
51 void initTestCase();
52 void init();
53 void construction();
54 void errorTest_data();
55 void errorTest();
56 void simpleConnectToIMAP();
57 void simpleErrorsAndStates();
58
59 void tcpSocketBlockingTest();
60 void tcpSocketNonBlockingTest();
61 void downloadBigFile();
62 // void tcpLoopbackPerformance();
63 void passwordAuth();
64 void ensureEofTriggersNotification();
65
66protected slots:
67 void tcpSocketNonBlocking_hostFound();
68 void tcpSocketNonBlocking_connected();
69 void tcpSocketNonBlocking_closed();
70 void tcpSocketNonBlocking_readyRead();
71 void tcpSocketNonBlocking_bytesWritten(qint64);
72 void exitLoopSlot();
73 void downloadBigFileSlot();
74
75private:
76 QTcpSocket *tcpSocketNonBlocking_socket;
77 QStringList tcpSocketNonBlocking_data;
78 qint64 tcpSocketNonBlocking_totalWritten;
79 QTcpSocket *tmpSocket;
80 qint64 bytesAvailable;
81};
82
83class MiniHttpServer: public QTcpServer
84{
85 Q_OBJECT
86 QTcpSocket *client;
87 QList<QByteArray> dataToTransmit;
88
89public:
90 QByteArray receivedData;
91
92 MiniHttpServer(const QList<QByteArray> &data) : client(0), dataToTransmit(data)
93 {
94 listen();
95 connect(sender: this, SIGNAL(newConnection()), receiver: this, SLOT(doAccept()));
96 }
97
98public slots:
99 void doAccept()
100 {
101 client = nextPendingConnection();
102 connect(sender: client, SIGNAL(readyRead()), receiver: this, SLOT(sendData()));
103 }
104
105 void sendData()
106 {
107 receivedData += client->readAll();
108 int idx = client->property(name: "dataTransmitionIdx").toInt();
109 if (receivedData.contains(c: "\r\n\r\n") ||
110 receivedData.contains(c: "\n\n")) {
111 if (idx < dataToTransmit.length())
112 client->write(data: dataToTransmit.at(i: idx++));
113 if (idx == dataToTransmit.length()) {
114 client->disconnectFromHost();
115 disconnect(sender: client, signal: 0, receiver: this, member: 0);
116 client = 0;
117 } else {
118 client->setProperty(name: "dataTransmitionIdx", value: idx);
119 }
120 }
121 }
122};
123
124void tst_QHttpSocketEngine::initTestCase()
125{
126#ifdef QT_TEST_SERVER
127 QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3128));
128 QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1080));
129 QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpServerName(), 80));
130 QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::imapServerName(), 143));
131#else
132 if (!QtNetworkSettings::verifyTestNetworkSettings())
133 QSKIP("No network test server available");
134#endif
135}
136
137void tst_QHttpSocketEngine::init()
138{
139 tmpSocket = 0;
140 bytesAvailable = 0;
141}
142
143//---------------------------------------------------------------------------
144void tst_QHttpSocketEngine::construction()
145{
146 QHttpSocketEngine socketDevice;
147
148 QVERIFY(!socketDevice.isValid());
149
150 // Initialize device
151 QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
152 QVERIFY(socketDevice.isValid());
153 QCOMPARE(socketDevice.protocol(), QAbstractSocket::IPv4Protocol);
154 QCOMPARE(socketDevice.socketType(), QAbstractSocket::TcpSocket);
155 QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
156 // QVERIFY(socketDevice.socketDescriptor() != -1);
157 QCOMPARE(socketDevice.localAddress(), QHostAddress());
158 QCOMPARE(socketDevice.localPort(), quint16(0));
159 QCOMPARE(socketDevice.peerAddress(), QHostAddress());
160 QCOMPARE(socketDevice.peerPort(), quint16(0));
161 QCOMPARE(socketDevice.error(), QAbstractSocket::UnknownSocketError);
162
163 //QTest::ignoreMessage(QtWarningMsg, "QSocketLayer::bytesAvailable() was called in QAbstractSocket::UnconnectedState");
164 QCOMPARE(socketDevice.bytesAvailable(), 0);
165
166 //QTest::ignoreMessage(QtWarningMsg, "QSocketLayer::hasPendingDatagrams() was called in QAbstractSocket::UnconnectedState");
167 QVERIFY(!socketDevice.hasPendingDatagrams());
168}
169
170//---------------------------------------------------------------------------
171void tst_QHttpSocketEngine::errorTest_data()
172{
173 QTest::addColumn<QString>(name: "hostname");
174 QTest::addColumn<int>(name: "port");
175 QTest::addColumn<QString>(name: "username");
176 QTest::addColumn<QString>(name: "response");
177 QTest::addColumn<int>(name: "expectedError");
178
179 QQueue<QByteArray> responses;
180 QTest::newRow(dataTag: "proxy-host-not-found") << "this-host-does-not-exist." << 1080 << QString()
181 << QString()
182 << int(QAbstractSocket::ProxyNotFoundError);
183 QTest::newRow(dataTag: "proxy-connection-refused") << QtNetworkSettings::socksProxyServerName() << 2 << QString()
184 << QString()
185 << int(QAbstractSocket::ProxyConnectionRefusedError);
186
187 QTest::newRow(dataTag: "garbage1") << QString() << 0 << QString()
188 << "This is not HTTP\r\n\r\n"
189 << int(QAbstractSocket::ProxyProtocolError);
190
191 QTest::newRow(dataTag: "garbage2") << QString() << 0 << QString()
192 << "This is not HTTP"
193 << int(QAbstractSocket::ProxyProtocolError);
194
195 QTest::newRow(dataTag: "garbage3") << QString() << 0 << QString()
196 << ""
197 << int(QAbstractSocket::ProxyConnectionClosedError);
198
199 QTest::newRow(dataTag: "forbidden") << QString() << 0 << QString()
200 << "HTTP/1.0 403 Forbidden\r\n\r\n"
201 << int(QAbstractSocket::SocketAccessError);
202
203 QTest::newRow(dataTag: "method-not-allowed") << QString() << 0 << QString()
204 << "HTTP/1.0 405 Method Not Allowed\r\n\r\n"
205 << int(QAbstractSocket::SocketAccessError);
206
207 QTest::newRow(dataTag: "proxy-authentication-too-short")
208 << QString() << 0 << "foo"
209 << "HTTP/1.0 407 Proxy Authentication Required\r\n\r\n"
210 << int(QAbstractSocket::ProxyProtocolError);
211
212 QTest::newRow(dataTag: "proxy-authentication-invalid-method")
213 << QString() << 0 << "foo"
214 << "HTTP/1.0 407 Proxy Authentication Required\r\n"
215 "Proxy-Authenticate: Frobnicator\r\n\r\n"
216 << int(QAbstractSocket::ProxyProtocolError);
217
218 QTest::newRow(dataTag: "proxy-authentication-required")
219 << QString() << 0 << "foo"
220 << "HTTP/1.0 407 Proxy Authentication Required\r\n"
221 "Proxy-Connection: close\r\n"
222 "Proxy-Authenticate: Basic, realm=wonderland\r\n\r\n"
223 << int(QAbstractSocket::ProxyAuthenticationRequiredError);
224
225 QTest::newRow(dataTag: "proxy-authentication-required2")
226 << QString() << 0 << "foo"
227 << "HTTP/1.0 407 Proxy Authentication Required\r\n"
228 "Proxy-Connection: keep-alive\r\n"
229 "Proxy-Authenticate: Basic, realm=wonderland\r\n\r\n"
230 "\1"
231 "HTTP/1.0 407 Proxy Authentication Required\r\n"
232 "Proxy-Authenticate: Basic, realm=wonderland\r\n\r\n"
233 << int(QAbstractSocket::ProxyAuthenticationRequiredError);
234
235 QTest::newRow(dataTag: "proxy-authentication-required-noclose")
236 << QString() << 0 << "foo"
237 << "HTTP/1.0 407 Proxy Authentication Required\r\n"
238 "Proxy-Authenticate: Basic\r\n"
239 "\r\n"
240 << int(QAbstractSocket::ProxyAuthenticationRequiredError);
241
242 QTest::newRow(dataTag: "connection-refused") << QString() << 0 << QString()
243 << "HTTP/1.0 503 Service Unavailable\r\n\r\n"
244 << int(QAbstractSocket::ConnectionRefusedError);
245
246 QTest::newRow(dataTag: "host-not-found") << QString() << 0 << QString()
247 << "HTTP/1.0 404 Not Found\r\n\r\n"
248 << int(QAbstractSocket::HostNotFoundError);
249
250 QTest::newRow(dataTag: "weird-http-reply") << QString() << 0 << QString()
251 << "HTTP/1.0 206 Partial Content\r\n\r\n"
252 << int(QAbstractSocket::ProxyProtocolError);
253}
254
255void tst_QHttpSocketEngine::errorTest()
256{
257 QFETCH(QString, hostname);
258 QFETCH(int, port);
259 QFETCH(QString, username);
260 QFETCH(QString, response);
261 QFETCH(int, expectedError);
262
263 MiniHttpServer server(response.toLatin1().split(sep: '\1'));
264
265 if (hostname.isEmpty()) {
266 hostname = "127.0.0.1";
267 port = server.serverPort();
268 }
269 QTcpSocket socket;
270 socket.setProxy(QNetworkProxy(QNetworkProxy::HttpProxy, hostname, port, username, username));
271 socket.connectToHost(hostName: "0.1.2.3", port: 12345);
272
273 connect(sender: &socket, SIGNAL(errorOccurred(QAbstractSocket::SocketError)),
274 receiver: &QTestEventLoop::instance(), SLOT(exitLoop()));
275 QTestEventLoop::instance().enterLoop(secs: 30);
276 QVERIFY(!QTestEventLoop::instance().timeout());
277
278 QCOMPARE(int(socket.error()), expectedError);
279}
280
281//---------------------------------------------------------------------------
282void tst_QHttpSocketEngine::simpleConnectToIMAP()
283{
284 QHttpSocketEngine socketDevice;
285
286 // Initialize device
287 QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
288 QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
289
290 socketDevice.setProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::httpProxyServerName(), 3128));
291 QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::imapServerIp(), 143));
292 QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectingState);
293 QVERIFY(socketDevice.waitForWrite());
294 QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectedState);
295 QCOMPARE(socketDevice.peerAddress(), QtNetworkSettings::imapServerIp());
296 QVERIFY(!socketDevice.localAddress().isNull());
297 QVERIFY(socketDevice.localPort() > 0);
298
299 // Wait for the greeting
300 QVERIFY(socketDevice.waitForRead());
301
302 // Read the greeting
303 qint64 available = int(socketDevice.bytesAvailable());
304 QVERIFY(available > 0);
305 QByteArray array;
306 array.resize(size: int(available));
307 QVERIFY(socketDevice.read(array.data(), array.size()) == available);
308
309 // Check that the greeting is what we expect it to be
310 QVERIFY2(QtNetworkSettings::compareReplyIMAP(array), array.constData());
311
312
313 // Write a logout message
314 QByteArray array2 = "XXXX LOGOUT\r\n";
315 QVERIFY(socketDevice.write(array2.data(),
316 array2.size()) == array2.size());
317
318 // Wait for the response
319 QVERIFY(socketDevice.waitForRead());
320
321 available = int(socketDevice.bytesAvailable());
322 QVERIFY(available > 0);
323 array.resize(size: int(available));
324 QVERIFY(socketDevice.read(array.data(), array.size()) == available);
325
326 // Check that the greeting is what we expect it to be
327 QCOMPARE(array.constData(), "* BYE LOGOUT received\r\nXXXX OK Completed\r\n");
328
329 // Wait for the response
330 QVERIFY(socketDevice.waitForRead());
331 char c;
332 QCOMPARE(socketDevice.read(&c, sizeof(c)), qint64(-1));
333 QCOMPARE(socketDevice.error(), QAbstractSocket::RemoteHostClosedError);
334 QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
335}
336
337//---------------------------------------------------------------------------
338void tst_QHttpSocketEngine::simpleErrorsAndStates()
339{
340 {
341 QHttpSocketEngine socketDevice;
342
343 // Initialize device
344 QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
345
346 socketDevice.setProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::httpProxyServerName(), 3128));
347
348 QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
349 QVERIFY(!socketDevice.connectToHost(QHostAddress(QtNetworkSettings::socksProxyServerName()), 8088));
350 QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectingState);
351 if (socketDevice.waitForWrite(msecs: 30000)) {
352 QVERIFY(socketDevice.state() == QAbstractSocket::ConnectedState ||
353 socketDevice.state() == QAbstractSocket::UnconnectedState);
354 } else {
355 QCOMPARE(socketDevice.error(), QAbstractSocket::SocketTimeoutError);
356 }
357 }
358
359}
360
361/*
362//---------------------------------------------------------------------------
363void tst_QHttpSocketEngine::tcpLoopbackPerformance()
364{
365 QTcpServer server;
366
367 // Bind to any port on all interfaces
368 QVERIFY(server.bind(QHostAddress("0.0.0.0"), 0));
369 QCOMPARE(server.state(), QAbstractSocket::BoundState);
370 quint16 port = server.localPort();
371
372 // Listen for incoming connections
373 QVERIFY(server.listen());
374 QCOMPARE(server.state(), QAbstractSocket::ListeningState);
375
376 // Initialize a Tcp socket
377 QHttpSocketEngine client;
378 QVERIFY(client.initialize(QAbstractSocket::TcpSocket));
379
380 client.setProxy(QHostAddress("80.232.37.158"), 1081);
381
382 // Connect to our server
383 if (!client.connectToHost(QHostAddress("127.0.0.1"), port)) {
384 QVERIFY(client.waitForWrite());
385 QVERIFY(client.connectToHost(QHostAddress("127.0.0.1"), port));
386 }
387
388 // The server accepts the connectio
389 int socketDescriptor = server.accept();
390 QVERIFY(socketDescriptor > 0);
391
392 // A socket device is initialized on the server side, passing the
393 // socket descriptor from accept(). It's pre-connected.
394 QSocketLayer serverSocket;
395 QVERIFY(serverSocket.initialize(socketDescriptor));
396 QCOMPARE(serverSocket.state(), QAbstractSocket::ConnectedState);
397
398 const int messageSize = 1024 * 256;
399 QByteArray message1(messageSize, '@');
400 QByteArray answer(messageSize, '@');
401
402 QElapsedTimer timer;
403 timer.start();
404 qlonglong readBytes = 0;
405 while (timer.elapsed() < 30000) {
406 qlonglong written = serverSocket.write(message1.data(), message1.size());
407 while (written > 0) {
408 client.waitForRead();
409 if (client.bytesAvailable() > 0) {
410 qlonglong readNow = client.read(answer.data(), answer.size());
411 written -= readNow;
412 readBytes += readNow;
413 }
414 }
415 }
416
417 qDebug("\t\t%.1fMB/%.1fs: %.1fMB/s",
418 readBytes / (1024.0 * 1024.0),
419 timer.elapsed() / 1024.0,
420 (readBytes / (timer.elapsed() / 1000.0)) / (1024 * 1024));
421}
422*/
423
424
425
426void tst_QHttpSocketEngine::tcpSocketBlockingTest()
427{
428 QHttpSocketEngineHandler http;
429
430 QTcpSocket socket;
431
432 // Connect
433 socket.connectToHost(hostName: QtNetworkSettings::imapServerName(), port: 143);
434 QVERIFY(socket.waitForConnected());
435 QCOMPARE(socket.state(), QTcpSocket::ConnectedState);
436
437 // Read greeting
438 QVERIFY(socket.waitForReadyRead(30000));
439 QString s = socket.readLine();
440 QVERIFY2(QtNetworkSettings::compareReplyIMAP(s.toLatin1()), qPrintable(s));
441
442 // Write NOOP
443 QCOMPARE((int) socket.write("1 NOOP\r\n", 8), 8);
444
445 if (!socket.canReadLine())
446 QVERIFY(socket.waitForReadyRead(30000));
447
448 // Read response
449 s = socket.readLine();
450 QCOMPARE(s.toLatin1().constData(), "1 OK Completed\r\n");
451
452 // Write LOGOUT
453 QCOMPARE((int) socket.write("2 LOGOUT\r\n", 10), 10);
454
455 if (!socket.canReadLine())
456 QVERIFY(socket.waitForReadyRead(30000));
457
458 // Read two lines of respose
459 s = socket.readLine();
460 QCOMPARE(s.toLatin1().constData(), "* BYE LOGOUT received\r\n");
461
462 if (!socket.canReadLine())
463 QVERIFY(socket.waitForReadyRead(30000));
464
465 s = socket.readLine();
466 QCOMPARE(s.toLatin1().constData(), "2 OK Completed\r\n");
467
468 // Close the socket
469 socket.close();
470
471 // Check that it's closed
472 QCOMPARE(socket.state(), QTcpSocket::UnconnectedState);
473}
474
475//----------------------------------------------------------------------------------
476
477void tst_QHttpSocketEngine::tcpSocketNonBlockingTest()
478{
479 QHttpSocketEngineHandler http;
480
481 QTcpSocket socket;
482 connect(asender: &socket, SIGNAL(hostFound()), SLOT(tcpSocketNonBlocking_hostFound()));
483 connect(asender: &socket, SIGNAL(connected()), SLOT(tcpSocketNonBlocking_connected()));
484 connect(asender: &socket, SIGNAL(disconnected()), SLOT(tcpSocketNonBlocking_closed()));
485 connect(asender: &socket, SIGNAL(bytesWritten(qint64)), SLOT(tcpSocketNonBlocking_bytesWritten(qint64)));
486 connect(asender: &socket, SIGNAL(readyRead()), SLOT(tcpSocketNonBlocking_readyRead()));
487 tcpSocketNonBlocking_socket = &socket;
488
489 // Connect
490 socket.connectToHost(hostName: QtNetworkSettings::imapServerName(), port: 143);
491 QVERIFY(socket.state() == QTcpSocket::HostLookupState ||
492 socket.state() == QTcpSocket::ConnectingState);
493
494 QTestEventLoop::instance().enterLoop(secs: 30);
495 if (QTestEventLoop::instance().timeout()) {
496 QFAIL("Timed out");
497 }
498
499 if (socket.state() == QTcpSocket::ConnectingState) {
500 QTestEventLoop::instance().enterLoop(secs: 30);
501 if (QTestEventLoop::instance().timeout()) {
502 QFAIL("Timed out");
503 }
504 }
505
506 QCOMPARE(socket.state(), QTcpSocket::ConnectedState);
507
508 QTestEventLoop::instance().enterLoop(secs: 30);
509 if (QTestEventLoop::instance().timeout()) {
510 QFAIL("Timed out");
511 }
512
513 // Read greeting
514 QVERIFY(!tcpSocketNonBlocking_data.isEmpty());
515 QByteArray data = tcpSocketNonBlocking_data.at(i: 0).toLatin1();
516 QVERIFY2(QtNetworkSettings::compareReplyIMAP(data), data.constData());
517
518
519 tcpSocketNonBlocking_data.clear();
520
521 tcpSocketNonBlocking_totalWritten = 0;
522
523 // Write NOOP
524 QCOMPARE((int) socket.write("1 NOOP\r\n", 8), 8);
525
526
527 QTestEventLoop::instance().enterLoop(secs: 30);
528 if (QTestEventLoop::instance().timeout()) {
529 QFAIL("Timed out");
530 }
531
532 QCOMPARE(tcpSocketNonBlocking_totalWritten, 8);
533
534
535 QTestEventLoop::instance().enterLoop(secs: 30);
536 if (QTestEventLoop::instance().timeout()) {
537 QFAIL("Timed out");
538 }
539
540
541 // Read response
542 QVERIFY(!tcpSocketNonBlocking_data.isEmpty());
543 QCOMPARE(tcpSocketNonBlocking_data.at(0).toLatin1().constData(), "1 OK Completed\r\n");
544 tcpSocketNonBlocking_data.clear();
545
546
547 tcpSocketNonBlocking_totalWritten = 0;
548
549 // Write LOGOUT
550 QCOMPARE((int) socket.write("2 LOGOUT\r\n", 10), 10);
551
552 QTestEventLoop::instance().enterLoop(secs: 30);
553 if (QTestEventLoop::instance().timeout()) {
554 QFAIL("Timed out");
555 }
556
557 QCOMPARE(tcpSocketNonBlocking_totalWritten, 10);
558
559 // Wait for greeting
560 QTestEventLoop::instance().enterLoop(secs: 30);
561 if (QTestEventLoop::instance().timeout()) {
562 QFAIL("Timed out");
563 }
564
565 // Read two lines of respose
566 QCOMPARE(tcpSocketNonBlocking_data.at(0).toLatin1().constData(), "* BYE LOGOUT received\r\n");
567 QCOMPARE(tcpSocketNonBlocking_data.at(1).toLatin1().constData(), "2 OK Completed\r\n");
568 tcpSocketNonBlocking_data.clear();
569
570 // Close the socket
571 socket.close();
572
573 // Check that it's closed
574 QCOMPARE(socket.state(), QTcpSocket::UnconnectedState);
575}
576
577void tst_QHttpSocketEngine::tcpSocketNonBlocking_hostFound()
578{
579 QTestEventLoop::instance().exitLoop();
580}
581
582void tst_QHttpSocketEngine::tcpSocketNonBlocking_connected()
583{
584 QTestEventLoop::instance().exitLoop();
585}
586
587void tst_QHttpSocketEngine::tcpSocketNonBlocking_readyRead()
588{
589 while (tcpSocketNonBlocking_socket->canReadLine())
590 tcpSocketNonBlocking_data.append(t: tcpSocketNonBlocking_socket->readLine());
591
592 QTestEventLoop::instance().exitLoop();
593}
594
595void tst_QHttpSocketEngine::tcpSocketNonBlocking_bytesWritten(qint64 written)
596{
597 tcpSocketNonBlocking_totalWritten += written;
598 QTestEventLoop::instance().exitLoop();
599}
600
601void tst_QHttpSocketEngine::tcpSocketNonBlocking_closed()
602{
603}
604
605//----------------------------------------------------------------------------------
606
607void tst_QHttpSocketEngine::downloadBigFile()
608{
609 QHttpSocketEngineHandler http;
610
611 if (tmpSocket)
612 delete tmpSocket;
613 tmpSocket = new QTcpSocket;
614
615 connect(asender: tmpSocket, SIGNAL(connected()), SLOT(exitLoopSlot()));
616 connect(asender: tmpSocket, SIGNAL(readyRead()), SLOT(downloadBigFileSlot()));
617
618 tmpSocket->connectToHost(hostName: QtNetworkSettings::httpServerName(), port: 80);
619
620 QTestEventLoop::instance().enterLoop(secs: 30);
621 if (QTestEventLoop::instance().timeout())
622 QFAIL("Network operation timed out");
623
624 QByteArray hostName = QtNetworkSettings::httpServerName().toLatin1();
625 QCOMPARE(tmpSocket->state(), QAbstractSocket::ConnectedState);
626 QVERIFY(tmpSocket->write("GET /qtest/mediumfile HTTP/1.0\r\n") > 0);
627 QVERIFY(tmpSocket->write("Host: ") > 0);
628 QVERIFY(tmpSocket->write(hostName.data()) > 0);
629 QVERIFY(tmpSocket->write("\r\n") > 0);
630 QVERIFY(tmpSocket->write("\r\n") > 0);
631
632 bytesAvailable = 0;
633
634 QElapsedTimer stopWatch;
635 stopWatch.start();
636
637 QTestEventLoop::instance().enterLoop(secs: 60);
638 if (QTestEventLoop::instance().timeout())
639 QFAIL("Network operation timed out");
640
641 QVERIFY(bytesAvailable >= 10000000);
642
643 QCOMPARE(tmpSocket->state(), QAbstractSocket::ConnectedState);
644
645 qDebug(msg: "\t\t%.1fMB/%.1fs: %.1fMB/s",
646 bytesAvailable / (1024.0 * 1024.0),
647 stopWatch.elapsed() / 1024.0,
648 (bytesAvailable / (stopWatch.elapsed() / 1000.0)) / (1024 * 1024));
649
650 delete tmpSocket;
651 tmpSocket = 0;
652}
653
654void tst_QHttpSocketEngine::exitLoopSlot()
655{
656 QTestEventLoop::instance().exitLoop();
657}
658
659
660void tst_QHttpSocketEngine::downloadBigFileSlot()
661{
662 bytesAvailable += tmpSocket->readAll().size();
663 if (bytesAvailable >= 10000000)
664 QTestEventLoop::instance().exitLoop();
665}
666
667void tst_QHttpSocketEngine::passwordAuth()
668{
669 QHttpSocketEngine socketDevice;
670
671 // Initialize device
672 QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol));
673 QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
674
675 socketDevice.setProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::httpProxyServerName(), 3128, "qsockstest", "password"));
676
677 QVERIFY(!socketDevice.connectToHost(QtNetworkSettings::imapServerIp(), 143));
678 QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectingState);
679 QVERIFY(socketDevice.waitForWrite());
680 QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectedState);
681 QCOMPARE(socketDevice.peerAddress(), QtNetworkSettings::imapServerIp());
682
683 // Wait for the greeting
684 QVERIFY(socketDevice.waitForRead());
685
686 // Read the greeting
687 qint64 available = socketDevice.bytesAvailable();
688 QVERIFY(available > 0);
689 QByteArray array;
690 array.resize(size: available);
691 QVERIFY(socketDevice.read(array.data(), array.size()) == available);
692
693 // Check that the greeting is what we expect it to be
694 QVERIFY2(QtNetworkSettings::compareReplyIMAP(array), array.constData());
695
696
697 // Write a logout message
698 QByteArray array2 = "XXXX LOGOUT\r\n";
699 QVERIFY(socketDevice.write(array2.data(),
700 array2.size()) == array2.size());
701
702 // Wait for the response
703 QVERIFY(socketDevice.waitForRead());
704
705 available = socketDevice.bytesAvailable();
706 QVERIFY(available > 0);
707 array.resize(size: available);
708 QVERIFY(socketDevice.read(array.data(), array.size()) == available);
709
710 // Check that the greeting is what we expect it to be
711 QCOMPARE(array.constData(), "* BYE LOGOUT received\r\nXXXX OK Completed\r\n");
712
713 // Wait for the response
714 QVERIFY(socketDevice.waitForRead());
715 char c;
716 QVERIFY(socketDevice.read(&c, sizeof(c)) == -1);
717 QCOMPARE(socketDevice.error(), QAbstractSocket::RemoteHostClosedError);
718 QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
719}
720
721//----------------------------------------------------------------------------------
722
723void tst_QHttpSocketEngine::ensureEofTriggersNotification()
724{
725 QList<QByteArray> serverData;
726 // Set the handshake and server response data
727 serverData << "HTTP/1.0 200 Connection established\r\n\r\n" << "0";
728 MiniHttpServer server(serverData);
729
730 QTcpSocket socket;
731 connect(asender: &socket, SIGNAL(connected()), SLOT(exitLoopSlot()));
732 socket.setProxy(QNetworkProxy(QNetworkProxy::HttpProxy, server.serverAddress().toString(),
733 server.serverPort()));
734 socket.connectToHost(hostName: "0.1.2.3", port: 12345);
735
736 QTestEventLoop::instance().enterLoop(secs: 5);
737 if (QTestEventLoop::instance().timeout())
738 QFAIL("Connect timed out");
739
740 QCOMPARE(socket.state(), QTcpSocket::ConnectedState);
741 // Disable read notification on server response
742 socket.setReadBufferSize(1);
743 socket.putChar(c: 0);
744
745 // Wait for the response
746 connect(asender: &socket, SIGNAL(readyRead()), SLOT(exitLoopSlot()));
747 QTestEventLoop::instance().enterLoop(secs: 5);
748 if (QTestEventLoop::instance().timeout())
749 QFAIL("Read timed out");
750
751 QCOMPARE(socket.state(), QTcpSocket::ConnectedState);
752 QCOMPARE(socket.bytesAvailable(), 1);
753 // Trigger a read notification
754 socket.readAll();
755 // Check for pending EOF at input
756 QCOMPARE(socket.bytesAvailable(), 0);
757 QCOMPARE(socket.state(), QTcpSocket::ConnectedState);
758
759 // Try to read EOF
760 connect(asender: &socket, SIGNAL(disconnected()), SLOT(exitLoopSlot()));
761 QTestEventLoop::instance().enterLoop(secs: 5);
762 if (QTestEventLoop::instance().timeout())
763 QFAIL("Disconnect timed out");
764
765 // Check that it's closed
766 QCOMPARE(socket.state(), QTcpSocket::UnconnectedState);
767}
768
769QTEST_MAIN(tst_QHttpSocketEngine)
770#include "tst_qhttpsocketengine.moc"
771

source code of qtbase/tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp