tests/auto/qnetworkreply/tst_qnetworkreply.cpp
branchRCL_3
changeset 8 3f74d0d4af4c
parent 4 3b1da2848fc7
child 14 c0432d11811c
equal deleted inserted replaced
6:dee5afe5301f 8:3f74d0d4af4c
   197     void ioGetFromHttpsWithIgnoreSslErrors();
   197     void ioGetFromHttpsWithIgnoreSslErrors();
   198     void ioGetFromHttpsWithSslHandshakeError();
   198     void ioGetFromHttpsWithSslHandshakeError();
   199 #endif
   199 #endif
   200     void ioGetFromHttpBrokenServer_data();
   200     void ioGetFromHttpBrokenServer_data();
   201     void ioGetFromHttpBrokenServer();
   201     void ioGetFromHttpBrokenServer();
       
   202     void ioGetFromHttpStatus100_data();
       
   203     void ioGetFromHttpStatus100();
       
   204     void ioGetFromHttpNoHeaders_data();
       
   205     void ioGetFromHttpNoHeaders();
   202     void ioGetFromHttpWithCache_data();
   206     void ioGetFromHttpWithCache_data();
   203     void ioGetFromHttpWithCache();
   207     void ioGetFromHttpWithCache();
   204 
   208 
   205     void ioGetWithManyProxies_data();
   209     void ioGetWithManyProxies_data();
   206     void ioGetWithManyProxies();
   210     void ioGetWithManyProxies();
   255     void authorizationError_data();
   259     void authorizationError_data();
   256     void authorizationError();
   260     void authorizationError();
   257 
   261 
   258     void httpConnectionCount();
   262     void httpConnectionCount();
   259 
   263 
       
   264     void httpReUsingConnectionSequential_data();
       
   265     void httpReUsingConnectionSequential();
       
   266     void httpReUsingConnectionFromFinishedSlot_data();
       
   267     void httpReUsingConnectionFromFinishedSlot();
       
   268 
       
   269     void httpRecursiveCreation();
       
   270 
   260 #ifndef QT_NO_OPENSSL
   271 #ifndef QT_NO_OPENSSL
   261     void ioPostToHttpsUploadProgress();
   272     void ioPostToHttpsUploadProgress();
   262     void ignoreSslErrorsList_data();
   273     void ignoreSslErrorsList_data();
   263     void ignoreSslErrorsList();
   274     void ignoreSslErrorsList();
   264     void ignoreSslErrorsListWithSlot_data();
   275     void ignoreSslErrorsListWithSlot_data();
   265     void ignoreSslErrorsListWithSlot();
   276     void ignoreSslErrorsListWithSlot();
   266 #endif
   277 #endif
       
   278 
       
   279     // NOTE: This test must be last!
       
   280     void parentingRepliesToTheApp();
   267 };
   281 };
   268 
   282 
   269 QT_BEGIN_NAMESPACE
   283 QT_BEGIN_NAMESPACE
   270 
   284 
   271 namespace QTest {
   285 namespace QTest {
   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;
  2032     QTest::newRow("with-newlines3+disconnect") << QByteArray("ICY\r\nSecond line") << true;
  2054     QTest::newRow("with-newlines3+disconnect") << QByteArray("ICY\r\nSecond line") << true;
  2033 
  2055 
  2034     QTest::newRow("invalid-version+disconnect") << QByteArray("HTTP/123 200 ") << true;
  2056     QTest::newRow("invalid-version+disconnect") << QByteArray("HTTP/123 200 ") << true;
  2035     QTest::newRow("invalid-version2+disconnect") << QByteArray("HTTP/a.\033 200 ") << true;
  2057     QTest::newRow("invalid-version2+disconnect") << QByteArray("HTTP/a.\033 200 ") << true;
  2036     QTest::newRow("invalid-reply-code+disconnect") << QByteArray("HTTP/1.0 fuu ") << true;
  2058     QTest::newRow("invalid-reply-code+disconnect") << QByteArray("HTTP/1.0 fuu ") << true;
       
  2059 
       
  2060     QTest::newRow("immediate disconnect") << QByteArray("") << true;
       
  2061     QTest::newRow("justHalfStatus+disconnect") << QByteArray("HTTP/1.1") << true;
       
  2062     QTest::newRow("justStatus+disconnect") << QByteArray("HTTP/1.1 200 OK\r\n") << true;
       
  2063     QTest::newRow("justStatusAndHalfHeaders+disconnect") << QByteArray("HTTP/1.1 200 OK\r\nContent-L") << true;
  2037 }
  2064 }
  2038 
  2065 
  2039 void tst_QNetworkReply::ioGetFromHttpBrokenServer()
  2066 void tst_QNetworkReply::ioGetFromHttpBrokenServer()
  2040 {
  2067 {
  2041     QFETCH(QByteArray, dataToSend);
  2068     QFETCH(QByteArray, dataToSend);
  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>();
  3751     QCoreApplication::instance()->processEvents();
  3832     QCoreApplication::instance()->processEvents();
  3752 
  3833 
  3753     for (int i = 0; i < 10; i++) {
  3834     for (int i = 0; i < 10; i++) {
  3754         QNetworkRequest request (QUrl("http://127.0.0.1:" + QString::number(server.serverPort()) + "/" +  QString::number(i)));
  3835         QNetworkRequest request (QUrl("http://127.0.0.1:" + QString::number(server.serverPort()) + "/" +  QString::number(i)));
  3755         QNetworkReply* reply = manager.get(request);
  3836         QNetworkReply* reply = manager.get(request);
  3756         reply->setParent(this);
  3837         reply->setParent(&server);
  3757     }
  3838     }
  3758 
  3839 
  3759     int pendingConnectionCount = 0;
  3840     int pendingConnectionCount = 0;
  3760     QTime time;
  3841     QTime time;
  3761     time.start();
  3842     time.start();
  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 {
  3857     QCOMPARE(reply->error(), expectedNetworkError);
  4106     QCOMPARE(reply->error(), expectedNetworkError);
  3858 }
  4107 }
  3859 
  4108 
  3860 #endif // QT_NO_OPENSSL
  4109 #endif // QT_NO_OPENSSL
  3861 
  4110 
       
  4111 // NOTE: This test must be last testcase in tst_qnetworkreply!
       
  4112 void tst_QNetworkReply::parentingRepliesToTheApp()
       
  4113 {
       
  4114     QNetworkRequest request (QUrl("http://" + QtNetworkSettings::serverName()));
       
  4115     manager.get(request)->setParent(this); // parent to this object
       
  4116     manager.get(request)->setParent(qApp); // parent to the app
       
  4117 }
       
  4118 
  3862 QTEST_MAIN(tst_QNetworkReply)
  4119 QTEST_MAIN(tst_QNetworkReply)
  3863 #include "tst_qnetworkreply.moc"
  4120 #include "tst_qnetworkreply.moc"