tst_http2 - make the test less rough in general

1. Use per-case QNAM objects
2. In a slots (connected to QNetworkReplies) - if an error detected - stop
   the event loop (no reason to continue waiting) and then do normal
   QVERIFY/QCOMPARE things.
3. In tests, check QTest::currentTestFailed after the event loop returned -
   if an error was detected by a slot, no need to continue with QCOMPARE/QVERIFY
   in the test itself.

Task-number: QTBUG-77053
Change-Id: I3827a629a2749becd3dc6eee7fd6994d96441e65
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
Timur Pocheptsov 2019-07-16 12:27:34 +02:00
parent 1d8c9978fa
commit 334f09b585

View File

@ -46,6 +46,7 @@
#endif // NO_SSL #endif // NO_SSL
#include <cstdlib> #include <cstdlib>
#include <memory>
#include <string> #include <string>
#include "emulationdetector.h" #include "emulationdetector.h"
@ -116,7 +117,7 @@ private:
quint16 serverPort = 0; quint16 serverPort = 0;
QThread *workerThread = nullptr; QThread *workerThread = nullptr;
QNetworkAccessManager manager; std::unique_ptr<QNetworkAccessManager> manager;
QTestEventLoop eventLoop; QTestEventLoop eventLoop;
@ -130,6 +131,10 @@ private:
static const Http2::RawSettings defaultServerSettings; static const Http2::RawSettings defaultServerSettings;
}; };
#define STOP_ON_FAILURE \
if (QTest::currentTestFailed()) \
return;
const Http2::RawSettings tst_Http2::defaultServerSettings{{Http2::Settings::MAX_CONCURRENT_STREAMS_ID, 100}}; const Http2::RawSettings tst_Http2::defaultServerSettings{{Http2::Settings::MAX_CONCURRENT_STREAMS_ID, 100}};
namespace { namespace {
@ -177,7 +182,7 @@ tst_Http2::~tst_Http2()
void tst_Http2::init() void tst_Http2::init()
{ {
manager.clearConnectionCache(); manager.reset(new QNetworkAccessManager);
} }
void tst_Http2::singleRequest_data() void tst_Http2::singleRequest_data()
@ -234,13 +239,14 @@ void tst_Http2::singleRequest()
QFETCH(const QNetworkRequest::Attribute, h2Attribute); QFETCH(const QNetworkRequest::Attribute, h2Attribute);
request.setAttribute(h2Attribute, QVariant(true)); request.setAttribute(h2Attribute, QVariant(true));
auto reply = manager.get(request); auto reply = manager->get(request);
connect(reply, &QNetworkReply::finished, this, &tst_Http2::replyFinished); connect(reply, &QNetworkReply::finished, this, &tst_Http2::replyFinished);
// Since we're using self-signed certificates, // Since we're using self-signed certificates,
// ignore SSL errors: // ignore SSL errors:
reply->ignoreSslErrors(); reply->ignoreSslErrors();
runEventLoop(); runEventLoop();
STOP_ON_FAILURE
QVERIFY(nRequests == 0); QVERIFY(nRequests == 0);
QVERIFY(prefaceOK); QVERIFY(prefaceOK);
@ -276,6 +282,7 @@ void tst_Http2::multipleRequests()
sendRequest(i, priorities[QRandomGenerator::global()->bounded(3)]); sendRequest(i, priorities[QRandomGenerator::global()->bounded(3)]);
runEventLoop(); runEventLoop();
STOP_ON_FAILURE
QVERIFY(nRequests == 0); QVERIFY(nRequests == 0);
QVERIFY(prefaceOK); QVERIFY(prefaceOK);
@ -305,7 +312,7 @@ void tst_Http2::flowControlClientSide()
params.maxSessionReceiveWindowSize = Http2::defaultSessionWindowSize * 5; params.maxSessionReceiveWindowSize = Http2::defaultSessionWindowSize * 5;
params.settingsFrameData[Settings::INITIAL_WINDOW_SIZE_ID] = Http2::defaultSessionWindowSize; params.settingsFrameData[Settings::INITIAL_WINDOW_SIZE_ID] = Http2::defaultSessionWindowSize;
// Inform our manager about non-default settings: // Inform our manager about non-default settings:
manager.setProperty(Http2::http2ParametersPropertyName, QVariant::fromValue(params)); manager->setProperty(Http2::http2ParametersPropertyName, QVariant::fromValue(params));
const Http2::RawSettings serverSettings = {{Settings::MAX_CONCURRENT_STREAMS_ID, quint32(3)}}; const Http2::RawSettings serverSettings = {{Settings::MAX_CONCURRENT_STREAMS_ID, quint32(3)}};
ServerPtr srv(newServer(serverSettings, defaultConnectionType(), params)); ServerPtr srv(newServer(serverSettings, defaultConnectionType(), params));
@ -323,6 +330,7 @@ void tst_Http2::flowControlClientSide()
sendRequest(i); sendRequest(i);
runEventLoop(120000); runEventLoop(120000);
STOP_ON_FAILURE
QVERIFY(nRequests == 0); QVERIFY(nRequests == 0);
QVERIFY(prefaceOK); QVERIFY(prefaceOK);
@ -363,6 +371,7 @@ void tst_Http2::flowControlServerSide()
sendRequest(i, QNetworkRequest::NormalPriority, payload); sendRequest(i, QNetworkRequest::NormalPriority, payload);
runEventLoop(120000); runEventLoop(120000);
STOP_ON_FAILURE
QVERIFY(nRequests == 0); QVERIFY(nRequests == 0);
QVERIFY(prefaceOK); QVERIFY(prefaceOK);
@ -383,7 +392,7 @@ void tst_Http2::pushPromise()
Http2::ProtocolParameters params; Http2::ProtocolParameters params;
// Defaults are good, except ENABLE_PUSH: // Defaults are good, except ENABLE_PUSH:
params.settingsFrameData[Settings::ENABLE_PUSH_ID] = 1; params.settingsFrameData[Settings::ENABLE_PUSH_ID] = 1;
manager.setProperty(Http2::http2ParametersPropertyName, QVariant::fromValue(params)); manager->setProperty(Http2::http2ParametersPropertyName, QVariant::fromValue(params));
ServerPtr srv(newServer(defaultServerSettings, defaultConnectionType(), params)); ServerPtr srv(newServer(defaultServerSettings, defaultConnectionType(), params));
srv->enablePushPromise(true, QByteArray("/script.js")); srv->enablePushPromise(true, QByteArray("/script.js"));
@ -399,12 +408,13 @@ void tst_Http2::pushPromise()
QNetworkRequest request(url); QNetworkRequest request(url);
request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, QVariant(true)); request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, QVariant(true));
auto reply = manager.get(request); auto reply = manager->get(request);
connect(reply, &QNetworkReply::finished, this, &tst_Http2::replyFinished); connect(reply, &QNetworkReply::finished, this, &tst_Http2::replyFinished);
// Since we're using self-signed certificates, ignore SSL errors: // Since we're using self-signed certificates, ignore SSL errors:
reply->ignoreSslErrors(); reply->ignoreSslErrors();
runEventLoop(); runEventLoop();
STOP_ON_FAILURE
QVERIFY(nRequests == 0); QVERIFY(nRequests == 0);
QVERIFY(prefaceOK); QVERIFY(prefaceOK);
@ -422,7 +432,7 @@ void tst_Http2::pushPromise()
url.setPath("/script.js"); url.setPath("/script.js");
QNetworkRequest promisedRequest(url); QNetworkRequest promisedRequest(url);
promisedRequest.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, QVariant(true)); promisedRequest.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, QVariant(true));
reply = manager.get(promisedRequest); reply = manager->get(promisedRequest);
connect(reply, &QNetworkReply::finished, this, &tst_Http2::replyFinished); connect(reply, &QNetworkReply::finished, this, &tst_Http2::replyFinished);
reply->ignoreSslErrors(); reply->ignoreSslErrors();
@ -473,7 +483,7 @@ void tst_Http2::goaway()
url.setPath(QString("/%1").arg(i)); url.setPath(QString("/%1").arg(i));
QNetworkRequest request(url); QNetworkRequest request(url);
request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, QVariant(true)); request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, QVariant(true));
replies[i] = manager.get(request); replies[i] = manager->get(request);
QCOMPARE(replies[i]->error(), QNetworkReply::NoError); QCOMPARE(replies[i]->error(), QNetworkReply::NoError);
void (QNetworkReply::*errorSignal)(QNetworkReply::NetworkError) = void (QNetworkReply::*errorSignal)(QNetworkReply::NetworkError) =
&QNetworkReply::error; &QNetworkReply::error;
@ -483,6 +493,7 @@ void tst_Http2::goaway()
} }
runEventLoop(5000 + responseTimeoutMS); runEventLoop(5000 + responseTimeoutMS);
STOP_ON_FAILURE
// No request processed, no 'replyFinished' slot calls: // No request processed, no 'replyFinished' slot calls:
QCOMPARE(nRequests, 0); QCOMPARE(nRequests, 0);
@ -526,6 +537,7 @@ void tst_Http2::earlyResponse()
sendRequest(1, QNetworkRequest::NormalPriority, {1000000, Qt::Uninitialized}); sendRequest(1, QNetworkRequest::NormalPriority, {1000000, Qt::Uninitialized});
runEventLoop(); runEventLoop();
STOP_ON_FAILURE
QVERIFY(nRequests == 0); QVERIFY(nRequests == 0);
QVERIFY(prefaceOK); QVERIFY(prefaceOK);
@ -543,7 +555,7 @@ void tst_Http2::clearHTTP2State()
windowUpdates = 0; windowUpdates = 0;
prefaceOK = false; prefaceOK = false;
serverGotSettingsACK = false; serverGotSettingsACK = false;
manager.setProperty(Http2::http2ParametersPropertyName, QVariant()); manager->setProperty(Http2::http2ParametersPropertyName, QVariant());
} }
void tst_Http2::runEventLoop(int ms) void tst_Http2::runEventLoop(int ms)
@ -596,9 +608,9 @@ void tst_Http2::sendRequest(int streamNumber,
QNetworkReply *reply = nullptr; QNetworkReply *reply = nullptr;
if (payload.size()) if (payload.size())
reply = manager.post(request, payload); reply = manager->post(request, payload);
else else
reply = manager.get(request); reply = manager->get(request);
reply->ignoreSslErrors(); reply->ignoreSslErrors();
connect(reply, &QNetworkReply::finished, this, &tst_Http2::replyFinished); connect(reply, &QNetworkReply::finished, this, &tst_Http2::replyFinished);
@ -690,14 +702,29 @@ void tst_Http2::replyFinished()
QVERIFY(nRequests); QVERIFY(nRequests);
if (const auto reply = qobject_cast<QNetworkReply *>(sender())) { if (const auto reply = qobject_cast<QNetworkReply *>(sender())) {
if (reply->error() != QNetworkReply::NoError)
stopEventLoop();
QCOMPARE(reply->error(), QNetworkReply::NoError); QCOMPARE(reply->error(), QNetworkReply::NoError);
const QVariant http2Used(reply->attribute(QNetworkRequest::HTTP2WasUsedAttribute)); const QVariant http2Used(reply->attribute(QNetworkRequest::HTTP2WasUsedAttribute));
if (!http2Used.isValid() || !http2Used.toBool())
stopEventLoop();
QVERIFY(http2Used.isValid()); QVERIFY(http2Used.isValid());
QVERIFY(http2Used.toBool()); QVERIFY(http2Used.toBool());
const QVariant spdyUsed(reply->attribute(QNetworkRequest::SpdyWasUsedAttribute)); const QVariant spdyUsed(reply->attribute(QNetworkRequest::SpdyWasUsedAttribute));
if (!spdyUsed.isValid() || spdyUsed.toBool())
stopEventLoop();
QVERIFY(spdyUsed.isValid()); QVERIFY(spdyUsed.isValid());
QVERIFY(!spdyUsed.toBool()); QVERIFY(!spdyUsed.toBool());
const QVariant code(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute)); const QVariant code(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute));
if (!code.isValid() || !code.canConvert<int>() || code.value<int>() != 200)
stopEventLoop();
QVERIFY(code.isValid()); QVERIFY(code.isValid());
QVERIFY(code.canConvert<int>()); QVERIFY(code.canConvert<int>());
QCOMPARE(code.value<int>(), 200); QCOMPARE(code.value<int>(), 200);
@ -715,6 +742,8 @@ void tst_Http2::replyFinishedWithError()
if (const auto reply = qobject_cast<QNetworkReply *>(sender())) { if (const auto reply = qobject_cast<QNetworkReply *>(sender())) {
// For now this is a 'generic' code, it just verifies some error was // For now this is a 'generic' code, it just verifies some error was
// reported without testing its type. // reported without testing its type.
if (reply->error() == QNetworkReply::NoError)
stopEventLoop();
QVERIFY(reply->error() != QNetworkReply::NoError); QVERIFY(reply->error() != QNetworkReply::NoError);
} }