diff options
author | Qt Continuous Integration System <qt-info@nokia.com> | 2010-11-25 17:00:40 (GMT) |
---|---|---|
committer | Qt Continuous Integration System <qt-info@nokia.com> | 2010-11-25 17:00:40 (GMT) |
commit | 4ab8b588256cfd12c32e166cf15d4ede050222fb (patch) | |
tree | 0f4417221e7634c99ffc12a3b4f75672e7e56dc7 /tests | |
parent | 482437316b5deb6ff10577283016fb713cf92efc (diff) | |
parent | 062e4383c3b8c7c93e62ad564c47826369aa8a33 (diff) | |
download | Qt-4ab8b588256cfd12c32e166cf15d4ede050222fb.zip Qt-4ab8b588256cfd12c32e166cf15d4ede050222fb.tar.gz Qt-4ab8b588256cfd12c32e166cf15d4ede050222fb.tar.bz2 |
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-1 into 4.7-integration
* '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-1:
Fix a missing error-signal when a server is shut down while downloading
Ensure that if this is does not have a valid filter when on XP or less
HTTP backend: fix build without Qt3 support
QNetworkAccessManager: enable synchronous HTTP calls
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/qabstractnetworkcache/tst_qabstractnetworkcache.cpp | 111 | ||||
-rw-r--r-- | tests/auto/qnetworkreply/tst_qnetworkreply.cpp | 506 |
2 files changed, 590 insertions, 27 deletions
diff --git a/tests/auto/qabstractnetworkcache/tst_qabstractnetworkcache.cpp b/tests/auto/qabstractnetworkcache/tst_qabstractnetworkcache.cpp index 04bd432..fc8a126 100644 --- a/tests/auto/qabstractnetworkcache/tst_qabstractnetworkcache.cpp +++ b/tests/auto/qabstractnetworkcache/tst_qabstractnetworkcache.cpp @@ -58,20 +58,29 @@ public: private slots: void expires_data(); void expires(); + void expiresSynchronous_data(); + void expiresSynchronous(); void lastModified_data(); void lastModified(); + void lastModifiedSynchronous_data(); + void lastModifiedSynchronous(); void etag_data(); void etag(); + void etagSynchronous_data(); + void etagSynchronous(); void cacheControl_data(); void cacheControl(); + void cacheControlSynchronous_data(); + void cacheControlSynchronous(); void deleteCache(); private: void check(); + void checkSynchronous(); }; class NetworkDiskCache : public QNetworkDiskCache @@ -142,6 +151,16 @@ void tst_QAbstractNetworkCache::expires() check(); } +void tst_QAbstractNetworkCache::expiresSynchronous_data() +{ + expires_data(); +} + +void tst_QAbstractNetworkCache::expiresSynchronous() +{ + checkSynchronous(); +} + void tst_QAbstractNetworkCache::lastModified_data() { QTest::addColumn<QNetworkRequest::CacheLoadControl>("cacheLoadControl"); @@ -164,6 +183,16 @@ void tst_QAbstractNetworkCache::lastModified() check(); } +void tst_QAbstractNetworkCache::lastModifiedSynchronous_data() +{ + tst_QAbstractNetworkCache::lastModified_data(); +} + +void tst_QAbstractNetworkCache::lastModifiedSynchronous() +{ + checkSynchronous(); +} + void tst_QAbstractNetworkCache::etag_data() { QTest::addColumn<QNetworkRequest::CacheLoadControl>("cacheLoadControl"); @@ -186,6 +215,16 @@ void tst_QAbstractNetworkCache::etag() check(); } +void tst_QAbstractNetworkCache::etagSynchronous_data() +{ + tst_QAbstractNetworkCache::etag_data(); +} + +void tst_QAbstractNetworkCache::etagSynchronous() +{ + checkSynchronous(); +} + void tst_QAbstractNetworkCache::cacheControl_data() { QTest::addColumn<QNetworkRequest::CacheLoadControl>("cacheLoadControl"); @@ -217,6 +256,16 @@ void tst_QAbstractNetworkCache::cacheControl() check(); } +void tst_QAbstractNetworkCache::cacheControlSynchronous_data() +{ + tst_QAbstractNetworkCache::cacheControl_data(); +} + +void tst_QAbstractNetworkCache::cacheControlSynchronous() +{ + checkSynchronous(); +} + void tst_QAbstractNetworkCache::check() { QFETCH(QNetworkRequest::CacheLoadControl, cacheLoadControl); @@ -250,8 +299,6 @@ void tst_QAbstractNetworkCache::check() QCOMPARE(reply2->error(), QNetworkReply::ContentNotFoundError); QCOMPARE(secondData, QByteArray()); } else { - if (reply2->error() != QNetworkReply::NoError) - qDebug() << reply2->errorString(); QCOMPARE(reply2->error(), QNetworkReply::NoError); QCOMPARE(QString(secondData), QString(goodData)); QCOMPARE(secondData, goodData); @@ -263,16 +310,60 @@ void tst_QAbstractNetworkCache::check() QList<QByteArray> rawHeaderList2 = reply2->rawHeaderList(); qSort(rawHeaderList); qSort(rawHeaderList2); + } + QCOMPARE(diskCache->gotData, fetchFromCache); +} - // headers can change - for (int i = 0; i < rawHeaderList.count(); ++i) { - //qDebug() << i << rawHeaderList.value(i) << reply->rawHeader(rawHeaderList.value(i)); - //qDebug() << i << rawHeaderList2.value(i) << reply2->rawHeader(rawHeaderList2.value(i)); - //QCOMPARE(QString(rawHeaderList.value(i)), QString(rawHeaderList2.value(i))); - //QCOMPARE(QString(reply->rawHeader(rawHeaderList.value(i))), QString(reply2->rawHeader(rawHeaderList2.value(i)))); - } - //QCOMPARE(rawHeaderList.count(), rawHeaderList2.count()); +void tst_QAbstractNetworkCache::checkSynchronous() +{ + QSKIP("not working yet, see QTBUG-15221", SkipAll); + QFETCH(QNetworkRequest::CacheLoadControl, cacheLoadControl); + QFETCH(QString, url); + QFETCH(bool, fetchFromCache); + + QNetworkAccessManager manager; + NetworkDiskCache *diskCache = new NetworkDiskCache(&manager); + manager.setCache(diskCache); + QCOMPARE(diskCache->gotData, false); + + QUrl realUrl = url.contains("://") ? url : TESTFILE + url; + QNetworkRequest request(realUrl); + + request.setAttribute( + static_cast<QNetworkRequest::Attribute>(QNetworkRequest::DownloadBufferAttribute + 1), + true); + + // prime the cache + QNetworkReply *reply = manager.get(request); + QVERIFY(reply->isFinished()); // synchronous + QCOMPARE(diskCache->gotData, false); + QByteArray goodData = reply->readAll(); + + request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, cacheLoadControl); + + // should be in the cache now + QNetworkReply *reply2 = manager.get(request); + QVERIFY(reply2->isFinished()); // synchronous + + QByteArray secondData = reply2->readAll(); + if (!fetchFromCache && cacheLoadControl == QNetworkRequest::AlwaysCache) { + QCOMPARE(reply2->error(), QNetworkReply::ContentNotFoundError); + QCOMPARE(secondData, QByteArray()); + } else { + if (reply2->error() != QNetworkReply::NoError) + qDebug() << reply2->errorString(); + QCOMPARE(reply2->error(), QNetworkReply::NoError); + QCOMPARE(QString(secondData), QString(goodData)); + QCOMPARE(secondData, goodData); + QCOMPARE(reply2->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); + } + + if (fetchFromCache) { + QList<QByteArray> rawHeaderList = reply->rawHeaderList(); + QList<QByteArray> rawHeaderList2 = reply2->rawHeaderList(); + qSort(rawHeaderList); + qSort(rawHeaderList2); } QCOMPARE(diskCache->gotData, fetchFromCache); } diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp index ddb7687..90416f2 100644 --- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp @@ -75,7 +75,6 @@ #include "../network-settings.h" - Q_DECLARE_METATYPE(QNetworkReply*) Q_DECLARE_METATYPE(QAuthenticator*) Q_DECLARE_METATYPE(QNetworkProxy) @@ -84,6 +83,8 @@ Q_DECLARE_METATYPE(QList<QNetworkProxy>) Q_DECLARE_METATYPE(QNetworkReply::NetworkError) Q_DECLARE_METATYPE(QBuffer*) +const int SynchronousRequestAttribute = QNetworkRequest::DownloadBufferAttribute + 1; + class QNetworkReplyPtr: public QSharedPointer<QNetworkReply> { public: @@ -108,6 +109,16 @@ class tst_QNetworkReply: public QObject bool requiresAuthentication; }; + static bool seedCreated; + static QString createUniqueExtension() { + if (!seedCreated) { + qsrand(QTime(0,0,0).msecsTo(QTime::currentTime()) + QCoreApplication::applicationPid()); + seedCreated = true; // not thread-safe, but who cares + } + QString s = QString("%1-%2-%3").arg(QTime(0,0,0).msecsTo(QTime::currentTime())).arg(QCoreApplication::applicationPid()).arg(qrand()); + return s; + }; + QEventLoop *loop; enum RunSimpleRequestReturn { Timeout = 0, Success, Failure }; int returnCode; @@ -173,8 +184,12 @@ private Q_SLOTS: void putToFtp(); void putToHttp_data(); void putToHttp(); + void putToHttpSynchronous_data(); + void putToHttpSynchronous(); void postToHttp_data(); void postToHttp(); + void postToHttpSynchronous_data(); + void postToHttpSynchronous(); void deleteFromHttp_data(); void deleteFromHttp(); void putGetDeleteGetFromHttp_data(); @@ -198,7 +213,9 @@ private Q_SLOTS: void ioGetFromHttpWithReuseParallel(); void ioGetFromHttpWithReuseSequential(); void ioGetFromHttpWithAuth(); + void ioGetFromHttpWithAuthSynchronous(); void ioGetFromHttpWithProxyAuth(); + void ioGetFromHttpWithProxyAuthSynchronous(); void ioGetFromHttpWithSocksProxy(); #ifndef QT_NO_OPENSSL void ioGetFromHttpsWithSslErrors(); @@ -233,6 +250,8 @@ private Q_SLOTS: void ioPostToHttpFromFile(); void ioPostToHttpFromSocket_data(); void ioPostToHttpFromSocket(); + void ioPostToHttpFromSocketSynchronous(); + void ioPostToHttpFromSocketSynchronous_data(); void ioPostToHttpFromMiddleOfFileToEnd(); void ioPostToHttpFromMiddleOfFileFiveBytes(); void ioPostToHttpFromMiddleOfQBufferFiveBytes(); @@ -258,13 +277,19 @@ private Q_SLOTS: void receiveCookiesFromHttp_data(); void receiveCookiesFromHttp(); + void receiveCookiesFromHttpSynchronous_data(); + void receiveCookiesFromHttpSynchronous(); void sendCookies_data(); void sendCookies(); + void sendCookiesSynchronous_data(); + void sendCookiesSynchronous(); void nestedEventLoops(); void httpProxyCommands_data(); void httpProxyCommands(); + void httpProxyCommandsSynchronous_data(); + void httpProxyCommandsSynchronous(); void proxyChange(); void authorizationError_data(); void authorizationError(); @@ -303,12 +328,18 @@ private Q_SLOTS: void qtbug15311doubleContentLength(); + void synchronousRequest_data(); + void synchronousRequest(); + void synchronousRequestSslFailure(); + // NOTE: This test must be last! void parentingRepliesToTheApp(); }; QT_BEGIN_NAMESPACE +bool tst_QNetworkReply::seedCreated = false; + namespace QTest { template<> char *toString(const QNetworkReply::NetworkError& code) @@ -915,14 +946,15 @@ protected: tst_QNetworkReply::tst_QNetworkReply() { + qRegisterMetaType<QNetworkReply *>(); // for QSignalSpy + qRegisterMetaType<QAuthenticator *>(); + qRegisterMetaType<QNetworkProxy>(); + qRegisterMetaType<QList<QSslError> >(); + Q_SET_DEFAULT_IAP testFileName = QDir::currentPath() + "/testfile"; -#ifndef Q_OS_WINCE - uniqueExtension = QString("%1%2%3").arg((qulonglong)this).arg(rand()).arg((qulonglong)time(0)); -#else - uniqueExtension = QString("%1%2").arg((qulonglong)this).arg(rand()); -#endif + uniqueExtension = createUniqueExtension(); cookieJar = new MyCookieJar; manager.setCookieJar(cookieJar); @@ -1009,15 +1041,25 @@ QString tst_QNetworkReply::runSimpleRequest(QNetworkAccessManager::Operation op, Q_ASSERT_X(false, "tst_QNetworkReply", "Invalid/unknown operation requested"); } reply->setParent(this); - connect(reply, SIGNAL(finished()), SLOT(finished())); - connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(gotError())); returnCode = Timeout; - loop = new QEventLoop; - QTimer::singleShot(20000, loop, SLOT(quit())); - int code = returnCode == Timeout ? loop->exec() : returnCode; - delete loop; - loop = 0; + int code = Success; + + if (request.attribute(static_cast<QNetworkRequest::Attribute>(SynchronousRequestAttribute)).toBool()) { + if (reply->isFinished()) + code = reply->error() != QNetworkReply::NoError ? Failure : Success; + else + code = Failure; + } else { + connect(reply, SIGNAL(finished()), SLOT(finished())); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(gotError())); + + loop = new QEventLoop; + QTimer::singleShot(20000, loop, SLOT(quit())); + code = returnCode == Timeout ? loop->exec() : returnCode; + delete loop; + loop = 0; + } switch (code) { case Failure: @@ -1492,6 +1534,9 @@ void tst_QNetworkReply::putToFile_data() data = QByteArray(128*1024+1, '\177'); QTest::newRow("128k+1") << data << md5sum(data); + + data = QByteArray(2*1024*1024+1, '\177'); + QTest::newRow("2MB+1") << data << md5sum(data); } void tst_QNetworkReply::putToFile() @@ -1598,6 +1643,47 @@ void tst_QNetworkReply::putToHttp() QCOMPARE(uploadedData, data); } +void tst_QNetworkReply::putToHttpSynchronous_data() +{ + uniqueExtension = createUniqueExtension(); + putToFile_data(); +} + +void tst_QNetworkReply::putToHttpSynchronous() +{ + QUrl url("http://" + QtNetworkSettings::serverName()); + url.setPath(QString("/dav/qnetworkaccess-putToHttp-%1-%2") + .arg(QTest::currentDataTag()) + .arg(uniqueExtension)); + + QNetworkRequest request(url); + QNetworkReplyPtr reply; + + QFETCH(QByteArray, data); + + request.setAttribute( + static_cast<QNetworkRequest::Attribute>(SynchronousRequestAttribute), + true); + + RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::PutOperation, request, reply, data)); + + QCOMPARE(reply->url(), url); + QCOMPARE(reply->error(), QNetworkReply::NoError); + + QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 201); // 201 Created + + // download the file again from HTTP to make sure it was uploaded + // correctly. HTTP/0.9 is enough + QTcpSocket socket; + socket.connectToHost(QtNetworkSettings::serverName(), 80); + socket.write("GET " + url.toEncoded(QUrl::RemoveScheme | QUrl::RemoveAuthority) + "\r\n"); + if (!socket.waitForDisconnected(10000)) + QFAIL("Network timeout"); + + QByteArray uploadedData = socket.readAll(); + QCOMPARE(uploadedData, data); +} + void tst_QNetworkReply::postToHttp_data() { putToFile_data(); @@ -1624,6 +1710,37 @@ void tst_QNetworkReply::postToHttp() QCOMPARE(uploadedData, md5sum.toHex()); } +void tst_QNetworkReply::postToHttpSynchronous_data() +{ + putToFile_data(); +} + +void tst_QNetworkReply::postToHttpSynchronous() +{ + QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi"); + + QNetworkRequest request(url); + + request.setAttribute( + static_cast<QNetworkRequest::Attribute>(SynchronousRequestAttribute), + true); + + QNetworkReplyPtr reply; + + QFETCH(QByteArray, data); + + RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::PostOperation, request, reply, data)); + + QCOMPARE(reply->url(), url); + QCOMPARE(reply->error(), QNetworkReply::NoError); + + QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // 200 Ok + + QFETCH(QByteArray, md5sum); + QByteArray uploadedData = reply->readAll().trimmed(); + QCOMPARE(uploadedData, md5sum.toHex()); +} + void tst_QNetworkReply::deleteFromHttp_data() { QTest::addColumn<QUrl>("url"); @@ -2048,9 +2165,6 @@ void tst_QNetworkReply::ioGetFromHttpWithReuseSequential() void tst_QNetworkReply::ioGetFromHttpWithAuth() { - qRegisterMetaType<QNetworkReply *>(); // for QSignalSpy - qRegisterMetaType<QAuthenticator *>(); - // This test sends three requests // The first two in parallel // The third after the first two finished @@ -2109,6 +2223,44 @@ void tst_QNetworkReply::ioGetFromHttpWithAuth() QCOMPARE(authspy.count(), 0); } + + // now check with synchronous calls: + reference.seek(0); + { + request.setAttribute( + static_cast<QNetworkRequest::Attribute>(SynchronousRequestAttribute), + true); + + QSignalSpy authspy(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*))); + QNetworkReplyPtr replySync = manager.get(request); + QVERIFY(replySync->isFinished()); // synchronous + QCOMPARE(authspy.count(), 0); + + // we cannot use a data reader here, since that connects to the readyRead signal, + // just use readAll() + + // the only thing we check here is that the auth cache was used when using synchronous requests + QCOMPARE(replySync->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); + QCOMPARE(replySync->readAll(), reference.readAll()); + } +} + +void tst_QNetworkReply::ioGetFromHttpWithAuthSynchronous() +{ + // verify that we do not enter an endless loop with synchronous calls and wrong credentials + // the case when we succed with the login is tested in ioGetFromHttpWithAuth() + + QNetworkRequest request(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfcs-auth/rfc3252.txt")); + request.setAttribute( + static_cast<QNetworkRequest::Attribute>(SynchronousRequestAttribute), + true); + + QSignalSpy authspy(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*))); + QNetworkReplyPtr replySync = manager.get(request); + QVERIFY(replySync->isFinished()); // synchronous + QCOMPARE(replySync->error(), QNetworkReply::AuthenticationRequiredError); + QCOMPARE(authspy.count(), 0); + QCOMPARE(replySync->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 401); } void tst_QNetworkReply::ioGetFromHttpWithProxyAuth() @@ -2180,6 +2332,47 @@ void tst_QNetworkReply::ioGetFromHttpWithProxyAuth() QCOMPARE(authspy.count(), 0); } + + // now check with synchronous calls: + reference.seek(0); + { + request.setAttribute( + static_cast<QNetworkRequest::Attribute>(SynchronousRequestAttribute), + true); + + QSignalSpy authspy(&manager, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*))); + QNetworkReplyPtr replySync = manager.get(request); + QVERIFY(replySync->isFinished()); // synchronous + QCOMPARE(authspy.count(), 0); + + // we cannot use a data reader here, since that connects to the readyRead signal, + // just use readAll() + + // the only thing we check here is that the proxy auth cache was used when using synchronous requests + QCOMPARE(replySync->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); + QCOMPARE(replySync->readAll(), reference.readAll()); + } +} + +void tst_QNetworkReply::ioGetFromHttpWithProxyAuthSynchronous() +{ + // verify that we do not enter an endless loop with synchronous calls and wrong credentials + // the case when we succed with the login is tested in ioGetFromHttpWithAuth() + + QNetworkProxy proxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129); + QNetworkRequest request(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt")); + manager.setProxy(proxy); + request.setAttribute( + static_cast<QNetworkRequest::Attribute>(SynchronousRequestAttribute), + true); + + QSignalSpy authspy(&manager, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*))); + QNetworkReplyPtr replySync = manager.get(request); + manager.setProxy(QNetworkProxy()); // reset + QVERIFY(replySync->isFinished()); // synchronous + QCOMPARE(replySync->error(), QNetworkReply::ProxyAuthenticationRequiredError); + QCOMPARE(authspy.count(), 0); + QCOMPARE(replySync->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 407); } void tst_QNetworkReply::ioGetFromHttpWithSocksProxy() @@ -3238,7 +3431,67 @@ void tst_QNetworkReply::ioPostToHttpFromSocket() QTEST(authenticationRequiredSpy.count(), "authenticationRequiredCount"); QTEST(proxyAuthenticationRequiredSpy.count(), "proxyAuthenticationRequiredCount"); - } +} + +void tst_QNetworkReply::ioPostToHttpFromSocketSynchronous_data() +{ + QTest::addColumn<QByteArray>("data"); + QTest::addColumn<QByteArray>("md5sum"); + + QByteArray data; + data = ""; + QTest::newRow("empty") << data << md5sum(data); + + data = "This is a normal message."; + QTest::newRow("generic") << data << md5sum(data); + + data = "This is a message to show that Qt rocks!\r\n\n"; + QTest::newRow("small") << data << md5sum(data); + + data = QByteArray("abcd\0\1\2\abcd",12); + QTest::newRow("with-nul") << data << md5sum(data); + + data = QByteArray(4097, '\4'); + QTest::newRow("4k+1") << data << md5sum(data); + + data = QByteArray(128*1024+1, '\177'); + QTest::newRow("128k+1") << data << md5sum(data); + + data = QByteArray(2*1024*1024+1, '\177'); + QTest::newRow("2MB+1") << data << md5sum(data); +} + +void tst_QNetworkReply::ioPostToHttpFromSocketSynchronous() +{ + QFETCH(QByteArray, data); + + SocketPair socketpair; + QVERIFY(socketpair.create()); + QVERIFY(socketpair.endPoints[0] && socketpair.endPoints[1]); + socketpair.endPoints[0]->write(data); + socketpair.endPoints[0]->waitForBytesWritten(5000); + // ### for 4.8: make the socket pair unbuffered, to not read everything in one go in QNetworkReplyImplPrivate::setup() + QTestEventLoop::instance().enterLoop(3); + + QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi"); + QNetworkRequest request(url); + request.setAttribute( + static_cast<QNetworkRequest::Attribute>(SynchronousRequestAttribute), + true); + + QNetworkReplyPtr reply = manager.post(request, socketpair.endPoints[1]); + QVERIFY(reply->isFinished()); + socketpair.endPoints[0]->close(); + + QCOMPARE(reply->error(), QNetworkReply::NoError); + + QCOMPARE(reply->url(), url); + QCOMPARE(reply->error(), QNetworkReply::NoError); + // verify that the HTTP status code is 200 Ok + QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); + + QCOMPARE(reply->readAll().trimmed(), md5sum(data).toHex()); +} // this tests checks if rewinding the POST-data to some place in the middle // worked. @@ -3981,6 +4234,38 @@ void tst_QNetworkReply::receiveCookiesFromHttp() QTEST(cookieJar->allCookies(), "expectedCookiesInJar"); } +void tst_QNetworkReply::receiveCookiesFromHttpSynchronous_data() +{ + tst_QNetworkReply::receiveCookiesFromHttp_data(); +} + +void tst_QNetworkReply::receiveCookiesFromHttpSynchronous() +{ + QFETCH(QString, cookieString); + + QByteArray data = cookieString.toLatin1() + '\n'; + QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/set-cookie.cgi"); + + QNetworkRequest request(url); + + request.setAttribute( + static_cast<QNetworkRequest::Attribute>(SynchronousRequestAttribute), + true); + + QNetworkReplyPtr reply; + RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::PostOperation, request, reply, data)); + + QCOMPARE(reply->url(), url); + QCOMPARE(reply->error(), QNetworkReply::NoError); + + QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // 200 Ok + + QList<QNetworkCookie> setCookies = + qvariant_cast<QList<QNetworkCookie> >(reply->header(QNetworkRequest::SetCookieHeader)); + QTEST(setCookies, "expectedCookiesFromHttp"); + QTEST(cookieJar->allCookies(), "expectedCookiesInJar"); +} + void tst_QNetworkReply::sendCookies_data() { QTest::addColumn<QList<QNetworkCookie> >("cookiesToSet"); @@ -4041,6 +4326,35 @@ void tst_QNetworkReply::sendCookies() QCOMPARE(QString::fromLatin1(reply->readAll()).trimmed(), expectedCookieString); } +void tst_QNetworkReply::sendCookiesSynchronous_data() +{ + tst_QNetworkReply::sendCookies_data(); +} + +void tst_QNetworkReply::sendCookiesSynchronous() +{ + QFETCH(QString, expectedCookieString); + QFETCH(QList<QNetworkCookie>, cookiesToSet); + cookieJar->setAllCookies(cookiesToSet); + + QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/get-cookie.cgi"); + QNetworkRequest request(url); + + request.setAttribute( + static_cast<QNetworkRequest::Attribute>(SynchronousRequestAttribute), + true); + + QNetworkReplyPtr reply; + RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::GetOperation, request, reply)); + + QCOMPARE(reply->url(), url); + QCOMPARE(reply->error(), QNetworkReply::NoError); + + QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // 200 Ok + + QCOMPARE(QString::fromLatin1(reply->readAll()).trimmed(), expectedCookieString); +} + void tst_QNetworkReply::nestedEventLoops_slot() { QEventLoop subloop; @@ -4144,6 +4458,49 @@ private: int signalCount; }; +void tst_QNetworkReply::httpProxyCommandsSynchronous_data() +{ + httpProxyCommands_data(); +} + +void tst_QNetworkReply::httpProxyCommandsSynchronous() +{ + QFETCH(QUrl, url); + QFETCH(QByteArray, responseToSend); + QFETCH(QString, expectedCommand); + + // when using synchronous commands, we need a different event loop for + // the server thread, because the client is never returning to the + // event loop + MiniHttpServer proxyServer(responseToSend); + QThread serverThread; + proxyServer.moveToThread(&serverThread); + serverThread.start(); + QNetworkProxy proxy(QNetworkProxy::HttpProxy, "127.0.0.1", proxyServer.serverPort()); + + manager.setProxy(proxy); + QNetworkRequest request(url); + + // send synchronous request + request.setAttribute( + static_cast<QNetworkRequest::Attribute>(SynchronousRequestAttribute), + true); + + QNetworkReplyPtr reply = manager.get(request); + QVERIFY(reply->isFinished()); // synchronous + manager.setProxy(QNetworkProxy()); + serverThread.quit(); + + //qDebug() << reply->error() << reply->errorString(); + + // we don't really care if the request succeeded + // especially since it won't succeed in the HTTPS case + // so just check that the command was correct + + QString receivedHeader = proxyServer.receivedData.left(expectedCommand.length()); + QCOMPARE(receivedHeader, expectedCommand); +} + void tst_QNetworkReply::proxyChange() { ProxyChangeHelper helper; @@ -4746,7 +5103,122 @@ void tst_QNetworkReply::qtbug15311doubleContentLength() QCOMPARE(reply->readAll(), QByteArray("ABC")); } +void tst_QNetworkReply::synchronousRequest_data() +{ + QTest::addColumn<QUrl>("url"); + QTest::addColumn<QString>("expected"); + QTest::addColumn<bool>("checkContentLength"); + QTest::addColumn<QString>("mimeType"); + + // ### cache, auth, proxies + + QTest::newRow("http") + << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt") + << QString("file:" SRCDIR "/rfc3252.txt") + << true + << QString("text/plain"); + + QTest::newRow("http-gzip") + << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/deflate/rfc3252.txt") + << QString("file:" SRCDIR "/rfc3252.txt") + << false // don't check content length, because it's gzip encoded + // ### we would need to enflate (un-deflate) the file content and compare the sizes + << QString("text/plain"); + +#ifndef QT_NO_OPENSSL + QTest::newRow("https") + << QUrl("https://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt") + << QString("file:" SRCDIR "/rfc3252.txt") + << true + << QString("text/plain"); +#endif + + QTest::newRow("data") + << QUrl(QString::fromLatin1("data:text/plain,hello world")) + << QString("data:hello world") + << true // check content length + << QString("text/plain"); + + QTest::newRow("simple-file") + << QUrl(QString::fromLatin1("file:///" SRCDIR "/rfc3252.txt")) + << QString("file:" SRCDIR "/rfc3252.txt") + << true + << QString(); +} + +// FIXME add testcase for failing network etc +void tst_QNetworkReply::synchronousRequest() +{ + QFETCH(QUrl, url); + QFETCH(QString, expected); + QFETCH(bool, checkContentLength); + QFETCH(QString, mimeType); + + QNetworkRequest request(url); + +#ifndef QT_NO_OPENSSL + // workaround for HTTPS requests: add self-signed server cert to list of CA certs, + // since we cannot react to the sslErrors() signal + // to fix this properly we would need to have an ignoreSslErrors() method in the + // QNetworkRequest, see http://bugreports.qt.nokia.com/browse/QTBUG-14774 + if (url.scheme() == "https") { + QSslConfiguration sslConf; + QList<QSslCertificate> certs = QSslCertificate::fromPath(SRCDIR "/certs/qt-test-server-cacert.pem"); + sslConf.setCaCertificates(certs); + request.setSslConfiguration(sslConf); + } +#endif + + request.setAttribute( + static_cast<QNetworkRequest::Attribute>(SynchronousRequestAttribute), + true); + + QNetworkReplyPtr reply; + QSignalSpy finishedSpy(&manager, SIGNAL(finished(QNetworkReply*))); + QSignalSpy sslErrorsSpy(&manager, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>))); + RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::GetOperation, request, reply, 0)); + QVERIFY(reply->isFinished()); + QCOMPARE(finishedSpy.count(), 0); + QCOMPARE(sslErrorsSpy.count(), 0); + + QCOMPARE(reply->header(QNetworkRequest::ContentTypeHeader).toString(), mimeType); + + QByteArray expectedContent; + + if (expected.startsWith("file:")) { + QString path = expected.mid(5); + QFile file(path); + file.open(QIODevice::ReadOnly); + expectedContent = file.readAll(); + } else if (expected.startsWith("data:")) { + expectedContent = expected.mid(5).toUtf8(); + } + + if (checkContentLength) + QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), qint64(expectedContent.size())); + QCOMPARE(reply->readAll(), expectedContent); + + reply->deleteLater(); +} + +void tst_QNetworkReply::synchronousRequestSslFailure() +{ + // test that SSL won't be accepted with self-signed certificate, + // and that we do not emit the sslError signal (in the manager that is, + // in the reply we don't care) + QUrl url("https://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"); + QNetworkRequest request(url); + request.setAttribute( + static_cast<QNetworkRequest::Attribute>(SynchronousRequestAttribute), + true); + QNetworkReplyPtr reply; + QSignalSpy sslErrorsSpy(&manager, SIGNAL(sslErrors(QNetworkReply *, const QList<QSslError> &))); + runSimpleRequest(QNetworkAccessManager::GetOperation, request, reply, 0); + QVERIFY(reply->isFinished()); + QCOMPARE(reply->error(), QNetworkReply::SslHandshakeFailedError); + QCOMPARE(sslErrorsSpy.count(), 0); +} // NOTE: This test must be last testcase in tst_qnetworkreply! void tst_QNetworkReply::parentingRepliesToTheApp() |