diff options
Diffstat (limited to 'tests/auto/network')
11 files changed, 406 insertions, 149 deletions
diff --git a/tests/auto/network/access/hsts/tst_qhsts.cpp b/tests/auto/network/access/hsts/tst_qhsts.cpp index 656516f46b..d72991a2eb 100644 --- a/tests/auto/network/access/hsts/tst_qhsts.cpp +++ b/tests/auto/network/access/hsts/tst_qhsts.cpp @@ -32,7 +32,9 @@ #include <QtCore/qvector.h> #include <QtCore/qpair.h> #include <QtCore/qurl.h> +#include <QtCore/qdir.h> +#include <QtNetwork/private/qhstsstore_p.h> #include <QtNetwork/private/qhsts_p.h> QT_USE_NAMESPACE @@ -46,6 +48,7 @@ private Q_SLOTS: void testMultilpeKnownHosts(); void testPolicyExpiration(); void testSTSHeaderParser(); + void testStore(); }; void tst_QHsts::testSingleKnownHost_data() @@ -313,6 +316,75 @@ void tst_QHsts::testSTSHeaderParser() QVERIFY(!parser.expirationDate().isValid()); } +const QLatin1String storeDir("."); + +struct TestStoreDeleter +{ + ~TestStoreDeleter() + { + QDir cwd; + if (!cwd.remove(QHstsStore::absoluteFilePath(storeDir))) + qWarning() << "tst_QHsts::testStore: failed to remove the hsts store file"; + } +}; + +void tst_QHsts::testStore() +{ + // Delete the store's file after we finish the test. + TestStoreDeleter cleaner; + + const QUrl exampleCom(QStringLiteral("http://example.com")); + const QUrl subDomain(QStringLiteral("http://subdomain.example.com")); + const QDateTime validDate(QDateTime::currentDateTimeUtc().addDays(1)); + + { + // We start from an empty cache and empty store: + QHstsCache cache; + QHstsStore store(storeDir); + cache.setStore(&store); + QVERIFY(!cache.isKnownHost(exampleCom)); + QVERIFY(!cache.isKnownHost(subDomain)); + // (1) This will also store the policy: + cache.updateKnownHost(exampleCom, validDate, true); + QVERIFY(cache.isKnownHost(exampleCom)); + QVERIFY(cache.isKnownHost(subDomain)); + } + { + // Test the policy stored at (1): + QHstsCache cache; + QHstsStore store(storeDir); + cache.setStore(&store); + QVERIFY(cache.isKnownHost(exampleCom)); + QVERIFY(cache.isKnownHost(subDomain)); + // (2) Remove subdomains: + cache.updateKnownHost(exampleCom, validDate, false); + QVERIFY(!cache.isKnownHost(subDomain)); + } + { + // Test the previous update (2): + QHstsCache cache; + QHstsStore store(storeDir); + cache.setStore(&store); + QVERIFY(cache.isKnownHost(exampleCom)); + QVERIFY(!cache.isKnownHost(subDomain)); + } + { + QHstsCache cache; + cache.updateKnownHost(subDomain, validDate, false); + QVERIFY(cache.isKnownHost(subDomain)); + QHstsStore store(storeDir); + // (3) This should store policy from cache, over old policy from store: + cache.setStore(&store); + } + { + // Test that (3) was stored: + QHstsCache cache; + QHstsStore store(storeDir); + cache.setStore(&store); + QVERIFY(cache.isKnownHost(subDomain)); + } +} + QTEST_MAIN(tst_QHsts) #include "tst_qhsts.moc" diff --git a/tests/auto/network/access/http2/http2srv.cpp b/tests/auto/network/access/http2/http2srv.cpp index d0686eb01c..663f40cbae 100644 --- a/tests/auto/network/access/http2/http2srv.cpp +++ b/tests/auto/network/access/http2/http2srv.cpp @@ -132,8 +132,23 @@ void Http2Server::startServer() if (!clearTextHTTP2) return; #endif - if (listen()) + if (listen()) { + if (clearTextHTTP2) + authority = QStringLiteral("127.0.0.1:%1").arg(serverPort()).toLatin1(); emit serverStarted(serverPort()); + } +} + +bool Http2Server::sendProtocolSwitchReply() +{ + Q_ASSERT(socket); + Q_ASSERT(clearTextHTTP2 && upgradeProtocol); + // The first and the last HTTP/1.1 response we send: + const char response[] = "HTTP/1.1 101 Switching Protocols\r\n" + "Connection: Upgrade\r\n" + "Upgrade: h2c\r\n\r\n"; + const qint64 size = sizeof response - 1; + return socket->write(response, size) == size; } void Http2Server::sendServerSettings() @@ -232,6 +247,7 @@ void Http2Server::incomingConnection(qintptr socketDescriptor) Q_ASSERT(set); // Stop listening: close(); + upgradeProtocol = true; QMetaObject::invokeMethod(this, "connectionEstablished", Qt::QueuedConnection); } else { @@ -275,19 +291,77 @@ quint32 Http2Server::clientSetting(Http2::Settings identifier, quint32 defaultVa return defaultValue; } +bool Http2Server::readMethodLine() +{ + // We know for sure that Qt did the right thing sending us the correct + // Request-line with CRLF at the end ... + // We're overly simplistic here but all we need to know - the method. + while (socket->bytesAvailable()) { + char c = 0; + if (socket->read(&c, 1) != 1) + return false; + if (c == '\n' && requestLine.endsWith('\r')) { + if (requestLine.startsWith("GET")) + requestType = QHttpNetworkRequest::Get; + else if (requestLine.startsWith("POST")) + requestType = QHttpNetworkRequest::Post; + else + requestType = QHttpNetworkRequest::Custom; // 'invalid'. + requestLine.clear(); + + return true; + } else { + requestLine.append(c); + } + } + + return false; +} + +bool Http2Server::verifyProtocolUpgradeRequest() +{ + Q_ASSERT(protocolUpgradeHandler.data()); + + bool connectionOk = false; + bool upgradeOk = false; + bool settingsOk = false; + + QHttpNetworkReplyPrivate *firstRequestReader = protocolUpgradeHandler->d_func(); + + // That's how we append them, that's what I expect to find: + for (const auto &header : firstRequestReader->fields) { + if (header.first == "Connection") + connectionOk = header.second.contains("Upgrade, HTTP2-Settings"); + else if (header.first == "Upgrade") + upgradeOk = header.second.contains("h2c"); + else if (header.first == "HTTP2-Settings") + settingsOk = true; + } + + return connectionOk && upgradeOk && settingsOk; +} + +void Http2Server::triggerGOAWAYEmulation() +{ + Q_ASSERT(testingGOAWAY); + auto timer = new QTimer(this); + timer->setSingleShot(true); + connect(timer, &QTimer::timeout, [this]() { + sendGOAWAY(quint32(connectionStreamID), quint32(INTERNAL_ERROR), 0); + }); + timer->start(goawayTimeout); +} + void Http2Server::connectionEstablished() { using namespace Http2; - if (testingGOAWAY) { - auto timer = new QTimer(this); - timer->setSingleShot(true); - connect(timer, &QTimer::timeout, [this]() { - sendGOAWAY(quint32(connectionStreamID), quint32(INTERNAL_ERROR), 0); - }); - timer->start(goawayTimeout); - return; - } + if (testingGOAWAY && !clearTextHTTP2) + return triggerGOAWAYEmulation(); + + // For clearTextHTTP2 we first have to respond with 'protocol switch' + // and then continue with whatever logic we have (testingGOAWAY or not), + // otherwise our 'peer' cannot process HTTP/2 frames yet. connect(socket.data(), SIGNAL(readyRead()), this, SLOT(readReady())); @@ -296,9 +370,17 @@ void Http2Server::connectionEstablished() waitingClientAck = false; waitingClientSettings = false; settingsSent = false; - // We immediately send our settings so that our client - // can use flow control correctly. - sendServerSettings(); + + if (clearTextHTTP2) { + requestLine.clear(); + // Now we have to handle HTTP/1.1 request. We use Get/Post in our test, + // so set requestType to something unsupported: + requestType = QHttpNetworkRequest::Options; + } else { + // We immediately send our settings so that our client + // can use flow control correctly. + sendServerSettings(); + } if (socket->bytesAvailable()) readReady(); @@ -328,7 +410,9 @@ void Http2Server::readReady() if (connectionError) return; - if (waitingClientPreface) { + if (upgradeProtocol) { + handleProtocolUpgrade(); + } else if (waitingClientPreface) { handleConnectionPreface(); } else { const auto status = reader.read(*socket); @@ -348,6 +432,79 @@ void Http2Server::readReady() QMetaObject::invokeMethod(this, "readReady", Qt::QueuedConnection); } +void Http2Server::handleProtocolUpgrade() +{ + using ReplyPrivate = QHttpNetworkReplyPrivate; + Q_ASSERT(upgradeProtocol); + + if (!protocolUpgradeHandler.data()) + protocolUpgradeHandler.reset(new Http11Reply); + + QHttpNetworkReplyPrivate *firstRequestReader = protocolUpgradeHandler->d_func(); + + // QHttpNetworkReplyPrivate parses ... reply. It will, unfortunately, fail + // on the first line ... which is a part of request. So we read this line + // and extract the method first. + if (firstRequestReader->state == ReplyPrivate::NothingDoneState) { + if (!readMethodLine()) + return; + + if (requestType != QHttpNetworkRequest::Get && requestType != QHttpNetworkRequest::Post) { + emit invalidRequest(1); + return; + } + + firstRequestReader->state = ReplyPrivate::ReadingHeaderState; + } + + if (!socket->bytesAvailable()) + return; + + if (firstRequestReader->state == ReplyPrivate::ReadingHeaderState) + firstRequestReader->readHeader(socket.data()); + else if (firstRequestReader->state == ReplyPrivate::ReadingDataState) + firstRequestReader->readBodyFast(socket.data(), &firstRequestReader->responseData); + + switch (firstRequestReader->state) { + case ReplyPrivate::ReadingHeaderState: + return; + case ReplyPrivate::ReadingDataState: + if (requestType == QHttpNetworkRequest::Post) + return; + break; + case ReplyPrivate::AllDoneState: + break; + default: + socket->close(); + return; + } + + if (!verifyProtocolUpgradeRequest() || !sendProtocolSwitchReply()) { + socket->close(); + return; + } + + upgradeProtocol = false; + protocolUpgradeHandler.reset(nullptr); + + if (testingGOAWAY) + return triggerGOAWAYEmulation(); + + // HTTP/1.1 'fields' we have in firstRequestRead are useless (they are not + // even allowed in HTTP/2 header). Let's pretend we have received + // valid HTTP/2 headers and can extract fields we need: + HttpHeader h2header; + h2header.push_back(HeaderField(":scheme", "http")); // we are in clearTextHTTP2 mode. + h2header.push_back(HeaderField(":authority", authority)); + activeRequests[1] = std::move(h2header); + // After protocol switch we immediately send our SETTINGS. + sendServerSettings(); + if (requestType == QHttpNetworkRequest::Get) + emit receivedRequest(1); + else + emit receivedData(1); +} + void Http2Server::handleConnectionPreface() { Q_ASSERT(waitingClientPreface); @@ -382,6 +539,16 @@ void Http2Server::handleIncomingFrame() // 7. RST_STREAM // 8. GOAWAY + if (testingGOAWAY) { + // GOAWAY test is simplistic for now: after HTTP/2 was + // negotiated (via ALPN/NPN or a protocol switch), send + // a GOAWAY frame after some (probably non-zero) timeout. + // We do not handle any frames, but timeout gives QNAM + // more time to initiate more streams and thus make the + // test more interesting/complex (on a client side). + return; + } + inboundFrame = std::move(reader.inboundFrame()); if (continuedRequest.size()) { diff --git a/tests/auto/network/access/http2/http2srv.h b/tests/auto/network/access/http2/http2srv.h index 63a4a4c8e9..10d0e86736 100644 --- a/tests/auto/network/access/http2/http2srv.h +++ b/tests/auto/network/access/http2/http2srv.h @@ -29,11 +29,14 @@ #ifndef HTTP2SRV_H #define HTTP2SRV_H +#include <QtNetwork/private/qhttpnetworkrequest_p.h> +#include <QtNetwork/private/qhttpnetworkreply_p.h> #include <QtNetwork/private/http2protocol_p.h> #include <QtNetwork/private/http2frames_p.h> #include <QtNetwork/private/hpack_p.h> #include <QtNetwork/qabstractsocket.h> +#include <QtCore/qsharedpointer.h> #include <QtCore/qscopedpointer.h> #include <QtNetwork/qtcpserver.h> #include <QtCore/qbytearray.h> @@ -58,6 +61,19 @@ struct Http2Setting using Http2Settings = std::vector<Http2Setting>; +// At the moment we do not have any public API parsing HTTP headers. Even worse - +// the code that can do this exists only in QHttpNetworkReplyPrivate class. +// To be able to access reply's d_func() we have these classes: +class Http11ReplyPrivate : public QHttpNetworkReplyPrivate +{ +}; + +class Http11Reply : public QHttpNetworkReply +{ +public: + Q_DECLARE_PRIVATE(Http11Reply) +}; + class Http2Server : public QTcpServer { Q_OBJECT @@ -75,6 +91,7 @@ public: // Invokables, since we can call them from the main thread, // but server (can) work on its own thread. Q_INVOKABLE void startServer(); + bool sendProtocolSwitchReply(); Q_INVOKABLE void sendServerSettings(); Q_INVOKABLE void sendGOAWAY(quint32 streamID, quint32 error, quint32 lastStreamID); @@ -82,6 +99,7 @@ public: Q_INVOKABLE void sendDATA(quint32 streamID, quint32 windowSize); Q_INVOKABLE void sendWINDOW_UPDATE(quint32 streamID, quint32 delta); + Q_INVOKABLE void handleProtocolUpgrade(); Q_INVOKABLE void handleConnectionPreface(); Q_INVOKABLE void handleIncomingFrame(); Q_INVOKABLE void handleSETTINGS(); @@ -114,6 +132,9 @@ private: void incomingConnection(qintptr socketDescriptor) Q_DECL_OVERRIDE; quint32 clientSetting(Http2::Settings identifier, quint32 defaultValue); + bool readMethodLine(); + bool verifyProtocolUpgradeRequest(); + void triggerGOAWAYEmulation(); QScopedPointer<QAbstractSocket> socket; @@ -166,6 +187,18 @@ private: bool testingGOAWAY = false; int goawayTimeout = 0; + // Clear text HTTP/2, we have to deal with the protocol upgrade request + // from the initial HTTP/1.1 request. + bool upgradeProtocol = false; + QByteArray requestLine; + QHttpNetworkRequest::Operation requestType; + // We need QHttpNetworkReply (actually its private d-object) to handle the + // first HTTP/1.1 request. QHttpNetworkReplyPrivate does parsing + in case + // of POST it is also reading the body for us. + QScopedPointer<Http11Reply> protocolUpgradeHandler; + // We need it for PUSH_PROMISE, with the correct port number appended, + // when replying to essentially 1.1 request. + QByteArray authority; protected slots: void ignoreErrorSlot(); }; diff --git a/tests/auto/network/access/http2/tst_http2.cpp b/tests/auto/network/access/http2/tst_http2.cpp index d7a57f5e26..e433293a2c 100644 --- a/tests/auto/network/access/http2/tst_http2.cpp +++ b/tests/auto/network/access/http2/tst_http2.cpp @@ -47,10 +47,12 @@ #include <cstdlib> #include <string> -// At the moment our HTTP/2 imlpementation requires ALPN and this means OpenSSL. #if !defined(QT_NO_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_TLSEXT) +// HTTP/2 over TLS requires ALPN/NPN to negotiate the protocol version. const bool clearTextHTTP2 = false; #else +// No ALPN/NPN support to negotiate HTTP/2, we'll use cleartext 'h2c' with +// a protocol upgrade procedure. const bool clearTextHTTP2 = true; #endif @@ -507,6 +509,7 @@ void tst_Http2::sendRequest(int streamNumber, QNetworkRequest request(url); request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, QVariant(true)); + request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain")); request.setPriority(priority); QNetworkReply *reply = nullptr; diff --git a/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp b/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp index af6f2d0e10..e996347a9a 100644 --- a/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp +++ b/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp @@ -281,6 +281,7 @@ void tst_QNetworkDiskCache::clear() // don't delete files that it didn't create QTemporaryFile file(cacheDirectory + "/XXXXXX"); if (file.open()) { + file.fileName(); // make sure it exists with a name QCOMPARE(countFiles(cacheDirectory).count(), NUM_SUBDIRECTORIES + 3); cache.clear(); QCOMPARE(countFiles(cacheDirectory).count(), NUM_SUBDIRECTORIES + 3); diff --git a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp index 2671c253cb..cb7e66bad4 100644 --- a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp +++ b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp @@ -86,6 +86,8 @@ class tst_QHostInfo : public QObject private slots: void init(); void initTestCase(); + void swapFunction(); + void moveOperator(); void getSetCheck(); void staticInformation(); void lookupIPv4_data(); @@ -129,6 +131,29 @@ private: #endif }; +void tst_QHostInfo::swapFunction() +{ + QHostInfo obj1, obj2; + obj1.setError(QHostInfo::HostInfoError(0)); + obj2.setError(QHostInfo::HostInfoError(1)); + obj1.swap(obj2); + QCOMPARE(QHostInfo::HostInfoError(0), obj2.error()); + QCOMPARE(QHostInfo::HostInfoError(1), obj1.error()); +} + +void tst_QHostInfo::moveOperator() +{ + QHostInfo obj1, obj2, obj3(1); + obj1.setError(QHostInfo::HostInfoError(0)); + obj2.setError(QHostInfo::HostInfoError(1)); + obj1 = std::move(obj2); + obj2 = obj3; + QCOMPARE(QHostInfo::HostInfoError(1), obj1.error()); + QCOMPARE(obj3.lookupId(), obj2.lookupId()); +} + + + // Testing get/set functions void tst_QHostInfo::getSetCheck() { diff --git a/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp b/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp index 5695f90c53..36dcec0a82 100644 --- a/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp +++ b/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp @@ -32,7 +32,7 @@ #include <qcoreapplication.h> #include <qnetworkinterface.h> -#include <qtcpsocket.h> +#include <qudpsocket.h> #ifndef QT_NO_BEARERMANAGEMENT #include <QNetworkConfigurationManager> #include <QNetworkSession> @@ -48,6 +48,8 @@ public: tst_QNetworkInterface(); virtual ~tst_QNetworkInterface(); + bool isIPv6Working(); + private slots: void initTestCase(); void cleanupTestCase(); @@ -76,6 +78,13 @@ tst_QNetworkInterface::~tst_QNetworkInterface() { } +bool tst_QNetworkInterface::isIPv6Working() +{ + QUdpSocket socket; + socket.connectToHost(QHostAddress::LocalHostIPv6, 1234); + return socket.state() == QAbstractSocket::ConnectedState || socket.waitForConnected(100); +} + void tst_QNetworkInterface::initTestCase() { if (!QtNetworkSettings::verifyTestNetworkSettings()) @@ -172,35 +181,21 @@ void tst_QNetworkInterface::loopbackIPv4() void tst_QNetworkInterface::loopbackIPv6() { + if (!isIPv6Working()) + QSKIP("IPv6 not active on this machine"); QList<QHostAddress> all = QNetworkInterface::allAddresses(); - - bool loopbackfound = false; - bool anyIPv6 = false; - foreach (QHostAddress addr, all) - if (addr == QHostAddress::LocalHostIPv6) { - loopbackfound = true; - anyIPv6 = true; - break; - } else if (addr.protocol() == QAbstractSocket::IPv6Protocol) - anyIPv6 = true; - - QVERIFY(!anyIPv6 || loopbackfound); + QVERIFY(all.contains(QHostAddress(QHostAddress::LocalHostIPv6))); } void tst_QNetworkInterface::localAddress() { - QTcpSocket socket; + QUdpSocket socket; socket.connectToHost(QtNetworkSettings::serverName(), 80); QVERIFY(socket.waitForConnected(5000)); QHostAddress local = socket.localAddress(); - // make Apache happy on fluke - socket.write("GET / HTTP/1.0\r\n\r\n"); - socket.waitForBytesWritten(1000); - socket.close(); - - // test that we can find the address that QTcpSocket reported + // test that we can find the address that QUdpSocket reported QList<QHostAddress> all = QNetworkInterface::allAddresses(); QVERIFY(all.contains(local)); } diff --git a/tests/auto/network/kernel/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp b/tests/auto/network/kernel/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp index 7fef603003..90da0b64e2 100644 --- a/tests/auto/network/kernel/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp +++ b/tests/auto/network/kernel/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp @@ -34,10 +34,8 @@ #include <qdebug.h> #include <qnetworkproxy.h> -#include <QNetworkConfiguration> -#include <QNetworkConfigurationManager> -#include <QNetworkSession> #include <QNetworkAccessManager> +#include <QNetworkInterface> #include <QNetworkReply> #include <QNetworkRequest> #include <QList> @@ -71,11 +69,6 @@ private slots: void systemProxyForQuery_data(); void systemProxyForQuery() const; void systemProxyForQuery_local(); -#ifndef QT_NO_BEARERMANAGEMENT - void fromConfigurations(); - void inNetworkAccessManager_data(); - void inNetworkAccessManager(); -#endif void genericSystemProxy(); void genericSystemProxy_data(); @@ -253,111 +246,6 @@ void tst_QNetworkProxyFactory::systemProxyForQuery_local() QVERIFY(list.isEmpty() || (list[0].type() == QNetworkProxy::NoProxy)); } -#ifndef QT_NO_BEARERMANAGEMENT - -//Purpose of this test is just to check systemProxyForQuery doesn't hang or crash -//with any given configuration including no configuration. -//We can't test it returns the right proxies without implementing the native proxy code -//again here, which would be testing our implementation against itself. -//Therefore it's just testing that something valid is returned (at least a NoProxy entry) -void tst_QNetworkProxyFactory::fromConfigurations() -{ - QNetworkConfigurationManager manager; - QList<QNetworkProxy> proxies; - QUrl url(QLatin1String("http://qt-project.org")); - //get from known configurations - foreach (QNetworkConfiguration config, manager.allConfigurations()) { - QNetworkProxyQuery query(config, url, QNetworkProxyQuery::UrlRequest); - proxies = QNetworkProxyFactory::systemProxyForQuery(query); - QVERIFY(!proxies.isEmpty()); - foreach (QNetworkProxy proxy, proxies) { - qDebug() << config.name() << " - " << config.identifier() << " - " << formatProxyName(proxy); - } - } - - //get from default configuration - QNetworkProxyQuery defaultquery(url, QNetworkProxyQuery::UrlRequest); - proxies = QNetworkProxyFactory::systemProxyForQuery(defaultquery); - QVERIFY(!proxies.isEmpty()); - foreach (QNetworkProxy proxy, proxies) { - qDebug() << "default - " << formatProxyName(proxy); - } - - //get from active configuration - QNetworkSession session(manager.defaultConfiguration()); - session.open(); - QVERIFY(session.waitForOpened(30000)); - proxies = QNetworkProxyFactory::systemProxyForQuery(defaultquery); - QVERIFY(!proxies.isEmpty()); - foreach (QNetworkProxy proxy, proxies) { - qDebug() << "active - " << formatProxyName(proxy); - } - - //get from known configurations while there is one active - foreach (QNetworkConfiguration config, manager.allConfigurations()) { - QNetworkProxyQuery query(config, url, QNetworkProxyQuery::UrlRequest); - proxies = QNetworkProxyFactory::systemProxyForQuery(query); - QVERIFY(!proxies.isEmpty()); - foreach (QNetworkProxy proxy, proxies) { - qDebug() << config.name() << " - " << config.identifier() << " - " << formatProxyName(proxy); - } - } -} - -void tst_QNetworkProxyFactory::inNetworkAccessManager_data() -{ - QTest::addColumn<QNetworkConfiguration>("config"); - QTest::addColumn<QList<QNetworkProxy> >("proxies"); - QNetworkConfigurationManager manager; - //get from known configurations - foreach (QNetworkConfiguration config, manager.allConfigurations()) { - QNetworkProxyQuery query(config, QUrl(QString("http://qt-project.org")), QNetworkProxyQuery::UrlRequest); - QList<QNetworkProxy> proxies = QNetworkProxyFactory::systemProxyForQuery(query); - QTest::newRow(config.name().toUtf8()) << config << proxies; - } -} - -//Purpose of this test is to check that QNetworkAccessManager uses the proxy from the configuration it -//has been given. Needs two or more working configurations to be a good test. -void tst_QNetworkProxyFactory::inNetworkAccessManager() -{ - QFETCH(QNetworkConfiguration, config); - QFETCH(QList<QNetworkProxy>, proxies); - - int count = QDebugProxyFactory::requestCounter; - - QNetworkAccessManager manager; - manager.setConfiguration(config); - - //using an internet server, because cellular APs won't have a route to the test server. - QNetworkRequest req(QUrl(QString("http://qt-project.org"))); - QNetworkReply *reply = manager.get(req); - connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); - QTestEventLoop::instance().enterLoop(30); - delete reply; - - if (count == QDebugProxyFactory::requestCounter) { - //RND phones are preconfigured with several test access points which won't work without a matching SIM - //If the network fails to start, QNAM won't ask the factory for proxies so we can't test. - QSKIP("network configuration didn't start"); - } - QVERIFY(factory); - - qDebug() << "testing network configuration for" << config.name(); - foreach (QNetworkProxy proxy, factory->returnedList) { - qDebug() << formatProxyName(proxy); - } - qDebug() << " <vs> "; - foreach (QNetworkProxy proxy, proxies) { - qDebug() << formatProxyName(proxy); - } - if (config.type() != QNetworkConfiguration::InternetAccessPoint) - QEXPECT_FAIL("","QNetworkProxyFactory::systemProxyForQuery doesn't work for service networks yet", Continue); - QCOMPARE(factory->returnedList, proxies); -} - -#endif //QT_NO_BEARERMANAGEMENT - Q_DECLARE_METATYPE(QNetworkProxy::ProxyType) void tst_QNetworkProxyFactory::genericSystemProxy() diff --git a/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp b/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp index 43b5422635..bc53faf106 100644 --- a/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp +++ b/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp @@ -76,7 +76,9 @@ private slots: void serverTest(); void udpLoopbackPerformance(); void tcpLoopbackPerformance(); +#if 0 void readWriteBufferSize(); +#endif void bind(); void networkError(); void setSocketDescriptor(); @@ -485,6 +487,7 @@ void tst_PlatformSocketEngine::tcpLoopbackPerformance() (readBytes / (timer.elapsed() / 1000.0)) / (1024 * 1024)); } +#if 0 // unused //--------------------------------------------------------------------------- void tst_PlatformSocketEngine::readWriteBufferSize() { @@ -503,6 +506,7 @@ void tst_PlatformSocketEngine::readWriteBufferSize() QVERIFY(device.sendBufferSize() > bufferSize); } +#endif //--------------------------------------------------------------------------- void tst_PlatformSocketEngine::tooManySockets() diff --git a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp index 60ee4eb471..7760138067 100644 --- a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp +++ b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp @@ -306,9 +306,11 @@ void tst_QLocalSocket::listen() // already isListening QTest::ignoreMessage(QtWarningMsg, "QLocalServer::listen() called when already listening"); QVERIFY(!server.listen(name)); + QVERIFY(server.socketDescriptor() != -1); } else { QVERIFY(!server.errorString().isEmpty()); QCOMPARE(server.serverError(), QAbstractSocket::HostNotFoundError); + QCOMPARE(server.socketDescriptor(), -1); } QCOMPARE(server.maxPendingConnections(), 30); bool timedOut = false; diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index 1545743ee9..12588c5e29 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -1098,6 +1098,9 @@ public: QString m_interFile; QString ciphers; +signals: + void socketError(QAbstractSocket::SocketError); + protected: void incomingConnection(qintptr socketDescriptor) { @@ -1107,6 +1110,7 @@ protected: socket->setProtocol(protocol); if (ignoreSslErrors) connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot())); + connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SIGNAL(socketError(QAbstractSocket::SocketError))); QFile file(m_keyFile); QVERIFY(file.open(QIODevice::ReadOnly)); @@ -1167,6 +1171,19 @@ void tst_QSslSocket::protocolServerSide_data() QTest::addColumn<QSsl::SslProtocol>("clientProtocol"); QTest::addColumn<bool>("works"); +#if QT_CONFIG(opensslv11) +#if !defined(OPENSSL_NO_SSL2) + // OpenSSL 1.1 has removed SSL2 support. But there is no OPENSSL_NO_SSL2 macro ... +#define OPENSSL_NO_SSL2 +#endif + // A client using our OpenSSL1.1 backend will negotiate up from TLS 1.0 or 1.1 + // to TLS 1.2 if the server asks for it, where our older backend fails to compromise. + // So some tests that fail for the old pass with the new. + const bool willUseTLS12 = true; +#else + const bool willUseTLS12 = false; +#endif // opensslv11 + #if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT) QTest::newRow("ssl2-ssl2") << QSsl::SslV2 << QSsl::SslV2 << false; // no idea why it does not work, but we don't care about SSL 2 #endif @@ -1242,6 +1259,38 @@ void tst_QSslSocket::protocolServerSide_data() #if !defined(OPENSSL_NO_SSL3) QTest::newRow("any-ssl3") << QSsl::AnyProtocol << QSsl::SslV3 << true; #endif + +#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT) + QTest::newRow("tls1.0orlater-ssl2") << QSsl::TlsV1_0OrLater << QSsl::SslV2 << false; +#endif +#if !defined(OPENSSL_NO_SSL3) + QTest::newRow("tls1.0orlater-ssl3") << QSsl::TlsV1_0OrLater << QSsl::SslV3 << false; +#endif + QTest::newRow("tls1.0orlater-tls1.0") << QSsl::TlsV1_0OrLater << QSsl::TlsV1_0 << true; + QTest::newRow("tls1.0orlater-tls1.1") << QSsl::TlsV1_0OrLater << QSsl::TlsV1_1 << true; + QTest::newRow("tls1.0orlater-tls1.2") << QSsl::TlsV1_0OrLater << QSsl::TlsV1_2 << true; + +#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT) + QTest::newRow("tls1.1orlater-ssl2") << QSsl::TlsV1_1OrLater << QSsl::SslV2 << false; +#endif +#if !defined(OPENSSL_NO_SSL3) + QTest::newRow("tls1.1orlater-ssl3") << QSsl::TlsV1_1OrLater << QSsl::SslV3 << false; +#endif + + QTest::newRow("tls1.1orlater-tls1.0") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_0 << willUseTLS12; + QTest::newRow("tls1.1orlater-tls1.1") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_1 << true; + QTest::newRow("tls1.1orlater-tls1.2") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_2 << true; + +#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT) + QTest::newRow("tls1.2orlater-ssl2") << QSsl::TlsV1_2OrLater << QSsl::SslV2 << false; +#endif +#if !defined(OPENSSL_NO_SSL3) + QTest::newRow("tls1.2orlater-ssl3") << QSsl::TlsV1_2OrLater << QSsl::SslV3 << false; +#endif + QTest::newRow("tls1.2orlater-tls1.0") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_0 << willUseTLS12; + QTest::newRow("tls1.2orlater-tls1.1") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_1 << willUseTLS12; + QTest::newRow("tls1.2orlater-tls1.2") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_2 << true; + QTest::newRow("any-tls1.0") << QSsl::AnyProtocol << QSsl::TlsV1_0 << true; QTest::newRow("any-tls1ssl3") << QSsl::AnyProtocol << QSsl::TlsV1SslV3 << true; QTest::newRow("any-secure") << QSsl::AnyProtocol << QSsl::SecureProtocols << true; @@ -1264,6 +1313,7 @@ void tst_QSslSocket::protocolServerSide() QVERIFY(server.listen()); QEventLoop loop; + connect(&server, SIGNAL(socketError(QAbstractSocket::SocketError)), &loop, SLOT(quit())); QTimer::singleShot(5000, &loop, SLOT(quit())); QSslSocket client; @@ -1281,7 +1331,15 @@ void tst_QSslSocket::protocolServerSide() QFETCH(bool, works); QAbstractSocket::SocketState expectedState = (works) ? QAbstractSocket::ConnectedState : QAbstractSocket::UnconnectedState; - QCOMPARE(int(client.state()), int(expectedState)); + // Determine whether the client or the server caused the event loop + // to quit due to a socket error, and investigate the culprit. + if (server.socket->error() != QAbstractSocket::UnknownSocketError) { + QVERIFY(client.error() == QAbstractSocket::UnknownSocketError); + QCOMPARE(int(server.socket->state()), int(expectedState)); + } else if (client.error() != QAbstractSocket::UnknownSocketError) { + QVERIFY(server.socket->error() == QAbstractSocket::UnknownSocketError); + QCOMPARE(int(client.state()), int(expectedState)); + } QCOMPARE(client.isEncrypted(), works); } @@ -2119,6 +2177,13 @@ void tst_QSslSocket::waitForMinusOne() // fifth verification: it should wait for 200 ms more QVERIFY(socket.waitForDisconnected(-1)); + + // sixth verification: reading from a disconnected socket returns -1 + // once we deplete the read buffer + QCOMPARE(socket.state(), QAbstractSocket::UnconnectedState); + socket.readAll(); + char aux; + QCOMPARE(socket.read(&aux, 1), -1); } class VerifyServer : public QTcpServer @@ -3621,7 +3686,9 @@ void tst_QSslSocket::ephemeralServerKey_data() QTest::addColumn<QString>("cipher"); QTest::addColumn<bool>("emptyKey"); +#if !QT_CONFIG(opensslv11) // 1.1 drops support for RC4-SHA QTest::newRow("NonForwardSecrecyCipher") << "RC4-SHA" << true; +#endif // !opensslv11 QTest::newRow("ForwardSecrecyCipher") << "ECDHE-RSA-AES256-SHA" << (QSslSocket::sslLibraryVersionNumber() < 0x10002000L); } |