summaryrefslogtreecommitdiffstats
path: root/tests/auto/network/access/qhttpnetworkconnection
diff options
context:
space:
mode:
authorJo Asplin <jo.asplin@nokia.com>2011-09-06 13:46:40 +0200
committerJo Asplin <jo.asplin@nokia.com>2011-09-09 09:32:17 +0200
commitc59f9ad7768a007ca7a49ea11b16617529e86d52 (patch)
treed481be2a727f8461a76c2b729fc7e93784a3cff1 /tests/auto/network/access/qhttpnetworkconnection
parent2d41aff1e8557a43268bce631df834bfa79593cf (diff)
Moved network autotests into new directory structure
Task-number: QTBUG-21223 Change-Id: I55dbf5c42a1c5d938b9e0c9bf7d90457a6c26bbc Reviewed-on: http://codereview.qt-project.org/4259 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Sergio Ahumada <sergio.ahumada@nokia.com> Reviewed-by: Rohan McGovern <rohan.mcgovern@nokia.com>
Diffstat (limited to 'tests/auto/network/access/qhttpnetworkconnection')
-rw-r--r--tests/auto/network/access/qhttpnetworkconnection/.gitignore1
-rw-r--r--tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro13
-rw-r--r--tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp1131
3 files changed, 1145 insertions, 0 deletions
diff --git a/tests/auto/network/access/qhttpnetworkconnection/.gitignore b/tests/auto/network/access/qhttpnetworkconnection/.gitignore
new file mode 100644
index 0000000000..4fe208868b
--- /dev/null
+++ b/tests/auto/network/access/qhttpnetworkconnection/.gitignore
@@ -0,0 +1 @@
+tst_qhttpnetworkconnection
diff --git a/tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro b/tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro
new file mode 100644
index 0000000000..1ce5d8a092
--- /dev/null
+++ b/tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro
@@ -0,0 +1,13 @@
+load(qttest_p4)
+SOURCES += tst_qhttpnetworkconnection.cpp
+INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/zlib
+requires(contains(QT_CONFIG,private_tests))
+
+QT = core-private network-private
+
+symbian: TARGET.CAPABILITY = NetworkServices
+symbian: {
+ INCLUDEPATH += $$MW_LAYER_SYSTEMINCLUDE
+}
+
+CONFIG+=insignificant_test # QTBUG-20981, crashes sometimes
diff --git a/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp b/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
new file mode 100644
index 0000000000..2d30f6bca1
--- /dev/null
+++ b/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
@@ -0,0 +1,1131 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include "private/qhttpnetworkconnection_p.h"
+#include "private/qnoncontiguousbytedevice_p.h"
+#include <QAuthenticator>
+
+#include "../../../network-settings.h"
+
+class tst_QHttpNetworkConnection: public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QHttpNetworkConnection();
+
+public Q_SLOTS:
+ void finishedReply();
+ void finishedWithError(QNetworkReply::NetworkError errorCode, const QString &detail);
+ void challenge401(const QHttpNetworkRequest &request, QAuthenticator *authenticator);
+#ifndef QT_NO_OPENSSL
+ void sslErrors(const QList<QSslError> &errors);
+#endif
+private:
+ bool finishedCalled;
+ bool finishedWithErrorCalled;
+ QNetworkReply::NetworkError netErrorCode;
+
+private Q_SLOTS:
+ void init();
+ void cleanup();
+ void initTestCase();
+ void cleanupTestCase();
+
+ void options_data();
+ void options();
+ void get_data();
+ void get();
+ void head_data();
+ void head();
+ void post_data();
+ void post();
+ void put_data();
+ void put();
+ void _delete_data();
+ void _delete();
+ void trace_data();
+ void trace();
+ void _connect_data();
+ void _connect();
+#ifndef QT_NO_COMPRESS
+ void compression_data();
+ void compression();
+#endif
+#ifndef QT_NO_OPENSSL
+ void ignoresslerror_data();
+ void ignoresslerror();
+#endif
+#ifdef QT_NO_OPENSSL
+ void nossl_data();
+ void nossl();
+#endif
+ void get401_data();
+ void get401();
+
+ void getMultiple_data();
+ void getMultiple();
+ void getMultipleWithPipeliningAndMultiplePriorities();
+ void getMultipleWithPriorities();
+
+ void getEmptyWithPipelining();
+
+ void getAndEverythingShouldBePipelined();
+
+ void getAndThenDeleteObject();
+ void getAndThenDeleteObject_data();
+};
+
+tst_QHttpNetworkConnection::tst_QHttpNetworkConnection()
+{
+ Q_SET_DEFAULT_IAP
+}
+
+void tst_QHttpNetworkConnection::initTestCase()
+{
+}
+
+void tst_QHttpNetworkConnection::cleanupTestCase()
+{
+}
+
+void tst_QHttpNetworkConnection::init()
+{
+}
+
+void tst_QHttpNetworkConnection::cleanup()
+{
+}
+
+void tst_QHttpNetworkConnection::options_data()
+{
+ // not tested yet
+}
+
+void tst_QHttpNetworkConnection::options()
+{
+ QEXPECT_FAIL("", "not tested yet", Continue);
+ QVERIFY(false);
+}
+
+void tst_QHttpNetworkConnection::head_data()
+{
+ QTest::addColumn<QString>("protocol");
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<ushort>("port");
+ QTest::addColumn<bool>("encrypt");
+ QTest::addColumn<int>("statusCode");
+ QTest::addColumn<QString>("statusString");
+ QTest::addColumn<int>("contentLength");
+
+ QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962;
+ QTest::newRow("success-external") << "http://" << "www.ietf.org" << "/rfc/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962;
+
+ QTest::newRow("failure-path") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << 404 << "Not Found" << -1;
+ QTest::newRow("failure-protocol") << "" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 400 << "Bad Request" << -1;
+}
+
+void tst_QHttpNetworkConnection::head()
+{
+ QFETCH(QString, protocol);
+ QFETCH(QString, host);
+ QFETCH(QString, path);
+ QFETCH(ushort, port);
+ QFETCH(bool, encrypt);
+ QFETCH(int, statusCode);
+ QFETCH(QString, statusString);
+ QFETCH(int, contentLength);
+
+ QHttpNetworkConnection connection(host, port, encrypt);
+ QCOMPARE(connection.port(), port);
+ QCOMPARE(connection.hostName(), host);
+ QCOMPARE(connection.isSsl(), encrypt);
+
+ QHttpNetworkRequest request(protocol + host + path, QHttpNetworkRequest::Head);
+ QHttpNetworkReply *reply = connection.sendRequest(request);
+
+ QTime stopWatch;
+ stopWatch.start();
+ do {
+ QCoreApplication::instance()->processEvents();
+ if (stopWatch.elapsed() >= 30000)
+ break;
+ } while (!reply->isFinished());
+
+ QCOMPARE(reply->statusCode(), statusCode);
+ QCOMPARE(reply->reasonPhrase(), statusString);
+ // only check it if it is set and expected
+ if (reply->contentLength() != -1 && contentLength != -1)
+ QCOMPARE(reply->contentLength(), qint64(contentLength));
+
+ QVERIFY(reply->isFinished());
+
+ delete reply;
+}
+
+void tst_QHttpNetworkConnection::get_data()
+{
+ QTest::addColumn<QString>("protocol");
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<ushort>("port");
+ QTest::addColumn<bool>("encrypt");
+ QTest::addColumn<int>("statusCode");
+ QTest::addColumn<QString>("statusString");
+ QTest::addColumn<int>("contentLength");
+ QTest::addColumn<int>("downloadSize");
+
+ QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962 << 25962;
+ QTest::newRow("success-external") << "http://" << "www.ietf.org" << "/rfc/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962 << 25962;
+
+ QTest::newRow("failure-path") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << 404 << "Not Found" << -1 << -1;
+ QTest::newRow("failure-protocol") << "" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 400 << "Bad Request" << -1 << -1;
+}
+
+void tst_QHttpNetworkConnection::get()
+{
+ QFETCH(QString, protocol);
+ QFETCH(QString, host);
+ QFETCH(QString, path);
+ QFETCH(ushort, port);
+ QFETCH(bool, encrypt);
+ QFETCH(int, statusCode);
+ QFETCH(QString, statusString);
+ QFETCH(int, contentLength);
+ QFETCH(int, downloadSize);
+
+ QHttpNetworkConnection connection(host, port, encrypt);
+ QCOMPARE(connection.port(), port);
+ QCOMPARE(connection.hostName(), host);
+ QCOMPARE(connection.isSsl(), encrypt);
+
+ QHttpNetworkRequest request(protocol + host + path);
+ QHttpNetworkReply *reply = connection.sendRequest(request);
+
+ QTime stopWatch;
+ stopWatch.start();
+ forever {
+ QCoreApplication::instance()->processEvents();
+ if (reply->bytesAvailable())
+ break;
+ if (stopWatch.elapsed() >= 30000)
+ break;
+ }
+
+ QCOMPARE(reply->statusCode(), statusCode);
+ QCOMPARE(reply->reasonPhrase(), statusString);
+ // only check it if it is set and expected
+ if (reply->contentLength() != -1 && contentLength != -1)
+ QCOMPARE(reply->contentLength(), qint64(contentLength));
+
+ stopWatch.start();
+ QByteArray ba;
+ do {
+ QCoreApplication::instance()->processEvents();
+ while (reply->bytesAvailable())
+ ba += reply->readAny();
+ if (stopWatch.elapsed() >= 30000)
+ break;
+ } while (!reply->isFinished());
+
+ QVERIFY(reply->isFinished());
+ //do not require server generated error pages to be a fixed size
+ if (downloadSize != -1)
+ QCOMPARE(ba.size(), downloadSize);
+ //but check against content length if it was sent
+ if (reply->contentLength() != -1)
+ QCOMPARE(ba.size(), (int)reply->contentLength());
+
+ delete reply;
+}
+
+void tst_QHttpNetworkConnection::finishedReply()
+{
+ finishedCalled = true;
+}
+
+void tst_QHttpNetworkConnection::finishedWithError(QNetworkReply::NetworkError errorCode, const QString &detail)
+{
+ Q_UNUSED(detail)
+ finishedWithErrorCalled = true;
+ netErrorCode = errorCode;
+}
+
+void tst_QHttpNetworkConnection::put_data()
+{
+
+ QTest::addColumn<QString>("protocol");
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<ushort>("port");
+ QTest::addColumn<bool>("encrypt");
+ QTest::addColumn<QString>("data");
+ QTest::addColumn<bool>("succeed");
+
+ QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/dav/file1.txt" << ushort(80) << false << "Hello World\nEnd of file\n"<<true;
+ QTest::newRow("fail-internal") << "http://" << QtNetworkSettings::serverName() << "/dav2/file1.txt" << ushort(80) << false << "Hello World\nEnd of file\n"<<false;
+ QTest::newRow("fail-host") << "http://" << "fluke-nosuchhost.troll.no" << "/dav2/file1.txt" << ushort(80) << false << "Hello World\nEnd of file\n"<<false;
+}
+
+void tst_QHttpNetworkConnection::put()
+{
+ QFETCH(QString, protocol);
+ QFETCH(QString, host);
+ QFETCH(QString, path);
+ QFETCH(ushort, port);
+ QFETCH(bool, encrypt);
+ QFETCH(QString, data);
+ QFETCH(bool, succeed);
+
+ QHttpNetworkConnection connection(host, port, encrypt);
+ QCOMPARE(connection.port(), port);
+ QCOMPARE(connection.hostName(), host);
+ QCOMPARE(connection.isSsl(), encrypt);
+
+ QHttpNetworkRequest request(protocol + host + path, QHttpNetworkRequest::Put);
+
+ QByteArray array = data.toLatin1();
+ QNonContiguousByteDevice *bd = QNonContiguousByteDeviceFactory::create(&array);
+ bd->setParent(this);
+ request.setUploadByteDevice(bd);
+
+ finishedCalled = false;
+ finishedWithErrorCalled = false;
+
+ QHttpNetworkReply *reply = connection.sendRequest(request);
+ connect(reply, SIGNAL(finished()), SLOT(finishedReply()));
+ connect(reply, SIGNAL(finishedWithError(QNetworkReply::NetworkError, const QString &)),
+ SLOT(finishedWithError(QNetworkReply::NetworkError, const QString &)));
+
+ QTime stopWatch;
+ stopWatch.start();
+ do {
+ QCoreApplication::instance()->processEvents();
+ if (stopWatch.elapsed() >= 30000)
+ break;
+ } while (!reply->isFinished() && !finishedCalled && !finishedWithErrorCalled);
+
+ if (reply->isFinished()) {
+ QByteArray ba;
+ while (reply->bytesAvailable())
+ ba += reply->readAny();
+ } else if(finishedWithErrorCalled) {
+ if(!succeed) {
+ delete reply;
+ return;
+ } else {
+ QFAIL("Error in PUT");
+ }
+ } else {
+ QFAIL("PUT timed out");
+ }
+
+ int status = reply->statusCode();
+ if (status != 200 && status != 201 && status != 204) {
+ if (succeed) {
+ qDebug()<<"PUT failed, Status Code:" <<status;
+ QFAIL("Error in PUT");
+ }
+ } else {
+ if (!succeed) {
+ qDebug()<<"PUT Should fail, Status Code:" <<status;
+ QFAIL("Error in PUT");
+ }
+ }
+ delete reply;
+}
+
+void tst_QHttpNetworkConnection::post_data()
+{
+ QTest::addColumn<QString>("protocol");
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<ushort>("port");
+ QTest::addColumn<bool>("encrypt");
+ QTest::addColumn<QString>("data");
+ QTest::addColumn<int>("statusCode");
+ QTest::addColumn<QString>("statusString");
+ QTest::addColumn<int>("contentLength");
+ QTest::addColumn<int>("downloadSize");
+
+ QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/qtest/cgi-bin/echo.cgi" << ushort(80) << false << "7 bytes" << 200 << "OK" << 7 << 7;
+ QTest::newRow("failure-internal") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << "Hello World" << 404 << "Not Found" << -1 << -1;
+}
+
+void tst_QHttpNetworkConnection::post()
+{
+ QFETCH(QString, protocol);
+ QFETCH(QString, host);
+ QFETCH(QString, path);
+ QFETCH(ushort, port);
+ QFETCH(bool, encrypt);
+ QFETCH(QString, data);
+ QFETCH(int, statusCode);
+ QFETCH(QString, statusString);
+ QFETCH(int, contentLength);
+ QFETCH(int, downloadSize);
+
+ QHttpNetworkConnection connection(host, port, encrypt);
+ QCOMPARE(connection.port(), port);
+ QCOMPARE(connection.hostName(), host);
+ QCOMPARE(connection.isSsl(), encrypt);
+
+ QHttpNetworkRequest request(protocol + host + path, QHttpNetworkRequest::Post);
+
+ QByteArray array = data.toLatin1();
+ QNonContiguousByteDevice *bd = QNonContiguousByteDeviceFactory::create(&array);
+ bd->setParent(this);
+ request.setUploadByteDevice(bd);
+
+ QHttpNetworkReply *reply = connection.sendRequest(request);
+
+ QTime stopWatch;
+ stopWatch.start();
+ forever {
+ QCoreApplication::instance()->processEvents();
+ if (reply->bytesAvailable())
+ break;
+ if (stopWatch.elapsed() >= 30000)
+ break;
+ }
+
+ QCOMPARE(reply->statusCode(), statusCode);
+ QCOMPARE(reply->reasonPhrase(), statusString);
+
+ qint64 cLen = reply->contentLength();
+ if (contentLength != -1) {
+ // only check the content length if test expected it to be set
+ if (cLen==-1) {
+ // HTTP 1.1 server may respond with chunked encoding and in that
+ // case contentLength is not present in reply -> verify that it is the case
+ QByteArray transferEnc = reply->headerField("Transfer-Encoding");
+ QCOMPARE(transferEnc, QByteArray("chunked"));
+ } else {
+ QCOMPARE(cLen, qint64(contentLength));
+ }
+ }
+
+ stopWatch.start();
+ QByteArray ba;
+ do {
+ QCoreApplication::instance()->processEvents();
+ while (reply->bytesAvailable())
+ ba += reply->readAny();
+ if (stopWatch.elapsed() >= 30000)
+ break;
+ } while (!reply->isFinished());
+
+ QVERIFY(reply->isFinished());
+ //don't require fixed size for generated error pages
+ if (downloadSize != -1)
+ QCOMPARE(ba.size(), downloadSize);
+ //but do compare with content length if possible
+ if (cLen != -1)
+ QCOMPARE(ba.size(), (int)cLen);
+
+ delete reply;
+}
+
+void tst_QHttpNetworkConnection::_delete_data()
+{
+ // not tested yet
+}
+
+void tst_QHttpNetworkConnection::_delete()
+{
+ QEXPECT_FAIL("", "not tested yet", Continue);
+ QVERIFY(false);
+}
+
+void tst_QHttpNetworkConnection::trace_data()
+{
+ // not tested yet
+}
+
+void tst_QHttpNetworkConnection::trace()
+{
+ QEXPECT_FAIL("", "not tested yet", Continue);
+ QVERIFY(false);
+}
+
+void tst_QHttpNetworkConnection::_connect_data()
+{
+ // not tested yet
+}
+
+void tst_QHttpNetworkConnection::_connect()
+{
+ QEXPECT_FAIL("", "not tested yet", Continue);
+ QVERIFY(false);
+}
+
+void tst_QHttpNetworkConnection::challenge401(const QHttpNetworkRequest &request,
+ QAuthenticator *authenticator)
+{
+ Q_UNUSED(request)
+
+ QHttpNetworkReply *reply = qobject_cast<QHttpNetworkReply*>(sender());
+ if (reply) {
+ QHttpNetworkConnection *c = reply->connection();
+
+ QVariant val = c->property("setCredentials");
+ if (val.toBool()) {
+ QVariant user = c->property("username");
+ QVariant password = c->property("password");
+ authenticator->setUser(user.toString());
+ authenticator->setPassword(password.toString());
+ c->setProperty("setCredentials", false);
+ }
+ }
+}
+
+void tst_QHttpNetworkConnection::get401_data()
+{
+ QTest::addColumn<QString>("protocol");
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<ushort>("port");
+ QTest::addColumn<bool>("encrypt");
+ QTest::addColumn<bool>("setCredentials");
+ QTest::addColumn<QString>("username");
+ QTest::addColumn<QString>("password");
+ QTest::addColumn<int>("statusCode");
+
+ QTest::newRow("no-credentials") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs-auth/index.html" << ushort(80) << false << false << "" << ""<<401;
+ QTest::newRow("invalid-credentials") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs-auth/index.html" << ushort(80) << false << true << "test" << "test"<<401;
+ QTest::newRow("valid-credentials") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs-auth/index.html" << ushort(80) << false << true << "httptest" << "httptest"<<200;
+ QTest::newRow("digest-authentication-invalid") << "http://" << QtNetworkSettings::serverName() << "/qtest/auth-digest/index.html" << ushort(80) << false << true << "wrong" << "wrong"<<401;
+ QTest::newRow("digest-authentication-valid") << "http://" << QtNetworkSettings::serverName() << "/qtest/auth-digest/index.html" << ushort(80) << false << true << "httptest" << "httptest"<<200;
+}
+
+void tst_QHttpNetworkConnection::get401()
+{
+ QFETCH(QString, protocol);
+ QFETCH(QString, host);
+ QFETCH(QString, path);
+ QFETCH(ushort, port);
+ QFETCH(bool, encrypt);
+ QFETCH(bool, setCredentials);
+ QFETCH(QString, username);
+ QFETCH(QString, password);
+ QFETCH(int, statusCode);
+
+ QHttpNetworkConnection connection(host, port, encrypt);
+ QCOMPARE(connection.port(), port);
+ QCOMPARE(connection.hostName(), host);
+ QCOMPARE(connection.isSsl(), encrypt);
+ connection.setProperty("setCredentials", setCredentials);
+ connection.setProperty("username", username);
+ connection.setProperty("password", password);
+
+ QHttpNetworkRequest request(protocol + host + path);
+ QHttpNetworkReply *reply = connection.sendRequest(request);
+ connect(reply, SIGNAL(authenticationRequired(const QHttpNetworkRequest&, QAuthenticator *)),
+ SLOT(challenge401(const QHttpNetworkRequest&, QAuthenticator *)));
+
+ finishedCalled = false;
+ finishedWithErrorCalled = false;
+
+ connect(reply, SIGNAL(finished()), SLOT(finishedReply()));
+ connect(reply, SIGNAL(finishedWithError(QNetworkReply::NetworkError, const QString &)),
+ SLOT(finishedWithError(QNetworkReply::NetworkError, const QString &)));
+
+ QTime stopWatch;
+ stopWatch.start();
+ forever {
+ QCoreApplication::instance()->processEvents();
+ if (finishedCalled)
+ break;
+ if (finishedWithErrorCalled)
+ break;
+ if (stopWatch.elapsed() >= 30000)
+ break;
+ }
+ QCOMPARE(reply->statusCode(), statusCode);
+ delete reply;
+}
+
+#ifndef QT_NO_COMPRESS
+void tst_QHttpNetworkConnection::compression_data()
+{
+ QTest::addColumn<QString>("protocol");
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<ushort>("port");
+ QTest::addColumn<bool>("encrypt");
+ QTest::addColumn<int>("statusCode");
+ QTest::addColumn<QString>("statusString");
+ QTest::addColumn<int>("contentLength");
+ QTest::addColumn<int>("downloadSize");
+ QTest::addColumn<bool>("autoCompress");
+ QTest::addColumn<QString>("contentCoding");
+
+ QTest::newRow("success-autogzip-temp") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs/rfc2616.html" << ushort(80) << false << 200 << "OK" << -1 << 418321 << true << "";
+ QTest::newRow("success-nogzip-temp") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs/rfc2616.html" << ushort(80) << false << 200 << "OK" << 418321 << 418321 << false << "identity";
+ QTest::newRow("success-manualgzip-temp") << "http://" << QtNetworkSettings::serverName() << "/qtest/deflate/rfc2616.html" << ushort(80) << false << 200 << "OK" << 119124 << 119124 << false << "gzip";
+
+}
+
+void tst_QHttpNetworkConnection::compression()
+{
+ QFETCH(QString, protocol);
+ QFETCH(QString, host);
+ QFETCH(QString, path);
+ QFETCH(ushort, port);
+ QFETCH(bool, encrypt);
+ QFETCH(int, statusCode);
+ QFETCH(QString, statusString);
+ QFETCH(int, contentLength);
+ QFETCH(int, downloadSize);
+ QFETCH(bool, autoCompress);
+ QFETCH(QString, contentCoding);
+
+ QHttpNetworkConnection connection(host, port, encrypt);
+ QCOMPARE(connection.port(), port);
+ QCOMPARE(connection.hostName(), host);
+ QCOMPARE(connection.isSsl(), encrypt);
+
+ QHttpNetworkRequest request(protocol + host + path);
+ if (!autoCompress)
+ request.setHeaderField("Accept-Encoding", contentCoding.toLatin1());
+ QHttpNetworkReply *reply = connection.sendRequest(request);
+ QTime stopWatch;
+ stopWatch.start();
+ forever {
+ QCoreApplication::instance()->processEvents();
+ if (reply->bytesAvailable())
+ break;
+ if (stopWatch.elapsed() >= 30000)
+ break;
+ }
+
+ QCOMPARE(reply->statusCode(), statusCode);
+ QCOMPARE(reply->reasonPhrase(), statusString);
+ bool isLengthOk = (reply->contentLength() == qint64(contentLength)
+ || reply->contentLength() == qint64(downloadSize)
+ || reply->contentLength() == -1); //apache2 does not send content-length for compressed pages
+
+ QVERIFY(isLengthOk);
+
+ stopWatch.start();
+ QByteArray ba;
+ do {
+ QCoreApplication::instance()->processEvents();
+ while (reply->bytesAvailable())
+ ba += reply->readAny();
+ if (stopWatch.elapsed() >= 30000)
+ break;
+ } while (!reply->isFinished());
+
+ QVERIFY(reply->isFinished());
+ QCOMPARE(ba.size(), downloadSize);
+
+ delete reply;
+}
+#endif
+
+#ifndef QT_NO_OPENSSL
+void tst_QHttpNetworkConnection::sslErrors(const QList<QSslError> &errors)
+{
+ Q_UNUSED(errors)
+
+ QHttpNetworkReply *reply = qobject_cast<QHttpNetworkReply*>(sender());
+ if (reply) {
+ QHttpNetworkConnection *connection = reply->connection();
+
+ QVariant val = connection->property("ignoreFromSignal");
+ if (val.toBool())
+ connection->ignoreSslErrors();
+ finishedWithErrorCalled = true;
+ }
+}
+
+void tst_QHttpNetworkConnection::ignoresslerror_data()
+{
+ QTest::addColumn<QString>("protocol");
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<ushort>("port");
+ QTest::addColumn<bool>("encrypt");
+ QTest::addColumn<bool>("ignoreInit");
+ QTest::addColumn<bool>("ignoreFromSignal");
+ QTest::addColumn<int>("statusCode");
+
+ // This test will work only if the website has ssl errors.
+ // fluke's certificate is signed by a non-standard authority.
+ // Since we don't introduce that CA into the SSL verification chain,
+ // connecting should fail.
+ QTest::newRow("success-init") << "https://" << QtNetworkSettings::serverName() << "/" << ushort(443) << true << true << false << 200;
+ QTest::newRow("success-fromSignal") << "https://" << QtNetworkSettings::serverName() << "/" << ushort(443) << true << false << true << 200;
+ QTest::newRow("failure") << "https://" << QtNetworkSettings::serverName() << "/" << ushort(443) << true << false << false << 100;
+}
+
+void tst_QHttpNetworkConnection::ignoresslerror()
+{
+ QFETCH(QString, protocol);
+ QFETCH(QString, host);
+ QFETCH(QString, path);
+ QFETCH(ushort, port);
+ QFETCH(bool, encrypt);
+ QFETCH(bool, ignoreInit);
+ QFETCH(bool, ignoreFromSignal);
+ QFETCH(int, statusCode);
+
+ QHttpNetworkConnection connection(host, port, encrypt);
+ QCOMPARE(connection.port(), port);
+ QCOMPARE(connection.hostName(), host);
+ if (ignoreInit)
+ connection.ignoreSslErrors();
+ QCOMPARE(connection.isSsl(), encrypt);
+ connection.setProperty("ignoreFromSignal", ignoreFromSignal);
+
+ QHttpNetworkRequest request(protocol + host + path);
+ QHttpNetworkReply *reply = connection.sendRequest(request);
+ connect(reply, SIGNAL(sslErrors(const QList<QSslError>&)),
+ SLOT(sslErrors(const QList<QSslError>&)));
+
+ finishedWithErrorCalled = false;
+
+ connect(reply, SIGNAL(finished()), SLOT(finishedReply()));
+
+ QTime stopWatch;
+ stopWatch.start();
+ forever {
+ QCoreApplication::instance()->processEvents();
+ if (reply->bytesAvailable())
+ break;
+ if (statusCode == 100 && finishedWithErrorCalled)
+ break;
+ if (stopWatch.elapsed() >= 30000)
+ break;
+ }
+ QCOMPARE(reply->statusCode(), statusCode);
+ delete reply;
+}
+#endif
+
+#ifdef QT_NO_OPENSSL
+Q_DECLARE_METATYPE(QNetworkReply::NetworkError)
+void tst_QHttpNetworkConnection::nossl_data()
+{
+ QTest::addColumn<QString>("protocol");
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<ushort>("port");
+ QTest::addColumn<bool>("encrypt");
+ QTest::addColumn<QNetworkReply::NetworkError>("networkError");
+
+ QTest::newRow("protocol-error") << "https://" << QtNetworkSettings::serverName() << "/" << ushort(443) << true <<QNetworkReply::ProtocolUnknownError;
+}
+
+void tst_QHttpNetworkConnection::nossl()
+{
+ QFETCH(QString, protocol);
+ QFETCH(QString, host);
+ QFETCH(QString, path);
+ QFETCH(ushort, port);
+ QFETCH(bool, encrypt);
+ QFETCH(QNetworkReply::NetworkError, networkError);
+
+ QHttpNetworkConnection connection(host, port, encrypt);
+ QCOMPARE(connection.port(), port);
+ QCOMPARE(connection.hostName(), host);
+
+ QHttpNetworkRequest request(protocol + host + path);
+ QHttpNetworkReply *reply = connection.sendRequest(request);
+
+ finishedWithErrorCalled = false;
+ netErrorCode = QNetworkReply::NoError;
+
+ connect(reply, SIGNAL(finished()), SLOT(finishedReply()));
+ connect(reply, SIGNAL(finishedWithError(QNetworkReply::NetworkError, const QString &)),
+ SLOT(finishedWithError(QNetworkReply::NetworkError, const QString &)));
+
+ QTime stopWatch;
+ stopWatch.start();
+ forever {
+ QCoreApplication::instance()->processEvents();
+ if (finishedWithErrorCalled)
+ break;
+ if (stopWatch.elapsed() >= 30000)
+ break;
+ }
+ QCOMPARE(netErrorCode, networkError);
+ delete reply;
+}
+#endif
+
+
+void tst_QHttpNetworkConnection::getMultiple_data()
+{
+ QTest::addColumn<quint16>("connectionCount");
+ QTest::addColumn<bool>("pipeliningAllowed");
+ // send 100 requests. apache will usually force-close after 100 requests in a single tcp connection
+ QTest::addColumn<int>("requestCount");
+
+ QTest::newRow("6 connections, no pipelining, 100 requests") << quint16(6) << false << 100;
+ QTest::newRow("1 connection, no pipelining, 100 requests") << quint16(1) << false << 100;
+ QTest::newRow("6 connections, pipelining allowed, 100 requests") << quint16(6) << true << 100;
+ QTest::newRow("1 connection, pipelining allowed, 100 requests") << quint16(1) << true << 100;
+}
+
+void tst_QHttpNetworkConnection::getMultiple()
+{
+ QFETCH(quint16, connectionCount);
+ QFETCH(bool, pipeliningAllowed);
+ QFETCH(int, requestCount);
+
+ QHttpNetworkConnection connection(connectionCount, QtNetworkSettings::serverName());
+
+ QList<QHttpNetworkRequest*> requests;
+ QList<QHttpNetworkReply*> replies;
+
+ for (int i = 0; i < requestCount; i++) {
+ // depending on what you use the results will vary.
+ // for the "real" results, use a URL that has "internet latency" for you. Then (6 connections, pipelining) will win.
+ // for LAN latency, you will possibly get that (1 connection, no pipelining) is the fastest
+ QHttpNetworkRequest *request = new QHttpNetworkRequest("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt");
+ // located in Berlin:
+ //QHttpNetworkRequest *request = new QHttpNetworkRequest(QUrl("http://klinsmann.nokia.trolltech.de/~berlin/qtcreatorad.gif"));
+ if (pipeliningAllowed)
+ request->setPipeliningAllowed(true);
+ requests.append(request);
+ QHttpNetworkReply *reply = connection.sendRequest(*request);
+ replies.append(reply);
+ }
+
+ QTime stopWatch;
+ stopWatch.start();
+ int finishedCount = 0;
+ do {
+ QCoreApplication::instance()->processEvents();
+ if (stopWatch.elapsed() >= 60000)
+ break;
+
+ finishedCount = 0;
+ for (int i = 0; i < replies.length(); i++)
+ if (replies.at(i)->isFinished())
+ finishedCount++;
+
+ } while (finishedCount != replies.length());
+
+ // redundant
+ for (int i = 0; i < replies.length(); i++)
+ QVERIFY(replies.at(i)->isFinished());
+
+ qDebug() << "===" << stopWatch.elapsed() << "msec ===";
+
+ qDeleteAll(requests);
+ qDeleteAll(replies);
+}
+
+void tst_QHttpNetworkConnection::getMultipleWithPipeliningAndMultiplePriorities()
+{
+ quint16 requestCount = 100;
+
+ // use 2 connections.
+ QHttpNetworkConnection connection(2, QtNetworkSettings::serverName());
+
+ QList<QHttpNetworkRequest*> requests;
+ QList<QHttpNetworkReply*> replies;
+
+ for (int i = 0; i < requestCount; i++) {
+ QHttpNetworkRequest *request = 0;
+ if (i % 3)
+ request = new QHttpNetworkRequest("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt", QHttpNetworkRequest::Get);
+ else
+ request = new QHttpNetworkRequest("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt", QHttpNetworkRequest::Head);
+
+ if (i % 2 || i % 3)
+ request->setPipeliningAllowed(true);
+
+ if (i % 3)
+ request->setPriority(QHttpNetworkRequest::HighPriority);
+ else if (i % 5)
+ request->setPriority(QHttpNetworkRequest::NormalPriority);
+ else if (i % 7)
+ request->setPriority(QHttpNetworkRequest::LowPriority);
+
+ requests.append(request);
+ QHttpNetworkReply *reply = connection.sendRequest(*request);
+ replies.append(reply);
+ }
+
+ QTime stopWatch;
+ stopWatch.start();
+ int finishedCount = 0;
+ do {
+ QCoreApplication::instance()->processEvents();
+ if (stopWatch.elapsed() >= 60000)
+ break;
+
+ finishedCount = 0;
+ for (int i = 0; i < replies.length(); i++)
+ if (replies.at(i)->isFinished())
+ finishedCount++;
+
+ } while (finishedCount != replies.length());
+
+ int pipelinedCount = 0;
+ for (int i = 0; i < replies.length(); i++) {
+ QVERIFY(replies.at(i)->isFinished());
+ QVERIFY (!(replies.at(i)->request().isPipeliningAllowed() == false
+ && replies.at(i)->isPipeliningUsed()));
+
+ if (replies.at(i)->isPipeliningUsed())
+ pipelinedCount++;
+ }
+
+ // We allow pipelining for every 2nd,3rd,4th,6th,8th,9th,10th etc request.
+ // Assume that half of the requests had been pipelined.
+ // (this is a very relaxed condition, when last measured 79 of 100
+ // requests had been pipelined)
+ QVERIFY(pipelinedCount >= requestCount / 2);
+
+ qDebug() << "===" << stopWatch.elapsed() << "msec ===";
+
+ qDeleteAll(requests);
+ qDeleteAll(replies);
+}
+
+class GetMultipleWithPrioritiesReceiver : public QObject
+{
+ Q_OBJECT
+public:
+ int highPrioReceived;
+ int lowPrioReceived;
+ int requestCount;
+ GetMultipleWithPrioritiesReceiver(int rq) : highPrioReceived(0), lowPrioReceived(0), requestCount(rq) { }
+public Q_SLOTS:
+ void finishedSlot() {
+ QHttpNetworkReply *reply = (QHttpNetworkReply*) sender();
+ if (reply->request().priority() == QHttpNetworkRequest::HighPriority)
+ highPrioReceived++;
+ else if (reply->request().priority() == QHttpNetworkRequest::LowPriority)
+ lowPrioReceived++;
+ else
+ QFAIL("Wrong priority!?");
+
+ QVERIFY(highPrioReceived + 7 >= lowPrioReceived);
+
+ if (highPrioReceived + lowPrioReceived == requestCount)
+ QTestEventLoop::instance().exitLoop();
+ }
+};
+
+void tst_QHttpNetworkConnection::getMultipleWithPriorities()
+{
+ quint16 requestCount = 100;
+ // use 2 connections.
+ QHttpNetworkConnection connection(2, QtNetworkSettings::serverName());
+ GetMultipleWithPrioritiesReceiver receiver(requestCount);
+ QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt");
+ QList<QHttpNetworkRequest*> requests;
+ QList<QHttpNetworkReply*> replies;
+
+ for (int i = 0; i < requestCount; i++) {
+ QHttpNetworkRequest *request = 0;
+ if (i % 3)
+ request = new QHttpNetworkRequest(url, QHttpNetworkRequest::Get);
+ else
+ request = new QHttpNetworkRequest(url, QHttpNetworkRequest::Head);
+
+ if (i % 2)
+ request->setPriority(QHttpNetworkRequest::HighPriority);
+ else
+ request->setPriority(QHttpNetworkRequest::LowPriority);
+
+ requests.append(request);
+ QHttpNetworkReply *reply = connection.sendRequest(*request);
+ connect(reply, SIGNAL(finished()), &receiver, SLOT(finishedSlot()));
+ replies.append(reply);
+ }
+
+ QTestEventLoop::instance().enterLoop(40);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ qDeleteAll(requests);
+ qDeleteAll(replies);
+}
+
+
+class GetEmptyWithPipeliningReceiver : public QObject
+{
+ Q_OBJECT
+public:
+ int receivedCount;
+ int requestCount;
+ GetEmptyWithPipeliningReceiver(int rq) : receivedCount(0),requestCount(rq) { }
+public Q_SLOTS:
+ void finishedSlot() {
+ QHttpNetworkReply *reply = (QHttpNetworkReply*) sender();
+ Q_UNUSED(reply);
+ receivedCount++;
+
+ if (receivedCount == requestCount)
+ QTestEventLoop::instance().exitLoop();
+ }
+};
+
+void tst_QHttpNetworkConnection::getEmptyWithPipelining()
+{
+ quint16 requestCount = 50;
+ // use 2 connections.
+ QHttpNetworkConnection connection(2, QtNetworkSettings::serverName());
+ GetEmptyWithPipeliningReceiver receiver(requestCount);
+
+ QUrl url("http://" + QtNetworkSettings::serverName() + "/cgi-bin/echo.cgi"); // a get on this = getting an empty file
+ QList<QHttpNetworkRequest*> requests;
+ QList<QHttpNetworkReply*> replies;
+
+ for (int i = 0; i < requestCount; i++) {
+ QHttpNetworkRequest *request = 0;
+ request = new QHttpNetworkRequest(url, QHttpNetworkRequest::Get);
+ request->setPipeliningAllowed(true);
+
+ requests.append(request);
+ QHttpNetworkReply *reply = connection.sendRequest(*request);
+ connect(reply, SIGNAL(finished()), &receiver, SLOT(finishedSlot()));
+ replies.append(reply);
+ }
+
+ QTestEventLoop::instance().enterLoop(20);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ qDeleteAll(requests);
+ qDeleteAll(replies);
+}
+
+class GetAndEverythingShouldBePipelinedReceiver : public QObject
+{
+ Q_OBJECT
+public:
+ int receivedCount;
+ int requestCount;
+ GetAndEverythingShouldBePipelinedReceiver(int rq) : receivedCount(0),requestCount(rq) { }
+public Q_SLOTS:
+ void finishedSlot() {
+ QHttpNetworkReply *reply = (QHttpNetworkReply*) sender();
+ Q_UNUSED(reply);
+ receivedCount++;
+
+ if (receivedCount == requestCount)
+ QTestEventLoop::instance().exitLoop();
+ }
+};
+
+void tst_QHttpNetworkConnection::getAndEverythingShouldBePipelined()
+{
+ quint16 requestCount = 100;
+ // use 1 connection.
+ QHttpNetworkConnection connection(1, QtNetworkSettings::serverName());
+ QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt");
+ QList<QHttpNetworkRequest*> requests;
+ QList<QHttpNetworkReply*> replies;
+
+ GetAndEverythingShouldBePipelinedReceiver receiver(requestCount);
+
+ for (int i = 0; i < requestCount; i++) {
+ QHttpNetworkRequest *request = 0;
+ request = new QHttpNetworkRequest(url, QHttpNetworkRequest::Get);
+ request->setPipeliningAllowed(true);
+ requests.append(request);
+ QHttpNetworkReply *reply = connection.sendRequest(*request);
+ connect(reply, SIGNAL(finished()), &receiver, SLOT(finishedSlot()));
+ replies.append(reply);
+ }
+ QTestEventLoop::instance().enterLoop(40);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ qDeleteAll(requests);
+ qDeleteAll(replies);
+
+}
+
+
+void tst_QHttpNetworkConnection::getAndThenDeleteObject_data()
+{
+ QTest::addColumn<bool>("replyFirst");
+
+ QTest::newRow("delete-reply-first") << true;
+ QTest::newRow("delete-connection-first") << false;
+}
+
+void tst_QHttpNetworkConnection::getAndThenDeleteObject()
+{
+ // yes, this will leak if the testcase fails. I don't care. It must not fail then :P
+ QHttpNetworkConnection *connection = new QHttpNetworkConnection(QtNetworkSettings::serverName());
+ QHttpNetworkRequest request("http://" + QtNetworkSettings::serverName() + "/qtest/bigfile");
+ QHttpNetworkReply *reply = connection->sendRequest(request);
+ reply->setDownstreamLimited(true);
+
+ QTime stopWatch;
+ stopWatch.start();
+ forever {
+ QCoreApplication::instance()->processEvents();
+ if (reply->bytesAvailable())
+ break;
+ if (stopWatch.elapsed() >= 30000)
+ break;
+ }
+
+ QVERIFY(reply->bytesAvailable());
+ QCOMPARE(reply->statusCode() ,200);
+ QVERIFY(!reply->isFinished()); // must not be finished
+
+ QFETCH(bool, replyFirst);
+
+ if (replyFirst) {
+ delete reply;
+ delete connection;
+ } else {
+ delete connection;
+ delete reply;
+ }
+}
+
+
+
+QTEST_MAIN(tst_QHttpNetworkConnection)
+#include "tst_qhttpnetworkconnection.moc"