tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 
       
    43 #include <QtTest/QtTest>
       
    44 #include "private/qhttpnetworkconnection_p.h"
       
    45 #include "private/qnoncontiguousbytedevice_p.h"
       
    46 #include <QAuthenticator>
       
    47 
       
    48 #include "../network-settings.h"
       
    49 
       
    50 class tst_QHttpNetworkConnection: public QObject
       
    51 {
       
    52     Q_OBJECT
       
    53 
       
    54 public:
       
    55     tst_QHttpNetworkConnection();
       
    56 
       
    57 public Q_SLOTS:
       
    58     void finishedReply();
       
    59     void finishedWithError(QNetworkReply::NetworkError errorCode, const QString &detail);
       
    60     void challenge401(const QHttpNetworkRequest &request, QAuthenticator *authenticator, const QHttpNetworkConnection *connection);
       
    61 #ifndef QT_NO_OPENSSL
       
    62     void sslErrors(const QList<QSslError> &errors);
       
    63 #endif
       
    64 private:
       
    65     bool finishedCalled;
       
    66     bool finishedWithErrorCalled;
       
    67     QNetworkReply::NetworkError netErrorCode;
       
    68 
       
    69 private Q_SLOTS:
       
    70     void init();
       
    71     void cleanup();
       
    72     void initTestCase();
       
    73     void cleanupTestCase();
       
    74 
       
    75     void options_data();
       
    76     void options();
       
    77     void get_data();
       
    78     void get();
       
    79     void head_data();
       
    80     void head();
       
    81     void post_data();
       
    82     void post();
       
    83     void put_data();
       
    84     void put();
       
    85     void _delete_data();
       
    86     void _delete();
       
    87     void trace_data();
       
    88     void trace();
       
    89     void _connect_data();
       
    90     void _connect();
       
    91 #ifndef QT_NO_COMPRESS
       
    92     void compression_data();
       
    93     void compression();
       
    94 #endif
       
    95 #ifndef QT_NO_OPENSSL
       
    96     void ignoresslerror_data();
       
    97     void ignoresslerror();
       
    98 #endif
       
    99 #ifdef QT_NO_OPENSSL
       
   100     void nossl_data();
       
   101     void nossl();
       
   102 #endif
       
   103     void get401_data();
       
   104     void get401();
       
   105 
       
   106     void getMultiple_data();
       
   107     void getMultiple();
       
   108     void getMultipleWithPipeliningAndMultiplePriorities();
       
   109     void getMultipleWithPriorities();
       
   110 };
       
   111 
       
   112 tst_QHttpNetworkConnection::tst_QHttpNetworkConnection()
       
   113 {
       
   114     Q_SET_DEFAULT_IAP
       
   115 }
       
   116 
       
   117 void tst_QHttpNetworkConnection::initTestCase()
       
   118 {
       
   119 }
       
   120 
       
   121 void tst_QHttpNetworkConnection::cleanupTestCase()
       
   122 {
       
   123 }
       
   124 
       
   125 void tst_QHttpNetworkConnection::init()
       
   126 {
       
   127 }
       
   128 
       
   129 void tst_QHttpNetworkConnection::cleanup()
       
   130 {
       
   131 }
       
   132 
       
   133 void tst_QHttpNetworkConnection::options_data()
       
   134 {
       
   135     // not tested yet
       
   136 }
       
   137 
       
   138 void tst_QHttpNetworkConnection::options()
       
   139 {
       
   140     QEXPECT_FAIL("", "not tested yet", Continue);
       
   141     QVERIFY(false);
       
   142 }
       
   143 
       
   144 void tst_QHttpNetworkConnection::head_data()
       
   145 {
       
   146     QTest::addColumn<QString>("protocol");
       
   147     QTest::addColumn<QString>("host");
       
   148     QTest::addColumn<QString>("path");
       
   149     QTest::addColumn<ushort>("port");
       
   150     QTest::addColumn<bool>("encrypt");
       
   151     QTest::addColumn<int>("statusCode");
       
   152     QTest::addColumn<QString>("statusString");
       
   153     QTest::addColumn<int>("contentLength");
       
   154 
       
   155     QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962;
       
   156     QTest::newRow("success-external") << "http://" << "www.ietf.org" << "/rfc/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962;
       
   157 
       
   158     QTest::newRow("failure-path") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << 404 << "Not Found" << -1;
       
   159     QTest::newRow("failure-protocol") << "" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 400 << "Bad Request" << -1;
       
   160 }
       
   161 
       
   162 void tst_QHttpNetworkConnection::head()
       
   163 {
       
   164     QFETCH(QString, protocol);
       
   165     QFETCH(QString, host);
       
   166     QFETCH(QString, path);
       
   167     QFETCH(ushort, port);
       
   168     QFETCH(bool, encrypt);
       
   169     QFETCH(int, statusCode);
       
   170     QFETCH(QString, statusString);
       
   171     QFETCH(int, contentLength);
       
   172 
       
   173     QHttpNetworkConnection connection(host);
       
   174     QCOMPARE(connection.port(), port);
       
   175     QCOMPARE(connection.hostName(), host);
       
   176     if (encrypt)
       
   177         connection.enableEncryption();
       
   178     QCOMPARE(connection.isEncrypted(), encrypt);
       
   179 
       
   180     QHttpNetworkRequest request(protocol + host + path, QHttpNetworkRequest::Head);
       
   181     QHttpNetworkReply *reply = connection.sendRequest(request);
       
   182 
       
   183     QTime stopWatch;
       
   184     stopWatch.start();
       
   185     do {
       
   186         QCoreApplication::instance()->processEvents();
       
   187         if (stopWatch.elapsed() >= 30000)
       
   188             break;
       
   189     } while (!reply->isFinished());
       
   190 
       
   191     QCOMPARE(reply->statusCode(), statusCode);
       
   192     QCOMPARE(reply->reasonPhrase(), statusString);
       
   193     // only check it if it is set
       
   194     if (reply->contentLength() != -1)
       
   195         QCOMPARE(reply->contentLength(), qint64(contentLength));
       
   196 
       
   197     QVERIFY(reply->isFinished());
       
   198 
       
   199     delete reply;
       
   200 }
       
   201 
       
   202 void tst_QHttpNetworkConnection::get_data()
       
   203 {
       
   204     QTest::addColumn<QString>("protocol");
       
   205     QTest::addColumn<QString>("host");
       
   206     QTest::addColumn<QString>("path");
       
   207     QTest::addColumn<ushort>("port");
       
   208     QTest::addColumn<bool>("encrypt");
       
   209     QTest::addColumn<int>("statusCode");
       
   210     QTest::addColumn<QString>("statusString");
       
   211     QTest::addColumn<int>("contentLength");
       
   212     QTest::addColumn<int>("downloadSize");
       
   213 
       
   214     QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962 << 25962;
       
   215     QTest::newRow("success-external") << "http://" << "www.ietf.org" << "/rfc/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962 << 25962;
       
   216 
       
   217     QTest::newRow("failure-path") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << 404 << "Not Found" << -1 << 997 + QtNetworkSettings::serverName().size();
       
   218     QTest::newRow("failure-protocol") << "" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 400 << "Bad Request" << -1 << 930 + QtNetworkSettings::serverName().size();
       
   219 }
       
   220 
       
   221 void tst_QHttpNetworkConnection::get()
       
   222 {
       
   223     QFETCH(QString, protocol);
       
   224     QFETCH(QString, host);
       
   225     QFETCH(QString, path);
       
   226     QFETCH(ushort, port);
       
   227     QFETCH(bool, encrypt);
       
   228     QFETCH(int, statusCode);
       
   229     QFETCH(QString, statusString);
       
   230     QFETCH(int, contentLength);
       
   231     QFETCH(int, downloadSize);
       
   232 
       
   233     QHttpNetworkConnection connection(host);
       
   234     QCOMPARE(connection.port(), port);
       
   235     QCOMPARE(connection.hostName(), host);
       
   236     if (encrypt)
       
   237         connection.enableEncryption();
       
   238     QCOMPARE(connection.isEncrypted(), encrypt);
       
   239 
       
   240     QHttpNetworkRequest request(protocol + host + path);
       
   241     QHttpNetworkReply *reply = connection.sendRequest(request);
       
   242 
       
   243     QTime stopWatch;
       
   244     stopWatch.start();
       
   245     forever {
       
   246         QCoreApplication::instance()->processEvents();
       
   247         if (reply->bytesAvailable())
       
   248             break;
       
   249         if (stopWatch.elapsed() >= 30000)
       
   250             break;
       
   251     }
       
   252 
       
   253     QCOMPARE(reply->statusCode(), statusCode);
       
   254     QCOMPARE(reply->reasonPhrase(), statusString);
       
   255     // only check it if it is set
       
   256     if (reply->contentLength() != -1)
       
   257         QCOMPARE(reply->contentLength(), qint64(contentLength));
       
   258 
       
   259     stopWatch.start();
       
   260     QByteArray ba;
       
   261     do {
       
   262         QCoreApplication::instance()->processEvents();
       
   263         while (reply->bytesAvailable())
       
   264             ba += reply->readAny();
       
   265         if (stopWatch.elapsed() >= 30000)
       
   266             break;
       
   267     } while (!reply->isFinished());
       
   268 
       
   269     QVERIFY(reply->isFinished());
       
   270     QCOMPARE(ba.size(), downloadSize);
       
   271 
       
   272     delete reply;
       
   273 }
       
   274 
       
   275 void tst_QHttpNetworkConnection::finishedReply()
       
   276 {
       
   277     finishedCalled = true;
       
   278 }
       
   279 
       
   280 void tst_QHttpNetworkConnection::finishedWithError(QNetworkReply::NetworkError errorCode, const QString &detail)
       
   281 {
       
   282     Q_UNUSED(detail)
       
   283     finishedWithErrorCalled = true;
       
   284     netErrorCode = errorCode;
       
   285 }
       
   286 
       
   287 void tst_QHttpNetworkConnection::put_data()
       
   288 {
       
   289 
       
   290     QTest::addColumn<QString>("protocol");
       
   291     QTest::addColumn<QString>("host");
       
   292     QTest::addColumn<QString>("path");
       
   293     QTest::addColumn<ushort>("port");
       
   294     QTest::addColumn<bool>("encrypt");
       
   295     QTest::addColumn<QString>("data");
       
   296     QTest::addColumn<bool>("succeed");
       
   297 
       
   298     QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/dav/file1.txt" << ushort(80) << false << "Hello World\nEnd of file\n"<<true;
       
   299     QTest::newRow("fail-internal") << "http://" << QtNetworkSettings::serverName() << "/dav2/file1.txt" << ushort(80) << false << "Hello World\nEnd of file\n"<<false;
       
   300     QTest::newRow("fail-host") << "http://" << "fluke-nosuchhost.troll.no" << "/dav2/file1.txt" << ushort(80) << false << "Hello World\nEnd of file\n"<<false;
       
   301 }
       
   302 
       
   303 void tst_QHttpNetworkConnection::put()
       
   304 {
       
   305     QFETCH(QString, protocol);
       
   306     QFETCH(QString, host);
       
   307     QFETCH(QString, path);
       
   308     QFETCH(ushort, port);
       
   309     QFETCH(bool, encrypt);
       
   310     QFETCH(QString, data);
       
   311     QFETCH(bool, succeed);
       
   312 
       
   313     QHttpNetworkConnection connection(host);
       
   314     QCOMPARE(connection.port(), port);
       
   315     QCOMPARE(connection.hostName(), host);
       
   316     if (encrypt)
       
   317         connection.enableEncryption();
       
   318     QCOMPARE(connection.isEncrypted(), encrypt);
       
   319 
       
   320     QHttpNetworkRequest request(protocol + host + path, QHttpNetworkRequest::Put);
       
   321 
       
   322     QByteArray array = data.toLatin1();
       
   323     QNonContiguousByteDevice *bd = QNonContiguousByteDeviceFactory::create(&array);
       
   324     bd->setParent(this);
       
   325     request.setUploadByteDevice(bd);
       
   326 
       
   327     finishedCalled = false;
       
   328     finishedWithErrorCalled = false;
       
   329 
       
   330     QHttpNetworkReply *reply = connection.sendRequest(request);
       
   331     connect(reply, SIGNAL(finished()), SLOT(finishedReply()));
       
   332     connect(reply, SIGNAL(finishedWithError(QNetworkReply::NetworkError, const QString &)),
       
   333         SLOT(finishedWithError(QNetworkReply::NetworkError, const QString &)));
       
   334     connect(&connection, SIGNAL(error(QNetworkReply::NetworkError, const QString &)),
       
   335         SLOT(finishedWithError(QNetworkReply::NetworkError, const QString &)));
       
   336 
       
   337     QTime stopWatch;
       
   338     stopWatch.start();
       
   339     do {
       
   340         QCoreApplication::instance()->processEvents();
       
   341         if (stopWatch.elapsed() >= 30000)
       
   342             break;
       
   343     } while (!reply->isFinished() && !finishedCalled && !finishedWithErrorCalled);
       
   344 
       
   345     if (reply->isFinished()) {
       
   346         QByteArray ba;
       
   347         while (reply->bytesAvailable())
       
   348             ba += reply->readAny();
       
   349     } else if(finishedWithErrorCalled) {
       
   350         if(!succeed) {
       
   351             delete reply;
       
   352             return;
       
   353         } else {
       
   354             QFAIL("Error in PUT");
       
   355         }
       
   356     } else {
       
   357         QFAIL("PUT timed out");
       
   358     }
       
   359 
       
   360     int status = reply->statusCode();
       
   361     if (status != 200 && status != 201 && status != 204) {
       
   362         if (succeed) {
       
   363             qDebug()<<"PUT failed, Status Code:" <<status;
       
   364             QFAIL("Error in PUT");
       
   365         }
       
   366     } else {
       
   367         if (!succeed) {
       
   368             qDebug()<<"PUT Should fail, Status Code:" <<status;
       
   369             QFAIL("Error in PUT");
       
   370         }
       
   371     }
       
   372     delete reply;
       
   373 }
       
   374 
       
   375 void tst_QHttpNetworkConnection::post_data()
       
   376 {
       
   377     QTest::addColumn<QString>("protocol");
       
   378     QTest::addColumn<QString>("host");
       
   379     QTest::addColumn<QString>("path");
       
   380     QTest::addColumn<ushort>("port");
       
   381     QTest::addColumn<bool>("encrypt");
       
   382     QTest::addColumn<QString>("data");
       
   383     QTest::addColumn<int>("statusCode");
       
   384     QTest::addColumn<QString>("statusString");
       
   385     QTest::addColumn<int>("contentLength");
       
   386     QTest::addColumn<int>("downloadSize");
       
   387 
       
   388     QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/cgi-bin/echo.cgi" << ushort(80) << false << "7 bytes" << 200 << "OK" << 7 << 7;
       
   389     QTest::newRow("failure-internal") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << "Hello World" << 404 << "Not Found" << -1 << 997 + QtNetworkSettings::serverName().size();
       
   390 }
       
   391 
       
   392 void tst_QHttpNetworkConnection::post()
       
   393 {
       
   394     QFETCH(QString, protocol);
       
   395     QFETCH(QString, host);
       
   396     QFETCH(QString, path);
       
   397     QFETCH(ushort, port);
       
   398     QFETCH(bool, encrypt);
       
   399     QFETCH(QString, data);
       
   400     QFETCH(int, statusCode);
       
   401     QFETCH(QString, statusString);
       
   402     QFETCH(int, contentLength);
       
   403     QFETCH(int, downloadSize);
       
   404 
       
   405     QHttpNetworkConnection connection(host);
       
   406     QCOMPARE(connection.port(), port);
       
   407     QCOMPARE(connection.hostName(), host);
       
   408     if (encrypt)
       
   409         connection.enableEncryption();
       
   410     QCOMPARE(connection.isEncrypted(), encrypt);
       
   411 
       
   412     QHttpNetworkRequest request(protocol + host + path, QHttpNetworkRequest::Post);
       
   413 
       
   414     QByteArray array = data.toLatin1();
       
   415     QNonContiguousByteDevice *bd = QNonContiguousByteDeviceFactory::create(&array);
       
   416     bd->setParent(this);
       
   417     request.setUploadByteDevice(bd);
       
   418 
       
   419     QHttpNetworkReply *reply = connection.sendRequest(request);
       
   420 
       
   421     QTime stopWatch;
       
   422     stopWatch.start();
       
   423     forever {
       
   424         QCoreApplication::instance()->processEvents();
       
   425         if (reply->bytesAvailable())
       
   426             break;
       
   427         if (stopWatch.elapsed() >= 30000)
       
   428             break;
       
   429     }
       
   430 
       
   431     QCOMPARE(reply->statusCode(), statusCode);
       
   432     QCOMPARE(reply->reasonPhrase(), statusString);
       
   433 
       
   434     qint64 cLen = reply->contentLength();
       
   435     if (cLen==-1) {
       
   436         // HTTP 1.1 server may respond with chunked encoding and in that
       
   437         // case contentLength is not present in reply -> verify that it is the case
       
   438         QByteArray transferEnc = reply->headerField("Transfer-Encoding");
       
   439         QCOMPARE(transferEnc, QByteArray("chunked"));
       
   440     } else {
       
   441         QCOMPARE(cLen, qint64(contentLength));
       
   442     }
       
   443 
       
   444     stopWatch.start();
       
   445     QByteArray ba;
       
   446     do {
       
   447         QCoreApplication::instance()->processEvents();
       
   448         while (reply->bytesAvailable())
       
   449             ba += reply->readAny();
       
   450         if (stopWatch.elapsed() >= 30000)
       
   451             break;
       
   452     } while (!reply->isFinished());
       
   453 
       
   454     QVERIFY(reply->isFinished());
       
   455     QCOMPARE(ba.size(), downloadSize);
       
   456 
       
   457     delete reply;
       
   458 }
       
   459 
       
   460 void tst_QHttpNetworkConnection::_delete_data()
       
   461 {
       
   462     // not tested yet
       
   463 }
       
   464 
       
   465 void tst_QHttpNetworkConnection::_delete()
       
   466 {
       
   467     QEXPECT_FAIL("", "not tested yet", Continue);
       
   468     QVERIFY(false);
       
   469 }
       
   470 
       
   471 void tst_QHttpNetworkConnection::trace_data()
       
   472 {
       
   473     // not tested yet
       
   474 }
       
   475 
       
   476 void tst_QHttpNetworkConnection::trace()
       
   477 {
       
   478     QEXPECT_FAIL("", "not tested yet", Continue);
       
   479     QVERIFY(false);
       
   480 }
       
   481 
       
   482 void tst_QHttpNetworkConnection::_connect_data()
       
   483 {
       
   484     // not tested yet
       
   485 }
       
   486 
       
   487 void tst_QHttpNetworkConnection::_connect()
       
   488 {
       
   489     QEXPECT_FAIL("", "not tested yet", Continue);
       
   490     QVERIFY(false);
       
   491 }
       
   492 
       
   493 void tst_QHttpNetworkConnection::challenge401(const QHttpNetworkRequest &request,
       
   494                                                         QAuthenticator *authenticator,
       
   495                                                         const QHttpNetworkConnection *connection)
       
   496 {
       
   497     Q_UNUSED(request)
       
   498     Q_UNUSED(connection)
       
   499 
       
   500     QHttpNetworkConnection *c = qobject_cast<QHttpNetworkConnection*>(sender());
       
   501     if (connection) {
       
   502         QVariant val = c->property("setCredentials");
       
   503         if (val.toBool()) {
       
   504             QVariant user = c->property("username");
       
   505             QVariant password = c->property("password");
       
   506             authenticator->setUser(user.toString());
       
   507             authenticator->setPassword(password.toString());
       
   508             c->setProperty("setCredentials", false);
       
   509         }
       
   510     }
       
   511 }
       
   512 
       
   513 void tst_QHttpNetworkConnection::get401_data()
       
   514 {
       
   515     QTest::addColumn<QString>("protocol");
       
   516     QTest::addColumn<QString>("host");
       
   517     QTest::addColumn<QString>("path");
       
   518     QTest::addColumn<ushort>("port");
       
   519     QTest::addColumn<bool>("encrypt");
       
   520     QTest::addColumn<bool>("setCredentials");
       
   521     QTest::addColumn<QString>("username");
       
   522     QTest::addColumn<QString>("password");
       
   523     QTest::addColumn<int>("statusCode");
       
   524 
       
   525     QTest::newRow("no-credentials") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs-auth/index.html" << ushort(80) << false << false << "" << ""<<401;
       
   526     QTest::newRow("invalid-credentials") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs-auth/index.html" << ushort(80) << false << true << "test" << "test"<<401;
       
   527     QTest::newRow("valid-credentials") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs-auth/index.html" << ushort(80) << false << true << "httptest" << "httptest"<<200;
       
   528     QTest::newRow("digest-authentication-invalid") << "http://" << QtNetworkSettings::serverName() << "/qtest/auth-digest/index.html" << ushort(80) << false << true << "wrong" << "wrong"<<401;
       
   529     QTest::newRow("digest-authentication-valid") << "http://" << QtNetworkSettings::serverName() << "/qtest/auth-digest/index.html" << ushort(80) << false << true << "httptest" << "httptest"<<200;
       
   530 }
       
   531 
       
   532 void tst_QHttpNetworkConnection::get401()
       
   533 {
       
   534     QFETCH(QString, protocol);
       
   535     QFETCH(QString, host);
       
   536     QFETCH(QString, path);
       
   537     QFETCH(ushort, port);
       
   538     QFETCH(bool, encrypt);
       
   539     QFETCH(bool, setCredentials);
       
   540     QFETCH(QString, username);
       
   541     QFETCH(QString, password);
       
   542     QFETCH(int, statusCode);
       
   543 
       
   544     QHttpNetworkConnection connection(host, port, encrypt);
       
   545     QCOMPARE(connection.port(), port);
       
   546     QCOMPARE(connection.hostName(), host);
       
   547     if (encrypt)
       
   548         connection.enableEncryption();
       
   549     QCOMPARE(connection.isEncrypted(), encrypt);
       
   550     connect(&connection, SIGNAL(authenticationRequired(const QHttpNetworkRequest&, QAuthenticator *, const QHttpNetworkConnection*)),
       
   551                 SLOT(challenge401(const QHttpNetworkRequest&, QAuthenticator *, const QHttpNetworkConnection*)));
       
   552     connection.setProperty("setCredentials", setCredentials);
       
   553     connection.setProperty("username", username);
       
   554     connection.setProperty("password", password);
       
   555 
       
   556     QHttpNetworkRequest request(protocol + host + path);
       
   557     QHttpNetworkReply *reply = connection.sendRequest(request);
       
   558 
       
   559     finishedCalled = false;
       
   560     finishedWithErrorCalled = false;
       
   561 
       
   562     connect(reply, SIGNAL(finished()), SLOT(finishedReply()));
       
   563     connect(reply, SIGNAL(finishedWithError(QNetworkReply::NetworkError, const QString &)),
       
   564         SLOT(finishedWithError(QNetworkReply::NetworkError, const QString &)));
       
   565 
       
   566     QTime stopWatch;
       
   567     stopWatch.start();
       
   568     forever {
       
   569         QCoreApplication::instance()->processEvents();
       
   570         if (finishedCalled)
       
   571             break;
       
   572         if (finishedWithErrorCalled)
       
   573             break;
       
   574         if (stopWatch.elapsed() >= 30000)
       
   575             break;
       
   576     }
       
   577     QCOMPARE(reply->statusCode(), statusCode);
       
   578     delete reply;
       
   579 }
       
   580 
       
   581 #ifndef QT_NO_COMPRESS
       
   582 void tst_QHttpNetworkConnection::compression_data()
       
   583 {
       
   584     QTest::addColumn<QString>("protocol");
       
   585     QTest::addColumn<QString>("host");
       
   586     QTest::addColumn<QString>("path");
       
   587     QTest::addColumn<ushort>("port");
       
   588     QTest::addColumn<bool>("encrypt");
       
   589     QTest::addColumn<int>("statusCode");
       
   590     QTest::addColumn<QString>("statusString");
       
   591     QTest::addColumn<int>("contentLength");
       
   592     QTest::addColumn<int>("downloadSize");
       
   593     QTest::addColumn<bool>("autoCompress");
       
   594     QTest::addColumn<QString>("contentCoding");
       
   595 
       
   596     QTest::newRow("success-autogzip-temp") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs/rfc2616.html" << ushort(80) << false << 200 << "OK" << -1 << 418321 << true << "";
       
   597     QTest::newRow("success-nogzip-temp") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfcs/rfc2616.html" << ushort(80) << false << 200 << "OK" << 418321 << 418321 << false << "identity";
       
   598     QTest::newRow("success-manualgzip-temp") << "http://" << QtNetworkSettings::serverName() << "/qtest/deflate/rfc2616.html" << ushort(80) << false << 200 << "OK" << 119124 << 119124 << false << "gzip";
       
   599 
       
   600 }
       
   601 
       
   602 void tst_QHttpNetworkConnection::compression()
       
   603 {
       
   604     QFETCH(QString, protocol);
       
   605     QFETCH(QString, host);
       
   606     QFETCH(QString, path);
       
   607     QFETCH(ushort, port);
       
   608     QFETCH(bool, encrypt);
       
   609     QFETCH(int, statusCode);
       
   610     QFETCH(QString, statusString);
       
   611     QFETCH(int, contentLength);
       
   612     QFETCH(int, downloadSize);
       
   613     QFETCH(bool, autoCompress);
       
   614     QFETCH(QString, contentCoding);
       
   615 
       
   616     QHttpNetworkConnection connection(host);
       
   617     QCOMPARE(connection.port(), port);
       
   618     QCOMPARE(connection.hostName(), host);
       
   619     if (encrypt)
       
   620         connection.enableEncryption();
       
   621     QCOMPARE(connection.isEncrypted(), encrypt);
       
   622 
       
   623     QHttpNetworkRequest request(protocol + host + path);
       
   624     if (!autoCompress)
       
   625         request.setHeaderField("Accept-Encoding", contentCoding.toLatin1());
       
   626     QHttpNetworkReply *reply = connection.sendRequest(request);
       
   627     QTime stopWatch;
       
   628     stopWatch.start();
       
   629     forever {
       
   630         QCoreApplication::instance()->processEvents();
       
   631         if (reply->bytesAvailable())
       
   632             break;
       
   633         if (stopWatch.elapsed() >= 30000)
       
   634             break;
       
   635     }
       
   636 
       
   637     QCOMPARE(reply->statusCode(), statusCode);
       
   638     QCOMPARE(reply->reasonPhrase(), statusString);
       
   639     bool isLengthOk = (reply->contentLength() == qint64(contentLength)
       
   640     				  || reply->contentLength() == qint64(downloadSize));
       
   641 
       
   642     QVERIFY(isLengthOk);
       
   643 
       
   644     stopWatch.start();
       
   645     QByteArray ba;
       
   646     do {
       
   647         QCoreApplication::instance()->processEvents();
       
   648         while (reply->bytesAvailable())
       
   649             ba += reply->readAny();
       
   650         if (stopWatch.elapsed() >= 30000)
       
   651             break;
       
   652     } while (!reply->isFinished());
       
   653 
       
   654     QVERIFY(reply->isFinished());
       
   655     QCOMPARE(ba.size(), downloadSize);
       
   656 
       
   657     delete reply;
       
   658 }
       
   659 #endif
       
   660 
       
   661 #ifndef QT_NO_OPENSSL
       
   662 void tst_QHttpNetworkConnection::sslErrors(const QList<QSslError> &errors)
       
   663 {
       
   664     Q_UNUSED(errors)
       
   665 
       
   666     QHttpNetworkConnection *connection = qobject_cast<QHttpNetworkConnection*>(sender());
       
   667     if (connection) {
       
   668         QVariant val = connection->property("ignoreFromSignal");
       
   669         if (val.toBool())
       
   670             connection->ignoreSslErrors();
       
   671         finishedWithErrorCalled = true;
       
   672     }
       
   673 }
       
   674 
       
   675 void tst_QHttpNetworkConnection::ignoresslerror_data()
       
   676 {
       
   677     QTest::addColumn<QString>("protocol");
       
   678     QTest::addColumn<QString>("host");
       
   679     QTest::addColumn<QString>("path");
       
   680     QTest::addColumn<ushort>("port");
       
   681     QTest::addColumn<bool>("encrypt");
       
   682     QTest::addColumn<bool>("ignoreInit");
       
   683     QTest::addColumn<bool>("ignoreFromSignal");
       
   684     QTest::addColumn<int>("statusCode");
       
   685 
       
   686     // This test will work only if the website has ssl errors.
       
   687     // fluke's certificate is signed by a non-standard authority.
       
   688     // Since we don't introduce that CA into the SSL verification chain,
       
   689     // connecting should fail.
       
   690     QTest::newRow("success-init") << "https://" << QtNetworkSettings::serverName() << "/" << ushort(443) << true << true << false << 200;
       
   691     QTest::newRow("success-fromSignal") << "https://" << QtNetworkSettings::serverName() << "/" << ushort(443) << true << false << true << 200;
       
   692     QTest::newRow("failure") << "https://" << QtNetworkSettings::serverName() << "/" << ushort(443) << true << false << false << 100;
       
   693 }
       
   694 
       
   695 void tst_QHttpNetworkConnection::ignoresslerror()
       
   696 {
       
   697     QFETCH(QString, protocol);
       
   698     QFETCH(QString, host);
       
   699     QFETCH(QString, path);
       
   700     QFETCH(ushort, port);
       
   701     QFETCH(bool, encrypt);
       
   702     QFETCH(bool, ignoreInit);
       
   703     QFETCH(bool, ignoreFromSignal);
       
   704     QFETCH(int, statusCode);
       
   705 
       
   706     QHttpNetworkConnection connection(host, port, encrypt);
       
   707     QCOMPARE(connection.port(), port);
       
   708     QCOMPARE(connection.hostName(), host);
       
   709     if (encrypt)
       
   710         connection.enableEncryption();
       
   711     if (ignoreInit)
       
   712         connection.ignoreSslErrors();
       
   713     QCOMPARE(connection.isEncrypted(), encrypt);
       
   714     connect(&connection, SIGNAL(sslErrors(const QList<QSslError>&)),
       
   715         SLOT(sslErrors(const QList<QSslError>&)));
       
   716     connection.setProperty("ignoreFromSignal", ignoreFromSignal);
       
   717 
       
   718     QHttpNetworkRequest request(protocol + host + path);
       
   719     QHttpNetworkReply *reply = connection.sendRequest(request);
       
   720 
       
   721     finishedWithErrorCalled = false;
       
   722 
       
   723     connect(reply, SIGNAL(finished()), SLOT(finishedReply()));
       
   724 
       
   725     QTime stopWatch;
       
   726     stopWatch.start();
       
   727     forever {
       
   728         QCoreApplication::instance()->processEvents();
       
   729         if (reply->bytesAvailable())
       
   730             break;
       
   731         if (statusCode == 100 && finishedWithErrorCalled)
       
   732             break;
       
   733         if (stopWatch.elapsed() >= 30000)
       
   734             break;
       
   735     }
       
   736     QCOMPARE(reply->statusCode(), statusCode);
       
   737     delete reply;
       
   738 }
       
   739 #endif
       
   740 
       
   741 #ifdef QT_NO_OPENSSL
       
   742 Q_DECLARE_METATYPE(QNetworkReply::NetworkError)
       
   743 void tst_QHttpNetworkConnection::nossl_data()
       
   744 {
       
   745     QTest::addColumn<QString>("protocol");
       
   746     QTest::addColumn<QString>("host");
       
   747     QTest::addColumn<QString>("path");
       
   748     QTest::addColumn<ushort>("port");
       
   749     QTest::addColumn<bool>("encrypt");
       
   750     QTest::addColumn<QNetworkReply::NetworkError>("networkError");
       
   751 
       
   752     QTest::newRow("protocol-error") << "https://" << QtNetworkSettings::serverName() << "/" << ushort(443) << true <<QNetworkReply::ProtocolUnknownError;
       
   753 }
       
   754 
       
   755 void tst_QHttpNetworkConnection::nossl()
       
   756 {
       
   757     QFETCH(QString, protocol);
       
   758     QFETCH(QString, host);
       
   759     QFETCH(QString, path);
       
   760     QFETCH(ushort, port);
       
   761     QFETCH(bool, encrypt);
       
   762     QFETCH(QNetworkReply::NetworkError, networkError);
       
   763 
       
   764     QHttpNetworkConnection connection(host, port, encrypt);
       
   765     QCOMPARE(connection.port(), port);
       
   766     QCOMPARE(connection.hostName(), host);
       
   767     if (encrypt)
       
   768         connection.enableEncryption();
       
   769 
       
   770     QHttpNetworkRequest request(protocol + host + path);
       
   771     QHttpNetworkReply *reply = connection.sendRequest(request);
       
   772 
       
   773     finishedWithErrorCalled = false;
       
   774     netErrorCode = QNetworkReply::NoError;
       
   775 
       
   776     connect(reply, SIGNAL(finished()), SLOT(finishedReply()));
       
   777     connect(reply, SIGNAL(finishedWithError(QNetworkReply::NetworkError, const QString &)),
       
   778         SLOT(finishedWithError(QNetworkReply::NetworkError, const QString &)));
       
   779 
       
   780     QTime stopWatch;
       
   781     stopWatch.start();
       
   782     forever {
       
   783         QCoreApplication::instance()->processEvents();
       
   784         if (finishedWithErrorCalled)
       
   785             break;
       
   786         if (stopWatch.elapsed() >= 30000)
       
   787             break;
       
   788     }
       
   789     QCOMPARE(netErrorCode, networkError);
       
   790     delete reply;
       
   791 }
       
   792 #endif
       
   793 
       
   794 
       
   795 void tst_QHttpNetworkConnection::getMultiple_data()
       
   796 {
       
   797     QTest::addColumn<quint16>("connectionCount");
       
   798     QTest::addColumn<bool>("pipeliningAllowed");
       
   799     // send 100 requests. apache will usually force-close after 100 requests in a single tcp connection
       
   800     QTest::addColumn<int>("requestCount");
       
   801 
       
   802     QTest::newRow("6 connections, no pipelining, 100 requests")  << quint16(6) << false << 100;
       
   803     QTest::newRow("1 connection, no pipelining, 100 requests")  << quint16(1) << false << 100;
       
   804     QTest::newRow("6 connections, pipelining allowed, 100 requests")  << quint16(2) << true << 100;
       
   805     QTest::newRow("1 connection, pipelining allowed, 100 requests")  << quint16(1) << true << 100;
       
   806 }
       
   807 
       
   808 void tst_QHttpNetworkConnection::getMultiple()
       
   809 {
       
   810     QFETCH(quint16, connectionCount);
       
   811     QFETCH(bool, pipeliningAllowed);
       
   812     QFETCH(int, requestCount);
       
   813 
       
   814     QHttpNetworkConnection connection(connectionCount, QtNetworkSettings::serverName());
       
   815 
       
   816     QList<QHttpNetworkRequest*> requests;
       
   817     QList<QHttpNetworkReply*> replies;
       
   818 
       
   819     for (int i = 0; i < requestCount; i++) {
       
   820         // depending on what you use the results will vary.
       
   821         // for the "real" results, use a URL that has "internet latency" for you. Then (6 connections, pipelining) will win.
       
   822         // for LAN latency, you will possibly get that (1 connection, no pipelining) is the fastest
       
   823         QHttpNetworkRequest *request = new QHttpNetworkRequest("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt");
       
   824         // located in Berlin:
       
   825         //QHttpNetworkRequest *request = new QHttpNetworkRequest(QUrl("http://klinsmann.nokia.trolltech.de/~berlin/qtcreatorad.gif"));
       
   826         if (pipeliningAllowed)
       
   827             request->setPipeliningAllowed(true);
       
   828         requests.append(request);
       
   829         QHttpNetworkReply *reply = connection.sendRequest(*request);
       
   830         replies.append(reply);
       
   831     }
       
   832 
       
   833     QTime stopWatch;
       
   834     stopWatch.start();
       
   835     int finishedCount = 0;
       
   836     do {
       
   837         QCoreApplication::instance()->processEvents();
       
   838         if (stopWatch.elapsed() >= 60000)
       
   839             break;
       
   840 
       
   841         finishedCount = 0;
       
   842         for (int i = 0; i < replies.length(); i++)
       
   843             if (replies.at(i)->isFinished())
       
   844                 finishedCount++;
       
   845 
       
   846     } while (finishedCount != replies.length());
       
   847 
       
   848     // redundant
       
   849     for (int i = 0; i < replies.length(); i++)
       
   850         QVERIFY(replies.at(i)->isFinished());
       
   851 
       
   852     qDebug() << "===" << stopWatch.elapsed() << "msec ===";
       
   853 
       
   854     qDeleteAll(requests);
       
   855     qDeleteAll(replies);
       
   856 }
       
   857 
       
   858 void tst_QHttpNetworkConnection::getMultipleWithPipeliningAndMultiplePriorities()
       
   859 {
       
   860     quint16 requestCount = 100;
       
   861 
       
   862     // use 2 connections.
       
   863     QHttpNetworkConnection connection(2, QtNetworkSettings::serverName());
       
   864 
       
   865     QList<QHttpNetworkRequest*> requests;
       
   866     QList<QHttpNetworkReply*> replies;
       
   867 
       
   868     for (int i = 0; i < requestCount; i++) {
       
   869 
       
   870         QHttpNetworkRequest *request = new QHttpNetworkRequest("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt");
       
   871         
       
   872         if (i % 2 || i % 3)
       
   873             request->setPipeliningAllowed(true);
       
   874         
       
   875         if (i % 3)
       
   876             request->setPriority(QHttpNetworkRequest::HighPriority);
       
   877         else if (i % 5)
       
   878             request->setPriority(QHttpNetworkRequest::NormalPriority);
       
   879         else if (i % 7)
       
   880             request->setPriority(QHttpNetworkRequest::LowPriority);
       
   881         
       
   882         requests.append(request);
       
   883         QHttpNetworkReply *reply = connection.sendRequest(*request);
       
   884         replies.append(reply);
       
   885     }
       
   886 
       
   887     QTime stopWatch;
       
   888     stopWatch.start();
       
   889     int finishedCount = 0;
       
   890     do {
       
   891         QCoreApplication::instance()->processEvents();
       
   892         if (stopWatch.elapsed() >= 60000)
       
   893             break;
       
   894 
       
   895         finishedCount = 0;
       
   896         for (int i = 0; i < replies.length(); i++)
       
   897             if (replies.at(i)->isFinished())
       
   898                 finishedCount++;
       
   899 
       
   900     } while (finishedCount != replies.length());
       
   901 
       
   902     int pipelinedCount = 0;
       
   903     for (int i = 0; i < replies.length(); i++) {
       
   904         QVERIFY(replies.at(i)->isFinished());
       
   905         QVERIFY (!(replies.at(i)->request().isPipeliningAllowed() == false
       
   906             && replies.at(i)->isPipeliningUsed()));
       
   907 
       
   908         if (replies.at(i)->isPipeliningUsed())
       
   909             pipelinedCount++;
       
   910     }
       
   911 
       
   912     // We allow pipelining for every 2nd,3rd,4th,6th,8th,9th,10th etc request.
       
   913     // Assume that half of the requests had been pipelined.
       
   914     // (this is a very relaxed condition, when last measured 79 of 100
       
   915     // requests had been pipelined)
       
   916     QVERIFY(pipelinedCount >= requestCount / 2);
       
   917 
       
   918     qDebug() << "===" << stopWatch.elapsed() << "msec ===";
       
   919 
       
   920     qDeleteAll(requests);
       
   921     qDeleteAll(replies);
       
   922 }
       
   923 
       
   924 class GetMultipleWithPrioritiesReceiver : public QObject
       
   925 {
       
   926     Q_OBJECT
       
   927 public:
       
   928     int highPrioReceived;
       
   929     int lowPrioReceived;
       
   930     int requestCount;
       
   931     GetMultipleWithPrioritiesReceiver(int rq) : highPrioReceived(0), lowPrioReceived(0), requestCount(rq) { }
       
   932 public Q_SLOTS:
       
   933     void finishedSlot() {
       
   934         QHttpNetworkReply *reply = (QHttpNetworkReply*) sender();
       
   935         if (reply->request().priority() == QHttpNetworkRequest::HighPriority)
       
   936             highPrioReceived++;
       
   937         else if (reply->request().priority() == QHttpNetworkRequest::LowPriority)
       
   938             lowPrioReceived++;
       
   939         else
       
   940             QFAIL("Wrong priority!?");
       
   941 
       
   942         QVERIFY(highPrioReceived >= lowPrioReceived);
       
   943 
       
   944         if (highPrioReceived + lowPrioReceived == requestCount)
       
   945             QTestEventLoop::instance().exitLoop();
       
   946     }
       
   947 };
       
   948 
       
   949 void tst_QHttpNetworkConnection::getMultipleWithPriorities()
       
   950 {
       
   951     quint16 requestCount = 100;
       
   952     // use 2 connections.
       
   953     QHttpNetworkConnection connection(2, QtNetworkSettings::serverName());
       
   954     GetMultipleWithPrioritiesReceiver receiver(requestCount);
       
   955     QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt");
       
   956     QList<QHttpNetworkRequest*> requests;
       
   957     QList<QHttpNetworkReply*> replies;
       
   958 
       
   959     for (int i = 0; i < requestCount; i++) {
       
   960         QHttpNetworkRequest *request = new QHttpNetworkRequest(url);;
       
   961 
       
   962         if (i % 2)
       
   963             request->setPriority(QHttpNetworkRequest::HighPriority);
       
   964         else
       
   965             request->setPriority(QHttpNetworkRequest::LowPriority);
       
   966 
       
   967         requests.append(request);
       
   968         QHttpNetworkReply *reply = connection.sendRequest(*request);
       
   969         connect(reply, SIGNAL(finished()), &receiver, SLOT(finishedSlot()));
       
   970         replies.append(reply);
       
   971     }
       
   972 
       
   973     QTestEventLoop::instance().enterLoop(40);
       
   974     QVERIFY(!QTestEventLoop::instance().timeout());
       
   975 
       
   976     qDeleteAll(requests);
       
   977     qDeleteAll(replies);
       
   978 }
       
   979 
       
   980 
       
   981 
       
   982 QTEST_MAIN(tst_QHttpNetworkConnection)
       
   983 #include "tst_qhttpnetworkconnection.moc"