tests/auto/qnetworkreply/tst_qnetworkreply.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
child 7 f7bc934e204c
child 18 2f34d5167611
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
   223     void ioPostToHttpFromMiddleOfQBufferFiveBytes();
   223     void ioPostToHttpFromMiddleOfQBufferFiveBytes();
   224     void ioPostToHttpNoBufferFlag();
   224     void ioPostToHttpNoBufferFlag();
   225     void ioPostToHttpUploadProgress();
   225     void ioPostToHttpUploadProgress();
   226     void ioPostToHttpEmtpyUploadProgress();
   226     void ioPostToHttpEmtpyUploadProgress();
   227 
   227 
       
   228     void lastModifiedHeaderForFile();
       
   229     void lastModifiedHeaderForHttp();
       
   230 
   228     void rateControl_data();
   231     void rateControl_data();
   229     void rateControl();
   232     void rateControl();
   230     void downloadPerformance();
       
   231     void uploadPerformance();
       
   232     void performanceControlRate();
       
   233     void httpUploadPerformance();
       
   234     void httpDownloadPerformance_data();
       
   235     void httpDownloadPerformance();
       
   236 
   233 
   237     void downloadProgress_data();
   234     void downloadProgress_data();
   238     void downloadProgress();
   235     void downloadProgress();
   239     void uploadProgress_data();
   236     void uploadProgress_data();
   240     void uploadProgress();
   237     void uploadProgress();
   410 
   407 
   411         if (accumulate)
   408         if (accumulate)
   412             data += buffer;
   409             data += buffer;
   413     }
   410     }
   414 };
   411 };
   415 
       
   416 class FixedSizeDataGenerator : public QIODevice
       
   417 {
       
   418     Q_OBJECT
       
   419     enum { Idle, Started, Stopped } state;
       
   420 public:
       
   421     FixedSizeDataGenerator(qint64 size) : state(Idle)
       
   422     { open(ReadOnly | Unbuffered);
       
   423       toBeGeneratedTotalCount = toBeGeneratedCount = size;
       
   424     }
       
   425 
       
   426     virtual qint64 bytesAvailable() const
       
   427     {
       
   428         return state == Started ? toBeGeneratedCount + QIODevice::bytesAvailable() : 0;
       
   429     }
       
   430 
       
   431     virtual bool isSequential() const{
       
   432         return false;
       
   433     }
       
   434 
       
   435     virtual bool reset() const{
       
   436         return false;
       
   437     }
       
   438 
       
   439     qint64 size() const {
       
   440         return toBeGeneratedTotalCount;
       
   441     }
       
   442 
       
   443 public slots:
       
   444     void start() { state = Started; emit readyRead(); }
       
   445 
       
   446 protected:
       
   447     virtual qint64 readData(char *data, qint64 maxlen)
       
   448     {
       
   449         memset(data, '@', maxlen);
       
   450 
       
   451         if (toBeGeneratedCount <= 0) {
       
   452             return -1;
       
   453         }
       
   454 
       
   455         qint64 n = qMin(maxlen, toBeGeneratedCount);
       
   456         toBeGeneratedCount -= n;
       
   457 
       
   458         if (toBeGeneratedCount <= 0) {
       
   459             // make sure this is a queued connection!
       
   460             emit readChannelFinished();
       
   461         }
       
   462 
       
   463         return n;
       
   464     }
       
   465     virtual qint64 writeData(const char *, qint64)
       
   466     { return -1; }
       
   467 
       
   468     qint64 toBeGeneratedCount;
       
   469     qint64 toBeGeneratedTotalCount;
       
   470 };
       
   471 
       
   472 
       
   473 class DataGenerator: public QIODevice
       
   474 {
       
   475     Q_OBJECT
       
   476     enum { Idle, Started, Stopped } state;
       
   477 public:
       
   478     DataGenerator() : state(Idle)
       
   479     { open(ReadOnly); }
       
   480 
       
   481     virtual bool isSequential() const { return true; }
       
   482     virtual qint64 bytesAvailable() const { return state == Started ? 1024*1024 : 0; }
       
   483 
       
   484 public slots:
       
   485     void start() { state = Started; emit readyRead(); }
       
   486     void stop() { state = Stopped; emit readyRead(); }
       
   487 
       
   488 protected:
       
   489     virtual qint64 readData(char *data, qint64 maxlen)
       
   490     {
       
   491         if (state == Stopped)
       
   492             return -1;          // EOF
       
   493 
       
   494         // return as many bytes as are wanted
       
   495         memset(data, '@', maxlen);
       
   496         return maxlen;
       
   497     }
       
   498     virtual qint64 writeData(const char *, qint64)
       
   499     { return -1; }
       
   500 };
       
   501 
       
   502 
   412 
   503 
   413 
   504 class SocketPair: public QObject
   414 class SocketPair: public QObject
   505 {
   415 {
   506     Q_OBJECT
   416     Q_OBJECT
   687         } while (bytesRead < bytesToRead);// && stopWatch.elapsed() < interval/4);
   597         } while (bytesRead < bytesToRead);// && stopWatch.elapsed() < interval/4);
   688         totalBytesRead += bytesRead;
   598         totalBytesRead += bytesRead;
   689 
   599 
   690         if (bytesRead < bytesToRead)
   600         if (bytesRead < bytesToRead)
   691             qWarning() << bytesToRead - bytesRead << "bytes not read";
   601             qWarning() << bytesToRead - bytesRead << "bytes not read";
   692     }
       
   693 };
       
   694 
       
   695 class TimedSender: public QThread
       
   696 {
       
   697     Q_OBJECT
       
   698     qint64 totalBytes;
       
   699     QSemaphore ready;
       
   700     QByteArray dataToSend;
       
   701     QTcpSocket *client;
       
   702     int timeout;
       
   703     int port;
       
   704 public:
       
   705     int transferRate;
       
   706     TimedSender(int ms)
       
   707         : totalBytes(0), timeout(ms), port(-1), transferRate(-1)
       
   708     {
       
   709         dataToSend = QByteArray(16*1024, '@');
       
   710         start();
       
   711         ready.acquire();
       
   712     }
       
   713 
       
   714     inline int serverPort() const { return port; }
       
   715 
       
   716 private slots:
       
   717     void writeMore()
       
   718     {
       
   719         while (client->bytesToWrite() < 128 * 1024) {
       
   720             writePacket(dataToSend);
       
   721         }
       
   722     }
       
   723 
       
   724 protected:
       
   725     void run()
       
   726     {
       
   727         QTcpServer server;
       
   728         server.listen();
       
   729         port = server.serverPort();
       
   730         ready.release();
       
   731 
       
   732         server.waitForNewConnection(-1);
       
   733         client = server.nextPendingConnection();
       
   734 
       
   735         writeMore();
       
   736         connect(client, SIGNAL(bytesWritten(qint64)), SLOT(writeMore()), Qt::DirectConnection);
       
   737 
       
   738         QEventLoop eventLoop;
       
   739         QTimer::singleShot(timeout, &eventLoop, SLOT(quit()));
       
   740 
       
   741         QTime timer;
       
   742         timer.start();
       
   743         eventLoop.exec();
       
   744         disconnect(client, SIGNAL(bytesWritten(qint64)), this, 0);
       
   745 
       
   746         // wait for the connection to shut down
       
   747         client->disconnectFromHost();
       
   748         if (!client->waitForDisconnected(10000))
       
   749             return;
       
   750 
       
   751         transferRate = totalBytes * 1000 / timer.elapsed();
       
   752         qDebug() << "TimedSender::run" << "receive rate:" << (transferRate / 1024) << "kB/s in"
       
   753                  << timer.elapsed() << "ms";
       
   754     }
       
   755 
       
   756     void writePacket(const QByteArray &array)
       
   757     {
       
   758         client->write(array);
       
   759         totalBytes += array.size();
       
   760     }
       
   761 };
       
   762 
       
   763 class ThreadedDataReader: public QThread
       
   764 {
       
   765     Q_OBJECT
       
   766     // used to make the constructor only return after the tcp server started listening
       
   767     QSemaphore ready;
       
   768     QTcpSocket *client;
       
   769     int timeout;
       
   770     int port;
       
   771 public:
       
   772     qint64 transferRate;
       
   773     ThreadedDataReader()
       
   774         : port(-1), transferRate(-1)
       
   775     {
       
   776         start();
       
   777         ready.acquire();
       
   778     }
       
   779 
       
   780     inline int serverPort() const { return port; }
       
   781 
       
   782 protected:
       
   783     void run()
       
   784     {
       
   785         QTcpServer server;
       
   786         server.listen();
       
   787         port = server.serverPort();
       
   788         ready.release();
       
   789 
       
   790         server.waitForNewConnection(-1);
       
   791         client = server.nextPendingConnection();
       
   792 
       
   793         QEventLoop eventLoop;
       
   794         DataReader reader(client, false);
       
   795         QObject::connect(client, SIGNAL(disconnected()), &eventLoop, SLOT(quit()));
       
   796 
       
   797         QTime timer;
       
   798         timer.start();
       
   799         eventLoop.exec();
       
   800         qint64 elapsed = timer.elapsed();
       
   801 
       
   802         transferRate = reader.totalBytes * 1000 / elapsed;
       
   803         qDebug() << "ThreadedDataReader::run" << "send rate:" << (transferRate / 1024) << "kB/s in" << elapsed << "msec";
       
   804     }
       
   805 };
       
   806 
       
   807 class ThreadedDataReaderHttpServer: public QThread
       
   808 {
       
   809     Q_OBJECT
       
   810     // used to make the constructor only return after the tcp server started listening
       
   811     QSemaphore ready;
       
   812     QTcpSocket *client;
       
   813     int timeout;
       
   814     int port;
       
   815 public:
       
   816     qint64 transferRate;
       
   817     ThreadedDataReaderHttpServer()
       
   818         : port(-1), transferRate(-1)
       
   819     {
       
   820         start();
       
   821         ready.acquire();
       
   822     }
       
   823 
       
   824     inline int serverPort() const { return port; }
       
   825 
       
   826 protected:
       
   827     void run()
       
   828     {
       
   829         QTcpServer server;
       
   830         server.listen();
       
   831         port = server.serverPort();
       
   832         ready.release();
       
   833 
       
   834         server.waitForNewConnection(-1);
       
   835         client = server.nextPendingConnection();
       
   836         client->write("HTTP/1.0 200 OK\r\n");
       
   837         client->write("Content-length: 0\r\n");
       
   838         client->write("\r\n");
       
   839         client->flush();
       
   840 
       
   841         QCoreApplication::processEvents();
       
   842 
       
   843         QEventLoop eventLoop;
       
   844         DataReader reader(client, false);
       
   845         QObject::connect(client, SIGNAL(disconnected()), &eventLoop, SLOT(quit()));
       
   846 
       
   847         QTime timer;
       
   848         timer.start();
       
   849         eventLoop.exec();
       
   850         qint64 elapsed = timer.elapsed();
       
   851 
       
   852         transferRate = reader.totalBytes * 1000 / elapsed;
       
   853         qDebug() << "ThreadedDataReaderHttpServer::run" << "send rate:" << (transferRate / 1024) << "kB/s in" << elapsed << "msec";
       
   854     }
       
   855 };
       
   856 
       
   857 class HttpDownloadPerformanceClient : QObject {
       
   858     Q_OBJECT;
       
   859     QIODevice *device;
       
   860     public:
       
   861     HttpDownloadPerformanceClient (QIODevice *dev) : device(dev){
       
   862         connect(dev, SIGNAL(readyRead()), this, SLOT(readyReadSlot()));
       
   863     }
       
   864 
       
   865     public slots:
       
   866     void readyReadSlot() {
       
   867         device->readAll();
       
   868     }
       
   869 
       
   870 };
       
   871 
       
   872 class HttpDownloadPerformanceServer : QObject {
       
   873     Q_OBJECT;
       
   874     qint64 dataSize;
       
   875     qint64 dataSent;
       
   876     QTcpServer server;
       
   877     QTcpSocket *client;
       
   878     bool serverSendsContentLength;
       
   879     bool chunkedEncoding;
       
   880 
       
   881 public:
       
   882     HttpDownloadPerformanceServer (qint64 ds, bool sscl, bool ce) : dataSize(ds), dataSent(0),
       
   883     client(0), serverSendsContentLength(sscl), chunkedEncoding(ce) {
       
   884         server.listen();
       
   885         connect(&server, SIGNAL(newConnection()), this, SLOT(newConnectionSlot()));
       
   886     }
       
   887 
       
   888     int serverPort() {
       
   889         return server.serverPort();
       
   890     }
       
   891 
       
   892 public slots:
       
   893 
       
   894     void newConnectionSlot() {
       
   895         client = server.nextPendingConnection();
       
   896         client->setParent(this);
       
   897         connect(client, SIGNAL(readyRead()), this, SLOT(readyReadSlot()));
       
   898         connect(client, SIGNAL(bytesWritten(qint64)), this, SLOT(bytesWrittenSlot(qint64)));
       
   899     }
       
   900 
       
   901     void readyReadSlot() {
       
   902         client->readAll();
       
   903         client->write("HTTP/1.0 200 OK\n");
       
   904         if (serverSendsContentLength)
       
   905             client->write(QString("Content-Length: " + QString::number(dataSize) + "\n").toAscii());
       
   906         if (chunkedEncoding)
       
   907             client->write(QString("Transfer-Encoding: chunked\n").toAscii());
       
   908         client->write("Connection: close\n\n");
       
   909     }
       
   910 
       
   911     void bytesWrittenSlot(qint64 amount) {
       
   912         Q_UNUSED(amount);
       
   913         if (dataSent == dataSize && client) {
       
   914             // close eventually
       
   915 
       
   916             // chunked encoding: we have to send a last "empty" chunk
       
   917             if (chunkedEncoding)
       
   918                 client->write(QString("0\r\n\r\n").toAscii());
       
   919 
       
   920             client->disconnectFromHost();
       
   921             server.close();
       
   922             client = 0;
       
   923             return;
       
   924         }
       
   925 
       
   926         // send data
       
   927         if (client && client->bytesToWrite() < 100*1024 && dataSent < dataSize) {
       
   928             qint64 amount = qMin(qint64(16*1024), dataSize - dataSent);
       
   929             QByteArray data(amount, '@');
       
   930 
       
   931             if (chunkedEncoding) {
       
   932                 client->write(QString(QString("%1").arg(amount,0,16).toUpper() + "\r\n").toAscii());
       
   933                 client->write(data.constData(), amount);
       
   934                 client->write(QString("\r\n").toAscii());
       
   935             } else {
       
   936                 client->write(data.constData(), amount);
       
   937             }
       
   938 
       
   939             dataSent += amount;
       
   940         }
       
   941     }
   602     }
   942 };
   603 };
   943 
   604 
   944 
   605 
   945 tst_QNetworkReply::tst_QNetworkReply()
   606 tst_QNetworkReply::tst_QNetworkReply()
  2549     connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
  2210     connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
  2550 #ifndef QT_NO_OPENSSL
  2211 #ifndef QT_NO_OPENSSL
  2551     connect(&manager, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
  2212     connect(&manager, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
  2552             SLOT(sslErrors(QNetworkReply*,QList<QSslError>)));
  2213             SLOT(sslErrors(QNetworkReply*,QList<QSslError>)));
  2553 #endif
  2214 #endif
  2554     QTestEventLoop::instance().enterLoop(10);
  2215     QTestEventLoop::instance().enterLoop(15);
  2555     QVERIFY(!QTestEventLoop::instance().timeout());
  2216     QVERIFY(!QTestEventLoop::instance().timeout());
  2556 
  2217 
  2557     manager.disconnect(SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
  2218     manager.disconnect(SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
  2558                        this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
  2219                        this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
  2559 #ifndef QT_NO_OPENSSL
  2220 #ifndef QT_NO_OPENSSL
  2959             SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*)));
  2620             SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*)));
  2960 
  2621 
  2961     QSignalSpy authenticationRequiredSpy(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)));
  2622     QSignalSpy authenticationRequiredSpy(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)));
  2962     QSignalSpy proxyAuthenticationRequiredSpy(&manager, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
  2623     QSignalSpy proxyAuthenticationRequiredSpy(&manager, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
  2963 
  2624 
  2964 #ifdef Q_OS_SYMBIAN
  2625     QTestEventLoop::instance().enterLoop(12);
  2965     QTestEventLoop::instance().enterLoop(6);
       
  2966 #else
       
  2967     QTestEventLoop::instance().enterLoop(3);
       
  2968 #endif
       
  2969 
       
  2970     disconnect(&manager, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
  2626     disconnect(&manager, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
  2971                this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
  2627                this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
  2972     disconnect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
  2628     disconnect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
  2973                this, SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*)));
  2629                this, SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*)));
  2974     QCOMPARE(reply->error(), QNetworkReply::NoError);
  2630     QCOMPARE(reply->error(), QNetworkReply::NoError);
  3309 
  2965 
  3310     incomingSocket->close();
  2966     incomingSocket->close();
  3311     server.close();
  2967     server.close();
  3312 }
  2968 }
  3313 
  2969 
       
  2970 void tst_QNetworkReply::lastModifiedHeaderForFile()
       
  2971 {
       
  2972     QFileInfo fileInfo(SRCDIR "./bigfile");
       
  2973     QUrl url = QUrl::fromLocalFile(fileInfo.filePath());
       
  2974 
       
  2975     QNetworkRequest request(url);
       
  2976     QNetworkReplyPtr reply = manager.head(request);
       
  2977     QSignalSpy spy(reply, SIGNAL(uploadProgress(qint64,qint64)));
       
  2978     connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
       
  2979     QTestEventLoop::instance().enterLoop(10);
       
  2980     QVERIFY(!QTestEventLoop::instance().timeout());
       
  2981 
       
  2982     QDateTime header = reply->header(QNetworkRequest::LastModifiedHeader).toDateTime();
       
  2983     QCOMPARE(header, fileInfo.lastModified());
       
  2984 }
       
  2985 
       
  2986 void tst_QNetworkReply::lastModifiedHeaderForHttp()
       
  2987 {
       
  2988     // Tue, 22 May 2007 12:04:57 GMT according to webserver
       
  2989     QUrl url = "http://" + QtNetworkSettings::serverName() + "/gif/fluke.gif";
       
  2990 
       
  2991     QNetworkRequest request(url);
       
  2992     QNetworkReplyPtr reply = manager.head(request);
       
  2993     QSignalSpy spy(reply, SIGNAL(uploadProgress(qint64,qint64)));
       
  2994     connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
       
  2995     QTestEventLoop::instance().enterLoop(10);
       
  2996     QVERIFY(!QTestEventLoop::instance().timeout());
       
  2997 
       
  2998     QDateTime header = reply->header(QNetworkRequest::LastModifiedHeader).toDateTime();
       
  2999     QDateTime realDate = QDateTime::fromString("2007-05-22T12:04:57", Qt::ISODate);
       
  3000     realDate.setTimeSpec(Qt::UTC);
       
  3001 
       
  3002     QCOMPARE(header, realDate);
       
  3003 }
  3314 
  3004 
  3315 void tst_QNetworkReply::rateControl_data()
  3005 void tst_QNetworkReply::rateControl_data()
  3316 {
  3006 {
  3317     QTest::addColumn<int>("rate");
  3007     QTest::addColumn<int>("rate");
  3318 
  3008 
  3361     QVERIFY(sender.transferRate != -1);
  3051     QVERIFY(sender.transferRate != -1);
  3362     int minRate = rate * 1024 * 9 / 10;
  3052     int minRate = rate * 1024 * 9 / 10;
  3363     int maxRate = rate * 1024 * 11 / 10;
  3053     int maxRate = rate * 1024 * 11 / 10;
  3364     QVERIFY(sender.transferRate >= minRate);
  3054     QVERIFY(sender.transferRate >= minRate);
  3365     QVERIFY(sender.transferRate <= maxRate);
  3055     QVERIFY(sender.transferRate <= maxRate);
  3366 }
       
  3367 
       
  3368 void tst_QNetworkReply::downloadPerformance()
       
  3369 {
       
  3370     // unlike the above function, this one tries to send as fast as possible
       
  3371     // and measures how fast it was.
       
  3372     TimedSender sender(5000);
       
  3373     QNetworkRequest request("debugpipe://127.0.0.1:" + QString::number(sender.serverPort()) + "/?bare=1");
       
  3374     QNetworkReplyPtr reply = manager.get(request);
       
  3375     DataReader reader(reply, false);
       
  3376 
       
  3377     QTime loopTime;
       
  3378     connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
       
  3379     loopTime.start();
       
  3380     QTestEventLoop::instance().enterLoop(40);
       
  3381     int elapsedTime = loopTime.elapsed();
       
  3382     sender.wait();
       
  3383 
       
  3384     qint64 receivedBytes = reader.totalBytes;
       
  3385     qDebug() << "tst_QNetworkReply::downloadPerformance" << "receive rate:" << (receivedBytes * 1000 / elapsedTime / 1024) << "kB/s and"
       
  3386              << elapsedTime << "ms";
       
  3387 }
       
  3388 
       
  3389 void tst_QNetworkReply::uploadPerformance()
       
  3390 {
       
  3391       ThreadedDataReader reader;
       
  3392       DataGenerator generator;
       
  3393 
       
  3394 
       
  3395       QNetworkRequest request("debugpipe://127.0.0.1:" + QString::number(reader.serverPort()) + "/?bare=1");
       
  3396       QNetworkReplyPtr reply = manager.put(request, &generator);
       
  3397       generator.start();
       
  3398       connect(&reader, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
       
  3399       QTimer::singleShot(5000, &generator, SLOT(stop()));
       
  3400 
       
  3401       QTestEventLoop::instance().enterLoop(30);
       
  3402       QCOMPARE(reply->error(), QNetworkReply::NoError);
       
  3403       QVERIFY(!QTestEventLoop::instance().timeout());
       
  3404 }
       
  3405 
       
  3406 void tst_QNetworkReply::httpUploadPerformance()
       
  3407 {
       
  3408 #ifdef Q_OS_SYMBIAN
       
  3409       // SHow some mercy for non-desktop platform/s
       
  3410       enum {UploadSize = 4*1024*1024}; // 4 MB
       
  3411 #else
       
  3412       enum {UploadSize = 128*1024*1024}; // 128 MB
       
  3413 #endif
       
  3414       ThreadedDataReaderHttpServer reader;
       
  3415       FixedSizeDataGenerator generator(UploadSize);
       
  3416 
       
  3417       QNetworkRequest request(QUrl("http://127.0.0.1:" + QString::number(reader.serverPort()) + "/?bare=1"));
       
  3418       request.setHeader(QNetworkRequest::ContentLengthHeader,UploadSize);
       
  3419 
       
  3420       QNetworkReplyPtr reply = manager.put(request, &generator);
       
  3421 
       
  3422       connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
       
  3423 
       
  3424       QTime time;
       
  3425       generator.start();
       
  3426       time.start();
       
  3427       QTestEventLoop::instance().enterLoop(40);
       
  3428       QCOMPARE(reply->error(), QNetworkReply::NoError);
       
  3429       QVERIFY(!QTestEventLoop::instance().timeout());
       
  3430 
       
  3431       qint64 elapsed = time.elapsed();
       
  3432       qDebug() << "tst_QNetworkReply::httpUploadPerformance" << elapsed << "msec, "
       
  3433               << ((UploadSize/1024.0)/(elapsed/1000.0)) << " kB/sec";
       
  3434 
       
  3435       reader.exit();
       
  3436       reader.wait();
       
  3437 }
       
  3438 
       
  3439 
       
  3440 void tst_QNetworkReply::performanceControlRate()
       
  3441 {
       
  3442     // this is a control comparison for the other two above
       
  3443     // it does the same thing, but instead bypasses the QNetworkAccess system
       
  3444     qDebug() << "The following are the maximum transfer rates that we can get in this system"
       
  3445         " (bypassing QNetworkAccess)";
       
  3446 
       
  3447     TimedSender sender(5000);
       
  3448     QTcpSocket sink;
       
  3449     sink.connectToHost("127.0.0.1", sender.serverPort());
       
  3450     DataReader reader(&sink, false);
       
  3451 
       
  3452     QTime loopTime;
       
  3453     connect(&sink, SIGNAL(disconnected()), &QTestEventLoop::instance(), SLOT(exitLoop()));
       
  3454     loopTime.start();
       
  3455     QTestEventLoop::instance().enterLoop(40);
       
  3456     int elapsedTime = loopTime.elapsed();
       
  3457     sender.wait();
       
  3458 
       
  3459     qint64 receivedBytes = reader.totalBytes;
       
  3460     qDebug() << "tst_QNetworkReply::performanceControlRate" << "receive rate:" << (receivedBytes * 1000 / elapsedTime / 1024) << "kB/s and"
       
  3461              << elapsedTime << "ms";
       
  3462 }
       
  3463 
       
  3464 void tst_QNetworkReply::httpDownloadPerformance_data()
       
  3465 {
       
  3466     QTest::addColumn<bool>("serverSendsContentLength");
       
  3467     QTest::addColumn<bool>("chunkedEncoding");
       
  3468 
       
  3469     QTest::newRow("Server sends no Content-Length") << false << false;
       
  3470     QTest::newRow("Server sends Content-Length")     << true << false;
       
  3471     QTest::newRow("Server uses chunked encoding")     << false << true;
       
  3472 
       
  3473 }
       
  3474 
       
  3475 void tst_QNetworkReply::httpDownloadPerformance()
       
  3476 {
       
  3477     QFETCH(bool, serverSendsContentLength);
       
  3478     QFETCH(bool, chunkedEncoding);
       
  3479 #ifdef Q_OS_SYMBIAN
       
  3480     // Show some mercy to non-desktop platform/s
       
  3481     enum {UploadSize = 4*1024*1024}; // 4 MB
       
  3482 #else
       
  3483     enum {UploadSize = 128*1024*1024}; // 128 MB
       
  3484 #endif
       
  3485     HttpDownloadPerformanceServer server(UploadSize, serverSendsContentLength, chunkedEncoding);
       
  3486 
       
  3487     QNetworkRequest request(QUrl("http://127.0.0.1:" + QString::number(server.serverPort()) + "/?bare=1"));
       
  3488     QNetworkReplyPtr reply = manager.get(request);
       
  3489 
       
  3490     connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection);
       
  3491     HttpDownloadPerformanceClient client(reply);
       
  3492 
       
  3493     QTime time;
       
  3494     time.start();
       
  3495     QTestEventLoop::instance().enterLoop(40);
       
  3496     QCOMPARE(reply->error(), QNetworkReply::NoError);
       
  3497     QVERIFY(!QTestEventLoop::instance().timeout());
       
  3498 
       
  3499     qint64 elapsed = time.elapsed();
       
  3500     qDebug() << "tst_QNetworkReply::httpDownloadPerformance" << elapsed << "msec, "
       
  3501             << ((UploadSize/1024.0)/(elapsed/1000.0)) << " kB/sec";
       
  3502 }
  3056 }
  3503 
  3057 
  3504 void tst_QNetworkReply::downloadProgress_data()
  3058 void tst_QNetworkReply::downloadProgress_data()
  3505 {
  3059 {
  3506     QTest::addColumn<int>("loopCount");
  3060     QTest::addColumn<int>("loopCount");
  3685     header.clear();
  3239     header.clear();
  3686     jar.clear();
  3240     jar.clear();
  3687     cookie = QNetworkCookie("a", "b");
  3241     cookie = QNetworkCookie("a", "b");
  3688     cookie.setPath("/not/part-of-path");
  3242     cookie.setPath("/not/part-of-path");
  3689     header << cookie;
  3243     header << cookie;
       
  3244     cookie.setDomain(QtNetworkSettings::serverName());
       
  3245     jar << cookie;
  3690     QTest::newRow("invalid-cookie-path") << "a=b; path=/not/part-of-path" << header << jar;
  3246     QTest::newRow("invalid-cookie-path") << "a=b; path=/not/part-of-path" << header << jar;
  3691 
  3247 
       
  3248     jar.clear();
  3692     cookie = QNetworkCookie("a", "b");
  3249     cookie = QNetworkCookie("a", "b");
  3693     cookie.setDomain(".example.com");
  3250     cookie.setDomain(".example.com");
  3694     header.clear();
  3251     header.clear();
  3695     header << cookie;
  3252     header << cookie;
  3696     QTest::newRow("invalid-cookie-domain") << "a=b; domain=.example.com" << header << jar;
  3253     QTest::newRow("invalid-cookie-domain") << "a=b; domain=.example.com" << header << jar;