310 QString errorMsg = call; \ |
324 QString errorMsg = call; \ |
311 if (!errorMsg.isEmpty()) \ |
325 if (!errorMsg.isEmpty()) \ |
312 QFAIL(qPrintable(errorMsg)); \ |
326 QFAIL(qPrintable(errorMsg)); \ |
313 } while (0); |
327 } while (0); |
314 |
328 |
|
329 |
|
330 // Does not work for POST/PUT! |
315 class MiniHttpServer: public QTcpServer |
331 class MiniHttpServer: public QTcpServer |
316 { |
332 { |
317 Q_OBJECT |
333 Q_OBJECT |
318 QTcpSocket *client; |
|
319 |
|
320 public: |
334 public: |
|
335 QTcpSocket *client; // always the last one that was received |
321 QByteArray dataToTransmit; |
336 QByteArray dataToTransmit; |
322 QByteArray receivedData; |
337 QByteArray receivedData; |
323 bool doClose; |
338 bool doClose; |
|
339 bool multiple; |
324 int totalConnections; |
340 int totalConnections; |
325 |
341 |
326 MiniHttpServer(const QByteArray &data) : client(0), dataToTransmit(data), doClose(true), totalConnections(0) |
342 MiniHttpServer(const QByteArray &data) : client(0), dataToTransmit(data), doClose(true), multiple(false), totalConnections(0) |
327 { |
343 { |
328 listen(); |
344 listen(); |
329 connect(this, SIGNAL(newConnection()), this, SLOT(doAccept())); |
345 connect(this, SIGNAL(newConnection()), this, SLOT(doAccept())); |
330 } |
346 } |
331 |
347 |
332 public slots: |
348 public slots: |
333 void doAccept() |
349 void doAccept() |
334 { |
350 { |
335 client = nextPendingConnection(); |
351 client = nextPendingConnection(); |
|
352 client->setParent(this); |
336 ++totalConnections; |
353 ++totalConnections; |
337 connect(client, SIGNAL(readyRead()), this, SLOT(sendData())); |
354 connect(client, SIGNAL(readyRead()), this, SLOT(readyReadSlot())); |
338 } |
355 } |
339 |
356 |
340 void sendData() |
357 void readyReadSlot() |
341 { |
358 { |
342 receivedData += client->readAll(); |
359 receivedData += client->readAll(); |
343 if (receivedData.contains("\r\n\r\n") || |
360 int doubleEndlPos = receivedData.indexOf("\r\n\r\n"); |
344 receivedData.contains("\n\n")) { |
361 |
|
362 if (doubleEndlPos != -1) { |
|
363 // multiple requests incoming. remove the bytes of the current one |
|
364 if (multiple) |
|
365 receivedData.remove(0, doubleEndlPos+4); |
|
366 |
345 client->write(dataToTransmit); |
367 client->write(dataToTransmit); |
346 if (doClose) { |
368 if (doClose) { |
347 client->disconnectFromHost(); |
369 client->disconnectFromHost(); |
348 disconnect(client, 0, this, 0); |
370 disconnect(client, 0, this, 0); |
349 client = 0; |
371 client = 0; |
2050 QTestEventLoop::instance().enterLoop(10); |
2077 QTestEventLoop::instance().enterLoop(10); |
2051 QVERIFY(!QTestEventLoop::instance().timeout()); |
2078 QVERIFY(!QTestEventLoop::instance().timeout()); |
2052 |
2079 |
2053 QCOMPARE(reply->url(), request.url()); |
2080 QCOMPARE(reply->url(), request.url()); |
2054 QVERIFY(reply->error() != QNetworkReply::NoError); |
2081 QVERIFY(reply->error() != QNetworkReply::NoError); |
|
2082 } |
|
2083 |
|
2084 void tst_QNetworkReply::ioGetFromHttpStatus100_data() |
|
2085 { |
|
2086 QTest::addColumn<QByteArray>("dataToSend"); |
|
2087 QTest::newRow("normal") << QByteArray("HTTP/1.1 100 Continue\r\n\r\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); |
|
2088 QTest::newRow("minimal") << QByteArray("HTTP/1.1 100 Continue\n\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); |
|
2089 QTest::newRow("minimal2") << QByteArray("HTTP/1.1 100 Continue\n\nHTTP/1.0 200 OK\r\n\r\n"); |
|
2090 QTest::newRow("minimal3") << QByteArray("HTTP/1.1 100 Continue\n\nHTTP/1.0 200 OK\n\n"); |
|
2091 QTest::newRow("with_headers") << QByteArray("HTTP/1.1 100 Continue\r\nBla: x\r\n\r\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); |
|
2092 QTest::newRow("with_headers2") << QByteArray("HTTP/1.1 100 Continue\nBla: x\n\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); |
|
2093 } |
|
2094 |
|
2095 void tst_QNetworkReply::ioGetFromHttpStatus100() |
|
2096 { |
|
2097 QFETCH(QByteArray, dataToSend); |
|
2098 MiniHttpServer server(dataToSend); |
|
2099 server.doClose = true; |
|
2100 |
|
2101 QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort()))); |
|
2102 QNetworkReplyPtr reply = manager.get(request); |
|
2103 |
|
2104 connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); |
|
2105 QTestEventLoop::instance().enterLoop(10); |
|
2106 QVERIFY(!QTestEventLoop::instance().timeout()); |
|
2107 |
|
2108 QCOMPARE(reply->url(), request.url()); |
|
2109 QCOMPARE(reply->error(), QNetworkReply::NoError); |
|
2110 QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); |
|
2111 QVERIFY(reply->rawHeader("bla").isNull()); |
|
2112 } |
|
2113 |
|
2114 void tst_QNetworkReply::ioGetFromHttpNoHeaders_data() |
|
2115 { |
|
2116 QTest::addColumn<QByteArray>("dataToSend"); |
|
2117 QTest::newRow("justStatus+noheaders+disconnect") << QByteArray("HTTP/1.0 200 OK\r\n\r\n"); |
|
2118 } |
|
2119 |
|
2120 void tst_QNetworkReply::ioGetFromHttpNoHeaders() |
|
2121 { |
|
2122 QFETCH(QByteArray, dataToSend); |
|
2123 MiniHttpServer server(dataToSend); |
|
2124 server.doClose = true; |
|
2125 |
|
2126 QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort()))); |
|
2127 QNetworkReplyPtr reply = manager.get(request); |
|
2128 |
|
2129 connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); |
|
2130 QTestEventLoop::instance().enterLoop(10); |
|
2131 QVERIFY(!QTestEventLoop::instance().timeout()); |
|
2132 |
|
2133 QCOMPARE(reply->url(), request.url()); |
|
2134 QCOMPARE(reply->error(), QNetworkReply::NoError); |
|
2135 QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); |
2055 } |
2136 } |
2056 |
2137 |
2057 void tst_QNetworkReply::ioGetFromHttpWithCache_data() |
2138 void tst_QNetworkReply::ioGetFromHttpWithCache_data() |
2058 { |
2139 { |
2059 qRegisterMetaType<MyMemoryCache::CachedContent>(); |
2140 qRegisterMetaType<MyMemoryCache::CachedContent>(); |
3779 // hardcoded defaultChannelCount = 3 |
3860 // hardcoded defaultChannelCount = 3 |
3780 QCOMPARE(pendingConnectionCount, 3); |
3861 QCOMPARE(pendingConnectionCount, 3); |
3781 #else |
3862 #else |
3782 QCOMPARE(pendingConnectionCount, 6); |
3863 QCOMPARE(pendingConnectionCount, 6); |
3783 #endif |
3864 #endif |
|
3865 } |
|
3866 |
|
3867 void tst_QNetworkReply::httpReUsingConnectionSequential_data() |
|
3868 { |
|
3869 QTest::addColumn<bool>("doDeleteLater"); |
|
3870 QTest::newRow("deleteLater") << true; |
|
3871 QTest::newRow("noDeleteLater") << false; |
|
3872 } |
|
3873 |
|
3874 void tst_QNetworkReply::httpReUsingConnectionSequential() |
|
3875 { |
|
3876 QFETCH(bool, doDeleteLater); |
|
3877 |
|
3878 QByteArray response("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); |
|
3879 MiniHttpServer server(response); |
|
3880 server.multiple = true; |
|
3881 server.doClose = false; |
|
3882 |
|
3883 QUrl url; |
|
3884 url.setScheme("http"); |
|
3885 url.setPort(server.serverPort()); |
|
3886 url.setHost("127.0.0.1"); |
|
3887 // first request |
|
3888 QNetworkReply* reply1 = manager.get(QNetworkRequest(url)); |
|
3889 connect(reply1, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); |
|
3890 QTestEventLoop::instance().enterLoop(2); |
|
3891 QVERIFY(!QTestEventLoop::instance().timeout()); |
|
3892 QVERIFY(!reply1->error()); |
|
3893 int reply1port = server.client->peerPort(); |
|
3894 |
|
3895 if (doDeleteLater) |
|
3896 reply1->deleteLater(); |
|
3897 |
|
3898 // finished received, send the next one |
|
3899 QNetworkReply*reply2 = manager.get(QNetworkRequest(url)); |
|
3900 connect(reply2, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); |
|
3901 QTestEventLoop::instance().enterLoop(2); |
|
3902 QVERIFY(!QTestEventLoop::instance().timeout()); |
|
3903 QVERIFY(!reply2->error()); |
|
3904 int reply2port = server.client->peerPort(); // should still be the same object |
|
3905 |
|
3906 QVERIFY(reply1port > 0); |
|
3907 QCOMPARE(server.totalConnections, 1); |
|
3908 QCOMPARE(reply2port, reply1port); |
|
3909 |
|
3910 if (!doDeleteLater) |
|
3911 reply1->deleteLater(); // only do it if it was not done earlier |
|
3912 reply2->deleteLater(); |
|
3913 } |
|
3914 |
|
3915 class HttpReUsingConnectionFromFinishedSlot : public QObject { |
|
3916 Q_OBJECT; |
|
3917 public: |
|
3918 QNetworkReply* reply1; |
|
3919 QNetworkReply* reply2; |
|
3920 QUrl url; |
|
3921 QNetworkAccessManager manager; |
|
3922 public slots: |
|
3923 void finishedSlot() { |
|
3924 QVERIFY(!reply1->error()); |
|
3925 |
|
3926 QFETCH(bool, doDeleteLater); |
|
3927 if (doDeleteLater) { |
|
3928 reply1->deleteLater(); |
|
3929 reply1 = 0; |
|
3930 } |
|
3931 |
|
3932 // kick off 2nd request and exit the loop when it is done |
|
3933 reply2 = manager.get(QNetworkRequest(url)); |
|
3934 reply2->setParent(this); |
|
3935 connect(reply2, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); |
|
3936 } |
|
3937 }; |
|
3938 |
|
3939 void tst_QNetworkReply::httpReUsingConnectionFromFinishedSlot_data() |
|
3940 { |
|
3941 httpReUsingConnectionSequential_data(); |
|
3942 } |
|
3943 |
|
3944 void tst_QNetworkReply::httpReUsingConnectionFromFinishedSlot() |
|
3945 { |
|
3946 QByteArray response("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); |
|
3947 MiniHttpServer server(response); |
|
3948 server.multiple = true; |
|
3949 server.doClose = false; |
|
3950 |
|
3951 HttpReUsingConnectionFromFinishedSlot helper; |
|
3952 helper.reply1 = 0; |
|
3953 helper.reply2 = 0; |
|
3954 helper.url.setScheme("http"); |
|
3955 helper.url.setPort(server.serverPort()); |
|
3956 helper.url.setHost("127.0.0.1"); |
|
3957 |
|
3958 // first request |
|
3959 helper.reply1 = helper.manager.get(QNetworkRequest(helper.url)); |
|
3960 helper.reply1->setParent(&helper); |
|
3961 connect(helper.reply1, SIGNAL(finished()), &helper, SLOT(finishedSlot())); |
|
3962 QTestEventLoop::instance().enterLoop(4); |
|
3963 QVERIFY(!QTestEventLoop::instance().timeout()); |
|
3964 |
|
3965 QVERIFY(helper.reply2); |
|
3966 QVERIFY(!helper.reply2->error()); |
|
3967 |
|
3968 QCOMPARE(server.totalConnections, 1); |
|
3969 } |
|
3970 |
|
3971 class HttpRecursiveCreationHelper : public QObject { |
|
3972 Q_OBJECT |
|
3973 public: |
|
3974 |
|
3975 HttpRecursiveCreationHelper(): |
|
3976 QObject(0), |
|
3977 requestsStartedCount_finished(0), |
|
3978 requestsStartedCount_readyRead(0), |
|
3979 requestsFinishedCount(0) |
|
3980 { |
|
3981 } |
|
3982 QNetworkAccessManager manager; |
|
3983 int requestsStartedCount_finished; |
|
3984 int requestsStartedCount_readyRead; |
|
3985 int requestsFinishedCount; |
|
3986 public slots: |
|
3987 void finishedSlot() { |
|
3988 requestsFinishedCount++; |
|
3989 |
|
3990 QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender()); |
|
3991 QVERIFY(!reply->error()); |
|
3992 QVERIFY(reply->bytesAvailable() == 27906); |
|
3993 |
|
3994 if (requestsFinishedCount == 60) { |
|
3995 QTestEventLoop::instance().exitLoop(); |
|
3996 return; |
|
3997 } |
|
3998 |
|
3999 if (requestsStartedCount_finished < 30) { |
|
4000 startOne(); |
|
4001 requestsStartedCount_finished++; |
|
4002 } |
|
4003 |
|
4004 reply->deleteLater(); |
|
4005 } |
|
4006 void readyReadSlot() { |
|
4007 QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender()); |
|
4008 QVERIFY(!reply->error()); |
|
4009 |
|
4010 if (requestsStartedCount_readyRead < 30 && reply->bytesAvailable() > 27906/2) { |
|
4011 startOne(); |
|
4012 requestsStartedCount_readyRead++; |
|
4013 } |
|
4014 } |
|
4015 void startOne() { |
|
4016 QUrl url = "http://" + QtNetworkSettings::serverName() + "/gif/fluke.gif"; |
|
4017 QNetworkRequest request(url); |
|
4018 QNetworkReply *reply = manager.get(request); |
|
4019 reply->setParent(this); |
|
4020 connect(reply, SIGNAL(finished()), this, SLOT(finishedSlot())); |
|
4021 connect(reply, SIGNAL(readyRead()), this, SLOT(readyReadSlot())); |
|
4022 } |
|
4023 }; |
|
4024 |
|
4025 void tst_QNetworkReply::httpRecursiveCreation() |
|
4026 { |
|
4027 // this test checks if creation of new requests to the same host properly works |
|
4028 // from readyRead() and finished() signals |
|
4029 HttpRecursiveCreationHelper helper; |
|
4030 helper.startOne(); |
|
4031 QTestEventLoop::instance().enterLoop(30); |
|
4032 QVERIFY(!QTestEventLoop::instance().timeout()); |
3784 } |
4033 } |
3785 |
4034 |
3786 #ifndef QT_NO_OPENSSL |
4035 #ifndef QT_NO_OPENSSL |
3787 void tst_QNetworkReply::ignoreSslErrorsList_data() |
4036 void tst_QNetworkReply::ignoreSslErrorsList_data() |
3788 { |
4037 { |