| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Copyright (C) 2014 BlackBerry Limited. All rights reserved. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the test suite of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| // This file contains benchmarks for QNetworkReply functions. |
| |
| #include <QDebug> |
| #include <qtest.h> |
| #include <QtTest/QtTest> |
| #include <QtNetwork/qnetworkreply.h> |
| #include <QtNetwork/qnetworkrequest.h> |
| #include <QtNetwork/qnetworkaccessmanager.h> |
| #include <QtNetwork/qsslconfiguration.h> |
| #include <QtNetwork/qhttpmultipart.h> |
| #include <QtNetwork/qauthenticator.h> |
| #include <QtCore/QJsonDocument> |
| #include "../../auto/network-settings.h" |
| |
| #if defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) |
| #include "private/qsslsocket_p.h" |
| #include <QtNetwork/private/qsslsocket_openssl_p.h> |
| #endif |
| |
| #define BANDWIDTH_LIMIT_BYTES (1024*100) |
| #define TIME_ESTIMATION_SECONDS (97) |
| |
| class tst_qnetworkreply : public QObject |
| { |
| Q_OBJECT |
| private slots: |
| void initTestCase(); |
| void limiting_data(); |
| void limiting(); |
| void setSslConfiguration_data(); |
| void setSslConfiguration(); |
| void uploadToFacebook(); |
| void spdy_data(); |
| void spdy(); |
| void spdyMultipleRequestsPerHost(); |
| void proxyAuthentication_data(); |
| void proxyAuthentication(); |
| void authentication(); |
| void npnWithEmptyList(); // QTBUG-40714 |
| |
| protected slots: |
| void spdyReplyFinished(); // only used by spdyMultipleRequestsPerHost test |
| void authenticationRequiredSlot(QNetworkReply *, QAuthenticator *authenticator); |
| |
| private: |
| QHttpMultiPart *createFacebookMultiPart(const QByteArray &accessToken); |
| QNetworkAccessManager m_manager; |
| }; |
| |
| QNetworkReply *reply; |
| |
| class HttpReceiver : public QObject |
| { |
| Q_OBJECT |
| public slots: |
| void finishedSlot() { |
| quint64 bytesPerSec = (reply->header(QNetworkRequest::ContentLengthHeader).toLongLong()) / (stopwatch.elapsed() / 1000.0); |
| qDebug() << "Finished HTTP(S) request with" << bytesPerSec << "bytes/sec"; |
| QVERIFY(bytesPerSec < BANDWIDTH_LIMIT_BYTES*1.05); |
| QVERIFY(bytesPerSec > BANDWIDTH_LIMIT_BYTES*0.95); |
| timer->stop(); |
| QTestEventLoop::instance().exitLoop(); |
| } |
| void readyReadSlot() { |
| } |
| void timeoutSlot() { |
| reply->read(BANDWIDTH_LIMIT_BYTES).size(); |
| } |
| void startTimer() { |
| stopwatch.start(); |
| timer = new QTimer(this); |
| QObject::connect(timer, SIGNAL(timeout()), this, SLOT(timeoutSlot())); |
| timer->start(1000); |
| } |
| protected: |
| QTimer *timer; |
| QTime stopwatch; |
| }; |
| |
| void tst_qnetworkreply::initTestCase() |
| { |
| qRegisterMetaType<QNetworkReply *>(); // for QSignalSpy |
| if (!QtNetworkSettings::verifyTestNetworkSettings()) |
| QSKIP("No network test server available"); |
| } |
| |
| void tst_qnetworkreply::limiting_data() |
| { |
| QTest::addColumn<QUrl>("url"); |
| |
| QTest::newRow("HTTP") << QUrl("http://" + QtNetworkSettings::serverName() + "/mediumfile"); |
| #ifndef QT_NO_SSL |
| QTest::newRow("HTTP+SSL") << QUrl("https://" + QtNetworkSettings::serverName() + "/mediumfile"); |
| #endif |
| |
| } |
| |
| void tst_qnetworkreply::limiting() |
| { |
| HttpReceiver receiver; |
| QNetworkAccessManager manager; |
| |
| QFETCH(QUrl, url); |
| QNetworkRequest req (url); |
| |
| qDebug() << "Starting. This will take a while (around" << TIME_ESTIMATION_SECONDS << "sec)."; |
| qDebug() << "Please check the actual bandwidth usage with a network monitor, e.g. the KDE"; |
| qDebug() << "network plasma widget. It should be around" << BANDWIDTH_LIMIT_BYTES << "bytes/sec."; |
| reply = manager.get(req); |
| reply->ignoreSslErrors(); |
| reply->setReadBufferSize(BANDWIDTH_LIMIT_BYTES); |
| QObject::connect(reply, SIGNAL(readyRead()), &receiver, SLOT(readyReadSlot())); |
| QObject::connect(reply, SIGNAL(finished()), &receiver, SLOT(finishedSlot())); |
| receiver.startTimer(); |
| |
| // event loop |
| QTestEventLoop::instance().enterLoop(TIME_ESTIMATION_SECONDS + 20); |
| QVERIFY(!QTestEventLoop::instance().timeout()); |
| } |
| |
| void tst_qnetworkreply::setSslConfiguration_data() |
| { |
| QTest::addColumn<QUrl>("url"); |
| QTest::addColumn<bool>("works"); |
| |
| QTest::newRow("codereview.qt-project.org") << QUrl("https://codereview.qt-project.org") << true; |
| QTest::newRow("test-server") << QUrl("https://" + QtNetworkSettings::serverName() + "/") << false; |
| } |
| |
| void tst_qnetworkreply::setSslConfiguration() |
| { |
| #ifdef QT_NO_SSL |
| QSKIP("SSL is not enabled."); |
| #else |
| QFETCH(QUrl, url); |
| QNetworkRequest request(url); |
| QSslConfiguration conf = request.sslConfiguration(); |
| conf.setProtocol(QSsl::TlsV1_0); // TLS 1.0 will be used anyway, just make sure we change the configuration |
| request.setSslConfiguration(conf); |
| QNetworkAccessManager manager; |
| reply = manager.get(request); |
| QObject::connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); |
| QTestEventLoop::instance().enterLoop(15); |
| QVERIFY(!QTestEventLoop::instance().timeout()); |
| #ifdef QT_BUILD_INTERNAL |
| QFETCH(bool, works); |
| bool rootCertLoadingAllowed = QSslSocketPrivate::rootCertOnDemandLoadingSupported(); |
| #if defined(Q_OS_LINUX) |
| QCOMPARE(rootCertLoadingAllowed, true); |
| #elif defined(Q_OS_MAC) |
| QCOMPARE(rootCertLoadingAllowed, false); |
| #else |
| Q_UNUSED(rootCertLoadingAllowed) |
| #endif // other platforms: undecided (Windows: depends on the version) |
| if (works) { |
| QCOMPARE(reply->error(), QNetworkReply::NoError); |
| } else { |
| QCOMPARE(reply->error(), QNetworkReply::SslHandshakeFailedError); |
| } |
| #endif |
| #endif // QT_NO_SSL |
| } |
| |
| QHttpMultiPart *tst_qnetworkreply::createFacebookMultiPart(const QByteArray &accessToken) |
| { |
| QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); |
| QHttpPart accessTokenPart; |
| accessTokenPart.setHeader(QNetworkRequest::ContentDispositionHeader, |
| QVariant("form-data; name=\"access_token\"")); |
| accessTokenPart.setBody(accessToken); |
| multiPart->append(accessTokenPart); |
| |
| QHttpPart batchPart; |
| batchPart.setHeader(QNetworkRequest::ContentDispositionHeader, |
| QVariant("form-data; name=\"batch\"")); |
| batchPart.setBody("[" |
| " {" |
| " \"attached_files\" : \"image1\"," |
| " \"body\" : \"message=&published=0\"," |
| " \"method\" : \"POST\"," |
| " \"relative_url\" : \"me/photos\"" |
| " }," |
| " {" |
| " \"attached_files\" : \"image2\"," |
| " \"body\" : \"message=&published=0\"," |
| " \"method\" : \"POST\"," |
| " \"relative_url\" : \"me/photos\"" |
| " }," |
| " {" |
| " \"attached_files\" : \"image3\"," |
| " \"body\" : \"message=&published=0\"," |
| " \"method\" : \"POST\"," |
| " \"relative_url\" : \"me/photos\"" |
| " }" |
| "]"); |
| multiPart->append(batchPart); |
| |
| QHttpPart imagePart1; |
| imagePart1.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpg")); |
| imagePart1.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"image1\"; filename=\"image1.jpg\"")); |
| QFile *file1 = new QFile(QFINDTESTDATA("../../auto/network/access/qnetworkreply/image1.jpg")); |
| file1->open(QIODevice::ReadOnly); |
| imagePart1.setBodyDevice(file1); |
| file1->setParent(multiPart); |
| |
| multiPart->append(imagePart1); |
| |
| QHttpPart imagePart2; |
| imagePart2.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpg")); |
| imagePart2.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"image2\"; filename=\"image2.jpg\"")); |
| QFile *file2 = new QFile(QFINDTESTDATA("../../auto/network/access/qnetworkreply/image2.jpg")); |
| file2->open(QIODevice::ReadOnly); |
| imagePart2.setBodyDevice(file2); |
| file2->setParent(multiPart); |
| |
| multiPart->append(imagePart2); |
| |
| QHttpPart imagePart3; |
| imagePart3.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpg")); |
| imagePart3.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"image3\"; filename=\"image3.jpg\"")); |
| QFile *file3 = new QFile(QFINDTESTDATA("../../auto/network/access/qnetworkreply/image3.jpg")); |
| file3->open(QIODevice::ReadOnly); |
| imagePart3.setBodyDevice(file3); |
| file3->setParent(multiPart); |
| |
| multiPart->append(imagePart3); |
| return multiPart; |
| } |
| |
| void tst_qnetworkreply::uploadToFacebook() |
| { |
| QByteArray accessToken = qgetenv("QT_FACEBOOK_ACCESS_TOKEN"); |
| if (accessToken.isEmpty()) |
| QSKIP("This test requires the QT_FACEBOOK_ACCESS_TOKEN environment variable to be set. " |
| "Do something like 'export QT_FACEBOOK_ACCESS_TOKEN=MyAccessToken'"); |
| |
| QElapsedTimer timer; |
| QNetworkAccessManager manager; |
| QNetworkRequest request(QUrl("https://graph.facebook.com/me/photos")); |
| QHttpMultiPart *multiPart = createFacebookMultiPart(accessToken); |
| timer.start(); |
| |
| QNetworkReply *reply = manager.post(request, multiPart); |
| multiPart->setParent(reply); |
| QObject::connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); |
| QTestEventLoop::instance().enterLoop(120); |
| qint64 elapsed = timer.elapsed(); |
| QVERIFY(!QTestEventLoop::instance().timeout()); |
| qDebug() << "reply finished after" << elapsed / 1000.0 << "seconds"; |
| QCOMPARE(reply->error(), QNetworkReply::NoError); |
| |
| QByteArray content = reply->readAll(); |
| QJsonDocument jsonDocument = QJsonDocument::fromJson(content); |
| QVERIFY(jsonDocument.isArray()); |
| QJsonArray uploadStatuses = jsonDocument.array(); |
| QVERIFY(uploadStatuses.size() > 0); |
| for (int a = 0; a < uploadStatuses.size(); a++) { |
| QJsonValue currentUploadStatus = uploadStatuses.at(a); |
| QVERIFY(currentUploadStatus.isObject()); |
| QJsonObject statusObject = currentUploadStatus.toObject(); |
| QJsonValue statusCode = statusObject.value(QLatin1String("code")); |
| QCOMPARE(statusCode.toVariant().toInt(), 200); // 200 OK |
| } |
| } |
| |
| void tst_qnetworkreply::spdy_data() |
| { |
| QTest::addColumn<QString>("host"); |
| QTest::addColumn<bool>("setAttribute"); |
| QTest::addColumn<bool>("enabled"); |
| QTest::addColumn<QByteArray>("expectedProtocol"); |
| |
| QList<QString> hosts = QList<QString>() |
| << QStringLiteral("www.google.com") // sends SPDY and 30x redirect |
| << QStringLiteral("www.google.de") // sends SPDY and 200 OK |
| << QStringLiteral("mail.google.com") // sends SPDY and 200 OK |
| << QStringLiteral("www.youtube.com") // sends SPDY and 200 OK |
| << QStringLiteral("www.dropbox.com") // no SPDY, but NPN which selects HTTP |
| << QStringLiteral("www.facebook.com") // sends SPDY and 200 OK |
| << QStringLiteral("graph.facebook.com") // sends SPDY and 200 OK |
| << QStringLiteral("www.twitter.com") // sends SPDY and 30x redirect |
| << QStringLiteral("twitter.com") // sends SPDY and 200 OK |
| << QStringLiteral("api.twitter.com"); // sends SPDY and 200 OK |
| |
| foreach (const QString &host, hosts) { |
| QByteArray tag = host.toLocal8Bit(); |
| tag.append("-not-used"); |
| QTest::newRow(tag) |
| << QStringLiteral("https://") + host |
| << false |
| << false |
| << QByteArray(); |
| |
| tag = host.toLocal8Bit(); |
| tag.append("-disabled"); |
| QTest::newRow(tag) |
| << QStringLiteral("https://") + host |
| << true |
| << false |
| << QByteArray(); |
| |
| if (host != QStringLiteral("api.twitter.com")) { // they don't offer an API over HTTP |
| tag = host.toLocal8Bit(); |
| tag.append("-no-https-url"); |
| QTest::newRow(tag) |
| << QStringLiteral("http://") + host |
| << true |
| << true |
| << QByteArray(); |
| } |
| |
| #ifndef QT_NO_OPENSSL |
| tag = host.toLocal8Bit(); |
| tag.append("-enabled"); |
| QTest::newRow(tag) |
| << QStringLiteral("https://") + host |
| << true |
| << true |
| << (host == QStringLiteral("www.dropbox.com") |
| ? QByteArray(QSslConfiguration::NextProtocolHttp1_1) |
| : QByteArray(QSslConfiguration::NextProtocolSpdy3_0)); |
| #endif // QT_NO_OPENSSL |
| } |
| } |
| |
| void tst_qnetworkreply::spdy() |
| { |
| #if defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) && OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) |
| |
| m_manager.clearAccessCache(); |
| |
| QFETCH(QString, host); |
| QUrl url(host); |
| QNetworkRequest request(url); |
| |
| QFETCH(bool, setAttribute); |
| QFETCH(bool, enabled); |
| if (setAttribute) { |
| request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, QVariant(enabled)); |
| } |
| |
| QNetworkReply *reply = m_manager.get(request); |
| QObject::connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); |
| |
| QSignalSpy metaDataChangedSpy(reply, SIGNAL(metaDataChanged())); |
| QSignalSpy readyReadSpy(reply, SIGNAL(readyRead())); |
| QSignalSpy finishedSpy(reply, SIGNAL(finished())); |
| QSignalSpy finishedManagerSpy(&m_manager, SIGNAL(finished(QNetworkReply*))); |
| |
| QTestEventLoop::instance().enterLoop(15); |
| QVERIFY(!QTestEventLoop::instance().timeout()); |
| |
| QFETCH(QByteArray, expectedProtocol); |
| |
| bool expectedSpdyUsed = (expectedProtocol == QSslConfiguration::NextProtocolSpdy3_0); |
| QCOMPARE(reply->attribute(QNetworkRequest::SpdyWasUsedAttribute).toBool(), expectedSpdyUsed); |
| |
| QCOMPARE(metaDataChangedSpy.count(), 1); |
| QCOMPARE(finishedSpy.count(), 1); |
| QCOMPARE(finishedManagerSpy.count(), 1); |
| |
| QUrl redirectUrl = reply->header(QNetworkRequest::LocationHeader).toUrl(); |
| QByteArray content = reply->readAll(); |
| |
| int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); |
| QVERIFY(statusCode >= 200 && statusCode < 500); |
| if (statusCode == 200 || statusCode >= 400) { |
| QVERIFY(readyReadSpy.count() > 0); |
| QVERIFY(!content.isEmpty()); |
| } else if (statusCode >= 300 && statusCode < 400) { |
| QVERIFY(!redirectUrl.isEmpty()); |
| } |
| |
| QSslConfiguration::NextProtocolNegotiationStatus expectedStatus = |
| expectedProtocol.isNull() ? QSslConfiguration::NextProtocolNegotiationNone |
| : QSslConfiguration::NextProtocolNegotiationNegotiated; |
| QCOMPARE(reply->sslConfiguration().nextProtocolNegotiationStatus(), |
| expectedStatus); |
| |
| QCOMPARE(reply->sslConfiguration().nextNegotiatedProtocol(), expectedProtocol); |
| #else |
| QSKIP("Qt built withouth OpenSSL, or the OpenSSL version is too old"); |
| #endif // defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) ... |
| } |
| |
| void tst_qnetworkreply::spdyReplyFinished() |
| { |
| static int finishedCount = 0; |
| finishedCount++; |
| |
| if (finishedCount == 12) |
| QTestEventLoop::instance().exitLoop(); |
| } |
| |
| void tst_qnetworkreply::spdyMultipleRequestsPerHost() |
| { |
| #if defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) && OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) |
| |
| QList<QNetworkRequest> requests; |
| requests |
| << QNetworkRequest(QUrl("https://www.facebook.com")) |
| << QNetworkRequest(QUrl("https://www.facebook.com/images/fb_icon_325x325.png")) |
| |
| << QNetworkRequest(QUrl("https://www.google.de")) |
| << QNetworkRequest(QUrl("https://www.google.de/preferences?hl=de")) |
| << QNetworkRequest(QUrl("https://www.google.de/intl/de/policies/?fg=1")) |
| << QNetworkRequest(QUrl("https://www.google.de/intl/de/about.html?fg=1")) |
| << QNetworkRequest(QUrl("https://www.google.de/services/?fg=1")) |
| << QNetworkRequest(QUrl("https://www.google.de/intl/de/ads/?fg=1")) |
| |
| << QNetworkRequest(QUrl("https://i1.ytimg.com/li/tnHdj3df7iM/default.jpg")) |
| << QNetworkRequest(QUrl("https://i1.ytimg.com/li/7Dr1BKwqctY/default.jpg")) |
| << QNetworkRequest(QUrl("https://i1.ytimg.com/li/hfZhJdhTqX8/default.jpg")) |
| << QNetworkRequest(QUrl("https://i1.ytimg.com/vi/14Nprh8163I/hqdefault.jpg")) |
| ; |
| QList<QNetworkReply *> replies; |
| QList<QSignalSpy *> metaDataChangedSpies; |
| QList<QSignalSpy *> readyReadSpies; |
| QList<QSignalSpy *> finishedSpies; |
| |
| QSignalSpy finishedManagerSpy(&m_manager, SIGNAL(finished(QNetworkReply*))); |
| |
| foreach (QNetworkRequest request, requests) { |
| request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, true); |
| QNetworkReply *reply = m_manager.get(request); |
| QObject::connect(reply, SIGNAL(finished()), this, SLOT(spdyReplyFinished())); |
| replies << reply; |
| QSignalSpy *metaDataChangedSpy = new QSignalSpy(reply, SIGNAL(metaDataChanged())); |
| metaDataChangedSpies << metaDataChangedSpy; |
| QSignalSpy *readyReadSpy = new QSignalSpy(reply, SIGNAL(readyRead())); |
| readyReadSpies << readyReadSpy; |
| QSignalSpy *finishedSpy = new QSignalSpy(reply, SIGNAL(finished())); |
| finishedSpies << finishedSpy; |
| } |
| |
| QCOMPARE(requests.count(), replies.count()); |
| |
| QTestEventLoop::instance().enterLoop(15); |
| QVERIFY(!QTestEventLoop::instance().timeout()); |
| |
| QCOMPARE(finishedManagerSpy.count(), requests.count()); |
| |
| for (int a = 0; a < replies.count(); ++a) { |
| |
| QCOMPARE(replies.at(a)->sslConfiguration().nextProtocolNegotiationStatus(), |
| QSslConfiguration::NextProtocolNegotiationNegotiated); |
| QCOMPARE(replies.at(a)->sslConfiguration().nextNegotiatedProtocol(), |
| QByteArray(QSslConfiguration::NextProtocolSpdy3_0)); |
| |
| QCOMPARE(replies.at(a)->error(), QNetworkReply::NoError); |
| QCOMPARE(replies.at(a)->attribute(QNetworkRequest::SpdyWasUsedAttribute).toBool(), true); |
| QCOMPARE(replies.at(a)->attribute(QNetworkRequest::ConnectionEncryptedAttribute).toBool(), true); |
| QCOMPARE(replies.at(a)->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); |
| |
| QByteArray content = replies.at(a)->readAll(); |
| QVERIFY(content.count() > 0); |
| |
| QCOMPARE(metaDataChangedSpies.at(a)->count(), 1); |
| metaDataChangedSpies.at(a)->deleteLater(); |
| |
| QCOMPARE(finishedSpies.at(a)->count(), 1); |
| finishedSpies.at(a)->deleteLater(); |
| |
| QVERIFY(readyReadSpies.at(a)->count() > 0); |
| readyReadSpies.at(a)->deleteLater(); |
| |
| replies.at(a)->deleteLater(); |
| } |
| #else |
| QSKIP("Qt built withouth OpenSSL, or the OpenSSL version is too old"); |
| #endif // defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) ... |
| } |
| |
| void tst_qnetworkreply::proxyAuthentication_data() |
| { |
| QTest::addColumn<QUrl>("url"); |
| |
| QTest::newRow("http://www.google.com") << QUrl("http://www.google.com"); |
| QTest::newRow("https://www.google.com") << QUrl("https://www.google.com"); |
| } |
| |
| void tst_qnetworkreply::proxyAuthentication() |
| { |
| QFETCH(QUrl, url); |
| QNetworkRequest request(url); |
| QNetworkAccessManager manager; |
| |
| QByteArray proxyHostName = qgetenv("QT_PROXY_HOST"); |
| QByteArray proxyPort = qgetenv("QT_PROXY_PORT"); |
| QByteArray proxyUser = qgetenv("QT_PROXY_USER"); |
| QByteArray proxyPassword = qgetenv("QT_PROXY_PASSWORD"); |
| if (proxyHostName.isEmpty() || proxyPort.isEmpty() || proxyUser.isEmpty() |
| || proxyPassword.isEmpty()) |
| QSKIP("This test requires the QT_PROXY_* environment variables to be set. " |
| "Do something like:\n" |
| "export QT_PROXY_HOST=myNTLMHost\n" |
| "export QT_PROXY_PORT=8080\n" |
| "export QT_PROXY_USER='myDomain\\myUser'\n" |
| "export QT_PROXY_PASSWORD=myPassword\n"); |
| |
| QNetworkProxy proxy(QNetworkProxy::HttpProxy); |
| proxy.setHostName(proxyHostName); |
| proxy.setPort(proxyPort.toInt()); |
| proxy.setUser(proxyUser); |
| proxy.setPassword(proxyPassword); |
| |
| manager.setProxy(proxy); |
| |
| reply = manager.get(request); |
| QObject::connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); |
| QTestEventLoop::instance().enterLoop(15); |
| QVERIFY(!QTestEventLoop::instance().timeout()); |
| QCOMPARE(reply->error(), QNetworkReply::NoError); |
| int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); |
| QVERIFY(statusCode >= 200 && statusCode < 400); |
| } |
| |
| void tst_qnetworkreply::authenticationRequiredSlot(QNetworkReply *, |
| QAuthenticator *authenticator) |
| { |
| QString authUser = QString::fromLocal8Bit(qgetenv("QT_AUTH_USER")); |
| QString authPassword = QString::fromLocal8Bit(qgetenv("QT_AUTH_PASSWORD")); |
| authenticator->setUser(authUser); |
| authenticator->setPassword(authPassword); |
| } |
| |
| void tst_qnetworkreply::authentication() |
| { |
| QByteArray authUrl = qgetenv("QT_AUTH_URL"); |
| if (authUrl.isEmpty()) |
| QSKIP("This test requires the QT_AUTH_* environment variables to be set. " |
| "Do something like:\n" |
| "export QT_AUTH_URL='http://myUrl.com/myPath'\n" |
| "export QT_AUTH_USER='myDomain\\myUser'\n" |
| "export QT_AUTH_PASSWORD=myPassword\n"); |
| |
| QUrl url(QString::fromLocal8Bit(authUrl)); |
| QNetworkRequest request(url); |
| QNetworkAccessManager manager; |
| QObject::connect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), |
| this, SLOT(authenticationRequiredSlot(QNetworkReply*,QAuthenticator*))); |
| reply = manager.get(request); |
| QObject::connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); |
| QTestEventLoop::instance().enterLoop(15); |
| QVERIFY(!QTestEventLoop::instance().timeout()); |
| QVERIFY2(reply->error() == QNetworkReply::NoError, reply->errorString().toLocal8Bit()); |
| int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); |
| QVERIFY(statusCode >= 200 && statusCode < 400); |
| } |
| |
| void tst_qnetworkreply::npnWithEmptyList() // QTBUG-40714 |
| { |
| #if defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) && OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) |
| |
| // The server does not send a list of Next Protocols, so we test |
| // that we continue anyhow and it works |
| |
| m_manager.clearAccessCache(); |
| |
| QUrl url(QStringLiteral("https://www.ossifrage.net/")); |
| QNetworkRequest request(url); |
| request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, QVariant(true)); |
| QNetworkReply *reply = m_manager.get(request); |
| QObject::connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); |
| |
| QTestEventLoop::instance().enterLoop(15); |
| QVERIFY(!QTestEventLoop::instance().timeout()); |
| |
| int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); |
| QVERIFY(statusCode == 200); |
| |
| QCOMPARE(reply->sslConfiguration().nextProtocolNegotiationStatus(), |
| QSslConfiguration::NextProtocolNegotiationUnsupported); |
| #else |
| QSKIP("Qt built withouth OpenSSL, or the OpenSSL version is too old"); |
| #endif // defined(QT_BUILD_INTERNAL) && !defined(QT_NO_SSL) ... |
| } |
| |
| QTEST_MAIN(tst_qnetworkreply) |
| |
| #include "main.moc" |