summaryrefslogtreecommitdiffstats
path: root/tests/auto
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2019-04-11 07:47:21 +0200
committerLiang Qi <liang.qi@qt.io>2019-04-11 07:47:21 +0200
commitc7af193d2e49e9f10b86262e63d8d13abf72b5cf (patch)
tree7ca5d4ba83888bb5ad4d9b0141e5c62f8a5138f2 /tests/auto
parent235ac95520a0fc2c822dedce7358e3c64a764255 (diff)
parent63e88f60a769f2535945db0e1cabb9815ff45a77 (diff)
Merge remote-tracking branch 'origin/5.13' into dev
Conflicts: src/widgets/styles/qstyle_p.h Change-Id: I0e6e856bd6628da1135b3ba674dddffabbeb5c09
Diffstat (limited to 'tests/auto')
-rw-r--r--tests/auto/corelib/io/qurl/tst_qurl.cpp8
-rw-r--r--tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp13
-rw-r--r--tests/auto/network/access/http2/http2srv.cpp55
-rw-r--r--tests/auto/network/access/http2/http2srv.h15
-rw-r--r--tests/auto/network/access/http2/tst_http2.cpp93
5 files changed, 140 insertions, 44 deletions
diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp
index 3ee6a656b0..9c106c7f58 100644
--- a/tests/auto/corelib/io/qurl/tst_qurl.cpp
+++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp
@@ -47,6 +47,7 @@ class tst_QUrl : public QObject
private slots:
void initTestCase();
+ void cleanupTestCase();
void effectiveTLDs_data();
void effectiveTLDs();
void getSetCheck();
@@ -188,6 +189,7 @@ private slots:
private:
void testThreadingHelper();
+ const QString m_currentPath = QDir::currentPath();
QTemporaryDir m_tempDir;
};
@@ -196,6 +198,12 @@ void tst_QUrl::initTestCase()
QVERIFY2(m_tempDir.isValid(), qPrintable(m_tempDir.errorString()));
}
+void tst_QUrl::cleanupTestCase()
+{
+ // Restore working directory changed in fromUserInputWithCwd()
+ QDir::setCurrent(m_currentPath);
+}
+
// Testing get/set functions
void tst_QUrl::getSetCheck()
{
diff --git a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
index 467d299526..350ed24c28 100644
--- a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
+++ b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
@@ -40,6 +40,13 @@ struct MyStruct
int i;
};
+class MyGadget
+{
+ Q_GADGET
+public:
+ Q_INVOKABLE MyGadget() {}
+};
+
namespace MyNamespace {
// Used in tst_QMetaObject::checkScope
class MyClass : public QObject
@@ -1208,6 +1215,12 @@ void tst_QMetaObject::invokeMetaConstructor()
QCOMPARE(obj2->parent(), (QObject*)&obj);
QVERIFY(qobject_cast<NamespaceWithConstructibleClass::ConstructibleClass*>(obj2) != 0);
}
+ // gadget shouldn't return a valid pointer
+ {
+ QCOMPARE(MyGadget::staticMetaObject.constructorCount(), 1);
+ QTest::ignoreMessage(QtWarningMsg, "QMetaObject::newInstance: type MyGadget does not inherit QObject");
+ QVERIFY(!MyGadget::staticMetaObject.newInstance());
+ }
}
void tst_QMetaObject::invokeTypedefTypes()
diff --git a/tests/auto/network/access/http2/http2srv.cpp b/tests/auto/network/access/http2/http2srv.cpp
index 6e2220fa67..5a99d4e50c 100644
--- a/tests/auto/network/access/http2/http2srv.cpp
+++ b/tests/auto/network/access/http2/http2srv.cpp
@@ -76,11 +76,15 @@ void fill_push_header(const HttpHeader &originalRequest, HttpHeader &promisedReq
}
-Http2Server::Http2Server(bool h2c, const Http2::RawSettings &ss, const Http2::RawSettings &cs)
- : serverSettings(ss),
- expectedClientSettings(cs),
- clearTextHTTP2(h2c)
+Http2Server::Http2Server(H2Type type, const Http2::RawSettings &ss, const Http2::RawSettings &cs)
+ : connectionType(type),
+ serverSettings(ss),
+ expectedClientSettings(cs)
{
+#if !QT_CONFIG(ssl)
+ Q_ASSERT(type != H2Type::h2Alpn && type != H2Type::h2Direct);
+#endif
+
responseBody = "<html>\n"
"<head>\n"
"<title>Sample \"Hello, World\" Application</title>\n"
@@ -129,15 +133,15 @@ void Http2Server::redirectOpenStream(quint16 port)
targetPort = port;
}
+bool Http2Server::isClearText() const
+{
+ return connectionType == H2Type::h2c || connectionType == H2Type::h2cDirect;
+}
+
void Http2Server::startServer()
{
-#ifdef QT_NO_SSL
- // Let the test fail with timeout.
- if (!clearTextHTTP2)
- return;
-#endif
if (listen()) {
- if (clearTextHTTP2)
+ if (isClearText())
authority = QStringLiteral("127.0.0.1:%1").arg(serverPort()).toLatin1();
emit serverStarted(serverPort());
}
@@ -146,7 +150,7 @@ void Http2Server::startServer()
bool Http2Server::sendProtocolSwitchReply()
{
Q_ASSERT(socket);
- Q_ASSERT(clearTextHTTP2 && upgradeProtocol);
+ Q_ASSERT(connectionType == H2Type::h2c);
// 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"
@@ -262,25 +266,28 @@ void Http2Server::sendWINDOW_UPDATE(quint32 streamID, quint32 delta)
void Http2Server::incomingConnection(qintptr socketDescriptor)
{
- if (clearTextHTTP2) {
+ if (isClearText()) {
socket.reset(new QTcpSocket);
const bool set = socket->setSocketDescriptor(socketDescriptor);
Q_ASSERT(set);
// Stop listening:
close();
- upgradeProtocol = true;
+ upgradeProtocol = connectionType == H2Type::h2c;
QMetaObject::invokeMethod(this, "connectionEstablished",
Qt::QueuedConnection);
} else {
-#ifndef QT_NO_SSL
+#if QT_CONFIG(ssl)
socket.reset(new QSslSocket);
QSslSocket *sslSocket = static_cast<QSslSocket *>(socket.data());
- // Add HTTP2 as supported protocol:
- auto conf = QSslConfiguration::defaultConfiguration();
- auto protos = conf.allowedNextProtocols();
- protos.prepend(QSslConfiguration::ALPNProtocolHTTP2);
- conf.setAllowedNextProtocols(protos);
- sslSocket->setSslConfiguration(conf);
+
+ if (connectionType == H2Type::h2Alpn) {
+ // Add HTTP2 as supported protocol:
+ auto conf = QSslConfiguration::defaultConfiguration();
+ auto protos = conf.allowedNextProtocols();
+ protos.prepend(QSslConfiguration::ALPNProtocolHTTP2);
+ conf.setAllowedNextProtocols(protos);
+ sslSocket->setSslConfiguration(conf);
+ }
// SSL-related setup ...
sslSocket->setPeerVerifyMode(QSslSocket::VerifyNone);
sslSocket->setProtocol(QSsl::TlsV1_2OrLater);
@@ -299,7 +306,7 @@ void Http2Server::incomingConnection(qintptr socketDescriptor)
connect(sslSocket, SIGNAL(encrypted()), this, SLOT(connectionEstablished()));
sslSocket->startServerEncryption();
#else
- Q_UNREACHABLE();
+ Q_ASSERT(0);
#endif
}
}
@@ -377,7 +384,7 @@ void Http2Server::connectionEstablished()
{
using namespace Http2;
- if (testingGOAWAY && !clearTextHTTP2)
+ if (testingGOAWAY && !isClearText())
return triggerGOAWAYEmulation();
// For clearTextHTTP2 we first have to respond with 'protocol switch'
@@ -392,7 +399,7 @@ void Http2Server::connectionEstablished()
waitingClientSettings = false;
settingsSent = false;
- if (clearTextHTTP2) {
+ if (connectionType == H2Type::h2c) {
requestLine.clear();
// Now we have to handle HTTP/1.1 request. We use Get/Post in our test,
// so set requestType to something unsupported:
@@ -818,7 +825,7 @@ void Http2Server::sendResponse(quint32 streamID, bool emptyBody)
Q_ASSERT(targetPort);
header.push_back({":status", "308"});
const QString url("%1://localhost:%2/");
- header.push_back({"location", url.arg(clearTextHTTP2 ? QStringLiteral("http") : QStringLiteral("https"),
+ header.push_back({"location", url.arg(isClearText() ? QStringLiteral("http") : QStringLiteral("https"),
QString::number(targetPort)).toLatin1()});
} else {
diff --git a/tests/auto/network/access/http2/http2srv.h b/tests/auto/network/access/http2/http2srv.h
index ae3f084fdc..4ef4b25101 100644
--- a/tests/auto/network/access/http2/http2srv.h
+++ b/tests/auto/network/access/http2/http2srv.h
@@ -62,21 +62,32 @@ public:
Q_DECLARE_PRIVATE(Http11Reply)
};
+enum class H2Type {
+ h2Alpn, // Secure connection, ALPN to negotiate h2.
+ h2c, // Clear text with protocol upgrade.
+ h2Direct, // Secure connection, ALPN not supported.
+ h2cDirect, // Clear text direct
+};
+
class Http2Server : public QTcpServer
{
Q_OBJECT
public:
- Http2Server(bool clearText, const Http2::RawSettings &serverSettings,
+
+ Http2Server(H2Type type, const Http2::RawSettings &serverSettings,
const Http2::RawSettings &clientSettings);
~Http2Server();
+
// To be called before server started:
void enablePushPromise(bool enabled, const QByteArray &path = QByteArray());
void setResponseBody(const QByteArray &body);
void emulateGOAWAY(int timeout);
void redirectOpenStream(quint16 targetPort);
+ bool isClearText() const;
+
// Invokables, since we can call them from the main thread,
// but server (can) work on its own thread.
Q_INVOKABLE void startServer();
@@ -129,6 +140,7 @@ private:
QScopedPointer<QAbstractSocket> socket;
+ H2Type connectionType = H2Type::h2Alpn;
// Connection preface:
bool waitingClientPreface = false;
bool waitingClientSettings = false;
@@ -170,7 +182,6 @@ private:
quint32 streamRecvWindowSize = Http2::defaultSessionWindowSize;
QByteArray responseBody;
- bool clearTextHTTP2 = false;
bool pushPromiseEnabled = false;
quint32 lastPromisedStream = 0;
QByteArray pushPath;
diff --git a/tests/auto/network/access/http2/tst_http2.cpp b/tests/auto/network/access/http2/tst_http2.cpp
index 02c5e51cbe..53d0e7a694 100644
--- a/tests/auto/network/access/http2/tst_http2.cpp
+++ b/tests/auto/network/access/http2/tst_http2.cpp
@@ -60,6 +60,9 @@ const bool clearTextHTTP2 = false;
const bool clearTextHTTP2 = true;
#endif
+Q_DECLARE_METATYPE(H2Type)
+Q_DECLARE_METATYPE(QNetworkRequest::Attribute)
+
QT_BEGIN_NAMESPACE
class tst_Http2 : public QObject
@@ -70,6 +73,7 @@ public:
~tst_Http2();
private slots:
// Tests:
+ void singleRequest_data();
void singleRequest();
void multipleRequests();
void flowControlClientSide();
@@ -101,13 +105,13 @@ private:
// small payload.
void runEventLoop(int ms = 5000);
void stopEventLoop();
- Http2Server *newServer(const Http2::RawSettings &serverSettings,
+ Http2Server *newServer(const Http2::RawSettings &serverSettings, H2Type connectionType,
const Http2::ProtocolParameters &clientSettings = {});
// Send a get or post request, depending on a payload (empty or not).
void sendRequest(int streamNumber,
QNetworkRequest::Priority priority = QNetworkRequest::NormalPriority,
const QByteArray &payload = QByteArray());
- QUrl requestUrl() const;
+ QUrl requestUrl(H2Type connnectionType) const;
quint16 serverPort = 0;
QThread *workerThread = nullptr;
@@ -144,6 +148,11 @@ struct ServerDeleter
using ServerPtr = QScopedPointer<Http2Server, ServerDeleter>;
+H2Type defaultConnectionType()
+{
+ return clearTextHTTP2 ? H2Type::h2c : H2Type::h2Alpn;
+}
+
} // unnamed namespace
tst_Http2::tst_Http2()
@@ -165,25 +174,59 @@ tst_Http2::~tst_Http2()
}
}
+void tst_Http2::singleRequest_data()
+{
+ QTest::addColumn<QNetworkRequest::Attribute>("h2Attribute");
+ QTest::addColumn<H2Type>("connectionType");
+
+ // 'Clear text' that should always work, either via the protocol upgrade
+ // or as direct.
+ QTest::addRow("h2c-upgrade") << QNetworkRequest::HTTP2AllowedAttribute << H2Type::h2c;
+ QTest::addRow("h2c-direct") << QNetworkRequest::Http2DirectAttribute << H2Type::h2cDirect;
+
+ if (!clearTextHTTP2) {
+ // Qt with TLS where TLS-backend supports ALPN.
+ QTest::addRow("h2-ALPN") << QNetworkRequest::HTTP2AllowedAttribute << H2Type::h2Alpn;
+ }
+
+#if QT_CONFIG(ssl)
+ QTest::addRow("h2-direct") << QNetworkRequest::Http2DirectAttribute << H2Type::h2Direct;
+#endif
+}
+
void tst_Http2::singleRequest()
{
clearHTTP2State();
+#if QT_CONFIG(securetransport)
+ // Normally on macOS we use plain text only for SecureTransport
+ // does not support ALPN on the server side. With 'direct encrytped'
+ // we have to use TLS sockets (== private key) and thus suppress a
+ // keychain UI asking for permission to use a private key.
+ // Our CI has this, but somebody testing locally - will have a problem.
+ qputenv("QT_SSL_USE_TEMPORARY_KEYCHAIN", QByteArray("1"));
+ auto envRollback = qScopeGuard([](){
+ qunsetenv("QT_SSL_USE_TEMPORARY_KEYCHAIN");
+ });
+#endif
+
serverPort = 0;
nRequests = 1;
- ServerPtr srv(newServer(defaultServerSettings));
+ QFETCH(const H2Type, connectionType);
+ ServerPtr srv(newServer(defaultServerSettings, connectionType));
QMetaObject::invokeMethod(srv.data(), "startServer", Qt::QueuedConnection);
runEventLoop();
QVERIFY(serverPort != 0);
- auto url = requestUrl();
+ auto url = requestUrl(connectionType);
url.setPath("/index.html");
QNetworkRequest request(url);
- request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, QVariant(true));
+ QFETCH(const QNetworkRequest::Attribute, h2Attribute);
+ request.setAttribute(h2Attribute, QVariant(true));
auto reply = manager.get(request);
connect(reply, &QNetworkReply::finished, this, &tst_Http2::replyFinished);
@@ -208,7 +251,7 @@ void tst_Http2::multipleRequests()
serverPort = 0;
nRequests = 10;
- ServerPtr srv(newServer(defaultServerSettings));
+ ServerPtr srv(newServer(defaultServerSettings, defaultConnectionType()));
QMetaObject::invokeMethod(srv.data(), "startServer", Qt::QueuedConnection);
@@ -259,7 +302,7 @@ void tst_Http2::flowControlClientSide()
manager.setProperty(Http2::http2ParametersPropertyName, QVariant::fromValue(params));
const Http2::RawSettings serverSettings = {{Settings::MAX_CONCURRENT_STREAMS_ID, quint32(3)}};
- ServerPtr srv(newServer(serverSettings, params));
+ ServerPtr srv(newServer(serverSettings, defaultConnectionType(), params));
const QByteArray respond(int(Http2::defaultSessionWindowSize * 10), 'x');
@@ -301,7 +344,7 @@ void tst_Http2::flowControlServerSide()
const Http2::RawSettings serverSettings = {{Settings::MAX_CONCURRENT_STREAMS_ID, 7}};
- ServerPtr srv(newServer(serverSettings));
+ ServerPtr srv(newServer(serverSettings, defaultConnectionType()));
const QByteArray payload(int(Http2::defaultSessionWindowSize * 500), 'x');
@@ -336,7 +379,7 @@ void tst_Http2::pushPromise()
params.settingsFrameData[Settings::ENABLE_PUSH_ID] = 1;
manager.setProperty(Http2::http2ParametersPropertyName, QVariant::fromValue(params));
- ServerPtr srv(newServer(defaultServerSettings, params));
+ ServerPtr srv(newServer(defaultServerSettings, defaultConnectionType(), params));
srv->enablePushPromise(true, QByteArray("/script.js"));
QMetaObject::invokeMethod(srv.data(), "startServer", Qt::QueuedConnection);
@@ -344,7 +387,7 @@ void tst_Http2::pushPromise()
QVERIFY(serverPort != 0);
- auto url = requestUrl();
+ auto url = requestUrl(defaultConnectionType());
url.setPath("/index.html");
QNetworkRequest request(url);
@@ -410,14 +453,14 @@ void tst_Http2::goaway()
serverPort = 0;
nRequests = 3;
- ServerPtr srv(newServer(defaultServerSettings));
+ ServerPtr srv(newServer(defaultServerSettings, defaultConnectionType()));
srv->emulateGOAWAY(responseTimeoutMS);
QMetaObject::invokeMethod(srv.data(), "startServer", Qt::QueuedConnection);
runEventLoop();
QVERIFY(serverPort != 0);
- auto url = requestUrl();
+ auto url = requestUrl(defaultConnectionType());
// We have to store these replies, so that we can check errors later.
std::vector<QNetworkReply *> replies(nRequests);
for (int i = 0; i < nRequests; ++i) {
@@ -457,7 +500,7 @@ void tst_Http2::earlyResponse()
serverPort = 0;
nRequests = 1;
- ServerPtr targetServer(newServer(defaultServerSettings));
+ ServerPtr targetServer(newServer(defaultServerSettings, defaultConnectionType()));
QMetaObject::invokeMethod(targetServer.data(), "startServer", Qt::QueuedConnection);
runEventLoop();
@@ -467,7 +510,7 @@ void tst_Http2::earlyResponse()
const quint16 targetPort = serverPort;
serverPort = 0;
- ServerPtr redirector(newServer(defaultServerSettings));
+ ServerPtr redirector(newServer(defaultServerSettings, defaultConnectionType()));
redirector->redirectOpenStream(targetPort);
QMetaObject::invokeMethod(redirector.data(), "startServer", Qt::QueuedConnection);
@@ -507,11 +550,11 @@ void tst_Http2::stopEventLoop()
eventLoop.exitLoop();
}
-Http2Server *tst_Http2::newServer(const Http2::RawSettings &serverSettings,
+Http2Server *tst_Http2::newServer(const Http2::RawSettings &serverSettings, H2Type connectionType,
const Http2::ProtocolParameters &clientSettings)
{
using namespace Http2;
- auto srv = new Http2Server(clearTextHTTP2, serverSettings,
+ auto srv = new Http2Server(connectionType, serverSettings,
clientSettings.settingsFrameData);
using Srv = Http2Server;
@@ -536,7 +579,7 @@ void tst_Http2::sendRequest(int streamNumber,
QNetworkRequest::Priority priority,
const QByteArray &payload)
{
- auto url = requestUrl();
+ auto url = requestUrl(defaultConnectionType());
url.setPath(QString("/stream%1.html").arg(streamNumber));
QNetworkRequest request(url);
@@ -555,10 +598,24 @@ void tst_Http2::sendRequest(int streamNumber,
connect(reply, &QNetworkReply::finished, this, &tst_Http2::replyFinished);
}
-QUrl tst_Http2::requestUrl() const
+QUrl tst_Http2::requestUrl(H2Type connectionType) const
{
+#if !QT_CONFIG(ssl)
+ Q_ASSERT(connectionType != H2Type::h2Alpn && connectionType != H2Type::h2Direct);
+#endif
static auto url = QUrl(QLatin1String(clearTextHTTP2 ? "http://127.0.0.1" : "https://127.0.0.1"));
url.setPort(serverPort);
+ // Clear text may mean no-TLS-at-all or crappy-TLS-without-ALPN.
+ switch (connectionType) {
+ case H2Type::h2Alpn:
+ case H2Type::h2Direct:
+ url.setScheme(QStringLiteral("https"));
+ break;
+ case H2Type::h2c:
+ case H2Type::h2cDirect:
+ url.setScheme(QStringLiteral("http"));
+ break;
+ }
return url;
}