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"); |