tests/auto/qnetworkreply/tst_qnetworkreply.cpp
changeset 18 2f34d5167611
parent 3 41300fa6a67c
child 19 fcece45ef507
equal deleted inserted replaced
3:41300fa6a67c 18:2f34d5167611
     1 /****************************************************************************
     1 /****************************************************************************
     2 **
     2 **
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     4 ** All rights reserved.
     4 ** All rights reserved.
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     6 **
     6 **
     7 ** This file is part of the test suite of the Qt Toolkit.
     7 ** This file is part of the test suite of the Qt Toolkit.
     8 **
     8 **
    52 #include <QtNetwork/QTcpSocket>
    52 #include <QtNetwork/QTcpSocket>
    53 #include <QtNetwork/QLocalSocket>
    53 #include <QtNetwork/QLocalSocket>
    54 #include <QtNetwork/QLocalServer>
    54 #include <QtNetwork/QLocalServer>
    55 #include <QtNetwork/QHostInfo>
    55 #include <QtNetwork/QHostInfo>
    56 #include <QtNetwork/QFtp>
    56 #include <QtNetwork/QFtp>
       
    57 #include <QtNetwork/QAbstractNetworkCache>
    57 #include <QtNetwork/qauthenticator.h>
    58 #include <QtNetwork/qauthenticator.h>
    58 #include <QtNetwork/qnetworkaccessmanager.h>
    59 #include <QtNetwork/qnetworkaccessmanager.h>
    59 #include <QtNetwork/qnetworkrequest.h>
    60 #include <QtNetwork/qnetworkrequest.h>
    60 #include <QtNetwork/qnetworkreply.h>
    61 #include <QtNetwork/qnetworkreply.h>
    61 #include <QtNetwork/qnetworkcookie.h>
    62 #include <QtNetwork/qnetworkcookie.h>
   196     void ioGetFromHttpsWithIgnoreSslErrors();
   197     void ioGetFromHttpsWithIgnoreSslErrors();
   197     void ioGetFromHttpsWithSslHandshakeError();
   198     void ioGetFromHttpsWithSslHandshakeError();
   198 #endif
   199 #endif
   199     void ioGetFromHttpBrokenServer_data();
   200     void ioGetFromHttpBrokenServer_data();
   200     void ioGetFromHttpBrokenServer();
   201     void ioGetFromHttpBrokenServer();
       
   202     void ioGetFromHttpWithCache_data();
       
   203     void ioGetFromHttpWithCache();
   201 
   204 
   202     void ioGetWithManyProxies_data();
   205     void ioGetWithManyProxies_data();
   203     void ioGetWithManyProxies();
   206     void ioGetWithManyProxies();
   204 
   207 
   205     void ioPutToFileFromFile_data();
   208     void ioPutToFileFromFile_data();
   221     void ioPostToHttpFromMiddleOfFileToEnd();
   224     void ioPostToHttpFromMiddleOfFileToEnd();
   222     void ioPostToHttpFromMiddleOfFileFiveBytes();
   225     void ioPostToHttpFromMiddleOfFileFiveBytes();
   223     void ioPostToHttpFromMiddleOfQBufferFiveBytes();
   226     void ioPostToHttpFromMiddleOfQBufferFiveBytes();
   224     void ioPostToHttpNoBufferFlag();
   227     void ioPostToHttpNoBufferFlag();
   225     void ioPostToHttpUploadProgress();
   228     void ioPostToHttpUploadProgress();
   226     void ioPostToHttpEmtpyUploadProgress();
   229     void ioPostToHttpEmptyUploadProgress();
   227 
   230 
   228     void lastModifiedHeaderForFile();
   231     void lastModifiedHeaderForFile();
   229     void lastModifiedHeaderForHttp();
   232     void lastModifiedHeaderForHttp();
   230 
   233 
   231     void rateControl_data();
   234     void rateControl_data();
   251     void proxyChange();
   254     void proxyChange();
   252     void authorizationError_data();
   255     void authorizationError_data();
   253     void authorizationError();
   256     void authorizationError();
   254 
   257 
   255     void httpConnectionCount();
   258     void httpConnectionCount();
       
   259 
       
   260     void httpReUsingConnectionSequential_data();
       
   261     void httpReUsingConnectionSequential();
       
   262     void httpReUsingConnectionFromFinishedSlot_data();
       
   263     void httpReUsingConnectionFromFinishedSlot();
       
   264 
       
   265     void httpRecursiveCreation();
   256 
   266 
   257 #ifndef QT_NO_OPENSSL
   267 #ifndef QT_NO_OPENSSL
   258     void ioPostToHttpsUploadProgress();
   268     void ioPostToHttpsUploadProgress();
   259     void ignoreSslErrorsList_data();
   269     void ignoreSslErrorsList_data();
   260     void ignoreSslErrorsList();
   270     void ignoreSslErrorsList();
   307         QString errorMsg = call;                \
   317         QString errorMsg = call;                \
   308         if (!errorMsg.isEmpty())                \
   318         if (!errorMsg.isEmpty())                \
   309             QFAIL(qPrintable(errorMsg));        \
   319             QFAIL(qPrintable(errorMsg));        \
   310     } while (0);
   320     } while (0);
   311 
   321 
       
   322 
       
   323 // Does not work for POST/PUT!
   312 class MiniHttpServer: public QTcpServer
   324 class MiniHttpServer: public QTcpServer
   313 {
   325 {
   314     Q_OBJECT
   326     Q_OBJECT
   315     QTcpSocket *client;
       
   316 
       
   317 public:
   327 public:
       
   328     QTcpSocket *client; // always the last one that was received
   318     QByteArray dataToTransmit;
   329     QByteArray dataToTransmit;
   319     QByteArray receivedData;
   330     QByteArray receivedData;
   320     bool doClose;
   331     bool doClose;
   321 
   332     bool multiple;
   322     MiniHttpServer(const QByteArray &data) : client(0), dataToTransmit(data), doClose(true)
   333     int totalConnections;
       
   334 
       
   335     MiniHttpServer(const QByteArray &data) : client(0), dataToTransmit(data), doClose(true), multiple(false), totalConnections(0)
   323     {
   336     {
   324         listen();
   337         listen();
   325         connect(this, SIGNAL(newConnection()), this, SLOT(doAccept()));
   338         connect(this, SIGNAL(newConnection()), this, SLOT(doAccept()));
   326     }
   339     }
   327 
   340 
   328 public slots:
   341 public slots:
   329     void doAccept()
   342     void doAccept()
   330     {
   343     {
   331         client = nextPendingConnection();
   344         client = nextPendingConnection();
   332         connect(client, SIGNAL(readyRead()), this, SLOT(sendData()));
   345         client->setParent(this);
   333     }
   346         ++totalConnections;
   334 
   347         connect(client, SIGNAL(readyRead()), this, SLOT(readyReadSlot()));
   335     void sendData()
   348     }
       
   349 
       
   350     void readyReadSlot()
   336     {
   351     {
   337         receivedData += client->readAll();
   352         receivedData += client->readAll();
   338         if (receivedData.contains("\r\n\r\n") ||
   353         int doubleEndlPos = receivedData.indexOf("\r\n\r\n");
   339             receivedData.contains("\n\n")) {
   354 
       
   355         if (doubleEndlPos != -1) {
       
   356             // multiple requests incoming. remove the bytes of the current one
       
   357             if (multiple)
       
   358                 receivedData.remove(0, doubleEndlPos+4);
       
   359 
   340             client->write(dataToTransmit);
   360             client->write(dataToTransmit);
   341             if (doClose) {
   361             if (doClose) {
   342                 client->disconnectFromHost();
   362                 client->disconnectFromHost();
   343                 disconnect(client, 0, this, 0);
   363                 disconnect(client, 0, this, 0);
   344                 client = 0;
   364                 client = 0;
   376         lastQuery = query;
   396         lastQuery = query;
   377         ++callCount;
   397         ++callCount;
   378         return toReturn;
   398         return toReturn;
   379     }
   399     }
   380 };
   400 };
       
   401 
       
   402 class MyMemoryCache: public QAbstractNetworkCache
       
   403 {
       
   404 public:
       
   405     typedef QPair<QNetworkCacheMetaData, QByteArray> CachedContent;
       
   406     typedef QHash<QByteArray, CachedContent> CacheData;
       
   407     CacheData cache;
       
   408 
       
   409     MyMemoryCache(QObject *parent) : QAbstractNetworkCache(parent) {}
       
   410 
       
   411     QNetworkCacheMetaData metaData(const QUrl &url)
       
   412     {
       
   413         return cache.value(url.toEncoded()).first;
       
   414     }
       
   415 
       
   416     void updateMetaData(const QNetworkCacheMetaData &metaData)
       
   417     {
       
   418         cache[metaData.url().toEncoded()].first = metaData;
       
   419     }
       
   420 
       
   421     QIODevice *data(const QUrl &url)
       
   422     {
       
   423         CacheData::ConstIterator it = cache.find(url.toEncoded());
       
   424         if (it == cache.constEnd())
       
   425             return 0;
       
   426         QBuffer *io = new QBuffer(this);
       
   427         io->setData(it->second);
       
   428         io->open(QIODevice::ReadOnly);
       
   429         io->seek(0);
       
   430         return io;
       
   431     }
       
   432 
       
   433     bool remove(const QUrl &url)
       
   434     {
       
   435         cache.remove(url.toEncoded());
       
   436         return true;
       
   437     }
       
   438 
       
   439     qint64 cacheSize() const
       
   440     {
       
   441         qint64 total = 0;
       
   442         foreach (const CachedContent &entry, cache)
       
   443             total += entry.second.size();
       
   444         return total;
       
   445     }
       
   446 
       
   447     QIODevice *prepare(const QNetworkCacheMetaData &)
       
   448     { Q_ASSERT(0 && "Should not have tried to add to the cache"); return 0; }
       
   449     void insert(QIODevice *)
       
   450     { Q_ASSERT(0 && "Should not have tried to add to the cache"); }
       
   451 
       
   452     void clear() { cache.clear(); }
       
   453 };
       
   454 Q_DECLARE_METATYPE(MyMemoryCache::CachedContent)
       
   455 Q_DECLARE_METATYPE(MyMemoryCache::CacheData)
   381 
   456 
   382 class DataReader: public QObject
   457 class DataReader: public QObject
   383 {
   458 {
   384     Q_OBJECT
   459     Q_OBJECT
   385 public:
   460 public:
   760     QVERIFY(!file.exists() || file.remove());
   835     QVERIFY(!file.exists() || file.remove());
   761 
   836 
   762     // clear the internal cache
   837     // clear the internal cache
   763     QNetworkAccessManagerPrivate::clearCache(&manager);
   838     QNetworkAccessManagerPrivate::clearCache(&manager);
   764     manager.setProxy(QNetworkProxy());
   839     manager.setProxy(QNetworkProxy());
       
   840     manager.setCache(0);
   765 
   841 
   766     // clear cookies
   842     // clear cookies
   767     cookieJar->setAllCookies(QList<QNetworkCookie>());
   843     cookieJar->setAllCookies(QList<QNetworkCookie>());
   768 }
   844 }
   769 
   845 
   775 
   851 
   776     QVERIFY(reply.data());
   852     QVERIFY(reply.data());
   777     QVERIFY(reply->isOpen());
   853     QVERIFY(reply->isOpen());
   778     QVERIFY(reply->isReadable());
   854     QVERIFY(reply->isReadable());
   779     QVERIFY(!reply->isWritable());
   855     QVERIFY(!reply->isWritable());
   780     QCOMPARE(reply->errorString(), QString("Unknown error"));
   856 
       
   857     // both behaviours are OK since we might change underlying behaviour again
       
   858     if (!reply->isFinished())
       
   859         QCOMPARE(reply->errorString(), QString("Unknown error"));
       
   860     else
       
   861         QVERIFY(!reply->errorString().isEmpty());
       
   862 
   781 
   863 
   782     QCOMPARE(reply->manager(), &manager);
   864     QCOMPARE(reply->manager(), &manager);
   783     QCOMPARE(reply->request(), req);
   865     QCOMPARE(reply->request(), req);
   784     QCOMPARE(int(reply->operation()), int(QNetworkAccessManager::GetOperation));
   866     QCOMPARE(int(reply->operation()), int(QNetworkAccessManager::GetOperation));
   785     QCOMPARE(reply->error(), QNetworkReply::NoError);
   867     // error and not error are OK since we might change underlying behaviour again
   786     QCOMPARE(reply->isFinished(), false);
   868     if (!reply->isFinished())
       
   869         QCOMPARE(reply->error(), QNetworkReply::NoError);
   787     QCOMPARE(reply->url(), url);
   870     QCOMPARE(reply->url(), url);
   788 
   871 
   789     reply->abort();
   872     reply->abort();
   790 }
   873 }
   791 
   874 
  1088     QFETCH(QString, url);
  1171     QFETCH(QString, url);
  1089     QNetworkRequest request(url);
  1172     QNetworkRequest request(url);
  1090     QNetworkReplyPtr reply = manager.get(request);
  1173     QNetworkReplyPtr reply = manager.get(request);
  1091     reply->setParent(this);     // we have expect-fails
  1174     reply->setParent(this);     // we have expect-fails
  1092 
  1175 
  1093     QCOMPARE(reply->error(), QNetworkReply::NoError);
  1176     if (!reply->isFinished())
       
  1177         QCOMPARE(reply->error(), QNetworkReply::NoError);
  1094 
  1178 
  1095     // now run the request:
  1179     // now run the request:
  1096     connect(reply, SIGNAL(finished()),
  1180     connect(reply, SIGNAL(finished()),
  1097             &QTestEventLoop::instance(), SLOT(exitLoop()));
  1181             &QTestEventLoop::instance(), SLOT(exitLoop()));
  1098     QTestEventLoop::instance().enterLoop(10);
  1182     QTestEventLoop::instance().enterLoop(10);
  1449     file.flush();
  1533     file.flush();
  1450     QCOMPARE(file.size(), qint64(data.size()));
  1534     QCOMPARE(file.size(), qint64(data.size()));
  1451 
  1535 
  1452     QNetworkRequest request(QUrl::fromLocalFile(file.fileName()));
  1536     QNetworkRequest request(QUrl::fromLocalFile(file.fileName()));
  1453     QNetworkReplyPtr reply = manager.get(request);
  1537     QNetworkReplyPtr reply = manager.get(request);
       
  1538     QVERIFY(reply->isFinished()); // a file should immediatly be done
  1454     DataReader reader(reply);
  1539     DataReader reader(reply);
  1455 
  1540 
  1456     connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
  1541     connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
  1457     QTestEventLoop::instance().enterLoop(10);
  1542     QTestEventLoop::instance().enterLoop(10);
  1458     QVERIFY(!QTestEventLoop::instance().timeout());
  1543     QVERIFY(!QTestEventLoop::instance().timeout());
  1962     QTest::newRow("with-newlines3+disconnect") << QByteArray("ICY\r\nSecond line") << true;
  2047     QTest::newRow("with-newlines3+disconnect") << QByteArray("ICY\r\nSecond line") << true;
  1963 
  2048 
  1964     QTest::newRow("invalid-version+disconnect") << QByteArray("HTTP/123 200 ") << true;
  2049     QTest::newRow("invalid-version+disconnect") << QByteArray("HTTP/123 200 ") << true;
  1965     QTest::newRow("invalid-version2+disconnect") << QByteArray("HTTP/a.\033 200 ") << true;
  2050     QTest::newRow("invalid-version2+disconnect") << QByteArray("HTTP/a.\033 200 ") << true;
  1966     QTest::newRow("invalid-reply-code+disconnect") << QByteArray("HTTP/1.0 fuu ") << true;
  2051     QTest::newRow("invalid-reply-code+disconnect") << QByteArray("HTTP/1.0 fuu ") << true;
       
  2052 
       
  2053     QTest::newRow("immediate disconnect") << QByteArray("") << true;
       
  2054     QTest::newRow("justHalfStatus+disconnect") << QByteArray("HTTP/1.1") << true;
       
  2055     QTest::newRow("justStatus+disconnect") << QByteArray("HTTP/1.1 200 OK\r\n") << true;
       
  2056     QTest::newRow("justStatusAndHalfHeaders+disconnect") << QByteArray("HTTP/1.1 200 OK\r\nContent-L") << true;
  1967 }
  2057 }
  1968 
  2058 
  1969 void tst_QNetworkReply::ioGetFromHttpBrokenServer()
  2059 void tst_QNetworkReply::ioGetFromHttpBrokenServer()
  1970 {
  2060 {
  1971     QFETCH(QByteArray, dataToSend);
  2061     QFETCH(QByteArray, dataToSend);
  1980     QTestEventLoop::instance().enterLoop(10);
  2070     QTestEventLoop::instance().enterLoop(10);
  1981     QVERIFY(!QTestEventLoop::instance().timeout());
  2071     QVERIFY(!QTestEventLoop::instance().timeout());
  1982 
  2072 
  1983     QCOMPARE(reply->url(), request.url());
  2073     QCOMPARE(reply->url(), request.url());
  1984     QVERIFY(reply->error() != QNetworkReply::NoError);
  2074     QVERIFY(reply->error() != QNetworkReply::NoError);
       
  2075 }
       
  2076 
       
  2077 void tst_QNetworkReply::ioGetFromHttpWithCache_data()
       
  2078 {
       
  2079     qRegisterMetaType<MyMemoryCache::CachedContent>();
       
  2080     QTest::addColumn<QByteArray>("dataToSend");
       
  2081     QTest::addColumn<QString>("body");
       
  2082     QTest::addColumn<MyMemoryCache::CachedContent>("cachedReply");
       
  2083     QTest::addColumn<int>("cacheMode");
       
  2084     QTest::addColumn<bool>("loadedFromCache");
       
  2085     QTest::addColumn<bool>("networkUsed");
       
  2086 
       
  2087     QByteArray reply200 =
       
  2088             "HTTP/1.0 200\r\n"
       
  2089             "Connection: keep-alive\r\n"
       
  2090             "Content-Type: text/plain\r\n"
       
  2091             "Cache-control: no-cache\r\n"
       
  2092             "Content-length: 8\r\n"
       
  2093             "\r\n"
       
  2094             "Reloaded";
       
  2095     QByteArray reply304 =
       
  2096             "HTTP/1.0 304 Use Cache\r\n"
       
  2097             "Connection: keep-alive\r\n"
       
  2098             "\r\n";
       
  2099 
       
  2100     QTest::newRow("not-cached,always-network")
       
  2101             << reply200 << "Reloaded" << MyMemoryCache::CachedContent() << int(QNetworkRequest::AlwaysNetwork) << false << true;
       
  2102     QTest::newRow("not-cached,prefer-network")
       
  2103             << reply200 << "Reloaded" << MyMemoryCache::CachedContent() << int(QNetworkRequest::PreferNetwork) << false << true;
       
  2104     QTest::newRow("not-cached,prefer-cache")
       
  2105             << reply200 << "Reloaded" << MyMemoryCache::CachedContent() << int(QNetworkRequest::PreferCache) << false << true;
       
  2106 
       
  2107     QDateTime present = QDateTime::currentDateTime().toUTC();
       
  2108     QDateTime past = present.addSecs(-3600);
       
  2109     QDateTime future = present.addSecs(3600);
       
  2110     static const char dateFormat[] = "ddd, dd MMM yyyy hh:mm:ss 'GMT'";
       
  2111 
       
  2112     QNetworkCacheMetaData::RawHeaderList rawHeaders;
       
  2113     MyMemoryCache::CachedContent content;
       
  2114     content.second = "Not-reloaded";
       
  2115     content.first.setLastModified(past);
       
  2116 
       
  2117     //
       
  2118     // Set to expired
       
  2119     //
       
  2120     rawHeaders.clear();
       
  2121     rawHeaders << QNetworkCacheMetaData::RawHeader("Date", QLocale::c().toString(past, dateFormat).toLatin1())
       
  2122             << QNetworkCacheMetaData::RawHeader("Cache-control", "max-age=0"); // isn't used in cache loading
       
  2123     content.first.setRawHeaders(rawHeaders);
       
  2124     content.first.setLastModified(past);
       
  2125 
       
  2126     QTest::newRow("expired,200,prefer-network")
       
  2127             << reply200 << "Reloaded" << content << int(QNetworkRequest::PreferNetwork) << false << true;
       
  2128     QTest::newRow("expired,200,prefer-cache")
       
  2129             << reply200 << "Reloaded" << content << int(QNetworkRequest::PreferCache) << false << true;
       
  2130 
       
  2131     QTest::newRow("expired,304,prefer-network")
       
  2132             << reply304 << "Not-reloaded" << content << int(QNetworkRequest::PreferNetwork) << true << true;
       
  2133     QTest::newRow("expired,304,prefer-cache")
       
  2134             << reply304 << "Not-reloaded" << content << int(QNetworkRequest::PreferCache) << true << true;
       
  2135 
       
  2136     //
       
  2137     // Set to not-expired
       
  2138     //
       
  2139     rawHeaders.clear();
       
  2140     rawHeaders << QNetworkCacheMetaData::RawHeader("Date", QLocale::c().toString(past, dateFormat).toLatin1())
       
  2141             << QNetworkCacheMetaData::RawHeader("Cache-control", "max-age=7200"); // isn't used in cache loading
       
  2142     content.first.setRawHeaders(rawHeaders);
       
  2143     content.first.setExpirationDate(future);
       
  2144 
       
  2145     QTest::newRow("not-expired,200,always-network")
       
  2146             << reply200 << "Reloaded" << content << int(QNetworkRequest::AlwaysNetwork) << false << true;
       
  2147     QTest::newRow("not-expired,200,prefer-network")
       
  2148             << reply200 << "Not-reloaded" << content << int(QNetworkRequest::PreferNetwork) << true << false;
       
  2149     QTest::newRow("not-expired,200,prefer-cache")
       
  2150             << reply200 << "Not-reloaded" << content << int(QNetworkRequest::PreferCache) << true << false;
       
  2151     QTest::newRow("not-expired,200,always-cache")
       
  2152             << reply200 << "Not-reloaded" << content << int(QNetworkRequest::AlwaysCache) << true << false;
       
  2153 
       
  2154     QTest::newRow("not-expired,304,prefer-network")
       
  2155             << reply304 << "Not-reloaded" << content << int(QNetworkRequest::PreferNetwork) << true << false;
       
  2156     QTest::newRow("not-expired,304,prefer-cache")
       
  2157             << reply304 << "Not-reloaded" << content << int(QNetworkRequest::PreferCache) << true << false;
       
  2158     QTest::newRow("not-expired,304,always-cache")
       
  2159             << reply304 << "Not-reloaded" << content << int(QNetworkRequest::AlwaysCache) << true << false;
       
  2160 
       
  2161     //
       
  2162     // Set must-revalidate now
       
  2163     //
       
  2164     rawHeaders.clear();
       
  2165     rawHeaders << QNetworkCacheMetaData::RawHeader("Date", QLocale::c().toString(past, dateFormat).toLatin1())
       
  2166             << QNetworkCacheMetaData::RawHeader("Cache-control", "max-age=7200, must-revalidate"); // must-revalidate is used
       
  2167     content.first.setRawHeaders(rawHeaders);
       
  2168 
       
  2169     QTest::newRow("must-revalidate,200,always-network")
       
  2170             << reply200 << "Reloaded" << content << int(QNetworkRequest::AlwaysNetwork) << false << true;
       
  2171     QTest::newRow("must-revalidate,200,prefer-network")
       
  2172             << reply200 << "Reloaded" << content << int(QNetworkRequest::PreferNetwork) << false << true;
       
  2173     QTest::newRow("must-revalidate,200,prefer-cache")
       
  2174             << reply200 << "Not-reloaded" << content << int(QNetworkRequest::PreferCache) << true << false;
       
  2175     QTest::newRow("must-revalidate,200,always-cache")
       
  2176             << reply200 << "Not-reloaded" << content << int(QNetworkRequest::AlwaysCache) << true << false;
       
  2177 
       
  2178     QTest::newRow("must-revalidate,304,prefer-network")
       
  2179             << reply304 << "Not-reloaded" << content << int(QNetworkRequest::PreferNetwork) << true << true;
       
  2180     QTest::newRow("must-revalidate,304,prefer-cache")
       
  2181             << reply304 << "Not-reloaded" << content << int(QNetworkRequest::PreferCache) << true << false;
       
  2182     QTest::newRow("must-revalidate,304,always-cache")
       
  2183             << reply304 << "Not-reloaded" << content << int(QNetworkRequest::AlwaysCache) << true << false;
       
  2184 }
       
  2185 
       
  2186 void tst_QNetworkReply::ioGetFromHttpWithCache()
       
  2187 {
       
  2188     QFETCH(QByteArray, dataToSend);
       
  2189     MiniHttpServer server(dataToSend);
       
  2190     server.doClose = false;
       
  2191 
       
  2192     MyMemoryCache *memoryCache = new MyMemoryCache(&manager);
       
  2193     manager.setCache(memoryCache);
       
  2194 
       
  2195     QFETCH(MyMemoryCache::CachedContent, cachedReply);
       
  2196     QUrl url = "http://localhost:" + QString::number(server.serverPort());
       
  2197     cachedReply.first.setUrl(url);
       
  2198     if (!cachedReply.second.isNull())
       
  2199         memoryCache->cache.insert(url.toEncoded(), cachedReply);
       
  2200 
       
  2201     QFETCH(int, cacheMode);
       
  2202     QNetworkRequest request(url);
       
  2203     request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, cacheMode);
       
  2204     request.setAttribute(QNetworkRequest::CacheSaveControlAttribute, false);
       
  2205     QNetworkReplyPtr reply = manager.get(request);
       
  2206 
       
  2207     connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
       
  2208     QTestEventLoop::instance().enterLoop(10);
       
  2209     QVERIFY(!QTestEventLoop::instance().timeout());
       
  2210 
       
  2211     QTEST(reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool(), "loadedFromCache");
       
  2212     QTEST(server.totalConnections > 0, "networkUsed");
       
  2213     QFETCH(QString, body);
       
  2214     QCOMPARE(reply->readAll().constData(), qPrintable(body));
  1985 }
  2215 }
  1986 
  2216 
  1987 void tst_QNetworkReply::ioGetWithManyProxies_data()
  2217 void tst_QNetworkReply::ioGetWithManyProxies_data()
  1988 {
  2218 {
  1989     QTest::addColumn<QList<QNetworkProxy> >("proxyList");
  2219     QTest::addColumn<QList<QNetworkProxy> >("proxyList");
  2919 
  3149 
  2920     incomingSocket->close();
  3150     incomingSocket->close();
  2921     server.close();
  3151     server.close();
  2922 }
  3152 }
  2923 
  3153 
  2924 void tst_QNetworkReply::ioPostToHttpEmtpyUploadProgress()
  3154 void tst_QNetworkReply::ioPostToHttpEmptyUploadProgress()
  2925 {
  3155 {
  2926     QByteArray ba;
  3156     QByteArray ba;
  2927     ba.resize(0);
  3157     ba.resize(0);
  2928     QBuffer buffer(&ba,0);
  3158     QBuffer buffer(&ba,0);
  2929     QVERIFY(buffer.open(QIODevice::ReadOnly));
  3159     QVERIFY(buffer.open(QIODevice::ReadOnly));
  2967     server.close();
  3197     server.close();
  2968 }
  3198 }
  2969 
  3199 
  2970 void tst_QNetworkReply::lastModifiedHeaderForFile()
  3200 void tst_QNetworkReply::lastModifiedHeaderForFile()
  2971 {
  3201 {
  2972     QFileInfo fileInfo(SRCDIR "./bigfile");
  3202     QFileInfo fileInfo(SRCDIR "/bigfile");
       
  3203     QVERIFY(fileInfo.exists());
       
  3204 
  2973     QUrl url = QUrl::fromLocalFile(fileInfo.filePath());
  3205     QUrl url = QUrl::fromLocalFile(fileInfo.filePath());
  2974 
  3206 
  2975     QNetworkRequest request(url);
  3207     QNetworkRequest request(url);
  2976     QNetworkReplyPtr reply = manager.head(request);
  3208     QNetworkReplyPtr reply = manager.head(request);
  2977     QSignalSpy spy(reply, SIGNAL(uploadProgress(qint64,qint64)));
       
  2978     connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
  3209     connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
  2979     QTestEventLoop::instance().enterLoop(10);
  3210     QTestEventLoop::instance().enterLoop(10);
  2980     QVERIFY(!QTestEventLoop::instance().timeout());
  3211     QVERIFY(!QTestEventLoop::instance().timeout());
  2981 
  3212 
  2982     QDateTime header = reply->header(QNetworkRequest::LastModifiedHeader).toDateTime();
  3213     QDateTime header = reply->header(QNetworkRequest::LastModifiedHeader).toDateTime();
  2988     // Tue, 22 May 2007 12:04:57 GMT according to webserver
  3219     // Tue, 22 May 2007 12:04:57 GMT according to webserver
  2989     QUrl url = "http://" + QtNetworkSettings::serverName() + "/gif/fluke.gif";
  3220     QUrl url = "http://" + QtNetworkSettings::serverName() + "/gif/fluke.gif";
  2990 
  3221 
  2991     QNetworkRequest request(url);
  3222     QNetworkRequest request(url);
  2992     QNetworkReplyPtr reply = manager.head(request);
  3223     QNetworkReplyPtr reply = manager.head(request);
  2993     QSignalSpy spy(reply, SIGNAL(uploadProgress(qint64,qint64)));
       
  2994     connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
  3224     connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
  2995     QTestEventLoop::instance().enterLoop(10);
  3225     QTestEventLoop::instance().enterLoop(10);
  2996     QVERIFY(!QTestEventLoop::instance().timeout());
  3226     QVERIFY(!QTestEventLoop::instance().timeout());
  2997 
  3227 
  2998     QDateTime header = reply->header(QNetworkRequest::LastModifiedHeader).toDateTime();
  3228     QDateTime header = reply->header(QNetworkRequest::LastModifiedHeader).toDateTime();
  3571 #else
  3801 #else
  3572     QCOMPARE(pendingConnectionCount, 6);
  3802     QCOMPARE(pendingConnectionCount, 6);
  3573 #endif
  3803 #endif
  3574 }
  3804 }
  3575 
  3805 
       
  3806 void tst_QNetworkReply::httpReUsingConnectionSequential_data()
       
  3807 {
       
  3808     QTest::addColumn<bool>("doDeleteLater");
       
  3809     QTest::newRow("deleteLater") << true;
       
  3810     QTest::newRow("noDeleteLater") << false;
       
  3811 }
       
  3812 
       
  3813 void tst_QNetworkReply::httpReUsingConnectionSequential()
       
  3814 {
       
  3815     QFETCH(bool, doDeleteLater);
       
  3816 
       
  3817     QByteArray response("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
       
  3818     MiniHttpServer server(response);
       
  3819     server.multiple = true;
       
  3820     server.doClose = false;
       
  3821 
       
  3822     QUrl url;
       
  3823     url.setScheme("http");
       
  3824     url.setPort(server.serverPort());
       
  3825     url.setHost("127.0.0.1");
       
  3826     // first request
       
  3827     QNetworkReply* reply1 = manager.get(QNetworkRequest(url));
       
  3828     connect(reply1, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
       
  3829     QTestEventLoop::instance().enterLoop(2);
       
  3830     QVERIFY(!QTestEventLoop::instance().timeout());
       
  3831     QVERIFY(!reply1->error());
       
  3832     int reply1port = server.client->peerPort();
       
  3833 
       
  3834     if (doDeleteLater)
       
  3835         reply1->deleteLater();
       
  3836 
       
  3837     // finished received, send the next one
       
  3838     QNetworkReply*reply2 = manager.get(QNetworkRequest(url));
       
  3839     connect(reply2, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
       
  3840     QTestEventLoop::instance().enterLoop(2);
       
  3841     QVERIFY(!QTestEventLoop::instance().timeout());
       
  3842     QVERIFY(!reply2->error());
       
  3843     int reply2port = server.client->peerPort(); // should still be the same object
       
  3844 
       
  3845     QVERIFY(reply1port > 0);
       
  3846     QCOMPARE(server.totalConnections, 1);
       
  3847     QCOMPARE(reply2port, reply1port);
       
  3848 
       
  3849     if (!doDeleteLater)
       
  3850         reply1->deleteLater(); // only do it if it was not done earlier
       
  3851     reply2->deleteLater();
       
  3852 }
       
  3853 
       
  3854 class HttpReUsingConnectionFromFinishedSlot : public QObject {
       
  3855     Q_OBJECT;
       
  3856 public:
       
  3857     QNetworkReply* reply1;
       
  3858     QNetworkReply* reply2;
       
  3859     QUrl url;
       
  3860     QNetworkAccessManager manager;
       
  3861 public slots:
       
  3862     void finishedSlot() {
       
  3863         QVERIFY(!reply1->error());
       
  3864 
       
  3865         QFETCH(bool, doDeleteLater);
       
  3866         if (doDeleteLater) {
       
  3867             reply1->deleteLater();
       
  3868             reply1 = 0;
       
  3869         }
       
  3870 
       
  3871         // kick off 2nd request and exit the loop when it is done
       
  3872         reply2 = manager.get(QNetworkRequest(url));
       
  3873         reply2->setParent(this);
       
  3874         connect(reply2, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
       
  3875     }
       
  3876 };
       
  3877 
       
  3878 void tst_QNetworkReply::httpReUsingConnectionFromFinishedSlot_data()
       
  3879 {
       
  3880     httpReUsingConnectionSequential_data();
       
  3881 }
       
  3882 
       
  3883 void tst_QNetworkReply::httpReUsingConnectionFromFinishedSlot()
       
  3884 {
       
  3885     QByteArray response("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
       
  3886     MiniHttpServer server(response);
       
  3887     server.multiple = true;
       
  3888     server.doClose = false;
       
  3889 
       
  3890     HttpReUsingConnectionFromFinishedSlot helper;
       
  3891     helper.reply1 = 0;
       
  3892     helper.reply2 = 0;
       
  3893     helper.url.setScheme("http");
       
  3894     helper.url.setPort(server.serverPort());
       
  3895     helper.url.setHost("127.0.0.1");
       
  3896 
       
  3897     // first request
       
  3898     helper.reply1 = helper.manager.get(QNetworkRequest(helper.url));
       
  3899     helper.reply1->setParent(&helper);
       
  3900     connect(helper.reply1, SIGNAL(finished()), &helper, SLOT(finishedSlot()));
       
  3901     QTestEventLoop::instance().enterLoop(4);
       
  3902     QVERIFY(!QTestEventLoop::instance().timeout());
       
  3903 
       
  3904     QVERIFY(helper.reply2);
       
  3905     QVERIFY(!helper.reply2->error());
       
  3906 
       
  3907     QCOMPARE(server.totalConnections, 1);
       
  3908 }
       
  3909 
       
  3910 class HttpRecursiveCreationHelper : public QObject {
       
  3911     Q_OBJECT
       
  3912 public:
       
  3913 
       
  3914     HttpRecursiveCreationHelper():
       
  3915             QObject(0),
       
  3916             requestsStartedCount_finished(0),
       
  3917             requestsStartedCount_readyRead(0),
       
  3918             requestsFinishedCount(0)
       
  3919     {
       
  3920     }
       
  3921     QNetworkAccessManager manager;
       
  3922     int requestsStartedCount_finished;
       
  3923     int requestsStartedCount_readyRead;
       
  3924     int requestsFinishedCount;
       
  3925 public slots:
       
  3926     void finishedSlot() {
       
  3927         requestsFinishedCount++;
       
  3928 
       
  3929         QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
       
  3930         QVERIFY(!reply->error());
       
  3931         QVERIFY(reply->bytesAvailable() == 27906);
       
  3932 
       
  3933         if (requestsFinishedCount == 60) {
       
  3934             QTestEventLoop::instance().exitLoop();
       
  3935             return;
       
  3936         }
       
  3937 
       
  3938         if (requestsStartedCount_finished < 30) {
       
  3939             startOne();
       
  3940             requestsStartedCount_finished++;
       
  3941         }
       
  3942 
       
  3943         reply->deleteLater();
       
  3944     }
       
  3945     void readyReadSlot() {
       
  3946         QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
       
  3947         QVERIFY(!reply->error());
       
  3948 
       
  3949         if (requestsStartedCount_readyRead < 30 && reply->bytesAvailable() > 27906/2) {
       
  3950             startOne();
       
  3951             requestsStartedCount_readyRead++;
       
  3952         }
       
  3953     }
       
  3954     void startOne() {
       
  3955         QUrl url = "http://" + QtNetworkSettings::serverName() + "/gif/fluke.gif";
       
  3956         QNetworkRequest request(url);
       
  3957         QNetworkReply *reply = manager.get(request);
       
  3958         reply->setParent(this);
       
  3959         connect(reply, SIGNAL(finished()), this, SLOT(finishedSlot()));
       
  3960         connect(reply, SIGNAL(readyRead()), this, SLOT(readyReadSlot()));
       
  3961     }
       
  3962 };
       
  3963 
       
  3964 void tst_QNetworkReply::httpRecursiveCreation()
       
  3965 {
       
  3966     // this test checks if creation of new requests to the same host properly works
       
  3967     // from readyRead() and finished() signals
       
  3968     HttpRecursiveCreationHelper helper;
       
  3969     helper.startOne();
       
  3970     QTestEventLoop::instance().enterLoop(30);
       
  3971     QVERIFY(!QTestEventLoop::instance().timeout());
       
  3972 }
       
  3973 
  3576 #ifndef QT_NO_OPENSSL
  3974 #ifndef QT_NO_OPENSSL
  3577 void tst_QNetworkReply::ignoreSslErrorsList_data()
  3975 void tst_QNetworkReply::ignoreSslErrorsList_data()
  3578 {
  3976 {
  3579     QTest::addColumn<QString>("url");
  3977     QTest::addColumn<QString>("url");
  3580     QTest::addColumn<QList<QSslError> >("expectedSslErrors");
  3978     QTest::addColumn<QList<QSslError> >("expectedSslErrors");