summaryrefslogtreecommitdiffstats
path: root/tests/auto/network
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/network')
-rw-r--r--tests/auto/network/CMakeLists.txt5
-rw-r--r--tests/auto/network/access/CMakeLists.txt15
-rw-r--r--tests/auto/network/access/hpack/CMakeLists.txt11
-rw-r--r--tests/auto/network/access/hpack/tst_hpack.cpp2
-rw-r--r--tests/auto/network/access/hsts/CMakeLists.txt9
-rw-r--r--tests/auto/network/access/hsts/tst_qhsts.cpp91
-rw-r--r--tests/auto/network/access/http2/BLACKLIST2
-rw-r--r--tests/auto/network/access/http2/CMakeLists.txt9
-rw-r--r--tests/auto/network/access/http2/http2srv.cpp73
-rw-r--r--tests/auto/network/access/http2/http2srv.h12
-rw-r--r--tests/auto/network/access/http2/tst_http2.cpp315
-rw-r--r--tests/auto/network/access/qabstractnetworkcache/CMakeLists.txt11
-rw-r--r--tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp24
-rw-r--r--tests/auto/network/access/qdecompresshelper/CMakeLists.txt13
-rw-r--r--tests/auto/network/access/qdecompresshelper/tst_qdecompresshelper.cpp15
-rw-r--r--tests/auto/network/access/qformdatabuilder/CMakeLists.txt22
-rw-r--r--tests/auto/network/access/qformdatabuilder/document.docxbin0 -> 10548 bytes
-rw-r--r--tests/auto/network/access/qformdatabuilder/image1.jpgbin0 -> 518 bytes
-rw-r--r--tests/auto/network/access/qformdatabuilder/rfc3252.txt1
-rw-r--r--tests/auto/network/access/qformdatabuilder/sheet.xlsxbin0 -> 8534 bytes
-rw-r--r--tests/auto/network/access/qformdatabuilder/tst_qformdatabuilder.cpp203
-rw-r--r--tests/auto/network/access/qhttp2connection/CMakeLists.txt16
-rw-r--r--tests/auto/network/access/qhttp2connection/tst_qhttp2connection.cpp397
-rw-r--r--tests/auto/network/access/qhttpheaderparser/CMakeLists.txt5
-rw-r--r--tests/auto/network/access/qhttpheaderparser/tst_qhttpheaderparser.cpp2
-rw-r--r--tests/auto/network/access/qhttpheaders/CMakeLists.txt16
-rw-r--r--tests/auto/network/access/qhttpheaders/tst_qhttpheaders.cpp552
-rw-r--r--tests/auto/network/access/qhttpheadershelper/CMakeLists.txt15
-rw-r--r--tests/auto/network/access/qhttpheadershelper/tst_qhttpheadershelper.cpp76
-rw-r--r--tests/auto/network/access/qhttpnetworkconnection/CMakeLists.txt12
-rw-r--r--tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp24
-rw-r--r--tests/auto/network/access/qhttpnetworkreply/CMakeLists.txt9
-rw-r--r--tests/auto/network/access/qhttpnetworkreply/tst_qhttpnetworkreply.cpp4
-rw-r--r--tests/auto/network/access/qnetworkaccessmanager/CMakeLists.txt8
-rw-r--r--tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp2
-rw-r--r--tests/auto/network/access/qnetworkcachemetadata/CMakeLists.txt8
-rw-r--r--tests/auto/network/access/qnetworkcachemetadata/tst_qnetworkcachemetadata.cpp53
-rw-r--r--tests/auto/network/access/qnetworkcookie/CMakeLists.txt8
-rw-r--r--tests/auto/network/access/qnetworkcookie/tst_qnetworkcookie.cpp222
-rw-r--r--tests/auto/network/access/qnetworkcookiejar/CMakeLists.txt8
-rw-r--r--tests/auto/network/access/qnetworkcookiejar/testdata/publicsuffix/public_suffix_list.dafsabin53663 -> 52422 bytes
-rw-r--r--tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp31
-rw-r--r--tests/auto/network/access/qnetworkdiskcache/CMakeLists.txt8
-rw-r--r--tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp47
-rw-r--r--tests/auto/network/access/qnetworkreply/CMakeLists.txt6
-rw-r--r--tests/auto/network/access/qnetworkreply/echo/CMakeLists.txt4
-rw-r--r--tests/auto/network/access/qnetworkreply/echo/main.cpp8
-rw-r--r--tests/auto/network/access/qnetworkreply/test/CMakeLists.txt19
-rw-r--r--tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp1371
-rw-r--r--tests/auto/network/access/qnetworkreply_local/CMakeLists.txt9
-rw-r--r--tests/auto/network/access/qnetworkreply_local/minihttpserver.h246
-rw-r--r--tests/auto/network/access/qnetworkreply_local/tst_qnetworkreply_local.cpp177
-rw-r--r--tests/auto/network/access/qnetworkrequest/CMakeLists.txt8
-rw-r--r--tests/auto/network/access/qnetworkrequest/tst_qnetworkrequest.cpp197
-rw-r--r--tests/auto/network/access/qnetworkrequestfactory/CMakeLists.txt17
-rw-r--r--tests/auto/network/access/qnetworkrequestfactory/tst_qnetworkrequestfactory.cpp423
-rw-r--r--tests/auto/network/access/qrestaccessmanager/CMakeLists.txt17
-rw-r--r--tests/auto/network/access/qrestaccessmanager/httptestserver.cpp268
-rw-r--r--tests/auto/network/access/qrestaccessmanager/httptestserver_p.h90
-rw-r--r--tests/auto/network/access/qrestaccessmanager/tst_qrestaccessmanager.cpp876
-rw-r--r--tests/auto/network/kernel/CMakeLists.txt13
-rw-r--r--tests/auto/network/kernel/qauthenticator/CMakeLists.txt9
-rw-r--r--tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp19
-rw-r--r--tests/auto/network/kernel/qdnslookup/BLACKLIST2
-rw-r--r--tests/auto/network/kernel/qdnslookup/CMakeLists.txt14
-rw-r--r--tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp865
-rw-r--r--tests/auto/network/kernel/qdnslookup_appless/CMakeLists.txt8
-rw-r--r--tests/auto/network/kernel/qdnslookup_appless/tst_qdnslookup_appless.cpp2
-rw-r--r--tests/auto/network/kernel/qhostaddress/CMakeLists.txt8
-rw-r--r--tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp12
-rw-r--r--tests/auto/network/kernel/qhostinfo/CMakeLists.txt9
-rw-r--r--tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp367
-rw-r--r--tests/auto/network/kernel/qnetworkaddressentry/CMakeLists.txt8
-rw-r--r--tests/auto/network/kernel/qnetworkaddressentry/tst_qnetworkaddressentry.cpp2
-rw-r--r--tests/auto/network/kernel/qnetworkdatagram/CMakeLists.txt8
-rw-r--r--tests/auto/network/kernel/qnetworkdatagram/tst_qnetworkdatagram.cpp2
-rw-r--r--tests/auto/network/kernel/qnetworkinformation/CMakeLists.txt6
-rw-r--r--tests/auto/network/kernel/qnetworkinformation/tst_qnetworkinformation.cpp6
-rw-r--r--tests/auto/network/kernel/qnetworkinformation_appless/CMakeLists.txt6
-rw-r--r--tests/auto/network/kernel/qnetworkinformation_appless/tst_qnetworkinformation_appless.cpp2
-rw-r--r--tests/auto/network/kernel/qnetworkinterface/CMakeLists.txt10
-rw-r--r--tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp48
-rw-r--r--tests/auto/network/kernel/qnetworkproxy/CMakeLists.txt8
-rw-r--r--tests/auto/network/kernel/qnetworkproxy/tst_qnetworkproxy.cpp2
-rw-r--r--tests/auto/network/kernel/qnetworkproxyfactory/CMakeLists.txt8
-rw-r--r--tests/auto/network/kernel/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp11
-rw-r--r--tests/auto/network/selftest/tst_networkselftest.cpp2
-rw-r--r--tests/auto/network/socket/CMakeLists.txt16
-rw-r--r--tests/auto/network/socket/platformsocketengine/BLACKLIST9
-rw-r--r--tests/auto/network/socket/platformsocketengine/CMakeLists.txt12
-rw-r--r--tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp6
-rw-r--r--tests/auto/network/socket/qabstractsocket/CMakeLists.txt8
-rw-r--r--tests/auto/network/socket/qabstractsocket/tst_qabstractsocket.cpp2
-rw-r--r--tests/auto/network/socket/qhttpsocketengine/BLACKLIST3
-rw-r--r--tests/auto/network/socket/qhttpsocketengine/CMakeLists.txt13
-rw-r--r--tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp10
-rw-r--r--tests/auto/network/socket/qlocalsocket/CMakeLists.txt10
-rw-r--r--tests/auto/network/socket/qlocalsocket/socketprocess/CMakeLists.txt2
-rw-r--r--tests/auto/network/socket/qlocalsocket/socketprocess/main.cpp2
-rw-r--r--tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp115
-rw-r--r--tests/auto/network/socket/qsctpsocket/CMakeLists.txt8
-rw-r--r--tests/auto/network/socket/qsctpsocket/tst_qsctpsocket.cpp13
-rw-r--r--tests/auto/network/socket/qsocks5socketengine/BLACKLIST3
-rw-r--r--tests/auto/network/socket/qsocks5socketengine/CMakeLists.txt13
-rw-r--r--tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp14
-rw-r--r--tests/auto/network/socket/qtcpserver/BLACKLIST5
-rw-r--r--tests/auto/network/socket/qtcpserver/CMakeLists.txt6
-rw-r--r--tests/auto/network/socket/qtcpserver/crashingServer/CMakeLists.txt2
-rw-r--r--tests/auto/network/socket/qtcpserver/crashingServer/main.cpp35
-rw-r--r--tests/auto/network/socket/qtcpserver/test/CMakeLists.txt12
-rw-r--r--tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp74
-rw-r--r--tests/auto/network/socket/qtcpsocket/CMakeLists.txt6
-rw-r--r--tests/auto/network/socket/qtcpsocket/stressTest/CMakeLists.txt6
-rw-r--r--tests/auto/network/socket/qtcpsocket/stressTest/Test.cpp2
-rw-r--r--tests/auto/network/socket/qtcpsocket/stressTest/Test.h2
-rw-r--r--tests/auto/network/socket/qtcpsocket/stressTest/main.cpp2
-rw-r--r--tests/auto/network/socket/qtcpsocket/test/CMakeLists.txt18
-rw-r--r--tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp68
-rw-r--r--tests/auto/network/socket/qudpsocket/BLACKLIST4
-rw-r--r--tests/auto/network/socket/qudpsocket/CMakeLists.txt8
-rw-r--r--tests/auto/network/socket/qudpsocket/clientserver/CMakeLists.txt2
-rw-r--r--tests/auto/network/socket/qudpsocket/clientserver/main.cpp2
-rw-r--r--tests/auto/network/socket/qudpsocket/test/CMakeLists.txt27
-rw-r--r--tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp313
-rw-r--r--tests/auto/network/socket/qudpsocket/udpServer/CMakeLists.txt4
-rw-r--r--tests/auto/network/socket/qudpsocket/udpServer/main.cpp2
-rw-r--r--tests/auto/network/ssl/CMakeLists.txt10
-rw-r--r--tests/auto/network/ssl/qasn1element/CMakeLists.txt14
-rw-r--r--tests/auto/network/ssl/qasn1element/tst_qasn1element.cpp22
-rw-r--r--tests/auto/network/ssl/qdtls/CMakeLists.txt18
-rw-r--r--tests/auto/network/ssl/qdtls/tst_qdtls.cpp62
-rw-r--r--tests/auto/network/ssl/qdtlscookie/CMakeLists.txt18
-rw-r--r--tests/auto/network/ssl/qdtlscookie/tst_qdtlscookie.cpp10
-rw-r--r--tests/auto/network/ssl/qocsp/CMakeLists.txt21
-rw-r--r--tests/auto/network/ssl/qocsp/tst_qocsp.cpp24
-rw-r--r--tests/auto/network/ssl/qpassworddigestor/CMakeLists.txt9
-rw-r--r--tests/auto/network/ssl/qpassworddigestor/tst_qpassworddigestor.cpp2
-rw-r--r--tests/auto/network/ssl/qsslcertificate/CMakeLists.txt11
-rw-r--r--tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp128
-rw-r--r--tests/auto/network/ssl/qsslcipher/CMakeLists.txt18
-rw-r--r--tests/auto/network/ssl/qsslcipher/tst_qsslcipher.cpp2
-rw-r--r--tests/auto/network/ssl/qssldiffiehellmanparameters/CMakeLists.txt9
-rw-r--r--tests/auto/network/ssl/qssldiffiehellmanparameters/tst_qssldiffiehellmanparameters.cpp2
-rw-r--r--tests/auto/network/ssl/qsslellipticcurve/CMakeLists.txt9
-rw-r--r--tests/auto/network/ssl/qsslellipticcurve/tst_qsslellipticcurve.cpp9
-rw-r--r--tests/auto/network/ssl/qsslerror/CMakeLists.txt18
-rw-r--r--tests/auto/network/ssl/qsslerror/tst_qsslerror.cpp2
-rw-r--r--tests/auto/network/ssl/qsslkey/CMakeLists.txt16
-rw-r--r--tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp37
-rw-r--r--tests/auto/network/ssl/qsslserver/CMakeLists.txt7
-rw-r--r--tests/auto/network/ssl/qsslserver/tst_qsslserver.cpp148
-rw-r--r--tests/auto/network/ssl/qsslsocket/BLACKLIST5
-rw-r--r--tests/auto/network/ssl/qsslsocket/CMakeLists.txt27
-rw-r--r--tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp266
-rw-r--r--tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/BLACKLIST8
-rw-r--r--tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/CMakeLists.txt25
-rw-r--r--tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp19
-rw-r--r--tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/CMakeLists.txt24
-rw-r--r--tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/tst_qsslsocket_onDemandCertificates_static.cpp2
-rw-r--r--tests/auto/network/ssl/shared/qopenssl_symbols.h17
-rw-r--r--tests/auto/network/ssl/shared/tlshelpers.h7
161 files changed, 7358 insertions, 2076 deletions
diff --git a/tests/auto/network/CMakeLists.txt b/tests/auto/network/CMakeLists.txt
index 07665cd307..9b15208f71 100644
--- a/tests/auto/network/CMakeLists.txt
+++ b/tests/auto/network/CMakeLists.txt
@@ -1,8 +1,6 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from network.pro.
-# special case begin
# SSL library include path is not propagated with private tests which results in
# test not being able to find the ssl header when they are not in the standard
# include paths
@@ -15,9 +13,8 @@ if (QT_FEATURE_private_tests)
include_directories($<TARGET_PROPERTY:WrapOpenSSLHeaders::WrapOpenSSLHeaders,INTERFACE_INCLUDE_DIRECTORIES>)
endif()
endif()
-# special case end
-# add_subdirectory(selftest) # special case not ported
+# add_subdirectory(selftest) # TODO: not ported
add_subdirectory(access)
add_subdirectory(kernel)
add_subdirectory(ssl)
diff --git a/tests/auto/network/access/CMakeLists.txt b/tests/auto/network/access/CMakeLists.txt
index 6e3c000ca0..ed99aa8746 100644
--- a/tests/auto/network/access/CMakeLists.txt
+++ b/tests/auto/network/access/CMakeLists.txt
@@ -1,9 +1,10 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from access.pro.
-
-add_subdirectory(qnetworkdiskcache)
+add_subdirectory(qhttpheaders)
+if(QT_FEATURE_networkdiskcache)
+ add_subdirectory(qnetworkdiskcache)
+endif()
add_subdirectory(qnetworkcookiejar)
add_subdirectory(qnetworkaccessmanager)
add_subdirectory(qnetworkcookie)
@@ -11,8 +12,16 @@ add_subdirectory(qnetworkrequest)
add_subdirectory(qnetworkreply)
add_subdirectory(qnetworkcachemetadata)
add_subdirectory(qabstractnetworkcache)
+if(QT_FEATURE_http)
+ add_subdirectory(qnetworkreply_local)
+ add_subdirectory(qformdatabuilder)
+ add_subdirectory(qnetworkrequestfactory)
+ add_subdirectory(qrestaccessmanager)
+endif()
if(QT_FEATURE_private_tests)
+ add_subdirectory(qhttp2connection)
add_subdirectory(qhttpheaderparser)
+ add_subdirectory(qhttpheadershelper)
add_subdirectory(qhttpnetworkconnection)
add_subdirectory(qhttpnetworkreply)
add_subdirectory(hpack)
diff --git a/tests/auto/network/access/hpack/CMakeLists.txt b/tests/auto/network/access/hpack/CMakeLists.txt
index 498f59749d..32cd4b2f06 100644
--- a/tests/auto/network/access/hpack/CMakeLists.txt
+++ b/tests/auto/network/access/hpack/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from hpack.pro.
-
#####################################################################
## tst_hpack Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_hpack LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_hpack
SOURCES
tst_hpack.cpp
@@ -15,6 +19,3 @@ qt_internal_add_test(tst_hpack
Qt::Network
Qt::NetworkPrivate
)
-
-#### Keys ignored in scope 1:.:.:hpack.pro:<TRUE>:
-# TEMPLATE = "app"
diff --git a/tests/auto/network/access/hpack/tst_hpack.cpp b/tests/auto/network/access/hpack/tst_hpack.cpp
index 1e2d32a27a..e6b43eaed4 100644
--- a/tests/auto/network/access/hpack/tst_hpack.cpp
+++ b/tests/auto/network/access/hpack/tst_hpack.cpp
@@ -1,6 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// Copyright (C) 2014 Governikus GmbH & Co. KG.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
#include <QRandomGenerator>
diff --git a/tests/auto/network/access/hsts/CMakeLists.txt b/tests/auto/network/access/hsts/CMakeLists.txt
index 5c0f012b6f..821a034940 100644
--- a/tests/auto/network/access/hsts/CMakeLists.txt
+++ b/tests/auto/network/access/hsts/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from hsts.pro.
-
#####################################################################
## tst_qhsts Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qhsts LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qhsts
SOURCES
tst_qhsts.cpp
@@ -16,5 +20,4 @@ qt_internal_add_test(tst_qhsts
Qt::NetworkPrivate
)
-#### Keys ignored in scope 1:.:.:hsts.pro:<TRUE>:
# TEMPLATE = "app"
diff --git a/tests/auto/network/access/hsts/tst_qhsts.cpp b/tests/auto/network/access/hsts/tst_qhsts.cpp
index 252f5e8f57..4e9a5cc53f 100644
--- a/tests/auto/network/access/hsts/tst_qhsts.cpp
+++ b/tests/auto/network/access/hsts/tst_qhsts.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
@@ -9,6 +9,7 @@
#include <QtCore/qpair.h>
#include <QtCore/qurl.h>
+#include <QtNetwork/qhttpheaders.h>
#include <QtNetwork/private/qhstsstore_p.h>
#include <QtNetwork/private/qhsts_p.h>
@@ -189,104 +190,108 @@ void tst_QHsts::testPolicyExpiration()
void tst_QHsts::testSTSHeaderParser()
{
QHstsHeaderParser parser;
- using Header = QPair<QByteArray, QByteArray>;
- using Headers = QList<Header>;
QVERIFY(!parser.includeSubDomains());
QVERIFY(!parser.expirationDate().isValid());
- Headers list;
- QVERIFY(!parser.parse(list));
+ QHttpHeaders headers;
+ QVERIFY(!parser.parse(headers));
QVERIFY(!parser.includeSubDomains());
QVERIFY(!parser.expirationDate().isValid());
- list << Header("Strict-Transport-security", "200");
- QVERIFY(!parser.parse(list));
+ headers.append("Strict-Transport-security", "200");
+ QVERIFY(!parser.parse(headers));
QVERIFY(!parser.includeSubDomains());
QVERIFY(!parser.expirationDate().isValid());
// This header is missing REQUIRED max-age directive, so we'll ignore it:
- list << Header("Strict-Transport-Security", "includeSubDomains");
- QVERIFY(!parser.parse(list));
+ headers.append("Strict-Transport-Security", "includeSubDomains");
+ QVERIFY(!parser.parse(headers));
QVERIFY(!parser.includeSubDomains());
QVERIFY(!parser.expirationDate().isValid());
- list.pop_back();
- list << Header("Strict-Transport-Security", "includeSubDomains;max-age=1000");
- QVERIFY(parser.parse(list));
+ headers.removeAt(headers.size() - 1);
+ headers.append("Strict-Transport-Security", "includeSubDomains;max-age=1000");
+ QVERIFY(parser.parse(headers));
QVERIFY(parser.expirationDate() > QDateTime::currentDateTimeUtc());
QVERIFY(parser.includeSubDomains());
- list.pop_back();
+ headers.removeAt(headers.size() - 1);
+ headers.append("strict-transport-security", "includeSubDomains;max-age=1000");
+ QVERIFY(parser.parse(headers));
+ QVERIFY(parser.expirationDate() > QDateTime::currentDateTimeUtc());
+ QVERIFY(parser.includeSubDomains());
+
+ headers.removeAt(headers.size() - 1);
// Invalid (includeSubDomains twice):
- list << Header("Strict-Transport-Security", "max-age = 1000 ; includeSubDomains;includeSubDomains");
- QVERIFY(!parser.parse(list));
+ headers.append("Strict-Transport-Security", "max-age = 1000 ; includeSubDomains;includeSubDomains");
+ QVERIFY(!parser.parse(headers));
QVERIFY(!parser.includeSubDomains());
QVERIFY(!parser.expirationDate().isValid());
- list.pop_back();
+ headers.removeAt(headers.size() - 1);
// Invalid (weird number of seconds):
- list << Header("Strict-Transport-Security", "max-age=-1000 ; includeSubDomains");
- QVERIFY(!parser.parse(list));
+ headers.append("Strict-Transport-Security", "max-age=-1000 ; includeSubDomains");
+ QVERIFY(!parser.parse(headers));
QVERIFY(!parser.includeSubDomains());
QVERIFY(!parser.expirationDate().isValid());
- list.pop_back();
+ headers.removeAt(headers.size() - 1);
// Note, directives are case-insensitive + we should ignore unknown directive.
- list << Header("Strict-Transport-Security", ";max-age=1000 ;includesubdomains;;"
+ headers.append("Strict-Transport-Security", ";max-age=1000 ;includesubdomains;;"
"nowsomeunknownheader=\"somevaluewithescapes\\;\"");
- QVERIFY(parser.parse(list));
+ QVERIFY(parser.parse(headers));
QVERIFY(parser.includeSubDomains());
QVERIFY(parser.expirationDate().isValid());
- list.pop_back();
+ headers.removeAt(headers.size() - 1);
// Check that we know how to unescape max-age:
- list << Header("Strict-Transport-Security", "max-age=\"1000\"");
- QVERIFY(parser.parse(list));
+ headers.append("Strict-Transport-Security", "max-age=\"1000\"");
+ QVERIFY(parser.parse(headers));
QVERIFY(!parser.includeSubDomains());
QVERIFY(parser.expirationDate().isValid());
- list.pop_back();
+ headers.removeAt(headers.size() - 1);
// The only STS header, with invalid syntax though, to be ignored:
- list << Header("Strict-Transport-Security", "max-age; max-age=15768000");
- QVERIFY(!parser.parse(list));
+ headers.append("Strict-Transport-Security", "max-age; max-age=15768000");
+ QVERIFY(!parser.parse(headers));
QVERIFY(!parser.includeSubDomains());
QVERIFY(!parser.expirationDate().isValid());
// Now we check that our parse chosses the first valid STS header and ignores
// others:
- list.clear();
- list << Header("Strict-Transport-Security", "includeSubdomains; max-age=\"hehehe\";");
- list << Header("Strict-Transport-Security", "max-age=10101");
- QVERIFY(parser.parse(list));
+ headers.clear();
+ headers.append("Strict-Transport-Security", "includeSubdomains; max-age=\"hehehe\";");
+ headers.append("Strict-Transport-Security", "max-age=10101");
+ QVERIFY(parser.parse(headers));
QVERIFY(!parser.includeSubDomains());
QVERIFY(parser.expirationDate().isValid());
- list.clear();
- list << Header("Strict-Transport-Security", "max-age=0");
- QVERIFY(parser.parse(list));
+ headers.clear();
+ headers.append("Strict-Transport-Security", "max-age=0");
+ QVERIFY(parser.parse(headers));
QVERIFY(!parser.includeSubDomains());
QVERIFY(parser.expirationDate() <= QDateTime::currentDateTimeUtc());
// Parsing is case-insensitive:
- list.pop_back();
- list << Header("Strict-Transport-Security", "Max-aGE=1000; InclUdesUbdomains");
- QVERIFY(parser.parse(list));
+ headers.removeAt(headers.size() - 1);
+ headers.append("Strict-Transport-Security", "Max-aGE=1000; InclUdesUbdomains");
+ QVERIFY(parser.parse(headers));
QVERIFY(parser.includeSubDomains());
QVERIFY(parser.expirationDate().isValid());
// Grammar of STS header is quite permissive, let's check we can parse
// some weird but valid header:
- list.pop_back();
- list << Header("Strict-Transport-Security", ";;; max-age = 17; ; ; ; ;;; ;;"
+ headers.removeAt(headers.size() - 1);
+ headers.append("Strict-Transport-Security", ";;; max-age = 17; ; ; ; ;;; ;;"
";;; ; includeSubdomains ;;thisIsUnknownDirective;;;;");
- QVERIFY(parser.parse(list));
+ QVERIFY(parser.parse(headers));
QVERIFY(parser.includeSubDomains());
QVERIFY(parser.expirationDate().isValid());
- list.pop_back();
- list << Header("Strict-Transport-Security", "max-age=1000; includeSubDomains bogon");
- QVERIFY(!parser.parse(list));
+ headers.removeAt(headers.size() - 1);
+ headers.append("Strict-Transport-Security", "max-age=1000; includeSubDomains bogon");
+ QVERIFY(!parser.parse(headers));
QVERIFY(!parser.includeSubDomains());
QVERIFY(!parser.expirationDate().isValid());
}
diff --git a/tests/auto/network/access/http2/BLACKLIST b/tests/auto/network/access/http2/BLACKLIST
new file mode 100644
index 0000000000..3de8d6d448
--- /dev/null
+++ b/tests/auto/network/access/http2/BLACKLIST
@@ -0,0 +1,2 @@
+[duplicateRequestsWithAborts]
+qnx ci # QTBUG-119616
diff --git a/tests/auto/network/access/http2/CMakeLists.txt b/tests/auto/network/access/http2/CMakeLists.txt
index 9825078dd7..7ea559940b 100644
--- a/tests/auto/network/access/http2/CMakeLists.txt
+++ b/tests/auto/network/access/http2/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from http2.pro.
-
#####################################################################
## tst_http2 Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_http2 LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_http2
SOURCES
http2srv.cpp http2srv.h
@@ -16,4 +20,5 @@ qt_internal_add_test(tst_http2
Qt::Network
Qt::NetworkPrivate
Qt::TestPrivate
+ BUNDLE_ANDROID_OPENSSL_LIBS
)
diff --git a/tests/auto/network/access/http2/http2srv.cpp b/tests/auto/network/access/http2/http2srv.cpp
index bf2625876e..b52ea5527b 100644
--- a/tests/auto/network/access/http2/http2srv.cpp
+++ b/tests/auto/network/access/http2/http2srv.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
@@ -84,6 +84,12 @@ Http2Server::~Http2Server()
{
}
+void Http2Server::setInformationalStatusCode(int code)
+{
+ if (code == 100 || (102 <= code && code <= 199))
+ informationalStatusCode = code;
+}
+
void Http2Server::enablePushPromise(bool pushEnabled, const QByteArray &path)
{
pushPromiseEnabled = pushEnabled;
@@ -105,12 +111,23 @@ void Http2Server::setAuthenticationHeader(const QByteArray &authentication)
authenticationHeader = authentication;
}
+void Http2Server::setAuthenticationRequired(bool enable)
+{
+ Q_ASSERT(!enable || authenticationHeader.isEmpty());
+ authenticationRequired = enable;
+}
+
void Http2Server::setRedirect(const QByteArray &url, int count)
{
redirectUrl = url;
redirectCount = count;
}
+void Http2Server::setSendTrailingHEADERS(bool enable)
+{
+ sendTrailingHEADERS = enable;
+}
+
void Http2Server::emulateGOAWAY(int timeout)
{
Q_ASSERT(timeout >= 0);
@@ -248,9 +265,20 @@ void Http2Server::sendDATA(quint32 streamID, quint32 windowSize)
return;
if (last) {
- writer.start(FrameType::DATA, FrameFlag::END_STREAM, streamID);
- writer.setPayloadSize(0);
- writer.write(*socket);
+ if (sendTrailingHEADERS) {
+ writer.start(FrameType::HEADERS,
+ FrameFlag::PRIORITY | FrameFlag::END_HEADERS | FrameFlag::END_STREAM, streamID);
+ const quint32 maxFrameSize(clientSetting(Settings::MAX_FRAME_SIZE_ID,
+ Http2::maxPayloadSize));
+ // 5 bytes for PRIORITY data:
+ writer.append(quint32(0)); // streamID 0 (32-bit)
+ writer.append(quint8(0)); // + weight 0 (8-bit)
+ writer.writeHEADERS(*socket, maxFrameSize);
+ } else {
+ writer.start(FrameType::DATA, FrameFlag::END_STREAM, streamID);
+ writer.setPayloadSize(0);
+ writer.write(*socket);
+ }
suspendedStreams.erase(it);
activeRequests.erase(streamID);
@@ -300,7 +328,8 @@ void Http2Server::incomingConnection(qintptr socketDescriptor)
connect(sslSocket, SIGNAL(sslErrors(QList<QSslError>)),
this, SLOT(ignoreErrorSlot()));
QFile file(QT_TESTCASE_SOURCEDIR "/certs/fluke.key");
- file.open(QIODevice::ReadOnly);
+ if (!file.open(QIODevice::ReadOnly))
+ qFatal("Cannot open certificate file %s", qPrintable(file.fileName()));
QSslKey key(file.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
sslSocket->setPrivateKey(key);
auto localCert = QSslCertificate::fromPath(QT_TESTCASE_SOURCEDIR "/certs/fluke.cert");
@@ -361,16 +390,12 @@ bool Http2Server::verifyProtocolUpgradeRequest()
bool settingsOk = false;
QHttpNetworkReplyPrivate *firstRequestReader = protocolUpgradeHandler->d_func();
+ const auto headers = firstRequestReader->headers();
// That's how we append them, that's what I expect to find:
- for (const auto &header : firstRequestReader->headers()) {
- 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;
- }
+ connectionOk = headers.combinedValue(QHttpHeaders::WellKnownHeader::Connection).contains("Upgrade, HTTP2-Settings");
+ upgradeOk = headers.combinedValue(QHttpHeaders::WellKnownHeader::Upgrade).contains("h2c");
+ settingsOk = headers.contains("HTTP2-Settings");
return connectionOk && upgradeOk && settingsOk;
}
@@ -819,6 +844,25 @@ void Http2Server::sendResponse(quint32 streamID, bool emptyBody)
// Now we'll continue with _normal_ response.
}
+ // Create a header with an informational status code and some random header
+ // fields. The setter ensures that the value is 100 or is between 102 and 199
+ // (inclusive) if set - otherwise it is 0
+
+ if (informationalStatusCode > 0) {
+ writer.start(FrameType::HEADERS, FrameFlag::END_HEADERS, streamID);
+
+ HttpHeader informationalHeader;
+ informationalHeader.push_back({":status", QByteArray::number(informationalStatusCode)});
+ informationalHeader.push_back(HeaderField("a_random_header_field", "it_will_be_dropped"));
+ informationalHeader.push_back(HeaderField("another_random_header_field", "drop_this_too"));
+
+ HPack::BitOStream ostream(writer.outboundFrame().buffer);
+ const bool result = encoder.encodeResponse(ostream, informationalHeader);
+ Q_ASSERT(result);
+
+ writer.writeHEADERS(*socket, maxFrameSize);
+ }
+
writer.start(FrameType::HEADERS, FrameFlag::END_HEADERS, streamID);
if (emptyBody)
writer.addFlag(FrameFlag::END_STREAM);
@@ -848,7 +892,8 @@ void Http2Server::sendResponse(quint32 streamID, bool emptyBody)
} else if (!authenticationHeader.isEmpty() && !hasAuth) {
header.push_back({ ":status", "401" });
header.push_back(HPack::HeaderField("www-authenticate", authenticationHeader));
- authenticationHeader.clear();
+ } else if (authenticationRequired) {
+ header.push_back({ ":status", "401" });
} else {
header.push_back({":status", "200"});
}
diff --git a/tests/auto/network/access/http2/http2srv.h b/tests/auto/network/access/http2/http2srv.h
index e42ed8b148..dc94318527 100644
--- a/tests/auto/network/access/http2/http2srv.h
+++ b/tests/auto/network/access/http2/http2srv.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef HTTP2SRV_H
#define HTTP2SRV_H
@@ -58,6 +58,8 @@ public:
~Http2Server();
+ // To send responses with status code 1xx
+ void setInformationalStatusCode(int code);
// To be called before server started:
void enablePushPromise(bool enabled, const QByteArray &path = QByteArray());
void setResponseBody(const QByteArray &body);
@@ -65,9 +67,13 @@ public:
void setContentEncoding(const QByteArray &contentEncoding);
// No authentication data is generated for the method, the full header value must be set
void setAuthenticationHeader(const QByteArray &authentication);
+ // Authentication always required, no challenge provided
+ void setAuthenticationRequired(bool enable);
// Set the redirect URL and count. The server will return a redirect response with the url
// 'count' amount of times
void setRedirect(const QByteArray &redirectUrl, int count);
+ // Send a trailing HEADERS frame with PRIORITY and END_STREAM flag
+ void setSendTrailingHEADERS(bool enable);
void emulateGOAWAY(int timeout);
void redirectOpenStream(quint16 targetPort);
@@ -200,9 +206,13 @@ private:
QByteArray contentEncoding;
QByteArray authenticationHeader;
+ bool authenticationRequired = false;
QByteArray redirectUrl;
int redirectCount = 0;
+
+ bool sendTrailingHEADERS = false;
+ int informationalStatusCode = 0;
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 5525fd7630..396a6f2fda 100644
--- a/tests/auto/network/access/http2/tst_http2.cpp
+++ b/tests/auto/network/access/http2/tst_http2.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtNetwork/qtnetworkglobal.h>
@@ -25,6 +25,7 @@
#include <QtCore/qobject.h>
#include <QtCore/qthread.h>
#include <QtCore/qurl.h>
+#include <QtCore/qset.h>
#include <cstdlib>
#include <memory>
@@ -72,6 +73,8 @@ private slots:
void defaultQnamHttp2Configuration();
void singleRequest_data();
void singleRequest();
+ void informationalRequest_data();
+ void informationalRequest();
void multipleRequests();
void flowControlClientSide();
void flowControlServerSide();
@@ -93,12 +96,18 @@ private slots:
void authenticationRequired_data();
void authenticationRequired();
+ void unsupportedAuthenticateChallenge();
+
void h2cAllowedAttribute_data();
void h2cAllowedAttribute();
void redirect_data();
void redirect();
+ void trailingHEADERS();
+
+ void duplicateRequestsWithAborts();
+
protected slots:
// Slots to listen to our in-process server:
void serverStarted(quint16 port);
@@ -283,7 +292,7 @@ void tst_Http2::singleRequest()
runEventLoop();
STOP_ON_FAILURE
- QVERIFY(nRequests == 0);
+ QCOMPARE(nRequests, 0);
QVERIFY(prefaceOK);
QVERIFY(serverGotSettingsACK);
@@ -292,10 +301,74 @@ void tst_Http2::singleRequest()
#if QT_CONFIG(ssl)
if (connectionType == H2Type::h2Alpn || connectionType == H2Type::h2Direct)
- QCOMPARE(encSpy.count(), 1);
+ QCOMPARE(encSpy.size(), 1);
#endif // QT_CONFIG(ssl)
}
+void tst_Http2::informationalRequest_data()
+{
+ QTest::addColumn<int>("statusCode");
+
+ // 'Clear text' that should always work, either via the protocol upgrade
+ // or as direct.
+ QTest::addRow("statusCode-100") << 100;
+ QTest::addRow("statusCode-125") << 125;
+ QTest::addRow("statusCode-150") << 150;
+ QTest::addRow("statusCode-175") << 175;
+}
+
+void tst_Http2::informationalRequest()
+{
+ clearHTTP2State();
+
+ serverPort = 0;
+ nRequests = 1;
+
+ ServerPtr srv(newServer(defaultServerSettings, defaultConnectionType()));
+
+ QFETCH(const int, statusCode);
+ srv->setInformationalStatusCode(statusCode);
+
+ QMetaObject::invokeMethod(srv.data(), "startServer", Qt::QueuedConnection);
+ runEventLoop();
+
+ QVERIFY(serverPort != 0);
+
+ auto url = requestUrl(defaultConnectionType());
+ url.setPath("/index.html");
+
+ QNetworkRequest request(url);
+ request.setAttribute(QNetworkRequest::Http2CleartextAllowedAttribute, true);
+
+ auto reply = manager->get(request);
+
+ connect(reply, &QNetworkReply::finished, this, &tst_Http2::replyFinished);
+ // Since we're using self-signed certificates,
+ // ignore SSL errors:
+ reply->ignoreSslErrors();
+
+ runEventLoop();
+ STOP_ON_FAILURE
+
+ QCOMPARE(nRequests, 0);
+ QVERIFY(prefaceOK);
+ QVERIFY(serverGotSettingsACK);
+
+ QCOMPARE(reply->error(), QNetworkReply::NoError);
+ QVERIFY(reply->isFinished());
+
+ const QVariant code(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute));
+
+ // We are discarding informational headers if the status code is in the range of
+ // 102-199 or if it is 100. As these header fields were part of the informational
+ // header used for this test case, we should not see them at this point and the
+ // status code should be 200.
+
+ QCOMPARE(code.value<int>(), 200);
+ QVERIFY(!reply->hasRawHeader("a_random_header_field"));
+ QVERIFY(!reply->hasRawHeader("another_random_header_field"));
+}
+
void tst_Http2::multipleRequests()
{
clearHTTP2State();
@@ -324,7 +397,7 @@ void tst_Http2::multipleRequests()
runEventLoop();
STOP_ON_FAILURE
- QVERIFY(nRequests == 0);
+ QCOMPARE(nRequests, 0);
QVERIFY(prefaceOK);
QVERIFY(serverGotSettingsACK);
}
@@ -369,7 +442,7 @@ void tst_Http2::flowControlClientSide()
runEventLoop(120000);
STOP_ON_FAILURE
- QVERIFY(nRequests == 0);
+ QCOMPARE(nRequests, 0);
QVERIFY(prefaceOK);
QVERIFY(serverGotSettingsACK);
QVERIFY(windowUpdates > 0);
@@ -410,7 +483,7 @@ void tst_Http2::flowControlServerSide()
runEventLoop(120000);
STOP_ON_FAILURE
- QVERIFY(nRequests == 0);
+ QCOMPARE(nRequests, 0);
QVERIFY(prefaceOK);
QVERIFY(serverGotSettingsACK);
}
@@ -454,7 +527,7 @@ void tst_Http2::pushPromise()
runEventLoop();
STOP_ON_FAILURE
- QVERIFY(nRequests == 0);
+ QCOMPARE(nRequests, 0);
QVERIFY(prefaceOK);
QVERIFY(serverGotSettingsACK);
@@ -580,7 +653,7 @@ void tst_Http2::earlyResponse()
runEventLoop();
STOP_ON_FAILURE
- QVERIFY(nRequests == 0);
+ QCOMPARE(nRequests, 0);
QVERIFY(prefaceOK);
QVERIFY(serverGotSettingsACK);
}
@@ -711,7 +784,7 @@ void tst_Http2::connectToHost()
runEventLoop();
STOP_ON_FAILURE
- QVERIFY(nRequests == 0);
+ QCOMPARE(nRequests, 0);
QVERIFY(prefaceOK);
QVERIFY(serverGotSettingsACK);
@@ -780,9 +853,9 @@ void tst_Http2::maxFrameSize()
// Normally, with a 16kb limit, our server would split such
// a response into 3 'DATA' frames (16kb + 16kb + 0|END_STREAM).
- QCOMPARE(frameCounter.count(), 1);
+ QCOMPARE(frameCounter.size(), 1);
- QVERIFY(nRequests == 0);
+ QCOMPARE(nRequests, 0);
QVERIFY(prefaceOK);
QVERIFY(serverGotSettingsACK);
}
@@ -934,7 +1007,7 @@ void tst_Http2::moreActivitySignals()
runEventLoop();
STOP_ON_FAILURE
- QVERIFY(nRequests == 0);
+ QCOMPARE(nRequests, 0);
QVERIFY(prefaceOK);
QVERIFY(serverGotSettingsACK);
@@ -1047,7 +1120,7 @@ void tst_Http2::contentEncoding()
runEventLoop();
STOP_ON_FAILURE
- QVERIFY(nRequests == 0);
+ QCOMPARE(nRequests, 0);
QVERIFY(prefaceOK);
QVERIFY(serverGotSettingsACK);
@@ -1060,13 +1133,18 @@ void tst_Http2::authenticationRequired_data()
{
QTest::addColumn<bool>("success");
QTest::addColumn<bool>("responseHEADOnly");
+ QTest::addColumn<bool>("withChallenge");
- QTest::addRow("failed-auth") << false << true;
- QTest::addRow("successful-auth") << true << true;
+ QTest::addRow("failed-auth") << false << true << true;
+ QTest::addRow("successful-auth") << true << true << true;
// Include a DATA frame in the response from the remote server. An example would be receiving a
// JSON response on a request along with the 401 error.
- QTest::addRow("failed-auth-with-response") << false << false;
- QTest::addRow("successful-auth-with-response") << true << false;
+ QTest::addRow("failed-auth-with-response") << false << false << true;
+ QTest::addRow("successful-auth-with-response") << true << false << true;
+
+ // Don't provide a challenge header. This is valid if you are actually just
+ // denied access for whatever reason.
+ QTest::addRow("no-challenge") << false << false << false;
}
void tst_Http2::authenticationRequired()
@@ -1077,10 +1155,15 @@ void tst_Http2::authenticationRequired()
POSTResponseHEADOnly = responseHEADOnly;
QFETCH(const bool, success);
+ QFETCH(const bool, withChallenge);
ServerPtr targetServer(newServer(defaultServerSettings, defaultConnectionType()));
- targetServer->setResponseBody("Hello");
- targetServer->setAuthenticationHeader("Basic realm=\"Shadow\"");
+ QByteArray responseBody = "Hello"_ba;
+ targetServer->setResponseBody(responseBody);
+ if (withChallenge)
+ targetServer->setAuthenticationHeader("Basic realm=\"Shadow\"");
+ else
+ targetServer->setAuthenticationRequired(true);
QMetaObject::invokeMethod(targetServer.data(), "startServer", Qt::QueuedConnection);
runEventLoop();
@@ -1116,24 +1199,30 @@ void tst_Http2::authenticationRequired()
receivedBody += body;
});
- if (success)
+ if (success) {
connect(reply.get(), &QNetworkReply::finished, this, &tst_Http2::replyFinished);
- else
- connect(reply.get(), &QNetworkReply::errorOccurred, this, &tst_Http2::replyFinishedWithError);
+ } else {
+ // Use queued connection so that the finished signal can be emitted and the isFinished
+ // property can be set.
+ connect(reply.get(), &QNetworkReply::errorOccurred, this,
+ &tst_Http2::replyFinishedWithError, Qt::QueuedConnection);
+ }
// Since we're using self-signed certificates,
// ignore SSL errors:
reply->ignoreSslErrors();
runEventLoop();
STOP_ON_FAILURE
+ QVERIFY2(reply->isFinished(),
+ "The reply should error out if authentication fails, or finish if it succeeds");
if (!success)
QCOMPARE(reply->error(), QNetworkReply::AuthenticationRequiredError);
// else: no error (is checked in tst_Http2::replyFinished)
- QVERIFY(authenticationRequested);
+ QVERIFY(authenticationRequested || !withChallenge);
- const auto isAuthenticated = [](QByteArray bv) {
+ const auto isAuthenticated = [](const QByteArray &bv) {
return bv == "Basic YWRtaW46YWRtaW4="; // admin:admin
};
// Get the "authorization" header out from the server and make sure it's as expected:
@@ -1141,12 +1230,105 @@ void tst_Http2::authenticationRequired()
QCOMPARE(isAuthenticated(reqAuthHeader), success);
if (success)
QCOMPARE(receivedBody, expectedBody);
+ if (responseHEADOnly) {
+ const QVariant contentLenHeader = reply->header(QNetworkRequest::ContentLengthHeader);
+ QVERIFY2(!contentLenHeader.isValid(), "We expect no DATA frames to be received");
+ QCOMPARE(reply->readAll(), QByteArray());
+ } else {
+ const qint32 contentLen = reply->header(QNetworkRequest::ContentLengthHeader).toInt();
+ QCOMPARE(contentLen, responseBody.length());
+ QCOMPARE(reply->bytesAvailable(), responseBody.length());
+ QCOMPARE(reply->readAll(), QByteArray("Hello"));
+ }
// In the `!success` case we need to wait for the server to emit this or it might cause issues
// in the next test running after this. In the `success` case we anyway expect it to have been
// received.
QTRY_VERIFY(serverGotSettingsACK);
}
+void tst_Http2::unsupportedAuthenticateChallenge()
+{
+ clearHTTP2State();
+ serverPort = 0;
+
+ if (defaultConnectionType() == H2Type::h2c)
+ QSKIP("This test requires TLS with ALPN to work");
+
+ ServerPtr targetServer(newServer(defaultServerSettings, defaultConnectionType()));
+ QByteArray responseBody = "Hello"_ba;
+ targetServer->setResponseBody(responseBody);
+ targetServer->setAuthenticationHeader("Bearer realm=\"qt.io accounts\"");
+
+ QMetaObject::invokeMethod(targetServer.data(), "startServer", Qt::QueuedConnection);
+ runEventLoop();
+
+ QVERIFY(serverPort != 0);
+
+ nRequests = 1;
+
+ QUrl url = requestUrl(defaultConnectionType());
+ url.setPath("/index.html");
+ QNetworkRequest request(url);
+
+ QByteArray expectedBody = "Hello, World!";
+ request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
+ QScopedPointer<QNetworkReply> reply;
+ reply.reset(manager->post(request, expectedBody));
+
+ bool authenticationRequested = false;
+ connect(manager.get(), &QNetworkAccessManager::authenticationRequired, reply.get(),
+ [&](QNetworkReply *, QAuthenticator *) {
+ authenticationRequested = true;
+ });
+
+ bool finishedReceived = false;
+ connect(reply.get(), &QNetworkReply::finished, reply.get(),
+ [&]() { finishedReceived = true; });
+ bool errorReceived = false;
+ connect(reply.get(), &QNetworkReply::errorOccurred, reply.get(),
+ [&]() { errorReceived = true; });
+
+ QSet<quint32> receivedDataOnStreams;
+ connect(targetServer.get(), &Http2Server::receivedDATAFrame, reply.get(),
+ [&receivedDataOnStreams](quint32 streamID, const QByteArray &body) {
+ Q_UNUSED(body);
+ receivedDataOnStreams.insert(streamID);
+ });
+
+ // Use queued connection so that the finished signal can be emitted and the
+ // isFinished property can be set.
+ connect(reply.get(), &QNetworkReply::errorOccurred, this,
+ &tst_Http2::replyFinishedWithError, Qt::QueuedConnection);
+
+ // Since we're using self-signed certificates, ignore SSL errors:
+ reply->ignoreSslErrors();
+
+ runEventLoop();
+ STOP_ON_FAILURE
+ QVERIFY2(reply->isFinished(),
+ "The reply should error out if authentication fails, or finish if it succeeds");
+
+ QCOMPARE(reply->error(), QNetworkReply::AuthenticationRequiredError);
+ QVERIFY(reply->isFinished());
+ QVERIFY(errorReceived);
+ QVERIFY(finishedReceived);
+ QCOMPARE(receivedDataOnStreams.size(), 1);
+ QVERIFY(receivedDataOnStreams.contains(1)); // the original, failed, request
+
+ QVERIFY(!authenticationRequested);
+
+ // We should not have sent any authentication headers to the server, since
+ // we don't support the challenge.
+ const QByteArray reqAuthHeader = targetServer->requestAuthorizationHeader();
+ QVERIFY(reqAuthHeader.isEmpty());
+
+ // In the `!success` case we need to wait for the server to emit this or it might cause issues
+ // in the next test running after this. In the `success` case we anyway expect it to have been
+ // received.
+ QTRY_VERIFY(serverGotSettingsACK);
+
+}
+
void tst_Http2::h2cAllowedAttribute_data()
{
QTest::addColumn<bool>("h2cAllowed");
@@ -1242,7 +1424,7 @@ void tst_Http2::redirect()
QVERIFY(serverPort != 0);
- nRequests = 1 + maxRedirects;
+ nRequests = 1;
auto originalUrl = requestUrl(defaultConnectionType());
auto url = originalUrl;
@@ -1270,6 +1452,7 @@ void tst_Http2::redirect()
runEventLoop();
STOP_ON_FAILURE
+ QCOMPARE(nRequests, 0);
if (success) {
QCOMPARE(reply->error(), QNetworkReply::NoError);
QCOMPARE(reply->url().toString(),
@@ -1280,6 +1463,88 @@ void tst_Http2::redirect()
QTRY_VERIFY(serverGotSettingsACK);
}
+void tst_Http2::trailingHEADERS()
+{
+ clearHTTP2State();
+ serverPort = 0;
+
+ ServerPtr targetServer(newServer(defaultServerSettings, defaultConnectionType()));
+ targetServer->setSendTrailingHEADERS(true);
+
+ QMetaObject::invokeMethod(targetServer.data(), "startServer", Qt::QueuedConnection);
+ runEventLoop();
+
+ QVERIFY(serverPort != 0);
+
+ nRequests = 1;
+
+ const auto url = requestUrl(defaultConnectionType());
+ QNetworkRequest request(url);
+ // H2C might be used on macOS where SecureTransport doesn't support server-side ALPN
+ request.setAttribute(QNetworkRequest::Http2CleartextAllowedAttribute, true);
+
+ std::unique_ptr<QNetworkReply> reply{ manager->get(request) };
+ connect(reply.get(), &QNetworkReply::finished, this, &tst_Http2::replyFinished);
+
+ // Since we're using self-signed certificates, ignore SSL errors:
+ reply->ignoreSslErrors();
+
+ runEventLoop();
+ STOP_ON_FAILURE
+
+ QCOMPARE(nRequests, 0);
+
+ QCOMPARE(reply->error(), QNetworkReply::NoError);
+ QTRY_VERIFY(serverGotSettingsACK);
+}
+
+void tst_Http2::duplicateRequestsWithAborts()
+{
+ clearHTTP2State();
+ serverPort = 0;
+
+ ServerPtr targetServer(newServer(defaultServerSettings, defaultConnectionType()));
+
+ QMetaObject::invokeMethod(targetServer.data(), "startServer", Qt::QueuedConnection);
+ runEventLoop();
+
+ QVERIFY(serverPort != 0);
+
+ constexpr int ExpectedSuccessfulRequests = 1;
+ nRequests = ExpectedSuccessfulRequests;
+
+ const auto url = requestUrl(defaultConnectionType());
+ QNetworkRequest request(url);
+ // H2C might be used on macOS where SecureTransport doesn't support server-side ALPN
+ request.setAttribute(QNetworkRequest::Http2CleartextAllowedAttribute, true);
+
+ qint32 finishedCount = 0;
+ auto connectToSlots = [this, &finishedCount](QNetworkReply *reply){
+ const auto onFinished = [&finishedCount, reply, this]() {
+ ++finishedCount;
+ if (reply->error() == QNetworkReply::NoError)
+ replyFinished();
+ };
+ connect(reply, &QNetworkReply::finished, reply, onFinished);
+ };
+
+ std::vector<QNetworkReply *> replies;
+ for (qint32 i = 0; i < 3; ++i) {
+ auto &reply = replies.emplace_back(manager->get(request));
+ connectToSlots(reply);
+ if (i < 2) // Delete and abort all-but-one:
+ reply->deleteLater();
+ // Since we're using self-signed certificates, ignore SSL errors:
+ reply->ignoreSslErrors();
+ }
+
+ runEventLoop();
+ STOP_ON_FAILURE
+
+ QCOMPARE(nRequests, 0);
+ QCOMPARE(finishedCount, ExpectedSuccessfulRequests);
+}
+
void tst_Http2::serverStarted(quint16 port)
{
serverPort = port;
diff --git a/tests/auto/network/access/qabstractnetworkcache/CMakeLists.txt b/tests/auto/network/access/qabstractnetworkcache/CMakeLists.txt
index b7c1522c43..37c3dbda8a 100644
--- a/tests/auto/network/access/qabstractnetworkcache/CMakeLists.txt
+++ b/tests/auto/network/access/qabstractnetworkcache/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qabstractnetworkcache.pro.
-
#####################################################################
## tst_qabstractnetworkcache Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qabstractnetworkcache LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -19,8 +23,7 @@ qt_internal_add_test(tst_qabstractnetworkcache
LIBRARIES
Qt::Network
TESTDATA ${test_data}
- QT_TEST_SERVER_LIST "apache2" # special case
+ QT_TEST_SERVER_LIST "apache2"
)
-#### Keys ignored in scope 1:.:.:qabstractnetworkcache.pro:<TRUE>:
# QT_TEST_SERVER_LIST = "apache2"
diff --git a/tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp b/tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp
index d40411ba3d..95f067a66e 100644
--- a/tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp
+++ b/tests/auto/network/access/qabstractnetworkcache/tst_qabstractnetworkcache.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTemporaryDir>
#include <QTest>
@@ -50,6 +50,7 @@ private:
};
+#if QT_CONFIG(networkdiskcache)
class NetworkDiskCache : public QNetworkDiskCache
{
Q_OBJECT
@@ -72,6 +73,7 @@ public:
QTemporaryDir tempDir;
bool gotData;
};
+#endif
tst_QAbstractNetworkCache::tst_QAbstractNetworkCache()
@@ -254,10 +256,12 @@ void tst_QAbstractNetworkCache::runTest()
QFETCH(bool, fetchFromCache);
QNetworkAccessManager manager;
+#if QT_CONFIG(networkdiskcache)
NetworkDiskCache *diskCache = new NetworkDiskCache(&manager);
QVERIFY2(diskCache->tempDir.isValid(), qPrintable(diskCache->tempDir.errorString()));
manager.setCache(diskCache);
QCOMPARE(diskCache->gotData, false);
+#endif
QUrl realUrl = url.contains("://") ? url : TESTFILE + url;
QNetworkRequest request(realUrl);
@@ -265,8 +269,10 @@ void tst_QAbstractNetworkCache::runTest()
// prime the cache
QNetworkReply *reply = manager.get(request);
QSignalSpy downloaded1(reply, SIGNAL(finished()));
- QTRY_COMPARE(downloaded1.count(), 1);
+ QTRY_COMPARE(downloaded1.size(), 1);
+#if QT_CONFIG(networkdiskcache)
QCOMPARE(diskCache->gotData, false);
+#endif
QByteArray goodData = reply->readAll();
request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, cacheLoadControl);
@@ -274,7 +280,7 @@ void tst_QAbstractNetworkCache::runTest()
// should be in the cache now
QNetworkReply *reply2 = manager.get(request);
QSignalSpy downloaded2(reply2, SIGNAL(finished()));
- QTRY_COMPARE(downloaded2.count(), 1);
+ QTRY_COMPARE(downloaded2.size(), 1);
QByteArray secondData = reply2->readAll();
if (!fetchFromCache && cacheLoadControl == QNetworkRequest::AlwaysCache) {
@@ -293,7 +299,9 @@ void tst_QAbstractNetworkCache::runTest()
std::sort(rawHeaderList.begin(), rawHeaderList.end());
std::sort(rawHeaderList2.begin(), rawHeaderList2.end());
}
+#if QT_CONFIG(networkdiskcache)
QCOMPARE(diskCache->gotData, fetchFromCache);
+#endif
}
void tst_QAbstractNetworkCache::checkSynchronous()
@@ -305,10 +313,12 @@ void tst_QAbstractNetworkCache::checkSynchronous()
QFETCH(bool, fetchFromCache);
QNetworkAccessManager manager;
+#if QT_CONFIG(networkdiskcache)
NetworkDiskCache *diskCache = new NetworkDiskCache(&manager);
QVERIFY2(diskCache->tempDir.isValid(), qPrintable(diskCache->tempDir.errorString()));
manager.setCache(diskCache);
QCOMPARE(diskCache->gotData, false);
+#endif
QUrl realUrl = url.contains("://") ? url : TESTFILE + url;
QNetworkRequest request(realUrl);
@@ -320,7 +330,9 @@ void tst_QAbstractNetworkCache::checkSynchronous()
// prime the cache
QNetworkReply *reply = manager.get(request);
QVERIFY(reply->isFinished()); // synchronous
+#if QT_CONFIG(networkdiskcache)
QCOMPARE(diskCache->gotData, false);
+#endif
QByteArray goodData = reply->readAll();
request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, cacheLoadControl);
@@ -348,22 +360,26 @@ void tst_QAbstractNetworkCache::checkSynchronous()
std::sort(rawHeaderList.begin(), rawHeaderList.end());
std::sort(rawHeaderList2.begin(), rawHeaderList2.end());
}
+#if QT_CONFIG(networkdiskcache)
QCOMPARE(diskCache->gotData, fetchFromCache);
+#endif
}
void tst_QAbstractNetworkCache::deleteCache()
{
QNetworkAccessManager manager;
+#if QT_CONFIG(networkdiskcache)
NetworkDiskCache *diskCache = new NetworkDiskCache(&manager);
QVERIFY2(diskCache->tempDir.isValid(), qPrintable(diskCache->tempDir.errorString()));
manager.setCache(diskCache);
+#endif
QString url = "httpcachetest_cachecontrol.cgi?max-age=1000";
QNetworkRequest request(QUrl(TESTFILE + url));
QNetworkReply *reply = manager.get(request);
QSignalSpy downloaded1(reply, SIGNAL(finished()));
manager.setCache(0);
- QTRY_COMPARE(downloaded1.count(), 1);
+ QTRY_COMPARE(downloaded1.size(), 1);
}
diff --git a/tests/auto/network/access/qdecompresshelper/CMakeLists.txt b/tests/auto/network/access/qdecompresshelper/CMakeLists.txt
index 18a2e22576..09317ca3eb 100644
--- a/tests/auto/network/access/qdecompresshelper/CMakeLists.txt
+++ b/tests/auto/network/access/qdecompresshelper/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qdecompresshelper.pro.
-
#####################################################################
## tst_qdecompresshelper Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qdecompresshelper LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qdecompresshelper
SOURCES
gzip.rcc.cpp
@@ -14,10 +18,7 @@ qt_internal_add_test(tst_qdecompresshelper
tst_qdecompresshelper.cpp
zstandard.rcc.cpp
DEFINES
- SRC_DIR=${CMAKE_CURRENT_SOURCE_DIR} # special case
+ SRC_DIR=${CMAKE_CURRENT_SOURCE_DIR}
LIBRARIES
Qt::NetworkPrivate
)
-
-#### Keys ignored in scope 1:.:.:qdecompresshelper.pro:<TRUE>:
-# TEMPLATE = "app"
diff --git a/tests/auto/network/access/qdecompresshelper/tst_qdecompresshelper.cpp b/tests/auto/network/access/qdecompresshelper/tst_qdecompresshelper.cpp
index 43248a99dc..cd5a52c209 100644
--- a/tests/auto/network/access/qdecompresshelper/tst_qdecompresshelper.cpp
+++ b/tests/auto/network/access/qdecompresshelper/tst_qdecompresshelper.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
@@ -319,6 +319,9 @@ void tst_QDecompressHelper::countAheadPartialRead()
void tst_QDecompressHelper::decompressBigData_data()
{
+#if defined(QT_ASAN_ENABLED)
+ QSKIP("Tests are too slow with asan enabled");
+#endif
QTest::addColumn<QByteArray>("encoding");
QTest::addColumn<QString>("path");
QTest::addColumn<qint64>("size");
@@ -420,10 +423,12 @@ void tst_QDecompressHelper::bigZlib()
{
#if QT_POINTER_SIZE < 8
QSKIP("This cannot be tested on 32-bit systems");
+#elif defined(QT_ASAN_ENABLED)
+ QSKIP("Test is too slow with asan enabled");
#else
-#ifndef QT_NO_EXCEPTIONS
+# ifndef QT_NO_EXCEPTIONS
try {
-#endif
+# endif
// ZLib uses unsigned integers as their size type internally which creates some special
// cases in the internal code that should be tested!
QFile file(":/5GiB.txt.inflate");
@@ -443,11 +448,11 @@ void tst_QDecompressHelper::bigZlib()
QByteArray output(expected + 42, Qt::Uninitialized);
const qsizetype size = helper.read(output.data(), output.size());
QCOMPARE(size, expected);
-#ifndef QT_NO_EXCEPTIONS
+# ifndef QT_NO_EXCEPTIONS
} catch (const std::bad_alloc &) {
QSKIP("Encountered most likely OOM.");
}
-#endif
+# endif
#endif
}
diff --git a/tests/auto/network/access/qformdatabuilder/CMakeLists.txt b/tests/auto/network/access/qformdatabuilder/CMakeLists.txt
new file mode 100644
index 0000000000..dde2dc10e0
--- /dev/null
+++ b/tests/auto/network/access/qformdatabuilder/CMakeLists.txt
@@ -0,0 +1,22 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qformdatabuilder LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_test(tst_qformdatabuilder
+ SOURCES
+ tst_qformdatabuilder.cpp
+ LIBRARIES
+ Qt::Core
+ Qt::Network
+ TESTDATA
+ rfc3252.txt
+ image1.jpg
+ document.docx
+ sheet.xlsx
+)
+
diff --git a/tests/auto/network/access/qformdatabuilder/document.docx b/tests/auto/network/access/qformdatabuilder/document.docx
new file mode 100644
index 0000000000..49005f14b6
--- /dev/null
+++ b/tests/auto/network/access/qformdatabuilder/document.docx
Binary files differ
diff --git a/tests/auto/network/access/qformdatabuilder/image1.jpg b/tests/auto/network/access/qformdatabuilder/image1.jpg
new file mode 100644
index 0000000000..d1d27bf7cf
--- /dev/null
+++ b/tests/auto/network/access/qformdatabuilder/image1.jpg
Binary files differ
diff --git a/tests/auto/network/access/qformdatabuilder/rfc3252.txt b/tests/auto/network/access/qformdatabuilder/rfc3252.txt
new file mode 100644
index 0000000000..5436ce5b26
--- /dev/null
+++ b/tests/auto/network/access/qformdatabuilder/rfc3252.txt
@@ -0,0 +1 @@
+some text for reference
diff --git a/tests/auto/network/access/qformdatabuilder/sheet.xlsx b/tests/auto/network/access/qformdatabuilder/sheet.xlsx
new file mode 100644
index 0000000000..2cb1ec7361
--- /dev/null
+++ b/tests/auto/network/access/qformdatabuilder/sheet.xlsx
Binary files differ
diff --git a/tests/auto/network/access/qformdatabuilder/tst_qformdatabuilder.cpp b/tests/auto/network/access/qformdatabuilder/tst_qformdatabuilder.cpp
new file mode 100644
index 0000000000..ad40c79bf9
--- /dev/null
+++ b/tests/auto/network/access/qformdatabuilder/tst_qformdatabuilder.cpp
@@ -0,0 +1,203 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtNetwork/qformdatabuilder.h>
+
+#include <QtCore/qbuffer.h>
+#include <QtCore/qfile.h>
+
+#include <QtTest/qtest.h>
+
+using namespace Qt::StringLiterals;
+
+class tst_QFormDataBuilder : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void generateQHttpPartWithDevice_data();
+ void generateQHttpPartWithDevice();
+
+ void escapesBackslashAndQuotesInFilenameAndName_data();
+ void escapesBackslashAndQuotesInFilenameAndName();
+
+ void picksUtf8EncodingOnlyIfL1OrAsciiDontSuffice_data();
+ void picksUtf8EncodingOnlyIfL1OrAsciiDontSuffice();
+};
+
+void tst_QFormDataBuilder::generateQHttpPartWithDevice_data()
+{
+ QTest::addColumn<QLatin1StringView>("name_data");
+ QTest::addColumn<QString>("real_file_name");
+ QTest::addColumn<QString>("body_name_data");
+ QTest::addColumn<QByteArray>("expected_content_type_data");
+ QTest::addColumn<QByteArray>("expected_content_disposition_data");
+
+ QTest::newRow("txt-ascii") << "text"_L1 << "rfc3252.txt" << "rfc3252.txt" << "text/plain"_ba
+ << "form-data; name=\"text\"; filename=rfc3252.txt"_ba;
+ QTest::newRow("txt-latin") << "text"_L1 << "rfc3252.txt" << "szöveg.txt" << "text/plain"_ba
+ << "form-data; name=\"text\"; filename*=ISO-8859-1''sz%F6veg.txt"_ba;
+ QTest::newRow("txt-unicode") << "text"_L1 << "rfc3252.txt" << "テキスト.txt" << "text/plain"_ba
+ << "form-data; name=\"text\"; filename*=UTF-8''%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88.txt"_ba;
+
+ QTest::newRow("jpg-ascii") << "image"_L1 << "image1.jpg" << "image1.jpg" << "image/jpeg"_ba
+ << "form-data; name=\"image\"; filename=image1.jpg"_ba;
+ QTest::newRow("jpg-latin") << "image"_L1 << "image1.jpg" << "kép.jpg" << "image/jpeg"_ba
+ << "form-data; name=\"image\"; filename*=ISO-8859-1''k%E9p.jpg"_ba;
+ QTest::newRow("jpg-unicode") << "image"_L1 << "image1.jpg" << "絵.jpg" << "image/jpeg"_ba
+ << "form-data; name=\"image\"; filename*=UTF-8''%E7%B5%B5"_ba;
+
+ QTest::newRow("doc-ascii") << "text"_L1 << "document.docx" << "word.docx"
+ << "application/vnd.openxmlformats-officedocument.wordprocessingml.document"_ba
+ << "form-data; name=\"text\"; filename=word.docx"_ba;
+ QTest::newRow("doc-latin") << "text"_L1 << "document.docx" << "szöveg.docx"
+ << "application/vnd.openxmlformats-officedocument.wordprocessingml.document"_ba
+ << "form-data; name=\"text\"; filename*=ISO-8859-1''sz%F6veg.docx"_ba;
+ QTest::newRow("doc-unicode") << "text"_L1 << "document.docx" << "テキスト.docx"
+ << "application/vnd.openxmlformats-officedocument.wordprocessingml.document"_ba
+ << "form-data; name=\"text\"; filename*=UTF-8''%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88.docx"_ba;
+
+ QTest::newRow("xls-ascii") << "spreadsheet"_L1 << "sheet.xlsx" << "sheet.xlsx"
+ << "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"_ba
+ << "form-data; name=\"spreadsheet\"; filename=sheet.xlsx"_ba;
+ QTest::newRow("xls-latin") << "spreadsheet"_L1 << "sheet.xlsx" << "szöveg.xlsx"
+ << "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"_ba
+ << "form-data; name=\"spreadsheet\"; filename*=ISO-8859-1''sz%F6veg.xlsx"_ba;
+ QTest::newRow("xls-unicode") << "spreadsheet"_L1 << "sheet.xlsx" << "テキスト.xlsx"
+ << "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"_ba
+ << "form-data; name=\"spreadsheet\"; filename*=UTF-8''%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88.xlsx"_ba;
+
+}
+
+void tst_QFormDataBuilder::generateQHttpPartWithDevice()
+{
+ QFETCH(const QLatin1StringView, name_data);
+ QFETCH(const QString, real_file_name);
+ QFETCH(const QString, body_name_data);
+ QFETCH(const QByteArray, expected_content_type_data);
+ QFETCH(const QByteArray, expected_content_disposition_data);
+
+ QString testData = QFileInfo(QFINDTESTDATA(real_file_name)).absoluteFilePath();
+ QFile data_file(testData);
+
+ QHttpPart httpPart = QFormDataPartBuilder(name_data, QFormDataPartBuilder::PrivateConstructor())
+ .setBodyDevice(&data_file, body_name_data)
+ .build();
+
+ QByteArray msg;
+ {
+ QBuffer buf(&msg);
+ QVERIFY(buf.open(QIODevice::WriteOnly));
+ QDebug debug(&buf);
+ debug << httpPart;
+ }
+
+ QVERIFY(msg.contains(expected_content_type_data));
+ QVERIFY(msg.contains(expected_content_disposition_data));
+}
+
+void tst_QFormDataBuilder::escapesBackslashAndQuotesInFilenameAndName_data()
+{
+ QTest::addColumn<QLatin1StringView>("name_data");
+ QTest::addColumn<QString>("body_name_data");
+ QTest::addColumn<QByteArray>("expected_content_type_data");
+ QTest::addColumn<QByteArray>("expected_content_disposition_data");
+
+ QTest::newRow("quote") << "t\"ext"_L1 << "rfc3252.txt" << "text/plain"_ba
+ << R"(form-data; name="t\"ext"; filename=rfc3252.txt)"_ba;
+
+ QTest::newRow("slash") << "t\\ext"_L1 << "rfc3252.txt" << "text/plain"_ba
+ << R"(form-data; name="t\\ext"; filename=rfc3252.txt)"_ba;
+
+ QTest::newRow("quotes") << "t\"e\"xt"_L1 << "rfc3252.txt" << "text/plain"_ba
+ << R"(form-data; name="t\"e\"xt"; filename=rfc3252.txt)"_ba;
+
+ QTest::newRow("slashes") << "t\\\\ext"_L1 << "rfc3252.txt" << "text/plain"_ba
+ << R"(form-data; name="t\\\\ext"; filename=rfc3252.txt)"_ba;
+
+ QTest::newRow("quote-slash") << "t\"ex\\t"_L1 << "rfc3252.txt" << "text/plain"_ba
+ << R"(form-data; name="t\"ex\\t"; filename=rfc3252.txt)"_ba;
+
+ QTest::newRow("quotes-slashes") << "t\"e\"x\\t\\"_L1 << "rfc3252.txt" << "text/plain"_ba
+ << R"(form-data; name="t\"e\"x\\t\\"; filename=rfc3252.txt)"_ba;
+}
+
+void tst_QFormDataBuilder::escapesBackslashAndQuotesInFilenameAndName()
+{
+ QFETCH(const QLatin1StringView, name_data);
+ QFETCH(const QString, body_name_data);
+ QFETCH(const QByteArray, expected_content_type_data);
+ QFETCH(const QByteArray, expected_content_disposition_data);
+
+ QFile dummy_file(body_name_data);
+
+ QHttpPart httpPart = QFormDataPartBuilder(name_data, QFormDataPartBuilder::PrivateConstructor())
+ .setBodyDevice(&dummy_file, body_name_data)
+ .build();
+
+ QByteArray msg;
+ {
+ QBuffer buf(&msg);
+ QVERIFY(buf.open(QIODevice::WriteOnly));
+ QDebug debug(&buf);
+ debug << httpPart;
+ }
+
+ QVERIFY(msg.contains(expected_content_type_data));
+ QVERIFY(msg.contains(expected_content_disposition_data));
+}
+
+void tst_QFormDataBuilder::picksUtf8EncodingOnlyIfL1OrAsciiDontSuffice_data()
+{
+ QTest::addColumn<QLatin1StringView>("name_data");
+ QTest::addColumn<QAnyStringView>("body_name_data");
+ QTest::addColumn<QByteArray>("expected_content_type_data");
+ QTest::addColumn<QByteArray>("expected_content_disposition_data");
+
+ QTest::newRow("latin1-ascii") << "text"_L1 << QAnyStringView("rfc3252.txt"_L1) << "text/plain"_ba
+ << "form-data; name=\"text\"; filename=rfc3252.txt"_ba;
+ QTest::newRow("u8-ascii") << "text"_L1 << QAnyStringView(u8"rfc3252.txt") << "text/plain"_ba
+ << "form-data; name=\"text\"; filename=rfc3252.txt"_ba;
+ QTest::newRow("u-ascii") << "text"_L1 << QAnyStringView(u"rfc3252.txt") << "text/plain"_ba
+ << "form-data; name=\"text\"; filename=rfc3252.txt"_ba;
+
+
+ QTest::newRow("latin1-latin") << "text"_L1 << QAnyStringView("sz\366veg.txt"_L1) << "text/plain"_ba
+ << "form-data; name=\"text\"; filename*=ISO-8859-1''sz%F6veg.txt"_ba;
+ QTest::newRow("u8-latin") << "text"_L1 << QAnyStringView(u8"szöveg.txt") << "text/plain"_ba
+ << "form-data; name=\"text\"; filename*=ISO-8859-1''sz%F6veg.txt"_ba;
+ QTest::newRow("u-latin") << "text"_L1 << QAnyStringView(u"szöveg.txt") << "text/plain"_ba
+ << "form-data; name=\"text\"; filename*=ISO-8859-1''sz%F6veg.txt"_ba;
+
+ QTest::newRow("u8-u8") << "text"_L1 << QAnyStringView(u8"テキスト.txt") << "text/plain"_ba
+ << "form-data; name=\"text\"; filename*=UTF-8''%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88.txt"_ba;
+}
+
+void tst_QFormDataBuilder::picksUtf8EncodingOnlyIfL1OrAsciiDontSuffice()
+{
+ QFETCH(const QLatin1StringView, name_data);
+ QFETCH(const QAnyStringView, body_name_data);
+ QFETCH(const QByteArray, expected_content_type_data);
+ QFETCH(const QByteArray, expected_content_disposition_data);
+
+ QBuffer buff;
+
+ QHttpPart httpPart = QFormDataPartBuilder(name_data, QFormDataPartBuilder::PrivateConstructor())
+ .setBodyDevice(&buff, body_name_data)
+ .build();
+
+ QByteArray msg;
+ {
+ QBuffer buf(&msg);
+ QVERIFY(buf.open(QIODevice::WriteOnly));
+ QDebug debug(&buf);
+ debug << httpPart;
+ }
+
+ QVERIFY(msg.contains(expected_content_type_data));
+ QVERIFY(msg.contains(expected_content_disposition_data));
+}
+
+
+QTEST_MAIN(tst_QFormDataBuilder)
+#include "tst_qformdatabuilder.moc"
diff --git a/tests/auto/network/access/qhttp2connection/CMakeLists.txt b/tests/auto/network/access/qhttp2connection/CMakeLists.txt
new file mode 100644
index 0000000000..9a6e7a064e
--- /dev/null
+++ b/tests/auto/network/access/qhttp2connection/CMakeLists.txt
@@ -0,0 +1,16 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qhttp2connection LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_test(tst_qhttp2connection
+ SOURCES
+ tst_qhttp2connection.cpp
+ LIBRARIES
+ Qt::NetworkPrivate
+ Qt::Test
+)
diff --git a/tests/auto/network/access/qhttp2connection/tst_qhttp2connection.cpp b/tests/auto/network/access/qhttp2connection/tst_qhttp2connection.cpp
new file mode 100644
index 0000000000..b9d5219ae9
--- /dev/null
+++ b/tests/auto/network/access/qhttp2connection/tst_qhttp2connection.cpp
@@ -0,0 +1,397 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtTest/QTest>
+#include <QtTest/QSignalSpy>
+
+#include <QtNetwork/private/qhttp2connection_p.h>
+#include <QtNetwork/private/hpack_p.h>
+#include <QtNetwork/private/bitstreams_p.h>
+
+#include <limits>
+
+using namespace Qt::StringLiterals;
+
+class tst_QHttp2Connection : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void construct();
+ void constructStream();
+ void testSETTINGSFrame();
+ void testPING();
+ void connectToServer();
+ void WINDOW_UPDATE();
+
+private:
+ enum PeerType { Client, Server };
+ [[nodiscard]] auto makeFakeConnectedSockets();
+ [[nodiscard]] auto getRequiredHeaders();
+ [[nodiscard]] QHttp2Connection *makeHttp2Connection(QIODevice *socket,
+ QHttp2Configuration config, PeerType type);
+ [[nodiscard]] bool waitForSettingsExchange(QHttp2Connection *client, QHttp2Connection *server);
+};
+
+class IOBuffer : public QIODevice
+{
+ Q_OBJECT
+public:
+ IOBuffer(QObject *parent, std::shared_ptr<QBuffer> _in, std::shared_ptr<QBuffer> _out)
+ : QIODevice(parent), in(std::move(_in)), out(std::move(_out))
+ {
+ connect(in.get(), &QIODevice::readyRead, this, &IOBuffer::readyRead);
+ connect(out.get(), &QIODevice::bytesWritten, this, &IOBuffer::bytesWritten);
+ connect(out.get(), &QIODevice::aboutToClose, this, &IOBuffer::readChannelFinished);
+ connect(out.get(), &QIODevice::aboutToClose, this, &IOBuffer::aboutToClose);
+ }
+
+ bool open(OpenMode mode) override
+ {
+ QIODevice::open(mode);
+ Q_ASSERT(in->isOpen());
+ Q_ASSERT(out->isOpen());
+ return false;
+ }
+
+ bool isSequential() const override { return true; }
+
+ qint64 bytesAvailable() const override { return in->pos() - readHead; }
+ qint64 bytesToWrite() const override { return 0; }
+
+ qint64 readData(char *data, qint64 maxlen) override
+ {
+ qint64 temp = in->pos();
+ in->seek(readHead);
+ qint64 res = in->read(data, std::min(maxlen, temp - readHead));
+ readHead += res;
+ if (readHead == temp) {
+ // Reached end of buffer, reset
+ in->seek(0);
+ in->buffer().resize(0);
+ readHead = 0;
+ } else {
+ in->seek(temp);
+ }
+ return res;
+ }
+
+ qint64 writeData(const char *data, qint64 len) override
+ {
+ return out->write(data, len);
+ }
+
+ std::shared_ptr<QBuffer> in;
+ std::shared_ptr<QBuffer> out;
+
+ qint64 readHead = 0;
+};
+
+auto tst_QHttp2Connection::makeFakeConnectedSockets()
+{
+ auto clientIn = std::make_shared<QBuffer>();
+ auto serverIn = std::make_shared<QBuffer>();
+ clientIn->open(QIODevice::ReadWrite);
+ serverIn->open(QIODevice::ReadWrite);
+
+ auto client = std::make_unique<IOBuffer>(this, clientIn, serverIn);
+ auto server = std::make_unique<IOBuffer>(this, std::move(serverIn), std::move(clientIn));
+
+ client->open(QIODevice::ReadWrite);
+ server->open(QIODevice::ReadWrite);
+
+ return std::pair{ std::move(client), std::move(server) };
+}
+
+auto tst_QHttp2Connection::getRequiredHeaders()
+{
+ return HPack::HttpHeader{
+ { ":authority", "example.com" },
+ { ":method", "GET" },
+ { ":path", "/" },
+ { ":scheme", "https" },
+ };
+}
+
+QHttp2Connection *tst_QHttp2Connection::makeHttp2Connection(QIODevice *socket,
+ QHttp2Configuration config,
+ PeerType type)
+{
+ QHttp2Connection *connection = nullptr;
+ if (type == PeerType::Server)
+ connection = QHttp2Connection::createDirectServerConnection(socket, config);
+ else
+ connection = QHttp2Connection::createDirectConnection(socket, config);
+ connect(socket, &QIODevice::readyRead, connection, &QHttp2Connection::handleReadyRead);
+ return connection;
+}
+
+bool tst_QHttp2Connection::waitForSettingsExchange(QHttp2Connection *client,
+ QHttp2Connection *server)
+{
+ bool settingsFrameReceived = false;
+ bool serverSettingsFrameReceived = false;
+
+ QMetaObject::Connection c = connect(client, &QHttp2Connection::settingsFrameReceived, client,
+ [&settingsFrameReceived]() {
+ settingsFrameReceived = true;
+ });
+ QMetaObject::Connection s = connect(server, &QHttp2Connection::settingsFrameReceived, server,
+ [&serverSettingsFrameReceived]() {
+ serverSettingsFrameReceived = true;
+ });
+
+ client->handleReadyRead(); // handle incoming frames, send response
+
+ bool success = QTest::qWaitFor([&]() {
+ return settingsFrameReceived && serverSettingsFrameReceived;
+ });
+
+ disconnect(c);
+ disconnect(s);
+
+ return success;
+}
+
+void tst_QHttp2Connection::construct()
+{
+ QBuffer buffer;
+ buffer.open(QIODevice::ReadWrite);
+ auto *connection = QHttp2Connection::createDirectConnection(&buffer, {});
+ QVERIFY(!connection->isGoingAway());
+ QCOMPARE(connection->maxConcurrentStreams(), 100u);
+ QCOMPARE(connection->maxHeaderListSize(), std::numeric_limits<quint32>::max());
+ QVERIFY(!connection->isUpgradedConnection());
+ QVERIFY(!connection->getStream(1)); // No stream has been created yet
+
+ auto *upgradedConnection = QHttp2Connection::createUpgradedConnection(&buffer, {});
+ QVERIFY(upgradedConnection->isUpgradedConnection());
+ // Stream 1 is created by default for an upgraded connection
+ QVERIFY(upgradedConnection->getStream(1));
+}
+
+void tst_QHttp2Connection::constructStream()
+{
+ QBuffer buffer;
+ buffer.open(QIODevice::ReadWrite);
+ auto connection = QHttp2Connection::createDirectConnection(&buffer, {});
+ QHttp2Stream *stream = connection->createStream().unwrap();
+ QVERIFY(stream);
+ QCOMPARE(stream->isPromisedStream(), false);
+ QCOMPARE(stream->isActive(), false);
+ QCOMPARE(stream->RST_STREAM_code(), 0u);
+ QCOMPARE(stream->streamID(), 1u);
+ QCOMPARE(stream->receivedHeaders(), {});
+ QCOMPARE(stream->state(), QHttp2Stream::State::Idle);
+ QCOMPARE(stream->isUploadBlocked(), false);
+ QCOMPARE(stream->isUploadingDATA(), false);
+}
+
+void tst_QHttp2Connection::testSETTINGSFrame()
+{
+ constexpr qint32 PrefaceLength = 24;
+ QBuffer buffer;
+ buffer.open(QIODevice::ReadWrite);
+ QHttp2Configuration config;
+ constexpr quint32 MaxFrameSize = 16394;
+ constexpr bool ServerPushEnabled = false;
+ constexpr quint32 StreamReceiveWindowSize = 50000;
+ constexpr quint32 SessionReceiveWindowSize = 50001;
+ config.setMaxFrameSize(MaxFrameSize);
+ config.setServerPushEnabled(ServerPushEnabled);
+ config.setStreamReceiveWindowSize(StreamReceiveWindowSize);
+ config.setSessionReceiveWindowSize(SessionReceiveWindowSize);
+ auto connection = QHttp2Connection::createDirectConnection(&buffer, config);
+ Q_UNUSED(connection);
+ QCOMPARE_GE(buffer.size(), PrefaceLength);
+
+ // Preface
+ QByteArray preface = buffer.data().first(PrefaceLength);
+ QCOMPARE(preface, "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n");
+
+ // SETTINGS
+ buffer.seek(PrefaceLength);
+ const quint32 maxSize = buffer.size() - PrefaceLength;
+ Http2::FrameReader reader;
+ Http2::FrameStatus status = reader.read(buffer);
+ QCOMPARE(status, Http2::FrameStatus::goodFrame);
+ Http2::Frame f = reader.inboundFrame();
+ QCOMPARE(f.type(), Http2::FrameType::SETTINGS);
+ QCOMPARE_LT(f.payloadSize(), maxSize);
+
+ const qint32 settingsReceived = f.dataSize() / 6;
+ QCOMPARE_GT(settingsReceived, 0);
+ QCOMPARE_LE(settingsReceived, 6);
+
+ struct ExpectedSetting
+ {
+ Http2::Settings identifier;
+ quint32 value;
+ };
+ // Commented-out settings are not sent since they are defaults
+ ExpectedSetting expectedSettings[]{
+ // { Http2::Settings::HEADER_TABLE_SIZE_ID, HPack::FieldLookupTable::DefaultSize },
+ { Http2::Settings::ENABLE_PUSH_ID, ServerPushEnabled ? 1 : 0 },
+ // { Http2::Settings::MAX_CONCURRENT_STREAMS_ID, Http2::maxConcurrentStreams },
+ { Http2::Settings::INITIAL_WINDOW_SIZE_ID, StreamReceiveWindowSize },
+ { Http2::Settings::MAX_FRAME_SIZE_ID, MaxFrameSize },
+ // { Http2::Settings::MAX_HEADER_LIST_SIZE_ID, ??? },
+ };
+
+ QCOMPARE(quint32(settingsReceived), std::size(expectedSettings));
+ for (qint32 i = 0; i < settingsReceived; ++i) {
+ const uchar *it = f.dataBegin() + i * 6;
+ const quint16 ident = qFromBigEndian<quint16>(it);
+ const quint32 intVal = qFromBigEndian<quint32>(it + 2);
+
+ ExpectedSetting expectedSetting = expectedSettings[i];
+ QVERIFY2(ident == quint16(expectedSetting.identifier),
+ qPrintable("ident: %1, expected: %2, index: %3"_L1
+ .arg(QString::number(ident),
+ QString::number(quint16(expectedSetting.identifier)),
+ QString::number(i))));
+ QVERIFY2(intVal == expectedSetting.value,
+ qPrintable("intVal: %1, expected: %2, index: %3"_L1
+ .arg(QString::number(intVal),
+ QString::number(expectedSetting.value),
+ QString::number(i))));
+ }
+}
+
+void tst_QHttp2Connection::testPING()
+{
+ auto [client, server] = makeFakeConnectedSockets();
+ auto connection = makeHttp2Connection(client.get(), {}, Client);
+ auto serverConnection = makeHttp2Connection(server.get(), {}, Server);
+
+ QVERIFY(waitForSettingsExchange(connection, serverConnection));
+
+ QSignalSpy serverPingSpy{ serverConnection, &QHttp2Connection::pingFrameRecived };
+ QSignalSpy clientPingSpy{ connection, &QHttp2Connection::pingFrameRecived };
+
+ QByteArray data{"pingpong"};
+ connection->sendPing(data);
+
+ QVERIFY(serverPingSpy.wait());
+ QVERIFY(clientPingSpy.wait());
+
+ QCOMPARE(serverPingSpy.last().at(0).toInt(), int(QHttp2Connection::PingState::Ping));
+ QCOMPARE(clientPingSpy.last().at(0).toInt(), int(QHttp2Connection::PingState::PongSignatureIdentical));
+
+ serverConnection->sendPing();
+
+ QVERIFY(clientPingSpy.wait());
+ QVERIFY(serverPingSpy.wait());
+
+ QCOMPARE(clientPingSpy.last().at(0).toInt(), int(QHttp2Connection::PingState::Ping));
+ QCOMPARE(serverPingSpy.last().at(0).toInt(), int(QHttp2Connection::PingState::PongSignatureIdentical));
+}
+
+void tst_QHttp2Connection::connectToServer()
+{
+ auto [client, server] = makeFakeConnectedSockets();
+ auto connection = makeHttp2Connection(client.get(), {}, Client);
+ auto serverConnection = makeHttp2Connection(server.get(), {}, Server);
+
+ QVERIFY(waitForSettingsExchange(connection, serverConnection));
+
+ QSignalSpy newIncomingStreamSpy{ serverConnection, &QHttp2Connection::newIncomingStream };
+ QSignalSpy clientIncomingStreamSpy{ connection, &QHttp2Connection::newIncomingStream };
+
+ QHttp2Stream *clientStream = connection->createStream().unwrap();
+ QSignalSpy clientHeaderReceivedSpy{ clientStream, &QHttp2Stream::headersReceived };
+ QVERIFY(clientStream);
+ HPack::HttpHeader headers = getRequiredHeaders();
+ clientStream->sendHEADERS(headers, false);
+
+ QVERIFY(newIncomingStreamSpy.wait());
+ auto *serverStream = newIncomingStreamSpy.front().front().value<QHttp2Stream *>();
+ QVERIFY(serverStream);
+ const HPack::HttpHeader ExpectedResponseHeaders{ { ":status", "200" } };
+ serverStream->sendHEADERS(ExpectedResponseHeaders, true);
+
+ QVERIFY(clientHeaderReceivedSpy.wait());
+ const HPack::HttpHeader
+ headersReceived = clientHeaderReceivedSpy.front().front().value<HPack::HttpHeader>();
+ QCOMPARE(headersReceived, ExpectedResponseHeaders);
+
+ QCOMPARE(clientIncomingStreamSpy.count(), 0);
+}
+
+void tst_QHttp2Connection::WINDOW_UPDATE()
+{
+ auto [client, server] = makeFakeConnectedSockets();
+ auto connection = makeHttp2Connection(client.get(), {}, Client);
+
+ QHttp2Configuration config;
+ config.setStreamReceiveWindowSize(1024); // Small window on server to provoke WINDOW_UPDATE
+ auto serverConnection = makeHttp2Connection(server.get(), config, Server);
+
+ QVERIFY(waitForSettingsExchange(connection, serverConnection));
+
+ QSignalSpy newIncomingStreamSpy{ serverConnection, &QHttp2Connection::newIncomingStream };
+
+ QHttp2Stream *clientStream = connection->createStream().unwrap();
+ QSignalSpy clientHeaderReceivedSpy{ clientStream, &QHttp2Stream::headersReceived };
+ QSignalSpy clientDataReceivedSpy{ clientStream, &QHttp2Stream::dataReceived };
+ QVERIFY(clientStream);
+ HPack::HttpHeader expectedRequestHeaders = HPack::HttpHeader{
+ { ":authority", "example.com" },
+ { ":method", "POST" },
+ { ":path", "/" },
+ { ":scheme", "https" },
+ };
+ clientStream->sendHEADERS(expectedRequestHeaders, false);
+
+ QVERIFY(newIncomingStreamSpy.wait());
+ auto *serverStream = newIncomingStreamSpy.front().front().value<QHttp2Stream *>();
+ QVERIFY(serverStream);
+ QSignalSpy serverDataReceivedSpy{ serverStream, &QHttp2Stream::dataReceived };
+
+ // Since a stream is only opened on the remote side when the header is received,
+ // we can check the headers now immediately
+ QCOMPARE(serverStream->receivedHeaders(), expectedRequestHeaders);
+
+ QBuffer *buffer = new QBuffer(clientStream);
+ QByteArray uploadedData = "Hello World"_ba.repeated(1000);
+ buffer->setData(uploadedData);
+ buffer->open(QIODevice::ReadWrite);
+ clientStream->sendDATA(buffer, true);
+
+ bool streamEnd = false;
+ QByteArray serverReceivedData;
+ while (!streamEnd) { // The window is too small to receive all data at once, so loop
+ QVERIFY(serverDataReceivedSpy.wait());
+ auto latestEmission = serverDataReceivedSpy.back();
+ serverReceivedData += latestEmission.front().value<QByteArray>();
+ streamEnd = latestEmission.back().value<bool>();
+ }
+ QCOMPARE(serverReceivedData.size(), uploadedData.size());
+ QCOMPARE(serverReceivedData, uploadedData);
+
+ QCOMPARE(clientStream->state(), QHttp2Stream::State::HalfClosedLocal);
+ QCOMPARE(serverStream->state(), QHttp2Stream::State::HalfClosedRemote);
+
+ const HPack::HttpHeader ExpectedResponseHeaders{ { ":status", "200" } };
+ serverStream->sendHEADERS(ExpectedResponseHeaders, false);
+ QBuffer *serverBuffer = new QBuffer(serverStream);
+ serverBuffer->setData(uploadedData);
+ serverBuffer->open(QIODevice::ReadWrite);
+ serverStream->sendDATA(serverBuffer, true);
+
+ QVERIFY(clientHeaderReceivedSpy.wait());
+ const HPack::HttpHeader
+ headersReceived = clientHeaderReceivedSpy.front().front().value<HPack::HttpHeader>();
+ QCOMPARE(headersReceived, ExpectedResponseHeaders);
+
+ QTRY_COMPARE_GT(clientDataReceivedSpy.count(), 0);
+ QCOMPARE(clientDataReceivedSpy.count(), 1); // Only one DATA frame since our window is larger
+ QCOMPARE(clientDataReceivedSpy.front().front().value<QByteArray>(), uploadedData);
+
+ QCOMPARE(clientStream->state(), QHttp2Stream::State::Closed);
+ QCOMPARE(serverStream->state(), QHttp2Stream::State::Closed);
+}
+
+QTEST_MAIN(tst_QHttp2Connection)
+
+#include "tst_qhttp2connection.moc"
diff --git a/tests/auto/network/access/qhttpheaderparser/CMakeLists.txt b/tests/auto/network/access/qhttpheaderparser/CMakeLists.txt
index 0672cbb550..50deeb3e56 100644
--- a/tests/auto/network/access/qhttpheaderparser/CMakeLists.txt
+++ b/tests/auto/network/access/qhttpheaderparser/CMakeLists.txt
@@ -1,6 +1,11 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qhttpheaderparser LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
if(NOT QT_FEATURE_private_tests)
return()
diff --git a/tests/auto/network/access/qhttpheaderparser/tst_qhttpheaderparser.cpp b/tests/auto/network/access/qhttpheaderparser/tst_qhttpheaderparser.cpp
index a1ea1c8ce7..9ba889fdb3 100644
--- a/tests/auto/network/access/qhttpheaderparser/tst_qhttpheaderparser.cpp
+++ b/tests/auto/network/access/qhttpheaderparser/tst_qhttpheaderparser.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QObject>
diff --git a/tests/auto/network/access/qhttpheaders/CMakeLists.txt b/tests/auto/network/access/qhttpheaders/CMakeLists.txt
new file mode 100644
index 0000000000..0de1f96c67
--- /dev/null
+++ b/tests/auto/network/access/qhttpheaders/CMakeLists.txt
@@ -0,0 +1,16 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qhttpheaders LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_test(tst_qhttpheaders
+ SOURCES
+ tst_qhttpheaders.cpp
+ LIBRARIES
+ Qt::Core
+ Qt::Network
+)
diff --git a/tests/auto/network/access/qhttpheaders/tst_qhttpheaders.cpp b/tests/auto/network/access/qhttpheaders/tst_qhttpheaders.cpp
new file mode 100644
index 0000000000..457d30feeb
--- /dev/null
+++ b/tests/auto/network/access/qhttpheaders/tst_qhttpheaders.cpp
@@ -0,0 +1,552 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtNetwork/qhttpheaders.h>
+
+#include <QtTest/qtest.h>
+
+#include <QtCore/qmap.h>
+#include <QtCore/qset.h>
+
+using namespace Qt::StringLiterals;
+
+class tst_QHttpHeaders : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void constructors();
+ void accessors();
+ void wellKnownHeader();
+ void headerNameField();
+ void headerValueField();
+ void valueEncoding();
+ void replaceOrAppend();
+
+private:
+ static constexpr QAnyStringView n1{"name1"};
+ static constexpr QAnyStringView n2{"name2"};
+ static constexpr QAnyStringView n3{"name3"};
+ static constexpr QAnyStringView v1{"value1"};
+ static constexpr QAnyStringView v2{"value2"};
+ static constexpr QAnyStringView v3{"value3"};
+ static constexpr QAnyStringView N1{"NAME1"};
+ static constexpr QAnyStringView N2{"NAME2"};
+ static constexpr QAnyStringView N3{"NAME3"};
+ static constexpr QAnyStringView V1{"VALUE1"};
+ static constexpr QAnyStringView V2{"VALUE2"};
+ static constexpr QAnyStringView V3{"VALUE3"};
+};
+
+void tst_QHttpHeaders::constructors()
+{
+ // Default ctor
+ QHttpHeaders h1;
+ QVERIFY(h1.isEmpty());
+
+ // Copy ctor
+ QHttpHeaders h2(h1);
+ QCOMPARE(h2.toListOfPairs(), h1.toListOfPairs());
+
+ // Copy assignment
+ QHttpHeaders h3;
+ h3 = h1;
+ QCOMPARE(h3.toListOfPairs(), h1.toListOfPairs());
+
+ // Move assignment
+ QHttpHeaders h4;
+ h4 = std::move(h2);
+ QCOMPARE(h4.toListOfPairs(), h1.toListOfPairs());
+
+ // Move ctor
+ QHttpHeaders h5(std::move(h4));
+ QCOMPARE(h5.toListOfPairs(), h1.toListOfPairs());
+
+ // Constructors that are counterparts to 'toXXX()' conversion getters
+ const QByteArray nb1{"name1"};
+ const QByteArray nb2{"name2"};
+ const QByteArray nv1{"value1"};
+ const QByteArray nv2{"value2"};
+ // Initialize three QHttpHeaders with similar content, and verify that they have
+ // similar header entries
+#define CONTAINS_HEADER(NAME, VALUE) \
+ QVERIFY(hlist.contains(NAME) && hmap.contains(NAME) && hhash.contains(NAME)); \
+ QCOMPARE(hlist.combinedValue(NAME), VALUE); \
+ QCOMPARE(hmap.combinedValue(NAME), VALUE); \
+ QCOMPARE(hhash.combinedValue(NAME), VALUE); \
+
+ QList<std::pair<QByteArray, QByteArray>> list{{nb1, nv1}, {nb2, nv2}, {nb2, nv2}};
+ QMultiMap<QByteArray, QByteArray> map{{nb1, nv1}, {nb2, nv2}, {nb2, nv2}};
+ QMultiHash<QByteArray, QByteArray> hash{{nb1, nv1}, {nb2, nv2}, {nb2, nv2}};
+ QHttpHeaders hlist = QHttpHeaders::fromListOfPairs(list);
+ QHttpHeaders hmap = QHttpHeaders::fromMultiMap(map);
+ QHttpHeaders hhash = QHttpHeaders::fromMultiHash(hash);
+ CONTAINS_HEADER(nb1, v1);
+ CONTAINS_HEADER(nb2, nv2 + ", " + nv2)
+#undef CONTAINS_HEADER
+}
+
+void tst_QHttpHeaders::accessors()
+{
+ QHttpHeaders h1;
+
+ // isEmpty(), clear(), size()
+ h1.append(n1,v1);
+ QVERIFY(!h1.isEmpty());
+ QCOMPARE(h1.size(), 1);
+ QVERIFY(h1.append(n1, v1));
+ QCOMPARE(h1.size(), 2);
+ h1.insert(0, n1, v1);
+ QCOMPARE(h1.size(), 3);
+ h1.clear();
+ QVERIFY(h1.isEmpty());
+
+ // contains()
+ h1.append(n1, v1);
+ QVERIFY(h1.contains(n1));
+ QVERIFY(h1.contains(N1));
+ QVERIFY(!h1.contains(n2));
+ QVERIFY(!h1.contains(QHttpHeaders::WellKnownHeader::Allow));
+ h1.append(QHttpHeaders::WellKnownHeader::Accept, "nothing");
+ QVERIFY(h1.contains(QHttpHeaders::WellKnownHeader::Accept));
+ QVERIFY(h1.contains("accept"));
+
+ // values()/value()
+#define EXISTS_NOT(H, N) do { \
+ QVERIFY(!H.contains(N)); \
+ QCOMPARE(H.value(N, "ENOENT"), "ENOENT"); \
+ const auto values = H.values(N); \
+ QVERIFY(values.isEmpty()); \
+ QVERIFY(H.combinedValue(N).isNull()); \
+ } while (false)
+
+#define EXISTS_N_TIMES(X, H, N, ...) do { \
+ const std::array expected = { __VA_ARGS__ }; \
+ static_assert(std::tuple_size_v<decltype(expected)> == X); \
+ QVERIFY(H.contains(N)); \
+ QCOMPARE(H.value(N, "ENOENT"), expected.front()); \
+ const auto values = H.values(N); \
+ QCOMPARE(values.size(), X); \
+ QCOMPARE(values.front(), expected.front()); \
+ /* ignore in-between */ \
+ QCOMPARE(values.back(), expected.back()); \
+ QCOMPARE(H.combinedValue(N), values.join(", ")); \
+ } while (false)
+
+#define EXISTS_ONCE(H, N, V) EXISTS_N_TIMES(1, H, N, V)
+
+ EXISTS_ONCE(h1, n1, v1);
+ EXISTS_ONCE(h1, N1, v1);
+ EXISTS_ONCE(h1, QHttpHeaders::WellKnownHeader::Accept, "nothing");
+ EXISTS_ONCE(h1, "Accept", "nothing");
+
+ EXISTS_NOT(h1, N2);
+ EXISTS_NOT(h1, QHttpHeaders::WellKnownHeader::Allow);
+
+ h1.clear();
+
+ EXISTS_NOT(h1, n1);
+
+ h1.append(n1, v1);
+ h1.append(n1, v2);
+ h1.append(n1, v3);
+ h1.append(n2, v2);
+ h1.append(n3, ""); // empty value
+
+ EXISTS_N_TIMES(3, h1, n1, v1, v2, v3);
+ EXISTS_N_TIMES(3, h1, N1, v1, v2, v3);
+ EXISTS_ONCE(h1, n3, ""); // empty value
+
+ h1.append(QHttpHeaders::WellKnownHeader::Accept, "nothing");
+ h1.append(QHttpHeaders::WellKnownHeader::Accept, "ever");
+
+ EXISTS_N_TIMES(2, h1, QHttpHeaders::WellKnownHeader::Accept, "nothing", "ever");
+ EXISTS_NOT(h1, "nonexistent");
+
+#undef EXISTS_ONCE
+#undef EXISTS_N_TIMES
+#undef EXISTS_NOT
+
+ // valueAt()
+ h1.clear();
+ h1.append(n1, v1);
+ h1.append(n2, v2);
+ h1.append(n3, v3);
+ QCOMPARE(h1.valueAt(0), v1);
+ QCOMPARE(h1.valueAt(1), v2);
+ QCOMPARE(h1.valueAt(2), v3);
+
+ // nameAt()
+ h1.clear();
+ h1.append(n1, v1);
+ h1.append(n2, v2);
+ h1.append(n3, v3);
+ QCOMPARE(h1.nameAt(0), n1);
+ QCOMPARE(h1.nameAt(1), n2);
+ QCOMPARE(h1.nameAt(2), n3);
+
+ // removeAll()
+ h1.clear();
+ QVERIFY(h1.append(n1, v1));
+ QVERIFY(h1.append(QHttpHeaders::WellKnownHeader::Accept, "nothing"));
+ QVERIFY(h1.append(n1, v1));
+ QCOMPARE(h1.size(), 3);
+ h1.removeAll(n1);
+ QVERIFY(!h1.contains(n1));
+ QCOMPARE(h1.size(), 1);
+ QVERIFY(h1.contains("accept"));
+ h1.removeAll(QHttpHeaders::WellKnownHeader::Accept);
+ QVERIFY(!h1.contains(QHttpHeaders::WellKnownHeader::Accept));
+
+ // removeAt()
+ h1.clear();
+ h1.append(n1, v1);
+ h1.append(n2, v2);
+ h1.append(n3, v3);
+
+ // Valid removals
+ QVERIFY(h1.contains(n3));
+ h1.removeAt(2);
+ QVERIFY(!h1.contains(n3));
+ QVERIFY(h1.contains(n1));
+ h1.removeAt(0);
+ QVERIFY(!h1.contains(n1));
+ QVERIFY(h1.contains(n2));
+ h1.removeAt(0);
+ QVERIFY(!h1.contains(n2));
+ QVERIFY(h1.isEmpty());
+
+ // toListOfPairs()
+ h1.clear();
+ h1.append(n1, v1);
+ h1.append(n2, v2);
+ h1.append(N3, V3); // uppercase of n3
+ auto list = h1.toListOfPairs();
+ QCOMPARE(list.size(), h1.size());
+ QCOMPARE(list.at(0).first, n1);
+ QCOMPARE(list.at(0).second, v1);
+ QCOMPARE(list.at(1).first, n2);
+ QCOMPARE(list.at(1).second, v2);
+ QCOMPARE(list.at(2).first, n3); // N3 has been lower-cased
+ QCOMPARE(list.at(2).second, V3);
+
+ // toMultiMap()
+ auto map = h1.toMultiMap();
+ QCOMPARE(map.size(), h1.size());
+ QCOMPARE(map.value(n1.toString().toLatin1()), v1);
+ QCOMPARE(map.value(n2.toString().toLatin1()), v2);
+ QCOMPARE(map.value(n3.toString().toLatin1()), V3);
+
+ // toMultiHash()
+ auto hash = h1.toMultiHash();
+ QCOMPARE(hash.size(), h1.size());
+ QCOMPARE(hash.value(n1.toString().toLatin1()), v1);
+ QCOMPARE(hash.value(n2.toString().toLatin1()), v2);
+ QCOMPARE(hash.value(n3.toString().toLatin1()), V3);
+
+ // insert()
+ h1.clear();
+ h1.append(n3, v3);
+ QVERIFY(h1.insert(0, n1, v1));
+ list = h1.toListOfPairs();
+ QCOMPARE(list.size(), 2);
+ QCOMPARE(list.at(0).first, n1);
+ QCOMPARE(list.at(0).second, v1);
+ QCOMPARE(list.at(1).first, n3);
+ QCOMPARE(list.at(1).second, v3);
+ QVERIFY(h1.insert(1, n2, v2));
+ list = h1.toListOfPairs();
+ QCOMPARE(list.size(), 3);
+ QCOMPARE(list.at(0).first, n1);
+ QCOMPARE(list.at(0).second, v1);
+ QCOMPARE(list.at(1).first, n2);
+ QCOMPARE(list.at(1).second, v2);
+ QCOMPARE(list.at(2).first, n3);
+ QCOMPARE(list.at(2).second, v3);
+ QVERIFY(h1.insert(1, QHttpHeaders::WellKnownHeader::Accept, "nothing"));
+ QCOMPARE(h1.size(), 4);
+ list = h1.toListOfPairs();
+ QCOMPARE(list.at(1).first, "accept");
+ QCOMPARE(list.at(1).second, "nothing");
+ QVERIFY(h1.insert(list.size(), "LastName", "lastValue"));
+ QCOMPARE(h1.size(), 5);
+ list = h1.toListOfPairs();
+ QCOMPARE(list.last().first, "lastname");
+ QCOMPARE(list.last().second, "lastValue");
+ // Failed insert
+ QRegularExpression re("HTTP header name contained*");
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, re);
+ QVERIFY(!h1.insert(0, "a€", "b"));
+
+ // replace
+ h1.clear();
+ h1.append(n1, v1);
+ h1.append(n2, v2);
+ QCOMPARE(h1.size(), 2);
+ QVERIFY(h1.replace(0, n3, v3));
+ QVERIFY(h1.replace(1, QHttpHeaders::WellKnownHeader::Accept, "nothing"));
+ QCOMPARE(h1.size(), 2);
+ list = h1.toListOfPairs();
+ QCOMPARE(list.at(0).first, n3);
+ QCOMPARE(list.at(0).second, v3);
+ QCOMPARE(list.at(1).first, "accept");
+ QCOMPARE(list.at(1).second, "nothing");
+ QVERIFY(h1.replace(1, "ACCEPT", "NOTHING"));
+ QCOMPARE(h1.size(), 2);
+ list = h1.toListOfPairs();
+ QCOMPARE(list.at(0).first, n3);
+ QCOMPARE(list.at(0).second, v3);
+ QCOMPARE(list.at(1).first, "accept");
+ QCOMPARE(list.at(1).second, "NOTHING");
+ // Failed replace
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, re);
+ QVERIFY(!h1.replace(0, "a€", "b"));
+
+}
+
+void tst_QHttpHeaders::wellKnownHeader()
+{
+ QByteArrayView view = QHttpHeaders::wellKnownHeaderName(QHttpHeaders::WellKnownHeader::AIM);
+ QCOMPARE(view, "a-im");
+}
+
+#define TEST_ILLEGAL_HEADER_NAME_CHARACTER(NAME) \
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, re); \
+ QVERIFY(!h1.append(NAME, v1)); \
+ QVERIFY(h1.isEmpty()); \
+
+void tst_QHttpHeaders::headerNameField()
+{
+ QHttpHeaders h1;
+
+ // All allowed characters in different encodings and types
+ // const char[]
+ h1.append("abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%&'*+-.^_`|~", v1);
+ QCOMPARE(h1.size(), 1);
+ // UTF-8
+ h1.append(u8"abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%&'*+-.^_`|~",
+ v1);
+ QCOMPARE(h1.size(), 2);
+ // UTF-16
+ h1.append(u"abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%&'*+-.^_`|~", v1);
+ QCOMPARE(h1.size(), 3);
+ // QString (UTF-16)
+ h1.append(u"abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%&'*+-.^_`|~"_s,
+ v1);
+ QCOMPARE(h1.size(), 4);
+ QCOMPARE(h1.nameAt(0), h1.nameAt(1));
+ QCOMPARE(h1.nameAt(1), h1.nameAt(2));
+ QCOMPARE(h1.nameAt(2), h1.nameAt(3));
+ h1.clear();
+
+ // Error cases
+ // Header name must contain at least 1 character
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, "HTTP header name cannot be empty");
+ h1.append("", v1);
+ QVERIFY(h1.isEmpty());
+ // Disallowed ASCII/extended ASCII characters (not exhaustive list)
+ QRegularExpression re("HTTP header name contained illegal character*");
+ TEST_ILLEGAL_HEADER_NAME_CHARACTER("foo\x08" "bar"); // BS
+ TEST_ILLEGAL_HEADER_NAME_CHARACTER("foo\x7F" "bar"); // DEL
+ TEST_ILLEGAL_HEADER_NAME_CHARACTER("foo()" "bar"); // parantheses
+ TEST_ILLEGAL_HEADER_NAME_CHARACTER("foobar" "¿"); // extended ASCII
+ TEST_ILLEGAL_HEADER_NAME_CHARACTER("©" "foobar"); // extended ASCII
+ TEST_ILLEGAL_HEADER_NAME_CHARACTER("foo,bar"); // comma
+ // Disallowed UTF-8 characters
+ TEST_ILLEGAL_HEADER_NAME_CHARACTER(u8"€");
+ TEST_ILLEGAL_HEADER_NAME_CHARACTER(u8"𝒜𝒴𝟘𝟡𐎀𐎜𐒀𐒐𝓐𝓩𝔸𝔹𝕀𝕁𝕌𝕍𓂀𓂁𓃀𓃁𓇋𓇌𓉐𓉑𓋴𓋵𓎡𓎢𓎣𓏏");
+ // Disallowed UTF-16 characters
+ TEST_ILLEGAL_HEADER_NAME_CHARACTER(u"€");
+ TEST_ILLEGAL_HEADER_NAME_CHARACTER(u"𝒜𝒴𝟘𝟡𐎀𐎜𐒀𐒐𝓐𝓩𝔸𝔹𝕀𝕁𝕌𝕍𓂀𓂁𓃀𓃁𓇋𓇌𓉐𓉑𓋴𓋵𓎡𓎢𓎣𓏏");
+
+ // Non-null-terminated name. The 'x' below is to make sure the strings don't
+ // null-terminate by happenstance
+ h1.clear();
+ constexpr char L1Array[] = {'a','b','c','x'};
+ const QLatin1StringView nonNullLatin1{L1Array, sizeof(L1Array) - 1}; // abc
+
+ constexpr char UTF8Array[] = {0x64, 0x65, 0x66, 0x78};
+ const QUtf8StringView nonNullUTF8(UTF8Array, sizeof(UTF8Array) - 1); // def
+
+ constexpr QChar UTF16Array[] = {'g', 'h', 'i', 'x'};
+ QStringView nonNullUTF16(UTF16Array, sizeof(UTF16Array) / sizeof(QChar) - 1); // ghi
+
+ h1.append(nonNullLatin1, v1);
+ QCOMPARE(h1.size(), 1);
+ QVERIFY(h1.contains(nonNullLatin1));
+ QCOMPARE(h1.combinedValue(nonNullLatin1), v1);
+
+ h1.append(nonNullUTF8, v2);
+ QCOMPARE(h1.size(), 2);
+ QVERIFY(h1.contains(nonNullUTF8));
+ QCOMPARE(h1.combinedValue(nonNullUTF8), v2);
+
+ h1.append(nonNullUTF16, v3);
+ QCOMPARE(h1.size(), 3);
+ QVERIFY(h1.contains(nonNullUTF16));
+ QCOMPARE(h1.combinedValue(nonNullUTF16), v3);
+}
+
+#define TEST_ILLEGAL_HEADER_VALUE_CHARACTER(VALUE) \
+QTest::ignoreMessage(QtMsgType::QtWarningMsg, re); \
+ QVERIFY(!h1.append(n1, VALUE)); \
+ QVERIFY(h1.isEmpty()); \
+
+void tst_QHttpHeaders::headerValueField()
+{
+ QHttpHeaders h1;
+
+ // Visible ASCII characters and space and horizontal tab
+ // const char[]
+ h1.append(n1, "!\"#$%&'()*+,-./0123456789:; \t<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
+ "`abcdefghijklmnopqrstuvwxyz{|}~");
+ QCOMPARE(h1.size(), 1);
+ // UTF-8
+ h1.append(n1, u8"!\"#$%&'()*+,-./0123456789:; \t<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
+ "`abcdefghijklmnopqrstuvwxyz{|}~");
+ QCOMPARE(h1.size(), 2);
+ // UTF-16
+ h1.append(n1, u"!\"#$%&'()*+,-./0123456789:; \t<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
+ "`abcdefghijklmnopqrstuvwxyz{|}~");
+ QCOMPARE(h1.size(), 3);
+ // QString / UTF-16
+ h1.append(n1, u"!\"#$%&'()*+,-./0123456789:; \t<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
+ "`abcdefghijklmnopqrstuvwxyz{|}~"_s);
+ QCOMPARE(h1.size(), 4);
+ const auto values = h1.values(n1);
+ QVERIFY(!values.isEmpty() && values.size() == 4);
+ QVERIFY(values[0] == values[1]
+ && values[1] == values[2]
+ && values[2] == values[3]);
+ // Extended ASCII (explicit on Latin-1 to avoid UTF-8 interpretation)
+ h1.append(n1, "\x80\x09\xB2\xFF"_L1);
+ QCOMPARE(h1.size(), 5);
+ // Empty value
+ h1.append(n1, "");
+ QCOMPARE(h1.size(), 6);
+ // Leading and trailing space
+ h1.clear();
+ h1.append(n1, " foo ");
+ QCOMPARE(h1.combinedValue(n1), "foo");
+ h1.append(n1, "\tbar\t");
+ QCOMPARE(h1.combinedValue(n1), "foo, bar");
+ QCOMPARE(h1.size(), 2);
+
+ h1.clear();
+ QRegularExpression re("HTTP header value contained illegal character*");
+ TEST_ILLEGAL_HEADER_VALUE_CHARACTER("foo\x08" "bar"); // BS
+ TEST_ILLEGAL_HEADER_VALUE_CHARACTER("foo\x1B" "bar"); // ESC
+ // Disallowed UTF-8 characters
+ TEST_ILLEGAL_HEADER_VALUE_CHARACTER(u8"€");
+ TEST_ILLEGAL_HEADER_VALUE_CHARACTER(u8"𝒜𝒴𝟘𝟡𐎀𐎜𐒀𐒐𝓐𝓩𝔸𝔹𝕀𝕁𝕌𝕍𓂀𓂁𓃀𓃁𓇋𓇌𓉐𓉑𓋴𓋵𓎡𓎢𓎣𓏏");
+ // Disallowed UTF-16 characters
+ TEST_ILLEGAL_HEADER_VALUE_CHARACTER(u"€");
+ TEST_ILLEGAL_HEADER_VALUE_CHARACTER(u"𝒜𝒴𝟘𝟡𐎀𐎜𐒀𐒐𝓐𝓩𝔸𝔹𝕀𝕁𝕌𝕍𓂀𓂁𓃀𓃁𓇋𓇌𓉐𓉑𓋴𓋵𓎡𓎢𓎣𓏏");
+
+ // Non-null-terminated value. The 'x' below is to make sure the strings don't
+ // null-terminate by happenstance
+ h1.clear();
+ constexpr char L1Array[] = {'a','b','c','x'};
+ const QLatin1StringView nonNullLatin1{L1Array, sizeof(L1Array) - 1}; // abc
+
+ constexpr char UTF8Array[] = {0x64, 0x65, 0x66, 0x78};
+ const QUtf8StringView nonNullUTF8(UTF8Array, sizeof(UTF8Array) - 1); // def
+
+ constexpr QChar UTF16Array[] = {'g', 'h', 'i', 'x'};
+ QStringView nonNullUTF16(UTF16Array, sizeof(UTF16Array) / sizeof(QChar) - 1); // ghi
+
+ h1.append(n1, nonNullLatin1);
+ QCOMPARE(h1.size(), 1);
+ QVERIFY(h1.contains(n1));
+ QCOMPARE(h1.combinedValue(n1), "abc");
+
+ h1.append(n2, nonNullUTF8);
+ QCOMPARE(h1.size(), 2);
+ QVERIFY(h1.contains(n2));
+ QCOMPARE(h1.combinedValue(n2), "def");
+
+ h1.append(n3, nonNullUTF16);
+ QCOMPARE(h1.size(), 3);
+ QVERIFY(h1.contains(n3));
+ QCOMPARE(h1.combinedValue(n3), "ghi");
+}
+
+void tst_QHttpHeaders::valueEncoding()
+{
+ // Test that common encodings are possible to set and not blocked by
+ // header value character filter (ie. don't contain disallowed characters as per RFC 9110)
+ QHttpHeaders h1;
+ // Within visible ASCII range
+ QVERIFY(h1.append(n1, "foo"_ba.toBase64()));
+ QCOMPARE(h1.values(n1).at(0), "Zm9v");
+ h1.replace(0, n1, "foo"_ba.toPercentEncoding());
+ QCOMPARE(h1.values(n1).at(0), "foo");
+
+ // Outside of ASCII/Latin-1 range (€)
+ h1.replace(0, n1, "foo€"_ba.toBase64());
+ QCOMPARE(h1.values(n1).at(0), "Zm9v4oKs");
+ h1.replace(0, n1, "foo€"_ba.toPercentEncoding());
+ QCOMPARE(h1.values(n1).at(0), "foo%E2%82%AC");
+}
+
+void tst_QHttpHeaders::replaceOrAppend()
+{
+ QHttpHeaders h1;
+
+#define REPLACE_OR_APPEND(NAME, VALUE, INDEX, TOTALSIZE) \
+ do { \
+ QVERIFY(h1.replaceOrAppend(NAME, VALUE)); \
+ QCOMPARE(h1.size(), TOTALSIZE); \
+ QCOMPARE(h1.nameAt(INDEX), NAME); \
+ QCOMPARE(h1.valueAt(INDEX), VALUE); \
+ } while (false)
+
+ // Append to empty container and replace it
+ REPLACE_OR_APPEND(n1, v1, 0, 1); // Appends
+ REPLACE_OR_APPEND(n1, v2, 0, 1); // Replaces
+
+ // Replace at beginning, middle, and end
+ h1.clear();
+ REPLACE_OR_APPEND(n1, v1, 0, 1); // Appends
+ REPLACE_OR_APPEND(n2, v2, 1, 2); // Appends
+ REPLACE_OR_APPEND(n3, v3, 2, 3); // Appends
+ REPLACE_OR_APPEND(n1, V1, 0, 3); // Replaces at beginning
+ REPLACE_OR_APPEND(n2, V2, 1, 3); // Replaces at middle
+ REPLACE_OR_APPEND(n3, V3, 2, 3); // Replaces at end
+
+ // Pre-existing multiple values (n2) are removed
+ h1.clear();
+ h1.append(n1, v1);
+ h1.append(n2, v2); // First n2 is at index 1
+ h1.append(n2, v2);
+ h1.append(n3, v3);
+ h1.append(n2, v2);
+ QCOMPARE(h1.size(), 5);
+ QCOMPARE(h1.combinedValue(n2), "value2, value2, value2");
+ REPLACE_OR_APPEND(n2, V2, 1, 3); // Replaces value at index 1, and removes the rest
+ QCOMPARE(h1.combinedValue(n2), "VALUE2");
+#undef REPLACE_OR_APPEND
+
+ // Implicit sharing / detaching
+ h1.clear();
+ h1.append(n1, v1);
+ QHttpHeaders h2 = h1;
+ QCOMPARE(h1.size(), h2.size());
+ QCOMPARE(h1.valueAt(0), h2.valueAt(0)); // Iniially values are equal
+ h1.replaceOrAppend(n1, v2); // Change value in h1 => detaches h1
+ QCOMPARE_NE(h1.valueAt(0), h2.valueAt(0)); // Values are no more equal
+ QCOMPARE(h1.valueAt(0), v2); // Value in h1 changed
+ QCOMPARE(h2.valueAt(0), v1); // Value in h2 remained
+
+ // Failed attempts
+ h1.clear();
+ h1.append(n1, v1);
+ QRegularExpression re("HTTP header*");
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, re);
+ QVERIFY(!h1.replaceOrAppend("", V1));
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, re);
+ QVERIFY(!h1.replaceOrAppend(v1, "foo\x08"));
+}
+
+QTEST_MAIN(tst_QHttpHeaders)
+#include "tst_qhttpheaders.moc"
diff --git a/tests/auto/network/access/qhttpheadershelper/CMakeLists.txt b/tests/auto/network/access/qhttpheadershelper/CMakeLists.txt
new file mode 100644
index 0000000000..75935d2844
--- /dev/null
+++ b/tests/auto/network/access/qhttpheadershelper/CMakeLists.txt
@@ -0,0 +1,15 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qhttpheadershelper LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_test(tst_qhttpheadershelper
+ SOURCES
+ tst_qhttpheadershelper.cpp
+ LIBRARIES
+ Qt::NetworkPrivate
+)
diff --git a/tests/auto/network/access/qhttpheadershelper/tst_qhttpheadershelper.cpp b/tests/auto/network/access/qhttpheadershelper/tst_qhttpheadershelper.cpp
new file mode 100644
index 0000000000..b204d0cbe3
--- /dev/null
+++ b/tests/auto/network/access/qhttpheadershelper/tst_qhttpheadershelper.cpp
@@ -0,0 +1,76 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtNetwork/qhttpheaders.h>
+#include <QtNetwork/private/qhttpheadershelper_p.h>
+
+#include <QtTest/qtest.h>
+
+using namespace Qt::StringLiterals;
+
+class tst_QHttpHeadersHelper : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testCompareStrict();
+
+private:
+ static constexpr QAnyStringView n1{"name1"};
+ static constexpr QAnyStringView n2{"name2"};
+ static constexpr QAnyStringView v1{"value1"};
+ static constexpr QAnyStringView v2{"value2"};
+ static constexpr QAnyStringView N1{"NAME1"};
+ static constexpr QAnyStringView N2{"NAME2"};
+ static constexpr QAnyStringView V1{"VALUE1"};
+ static constexpr QAnyStringView V2{"VALUE2"};
+};
+
+void tst_QHttpHeadersHelper::testCompareStrict()
+{
+ using namespace QHttpHeadersHelper;
+
+ // Basic comparisons
+ QHttpHeaders h1;
+ QHttpHeaders h2;
+ QVERIFY(compareStrict(h1, h2)); // empties
+ h1.append(n1, v1);
+ QVERIFY(compareStrict(h1, h1)); // self
+ h2.append(n1, v1);
+ QVERIFY(compareStrict(h1, h2));
+ h1.append(n2, v2);
+ QVERIFY(!compareStrict(h1, h2));
+ h1.removeAll(n2);
+ QVERIFY(compareStrict(h1, h2));
+
+ // Order-sensitivity
+ h1.clear();
+ h2.clear();
+ // Same headers but in different order
+ h1.append(n1, v1);
+ h1.append(n2, v2);
+ h2.append(n2, v2);
+ h2.append(n1, v1);
+ QVERIFY(!compareStrict(h1, h2));
+
+ // Different number of headers
+ h1.clear();
+ h2.clear();
+ h1.append(n1, v1);
+ h2.append(n1, v1);
+ h2.append(n2, v2);
+ QVERIFY(!compareStrict(h1, h2));
+
+ // Same header name, multiple values
+ h1.clear();
+ h2.clear();
+ h1.append(n1, v1);
+ h1.append(n1, v2);
+ h2.append(n1, v1);
+ QVERIFY(!compareStrict(h1, h2));
+ h2.append(n1, v2);
+ QVERIFY(compareStrict(h1, h2));
+}
+
+QTEST_MAIN(tst_QHttpHeadersHelper)
+#include "tst_qhttpheadershelper.moc"
diff --git a/tests/auto/network/access/qhttpnetworkconnection/CMakeLists.txt b/tests/auto/network/access/qhttpnetworkconnection/CMakeLists.txt
index 3492dd6df3..679990062f 100644
--- a/tests/auto/network/access/qhttpnetworkconnection/CMakeLists.txt
+++ b/tests/auto/network/access/qhttpnetworkconnection/CMakeLists.txt
@@ -1,7 +1,11 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qhttpnetworkconnection.pro.
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qhttpnetworkconnection LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
if(NOT QT_FEATURE_private_tests)
return()
@@ -17,9 +21,5 @@ qt_internal_add_test(tst_qhttpnetworkconnection
LIBRARIES
Qt::CorePrivate
Qt::NetworkPrivate
- QT_TEST_SERVER_LIST "apache2" # special case
+ QT_TEST_SERVER_LIST "apache2"
)
-
-#### Keys ignored in scope 1:.:.:qhttpnetworkconnection.pro:<TRUE>:
-# QT_TEST_SERVER_LIST = "apache2"
-# _REQUIREMENTS = "qtConfig(private_tests)"
diff --git a/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp b/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
index b1f3966285..decd442164 100644
--- a/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
+++ b/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
@@ -125,7 +125,7 @@ void tst_QHttpNetworkConnection::head()
QFETCH(QString, statusString);
QFETCH(int, contentLength);
- QHttpNetworkConnection connection(host, port, encrypt);
+ QHttpNetworkConnection connection(QHttpNetworkConnectionPrivate::defaultHttpChannelCount, host, port, encrypt);
QCOMPARE(connection.port(), port);
QCOMPARE(connection.hostName(), host);
QCOMPARE(connection.isSsl(), encrypt);
@@ -175,7 +175,7 @@ void tst_QHttpNetworkConnection::get()
QFETCH(int, contentLength);
QFETCH(int, downloadSize);
- QHttpNetworkConnection connection(host, port, encrypt);
+ QHttpNetworkConnection connection(QHttpNetworkConnectionPrivate::defaultHttpChannelCount, host, port, encrypt);
QCOMPARE(connection.port(), port);
QCOMPARE(connection.hostName(), host);
QCOMPARE(connection.isSsl(), encrypt);
@@ -241,7 +241,7 @@ void tst_QHttpNetworkConnection::put()
QFETCH(QString, data);
QFETCH(bool, succeed);
- QHttpNetworkConnection connection(host, port, encrypt);
+ QHttpNetworkConnection connection(QHttpNetworkConnectionPrivate::defaultHttpChannelCount, host, port, encrypt);
QCOMPARE(connection.port(), port);
QCOMPARE(connection.hostName(), host);
QCOMPARE(connection.isSsl(), encrypt);
@@ -323,7 +323,7 @@ void tst_QHttpNetworkConnection::post()
QFETCH(int, contentLength);
QFETCH(int, downloadSize);
- QHttpNetworkConnection connection(host, port, encrypt);
+ QHttpNetworkConnection connection(QHttpNetworkConnectionPrivate::defaultHttpChannelCount, host, port, encrypt);
QCOMPARE(connection.port(), port);
QCOMPARE(connection.hostName(), host);
QCOMPARE(connection.isSsl(), encrypt);
@@ -450,7 +450,7 @@ void tst_QHttpNetworkConnection::get401()
QFETCH(QString, password);
QFETCH(int, statusCode);
- QHttpNetworkConnection connection(host, port, encrypt);
+ QHttpNetworkConnection connection(QHttpNetworkConnectionPrivate::defaultHttpChannelCount, host, port, encrypt);
QCOMPARE(connection.port(), port);
QCOMPARE(connection.hostName(), host);
QCOMPARE(connection.isSsl(), encrypt);
@@ -510,7 +510,7 @@ void tst_QHttpNetworkConnection::compression()
QFETCH(bool, autoCompress);
QFETCH(QString, contentCoding);
- QHttpNetworkConnection connection(host, port, encrypt);
+ QHttpNetworkConnection connection(QHttpNetworkConnectionPrivate::defaultHttpChannelCount, host, port, encrypt);
QCOMPARE(connection.port(), port);
QCOMPARE(connection.hostName(), host);
QCOMPARE(connection.isSsl(), encrypt);
@@ -584,7 +584,7 @@ void tst_QHttpNetworkConnection::ignoresslerror()
QFETCH(bool, ignoreFromSignal);
QFETCH(int, statusCode);
- QHttpNetworkConnection connection(host, port, encrypt);
+ QHttpNetworkConnection connection(QHttpNetworkConnectionPrivate::defaultHttpChannelCount, host, port, encrypt);
QCOMPARE(connection.port(), port);
QCOMPARE(connection.hostName(), host);
if (ignoreInit)
@@ -629,7 +629,7 @@ void tst_QHttpNetworkConnection::nossl()
QFETCH(bool, encrypt);
QFETCH(QNetworkReply::NetworkError, networkError);
- QHttpNetworkConnection connection(host, port, encrypt);
+ QHttpNetworkConnection connection(QHttpNetworkConnectionPrivate::defaultHttpChannelCount, host, port, encrypt);
QCOMPARE(connection.port(), port);
QCOMPARE(connection.hostName(), host);
@@ -666,7 +666,7 @@ void tst_QHttpNetworkConnection::getMultiple_data()
static bool allRepliesFinished(const QList<QHttpNetworkReply*> *_replies)
{
const QList<QHttpNetworkReply*> &replies = *_replies;
- for (int i = 0; i < replies.length(); i++)
+ for (int i = 0; i < replies.size(); i++)
if (!replies.at(i)->isFinished())
return false;
return true;
@@ -735,7 +735,7 @@ void tst_QHttpNetworkConnection::getMultipleWithPipeliningAndMultiplePriorities(
QTRY_VERIFY_WITH_TIMEOUT(allRepliesFinished(&replies), 60000);
int pipelinedCount = 0;
- for (int i = 0; i < replies.length(); i++) {
+ for (int i = 0; i < replies.size(); i++) {
QVERIFY (!(replies.at(i)->request().isPipeliningAllowed() == false
&& replies.at(i)->isPipeliningUsed()));
@@ -919,7 +919,7 @@ void tst_QHttpNetworkConnection::getAndThenDeleteObject_data()
void tst_QHttpNetworkConnection::getAndThenDeleteObject()
{
// yes, this will leak if the testcase fails. I don't care. It must not fail then :P
- QHttpNetworkConnection *connection = new QHttpNetworkConnection(httpServerName());
+ QHttpNetworkConnection *connection = new QHttpNetworkConnection(QHttpNetworkConnectionPrivate::defaultHttpChannelCount, httpServerName());
QHttpNetworkRequest request("http://" + httpServerName() + "/qtest/bigfile");
QHttpNetworkReply *reply = connection->sendRequest(request);
reply->setDownstreamLimited(true);
diff --git a/tests/auto/network/access/qhttpnetworkreply/CMakeLists.txt b/tests/auto/network/access/qhttpnetworkreply/CMakeLists.txt
index 2be2d677ae..b4e4a822ee 100644
--- a/tests/auto/network/access/qhttpnetworkreply/CMakeLists.txt
+++ b/tests/auto/network/access/qhttpnetworkreply/CMakeLists.txt
@@ -1,7 +1,11 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qhttpnetworkreply.pro.
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qhttpnetworkreply LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
if(NOT QT_FEATURE_private_tests)
return()
@@ -18,6 +22,3 @@ qt_internal_add_test(tst_qhttpnetworkreply
Qt::CorePrivate
Qt::NetworkPrivate
)
-
-#### Keys ignored in scope 1:.:.:qhttpnetworkreply.pro:<TRUE>:
-# _REQUIREMENTS = "qtConfig(private_tests)"
diff --git a/tests/auto/network/access/qhttpnetworkreply/tst_qhttpnetworkreply.cpp b/tests/auto/network/access/qhttpnetworkreply/tst_qhttpnetworkreply.cpp
index e36acc81da..e83d15fdc3 100644
--- a/tests/auto/network/access/qhttpnetworkreply/tst_qhttpnetworkreply.cpp
+++ b/tests/auto/network/access/qhttpnetworkreply/tst_qhttpnetworkreply.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
@@ -77,7 +77,7 @@ void tst_QHttpNetworkReply::parseHeader()
QHttpNetworkReply reply;
reply.parseHeader(headers);
- for (int i = 0; i < fields.count(); ++i) {
+ for (int i = 0; i < fields.size(); ++i) {
//qDebug() << "field" << fields.at(i) << "value" << reply.headerField(fields.at(i)) << "expected" << values.at(i);
QString field = reply.headerField(fields.at(i).toLatin1());
QCOMPARE(field, values.at(i));
diff --git a/tests/auto/network/access/qnetworkaccessmanager/CMakeLists.txt b/tests/auto/network/access/qnetworkaccessmanager/CMakeLists.txt
index 496fb0a50c..b0fe6eda46 100644
--- a/tests/auto/network/access/qnetworkaccessmanager/CMakeLists.txt
+++ b/tests/auto/network/access/qnetworkaccessmanager/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qnetworkaccessmanager.pro.
-
#####################################################################
## tst_qnetworkaccessmanager Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qnetworkaccessmanager LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qnetworkaccessmanager
SOURCES
tst_qnetworkaccessmanager.cpp
diff --git a/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp b/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp
index 568aceadd3..43db6d5841 100644
--- a/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp
+++ b/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
diff --git a/tests/auto/network/access/qnetworkcachemetadata/CMakeLists.txt b/tests/auto/network/access/qnetworkcachemetadata/CMakeLists.txt
index ff928b377f..2aa918c49c 100644
--- a/tests/auto/network/access/qnetworkcachemetadata/CMakeLists.txt
+++ b/tests/auto/network/access/qnetworkcachemetadata/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qnetworkcachemetadata.pro.
-
#####################################################################
## tst_qnetworkcachemetadata Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qnetworkcachemetadata LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qnetworkcachemetadata
SOURCES
tst_qnetworkcachemetadata.cpp
diff --git a/tests/auto/network/access/qnetworkcachemetadata/tst_qnetworkcachemetadata.cpp b/tests/auto/network/access/qnetworkcachemetadata/tst_qnetworkcachemetadata.cpp
index c3c5c92e55..d49195efc6 100644
--- a/tests/auto/network/access/qnetworkcachemetadata/tst_qnetworkcachemetadata.cpp
+++ b/tests/auto/network/access/qnetworkcachemetadata/tst_qnetworkcachemetadata.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
@@ -29,6 +29,8 @@ private slots:
void operatorEqualEqual();
void rawHeaders_data();
void rawHeaders();
+ void headers_data();
+ void headers();
void saveToDisk_data();
void saveToDisk();
void url_data();
@@ -114,6 +116,12 @@ void tst_QNetworkCacheMetaData::isValid_data()
QNetworkCacheMetaData data5;
data5.setSaveToDisk(false);
QTest::newRow("valid-5") << data5 << true;
+
+ QNetworkCacheMetaData data6;
+ QHttpHeaders httpHeaders;
+ httpHeaders.append("name", "value");
+ data6.setHeaders(httpHeaders);
+ QTest::newRow("valid-6") << data6 << true;
}
// public bool isValid() const
@@ -153,6 +161,9 @@ void tst_QNetworkCacheMetaData::operatorEqual_data()
QNetworkCacheMetaData::RawHeaderList headers;
headers.append(QNetworkCacheMetaData::RawHeader("foo", "Bar"));
data.setRawHeaders(headers);
+ QHttpHeaders httpHeaders;
+ httpHeaders.append("name", "value");
+ data.setHeaders(httpHeaders);
data.setLastModified(QDateTime::currentDateTime());
data.setExpirationDate(QDateTime::currentDateTime());
data.setSaveToDisk(false);
@@ -212,6 +223,18 @@ void tst_QNetworkCacheMetaData::operatorEqualEqual_data()
QTest::newRow("valid-5-4") << data5 << data2 << false;
QTest::newRow("valid-5-5") << data5 << data3 << false;
QTest::newRow("valid-5-6") << data5 << data4 << false;
+
+ QNetworkCacheMetaData data6;
+ QHttpHeaders httpHeaders;
+ httpHeaders.append("name", "value");
+ data6.setHeaders(httpHeaders);
+ QTest::newRow("valid-6-1") << data6 << QNetworkCacheMetaData() << false;
+ QTest::newRow("valid-6-2") << data6 << data6 << true;
+ QTest::newRow("valid-6-3") << data6 << data1 << false;
+ QTest::newRow("valid-6-4") << data6 << data2 << false;
+ QTest::newRow("valid-6-5") << data6 << data3 << false;
+ QTest::newRow("valid-6-6") << data6 << data4 << false;
+ QTest::newRow("valid-6-7") << data6 << data5 << false;
}
// public bool operator==(QNetworkCacheMetaData const& other) const
@@ -231,7 +254,11 @@ void tst_QNetworkCacheMetaData::rawHeaders_data()
QTest::newRow("null") << QNetworkCacheMetaData::RawHeaderList();
QNetworkCacheMetaData::RawHeaderList headers;
headers.append(QNetworkCacheMetaData::RawHeader("foo", "Bar"));
- QTest::newRow("valie") << headers;
+ QTest::newRow("valid") << headers;
+ headers.append(QNetworkCacheMetaData::RawHeader("n1", "V1, v2, v3"));
+ headers.append(QNetworkCacheMetaData::RawHeader("n2", "V2"));
+ headers.append(QNetworkCacheMetaData::RawHeader("set-cookie", "v1\nV2\nV3"));
+ QTest::newRow("valid-2") << headers;
}
// public QNetworkCacheMetaData::RawHeaderList rawHeaders() const
@@ -245,6 +272,25 @@ void tst_QNetworkCacheMetaData::rawHeaders()
QCOMPARE(data.rawHeaders(), rawHeaders);
}
+void tst_QNetworkCacheMetaData::headers_data()
+{
+ QTest::addColumn<QHttpHeaders>("httpHeaders");
+ QTest::newRow("null") << QHttpHeaders();
+ QHttpHeaders headers;
+ headers.append("foo", "Bar");
+ QTest::newRow("valid") << headers;
+}
+
+void tst_QNetworkCacheMetaData::headers()
+{
+ QFETCH(QHttpHeaders, httpHeaders);
+
+ SubQNetworkCacheMetaData data;
+
+ data.setHeaders(httpHeaders);
+ QCOMPARE(data.headers().toListOfPairs(), httpHeaders.toListOfPairs());
+}
+
void tst_QNetworkCacheMetaData::saveToDisk_data()
{
QTest::addColumn<bool>("saveToDisk");
@@ -289,6 +335,9 @@ void tst_QNetworkCacheMetaData::stream()
QNetworkCacheMetaData::RawHeaderList headers;
headers.append(QNetworkCacheMetaData::RawHeader("foo", "Bar"));
data.setRawHeaders(headers);
+ QHttpHeaders httpHeaders;
+ httpHeaders.append("name", "value");
+ data.setHeaders(httpHeaders);
data.setLastModified(QDateTime::currentDateTime());
data.setExpirationDate(QDateTime::currentDateTime());
data.setSaveToDisk(false);
diff --git a/tests/auto/network/access/qnetworkcookie/CMakeLists.txt b/tests/auto/network/access/qnetworkcookie/CMakeLists.txt
index 71328ee8c7..91773a83fd 100644
--- a/tests/auto/network/access/qnetworkcookie/CMakeLists.txt
+++ b/tests/auto/network/access/qnetworkcookie/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qnetworkcookie.pro.
-
#####################################################################
## tst_qnetworkcookie Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qnetworkcookie LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qnetworkcookie
SOURCES
tst_qnetworkcookie.cpp
diff --git a/tests/auto/network/access/qnetworkcookie/tst_qnetworkcookie.cpp b/tests/auto/network/access/qnetworkcookie/tst_qnetworkcookie.cpp
index d6709a614c..438c5e6983 100644
--- a/tests/auto/network/access/qnetworkcookie/tst_qnetworkcookie.cpp
+++ b/tests/auto/network/access/qnetworkcookie/tst_qnetworkcookie.cpp
@@ -1,11 +1,13 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
-#include <QtCore/QUrl>
#include <QtNetwork/QNetworkCookie>
+#include <QtCore/QDateTime>
+#include <QtCore/QTimeZone>
+#include <QtCore/QUrl>
class tst_QNetworkCookie: public QObject
{
@@ -85,6 +87,12 @@ void tst_QNetworkCookie::parseSingleCookie_data()
{
QTest::addColumn<QString>("cookieString");
QTest::addColumn<QNetworkCookie>("expectedCookie");
+ const auto utc = [](int year, int month, int day,
+ int hour = 0, int minute = 0, int second = 0, int millis = 0) {
+ return QDateTime(QDate(year, month, day),
+ QTime(hour, minute, second, millis),
+ QTimeZone::UTC);
+ };
QNetworkCookie cookie;
cookie.setName("a");
@@ -229,140 +237,140 @@ void tst_QNetworkCookie::parseSingleCookie_data()
cookie = QNetworkCookie();
cookie.setName("a");
cookie.setValue("b");
- cookie.setExpirationDate(QDateTime(QDate(2012, 1, 29), QTime(23, 59, 59), Qt::UTC));
+ cookie.setExpirationDate(utc(2012, 1, 29, 23, 59, 59));
QTest::newRow("broken-expiration1") << "a=b; expires=Sun, 29-Jan-2012 23:59:59;" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1999, 11, 9), QTime(23, 12, 40), Qt::UTC));
+ cookie.setExpirationDate(utc(1999, 11, 9, 23, 12, 40));
QTest::newRow("expiration1") << "a=b;expires=Wednesday, 09-Nov-1999 23:12:40 GMT" << cookie;
QTest::newRow("expiration2") << "a=b;expires=Wed, 09-Nov-1999 23:12:40 GMT" << cookie;
QTest::newRow("expiration3") << "a=b; expires=Wednesday, 09-Nov-1999 23:12:40 GMT " << cookie;
QTest::newRow("expiration-utc") << "a=b;expires=Wednesday, 09-Nov-1999 23:12:40 UTC" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 4, 14), QTime(3, 20, 0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 4, 14, 3, 20));
QTest::newRow("time-0") << "a=b;expires=14 Apr 89 03:20" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 4, 14), QTime(3, 20, 12, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 4, 14, 3, 20, 12));
QTest::newRow("time-1") << "a=b;expires=14 Apr 89 03:20:12" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 4, 14), QTime(3, 20, 12, 88), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 4, 14, 3, 20, 12, 88));
QTest::newRow("time-2") << "a=b;expires=14 Apr 89 03:20:12.88" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 4, 14), QTime(3, 20, 12, 88), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 4, 14, 3, 20, 12, 88));
QTest::newRow("time-3") << "a=b;expires=14 Apr 89 03:20:12.88am" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 4, 14), QTime(15, 20, 12, 88), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 4, 14, 15, 20, 12, 88));
QTest::newRow("time-4") << "a=b;expires=14 Apr 89 03:20:12.88pm" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 4, 14), QTime(3, 20, 12, 88), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 4, 14, 3, 20, 12, 88));
QTest::newRow("time-5") << "a=b;expires=14 Apr 89 03:20:12.88 Am" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 4, 14), QTime(15, 20, 12, 88), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 4, 14, 15, 20, 12, 88));
QTest::newRow("time-6") << "a=b;expires=14 Apr 89 03:20:12.88 PM" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 4, 14), QTime(15, 20, 12, 88), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 4, 14, 15, 20, 12, 88));
QTest::newRow("time-7") << "a=b;expires=14 Apr 89 3:20:12.88 PM" << cookie;
// normal months
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(1, 1), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 1, 1, 1));
QTest::newRow("months-1") << "a=b;expires=Jan 1 89 1:1" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 2, 1), QTime(1, 1), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 2, 1, 1, 1));
QTest::newRow("months-2") << "a=b;expires=Feb 1 89 1:1" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 3, 1), QTime(1, 1), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 3, 1, 1, 1));
QTest::newRow("months-3") << "a=b;expires=mar 1 89 1:1" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 4, 1), QTime(1, 1), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 4, 1, 1, 1));
QTest::newRow("months-4") << "a=b;expires=Apr 1 89 1:1" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 5, 1), QTime(1, 1), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 5, 1, 1, 1));
QTest::newRow("months-5") << "a=b;expires=May 1 89 1:1" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 6, 1), QTime(1, 1), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 6, 1, 1, 1));
QTest::newRow("months-6") << "a=b;expires=Jun 1 89 1:1" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 7, 1), QTime(1, 1), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 7, 1, 1, 1));
QTest::newRow("months-7") << "a=b;expires=Jul 1 89 1:1" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 8, 1), QTime(1, 1), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 8, 1, 1, 1));
QTest::newRow("months-8") << "a=b;expires=Aug 1 89 1:1" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 9, 1), QTime(1, 1), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 9, 1, 1, 1));
QTest::newRow("months-9") << "a=b;expires=Sep 1 89 1:1" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 10, 1), QTime(1, 1), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 10, 1, 1, 1));
QTest::newRow("months-10") << "a=b;expires=Oct 1 89 1:1" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 11, 1), QTime(1, 1), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 11, 1, 1, 1));
QTest::newRow("months-11") << "a=b;expires=Nov 1 89 1:1" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 12, 1), QTime(1, 1), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 12, 1, 1, 1));
QTest::newRow("months-12") << "a=b;expires=Dec 1 89 1:1" << cookie;
// extra months
- cookie.setExpirationDate(QDateTime(QDate(1989, 12, 1), QTime(1, 1), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 12, 1, 1, 1));
QTest::newRow("months-13") << "a=b;expires=December 1 89 1:1" << cookie;
QTest::newRow("months-14") << "a=b;expires=1 89 1:1 Dec" << cookie;
//cookie.setExpirationDate(QDateTime());
//QTest::newRow("months-15") << "a=b;expires=1 89 1:1 De" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(2024, 2, 29), QTime(1, 1), Qt::UTC));
+ cookie.setExpirationDate(utc(2024, 2, 29, 1, 1));
QTest::newRow("months-16") << "a=b;expires=2024 29 Feb 1:1" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(2024, 2, 29), QTime(1, 1), Qt::UTC));
+ cookie.setExpirationDate(utc(2024, 2, 29, 1, 1));
QTest::newRow("months-17") << "a=b;expires=Fri, 29-Feb-2024 01:01:00 GMT" << cookie;
QTest::newRow("months-18") << "a=b;expires=2024 29 Feb 1:1 GMT" << cookie;
// normal offsets
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 1));
QTest::newRow("zoneoffset-0") << "a=b;expires=Jan 1 89 8:0 PST" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 1));
QTest::newRow("zoneoffset-1") << "a=b;expires=Jan 1 89 8:0 PDT" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 1));
QTest::newRow("zoneoffset-2") << "a=b;expires=Jan 1 89 7:0 MST" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 1));
QTest::newRow("zoneoffset-3") << "a=b;expires=Jan 1 89 7:0 MDT" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 1));
QTest::newRow("zoneoffset-4") << "a=b;expires=Jan 1 89 6:0 CST" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 1));
QTest::newRow("zoneoffset-5") << "a=b;expires=Jan 1 89 6:0 CDT" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 1));
QTest::newRow("zoneoffset-6") << "a=b;expires=Jan 1 89 5:0 EST" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 1));
QTest::newRow("zoneoffset-7") << "a=b;expires=Jan 1 89 5:0 EDT" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 1));
QTest::newRow("zoneoffset-8") << "a=b;expires=Jan 1 89 4:0 AST" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 1));
QTest::newRow("zoneoffset-9") << "a=b;expires=Jan 1 89 3:0 NST" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 1));
QTest::newRow("zoneoffset-10") << "a=b;expires=Jan 1 89 0:0 GMT" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 1));
QTest::newRow("zoneoffset-11") << "a=b;expires=Jan 1 89 0:0 BST" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 2), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 2));
QTest::newRow("zoneoffset-12") << "a=b;expires=Jan 1 89 23:0 MET" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 2), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 2));
QTest::newRow("zoneoffset-13") << "a=b;expires=Jan 1 89 22:0 EET" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 2), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 2));
QTest::newRow("zoneoffset-14") << "a=b;expires=Jan 1 89 15:0 JST" << cookie;
// extra offsets
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 2), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 2));
QTest::newRow("zoneoffset-15") << "a=b;expires=Jan 1 89 15:0 JST+1" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(1, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 1, 1));
QTest::newRow("zoneoffset-16") << "a=b;expires=Jan 1 89 0:0 GMT+1" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 1));
QTest::newRow("zoneoffset-17") << "a=b;expires=Jan 1 89 1:0 GMT-1" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(1, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 1, 1));
QTest::newRow("zoneoffset-18") << "a=b;expires=Jan 1 89 0:0 GMT+01" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(1, 5), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 1, 1, 5));
QTest::newRow("zoneoffset-19") << "a=b;expires=Jan 1 89 0:0 GMT+0105" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 1));
QTest::newRow("zoneoffset-20") << "a=b;expires=Jan 1 89 0:0 GMT+015" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 1));
QTest::newRow("zoneoffset-21") << "a=b;expires=Jan 1 89 0:0 GM" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 1));
QTest::newRow("zoneoffset-22") << "a=b;expires=Jan 1 89 0:0 GMT" << cookie;
// offsets from gmt
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(1, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 1, 1));
QTest::newRow("zoneoffset-23") << "a=b;expires=Jan 1 89 0:0 +1" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(1, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 1, 1));
QTest::newRow("zoneoffset-24") << "a=b;expires=Jan 1 89 0:0 +01" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(1, 1), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 1, 1, 1));
QTest::newRow("zoneoffset-25") << "a=b;expires=Jan 1 89 0:0 +0101" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 1), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 1));
QTest::newRow("zoneoffset-26") << "a=b;expires=Jan 1 89 1:0 -1" << cookie;
// Y2k
- cookie.setExpirationDate(QDateTime(QDate(2000, 1, 1), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(2000, 1, 1));
QTest::newRow("year-0") << "a=b;expires=Jan 1 00 0:0" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1970, 1, 1), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1970, 1, 1));
QTest::newRow("year-1") << "a=b;expires=Jan 1 70 0:0" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1971, 1, 1), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1971, 1, 1));
QTest::newRow("year-2") << "a=b;expires=Jan 1 71 0:0" << cookie;
// Day, month, year
- cookie.setExpirationDate(QDateTime(QDate(2013, 1, 2), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(2013, 1, 2));
QTest::newRow("date-0") << "a=b;expires=Jan 2 13 0:0" << cookie;
QTest::newRow("date-1") << "a=b;expires=1-2-13 0:0" << cookie;
QTest::newRow("date-2") << "a=b;expires=1/2/13 0:0" << cookie;
@@ -372,141 +380,141 @@ void tst_QNetworkCookie::parseSingleCookie_data()
QTest::newRow("date-6") << "a=b;expires=1/2/13 0:0" << cookie;
// Known Year, determine month and day
- cookie.setExpirationDate(QDateTime(QDate(1995, 1, 13), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1995, 1, 13));
QTest::newRow("knownyear-0") << "a=b;expires=13/1/95 0:0" << cookie;
QTest::newRow("knownyear-1") << "a=b;expires=95/13/1 0:0" << cookie;
QTest::newRow("knownyear-2") << "a=b;expires=1995/1/13 0:0" << cookie;
QTest::newRow("knownyear-3") << "a=b;expires=1995/13/1 0:0" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1995, 1, 2), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1995, 1, 2));
QTest::newRow("knownyear-4") << "a=b;expires=1/2/95 0:0" << cookie;
QTest::newRow("knownyear-5") << "a=b;expires=95/1/2 0:0" << cookie;
// Known Year, Known day, determining month
- cookie.setExpirationDate(QDateTime(QDate(1995, 1, 13), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1995, 1, 13));
QTest::newRow("knownYD-0") << "a=b;expires=13/1/95 0:0" << cookie;
QTest::newRow("knownYD-1") << "a=b;expires=1/13/95 0:0" << cookie;
QTest::newRow("knownYD-2") << "a=b;expires=95/13/1 0:0" << cookie;
QTest::newRow("knownYD-3") << "a=b;expires=95/1/13 0:0" << cookie;
// Month comes before Year
- cookie.setExpirationDate(QDateTime(QDate(2021, 03, 26), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(2021, 03, 26));
QTest::newRow("month-0") << "a=b;expires=26/03/21 0:0" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(2015, 12, 30), QTime(16, 25, 0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(2015, 12, 30, 16, 25));
QTest::newRow("month-1") << "a=b;expires=wed 16:25pm December 2015 30" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(2031, 11, 11), QTime(16, 25, 0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(2031, 11, 11, 16, 25));
QTest::newRow("month-2") << "a=b;expires=16:25 11 31 11" << cookie;
// The very ambiguous cases
// Matching Firefox's behavior of guessing month, day, year in those cases
- cookie.setExpirationDate(QDateTime(QDate(2013, 10, 2), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(2013, 10, 2));
QTest::newRow("ambiguousd-0") << "a=b;expires=10/2/13 0:0" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(2013, 2, 10), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(2013, 2, 10));
QTest::newRow("ambiguousd-1") << "a=b;expires=2/10/13 0:0" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(2010, 2, 3), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(2010, 2, 3));
QTest::newRow("ambiguousd-2") << "a=b;expires=2/3/10 0:0" << cookie;
// FYI If you try these in Firefox it won't set a cookie for the following two string
// because 03 is turned into the year at which point it is expired
- cookie.setExpirationDate(QDateTime(QDate(2003, 2, 10), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(2003, 2, 10));
QTest::newRow("ambiguousd-3") << "a=b;expires=2/10/3 0:0" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(2003, 10, 2), QTime(0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(2003, 10, 2));
QTest::newRow("ambiguousd-4") << "a=b;expires=10/2/3 0:0" << cookie;
// These are the cookies that firefox's source says it can parse
- cookie.setExpirationDate(QDateTime(QDate(1989, 4, 14), QTime(3, 20, 0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 4, 14, 3, 20));
QTest::newRow("firefox-0") << "a=b;expires=14 Apr 89 03:20" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 4, 14), QTime(3, 20, 0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 4, 14, 3, 20));
QTest::newRow("firefox-1") << "a=b;expires=14 Apr 89 03:20 GMT" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 3, 17), QTime(4, 1, 33, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 3, 17, 4, 1, 33));
QTest::newRow("firefox-2") << "a=b;expires=Fri, 17 Mar 89 4:01:33" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 3, 17), QTime(4, 1, 0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 3, 17, 4, 1));
QTest::newRow("firefox-3") << "a=b;expires=Fri, 17 Mar 89 4:01 GMT" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 16), QTime(16-8, 12, 0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 16, 16-8, 12));
QTest::newRow("firefox-4") << "a=b;expires=Mon Jan 16 16:12 PDT 1989" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1989, 1, 16), QTime(17, 42, 0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1989, 1, 16, 17, 42));
QTest::newRow("firefox-5") << "a=b;expires=Mon Jan 16 16:12 +0130 1989" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1992, 5, 6), QTime(16-9, 41, 0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1992, 5, 6, 16-9, 41));
QTest::newRow("firefox-6") << "a=b;expires=6 May 1992 16:41-JST (Wednesday)" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1993, 8, 22), QTime(10, 59, 12, 82), Qt::UTC));
+ cookie.setExpirationDate(utc(1993, 8, 22, 10, 59, 12, 82));
QTest::newRow("firefox-7") << "a=b;expires=22-AUG-1993 10:59:12.82" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1993, 8, 22), QTime(22, 59, 0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1993, 8, 22, 22, 59));
QTest::newRow("firefox-8") << "a=b;expires=22-AUG-1993 10:59pm" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1993, 8, 22), QTime(12, 59, 0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1993, 8, 22, 12, 59));
QTest::newRow("firefox-9") << "a=b;expires=22-AUG-1993 12:59am" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1993, 8, 22), QTime(12, 59, 0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1993, 8, 22, 12, 59));
QTest::newRow("firefox-10") << "a=b;expires=22-AUG-1993 12:59 PM" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1995, 8, 4), QTime(15, 54, 0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1995, 8, 4, 15, 54));
QTest::newRow("firefox-11") << "a=b;expires=Friday, August 04, 1995 3:54 PM" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1995, 6, 21), QTime(16, 24, 34, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1995, 6, 21, 16, 24, 34));
QTest::newRow("firefox-12") << "a=b;expires=06/21/95 04:24:34 PM" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1995, 6, 20), QTime(21, 7, 0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1995, 6, 20, 21, 7));
QTest::newRow("firefox-13") << "a=b;expires=20/06/95 21:07" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1995, 6, 8), QTime(19-5, 32, 48, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(1995, 6, 8, 19-5, 32, 48));
QTest::newRow("firefox-14") << "a=b;expires=95-06-08 19:32:48 EDT" << cookie;
// Edge cases caught by fuzzing
// These are about the default cause creates dates that don't exits
- cookie.setExpirationDate(QDateTime(QDate(2030, 2, 25), QTime(1, 1, 0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(2030, 2, 25, 1, 1));
QTest::newRow("fuzz-0") << "a=b; expires=30 -000002 1:1 25;" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(2031, 11, 20), QTime(1, 1, 0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(2031, 11, 20, 1, 1));
QTest::newRow("fuzz-1") << "a=b; expires=31 11 20 1:1;" << cookie;
// April only has 30 days
- cookie.setExpirationDate(QDateTime(QDate(2031, 4, 30), QTime(1, 1, 0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(2031, 4, 30, 1, 1));
QTest::newRow("fuzz-2") << "a=b; expires=31 30 4 1:1" << cookie;
// 9 must be the month so 31 can't be the day
- cookie.setExpirationDate(QDateTime(QDate(2031, 9, 21), QTime(1, 1, 0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(2031, 9, 21, 1, 1));
QTest::newRow("fuzz-3") << "a=b; expires=31 21 9 1:1" << cookie;
// Year is known, then fallback to defaults of filling in month and day
- cookie.setExpirationDate(QDateTime(QDate(2031, 11, 1), QTime(1, 1, 0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(2031, 11, 1, 1, 1));
QTest::newRow("fuzz-4") << "a=b; expires=31 11 01 1:1" << cookie;
// 2 must be the month so 30 can't be the day
- cookie.setExpirationDate(QDateTime(QDate(2030, 2, 20), QTime(1, 1, 0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(2030, 2, 20, 1, 1));
QTest::newRow("fuzz-5") << "a=b; expires=30 02 20 1:1" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(2021, 12, 22), QTime(1, 1, 0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(2021, 12, 22, 1, 1));
QTest::newRow("fuzz-6") << "a=b; expires=2021 12 22 1:1" << cookie;
- cookie.setExpirationDate(QDateTime(QDate(2029, 2, 23), QTime(1, 1, 0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(2029, 2, 23, 1, 1));
QTest::newRow("fuzz-7") << "a=b; expires=29 23 Feb 1:1" << cookie;
// 11 and 6 don't have 31 days
- cookie.setExpirationDate(QDateTime(QDate(2031, 11, 06), QTime(1, 1, 0, 0), Qt::UTC));
+ cookie.setExpirationDate(utc(2031, 11, 06, 1, 1));
QTest::newRow("fuzz-8") << "a=b; expires=31 11 06 1:1" << cookie;
// two-digit years:
// from 70 until 99, we assume 20th century
- cookie.setExpirationDate(QDateTime(QDate(1999, 11, 9), QTime(23, 12, 40), Qt::UTC));
+ cookie.setExpirationDate(utc(1999, 11, 9, 23, 12, 40));
QTest::newRow("expiration-2digit1") << "a=b; expires=Wednesday, 09-Nov-99 23:12:40 GMT " << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1970, 1, 1), QTime(23, 12, 40), Qt::UTC));
+ cookie.setExpirationDate(utc(1970, 1, 1, 23, 12, 40));
QTest::newRow("expiration-2digit2") << "a=b; expires=Thursday, 01-Jan-70 23:12:40 GMT " << cookie;
// from 00 until 69, we assume 21st century
- cookie.setExpirationDate(QDateTime(QDate(2000, 1, 1), QTime(23, 12, 40), Qt::UTC));
+ cookie.setExpirationDate(utc(2000, 1, 1, 23, 12, 40));
QTest::newRow("expiration-2digit3") << "a=b; expires=Saturday, 01-Jan-00 23:12:40 GMT " << cookie;
- cookie.setExpirationDate(QDateTime(QDate(2020, 1, 1), QTime(23, 12, 40), Qt::UTC));
+ cookie.setExpirationDate(utc(2020, 1, 1, 23, 12, 40));
QTest::newRow("expiration-2digit4") << "a=b; expires=Wednesday, 01-Jan-20 23:12:40 GMT " << cookie;
- cookie.setExpirationDate(QDateTime(QDate(2069, 1, 1), QTime(23, 12, 40), Qt::UTC));
+ cookie.setExpirationDate(utc(2069, 1, 1, 23, 12, 40));
QTest::newRow("expiration-2digit5") << "a=b; expires=Wednesday, 01-Jan-69 23:12:40 GMT " << cookie;
- cookie.setExpirationDate(QDateTime(QDate(1999, 11, 9), QTime(23, 12, 40), Qt::UTC));
+ cookie.setExpirationDate(utc(1999, 11, 9, 23, 12, 40));
cookie.setPath("/");
QTest::newRow("expires+path") << "a=b; expires=Wed, 09-Nov-1999 23:12:40 GMT; path=/" << cookie;
@@ -519,7 +527,7 @@ void tst_QNetworkCookie::parseSingleCookie_data()
// cookies obtained from the network:
cookie = QNetworkCookie("__siteid", "1");
cookie.setPath("/");
- cookie.setExpirationDate(QDateTime(QDate(9999, 12, 31), QTime(23, 59, 59), Qt::UTC));
+ cookie.setExpirationDate(utc(9999, 12, 31, 23, 59, 59));
QTest::newRow("network2") << "__siteid=1; expires=Fri, 31-Dec-9999 23:59:59 GMT; path=/" << cookie;
cookie = QNetworkCookie("YM.LC", "v=2&m=9993_262838_159_1558_1063_0_5649_4012_3776161073,9426_260205_549_1295_1336_0_5141_4738_3922731647,6733_258196_952_1364_643_0_3560_-1_0,3677_237633_1294_1294_19267_0_3244_29483_4102206176,1315_235149_1693_1541_941_0_3224_1691_1861378060,1858_214311_2100_1298_19538_0_2873_30900_716411652,6258_212007_2506_1285_1017_0_2868_3606_4288540264,3743_207884_2895_1362_2759_0_2545_7114_3388520216,2654_205253_3257_1297_1332_0_2504_4682_3048534803,1891_184881_3660_1291_19079_0_978_29178_2592538685&f=1&n=20&s=date&o=down&e=1196548712&b=Inbox&u=removed");
@@ -529,13 +537,13 @@ void tst_QNetworkCookie::parseSingleCookie_data()
cookie = QNetworkCookie("__ac", "\"c2hhdXNtYW46U2FTYW80Wm8%3D\"");
cookie.setPath("/");
- cookie.setExpirationDate(QDateTime(QDate(2008, 8, 30), QTime(20, 21, 49), Qt::UTC));
+ cookie.setExpirationDate(utc(2008, 8, 30, 20, 21, 49));
QTest::newRow("network4") << "__ac=\"c2hhdXNtYW46U2FTYW80Wm8%3D\"; Path=/; Expires=Sat, 30 Aug 2008 20:21:49 +0000" << cookie;
// linkedin.com sends cookies in quotes and expects the cookie in quotes
cookie = QNetworkCookie("leo_auth_token", "\"GST:UroVXaxYA3sVSkoVjMNH9bj4dZxVzK2yekgrAUxMfUsyLTNyPjoP60:1298974875:b675566ae32ab36d7a708c0efbf446a5c22b9fca\"");
cookie.setPath("/");
- cookie.setExpirationDate(QDateTime(QDate(2011, 3, 1), QTime(10, 51, 14), Qt::UTC));
+ cookie.setExpirationDate(utc(2011, 3, 1, 10, 51, 14));
QTest::newRow("network5") << "leo_auth_token=\"GST:UroVXaxYA3sVSkoVjMNH9bj4dZxVzK2yekgrAUxMfUsyLTNyPjoP60:1298974875:b675566ae32ab36d7a708c0efbf446a5c22b9fca\"; Version=1; Max-Age=1799; Expires=Tue, 01-Mar-2011 10:51:14 GMT; Path=/" << cookie;
// cookie containing JSON data (illegal for server, client should accept) - QTBUG-26002
@@ -553,11 +561,11 @@ void tst_QNetworkCookie::parseSingleCookie()
QList<QNetworkCookie> result = QNetworkCookie::parseCookies(cookieString.toUtf8());
//QEXPECT_FAIL("network2", "QDateTime parsing problem: the date is beyond year 8000", Abort);
- QCOMPARE(result.count(), 1);
+ QCOMPARE(result.size(), 1);
QCOMPARE(result.at(0), expectedCookie);
result = QNetworkCookie::parseCookies(result.at(0).toRawForm());
- QCOMPARE(result.count(), 1);
+ QCOMPARE(result.size(), 1);
// Drop any millisecond information, if there's any
QDateTime dt = expectedCookie.expirationDate();
@@ -611,7 +619,7 @@ void tst_QNetworkCookie::parseMultipleCookies_data()
cookie = QNetworkCookie("id", "51706646077999719");
cookie.setDomain(".bluestreak.com");
cookie.setPath("/");
- cookie.setExpirationDate(QDateTime(QDate(2017, 12, 05), QTime(9, 11, 7), Qt::UTC));
+ cookie.setExpirationDate(QDateTime(QDate(2017, 12, 05), QTime(9, 11, 7), QTimeZone::UTC));
list << cookie;
cookie.setName("bb");
cookie.setValue("\\\"K14144t\\\"_AAQ\\\"ototrK_A_ttot44AQ4KwoRQtoto|");
@@ -630,8 +638,8 @@ void tst_QNetworkCookie::parseMultipleCookies_data()
cookieB.setValue("d");
// NewLine
- cookieA.setExpirationDate(QDateTime(QDate(2009, 3, 10), QTime(7, 0, 0, 0), Qt::UTC));
- cookieB.setExpirationDate(QDateTime(QDate(2009, 3, 20), QTime(7, 0, 0, 0), Qt::UTC));
+ cookieA.setExpirationDate(QDateTime(QDate(2009, 3, 10), QTime(7, 0), QTimeZone::UTC));
+ cookieB.setExpirationDate(QDateTime(QDate(2009, 3, 20), QTime(7, 0), QTimeZone::UTC));
list = QList<QNetworkCookie>() << cookieA << cookieB;
QTest::newRow("real-0") << "a=b; expires=Tue Mar 10 07:00:00 2009 GMT\nc=d; expires=Fri Mar 20 07:00:00 2009 GMT" << list;
QTest::newRow("real-1") << "a=b; expires=Tue Mar 10 07:00:00 2009 GMT\n\nc=d; expires=Fri Mar 20 07:00:00 2009 GMT" << list;
diff --git a/tests/auto/network/access/qnetworkcookiejar/CMakeLists.txt b/tests/auto/network/access/qnetworkcookiejar/CMakeLists.txt
index ddc8290a17..0d74a1d84d 100644
--- a/tests/auto/network/access/qnetworkcookiejar/CMakeLists.txt
+++ b/tests/auto/network/access/qnetworkcookiejar/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qnetworkcookiejar.pro.
-
#####################################################################
## tst_qnetworkcookiejar Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qnetworkcookiejar LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
list(APPEND test_data "parser.json" "testdata/publicsuffix/public_suffix_list.dafsa")
diff --git a/tests/auto/network/access/qnetworkcookiejar/testdata/publicsuffix/public_suffix_list.dafsa b/tests/auto/network/access/qnetworkcookiejar/testdata/publicsuffix/public_suffix_list.dafsa
index 2302ad2f97..2bd4ca05f3 100644
--- a/tests/auto/network/access/qnetworkcookiejar/testdata/publicsuffix/public_suffix_list.dafsa
+++ b/tests/auto/network/access/qnetworkcookiejar/testdata/publicsuffix/public_suffix_list.dafsa
Binary files differ
diff --git a/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp b/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp
index ddce612684..9460060dbf 100644
--- a/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp
+++ b/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp
@@ -1,6 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
#include <QtCore/QJsonArray>
@@ -14,6 +13,8 @@
#include "private/qtldurl_p.h"
#endif
+#include <memory>
+
class tst_QNetworkCookieJar: public QObject
{
Q_OBJECT
@@ -235,7 +236,7 @@ void tst_QNetworkCookieJar::setCookiesFromUrl()
QFETCH(QList<QNetworkCookie>, preset);
QFETCH(QNetworkCookie, newCookie);
QFETCH(QString, referenceUrl);
- QFETCH(QList<QNetworkCookie>, expectedResult);
+ QFETCH(const QList<QNetworkCookie>, expectedResult);
QFETCH(bool, setCookies);
QList<QNetworkCookie> cookieList;
@@ -245,11 +246,11 @@ void tst_QNetworkCookieJar::setCookiesFromUrl()
QCOMPARE(jar.setCookiesFromUrl(cookieList, referenceUrl), setCookies);
QList<QNetworkCookie> result = jar.allCookies();
- foreach (QNetworkCookie cookie, expectedResult) {
+ for (const QNetworkCookie &cookie : expectedResult) {
QVERIFY2(result.contains(cookie), cookie.toRawForm());
result.removeAll(cookie);
}
- QVERIFY2(result.isEmpty(), QTest::toString(result));
+ QVERIFY2(result.isEmpty(), std::unique_ptr<char[]>(QTest::toString(result)).get());
}
void tst_QNetworkCookieJar::cookiesForUrl_data()
@@ -408,13 +409,11 @@ void tst_QNetworkCookieJar::effectiveTLDs_data()
QTest::newRow("yes1") << "com" << true;
QTest::newRow("yes2") << "de" << true;
- QTest::newRow("yes3") << "ulm.museum" << true;
QTest::newRow("yes4") << "krodsherad.no" << true;
QTest::newRow("yes5") << "1.bg" << true;
QTest::newRow("yes6") << "com.cn" << true;
QTest::newRow("yes7") << "org.ws" << true;
QTest::newRow("yes8") << "co.uk" << true;
- QTest::newRow("yes9") << "wallonie.museum" << true;
QTest::newRow("yes10") << "hk.com" << true;
QTest::newRow("yes11") << "hk.org" << true;
@@ -431,33 +430,23 @@ void tst_QNetworkCookieJar::effectiveTLDs_data()
QTest::newRow("no11") << "mosreg.ru" << false;
const char16_t s1[] = {0x74, 0x72, 0x61, 0x6e, 0xf8, 0x79, 0x2e, 0x6e, 0x6f, 0x00}; // xn--trany-yua.no
- const char16_t s2[] = {0x5d9, 0x5e8, 0x5d5, 0x5e9, 0x5dc, 0x5d9, 0x5dd, 0x2e, 0x6d, 0x75, 0x73, 0x65, 0x75, 0x6d, 0x00}; // xn--9dbhblg6di.museum
const char16_t s3[] = {0x7ec4, 0x7e54, 0x2e, 0x68, 0x6b, 0x00}; // xn--mk0axi.hk
const char16_t s4[] = {0x7f51, 0x7edc, 0x2e, 0x63, 0x6e, 0x00}; // xn--io0a7i.cn
const char16_t s5[] = {0x72, 0xe1, 0x68, 0x6b, 0x6b, 0x65, 0x72, 0xe1, 0x76, 0x6a, 0x75, 0x2e, 0x6e, 0x6f, 0x00}; // xn--rhkkervju-01af.no
const char16_t s6[] = {0xb9a, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbaa, 0xbcd, 0xbaa, 0xbc2, 0xbb0, 0xbcd, 0x00}; // xn--clchc0ea0b2g2a9gcd
const char16_t s7[] = {0x627, 0x644, 0x627, 0x631, 0x62f, 0x646, 0x00}; // xn--mgbayh7gpa
- const char16_t s8[] = {0x63, 0x6f, 0x72, 0x72, 0x65, 0x69, 0x6f, 0x73, 0x2d, 0x65, 0x2d, 0x74, 0x65, 0x6c, 0x65,
- 0x63, 0x6f, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0xe7, 0xf5, 0x65, 0x73, 0x2e, 0x6d, 0x75,
- 0x73, 0x65, 0x75, 0x6d, 0x00}; // xn--correios-e-telecomunicaes-ghc29a.museum
QTest::newRow("yes-specialchars1") << QString::fromUtf16(s1) << true;
- QTest::newRow("yes-specialchars2") << QString::fromUtf16(s2) << true;
QTest::newRow("yes-specialchars3") << QString::fromUtf16(s3) << true;
QTest::newRow("yes-specialchars4") << QString::fromUtf16(s4) << true;
QTest::newRow("yes-specialchars5") << QString::fromUtf16(s5) << true;
QTest::newRow("yes-specialchars6") << QString::fromUtf16(s6) << true;
QTest::newRow("yes-specialchars7") << QString::fromUtf16(s7) << true;
- QTest::newRow("yes-specialchars8") << QString::fromUtf16(s8) << true;
QTest::newRow("no-specialchars1") << QString::fromUtf16(s1).prepend("something") << false;
- QTest::newRow("no-specialchars2") << QString::fromUtf16(s2).prepend(QString::fromUtf16(s2)) << false;
- QTest::newRow("no-specialchars2.5") << QString::fromUtf16(s2).prepend("whatever") << false;
QTest::newRow("no-specialchars3") << QString::fromUtf16(s3).prepend("foo") << false;
QTest::newRow("no-specialchars4") << QString::fromUtf16(s4).prepend("bar") << false;
- QTest::newRow("no-specialchars5") << QString::fromUtf16(s5).prepend(QString::fromUtf16(s2)) << false;
QTest::newRow("no-specialchars6") << QString::fromUtf16(s6).prepend(QLatin1Char('.') + QString::fromUtf16(s6)) << false;
QTest::newRow("no-specialchars7") << QString::fromUtf16(s7).prepend("bla") << false;
- QTest::newRow("no-specialchars8") << QString::fromUtf16(s8).append("foo") << false;
QTest::newRow("exception1") << "pref.iwate.jp" << false;
QTest::newRow("exception2") << "omanpost.om" << false;
@@ -528,7 +517,7 @@ void tst_QNetworkCookieJar::rfc6265_data()
void tst_QNetworkCookieJar::rfc6265()
{
- QFETCH(QStringList, received);
+ QFETCH(const QStringList, received);
QFETCH(QList<QNetworkCookie>, sent);
QFETCH(QString, sentTo);
@@ -539,16 +528,16 @@ void tst_QNetworkCookieJar::rfc6265()
QNetworkCookieJar jar;
QList<QNetworkCookie> receivedCookies;
- foreach (const QString &cookieLine, received)
+ for (const QString &cookieLine : received)
receivedCookies.append(QNetworkCookie::parseCookies(cookieLine.toUtf8()));
jar.setCookiesFromUrl(receivedCookies, receivedUrl);
QList<QNetworkCookie> cookiesToSend = jar.cookiesForUrl(sentUrl);
//compare cookies only using name/value, as the metadata isn't sent over the network
- QCOMPARE(cookiesToSend.count(), sent.count());
+ QCOMPARE(cookiesToSend.size(), sent.size());
bool ok = true;
- for (int i = 0; i < cookiesToSend.count(); i++) {
+ for (int i = 0; i < cookiesToSend.size(); i++) {
if (cookiesToSend.at(i).name() != sent.at(i).name()) {
ok = false;
break;
diff --git a/tests/auto/network/access/qnetworkdiskcache/CMakeLists.txt b/tests/auto/network/access/qnetworkdiskcache/CMakeLists.txt
index 235f486a8e..023868f57e 100644
--- a/tests/auto/network/access/qnetworkdiskcache/CMakeLists.txt
+++ b/tests/auto/network/access/qnetworkdiskcache/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qnetworkdiskcache.pro.
-
#####################################################################
## tst_qnetworkdiskcache Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qnetworkdiskcache LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qnetworkdiskcache
SOURCES
tst_qnetworkdiskcache.cpp
diff --git a/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp b/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp
index fec66ebbd0..ec32c780cd 100644
--- a/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp
+++ b/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtNetwork/QtNetwork>
#include <QTest>
@@ -12,7 +12,7 @@
#define EXAMPLE_URL "http://user:pass@localhost:4/#foo"
#define EXAMPLE_URL2 "http://user:pass@localhost:4/bar"
//cached objects are organized into these many subdirs
-#define NUM_SUBDIRECTORIES 16
+#define NUM_SUBDIRECTORIES 15
class tst_QNetworkDiskCache : public QObject
{
@@ -278,17 +278,17 @@ void tst_QNetworkDiskCache::clear()
QVERIFY(cache.cacheSize() > qint64(0));
QString cacheDirectory = cache.cacheDirectory();
- QCOMPARE(countFiles(cacheDirectory).count(), NUM_SUBDIRECTORIES + 3);
+ QCOMPARE(countFiles(cacheDirectory).size(), NUM_SUBDIRECTORIES + 3);
cache.clear();
- QCOMPARE(countFiles(cacheDirectory).count(), NUM_SUBDIRECTORIES + 2);
+ QCOMPARE(countFiles(cacheDirectory).size(), NUM_SUBDIRECTORIES + 2);
// 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);
+ QCOMPARE(countFiles(cacheDirectory).size(), NUM_SUBDIRECTORIES + 3);
cache.clear();
- QCOMPARE(countFiles(cacheDirectory).count(), NUM_SUBDIRECTORIES + 3);
+ QCOMPARE(countFiles(cacheDirectory).size(), NUM_SUBDIRECTORIES + 3);
}
}
@@ -355,9 +355,9 @@ void tst_QNetworkDiskCache::remove()
QUrl url(EXAMPLE_URL);
cache.setupWithOne(tempDir.path(), url);
QString cacheDirectory = cache.cacheDirectory();
- QCOMPARE(countFiles(cacheDirectory).count(), NUM_SUBDIRECTORIES + 3);
+ QCOMPARE(countFiles(cacheDirectory).size(), NUM_SUBDIRECTORIES + 3);
cache.remove(url);
- QCOMPARE(countFiles(cacheDirectory).count(), NUM_SUBDIRECTORIES + 2);
+ QCOMPARE(countFiles(cacheDirectory).size(), NUM_SUBDIRECTORIES + 2);
}
void tst_QNetworkDiskCache::accessAfterRemove() // QTBUG-17400
@@ -476,9 +476,9 @@ void tst_QNetworkDiskCache::fileMetaData()
url.setFragment(QString());
QString cacheDirectory = cache.cacheDirectory();
- QStringList list = countFiles(cacheDirectory);
- QCOMPARE(list.count(), NUM_SUBDIRECTORIES + 3);
- foreach(QString fileName, list) {
+ const QStringList list = countFiles(cacheDirectory);
+ QCOMPARE(list.size(), NUM_SUBDIRECTORIES + 3);
+ for (const QString &fileName : list) {
QFileInfo info(fileName);
if (info.isFile()) {
QNetworkCacheMetaData metaData = cache.call_fileMetaData(fileName);
@@ -521,9 +521,9 @@ void tst_QNetworkDiskCache::expire()
}
QString cacheDirectory = cache.cacheDirectory();
- QStringList list = countFiles(cacheDirectory);
+ const QStringList list = countFiles(cacheDirectory);
QStringList cacheList;
- foreach(QString fileName, list) {
+ for (const QString &fileName : list) {
QFileInfo info(fileName);
if (info.isFile()) {
QNetworkCacheMetaData metaData = cache.call_fileMetaData(fileName);
@@ -531,7 +531,7 @@ void tst_QNetworkDiskCache::expire()
}
}
std::sort(cacheList.begin(), cacheList.end());
- for (int i = 0; i < cacheList.count(); ++i) {
+ for (int i = 0; i < cacheList.size(); ++i) {
QString fileName = cacheList[i];
QCOMPARE(fileName, QLatin1String("http://localhost:4/") + QString::number(i + 6));
}
@@ -569,11 +569,11 @@ void tst_QNetworkDiskCache::oldCacheVersionFile()
QVERIFY(!metaData.isValid());
QVERIFY(!QFile::exists(name));
} else {
- QStringList files = countFiles(cache.cacheDirectory());
- QCOMPARE(files.count(), NUM_SUBDIRECTORIES + 3);
+ const QStringList files = countFiles(cache.cacheDirectory());
+ QCOMPARE(files.size(), NUM_SUBDIRECTORIES + 3);
// find the file
QString cacheFile;
- foreach (QString file, files) {
+ for (const QString &file : files) {
QFileInfo info(file);
if (info.isFile())
cacheFile = file;
@@ -610,8 +610,8 @@ void tst_QNetworkDiskCache::streamVersion()
QString cacheFile;
// find the file
- QStringList files = countFiles(cache.cacheDirectory());
- foreach (const QString &file, files) {
+ const QStringList files = countFiles(cache.cacheDirectory());
+ for (const QString &file : files) {
QFileInfo info(file);
if (info.isFile()) {
cacheFile = file;
@@ -657,6 +657,7 @@ void tst_QNetworkDiskCache::streamVersion()
QIODevice *dataDevice = cache.data(url);
QVERIFY(dataDevice != 0);
QByteArray cachedData = dataDevice->readAll();
+ delete dataDevice;
QCOMPARE(cachedData, data);
}
}
@@ -693,8 +694,6 @@ public:
QNetworkDiskCache cache;
cache.setCacheDirectory(cachePath);
- int read = 0;
-
int i = 0;
for (; i < 5000; ++i) {
if (other && other->isFinished())
@@ -736,7 +735,7 @@ public:
if (d) {
QByteArray x = d->readAll();
if (x != longString && x != longString2) {
- qDebug() << x.length() << QString(x);
+ qDebug() << x.size() << QString(x);
gotMetaData = cache.metaData(url);
qDebug() << (gotMetaData.url().toString())
<< gotMetaData.lastModified()
@@ -745,7 +744,6 @@ public:
}
if (gotMetaData.isValid())
QVERIFY(x == longString || x == longString2);
- read++;
delete d;
}
}
@@ -753,9 +751,8 @@ public:
cache.remove(url);
if (QRandomGenerator::global()->bounded(5) == 1)
cache.clear();
- sleep(0);
+ sleep(std::chrono::seconds{0});
}
- //qDebug() << "read!" << read << i;
}
QDateTime dt;
diff --git a/tests/auto/network/access/qnetworkreply/CMakeLists.txt b/tests/auto/network/access/qnetworkreply/CMakeLists.txt
index 0ec53e24bd..9bfd90cd56 100644
--- a/tests/auto/network/access/qnetworkreply/CMakeLists.txt
+++ b/tests/auto/network/access/qnetworkreply/CMakeLists.txt
@@ -1,7 +1,11 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qnetworkreply.pro.
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qnetworkreply LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
add_subdirectory(echo)
add_subdirectory(test)
diff --git a/tests/auto/network/access/qnetworkreply/echo/CMakeLists.txt b/tests/auto/network/access/qnetworkreply/echo/CMakeLists.txt
index 63f5c0ebab..137b29110d 100644
--- a/tests/auto/network/access/qnetworkreply/echo/CMakeLists.txt
+++ b/tests/auto/network/access/qnetworkreply/echo/CMakeLists.txt
@@ -1,14 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from echo.pro.
-
#####################################################################
## echo Binary:
#####################################################################
qt_internal_add_executable(echo
- OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} # special case
+ OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
SOURCES
main.cpp
)
diff --git a/tests/auto/network/access/qnetworkreply/echo/main.cpp b/tests/auto/network/access/qnetworkreply/echo/main.cpp
index 770b7bc47b..b10eaa745c 100644
--- a/tests/auto/network/access/qnetworkreply/echo/main.cpp
+++ b/tests/auto/network/access/qnetworkreply/echo/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/QFile>
@@ -12,11 +12,13 @@ int main(int argc, char **)
}
QFile file;
- file.open(stdin, QFile::ReadWrite);
+ if (!file.open(stdin, QFile::ReadWrite))
+ return 1;
QByteArray data = file.readAll();
file.close();
- file.open(stdout, QFile::WriteOnly);
+ if (!file.open(stdout, QFile::WriteOnly))
+ return 1;
file.write(data);
file.close();
return 0;
diff --git a/tests/auto/network/access/qnetworkreply/test/CMakeLists.txt b/tests/auto/network/access/qnetworkreply/test/CMakeLists.txt
index d3f12a95df..fa353b2769 100644
--- a/tests/auto/network/access/qnetworkreply/test/CMakeLists.txt
+++ b/tests/auto/network/access/qnetworkreply/test/CMakeLists.txt
@@ -1,8 +1,6 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from test.pro.
-
#####################################################################
## tst_qnetworkreply Test:
#####################################################################
@@ -21,7 +19,7 @@ list(APPEND test_data "../index.html")
list(APPEND test_data "../smb-file.txt")
qt_internal_add_test(tst_qnetworkreply
- OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../" # special case
+ OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../"
SOURCES
../tst_qnetworkreply.cpp
../data/gzip.rcc.cpp
@@ -30,7 +28,8 @@ qt_internal_add_test(tst_qnetworkreply
Qt::CorePrivate
Qt::NetworkPrivate
TESTDATA ${test_data}
- QT_TEST_SERVER_LIST "vsftpd" "apache2" "ftp-proxy" "danted" "squid" # special case
+ QT_TEST_SERVER_LIST "vsftpd" "apache2" "ftp-proxy" "danted" "squid"
+ BUNDLE_ANDROID_OPENSSL_LIBS
)
add_dependencies(tst_qnetworkreply echo)
@@ -47,15 +46,3 @@ qt_internal_add_resource(tst_qnetworkreply "qnetworkreply"
FILES
${qnetworkreply_resource_files}
)
-
-
-#### Keys ignored in scope 1:.:.:test.pro:<TRUE>:
-# QT_FOR_CONFIG = "gui-private"
-# QT_TEST_SERVER_LIST = "vsftpd" "apache2" "ftp-proxy" "danted" "squid"
-# testcase.timeout = "600"
-
-## Scopes:
-#####################################################################
-
-#### Keys ignored in scope 2:.:.:test.pro:NOT ANDROID:
-# TEST_HELPER_INSTALLS = "../echo/echo"
diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
index e653ebf698..64e7716e0c 100644
--- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtNetwork/qtnetworkglobal.h>
@@ -16,24 +16,29 @@
#include <QBuffer>
#include <QMap>
-#include <QtCore/qlist.h>
-#include <QtCore/qset.h>
#include <QtCore/QCryptographicHash>
#include <QtCore/QDataStream>
-#include <QtCore/QUrl>
+#include <QtCore/QDateTime>
#include <QtCore/QEventLoop>
#include <QtCore/QElapsedTimer>
#include <QtCore/QFile>
+#include <QtCore/QList>
#include <QtCore/QRandomGenerator>
#include <QtCore/QRegularExpression>
#include <QtCore/QRegularExpressionMatch>
+#include <QtCore/QSet>
#include <QtCore/QSharedPointer>
#include <QtCore/QScopedPointer>
#include <QtCore/QTemporaryFile>
+#include <QtCore/QTimeZone>
+#include <QtCore/QUrl>
+
#include <QtNetwork/QTcpServer>
#include <QtNetwork/QTcpSocket>
+#if QT_CONFIG(localserver)
#include <QtNetwork/QLocalSocket>
#include <QtNetwork/QLocalServer>
+#endif
#include <QtNetwork/QHostInfo>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
@@ -41,13 +46,18 @@
#include <QtNetwork/QAbstractNetworkCache>
#include <QtNetwork/qauthenticator.h>
#include <QtNetwork/qnetworkaccessmanager.h>
+#if QT_CONFIG(networkdiskcache)
#include <QtNetwork/qnetworkdiskcache.h>
+#endif
#include <QtNetwork/qnetworkrequest.h>
#include <QtNetwork/qnetworkreply.h>
#include <QtNetwork/qnetworkcookie.h>
#include <QtNetwork/QNetworkCookieJar>
+#if QT_CONFIG(http)
#include <QtNetwork/QHttpPart>
#include <QtNetwork/QHttpMultiPart>
+#include <QtNetwork/QHttp1Configuration>
+#endif
#include <QtNetwork/QNetworkProxyQuery>
#if QT_CONFIG(ssl)
#include <QtNetwork/qsslerror.h>
@@ -64,6 +74,9 @@
Q_DECLARE_METATYPE(QSharedPointer<char>)
#endif
+#include <memory>
+#include <optional>
+
#ifdef Q_OS_UNIX
# include <sys/types.h>
# include <unistd.h> // for getuid()
@@ -84,6 +97,7 @@ Q_DECLARE_METATYPE(QNetworkProxyQuery)
typedef QSharedPointer<QNetworkReply> QNetworkReplyPtr;
using namespace Qt::StringLiterals;
+using namespace std::chrono_literals;
#if QT_CONFIG(ssl)
QT_BEGIN_NAMESPACE
@@ -121,7 +135,30 @@ class tst_QNetworkReply: public QObject
static QString tempRedirectReplyStr() {
QString s = "HTTP/1.1 307 Temporary Redirect\r\n"
- "Content-Type: text/plain\r\n"
+ "content-type: text/plain\r\n"
+ "location: %1\r\n"
+ "\r\n";
+ return s;
+ }
+ static QString movedReplyStr() {
+ QString s = "HTTP/1.1 301 Moved Permanently\r\n"
+ "content-type: text/plain\r\n"
+ "location: %1\r\n"
+ "\r\n";
+ return s;
+ }
+
+ static QString foundReplyStr() {
+ QString s = "HTTP/1.1 302 Found\r\n"
+ "content-type: text/plain\r\n"
+ "location: %1\r\n"
+ "\r\n";
+ return s;
+ }
+
+ static QString permRedirectReplyStr() {
+ QString s = "HTTP/1.1 308 Permanent Redirect\r\n"
+ "content-type: text/plain\r\n"
"location: %1\r\n"
"\r\n";
return s;
@@ -163,8 +200,10 @@ public:
~tst_QNetworkReply();
QString runSimpleRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &request,
QNetworkReplyPtr &reply, const QByteArray &data = QByteArray());
+#if QT_CONFIG(http)
QString runMultipartRequest(const QNetworkRequest &request, QNetworkReplyPtr &reply,
QHttpMultiPart *multiPart, const QByteArray &verb);
+#endif
QString runCustomRequest(const QNetworkRequest &request, QNetworkReplyPtr &reply,
const QByteArray &verb, QIODevice *data);
@@ -209,6 +248,12 @@ private Q_SLOTS:
void getFromFtpAfterError(); // QTBUG-40797
void getFromHttp_data();
void getFromHttp();
+ void getWithBodyFromHttp_data();
+ void getWithBodyFromHttp();
+ void getWithAndWithoutBodyFromHttp_data();
+ void getWithAndWithoutBodyFromHttp();
+ void getWithBodyRedirected_data();
+ void getWithBodyRedirected();
void getErrors_data();
void getErrors();
#if QT_CONFIG(networkproxy)
@@ -224,15 +269,23 @@ private Q_SLOTS:
void putToHttp();
void putToHttpSynchronous_data();
void putToHttpSynchronous();
+#if QT_CONFIG(http)
void putToHttpMultipart_data();
void putToHttpMultipart();
+#endif
+ void putWithoutBody();
+ void putWithoutBody_data();
void postToHttp_data();
void postToHttp();
void postToHttpSynchronous_data();
void postToHttpSynchronous();
+#if QT_CONFIG(http)
void postToHttpMultipart_data();
void postToHttpMultipart();
void multipartSkipIndices(); // QTBUG-32534
+#endif
+ void postWithoutBody_data();
+ void postWithoutBody();
#if QT_CONFIG(ssl)
void putToHttps_data();
void putToHttps();
@@ -285,8 +338,8 @@ private Q_SLOTS:
#endif
void ioGetFromHttpBrokenServer_data();
void ioGetFromHttpBrokenServer();
- void ioGetFromHttpStatus100_data();
- void ioGetFromHttpStatus100();
+ void ioGetFromHttpStatusInformational_data();
+ void ioGetFromHttpStatusInformational();
void ioGetFromHttpNoHeaders_data();
void ioGetFromHttpNoHeaders();
void ioGetFromHttpWithCache_data();
@@ -301,8 +354,10 @@ private Q_SLOTS:
void ioPutToFileFromFile();
void ioPutToFileFromSocket_data();
void ioPutToFileFromSocket();
+#if QT_CONFIG(localserver)
void ioPutToFileFromLocalSocket_data();
void ioPutToFileFromLocalSocket();
+#endif
void ioPutToFileFromProcess_data();
void ioPutToFileFromProcess();
void ioPutToFtpFromFile_data();
@@ -408,7 +463,9 @@ private Q_SLOTS:
void ioGetFromHttpWithoutContentLength();
void ioGetFromHttpBrokenChunkedEncoding();
+#if QT_CONFIG(http)
void qtbug12908compressedHttpReply();
+#endif
void compressedHttpReplyBrokenGzip();
void getFromUnreachableIp();
@@ -427,7 +484,9 @@ private Q_SLOTS:
void qtbug27161httpHeaderMayBeDamaged_data();
void qtbug27161httpHeaderMayBeDamaged();
+#if QT_CONFIG(networkdiskcache)
void qtbug28035browserDoesNotLoadQtProjectOrgCorrectly();
+#endif
void qtbug45581WrongReplyStatusCode();
@@ -443,6 +502,11 @@ private Q_SLOTS:
void varyingCacheExpiry_data();
void varyingCacheExpiry();
+#if QT_CONFIG(http)
+ void amountOfHttp1ConnectionsQtbug25280_data();
+ void amountOfHttp1ConnectionsQtbug25280();
+#endif
+
void dontInsertPartialContentIntoTheCache();
void httpUserAgent();
@@ -477,12 +541,16 @@ private Q_SLOTS:
void ioHttpCookiesDuringRedirect();
void ioHttpRedirect_data();
void ioHttpRedirect();
+#if QT_CONFIG(networkdiskcache)
void ioHttpRedirectWithCache();
+#endif
void ioHttpRedirectFromLocalToRemote();
void ioHttpRedirectPostPut_data();
void ioHttpRedirectPostPut();
+#if QT_CONFIG(http)
void ioHttpRedirectMultipartPost_data();
void ioHttpRedirectMultipartPost();
+#endif
void ioHttpRedirectDelete();
void ioHttpRedirectCustom();
void ioHttpRedirectWithUploadDevice_data();
@@ -496,16 +564,20 @@ private Q_SLOTS:
void autoDeleteReplies_data();
void autoDeleteReplies();
- void getWithTimeout();
- void postWithTimeout();
+#if QT_CONFIG(http) || defined (Q_OS_WASM)
+ void requestWithTimeout_data();
+ void requestWithTimeout();
+#endif
void moreActivitySignals_data();
void moreActivitySignals();
void contentEncoding_data();
void contentEncoding();
+#if QT_CONFIG(http)
void contentEncodingBigPayload_data();
void contentEncodingBigPayload();
+#endif
void cacheWithContentEncoding_data();
void cacheWithContentEncoding();
void downloadProgressWithContentEncoding_data();
@@ -516,6 +588,16 @@ private Q_SLOTS:
void notFoundWithCompression_data();
void notFoundWithCompression();
+#if QT_CONFIG(http)
+ void qhttpPartDebug_data();
+ void qhttpPartDebug();
+
+ void qtbug68821proxyError_data();
+ void qtbug68821proxyError();
+#endif
+
+ void abortAndError();
+
// NOTE: This test must be last!
void parentingRepliesToTheApp();
private:
@@ -600,7 +682,8 @@ public:
int totalConnections;
bool stopTransfer = false;
- bool hasContent = false;
+ bool checkedContentLength = false;
+ bool foundContentLength = false;
int contentRead = 0;
int contentLength = 0;
@@ -632,6 +715,7 @@ public:
{
contentLength = 0;
receivedData.clear();
+ foundContentLength = false;
}
protected:
@@ -688,8 +772,13 @@ private:
void parseContentLength()
{
- int index = receivedData.indexOf("Content-Length:");
- index += sizeof("Content-Length:") - 1;
+ int index = receivedData.indexOf("content-length:");
+ if (index == -1)
+ return;
+
+ foundContentLength = true;
+
+ index += sizeof("content-length:") - 1;
const auto end = std::find(receivedData.cbegin() + index, receivedData.cend(), '\r');
auto num = receivedData.mid(index, std::distance(receivedData.cbegin() + index, end));
bool ok;
@@ -729,12 +818,14 @@ public slots:
if (doubleEndlPos != -1) {
const int endOfHeader = doubleEndlPos + 4;
- hasContent = receivedData.startsWith("POST") || receivedData.startsWith("PUT")
- || receivedData.startsWith("CUSTOM_WITH_PAYLOAD");
- if (hasContent && contentLength == 0)
+ contentRead = receivedData.size() - endOfHeader;
+
+ if (!checkedContentLength) {
parseContentLength();
- contentRead = receivedData.length() - endOfHeader;
- if (hasContent && contentRead < contentLength)
+ checkedContentLength = true;
+ }
+
+ if (contentRead < contentLength)
return;
// multiple requests incoming. remove the bytes of the current one
@@ -835,7 +926,7 @@ public:
qint64 cacheSize() const override
{
qint64 total = 0;
- foreach (const CachedContent &entry, cache)
+ for (const auto &[_, entry] : cache.asKeyValueRange())
total += entry.second.size();
return total;
}
@@ -1379,6 +1470,7 @@ void tst_QNetworkReply::storeSslConfiguration()
}
#endif
+#if QT_CONFIG(http)
QString tst_QNetworkReply::runMultipartRequest(const QNetworkRequest &request,
QNetworkReplyPtr &reply,
QHttpMultiPart *multiPart,
@@ -1410,6 +1502,7 @@ QString tst_QNetworkReply::runMultipartRequest(const QNetworkRequest &request,
}
return QString();
}
+#endif
QString tst_QNetworkReply::runSimpleRequest(QNetworkAccessManager::Operation op,
const QNetworkRequest &request,
@@ -1460,11 +1553,11 @@ QString tst_QNetworkReply::runSimpleRequest(QNetworkAccessManager::Operation op,
while (!reply->isFinished()) {
QTimer::singleShot(20000, loop, SLOT(quit()));
code = loop->exec();
- if (count == spy.count() && !reply->isFinished()) {
+ if (count == spy.size() && !reply->isFinished()) {
code = Timeout;
break;
}
- count = spy.count();
+ count = spy.size();
}
delete loop;
loop = 0;
@@ -1530,11 +1623,11 @@ int tst_QNetworkReply::waitForFinish(QNetworkReplyPtr &reply)
QSignalSpy spy(reply.data(), SIGNAL(downloadProgress(qint64,qint64)));
while (!reply->isFinished()) {
QTimer::singleShot(5000, loop, SLOT(quit()));
- if (loop->exec() == Timeout && count == spy.count() && !reply->isFinished()) {
+ if (loop->exec() == Timeout && count == spy.size() && !reply->isFinished()) {
returnCode = Timeout;
break;
}
- count = spy.count();
+ count = spy.size();
}
delete loop;
loop = 0;
@@ -1562,8 +1655,10 @@ void tst_QNetworkReply::initTestCase()
testDataDir = QCoreApplication::applicationDirPath();
#if defined(QT_TEST_SERVER)
- QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::ftpServerName(), 21));
- QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::ftpProxyServerName(), 2121));
+ if (ftpSupported) {
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::ftpServerName(), 21));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::ftpProxyServerName(), 2121));
+ }
QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpServerName(), 80));
QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpServerName(), 443));
QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3128));
@@ -1976,6 +2071,253 @@ void tst_QNetworkReply::getFromHttp()
QCOMPARE(reply->readAll(), reference.readAll());
}
+void tst_QNetworkReply::getWithBodyFromHttp_data()
+{
+ QTest::addColumn<QByteArray>("dataFromClientToServer");
+ QTest::addColumn<bool>("useDevice");
+ QTest::newRow("with-bytearray") << QByteArray("Body 1") << false;
+ QTest::newRow("with-bytearray2") << QByteArray("Body 2") << false;
+ QTest::newRow("with-bytearray3") << QByteArray("Body 3") << false;
+ QTest::newRow("with-device") << QByteArray("Body 1") << true;
+ QTest::newRow("with-device2") << QByteArray("Body 2") << true;
+ QTest::newRow("with-device3") << QByteArray("Body 3") << true;
+}
+
+void tst_QNetworkReply::getWithBodyFromHttp()
+{
+ QFETCH(QByteArray, dataFromClientToServer);
+ QFETCH(bool, useDevice);
+
+ QBuffer buff;
+ buff.setData(dataFromClientToServer);
+ buff.open(QIODevice::ReadOnly);
+
+ QByteArray dataFromServerToClient = QByteArray("Long first line\r\nLong second line");
+ QByteArray httpResponse = QByteArray("HTTP/1.0 200 OK\r\nContent-Length: ");
+ httpResponse += QByteArray::number(dataFromServerToClient.size());
+ httpResponse += "\r\n\r\n";
+ httpResponse += dataFromServerToClient;
+
+ MiniHttpServer server(httpResponse);
+ server.doClose = true;
+
+ QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort())));
+ QNetworkReplyPtr reply;
+
+ if (useDevice)
+ reply.reset(manager.get(request, &buff));
+ else
+ reply.reset(manager.get(request, dataFromClientToServer));
+
+ QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply));
+ QCOMPARE(server.contentLength, dataFromClientToServer.size());
+ QCOMPARE(server.receivedData.right(dataFromClientToServer.size()), dataFromClientToServer);
+ QByteArray content = reply->readAll();
+ QCOMPARE(content, dataFromServerToClient);
+}
+
+void tst_QNetworkReply::getWithAndWithoutBodyFromHttp_data()
+{
+ QTest::addColumn<QByteArray>("dataFromClientToServer");
+ QTest::addColumn<bool>("alwaysCache");
+ QTest::addColumn<tst_QNetworkReply::RunSimpleRequestReturn>("requestReturn");
+ QTest::addColumn<bool>("useDevice");
+ QTest::newRow("with-bytearray") << QByteArray("Body 1") << false << Success << false;
+ QTest::newRow("with-bytearray2") << QByteArray("Body 2") << false << Success << false;
+ QTest::newRow("with-bytearray3") << QByteArray("Body 3") << false << Success << false;
+ QTest::newRow("with-bytearray-cache") << QByteArray("Body 1") << true << Failure << false;
+ QTest::newRow("with-bytearray-cache2") << QByteArray("Body 2") << true << Failure << false;
+ QTest::newRow("with-bytearray-cache3") << QByteArray("Body 3") << true << Failure << false;
+ QTest::newRow("with-device") << QByteArray("Body 1") << false << Success << true;
+ QTest::newRow("with-device2") << QByteArray("Body 2") << false << Success << true;
+ QTest::newRow("with-device3") << QByteArray("Body 3") << false << Success << true;
+ QTest::newRow("with-device-cache") << QByteArray("Body 1") << true << Failure << true;
+ QTest::newRow("with-device-cache2") << QByteArray("Body 2") << true << Failure << true;
+ QTest::newRow("with-device-cache3") << QByteArray("Body 3") << true << Failure << true;
+}
+
+void tst_QNetworkReply::getWithAndWithoutBodyFromHttp()
+{
+ QFETCH(QByteArray, dataFromClientToServer);
+ QFETCH(bool, alwaysCache);
+ QFETCH(tst_QNetworkReply::RunSimpleRequestReturn, requestReturn);
+ QFETCH(bool, useDevice);
+
+ QBuffer buff;
+ buff.setData(dataFromClientToServer);
+ buff.open(QIODevice::ReadOnly);
+
+ QNetworkAccessManager qnam;
+ MyMemoryCache *memoryCache = new MyMemoryCache(&qnam);
+ qnam.setCache(memoryCache);
+
+ const int sizeOfDataFromServerToClient =3;
+ QByteArray dataFromServerToClient1 = QByteArray("aaa");
+ QByteArray dataFromServerToClient2 = QByteArray("bbb");
+ QByteArray dataFromServerToClient3 = QByteArray("ccc");
+
+ QByteArray baseHttpResponse = QByteArray("HTTP/1.0 200 OK\r\nContent-Length: ");
+ baseHttpResponse += QByteArray::number(sizeOfDataFromServerToClient);
+ baseHttpResponse += "\r\n\r\n";
+
+ MiniHttpServer server(baseHttpResponse + dataFromServerToClient1);
+ server.doClose = true;
+
+ QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort())));
+
+ // Send request without body
+ QNetworkReplyPtr reply(manager.get(request));
+ QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply));
+ QByteArray content = reply->readAll();
+ QCOMPARE(content, dataFromServerToClient1);
+
+ if (alwaysCache) {
+ request.setAttribute(QNetworkRequest::CacheLoadControlAttribute,
+ QNetworkRequest::AlwaysCache);
+ }
+
+ server.dataToTransmit = baseHttpResponse + dataFromServerToClient2;
+
+ // Send request with body
+ QNetworkReplyPtr reply2;
+ if (useDevice)
+ reply2.reset(manager.get(request, &buff));
+ else
+ reply2.reset(manager.get(request, dataFromClientToServer));
+
+ QVERIFY2(waitForFinish(reply2) == requestReturn, msgWaitForFinished(reply2));
+ content = reply2->readAll();
+
+ if (alwaysCache)
+ QVERIFY(content.isEmpty());
+ else
+ QCOMPARE(content, dataFromServerToClient2);
+
+ QCOMPARE(reply2->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool(), false);
+
+ if (alwaysCache) {
+ request.setAttribute(QNetworkRequest::CacheLoadControlAttribute,
+ QNetworkRequest::PreferNetwork);
+ }
+
+ server.dataToTransmit = baseHttpResponse + dataFromServerToClient3;
+
+ // Send another request without a body
+ QNetworkReplyPtr reply3(manager.get(request));
+ QVERIFY2(waitForFinish(reply3) == Success, msgWaitForFinished(reply3));
+ content = reply3->readAll();
+ QCOMPARE(content, dataFromServerToClient3);
+ QCOMPARE(reply3->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool(), false);
+}
+
+void tst_QNetworkReply::getWithBodyRedirected_data()
+{
+ QTest::addColumn<QByteArray>("dataFromClientToServer");
+ QTest::addColumn<bool>("useDevice");
+ QTest::addColumn<int>("status");
+ QTest::newRow("with-bytearray - 301") << QByteArray("Body 1") << false << 301;
+ QTest::newRow("with-bytearray2 - 301") << QByteArray("Body 2") << false << 301;
+ QTest::newRow("with-bytearray3 - 301") << QByteArray("Body 3") << false << 301;
+ QTest::newRow("with-device - 301") << QByteArray("Body 1") << true << 301;
+ QTest::newRow("with-device2 - 301") << QByteArray("Body 2") << true << 301;
+ QTest::newRow("with-device3 - 301") << QByteArray("Body 3") << true << 301;
+ QTest::newRow("with-bytearray - 302") << QByteArray("Body 1") << false << 302;
+ QTest::newRow("with-bytearray2 - 302") << QByteArray("Body 2") << false << 302;
+ QTest::newRow("with-bytearray3 - 302") << QByteArray("Body 3") << false << 302;
+ QTest::newRow("with-device - 302") << QByteArray("Body 1") << true << 302;
+ QTest::newRow("with-device2 - 302") << QByteArray("Body 2") << true << 302;
+ QTest::newRow("with-device3 - 302") << QByteArray("Body 3") << true << 302;
+ QTest::newRow("with-bytearray - 307") << QByteArray("Body 1") << false << 307;
+ QTest::newRow("with-bytearray2 - 307") << QByteArray("Body 2") << false << 307;
+ QTest::newRow("with-bytearray3 - 307") << QByteArray("Body 3") << false << 307;
+ QTest::newRow("with-device - 307") << QByteArray("Body 1") << true << 307;
+ QTest::newRow("with-device2 - 307") << QByteArray("Body 2") << true << 307;
+ QTest::newRow("with-device3 - 307") << QByteArray("Body 3") << true << 307;
+ QTest::newRow("with-bytearray - 308") << QByteArray("Body 1") << false << 308;
+ QTest::newRow("with-bytearray2 - 308") << QByteArray("Body 2") << false << 308;
+ QTest::newRow("with-bytearray3 - 308") << QByteArray("Body 3") << false << 308;
+ QTest::newRow("with-device - 308") << QByteArray("Body 1") << true << 308;
+ QTest::newRow("with-device2 - 308") << QByteArray("Body 2") << true << 308;
+ QTest::newRow("with-device3 - 308") << QByteArray("Body 3") << true << 308;
+}
+
+void tst_QNetworkReply::getWithBodyRedirected()
+{
+ QFETCH(QByteArray, dataFromClientToServer);
+ QFETCH(bool, useDevice);
+ QFETCH(int, status);
+
+ QBuffer buff;
+ buff.setData(dataFromClientToServer);
+ buff.open(QIODevice::ReadOnly);
+
+ QUrl localhost = QUrl("http://localhost");
+
+ // Setup server to which the second server will redirect to
+ MiniHttpServer server2(httpEmpty200Response);
+
+ QUrl redirectUrl = QUrl(localhost);
+ redirectUrl.setPort(server2.serverPort());
+
+ QByteArray redirectReply;
+ switch (status) {
+ case 301: redirectReply =
+ foundReplyStr().arg(QString(redirectUrl.toEncoded())).toLatin1(); break;
+ case 302: redirectReply =
+ movedReplyStr().arg(QString(redirectUrl.toEncoded())).toLatin1(); break;
+ case 307: redirectReply =
+ tempRedirectReplyStr().arg(QString(redirectUrl.toEncoded())).toLatin1(); break;
+ case 308: redirectReply =
+ permRedirectReplyStr().arg(QString(redirectUrl.toEncoded())).toLatin1(); break;
+ default: QFAIL("Unexpected status code"); break;
+ }
+
+ // Setup redirect server
+ MiniHttpServer server(redirectReply);
+
+ localhost.setPort(server.serverPort());
+ QNetworkRequest request(localhost);
+ request.setAttribute(QNetworkRequest::RedirectPolicyAttribute,
+ QNetworkRequest::NoLessSafeRedirectPolicy);
+
+ QNetworkReplyPtr reply;
+ if (useDevice)
+ reply.reset(manager.get(request, &buff));
+ else
+ reply.reset(manager.get(request, dataFromClientToServer));
+
+ QSignalSpy redSpy(reply.data(), SIGNAL(redirected(QUrl)));
+ QSignalSpy finSpy(reply.data(), SIGNAL(finished()));
+
+ QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply));
+
+ // Redirected and finished should be emitted exactly once
+ QCOMPARE(redSpy.size(), 1);
+ QCOMPARE(finSpy.size(), 1);
+
+ // Original URL should not be changed after redirect
+ QCOMPARE(request.url(), localhost);
+
+ // Verify Redirect url
+ QList<QVariant> args = redSpy.takeFirst();
+ QCOMPARE(args.at(0).toUrl(), redirectUrl);
+
+ // Reply url is set to the redirect url
+ QCOMPARE(reply->url(), redirectUrl);
+ QCOMPARE(reply->error(), QNetworkReply::NoError);
+ QVERIFY(validateRedirectedResponseHeaders(reply));
+
+ // Verify that the message body has arrived to the server
+ if (status > 302) {
+ QVERIFY(server2.contentLength != 0);
+ QCOMPARE(server2.contentLength, dataFromClientToServer.size());
+ QCOMPARE(server2.receivedData.right(dataFromClientToServer.size()), dataFromClientToServer);
+ } else {
+ // In these cases the message body should not reach the server
+ QVERIFY(server2.contentLength == 0);
+ }
+}
+
#if QT_CONFIG(networkproxy)
void tst_QNetworkReply::headFromHttp_data()
{
@@ -1995,7 +2337,7 @@ void tst_QNetworkReply::headFromHttp_data()
QString httpServer = QtNetworkSettings::httpServerName();
//testing proxies, mainly for the 407 response from http proxy
- for (int i = 0; i < proxies.count(); ++i) {
+ for (int i = 0; i < proxies.size(); ++i) {
QTest::newRow("rfc" + proxies.at(i).tag)
<< rfcsize
<< QUrl("http://" + httpServer + "/qtest/rfc3252.txt")
@@ -2277,9 +2619,9 @@ void tst_QNetworkReply::putToFtp()
QSignalSpy spy(r, SIGNAL(downloadProgress(qint64,qint64)));
while (!r->isFinished()) {
QTestEventLoop::instance().enterLoop(10);
- if (count == spy.count() && !r->isFinished())
+ if (count == spy.size() && !r->isFinished())
break;
- count = spy.count();
+ count = spy.size();
}
QObject::disconnect(r, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
@@ -2394,6 +2736,48 @@ void tst_QNetworkReply::putToHttpSynchronous()
QCOMPARE(uploadedData, data);
}
+void tst_QNetworkReply::putWithoutBody_data()
+{
+ QTest::addColumn<bool>("client_data");
+
+ QTest::newRow("client_has_data") << true;
+ QTest::newRow("client_does_not_have_data") << false;
+}
+
+void tst_QNetworkReply::putWithoutBody()
+{
+ QFETCH(bool, client_data);
+
+ QBuffer buff;
+
+ if (client_data) {
+ buff.setData("Dummy data from client to server");
+ buff.open(QIODevice::ReadOnly);
+ }
+
+ QByteArray dataFromServerToClient = QByteArray("Some ridiculous dummy data");
+ QByteArray httpResponse = QByteArray("HTTP/1.0 200 OK\r\nContent-Length: ");
+ httpResponse += QByteArray::number(dataFromServerToClient.size());
+ httpResponse += "\r\n\r\n";
+ httpResponse += dataFromServerToClient;
+
+ MiniHttpServer server(httpResponse);
+ server.doClose = true;
+
+ QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort())));
+ request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
+
+ QNetworkReplyPtr reply;
+ if (client_data)
+ reply.reset(manager.put(request, &buff));
+ else
+ reply.reset(manager.put(request, nullptr));
+
+ QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply));
+ QCOMPARE(server.foundContentLength, client_data);
+}
+
+
void tst_QNetworkReply::postToHttp_data()
{
putToFile_data();
@@ -2404,7 +2788,7 @@ void tst_QNetworkReply::postToHttp()
QUrl url("http://" + QtNetworkSettings::httpServerName() + "/qtest/cgi-bin/md5sum.cgi");
QNetworkRequest request(url);
- request.setRawHeader("Content-Type", "application/octet-stream");
+ request.setRawHeader("content-type", "application/octet-stream");
QNetworkReplyPtr reply;
QFETCH(QByteArray, data);
@@ -2431,7 +2815,7 @@ void tst_QNetworkReply::postToHttpSynchronous()
QUrl url("http://" + QtNetworkSettings::httpServerName() + "/qtest/cgi-bin/md5sum.cgi");
QNetworkRequest request(url);
- request.setRawHeader("Content-Type", "application/octet-stream");
+ request.setRawHeader("content-type", "application/octet-stream");
request.setAttribute(
QNetworkRequest::SynchronousRequestAttribute,
@@ -2453,6 +2837,7 @@ void tst_QNetworkReply::postToHttpSynchronous()
QCOMPARE(uploadedData, md5sum.toHex());
}
+#if QT_CONFIG(http)
void tst_QNetworkReply::postToHttpMultipart_data()
{
QTest::addColumn<QUrl>("url");
@@ -2492,8 +2877,8 @@ void tst_QNetworkReply::postToHttpMultipart_data()
QHttpMultiPart *customMultiPart = new QHttpMultiPart;
customMultiPart->append(textPart);
- expectedData = "header: Content-Type, value: 'text/plain'\n"
- "header: Content-Disposition, value: 'form-data; name=\"text\"'\n"
+ expectedData = "header: content-type, value: 'text/plain'\n"
+ "header: content-disposition, value: 'form-data; name=\"text\"'\n"
"content: 7 bytes\n"
"\n";
QTest::newRow("text-custom") << url << customMultiPart << expectedData << QByteArray("custom");
@@ -2529,18 +2914,18 @@ void tst_QNetworkReply::postToHttpMultipart_data()
multiPart3->append(textPart);
multiPart3->append(textPart2);
multiPart3->append(textPart3);
- expectedData = "header: Content-Type, value: 'text/plain'\n"
- "header: Content-Disposition, value: 'form-data; name=\"text\"'\n"
+ expectedData = "header: content-type, value: 'text/plain'\n"
+ "header: content-disposition, value: 'form-data; name=\"text\"'\n"
"content: 7 bytes\n"
"\n"
- "header: Content-Type, value: 'text/plain'\n"
- "header: myRawHeader, value: 'myValue'\n"
- "header: Content-Disposition, value: 'form-data; name=\"text2\"'\n"
+ "header: content-type, value: 'text/plain'\n"
+ "header: myrawheader, value: 'myValue'\n"
+ "header: content-disposition, value: 'form-data; name=\"text2\"'\n"
"content: some more bytes\n"
"\n"
- "header: Content-Type, value: 'text/plain'\n"
- "header: Content-Disposition, value: 'form-data; name=\"text3\"'\n"
- "header: Content-Location, value: 'http://my.test.location.tld'\n"
+ "header: content-type, value: 'text/plain'\n"
+ "header: content-disposition, value: 'form-data; name=\"text3\"'\n"
+ "header: content-location, value: 'http://my.test.location.tld'\n"
"content: even more bytes\n\n";
QTest::newRow("text-text-text") << url << multiPart3 << expectedData << QByteArray("alternative");
@@ -2762,7 +3147,50 @@ void tst_QNetworkReply::multipartSkipIndices() // QTBUG-32534
}
multiPart->deleteLater();
}
+#endif
+
+void tst_QNetworkReply::postWithoutBody_data()
+{
+ QTest::addColumn<bool>("client_data");
+
+ QTest::newRow("client_has_data") << true;
+ QTest::newRow("client_does_not_have_data") << false;
+}
+
+void tst_QNetworkReply::postWithoutBody()
+{
+ QFETCH(bool, client_data);
+
+ QBuffer buff;
+
+ if (client_data) {
+ buff.setData("Dummy data from client to server");
+ buff.open(QIODevice::ReadOnly);
+ }
+
+ QByteArray dataFromServerToClient = QByteArray("Some ridiculous dummy data");
+ QByteArray httpResponse = QByteArray("HTTP/1.0 200 OK\r\nContent-Length: ");
+ httpResponse += QByteArray::number(dataFromServerToClient.size());
+ httpResponse += "\r\n\r\n";
+ httpResponse += dataFromServerToClient;
+ MiniHttpServer server(httpResponse);
+ server.doClose = true;
+
+ QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort())));
+ request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
+
+ QNetworkReplyPtr reply;
+ if (client_data)
+ reply.reset(manager.post(request, &buff));
+ else
+ reply.reset(manager.post(request, nullptr));
+
+ QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply));
+ QCOMPARE(server.foundContentLength, client_data);
+}
+
+#if QT_CONFIG(http)
void tst_QNetworkReply::putToHttpMultipart_data()
{
postToHttpMultipart_data();
@@ -2807,6 +3235,7 @@ void tst_QNetworkReply::putToHttpMultipart()
// QEXPECT_FAIL("nested", "the server does not understand nested multipart messages", Continue); // see above
QCOMPARE(replyData, expectedReplyData);
}
+#endif
#if QT_CONFIG(ssl)
void tst_QNetworkReply::putToHttps_data()
@@ -2918,7 +3347,7 @@ void tst_QNetworkReply::postToHttps()
QSslConfiguration conf;
conf.setCaCertificates(certs);
request.setSslConfiguration(conf);
- request.setRawHeader("Content-Type", "application/octet-stream");
+ request.setRawHeader("content-type", "application/octet-stream");
QNetworkReplyPtr reply;
QFETCH(QByteArray, data);
@@ -2952,7 +3381,7 @@ void tst_QNetworkReply::postToHttpsSynchronous()
QSslConfiguration conf;
conf.setCaCertificates(certs);
request.setSslConfiguration(conf);
- request.setRawHeader("Content-Type", "application/octet-stream");
+ request.setRawHeader("content-type", "application/octet-stream");
request.setAttribute(
QNetworkRequest::SynchronousRequestAttribute,
@@ -2974,6 +3403,7 @@ void tst_QNetworkReply::postToHttpsSynchronous()
QCOMPARE(uploadedData, md5sum.toHex());
}
+#if QT_CONFIG(http)
void tst_QNetworkReply::postToHttpsMultipart_data()
{
if (isSecureTransport)
@@ -3024,7 +3454,7 @@ void tst_QNetworkReply::postToHttpsMultipart()
expectedReplyData.prepend("content type: multipart/" + contentType + "; boundary=\"" + multiPart->boundary() + "\"\n");
QCOMPARE(replyData, expectedReplyData);
}
-
+#endif
#endif // QT_CONFIG(ssl)
void tst_QNetworkReply::deleteFromHttp_data()
@@ -3154,7 +3584,7 @@ void tst_QNetworkReply::connectToIPv6Address()
if (!QtNetworkSettings::hasIPv6())
QSKIP("system doesn't support ipv6!");
- QByteArray httpResponse = QByteArray("HTTP/1.0 200 OK\r\nContent-Length: ");
+ QByteArray httpResponse = QByteArray("HTTP/1.0 200 OK\r\ncontent-length: ");
httpResponse += QByteArray::number(dataToSend.size());
httpResponse += "\r\n\r\n";
httpResponse += dataToSend;
@@ -3169,7 +3599,7 @@ void tst_QNetworkReply::connectToIPv6Address()
QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply));
QByteArray content = reply->readAll();
//qDebug() << server.receivedData;
- QByteArray hostinfo = "\r\nHost: " + hostfield + ':' + QByteArray::number(server.serverPort()) + "\r\n";
+ QByteArray hostinfo = "\r\nhost: " + hostfield + ':' + QByteArray::number(server.serverPort()) + "\r\n";
QVERIFY(server.receivedData.contains(hostinfo));
QCOMPARE(content, dataToSend);
QCOMPARE(reply->url(), request.url());
@@ -3360,7 +3790,9 @@ void tst_QNetworkReply::ioGetFromFtp()
{
QFETCH(QString, fileName);
QFile reference(fileName);
- reference.open(QIODevice::ReadOnly); // will fail for bigfile
+ const bool ok = reference.open(QIODevice::ReadOnly); // will fail for bigfile
+ if (fileName != "bigfile")
+ QVERIFY(ok);
QNetworkRequest request("ftp://" + QtNetworkSettings::ftpServerName() + "/qtest/" + fileName);
QNetworkReplyPtr reply(manager.get(request));
@@ -3385,7 +3817,7 @@ void tst_QNetworkReply::ioGetFromFtpWithReuse()
QSKIP("FTP is not supported");
QString fileName = testDataDir + "/rfc3252.txt";
QFile reference(fileName);
- reference.open(QIODevice::ReadOnly);
+ QVERIFY(reference.open(QIODevice::ReadOnly));
QNetworkRequest request(QUrl("ftp://" + QtNetworkSettings::ftpServerName() + "/qtest/rfc3252.txt"));
@@ -3515,7 +3947,7 @@ void tst_QNetworkReply::ioGetFromHttpWithAuth_data()
QTest::addColumn<int>("expectedAuth");
QFile reference(testDataDir + "/rfc3252.txt");
- reference.open(QIODevice::ReadOnly);
+ QVERIFY(reference.open(QIODevice::ReadOnly));
QByteArray referenceData = reference.readAll();
QString httpServer = QtNetworkSettings::httpServerName();
QTest::newRow("basic")
@@ -3589,7 +4021,7 @@ void tst_QNetworkReply::ioGetFromHttpWithAuth()
QCOMPARE(reader1.data, expectedData);
QCOMPARE(reader2.data, expectedData);
- QCOMPARE(authspy.count(), (expectedAuth ? 1 : 0));
+ QCOMPARE(authspy.size(), (expectedAuth ? 1 : 0));
expectedAuth = qMax(0, expectedAuth - 1);
}
@@ -3610,7 +4042,7 @@ void tst_QNetworkReply::ioGetFromHttpWithAuth()
QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
QCOMPARE(reader.data, expectedData);
- QCOMPARE(authspy.count(), (expectedAuth ? 1 : 0));
+ QCOMPARE(authspy.size(), (expectedAuth ? 1 : 0));
expectedAuth = qMax(0, expectedAuth - 1);
}
@@ -3627,7 +4059,7 @@ void tst_QNetworkReply::ioGetFromHttpWithAuth()
// bad credentials in a synchronous request should just fail
QCOMPARE(replySync->error(), QNetworkReply::AuthenticationRequiredError);
} else {
- QCOMPARE(authspy.count(), 0);
+ QCOMPARE(authspy.size(), 0);
// we cannot use a data reader here, since that connects to the readyRead signal,
// just use readAll()
@@ -3653,7 +4085,7 @@ void tst_QNetworkReply::ioGetFromHttpWithAuth()
// bad credentials in a synchronous request should just fail
QCOMPARE(replySync->error(), QNetworkReply::AuthenticationRequiredError);
} else {
- QCOMPARE(authspy.count(), 0);
+ QCOMPARE(authspy.size(), 0);
// we cannot use a data reader here, since that connects to the readyRead signal,
// just use readAll()
@@ -3679,7 +4111,7 @@ void tst_QNetworkReply::ioGetFromHttpWithAuthSynchronous()
QNetworkReplyPtr replySync(manager.get(request));
QVERIFY(replySync->isFinished()); // synchronous
QCOMPARE(replySync->error(), QNetworkReply::AuthenticationRequiredError);
- QCOMPARE(authspy.count(), 0);
+ QCOMPARE(authspy.size(), 0);
QCOMPARE(replySync->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 401);
}
@@ -3720,7 +4152,7 @@ void tst_QNetworkReply::ioGetFromHttpWithProxyAuth()
QCOMPARE(reader1.data, referenceData);
QCOMPARE(reader2.data, referenceData);
- QCOMPARE(authspy.count(), 1);
+ QCOMPARE(authspy.size(), 1);
}
reference.seek(0);
@@ -3743,7 +4175,7 @@ void tst_QNetworkReply::ioGetFromHttpWithProxyAuth()
QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
QCOMPARE(reader.data, reference.readAll());
- QCOMPARE(authspy.count(), 0);
+ QCOMPARE(authspy.size(), 0);
}
// now check with synchronous calls:
@@ -3756,7 +4188,7 @@ void tst_QNetworkReply::ioGetFromHttpWithProxyAuth()
QSignalSpy authspy(&manager, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
QNetworkReplyPtr replySync(manager.get(request));
QVERIFY(replySync->isFinished()); // synchronous
- QCOMPARE(authspy.count(), 0);
+ QCOMPARE(authspy.size(), 0);
// we cannot use a data reader here, since that connects to the readyRead signal,
// just use readAll()
@@ -3784,7 +4216,7 @@ void tst_QNetworkReply::ioGetFromHttpWithProxyAuthSynchronous()
manager.setProxy(QNetworkProxy()); // reset
QVERIFY(replySync->isFinished()); // synchronous
QCOMPARE(replySync->error(), QNetworkReply::ProxyAuthenticationRequiredError);
- QCOMPARE(authspy.count(), 0);
+ QCOMPARE(authspy.size(), 0);
QCOMPARE(replySync->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 407);
}
@@ -3816,7 +4248,7 @@ void tst_QNetworkReply::ioGetFromHttpWithSocksProxy()
QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
QCOMPARE(reader.data, reference.readAll());
- QCOMPARE(authspy.count(), 0);
+ QCOMPARE(authspy.size(), 0);
}
// set an invalid proxy just to make sure that we can't load
@@ -3840,10 +4272,9 @@ void tst_QNetworkReply::ioGetFromHttpWithSocksProxy()
QVERIFY(reader.data.isEmpty());
QVERIFY(int(reply->error()) > 0);
- QEXPECT_FAIL("", "QTcpSocket doesn't return enough information yet", Continue);
QCOMPARE(int(reply->error()), int(QNetworkReply::ProxyConnectionRefusedError));
- QCOMPARE(authspy.count(), 0);
+ QCOMPARE(authspy.size(), 0);
}
}
#endif // QT_CONFIG(networkproxy)
@@ -3871,7 +4302,7 @@ void tst_QNetworkReply::ioGetFromHttpsWithSslErrors()
QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
QCOMPARE(reader.data, reference.readAll());
- QCOMPARE(sslspy.count(), 1);
+ QCOMPARE(sslspy.size(), 1);
QVERIFY(!storedSslConfiguration.isNull());
QVERIFY(!reply->sslConfiguration().isNull());
@@ -3899,7 +4330,7 @@ void tst_QNetworkReply::ioGetFromHttpsWithIgnoreSslErrors()
QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
QCOMPARE(reader.data, reference.readAll());
- QCOMPARE(sslspy.count(), 1);
+ QCOMPARE(sslspy.size(), 1);
QVERIFY(!storedSslConfiguration.isNull());
QVERIFY(!reply->sslConfiguration().isNull());
@@ -3922,7 +4353,7 @@ void tst_QNetworkReply::ioGetFromHttpsWithSslHandshakeError()
QCOMPARE(waitForFinish(reply), int(Failure));
QCOMPARE(reply->error(), QNetworkReply::SslHandshakeFailedError);
- QCOMPARE(sslspy.count(), 0);
+ QCOMPARE(sslspy.size(), 0);
}
#endif
@@ -3980,11 +4411,11 @@ void tst_QNetworkReply::ioGetFromHttpBrokenServer()
QCOMPARE(waitForFinish(reply), int(Failure));
QCOMPARE(reply->url(), request.url());
- QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.size(), 1);
QVERIFY(reply->error() != QNetworkReply::NoError);
}
-void tst_QNetworkReply::ioGetFromHttpStatus100_data()
+void tst_QNetworkReply::ioGetFromHttpStatusInformational_data()
{
QTest::addColumn<QByteArray>("dataToSend");
QTest::addColumn<int>("statusCode");
@@ -3995,9 +4426,25 @@ void tst_QNetworkReply::ioGetFromHttpStatus100_data()
QTest::newRow("minimal+404") << QByteArray("HTTP/1.1 100 Continue\n\nHTTP/1.0 204 No Content\r\n\r\n") << 204;
QTest::newRow("with_headers") << QByteArray("HTTP/1.1 100 Continue\r\nBla: x\r\n\r\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") << 200;
QTest::newRow("with_headers2") << QByteArray("HTTP/1.1 100 Continue\nBla: x\n\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") << 200;
+
+ QTest::newRow("normal-custom") << QByteArray("HTTP/1.1 133 Custom\r\n\r\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") << 200;
+ QTest::newRow("minimal-custom") << QByteArray("HTTP/1.1 133 Custom\n\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") << 200;
+ QTest::newRow("minimal2-custom") << QByteArray("HTTP/1.1 133 Custom\n\nHTTP/1.0 200 OK\r\n\r\n") << 200;
+ QTest::newRow("minimal3-custom") << QByteArray("HTTP/1.1 133 Custom\n\nHTTP/1.0 200 OK\n\n") << 200;
+ QTest::newRow("minimal+404-custom") << QByteArray("HTTP/1.1 133 Custom\n\nHTTP/1.0 204 No Content\r\n\r\n") << 204;
+ QTest::newRow("with_headers-custom") << QByteArray("HTTP/1.1 133 Custom\r\nBla: x\r\n\r\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") << 200;
+ QTest::newRow("with_headers2-custom") << QByteArray("HTTP/1.1 133 Custom\nBla: x\n\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") << 200;
+
+ QTest::newRow("normal-custom2") << QByteArray("HTTP/1.1 179 Custom2\r\n\r\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") << 200;
+ QTest::newRow("minimal-custom2") << QByteArray("HTTP/1.1 179 Custom2\n\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") << 200;
+ QTest::newRow("minimal2-custom2") << QByteArray("HTTP/1.1 179 Custom2\n\nHTTP/1.0 200 OK\r\n\r\n") << 200;
+ QTest::newRow("minimal3-custom2") << QByteArray("HTTP/1.1 179 Custom2\n\nHTTP/1.0 200 OK\n\n") << 200;
+ QTest::newRow("minimal+404-custom2") << QByteArray("HTTP/1.1 179 Custom2\n\nHTTP/1.0 204 No Content\r\n\r\n") << 204;
+ QTest::newRow("with_headers-custom2") << QByteArray("HTTP/1.1 179 Custom2\r\nBla: x\r\n\r\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") << 200;
+ QTest::newRow("with_headers2-custom2") << QByteArray("HTTP/1.1 179 Custom2\nBla: x\n\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n") << 200;
}
-void tst_QNetworkReply::ioGetFromHttpStatus100()
+void tst_QNetworkReply::ioGetFromHttpStatusInformational()
{
QFETCH(QByteArray, dataToSend);
QFETCH(int, statusCode);
@@ -4051,7 +4498,7 @@ void tst_QNetworkReply::ioGetFromHttpWithCache_data()
QByteArray reply200 =
"HTTP/1.0 200\r\n"
"Connection: keep-alive\r\n"
- "Content-Type: text/plain\r\n"
+ "content-type: text/plain\r\n"
"Cache-control: no-store\r\n"
"Content-length: 8\r\n"
"\r\n"
@@ -4186,7 +4633,7 @@ void tst_QNetworkReply::ioGetFromHttpWithCache_data()
QByteArray reply206 =
"HTTP/1.0 206\r\n"
"Connection: keep-alive\r\n"
- "Content-Type: text/plain\r\n"
+ "content-type: text/plain\r\n"
"Cache-control: no-cache\r\n"
"Content-Range: bytes 2-6/8\r\n"
"Content-length: 4\r\n"
@@ -4316,15 +4763,15 @@ void tst_QNetworkReply::ioGetWithManyProxies_data()
// Tests that fail:
- // HTTP request with FTP caching proxy
- proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121);
- QTest::newRow("http-on-ftp")
- << proxyList << QNetworkProxy()
- << "http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
- << QNetworkReply::ProxyNotFoundError;
-
if (ftpSupported) {
+ // HTTP request with FTP caching proxy
+ proxyList.clear();
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121);
+ QTest::newRow("http-on-ftp")
+ << proxyList << QNetworkProxy()
+ << "http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
+ << QNetworkReply::ProxyNotFoundError;
+
// FTP request with HTTP caching proxy
proxyList.clear();
proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy,
@@ -4355,13 +4802,15 @@ void tst_QNetworkReply::ioGetWithManyProxies_data()
<< "https://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
<< QNetworkReply::ProxyNotFoundError;
- // HTTPS with FTP caching proxy
- proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121);
- QTest::newRow("https-on-ftp")
- << proxyList << QNetworkProxy()
- << "https://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
- << QNetworkReply::ProxyNotFoundError;
+ if (ftpSupported) {
+ // HTTPS with FTP caching proxy
+ proxyList.clear();
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121);
+ QTest::newRow("https-on-ftp")
+ << proxyList << QNetworkProxy()
+ << "https://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
+ << QNetworkReply::ProxyNotFoundError;
+ }
#endif
// Complex requests:
@@ -4384,15 +4833,17 @@ void tst_QNetworkReply::ioGetWithManyProxies_data()
<< "http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
<< QNetworkReply::NoError;
- // HTTP request with FTP + HTTP + SOCKS
- proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121)
- << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129)
- << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1081);
- QTest::newRow("http-on-ftp+http+socks")
- << proxyList << proxyList.at(1) // second proxy should be used
- << "http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
- << QNetworkReply::NoError;
+ if (ftpSupported) {
+ // HTTP request with FTP + HTTP + SOCKS
+ proxyList.clear();
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121)
+ << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129)
+ << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1081);
+ QTest::newRow("http-on-ftp+http+socks")
+ << proxyList << proxyList.at(1) // second proxy should be used
+ << "http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
+ << QNetworkReply::NoError;
+ }
// HTTP request with NoProxy + HTTP
proxyList.clear();
@@ -4404,15 +4855,15 @@ void tst_QNetworkReply::ioGetWithManyProxies_data()
<< QNetworkReply::NoError;
// HTTP request with FTP + NoProxy
- proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121)
- << QNetworkProxy(QNetworkProxy::NoProxy);
- QTest::newRow("http-on-ftp+noproxy")
- << proxyList << proxyList.at(1) // second proxy should be used
- << "http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
- << QNetworkReply::NoError;
-
if (ftpSupported) {
+ proxyList.clear();
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121)
+ << QNetworkProxy(QNetworkProxy::NoProxy);
+ QTest::newRow("http-on-ftp+noproxy")
+ << proxyList << proxyList.at(1) // second proxy should be used
+ << "http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
+ << QNetworkReply::NoError;
+
// FTP request with HTTP Caching + FTP
proxyList.clear();
proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy,
@@ -4435,15 +4886,17 @@ void tst_QNetworkReply::ioGetWithManyProxies_data()
<< "https://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
<< QNetworkReply::NoError;
- // HTTPS request with FTP + HTTP C + HTTP T
- proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121)
- << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129)
- << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::httpProxyServerName(), 3129);
- QTest::newRow("https-on-ftp+httpcaching+http")
- << proxyList << proxyList.at(2) // skip the first two
- << "https://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
- << QNetworkReply::NoError;
+ if (ftpSupported) {
+ // HTTPS request with FTP + HTTP C + HTTP T
+ proxyList.clear();
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121)
+ << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129)
+ << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::httpProxyServerName(), 3129);
+ QTest::newRow("https-on-ftp+httpcaching+http")
+ << proxyList << proxyList.at(2) // skip the first two
+ << "https://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
+ << QNetworkReply::NoError;
+ }
#endif
}
@@ -4498,16 +4951,16 @@ void tst_QNetworkReply::ioGetWithManyProxies()
// now verify that the proxies worked:
QFETCH(QNetworkProxy, proxyUsed);
if (proxyUsed.type() == QNetworkProxy::NoProxy) {
- QCOMPARE(authspy.count(), 0);
+ QCOMPARE(authspy.size(), 0);
} else {
if (QByteArray(QTest::currentDataTag()).startsWith("ftp-"))
return; // No authentication with current FTP or with FTP proxies
- QCOMPARE(authspy.count(), 1);
+ QCOMPARE(authspy.size(), 1);
QCOMPARE(qvariant_cast<QNetworkProxy>(authspy.at(0).at(0)), proxyUsed);
}
} else {
// request failed
- QCOMPARE(authspy.count(), 0);
+ QCOMPARE(authspy.size(), 0);
}
}
#endif // QT_CONFIG(networkproxy)
@@ -4583,6 +5036,7 @@ void tst_QNetworkReply::ioPutToFileFromSocket()
QCOMPARE(contents, data);
}
+#if QT_CONFIG(localserver)
void tst_QNetworkReply::ioPutToFileFromLocalSocket_data()
{
putToFile_data();
@@ -4626,6 +5080,7 @@ void tst_QNetworkReply::ioPutToFileFromLocalSocket()
QByteArray contents = file.readAll();
QCOMPARE(contents, data);
}
+#endif
// Currently no stdin/out supported for Windows CE.
void tst_QNetworkReply::ioPutToFileFromProcess_data()
@@ -4675,6 +5130,10 @@ void tst_QNetworkReply::ioPutToFileFromProcess()
QByteArray contents = file.readAll();
QCOMPARE(contents, data);
+ if (process.state() == QProcess::Running)
+ QVERIFY(process.waitForFinished());
+ QCOMPARE(process.exitCode(), 0);
+
#endif // QT_CONFIG(process)
}
@@ -4785,7 +5244,7 @@ void tst_QNetworkReply::ioPostToHttpFromFile()
QUrl url("http://" + QtNetworkSettings::httpServerName() + "/qtest/cgi-bin/md5sum.cgi");
QNetworkRequest request(url);
- request.setRawHeader("Content-Type", "application/octet-stream");
+ request.setRawHeader("content-type", "application/octet-stream");
QNetworkReplyPtr reply(manager.post(request, &sourceFile));
@@ -4813,7 +5272,7 @@ void tst_QNetworkReply::ioPostToHttpFromSocket_data()
QTest::addColumn<int>("authenticationRequiredCount");
QTest::addColumn<int>("proxyAuthenticationRequiredCount");
- for (int i = 0; i < proxies.count(); ++i)
+ for (int i = 0; i < proxies.size(); ++i)
for (int auth = 0; auth < 2; ++auth) {
QUrl url;
if (auth)
@@ -4862,7 +5321,7 @@ void tst_QNetworkReply::ioPostToHttpFromSocket()
socketpair.endPoints[0]->write(data);
QNetworkRequest request(url);
- request.setRawHeader("Content-Type", "application/octet-stream");
+ request.setRawHeader("content-type", "application/octet-stream");
manager.setProxy(proxy);
QNetworkReplyPtr reply(manager.post(request, socketpair.endPoints[1]));
@@ -4891,8 +5350,8 @@ void tst_QNetworkReply::ioPostToHttpFromSocket()
QCOMPARE(reply->readAll().trimmed(), md5sum(data).toHex());
- QTEST(int(authenticationRequiredSpy.count()), "authenticationRequiredCount");
- QTEST(int(proxyAuthenticationRequiredSpy.count()), "proxyAuthenticationRequiredCount");
+ QTEST(int(authenticationRequiredSpy.size()), "authenticationRequiredCount");
+ QTEST(int(proxyAuthenticationRequiredSpy.size()), "proxyAuthenticationRequiredCount");
}
void tst_QNetworkReply::ioPostToHttpFromSocketSynchronous_data()
@@ -4936,7 +5395,7 @@ void tst_QNetworkReply::ioPostToHttpFromSocketSynchronous()
QUrl url("http://" + QtNetworkSettings::httpServerName() + "/qtest/cgi-bin/md5sum.cgi");
QNetworkRequest request(url);
- request.setRawHeader("Content-Type", "application/octet-stream");
+ request.setRawHeader("content-type", "application/octet-stream");
request.setAttribute(
QNetworkRequest::SynchronousRequestAttribute,
true);
@@ -4967,7 +5426,7 @@ void tst_QNetworkReply::ioPostToHttpFromMiddleOfFileToEnd()
QUrl url = "http://" + QtNetworkSettings::httpServerName() + "/qtest/protected/cgi-bin/md5sum.cgi";
QNetworkRequest request(url);
- request.setRawHeader("Content-Type", "application/octet-stream");
+ request.setRawHeader("content-type", "application/octet-stream");
QNetworkReplyPtr reply(manager.post(request, &sourceFile));
connect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
@@ -4993,7 +5452,7 @@ void tst_QNetworkReply::ioPostToHttpFromMiddleOfFileFiveBytes()
QUrl url = "http://" + QtNetworkSettings::httpServerName() + "/qtest/protected/cgi-bin/md5sum.cgi";
QNetworkRequest request(url);
- request.setRawHeader("Content-Type", "application/octet-stream");
+ request.setRawHeader("content-type", "application/octet-stream");
// only send 5 bytes
request.setHeader(QNetworkRequest::ContentLengthHeader, 5);
QVERIFY(request.header(QNetworkRequest::ContentLengthHeader).isValid());
@@ -5024,7 +5483,7 @@ void tst_QNetworkReply::ioPostToHttpFromMiddleOfQBufferFiveBytes()
QUrl url = "http://" + QtNetworkSettings::httpServerName() + "/qtest/protected/cgi-bin/md5sum.cgi";
QNetworkRequest request(url);
- request.setRawHeader("Content-Type", "application/octet-stream");
+ request.setRawHeader("content-type", "application/octet-stream");
QNetworkReplyPtr reply(manager.post(request, &uploadBuffer));
connect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
@@ -5052,7 +5511,7 @@ void tst_QNetworkReply::ioPostToHttpNoBufferFlag()
QUrl url = "http://" + QtNetworkSettings::httpServerName() + "/qtest/protected/cgi-bin/md5sum.cgi";
QNetworkRequest request(url);
- request.setRawHeader("Content-Type", "application/octet-stream");
+ request.setRawHeader("content-type", "application/octet-stream");
// disallow buffering
request.setAttribute(QNetworkRequest::DoNotBufferUploadDataAttribute, true);
request.setHeader(QNetworkRequest::ContentLengthHeader, data.size());
@@ -5137,7 +5596,7 @@ void tst_QNetworkReply::ioPostToHttpsUploadProgress()
QUrl url = QUrl(QLatin1String("https://127.0.0.1:") + QString::number(server.serverPort()) + QLatin1Char('/'));
QNetworkRequest request(url);
- request.setRawHeader("Content-Type", "application/octet-stream");
+ request.setRawHeader("content-type", "application/octet-stream");
QNetworkReplyPtr reply(manager.post(request, sourceFile));
QSignalSpy spy(reply.data(), SIGNAL(uploadProgress(qint64,qint64)));
@@ -5291,7 +5750,7 @@ void tst_QNetworkReply::ioPostToHttpUploadProgress()
// create the request
QUrl url = QUrl(QString("http://127.0.0.1:%1/").arg(server.serverPort()));
QNetworkRequest request(url);
- request.setRawHeader("Content-Type", "application/octet-stream");
+ request.setRawHeader("content-type", "application/octet-stream");
QNetworkReplyPtr reply(manager.post(request, &sourceFile));
QSignalSpy spy(reply.data(), SIGNAL(uploadProgress(qint64,qint64)));
connect(&server, SIGNAL(newConnection()), &QTestEventLoop::instance(), SLOT(exitLoop()));
@@ -5359,18 +5818,14 @@ void tst_QNetworkReply::emitAllUploadProgressSignals()
QUrl url = QUrl(QLatin1String("http://127.0.0.1:") + QString::number(server.serverPort()) + QLatin1Char('/'));
QNetworkRequest normalRequest(url);
- normalRequest.setRawHeader("Content-Type", "application/octet-stream");
+ normalRequest.setRawHeader("content-type", "application/octet-stream");
QNetworkRequest catchAllSignalsRequest(normalRequest);
catchAllSignalsRequest.setAttribute(QNetworkRequest::EmitAllUploadProgressSignalsAttribute, true);
- QList<QNetworkRequest> requests;
- requests << normalRequest << catchAllSignalsRequest;
-
QList<int> signalCount;
- foreach (const QNetworkRequest &request, requests) {
-
+ for (const QNetworkRequest &request : {normalRequest, catchAllSignalsRequest}) {
sourceFile.seek(0);
QNetworkReplyPtr reply(manager.post(request, &sourceFile));
QSignalSpy spy(reply.data(), SIGNAL(uploadProgress(qint64,qint64)));
@@ -5391,7 +5846,7 @@ void tst_QNetworkReply::emitAllUploadProgressSignals()
QVERIFY(!QTestEventLoop::instance().timeout());
incomingSocket->close();
- signalCount.append(spy.count());
+ signalCount.append(spy.size());
reply->deleteLater();
}
server.close();
@@ -5414,7 +5869,7 @@ void tst_QNetworkReply::ioPostToHttpEmptyUploadProgress()
// create the request
QUrl url = QUrl(QLatin1String("http://127.0.0.1:") + QString::number(server.serverPort()) + QLatin1Char('/'));
QNetworkRequest request(url);
- request.setRawHeader("Content-Type", "application/octet-stream");
+ request.setRawHeader("content-type", "application/octet-stream");
QNetworkReplyPtr reply(manager.post(request, &buffer));
QSignalSpy spy(reply.data(), SIGNAL(uploadProgress(qint64,qint64)));
connect(&server, SIGNAL(newConnection()), &QTestEventLoop::instance(), SLOT(exitLoop()));
@@ -5437,7 +5892,7 @@ void tst_QNetworkReply::ioPostToHttpEmptyUploadProgress()
QVERIFY(!QTestEventLoop::instance().timeout());
// final check: only 1 uploadProgress has been emitted
- QCOMPARE(spy.length(), 1);
+ QCOMPARE(spy.size(), 1);
QList<QVariant> args = spy.last();
QVERIFY(!args.isEmpty());
QCOMPARE(args.at(0).toLongLong(), buffer.size());
@@ -5460,7 +5915,11 @@ void tst_QNetworkReply::lastModifiedHeaderForFile()
QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply));
QDateTime header = reply->header(QNetworkRequest::LastModifiedHeader).toDateTime();
- QCOMPARE(header, fileInfo.lastModified());
+ QDateTime expected = fileInfo.lastModified();
+ // remove msecs, HTTP dates don't support it
+ expected = expected.addMSecs(-expected.time().msec());
+
+ QCOMPARE(header.toUTC(), expected.toUTC());
}
void tst_QNetworkReply::lastModifiedHeaderForHttp()
@@ -5475,7 +5934,7 @@ void tst_QNetworkReply::lastModifiedHeaderForHttp()
QDateTime header = reply->header(QNetworkRequest::LastModifiedHeader).toDateTime();
QDateTime realDate = QDateTime::fromString("2007-05-22T12:04:57", Qt::ISODate);
- realDate.setTimeSpec(Qt::UTC);
+ realDate.setTimeZone(QTimeZone::UTC);
QCOMPARE(header, realDate);
}
@@ -5608,7 +6067,7 @@ void tst_QNetworkReply::downloadProgress()
QVERIFY(!QTestEventLoop::instance().timeout());
QVERIFY(reply->isFinished());
- QVERIFY(spy.count() > 0);
+ QVERIFY(spy.size() > 0);
//final progress should have equal current & total
QList<QVariant> args = spy.takeLast();
@@ -5654,14 +6113,14 @@ void tst_QNetworkReply::uploadProgress()
QVERIFY(server.hasPendingConnections());
QTcpSocket *receiver = server.nextPendingConnection();
- if (finished.count() == 0) {
+ if (finished.size() == 0) {
// it's not finished yet, so wait for it to be
QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply));
}
delete receiver;
- QVERIFY(finished.count() > 0);
- QVERIFY(spy.count() > 0);
+ QVERIFY(finished.size() > 0);
+ QVERIFY(spy.size() > 0);
QList<QVariant> args = spy.last();
QCOMPARE(args.at(0).toInt(), data.size());
@@ -5766,7 +6225,7 @@ void tst_QNetworkReply::receiveCookiesFromHttp()
QByteArray data = cookieString.toLatin1() + '\n';
QUrl url("http://" + QtNetworkSettings::httpServerName() + "/qtest/cgi-bin/set-cookie.cgi");
QNetworkRequest request(url);
- request.setRawHeader("Content-Type", "application/octet-stream");
+ request.setRawHeader("content-type", "application/octet-stream");
QNetworkReplyPtr reply;
RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::PostOperation, request, reply, data));
@@ -5794,7 +6253,7 @@ void tst_QNetworkReply::receiveCookiesFromHttpSynchronous()
QUrl url("http://" + QtNetworkSettings::httpServerName() + "/qtest/cgi-bin/set-cookie.cgi");
QNetworkRequest request(url);
- request.setRawHeader("Content-Type", "application/octet-stream");
+ request.setRawHeader("content-type", "application/octet-stream");
request.setAttribute(
QNetworkRequest::SynchronousRequestAttribute,
true);
@@ -5943,8 +6402,8 @@ void tst_QNetworkReply::nestedEventLoops()
QTestEventLoop::instance().enterLoop(20);
QVERIFY2(!QTestEventLoop::instance().timeout(), "Network timeout");
- QCOMPARE(finishedspy.count(), 1);
- QCOMPARE(errorspy.count(), 0);
+ QCOMPARE(finishedspy.size(), 1);
+ QCOMPARE(errorspy.size(), 0);
}
#if QT_CONFIG(networkproxy)
@@ -5977,7 +6436,7 @@ void tst_QNetworkReply::httpProxyCommands()
manager.setProxy(proxy);
QNetworkRequest request(url);
- request.setRawHeader("User-Agent", "QNetworkReplyAutoTest/1.0");
+ request.setRawHeader("user-agent", "QNetworkReplyAutoTest/1.0");
QNetworkReplyPtr reply(manager.get(request));
// wait for the finished signal
@@ -5990,14 +6449,15 @@ void tst_QNetworkReply::httpProxyCommands()
// especially since it won't succeed in the HTTPS case
// so just check that the command was correct
- QString receivedHeader = proxyServer.receivedData.left(expectedCommand.length());
+ QString receivedHeader = proxyServer.receivedData.left(expectedCommand.size());
QCOMPARE(receivedHeader, expectedCommand);
//QTBUG-17223 - make sure the user agent from the request is sent to proxy server even for CONNECT
- int uapos = proxyServer.receivedData.indexOf("User-Agent");
+ const QByteArray cUserAgent = "user-agent: ";
+ int uapos = proxyServer.receivedData.toLower().indexOf(cUserAgent) + cUserAgent.size();
int uaend = proxyServer.receivedData.indexOf("\r\n", uapos);
QByteArray uaheader = proxyServer.receivedData.mid(uapos, uaend - uapos);
- QCOMPARE(uaheader, QByteArray("User-Agent: QNetworkReplyAutoTest/1.0"));
+ QCOMPARE(uaheader, QByteArray("QNetworkReplyAutoTest/1.0"));
}
class ProxyChangeHelper : public QObject
@@ -6034,14 +6494,6 @@ struct QThreadCleanup
}
};
-struct QDeleteLaterCleanup
-{
- static inline void cleanup(QObject *o)
- {
- o->deleteLater();
- }
-};
-
#if QT_CONFIG(networkproxy)
void tst_QNetworkReply::httpProxyCommandsSynchronous()
{
@@ -6053,7 +6505,7 @@ void tst_QNetworkReply::httpProxyCommandsSynchronous()
// the server thread, because the client is never returning to the
// event loop
QScopedPointer<QThread, QThreadCleanup> serverThread(new QThread);
- QScopedPointer<MiniHttpServer, QDeleteLaterCleanup> proxyServer(new MiniHttpServer(responseToSend, false, serverThread.data()));
+ QScopedPointer<MiniHttpServer, QScopedPointerDeleteLater> proxyServer(new MiniHttpServer(responseToSend, false, serverThread.data()));
QNetworkProxy proxy(QNetworkProxy::HttpProxy, "127.0.0.1", proxyServer->serverPort());
manager.setProxy(proxy);
@@ -6074,7 +6526,7 @@ void tst_QNetworkReply::httpProxyCommandsSynchronous()
// especially since it won't succeed in the HTTPS case
// so just check that the command was correct
- QString receivedHeader = proxyServer->receivedData.left(expectedCommand.length());
+ QString receivedHeader = proxyServer->receivedData.left(expectedCommand.size());
QCOMPARE(receivedHeader, expectedCommand);
}
@@ -6171,9 +6623,9 @@ void tst_QNetworkReply::authorizationError()
QCOMPARE(waitForFinish(reply), int(Failure));
QFETCH(int, errorSignalCount);
- QCOMPARE(errorSpy.count(), errorSignalCount);
+ QCOMPARE(errorSpy.size(), errorSignalCount);
QFETCH(int, finishedSignalCount);
- QCOMPARE(finishedSpy.count(), finishedSignalCount);
+ QCOMPARE(finishedSpy.size(), finishedSignalCount);
QFETCH(int, error);
QCOMPARE(reply->error(), QNetworkReply::NetworkError(error));
@@ -6211,7 +6663,6 @@ void tst_QNetworkReply::httpConnectionCount()
}
QVERIFY(server->listen());
- QCoreApplication::instance()->processEvents();
QUrl url("http://127.0.0.1:" + QString::number(server->serverPort()) + QLatin1Char('/'));
if (encrypted)
@@ -6222,7 +6673,7 @@ void tst_QNetworkReply::httpConnectionCount()
QUrl urlCopy = url;
urlCopy.setPath(u'/' + QString::number(i)); // Differentiate the requests a bit
QNetworkRequest request(urlCopy);
- request.setAttribute(QNetworkRequest::Http2AllowedAttribute, http2Enabled);
+ request.setAttribute(QNetworkRequest::Http2CleartextAllowedAttribute, http2Enabled);
QNetworkReply* reply = manager.get(request);
reply->setParent(server.data());
if (encrypted)
@@ -6230,26 +6681,39 @@ void tst_QNetworkReply::httpConnectionCount()
}
int pendingConnectionCount = 0;
- QElapsedTimer timer;
- timer.start();
- while(pendingConnectionCount <= 20) {
- QTestEventLoop::instance().enterLoop(1);
+ const auto newPendingConnection = [&server]() { return server->hasPendingConnections(); };
+ // If we have http2 enabled then the second connection will take a little
+ // longer to be established because we will wait for the first one to finish
+ // to see if we should upgrade:
+ const int rampDown = http2Enabled ? 2 : 1;
+ while (pendingConnectionCount <= 6) {
+ if (!QTest::qWaitFor(newPendingConnection, pendingConnectionCount >= rampDown ? 3s : 7s))
+ break;
QTcpSocket *socket = server->nextPendingConnection();
- while (socket != 0) {
- if (pendingConnectionCount == 0) {
- // respond to the first connection so we know to transition to HTTP/1.1 when using
- // HTTP/2
- socket->write(httpEmpty200Response);
+ while (socket) {
+ if (pendingConnectionCount == 0 && http2Enabled) {
+ // Respond to the first connection so we know to transition to HTTP/1.1 when using
+ // HTTP/2.
+ // Because of some internal state machinery we need to wait until the request has
+ // actually been written to the server before we can reply.
+ auto connection = std::make_shared<QMetaObject::Connection>();
+ auto replyOnRequest = [=, buffer = QByteArray()]() mutable {
+ buffer += socket->readAll();
+ if (!buffer.contains("\r\n\r\n"))
+ return;
+ socket->write(httpEmpty200Response);
+ QObject::disconnect(*connection);
+ };
+ *connection = QObject::connect(socket, &QTcpSocket::readyRead, socket,
+ std::move(replyOnRequest));
+ if (socket->bytesAvailable()) // If we already have data, check it now
+ emit socket->readyRead();
}
pendingConnectionCount++;
socket->setParent(server.data());
socket = server->nextPendingConnection();
}
-
- // at max. wait 10 sec
- if (timer.elapsed() > 10000)
- break;
}
QCOMPARE(pendingConnectionCount, 6);
@@ -6532,7 +6996,7 @@ void tst_QNetworkReply::encrypted()
QTestEventLoop::instance().enterLoop(20);
QVERIFY(!QTestEventLoop::instance().timeout());
- QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.size(), 1);
reply->deleteLater();
}
@@ -6561,7 +7025,7 @@ void tst_QNetworkReply::abortOnEncrypted()
});
QSignalSpy spyEncrypted(reply, &QNetworkReply::encrypted);
- QTRY_COMPARE(spyEncrypted.count(), 1);
+ QTRY_COMPARE(spyEncrypted.size(), 1);
// Wait for the socket to be closed again in order to be sure QTcpSocket::readyRead would have been emitted.
QTRY_VERIFY(server.socket != nullptr);
@@ -6755,7 +7219,20 @@ void tst_QNetworkReply::getAndThenDeleteObject()
// see https://bugs.webkit.org/show_bug.cgi?id=38935
void tst_QNetworkReply::symbianOpenCDataUrlCrash()
{
- QString requestUrl("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAWCAYAAAA1vze2AAAAB3RJTUUH2AUSEgolrgBvVQAAAAlwSFlzAAALEwAACxMBAJqcGAAAAARnQU1BAACxjwv8YQUAAAHlSURBVHja5VbNShxBEK6ZaXtnHTebQPA1gngNmfaeq+QNPIlIXkC9iQdJxJNvEHLN3VkxhxxE8gTmEhAVddXZ6Z3f9Ndriz89/sHmkBQUVVT1fB9d9c3uOERUKTunIdn3HzstxGpYBDS4wZk7TAJj/wlJ90J+jnuygqs8svSj+/rGHBos3rE18XBvfU3no7NzlJfUaY/5whAwl8Lr/WDUv4ODxTMb+P5xLExe5LmO559WqTX/MQR4WZYEAtSePS4pE0qSnuhnRUcBU5Gm2k9XljU4Z26I3NRxBrd80rj2fh+KNE0FY4xevRgTjREvPFpasAK8Xli6MUbbuKw3afAGgSBXozo5u4hkmncAlkl5wx8iMGbdyQjnCFEiEwGiosj1UQA/x2rVddiVoi+l4IxE0PTDnx+mrQBvvnx9cFz3krhVvuhzFn579/aq/n5rW8fbtTqiWhIQZEo17YBvbkxOXNVndnYpTvod7AtiuN2re0+siwcB9oH8VxxrNwQQAhzyRs30n7wTI2HIN2g2QtQwjjhJIQatOq7E8bIVCLwzpl83Lvtvl+NohWWlE8UZTWEMAGCcR77fHKhPnZF5tYie6dfdxCphACmLPM+j8bYfmTryg64kV9Vh3mV8jP0b/4wO/YUPiT/8i0MLf55lSQAAAABJRU5ErkJggg==");
+ QString requestUrl("data:image/"
+ "png;base64,"
+ "iVBORw0KGgoAAAANSUhEUgAAABkAAAAWCAYAAAA1vze2AAAAB3RJTUUH2AUSEgolrgBvVQAAAAl"
+ "wSFlzAAALEwAACxMBAJqcGAAAAARnQU1BAACxjwv8YQUAAAHlSURBVHja5VbNShxBEK6ZaXtnHT"
+ "ebQPA1gngNmfaeq+QNPIlIXkC9iQdJxJNvEHLN3VkxhxxE8gTmEhAVddXZ6Z3f9Ndriz89/"
+ "sHmkBQUVVT1fB9d9c3uOERUKTunIdn3HzstxGpYBDS4wZk7TAJj/wlJ90J+jnuygqs8svSj+/"
+ "rGHBos3rE18XBvfU3no7NzlJfUaY/5whAwl8Lr/WDUv4ODxTMb+P5xLExe5LmO559WqTX/"
+ "MQR4WZYEAtSePS4pE0qSnuhnRUcBU5Gm2k9XljU4Z26I3NRxBrd80rj2fh+"
+ "KNE0FY4xevRgTjREvPFpasAK8Xli6MUbbuKw3afAGgSBXozo5u4hkmncAlkl5wx8iMGbdyQjnCF"
+ "EiEwGiosj1UQA/x2rVddiVoi+l4IxE0PTDnx+mrQBvvnx9cFz3krhVvuhzFn579/aq/"
+ "n5rW8fbtTqiWhIQZEo17YBvbkxOXNVndnYpTvod7AtiuN2re0+"
+ "siwcB9oH8VxxrNwQQAhzyRs30n7wTI2HIN2g2QtQwjjhJIQatOq7E8bIVCLwzpl83Lvtvl+"
+ "NohWWlE8UZTWEMAGCcR77fHKhPnZF5tYie6dfdxCphACmLPM+j8bYfmTryg64kV9Vh3mV8jP0b/"
+ "4wO/YUPiT/8i0MLf55lSQAAAABJRU5ErkJggg==");
QUrl url = QUrl::fromEncoded(requestUrl.toLatin1());
QNetworkRequest req(url);
QNetworkReplyPtr reply;
@@ -7053,6 +7530,7 @@ void tst_QNetworkReply::ioGetFromHttpBrokenChunkedEncoding()
QCOMPARE(reply->error(), QNetworkReply::NoError);
}
+#if QT_CONFIG(http)
// TODO:
// Prepare a gzip that has one chunk that expands to the size mentioned in the bugreport.
// Then have a custom HTTP server that waits after this chunk so the returning gets
@@ -7081,6 +7559,7 @@ void tst_QNetworkReply::qtbug12908compressedHttpReply()
QCOMPARE(reply->size(), qint64(16384));
QCOMPARE(reply->readAll(), QByteArray(16384, '\0'));
}
+#endif
void tst_QNetworkReply::compressedHttpReplyBrokenGzip()
{
@@ -7144,9 +7623,9 @@ void tst_QNetworkReply::qtbug4121unknownAuthentication()
QTestEventLoop::instance().enterLoop(10);
QVERIFY(!QTestEventLoop::instance().timeout());
- QCOMPARE(authSpy.count(), 0);
- QCOMPARE(finishedSpy.count(), 1);
- QCOMPARE(errorSpy.count(), 1);
+ QCOMPARE(authSpy.size(), 0);
+ QCOMPARE(finishedSpy.size(), 1);
+ QCOMPARE(errorSpy.size(), 1);
QCOMPARE(reply->error(), QNetworkReply::AuthenticationRequiredError);
}
@@ -7157,7 +7636,7 @@ void tst_QNetworkReply::authenticationCacheAfterCancel_data()
QTest::addColumn<QNetworkProxy>("proxy");
QTest::addColumn<bool>("proxyAuth");
QTest::addColumn<QUrl>("url");
- for (int i = 0; i < proxies.count(); ++i) {
+ for (int i = 0; i < proxies.size(); ++i) {
QTest::newRow("http" + proxies.at(i).tag)
<< proxies.at(i).proxy
<< proxies.at(i).requiresAuthentication
@@ -7240,8 +7719,8 @@ void tst_QNetworkReply::authenticationCacheAfterCancel()
QVERIFY(!QTestEventLoop::instance().timeout());
QCOMPARE(reply->error(), QNetworkReply::ProxyAuthenticationRequiredError);
- QCOMPARE(authSpy.count(), 0);
- QCOMPARE(proxyAuthSpy.count(), 1);
+ QCOMPARE(authSpy.size(), 0);
+ QCOMPARE(proxyAuthSpy.size(), 1);
proxyAuthSpy.clear();
//should fail due to bad credentials
@@ -7255,8 +7734,8 @@ void tst_QNetworkReply::authenticationCacheAfterCancel()
// Work round known quirk in the old test server (danted -v < v1.1.19):
if (reply->error() != QNetworkReply::HostNotFoundError)
QCOMPARE(reply->error(), QNetworkReply::ProxyAuthenticationRequiredError);
- QCOMPARE(authSpy.count(), 0);
- QVERIFY(proxyAuthSpy.count() > 0);
+ QCOMPARE(authSpy.size(), 0);
+ QVERIFY(proxyAuthSpy.size() > 0);
proxyAuthSpy.clear();
// QTBUG-23136 workaround (needed even with danted v1.1.19):
@@ -7281,10 +7760,10 @@ void tst_QNetworkReply::authenticationCacheAfterCancel()
QVERIFY(!QTestEventLoop::instance().timeout());
QCOMPARE(reply->error(), QNetworkReply::AuthenticationRequiredError);
- QVERIFY(authSpy.count() > 0);
+ QVERIFY(authSpy.size() > 0);
authSpy.clear();
if (proxyAuth) {
- QVERIFY(proxyAuthSpy.count() > 0);
+ QVERIFY(proxyAuthSpy.size() > 0);
proxyAuthSpy.clear();
}
@@ -7297,11 +7776,11 @@ void tst_QNetworkReply::authenticationCacheAfterCancel()
QVERIFY(!QTestEventLoop::instance().timeout());
QCOMPARE(reply->error(), QNetworkReply::AuthenticationRequiredError);
- QVERIFY(authSpy.count() > 0);
+ QVERIFY(authSpy.size() > 0);
authSpy.clear();
if (proxyAuth) {
//should be supplied from cache
- QCOMPARE(proxyAuthSpy.count(), 0);
+ QCOMPARE(proxyAuthSpy.size(), 0);
proxyAuthSpy.clear();
}
@@ -7315,11 +7794,11 @@ void tst_QNetworkReply::authenticationCacheAfterCancel()
QVERIFY(!QTestEventLoop::instance().timeout());
QCOMPARE(reply->error(), QNetworkReply::NoError);
- QVERIFY(authSpy.count() > 0);
+ QVERIFY(authSpy.size() > 0);
authSpy.clear();
if (proxyAuth) {
//should be supplied from cache
- QCOMPARE(proxyAuthSpy.count(), 0);
+ QCOMPARE(proxyAuthSpy.size(), 0);
proxyAuthSpy.clear();
}
@@ -7331,11 +7810,11 @@ void tst_QNetworkReply::authenticationCacheAfterCancel()
QCOMPARE(reply->error(), QNetworkReply::NoError);
//should be supplied from cache
- QCOMPARE(authSpy.count(), 0);
+ QCOMPARE(authSpy.size(), 0);
authSpy.clear();
if (proxyAuth) {
//should be supplied from cache
- QCOMPARE(proxyAuthSpy.count(), 0);
+ QCOMPARE(proxyAuthSpy.size(), 0);
proxyAuthSpy.clear();
}
@@ -7437,8 +7916,8 @@ void tst_QNetworkReply::httpWithNoCredentialUsage()
QNetworkReplyPtr reply(manager.get(request));
QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply));
// credentials in URL, so don't expect authentication signal
- QCOMPARE(authSpy.count(), 0);
- QCOMPARE(finishedSpy.count(), 1);
+ QCOMPARE(authSpy.size(), 0);
+ QCOMPARE(finishedSpy.size(), 1);
finishedSpy.clear();
}
@@ -7448,8 +7927,8 @@ void tst_QNetworkReply::httpWithNoCredentialUsage()
QNetworkReplyPtr reply(manager.get(request));
QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply));
// credentials in cache, so don't expect authentication signal
- QCOMPARE(authSpy.count(), 0);
- QCOMPARE(finishedSpy.count(), 1);
+ QCOMPARE(authSpy.size(), 0);
+ QCOMPARE(finishedSpy.size(), 1);
finishedSpy.clear();
}
@@ -7466,9 +7945,9 @@ void tst_QNetworkReply::httpWithNoCredentialUsage()
QVERIFY(!QTestEventLoop::instance().timeout());
// We check if authenticationRequired was emitted, however we do not anything in it so it should be 401
- QCOMPARE(authSpy.count(), 1);
- QCOMPARE(finishedSpy.count(), 1);
- QCOMPARE(errorSpy.count(), 1);
+ QCOMPARE(authSpy.size(), 1);
+ QCOMPARE(finishedSpy.size(), 1);
+ QCOMPARE(errorSpy.size(), 1);
QCOMPARE(reply->error(), QNetworkReply::AuthenticationRequiredError);
}
@@ -7607,11 +8086,12 @@ void tst_QNetworkReply::qtbug27161httpHeaderMayBeDamaged(){
QCOMPARE(reply->readAll(), QByteArray("ABC"));
}
+#if QT_CONFIG(networkdiskcache)
void tst_QNetworkReply::qtbug28035browserDoesNotLoadQtProjectOrgCorrectly() {
QByteArray getReply =
"HTTP/1.1 200\r\n"
"Connection: keep-alive\r\n"
- "Content-Type: text/plain\r\n"
+ "content-type: text/plain\r\n"
"Cache-control: max-age = 6000\r\n"
"\r\n"
"GET";
@@ -7619,7 +8099,7 @@ void tst_QNetworkReply::qtbug28035browserDoesNotLoadQtProjectOrgCorrectly() {
QByteArray postReply =
"HTTP/1.1 200\r\n"
"Connection: keep-alive\r\n"
- "Content-Type: text/plain\r\n"
+ "content-type: text/plain\r\n"
"Cache-control: max-age = 6000\r\n"
"Content-length: 4\r\n"
"\r\n"
@@ -7628,7 +8108,7 @@ void tst_QNetworkReply::qtbug28035browserDoesNotLoadQtProjectOrgCorrectly() {
QByteArray putReply =
"HTTP/1.1 201\r\n"
"Connection: keep-alive\r\n"
- "Content-Type: text/plain\r\n"
+ "content-type: text/plain\r\n"
"Cache-control: max-age = 6000\r\n"
"\r\n";
@@ -7666,7 +8146,7 @@ void tst_QNetworkReply::qtbug28035browserDoesNotLoadQtProjectOrgCorrectly() {
server.clearHeaderParserState();
server.setDataToTransmit(postReply);
- request.setRawHeader("Content-Type", "text/plain");
+ request.setRawHeader("content-type", "text/plain");
reply.reset(manager.post(request, postData));
QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply));
@@ -7731,6 +8211,7 @@ void tst_QNetworkReply::qtbug28035browserDoesNotLoadQtProjectOrgCorrectly() {
QCOMPARE(reply->readAll(), QByteArray("GET"));
QCOMPARE(reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool(), true);
}
+#endif
void tst_QNetworkReply::qtbug45581WrongReplyStatusCode()
{
@@ -7753,8 +8234,8 @@ void tst_QNetworkReply::qtbug45581WrongReplyStatusCode()
QCOMPARE(reply->readAll(), expectedContent);
- QCOMPARE(finishedSpy.count(), 0);
- QCOMPARE(sslErrorsSpy.count(), 0);
+ QCOMPARE(finishedSpy.size(), 0);
+ QCOMPARE(sslErrorsSpy.size(), 0);
QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), expectedContent.size());
@@ -7843,8 +8324,8 @@ void tst_QNetworkReply::synchronousRequest()
QSignalSpy sslErrorsSpy(&manager, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)));
RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::GetOperation, request, reply, 0));
QVERIFY(reply->isFinished());
- QCOMPARE(finishedSpy.count(), 0);
- QCOMPARE(sslErrorsSpy.count(), 0);
+ QCOMPARE(finishedSpy.size(), 0);
+ QCOMPARE(sslErrorsSpy.size(), 0);
QCOMPARE(reply->header(QNetworkRequest::ContentTypeHeader).toString(), mimeType);
@@ -7853,7 +8334,7 @@ void tst_QNetworkReply::synchronousRequest()
if (expected.startsWith("file:")) {
QString path = expected.mid(5);
QFile file(path);
- file.open(QIODevice::ReadOnly);
+ QVERIFY(file.open(QIODevice::ReadOnly));
expectedContent = file.readAll();
} else if (expected.startsWith("data:")) {
expectedContent = expected.mid(5).toUtf8();
@@ -7883,7 +8364,7 @@ void tst_QNetworkReply::synchronousRequestSslFailure()
runSimpleRequest(QNetworkAccessManager::GetOperation, request, reply, 0);
QVERIFY(reply->isFinished());
QCOMPARE(reply->error(), QNetworkReply::SslHandshakeFailedError);
- QCOMPARE(sslErrorsSpy.count(), 0);
+ QCOMPARE(sslErrorsSpy.size(), 0);
}
#endif
@@ -8102,12 +8583,69 @@ void tst_QNetworkReply::varyingCacheExpiry()
QVERIFY(success);
}
+class Qtbug25280Server : public MiniHttpServer
+{
+public:
+ Qtbug25280Server(QByteArray qba) : MiniHttpServer(qba, false) {}
+ QSet<QTcpSocket*> receivedSockets;
+ void reply() override
+ {
+ // Save sockets in a list
+ receivedSockets.insert((QTcpSocket*)sender());
+ qobject_cast<QTcpSocket*>(sender())->write(dataToTransmit);
+ //qDebug() << "count=" << receivedSockets.count();
+ }
+};
+
+#if QT_CONFIG(http)
+void tst_QNetworkReply::amountOfHttp1ConnectionsQtbug25280_data()
+{
+ QTest::addColumn<int>("amount");
+ QTest::addRow("default") << 6;
+ QTest::addRow("minimize") << 1;
+ QTest::addRow("increase") << 12;
+}
+
+// Also kind of QTBUG-8468
+void tst_QNetworkReply::amountOfHttp1ConnectionsQtbug25280()
+{
+ QFETCH(const int, amount);
+ QNetworkAccessManager manager; // function local instance
+ Qtbug25280Server server(tst_QNetworkReply::httpEmpty200Response);
+ server.doClose = false;
+ server.multiple = true;
+ QUrl url(QLatin1String("http://127.0.0.1")); // not "localhost" to prevent "Happy Eyeballs"
+ // from skewing the counting
+ url.setPort(server.serverPort());
+ std::optional<QHttp1Configuration> http1Configuration;
+ if (amount != 6) // don't set if it's the default
+ http1Configuration.emplace().setNumberOfConnectionsPerHost(amount);
+ constexpr int NumRequests = 200; // send a lot more than we have sockets
+ int finished = 0;
+ std::array<std::unique_ptr<QNetworkReply>, NumRequests> replies;
+ for (auto &reply : replies) {
+ QNetworkRequest request(url);
+ if (http1Configuration)
+ request.setHttp1Configuration(*http1Configuration);
+ reply.reset(manager.get(request));
+ QObject::connect(reply.get(), &QNetworkReply::finished,
+ [&finished] { ++finished; });
+ }
+ QTRY_COMPARE_WITH_TIMEOUT(finished, NumRequests, 60'000);
+ for (const auto &reply : replies) {
+ QCOMPARE(reply->error(), QNetworkReply::NoError);
+ QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
+ }
+ QCOMPARE(server.receivedSockets.size(), amount);
+}
+#endif
+
void tst_QNetworkReply::dontInsertPartialContentIntoTheCache()
{
QByteArray reply206 =
"HTTP/1.0 206\r\n"
"Connection: keep-alive\r\n"
- "Content-Type: text/plain\r\n"
+ "content-type: text/plain\r\n"
"Cache-control: no-cache\r\n"
"Content-Range: bytes 2-6/8\r\n"
"Content-length: 4\r\n"
@@ -8130,7 +8668,7 @@ void tst_QNetworkReply::dontInsertPartialContentIntoTheCache()
QVERIFY(server.totalConnections > 0);
QCOMPARE(reply->readAll().constData(), "load");
- QCOMPARE(memoryCache->m_insertedUrls.count(), 0);
+ QCOMPARE(memoryCache->m_insertedUrls.size(), 0);
}
void tst_QNetworkReply::httpUserAgent()
@@ -8147,7 +8685,7 @@ void tst_QNetworkReply::httpUserAgent()
QVERIFY(reply->isFinished());
QCOMPARE(reply->error(), QNetworkReply::NoError);
- QVERIFY(server.receivedData.contains("\r\nUser-Agent: abcDEFghi\r\n"));
+ QVERIFY(server.receivedData.contains("\r\nuser-agent: abcDEFghi\r\n"));
}
void tst_QNetworkReply::synchronousAuthenticationCache()
@@ -8164,16 +8702,16 @@ void tst_QNetworkReply::synchronousAuthenticationCache()
"WWW-Authenticate: Basic realm=\"QNetworkAccessManager Test Realm\"\r\n"
"Content-Length: 4\r\n"
"Connection: close\r\n"
- "Content-Type: text/plain\r\n"
+ "content-type: text/plain\r\n"
"\r\n"
"auth";
- QRegularExpression rx("Authorization: Basic ([^\r\n]*)\r\n");
+ QRegularExpression rx("authorization: Basic ([^\r\n]*)\r\n");
QRegularExpressionMatch match = rx.match(receivedData);
if (match.hasMatch()) {
if (QByteArray::fromBase64(match.captured(1).toLatin1()) == "login:password") {
dataToTransmit =
"HTTP/1.0 200 OK\r\n"
- "Content-Type: text/plain\r\n"
+ "content-type: text/plain\r\n"
"Content-Length: 2\r\n"
"\r\n"
"OK";
@@ -8188,7 +8726,7 @@ void tst_QNetworkReply::synchronousAuthenticationCache()
// the server thread, because the client is never returning to the
// event loop
QScopedPointer<QThread, QThreadCleanup> serverThread(new QThread);
- QScopedPointer<MiniHttpServer, QDeleteLaterCleanup> server(new MiniAuthServer(serverThread.data()));
+ QScopedPointer<MiniHttpServer, QScopedPointerDeleteLater> server(new MiniAuthServer(serverThread.data()));
server->doClose = true;
//1) URL without credentials, we are not authenticated
@@ -8327,31 +8865,33 @@ void tst_QNetworkReply::ftpAuthentication()
void tst_QNetworkReply::emitErrorForAllReplies() // QTBUG-36890
{
// port 100 is not well-known and should be closed
- QList<QUrl> urls = QList<QUrl>() << QUrl("http://localhost:100/request1")
- << QUrl("http://localhost:100/request2")
- << QUrl("http://localhost:100/request3");
- QList<QNetworkReply *> replies;
- QList<QSignalSpy *> errorSpies;
- QList<QSignalSpy *> finishedSpies;
- for (int a = 0; a < urls.count(); ++a) {
- QNetworkRequest request(urls.at(a));
+ const QUrl urls[] = {
+ QUrl("http://localhost:100/request1"),
+ QUrl("http://localhost:100/request2"),
+ QUrl("http://localhost:100/request3"),
+ };
+ constexpr auto NUrls = std::size(urls);
+
+ std::unique_ptr<QNetworkReply, QScopedPointerDeleteLater> replies[NUrls];
+ std::optional<QSignalSpy> errorSpies[NUrls];
+ std::optional<QSignalSpy> finishedSpies[NUrls];
+
+ for (size_t i = 0; i < NUrls; ++i) {
+ QNetworkRequest request(urls[i]);
QNetworkReply *reply = manager.get(request);
- replies.append(reply);
- QSignalSpy *errorSpy = new QSignalSpy(reply, SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
- errorSpies.append(errorSpy);
- QSignalSpy *finishedSpy = new QSignalSpy(reply, SIGNAL(finished()));
- finishedSpies.append(finishedSpy);
+ replies[i].reset(reply);
+ errorSpies[i].emplace(reply, SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
+ finishedSpies[i].emplace(reply, SIGNAL(finished()));
QObject::connect(reply, SIGNAL(finished()), SLOT(emitErrorForAllRepliesSlot()));
}
+
QTestEventLoop::instance().enterLoop(10);
QVERIFY(!QTestEventLoop::instance().timeout());
- for (int a = 0; a < urls.count(); ++a) {
- QVERIFY(replies.at(a)->isFinished());
- QCOMPARE(errorSpies.at(a)->count(), 1);
- errorSpies.at(a)->deleteLater();
- QCOMPARE(finishedSpies.at(a)->count(), 1);
- finishedSpies.at(a)->deleteLater();
- replies.at(a)->deleteLater();
+
+ for (size_t i = 0; i < NUrls; ++i) {
+ QVERIFY(replies[i]->isFinished());
+ QCOMPARE(errorSpies[i]->size(), 1);
+ QCOMPARE(finishedSpies[i]->size(), 1);
}
}
@@ -8399,7 +8939,7 @@ public:
return ret;
}
virtual bool atEnd() const override { return buffer.atEnd(); }
- virtual qint64 size() const override { return data.length(); }
+ virtual qint64 size() const override { return data.size(); }
qint64 bytesAvailable() const override
{
return buffer.bytesAvailable() + QIODevice::bytesAvailable();
@@ -8420,9 +8960,9 @@ protected slots:
void tst_QNetworkReply::putWithRateLimiting()
{
QFile reference(testDataDir + "/rfc3252.txt");
- reference.open(QIODevice::ReadOnly);
+ QVERIFY(reference.open(QIODevice::ReadOnly));
QByteArray data = reference.readAll();
- QVERIFY(data.length() > 0);
+ QVERIFY(data.size() > 0);
QUrl url = QUrl::fromUserInput("http://" + QtNetworkSettings::httpServerName()+ "/qtest/cgi-bin/echo.cgi?");
@@ -8437,7 +8977,7 @@ void tst_QNetworkReply::putWithRateLimiting()
QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
QByteArray uploadedData = reply->readAll();
- QCOMPARE(uploadedData.length(), data.length());
+ QCOMPARE(uploadedData.size(), data.size());
QCOMPARE(uploadedData, data);
}
@@ -8469,8 +9009,8 @@ void tst_QNetworkReply::ioHttpSingleRedirect()
QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply));
// Redirected and finished should be emitted exactly once
- QCOMPARE(redSpy.count(), 1);
- QCOMPARE(finSpy.count(), 1);
+ QCOMPARE(redSpy.size(), 1);
+ QCOMPARE(finSpy.size(), 1);
// Original URL should not be changed after redirect
QCOMPARE(request.url(), localhost);
@@ -8516,8 +9056,8 @@ void tst_QNetworkReply::ioHttpChangeMaxRedirects()
QCOMPARE(waitForFinish(reply), int(Failure));
- QCOMPARE(redSpy.count(), request.maximumRedirectsAllowed());
- QCOMPARE(spy.count(), 1);
+ QCOMPARE(redSpy.size(), request.maximumRedirectsAllowed());
+ QCOMPARE(spy.size(), 1);
QCOMPARE(reply->error(), QNetworkReply::TooManyRedirectsError);
// Increase max redirects to allow successful completion
@@ -8528,7 +9068,7 @@ void tst_QNetworkReply::ioHttpChangeMaxRedirects()
QVERIFY2(waitForFinish(reply2) == Success, msgWaitForFinished(reply2));
- QCOMPARE(redSpy2.count(), 2);
+ QCOMPARE(redSpy2.size(), 2);
QCOMPARE(reply2->url(), server3Url);
QCOMPARE(reply2->error(), QNetworkReply::NoError);
QVERIFY(validateRedirectedResponseHeaders(reply2));
@@ -8541,7 +9081,7 @@ void tst_QNetworkReply::ioHttpRedirectErrors_data()
QTest::addColumn<QNetworkReply::NetworkError>("error");
QString tempRedirectReply = QString("HTTP/1.1 307 Temporary Redirect\r\n"
- "Content-Type: text/plain\r\n"
+ "content-type: text/plain\r\n"
"location: http://localhost:%1\r\n\r\n");
QTest::newRow("too-many-redirects") << "http://localhost" << tempRedirectReply << QNetworkReply::TooManyRedirectsError;
@@ -8661,8 +9201,8 @@ void tst_QNetworkReply::ioHttpRedirectPolicy()
QSignalSpy redirectSpy(reply.data(), SIGNAL(redirected(QUrl)));
QSignalSpy finishedSpy(reply.data(), SIGNAL(finished()));
QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply));
- QCOMPARE(finishedSpy.count(), 1);
- QCOMPARE(redirectSpy.count(), redirectCount);
+ QCOMPARE(finishedSpy.size(), 1);
+ QCOMPARE(redirectSpy.size(), redirectCount);
QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), statusCode);
QVERIFY(validateRedirectedResponseHeaders(reply) || statusCode != 200);
}
@@ -8745,7 +9285,7 @@ void tst_QNetworkReply::ioHttpRedirectPolicyErrors()
QSignalSpy spy(reply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
QCOMPARE(waitForFinish(reply), int(Failure));
- QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.size(), 1);
QCOMPARE(reply->error(), expectedError);
}
@@ -8795,7 +9335,7 @@ void tst_QNetworkReply::ioHttpUserVerifiedRedirect()
QSignalSpy finishedSpy(reply.data(), SIGNAL(finished()));
waitForFinish(reply);
- QCOMPARE(finishedSpy.count(), 1);
+ QCOMPARE(finishedSpy.size(), 1);
QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), statusCode);
QVERIFY(validateRedirectedResponseHeaders(reply) || statusCode != 200);
}
@@ -8807,7 +9347,7 @@ void tst_QNetworkReply::ioHttpCookiesDuringRedirect()
const QString cookieHeader = QStringLiteral("Set-Cookie: hello=world; Path=/;\r\n");
QString redirect = tempRedirectReplyStr();
// Insert 'cookieHeader' before the final \r\n
- redirect.insert(redirect.length() - 2, cookieHeader);
+ redirect.insert(redirect.size() - 2, cookieHeader);
QUrl url("http://localhost/");
url.setPort(target.serverPort());
@@ -8824,7 +9364,7 @@ void tst_QNetworkReply::ioHttpCookiesDuringRedirect()
manager.setRedirectPolicy(oldRedirectPolicy);
QVERIFY(waitForFinish(reply) == Success);
- QVERIFY(target.receivedData.contains("\r\nCookie: hello=world\r\n"));
+ QVERIFY(target.receivedData.contains("\r\ncookie: hello=world\r\n"));
QVERIFY(validateRedirectedResponseHeaders(reply));
}
@@ -8849,7 +9389,7 @@ void tst_QNetworkReply::ioHttpRedirect()
targetUrl.setPort(target.serverPort());
QString redirectReply = QStringLiteral("HTTP/1.1 %1\r\n"
- "Content-Type: text/plain\r\n"
+ "content-type: text/plain\r\n"
"location: %2\r\n"
"\r\n").arg(status, targetUrl.toString());
MiniHttpServer redirectServer(redirectReply.toLatin1(), false);
@@ -8867,6 +9407,7 @@ void tst_QNetworkReply::ioHttpRedirect()
QVERIFY(validateRedirectedResponseHeaders(reply));
}
+#if QT_CONFIG(networkdiskcache)
/*
Test that, if we load a redirect from cache, we don't treat the request to
the destination of the redirect as a redirect.
@@ -8877,7 +9418,7 @@ void tst_QNetworkReply::ioHttpRedirectWithCache()
{
// Disallow caching the result so that the second request must also send the request
QByteArray http200ResponseNoCache = "HTTP/1.1 200 OK\r\n"
- "Content-Type: text/plain\r\n"
+ "content-type: text/plain\r\n"
"Cache-Control: no-cache\r\n"
"\r\nHello";
@@ -8887,7 +9428,7 @@ void tst_QNetworkReply::ioHttpRedirectWithCache()
// A cache-able redirect reply
QString redirectReply = QStringLiteral("HTTP/1.1 308\r\n"
- "Content-Type: text/plain\r\n"
+ "content-type: text/plain\r\n"
"location: %1\r\n"
"Cache-Control: max-age=3600\r\n"
"\r\nYou're being redirected").arg(targetUrl.toString());
@@ -8924,6 +9465,7 @@ void tst_QNetworkReply::ioHttpRedirectWithCache()
QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
QVERIFY(validateRedirectedResponseHeaders(reply));
}
+#endif
void tst_QNetworkReply::ioHttpRedirectFromLocalToRemote()
{
@@ -8999,7 +9541,7 @@ void tst_QNetworkReply::ioHttpRedirectPostPut()
QUrl targetUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/cgi-bin/md5sum.cgi");
QString redirectReply = QStringLiteral("HTTP/1.1 %1\r\n"
- "Content-Type: text/plain\r\n"
+ "content-type: text/plain\r\n"
"location: %2\r\n"
"\r\n").arg(status, targetUrl.toString());
MiniHttpServer redirectServer(redirectReply.toLatin1());
@@ -9018,6 +9560,7 @@ void tst_QNetworkReply::ioHttpRedirectPostPut()
QCOMPARE(reply->readAll().trimmed(), md5sum(data).toHex());
}
+#if QT_CONFIG(http)
void tst_QNetworkReply::ioHttpRedirectMultipartPost_data()
{
postToHttpMultipart_data();
@@ -9078,6 +9621,7 @@ void tst_QNetworkReply::ioHttpRedirectMultipartPost()
// QEXPECT_FAIL("nested", "the server does not understand nested multipart messages", Continue); // see above
QCOMPARE(replyData, expectedReplyData);
}
+#endif
void tst_QNetworkReply::ioHttpRedirectDelete()
{
@@ -9153,7 +9697,7 @@ void tst_QNetworkReply::ioHttpRedirectWithUploadDevice()
targetUrl.setPort(target.serverPort());
QString redirectReply = QStringLiteral("HTTP/1.1 %1\r\n"
- "Content-Type: text/plain\r\n"
+ "content-type: text/plain\r\n"
"location: %2\r\n"
"\r\n").arg(status, targetUrl.toString());
MiniHttpServer redirectServer(redirectReply.toLatin1());
@@ -9187,8 +9731,8 @@ void tst_QNetworkReply::ioHttpRedirectWithUploadDevice()
// we shouldn't send Content-Length with not content (esp. for GET)
QVERIFY2(!target.receivedData.contains("Content-Length"),
"Target server should not have received a Content-Length header");
- QVERIFY2(!target.receivedData.contains("Content-Type"),
- "Target server should not have received a Content-Type header");
+ QVERIFY2(!target.receivedData.contains("content-type"),
+ "Target server should not have received a content-type header");
}
}
@@ -9234,7 +9778,7 @@ public slots:
//qDebug() << m_receivedData.left(m_receivedData.indexOf("\r\n\r\n"));
m_receivedData = m_receivedData.mid(m_receivedData.indexOf("\r\n\r\n")+4); // check only actual data
}
- if (m_receivedData.length() > 0 && !m_expectedData.startsWith(m_receivedData)) {
+ if (m_receivedData.size() > 0 && !m_expectedData.startsWith(m_receivedData)) {
// We had received some data but it is corrupt!
qDebug() << "CORRUPT" << m_receivedData.size();
@@ -9386,7 +9930,7 @@ void tst_QNetworkReply::autoDeleteRepliesAttribute()
QSignalSpy finishedSpy(reply, &QNetworkReply::finished);
QSignalSpy destroyedSpy(reply, &QObject::destroyed);
QVERIFY(finishedSpy.wait());
- QCOMPARE(destroyedSpy.count(), 0);
+ QCOMPARE(destroyedSpy.size(), 0);
QVERIFY(destroyedSpy.wait());
}
{
@@ -9397,7 +9941,7 @@ void tst_QNetworkReply::autoDeleteRepliesAttribute()
QSignalSpy finishedSpy(reply, &QNetworkReply::finished);
QSignalSpy destroyedSpy(reply, &QObject::destroyed);
QVERIFY(finishedSpy.wait());
- QCOMPARE(destroyedSpy.count(), 0);
+ QCOMPARE(destroyedSpy.size(), 0);
QVERIFY(destroyedSpy.wait());
}
// Now repeated, but without the attribute to make sure it does not get deleted automatically.
@@ -9411,10 +9955,10 @@ void tst_QNetworkReply::autoDeleteRepliesAttribute()
QSignalSpy finishedSpy(reply.data(), &QNetworkReply::finished);
QSignalSpy destroyedSpy(reply.data(), &QObject::destroyed);
QVERIFY(finishedSpy.wait());
- QCOMPARE(destroyedSpy.count(), 0);
+ QCOMPARE(destroyedSpy.size(), 0);
QCoreApplication::processEvents();
QCoreApplication::processEvents();
- QCOMPARE(destroyedSpy.count(), 0);
+ QCOMPARE(destroyedSpy.size(), 0);
}
{
// Post
@@ -9423,10 +9967,10 @@ void tst_QNetworkReply::autoDeleteRepliesAttribute()
QSignalSpy finishedSpy(reply.data(), &QNetworkReply::finished);
QSignalSpy destroyedSpy(reply.data(), &QObject::destroyed);
QVERIFY(finishedSpy.wait());
- QCOMPARE(destroyedSpy.count(), 0);
+ QCOMPARE(destroyedSpy.size(), 0);
QCoreApplication::processEvents();
QCoreApplication::processEvents();
- QCOMPARE(destroyedSpy.count(), 0);
+ QCOMPARE(destroyedSpy.size(), 0);
}
}
@@ -9447,7 +9991,7 @@ void tst_QNetworkReply::autoDeleteReplies()
QSignalSpy finishedSpy(reply, &QNetworkReply::finished);
QSignalSpy destroyedSpy(reply, &QObject::destroyed);
QVERIFY(finishedSpy.wait());
- QCOMPARE(destroyedSpy.count(), 0);
+ QCOMPARE(destroyedSpy.size(), 0);
QVERIFY(destroyedSpy.wait());
}
{
@@ -9457,7 +10001,7 @@ void tst_QNetworkReply::autoDeleteReplies()
QSignalSpy finishedSpy(reply, &QNetworkReply::finished);
QSignalSpy destroyedSpy(reply, &QObject::destroyed);
QVERIFY(finishedSpy.wait());
- QCOMPARE(destroyedSpy.count(), 0);
+ QCOMPARE(destroyedSpy.size(), 0);
QVERIFY(destroyedSpy.wait());
}
// Here we repeat the test, but override the auto-deletion in the QNetworkRequest
@@ -9472,10 +10016,10 @@ void tst_QNetworkReply::autoDeleteReplies()
QSignalSpy finishedSpy(reply.data(), &QNetworkReply::finished);
QSignalSpy destroyedSpy(reply.data(), &QObject::destroyed);
QVERIFY(finishedSpy.wait());
- QCOMPARE(destroyedSpy.count(), 0);
+ QCOMPARE(destroyedSpy.size(), 0);
QCoreApplication::processEvents();
QCoreApplication::processEvents();
- QCOMPARE(destroyedSpy.count(), 0);
+ QCOMPARE(destroyedSpy.size(), 0);
}
{
// Post
@@ -9485,10 +10029,10 @@ void tst_QNetworkReply::autoDeleteReplies()
QSignalSpy finishedSpy(reply.data(), &QNetworkReply::finished);
QSignalSpy destroyedSpy(reply.data(), &QObject::destroyed);
QVERIFY(finishedSpy.wait());
- QCOMPARE(destroyedSpy.count(), 0);
+ QCOMPARE(destroyedSpy.size(), 0);
QCoreApplication::processEvents();
QCoreApplication::processEvents();
- QCOMPARE(destroyedSpy.count(), 0);
+ QCOMPARE(destroyedSpy.size(), 0);
}
// Now we repeat the test with autoDeleteReplies set to false
cleanup.dismiss();
@@ -9500,10 +10044,10 @@ void tst_QNetworkReply::autoDeleteReplies()
QSignalSpy finishedSpy(reply.data(), &QNetworkReply::finished);
QSignalSpy destroyedSpy(reply.data(), &QObject::destroyed);
QVERIFY(finishedSpy.wait());
- QCOMPARE(destroyedSpy.count(), 0);
+ QCOMPARE(destroyedSpy.size(), 0);
QCoreApplication::processEvents();
QCoreApplication::processEvents();
- QCOMPARE(destroyedSpy.count(), 0);
+ QCOMPARE(destroyedSpy.size(), 0);
}
{
// Post
@@ -9512,90 +10056,74 @@ void tst_QNetworkReply::autoDeleteReplies()
QSignalSpy finishedSpy(reply.data(), &QNetworkReply::finished);
QSignalSpy destroyedSpy(reply.data(), &QObject::destroyed);
QVERIFY(finishedSpy.wait());
- QCOMPARE(destroyedSpy.count(), 0);
+ QCOMPARE(destroyedSpy.size(), 0);
QCoreApplication::processEvents();
QCoreApplication::processEvents();
- QCOMPARE(destroyedSpy.count(), 0);
+ QCOMPARE(destroyedSpy.size(), 0);
}
}
-void tst_QNetworkReply::getWithTimeout()
+#if QT_CONFIG(http) || defined (Q_OS_WASM)
+void tst_QNetworkReply::requestWithTimeout_data()
{
- MiniHttpServer server(tst_QNetworkReply::httpEmpty200Response, false);
-
- QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort())));
- QNetworkReplyPtr reply(manager.get(request));
- QSignalSpy spy(reply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
-
- QCOMPARE(waitForFinish(reply), int(Success));
-
- QCOMPARE(spy.count(), 0);
- QVERIFY(reply->error() == QNetworkReply::NoError);
-
- request.setTransferTimeout(1000);
- server.stopTransfer = true;
-
- QNetworkReplyPtr reply2(manager.get(request));
- QSignalSpy spy2(reply2.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
-
- QCOMPARE(waitForFinish(reply2), int(Failure));
-
- QCOMPARE(spy2.count(), 1);
- QVERIFY(reply2->error() == QNetworkReply::OperationCanceledError);
-
- request.setTransferTimeout(0);
- manager.setTransferTimeout(1000);
+ using Operation = QNetworkAccessManager::Operation;
+ QTest::addColumn<Operation>("method");
+ QTest::addColumn<int>("reqInt");
+ QTest::addColumn<std::chrono::milliseconds>("reqChrono");
+ QTest::addColumn<int>("mgrInt");
+ QTest::addColumn<std::chrono::milliseconds>("mgrChrono");
- QNetworkReplyPtr reply3(manager.get(request));
- QSignalSpy spy3(reply3.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
-
- QCOMPARE(waitForFinish(reply3), int(Failure));
+ QTest::addRow("get_req_int") << Operation::GetOperation << 500 << 0ms << 0 << 0ms;
+ QTest::addRow("get_req_chrono") << Operation::GetOperation << 0 << 500ms << 0 << 0ms;
+ QTest::addRow("get_mgr_int") << Operation::GetOperation << 0 << 0ms << 500 << 0ms;
+ QTest::addRow("get_mgr_chrono") << Operation::GetOperation << 0 << 0ms << 0 << 500ms;
- QCOMPARE(spy3.count(), 1);
- QVERIFY(reply3->error() == QNetworkReply::OperationCanceledError);
-
- manager.setTransferTimeout(0);
+ QTest::addRow("post_req_int") << Operation::PostOperation << 500 << 0ms << 0 << 0ms;
+ QTest::addRow("post_req_chrono") << Operation::PostOperation << 0 << 500ms << 0 << 0ms;
+ QTest::addRow("post_mgr_int") << Operation::PostOperation << 0 << 0ms << 500 << 0ms;
+ QTest::addRow("post_mgr_chrono") << Operation::PostOperation << 0 << 0ms << 0 << 500ms;
}
-void tst_QNetworkReply::postWithTimeout()
+void tst_QNetworkReply::requestWithTimeout()
{
- MiniHttpServer server(tst_QNetworkReply::httpEmpty200Response, false);
+ QFETCH(QNetworkAccessManager::Operation, method);
+ QFETCH(int, reqInt);
+ QFETCH(int, mgrInt);
+ QFETCH(std::chrono::milliseconds, reqChrono);
+ QFETCH(std::chrono::milliseconds, mgrChrono);
+ const auto data = "some data"_ba;
+ // Manager instance remains between case runs => always reset it's transferTimeout to
+ // ensure setting its transferTimeout in this case has effect
+ manager.setTransferTimeout(0ms);
+ auto cleanup = qScopeGuard([this] { manager.setTransferTimeout(0ms); });
- QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort())));
- request.setRawHeader("Content-Type", "application/octet-stream");
- QByteArray postData("Just some nonsense");
- QNetworkReplyPtr reply(manager.post(request, postData));
- QSignalSpy spy(reply.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
-
- QCOMPARE(waitForFinish(reply), int(Success));
-
- QCOMPARE(spy.count(), 0);
- QVERIFY(reply->error() == QNetworkReply::NoError);
-
- request.setTransferTimeout(1000);
+ MiniHttpServer server(tst_QNetworkReply::httpEmpty200Response, false);
server.stopTransfer = true;
- QNetworkReplyPtr reply2(manager.post(request, postData));
- QSignalSpy spy2(reply2.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
-
- QCOMPARE(waitForFinish(reply2), int(Failure));
-
- QCOMPARE(spy2.count(), 1);
- QVERIFY(reply2->error() == QNetworkReply::OperationCanceledError);
-
- request.setTransferTimeout(0);
- manager.setTransferTimeout(1000);
-
- QNetworkReplyPtr reply3(manager.post(request, postData));
- QSignalSpy spy3(reply3.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError)));
-
- QCOMPARE(waitForFinish(reply3), int(Failure));
+ QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort())));
+ request.setRawHeader("content-type", "application/octet-stream");
+ if (reqInt > 0)
+ request.setTransferTimeout(reqInt);
+ if (reqChrono > 0ms)
+ request.setTransferTimeout(reqChrono);
+ if (mgrInt > 0)
+ manager.setTransferTimeout(mgrInt);
+ if (mgrChrono > 0ms)
+ manager.setTransferTimeout(mgrChrono);
- QCOMPARE(spy3.count(), 1);
- QVERIFY(reply3->error() == QNetworkReply::OperationCanceledError);
+ QNetworkReplyPtr reply;
+ if (method == QNetworkAccessManager::GetOperation)
+ reply.reset(manager.get(request));
+ else if (method == QNetworkAccessManager::PostOperation)
+ reply.reset(manager.post(request, data));
+ QVERIFY(reply);
- manager.setTransferTimeout(0);
+ QSignalSpy spy(reply.data(), &QNetworkReply::errorOccurred);
+ QCOMPARE(waitForFinish(reply), int(Failure));
+ QCOMPARE(spy.size(), 1);
+ QCOMPARE(reply->error(), QNetworkReply::OperationCanceledError);
}
+#endif
void tst_QNetworkReply::moreActivitySignals_data()
{
@@ -9626,7 +10154,7 @@ void tst_QNetworkReply::moreActivitySignals()
QNetworkRequest request(url);
QNetworkReplyPtr reply;
if (postWithData) {
- request.setRawHeader("Content-Type", "text/plain");
+ request.setRawHeader("content-type", "text/plain");
reply.reset(manager.post(request, "Hello, world!"));
} else {
reply.reset(manager.get(request));
@@ -9636,18 +10164,18 @@ void tst_QNetworkReply::moreActivitySignals()
QSignalSpy spy3(reply.data(), SIGNAL(metaDataChanged()));
QSignalSpy spy4(reply.data(), SIGNAL(finished()));
spy1.wait();
- QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy1.size(), 1);
spy2.wait();
- QCOMPARE(spy2.count(), 1);
+ QCOMPARE(spy2.size(), 1);
spy3.wait();
- QCOMPARE(spy3.count(), 1);
+ QCOMPARE(spy3.size(), 1);
spy4.wait();
- QCOMPARE(spy4.count(), 1);
+ QCOMPARE(spy4.size(), 1);
QVERIFY(reply->error() == QNetworkReply::NoError);
// Second request will not send socketStartedConnecting because of keep-alive, so don't check it.
QNetworkReplyPtr secondreply;
if (postWithData) {
- request.setRawHeader("Content-Type", "text/plain");
+ request.setRawHeader("content-type", "text/plain");
secondreply.reset(manager.post(request, "Hello, world!"));
} else {
secondreply.reset(manager.get(request));
@@ -9656,11 +10184,11 @@ void tst_QNetworkReply::moreActivitySignals()
QSignalSpy secondspy3(secondreply.data(), SIGNAL(metaDataChanged()));
QSignalSpy secondspy4(secondreply.data(), SIGNAL(finished()));
secondspy2.wait();
- QCOMPARE(secondspy2.count(), 1);
+ QCOMPARE(secondspy2.size(), 1);
secondspy3.wait();
- QCOMPARE(secondspy3.count(), 1);
+ QCOMPARE(secondspy3.size(), 1);
secondspy4.wait();
- QCOMPARE(secondspy4.count(), 1);
+ QCOMPARE(secondspy4.size(), 1);
QVERIFY(secondreply->error() == QNetworkReply::NoError);
}
@@ -9734,7 +10262,7 @@ void tst_QNetworkReply::contentEncoding()
QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort())));
if (!decompress) {
// This disables decompression of the received content:
- request.setRawHeader("Accept-Encoding", QLatin1String("%1").arg(encoding).toLatin1());
+ request.setRawHeader("accept-encoding", QLatin1String("%1").arg(encoding).toLatin1());
// This disables the zerocopy optimization
request.setAttribute(QNetworkRequest::MaximumDownloadBufferSizeAttribute, 0);
}
@@ -9746,7 +10274,7 @@ void tst_QNetworkReply::contentEncoding()
{
// Check that we included the content encoding method in our Accept-Encoding header
const QByteArray &receivedData = server.receivedData;
- int start = receivedData.indexOf("Accept-Encoding");
+ int start = receivedData.indexOf("accept-encoding");
QVERIFY(start != -1);
int end = receivedData.indexOf("\r\n", start);
QVERIFY(end != -1);
@@ -9768,6 +10296,7 @@ void tst_QNetworkReply::contentEncoding()
}
}
+#if QT_CONFIG(http)
void tst_QNetworkReply::contentEncodingBigPayload_data()
{
QTest::addColumn<QByteArray>("encoding");
@@ -9826,6 +10355,7 @@ void tst_QNetworkReply::contentEncodingBigPayload()
}
QCOMPARE(total, expectedSize);
}
+#endif
void tst_QNetworkReply::cacheWithContentEncoding_data()
{
@@ -10008,6 +10538,143 @@ void tst_QNetworkReply::notFoundWithCompression()
QCOMPARE(reply->readAll(), expected);
}
+#if QT_CONFIG(http)
+void tst_QNetworkReply::qhttpPartDebug_data()
+{
+ QTest::addColumn<QByteArray>("header_data");
+ QTest::addColumn<QByteArray>("raw_header_data");
+ QTest::addColumn<QList<QByteArray>>("expected_header_values");
+ QTest::addColumn<bool>("overwrite");
+
+ QTest::newRow("header-data-set") << "form-data; name=\"prompt\""_ba << ""_ba
+ << (QList<QByteArray>() << "form-data; name=\"prompt\""_ba) << false;
+ QTest::newRow("raw-header-data-set") << ""_ba << "thisismykeyherebutnotreally"_ba
+ << (QList<QByteArray>() << "thisismykeyherebutnotreally"_ba) << false;
+ QTest::newRow("both-set") << "form-data; name=\"prompt\""_ba
+ << "thisismykeyherebutnotreally"_ba
+ << (QList<QByteArray>()
+ << "form-data; name=\"prompt\""_ba
+ << "thisismykeyherebutnotreally"_ba) << false;
+ QTest::newRow("overwrite") << "form-data; name=\"prompt\""_ba
+ << "thisismykeyherebutnotreally"_ba
+ << (QList<QByteArray>()
+ << "thisismykeyherebutnotreally"_ba
+ << "thisismykeyherebutnotreally"_ba) << true;
+}
+
+void tst_QNetworkReply::qhttpPartDebug()
+{
+ QFETCH(const QByteArray, header_data);
+ QFETCH(const QByteArray, raw_header_data);
+ QFETCH(const QList<QByteArray>, expected_header_values);
+ QFETCH(bool, overwrite);
+
+ QHttpPart httpPart;
+
+ if (!header_data.isEmpty())
+ httpPart.setHeader(QNetworkRequest::ContentDispositionHeader, header_data);
+
+ if (!raw_header_data.isEmpty())
+ httpPart.setRawHeader("Authorization", raw_header_data);
+
+ if (overwrite)
+ httpPart.setRawHeader("Content-Disposition", raw_header_data);
+
+ QByteArray msg;
+ {
+ QBuffer buf(&msg);
+ QVERIFY(buf.open(QIODevice::WriteOnly));
+ QDebug debug(&buf);
+ debug << httpPart;
+ }
+
+ for (const auto &value : expected_header_values)
+ QVERIFY2(msg.contains(value), "Missing header value: " + value);
+}
+
+void tst_QNetworkReply::qtbug68821proxyError_data()
+{
+ QTest::addColumn<QString>("proxyHost");
+ QTest::addColumn<QString>("scheme");
+ QTest::addColumn<QNetworkReply::NetworkError>("error");
+
+ QTest::newRow("invalidhost+http") << "this-host-will-never-exist.qt-project.org"
+ << "http" << QNetworkReply::ProxyNotFoundError;
+ QTest::newRow("localhost+http") << "localhost"
+ << "http" << QNetworkReply::ProxyConnectionRefusedError;
+#ifndef QT_NO_SSL
+ QTest::newRow("invalidhost+https") << "this-host-will-never-exist.qt-project.org"
+ << "https" << QNetworkReply::ProxyNotFoundError;
+ QTest::newRow("localhost+https") << "localhost"
+ << "https" << QNetworkReply::ProxyConnectionRefusedError;
+#endif
+}
+
+void tst_QNetworkReply::qtbug68821proxyError()
+{
+ auto getUnusedPort = []() -> std::optional<quint16> {
+ QTcpServer probeServer;
+ if (!probeServer.listen())
+ return std::nullopt;
+ // If we can listen on it, it was unused, and hopefully is also
+ // still unused after we stop listening.
+ return probeServer.serverPort();
+ };
+
+ auto proxyPort = getUnusedPort();
+ QVERIFY(proxyPort);
+
+ QFETCH(QString, proxyHost);
+ QNetworkProxy proxy(QNetworkProxy::HttpProxy, proxyHost, proxyPort.value());
+
+ manager.setProxy(proxy);
+
+ QFETCH(QString, scheme);
+ QNetworkReply *reply = manager.get(QNetworkRequest(QUrl(scheme + "://example.com")));
+ QSignalSpy spy(reply, &QNetworkReply::errorOccurred);
+ QVERIFY(spy.isValid());
+
+ QVERIFY(spy.wait(15000));
+
+ QFETCH(QNetworkReply::NetworkError, error);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0), error);
+}
+#endif
+
+void tst_QNetworkReply::abortAndError()
+{
+ const QByteArray response =
+ R"(HTTP/1.0 500 Internal Server Error
+Content-Length: 12
+Content-Type: text/plain
+
+Hello World!)"_ba;
+
+ MiniHttpServer server(response);
+
+ QNetworkAccessManager manager;
+ QNetworkRequest req(QUrl("http://127.0.0.1:" + QString::number(server.serverPort())));
+ std::unique_ptr<QNetworkReply> reply(manager.post(req, "my data goes here"_ba));
+ QSignalSpy errorSignal(reply.get(), &QNetworkReply::errorOccurred);
+ QSignalSpy finishedSignal(reply.get(), &QNetworkReply::finished);
+
+ reply->abort();
+
+ // We don't want to print this warning in this case because it is impossible
+ // for users to avoid it.
+ QTest::failOnWarning("QNetworkReplyImplPrivate::error: Internal problem, this method must only "
+ "be called once.");
+ // Process any signals from the http thread:
+ QTest::qWait(1s);
+ if (QTest::currentTestFailed())
+ return;
+
+ QCOMPARE(finishedSignal.count(), 1);
+ QCOMPARE(errorSignal.count(), 1);
+ QCOMPARE(reply->error(), QNetworkReply::OperationCanceledError);
+}
+
// NOTE: This test must be last testcase in tst_qnetworkreply!
void tst_QNetworkReply::parentingRepliesToTheApp()
{
diff --git a/tests/auto/network/access/qnetworkreply_local/CMakeLists.txt b/tests/auto/network/access/qnetworkreply_local/CMakeLists.txt
new file mode 100644
index 0000000000..13a60afb13
--- /dev/null
+++ b/tests/auto/network/access/qnetworkreply_local/CMakeLists.txt
@@ -0,0 +1,9 @@
+qt_internal_add_test(tst_qnetworkreply_local
+ SOURCES
+ minihttpserver.h
+ tst_qnetworkreply_local.cpp
+ LIBRARIES
+ Qt::CorePrivate
+ Qt::NetworkPrivate
+ BUNDLE_ANDROID_OPENSSL_LIBS
+)
diff --git a/tests/auto/network/access/qnetworkreply_local/minihttpserver.h b/tests/auto/network/access/qnetworkreply_local/minihttpserver.h
new file mode 100644
index 0000000000..eb0697a6f8
--- /dev/null
+++ b/tests/auto/network/access/qnetworkreply_local/minihttpserver.h
@@ -0,0 +1,246 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef MINIHTTPSERVER_H
+#define MINIHTTPSERVER_H
+
+#include <QtNetwork/qtnetworkglobal.h>
+
+#include <QtNetwork/qtcpserver.h>
+#include <QtNetwork/qtcpsocket.h>
+#include <QtNetwork/qlocalsocket.h>
+#if QT_CONFIG(ssl)
+# include <QtNetwork/qsslsocket.h>
+#endif
+#if QT_CONFIG(localserver)
+# include <QtNetwork/qlocalserver.h>
+#endif
+
+#include <QtCore/qpointer.h>
+#include <QtCore/qhash.h>
+
+#include <utility>
+
+static inline QByteArray default200Response()
+{
+ return QByteArrayLiteral("HTTP/1.1 200 OK\r\n"
+ "Content-Type: text/plain\r\n"
+ "Content-Length: 12\r\n"
+ "\r\n"
+ "Hello World!");
+}
+class MiniHttpServerV2 : public QObject
+{
+ Q_OBJECT
+
+public:
+ struct State;
+
+#if QT_CONFIG(localserver)
+ void bind(QLocalServer *server)
+ {
+ Q_ASSERT(!localServer);
+ localServer = server;
+ connect(server, &QLocalServer::newConnection, this,
+ &MiniHttpServerV2::incomingLocalConnection);
+ }
+#endif
+
+ void bind(QTcpServer *server)
+ {
+ Q_ASSERT(!tcpServer);
+ tcpServer = server;
+ connect(server, &QTcpServer::pendingConnectionAvailable, this,
+ &MiniHttpServerV2::incomingConnection);
+ }
+
+ void setDataToTransmit(QByteArray data) { dataToTransmit = std::move(data); }
+
+ void clearServerState()
+ {
+ auto copy = std::exchange(clientStates, {});
+ for (auto [socket, _] : copy.asKeyValueRange()) {
+ if (auto *tcpSocket = qobject_cast<QTcpSocket *>(socket))
+ tcpSocket->disconnectFromHost();
+ else if (auto *localSocket = qobject_cast<QLocalSocket *>(socket))
+ localSocket->disconnectFromServer();
+ else
+ Q_UNREACHABLE_RETURN();
+ socket->deleteLater();
+ }
+ }
+
+ bool hasPendingConnections() const
+ {
+ return
+#if QT_CONFIG(localserver)
+ (localServer && localServer->hasPendingConnections()) ||
+#endif
+ (tcpServer && tcpServer->hasPendingConnections());
+ }
+
+ QString addressForScheme(QStringView scheme) const
+ {
+ using namespace Qt::StringLiterals;
+ if (scheme.startsWith("unix"_L1) || scheme.startsWith("local"_L1)) {
+#if QT_CONFIG(localserver)
+ if (localServer)
+ return localServer->serverName();
+#endif
+ } else if (scheme == "http"_L1) {
+ if (tcpServer)
+ return "%1:%2"_L1.arg(tcpServer->serverAddress().toString(),
+ QString::number(tcpServer->serverPort()));
+ }
+ return {};
+ }
+
+ QList<State> peerStates() const { return clientStates.values(); }
+
+protected:
+#if QT_CONFIG(localserver)
+ void incomingLocalConnection()
+ {
+ auto *socket = localServer->nextPendingConnection();
+ connectSocketSignals(socket);
+ }
+#endif
+
+ void incomingConnection()
+ {
+ auto *socket = tcpServer->nextPendingConnection();
+ connectSocketSignals(socket);
+ }
+
+ void reply(QIODevice *socket)
+ {
+ Q_ASSERT(socket);
+ if (dataToTransmit.isEmpty()) {
+ emit socket->bytesWritten(0); // emulate having written the data
+ return;
+ }
+ if (!stopTransfer)
+ socket->write(dataToTransmit);
+ }
+
+private:
+ void connectSocketSignals(QIODevice *socket)
+ {
+ connect(socket, &QIODevice::readyRead, this, [this, socket]() { readyReadSlot(socket); });
+ connect(socket, &QIODevice::bytesWritten, this,
+ [this, socket]() { bytesWrittenSlot(socket); });
+#if QT_CONFIG(ssl)
+ if (auto *sslSocket = qobject_cast<QSslSocket *>(socket))
+ connect(sslSocket, &QSslSocket::sslErrors, this, &MiniHttpServerV2::slotSslErrors);
+#endif
+
+ if (auto *tcpSocket = qobject_cast<QTcpSocket *>(socket)) {
+ connect(tcpSocket, &QAbstractSocket::errorOccurred, this, &MiniHttpServerV2::slotError);
+ } else if (auto *localSocket = qobject_cast<QLocalSocket *>(socket)) {
+ connect(localSocket, &QLocalSocket::errorOccurred, this,
+ [this](QLocalSocket::LocalSocketError error) {
+ slotError(QAbstractSocket::SocketError(error));
+ });
+ } else {
+ Q_UNREACHABLE_RETURN();
+ }
+ }
+
+ void parseContentLength(State &st, QByteArrayView header)
+ {
+ qsizetype index = header.indexOf("\r\ncontent-length:");
+ if (index == -1)
+ return;
+ st.foundContentLength = true;
+
+ index += sizeof("\r\ncontent-length:") - 1;
+ const auto *end = std::find(header.cbegin() + index, header.cend(), '\r');
+ QByteArrayView num = header.mid(index, std::distance(header.cbegin() + index, end));
+ bool ok = false;
+ st.contentLength = num.toInt(&ok);
+ if (!ok)
+ st.contentLength = -1;
+ }
+
+private slots:
+#if QT_CONFIG(ssl)
+ void slotSslErrors(const QList<QSslError> &errors)
+ {
+ QTcpSocket *currentClient = qobject_cast<QTcpSocket *>(sender());
+ Q_ASSERT(currentClient);
+ qDebug() << "slotSslErrors" << currentClient->errorString() << errors;
+ }
+#endif
+ void slotError(QAbstractSocket::SocketError err)
+ {
+ QTcpSocket *currentClient = qobject_cast<QTcpSocket *>(sender());
+ Q_ASSERT(currentClient);
+ qDebug() << "slotError" << err << currentClient->errorString();
+ }
+
+public slots:
+
+ void readyReadSlot(QIODevice *socket)
+ {
+ if (stopTransfer)
+ return;
+ State &st = clientStates[socket];
+ st.receivedData += socket->readAll();
+ const qsizetype doubleEndlPos = st.receivedData.indexOf("\r\n\r\n");
+
+ if (doubleEndlPos != -1) {
+ const qsizetype endOfHeader = doubleEndlPos + 4;
+ st.contentRead = st.receivedData.size() - endOfHeader;
+
+ if (!st.checkedContentLength) {
+ parseContentLength(st, QByteArrayView(st.receivedData).first(endOfHeader));
+ st.checkedContentLength = true;
+ }
+
+ if (st.contentRead < st.contentLength)
+ return;
+
+ // multiple requests incoming, remove the bytes of the current one
+ if (multiple)
+ st.receivedData.remove(0, endOfHeader);
+
+ reply(socket);
+ }
+ }
+
+ void bytesWrittenSlot(QIODevice *socket)
+ {
+ // Disconnect and delete in next cycle (else Windows clients will fail with
+ // RemoteHostClosedError).
+ if (doClose && socket->bytesToWrite() == 0) {
+ disconnect(socket, nullptr, this, nullptr);
+ socket->deleteLater();
+ }
+ }
+
+private:
+ QByteArray dataToTransmit = default200Response();
+
+ QTcpServer *tcpServer = nullptr;
+#if QT_CONFIG(localserver)
+ QLocalServer *localServer = nullptr;
+#endif
+
+ QHash<QIODevice *, State> clientStates;
+
+public:
+ struct State
+ {
+ QByteArray receivedData;
+ qsizetype contentLength = 0;
+ qsizetype contentRead = 0;
+ bool checkedContentLength = false;
+ bool foundContentLength = false;
+ };
+
+ bool doClose = true;
+ bool multiple = false;
+ bool stopTransfer = false;
+};
+
+#endif // MINIHTTPSERVER_H
diff --git a/tests/auto/network/access/qnetworkreply_local/tst_qnetworkreply_local.cpp b/tests/auto/network/access/qnetworkreply_local/tst_qnetworkreply_local.cpp
new file mode 100644
index 0000000000..6d78c81593
--- /dev/null
+++ b/tests/auto/network/access/qnetworkreply_local/tst_qnetworkreply_local.cpp
@@ -0,0 +1,177 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtNetwork/qtnetworkglobal.h>
+
+#include <QtTest/qtest.h>
+
+#include <QtNetwork/qnetworkreply.h>
+#include <QtNetwork/qnetworkaccessmanager.h>
+
+#include "minihttpserver.h"
+
+using namespace Qt::StringLiterals;
+
+/*
+ The tests here are meant to be self-contained, using servers in the same
+ process if needed. This enables externals to more easily run the tests too.
+*/
+class tst_QNetworkReply_local : public QObject
+{
+ Q_OBJECT
+private slots:
+ void initTestCase_data();
+
+ void get();
+ void post();
+
+#if QT_CONFIG(localserver)
+ void fullServerName_data();
+ void fullServerName();
+#endif
+};
+
+void tst_QNetworkReply_local::initTestCase_data()
+{
+ QTest::addColumn<QString>("scheme");
+
+ QTest::newRow("http") << "http";
+#if QT_CONFIG(localserver)
+ QTest::newRow("unix") << "unix+http";
+ QTest::newRow("local") << "local+http"; // equivalent to unix, but test that it works
+#endif
+}
+
+static std::unique_ptr<MiniHttpServerV2> getServerForCurrentScheme()
+{
+ auto server = std::make_unique<MiniHttpServerV2>();
+ QFETCH_GLOBAL(QString, scheme);
+ if (scheme.startsWith("unix"_L1) || scheme.startsWith("local"_L1)) {
+#if QT_CONFIG(localserver)
+ QLocalServer *localServer = new QLocalServer(server.get());
+ localServer->listen(u"qt_networkreply_test_"_s
+ % QLatin1StringView(QTest::currentTestFunction())
+ % QString::number(QCoreApplication::applicationPid()));
+ server->bind(localServer);
+#endif
+ } else if (scheme == "http") {
+ QTcpServer *tcpServer = new QTcpServer(server.get());
+ tcpServer->listen(QHostAddress::LocalHost, 0);
+ server->bind(tcpServer);
+ }
+ return server;
+}
+
+static QUrl getUrlForCurrentScheme(MiniHttpServerV2 *server)
+{
+ QFETCH_GLOBAL(QString, scheme);
+ const QString address = server->addressForScheme(scheme);
+ const QString urlString = QLatin1StringView("%1://%2").arg(scheme, address);
+ return { urlString };
+}
+
+void tst_QNetworkReply_local::get()
+{
+ std::unique_ptr<MiniHttpServerV2> server = getServerForCurrentScheme();
+ const QUrl url = getUrlForCurrentScheme(server.get());
+
+ QNetworkAccessManager manager;
+ std::unique_ptr<QNetworkReply> reply(manager.get(QNetworkRequest(url)));
+
+ const bool res = QTest::qWaitFor([reply = reply.get()] { return reply->isFinished(); });
+ QVERIFY(res);
+
+ QCOMPARE(reply->readAll(), QByteArray("Hello World!"));
+ QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
+}
+
+void tst_QNetworkReply_local::post()
+{
+ std::unique_ptr<MiniHttpServerV2> server = getServerForCurrentScheme();
+ const QUrl url = getUrlForCurrentScheme(server.get());
+
+ QNetworkAccessManager manager;
+ const QByteArray payload = "Hello from the other side!"_ba;
+ QNetworkRequest req(url);
+ req.setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");
+ std::unique_ptr<QNetworkReply> reply(manager.post(req, payload));
+
+ const bool res = QTest::qWaitFor([reply = reply.get()] { return reply->isFinished(); });
+ QVERIFY(res);
+
+ QCOMPARE(reply->readAll(), QByteArray("Hello World!"));
+ QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
+
+ auto states = server->peerStates();
+ QCOMPARE(states.size(), 1);
+
+ const auto &firstRequest = states.at(0);
+
+ QVERIFY(firstRequest.checkedContentLength);
+ QCOMPARE(firstRequest.contentLength, payload.size());
+ QCOMPARE_GT(firstRequest.receivedData.size(), payload.size() + 4);
+ QCOMPARE(firstRequest.receivedData.last(payload.size() + 4), "\r\n\r\n" + payload);
+}
+
+#if QT_CONFIG(localserver)
+void tst_QNetworkReply_local::fullServerName_data()
+{
+#if defined(Q_OS_ANDROID) || defined(QT_PLATFORM_UIKIT)
+ QSKIP("While partially supported, the test as-is doesn't make sense on this platform.");
+#else
+
+ QTest::addColumn<QString>("hostAndPath");
+
+ QTest::newRow("dummy-host") << u"://irrelevant/test"_s;
+ QTest::newRow("no-host") << u":///test"_s;
+#endif
+}
+
+void tst_QNetworkReply_local::fullServerName()
+{
+ QFETCH_GLOBAL(QString, scheme);
+ if (!scheme.startsWith("unix"_L1) && !scheme.startsWith("local"_L1))
+ return; // only relevant for local sockets
+
+ MiniHttpServerV2 server;
+ QLocalServer localServer;
+
+ QString path;
+#ifdef Q_OS_WIN
+ path = uR"(\\.\pipe\qt_networkreply_test_fullServerName)"_s
+ % QString::number(QCoreApplication::applicationPid());
+#else
+ path = u"/tmp/qt_networkreply_test_fullServerName"_s
+ % QString::number(QCoreApplication::applicationPid()) % u".sock"_s;
+#endif
+
+ QVERIFY(localServer.listen(path));
+ server.bind(&localServer);
+
+ QFETCH(QString, hostAndPath);
+ QUrl url(scheme % hostAndPath);
+ QNetworkRequest req(url);
+ req.setAttribute(QNetworkRequest::FullLocalServerNameAttribute, path);
+
+ QNetworkAccessManager manager;
+ std::unique_ptr<QNetworkReply> reply(manager.get(req));
+
+ const bool res = QTest::qWaitFor([reply = reply.get()] { return reply->isFinished(); });
+ QVERIFY(res);
+
+ QCOMPARE(reply->readAll(), QByteArray("Hello World!"));
+ QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
+
+ const QByteArray receivedData = server.peerStates().at(0).receivedData;
+ const QByteArray expectedGet = "GET " % url.path().toUtf8() % " HTTP/1.1\r\n";
+ QVERIFY(receivedData.startsWith(expectedGet));
+
+ const QByteArray expectedHost = "host: " % url.host().toUtf8() % "\r\n";
+ QVERIFY(receivedData.contains(expectedHost));
+}
+#endif
+
+QTEST_MAIN(tst_QNetworkReply_local)
+
+#include "tst_qnetworkreply_local.moc"
+#include "moc_minihttpserver.cpp"
diff --git a/tests/auto/network/access/qnetworkrequest/CMakeLists.txt b/tests/auto/network/access/qnetworkrequest/CMakeLists.txt
index 2645b6e24f..2c4a7dd7ca 100644
--- a/tests/auto/network/access/qnetworkrequest/CMakeLists.txt
+++ b/tests/auto/network/access/qnetworkrequest/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qnetworkrequest.pro.
-
#####################################################################
## tst_qnetworkrequest Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qnetworkrequest LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qnetworkrequest
SOURCES
tst_qnetworkrequest.cpp
diff --git a/tests/auto/network/access/qnetworkrequest/tst_qnetworkrequest.cpp b/tests/auto/network/access/qnetworkrequest/tst_qnetworkrequest.cpp
index 315accd16b..f0b02ae91d 100644
--- a/tests/auto/network/access/qnetworkrequest/tst_qnetworkrequest.cpp
+++ b/tests/auto/network/access/qnetworkrequest/tst_qnetworkrequest.cpp
@@ -1,14 +1,19 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
-#include <QtCore/QUrl>
-#if QT_CONFIG(timezone)
-# include <QtCore/QTimeZone>
+
+#if QT_CONFIG(http)
+#include <QtNetwork/QHttp1Configuration>
+#include <QtNetwork/QHttp2Configuration>
#endif
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkCookie>
+#include <QtCore/QDateTime>
+#include <QtCore/QTimeZone>
+#include <QtCore/QUrl>
+
Q_DECLARE_METATYPE(QNetworkRequest::KnownHeaders)
class tst_QNetworkRequest: public QObject
@@ -30,6 +35,10 @@ private slots:
void rawHeaderParsing_data();
void rawHeaderParsing();
void originatingObject();
+ void setHeaders_data();
+ void setHeaders();
+ void operatorEqual_data();
+ void operatorEqual();
void removeHeader();
};
@@ -165,11 +174,11 @@ void tst_QNetworkRequest::rawHeaderList_data()
void tst_QNetworkRequest::rawHeaderList()
{
- QFETCH(QList<QByteArray>, set);
+ QFETCH(const QList<QByteArray>, set);
QFETCH(QList<QByteArray>, expected);
QNetworkRequest request;
- foreach (QByteArray header, set)
+ for (const QByteArray &header : set)
request.setRawHeader(header, "a value");
QList<QByteArray> got = request.rawHeaderList();
@@ -215,23 +224,25 @@ void tst_QNetworkRequest::setHeader_data()
<< "Thu, 01 Nov 2007 00:00:00 GMT";
QTest::newRow("Last-Modified-DateTime-UTC")
<< QNetworkRequest::LastModifiedHeader
- << QVariant(QDateTime(QDate(2007, 11, 1), QTime(18, 8, 30), Qt::UTC))
+ << QVariant(QDateTime(QDate(2007, 11, 1), QTime(18, 8, 30), QTimeZone::UTC))
<< true << "Last-Modified" << "Thu, 01 Nov 2007 18:08:30 GMT";
// QTBUG-80666: format dates correctly (as GMT) even if the date passed in isn't in UTC:
QTest::newRow("Last-Modified-DateTime-Local")
<< QNetworkRequest::LastModifiedHeader
- << QVariant(QDateTime(QDate(2007, 11, 1), QTime(18, 8, 30), Qt::UTC).toLocalTime())
+ << QVariant(QDateTime(QDate(2007, 11, 1), QTime(18, 8, 30), QTimeZone::UTC).toLocalTime())
<< true << "Last-Modified" << "Thu, 01 Nov 2007 18:08:30 GMT";
QTest::newRow("Last-Modified-DateTime-Offset")
<< QNetworkRequest::LastModifiedHeader
- << QVariant(QDateTime(QDate(2007, 11, 1), QTime(18, 8, 30), Qt::UTC).toOffsetFromUtc(3600))
+ << QVariant(QDateTime(QDate(2007, 11, 1), QTime(18, 8, 30),
+ QTimeZone::UTC).toOffsetFromUtc(3600))
<< true << "Last-Modified" << "Thu, 01 Nov 2007 18:08:30 GMT";
#if QT_CONFIG(timezone)
QTimeZone cet("Europe/Oslo");
if (cet.isValid()) {
QTest::newRow("Last-Modified-DateTime-CET")
<< QNetworkRequest::LastModifiedHeader
- << QVariant(QDateTime(QDate(2007, 11, 1), QTime(18, 8, 30), Qt::UTC).toTimeZone(cet))
+ << QVariant(QDateTime(QDate(2007, 11, 1), QTime(18, 8, 30),
+ QTimeZone::UTC).toTimeZone(cet))
<< true << "Last-Modified" << "Thu, 01 Nov 2007 18:08:30 GMT";
}
#endif
@@ -243,7 +254,7 @@ void tst_QNetworkRequest::setHeader_data()
QTest::newRow("If-Modified-Since-DateTime") << QNetworkRequest::IfModifiedSinceHeader
<< QVariant(QDateTime(QDate(2017, 7, 01),
QTime(3, 14, 15),
- Qt::UTC))
+ QTimeZone::UTC))
<< true << "If-Modified-Since"
<< "Sat, 01 Jul 2017 03:14:15 GMT";
@@ -344,45 +355,45 @@ void tst_QNetworkRequest::rawHeaderParsing_data()
<< true
<< "Content-Type" << "text/html";
QTest::newRow("Content-Length") << QNetworkRequest::ContentLengthHeader << QVariant(qint64(1))
- << true << "Content-Length" << " 1 ";
+ << true << "Content-Length" << "1";
QTest::newRow("Location") << QNetworkRequest::LocationHeader
<< QVariant(QUrl("http://foo/with space"))
<< true << "Location" << "http://foo/with%20space";
QTest::newRow("Last-Modified-RFC1123") << QNetworkRequest::LastModifiedHeader
<< QVariant(QDateTime(QDate(1994, 11, 06),
QTime(8, 49, 37),
- Qt::UTC))
+ QTimeZone::UTC))
<< true << "Last-Modified"
<< "Sun, 06 Nov 1994 08:49:37 GMT";
QTest::newRow("Last-Modified-RFC850") << QNetworkRequest::LastModifiedHeader
<< QVariant(QDateTime(QDate(1994, 11, 06),
QTime(8, 49, 37),
- Qt::UTC))
+ QTimeZone::UTC))
<< true << "Last-Modified"
<< "Sunday, 06-Nov-94 08:49:37 GMT";
QTest::newRow("Last-Modified-asctime") << QNetworkRequest::LastModifiedHeader
<< QVariant(QDateTime(QDate(1994, 11, 06),
QTime(8, 49, 37),
- Qt::UTC))
+ QTimeZone::UTC))
<< true << "Last-Modified"
<< "Sun Nov 6 08:49:37 1994";
QTest::newRow("If-Modified-Since-RFC1123") << QNetworkRequest::IfModifiedSinceHeader
<< QVariant(QDateTime(QDate(1994, 8, 06),
QTime(8, 49, 37),
- Qt::UTC))
+ QTimeZone::UTC))
<< true << "If-Modified-Since"
<< "Sun, 06 Aug 1994 08:49:37 GMT";
QTest::newRow("If-Modified-Since-RFC850") << QNetworkRequest::IfModifiedSinceHeader
<< QVariant(QDateTime(QDate(1994, 8, 06),
QTime(8, 49, 37),
- Qt::UTC))
+ QTimeZone::UTC))
<< true << "If-Modified-Since"
<< "Sunday, 06-Aug-94 08:49:37 GMT";
QTest::newRow("If-Modified-Since-asctime") << QNetworkRequest::IfModifiedSinceHeader
<< QVariant(QDateTime(QDate(1994, 8, 06),
QTime(8, 49, 37),
- Qt::UTC))
+ QTimeZone::UTC))
<< true << "If-Modified-Since"
<< "Sun Aug 6 08:49:37 1994";
@@ -549,5 +560,155 @@ void tst_QNetworkRequest::originatingObject()
QVERIFY(!request.originatingObject());
}
+void tst_QNetworkRequest::setHeaders_data()
+{
+ QTest::addColumn<QHttpHeaders>("h");
+ QTest::newRow("null") << QHttpHeaders();
+ QHttpHeaders headers;
+ headers.append("name1", "value1");
+ QTest::newRow("valid") << headers;
+}
+
+void tst_QNetworkRequest::setHeaders()
+{
+ QFETCH(QHttpHeaders, h);
+
+ QNetworkRequest r1;
+
+ auto result = r1.headers();
+ QVERIFY(result.isEmpty());
+
+ r1.setHeaders(h);
+ QCOMPARE(r1.headers().toListOfPairs(), h.toListOfPairs());
+
+ QNetworkRequest r2;
+ auto tmp = h;
+ r2.setHeaders(std::move(tmp));
+ QCOMPARE(r2.headers().toListOfPairs(), h.toListOfPairs());
+}
+
+void tst_QNetworkRequest::operatorEqual_data()
+{
+ QTest::addColumn<QNetworkRequest>("a");
+ QTest::addColumn<QNetworkRequest>("b");
+ QTest::addColumn<bool>("expectedToMatch");
+ QTest::newRow("null") << QNetworkRequest() << QNetworkRequest() << true;
+
+ QNetworkRequest data1;
+ data1.setUrl(QUrl("http://qt-project.org"));
+ QTest::newRow("url-1-1") << data1 << QNetworkRequest() << false;
+ QTest::newRow("url-1-2") << data1 << data1 << true;
+
+ QNetworkRequest data2;
+ QHttpHeaders headers;
+ headers.append("name1", "value1");
+ data2.setHeaders(headers);
+ QTest::newRow("headers-2-1") << data2 << QNetworkRequest() << false;
+ QTest::newRow("headers-2-2") << data2 << data2 << true;
+ QTest::newRow("headers-2-3") << data2 << data1 << false;
+
+ QNetworkRequest data3;
+ data3.setPeerVerifyName("peerName");
+ QTest::newRow("peerName-3-1") << data3 << QNetworkRequest() << false;
+ QTest::newRow("peerName-3-2") << data3 << data3 << true;
+ QTest::newRow("peerName-3-3") << data3 << data1 << false;
+ QTest::newRow("peerName-3-4") << data3 << data2 << false;
+
+ QNetworkRequest data4;
+ data4.setAttribute(QNetworkRequest::Http2AllowedAttribute, true);
+ QTest::newRow("attribute-4-1") << data4 << QNetworkRequest() << false;
+ QTest::newRow("attribute-4-2") << data4 << data4 << true;
+ QTest::newRow("attribute-4-3") << data4 << data1 << false;
+ QTest::newRow("attribute-4-4") << data4 << data2 << false;
+ QTest::newRow("attribute-4-5") << data4 << data3 << false;
+
+ QNetworkRequest data5;
+ data5.setPriority(QNetworkRequest::Priority::HighPriority);
+ QTest::newRow("priority-5-1") << data5 << QNetworkRequest() << false;
+ QTest::newRow("priority-5-2") << data5 << data5 << true;
+ QTest::newRow("priority-5-3") << data5 << data1 << false;
+ QTest::newRow("priority-5-4") << data5 << data2 << false;
+ QTest::newRow("priority-5-5") << data5 << data3 << false;
+ QTest::newRow("priority-5-6") << data5 << data4 << false;
+
+ QNetworkRequest data6;
+ data6.setMaximumRedirectsAllowed(3);
+ QTest::newRow("maxRedirects-6-1") << data6 << QNetworkRequest() << false;
+ QTest::newRow("maxRedirects-6-2") << data6 << data6 << true;
+ QTest::newRow("maxRedirects-6-3") << data6 << data1 << false;
+ QTest::newRow("maxRedirects-6-4") << data6 << data2 << false;
+ QTest::newRow("maxRedirects-6-5") << data6 << data3 << false;
+ QTest::newRow("maxRedirects-6-6") << data6 << data4 << false;
+ QTest::newRow("maxRedirects-6-7") << data6 << data5 << false;
+
+#if QT_CONFIG(http)
+ QNetworkRequest data7;
+ QHttp1Configuration http1Configuration;
+ http1Configuration.setNumberOfConnectionsPerHost(5);
+ data7.setHttp1Configuration(http1Configuration);
+ QTest::newRow("http1Config-7-1") << data7 << QNetworkRequest() << false;
+ QTest::newRow("http1Config-7-2") << data7 << data7 << true;
+ QTest::newRow("http1Config-7-3") << data7 << data1 << false;
+ QTest::newRow("http1Config-7-4") << data7 << data2 << false;
+ QTest::newRow("http1Config-7-5") << data7 << data3 << false;
+ QTest::newRow("http1Config-7-6") << data7 << data4 << false;
+ QTest::newRow("http1Config-7-7") << data7 << data5 << false;
+ QTest::newRow("http1Config-7-8") << data7 << data6 << false;
+
+ QNetworkRequest data8;
+ QHttp2Configuration http2Configuration;
+ http2Configuration.setMaxFrameSize(16386);
+ data8.setHttp2Configuration(http2Configuration);
+ QTest::newRow("http2Config-8-1") << data8 << QNetworkRequest() << false;
+ QTest::newRow("http2Config-8-2") << data8 << data8 << true;
+ QTest::newRow("http2Config-8-3") << data8 << data1 << false;
+ QTest::newRow("http2Config-8-4") << data8 << data2 << false;
+ QTest::newRow("http2Config-8-5") << data8 << data3 << false;
+ QTest::newRow("http2Config-8-6") << data8 << data4 << false;
+ QTest::newRow("http2Config-8-7") << data8 << data5 << false;
+ QTest::newRow("http2Config-8-8") << data8 << data6 << false;
+ QTest::newRow("http2Config-8-9") << data8 << data7 << false;
+
+ QNetworkRequest data9;
+ data9.setDecompressedSafetyCheckThreshold(-1);
+ QTest::newRow("threshold-9-1") << data9 << QNetworkRequest() << false;
+ QTest::newRow("threshold-9-2") << data9 << data9 << true;
+ QTest::newRow("threshold-9-3") << data9 << data1 << false;
+ QTest::newRow("threshold-9-4") << data9 << data2 << false;
+ QTest::newRow("threshold-9-5") << data9 << data3 << false;
+ QTest::newRow("threshold-9-6") << data9 << data4 << false;
+ QTest::newRow("threshold-9-7") << data9 << data5 << false;
+ QTest::newRow("threshold-9-8") << data9 << data6 << false;
+ QTest::newRow("threshold-9-9") << data9 << data7 << false;
+ QTest::newRow("threshold-9-10") << data9 << data8 << false;
+#endif
+
+#if QT_CONFIG(http) || defined (Q_OS_WASM)
+ QNetworkRequest data10;
+ data10.setTransferTimeout(50000);
+ QTest::newRow("timeout-10-1") << data10 << QNetworkRequest() << false;
+ QTest::newRow("timeout-10-2") << data10 << data10 << true;
+ QTest::newRow("timeout-10-3") << data10 << data1 << false;
+ QTest::newRow("timeout-10-4") << data10 << data2 << false;
+ QTest::newRow("timeout-10-5") << data10 << data3 << false;
+ QTest::newRow("timeout-10-6") << data10 << data4 << false;
+ QTest::newRow("timeout-10-7") << data10 << data5 << false;
+ QTest::newRow("timeout-10-8") << data10 << data6 << false;
+ QTest::newRow("timeout-10-9") << data10 << data7 << false;
+ QTest::newRow("timeout-10-10") << data10 << data8 << false;
+ QTest::newRow("timeout-10-11") << data10 << data9 << false;
+#endif
+}
+
+// public bool operator==(const QNetworkRequest &other) const
+void tst_QNetworkRequest::operatorEqual()
+{
+ QFETCH(QNetworkRequest, a);
+ QFETCH(QNetworkRequest, b);
+ QFETCH(bool, expectedToMatch);
+
+ QCOMPARE(a == b, expectedToMatch);
+}
+
QTEST_MAIN(tst_QNetworkRequest)
#include "tst_qnetworkrequest.moc"
diff --git a/tests/auto/network/access/qnetworkrequestfactory/CMakeLists.txt b/tests/auto/network/access/qnetworkrequestfactory/CMakeLists.txt
new file mode 100644
index 0000000000..d2112de58f
--- /dev/null
+++ b/tests/auto/network/access/qnetworkrequestfactory/CMakeLists.txt
@@ -0,0 +1,17 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qnetworkrequestfactory LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_test(tst_qnetworkrequestfactory
+ SOURCES
+ tst_qnetworkrequestfactory.cpp
+ LIBRARIES
+ Qt::Core
+ Qt::Test
+ Qt::Network
+)
diff --git a/tests/auto/network/access/qnetworkrequestfactory/tst_qnetworkrequestfactory.cpp b/tests/auto/network/access/qnetworkrequestfactory/tst_qnetworkrequestfactory.cpp
new file mode 100644
index 0000000000..d04a7ff3ec
--- /dev/null
+++ b/tests/auto/network/access/qnetworkrequestfactory/tst_qnetworkrequestfactory.cpp
@@ -0,0 +1,423 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtTest/qtest.h>
+#include <QtNetwork/qnetworkrequestfactory.h>
+#ifndef QT_NO_SSL
+#include <QtNetwork/qsslconfiguration.h>
+#endif
+#include <QtCore/qurlquery.h>
+#include <QtCore/qurl.h>
+
+using namespace Qt::StringLiterals;
+using namespace std::chrono_literals;
+
+class tst_QNetworkRequestFactory : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void urlAndPath_data();
+ void urlAndPath();
+ void queryParameters();
+ void sslConfiguration();
+ void headers();
+ void bearerToken();
+ void operators();
+ void timeout();
+ void userInfo();
+ void priority();
+ void attributes();
+
+private:
+ const QUrl url1{u"http://foo.io"_s};
+ const QUrl url2{u"http://bar.io"_s};
+ const QByteArray bearerToken1{"bearertoken1"};
+ const QByteArray bearerToken2{"bearertoken2"};
+};
+
+void tst_QNetworkRequestFactory::urlAndPath_data()
+{
+ QTest::addColumn<QUrl>("baseUrl");
+ QTest::addColumn<QString>("requestPath");
+ QTest::addColumn<QUrl>("expectedRequestUrl");
+
+ QUrl base{"http://xyz.io"};
+ QUrl result{"http://xyz.io/path/to"};
+ QTest::newRow("baseUrl_nopath_noslash_1") << base << u""_s << base;
+ QTest::newRow("baseUrl_nopath_noslash_2") << base << u"/path/to"_s << result;
+ QTest::newRow("baseUrl_nopath_noslash_3") << base << u"path/to"_s << result;
+
+ base.setUrl("http://xyz.io/");
+ result.setUrl("http://xyz.io/path/to");
+ QTest::newRow("baseUrl_nopath_withslash_1") << base << u""_s << base;
+ QTest::newRow("baseUrl_nopath_withslash_2") << base << u"/path/to"_s << result;
+ QTest::newRow("baseUrl_nopath_withslash_3") << base << u"path/to"_s << result;
+
+ base.setUrl("http://xyz.io/v1");
+ result.setUrl("http://xyz.io/v1/path/to");
+ QTest::newRow("baseUrl_withpath_noslash_1") << base << u""_s << base;
+ QTest::newRow("baseUrl_withpath_noslash_2") << base << u"/path/to"_s << result;
+ QTest::newRow("baseUrl_withpath_noslash_3") << base << u"path/to"_s << result;
+
+ base.setUrl("http://xyz.io/v1/");
+ QTest::newRow("baseUrl_withpath_withslash_1") << base << u""_s << base;
+ QTest::newRow("baseUrl_withpath_withslash_2") << base << u"/path/to"_s << result;
+ QTest::newRow("baseUrl_withpath_withslash_3") << base << u"path/to"_s << result;
+
+ // Currently we keep any double '//', but not sure if there is a use case for it, or could
+ // it be corrected to a single '/'
+ base.setUrl("http://xyz.io/v1//");
+ result.setUrl("http://xyz.io/v1//path/to");
+ QTest::newRow("baseUrl_withpath_doubleslash_1") << base << u""_s << base;
+ QTest::newRow("baseUrl_withpath_doubleslash_2") << base << u"/path/to"_s << result;
+ QTest::newRow("baseUrl_withpath_doubleslash_3") << base << u"path/to"_s << result;
+}
+
+void tst_QNetworkRequestFactory::urlAndPath()
+{
+ QFETCH(QUrl, baseUrl);
+ QFETCH(QString, requestPath);
+ QFETCH(QUrl, expectedRequestUrl);
+
+ // Set with constructor
+ QNetworkRequestFactory factory1{baseUrl};
+ QCOMPARE(factory1.baseUrl(), baseUrl);
+
+ // Set with setter calls
+ QNetworkRequestFactory factory2{};
+ factory2.setBaseUrl(baseUrl);
+ QCOMPARE(factory2.baseUrl(), baseUrl);
+
+ // Request path
+ QNetworkRequest request = factory1.createRequest();
+ QCOMPARE(request.url(), baseUrl); // No path was provided for createRequest(), expect baseUrl
+ request = factory1.createRequest(requestPath);
+ QCOMPARE(request.url(), expectedRequestUrl);
+
+ // Check the request path didn't change base url
+ QCOMPARE(factory1.baseUrl(), baseUrl);
+}
+
+void tst_QNetworkRequestFactory::queryParameters()
+{
+ QNetworkRequestFactory factory({"http://example.com"});
+ const QUrlQuery query1{{"q1k", "q1v"}};
+ const QUrlQuery query2{{"q2k", "q2v"}};
+
+ // Set query parameters in createRequest() call
+ QCOMPARE(factory.createRequest(query1).url(), QUrl{"http://example.com?q1k=q1v"});
+ QCOMPARE(factory.createRequest(query2).url(), QUrl{"http://example.com?q2k=q2v"});
+
+ // Set query parameters into the factory
+ factory.setQueryParameters(query1);
+ QUrlQuery resultQuery = factory.queryParameters();
+ for (const auto &item: query1.queryItems()) {
+ QVERIFY(resultQuery.hasQueryItem(item.first));
+ QCOMPARE(resultQuery.queryItemValue(item.first), item.second);
+ }
+ QCOMPARE(factory.createRequest().url(), QUrl{"http://example.com?q1k=q1v"});
+
+ // Set query parameters into both createRequest() and factory
+ QCOMPARE(factory.createRequest(query2).url(), QUrl{"http://example.com?q2k=q2v&q1k=q1v"});
+
+ // Clear query parameters
+ factory.clearQueryParameters();
+ QVERIFY(factory.queryParameters().isEmpty());
+ QCOMPARE(factory.createRequest().url(), QUrl{"http://example.com"});
+
+ const QString pathWithQuery{"content?raw=1"};
+ // Set query parameters in per-request path
+ QCOMPARE(factory.createRequest(pathWithQuery).url(),
+ QUrl{"http://example.com/content?raw=1"});
+ // Set query parameters in per-request path and the query parameter
+ QCOMPARE(factory.createRequest(pathWithQuery, query1).url(),
+ QUrl{"http://example.com/content?q1k=q1v&raw=1"});
+ // Set query parameter in per-request path and into the factory
+ factory.setQueryParameters(query2);
+ QCOMPARE(factory.createRequest(pathWithQuery).url(),
+ QUrl{"http://example.com/content?raw=1&q2k=q2v"});
+ // Set query parameters in per-request, as additional parameters, and into the factory
+ QCOMPARE(factory.createRequest(pathWithQuery, query1).url(),
+ QUrl{"http://example.com/content?q1k=q1v&raw=1&q2k=q2v"});
+
+ // Test that other than path and query items as part of path are ignored
+ factory.setQueryParameters(query1);
+ QRegularExpression re("The provided path*");
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, re);
+ QCOMPARE(factory.createRequest("https://example2.com").url(), QUrl{"http://example.com?q1k=q1v"});
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, re);
+ QCOMPARE(factory.createRequest("https://example2.com?q3k=q3v").url(),
+ QUrl{"http://example.com?q3k=q3v&q1k=q1v"});
+}
+
+void tst_QNetworkRequestFactory::sslConfiguration()
+{
+#ifdef QT_NO_SSL
+ QSKIP("Skipping SSL tests, not supported by build");
+#else
+ // Two initially equal factories
+ QNetworkRequestFactory factory1{url1};
+ QNetworkRequestFactory factory2{url1};
+
+ // Make two differing SSL configurations (for this test it's irrelevant how they differ)
+ QSslConfiguration config1;
+ config1.setProtocol(QSsl::TlsV1_2);
+ QSslConfiguration config2;
+ config2.setProtocol(QSsl::DtlsV1_2);
+
+ // Set configuration and verify that the same config is returned
+ factory1.setSslConfiguration(config1);
+ QCOMPARE(factory1.sslConfiguration(), config1);
+ factory2.setSslConfiguration(config2);
+ QCOMPARE(factory2.sslConfiguration(), config2);
+
+ // Verify requests are set with appropriate SSL configs
+ QNetworkRequest request1 = factory1.createRequest();
+ QCOMPARE(request1.sslConfiguration(), config1);
+ QNetworkRequest request2 = factory2.createRequest();
+ QCOMPARE(request2.sslConfiguration(), config2);
+#endif
+}
+
+void tst_QNetworkRequestFactory::headers()
+{
+ const QByteArray name1{"headername1"};
+ const QByteArray name2{"headername2"};
+ const QByteArray value1{"headervalue1"};
+ const QByteArray value2{"headervalue2"};
+ const QByteArray value3{"headervalue3"};
+
+ QNetworkRequestFactory factory{url1};
+ // Initial state when no headers are set
+ QVERIFY(factory.commonHeaders().isEmpty());
+ QVERIFY(factory.commonHeaders().values(name1).isEmpty());
+ QVERIFY(!factory.commonHeaders().contains(name1));
+
+ // Set headers
+ QHttpHeaders h1;
+ h1.append(name1, value1);
+ factory.setCommonHeaders(h1);
+ QVERIFY(factory.commonHeaders().contains(name1));
+ QCOMPARE(factory.commonHeaders().combinedValue(name1), value1);
+ QCOMPARE(factory.commonHeaders().size(), 1);
+ QVERIFY(factory.commonHeaders().values("nonexistent").isEmpty());
+ QNetworkRequest request = factory.createRequest();
+ QVERIFY(request.hasRawHeader(name1));
+ QCOMPARE(request.rawHeader(name1), value1);
+
+ // Check that empty header does not match
+ QVERIFY(!factory.commonHeaders().contains(""_ba));
+ QVERIFY(factory.commonHeaders().values(""_ba).isEmpty());
+
+ // Clear headers
+ factory.clearCommonHeaders();
+ QVERIFY(factory.commonHeaders().isEmpty());
+ request = factory.createRequest();
+ QVERIFY(!request.hasRawHeader(name1));
+
+ // Set headers with more entries
+ h1.clear();
+ h1.append(name1, value1);
+ h1.append(name2, value2);
+ factory.setCommonHeaders(h1);
+ QVERIFY(factory.commonHeaders().contains(name1));
+ QVERIFY(factory.commonHeaders().contains(name2));
+ QCOMPARE(factory.commonHeaders().combinedValue(name1), value1);
+ QCOMPARE(factory.commonHeaders().combinedValue(name2), value2);
+ QCOMPARE(factory.commonHeaders().size(), 2);
+ request = factory.createRequest();
+ QVERIFY(request.hasRawHeader(name1));
+ QVERIFY(request.hasRawHeader(name2));
+ QCOMPARE(request.rawHeader(name1), value1);
+ QCOMPARE(request.rawHeader(name2), value2);
+ // Append more values to pre-existing header name2
+ h1.clear();
+ h1.append(name1, value1);
+ h1.append(name1, value2);
+ h1.append(name1, value3);
+ factory.setCommonHeaders(h1);
+ QVERIFY(factory.commonHeaders().contains(name1));
+ QCOMPARE(factory.commonHeaders().combinedValue(name1), value1 + ", " + value2 + ", " + value3);
+ request = factory.createRequest();
+ QVERIFY(request.hasRawHeader(name1));
+ QCOMPARE(request.rawHeader(name1), value1 + ", " + value2 + ", " + value3);
+}
+
+void tst_QNetworkRequestFactory::bearerToken()
+{
+ const auto authHeader = "Authorization"_ba;
+ QNetworkRequestFactory factory{url1};
+ QVERIFY(factory.bearerToken().isEmpty());
+
+ factory.setBearerToken(bearerToken1);
+ QCOMPARE(factory.bearerToken(), bearerToken1);
+ QNetworkRequest request = factory.createRequest();
+ QVERIFY(request.hasRawHeader(authHeader));
+ QCOMPARE(request.rawHeader(authHeader), "Bearer "_ba + bearerToken1);
+
+ // Verify that bearerToken is not in debug output
+ QString debugOutput;
+ QDebug debug(&debugOutput);
+ debug << factory;
+ QVERIFY(debugOutput.contains("bearerToken = (is set)"));
+ QVERIFY(!debugOutput.contains(bearerToken1));
+
+ factory.setBearerToken(bearerToken2);
+ QCOMPARE(factory.bearerToken(), bearerToken2);
+ request = factory.createRequest();
+ QVERIFY(request.hasRawHeader(authHeader));
+ QCOMPARE(request.rawHeader(authHeader), "Bearer "_ba + bearerToken2);
+
+ // Set authorization header manually
+ const auto value = "headervalue"_ba;
+ QHttpHeaders h1;
+ h1.append(authHeader, value);
+ factory.setCommonHeaders(h1);
+ request = factory.createRequest();
+ QVERIFY(request.hasRawHeader(authHeader));
+ // bearerToken has precedence over manually set header
+ QCOMPARE(request.rawHeader(authHeader), "Bearer "_ba + bearerToken2);
+ // clear bearer token, the manually set header is now used
+ factory.clearBearerToken();
+ request = factory.createRequest();
+ QVERIFY(request.hasRawHeader(authHeader));
+ QCOMPARE(request.rawHeader(authHeader), value);
+}
+
+void tst_QNetworkRequestFactory::operators()
+{
+ QNetworkRequestFactory factory1(url1);
+
+ // Copy ctor
+ QNetworkRequestFactory factory2(factory1);
+ QCOMPARE(factory2.baseUrl(), factory1.baseUrl());
+
+ // Copy assignment
+ QNetworkRequestFactory factory3;
+ factory3 = factory2;
+ QCOMPARE(factory3.baseUrl(), factory2.baseUrl());
+
+ // Move assignment
+ QNetworkRequestFactory factory4;
+ factory4 = std::move(factory3);
+ QCOMPARE(factory4.baseUrl(), factory2.baseUrl());
+
+ // Verify implicit sharing
+ factory1.setBaseUrl(url2);
+ QCOMPARE(factory1.baseUrl(), url2); // changed
+ QCOMPARE(factory2.baseUrl(), url1); // remains
+
+ // Move ctor
+ QNetworkRequestFactory factory5{std::move(factory4)};
+ QCOMPARE(factory5.baseUrl(), factory2.baseUrl()); // the moved factory4 originates from factory2
+ QCOMPARE(factory5.baseUrl(), url1);
+}
+
+void tst_QNetworkRequestFactory::timeout()
+{
+ constexpr auto defaultTimeout = 0ms;
+ constexpr auto timeout = 150ms;
+
+ QNetworkRequestFactory factory;
+ QNetworkRequest request = factory.createRequest();
+ QCOMPARE(factory.transferTimeout(), defaultTimeout);
+ QCOMPARE(request.transferTimeoutAsDuration(), defaultTimeout);
+
+ factory.setTransferTimeout(timeout);
+ request = factory.createRequest();
+ QCOMPARE(factory.transferTimeout(), timeout);
+ QCOMPARE(request.transferTimeoutAsDuration(), timeout);
+}
+
+void tst_QNetworkRequestFactory::userInfo()
+{
+ QNetworkRequestFactory factory;
+ QVERIFY(factory.userName().isEmpty());
+ QVERIFY(factory.password().isEmpty());
+
+ const auto uname = u"a_username"_s;
+ const auto password = u"a_password"_s;
+ factory.setUserName(uname);
+ QCOMPARE(factory.userName(), uname);
+ factory.setPassword(password);
+ QCOMPARE(factory.password(), password);
+
+ // Verify that debug output does not contain password
+ QString debugOutput;
+ QDebug debug(&debugOutput);
+ debug << factory;
+ QVERIFY(debugOutput.contains("password = (is set)"));
+ QVERIFY(!debugOutput.contains(password));
+
+ factory.clearUserName();
+ factory.clearPassword();
+ QVERIFY(factory.userName().isEmpty());
+ QVERIFY(factory.password().isEmpty());
+}
+
+void tst_QNetworkRequestFactory::priority()
+{
+ QNetworkRequestFactory factory(u"http://example.com"_s);
+ QCOMPARE(factory.priority(), QNetworkRequest::NormalPriority);
+ auto request = factory.createRequest("/index.html");
+ QCOMPARE(request.priority(), QNetworkRequest::NormalPriority);
+
+ factory.setPriority(QNetworkRequest::HighPriority);
+ QCOMPARE(factory.priority(), QNetworkRequest::HighPriority);
+ request = factory.createRequest("/index.html");
+ QCOMPARE(request.priority(), QNetworkRequest::HighPriority);
+}
+
+void tst_QNetworkRequestFactory::attributes()
+{
+ const auto attribute1 = QNetworkRequest::Attribute::BackgroundRequestAttribute;
+ const auto attribute2 = QNetworkRequest::User;
+ QNetworkRequestFactory factory;
+ QNetworkRequest request;
+
+ // Empty factory
+ QVERIFY(!factory.attribute(attribute1).isValid());
+ request = factory.createRequest();
+ QVERIFY(!request.attribute(attribute1).isValid());
+
+ // (Re-)set and clear individual attribute
+ factory.setAttribute(attribute1, true);
+ QVERIFY(factory.attribute(attribute1).isValid());
+ QCOMPARE(factory.attribute(attribute1).toBool(), true);
+ request = factory.createRequest();
+ QVERIFY(request.attribute(attribute1).isValid());
+ QCOMPARE(request.attribute(attribute1).toBool(), true);
+ // Replace previous value
+ factory.setAttribute(attribute1, false);
+ QVERIFY(factory.attribute(attribute1).isValid());
+ QCOMPARE(factory.attribute(attribute1).toBool(), false);
+ request = factory.createRequest();
+ QVERIFY(request.attribute(attribute1).isValid());
+ QCOMPARE(request.attribute(attribute1).toBool(), false);
+ // Clear individual attribute
+ factory.clearAttribute(attribute1);
+ QVERIFY(!factory.attribute(attribute1).isValid());
+
+ // Getter default value
+ QCOMPARE(factory.attribute(attribute2, 111).toInt(), 111); // default value returned
+ factory.setAttribute(attribute2, 222);
+ QCOMPARE(factory.attribute(attribute2, 111).toInt(), 222); // actual value returned
+ factory.clearAttribute(attribute2);
+ QCOMPARE(factory.attribute(attribute2, 111).toInt(), 111); // default value returned
+
+ // Clear attributes
+ factory.setAttribute(attribute1, true);
+ factory.setAttribute(attribute2, 333);
+ QVERIFY(factory.attribute(attribute1).isValid());
+ QVERIFY(factory.attribute(attribute2).isValid());
+ factory.clearAttributes();
+ QVERIFY(!factory.attribute(attribute1).isValid());
+ QVERIFY(!factory.attribute(attribute2).isValid());
+ request = factory.createRequest();
+ QVERIFY(!request.attribute(attribute1).isValid());
+ QVERIFY(!request.attribute(attribute2).isValid());
+}
+
+QTEST_MAIN(tst_QNetworkRequestFactory)
+#include "tst_qnetworkrequestfactory.moc"
diff --git a/tests/auto/network/access/qrestaccessmanager/CMakeLists.txt b/tests/auto/network/access/qrestaccessmanager/CMakeLists.txt
new file mode 100644
index 0000000000..614248be28
--- /dev/null
+++ b/tests/auto/network/access/qrestaccessmanager/CMakeLists.txt
@@ -0,0 +1,17 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qrestaccessmanager LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_test(tst_qrestaccessmanager
+ SOURCES
+ tst_qrestaccessmanager.cpp
+ httptestserver.cpp httptestserver_p.h
+ LIBRARIES
+ Qt::Network
+ Qt::CorePrivate
+)
diff --git a/tests/auto/network/access/qrestaccessmanager/httptestserver.cpp b/tests/auto/network/access/qrestaccessmanager/httptestserver.cpp
new file mode 100644
index 0000000000..25869eb46b
--- /dev/null
+++ b/tests/auto/network/access/qrestaccessmanager/httptestserver.cpp
@@ -0,0 +1,268 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "httptestserver_p.h"
+
+#include <QtNetwork/qtcpsocket.h>
+
+#include <QtCore/qcoreapplication.h>
+
+#include <private/qlocale_p.h>
+
+using namespace Qt::StringLiterals;
+
+static constexpr char CRLF[] = "\r\n";
+
+HttpTestServer::HttpTestServer(QObject *parent) : QTcpServer(parent)
+{
+ QObject::connect(this, &QTcpServer::newConnection, this, &HttpTestServer::handleConnected);
+ const auto ok = listen(QHostAddress::LocalHost);
+ Q_ASSERT(ok);
+};
+
+HttpTestServer::~HttpTestServer()
+{
+ if (isListening())
+ close();
+}
+
+QUrl HttpTestServer::url()
+{
+ return QUrl(u"http://127.0.0.1:%1"_s.arg(serverPort()));
+}
+
+void HttpTestServer::handleConnected()
+{
+ Q_ASSERT(!m_socket); // No socket must exist previously, this is a single-connection server
+ m_socket = nextPendingConnection();
+ Q_ASSERT(m_socket);
+ QObject::connect(m_socket, &QTcpSocket::readyRead,
+ this, &HttpTestServer::handleDataAvailable);
+}
+
+void HttpTestServer::handleDataAvailable()
+{
+ Q_ASSERT(m_socket);
+ bool ok = true;
+
+ // Parse the incoming request data into the HttpData object
+ while (m_socket->bytesAvailable()) {
+ if (state == State::ReadingMethod && !(ok = readMethod(m_socket)))
+ qWarning("Invalid Method");
+ if (ok && state == State::ReadingUrl && !(ok = readUrl(m_socket)))
+ qWarning("Invalid URL");
+ if (ok && state == State::ReadingStatus && !(ok = readStatus(m_socket)))
+ qWarning("Invalid Status");
+ if (ok && state == State::ReadingHeader && !(ok = readHeaders(m_socket)))
+ qWarning("Invalid Header");
+ if (ok && state == State::ReadingBody && !(ok = readBody(m_socket)))
+ qWarning("Invalid Body");
+ } // while bytes available
+
+ Q_ASSERT(ok);
+ Q_ASSERT(m_handler);
+ Q_ASSERT(state == State::AllDone);
+
+ if (auto values = m_request.headers.values(
+ QHttpHeaders::WellKnownHeader::Host); !values.empty()) {
+ const auto parts = values.first().split(':');
+ m_request.url.setHost(parts.at(0));
+ if (parts.size() == 2)
+ m_request.url.setPort(parts.at(1).toUInt());
+ }
+ HttpData response;
+ ResponseControl control;
+ // Inform the testcase about request and ask for response data
+ m_handler(m_request, response, control);
+
+ QByteArray responseMessage;
+ responseMessage += "HTTP/1.1 ";
+ responseMessage += QByteArray::number(response.status);
+ responseMessage += CRLF;
+ // Insert headers if any
+ for (const auto &[name,value] : response.headers.toListOfPairs()) {
+ responseMessage += name;
+ responseMessage += ": ";
+ responseMessage += value;
+ responseMessage += CRLF;
+ }
+ responseMessage += CRLF;
+ /*
+ qDebug() << "HTTPTestServer received request"
+ << "\nMethod:" << m_request.method
+ << "\nHeaders:" << m_request.headers
+ << "\nBody:" << m_request.body;
+ */
+ if (control.respond) {
+ if (control.responseChunkSize <= 0) {
+ responseMessage += response.body;
+ // qDebug() << "HTTPTestServer response:" << responseMessage;
+ m_socket->write(responseMessage);
+ } else {
+ // Respond in chunks, first write the headers
+ // qDebug() << "HTTPTestServer response:" << responseMessage;
+ m_socket->write(responseMessage);
+ // Then write bodydata in chunks, while allowing the testcase to process as well
+ QByteArray chunk;
+ while (!response.body.isEmpty()) {
+ chunk = response.body.left(control.responseChunkSize);
+ response.body.remove(0, control.responseChunkSize);
+ // qDebug() << "SERVER writing chunk" << chunk;
+ m_socket->write(chunk);
+ m_socket->flush();
+ m_socket->waitForBytesWritten();
+ // Process events until testcase indicates it's ready for next chunk.
+ // This way we can control the bytes the testcase gets in each chunk
+ control.readyForNextChunk = false;
+ while (!control.readyForNextChunk)
+ QCoreApplication::processEvents();
+ }
+ }
+ }
+ m_socket->disconnectFromHost();
+ m_request = {};
+ m_socket = nullptr; // deleted by QTcpServer during destruction
+ state = State::ReadingMethod;
+ fragment.clear();
+}
+
+bool HttpTestServer::readMethod(QTcpSocket *socket)
+{
+ bool finished = false;
+ while (socket->bytesAvailable() && !finished) {
+ const auto c = socket->read(1).at(0);
+ if (ascii_isspace(c))
+ finished = true;
+ else if (std::isupper(c) && fragment.size() < 8)
+ fragment += c;
+ else
+ return false;
+ }
+ if (finished) {
+ if (fragment == "HEAD")
+ method = Method::Head;
+ else if (fragment == "GET")
+ method = Method::Get;
+ else if (fragment == "PUT")
+ method = Method::Put;
+ else if (fragment == "PATCH")
+ method = Method::Patch;
+ else if (fragment == "POST")
+ method = Method::Post;
+ else if (fragment == "DELETE")
+ method = Method::Delete;
+ else if (fragment == "FOOBAR") // used by custom verb/method tests
+ method = Method::Custom;
+ else
+ qWarning("Invalid operation %s", fragment.data());
+
+ state = State::ReadingUrl;
+ m_request.method = fragment;
+ fragment.clear();
+
+ return method != Method::Unknown;
+ }
+ return true;
+}
+
+bool HttpTestServer::readUrl(QTcpSocket *socket)
+{
+ bool finished = false;
+ while (socket->bytesAvailable() && !finished) {
+ const auto c = socket->read(1).at(0);
+ if (std::isspace(c))
+ finished = true;
+ else
+ fragment += c;
+ }
+ if (finished) {
+ if (!fragment.startsWith('/')) {
+ qWarning("Invalid URL path %s", fragment.constData());
+ return false;
+ }
+ m_request.url = QStringLiteral("http://127.0.0.1:") + QString::number(m_request.port) +
+ QString::fromUtf8(fragment);
+ state = State::ReadingStatus;
+ if (!m_request.url.isValid()) {
+ qWarning("Invalid URL %s", fragment.constData());
+ return false;
+ }
+ fragment.clear();
+ }
+ return true;
+}
+
+bool HttpTestServer::readStatus(QTcpSocket *socket)
+{
+ bool finished = false;
+ while (socket->bytesAvailable() && !finished) {
+ fragment += socket->read(1);
+ if (fragment.endsWith(CRLF)) {
+ finished = true;
+ fragment.resize(fragment.size() - 2);
+ }
+ }
+ if (finished) {
+ if (!std::isdigit(fragment.at(fragment.size() - 3)) ||
+ fragment.at(fragment.size() - 2) != '.' ||
+ !std::isdigit(fragment.at(fragment.size() - 1))) {
+ qWarning("Invalid version");
+ return false;
+ }
+ m_request.version = std::pair(fragment.at(fragment.size() - 3) - '0',
+ fragment.at(fragment.size() - 1) - '0');
+ state = State::ReadingHeader;
+ fragment.clear();
+ }
+ return true;
+}
+
+bool HttpTestServer::readHeaders(QTcpSocket *socket)
+{
+ while (socket->bytesAvailable()) {
+ fragment += socket->read(1);
+ if (fragment.endsWith(CRLF)) {
+ if (fragment == CRLF) {
+ state = State::ReadingBody;
+ fragment.clear();
+ return true;
+ } else {
+ fragment.chop(2);
+ const int index = fragment.indexOf(':');
+ if (index == -1)
+ return false;
+
+ QByteArray key = fragment.sliced(0, index).trimmed();
+ QByteArray value = fragment.sliced(index + 1).trimmed();
+ m_request.headers.append(key, value);
+ fragment.clear();
+ }
+ }
+ }
+ return true;
+}
+
+bool HttpTestServer::readBody(QTcpSocket *socket)
+{
+ qint64 bytesLeft = 0;
+ if (auto values = m_request.headers.values(
+ QHttpHeaders::WellKnownHeader::ContentLength); !values.empty()) {
+ bool conversionResult;
+ bytesLeft = values.first().toInt(&conversionResult);
+ if (!conversionResult)
+ return false;
+ fragment.resize(bytesLeft);
+ }
+ while (bytesLeft) {
+ qint64 got = socket->read(&fragment.data()[fragment.size() - bytesLeft], bytesLeft);
+ if (got < 0)
+ return false; // error
+ bytesLeft -= got;
+ if (bytesLeft)
+ qApp->processEvents();
+ }
+ fragment.swap(m_request.body);
+ state = State::AllDone;
+ return true;
+}
+
diff --git a/tests/auto/network/access/qrestaccessmanager/httptestserver_p.h b/tests/auto/network/access/qrestaccessmanager/httptestserver_p.h
new file mode 100644
index 0000000000..0a94b2c8a6
--- /dev/null
+++ b/tests/auto/network/access/qrestaccessmanager/httptestserver_p.h
@@ -0,0 +1,90 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef QRESTACCESSSMANAGER_HTTPTESTSERVER_P_H
+#define QRESTACCESSSMANAGER_HTTPTESTSERVER_P_H
+
+#include <QtNetwork/qtcpserver.h>
+#include <QtNetwork/qhttpheaders.h>
+
+#include <QtCore/qmap.h>
+#include <QtCore/qurl.h>
+
+#include <functional>
+
+// This struct is used for parsing the incoming network request data into, as well
+// as getting the response data from the testcase
+struct HttpData {
+ QUrl url;
+ int status = 0;
+ QByteArray body;
+ QByteArray method;
+ quint16 port = 0;
+ QPair<quint8, quint8> version;
+ QHttpHeaders headers;
+};
+
+struct ResponseControl
+{
+ bool respond = true;
+ qsizetype responseChunkSize = -1;
+ bool readyForNextChunk = true;
+};
+
+// Simple HTTP server. Currently supports only one concurrent connection
+class HttpTestServer : public QTcpServer
+{
+ Q_OBJECT
+
+public:
+ explicit HttpTestServer(QObject *parent = nullptr);
+ ~HttpTestServer() override;
+
+ // Returns this server's URL for the testcase to send requests to
+ QUrl url();
+
+ enum class State {
+ ReadingMethod,
+ ReadingUrl,
+ ReadingStatus,
+ ReadingHeader,
+ ReadingBody,
+ AllDone
+ } state = State::ReadingMethod;
+
+ enum class Method {
+ Unknown,
+ Head,
+ Get,
+ Put,
+ Patch,
+ Post,
+ Delete,
+ Custom,
+ } method = Method::Unknown;
+
+ // Parsing helpers for incoming data => HttpData
+ bool readMethod(QTcpSocket *socket);
+ bool readUrl(QTcpSocket *socket);
+ bool readStatus(QTcpSocket *socket);
+ bool readHeaders(QTcpSocket *socket);
+ bool readBody(QTcpSocket *socket);
+ // Parsing-time buffer in case data is received a small chunk at a time (readyRead())
+ QByteArray fragment;
+
+ // Settable callback for testcase. Gives the received request data, and takes in response data
+ using Handler = std::function<void(const HttpData &request, HttpData &response,
+ ResponseControl &control)>;
+ void setHandler(Handler handler) { m_handler = std::move(handler); }
+
+private slots:
+ void handleConnected();
+ void handleDataAvailable();
+
+private:
+ QTcpSocket *m_socket = nullptr;
+ HttpData m_request;
+ Handler m_handler = nullptr;
+};
+
+#endif // QRESTACCESSSMANAGER_HTTPTESTSERVER_P_H
diff --git a/tests/auto/network/access/qrestaccessmanager/tst_qrestaccessmanager.cpp b/tests/auto/network/access/qrestaccessmanager/tst_qrestaccessmanager.cpp
new file mode 100644
index 0000000000..d6bdda76ca
--- /dev/null
+++ b/tests/auto/network/access/qrestaccessmanager/tst_qrestaccessmanager.cpp
@@ -0,0 +1,876 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "httptestserver_p.h"
+
+#if QT_CONFIG(http)
+#include <QtNetwork/qhttpmultipart.h>
+#endif
+#include <QtNetwork/qrestaccessmanager.h>
+#include <QtNetwork/qauthenticator.h>
+#include <QtNetwork/qnetworkreply.h>
+#include <QtNetwork/qnetworkrequestfactory.h>
+#include <QtNetwork/qrestreply.h>
+
+#include <QTest>
+#include <QtTest/qsignalspy.h>
+
+#include <QtCore/private/qglobal_p.h> // for access to Qt's feature system
+#include <QtCore/qbuffer.h>
+#include <QtCore/qjsonobject.h>
+#include <QtCore/qjsondocument.h>
+#include <QtCore/qjsonarray.h>
+#include <QtCore/qstringconverter.h>
+
+using namespace Qt::StringLiterals;
+using namespace std::chrono_literals;
+
+using Header = QHttpHeaders::WellKnownHeader;
+
+class tst_QRestAccessManager : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initialization();
+ void destruction();
+ void callbacks();
+#if QT_CONFIG(http)
+ void requests();
+#endif
+ void reply();
+ void errors();
+ void body();
+ void json();
+ void text();
+ void textStreaming();
+
+private:
+ void memberHandler(QRestReply &reply);
+
+ friend class Transient;
+ QList<QNetworkReply*> m_expectedReplies;
+ QList<QNetworkReply*> m_actualReplies;
+};
+
+void tst_QRestAccessManager::initialization()
+{
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, "QRestAccessManager: QNetworkAccesManager is nullptr");
+ QRestAccessManager manager1(nullptr);
+ QVERIFY(!manager1.networkAccessManager());
+
+ QNetworkAccessManager qnam;
+ QRestAccessManager manager2(&qnam);
+ QVERIFY(manager2.networkAccessManager());
+}
+
+void tst_QRestAccessManager::reply()
+{
+ QNetworkAccessManager qnam;
+
+ QNetworkReply *nr = qnam.get(QNetworkRequest(QUrl{"someurl"}));
+ QRestReply rr1(nr);
+ QCOMPARE(rr1.networkReply(), nr);
+
+ // Move-construct
+ QRestReply rr2(std::move(rr1));
+ QCOMPARE(rr2.networkReply(), nr);
+
+ // Move-assign
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, "QRestReply: QNetworkReply is nullptr");
+ QRestReply rr3(nullptr);
+ rr3 = std::move(rr2);
+ QCOMPARE(rr3.networkReply(), nr);
+}
+
+#define VERIFY_REPLY_OK(METHOD) \
+{ \
+ QTRY_VERIFY(networkReply); \
+ QRestReply restReply(networkReply); \
+ QCOMPARE(serverSideRequest.method, METHOD); \
+ QVERIFY(restReply.isSuccess()); \
+ QVERIFY(!restReply.hasError()); \
+ networkReply->deleteLater(); \
+ networkReply = nullptr; \
+}
+
+#if QT_CONFIG(http)
+void tst_QRestAccessManager::requests()
+{
+ // A basic test for each HTTP method against the local testserver.
+ QNetworkAccessManager qnam;
+ QRestAccessManager manager(&qnam);
+ HttpTestServer server;
+ QTRY_VERIFY(server.isListening());
+ QNetworkRequest request(server.url());
+ request.setRawHeader("Content-Type"_ba, "text/plain"); // To silence missing content-type warn
+ QNetworkReply *networkReply = nullptr;
+ std::unique_ptr<QHttpMultiPart> multiPart;
+ QHttpPart part;
+ part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"text\""));
+ part.setBody("multipart_text");
+ QByteArray ioDeviceData{"io_device_data"_ba};
+ QBuffer bufferIoDevice(&ioDeviceData);
+
+ HttpData serverSideRequest; // The request data the server received
+ HttpData serverSideResponse; // The response data the server responds with
+ serverSideResponse.status = 200;
+ server.setHandler([&](const HttpData &request, HttpData &response, ResponseControl&) {
+ serverSideRequest = request;
+ response = serverSideResponse;
+
+ });
+ auto callback = [&](QRestReply &reply) { networkReply = reply.networkReply(); };
+ const QByteArray byteArrayData{"some_data"_ba};
+ const QJsonObject jsonObjectData{{"key1", "value1"}, {"key2", "value2"}};
+ const QJsonArray jsonArrayData{{"arrvalue1", "arrvalue2", QJsonObject{{"key1", "value1"}}}};
+ const QVariantMap variantMapData{{"key1", "value1"}, {"key2", "value2"}};
+ const QByteArray methodDELETE{"DELETE"_ba};
+ const QByteArray methodHEAD{"HEAD"_ba};
+ const QByteArray methodPOST{"POST"_ba};
+ const QByteArray methodGET{"GET"_ba};
+ const QByteArray methodPUT{"PUT"_ba};
+ const QByteArray methodPATCH{"PATCH"_ba};
+ const QByteArray methodCUSTOM{"FOOBAR"_ba};
+
+ // DELETE
+ manager.deleteResource(request, this, callback);
+ VERIFY_REPLY_OK(methodDELETE);
+ QCOMPARE(serverSideRequest.body, ""_ba);
+
+ // HEAD
+ manager.head(request, this, callback);
+ VERIFY_REPLY_OK(methodHEAD);
+ QCOMPARE(serverSideRequest.body, ""_ba);
+
+ // GET
+ manager.get(request, this, callback);
+ VERIFY_REPLY_OK(methodGET);
+ QCOMPARE(serverSideRequest.body, ""_ba);
+
+ manager.get(request, byteArrayData, this, callback);
+ VERIFY_REPLY_OK(methodGET);
+ QCOMPARE(serverSideRequest.body, byteArrayData);
+
+ manager.get(request, QJsonDocument{jsonObjectData}, this, callback);
+ VERIFY_REPLY_OK(methodGET);
+ QCOMPARE(QJsonDocument::fromJson(serverSideRequest.body).object(), jsonObjectData);
+
+ manager.get(request, &bufferIoDevice, this, callback);
+ VERIFY_REPLY_OK(methodGET);
+ QCOMPARE(serverSideRequest.body, ioDeviceData);
+
+ // CUSTOM
+ manager.sendCustomRequest(request, methodCUSTOM, byteArrayData, this, callback);
+ VERIFY_REPLY_OK(methodCUSTOM);
+ QCOMPARE(serverSideRequest.body, byteArrayData);
+
+ manager.sendCustomRequest(request, methodCUSTOM, &bufferIoDevice, this, callback);
+ VERIFY_REPLY_OK(methodCUSTOM);
+ QCOMPARE(serverSideRequest.body, ioDeviceData);
+
+ multiPart.reset(new QHttpMultiPart(QHttpMultiPart::FormDataType));
+ multiPart->append(part);
+ manager.sendCustomRequest(request, methodCUSTOM, multiPart.get(), this, callback);
+ VERIFY_REPLY_OK(methodCUSTOM);
+ QVERIFY(serverSideRequest.body.contains("--boundary"_ba));
+ QVERIFY(serverSideRequest.body.contains("multipart_text"_ba));
+
+ // POST
+ manager.post(request, byteArrayData, this, callback);
+ VERIFY_REPLY_OK(methodPOST);
+ QCOMPARE(serverSideRequest.body, byteArrayData);
+
+ manager.post(request, QJsonDocument{jsonObjectData}, this, callback);
+ VERIFY_REPLY_OK(methodPOST);
+ QCOMPARE(QJsonDocument::fromJson(serverSideRequest.body).object(), jsonObjectData);
+
+ manager.post(request, QJsonDocument{jsonArrayData}, this, callback);
+ VERIFY_REPLY_OK(methodPOST);
+ QCOMPARE(QJsonDocument::fromJson(serverSideRequest.body).array(), jsonArrayData);
+
+ manager.post(request, variantMapData, this, callback);
+ VERIFY_REPLY_OK(methodPOST);
+ QCOMPARE(QJsonDocument::fromJson(serverSideRequest.body).object(), jsonObjectData);
+
+ multiPart = std::make_unique<QHttpMultiPart>(QHttpMultiPart::FormDataType);
+ multiPart->append(part);
+ manager.post(request, multiPart.get(), this, callback);
+ VERIFY_REPLY_OK(methodPOST);
+ QVERIFY(serverSideRequest.body.contains("--boundary"_ba));
+ QVERIFY(serverSideRequest.body.contains("multipart_text"_ba));
+
+ manager.post(request, &bufferIoDevice, this, callback);
+ VERIFY_REPLY_OK(methodPOST);
+ QCOMPARE(serverSideRequest.body, ioDeviceData);
+
+ // PUT
+ manager.put(request, byteArrayData, this, callback);
+ VERIFY_REPLY_OK(methodPUT);
+ QCOMPARE(serverSideRequest.body, byteArrayData);
+
+ manager.put(request, QJsonDocument{jsonObjectData}, this, callback);
+ VERIFY_REPLY_OK(methodPUT);
+ QCOMPARE(QJsonDocument::fromJson(serverSideRequest.body).object(), jsonObjectData);
+
+ manager.put(request, QJsonDocument{jsonArrayData}, this, callback);
+ VERIFY_REPLY_OK(methodPUT);
+ QCOMPARE(QJsonDocument::fromJson(serverSideRequest.body).array(), jsonArrayData);
+
+ manager.put(request, variantMapData, this, callback);
+ VERIFY_REPLY_OK(methodPUT);
+ QCOMPARE(QJsonDocument::fromJson(serverSideRequest.body).object(), jsonObjectData);
+
+ multiPart = std::make_unique<QHttpMultiPart>(QHttpMultiPart::FormDataType);
+ multiPart->append(part);
+ manager.put(request, multiPart.get(), this, callback);
+ VERIFY_REPLY_OK(methodPUT);
+ QVERIFY(serverSideRequest.body.contains("--boundary"_ba));
+ QVERIFY(serverSideRequest.body.contains("multipart_text"_ba));
+
+ manager.put(request, &bufferIoDevice, this, callback);
+ VERIFY_REPLY_OK(methodPUT);
+ QCOMPARE(serverSideRequest.body, ioDeviceData);
+
+ // PATCH
+ manager.patch(request, byteArrayData, this, callback);
+ VERIFY_REPLY_OK(methodPATCH);
+ QCOMPARE(serverSideRequest.body, byteArrayData);
+
+ manager.patch(request, QJsonDocument{jsonObjectData}, this, callback);
+ VERIFY_REPLY_OK(methodPATCH);
+ QCOMPARE(QJsonDocument::fromJson(serverSideRequest.body).object(), jsonObjectData);
+
+ manager.patch(request, QJsonDocument{jsonArrayData}, this, callback);
+ VERIFY_REPLY_OK(methodPATCH);
+ QCOMPARE(QJsonDocument::fromJson(serverSideRequest.body).array(), jsonArrayData);
+
+ manager.patch(request, variantMapData, this, callback);
+ VERIFY_REPLY_OK(methodPATCH);
+ QCOMPARE(QJsonDocument::fromJson(serverSideRequest.body).object(), jsonObjectData);
+
+ manager.patch(request, &bufferIoDevice, this, callback);
+ VERIFY_REPLY_OK(methodPATCH);
+ QCOMPARE(serverSideRequest.body, ioDeviceData);
+
+ //These must NOT compile
+ //manager.get(request, [](){}); // callback without context object
+ //manager.get(request, ""_ba, [](){}); // callback without context object
+ //manager.get(request, QString()); // wrong datatype
+ //manager.get(request, 123); // wrong datatype
+ //manager.post(request, QString()); // wrong datatype
+ //manager.put(request, 123); // wrong datatype
+ //manager.post(request); // data is required
+ //manager.put(request, QString()); // wrong datatype
+ //manager.put(request); // data is required
+ //manager.patch(request, 123); // wrong datatype
+ //manager.patch(request, QString()); // wrong datatype
+ //manager.patch(request); // data is required
+ //manager.deleteResource(request, "f"_ba); // data not allowed
+ //manager.head(request, "f"_ba); // data not allowed
+ //manager.post(request, ""_ba, this, [](int param){}); // Wrong callback signature
+ //manager.get(request, this, [](int param){}); // Wrong callback signature
+ //manager.sendCustomRequest(request, this, [](){}); // No verb && no data
+ //manager.sendCustomRequest(request, "FOOBAR", this, [](){}); // No verb || no data
+}
+#endif
+
+void tst_QRestAccessManager::memberHandler(QRestReply &reply)
+{
+ m_actualReplies.append(reply.networkReply());
+}
+
+// Class that is destroyed during an active request.
+// Used to test that the callbacks won't be called in these cases
+class Transient : public QObject
+{
+ Q_OBJECT
+public:
+ explicit Transient(tst_QRestAccessManager *test) : QObject(test), m_test(test) {}
+
+ void memberHandler(QRestReply &reply)
+ {
+ m_test->m_actualReplies.append(reply.networkReply());
+ }
+
+private:
+ tst_QRestAccessManager *m_test = nullptr;
+};
+
+template <typename Functor, std::enable_if_t<
+ QtPrivate::AreFunctionsCompatible<void(*)(QRestReply&), Functor>::value, bool> = true>
+inline constexpr bool isCompatibleCallback(Functor &&) { return true; }
+
+template <typename Functor, std::enable_if_t<
+ !QtPrivate::AreFunctionsCompatible<void(*)(QRestReply&), Functor>::value, bool> = true,
+ typename = void>
+inline constexpr bool isCompatibleCallback(Functor &&) { return false; }
+
+void tst_QRestAccessManager::callbacks()
+{
+ QNetworkAccessManager qnam;
+ QRestAccessManager manager(&qnam);
+
+ QNetworkRequest request{u"i_dont_exist"_s}; // Will result in ProtocolUnknown error
+
+ auto lambdaHandler = [this](QRestReply &reply) { m_actualReplies.append(reply.networkReply()); };
+ Transient *transient = nullptr;
+ QByteArray data{"some_data"};
+
+ // Compile-time tests for callback signatures
+ static_assert(isCompatibleCallback([](QRestReply&){})); // Correct signature
+ static_assert(isCompatibleCallback(lambdaHandler));
+ static_assert(isCompatibleCallback(&Transient::memberHandler));
+ static_assert(isCompatibleCallback([](){})); // Less parameters are allowed
+
+ static_assert(!isCompatibleCallback([](QString){})); // Wrong parameter type
+ static_assert(!isCompatibleCallback([](QRestReply*){})); // Wrong parameter type
+ static_assert(!isCompatibleCallback([](const QString &){})); // Wrong parameter type
+ static_assert(!isCompatibleCallback([](QRestReply&, QString){})); // Too many parameters
+
+ // -- Test without data
+ // Without callback using signals and slot
+ QNetworkReply* reply = manager.get(request);
+ m_expectedReplies.append(reply);
+ QObject::connect(reply, &QNetworkReply::finished, this,
+ [this, reply](){m_actualReplies.append(reply);});
+
+ // With lambda callback, without context object
+ m_expectedReplies.append(manager.get(request, nullptr, lambdaHandler));
+ m_expectedReplies.append(manager.get(request, nullptr,
+ [this](QRestReply &reply){m_actualReplies.append(reply.networkReply());}));
+ // With lambda callback and context object
+ m_expectedReplies.append(manager.get(request, this, lambdaHandler));
+ m_expectedReplies.append(manager.get(request, this,
+ [this](QRestReply &reply){m_actualReplies.append(reply.networkReply());}));
+ // With member callback and context object
+ m_expectedReplies.append(manager.get(request, this, &tst_QRestAccessManager::memberHandler));
+ // With context object that is destroyed, there should be no callback or eg. crash.
+ transient = new Transient(this);
+ manager.get(request, transient, &Transient::memberHandler); // Reply not added to expecteds
+ delete transient;
+
+ // Let requests finish
+ QTRY_COMPARE(m_actualReplies.size(), m_expectedReplies.size());
+ for (auto reply: m_actualReplies) {
+ QRestReply restReply(reply);
+ QVERIFY(!restReply.isSuccess());
+ QVERIFY(restReply.hasError());
+ QCOMPARE(restReply.error(), QNetworkReply::ProtocolUnknownError);
+ QCOMPARE(restReply.networkReply()->isFinished(), true);
+ restReply.networkReply()->deleteLater();
+ }
+ m_actualReplies.clear();
+ m_expectedReplies.clear();
+
+ // -- Test with data
+ // With lambda callback, without context object
+ m_expectedReplies.append(manager.post(request, data, nullptr, lambdaHandler));
+ m_expectedReplies.append(manager.post(request, data, nullptr,
+ [this](QRestReply &reply){m_actualReplies.append(reply.networkReply());}));
+ // With lambda callback and context object
+ m_expectedReplies.append(manager.post(request, data, this, lambdaHandler));
+ m_expectedReplies.append(manager.post(request, data, this,
+ [this](QRestReply &reply){m_actualReplies.append(reply.networkReply());}));
+ // With member callback and context object
+ m_expectedReplies.append(manager.post(request, data,
+ this, &tst_QRestAccessManager::memberHandler));
+ // With context object that is destroyed, there should be no callback or eg. crash
+ transient = new Transient(this);
+ manager.post(request, data, transient, &Transient::memberHandler); // Note: reply not expected
+ delete transient;
+
+ // Let requests finish
+ QTRY_COMPARE(m_actualReplies.size(), m_expectedReplies.size());
+ for (auto reply: m_actualReplies) {
+ QRestReply restReply(reply);
+ QVERIFY(!restReply.isSuccess());
+ QVERIFY(restReply.hasError());
+ QCOMPARE(restReply.error(), QNetworkReply::ProtocolUnknownError);
+ QCOMPARE(restReply.networkReply()->isFinished(), true);
+ reply->deleteLater();
+ }
+ m_actualReplies.clear();
+ m_expectedReplies.clear();
+
+ // -- Test GET with data separately, as GET provides methods that are usable with and
+ // without data, and fairly easy to get the qrestaccessmanager.h template SFINAE subtly wrong.
+ // With lambda callback, without context object
+ m_expectedReplies.append(manager.get(request, data, nullptr, lambdaHandler));
+ m_expectedReplies.append(manager.get(request, data, nullptr,
+ [this](QRestReply &reply){m_actualReplies.append(reply.networkReply());}));
+ // With lambda callback and context object
+ m_expectedReplies.append(manager.get(request, data, this, lambdaHandler));
+ m_expectedReplies.append(manager.get(request, data, this,
+ [this](QRestReply &reply){m_actualReplies.append(reply.networkReply());}));
+ // With member callback and context object
+ m_expectedReplies.append(manager.get(request, data,
+ this, &tst_QRestAccessManager::memberHandler));
+ // With context object that is destroyed, there should be no callback or eg. crash
+ transient = new Transient(this);
+ manager.get(request, data, transient, &Transient::memberHandler); // Reply not added
+ delete transient;
+
+ // Let requests finish
+ QTRY_COMPARE(m_actualReplies.size(), m_expectedReplies.size());
+ for (auto reply: m_actualReplies) {
+ QRestReply restReply(reply);
+ QVERIFY(!restReply.isSuccess());
+ QVERIFY(restReply.hasError());
+ QCOMPARE(restReply.error(), QNetworkReply::ProtocolUnknownError);
+ QCOMPARE(restReply.networkReply()->isFinished(), true);
+ restReply.networkReply()->deleteLater();
+ }
+ m_actualReplies.clear();
+ m_expectedReplies.clear();
+}
+
+void tst_QRestAccessManager::destruction()
+{
+ std::unique_ptr<QNetworkAccessManager> qnam = std::make_unique<QNetworkAccessManager>();
+ std::unique_ptr<QRestAccessManager> manager = std::make_unique<QRestAccessManager>(qnam.get());
+ QNetworkRequest request{u"i_dont_exist"_s}; // Will result in ProtocolUnknown error
+ m_expectedReplies.clear();
+ m_actualReplies.clear();
+ auto handler = [this](QRestReply &reply) { m_actualReplies.append(reply.networkReply()); };
+
+ // Delete reply immediately, make sure nothing bad happens and that there is no callback
+ QNetworkReply *networkReply = manager->get(request, this, handler);
+ delete networkReply;
+ QTest::qWait(20); // allow some time for the callback to arrive (it shouldn't)
+ QCOMPARE(m_actualReplies.size(), m_expectedReplies.size()); // Both should be 0
+
+ // Delete access manager immediately after request, make sure nothing bad happens
+ manager->get(request, this, handler);
+ manager->post(request, "data"_ba, this, handler);
+ QTest::ignoreMessage(QtWarningMsg, "Access manager destroyed while 2 requests were still"
+ " in progress");
+ manager.reset();
+ QTest::qWait(20);
+ QCOMPARE(m_actualReplies.size(), m_expectedReplies.size()); // Both should be 0
+
+ // Destroy the underlying QNAM while requests in progress
+ manager = std::make_unique<QRestAccessManager>(qnam.get());
+ manager->get(request, this, handler);
+ manager->post(request, "data"_ba, this, handler);
+ qnam.reset();
+ QTest::qWait(20);
+ QCOMPARE(m_actualReplies.size(), m_expectedReplies.size()); // Both should be 0
+}
+
+#define VERIFY_HTTP_ERROR_STATUS(STATUS) \
+{ \
+ serverSideResponse.status = STATUS; \
+ QRestReply restReply(manager.get(request)); \
+ QTRY_VERIFY(restReply.networkReply()->isFinished()); \
+ QVERIFY(!restReply.hasError()); \
+ QCOMPARE(restReply.httpStatus(), serverSideResponse.status); \
+ QCOMPARE(restReply.error(), QNetworkReply::NetworkError::NoError); \
+ QVERIFY(!restReply.isSuccess()); \
+ restReply.networkReply()->deleteLater(); \
+} \
+
+void tst_QRestAccessManager::errors()
+{
+ // Tests the distinction between HTTP and other (network/protocol) errors
+ QNetworkAccessManager qnam;
+ QRestAccessManager manager(&qnam);
+ HttpTestServer server;
+ QTRY_VERIFY(server.isListening());
+ QNetworkRequest request(server.url());
+
+ HttpData serverSideResponse; // The response data the server responds with
+ server.setHandler([&](const HttpData &, HttpData &response, ResponseControl &) {
+ response = serverSideResponse;
+ });
+
+ // Test few HTTP statuses in different categories
+ VERIFY_HTTP_ERROR_STATUS(301) // QNetworkReply::ProtocolUnknownError
+ VERIFY_HTTP_ERROR_STATUS(302) // QNetworkReply::ProtocolUnknownError
+ VERIFY_HTTP_ERROR_STATUS(400) // QNetworkReply::ProtocolInvalidOperationError
+ VERIFY_HTTP_ERROR_STATUS(401) // QNetworkReply::AuthenticationRequiredEror
+ VERIFY_HTTP_ERROR_STATUS(402) // QNetworkReply::UnknownContentError
+ VERIFY_HTTP_ERROR_STATUS(403) // QNetworkReply::ContentAccessDenied
+ VERIFY_HTTP_ERROR_STATUS(404) // QNetworkReply::ContentNotFoundError
+ VERIFY_HTTP_ERROR_STATUS(405) // QNetworkReply::ContentOperationNotPermittedError
+ VERIFY_HTTP_ERROR_STATUS(406) // QNetworkReply::UnknownContentError
+ VERIFY_HTTP_ERROR_STATUS(407) // QNetworkReply::ProxyAuthenticationRequiredError
+ VERIFY_HTTP_ERROR_STATUS(408) // QNetworkReply::UnknownContentError
+ VERIFY_HTTP_ERROR_STATUS(409) // QNetworkReply::ContentConflictError
+ VERIFY_HTTP_ERROR_STATUS(410) // QNetworkReply::ContentGoneError
+ VERIFY_HTTP_ERROR_STATUS(500) // QNetworkReply::InternalServerError
+ VERIFY_HTTP_ERROR_STATUS(501) // QNetworkReply::OperationNotImplementedError
+ VERIFY_HTTP_ERROR_STATUS(502) // QNetworkReply::UnknownServerError
+ VERIFY_HTTP_ERROR_STATUS(503) // QNetworkReply::ServiceUnavailableError
+ VERIFY_HTTP_ERROR_STATUS(504) // QNetworkReply::UnknownServerError
+ VERIFY_HTTP_ERROR_STATUS(505) // QNetworkReply::UnknownServerError
+
+ {
+ // Test that actual network/protocol errors come through
+ QRestReply restReply(manager.get({})); // Empty url
+ QTRY_VERIFY(restReply.networkReply()->isFinished());
+ QVERIFY(restReply.hasError());
+ QVERIFY(!restReply.isSuccess());
+ QCOMPARE(restReply.error(), QNetworkReply::ProtocolUnknownError);
+ restReply.networkReply()->deleteLater();
+ }
+
+ {
+ QRestReply restReply(manager.get(QNetworkRequest{{"http://non-existent.foo.bar.test"}}));
+ QTRY_VERIFY(restReply.networkReply()->isFinished());
+ QVERIFY(restReply.hasError());
+ QVERIFY(!restReply.isSuccess());
+ QCOMPARE(restReply.error(), QNetworkReply::HostNotFoundError);
+ restReply.networkReply()->deleteLater();
+ }
+
+ {
+ QRestReply restReply(manager.get(request));
+ restReply.networkReply()->abort();
+ QTRY_VERIFY(restReply.networkReply()->isFinished());
+ QVERIFY(restReply.hasError());
+ QVERIFY(!restReply.isSuccess());
+ QCOMPARE(restReply.error(), QNetworkReply::OperationCanceledError);
+ restReply.networkReply()->deleteLater();
+ }
+}
+
+void tst_QRestAccessManager::body()
+{
+ // Test using QRestReply::body() data accessor
+ QNetworkAccessManager qnam;
+ QRestAccessManager manager(&qnam);
+ HttpTestServer server;
+ QTRY_VERIFY(server.isListening());
+ QNetworkRequest request(server.url());
+ QNetworkReply *networkReply = nullptr;
+
+ HttpData serverSideRequest; // The request data the server received
+ HttpData serverSideResponse; // The response data the server responds with
+ server.setHandler([&](const HttpData &request, HttpData &response, ResponseControl&) {
+ serverSideRequest = request;
+ response = serverSideResponse;
+ });
+
+ {
+ serverSideResponse.status = 200;
+ serverSideResponse.body = "some_data"_ba;
+ manager.get(request, this, [&](QRestReply &reply) { networkReply = reply.networkReply(); });
+ QTRY_VERIFY(networkReply);
+ QRestReply restReply(networkReply);
+ QCOMPARE(restReply.readBody(), serverSideResponse.body);
+ QCOMPARE(restReply.httpStatus(), serverSideResponse.status);
+ QVERIFY(!restReply.hasError());
+ QVERIFY(restReply.isSuccess());
+ networkReply->deleteLater();
+ networkReply = nullptr;
+ }
+
+ {
+ serverSideResponse.status = 200;
+ serverSideResponse.body = ""_ba; // Empty
+ manager.get(request, this, [&](QRestReply &reply) { networkReply = reply.networkReply(); });
+ QTRY_VERIFY(networkReply);
+ QRestReply restReply(networkReply);
+ QCOMPARE(restReply.readBody(), serverSideResponse.body);
+ networkReply->deleteLater();
+ networkReply = nullptr;
+ }
+
+ {
+ serverSideResponse.status = 500;
+ serverSideResponse.body = "some_other_data"_ba;
+ manager.get(request, this, [&](QRestReply &reply) { networkReply = reply.networkReply(); });
+ QTRY_VERIFY(networkReply);
+ QRestReply restReply(networkReply);
+ QCOMPARE(restReply.readBody(), serverSideResponse.body);
+ QCOMPARE(restReply.httpStatus(), serverSideResponse.status);
+ QVERIFY(!restReply.hasError());
+ QVERIFY(!restReply.isSuccess());
+ networkReply->deleteLater();
+ networkReply = nullptr;
+ }
+}
+
+void tst_QRestAccessManager::json()
+{
+ // Tests using QRestReply::readJson()
+ QNetworkAccessManager qnam;
+ QRestAccessManager manager(&qnam);
+ HttpTestServer server;
+ QTRY_VERIFY(server.isListening());
+ QNetworkRequest request(server.url());
+ QNetworkReply *networkReply = nullptr;
+ QJsonDocument responseJsonDocument;
+ std::optional<QJsonDocument> json;
+ QJsonParseError parseError;
+
+ HttpData serverSideRequest; // The request data the server received
+ HttpData serverSideResponse; // The response data the server responds with
+ serverSideResponse.status = 200;
+ server.setHandler([&](const HttpData &request, HttpData &response, ResponseControl&) {
+ serverSideRequest = request;
+ response = serverSideResponse;
+ });
+
+ {
+ // Test receiving valid json object
+ serverSideResponse.body = "{\"key1\":\"value1\",""\"key2\":\"value2\"}\n"_ba;
+ networkReply = manager.get(request);
+ // Read unfinished reply
+ QVERIFY(!networkReply->isFinished());
+ QTest::ignoreMessage(QtWarningMsg, "readJson() called on an unfinished reply, ignoring");
+ parseError.error = QJsonParseError::ParseError::DocumentTooLarge; // Reset to impossible value
+ QRestReply restReply(networkReply);
+ QVERIFY(!restReply.readJson(&parseError));
+ QCOMPARE(parseError.error, QJsonParseError::ParseError::NoError);
+ // Read finished reply
+ QTRY_VERIFY(networkReply->isFinished());
+ parseError.error = QJsonParseError::ParseError::DocumentTooLarge;
+ json = restReply.readJson(&parseError);
+ QVERIFY(json);
+ QCOMPARE(parseError.error, QJsonParseError::ParseError::NoError);
+ responseJsonDocument = *json;
+ QVERIFY(responseJsonDocument.isObject());
+ QCOMPARE(responseJsonDocument["key1"], "value1");
+ QCOMPARE(responseJsonDocument["key2"], "value2");
+ networkReply->deleteLater();
+ networkReply = nullptr;
+ }
+
+ {
+ // Test receiving an invalid json object
+ serverSideResponse.body = "foobar"_ba;
+ manager.get(request, this, [&](QRestReply &reply) { networkReply = reply.networkReply(); });
+ QTRY_VERIFY(networkReply);
+ QRestReply restReply(networkReply);
+ parseError.error = QJsonParseError::ParseError::DocumentTooLarge;
+ const auto json = restReply.readJson(&parseError);
+ networkReply->deleteLater();
+ networkReply = nullptr;
+ QCOMPARE_EQ(json, std::nullopt);
+ QCOMPARE_NE(parseError.error, QJsonParseError::ParseError::NoError);
+ QCOMPARE_NE(parseError.error, QJsonParseError::ParseError::DocumentTooLarge);
+ QCOMPARE_GT(parseError.offset, 0);
+ }
+
+ {
+ // Test receiving valid json array
+ serverSideResponse.body = "[\"foo\", \"bar\"]\n"_ba;
+ manager.get(request, this, [&](QRestReply &reply) { networkReply = reply.networkReply(); });
+ QTRY_VERIFY(networkReply);
+ QRestReply restReply(networkReply);
+ parseError.error = QJsonParseError::ParseError::DocumentTooLarge;
+ json = restReply.readJson(&parseError);
+ networkReply->deleteLater();
+ networkReply = nullptr;
+ QCOMPARE(parseError.error, QJsonParseError::ParseError::NoError);
+ QVERIFY(json);
+ responseJsonDocument = *json;
+ QVERIFY(responseJsonDocument.isArray());
+ QCOMPARE(responseJsonDocument.array().size(), 2);
+ QCOMPARE(responseJsonDocument[0].toString(), "foo"_L1);
+ QCOMPARE(responseJsonDocument[1].toString(), "bar"_L1);
+ }
+}
+
+#define VERIFY_TEXT_REPLY_OK \
+{ \
+ manager.get(request, this, [&](QRestReply &reply) { networkReply = reply.networkReply(); }); \
+ QTRY_VERIFY(networkReply); \
+ QRestReply restReply(networkReply); \
+ responseString = restReply.readText(); \
+ networkReply->deleteLater(); \
+ networkReply = nullptr; \
+ QCOMPARE(responseString, sourceString); \
+}
+
+#define VERIFY_TEXT_REPLY_ERROR(WARNING_MESSAGE) \
+{ \
+ manager.get(request, this, [&](QRestReply &reply) { networkReply = reply.networkReply(); }); \
+ QTRY_VERIFY(networkReply); \
+ QTest::ignoreMessage(QtWarningMsg, WARNING_MESSAGE); \
+ QRestReply restReply(networkReply); \
+ responseString = restReply.readText(); \
+ networkReply->deleteLater(); \
+ networkReply = nullptr; \
+ QVERIFY(responseString.isEmpty()); \
+}
+
+void tst_QRestAccessManager::text()
+{
+ // Test using QRestReply::text() data accessor with various text encodings
+ QNetworkAccessManager qnam;
+ QRestAccessManager manager(&qnam);
+ HttpTestServer server;
+ QTRY_VERIFY(server.isListening());
+ QNetworkRequest request(server.url());
+ QNetworkReply *networkReply = nullptr;
+ QJsonObject responseJsonObject;
+
+ QStringEncoder encUTF8("UTF-8");
+ QStringEncoder encUTF16("UTF-16");
+ QStringEncoder encUTF32("UTF-32");
+ QString responseString;
+
+ HttpData serverSideRequest; // The request data the server received
+ HttpData serverSideResponse; // The response data the server responds with
+ serverSideResponse.status = 200;
+ server.setHandler([&](const HttpData &request, HttpData &response, ResponseControl&) {
+ serverSideRequest = request;
+ response = serverSideResponse;
+ });
+
+ const QString sourceString("this is a string"_L1);
+
+ // Charset parameter of Content-Type header may specify non-UTF-8 character encoding.
+ //
+ // QString is UTF-16, and in the tests below we encode the response data to various
+ // charset encodings (into byte arrays). When we get the response data, the text()
+ // should consider the indicated charset and convert it to an UTF-16 QString => the returned
+ // QString from text() should match with the original (UTF-16) QString.
+
+ // Successful UTF-8 (explicit)
+ serverSideResponse.headers.append(Header::ContentType, "text/plain; charset=UTF-8"_ba);
+ serverSideResponse.body = encUTF8(sourceString);
+ VERIFY_TEXT_REPLY_OK;
+
+ // Successful UTF-8 (obfuscated)
+ serverSideResponse.headers.removeAll(Header::ContentType);
+ serverSideResponse.headers.append(Header::ContentType, "text/plain; charset=\"UT\\F-8\""_ba);
+ serverSideResponse.body = encUTF8(sourceString);
+ VERIFY_TEXT_REPLY_OK;
+
+ // Successful UTF-8 (empty charset)
+ serverSideResponse.headers.removeAll(Header::ContentType);
+ serverSideResponse.headers.append(Header::ContentType, "text/plain; charset=\"\""_ba);
+ serverSideResponse.body = encUTF8(sourceString);
+ VERIFY_TEXT_REPLY_OK;
+
+ // Successful UTF-8 (implicit)
+ serverSideResponse.headers.removeAll(Header::ContentType);
+ serverSideResponse.headers.append(Header::ContentType, "text/plain"_ba);
+ serverSideResponse.body = encUTF8(sourceString);
+ VERIFY_TEXT_REPLY_OK;
+
+ // Successful UTF-16
+ serverSideResponse.headers.removeAll(Header::ContentType);
+ serverSideResponse.headers.append(Header::ContentType, "text/plain; charset=UTF-16"_ba);
+ serverSideResponse.body = encUTF16(sourceString);
+ VERIFY_TEXT_REPLY_OK;
+
+ // Successful UTF-16, parameter case insensitivity
+ serverSideResponse.headers.removeAll(Header::ContentType);
+ serverSideResponse.headers.append(Header::ContentType, "text/plain; chARset=uTf-16"_ba);
+ serverSideResponse.body = encUTF16(sourceString);
+ VERIFY_TEXT_REPLY_OK;
+
+ // Successful UTF-32
+ serverSideResponse.headers.removeAll(Header::ContentType);
+ serverSideResponse.headers.append(Header::ContentType, "text/plain; charset=UTF-32"_ba);
+ serverSideResponse.body = encUTF32(sourceString);
+ VERIFY_TEXT_REPLY_OK;
+
+ // Successful UTF-32 with spec-wise allowed extra trailing content in the Content-Type header value
+ serverSideResponse.headers.removeAll(Header::ContentType);
+ serverSideResponse.headers.append(Header::ContentType,
+ "text(this is a \\)comment)/ (this (too)) plain; charset = \"UTF-32\";extraparameter=bar"_ba);
+ serverSideResponse.body = encUTF32(sourceString);
+ VERIFY_TEXT_REPLY_OK;
+
+ // Successful UTF-32 with spec-wise allowed extra leading content in the Content-Type header value
+ serverSideResponse.headers.removeAll(Header::ContentType);
+ serverSideResponse.headers.append(Header::ContentType,
+ "text/plain; extraparameter=bar;charset = \"UT\\F-32\""_ba);
+ serverSideResponse.body = encUTF32(sourceString);
+ VERIFY_TEXT_REPLY_OK;
+
+ {
+ // Unsuccessful UTF-32, wrong encoding indicated (indicated UTF-32 but data is UTF-8)
+ serverSideResponse.headers.removeAll(Header::ContentType);
+ serverSideResponse.headers.append(Header::ContentType, "text/plain; charset=UTF-32"_ba);
+ serverSideResponse.body = encUTF8(sourceString);
+ manager.get(request, this, [&](QRestReply &reply) { networkReply = reply.networkReply(); });
+ QTRY_VERIFY(networkReply);
+ QRestReply restReply(networkReply);
+ responseString = restReply.readText();
+ QCOMPARE_NE(responseString, sourceString);
+ networkReply->deleteLater();
+ networkReply = nullptr;
+ }
+
+ // Unsupported encoding
+ serverSideResponse.headers.removeAll(Header::ContentType);
+ serverSideResponse.headers.append(Header::ContentType, "text/plain; charset=foo"_ba);
+ serverSideResponse.body = encUTF8(sourceString);
+ VERIFY_TEXT_REPLY_ERROR("readText(): Charset \"foo\" is not supported")
+
+ // Broken UTF-8
+ serverSideResponse.headers.removeAll(Header::ContentType);
+ serverSideResponse.headers.append(Header::ContentType, "text/plain; charset=UTF-8"_ba);
+ serverSideResponse.body = "\xF0\x28\x8C\x28\xA0\xB0\xC0\xD0"; // invalid characters
+ VERIFY_TEXT_REPLY_ERROR("readText(): Decoding error occurred");
+}
+
+void tst_QRestAccessManager::textStreaming()
+{
+ // Tests textual data received in chunks
+ QNetworkAccessManager qnam;
+ QRestAccessManager manager(&qnam);
+ HttpTestServer server;
+ QTRY_VERIFY(server.isListening());
+ QNetworkRequest request(server.url());
+
+ // Create long text data
+ const QString expectedData = u"사랑abcd€fghiklmnΩpqrstuvwx愛사랑A사랑BCD€FGHIJKLMNΩPQRsTUVWXYZ愛"_s;
+ QString cumulativeReceivedText;
+ QStringEncoder encUTF8("UTF-8");
+ ResponseControl *responseControl = nullptr;
+
+ HttpData serverSideResponse; // The response data the server responds with
+ serverSideResponse.headers.removeAll(Header::ContentType);
+ serverSideResponse.headers.append(Header::ContentType, "text/plain; charset=UTF-8"_ba);
+ serverSideResponse.body = encUTF8(expectedData);
+ serverSideResponse.status = 200;
+
+ server.setHandler([&](const HttpData &, HttpData &response, ResponseControl &control) {
+ response = serverSideResponse;
+ responseControl = &control; // store for later
+ control.responseChunkSize = 5; // tell testserver to send data in chunks of this size
+ });
+
+ {
+ QRestReply restReply(manager.get(request));
+ QObject::connect(restReply.networkReply(), &QNetworkReply::readyRead, this, [&]() {
+ cumulativeReceivedText += restReply.readText();
+ // Tell testserver that test is ready for next chunk
+ responseControl->readyForNextChunk = true;
+ });
+ QTRY_VERIFY(restReply.networkReply()->isFinished());
+ QCOMPARE(cumulativeReceivedText, expectedData);
+ restReply.networkReply()->deleteLater();
+ }
+
+ {
+ cumulativeReceivedText.clear();
+ // Broken UTF-8 characters after first five ok characters
+ serverSideResponse.body =
+ "12345"_ba + "\xF0\x28\x8C\x28\xA0\xB0\xC0\xD0" + "abcde"_ba;
+ QRestReply restReply(manager.get(request));
+ QObject::connect(restReply.networkReply(), &QNetworkReply::readyRead, this, [&]() {
+ static bool firstTime = true;
+ if (!firstTime) // First text part is without warnings
+ QTest::ignoreMessage(QtWarningMsg, "readText(): Decoding error occurred");
+ firstTime = false;
+ cumulativeReceivedText += restReply.readText();
+ // Tell testserver that test is ready for next chunk
+ responseControl->readyForNextChunk = true;
+ });
+ QTRY_VERIFY(restReply.networkReply()->isFinished());
+ QCOMPARE(cumulativeReceivedText, "12345"_ba);
+ restReply.networkReply()->deleteLater();
+ }
+}
+
+QTEST_MAIN(tst_QRestAccessManager)
+#include "tst_qrestaccessmanager.moc"
diff --git a/tests/auto/network/kernel/CMakeLists.txt b/tests/auto/network/kernel/CMakeLists.txt
index ca0ce02f96..df87e9d58e 100644
--- a/tests/auto/network/kernel/CMakeLists.txt
+++ b/tests/auto/network/kernel/CMakeLists.txt
@@ -1,18 +1,21 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from kernel.pro.
-if(NOT INTEGRITY)
+if(QT_FEATURE_dnslookup AND (QT_FEATURE_libresolv OR WIN32))
add_subdirectory(qdnslookup)
add_subdirectory(qdnslookup_appless)
endif()
if(QT_FEATURE_networkinterface)
+ add_subdirectory(qnetworkaddressentry)
add_subdirectory(qnetworkproxyfactory)
add_subdirectory(qnetworkinterface)
endif()
-add_subdirectory(qnetworkproxy)
-add_subdirectory(qnetworkdatagram)
-add_subdirectory(qnetworkaddressentry)
+if(QT_FEATURE_networkproxy)
+ add_subdirectory(qnetworkproxy)
+endif()
+if(QT_FEATURE_udpsocket)
+ add_subdirectory(qnetworkdatagram)
+endif()
add_subdirectory(qhostaddress)
if(QT_FEATURE_private_tests AND NOT MACOS AND NOT INTEGRITY)
add_subdirectory(qhostinfo)
diff --git a/tests/auto/network/kernel/qauthenticator/CMakeLists.txt b/tests/auto/network/kernel/qauthenticator/CMakeLists.txt
index 5e8b65ce8a..552e9065ed 100644
--- a/tests/auto/network/kernel/qauthenticator/CMakeLists.txt
+++ b/tests/auto/network/kernel/qauthenticator/CMakeLists.txt
@@ -1,7 +1,11 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qauthenticator.pro.
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qauthenticator LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
if(NOT QT_FEATURE_private_tests)
return()
@@ -17,6 +21,3 @@ qt_internal_add_test(tst_qauthenticator
LIBRARIES
Qt::NetworkPrivate
)
-
-#### Keys ignored in scope 1:.:.:qauthenticator.pro:<TRUE>:
-# _REQUIREMENTS = "qtConfig(private_tests)"
diff --git a/tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp b/tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp
index 744dabd3da..1cd1b6a63b 100644
--- a/tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp
+++ b/tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp
@@ -1,11 +1,12 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/QString>
#include <QTest>
#include <QtCore/QCoreApplication>
#include <QtNetwork/QAuthenticator>
+#include <QtNetwork/QHttpHeaders>
#include <private/qauthenticator_p.h>
@@ -60,8 +61,8 @@ void tst_QAuthenticator::basicAuth()
QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(auth);
QCOMPARE(priv->phase, QAuthenticatorPrivate::Start);
- QList<QPair<QByteArray, QByteArray> > headers;
- headers << qMakePair(QByteArray("WWW-Authenticate"), "Basic " + data.toUtf8());
+ QHttpHeaders headers;
+ headers.append(QByteArray("WWW-Authenticate"), "Basic " + data.toUtf8());
priv->parseHttpResponse(headers, /*isProxy = */ false, {});
QCOMPARE(auth.realm(), realm);
@@ -103,13 +104,13 @@ void tst_QAuthenticator::ntlmAuth()
QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(auth);
QCOMPARE(priv->phase, QAuthenticatorPrivate::Start);
- QList<QPair<QByteArray, QByteArray> > headers;
+ QHttpHeaders headers;
// NTLM phase 1: negotiate
// This phase of NTLM contains no information, other than what we're willing to negotiate
// Current implementation uses flags:
// NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_REQUEST_TARGET
- headers << qMakePair(QByteArrayLiteral("WWW-Authenticate"), QByteArrayLiteral("NTLM"));
+ headers.append(QByteArrayLiteral("WWW-Authenticate"), QByteArrayLiteral("NTLM"));
priv->parseHttpResponse(headers, /*isProxy = */ false, {});
if (sso)
QVERIFY(priv->calculateResponse("GET", "/", u"").startsWith("NTLM "));
@@ -118,7 +119,7 @@ void tst_QAuthenticator::ntlmAuth()
// NTLM phase 2: challenge
headers.clear();
- headers << qMakePair(QByteArray("WWW-Authenticate"), "NTLM " + data.toUtf8());
+ headers.append(QByteArray("WWW-Authenticate"), "NTLM " + data.toUtf8());
priv->parseHttpResponse(headers, /*isProxy = */ false, {});
QEXPECT_FAIL("with-realm", "NTLM authentication code doesn't extract the realm", Continue);
@@ -143,10 +144,10 @@ void tst_QAuthenticator::sha256AndMd5Digest()
QVERIFY(priv->isMethodSupported("digest")); // sanity check
QCOMPARE(priv->phase, QAuthenticatorPrivate::Start);
- QList<QPair<QByteArray, QByteArray>> headers;
+ QHttpHeaders headers;
// Put sha256 first, so that its parsed first...
- headers.emplace_back("WWW-Authenticate", sha256);
- headers.emplace_back("WWW-Authenticate", md5);
+ headers.append("WWW-Authenticate", sha256);
+ headers.append("WWW-Authenticate", md5);
priv->parseHttpResponse(headers, false, QString());
QByteArray response = priv->calculateResponse("GET", "/index", {});
diff --git a/tests/auto/network/kernel/qdnslookup/BLACKLIST b/tests/auto/network/kernel/qdnslookup/BLACKLIST
deleted file mode 100644
index f07a8ce9a3..0000000000
--- a/tests/auto/network/kernel/qdnslookup/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[lookup]
-*
diff --git a/tests/auto/network/kernel/qdnslookup/CMakeLists.txt b/tests/auto/network/kernel/qdnslookup/CMakeLists.txt
index c3112e0f5f..ea539ecbe0 100644
--- a/tests/auto/network/kernel/qdnslookup/CMakeLists.txt
+++ b/tests/auto/network/kernel/qdnslookup/CMakeLists.txt
@@ -1,15 +1,25 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qdnslookup.pro.
-
#####################################################################
## tst_qdnslookup Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qdnslookup LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qdnslookup
SOURCES
tst_qdnslookup.cpp
LIBRARIES
Qt::Network
+ Qt::TestPrivate
+)
+
+qt_internal_extend_target(tst_qdnslookup CONDITION WIN32
+ LIBRARIES
+ iphlpapi
)
diff --git a/tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp b/tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp
index b1867d55fb..af3a74a498 100644
--- a/tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp
+++ b/tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp
@@ -1,39 +1,250 @@
// Copyright (C) 2012 Jeremy Lainé <jeremy.laine@m4x.org>
// Copyright (C) 2016 Intel Corporation.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
#include <QSignalSpy>
+#include <QtTest/private/qpropertytesthelper_p.h>
#include <QtNetwork/QDnsLookup>
+
+#include <QtCore/QRandomGenerator>
#include <QtNetwork/QHostAddress>
+#include <QtNetwork/QNetworkDatagram>
+#include <QtNetwork/QUdpSocket>
+
+#if QT_CONFIG(networkproxy)
+# include <QtNetwork/QNetworkProxyFactory>
+#endif
+#if QT_CONFIG(ssl)
+# include <QtNetwork/QSslSocket>
+#endif
+#ifdef Q_OS_UNIX
+# include <QtCore/QFile>
+#else
+# include <winsock2.h>
+# include <iphlpapi.h>
+#endif
+
+using namespace Qt::StringLiterals;
static const int Timeout = 15000; // 15s
class tst_QDnsLookup: public QObject
{
Q_OBJECT
+ const QString normalDomain = u".test.qt-project.org"_s;
+ const QString idnDomain = u".alqualondë.test.qt-project.org"_s;
+ bool usingIdnDomain = false;
+ bool dnsServersMustWork = false;
+
QString domainName(const QString &input);
QString domainNameList(const QString &input);
QStringList domainNameListAlternatives(const QString &input);
+
+ std::unique_ptr<QDnsLookup> lookupCommon(QDnsLookup::Type type, const QString &domain,
+ const QHostAddress &server = {}, quint16 port = 0,
+ QDnsLookup::Protocol protocol = QDnsLookup::Standard);
+ QStringList formatReply(const QDnsLookup *lookup) const;
+
+ void setNameserver_helper(QDnsLookup::Protocol protocol);
public slots:
void initTestCase();
private slots:
+ void lookupLocalhost();
+ void lookupRoot();
+ void lookupNxDomain_data();
+ void lookupNxDomain();
void lookup_data();
void lookup();
+ void lookupIdn_data() { lookup_data(); }
+ void lookupIdn();
+
void lookupReuse();
void lookupAbortRetry();
+ void setNameserverLoopback();
+ void setNameserver_data();
+ void setNameserver();
+ void dnsOverTls_data();
+ void dnsOverTls();
void bindingsAndProperties();
+ void automatedBindings();
};
+static constexpr qsizetype HeaderSize = 6 * sizeof(quint16);
+static const char preparedDnsQuery[] =
+ // header
+ "\x00\x00" // transaction ID, we'll replace
+ "\x01\x20" // flags
+ "\x00\x01" // qdcount
+ "\x00\x00" // ancount
+ "\x00\x00" // nscount
+ "\x00\x00" // arcount
+ // query:
+ "\x00\x00\x06\x00\x01" // <root domain> IN SOA
+ ;
+
+static QList<QHostAddress> systemNameservers(QDnsLookup::Protocol protocol)
+{
+ QList<QHostAddress> result;
+ if (protocol != QDnsLookup::Standard)
+ return result;
+
+#ifdef Q_OS_WIN
+ ULONG infosize = 0;
+ DWORD r = GetNetworkParams(nullptr, &infosize);
+ auto buffer = std::make_unique<uchar[]>(infosize);
+ auto info = new (buffer.get()) FIXED_INFO;
+ r = GetNetworkParams(info, &infosize);
+ if (r == NO_ERROR) {
+ for (PIP_ADDR_STRING ptr = &info->DnsServerList; ptr; ptr = ptr->Next) {
+ QLatin1StringView addr(ptr->IpAddress.String);
+ result.emplaceBack(addr);
+ }
+ }
+#else
+ auto parseFile = [&](QLatin1StringView path) {
+ QFile f(path);
+ if (!f.open(QIODevice::ReadOnly))
+ return;
+
+ while (!f.atEnd()) {
+ static const char command[] = "nameserver";
+ QByteArray line = f.readLine().simplified();
+ if (!line.startsWith(command))
+ continue;
+
+ QString addr = QLatin1StringView(line).mid(sizeof(command));
+ result.emplaceBack(addr);
+ }
+ };
+ parseFile("/etc/resolv.conf"_L1);
+ parseFile("/run/systemd/resolve/resolv.conf"_L1);
+#endif
+
+ return result;
+}
+
+static QList<QHostAddress> globalPublicNameservers(QDnsLookup::Protocol proto)
+{
+ const char *const candidates[] = {
+ // Google's dns.google
+ "8.8.8.8", "2001:4860:4860::8888",
+ //"8.8.4.4", "2001:4860:4860::8844",
+
+ // CloudFare's one.one.one.one
+ "1.1.1.1", "2606:4700:4700::1111",
+ //"1.0.0.1", "2606:4700:4700::1001",
+
+ // Quad9's dns9
+ //"9.9.9.9", "2620:fe::9",
+ };
+
+ auto udpSendAndReceive = [](const QHostAddress &addr, QByteArray &data) {
+ QUdpSocket socket;
+ socket.connectToHost(addr, 53);
+ if (socket.waitForConnected(1))
+ socket.write(data);
+
+ if (!socket.waitForReadyRead(1000))
+ return socket.errorString();
+
+ QNetworkDatagram dgram = socket.receiveDatagram();
+ if (!dgram.isValid())
+ return socket.errorString();
+
+ data = dgram.data();
+ return QString();
+ };
+
+ auto tlsSendAndReceive = [](const QHostAddress &addr, QByteArray &data) {
+#if QT_CONFIG(ssl)
+ QSslSocket socket;
+ QDeadlineTimer timeout(2000);
+ socket.connectToHostEncrypted(addr.toString(), 853);
+ if (!socket.waitForEncrypted(2000))
+ return socket.errorString();
+
+ quint16 size = qToBigEndian<quint16>(data.size());
+ socket.write(reinterpret_cast<char *>(&size), sizeof(size));
+ socket.write(data);
+
+ if (!socket.waitForReadyRead(timeout.remainingTime()))
+ return socket.errorString();
+ if (socket.bytesAvailable() < 2)
+ return u"protocol error"_s;
+
+ socket.read(reinterpret_cast<char *>(&size), sizeof(size));
+ size = qFromBigEndian(size);
+
+ while (socket.bytesAvailable() < size) {
+ int remaining = timeout.remainingTime();
+ if (remaining < 0 || !socket.waitForReadyRead(remaining))
+ return socket.errorString();
+ }
+
+ data = socket.readAll();
+ return QString();
+#else
+ return u"SSL/TLS support not compiled in"_s;
+#endif
+ };
+
+ QList<QHostAddress> result;
+ QRandomGenerator &rng = *QRandomGenerator::system();
+ for (auto name : candidates) {
+ // check the candidates for reachability
+ QHostAddress addr{QLatin1StringView(name)};
+ quint16 id = quint16(rng());
+ QByteArray data(preparedDnsQuery, sizeof(preparedDnsQuery));
+ char *ptr = data.data();
+ qToBigEndian(id, ptr);
+
+ QString errorString = [&] {
+ switch (proto) {
+ case QDnsLookup::Standard: return udpSendAndReceive(addr, data);
+ case QDnsLookup::DnsOverTls: return tlsSendAndReceive(addr, data);
+ }
+ Q_UNREACHABLE();
+ }();
+ if (!errorString.isEmpty()) {
+ qDebug() << addr << "discarded:" << errorString;
+ continue;
+ }
+
+ ptr = data.data();
+ if (data.size() < HeaderSize) {
+ qDebug() << addr << "discarded: reply too small";
+ continue;
+ }
+
+ bool ok = qFromBigEndian<quint16>(ptr) == id
+ && (ptr[2] & 0x80) // is a reply
+ && (ptr[3] & 0xf) == 0 // rcode NOERROR
+ && qFromBigEndian<quint16>(ptr + 4) == 1 // qdcount
+ && qFromBigEndian<quint16>(ptr + 6) >= 1; // ancount
+ if (!ok) {
+ qDebug() << addr << "discarded: invalid reply";
+ continue;
+ }
+
+ result.emplaceBack(std::move(addr));
+ }
+
+ return result;
+}
+
void tst_QDnsLookup::initTestCase()
{
- QTest::addColumn<QString>("tld");
- QTest::newRow("normal") << ".test.qt-project.org";
- QTest::newRow("idn") << ".alqualond\xc3\xab.test.qt-project.org";
+ if (qgetenv("QTEST_ENVIRONMENT") == "ci")
+ dnsServersMustWork = true;
+
+#if QT_CONFIG(networkproxy)
+ // for DNS-over-TLS
+ QNetworkProxyFactory::setUseSystemConfiguration(true);
+#endif
}
QString tst_QDnsLookup::domainName(const QString &input)
@@ -47,15 +258,16 @@ QString tst_QDnsLookup::domainName(const QString &input)
return nodot;
}
- QFETCH_GLOBAL(QString, tld);
- return input + tld;
+ if (usingIdnDomain)
+ return input + idnDomain;
+ return input + normalDomain;
}
QString tst_QDnsLookup::domainNameList(const QString &input)
{
- QStringList list = input.split(QLatin1Char(';'));
+ const QStringList list = input.split(QLatin1Char(';'));
QString result;
- foreach (const QString &s, list) {
+ for (const QString &s : list) {
if (!result.isEmpty())
result += ';';
result += domainName(s);
@@ -66,229 +278,289 @@ QString tst_QDnsLookup::domainNameList(const QString &input)
QStringList tst_QDnsLookup::domainNameListAlternatives(const QString &input)
{
QStringList alternatives = input.split('|');
- for (int i = 0; i < alternatives.length(); ++i)
+ for (int i = 0; i < alternatives.size(); ++i)
alternatives[i] = domainNameList(alternatives[i]);
return alternatives;
}
+std::unique_ptr<QDnsLookup>
+tst_QDnsLookup::lookupCommon(QDnsLookup::Type type, const QString &domain,
+ const QHostAddress &server, quint16 port,
+ QDnsLookup::Protocol protocol)
+{
+ auto lookup = std::make_unique<QDnsLookup>(type, domainName(domain), protocol, server, port);
+ QObject::connect(lookup.get(), &QDnsLookup::finished,
+ &QTestEventLoop::instance(), &QTestEventLoop::exitLoop);
+ lookup->lookup();
+ QTestEventLoop::instance().enterLoopMSecs(Timeout);
+
+ QDnsLookup::Error error = lookup->error();
+ if (QTestEventLoop::instance().timeout())
+ error = QDnsLookup::TimeoutError;
+
+ if (!dnsServersMustWork && (error == QDnsLookup::ServerFailureError
+ || error == QDnsLookup::ServerRefusedError
+ || error == QDnsLookup::TimeoutError)) {
+ // It's not a QDnsLookup problem if the server refuses to answer the query.
+ // This happens for queries of type ANY through Dnsmasq, for example.
+ [&] {
+ auto me = QMetaEnum::fromType<QDnsLookup::Type>();
+ QString msg = u"Server refused or was unable to answer query; %1 type %3: %2"_s
+ .arg(domain, lookup->errorString(), QString(me.valueToKey(int(type))));
+ QSKIP(msg.toLocal8Bit());
+ }();
+ return {};
+ }
+
+ return lookup;
+}
+
+QStringList tst_QDnsLookup::formatReply(const QDnsLookup *lookup) const
+{
+ QStringList result;
+ QString domain = lookup->name();
+
+ auto shorter = [this](QString value) {
+ const QString &ending = usingIdnDomain ? idnDomain : normalDomain;
+ if (value.endsWith(ending))
+ value.chop(ending.size());
+ else
+ value += u'.';
+ return value;
+ };
+
+ for (const QDnsMailExchangeRecord &rr : lookup->mailExchangeRecords()) {
+ QString entry = u"MX %1 %2"_s.arg(rr.preference(), 5).arg(shorter(rr.exchange()));
+ if (rr.name() != domain)
+ entry = "MX unexpected label to "_L1 + rr.name();
+ result.append(std::move(entry));
+ }
+
+ for (const QDnsServiceRecord &rr : lookup->serviceRecords()) {
+ QString entry = u"SRV %1 %2 %3 %4"_s.arg(rr.priority(), 5).arg(rr.weight())
+ .arg(rr.port()).arg(shorter(rr.target()));
+ if (rr.name() != domain)
+ entry = "SRV unexpected label to "_L1 + rr.name();
+ result.append(std::move(entry));
+ }
+
+ auto addNameRecords = [&](QLatin1StringView rrtype, const QList<QDnsDomainNameRecord> &rrset) {
+ for (const QDnsDomainNameRecord &rr : rrset) {
+ QString entry = u"%1 %2"_s.arg(rrtype, shorter(rr.value()));
+ if (rr.name() != domain)
+ entry = rrtype + " unexpected label to "_L1 + rr.name();
+ result.append(std::move(entry));
+ }
+ };
+ addNameRecords("NS"_L1, lookup->nameServerRecords());
+ addNameRecords("PTR"_L1, lookup->pointerRecords());
+ addNameRecords("CNAME"_L1, lookup->canonicalNameRecords());
+
+ for (const QDnsHostAddressRecord &rr : lookup->hostAddressRecords()) {
+ if (rr.name() != domain)
+ continue; // A and AAAA may appear as extra records in the answer section
+ QHostAddress addr = rr.value();
+ result.append(u"%1 %2"_s
+ .arg(addr.protocol() == QHostAddress::IPv6Protocol ? "AAAA" : "A",
+ addr.toString()));
+ }
+
+ for (const QDnsTextRecord &rr : lookup->textRecords()) {
+ QString entry = "TXT"_L1;
+ for (const QByteArray &data : rr.values()) {
+ entry += u' ';
+ entry += QDebug::toString(data);
+ }
+ result.append(std::move(entry));
+ }
+
+ for (const QDnsTlsAssociationRecord &rr : lookup->tlsAssociationRecords()) {
+ QString entry = u"TLSA %1 %2 %3 %4"_s.arg(int(rr.usage())).arg(int(rr.selector()))
+ .arg(int(rr.matchType())).arg(rr.value().toHex().toUpper());
+ if (rr.name() != domain)
+ entry = "TLSA unexpected label to "_L1 + rr.name();
+ result.append(std::move(entry));
+ }
+
+ result.sort();
+ return result;
+}
+
+void tst_QDnsLookup::lookupLocalhost()
+{
+ auto lookup = lookupCommon(QDnsLookup::Type::A, u"localhost."_s);
+ QVERIFY(lookup);
+ QCOMPARE(lookup->error(), QDnsLookup::NoError);
+
+ QList<QDnsHostAddressRecord> hosts = lookup->hostAddressRecords();
+ QCOMPARE(hosts.size(), 1);
+ QCOMPARE(hosts.at(0).value(), QHostAddress::LocalHost);
+ QVERIFY2(hosts.at(0).name().startsWith(lookup->name()),
+ qPrintable(hosts.at(0).name()));
+}
+
+void tst_QDnsLookup::lookupRoot()
+{
+#ifdef Q_OS_WIN
+ QSKIP("This test fails on Windows as it seems to treat the lookup as a local one.");
+#else
+ auto lookup = lookupCommon(QDnsLookup::Type::NS, u""_s);
+ if (!lookup)
+ return;
+ QCOMPARE(lookup->error(), QDnsLookup::NoError);
+
+ const QList<QDnsDomainNameRecord> servers = lookup->nameServerRecords();
+ QVERIFY(!servers.isEmpty());
+ for (const QDnsDomainNameRecord &ns : servers) {
+ QCOMPARE(ns.name(), QString());
+ QVERIFY(ns.value().endsWith(".root-servers.net"));
+ }
+#endif
+}
+
+void tst_QDnsLookup::lookupNxDomain_data()
+{
+ QTest::addColumn<QDnsLookup::Type>("type");
+ QTest::addColumn<QString>("domain");
+
+ QTest::newRow("a") << QDnsLookup::A << "invalid.invalid";
+ QTest::newRow("aaaa") << QDnsLookup::AAAA << "invalid.invalid";
+ QTest::newRow("any") << QDnsLookup::ANY << "invalid.invalid";
+ QTest::newRow("mx") << QDnsLookup::MX << "invalid.invalid";
+ QTest::newRow("ns") << QDnsLookup::NS << "invalid.invalid";
+ QTest::newRow("ptr") << QDnsLookup::PTR << "invalid.invalid";
+ QTest::newRow("srv") << QDnsLookup::SRV << "invalid.invalid";
+ QTest::newRow("txt") << QDnsLookup::TXT << "invalid.invalid";
+}
+
+void tst_QDnsLookup::lookupNxDomain()
+{
+ QFETCH(QDnsLookup::Type, type);
+ QFETCH(QString, domain);
+
+ auto lookup = lookupCommon(type, domain);
+ if (!lookup)
+ return;
+ QCOMPARE(lookup->name(), domainName(domain));
+ QCOMPARE(lookup->type(), type);
+ QCOMPARE(lookup->error(), QDnsLookup::NotFoundError);
+}
+
void tst_QDnsLookup::lookup_data()
{
- QTest::addColumn<int>("type");
+ QTest::addColumn<QDnsLookup::Type>("type");
QTest::addColumn<QString>("domain");
- QTest::addColumn<int>("error");
- QTest::addColumn<QString>("cname");
- QTest::addColumn<QString>("host");
- QTest::addColumn<QString>("mx");
- QTest::addColumn<QString>("ns");
- QTest::addColumn<QString>("ptr");
- QTest::addColumn<QString>("srv");
- QTest::addColumn<QString>("txt");
-
- QTest::newRow("a-empty") << int(QDnsLookup::A) << "" << int(QDnsLookup::InvalidRequestError) << "" << "" << "" << "" << ""<< "" << "";
- QTest::newRow("a-notfound") << int(QDnsLookup::A) << "invalid.invalid" << int(QDnsLookup::NotFoundError) << "" << "" << "" << "" << "" << "" << "";
- QTest::newRow("a-single") << int(QDnsLookup::A) << "a-single" << int(QDnsLookup::NoError) << "" << "192.0.2.1" << "" << "" << "" << "" << "";
- QTest::newRow("a-multi") << int(QDnsLookup::A) << "a-multi" << int(QDnsLookup::NoError) << "" << "192.0.2.1;192.0.2.2;192.0.2.3" << "" << "" << "" << "" << "";
- QTest::newRow("aaaa-empty") << int(QDnsLookup::AAAA) << "" << int(QDnsLookup::InvalidRequestError) << "" << "" << "" << "" << "" << "" << "";
- QTest::newRow("aaaa-notfound") << int(QDnsLookup::AAAA) << "invalid.invalid" << int(QDnsLookup::NotFoundError) << "" << "" << "" << "" << "" << "" << "";
- QTest::newRow("aaaa-single") << int(QDnsLookup::AAAA) << "aaaa-single" << int(QDnsLookup::NoError) << "" << "2001:db8::1" << "" << "" << "" << "" << "";
- QTest::newRow("aaaa-multi") << int(QDnsLookup::AAAA) << "aaaa-multi" << int(QDnsLookup::NoError) << "" << "2001:db8::1;2001:db8::2;2001:db8::3" << "" << "" << "" << "" << "";
-
- QTest::newRow("any-empty") << int(QDnsLookup::ANY) << "" << int(QDnsLookup::InvalidRequestError) << "" << "" << "" << "" << "" << "" << "";
- QTest::newRow("any-notfound") << int(QDnsLookup::ANY) << "invalid.invalid" << int(QDnsLookup::NotFoundError) << "" << "" << "" << "" << "" << "" << "";
- QTest::newRow("any-a-single") << int(QDnsLookup::ANY) << "a-single" << int(QDnsLookup::NoError) << "" << "192.0.2.1" << "" << "" << "" << "" << "";
- QTest::newRow("any-a-plus-aaaa") << int(QDnsLookup::ANY) << "a-plus-aaaa" << int(QDnsLookup::NoError) << "" << "198.51.100.1;2001:db8::1:1" << "" << "" << "" << "" << "";
- QTest::newRow("any-multi") << int(QDnsLookup::ANY) << "multi" << int(QDnsLookup::NoError) << "" << "198.51.100.1;198.51.100.2;198.51.100.3;2001:db8::1:1;2001:db8::1:2" << "" << "" << "" << "" << "";
-
- QTest::newRow("mx-empty") << int(QDnsLookup::MX) << "" << int(QDnsLookup::InvalidRequestError) << "" << "" << "" << "" << "" << "" << "";
- QTest::newRow("mx-notfound") << int(QDnsLookup::MX) << "invalid.invalid" << int(QDnsLookup::NotFoundError) << "" << "" << "" << "" << "" << "" << "";
- QTest::newRow("mx-single") << int(QDnsLookup::MX) << "mx-single" << int(QDnsLookup::NoError) << "" << "" << "10 multi" << "" << "" << "" << "";
- QTest::newRow("mx-single-cname") << int(QDnsLookup::MX) << "mx-single-cname" << int(QDnsLookup::NoError) << "" << "" << "10 cname" << "" << "" << "" << "";
- QTest::newRow("mx-multi") << int(QDnsLookup::MX) << "mx-multi" << int(QDnsLookup::NoError) << "" << "" << "10 multi;20 a-single" << "" << "" << "" << "";
- QTest::newRow("mx-multi-sameprio") << int(QDnsLookup::MX) << "mx-multi-sameprio" << int(QDnsLookup::NoError) << "" << ""
- << "10 multi;10 a-single|"
- "10 a-single;10 multi" << "" << "" << "" << "";
-
- QTest::newRow("ns-empty") << int(QDnsLookup::NS) << "" << int(QDnsLookup::InvalidRequestError) << "" << "" << "" << "" << "" << "" << "";
- QTest::newRow("ns-notfound") << int(QDnsLookup::NS) << "invalid.invalid" << int(QDnsLookup::NotFoundError) << "" << "" << "" << "" << "" << "" << "";
- QTest::newRow("ns-single") << int(QDnsLookup::NS) << "ns-single" << int(QDnsLookup::NoError) << "" << "" << "" << "ns11.cloudns.net." << "" << "" << "";
- QTest::newRow("ns-multi") << int(QDnsLookup::NS) << "ns-multi" << int(QDnsLookup::NoError) << "" << "" << "" << "ns11.cloudns.net.;ns12.cloudns.net." << "" << "" << "";
-
- QTest::newRow("ptr-empty") << int(QDnsLookup::PTR) << "" << int(QDnsLookup::InvalidRequestError) << "" << "" << "" << "" << "" << "" << "";
- QTest::newRow("ptr-notfound") << int(QDnsLookup::PTR) << "invalid.invalid" << int(QDnsLookup::NotFoundError) << "" << "" << "" << "" << "" << "" << "";
+ QTest::addColumn<QString>("expected");
+
+ QTest::newRow("a-single") << QDnsLookup::A << "a-single"
+ << "A 192.0.2.1";
+ QTest::newRow("a-multi") << QDnsLookup::A << "a-multi"
+ << "A 192.0.2.1;A 192.0.2.2;A 192.0.2.3";
+ QTest::newRow("aaaa-single") << QDnsLookup::AAAA << "aaaa-single"
+ << "AAAA 2001:db8::1";
+ QTest::newRow("aaaa-multi") << QDnsLookup::AAAA << "aaaa-multi"
+ << "AAAA 2001:db8::1;AAAA 2001:db8::2;AAAA 2001:db8::3";
+
+ QTest::newRow("any-a-single") << QDnsLookup::ANY << "a-single"
+ << "A 192.0.2.1";
+ QTest::newRow("any-a-plus-aaaa") << QDnsLookup::ANY << "a-plus-aaaa"
+ << "A 198.51.100.1;AAAA 2001:db8::1:1";
+ QTest::newRow("any-multi") << QDnsLookup::ANY << "multi"
+ << "A 198.51.100.1;A 198.51.100.2;A 198.51.100.3;"
+ "AAAA 2001:db8::1:1;AAAA 2001:db8::1:2" ;
+
+ QTest::newRow("mx-single") << QDnsLookup::MX << "mx-single"
+ << "MX 10 multi";
+ QTest::newRow("mx-single-cname") << QDnsLookup::MX << "mx-single-cname"
+ << "MX 10 cname";
+ QTest::newRow("mx-multi") << QDnsLookup::MX << "mx-multi"
+ << "MX 10 multi;MX 20 a-single";
+ QTest::newRow("mx-multi-sameprio") << QDnsLookup::MX << "mx-multi-sameprio"
+ << "MX 10 a-single;MX 10 multi";
+
+ QTest::newRow("ns-single") << QDnsLookup::NS << "ns-single"
+ << "NS ns11.cloudns.net.";
+ QTest::newRow("ns-multi") << QDnsLookup::NS << "ns-multi"
+ << "NS ns11.cloudns.net.;NS ns12.cloudns.net.";
+
#if 0
// temporarily disabled since the new hosting provider can't insert
// PTR records outside of the in-addr.arpa zone
- QTest::newRow("ptr-single") << int(QDnsLookup::PTR) << "ptr-single" << int(QDnsLookup::NoError) << "" << "" << "" << "" << "a-single" << "" << "";
+ QTest::newRow("ptr-single") << QDnsLookup::PTR << "ptr-single"
+ << "PTR a-single";
#endif
-
- QTest::newRow("srv-empty") << int(QDnsLookup::SRV) << "" << int(QDnsLookup::InvalidRequestError) << "" << "" << "" << "" << "" << "" << "";
- QTest::newRow("srv-notfound") << int(QDnsLookup::SRV) << "invalid.invalid" << int(QDnsLookup::NotFoundError) << "" << "" << "" << "" << "" << "" << "";
- QTest::newRow("srv-single") << int(QDnsLookup::SRV) << "_echo._tcp.srv-single" << int(QDnsLookup::NoError) << "" << "" << "" << "" << "" << "5 0 7 multi" << "";
- QTest::newRow("srv-prio") << int(QDnsLookup::SRV) << "_echo._tcp.srv-prio" << int(QDnsLookup::NoError) << "" << "" << "" << "" << "" << "1 0 7 multi;2 0 7 a-plus-aaaa" << "";
- QTest::newRow("srv-weighted") << int(QDnsLookup::SRV) << "_echo._tcp.srv-weighted" << int(QDnsLookup::NoError) << "" << "" << "" << "" << ""
- << "5 75 7 multi;5 25 7 a-plus-aaaa|"
- "5 25 7 a-plus-aaaa;5 75 7 multi" << "";
- QTest::newRow("srv-multi") << int(QDnsLookup::SRV) << "_echo._tcp.srv-multi" << int(QDnsLookup::NoError) << "" << "" << "" << "" << ""
- << "1 50 7 multi;2 50 7 a-single;2 50 7 aaaa-single;3 50 7 a-multi|"
- "1 50 7 multi;2 50 7 aaaa-single;2 50 7 a-single;3 50 7 a-multi" << "";
-
- QTest::newRow("txt-empty") << int(QDnsLookup::TXT) << "" << int(QDnsLookup::InvalidRequestError) << "" << "" << "" << "" << "" << "" << "";
- QTest::newRow("txt-notfound") << int(QDnsLookup::TXT) << "invalid.invalid" << int(QDnsLookup::NotFoundError) << "" << "" << "" << "" << "" << "" << "";
- QTest::newRow("txt-single") << int(QDnsLookup::TXT) << "txt-single" << int(QDnsLookup::NoError) << "" << "" << "" << "" << "" << "" << "Hello";
- QTest::newRow("txt-multi-onerr") << int(QDnsLookup::TXT) << "txt-multi-onerr" << int(QDnsLookup::NoError) << "" << "" << "" << "" << "" << ""
- << QString::fromLatin1("Hello\0World", sizeof("Hello\0World") - 1);
- QTest::newRow("txt-multi-multirr") << int(QDnsLookup::TXT) << "txt-multi-multirr" << int(QDnsLookup::NoError) << "" << "" << "" << "" << "" << "" << "Hello;World";
-}
-
-static QByteArray msgDnsLookup(QDnsLookup::Error actualError,
- int expectedError,
- const QString &domain,
- const QString &cname,
- const QString &host,
- const QString &srv,
- const QString &mx,
- const QString &ns,
- const QString &ptr,
- const QString &errorString)
-{
- QString result;
- QTextStream str(&result);
- str << "Actual error: " << actualError;
- if (!errorString.isEmpty())
- str << " (" << errorString << ')';
- str << ", expected: " << expectedError;
- str << ", domain: " << domain;
- if (!cname.isEmpty())
- str << ", cname: " << cname;
- str << ", host: " << host;
- if (!srv.isEmpty())
- str << " server: " << srv;
- if (!mx.isEmpty())
- str << " mx: " << mx;
- if (!ns.isEmpty())
- str << " ns: " << ns;
- if (!ptr.isEmpty())
- str << " ptr: " << ptr;
- return result.toLocal8Bit();
+ QTest::newRow("ptr-1.1.1.1") << QDnsLookup::PTR << "1.1.1.1.in-addr.arpa."
+ << "PTR one.one.one.one.";
+ QTest::newRow("ptr-8.8.8.8") << QDnsLookup::PTR << "8.8.8.8.in-addr.arpa."
+ << "PTR dns.google.";
+ QTest::newRow("ptr-2001:4860:4860::8888")
+ << QDnsLookup::PTR << "8.8.8.8.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.6.8.4.0.6.8.4.1.0.0.2.ip6.arpa."
+ << "PTR dns.google.";
+ QTest::newRow("ptr-2606:4700:4700::1111")
+ << QDnsLookup::PTR << "1.1.1.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.7.4.0.0.7.4.6.0.6.2.ip6.arpa."
+ << "PTR one.one.one.one.";
+
+ QTest::newRow("srv-single") << QDnsLookup::SRV << "_echo._tcp.srv-single"
+ << "SRV 5 0 7 multi";
+ QTest::newRow("srv-prio") << QDnsLookup::SRV << "_echo._tcp.srv-prio"
+ << "SRV 1 0 7 multi;SRV 2 0 7 a-plus-aaaa";
+ QTest::newRow("srv-weighted") << QDnsLookup::SRV << "_echo._tcp.srv-weighted"
+ << "SRV 5 25 7 a-plus-aaaa;SRV 5 75 7 multi";
+ QTest::newRow("srv-multi") << QDnsLookup::SRV << "_echo._tcp.srv-multi"
+ << "SRV 1 50 7 multi;"
+ "SRV 2 50 7 a-single;"
+ "SRV 2 50 7 aaaa-single;"
+ "SRV 3 50 7 a-multi";
+
+ QTest::newRow("tlsa") << QDnsLookup::Type::TLSA << "_25._tcp.multi"
+ << "TLSA 3 1 1 0123456789ABCDEFFEDCBA9876543210"
+ "0123456789ABCDEFFEDCBA9876543210";
+
+ QTest::newRow("txt-single") << QDnsLookup::TXT << "txt-single"
+ << "TXT \"Hello\"";
+ QTest::newRow("txt-multi-onerr") << QDnsLookup::TXT << "txt-multi-onerr"
+ << "TXT \"Hello\" \"World\"";
+ QTest::newRow("txt-multi-multirr") << QDnsLookup::TXT << "txt-multi-multirr"
+ << "TXT \"Hello\";TXT \"World\"";
}
void tst_QDnsLookup::lookup()
{
- QFETCH(int, type);
+ QFETCH(QDnsLookup::Type, type);
QFETCH(QString, domain);
- QFETCH(int, error);
- QFETCH(QString, cname);
- QFETCH(QString, host);
- QFETCH(QString, mx);
- QFETCH(QString, ns);
- QFETCH(QString, ptr);
- QFETCH(QString, srv);
- QFETCH(QString, txt);
-
- // transform the inputs
- domain = domainName(domain);
- cname = domainName(cname);
- ns = domainNameList(ns);
- ptr = domainNameList(ptr);
-
- // SRV and MX have reply entries that can change order
- // and we can't sort
- QStringList mx_alternatives = domainNameListAlternatives(mx);
- QStringList srv_alternatives = domainNameListAlternatives(srv);
+ QFETCH(QString, expected);
- QDnsLookup lookup;
- lookup.setType(static_cast<QDnsLookup::Type>(type));
- lookup.setName(domain);
- lookup.lookup();
- QTRY_VERIFY_WITH_TIMEOUT(lookup.isFinished(), Timeout);
+ std::unique_ptr<QDnsLookup> lookup = lookupCommon(type, domain);
+ if (!lookup)
+ return;
-#if defined(Q_OS_ANDROID)
- if (lookup.errorString() == QStringLiteral("Not yet supported on Android"))
- QEXPECT_FAIL("", "Not yet supported on Android", Abort);
+#ifdef Q_OS_WIN
+ if (QTest::currentDataTag() == "tlsa"_L1)
+ QSKIP("WinDNS doesn't work properly with TLSA records and we don't know why");
#endif
+ QCOMPARE(lookup->errorString(), QString());
+ QCOMPARE(lookup->error(), QDnsLookup::NoError);
+ QCOMPARE(lookup->type(), type);
+ QCOMPARE(lookup->name(), domainName(domain));
+
+ QString result = formatReply(lookup.get()).join(u';');
+ QCOMPARE(result, expected);
+
+ // confirm that MX and SRV records are properly sorted
+ const QList<QDnsMailExchangeRecord> mx = lookup->mailExchangeRecords();
+ for (qsizetype i = 1; i < mx.size(); ++i)
+ QCOMPARE_GE(mx[i].preference(), mx[i - 1].preference());
+
+ const QList<QDnsServiceRecord> srv = lookup->serviceRecords();
+ for (qsizetype i = 1; i < srv.size(); ++i)
+ QCOMPARE_GE(srv[i].priority(), srv[i - 1].priority());
+}
- QVERIFY2(int(lookup.error()) == error,
- msgDnsLookup(lookup.error(), error, domain, cname, host, srv, mx, ns, ptr, lookup.errorString()));
- if (error == QDnsLookup::NoError)
- QVERIFY(lookup.errorString().isEmpty());
- QCOMPARE(int(lookup.type()), type);
- QCOMPARE(lookup.name(), domain);
-
- // canonical names
- if (!cname.isEmpty()) {
- QVERIFY(!lookup.canonicalNameRecords().isEmpty());
- const QDnsDomainNameRecord cnameRecord = lookup.canonicalNameRecords().first();
- QCOMPARE(cnameRecord.name(), domain);
- QCOMPARE(cnameRecord.value(), cname);
- } else {
- QVERIFY(lookup.canonicalNameRecords().isEmpty());
- }
-
- // host addresses
- const QString hostName = cname.isEmpty() ? domain : cname;
- QStringList addresses;
- foreach (const QDnsHostAddressRecord &record, lookup.hostAddressRecords()) {
- //reply may include A & AAAA records for nameservers, ignore them and only look at records matching the query
- if (record.name() == hostName)
- addresses << record.value().toString().toLower();
- }
- addresses.sort();
- QCOMPARE(addresses.join(';'), host);
-
- // mail exchanges
- QStringList mailExchanges;
- foreach (const QDnsMailExchangeRecord &record, lookup.mailExchangeRecords()) {
- QCOMPARE(record.name(), domain);
- mailExchanges << QString::number(record.preference()) + QLatin1Char(' ') + record.exchange();
- }
- QVERIFY2(mx_alternatives.contains(mailExchanges.join(';')),
- qPrintable("Actual: " + mailExchanges.join(';') + "\nExpected one of:\n" + mx_alternatives.join('\n')));
-
- // name servers
- QStringList nameServers;
- foreach (const QDnsDomainNameRecord &record, lookup.nameServerRecords()) {
- //reply may include NS records for authoritative nameservers, ignore them and only look at records matching the query
- if (record.name() == domain)
- nameServers << record.value();
- }
- nameServers.sort();
- QCOMPARE(nameServers.join(';'), ns);
-
- // pointers
- if (!ptr.isEmpty()) {
- QVERIFY(!lookup.pointerRecords().isEmpty());
- const QDnsDomainNameRecord ptrRecord = lookup.pointerRecords().first();
- QCOMPARE(ptrRecord.name(), domain);
- QCOMPARE(ptrRecord.value(), ptr);
- } else {
- QVERIFY(lookup.pointerRecords().isEmpty());
- }
-
- // services
- QStringList services;
- foreach (const QDnsServiceRecord &record, lookup.serviceRecords()) {
- QCOMPARE(record.name(), domain);
- services << (QString::number(record.priority()) + QLatin1Char(' ')
- + QString::number(record.weight()) + QLatin1Char(' ')
- + QString::number(record.port()) + QLatin1Char(' ') + record.target());
- }
- QVERIFY2(srv_alternatives.contains(services.join(';')),
- qPrintable("Actual: " + services.join(';') + "\nExpected one of:\n" + srv_alternatives.join('\n')));
-
- // text
- QStringList texts;
- foreach (const QDnsTextRecord &record, lookup.textRecords()) {
- QCOMPARE(record.name(), domain);
- QString text;
- foreach (const QByteArray &ba, record.values()) {
- if (!text.isEmpty())
- text += '\0';
- text += QString::fromLatin1(ba);
- }
- texts << text;
- }
- texts.sort();
- QCOMPARE(texts.join(';'), txt);
+void tst_QDnsLookup::lookupIdn()
+{
+ usingIdnDomain = true;
+ lookup();
+ usingIdnDomain = false;
}
void tst_QDnsLookup::lookupReuse()
@@ -301,11 +573,6 @@ void tst_QDnsLookup::lookupReuse()
lookup.lookup();
QTRY_VERIFY_WITH_TIMEOUT(lookup.isFinished(), Timeout);
-#if defined(Q_OS_ANDROID)
- if (lookup.errorString() == QStringLiteral("Not yet supported on Android"))
- QEXPECT_FAIL("", "Not yet supported on Android", Abort);
-#endif
-
QCOMPARE(int(lookup.error()), int(QDnsLookup::NoError));
QVERIFY(!lookup.hostAddressRecords().isEmpty());
QCOMPARE(lookup.hostAddressRecords().first().name(), domainName("a-single"));
@@ -342,23 +609,124 @@ void tst_QDnsLookup::lookupAbortRetry()
lookup.lookup();
QTRY_VERIFY_WITH_TIMEOUT(lookup.isFinished(), Timeout);
-#if defined(Q_OS_ANDROID)
- if (lookup.errorString() == QStringLiteral("Not yet supported on Android"))
- QEXPECT_FAIL("", "Not yet supported on Android", Abort);
-#endif
-
QCOMPARE(int(lookup.error()), int(QDnsLookup::NoError));
QVERIFY(!lookup.hostAddressRecords().isEmpty());
QCOMPARE(lookup.hostAddressRecords().first().name(), domainName("aaaa-single"));
QCOMPARE(lookup.hostAddressRecords().first().value(), QHostAddress("2001:db8::1"));
}
-void tst_QDnsLookup::bindingsAndProperties()
+void tst_QDnsLookup::setNameserverLoopback()
+{
+#ifdef Q_OS_WIN
+ // Windows doesn't like sending DNS requests to ports other than 53, so
+ // let's try it first.
+ constexpr quint16 DesiredPort = 53;
+#else
+ // Trying to bind to port 53 will fail on Unix systems unless this test is
+ // run as root, so we try mDNS's port (to help decoding in a packet capture).
+ constexpr quint16 DesiredPort = 5353; // mDNS
+#endif
+ // random loopback address so multiple copies of this test can run
+ QHostAddress desiredAddress(0x7f000000 | QRandomGenerator::system()->bounded(0xffffff));
+
+ QUdpSocket server;
+ if (!server.bind(desiredAddress, DesiredPort)) {
+ // port in use, try a random one
+ server.bind(QHostAddress::LocalHost, 0);
+ }
+ QCOMPARE(server.state(), QUdpSocket::BoundState);
+
+ QDnsLookup lookup(QDnsLookup::Type::A, u"somelabel.somedomain"_s);
+ QSignalSpy spy(&lookup, SIGNAL(finished()));
+ lookup.setNameserver(server.localAddress(), server.localPort());
+
+ // QDnsLookup is threaded, so we can answer on the main thread
+ QObject::connect(&server, &QUdpSocket::readyRead,
+ &QTestEventLoop::instance(), &QTestEventLoop::exitLoop);
+ QObject::connect(&lookup, &QDnsLookup::finished,
+ &QTestEventLoop::instance(), &QTestEventLoop::exitLoop);
+ lookup.lookup();
+ QTestEventLoop::instance().enterLoop(5);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ QVERIFY2(spy.isEmpty(), qPrintable(lookup.errorString()));
+
+ QNetworkDatagram dgram = server.receiveDatagram();
+ QByteArray data = dgram.data();
+ QCOMPARE_GT(data.size(), HeaderSize);
+
+ quint8 opcode = (quint8(data.at(2)) >> 3) & 0xF;
+ QCOMPARE(opcode, 0); // standard query
+
+ // send an NXDOMAIN reply to release the lookup thread
+ QByteArray reply = data;
+ reply[2] = 0x80U; // header->qr = true;
+ reply[3] = 3; // header->rcode = NXDOMAIN;
+ server.writeDatagram(reply.constData(), reply.size(), dgram.senderAddress(),
+ dgram.senderPort());
+ server.close();
+
+ // now check that the QDnsLookup finished
+ QTestEventLoop::instance().enterLoop(5);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ QCOMPARE(spy.size(), 1);
+ QCOMPARE(lookup.error(), QDnsLookup::NotFoundError);
+}
+
+template <QDnsLookup::Protocol Protocol>
+static void setNameserver_data_helper(const QByteArray &protoName)
{
- QFETCH_GLOBAL(const QString, tld);
- if (tld == QStringLiteral("idn"))
+ if (!QDnsLookup::isProtocolSupported(Protocol))
+ QSKIP(protoName + " not supported");
+
+ static QList<QHostAddress> servers = systemNameservers(Protocol)
+ + globalPublicNameservers(Protocol);
+ QTest::addColumn<QHostAddress>("server");
+
+ if (servers.isEmpty()) {
+ QSKIP("No reachable " + protoName + " servers were found");
+ } else {
+ for (const QHostAddress &h : std::as_const(servers))
+ QTest::addRow("%s", qUtf8Printable(h.toString())) << h;
+ }
+}
+
+void tst_QDnsLookup::setNameserver_data()
+{
+ setNameserver_data_helper<QDnsLookup::Standard>("DNS");
+}
+
+void tst_QDnsLookup::setNameserver_helper(QDnsLookup::Protocol protocol)
+{
+ QFETCH(QHostAddress, server);
+ QElapsedTimer timer;
+ timer.start();
+ std::unique_ptr<QDnsLookup> lookup =
+ lookupCommon(QDnsLookup::Type::A, "a-single", server, 0, protocol);
+ if (!lookup)
return;
+ qDebug() << "Lookup took" << timer.elapsed() << "ms";
+ QCOMPARE(lookup->error(), QDnsLookup::NoError);
+ QString result = formatReply(lookup.get()).join(';');
+ QCOMPARE(result, "A 192.0.2.1");
+}
+
+void tst_QDnsLookup::setNameserver()
+{
+ setNameserver_helper(QDnsLookup::Standard);
+}
+
+void tst_QDnsLookup::dnsOverTls_data()
+{
+ setNameserver_data_helper<QDnsLookup::DnsOverTls>("DNS-over-TLS");
+}
+
+void tst_QDnsLookup::dnsOverTls()
+{
+ setNameserver_helper(QDnsLookup::DnsOverTls);
+}
+void tst_QDnsLookup::bindingsAndProperties()
+{
QDnsLookup lookup;
lookup.setType(QDnsLookup::A);
@@ -367,7 +735,7 @@ void tst_QDnsLookup::bindingsAndProperties()
const QSignalSpy typeChangeSpy(&lookup, &QDnsLookup::typeChanged);
dnsTypeProp = QDnsLookup::AAAA;
- QCOMPARE(typeChangeSpy.count(), 1);
+ QCOMPARE(typeChangeSpy.size(), 1);
QCOMPARE(lookup.type(), QDnsLookup::AAAA);
dnsTypeProp.setBinding(lookup.bindableType().makeBinding());
@@ -379,7 +747,7 @@ void tst_QDnsLookup::bindingsAndProperties()
const QSignalSpy nameChangeSpy(&lookup, &QDnsLookup::nameChanged);
nameProp = QStringLiteral("a-plus-aaaa");
- QCOMPARE(nameChangeSpy.count(), 1);
+ QCOMPARE(nameChangeSpy.size(), 1);
QCOMPARE(lookup.name(), QStringLiteral("a-plus-aaaa"));
nameProp.setBinding(lookup.bindableName().makeBinding());
@@ -389,14 +757,55 @@ void tst_QDnsLookup::bindingsAndProperties()
QProperty<QHostAddress> nameserverProp;
lookup.bindableNameserver().setBinding(Qt::makePropertyBinding(nameserverProp));
const QSignalSpy nameserverChangeSpy(&lookup, &QDnsLookup::nameserverChanged);
+ const QSignalSpy nameserverPortChangeSpy(&lookup, &QDnsLookup::nameserverPortChanged);
nameserverProp = QHostAddress::LocalHost;
- QCOMPARE(nameserverChangeSpy.count(), 1);
+ QCOMPARE(nameserverChangeSpy.size(), 1);
+ QCOMPARE(nameserverPortChangeSpy.size(), 0);
QCOMPARE(lookup.nameserver(), QHostAddress::LocalHost);
nameserverProp.setBinding(lookup.bindableNameserver().makeBinding());
lookup.setNameserver(QHostAddress::Any);
QCOMPARE(nameserverProp.value(), QHostAddress::Any);
+ QCOMPARE(nameserverChangeSpy.size(), 2);
+ QCOMPARE(nameserverPortChangeSpy.size(), 0);
+
+ lookup.setNameserver(QHostAddress::LocalHostIPv6, 10053);
+ QCOMPARE(nameserverProp.value(), QHostAddress::LocalHostIPv6);
+ QCOMPARE(nameserverChangeSpy.size(), 3);
+ QCOMPARE(nameserverPortChangeSpy.size(), 1);
+}
+
+void tst_QDnsLookup::automatedBindings()
+{
+ QDnsLookup lookup;
+
+ QTestPrivate::testReadWritePropertyBasics(lookup, u"aaaa"_s, u"txt"_s, "name");
+ if (QTest::currentTestFailed()) {
+ qDebug("Failed property test for QDnsLookup::name");
+ return;
+ }
+
+ QTestPrivate::testReadWritePropertyBasics(lookup, QDnsLookup::AAAA, QDnsLookup::TXT, "type");
+ if (QTest::currentTestFailed()) {
+ qDebug("Failed property test for QDnsLookup::type");
+ return;
+ }
+
+ QTestPrivate::testReadWritePropertyBasics(lookup, QHostAddress{QHostAddress::Any},
+ QHostAddress{QHostAddress::LocalHost},
+ "nameserver");
+ if (QTest::currentTestFailed()) {
+ qDebug("Failed property test for QDnsLookup::nameserver");
+ return;
+ }
+
+ QTestPrivate::testReadWritePropertyBasics(lookup, quint16(123), quint16(456),
+ "nameserverPort");
+ if (QTest::currentTestFailed()) {
+ qDebug("Failed property test for QDnsLookup::nameserverPort");
+ return;
+ }
}
QTEST_MAIN(tst_QDnsLookup)
diff --git a/tests/auto/network/kernel/qdnslookup_appless/CMakeLists.txt b/tests/auto/network/kernel/qdnslookup_appless/CMakeLists.txt
index a4e1c68edf..41cf19753f 100644
--- a/tests/auto/network/kernel/qdnslookup_appless/CMakeLists.txt
+++ b/tests/auto/network/kernel/qdnslookup_appless/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qdnslookup_appless.pro.
-
#####################################################################
## tst_qdnslookup_appless Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qdnslookup_appless LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qdnslookup_appless
SOURCES
tst_qdnslookup_appless.cpp
diff --git a/tests/auto/network/kernel/qdnslookup_appless/tst_qdnslookup_appless.cpp b/tests/auto/network/kernel/qdnslookup_appless/tst_qdnslookup_appless.cpp
index 52a53ea171..21393ee628 100644
--- a/tests/auto/network/kernel/qdnslookup_appless/tst_qdnslookup_appless.cpp
+++ b/tests/auto/network/kernel/qdnslookup_appless/tst_qdnslookup_appless.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2012 Jeremy Lainé <jeremy.laine@m4x.org>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/QCoreApplication>
#include <QtNetwork/QDnsLookup>
diff --git a/tests/auto/network/kernel/qhostaddress/CMakeLists.txt b/tests/auto/network/kernel/qhostaddress/CMakeLists.txt
index 6a181d2716..e11a600b60 100644
--- a/tests/auto/network/kernel/qhostaddress/CMakeLists.txt
+++ b/tests/auto/network/kernel/qhostaddress/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qhostaddress.pro.
-
#####################################################################
## tst_qhostaddress Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qhostaddress LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qhostaddress
SOURCES
tst_qhostaddress.cpp
diff --git a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp
index 4dbf891822..18d1c04a85 100644
--- a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp
+++ b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp
@@ -1,6 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// Copyright (C) 2016 Intel Corporation.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qhostaddress.h>
#include <private/qhostaddress_p.h>
@@ -15,7 +15,7 @@
# include <qt_windows.h>
#endif
-#if defined(Q_OS_ANDROID) || defined(Q_OS_WASM)
+#if defined(Q_OS_ANDROID) || defined(Q_OS_WASM) || defined(Q_OS_VXWORKS)
# include <netinet/in.h>
#endif
@@ -326,6 +326,12 @@ void tst_QHostAddress::isEqual_data()
QTest::newRow("anyv6-anyv4-local") << QHostAddress(QHostAddress::AnyIPv6) << QHostAddress(QHostAddress::AnyIPv4) << (int)QHostAddress::ConvertLocalHost << false;
QTest::newRow("any-anyv4-local") << QHostAddress(QHostAddress::Any) << QHostAddress(QHostAddress::AnyIPv4) << (int)QHostAddress::ConvertLocalHost << false;
QTest::newRow("any-anyv6-local") << QHostAddress(QHostAddress::Any) << QHostAddress(QHostAddress::AnyIPv6) << (int)QHostAddress::ConvertLocalHost << false;
+ QTest::newRow("localhostv6-any-tolerant") << QHostAddress(QHostAddress::LocalHostIPv6) << QHostAddress(QHostAddress::Any) << (int)QHostAddress::TolerantConversion << false;
+ QTest::newRow("localhostv4-any-tolerant") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::Any) << (int)QHostAddress::TolerantConversion << false;
+ QTest::newRow("localhostv6-anyv6-tolerant") << QHostAddress(QHostAddress::LocalHostIPv6) << QHostAddress(QHostAddress::AnyIPv6) << (int)QHostAddress::TolerantConversion << false;
+ QTest::newRow("localhostv4-anyv6-tolerant") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::AnyIPv6) << (int)QHostAddress::TolerantConversion << false;
+ QTest::newRow("localhostv6-anyv4-tolerant") << QHostAddress(QHostAddress::LocalHostIPv6) << QHostAddress(QHostAddress::AnyIPv4) << (int)QHostAddress::TolerantConversion << false;
+ QTest::newRow("localhostv4-anyv4-tolerant") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::AnyIPv4) << (int)QHostAddress::TolerantConversion << false;
}
void tst_QHostAddress::isEqual()
@@ -697,6 +703,7 @@ void tst_QHostAddress::classification()
bool isUniqueLocalAddress = (result == UniqueLocalAddress);
bool isMulticast = (result == MulticastAddress);
bool isBroadcast = (result == BroadcastAddress);
+ bool isPrivateUse = (result == PrivateNetworkAddress || result == UniqueLocalAddress);
QCOMPARE(address.isLoopback(), isLoopback);
QCOMPARE(address.isGlobal(), isGlobal);
@@ -705,6 +712,7 @@ void tst_QHostAddress::classification()
QCOMPARE(address.isUniqueLocalUnicast(), isUniqueLocalAddress);
QCOMPARE(address.isMulticast(), isMulticast);
QCOMPARE(address.isBroadcast(), isBroadcast);
+ QCOMPARE(address.isPrivateUse(), isPrivateUse);
}
void tst_QHostAddress::convertv4v6_data()
diff --git a/tests/auto/network/kernel/qhostinfo/CMakeLists.txt b/tests/auto/network/kernel/qhostinfo/CMakeLists.txt
index efaad8826e..dc7ab3b221 100644
--- a/tests/auto/network/kernel/qhostinfo/CMakeLists.txt
+++ b/tests/auto/network/kernel/qhostinfo/CMakeLists.txt
@@ -1,7 +1,11 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qhostinfo.pro.
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qhostinfo LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
if(NOT QT_FEATURE_private_tests)
return()
@@ -19,9 +23,6 @@ qt_internal_add_test(tst_qhostinfo
Qt::NetworkPrivate
)
-#### Keys ignored in scope 1:.:.:qhostinfo.pro:<TRUE>:
-# _REQUIREMENTS = "qtConfig(private_tests)"
-
## Scopes:
#####################################################################
diff --git a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp
index f5d1c1cb5e..bd4bb7ef81 100644
--- a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp
+++ b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp
@@ -1,51 +1,52 @@
// Copyright (C) 2016 The Qt Company Ltd.
// Copyright (C) 2016 Intel Corporation.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// When using WinSock2 on Windows, it's the first thing that can be included
// (except qglobal.h), or else you'll get tons of compile errors
#include <qglobal.h>
-// To prevent windows system header files from re-defining min/max
-#define NOMINMAX 1
-
#if defined(Q_OS_WIN)
# include <winsock2.h>
# include <ws2tcpip.h>
#endif
-#include <QTest>
-#include <QTestEventLoop>
-#include <QProcess>
+#include <qhostinfo.h>
+#include "private/qhostinfo_p.h"
+#include "private/qnativesocketengine_p.h"
+
#include <QCoreApplication>
#include <QDebug>
-#include <QTcpSocket>
#include <QTcpServer>
+#include <QTcpSocket>
+#include <QTest>
+#include <QTestEventLoop>
#include <private/qthread_p.h>
-#include <time.h>
+#include <sys/types.h>
+
#if defined(Q_OS_WIN)
-#include <qt_windows.h>
+# include <qt_windows.h>
+# ifdef gai_strerror
+# undef gai_strerror
+# define gai_strerror gai_strerrorA
+# endif
#else
-#include <unistd.h>
-#include <signal.h>
-#endif
-
-#include <qhostinfo.h>
-#include "private/qhostinfo_p.h"
-
-#include <sys/types.h>
-#if defined(Q_OS_UNIX)
-# include <sys/socket.h>
# include <netdb.h>
+# include <sys/socket.h>
+# include <unistd.h>
+#endif
+#ifndef NI_MAXHOST
+# define NI_MAXHOST 1025
#endif
#include "../../../network-settings.h"
#define TEST_DOMAIN ".test.qt-project.org"
+using namespace std::chrono_literals;
class tst_QHostInfo : public QObject
{
@@ -84,15 +85,55 @@ private slots:
void cache();
void abortHostLookup();
-protected slots:
- void resultsReady(const QHostInfo &);
private:
bool ipv6LookupsAvailable;
bool ipv6Available;
- bool lookupDone;
- int lookupsDoneCounter;
+};
+
+class tst_QHostInfo_Helper : public QObject
+{
+ Q_OBJECT
+protected slots:
+ void resultsReady(const QHostInfo &);
+public:
+ tst_QHostInfo_Helper(const QString &hostname)
+ : hostname(hostname)
+ {}
+
+ QString hostname;
+ bool lookupDone = false;
+ int lookupsDoneCounter = 0;
QHostInfo lookupResults;
+
+ void blockingLookup()
+ {
+ lookupResults = QHostInfo::fromName(hostname);
+ lookupDone = true;
+ ++lookupsDoneCounter;
+ }
+ void lookupHostOldStyle()
+ {
+ QHostInfo::lookupHost(hostname, this, SLOT(resultsReady(QHostInfo)));
+ }
+ void lookupHostNewStyle()
+ {
+ QHostInfo::lookupHost(hostname, this, &tst_QHostInfo_Helper::resultsReady);
+ }
+ void lookupHostLambda()
+ {
+ QHostInfo::lookupHost(hostname, this, [this](const QHostInfo &hostInfo) {
+ resultsReady(hostInfo);
+ });
+ }
+
+ bool waitForResults(std::chrono::milliseconds timeout = 15s)
+ {
+ QTestEventLoop::instance().enterLoop(timeout);
+ return !QTestEventLoop::instance().timeout() && lookupDone;
+ }
+
+ void checkResults(QHostInfo::HostInfoError err, const QString &addresses);
};
void tst_QHostInfo::swapFunction()
@@ -208,26 +249,15 @@ void tst_QHostInfo::lookupIPv4_data()
QTest::newRow("idn-unicode") << QString::fromLatin1("a-single.alqualond\353" TEST_DOMAIN) << "192.0.2.1" << int(QHostInfo::NoError);
}
-void tst_QHostInfo::lookupIPv4()
+void tst_QHostInfo_Helper::checkResults(QHostInfo::HostInfoError err, const QString &addresses)
{
- QFETCH(QString, hostname);
- QFETCH(int, err);
- QFETCH(QString, addresses);
-
- lookupDone = false;
- QHostInfo::lookupHost(hostname, this, SLOT(resultsReady(QHostInfo)));
-
- QTestEventLoop::instance().enterLoop(10);
- QVERIFY(!QTestEventLoop::instance().timeout());
- QVERIFY(lookupDone);
-
if ((int)lookupResults.error() != (int)err) {
qWarning() << hostname << "=>" << lookupResults.errorString();
}
- QCOMPARE((int)lookupResults.error(), (int)err);
+ QCOMPARE(lookupResults.error(), err);
QStringList tmp;
- for (int i = 0; i < lookupResults.addresses().count(); ++i)
+ for (int i = 0; i < lookupResults.addresses().size(); ++i)
tmp.append(lookupResults.addresses().at(i).toString());
tmp.sort();
@@ -237,6 +267,18 @@ void tst_QHostInfo::lookupIPv4()
QCOMPARE(tmp.join(' '), expected.join(' '));
}
+void tst_QHostInfo::lookupIPv4()
+{
+ QFETCH(QString, hostname);
+ QFETCH(int, err);
+ QFETCH(QString, addresses);
+
+ tst_QHostInfo_Helper helper(hostname);
+ helper.lookupHostOldStyle();
+ QVERIFY(helper.waitForResults());
+ helper.checkResults(QHostInfo::HostInfoError(err), addresses);
+}
+
void tst_QHostInfo::lookupIPv6_data()
{
QTest::addColumn<QString>("hostname");
@@ -262,24 +304,10 @@ void tst_QHostInfo::lookupIPv6()
if (!ipv6LookupsAvailable)
QSKIP("This platform does not support IPv6 lookups");
- lookupDone = false;
- QHostInfo::lookupHost(hostname, this, SLOT(resultsReady(QHostInfo)));
-
- QTestEventLoop::instance().enterLoop(10);
- QVERIFY(!QTestEventLoop::instance().timeout());
- QVERIFY(lookupDone);
-
- QCOMPARE((int)lookupResults.error(), (int)err);
-
- QStringList tmp;
- for (int i = 0; i < lookupResults.addresses().count(); ++i)
- tmp.append(lookupResults.addresses().at(i).toString());
- tmp.sort();
-
- QStringList expected = addresses.split(' ');
- expected.sort();
-
- QCOMPARE(tmp.join(' ').toLower(), expected.join(' ').toLower());
+ tst_QHostInfo_Helper helper(hostname);
+ helper.lookupHostOldStyle();
+ QVERIFY(helper.waitForResults());
+ helper.checkResults(QHostInfo::HostInfoError(err), addresses);
}
void tst_QHostInfo::lookupConnectToFunctionPointer_data()
@@ -293,26 +321,10 @@ void tst_QHostInfo::lookupConnectToFunctionPointer()
QFETCH(int, err);
QFETCH(QString, addresses);
- lookupDone = false;
- QHostInfo::lookupHost(hostname, this, &tst_QHostInfo::resultsReady);
-
- QTestEventLoop::instance().enterLoop(10);
- QVERIFY(!QTestEventLoop::instance().timeout());
- QVERIFY(lookupDone);
-
- if (int(lookupResults.error()) != int(err))
- qWarning() << hostname << "=>" << lookupResults.errorString();
- QCOMPARE(int(lookupResults.error()), int(err));
-
- QStringList tmp;
- for (const auto &result : lookupResults.addresses())
- tmp.append(result.toString());
- tmp.sort();
-
- QStringList expected = addresses.split(' ');
- expected.sort();
-
- QCOMPARE(tmp.join(' '), expected.join(' '));
+ tst_QHostInfo_Helper helper(hostname);
+ helper.lookupHostNewStyle();
+ QVERIFY(helper.waitForResults());
+ helper.checkResults(QHostInfo::HostInfoError(err), addresses);
}
void tst_QHostInfo::lookupConnectToFunctionPointerDeleted()
@@ -337,89 +349,38 @@ void tst_QHostInfo::lookupConnectToLambda()
QFETCH(int, err);
QFETCH(QString, addresses);
- lookupDone = false;
- QHostInfo::lookupHost(hostname, [this](const QHostInfo &hostInfo) {
- resultsReady(hostInfo);
- });
-
- QTestEventLoop::instance().enterLoop(10);
- QVERIFY(!QTestEventLoop::instance().timeout());
- QVERIFY(lookupDone);
-
- if (int(lookupResults.error()) != int(err))
- qWarning() << hostname << "=>" << lookupResults.errorString();
- QCOMPARE(int(lookupResults.error()), int(err));
-
- QStringList tmp;
- for (int i = 0; i < lookupResults.addresses().count(); ++i)
- tmp.append(lookupResults.addresses().at(i).toString());
- tmp.sort();
-
- QStringList expected = addresses.split(' ');
- expected.sort();
-
- QCOMPARE(tmp.join(' '), expected.join(' '));
+ tst_QHostInfo_Helper helper(hostname);
+ helper.lookupHostLambda();
+ QVERIFY(helper.waitForResults());
+ helper.checkResults(QHostInfo::HostInfoError(err), addresses);
}
static QStringList reverseLookupHelper(const QString &ip)
{
QStringList results;
-
- const QString pythonCode =
- "import socket;"
- "import sys;"
- "print (socket.getnameinfo((sys.argv[1], 0), 0)[0]);";
-
- QList<QByteArray> lines;
- QProcess python;
- python.setProcessChannelMode(QProcess::ForwardedErrorChannel);
- python.start("python", QStringList() << QString("-c") << pythonCode << ip);
- if (python.waitForFinished()) {
- if (python.exitStatus() == QProcess::NormalExit && python.exitCode() == 0)
- lines = python.readAllStandardOutput().split('\n');
- for (QByteArray line : lines) {
- if (!line.isEmpty())
- results << line.trimmed();
- }
- if (!results.isEmpty())
- return results;
- }
-
- qDebug() << "Python failed, falling back to nslookup";
- QProcess lookup;
- lookup.setProcessChannelMode(QProcess::ForwardedErrorChannel);
- lookup.start("nslookup", QStringList(ip));
- if (!lookup.waitForFinished()) {
- results << "nslookup failure";
- qDebug() << "nslookup failure";
+ union qt_sockaddr {
+ sockaddr a;
+ sockaddr_in a4;
+ sockaddr_in6 a6;
+ } sa = {};
+
+ QHostAddress addr(ip);
+ if (addr.isNull()) {
+ qWarning("Could not parse IP address: %ls", qUtf16Printable(ip));
return results;
}
- lines = lookup.readAllStandardOutput().split('\n');
-
- QByteArray name;
-
- const QByteArray nameMarkerNix("name =");
- const QByteArray nameMarkerWin("Name:");
- const QByteArray addressMarkerWin("Address:");
-
- for (QByteArray line : lines) {
- int index = -1;
- if ((index = line.indexOf(nameMarkerNix)) != -1) { // Linux and macOS
- name = line.mid(index + nameMarkerNix.length()).chopped(1).trimmed();
- results << name;
- } else if (line.startsWith(nameMarkerWin)) { // Windows formatting
- name = line.mid(line.lastIndexOf(" ")).trimmed();
- } else if (line.startsWith(addressMarkerWin)) {
- QByteArray address = line.mid(addressMarkerWin.length()).trimmed();
- if (address == ip.toUtf8()) {
- results << name;
- }
- }
- }
- if (results.isEmpty()) {
- qDebug() << "Failure to parse nslookup output: " << lines;
+ // from qnativesocketengine_p.h:
+ QT_SOCKLEN_T len = setSockaddr(&sa.a, addr, /*port = */ 0);
+
+ QByteArray name(NI_MAXHOST, Qt::Uninitialized);
+ int ni_flags = NI_NAMEREQD | NI_NUMERICSERV;
+ if (int r = getnameinfo(&sa.a, len, name.data(), name.size(), nullptr, 0, ni_flags)) {
+ qWarning("Failed to reverse look up '%ls': %s", qUtf16Printable(ip), gai_strerror(r));
+ } else {
+ results << QString::fromLatin1(name, qstrnlen(name, name.size()));
}
+
return results;
}
@@ -432,8 +393,10 @@ void tst_QHostInfo::reverseLookup_data()
QTest::newRow("dns.google") << QString("8.8.8.8") << reverseLookupHelper("8.8.8.8") << 0 << false;
QTest::newRow("one.one.one.one") << QString("1.1.1.1") << reverseLookupHelper("1.1.1.1") << 0 << false;
- QTest::newRow("dns.google IPv6") << QString("2001:4860:4860::8888") << reverseLookupHelper("2001:4860:4860::8888") << 0 << true;
- QTest::newRow("cloudflare IPv6") << QString("2606:4700:4700::1111") << reverseLookupHelper("2606:4700:4700::1111") << 0 << true;
+ if (QStringList hostNames = reverseLookupHelper("2001:4860:4860::8888"); !hostNames.isEmpty())
+ QTest::newRow("dns.google IPv6") << QString("2001:4860:4860::8888") << std::move(hostNames) << 0 << true;
+ if (QStringList hostNames = reverseLookupHelper("2606:4700:4700::1111"); !hostNames.isEmpty())
+ QTest::newRow("cloudflare IPv6") << QString("2606:4700:4700::1111") << std::move(hostNames) << 0 << true;
QTest::newRow("bogus-name IPv6") << QString("1::2::3::4") << QStringList() << 1 << true;
}
@@ -442,11 +405,6 @@ void tst_QHostInfo::reverseLookup()
QFETCH(QString, address);
QFETCH(QStringList, hostNames);
QFETCH(int, err);
- QFETCH(bool, ipv6);
-
- if (ipv6 && !ipv6LookupsAvailable) {
- QSKIP("IPv6 reverse lookups are not supported on this platform");
- }
QHostInfo info = QHostInfo::fromName(address);
@@ -454,7 +412,7 @@ void tst_QHostInfo::reverseLookup()
if (!hostNames.contains(info.hostName()))
qDebug() << "Failure: expecting" << hostNames << ",got " << info.hostName();
QVERIFY(hostNames.contains(info.hostName()));
- QCOMPARE(info.addresses().first(), QHostAddress(address));
+ QCOMPARE(info.addresses().constFirst(), QHostAddress(address));
} else {
QCOMPARE(info.hostName(), address);
QCOMPARE(info.error(), QHostInfo::HostNotFound);
@@ -475,21 +433,9 @@ void tst_QHostInfo::blockingLookup()
QFETCH(int, err);
QFETCH(QString, addresses);
- QHostInfo hostInfo = QHostInfo::fromName(hostname);
- QStringList tmp;
- for (int i = 0; i < hostInfo.addresses().count(); ++i)
- tmp.append(hostInfo.addresses().at(i).toString());
- tmp.sort();
-
- if ((int)hostInfo.error() != (int)err) {
- qWarning() << hostname << "=>" << lookupResults.errorString();
- }
- QCOMPARE((int)hostInfo.error(), (int)err);
-
- QStringList expected = addresses.split(' ');
- expected.sort();
-
- QCOMPARE(tmp.join(' ').toUpper(), expected.join(' ').toUpper());
+ tst_QHostInfo_Helper helper(hostname);
+ helper.blockingLookup();
+ helper.checkResults(QHostInfo::HostInfoError(err), addresses);
}
void tst_QHostInfo::raceCondition()
@@ -506,8 +452,9 @@ protected:
inline void run() override
{
QHostInfo info = QHostInfo::fromName("a-single" TEST_DOMAIN);
+ QCOMPARE(info.errorString(), "Unknown error"); // no error
QCOMPARE(info.error(), QHostInfo::NoError);
- QVERIFY(info.addresses().count() > 0);
+ QVERIFY(info.addresses().size() > 0);
QCOMPARE(info.addresses().at(0).toString(), QString("192.0.2.1"));
}
};
@@ -554,24 +501,22 @@ void tst_QHostInfo::threadSafetyAsynchronousAPI()
{
const int nattempts = 10;
const int lookupsperthread = 10;
- QList<QThread*> threads;
- QList<LookupReceiver*> receivers;
+ QThread threads[nattempts];
+ LookupReceiver receivers[nattempts];
for (int i = 0; i < nattempts; ++i) {
- QThread* thread = new QThread;
- LookupReceiver* receiver = new LookupReceiver;
+ QThread *thread = &threads[i];
+ LookupReceiver *receiver = &receivers[i];
receiver->numrequests = lookupsperthread;
- receivers.append(receiver);
receiver->moveToThread(thread);
connect(thread, SIGNAL(started()), receiver, SLOT(start()));
thread->start();
- threads.append(thread);
}
- for (int k = threads.count() - 1; k >= 0; --k)
- QVERIFY(threads.at(k)->wait(60000));
- foreach (LookupReceiver* receiver, receivers) {
- QCOMPARE(receiver->result.error(), QHostInfo::NoError);
- QCOMPARE(receiver->result.addresses().at(0).toString(), QString("192.0.2.1"));
- QCOMPARE(receiver->numrequests, 0);
+ for (int k = nattempts - 1; k >= 0; --k)
+ QVERIFY(threads[k].wait(60000));
+ for (LookupReceiver &receiver : receivers) {
+ QCOMPARE(receiver.result.error(), QHostInfo::NoError);
+ QCOMPARE(receiver.result.addresses().at(0).toString(), QString("192.0.2.1"));
+ QCOMPARE(receiver.numrequests, 0);
}
}
@@ -580,17 +525,11 @@ void tst_QHostInfo::threadSafetyAsynchronousAPI()
void tst_QHostInfo::multipleSameLookups()
{
const int COUNT = 10;
- lookupsDoneCounter = 0;
-
+ tst_QHostInfo_Helper helper("localhost");
for (int i = 0; i < COUNT; i++)
- QHostInfo::lookupHost("localhost", this, SLOT(resultsReady(QHostInfo)));
+ helper.lookupHostOldStyle();
- QElapsedTimer timer;
- timer.start();
- while (timer.elapsed() < 10000 && lookupsDoneCounter < COUNT) {
- QTestEventLoop::instance().enterLoop(2);
- }
- QCOMPARE(lookupsDoneCounter, COUNT);
+ QTRY_COMPARE_WITH_TIMEOUT(helper.lookupsDoneCounter, COUNT, 10s);
}
// this test is for the multi-threaded QHostInfo rewrite. It is about getting results at all,
@@ -619,19 +558,15 @@ void tst_QHostInfo::multipleDifferentLookups()
QFETCH(int, repeats);
const int COUNT = hostnameList.size();
- lookupsDoneCounter = 0;
+ tst_QHostInfo_Helper helper(QString{});
for (int i = 0; i < hostnameList.size(); i++)
- for (int j = 0; j < repeats; ++j)
- QHostInfo::lookupHost(hostnameList.at(i), this, SLOT(resultsReady(QHostInfo)));
-
- QElapsedTimer timer;
- timer.start();
- while (timer.elapsed() < 60000 && lookupsDoneCounter < repeats*COUNT) {
- QTestEventLoop::instance().enterLoop(2);
- //qDebug() << "t:" << timer.elapsed();
- }
- QCOMPARE(lookupsDoneCounter, repeats*COUNT);
+ for (int j = 0; j < repeats; ++j) {
+ helper.hostname = hostnameList.at(i);
+ helper.lookupHostOldStyle();
+ }
+
+ QTRY_COMPARE_WITH_TIMEOUT(helper.lookupsDoneCounter, repeats*COUNT, 60s);
}
void tst_QHostInfo::cache()
@@ -640,13 +575,12 @@ void tst_QHostInfo::cache()
if (!cache)
return; // test makes only sense when cache enabled
- // reset slot counter
- lookupsDoneCounter = 0;
+ tst_QHostInfo_Helper helper("localhost");
// lookup once, wait in event loop, result should not come directly.
bool valid = true;
int id = -1;
- QHostInfo result = qt_qhostinfo_lookup("localhost", this, SLOT(resultsReady(QHostInfo)), &valid, &id);
+ QHostInfo result = qt_qhostinfo_lookup(helper.hostname, &helper, SLOT(resultsReady(QHostInfo)), &valid, &id);
QTestEventLoop::instance().enterLoop(5);
QVERIFY(!QTestEventLoop::instance().timeout());
QVERIFY(!valid);
@@ -654,7 +588,7 @@ void tst_QHostInfo::cache()
// loopkup second time, result should come directly
valid = false;
- result = qt_qhostinfo_lookup("localhost", this, SLOT(resultsReady(QHostInfo)), &valid, &id);
+ result = qt_qhostinfo_lookup(helper.hostname, &helper, SLOT(resultsReady(QHostInfo)), &valid, &id);
QVERIFY(valid);
QVERIFY(!result.addresses().isEmpty());
@@ -663,17 +597,17 @@ void tst_QHostInfo::cache()
// lookup third time, result should not come directly.
valid = true;
- result = qt_qhostinfo_lookup("localhost", this, SLOT(resultsReady(QHostInfo)), &valid, &id);
+ result = qt_qhostinfo_lookup(helper.hostname, &helper, SLOT(resultsReady(QHostInfo)), &valid, &id);
QTestEventLoop::instance().enterLoop(5);
QVERIFY(!QTestEventLoop::instance().timeout());
QVERIFY(!valid);
QVERIFY(result.addresses().isEmpty());
// the slot should have been called 2 times.
- QCOMPARE(lookupsDoneCounter, 2);
+ QCOMPARE(helper.lookupsDoneCounter, 2);
}
-void tst_QHostInfo::resultsReady(const QHostInfo &hi)
+void tst_QHostInfo_Helper::resultsReady(const QHostInfo &hi)
{
QVERIFY(QThread::currentThread() == thread());
lookupDone = true;
@@ -684,16 +618,15 @@ void tst_QHostInfo::resultsReady(const QHostInfo &hi)
void tst_QHostInfo::abortHostLookup()
{
- //reset counter
- lookupsDoneCounter = 0;
+ tst_QHostInfo_Helper helper("a-single" TEST_DOMAIN);
bool valid = false;
int id = -1;
- QHostInfo result = qt_qhostinfo_lookup("a-single" TEST_DOMAIN, this, SLOT(resultsReady(QHostInfo)), &valid, &id);
+ QHostInfo result = qt_qhostinfo_lookup(helper.hostname, &helper, SLOT(resultsReady(QHostInfo)), &valid, &id);
QVERIFY(!valid);
//it is assumed that the DNS request/response in the backend is slower than it takes to call abort
QHostInfo::abortHostLookup(id);
QTestEventLoop::instance().enterLoop(5);
- QCOMPARE(lookupsDoneCounter, 0);
+ QCOMPARE(helper.lookupsDoneCounter, 0);
}
class LookupAborter : public QObject
diff --git a/tests/auto/network/kernel/qnetworkaddressentry/CMakeLists.txt b/tests/auto/network/kernel/qnetworkaddressentry/CMakeLists.txt
index 191be0656a..02bf37880a 100644
--- a/tests/auto/network/kernel/qnetworkaddressentry/CMakeLists.txt
+++ b/tests/auto/network/kernel/qnetworkaddressentry/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qnetworkaddressentry.pro.
-
#####################################################################
## tst_qnetworkaddressentry Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qnetworkaddressentry LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qnetworkaddressentry
SOURCES
tst_qnetworkaddressentry.cpp
diff --git a/tests/auto/network/kernel/qnetworkaddressentry/tst_qnetworkaddressentry.cpp b/tests/auto/network/kernel/qnetworkaddressentry/tst_qnetworkaddressentry.cpp
index 13d957dbcf..801eb58931 100644
--- a/tests/auto/network/kernel/qnetworkaddressentry/tst_qnetworkaddressentry.cpp
+++ b/tests/auto/network/kernel/qnetworkaddressentry/tst_qnetworkaddressentry.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
diff --git a/tests/auto/network/kernel/qnetworkdatagram/CMakeLists.txt b/tests/auto/network/kernel/qnetworkdatagram/CMakeLists.txt
index 105d32ddb5..5bfc2edc6a 100644
--- a/tests/auto/network/kernel/qnetworkdatagram/CMakeLists.txt
+++ b/tests/auto/network/kernel/qnetworkdatagram/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qnetworkdatagram.pro.
-
#####################################################################
## tst_qnetworkdatagram Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qnetworkdatagram LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qnetworkdatagram
SOURCES
tst_qnetworkdatagram.cpp
diff --git a/tests/auto/network/kernel/qnetworkdatagram/tst_qnetworkdatagram.cpp b/tests/auto/network/kernel/qnetworkdatagram/tst_qnetworkdatagram.cpp
index 6339e5dcd8..df473133a6 100644
--- a/tests/auto/network/kernel/qnetworkdatagram/tst_qnetworkdatagram.cpp
+++ b/tests/auto/network/kernel/qnetworkdatagram/tst_qnetworkdatagram.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Intel Corporation.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QNetworkDatagram>
#include <QTest>
diff --git a/tests/auto/network/kernel/qnetworkinformation/CMakeLists.txt b/tests/auto/network/kernel/qnetworkinformation/CMakeLists.txt
index 4c473cd4b3..354cefc993 100644
--- a/tests/auto/network/kernel/qnetworkinformation/CMakeLists.txt
+++ b/tests/auto/network/kernel/qnetworkinformation/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qnetworkinformation LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qnetworkinformation
SOURCES
tst_qnetworkinformation.cpp
diff --git a/tests/auto/network/kernel/qnetworkinformation/tst_qnetworkinformation.cpp b/tests/auto/network/kernel/qnetworkinformation/tst_qnetworkinformation.cpp
index cde2399424..daf81823e8 100644
--- a/tests/auto/network/kernel/qnetworkinformation/tst_qnetworkinformation.cpp
+++ b/tests/auto/network/kernel/qnetworkinformation/tst_qnetworkinformation.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtNetwork/private/qnetworkinformation_p.h>
#include <QtNetwork/qnetworkinformation.h>
@@ -241,14 +241,14 @@ void tst_QNetworkInformation::isMetered()
QSignalSpy spy(info, &QNetworkInformation::isMeteredChanged);
QVERIFY(!info->isMetered());
MockBackend::setNewMetered(true);
- QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.size(), 1);
QVERIFY(info->isMetered());
QVERIFY(spy[0][0].toBool());
spy.clear();
// Set the same value again, signal should not be emitted again
MockBackend::setNewMetered(true);
- QCOMPARE(spy.count(), 0);
+ QCOMPARE(spy.size(), 0);
}
QTEST_MAIN(tst_QNetworkInformation);
diff --git a/tests/auto/network/kernel/qnetworkinformation_appless/CMakeLists.txt b/tests/auto/network/kernel/qnetworkinformation_appless/CMakeLists.txt
index 1a7cf41079..d4a2e486bd 100644
--- a/tests/auto/network/kernel/qnetworkinformation_appless/CMakeLists.txt
+++ b/tests/auto/network/kernel/qnetworkinformation_appless/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qnetworkinformation_appless LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qnetworkinformation_appless
SOURCES
tst_qnetworkinformation_appless.cpp
diff --git a/tests/auto/network/kernel/qnetworkinformation_appless/tst_qnetworkinformation_appless.cpp b/tests/auto/network/kernel/qnetworkinformation_appless/tst_qnetworkinformation_appless.cpp
index ad67dbcdb5..b08843314a 100644
--- a/tests/auto/network/kernel/qnetworkinformation_appless/tst_qnetworkinformation_appless.cpp
+++ b/tests/auto/network/kernel/qnetworkinformation_appless/tst_qnetworkinformation_appless.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/qcoreapplication.h>
#include <QtNetwork/qnetworkinformation.h>
diff --git a/tests/auto/network/kernel/qnetworkinterface/CMakeLists.txt b/tests/auto/network/kernel/qnetworkinterface/CMakeLists.txt
index 3f19aa0951..3e5dab63e0 100644
--- a/tests/auto/network/kernel/qnetworkinterface/CMakeLists.txt
+++ b/tests/auto/network/kernel/qnetworkinterface/CMakeLists.txt
@@ -1,16 +1,20 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qnetworkinterface.pro.
-
#####################################################################
## tst_qnetworkinterface Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qnetworkinterface LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qnetworkinterface
SOURCES
tst_qnetworkinterface.cpp
LIBRARIES
- Qt::Network
+ Qt::NetworkPrivate
QT_TEST_SERVER_LIST "apache2"
)
diff --git a/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp b/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp
index d609bf5877..e5bbf3467c 100644
--- a/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp
+++ b/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp
@@ -1,7 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// Copyright (C) 2016 Intel Corporation.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
#include <QtEndian>
@@ -12,6 +11,8 @@
#include <qudpsocket.h>
#include "../../../network-settings.h"
+#include <private/qtnetwork-config_p.h>
+
Q_DECLARE_METATYPE(QHostAddress)
class tst_QNetworkInterface : public QObject
@@ -49,14 +50,13 @@ tst_QNetworkInterface::~tst_QNetworkInterface()
bool tst_QNetworkInterface::isIPv6Working()
{
- // Version without following cannot get IPV6 information
- #if !defined(QT_NO_GETIFADDRS) && !defined(QT_NO_IPV6IFNAME)
- QUdpSocket socket;
- socket.connectToHost(QHostAddress::LocalHostIPv6, 1234);
- return socket.state() == QAbstractSocket::ConnectedState || socket.waitForConnected(100);
- #else
- return false;
- #endif
+ // QNetworkInterface may be unable to detect IPv6 addresses even if they
+ // are there, due to limitations of the implementation.
+ if (QOperatingSystemVersion::currentType() == QOperatingSystemVersion::Windows ||
+ QT_CONFIG(linux_netlink) || (QT_CONFIG(getifaddrs) && QT_CONFIG(ipv6ifname))) {
+ return QtNetworkSettings::hasIPv6();
+ }
+ return false;
}
void tst_QNetworkInterface::initTestCase()
@@ -71,8 +71,8 @@ void tst_QNetworkInterface::initTestCase()
void tst_QNetworkInterface::dump()
{
// This is for manual testing:
- QList<QNetworkInterface> allInterfaces = QNetworkInterface::allInterfaces();
- foreach (const QNetworkInterface &i, allInterfaces) {
+ const QList<QNetworkInterface> allInterfaces = QNetworkInterface::allInterfaces();
+ for (const QNetworkInterface &i : allInterfaces) {
QString flags;
if (i.flags() & QNetworkInterface::IsUp) flags += "Up,";
if (i.flags() & QNetworkInterface::IsRunning) flags += "Running,";
@@ -99,7 +99,8 @@ void tst_QNetworkInterface::dump()
qDebug() << " MTU: " << i.maximumTransmissionUnit();
int count = 0;
- foreach (const QNetworkAddressEntry &e, i.addressEntries()) {
+ const auto entries = i.addressEntries();
+ for (const QNetworkAddressEntry &e : entries) {
QDebug s = qDebug();
s.nospace() << " address "
<< qSetFieldWidth(2) << count++ << qSetFieldWidth(0);
@@ -125,11 +126,11 @@ void tst_QNetworkInterface::dump()
void tst_QNetworkInterface::consistencyCheck()
{
- QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces();
+ const QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces();
QSet<QString> interfaceNames;
QList<int> interfaceIndexes;
- foreach (const QNetworkInterface &iface, ifaces) {
+ for (const QNetworkInterface &iface : ifaces) {
QVERIFY(iface.isValid());
QVERIFY2(!interfaceNames.contains(iface.name()),
"duplicate name = " + iface.name().toLocal8Bit());
@@ -196,6 +197,14 @@ void tst_QNetworkInterface::localAddress_data()
} else if (!ipv6 || entry.prefixLength() != 64) {
continue;
} else {
+#ifdef Q_OS_ANDROID
+ // Android seem to not allow IPv6 connection from interfaces other than wlan,
+ // if it's connected, and wlan is connected by default on Android emulators,
+ // so prefer selecting wlan in this test.
+ const QString scopeId = addr.scopeId();
+ if (!scopeId.isEmpty() && !scopeId.startsWith("wlan"))
+ continue;
+#endif
// add a random node in this IPv6 network
quint64 randomid = qFromBigEndian(Q_UINT64_C(0x8f41f072e5733caa));
QIPv6Address ip6 = addr.toIPv6Address();
@@ -250,10 +259,10 @@ void tst_QNetworkInterface::interfaceFromXXX_data()
{
QTest::addColumn<QNetworkInterface>("iface");
- QList<QNetworkInterface> allInterfaces = QNetworkInterface::allInterfaces();
- if (allInterfaces.count() == 0)
+ const QList<QNetworkInterface> allInterfaces = QNetworkInterface::allInterfaces();
+ if (allInterfaces.size() == 0)
QSKIP("No interfaces to test!");
- foreach (QNetworkInterface iface, allInterfaces)
+ for (const QNetworkInterface &iface : allInterfaces)
QTest::newRow(iface.name().toLocal8Bit()) << iface;
}
@@ -267,7 +276,8 @@ void tst_QNetworkInterface::interfaceFromXXX()
QCOMPARE(QNetworkInterface::interfaceNameFromIndex(idx), iface.name());
QCOMPARE(QNetworkInterface::interfaceIndexFromName(iface.name()), idx);
}
- foreach (QNetworkAddressEntry entry, iface.addressEntries()) {
+ const auto entries = iface.addressEntries();
+ for (const QNetworkAddressEntry &entry : entries) {
QVERIFY(!entry.ip().isNull());
if (!entry.netmask().isNull()) {
diff --git a/tests/auto/network/kernel/qnetworkproxy/CMakeLists.txt b/tests/auto/network/kernel/qnetworkproxy/CMakeLists.txt
index 77959cb95c..629bfb0a8a 100644
--- a/tests/auto/network/kernel/qnetworkproxy/CMakeLists.txt
+++ b/tests/auto/network/kernel/qnetworkproxy/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qnetworkproxy.pro.
-
#####################################################################
## tst_qnetworkproxy Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qnetworkproxy LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qnetworkproxy
SOURCES
tst_qnetworkproxy.cpp
diff --git a/tests/auto/network/kernel/qnetworkproxy/tst_qnetworkproxy.cpp b/tests/auto/network/kernel/qnetworkproxy/tst_qnetworkproxy.cpp
index 56d61db78c..1f00f8d054 100644
--- a/tests/auto/network/kernel/qnetworkproxy/tst_qnetworkproxy.cpp
+++ b/tests/auto/network/kernel/qnetworkproxy/tst_qnetworkproxy.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
diff --git a/tests/auto/network/kernel/qnetworkproxyfactory/CMakeLists.txt b/tests/auto/network/kernel/qnetworkproxyfactory/CMakeLists.txt
index bef3fd0cee..41dae6a02a 100644
--- a/tests/auto/network/kernel/qnetworkproxyfactory/CMakeLists.txt
+++ b/tests/auto/network/kernel/qnetworkproxyfactory/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qnetworkproxyfactory.pro.
-
#####################################################################
## tst_qnetworkproxyfactory Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qnetworkproxyfactory LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qnetworkproxyfactory
SOURCES
tst_qnetworkproxyfactory.cpp
diff --git a/tests/auto/network/kernel/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp b/tests/auto/network/kernel/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp
index 1350dee150..c38a480766 100644
--- a/tests/auto/network/kernel/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp
+++ b/tests/auto/network/kernel/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp
@@ -1,6 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QTest>
#include <QtTest/QTestEventLoop>
@@ -94,7 +93,8 @@ void tst_QNetworkProxyFactory::systemProxyForQuery_data()
QTest::newRow("autobind-server") << (int)QNetworkProxyQuery::TcpServer << QUrl() << QString() << QString() << 0 << (int)QNetworkProxy::ListeningCapability;
QTest::newRow("web-server") << (int)QNetworkProxyQuery::TcpServer << QUrl() << QString() << QString() << 80 << (int)QNetworkProxy::ListeningCapability;
//windows: these should be bypassed if "bypass proxy server for local addresses" is ticked
- foreach (QHostAddress address, QNetworkInterface::allAddresses()) {
+ const auto addresses = QNetworkInterface::allAddresses();
+ for (const QHostAddress &address : addresses) {
QTest::newRow(qPrintable(address.toString())) << (int)QNetworkProxyQuery::TcpSocket << QUrl() << QString() << address.toString() << 0 << 0;
}
@@ -147,16 +147,15 @@ void tst_QNetworkProxyFactory::systemProxyForQuery() const
QElapsedTimer sw;
sw.start();
- QList<QNetworkProxy> systemProxyList = QNetworkProxyFactory::systemProxyForQuery(query);
+ const QList<QNetworkProxy> systemProxyList = QNetworkProxyFactory::systemProxyForQuery(query);
qDebug() << sw.elapsed() << "ms";
QVERIFY(!systemProxyList.isEmpty());
// for manual comparison with system
qDebug() << systemProxyList;
- foreach (const QNetworkProxy &proxy, systemProxyList) {
+ for (const QNetworkProxy &proxy : systemProxyList)
QVERIFY((requiredCapabilities == 0) || (proxy.capabilities() & requiredCapabilities));
- }
}
void tst_QNetworkProxyFactory::systemProxyForQuery_local()
diff --git a/tests/auto/network/selftest/tst_networkselftest.cpp b/tests/auto/network/selftest/tst_networkselftest.cpp
index 11a5a6b880..4288a65a37 100644
--- a/tests/auto/network/selftest/tst_networkselftest.cpp
+++ b/tests/auto/network/selftest/tst_networkselftest.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
diff --git a/tests/auto/network/socket/CMakeLists.txt b/tests/auto/network/socket/CMakeLists.txt
index b34b2173e6..7136017f39 100644
--- a/tests/auto/network/socket/CMakeLists.txt
+++ b/tests/auto/network/socket/CMakeLists.txt
@@ -1,22 +1,26 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from socket.pro.
-
if(QT_FEATURE_private_tests)
add_subdirectory(qhttpsocketengine)
add_subdirectory(qtcpsocket)
add_subdirectory(qsocks5socketengine)
add_subdirectory(platformsocketengine)
endif()
-add_subdirectory(qudpsocket)
+if(QT_FEATURE_udpsocket)
+ add_subdirectory(qudpsocket)
+endif()
add_subdirectory(qabstractsocket)
-if(NOT ANDROID)
- # QTBUG-87387 # special case
+if(QT_FEATURE_localserver AND NOT ANDROID)
+ # QTBUG-87387
add_subdirectory(qlocalsocket)
- # QTBUG-87388 # special case
+endif()
+
+if(QT_FEATURE_networkinterface AND NOT ANDROID)
+ # QTBUG-87388
add_subdirectory(qtcpserver)
endif()
+
if(QT_FEATURE_sctp)
add_subdirectory(qsctpsocket)
endif()
diff --git a/tests/auto/network/socket/platformsocketengine/BLACKLIST b/tests/auto/network/socket/platformsocketengine/BLACKLIST
index f1f88d26d1..796f81a02a 100644
--- a/tests/auto/network/socket/platformsocketengine/BLACKLIST
+++ b/tests/auto/network/socket/platformsocketengine/BLACKLIST
@@ -1,11 +1,2 @@
[tcpLoopbackPerformance]
-windows-10 msvc-2015
-windows-7sp1
-[receiveUrgentData]
-windows-10 msvc-2015
-windows-7sp1
-[serverTest]
-windows-10 msvc-2015
-windows-7sp1
-[tcpLoopbackPerformance]
windows
diff --git a/tests/auto/network/socket/platformsocketengine/CMakeLists.txt b/tests/auto/network/socket/platformsocketengine/CMakeLists.txt
index 93f79dd8b1..891041df04 100644
--- a/tests/auto/network/socket/platformsocketengine/CMakeLists.txt
+++ b/tests/auto/network/socket/platformsocketengine/CMakeLists.txt
@@ -1,7 +1,11 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from platformsocketengine.pro.
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_platformsocketengine LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
if(NOT QT_FEATURE_private_tests)
return()
@@ -17,13 +21,9 @@ qt_internal_add_test(tst_platformsocketengine
LIBRARIES
Qt::CorePrivate
Qt::NetworkPrivate
- QT_TEST_SERVER_LIST "cyrus" # special case
+ QT_TEST_SERVER_LIST "cyrus"
)
-#### Keys ignored in scope 1:.:.:platformsocketengine.pro:<TRUE>:
-# MOC_DIR = "tmp"
-# _REQUIREMENTS = "qtConfig(private_tests)"
-
## Scopes:
#####################################################################
diff --git a/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp b/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp
index 5838f99970..1f6ecf9200 100644
--- a/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp
+++ b/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp
@@ -1,6 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// Copyright (C) 2016 Intel Corporation.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QTest>
@@ -23,7 +23,7 @@
#define PLATFORMSOCKETENGINE QNativeSocketEngine
#define PLATFORMSOCKETENGINESTRING "QNativeSocketEngine"
-#include <private/qnativesocketengine_p.h>
+#include <private/qnativesocketengine_p_p.h>
#include <qstringlist.h>
@@ -255,7 +255,7 @@ void tst_PlatformSocketEngine::broadcastTest()
PLATFORMSOCKETENGINE broadcastSocket;
// Initialize a regular Udp socket
- QVERIFY(broadcastSocket.initialize(QAbstractSocket::UdpSocket, QAbstractSocket::AnyIPProtocol));
+ QVERIFY(broadcastSocket.initialize(QAbstractSocket::UdpSocket, QAbstractSocket::IPv4Protocol));
// Bind to any port on all interfaces
QVERIFY(broadcastSocket.bind(QHostAddress::Any, 0));
diff --git a/tests/auto/network/socket/qabstractsocket/CMakeLists.txt b/tests/auto/network/socket/qabstractsocket/CMakeLists.txt
index 76b375d811..3ca18aceef 100644
--- a/tests/auto/network/socket/qabstractsocket/CMakeLists.txt
+++ b/tests/auto/network/socket/qabstractsocket/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qabstractsocket.pro.
-
#####################################################################
## tst_qabstractsocket Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qabstractsocket LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qabstractsocket
SOURCES
tst_qabstractsocket.cpp
diff --git a/tests/auto/network/socket/qabstractsocket/tst_qabstractsocket.cpp b/tests/auto/network/socket/qabstractsocket/tst_qabstractsocket.cpp
index 984f411550..6b038acdfa 100644
--- a/tests/auto/network/socket/qabstractsocket/tst_qabstractsocket.cpp
+++ b/tests/auto/network/socket/qabstractsocket/tst_qabstractsocket.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
diff --git a/tests/auto/network/socket/qhttpsocketengine/BLACKLIST b/tests/auto/network/socket/qhttpsocketengine/BLACKLIST
index ceb3b7862e..e0cd701636 100644
--- a/tests/auto/network/socket/qhttpsocketengine/BLACKLIST
+++ b/tests/auto/network/socket/qhttpsocketengine/BLACKLIST
@@ -1,5 +1,2 @@
-[downloadBigFile]
-windows-10 msvc-2015
-windows-7sp1
[ensureEofTriggersNotification]
windows
diff --git a/tests/auto/network/socket/qhttpsocketengine/CMakeLists.txt b/tests/auto/network/socket/qhttpsocketengine/CMakeLists.txt
index 0bcd607709..6b4f904725 100644
--- a/tests/auto/network/socket/qhttpsocketengine/CMakeLists.txt
+++ b/tests/auto/network/socket/qhttpsocketengine/CMakeLists.txt
@@ -1,7 +1,11 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qhttpsocketengine.pro.
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qhttpsocketengine LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
if(NOT QT_FEATURE_private_tests)
return()
@@ -17,17 +21,12 @@ qt_internal_add_test(tst_qhttpsocketengine
LIBRARIES
Qt::CorePrivate
Qt::NetworkPrivate
- QT_TEST_SERVER_LIST "squid" "danted" "cyrus" "apache2" # special case
+ QT_TEST_SERVER_LIST "squid" "danted" "cyrus" "apache2"
)
-#### Keys ignored in scope 1:.:.:qhttpsocketengine.pro:<TRUE>:
-# MOC_DIR = "tmp"
-# _REQUIREMENTS = "qtConfig(private_tests)"
-
## Scopes:
#####################################################################
-#### Keys ignored in scope 2:.:.:qhttpsocketengine.pro:LINUX:
# QT_TEST_SERVER_LIST = "squid" "danted" "cyrus" "apache2"
qt_internal_extend_target(tst_qhttpsocketengine CONDITION WIN32
diff --git a/tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp b/tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp
index 63bd17f130..a52099b5b4 100644
--- a/tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp
+++ b/tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QTest>
@@ -18,6 +18,8 @@
#include "../../../network-settings.h"
+using namespace std::chrono_literals;
+
class tst_QHttpSocketEngine : public QObject
{
Q_OBJECT
@@ -83,9 +85,9 @@ public slots:
int idx = client->property("dataTransmitionIdx").toInt();
if (receivedData.contains("\r\n\r\n") ||
receivedData.contains("\n\n")) {
- if (idx < dataToTransmit.length())
+ if (idx < dataToTransmit.size())
client->write(dataToTransmit.at(idx++));
- if (idx == dataToTransmit.length()) {
+ if (idx == dataToTransmit.size()) {
client->disconnectFromHost();
disconnect(client, 0, this, 0);
client = 0;
@@ -323,7 +325,7 @@ void tst_QHttpSocketEngine::simpleErrorsAndStates()
QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
QVERIFY(!socketDevice.connectToHost(QHostAddress(QtNetworkSettings::socksProxyServerName()), 8088));
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectingState);
- if (socketDevice.waitForWrite(30000)) {
+ if (socketDevice.waitForWrite(30s)) {
QVERIFY(socketDevice.state() == QAbstractSocket::ConnectedState ||
socketDevice.state() == QAbstractSocket::UnconnectedState);
} else {
diff --git a/tests/auto/network/socket/qlocalsocket/CMakeLists.txt b/tests/auto/network/socket/qlocalsocket/CMakeLists.txt
index 17fc287de6..4b886a02ee 100644
--- a/tests/auto/network/socket/qlocalsocket/CMakeLists.txt
+++ b/tests/auto/network/socket/qlocalsocket/CMakeLists.txt
@@ -1,10 +1,14 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qlocalsocket.pro.
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qlocalsocket LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
-# add_subdirectory(test) # special case remove
add_subdirectory(socketprocess)
+
qt_internal_add_test(tst_qlocalsocket
SOURCES
tst_qlocalsocket.cpp
@@ -13,6 +17,6 @@ qt_internal_add_test(tst_qlocalsocket
QLOCALSOCKET_DEBUG
LIBRARIES
Qt::Network
+ Qt::TestPrivate
)
add_dependencies(tst_qlocalsocket socketprocess)
-# special case end
diff --git a/tests/auto/network/socket/qlocalsocket/socketprocess/CMakeLists.txt b/tests/auto/network/socket/qlocalsocket/socketprocess/CMakeLists.txt
index 576823d889..3e0476d2b6 100644
--- a/tests/auto/network/socket/qlocalsocket/socketprocess/CMakeLists.txt
+++ b/tests/auto/network/socket/qlocalsocket/socketprocess/CMakeLists.txt
@@ -1,8 +1,6 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from socketprocess.pro.
-
#####################################################################
## socketprocess Binary:
#####################################################################
diff --git a/tests/auto/network/socket/qlocalsocket/socketprocess/main.cpp b/tests/auto/network/socket/qlocalsocket/socketprocess/main.cpp
index c1a78fae23..d254253aca 100644
--- a/tests/auto/network/socket/qlocalsocket/socketprocess/main.cpp
+++ b/tests/auto/network/socket/qlocalsocket/socketprocess/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qcoreapplication.h>
diff --git a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp
index 9b8fec384c..30ffb50d23 100644
--- a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp
+++ b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp
@@ -1,10 +1,11 @@
// Copyright (C) 2016 The Qt Company Ltd.
// Copyright (C) 2016 Intel Corporation.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
#include <QSignalSpy>
+#include <QtTest/private/qpropertytesthelper_p.h>
#if QT_CONFIG(process)
#include <QProcess>
#endif
@@ -123,6 +124,7 @@ private slots:
void verifyListenWithDescriptor_data();
void serverBindingsAndProperties();
+ void socketBindings();
protected slots:
void socketClosedSlot();
@@ -245,8 +247,8 @@ void tst_QLocalSocket::server_basic()
QVERIFY(!timedOut);
QCOMPARE(server.listen(QString()), false);
- QCOMPARE(server.hits.count(), 0);
- QCOMPARE(spyNewConnection.count(), 0);
+ QCOMPARE(server.hits.size(), 0);
+ QCOMPARE(spyNewConnection.size(), 0);
}
void tst_QLocalSocket::server_connectionsCount()
@@ -287,11 +289,11 @@ void tst_QLocalSocket::socket_basic()
QCOMPARE(socket.waitForDisconnected(0), false);
QCOMPARE(socket.waitForReadyRead(0), false);
- QCOMPARE(spyConnected.count(), 0);
- QCOMPARE(spyDisconnected.count(), 0);
- QCOMPARE(spyError.count(), 0);
- QCOMPARE(spyStateChanged.count(), 0);
- QCOMPARE(spyReadyRead.count(), 0);
+ QCOMPARE(spyConnected.size(), 0);
+ QCOMPARE(spyDisconnected.size(), 0);
+ QCOMPARE(spyError.size(), 0);
+ QCOMPARE(spyStateChanged.size(), 0);
+ QCOMPARE(spyReadyRead.size(), 0);
}
void tst_QLocalSocket::listen_data()
@@ -300,8 +302,8 @@ void tst_QLocalSocket::listen_data()
QTest::addColumn<bool>("canListen");
QTest::addColumn<bool>("close");
QTest::newRow("null") << QString() << false << false;
- QTest::newRow("tst_localsocket") << "tst_localsocket" << true << true;
- QTest::newRow("tst_localsocket") << "tst_localsocket" << true << false;
+ QTest::newRow("tst_localsocket,close") << "tst_localsocket" << true << true;
+ QTest::newRow("tst_localsocket,no-close") << "tst_localsocket" << true << false;
}
// start a server that listens, but don't connect a socket, make sure everything is in order
@@ -321,8 +323,8 @@ void tst_QLocalSocket::listen()
QCOMPARE(server.isListening(), canListen);
QCOMPARE(server.hasPendingConnections(), false);
QCOMPARE(server.nextPendingConnection(), (QLocalSocket*)0);
- QCOMPARE(server.hits.count(), 0);
- QCOMPARE(spyNewConnection.count(), 0);
+ QCOMPARE(server.hits.size(), 0);
+ QCOMPARE(spyNewConnection.size(), 0);
if (canListen) {
QVERIFY(server.errorString().isEmpty());
QCOMPARE(server.serverError(), QAbstractSocket::UnknownSocketError);
@@ -396,7 +398,7 @@ void tst_QLocalSocket::listenAndConnect()
QCOMPARE(socket->error(), QLocalSocket::UnknownSocketError);
QCOMPARE(socket->state(), QLocalSocket::ConnectedState);
//QVERIFY(socket->socketDescriptor() != -1);
- QCOMPARE(spyError.count(), 0);
+ QCOMPARE(spyError.size(), 0);
} else {
QVERIFY(!socket->errorString().isEmpty());
QVERIFY(socket->error() != QLocalSocket::UnknownSocketError);
@@ -415,13 +417,13 @@ void tst_QLocalSocket::listenAndConnect()
QCOMPARE(socket->waitForConnected(0), canListen);
QCOMPARE(socket->waitForReadyRead(0), false);
- QTRY_COMPARE(spyConnected.count(), canListen ? 1 : 0);
- QCOMPARE(spyDisconnected.count(), 0);
+ QTRY_COMPARE(spyConnected.size(), canListen ? 1 : 0);
+ QCOMPARE(spyDisconnected.size(), 0);
// error signals
- QVERIFY(spyError.count() >= 0);
+ QVERIFY(spyError.size() >= 0);
if (canListen) {
- if (spyError.count() > 0)
+ if (spyError.size() > 0)
QCOMPARE(qvariant_cast<QLocalSocket::LocalSocketError>(spyError.first()[0]),
QLocalSocket::SocketTimeoutError);
} else {
@@ -436,8 +438,8 @@ void tst_QLocalSocket::listenAndConnect()
if (canListen)
QCOMPARE(qvariant_cast<QLocalSocket::LocalSocketState>(spyStateChanged.last()[0]),
QLocalSocket::ConnectedState);
- QCOMPARE(spyStateChanged.count(), 2);
- QCOMPARE(spyReadyRead.count(), 0);
+ QCOMPARE(spyStateChanged.size(), 2);
+ QCOMPARE(spyReadyRead.size(), 0);
bool timedOut = true;
QCOMPARE(server.waitForNewConnection(3000, &timedOut), canListen);
@@ -451,16 +453,16 @@ void tst_QLocalSocket::listenAndConnect()
QCOMPARE(server.serverName(), name);
QVERIFY(server.fullServerName().contains(name));
QVERIFY(server.nextPendingConnection() != (QLocalSocket*)0);
- QTRY_COMPARE(server.hits.count(), i + 1);
- QCOMPARE(spyNewConnection.count(), i + 1);
+ QTRY_COMPARE(server.hits.size(), i + 1);
+ QCOMPARE(spyNewConnection.size(), i + 1);
QVERIFY(server.errorString().isEmpty());
QCOMPARE(server.serverError(), QAbstractSocket::UnknownSocketError);
} else {
QVERIFY(server.serverName().isEmpty());
QVERIFY(server.fullServerName().isEmpty());
QCOMPARE(server.nextPendingConnection(), (QLocalSocket*)0);
- QCOMPARE(spyNewConnection.count(), 0);
- QCOMPARE(server.hits.count(), 0);
+ QCOMPARE(spyNewConnection.size(), 0);
+ QCOMPARE(server.hits.size(), 0);
QVERIFY(!server.errorString().isEmpty());
QCOMPARE(server.serverError(), QAbstractSocket::HostNotFoundError);
}
@@ -469,8 +471,8 @@ void tst_QLocalSocket::listenAndConnect()
server.close();
- QCOMPARE(server.hits.count(), (canListen ? connections : 0));
- QCOMPARE(spyNewConnection.count(), (canListen ? connections : 0));
+ QCOMPARE(server.hits.size(), (canListen ? connections : 0));
+ QCOMPARE(spyNewConnection.size(), (canListen ? connections : 0));
}
void tst_QLocalSocket::connectWithOpen()
@@ -494,7 +496,7 @@ void tst_QLocalSocket::connectWithOpen()
socket.close();
server.close();
- QCOMPARE(spyAboutToClose.count(), 1);
+ QCOMPARE(spyAboutToClose.size(), 1);
}
void tst_QLocalSocket::listenAndConnectAbstractNamespaceTrailingZeros_data()
@@ -660,7 +662,7 @@ void tst_QLocalSocket::sendData()
QTest::qWait(250);
#endif
QVERIFY(!timedOut);
- QCOMPARE(spyConnected.count(), canListen ? 1 : 0);
+ QCOMPARE(spyConnected.size(), canListen ? 1 : 0);
QCOMPARE(socket.state(), canListen ? QLocalSocket::ConnectedState : QLocalSocket::UnconnectedState);
// test sending/receiving data
@@ -686,7 +688,7 @@ void tst_QLocalSocket::sendData()
QCOMPARE(socket.flush(), false);
QCOMPARE(socket.isValid(), canListen);
QCOMPARE(socket.readBufferSize(), (qint64)0);
- QCOMPARE(spyReadyRead.count(), expectedReadyReadSignals);
+ QCOMPARE(spyReadyRead.size(), expectedReadyReadSignals);
QVERIFY(testLine.startsWith(in.readLine()));
@@ -697,16 +699,16 @@ void tst_QLocalSocket::sendData()
}
socket.disconnectFromServer();
- QCOMPARE(spyConnected.count(), canListen ? 1 : 0);
- QCOMPARE(spyDisconnected.count(), canListen ? 1 : 0);
- QCOMPARE(spyError.count(), canListen ? 0 : 1);
- QCOMPARE(spyStateChanged.count(), canListen ? 4 : 2);
- QCOMPARE(spyReadyRead.count(), canListen ? expectedReadyReadSignals : 0);
+ QCOMPARE(spyConnected.size(), canListen ? 1 : 0);
+ QCOMPARE(spyDisconnected.size(), canListen ? 1 : 0);
+ QCOMPARE(spyError.size(), canListen ? 0 : 1);
+ QCOMPARE(spyStateChanged.size(), canListen ? 4 : 2);
+ QCOMPARE(spyReadyRead.size(), canListen ? expectedReadyReadSignals : 0);
server.close();
- QCOMPARE(server.hits.count(), (canListen ? 1 : 0));
- QCOMPARE(spy.count(), (canListen ? 1 : 0));
+ QCOMPARE(server.hits.size(), (canListen ? 1 : 0));
+ QCOMPARE(spy.size(), (canListen ? 1 : 0));
}
void tst_QLocalSocket::readLine_data()
@@ -1006,7 +1008,7 @@ void tst_QLocalSocket::simpleCommandProtocol2()
localSocketWrite.abort();
QCOMPARE(localSocketWrite.state(), QLocalSocket::UnconnectedState);
- QCOMPARE(spyDisconnected.count(), 1);
+ QCOMPARE(spyDisconnected.size(), 1);
QCOMPARE(localSocketWrite.bytesToWrite(), 0);
QVERIFY(!localSocketWrite.isOpen());
@@ -1068,7 +1070,7 @@ void tst_QLocalSocket::hitMaximumConnections()
bool timedOut = true;
QVERIFY(server.waitForNewConnection(3000, &timedOut));
QVERIFY(!timedOut);
- QVERIFY(server.hits.count() > 0);
+ QVERIFY(server.hits.size() > 0);
qDeleteAll(sockets.begin(), sockets.end());
}
@@ -1096,9 +1098,9 @@ public:
QVERIFY(socket.waitForConnected(1000));
// We should *not* have this signal yet!
- QCOMPARE(spyReadyRead.count(), 0);
+ QCOMPARE(spyReadyRead.size(), 0);
socket.waitForReadyRead();
- QCOMPARE(spyReadyRead.count(), 1);
+ QCOMPARE(spyReadyRead.size(), 1);
QTextStream in(&socket);
QCOMPARE(in.readLine(), testLine);
socket.close();
@@ -1140,7 +1142,7 @@ public:
--done;
delete serverSocket;
}
- QCOMPARE(server.hits.count(), clients);
+ QCOMPARE(server.hits.size(), clients);
}
};
@@ -1309,7 +1311,7 @@ void tst_QLocalSocket::waitForDisconnectByServer()
serverSocket->close();
QCOMPARE(serverSocket->state(), QLocalSocket::UnconnectedState);
QVERIFY(socket.waitForDisconnected(3000));
- QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.size(), 1);
}
void tst_QLocalSocket::waitForReadyReadOnDisconnected()
@@ -1426,7 +1428,7 @@ void tst_QLocalSocket::recycleClientSocket()
QLocalSocket client;
QSignalSpy clientReadyReadSpy(&client, SIGNAL(readyRead()));
QSignalSpy clientErrorSpy(&client, SIGNAL(errorOccurred(QLocalSocket::LocalSocketError)));
- for (int i = 0; i < lines.count(); ++i) {
+ for (int i = 0; i < lines.size(); ++i) {
client.abort();
clientReadyReadSpy.clear();
client.connectToServer(serverName);
@@ -1521,7 +1523,7 @@ void tst_QLocalSocket::writeToClientAndDisconnect()
QVERIFY(clientSocket->waitForDisconnected());
QVERIFY(client.waitForDisconnected());
- QCOMPARE(readChannelFinishedSpy.count(), 1);
+ QCOMPARE(readChannelFinishedSpy.size(), 1);
const QByteArray received = client.readAll();
QCOMPARE(received.size(), qint64(sizeof(buffer) * chunks));
QCOMPARE(client.state(), QLocalSocket::UnconnectedState);
@@ -1551,7 +1553,7 @@ void tst_QLocalSocket::writeToDisconnected()
QCOMPARE(client.bytesToWrite(), qint64(1));
QVERIFY(!client.waitForBytesWritten());
- QCOMPARE(spyError.count(), 1);
+ QCOMPARE(spyError.size(), 1);
QCOMPARE(client.state(), QLocalSocket::UnconnectedState);
}
@@ -1656,12 +1658,15 @@ void tst_QLocalSocket::asyncDisconnectNotify()
QVERIFY(serverSocket);
delete serverSocket;
QTRY_VERIFY(!disconnectedSpy.isEmpty());
- QCOMPARE(readChannelFinishedSpy.count(), 1);
+ QCOMPARE(readChannelFinishedSpy.size(), 1);
}
void tst_QLocalSocket::verifySocketOptions_data()
{
#ifdef Q_OS_LINUX
+ if (::geteuid() == 0)
+ QSKIP("Running this test as root doesn't make sense");
+
QTest::addColumn<QString>("service");
QTest::addColumn<QLocalServer::SocketOption>("opts");
QTest::addColumn<QFile::Permissions>("perms");
@@ -1707,7 +1712,7 @@ void tst_QLocalSocket::verifySocketOptions()
void tst_QLocalSocket::verifyListenWithDescriptor()
{
-#ifdef Q_OS_UNIX
+#if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS)
QFETCH(QString, path);
QFETCH(bool, abstract);
QFETCH(bool, bound);
@@ -1807,14 +1812,18 @@ void tst_QLocalSocket::serverBindingsAndProperties()
{
CrashSafeLocalServer server;
- QProperty<QLocalServer::SocketOptions> sockOpts;
- server.bindableSocketOptions().setBinding(Qt::makePropertyBinding(sockOpts));
- sockOpts = QLocalServer::GroupAccessOption | QLocalServer::UserAccessOption;
- QCOMPARE(server.socketOptions(), sockOpts.value());
+ QTestPrivate::testReadWritePropertyBasics(
+ server, QLocalServer::SocketOptions{QLocalServer::GroupAccessOption},
+ QLocalServer::SocketOptions{QLocalServer::OtherAccessOption}, "socketOptions");
+}
+
+void tst_QLocalSocket::socketBindings()
+{
+ QLocalSocket socket;
- sockOpts.setBinding(server.bindableSocketOptions().makeBinding());
- server.setSocketOptions(QLocalServer::OtherAccessOption);
- QCOMPARE(sockOpts.value(), QLocalServer::OtherAccessOption);
+ QTestPrivate::testReadWritePropertyBasics(
+ socket, QLocalSocket::SocketOptions{QLocalSocket::AbstractNamespaceOption},
+ QLocalSocket::SocketOptions{QLocalSocket::NoOptions}, "socketOptions");
}
QTEST_MAIN(tst_QLocalSocket)
diff --git a/tests/auto/network/socket/qsctpsocket/CMakeLists.txt b/tests/auto/network/socket/qsctpsocket/CMakeLists.txt
index 9e65d6a72e..4bf5438841 100644
--- a/tests/auto/network/socket/qsctpsocket/CMakeLists.txt
+++ b/tests/auto/network/socket/qsctpsocket/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qsctpsocket.pro.
-
#####################################################################
## tst_qsctpsocket Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qsctpsocket LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qsctpsocket
SOURCES
tst_qsctpsocket.cpp
diff --git a/tests/auto/network/socket/qsctpsocket/tst_qsctpsocket.cpp b/tests/auto/network/socket/qsctpsocket/tst_qsctpsocket.cpp
index d661ad5405..2893053158 100644
--- a/tests/auto/network/socket/qsctpsocket/tst_qsctpsocket.cpp
+++ b/tests/auto/network/socket/qsctpsocket/tst_qsctpsocket.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Alex Trotsenko <alex1973tr@gmail.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
#include <QDebug>
@@ -127,12 +127,13 @@ void tst_QSctpSocket::bind_data()
// these ranges are guaranteed to be reserved for 'documentation purposes',
// and thus, should be unused in the real world. Not that I'm assuming the
// world is full of competent administrators, or anything.
- QStringList knownBad;
- knownBad << "198.51.100.1";
- knownBad << "2001:0DB8::1";
- foreach (const QString &badAddress, knownBad) {
+ const QString knownBad[] = {
+ "198.51.100.1",
+ "2001:0DB8::1",
+ };
+
+ for (const QString &badAddress : knownBad)
QTest::newRow(badAddress.toLatin1().constData()) << badAddress << false << QString();
- }
}
// Testing bind function
diff --git a/tests/auto/network/socket/qsocks5socketengine/BLACKLIST b/tests/auto/network/socket/qsocks5socketengine/BLACKLIST
index 479d0f878f..6b3a39ab5e 100644
--- a/tests/auto/network/socket/qsocks5socketengine/BLACKLIST
+++ b/tests/auto/network/socket/qsocks5socketengine/BLACKLIST
@@ -7,7 +7,4 @@ qnx ci
# QTBUG-74162
[passwordAuth2]
ubuntu
-[downloadBigFile]
-windows-10 msvc-2015
-windows-7sp1
diff --git a/tests/auto/network/socket/qsocks5socketengine/CMakeLists.txt b/tests/auto/network/socket/qsocks5socketengine/CMakeLists.txt
index 7e6e90a09f..dc0b87cd94 100644
--- a/tests/auto/network/socket/qsocks5socketengine/CMakeLists.txt
+++ b/tests/auto/network/socket/qsocks5socketengine/CMakeLists.txt
@@ -1,7 +1,11 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qsocks5socketengine.pro.
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qsocks5socketengine LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
if(NOT QT_FEATURE_private_tests)
return()
@@ -17,17 +21,12 @@ qt_internal_add_test(tst_qsocks5socketengine
LIBRARIES
Qt::CorePrivate
Qt::NetworkPrivate
- QT_TEST_SERVER_LIST "danted" "apache2" "cyrus" # special case
+ QT_TEST_SERVER_LIST "danted" "apache2" "cyrus"
)
-#### Keys ignored in scope 1:.:.:qsocks5socketengine.pro:<TRUE>:
-# MOC_DIR = "tmp"
-# _REQUIREMENTS = "qtConfig(private_tests)"
-
## Scopes:
#####################################################################
-#### Keys ignored in scope 2:.:.:qsocks5socketengine.pro:LINUX:
# QT_TEST_SERVER_LIST = "danted" "apache2" "cyrus"
qt_internal_extend_target(tst_qsocks5socketengine CONDITION WIN32
diff --git a/tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp b/tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp
index 3ce1153031..cc77ba2da3 100644
--- a/tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp
+++ b/tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QTest>
@@ -23,6 +23,8 @@
#include "../../../network-settings.h"
+using namespace std::chrono_literals;
+
class tst_QSocks5SocketEngine : public QObject, public QAbstractSocketEngineReceiver
{
Q_OBJECT
@@ -341,7 +343,7 @@ void tst_QSocks5SocketEngine::simpleErrorsAndStates()
QCOMPARE(socketDevice.state(), QAbstractSocket::UnconnectedState);
QVERIFY(!socketDevice.connectToHost(QHostInfo::fromName(QtNetworkSettings::socksProxyServerName()).addresses().first(), 8088));
QCOMPARE(socketDevice.state(), QAbstractSocket::ConnectingState);
- if (socketDevice.waitForWrite(15000)) {
+ if (socketDevice.waitForWrite(15s)) {
QVERIFY(socketDevice.state() == QAbstractSocket::UnconnectedState ||
socketDevice.state() == QAbstractSocket::ConnectedState);
} else {
@@ -915,13 +917,13 @@ void tst_QSocks5SocketEngine::fragmentation_data()
responses << authMethodBasic << authSuccess.left(1) << authSuccess.mid(1) << connectResponseIPv4;
QTest::newRow("auth-response") << responses;
- for (int i = 1; i < connectResponseIPv4.length() - 1; i++) {
+ for (int i = 1; i < connectResponseIPv4.size() - 1; i++) {
responses.clear();
responses << authMethodNone << connectResponseIPv4.left(i) << connectResponseIPv4.mid(i);
QTest::newRow(qPrintable(QString("connect-response-ipv4-") + QString::number(i))) << responses;
}
- for (int i = 1; i < connectResponseIPv6.length() - 1; i++) {
+ for (int i = 1; i < connectResponseIPv6.size() - 1; i++) {
responses.clear();
responses << authMethodNone << connectResponseIPv6.left(i) << connectResponseIPv6.mid(i);
QTest::newRow(qPrintable(QString("connect-response-ipv6-") + QString::number(i))) << responses;
@@ -964,13 +966,13 @@ void tst_QSocks5SocketEngine::incomplete_data()
responses << authMethodBasic << authSuccess.left(1);
QTest::newRow("auth-response") << responses;
- for (int i = 1; i < connectResponseIPv4.length() - 1; i++) {
+ for (int i = 1; i < connectResponseIPv4.size() - 1; i++) {
responses.clear();
responses << authMethodNone << connectResponseIPv4.left(i);
QTest::newRow(qPrintable(QString("connect-response-ipv4-") + QString::number(i))) << responses;
}
- for (int i = 1; i < connectResponseIPv6.length() - 1; i++) {
+ for (int i = 1; i < connectResponseIPv6.size() - 1; i++) {
responses.clear();
responses << authMethodNone << connectResponseIPv6.left(i);
QTest::newRow(qPrintable(QString("connect-response-ipv6-") + QString::number(i))) << responses;
diff --git a/tests/auto/network/socket/qtcpserver/BLACKLIST b/tests/auto/network/socket/qtcpserver/BLACKLIST
index ecca156cef..a8b5f5d137 100644
--- a/tests/auto/network/socket/qtcpserver/BLACKLIST
+++ b/tests/auto/network/socket/qtcpserver/BLACKLIST
@@ -1,18 +1,13 @@
[listenWhileListening:WithSocks5Proxy]
linux
windows
-[ipv6Server]
-windows-7sp1
-windows-10 msvc-2017
[ipv6Server:WithoutProxy]
windows
osx
[serverAddress]
# QTBUG-103056
qnx
-windows-7sp1
windows-10
[linkLocal]
macos arm
-
diff --git a/tests/auto/network/socket/qtcpserver/CMakeLists.txt b/tests/auto/network/socket/qtcpserver/CMakeLists.txt
index 170cf4b805..b01a164302 100644
--- a/tests/auto/network/socket/qtcpserver/CMakeLists.txt
+++ b/tests/auto/network/socket/qtcpserver/CMakeLists.txt
@@ -1,7 +1,11 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qtcpserver.pro.
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qtcpserver LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
add_subdirectory(crashingServer)
add_subdirectory(test)
diff --git a/tests/auto/network/socket/qtcpserver/crashingServer/CMakeLists.txt b/tests/auto/network/socket/qtcpserver/crashingServer/CMakeLists.txt
index 5cb7575c37..bb1feb0237 100644
--- a/tests/auto/network/socket/qtcpserver/crashingServer/CMakeLists.txt
+++ b/tests/auto/network/socket/qtcpserver/crashingServer/CMakeLists.txt
@@ -1,8 +1,6 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from crashingServer.pro.
-
#####################################################################
## crashingServer Binary:
#####################################################################
diff --git a/tests/auto/network/socket/qtcpserver/crashingServer/main.cpp b/tests/auto/network/socket/qtcpserver/crashingServer/main.cpp
index 5e00a2bd20..1c41552eb5 100644
--- a/tests/auto/network/socket/qtcpserver/crashingServer/main.cpp
+++ b/tests/auto/network/socket/qtcpserver/crashingServer/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore>
@@ -7,18 +7,45 @@
#if defined(Q_OS_WIN) && defined(Q_CC_MSVC)
# include <crtdbg.h>
#endif
+#ifdef Q_OS_UNIX
+# include <sys/resource.h>
+# include <unistd.h>
+#endif
int main(int argc, char *argv[])
{
- // Windows: Suppress crash notification dialog.
#if defined(Q_OS_WIN) && defined(Q_CC_MSVC)
+ // Windows: Suppress crash notification dialog.
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
+#elif defined(RLIMIT_CORE)
+ // Unix: set our core dump limit to zero to request no dialogs.
+ if (struct rlimit rlim; getrlimit(RLIMIT_CORE, &rlim) == 0) {
+ rlim.rlim_cur = 0;
+ setrlimit(RLIMIT_CORE, &rlim);
+ }
#endif
+
QCoreApplication app(argc, argv);
+ if (argc < 1) {
+ fprintf(stderr, "Need a port number\n");
+ return 1;
+ }
+ int port = QByteArrayView(argv[1]).toInt();
QTcpServer server;
- if (!server.listen(QHostAddress::LocalHost, 49199)) {
- qDebug("Failed to listen: %s", server.errorString().toLatin1().constData());
+ if (!server.listen(QHostAddress::LocalHost, port)) {
+ fprintf(stderr, "Failed to listen: %s\n", server.errorString().toLatin1().constData());
+ if (server.serverError() == QTcpSocket::AddressInUseError) {
+ // let's see if we can find the process that would be holding this
+ // still open
+#ifdef Q_OS_LINUX
+ static const char *ss_args[] = {
+ "ss", "-nap", "sport", "=", argv[1], nullptr
+ };
+ dup2(STDERR_FILENO, STDOUT_FILENO);
+ execvp(ss_args[0], const_cast<char **>(ss_args));
+#endif
+ }
return 1;
}
diff --git a/tests/auto/network/socket/qtcpserver/test/CMakeLists.txt b/tests/auto/network/socket/qtcpserver/test/CMakeLists.txt
index df7334b7bc..55615bbae1 100644
--- a/tests/auto/network/socket/qtcpserver/test/CMakeLists.txt
+++ b/tests/auto/network/socket/qtcpserver/test/CMakeLists.txt
@@ -1,28 +1,23 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from test.pro.
-
#####################################################################
## tst_qtcpserver Test:
#####################################################################
qt_internal_add_test(tst_qtcpserver
- OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../" # special case
+ OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../"
SOURCES
../tst_qtcpserver.cpp
LIBRARIES
Qt::Network
- QT_TEST_SERVER_LIST "danted" "cyrus" "squid" "ftp-proxy" # special case
+ QT_TEST_SERVER_LIST "danted" "cyrus" "squid" "ftp-proxy"
)
add_dependencies(tst_qtcpserver
crashingServer
)
-#### Keys ignored in scope 1:.:.:test.pro:<TRUE>:
-# MOC_DIR = "tmp"
-
## Scopes:
#####################################################################
@@ -30,6 +25,3 @@ qt_internal_extend_target(tst_qtcpserver CONDITION WIN32
LIBRARIES
ws2_32
)
-
-#### Keys ignored in scope 6:.:.:test.pro:LINUX:
-# QT_TEST_SERVER_LIST = "danted" "cyrus" "squid" "ftp-proxy"
diff --git a/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp b/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp
index adf3781c50..c03076d98e 100644
--- a/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp
+++ b/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp
@@ -1,9 +1,7 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qglobal.h>
-// To prevent windows system header files from re-defining min/max
-#define NOMINMAX 1
#if defined(_WIN32)
#include <winsock2.h>
#else
@@ -140,7 +138,8 @@ void tst_QTcpServer::initTestCase()
#ifdef QT_TEST_SERVER
QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1080));
QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3128));
- QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::ftpProxyServerName(), 2121));
+ // FTP currently not supported:
+ // QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::ftpProxyServerName(), 2121));
QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::imapServerName(), 143));
#else
if (!QtNetworkSettings::verifyTestNetworkSettings())
@@ -248,7 +247,7 @@ void tst_QTcpServer::clientServerLoop()
QVERIFY(server.waitForNewConnection(5000));
QVERIFY(server.hasPendingConnections());
- QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.size(), 1);
QTcpSocket *serverSocket = server.nextPendingConnection();
QVERIFY(serverSocket != 0);
@@ -409,9 +408,9 @@ void tst_QTcpServer::maxPendingConnections()
// two connections have been made. The second compare makes sure no
// more are accepted. Creating connections happens multithreaded so
// qWait must be used for that.
- QTRY_COMPARE(spy.count(), 2);
+ QTRY_COMPARE(spy.size(), 2);
QTest::qWait(100);
- QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy.size(), 2);
QVERIFY(server.hasPendingConnections());
QVERIFY(server.nextPendingConnection());
@@ -460,7 +459,7 @@ public:
protected:
void run() override
{
- sleep(2);
+ sleep(std::chrono::seconds{2});
QTcpSocket socket;
socket.connectToHost(host, port);
@@ -578,9 +577,6 @@ void tst_QTcpServer::addressReusable()
#if !QT_CONFIG(process)
QSKIP("No qprocess support", SkipAll);
#else
-#ifdef Q_OS_LINUX
- QSKIP("The addressReusable test is unstable on Linux. See QTBUG-39985.");
-#endif
QFETCH_GLOBAL(bool, setProxy);
if (setProxy) {
#ifndef QT_NO_NETWORKPROXY
@@ -591,16 +587,25 @@ void tst_QTcpServer::addressReusable()
QSKIP("No proxy support");
#endif // QT_NO_NETWORKPROXY
}
+
+ QTcpServer server;
+ QVERIFY(server.listen(QHostAddress::LocalHost, 0));
+ quint16 serverPort = server.serverPort();
+ qDebug() << "Got port" << serverPort;
+ server.close(); // cleanly close
+
+ QTest::qSleep(10);
+
// The crashingServer process will crash once it gets a connection.
QProcess process;
QString processExe = crashingServerDir + "/crashingServer";
- process.start(processExe);
+ process.start(processExe, { QString::number(serverPort) });
QVERIFY2(process.waitForStarted(), qPrintable(
QString::fromLatin1("Could not start %1: %2").arg(processExe, process.errorString())));
- QVERIFY(process.waitForReadyRead(5000));
+ QVERIFY2(process.waitForReadyRead(5000), qPrintable(process.readAllStandardError()));
QTcpSocket socket;
- socket.connectToHost(QHostAddress::LocalHost, 49199);
+ socket.connectToHost(QHostAddress::LocalHost, serverPort);
QVERIFY(socket.waitForConnected(5000));
QVERIFY(process.waitForFinished(30000));
@@ -608,8 +613,9 @@ void tst_QTcpServer::addressReusable()
// Give the system some time.
QTest::qSleep(10);
- QTcpServer server;
- QVERIFY(server.listen(QHostAddress::LocalHost, 49199));
+ // listen again
+ QVERIFY2(server.listen(QHostAddress::LocalHost, serverPort),
+ qPrintable(server.errorString()));
#endif
}
@@ -728,6 +734,7 @@ void tst_QTcpServer::proxyFactory_data()
<< proxyList << proxyList.at(1)
<< false << int(QAbstractSocket::UnknownSocketError);
+#if 0 // ftp not currently supported
proxyList.clear();
proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121)
<< QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3128)
@@ -735,6 +742,7 @@ void tst_QTcpServer::proxyFactory_data()
QTest::newRow("ftp+cachinghttp+socks5")
<< proxyList << proxyList.at(2)
<< false << int(QAbstractSocket::UnknownSocketError);
+#endif
// tests that fail to listen
proxyList.clear();
@@ -749,6 +757,7 @@ void tst_QTcpServer::proxyFactory_data()
<< proxyList << QNetworkProxy()
<< true << int(QAbstractSocket::UnsupportedSocketOperationError);
+#if 0 // ftp not currently supported
proxyList.clear();
proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121);
QTest::newRow("ftp")
@@ -761,6 +770,7 @@ void tst_QTcpServer::proxyFactory_data()
QTest::newRow("ftp+cachinghttp")
<< proxyList << QNetworkProxy()
<< true << int(QAbstractSocket::UnsupportedSocketOperationError);
+#endif
}
void tst_QTcpServer::proxyFactory()
@@ -855,10 +865,12 @@ void tst_QTcpServer::serverAddress_data()
QTest::newRow("AnyIPv4") << QHostAddress(QHostAddress::AnyIPv4) << QHostAddress(QHostAddress::AnyIPv4);
if (QtNetworkSettings::hasIPv6())
QTest::newRow("AnyIPv6") << QHostAddress(QHostAddress::AnyIPv6) << QHostAddress(QHostAddress::AnyIPv6);
- foreach (const QNetworkInterface &iface, QNetworkInterface::allInterfaces()) {
+ const auto ifaces = QNetworkInterface::allInterfaces();
+ for (const QNetworkInterface &iface : ifaces) {
if ((iface.flags() & QNetworkInterface::IsUp) == 0)
continue;
- foreach (const QNetworkAddressEntry &entry, iface.addressEntries()) {
+ const auto entries = iface.addressEntries();
+ for (const QNetworkAddressEntry &entry : entries) {
QTest::newRow(qPrintable(entry.ip().toString())) << entry.ip() << entry.ip();
}
}
@@ -912,7 +924,8 @@ void tst_QTcpServer::linkLocal()
QSet <QString> scopes;
QHostAddress localMaskv4("169.254.0.0");
QHostAddress localMaskv6("fe80::");
- foreach (const QNetworkInterface& iface, QNetworkInterface::allInterfaces()) {
+ const auto ifaces = QNetworkInterface::allInterfaces();
+ for (const QNetworkInterface &iface : ifaces) {
//Windows preallocates link local addresses to interfaces that are down.
//These may or may not work depending on network driver (they do not work for the Bluetooth PAN driver)
if (iface.flags() & QNetworkInterface::IsUp) {
@@ -932,7 +945,8 @@ void tst_QTcpServer::linkLocal()
if (iface.name().startsWith("awdl"))
continue;
#endif
- foreach (QNetworkAddressEntry addressEntry, iface.addressEntries()) {
+ const auto entries = iface.addressEntries();
+ for (const QNetworkAddressEntry &addressEntry : entries) {
QHostAddress addr = addressEntry.ip();
if (addr.isInSubnet(localMaskv4, 16)) {
addresses << addr;
@@ -951,7 +965,7 @@ void tst_QTcpServer::linkLocal()
QList<QTcpServer*> servers;
quint16 port = 0;
- foreach (const QHostAddress& addr, addresses) {
+ for (const QHostAddress &addr : std::as_const(addresses)) {
QTcpServer *server = new QTcpServer;
QVERIFY(server->listen(addr, port));
port = server->serverPort(); //listen to same port on different interfaces
@@ -959,7 +973,7 @@ void tst_QTcpServer::linkLocal()
}
QList<QTcpSocket*> clients;
- foreach (const QHostAddress& addr, addresses) {
+ for (const QHostAddress &addr : std::as_const(addresses)) {
//unbound socket
QTcpSocket *socket = new QTcpSocket;
socket->connectToHost(addr, port);
@@ -974,7 +988,7 @@ void tst_QTcpServer::linkLocal()
}
//each server should have two connections
- foreach (QTcpServer* server, servers) {
+ for (QTcpServer *server : std::as_const(servers)) {
//qDebug() << "checking for connections" << server->serverAddress() << ":" << server->serverPort();
QVERIFY(server->waitForNewConnection(5000));
QTcpSocket* remote = server->nextPendingConnection();
@@ -1009,12 +1023,12 @@ void tst_QTcpServer::eagainBlockingAccept()
QTcpSocket s;
s.connectToHost(QHostAddress::LocalHost, 7896);
QSignalSpy spy(&server, SIGNAL(newConnection()));
- QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 1, 500);
+ QTRY_COMPARE_WITH_TIMEOUT(spy.size(), 1, 500);
s.close();
// To test try again, should connect just fine.
s.connectToHost(QHostAddress::LocalHost, 7896);
- QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 2, 500);
+ QTRY_COMPARE_WITH_TIMEOUT(spy.size(), 2, 500);
s.close();
server.close();
}
@@ -1050,13 +1064,13 @@ void tst_QTcpServer::pauseAccepting()
QTcpSocket sockets[NumSockets];
sockets[0].connectToHost(address, server.serverPort());
QVERIFY(spy.wait());
- QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.size(), 1);
server.pauseAccepting();
for (int i = 1; i < NumSockets; ++i)
sockets[i].connectToHost(address, server.serverPort());
QVERIFY(!spy.wait(400));
- QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.size(), 1);
server.resumeAccepting();
if (setProxy) {
@@ -1064,7 +1078,7 @@ void tst_QTcpServer::pauseAccepting()
Abort);
}
QVERIFY(spy.wait());
- QCOMPARE(spy.count(), 6);
+ QCOMPARE(spy.size(), 6);
}
@@ -1128,11 +1142,11 @@ void tst_QTcpServer::pendingConnectionAvailable()
QCOMPARE(socket.state(), QTcpSocket::ConnectedState);
int expectedPendingConnections = useDerivedServer ? 0 : 1;
- QCOMPARE(pendingConnectionSpy.count(), expectedPendingConnections);
+ QCOMPARE(pendingConnectionSpy.size(), expectedPendingConnections);
if (useDerivedServer)
static_cast<DerivedServer *>(server)->emitNextSocket();
- QCOMPARE(pendingConnectionSpy.count(), 1);
+ QCOMPARE(pendingConnectionSpy.size(), 1);
}
QTEST_MAIN(tst_QTcpServer)
diff --git a/tests/auto/network/socket/qtcpsocket/CMakeLists.txt b/tests/auto/network/socket/qtcpsocket/CMakeLists.txt
index 13b14f657f..7b6bb4d881 100644
--- a/tests/auto/network/socket/qtcpsocket/CMakeLists.txt
+++ b/tests/auto/network/socket/qtcpsocket/CMakeLists.txt
@@ -1,7 +1,11 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qtcpsocket.pro.
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qtcpsocket LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
if(NOT QT_FEATURE_private_tests)
return()
diff --git a/tests/auto/network/socket/qtcpsocket/stressTest/CMakeLists.txt b/tests/auto/network/socket/qtcpsocket/stressTest/CMakeLists.txt
index 78580ca047..3ea6c55895 100644
--- a/tests/auto/network/socket/qtcpsocket/stressTest/CMakeLists.txt
+++ b/tests/auto/network/socket/qtcpsocket/stressTest/CMakeLists.txt
@@ -1,8 +1,6 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from stressTest.pro.
-
#####################################################################
## stressTest Binary:
#####################################################################
@@ -16,7 +14,3 @@ qt_internal_add_executable(stressTest
Qt::Network
Qt::Test
)
-
-#### Keys ignored in scope 1:.:.:stressTest.pro:<TRUE>:
-# MOC_DIR = ".moc/"
-# TMP_DIR = ".tmp/"
diff --git a/tests/auto/network/socket/qtcpsocket/stressTest/Test.cpp b/tests/auto/network/socket/qtcpsocket/stressTest/Test.cpp
index 4a7c36d1c1..8d6e470220 100644
--- a/tests/auto/network/socket/qtcpsocket/stressTest/Test.cpp
+++ b/tests/auto/network/socket/qtcpsocket/stressTest/Test.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt
#include <QByteArray>
#include <QCoreApplication>
diff --git a/tests/auto/network/socket/qtcpsocket/stressTest/Test.h b/tests/auto/network/socket/qtcpsocket/stressTest/Test.h
index f5a19ae16a..495b90d733 100644
--- a/tests/auto/network/socket/qtcpsocket/stressTest/Test.h
+++ b/tests/auto/network/socket/qtcpsocket/stressTest/Test.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TEST_H
#define TEST_H
diff --git a/tests/auto/network/socket/qtcpsocket/stressTest/main.cpp b/tests/auto/network/socket/qtcpsocket/stressTest/main.cpp
index 57fec691d6..f989a4de34 100644
--- a/tests/auto/network/socket/qtcpsocket/stressTest/main.cpp
+++ b/tests/auto/network/socket/qtcpsocket/stressTest/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "Test.h"
#include <QCoreApplication>
diff --git a/tests/auto/network/socket/qtcpsocket/test/CMakeLists.txt b/tests/auto/network/socket/qtcpsocket/test/CMakeLists.txt
index e521d37bce..c3258f8a95 100644
--- a/tests/auto/network/socket/qtcpsocket/test/CMakeLists.txt
+++ b/tests/auto/network/socket/qtcpsocket/test/CMakeLists.txt
@@ -1,20 +1,18 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from test.pro.
-
#####################################################################
## tst_qtcpsocket Test:
#####################################################################
qt_internal_add_test(tst_qtcpsocket
- OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../" # special case
+ OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../"
SOURCES
../tst_qtcpsocket.cpp
LIBRARIES
Qt::CorePrivate
Qt::NetworkPrivate
- QT_TEST_SERVER_LIST "danted" "squid" "apache2" "ftp-proxy" "vsftpd" "iptables" "cyrus" # special case
+ QT_TEST_SERVER_LIST "danted" "squid" "apache2" "ftp-proxy" "vsftpd" "iptables" "cyrus"
)
## Scopes:
@@ -24,15 +22,3 @@ qt_internal_extend_target(tst_qtcpsocket CONDITION WIN32
LIBRARIES
ws2_32
)
-
-#### Keys ignored in scope 4:.:.:test.pro:(CMAKE_BUILD_TYPE STREQUAL Debug):
-# DESTDIR = "../debug"
-
-#### Keys ignored in scope 5:.:.:test.pro:else:
-# DESTDIR = "../release"
-
-#### Keys ignored in scope 6:.:.:test.pro:else:
-# DESTDIR = "../"
-
-#### Keys ignored in scope 7:.:.:test.pro:LINUX:
-# QT_TEST_SERVER_LIST = "danted" "squid" "apache2" "ftp-proxy" "vsftpd" "iptables" "cyrus"
diff --git a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp
index 981160ce6b..4ec01a9d94 100644
--- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp
+++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp
@@ -1,11 +1,9 @@
// Copyright (C) 2016 The Qt Company Ltd.
// Copyright (C) 2017 Intel Corporation.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qglobal.h>
-// To prevent windows system header files from re-defining min/max
-#define NOMINMAX 1
#if defined(_WIN32)
#include <winsock2.h>
#else
@@ -62,6 +60,8 @@
#include "../../../network-settings.h"
+using namespace Qt::StringLiterals;
+
QT_FORWARD_DECLARE_CLASS(QTcpSocket)
class SocketPair;
@@ -283,7 +283,7 @@ tst_QTcpSocket::tst_QTcpSocket()
tmpSocket = 0;
//This code relates to the socketsConstructedBeforeEventLoop test case
- earlyConstructedSockets = new SocketPair;
+ earlyConstructedSockets = new SocketPair(this);
QVERIFY(earlyConstructedSockets->create());
earlyBytesWrittenCount = 0;
earlyReadyReadCount = 0;
@@ -332,7 +332,8 @@ void tst_QTcpSocket::initTestCase()
//QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::firewallServerName(), 1357));
QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1080));
QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::ftpServerName(), 21));
- QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::ftpProxyServerName(), 2121));
+ // FTP currently not supported:
+ // QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::ftpProxyServerName(), 2121));
#else
if (!QtNetworkSettings::verifyTestNetworkSettings())
QSKIP("No network test server available");
@@ -347,8 +348,8 @@ void tst_QTcpSocket::init()
QFETCH_GLOBAL(int, proxyType);
QList<QHostAddress> socks5Addresses = QHostInfo::fromName(QtNetworkSettings::socksProxyServerName()).addresses();
QList<QHostAddress> httpProxyAddresses = QHostInfo::fromName(QtNetworkSettings::httpProxyServerName()).addresses();
- QVERIFY2(socks5Addresses.count() > 0, "failed to get ip address for SOCKS5 proxy server");
- QVERIFY2(httpProxyAddresses.count() > 0, "failed to get ip address for HTTP proxy server");
+ QVERIFY2(socks5Addresses.size() > 0, "failed to get ip address for SOCKS5 proxy server");
+ QVERIFY2(httpProxyAddresses.size() > 0, "failed to get ip address for HTTP proxy server");
QString socks5Address = socks5Addresses.first().toString();
QString httpProxyAddress = httpProxyAddresses.first().toString();
QNetworkProxy proxy;
@@ -488,12 +489,13 @@ void tst_QTcpSocket::bind_data()
bool testIpv6 = false;
// iterate all interfaces, add all addresses on them as test data
- QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
- foreach (const QNetworkInterface &netinterface, interfaces) {
+ const QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
+ for (const QNetworkInterface &netinterface : interfaces) {
if (!netinterface.isValid())
continue;
- foreach (const QNetworkAddressEntry &entry, netinterface.addressEntries()) {
+ const auto entries = netinterface.addressEntries();
+ for (const QNetworkAddressEntry &entry : entries) {
if (entry.ip().isInSubnet(QHostAddress::parseSubnet("fe80::/10"))
|| entry.ip().isInSubnet(QHostAddress::parseSubnet("169.254/16")))
continue; // link-local bind will fail, at least on Linux, so skip it.
@@ -523,12 +525,12 @@ void tst_QTcpSocket::bind_data()
// these ranges are guaranteed to be reserved for 'documentation purposes',
// and thus, should be unused in the real world. Not that I'm assuming the
// world is full of competent administrators, or anything.
- QStringList knownBad;
- knownBad << "198.51.100.1";
- knownBad << "2001:0DB8::1";
- foreach (const QString &badAddress, knownBad) {
+ const QString knownBad[] = {
+ u"198.51.100.1"_s,
+ u"2001:0DB8::1"_s
+ };
+ for (const QString &badAddress : knownBad)
QTest::addRow("%s:0", badAddress.toLatin1().constData()) << badAddress << 0 << false << QString();
- }
// try to bind to a privileged ports
// we should fail if we're not root (unless the ports are in use!)
@@ -563,7 +565,7 @@ void tst_QTcpSocket::bind()
std::unique_ptr<QTcpSocket> socket(newSocket());
quint16 boundPort;
- qintptr fd;
+ qintptr fd = 0;
if (successExpected) {
bool randomPort = port == -1;
@@ -1781,7 +1783,7 @@ void tst_QTcpSocket::recursiveReadyRead()
QVERIFY2(!timeout(),
"Timed out when waiting for the readyRead() signal.");
- QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.size(), 1);
delete testSocket;
}
@@ -1823,7 +1825,7 @@ void tst_QTcpSocket::atEnd()
QVERIFY2(greeting.startsWith("220 (vsFTPd 3."), qPrintable(greeting));
#else
// Test server must use some vsFTPd 2.x.x version
- QVERIFY2(greeting.length() == sizeof("220 (vsFTPd 2.x.x)")-1, qPrintable(greeting));
+ QVERIFY2(greeting.size() == sizeof("220 (vsFTPd 2.x.x)")-1, qPrintable(greeting));
QVERIFY2(greeting.startsWith("220 (vsFTPd 2."), qPrintable(greeting));
#endif
QVERIFY2(greeting.endsWith(QLatin1Char(')')), qPrintable(greeting));
@@ -2006,8 +2008,8 @@ void tst_QTcpSocket::remoteCloseError()
enterLoop(30);
QVERIFY(!timeout());
- QCOMPARE(disconnectedSpy.count(), 1);
- QCOMPARE(errorSpy.count(), 1);
+ QCOMPARE(disconnectedSpy.size(), 1);
+ QCOMPARE(errorSpy.size(), 1);
QCOMPARE(clientSocket->error(), QAbstractSocket::RemoteHostClosedError);
delete serverSocket;
@@ -2138,7 +2140,7 @@ void tst_QTcpSocket::waitForConnectedInHostLookupSlot()
if (tmpSocket->state() != QAbstractSocket::ConnectedState)
loop.exec();
- QCOMPARE(timerSpy.count(), 0);
+ QCOMPARE(timerSpy.size(), 0);
delete tmpSocket;
}
@@ -2243,7 +2245,7 @@ void tst_QTcpSocket::readyReadSignalsAfterWaitForReadyRead()
// Wait for the read
QVERIFY(socket->waitForReadyRead(10000));
- QCOMPARE(readyReadSpy.count(), 1);
+ QCOMPARE(readyReadSpy.size(), 1);
QString s = socket->readLine();
QVERIFY2(QtNetworkSettings::compareReplyIMAP(s.toLatin1()), s.toLatin1().constData());
@@ -2251,7 +2253,7 @@ void tst_QTcpSocket::readyReadSignalsAfterWaitForReadyRead()
QCoreApplication::instance()->processEvents();
QCOMPARE(socket->bytesAvailable(), qint64(0));
- QCOMPARE(readyReadSpy.count(), 1);
+ QCOMPARE(readyReadSpy.size(), 1);
delete socket;
}
@@ -2325,8 +2327,8 @@ void tst_QTcpSocket::abortiveClose()
enterLoop(5);
- QCOMPARE(readyReadSpy.count(), 0);
- QCOMPARE(errorSpy.count(), 1);
+ QCOMPARE(readyReadSpy.size(), 0);
+ QCOMPARE(errorSpy.size(), 1);
QCOMPARE(*static_cast<const int *>(errorSpy.at(0).at(0).constData()),
int(QAbstractSocket::RemoteHostClosedError));
@@ -2445,11 +2447,11 @@ void tst_QTcpSocket::connectionRefused()
QCOMPARE(socket->state(), QAbstractSocket::UnconnectedState);
QCOMPARE(socket->error(), QAbstractSocket::ConnectionRefusedError);
- QCOMPARE(stateSpy.count(), 3);
+ QCOMPARE(stateSpy.size(), 3);
QCOMPARE(qvariant_cast<QAbstractSocket::SocketState>(stateSpy.at(0).at(0)), QAbstractSocket::HostLookupState);
QCOMPARE(qvariant_cast<QAbstractSocket::SocketState>(stateSpy.at(1).at(0)), QAbstractSocket::ConnectingState);
QCOMPARE(qvariant_cast<QAbstractSocket::SocketState>(stateSpy.at(2).at(0)), QAbstractSocket::UnconnectedState);
- QCOMPARE(errorSpy.count(), 1);
+ QCOMPARE(errorSpy.size(), 1);
delete socket;
}
@@ -2581,7 +2583,7 @@ void tst_QTcpSocket::moveToThread0()
{
// Case 1: Moved after connecting, before waiting for connection.
- QTcpSocket *socket = newSocket();;
+ QTcpSocket *socket = newSocket();
socket->connectToHost(QtNetworkSettings::imapServerName(), 143);
socket->moveToThread(0);
QVERIFY(socket->waitForConnected(5000));
@@ -2912,6 +2914,7 @@ void tst_QTcpSocket::proxyFactory_data()
<< proxyList << proxyList.at(1)
<< false << int(QAbstractSocket::UnknownSocketError);
+#if 0 // FTP not currently supported
proxyList.clear();
proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121)
<< QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129)
@@ -2919,6 +2922,7 @@ void tst_QTcpSocket::proxyFactory_data()
QTest::newRow("ftp+cachinghttp+socks5")
<< proxyList << proxyList.at(2)
<< false << int(QAbstractSocket::UnknownSocketError);
+#endif
// tests that fail to connect
proxyList.clear();
@@ -2927,6 +2931,7 @@ void tst_QTcpSocket::proxyFactory_data()
<< proxyList << QNetworkProxy()
<< true << int(QAbstractSocket::UnsupportedSocketOperationError);
+#if 0 // FTP not currently supported
proxyList.clear();
proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121);
QTest::newRow("ftp")
@@ -2939,6 +2944,7 @@ void tst_QTcpSocket::proxyFactory_data()
QTest::newRow("ftp+cachinghttp")
<< proxyList << QNetworkProxy()
<< true << int(QAbstractSocket::UnsupportedSocketOperationError);
+#endif
}
void tst_QTcpSocket::proxyFactory()
@@ -3118,8 +3124,8 @@ void tst_QTcpSocket::serverDisconnectWithBuffered()
QCOMPARE(socket->state(), QAbstractSocket::UnconnectedState);
}
// Test signal emitting
- QCOMPARE(spyDisconnected.count(), 1);
- QVERIFY(spyStateChanged.count() > 0);
+ QCOMPARE(spyDisconnected.size(), 1);
+ QVERIFY(spyStateChanged.size() > 0);
QVERIFY(qvariant_cast<QAbstractSocket::SocketState>(spyStateChanged.last().first())
== QAbstractSocket::UnconnectedState);
@@ -3208,7 +3214,7 @@ void tst_QTcpSocket::readNotificationsAfterBind()
QTestEventLoop::instance().enterLoop(10);
QVERIFY2(!QTestEventLoop::instance().timeout(), "Connection to closed port timed out instead of refusing, something is wrong");
QVERIFY2(socket.state() == QAbstractSocket::UnconnectedState, "Socket connected unexpectedly!");
- QCOMPARE(spyReadyRead.count(), 0);
+ QCOMPARE(spyReadyRead.size(), 0);
}
QTEST_MAIN(tst_QTcpSocket)
diff --git a/tests/auto/network/socket/qudpsocket/BLACKLIST b/tests/auto/network/socket/qudpsocket/BLACKLIST
index 704d83509d..f5f6a8e156 100644
--- a/tests/auto/network/socket/qudpsocket/BLACKLIST
+++ b/tests/auto/network/socket/qudpsocket/BLACKLIST
@@ -1,11 +1,7 @@
[writeDatagramToNonExistingPeer]
windows
-# QTBUG-85364
-windows-10 gcc cmake
[readyReadForEmptyDatagram]
opensuse-leap
-[echo]
-opensuse-42.3
[multicast]
centos
macos arm
diff --git a/tests/auto/network/socket/qudpsocket/CMakeLists.txt b/tests/auto/network/socket/qudpsocket/CMakeLists.txt
index 85beeb9633..a7a2659340 100644
--- a/tests/auto/network/socket/qudpsocket/CMakeLists.txt
+++ b/tests/auto/network/socket/qudpsocket/CMakeLists.txt
@@ -1,7 +1,11 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qudpsocket.pro.
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qudpsocket LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
-add_subdirectory(test)
add_subdirectory(clientserver)
+add_subdirectory(test)
diff --git a/tests/auto/network/socket/qudpsocket/clientserver/CMakeLists.txt b/tests/auto/network/socket/qudpsocket/clientserver/CMakeLists.txt
index 649b343302..4644d0d96f 100644
--- a/tests/auto/network/socket/qudpsocket/clientserver/CMakeLists.txt
+++ b/tests/auto/network/socket/qudpsocket/clientserver/CMakeLists.txt
@@ -1,8 +1,6 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from clientserver.pro.
-
#####################################################################
## clientserver Binary:
#####################################################################
diff --git a/tests/auto/network/socket/qudpsocket/clientserver/main.cpp b/tests/auto/network/socket/qudpsocket/clientserver/main.cpp
index a83aa6d420..76bdf3aada 100644
--- a/tests/auto/network/socket/qudpsocket/clientserver/main.cpp
+++ b/tests/auto/network/socket/qudpsocket/clientserver/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtNetwork>
class ClientServer : public QUdpSocket
diff --git a/tests/auto/network/socket/qudpsocket/test/CMakeLists.txt b/tests/auto/network/socket/qudpsocket/test/CMakeLists.txt
index ec7dfb3198..69b62c2f9f 100644
--- a/tests/auto/network/socket/qudpsocket/test/CMakeLists.txt
+++ b/tests/auto/network/socket/qudpsocket/test/CMakeLists.txt
@@ -1,37 +1,20 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from test.pro.
-
#####################################################################
## tst_qudpsocket Test:
#####################################################################
qt_internal_add_test(tst_qudpsocket
- OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../" # special case
+ OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../"
SOURCES
../tst_qudpsocket.cpp
LIBRARIES
Qt::Network
Qt::TestPrivate
- QT_TEST_SERVER_LIST "danted" "echo" # special case
+ QT_TEST_SERVER_LIST "danted" "echo"
)
-#### Keys ignored in scope 1:.:.:test.pro:<TRUE>:
-# MOC_DIR = "tmp"
-# testcase.timeout = "800"
-
-## Scopes:
-#####################################################################
-
-#### Keys ignored in scope 3:.:.:test.pro:(CMAKE_BUILD_TYPE STREQUAL Debug):
-# DESTDIR = "../debug"
-
-#### Keys ignored in scope 4:.:.:test.pro:else:
-# DESTDIR = "../release"
-
-#### Keys ignored in scope 5:.:.:test.pro:else:
-# DESTDIR = "../"
-
-#### Keys ignored in scope 6:.:.:test.pro:LINUX:
-# QT_TEST_SERVER_LIST = "danted" "echo"
+if(QT_FEATURE_process)
+ add_dependencies(tst_qudpsocket clientserver)
+endif()
diff --git a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp
index 336b528567..689ff452f9 100644
--- a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp
+++ b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp
@@ -1,7 +1,6 @@
// Copyright (C) 2021 The Qt Company Ltd.
// Copyright (C) 2017 Intel Corporation.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
#include <QSignalSpy>
@@ -11,6 +10,7 @@
#endif
#include <QScopeGuard>
#include <QVersionNumber>
+#include <QSemaphore>
#include <qcoreapplication.h>
#include <qfileinfo.h>
@@ -46,6 +46,8 @@
# define RELIABLE_BYTES_AVAILABLE
#endif
+using namespace Qt::StringLiterals;
+
Q_DECLARE_METATYPE(QHostAddress)
QT_FORWARD_DECLARE_CLASS(QUdpSocket)
@@ -103,6 +105,8 @@ private slots:
void asyncReadDatagram();
void writeInHostLookupState();
+ void readyReadConnectionThrottling();
+
protected slots:
void empty_readyReadSlot();
void empty_connectedSlot();
@@ -121,6 +125,7 @@ private:
QList<QHostAddress> allAddresses;
QHostAddress multicastGroup4, multicastGroup6;
QList<QHostAddress> linklocalMulticastGroups;
+ QNetworkInterface ifaceWithIPv6;
QUdpSocket *m_asyncSender;
QUdpSocket *m_asyncReceiver;
};
@@ -171,26 +176,7 @@ QNetworkInterface tst_QUdpSocket::interfaceForGroup(const QHostAddress &multicas
if (!scope.isEmpty())
return QNetworkInterface::interfaceFromName(scope);
- static QNetworkInterface ipv6if = [&]() {
- // find any link local address in the allAddress list
- for (const QHostAddress &addr: qAsConst(allAddresses)) {
- if (addr.isLoopback())
- continue;
-
- QString scope = addr.scopeId();
- if (!scope.isEmpty()) {
- QNetworkInterface iface = QNetworkInterface::interfaceFromName(scope);
- qDebug() << "Will bind IPv6 sockets to" << iface;
- return iface;
- }
- }
-
- qWarning("interfaceForGroup(%s) could not find any link-local IPv6 address! "
- "Make sure this test is behind a check of QtNetworkSettings::hasIPv6().",
- qUtf8Printable(multicastGroup.toString()));
- return QNetworkInterface();
- }();
- return ipv6if;
+ return ifaceWithIPv6;
}
bool tst_QUdpSocket::shouldWorkaroundLinuxKernelBug()
@@ -269,15 +255,22 @@ void tst_QUdpSocket::initTestCase()
// ff12:: is temporary, not prefix-based, link-local
r[0] = qToBigEndian(Q_UINT64_C(0xff12) << 48);
QHostAddress llbase(*reinterpret_cast<Q_IPV6ADDR *>(&r));
- for (const QHostAddress &a : qAsConst(allAddresses)) {
+ for (const QHostAddress &a : std::as_const(allAddresses)) {
QString scope = a.scopeId();
if (scope.isEmpty())
continue;
llbase.setScopeId(scope);
linklocalMulticastGroups << llbase;
+ if (!ifaceWithIPv6.isValid()) {
+ // Remember the first interface we've found that has IPv6 so we can
+ // bind non-link-local sockets to it (the first is least likely to
+ // be some weird virtual interface).
+ ifaceWithIPv6 = QNetworkInterface::interfaceFromName(scope);
+ }
}
qDebug() << "Will use multicast groups" << multicastGroup4 << multicastGroup6 << linklocalMulticastGroups;
+ qDebug() << "Will bind IPv6 sockets to" << ifaceWithIPv6;
m_workaroundLinuxKernelBug = shouldWorkaroundLinuxKernelBug();
if (QTestPrivate::isRunningArmOnX86())
@@ -334,7 +327,7 @@ void tst_QUdpSocket::unconnectedServerAndClientTest()
QSignalSpy stateChangedSpy(&serverSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)));
QVERIFY2(serverSocket.bind(), serverSocket.errorString().toLatin1().constData());
- QCOMPARE(stateChangedSpy.count(), 1);
+ QCOMPARE(stateChangedSpy.size(), 1);
const char *message[] = {"Yo mista", "Yo", "Wassap"};
@@ -383,10 +376,11 @@ void tst_QUdpSocket::broadcasting()
const char *message[] = {"Yo mista", "", "Yo", "Wassap"};
QList<QHostAddress> broadcastAddresses;
- foreach (QNetworkInterface iface, QNetworkInterface::allInterfaces()) {
+ const auto ifaces = QNetworkInterface::allInterfaces();
+ for (const QNetworkInterface &iface : ifaces) {
if ((iface.flags() & QNetworkInterface::CanBroadcast)
&& iface.flags() & QNetworkInterface::IsUp) {
- for (int i=0;i<iface.addressEntries().count();i++) {
+ for (int i=0;i<iface.addressEntries().size();i++) {
QHostAddress broadcast = iface.addressEntries().at(i).broadcast();
if (broadcast.protocol() == QAbstractSocket::IPv4Protocol)
broadcastAddresses.append(broadcast);
@@ -411,7 +405,7 @@ void tst_QUdpSocket::broadcasting()
for (int k = 0; k < 4; k++) {
broadcastSocket.writeDatagram(message[i], strlen(message[i]),
QHostAddress::Broadcast, serverPort);
- foreach (QHostAddress addr, broadcastAddresses)
+ for (const QHostAddress &addr : std::as_const(broadcastAddresses))
broadcastSocket.writeDatagram(message[i], strlen(message[i]), addr, serverPort);
}
QTestEventLoop::instance().enterLoop(15);
@@ -431,7 +425,7 @@ void tst_QUdpSocket::broadcasting()
QVERIFY(dgram.isValid());
QByteArray arr = dgram.data();
- QCOMPARE(arr.length(), messageLength);
+ QCOMPARE(arr.size(), messageLength);
arr.resize(messageLength);
QCOMPARE(arr, QByteArray(message[i]));
@@ -491,27 +485,27 @@ void tst_QUdpSocket::loop()
QHostAddress peterAddress = makeNonAny(peter.localAddress());
QHostAddress paulAddress = makeNonAny(paul.localAddress());
- QCOMPARE(peter.writeDatagram(peterMessage.data(), peterMessage.length(),
- paulAddress, paul.localPort()), qint64(peterMessage.length()));
- QCOMPARE(paul.writeDatagram(paulMessage.data(), paulMessage.length(),
- peterAddress, peter.localPort()), qint64(paulMessage.length()));
+ QCOMPARE(peter.writeDatagram(peterMessage.data(), peterMessage.size(),
+ paulAddress, paul.localPort()), qint64(peterMessage.size()));
+ QCOMPARE(paul.writeDatagram(paulMessage.data(), paulMessage.size(),
+ peterAddress, peter.localPort()), qint64(paulMessage.size()));
QVERIFY2(peter.waitForReadyRead(9000), QtNetworkSettings::msgSocketError(peter).constData());
QVERIFY2(paul.waitForReadyRead(9000), QtNetworkSettings::msgSocketError(paul).constData());
- QNetworkDatagram peterDatagram = peter.receiveDatagram(paulMessage.length() * 2);
- QNetworkDatagram paulDatagram = paul.receiveDatagram(peterMessage.length() * 2);
+ QNetworkDatagram peterDatagram = peter.receiveDatagram(paulMessage.size() * 2);
+ QNetworkDatagram paulDatagram = paul.receiveDatagram(peterMessage.size() * 2);
if (success) {
- QCOMPARE(peterDatagram.data().length(), qint64(paulMessage.length()));
- QCOMPARE(paulDatagram.data().length(), qint64(peterMessage.length()));
+ QCOMPARE(peterDatagram.data().size(), qint64(paulMessage.size()));
+ QCOMPARE(paulDatagram.data().size(), qint64(peterMessage.size()));
} else {
// this code path seems to never be executed
- QVERIFY(peterDatagram.data().length() != paulMessage.length());
- QVERIFY(paulDatagram.data().length() != peterMessage.length());
+ QVERIFY(peterDatagram.data().size() != paulMessage.size());
+ QVERIFY(paulDatagram.data().size() != peterMessage.size());
}
- QCOMPARE(peterDatagram.data().left(paulMessage.length()), paulMessage);
- QCOMPARE(paulDatagram.data().left(peterMessage.length()), peterMessage);
+ QCOMPARE(peterDatagram.data().left(paulMessage.size()), paulMessage);
+ QCOMPARE(paulDatagram.data().left(peterMessage.size()), peterMessage);
QCOMPARE(peterDatagram.senderAddress(), paulAddress);
QCOMPARE(paulDatagram.senderAddress(), peterAddress);
@@ -568,27 +562,27 @@ void tst_QUdpSocket::ipv6Loop()
peterPort = peter.localPort();
paulPort = paul.localPort();
- QCOMPARE(peter.writeDatagram(peterMessage.data(), peterMessage.length(), QHostAddress("::1"),
- paulPort), qint64(peterMessage.length()));
- QCOMPARE(paul.writeDatagram(paulMessage.data(), paulMessage.length(),
- QHostAddress("::1"), peterPort), qint64(paulMessage.length()));
+ QCOMPARE(peter.writeDatagram(peterMessage.data(), peterMessage.size(), QHostAddress("::1"),
+ paulPort), qint64(peterMessage.size()));
+ QCOMPARE(paul.writeDatagram(paulMessage.data(), paulMessage.size(),
+ QHostAddress("::1"), peterPort), qint64(paulMessage.size()));
QVERIFY(peter.waitForReadyRead(5000));
QVERIFY(paul.waitForReadyRead(5000));
- QNetworkDatagram peterDatagram = peter.receiveDatagram(paulMessage.length() * 2);
- QNetworkDatagram paulDatagram = paul.receiveDatagram(peterMessage.length() * 2);
+ QNetworkDatagram peterDatagram = peter.receiveDatagram(paulMessage.size() * 2);
+ QNetworkDatagram paulDatagram = paul.receiveDatagram(peterMessage.size() * 2);
if (success) {
- QCOMPARE(peterDatagram.data().length(), qint64(paulMessage.length()));
- QCOMPARE(paulDatagram.data().length(), qint64(peterMessage.length()));
+ QCOMPARE(peterDatagram.data().size(), qint64(paulMessage.size()));
+ QCOMPARE(paulDatagram.data().size(), qint64(peterMessage.size()));
} else {
// this code path seems to never be executed
- QVERIFY(peterDatagram.data().length() != paulMessage.length());
- QVERIFY(paulDatagram.data().length() != peterMessage.length());
+ QVERIFY(peterDatagram.data().size() != paulMessage.size());
+ QVERIFY(paulDatagram.data().size() != peterMessage.size());
}
- QCOMPARE(peterDatagram.data().left(paulMessage.length()), paulMessage);
- QCOMPARE(paulDatagram.data().left(peterMessage.length()), peterMessage);
+ QCOMPARE(peterDatagram.data().left(paulMessage.size()), paulMessage);
+ QCOMPARE(paulDatagram.data().left(peterMessage.size()), peterMessage);
QCOMPARE(peterDatagram.senderAddress(), paulAddress);
QCOMPARE(paulDatagram.senderAddress(), peterAddress);
@@ -616,7 +610,7 @@ void tst_QUdpSocket::dualStack()
QVERIFY(v4Sock.bind(QHostAddress(QHostAddress::AnyIPv4), 0));
//test v4 -> dual
- QCOMPARE((int)v4Sock.writeDatagram(v4Data.constData(), v4Data.length(), QHostAddress(QHostAddress::LocalHost), dualSock.localPort()), v4Data.length());
+ QCOMPARE((int)v4Sock.writeDatagram(v4Data.constData(), v4Data.size(), QHostAddress(QHostAddress::LocalHost), dualSock.localPort()), v4Data.size());
QVERIFY2(dualSock.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(dualSock).constData());
QNetworkDatagram dgram = dualSock.receiveDatagram(100);
QVERIFY(dgram.isValid());
@@ -628,7 +622,7 @@ void tst_QUdpSocket::dualStack()
QCOMPARE(dgram.senderAddress(), makeNonAny(v4Sock.localAddress(), QHostAddress::Null));
if (dgram.destinationPort() != -1) {
QCOMPARE(dgram.destinationPort(), int(dualSock.localPort()));
- QVERIFY(dgram.destinationAddress().isEqual(dualSock.localAddress()));
+ QVERIFY(dgram.destinationAddress().isEqual(makeNonAny(dualSock.localAddress(), QHostAddress::LocalHost)));
} else {
qInfo("Getting IPv4 destination address failed.");
}
@@ -639,7 +633,7 @@ void tst_QUdpSocket::dualStack()
QVERIFY(v6Sock.bind(QHostAddress(QHostAddress::AnyIPv6), 0));
//test v6 -> dual
- QCOMPARE((int)v6Sock.writeDatagram(v6Data.constData(), v6Data.length(), QHostAddress(QHostAddress::LocalHostIPv6), dualSock.localPort()), v6Data.length());
+ QCOMPARE((int)v6Sock.writeDatagram(v6Data.constData(), v6Data.size(), QHostAddress(QHostAddress::LocalHostIPv6), dualSock.localPort()), v6Data.size());
QVERIFY2(dualSock.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(dualSock).constData());
dgram = dualSock.receiveDatagram(100);
QVERIFY(dgram.isValid());
@@ -650,7 +644,7 @@ void tst_QUdpSocket::dualStack()
QCOMPARE(dgram.destinationAddress(), makeNonAny(dualSock.localAddress(), QHostAddress::LocalHostIPv6));
//test dual -> v6
- QCOMPARE((int)dualSock.writeDatagram(dualData.constData(), dualData.length(), QHostAddress(QHostAddress::LocalHostIPv6), v6Sock.localPort()), dualData.length());
+ QCOMPARE((int)dualSock.writeDatagram(dualData.constData(), dualData.size(), QHostAddress(QHostAddress::LocalHostIPv6), v6Sock.localPort()), dualData.size());
QVERIFY2(v6Sock.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(v6Sock).constData());
dgram = v6Sock.receiveDatagram(100);
QVERIFY(dgram.isValid());
@@ -662,7 +656,7 @@ void tst_QUdpSocket::dualStack()
}
//test dual -> v4
- QCOMPARE((int)dualSock.writeDatagram(dualData.constData(), dualData.length(), QHostAddress(QHostAddress::LocalHost), v4Sock.localPort()), dualData.length());
+ QCOMPARE((int)dualSock.writeDatagram(dualData.constData(), dualData.size(), QHostAddress(QHostAddress::LocalHost), v4Sock.localPort()), dualData.size());
QVERIFY2(v4Sock.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(v4Sock).constData());
dgram = v4Sock.receiveDatagram(100);
QVERIFY(dgram.isValid());
@@ -701,19 +695,19 @@ void tst_QUdpSocket::dualStackAutoBinding()
//test an autobound socket can send to both v4 and v6 addresses (v4 first)
QUdpSocket dualSock;
- QCOMPARE((int)dualSock.writeDatagram(dualData.constData(), dualData.length(), QHostAddress(QHostAddress::LocalHost), v4Sock.localPort()), dualData.length());
+ QCOMPARE((int)dualSock.writeDatagram(dualData.constData(), dualData.size(), QHostAddress(QHostAddress::LocalHost), v4Sock.localPort()), dualData.size());
QVERIFY2(v4Sock.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(v4Sock).constData());
buffer.reserve(100);
size = v4Sock.readDatagram(buffer.data(), 100, &from, &port);
- QCOMPARE((int)size, dualData.length());
+ QCOMPARE((int)size, dualData.size());
buffer.resize(size);
QCOMPARE(buffer, dualData);
- QCOMPARE((int)dualSock.writeDatagram(dualData.constData(), dualData.length(), QHostAddress(QHostAddress::LocalHostIPv6), v6Sock.localPort()), dualData.length());
+ QCOMPARE((int)dualSock.writeDatagram(dualData.constData(), dualData.size(), QHostAddress(QHostAddress::LocalHostIPv6), v6Sock.localPort()), dualData.size());
QVERIFY2(v6Sock.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(v6Sock).constData());
buffer.reserve(100);
size = v6Sock.readDatagram(buffer.data(), 100, &from, &port);
- QCOMPARE((int)size, dualData.length());
+ QCOMPARE((int)size, dualData.size());
buffer.resize(size);
QCOMPARE(buffer, dualData);
}
@@ -722,19 +716,19 @@ void tst_QUdpSocket::dualStackAutoBinding()
//test an autobound socket can send to both v4 and v6 addresses (v6 first)
QUdpSocket dualSock;
- QCOMPARE((int)dualSock.writeDatagram(dualData.constData(), dualData.length(), QHostAddress(QHostAddress::LocalHostIPv6), v6Sock.localPort()), dualData.length());
+ QCOMPARE((int)dualSock.writeDatagram(dualData.constData(), dualData.size(), QHostAddress(QHostAddress::LocalHostIPv6), v6Sock.localPort()), dualData.size());
QVERIFY2(v6Sock.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(v6Sock).constData());
buffer.reserve(100);
size = v6Sock.readDatagram(buffer.data(), 100, &from, &port);
- QCOMPARE((int)size, dualData.length());
+ QCOMPARE((int)size, dualData.size());
buffer.resize(size);
QCOMPARE(buffer, dualData);
- QCOMPARE((int)dualSock.writeDatagram(dualData.constData(), dualData.length(), QHostAddress(QHostAddress::LocalHost), v4Sock.localPort()), dualData.length());
+ QCOMPARE((int)dualSock.writeDatagram(dualData.constData(), dualData.size(), QHostAddress(QHostAddress::LocalHost), v4Sock.localPort()), dualData.size());
QVERIFY2(v4Sock.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(v4Sock).constData());
buffer.reserve(100);
size = v4Sock.readDatagram(buffer.data(), 100, &from, &port);
- QCOMPARE((int)size, dualData.length());
+ QCOMPARE((int)size, dualData.size());
buffer.resize(size);
QCOMPARE(buffer, dualData);
}
@@ -755,7 +749,7 @@ void tst_QUdpSocket::dualStackNoIPv4onV6only()
QVERIFY(v6Sock.bind(QHostAddress(QHostAddress::AnyIPv6), 0));
//test v4 -> v6 (should not be received as this is a v6 only socket)
- QCOMPARE((int)v4Sock.writeDatagram(v4Data.constData(), v4Data.length(), QHostAddress(QHostAddress::LocalHost), v6Sock.localPort()), v4Data.length());
+ QCOMPARE((int)v4Sock.writeDatagram(v4Data.constData(), v4Data.size(), QHostAddress(QHostAddress::LocalHost), v6Sock.localPort()), v4Data.size());
QVERIFY(!v6Sock.waitForReadyRead(1000));
}
@@ -875,17 +869,17 @@ void tst_QUdpSocket::writeDatagram()
#if defined (Q_OS_HPUX)
QSKIP("HP-UX 11.11 on hai (PA-RISC 64) truncates too long datagrams.");
#endif
- QCOMPARE(bytesspy.count(), 0);
- QCOMPARE(errorspy.count(), 1);
+ QCOMPARE(bytesspy.size(), 0);
+ QCOMPARE(errorspy.size(), 1);
QCOMPARE(*static_cast<const int *>(errorspy.at(0).at(0).constData()),
int(QUdpSocket::DatagramTooLargeError));
QCOMPARE(client.error(), QUdpSocket::DatagramTooLargeError);
break;
}
- QCOMPARE(bytesspy.count(), 1);
+ QCOMPARE(bytesspy.size(), 1);
QCOMPARE(*static_cast<const qint64 *>(bytesspy.at(0).at(0).constData()),
qint64(i * 1024));
- QCOMPARE(errorspy.count(), 0);
+ QCOMPARE(errorspy.size(), 0);
if (!server.waitForReadyRead(5000))
QSKIP(QString("UDP packet lost at size %1, unable to complete the test.").arg(i * 1024).toLatin1().data());
QCOMPARE(server.pendingDatagramSize(), qint64(i * 1024));
@@ -998,7 +992,7 @@ void tst_QUdpSocket::writeDatagramToNonExistingPeer()
QVERIFY(sUdp.bind());
QCOMPARE(sUdp.writeDatagram("", 1, peerAddress, peerPort), qint64(1));
QTestEventLoop::instance().enterLoop(1);
- QCOMPARE(sReadyReadSpy.count(), 0);
+ QCOMPARE(sReadyReadSpy.size(), 0);
}
void tst_QUdpSocket::writeToNonExistingPeer_data()
@@ -1041,8 +1035,8 @@ void tst_QUdpSocket::writeToNonExistingPeer()
// the third one will succeed...
QCOMPARE(sConnected.write("", 1), qint64(1));
QTestEventLoop::instance().enterLoop(1);
- QCOMPARE(sConnectedReadyReadSpy.count(), 0);
- QCOMPARE(sConnectedErrorSpy.count(), 1);
+ QCOMPARE(sConnectedReadyReadSpy.size(), 0);
+ QCOMPARE(sConnectedErrorSpy.size(), 1);
QCOMPARE(int(sConnected.error()), int(QUdpSocket::ConnectionRefusedError));
// we should now get a read error
@@ -1241,11 +1235,12 @@ void tst_QUdpSocket::multicastTtlOption_data()
QTest::addColumn<int>("ttl");
QTest::addColumn<int>("expected");
- QList<QHostAddress> addresses;
- addresses += QHostAddress(QHostAddress::AnyIPv4);
- addresses += QHostAddress(QHostAddress::AnyIPv6);
+ const QHostAddress addresses[] = {
+ QHostAddress(QHostAddress::AnyIPv4),
+ QHostAddress(QHostAddress::AnyIPv6),
+ };
- foreach (const QHostAddress &address, addresses) {
+ for (const QHostAddress &address : addresses) {
const QByteArray addressB = address.toString().toLatin1();
QTest::newRow((addressB + " 0").constData()) << address << 0 << 0;
QTest::newRow((addressB + " 1").constData()) << address << 1 << 1;
@@ -1287,11 +1282,12 @@ void tst_QUdpSocket::multicastLoopbackOption_data()
QTest::addColumn<int>("loopback");
QTest::addColumn<int>("expected");
- QList<QHostAddress> addresses;
- addresses += QHostAddress(QHostAddress::AnyIPv4);
- addresses += QHostAddress(QHostAddress::AnyIPv6);
+ const QHostAddress addresses[] = {
+ QHostAddress(QHostAddress::AnyIPv4),
+ QHostAddress(QHostAddress::AnyIPv6),
+ };
- foreach (const QHostAddress &address, addresses) {
+ for (const QHostAddress &address : addresses) {
const QByteArray addressB = address.toString().toLatin1();
QTest::newRow((addressB + " 0").constData()) << address << 0 << 0;
QTest::newRow((addressB + " 1").constData()) << address << 1 << 1;
@@ -1334,7 +1330,7 @@ void tst_QUdpSocket::multicastJoinBeforeBind_data()
QTest::newRow("valid ipv4 group address") << multicastGroup4;
QTest::newRow("invalid ipv4 group address") << QHostAddress(QHostAddress::Broadcast);
QTest::newRow("valid ipv6 group address") << multicastGroup6;
- for (const QHostAddress &a : qAsConst(linklocalMulticastGroups))
+ for (const QHostAddress &a : std::as_const(linklocalMulticastGroups))
QTest::addRow("valid ipv6 %s-link group address", a.scopeId().toLatin1().constData()) << a;
QTest::newRow("invalid ipv6 group address") << QHostAddress(QHostAddress::AnyIPv6);
}
@@ -1354,7 +1350,7 @@ void tst_QUdpSocket::multicastLeaveAfterClose_data()
QTest::addColumn<QHostAddress>("groupAddress");
QTest::newRow("ipv4") << multicastGroup4;
QTest::newRow("ipv6") << multicastGroup6;
- for (const QHostAddress &a : qAsConst(linklocalMulticastGroups))
+ for (const QHostAddress &a : std::as_const(linklocalMulticastGroups))
QTest::addRow("ipv6-link-%s", a.scopeId().toLatin1().constData()) << a;
}
@@ -1391,11 +1387,12 @@ void tst_QUdpSocket::setMulticastInterface_data()
{
QTest::addColumn<QNetworkInterface>("iface");
QTest::addColumn<QHostAddress>("address");
- QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
- foreach (const QNetworkInterface &iface, interfaces) {
+ const QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
+ for (const QNetworkInterface &iface : interfaces) {
if ((iface.flags() & QNetworkInterface::IsUp) == 0)
continue;
- foreach (const QNetworkAddressEntry &entry, iface.addressEntries()) {
+ const auto entries = iface.addressEntries();
+ for (const QNetworkAddressEntry &entry : entries) {
const QByteArray testName = iface.name().toLatin1() + ':' + entry.ip().toString().toLatin1();
QTest::newRow(testName.constData()) << iface << entry.ip();
}
@@ -1448,13 +1445,13 @@ void tst_QUdpSocket::multicast_data()
QTest::newRow("valid bind, group ipv4 address") << anyAddress << true << groupAddress << true;
QTest::newRow("valid bind, invalid group ipv4 address") << anyAddress << true << anyAddress << false;
QTest::newRow("valid bind, group ipv6 address") << any6Address << true << group6Address << true;
- for (const QHostAddress &a : qAsConst(linklocalMulticastGroups))
+ for (const QHostAddress &a : std::as_const(linklocalMulticastGroups))
QTest::addRow("valid bind, %s-link group ipv6 address", a.scopeId().toLatin1().constData())
<< any6Address << true << a << true;
QTest::newRow("valid bind, invalid group ipv6 address") << any6Address << true << any6Address << false;
QTest::newRow("dual bind, group ipv4 address") << dualAddress << true << groupAddress << false;
QTest::newRow("dual bind, group ipv6 address") << dualAddress << true << group6Address << true;
- for (const QHostAddress &a : qAsConst(linklocalMulticastGroups))
+ for (const QHostAddress &a : std::as_const(linklocalMulticastGroups))
QTest::addRow("dual bind, %s-link group ipv6 address", a.scopeId().toLatin1().constData())
<< dualAddress << true << a << true;
}
@@ -1499,15 +1496,16 @@ void tst_QUdpSocket::multicast()
if (!joinResult)
return;
- QList<QByteArray> datagrams = QList<QByteArray>()
- << QByteArray("0123")
- << QByteArray("4567")
- << QByteArray("89ab")
- << QByteArray("cdef");
+ const QByteArray datagrams[] = {
+ "0123"_ba,
+ "4567"_ba,
+ "89ab"_ba,
+ "cdef"_ba,
+ };
QUdpSocket sender;
sender.bind();
- foreach (const QByteArray &datagram, datagrams) {
+ for (const QByteArray &datagram : datagrams) {
QNetworkDatagram dgram(datagram, groupAddress, receiver.localPort());
dgram.setInterfaceIndex(interfaceForGroup(groupAddress).index());
QCOMPARE(int(sender.writeDatagram(dgram)),
@@ -1550,7 +1548,7 @@ void tst_QUdpSocket::echo()
{
QFETCH(bool, connect);
QHostInfo info = QHostInfo::fromName(QtNetworkSettings::echoServerName());
- QVERIFY(info.addresses().count());
+ QVERIFY(info.addresses().size());
QHostAddress remote = info.addresses().first();
QUdpSocket sock;
@@ -1577,7 +1575,7 @@ void tst_QUdpSocket::echo()
in = sock.read(sock.pendingDatagramSize());
} else {
in.resize(sock.pendingDatagramSize());
- sock.readDatagram(in.data(), in.length(), &from, &port);
+ sock.readDatagram(in.data(), in.size(), &from, &port);
}
if (in==out)
successes++;
@@ -1600,7 +1598,8 @@ void tst_QUdpSocket::linkLocalIPv6()
QList <QHostAddress> addresses;
QSet <QString> scopes;
QHostAddress localMask("fe80::");
- foreach (const QNetworkInterface& iface, QNetworkInterface::allInterfaces()) {
+ const auto ifaces = QNetworkInterface::allInterfaces();
+ for (const QNetworkInterface &iface : ifaces) {
//Windows preallocates link local addresses to interfaces that are down.
//These may or may not work depending on network driver
if (iface.flags() & QNetworkInterface::IsUp) {
@@ -1615,7 +1614,8 @@ void tst_QUdpSocket::linkLocalIPv6()
continue;
#endif
- foreach (QNetworkAddressEntry addressEntry, iface.addressEntries()) {
+ const auto entries = iface.addressEntries();
+ for (const QNetworkAddressEntry &addressEntry : entries) {
QHostAddress addr(addressEntry.ip());
if (!addr.scopeId().isEmpty() && addr.isInSubnet(localMask, 64)) {
scopes << addr.scopeId();
@@ -1630,7 +1630,7 @@ void tst_QUdpSocket::linkLocalIPv6()
QList <QUdpSocket*> sockets;
quint16 port = 0;
- foreach (const QHostAddress& addr, addresses) {
+ for (const QHostAddress &addr : std::as_const(addresses)) {
QUdpSocket *s = new QUdpSocket;
QVERIFY2(s->bind(addr, port), addr.toString().toLatin1()
+ '/' + QByteArray::number(port) + ": " + qPrintable(s->errorString()));
@@ -1639,7 +1639,7 @@ void tst_QUdpSocket::linkLocalIPv6()
}
QByteArray testData("hello");
- foreach (QUdpSocket *s, sockets) {
+ for (QUdpSocket *s : std::as_const(sockets)) {
QUdpSocket neutral;
QVERIFY(neutral.bind(QHostAddress(QHostAddress::AnyIPv6)));
QSignalSpy neutralReadSpy(&neutral, SIGNAL(readyRead()));
@@ -1647,27 +1647,26 @@ void tst_QUdpSocket::linkLocalIPv6()
QSignalSpy spy(s, SIGNAL(readyRead()));
QVERIFY(s->writeDatagram(testData, s->localAddress(), neutral.localPort()));
- QTRY_VERIFY(neutralReadSpy.count() > 0); //note may need to accept a firewall prompt
+ QTRY_VERIFY(neutralReadSpy.size() > 0); //note may need to accept a firewall prompt
- QNetworkDatagram dgram = neutral.receiveDatagram(testData.length() * 2);
+ QNetworkDatagram dgram = neutral.receiveDatagram(testData.size() * 2);
QVERIFY(dgram.isValid());
QCOMPARE(dgram.senderAddress(), s->localAddress());
QCOMPARE(dgram.senderPort(), int(s->localPort()));
QCOMPARE(dgram.destinationAddress(), s->localAddress());
QCOMPARE(dgram.destinationPort(), int(neutral.localPort()));
- QCOMPARE(dgram.data().length(), testData.length());
+ QCOMPARE(dgram.data().size(), testData.size());
QCOMPARE(dgram.data(), testData);
QVERIFY(neutral.writeDatagram(dgram.makeReply(testData)));
- QTRY_VERIFY(spy.count() > 0); //note may need to accept a firewall prompt
+ QTRY_VERIFY(spy.size() > 0); //note may need to accept a firewall prompt
- dgram = s->receiveDatagram(testData.length() * 2);
+ dgram = s->receiveDatagram(testData.size() * 2);
QCOMPARE(dgram.data(), testData);
//sockets bound to other interfaces shouldn't have received anything
- foreach (QUdpSocket *s2, sockets) {
+ for (QUdpSocket *s2 : std::as_const(sockets))
QCOMPARE((int)s2->bytesAvailable(), 0);
- }
//Sending to the same address with different scope should normally fail
//However it will pass if there is a route between two interfaces,
@@ -1686,7 +1685,8 @@ void tst_QUdpSocket::linkLocalIPv4()
QList <QHostAddress> addresses;
QHostAddress localMask("169.254.0.0");
- foreach (const QNetworkInterface& iface, QNetworkInterface::allInterfaces()) {
+ const auto ifaces = QNetworkInterface::allInterfaces();
+ for (const QNetworkInterface &iface : ifaces) {
//Windows preallocates link local addresses to interfaces that are down.
//These may or may not work depending on network driver (they do not work for the Bluetooth PAN driver)
if (iface.flags() & QNetworkInterface::IsUp) {
@@ -1700,7 +1700,8 @@ void tst_QUdpSocket::linkLocalIPv4()
if (iface.name().startsWith("utun"))
continue;
#endif
- foreach (QNetworkAddressEntry addr, iface.addressEntries()) {
+ const auto entries = iface.addressEntries();
+ for (const QNetworkAddressEntry &addr : entries) {
if (addr.ip().isInSubnet(localMask, 16)) {
addresses << addr.ip();
qDebug() << "Found IPv4 link local address" << addr.ip();
@@ -1713,7 +1714,7 @@ void tst_QUdpSocket::linkLocalIPv4()
QList <QUdpSocket*> sockets;
quint16 port = 0;
- foreach (const QHostAddress& addr, addresses) {
+ for (const QHostAddress &addr : std::as_const(addresses)) {
QUdpSocket *s = new QUdpSocket;
QVERIFY2(s->bind(addr, port), qPrintable(s->errorString()));
port = s->localPort(); //bind same port, different networks
@@ -1724,15 +1725,15 @@ void tst_QUdpSocket::linkLocalIPv4()
QVERIFY(neutral.bind(QHostAddress(QHostAddress::AnyIPv4)));
QByteArray testData("hello");
- foreach (QUdpSocket *s, sockets) {
+ for (QUdpSocket *s : std::as_const(sockets)) {
QVERIFY(s->writeDatagram(testData, s->localAddress(), neutral.localPort()));
QVERIFY2(neutral.waitForReadyRead(10000), QtNetworkSettings::msgSocketError(neutral).constData());
- QNetworkDatagram dgram = neutral.receiveDatagram(testData.length() * 2);
+ QNetworkDatagram dgram = neutral.receiveDatagram(testData.size() * 2);
QVERIFY(dgram.isValid());
QCOMPARE(dgram.senderAddress(), s->localAddress());
QCOMPARE(dgram.senderPort(), int(s->localPort()));
- QCOMPARE(dgram.data().length(), testData.length());
+ QCOMPARE(dgram.data().size(), testData.size());
QCOMPARE(dgram.data(), testData);
// Unlike for IPv6 with IPV6_PKTINFO, IPv4 has no standardized way of
@@ -1751,14 +1752,13 @@ void tst_QUdpSocket::linkLocalIPv4()
QVERIFY(neutral.writeDatagram(dgram.makeReply(testData)));
QVERIFY2(s->waitForReadyRead(10000), QtNetworkSettings::msgSocketError(*s).constData());
- dgram = s->receiveDatagram(testData.length() * 2);
+ dgram = s->receiveDatagram(testData.size() * 2);
QVERIFY(dgram.isValid());
QCOMPARE(dgram.data(), testData);
//sockets bound to other interfaces shouldn't have received anything
- foreach (QUdpSocket *s2, sockets) {
+ for (QUdpSocket *s2 : std::as_const(sockets))
QCOMPARE((int)s2->bytesAvailable(), 0);
- }
}
qDeleteAll(sockets);
}
@@ -1786,7 +1786,7 @@ void tst_QUdpSocket::readyRead()
QTest::qWait(100);
// make sure only one signal was emitted
- QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.size(), 1);
QVERIFY(receiver.hasPendingDatagrams());
#ifdef RELIABLE_BYTES_AVAILABLE
QCOMPARE(receiver.bytesAvailable(), qint64(2));
@@ -1798,7 +1798,7 @@ void tst_QUdpSocket::readyRead()
// no new signal should be emitted because we haven't read the first datagram yet
QTest::qWait(100);
- QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.size(), 1);
QVERIFY(receiver.hasPendingDatagrams());
QVERIFY(receiver.bytesAvailable() >= 1); // most likely is 1, but it could be 1 + 2 in the future
QCOMPARE(receiver.pendingDatagramSize(), qint64(2));
@@ -1810,7 +1810,7 @@ void tst_QUdpSocket::readyRead()
// write a new datagram and ensure the signal is emitted now
sender.writeDatagram("abc", makeNonAny(receiver.localAddress()), port);
QTest::qWait(100);
- QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy.size(), 2);
QVERIFY(receiver.hasPendingDatagrams());
#ifdef RELIABLE_BYTES_AVAILABLE
QCOMPARE(receiver.bytesAvailable(), qint64(3));
@@ -1890,7 +1890,7 @@ void tst_QUdpSocket::asyncReadDatagram()
QTestEventLoop::instance().enterLoop(1);
QVERIFY(!QTestEventLoop::instance().timeout());
- QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy.size(), 2);
delete m_asyncSender;
delete m_asyncReceiver;
@@ -1908,5 +1908,78 @@ void tst_QUdpSocket::writeInHostLookupState()
QVERIFY(!socket.putChar('0'));
}
+void tst_QUdpSocket::readyReadConnectionThrottling()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+ using namespace std::chrono_literals;
+
+ // QTBUG-105871:
+ // We have some signal/slot connection throttling in QAbstractSocket, but it
+ // was caring about the bytes, not about the datagrams.
+ // Test that we don't disable read notifications until we have at least one
+ // datagram available. Otherwise our good users who use the datagram APIs
+ // can get into scenarios where they no longer get the readyRead signal
+ // unless they call a read function once in a while.
+
+ QUdpSocket receiver;
+ QVERIFY(receiver.bind(QHostAddress(QHostAddress::LocalHost), 0));
+
+ QSemaphore semaphore;
+
+ // Repro-ing deterministically eludes me, so we are bruteforcing it:
+ // The thread acts as a remote sender, flooding the receiver with datagrams,
+ // and at some point the receiver would get into the broken state mentioned
+ // earlier.
+ std::unique_ptr<QThread> thread(QThread::create([&semaphore, port = receiver.localPort()]() {
+ QUdpSocket sender;
+ sender.connectToHost(QHostAddress(QHostAddress::LocalHost), port);
+ QCOMPARE(sender.state(), QUdpSocket::ConnectedState);
+
+ constexpr qsizetype PayloadSize = 242;
+ const QByteArray payload(PayloadSize, 'a');
+
+ semaphore.acquire(); // Wait for main thread to be ready
+ while (true) {
+ // We send 100 datagrams at a time, then sleep.
+ // This is mostly to let the main thread catch up between bursts so
+ // it doesn't get stuck in the loop.
+ for (int i = 0; i < 100; ++i) {
+ [[maybe_unused]]
+ qsizetype sent = sender.write(payload);
+ Q_ASSERT(sent > 0);
+ }
+ if (QThread::currentThread()->isInterruptionRequested())
+ break;
+ QThread::sleep(20ms);
+ }
+ }));
+ thread->start();
+ auto threadStopAndWaitGuard = qScopeGuard([&thread] {
+ thread->requestInterruption();
+ thread->quit();
+ thread->wait();
+ });
+
+ qsizetype count = 0;
+ QObject::connect(&receiver, &QUdpSocket::readyRead, &receiver,
+ [&] {
+ while (receiver.hasPendingDatagrams()) {
+ receiver.readDatagram(nullptr, 0);
+ ++count;
+ }
+ // If this prints `false, xxxx` we were pretty much guaranteed
+ // that we would not get called again:
+ // qDebug() << receiver.hasPendingDatagrams() << receiver.bytesAvailable();
+ },
+ Qt::QueuedConnection);
+
+ semaphore.release();
+ constexpr qsizetype MaxCount = 500;
+ QVERIFY2(QTest::qWaitFor([&] { return count >= MaxCount; }, 10s),
+ QByteArray::number(count).constData());
+}
+
QTEST_MAIN(tst_QUdpSocket)
#include "tst_qudpsocket.moc"
diff --git a/tests/auto/network/socket/qudpsocket/udpServer/CMakeLists.txt b/tests/auto/network/socket/qudpsocket/udpServer/CMakeLists.txt
index 70407d72b3..7dd7f2ba5d 100644
--- a/tests/auto/network/socket/qudpsocket/udpServer/CMakeLists.txt
+++ b/tests/auto/network/socket/qudpsocket/udpServer/CMakeLists.txt
@@ -1,14 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from udpServer.pro.
-
#####################################################################
## udpServer Binary:
#####################################################################
qt_internal_add_executable(udpServer
- OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/./" # special case
+ OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/./"
SOURCES
main.cpp
LIBRARIES
diff --git a/tests/auto/network/socket/qudpsocket/udpServer/main.cpp b/tests/auto/network/socket/qudpsocket/udpServer/main.cpp
index 72bbcfa71e..ba5bb3c0d0 100644
--- a/tests/auto/network/socket/qudpsocket/udpServer/main.cpp
+++ b/tests/auto/network/socket/qudpsocket/udpServer/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtNetwork>
class Server : public QObject
diff --git a/tests/auto/network/ssl/CMakeLists.txt b/tests/auto/network/ssl/CMakeLists.txt
index 8521d7308a..b11b15b6ba 100644
--- a/tests/auto/network/ssl/CMakeLists.txt
+++ b/tests/auto/network/ssl/CMakeLists.txt
@@ -1,13 +1,11 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from ssl.pro.
-
add_subdirectory(qpassworddigestor)
-add_subdirectory(qsslcertificate)
-add_subdirectory(qsslcipher)
-add_subdirectory(qsslellipticcurve)
if(QT_FEATURE_ssl)
+ add_subdirectory(qsslcertificate)
+ add_subdirectory(qsslcipher)
+ add_subdirectory(qsslellipticcurve)
add_subdirectory(qsslkey)
add_subdirectory(qsslerror)
endif()
@@ -15,7 +13,7 @@ if(QT_FEATURE_private_tests AND QT_FEATURE_ssl)
add_subdirectory(qsslsocket)
add_subdirectory(qsslsocket_onDemandCertificates_member)
add_subdirectory(qsslsocket_onDemandCertificates_static)
-# add_subdirectory(qasn1element)
+ add_subdirectory(qasn1element)
add_subdirectory(qssldiffiehellmanparameters)
add_subdirectory(qsslserver)
endif()
diff --git a/tests/auto/network/ssl/qasn1element/CMakeLists.txt b/tests/auto/network/ssl/qasn1element/CMakeLists.txt
index e9ad1d8c17..7b01a0b22d 100644
--- a/tests/auto/network/ssl/qasn1element/CMakeLists.txt
+++ b/tests/auto/network/ssl/qasn1element/CMakeLists.txt
@@ -1,16 +1,26 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qasn1element.pro.
-
#####################################################################
## tst_qasn1element Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qasn1element LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qasn1element
SOURCES
tst_qasn1element.cpp
+ ../../../../../src/plugins/tls/shared/qasn1element_p.h
+ ../../../../../src/plugins/tls/shared/qasn1element.cpp
+ INCLUDE_DIRECTORIES
+ ../../../../../src/plugins/tls/shared
LIBRARIES
+ Qt::Core
Qt::Network
Qt::NetworkPrivate
+ BUNDLE_ANDROID_OPENSSL_LIBS
)
diff --git a/tests/auto/network/ssl/qasn1element/tst_qasn1element.cpp b/tests/auto/network/ssl/qasn1element/tst_qasn1element.cpp
index a788114daa..a54f0bd9d8 100644
--- a/tests/auto/network/ssl/qasn1element/tst_qasn1element.cpp
+++ b/tests/auto/network/ssl/qasn1element/tst_qasn1element.cpp
@@ -1,9 +1,12 @@
// Copyright (C) 2014 Jeremy Lainé <jeremy.laine@m4x.org>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+#include "qasn1element_p.h"
#include <QTest>
-#include "private/qasn1element_p.h"
+
+#include <QtCore/QDateTime>
+#include <QtCore/QTimeZone>
class tst_QAsn1Element : public QObject
{
@@ -102,7 +105,7 @@ void tst_QAsn1Element::dateTime_data()
<< QDateTime();
QTest::newRow("UTCTime - 070417074026Z")
<< QByteArray::fromHex("170d3037303431373037343032365a")
- << QDateTime(QDate(2007, 4, 17), QTime(7, 40, 26), Qt::UTC);
+ << QDateTime(QDate(2007, 4, 17), QTime(7, 40, 26), QTimeZone::UTC);
QTest::newRow("UTCTime - bad length")
<< QByteArray::fromHex("170c30373034313730373430325a")
<< QDateTime();
@@ -111,16 +114,19 @@ void tst_QAsn1Element::dateTime_data()
<< QDateTime();
QTest::newRow("UTCTime - year 1950")
<< QByteArray::fromHex("170d3530313232343035353530305a")
- << QDateTime(QDate(1950, 12, 24), QTime(5, 55), Qt::UTC);
+ << QDateTime(QDate(1950, 12, 24), QTime(5, 55), QTimeZone::UTC);
QTest::newRow("UTCTime - year 1999")
<< QByteArray::fromHex("170d3939313232343035353530305a")
- << QDateTime(QDate(1999, 12, 24), QTime(5, 55), Qt::UTC);
+ << QDateTime(QDate(1999, 12, 24), QTime(5, 55), QTimeZone::UTC);
QTest::newRow("UTCTime - year 2000")
<< QByteArray::fromHex("170d3030313232343035353530305a")
- << QDateTime(QDate(2000, 12, 24), QTime(5, 55), Qt::UTC);
+ << QDateTime(QDate(2000, 12, 24), QTime(5, 55), QTimeZone::UTC);
+ QTest::newRow("UTCTime - leap day year 2000")
+ << QByteArray::fromHex("170d3030303232393035353530305a")
+ << QDateTime(QDate(2000, 2, 29), QTime(5, 55), QTimeZone::UTC);
QTest::newRow("UTCTime - year 2049")
<< QByteArray::fromHex("170d3439313232343035353530305a")
- << QDateTime(QDate(2049, 12, 24), QTime(5, 55), Qt::UTC);
+ << QDateTime(QDate(2049, 12, 24), QTime(5, 55), QTimeZone::UTC);
QTest::newRow("UTCTime - invalid year ('-9')")
<< QByteArray::fromHex("170d2d39313232343035353530305a")
<< QDateTime();
@@ -138,7 +144,7 @@ void tst_QAsn1Element::dateTime_data()
<< QDateTime();
QTest::newRow("GeneralizedTime - 20510829095341Z")
<< QByteArray::fromHex("180f32303531303832393039353334315a")
- << QDateTime(QDate(2051, 8, 29), QTime(9, 53, 41), Qt::UTC);
+ << QDateTime(QDate(2051, 8, 29), QTime(9, 53, 41), QTimeZone::UTC);
QTest::newRow("GeneralizedTime - bad length")
<< QByteArray::fromHex("180e323035313038323930393533345a")
<< QDateTime();
diff --git a/tests/auto/network/ssl/qdtls/CMakeLists.txt b/tests/auto/network/ssl/qdtls/CMakeLists.txt
index bcb077a49f..1d5eef094c 100644
--- a/tests/auto/network/ssl/qdtls/CMakeLists.txt
+++ b/tests/auto/network/ssl/qdtls/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qdtls.pro.
-
#####################################################################
## tst_qdtls Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qdtls LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
list(APPEND test_data "certs")
@@ -16,13 +20,5 @@ qt_internal_add_test(tst_qdtls
LIBRARIES
Qt::NetworkPrivate
TESTDATA ${test_data}
+ BUNDLE_ANDROID_OPENSSL_LIBS
)
-
-## Scopes:
-#####################################################################
-
-#### Keys ignored in scope 3:.:.:qdtls.pro:(CMAKE_BUILD_TYPE STREQUAL Debug):
-# DESTDIR = "debug"
-
-#### Keys ignored in scope 4:.:.:qdtls.pro:else:
-# DESTDIR = "release"
diff --git a/tests/auto/network/ssl/qdtls/tst_qdtls.cpp b/tests/auto/network/ssl/qdtls/tst_qdtls.cpp
index 4ec4c1ef81..372ee3a181 100644
--- a/tests/auto/network/ssl/qdtls/tst_qdtls.cpp
+++ b/tests/auto/network/ssl/qdtls/tst_qdtls.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
#include <QTestEventLoop>
@@ -26,6 +26,8 @@
#include <algorithm>
+using namespace std::chrono_literals;
+
QT_BEGIN_NAMESPACE
namespace
@@ -127,8 +129,8 @@ private:
DtlsPtr clientCrypto;
QTestEventLoop testLoop;
- const int handshakeTimeoutMS = 5000;
- const int dataExchangeTimeoutMS = 1000;
+ static constexpr auto HandshakeTimeout = 5s;
+ static constexpr auto DataExchangeTimeout = 1s;
const QByteArray presharedKey = "DEADBEEFDEADBEEF";
QString certDirPath;
@@ -413,7 +415,7 @@ void tst_QDtls::handshake()
QDTLS_VERIFY_NO_ERROR(clientCrypto);
QCOMPARE(clientCrypto->handshakeState(), QDtls::HandshakeInProgress);
- testLoop.enterLoopMSecs(handshakeTimeoutMS);
+ testLoop.enterLoop(HandshakeTimeout);
QVERIFY(!testLoop.timeout());
@@ -473,7 +475,7 @@ void tst_QDtls::handshakeWithRetransmission()
// client will re-transmit in 1s., the first part of 'ServerHello' to be
// dropped, the client then will re-transmit after another 2 s. Thus it's ~3.
// We err on safe side and double our (already quite generous) 5s.
- testLoop.enterLoopMSecs(handshakeTimeoutMS * 2);
+ testLoop.enterLoop(HandshakeTimeout * 2);
QVERIFY(!testLoop.timeout());
QDTLS_VERIFY_HANDSHAKE_SUCCESS(serverCrypto);
@@ -496,7 +498,7 @@ void tst_QDtls::sessionCipher()
QVERIFY(clientCrypto->setPeer(serverAddress, serverPort, hostName));
QVERIFY(clientCrypto->doHandshake(&clientSocket));
- testLoop.enterLoopMSecs(handshakeTimeoutMS);
+ testLoop.enterLoop(HandshakeTimeout);
QVERIFY(!testLoop.timeout());
QDTLS_VERIFY_HANDSHAKE_SUCCESS(clientCrypto);
@@ -559,7 +561,7 @@ void tst_QDtls::cipherPreferences()
QVERIFY(clientCrypto->doHandshake(&clientSocket));
QDTLS_VERIFY_NO_ERROR(clientCrypto);
- testLoop.enterLoopMSecs(handshakeTimeoutMS);
+ testLoop.enterLoop(HandshakeTimeout);
QVERIFY(!testLoop.timeout());
QDTLS_VERIFY_HANDSHAKE_SUCCESS(clientCrypto);
QDTLS_VERIFY_HANDSHAKE_SUCCESS(serverCrypto);
@@ -579,28 +581,36 @@ void tst_QDtls::protocolVersionMatching_data()
QTest::addColumn<QSsl::SslProtocol>("clientProtocol");
QTest::addColumn<bool>("works");
+ //OPENSSL_VERSION_NUMBER :
+ //(OPENSSL_VERSION_MAJOR<<28) | (OPENSSL_VERSION_MINOR<<20) | (OPENSSL_VERSION_PATCH<<4)
+ const long ossl311 = 0x30100010;
+
+ if (QSslSocket::sslLibraryVersionNumber() < ossl311) {
#if QT_DEPRECATED_SINCE(6, 3)
QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
- QTest::addRow("DtlsV1_0 <-> DtlsV1_0") << QSsl::DtlsV1_0 << QSsl::DtlsV1_0 << true;
- QTest::addRow("DtlsV1_0OrLater <-> DtlsV1_0") << QSsl::DtlsV1_0OrLater << QSsl::DtlsV1_0 << true;
- QTest::addRow("DtlsV1_0 <-> DtlsV1_0OrLater") << QSsl::DtlsV1_0 << QSsl::DtlsV1_0OrLater << true;
- QTest::addRow("DtlsV1_0OrLater <-> DtlsV1_0OrLater") << QSsl::DtlsV1_0OrLater << QSsl::DtlsV1_0OrLater << true;
+ QTest::addRow("DtlsV1_0 <-> DtlsV1_0") << QSsl::DtlsV1_0 << QSsl::DtlsV1_0 << true;
+ QTest::addRow("DtlsV1_0OrLater <-> DtlsV1_0") << QSsl::DtlsV1_0OrLater << QSsl::DtlsV1_0 << true;
+ QTest::addRow("DtlsV1_0 <-> DtlsV1_0OrLater") << QSsl::DtlsV1_0 << QSsl::DtlsV1_0OrLater << true;
+ QTest::addRow("DtlsV1_0OrLater <-> DtlsV1_0OrLater") << QSsl::DtlsV1_0OrLater << QSsl::DtlsV1_0OrLater << true;
QT_WARNING_POP
#endif // QT_DEPRECATED_SINCE(6, 3)
+ }
QTest::addRow("DtlsV1_2 <-> DtlsV1_2") << QSsl::DtlsV1_2 << QSsl::DtlsV1_2 << true;
QTest::addRow("DtlsV1_2OrLater <-> DtlsV1_2") << QSsl::DtlsV1_2OrLater << QSsl::DtlsV1_2 << true;
QTest::addRow("DtlsV1_2 <-> DtlsV1_2OrLater") << QSsl::DtlsV1_2 << QSsl::DtlsV1_2OrLater << true;
QTest::addRow("DtlsV1_2OrLater <-> DtlsV1_2OrLater") << QSsl::DtlsV1_2OrLater << QSsl::DtlsV1_2OrLater << true;
+ if (QSslSocket::sslLibraryVersionNumber() < ossl311) {
#if QT_DEPRECATED_SINCE(6, 3)
QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
- QTest::addRow("DtlsV1_0 <-> DtlsV1_2") << QSsl::DtlsV1_0 << QSsl::DtlsV1_2 << false;
- QTest::addRow("DtlsV1_0 <-> DtlsV1_2OrLater") << QSsl::DtlsV1_0 << QSsl::DtlsV1_2OrLater << false;
- QTest::addRow("DtlsV1_2 <-> DtlsV1_0") << QSsl::DtlsV1_2 << QSsl::DtlsV1_0 << false;
- QTest::addRow("DtlsV1_2OrLater <-> DtlsV1_0") << QSsl::DtlsV1_2OrLater << QSsl::DtlsV1_0 << false;
+ QTest::addRow("DtlsV1_0 <-> DtlsV1_2") << QSsl::DtlsV1_0 << QSsl::DtlsV1_2 << false;
+ QTest::addRow("DtlsV1_0 <-> DtlsV1_2OrLater") << QSsl::DtlsV1_0 << QSsl::DtlsV1_2OrLater << false;
+ QTest::addRow("DtlsV1_2 <-> DtlsV1_0") << QSsl::DtlsV1_2 << QSsl::DtlsV1_0 << false;
+ QTest::addRow("DtlsV1_2OrLater <-> DtlsV1_0") << QSsl::DtlsV1_2OrLater << QSsl::DtlsV1_0 << false;
QT_WARNING_POP
-#endif // QT_DEPRECATED_SINCE(6, 3)
+#endif // QT_DEPRECATED_SINCE(6, 3
+ }
}
void tst_QDtls::protocolVersionMatching()
@@ -626,7 +636,7 @@ void tst_QDtls::protocolVersionMatching()
QVERIFY(clientCrypto->setPeer(serverAddress, serverPort));
QVERIFY(clientCrypto->doHandshake(&clientSocket));
- testLoop.enterLoopMSecs(handshakeTimeoutMS);
+ testLoop.enterLoop(HandshakeTimeout);
if (works) {
QDTLS_VERIFY_HANDSHAKE_SUCCESS(serverCrypto);
@@ -661,7 +671,7 @@ void tst_QDtls::verificationErrors()
// Now we are ready for handshake:
QVERIFY(clientCrypto->doHandshake(&clientSocket));
- testLoop.enterLoopMSecs(handshakeTimeoutMS);
+ testLoop.enterLoop(HandshakeTimeout);
QVERIFY(!testLoop.timeout());
QDTLS_VERIFY_NO_ERROR(serverCrypto);
@@ -731,7 +741,7 @@ void tst_QDtls::presetExpectedErrors()
QVERIFY(clientCrypto->setPeer(serverAddress, serverPort));
QVERIFY(clientCrypto->doHandshake(&clientSocket));
- testLoop.enterLoopMSecs(handshakeTimeoutMS);
+ testLoop.enterLoop(HandshakeTimeout);
QVERIFY(!testLoop.timeout());
@@ -818,7 +828,7 @@ void tst_QDtls::verifyServerCertificate()
QVERIFY(clientCrypto->doHandshake(&clientSocket));
- testLoop.enterLoopMSecs(handshakeTimeoutMS);
+ testLoop.enterLoop(HandshakeTimeout);
QVERIFY(!testLoop.timeout());
if (serverKey.isNull() && !serverCerts.isEmpty()) {
@@ -948,7 +958,7 @@ void tst_QDtls::verifyClientCertificate()
QVERIFY(clientCrypto->doHandshake(&clientSocket));
QDTLS_VERIFY_NO_ERROR(clientCrypto);
- testLoop.enterLoopMSecs(handshakeTimeoutMS);
+ testLoop.enterLoop(HandshakeTimeout);
serverConfig = serverCrypto->dtlsConfiguration();
@@ -995,7 +1005,7 @@ void tst_QDtls::blacklistedCerificate()
QVERIFY(clientCrypto->setPeer(serverAddress, serverPort, name));
QVERIFY(clientCrypto->doHandshake(&clientSocket));
- testLoop.enterLoopMSecs(handshakeTimeoutMS);
+ testLoop.enterLoop(HandshakeTimeout);
QVERIFY(!testLoop.timeout());
QCOMPARE(clientCrypto->handshakeState(), QDtls::PeerVerificationFailed);
QCOMPARE(clientCrypto->dtlsError(), QDtlsError::PeerVerificationError);
@@ -1047,7 +1057,7 @@ void tst_QDtls::readWriteEncrypted()
QCOMPARE(clientCrypto->dtlsError(), QDtlsError::InvalidOperation);
// 1.2 Finish the handshake:
- testLoop.enterLoopMSecs(handshakeTimeoutMS);
+ testLoop.enterLoop(HandshakeTimeout);
QVERIFY(!testLoop.timeout());
QDTLS_VERIFY_HANDSHAKE_SUCCESS(clientCrypto);
@@ -1065,7 +1075,7 @@ void tst_QDtls::readWriteEncrypted()
QVERIFY(clientBytesWritten > 0);
// 5. Exchange client/server messages:
- testLoop.enterLoopMSecs(dataExchangeTimeoutMS);
+ testLoop.enterLoop(DataExchangeTimeout);
QVERIFY(!testLoop.timeout());
QCOMPARE(serverExpectedPlainText, serverReceivedPlainText);
@@ -1083,7 +1093,7 @@ void tst_QDtls::readWriteEncrypted()
QCOMPARE(crypto->handshakeState(), QDtls::HandshakeNotStarted);
QVERIFY(!crypto->isConnectionEncrypted());
// 8. Receive this read notification and handle it:
- testLoop.enterLoopMSecs(dataExchangeTimeoutMS);
+ testLoop.enterLoop(DataExchangeTimeout);
QVERIFY(!testLoop.timeout());
DtlsPtr &peerCrypto = serverSideShutdown ? clientCrypto : serverCrypto;
@@ -1108,7 +1118,7 @@ void tst_QDtls::datagramFragmentation()
QVERIFY(clientCrypto->doHandshake(&clientSocket));
- testLoop.enterLoopMSecs(handshakeTimeoutMS);
+ testLoop.enterLoop(HandshakeTimeout);
QVERIFY(!testLoop.timeout());
QDTLS_VERIFY_HANDSHAKE_SUCCESS(clientCrypto);
diff --git a/tests/auto/network/ssl/qdtlscookie/CMakeLists.txt b/tests/auto/network/ssl/qdtlscookie/CMakeLists.txt
index 75b43ac9d4..d965c7efb6 100644
--- a/tests/auto/network/ssl/qdtlscookie/CMakeLists.txt
+++ b/tests/auto/network/ssl/qdtlscookie/CMakeLists.txt
@@ -1,24 +1,20 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qdtlscookie.pro.
-
#####################################################################
## tst_qdtlscookie Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qdtlscookie LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qdtlscookie
SOURCES
tst_qdtlscookie.cpp
LIBRARIES
Qt::NetworkPrivate
+ BUNDLE_ANDROID_OPENSSL_LIBS
)
-
-## Scopes:
-#####################################################################
-
-#### Keys ignored in scope 3:.:.:qdtlscookie.pro:(CMAKE_BUILD_TYPE STREQUAL Debug):
-# DESTDIR = "debug"
-
-#### Keys ignored in scope 4:.:.:qdtlscookie.pro:else:
-# DESTDIR = "release"
diff --git a/tests/auto/network/ssl/qdtlscookie/tst_qdtlscookie.cpp b/tests/auto/network/ssl/qdtlscookie/tst_qdtlscookie.cpp
index 55322608f2..167a196104 100644
--- a/tests/auto/network/ssl/qdtlscookie/tst_qdtlscookie.cpp
+++ b/tests/auto/network/ssl/qdtlscookie/tst_qdtlscookie.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
#include <QTestEventLoop>
@@ -22,6 +22,8 @@
#include <utility>
#include <vector>
+using namespace std::chrono_literals;
+
QT_BEGIN_NAMESPACE
#define STOP_ON_FAILURE \
@@ -76,7 +78,7 @@ private:
quint16 serverPort = 0;
QTestEventLoop testLoop;
- int handshakeTimeoutMS = 500;
+ static constexpr auto HandshakeTimeout = 500ms;
QDtlsClientVerifier listener;
using HandshakePtr = QSharedPointer<QDtls>;
@@ -327,7 +329,7 @@ void tst_QDtlsCookie::verifyMultipleClients()
clientsToAdd = clientsToWait = 100;
- testLoop.enterLoopMSecs(handshakeTimeoutMS * clientsToWait);
+ testLoop.enterLoop(HandshakeTimeout * clientsToWait);
QVERIFY(!testLoop.timeout());
QVERIFY(clientsToWait == 0);
}
@@ -351,7 +353,7 @@ void tst_QDtlsCookie::receiveMessage(QUdpSocket *socket, QByteArray *message,
Q_ASSERT(socket && message);
if (socket->pendingDatagramSize() <= 0)
- testLoop.enterLoopMSecs(handshakeTimeoutMS);
+ testLoop.enterLoop(HandshakeTimeout);
QVERIFY(!testLoop.timeout());
QVERIFY(socket->pendingDatagramSize());
diff --git a/tests/auto/network/ssl/qocsp/CMakeLists.txt b/tests/auto/network/ssl/qocsp/CMakeLists.txt
index c739e89583..98d38ec1c0 100644
--- a/tests/auto/network/ssl/qocsp/CMakeLists.txt
+++ b/tests/auto/network/ssl/qocsp/CMakeLists.txt
@@ -1,25 +1,26 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qocsp.pro.
-
#####################################################################
## tst_qocsp Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qocsp LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qocsp
SOURCES
tst_qocsp.cpp
LIBRARIES
Qt::Network
Qt::NetworkPrivate
+ BUNDLE_ANDROID_OPENSSL_LIBS
)
-## Scopes:
-#####################################################################
-
-#### Keys ignored in scope 3:.:.:qocsp.pro:(CMAKE_BUILD_TYPE STREQUAL Debug):
-# DESTDIR = "debug"
-
-#### Keys ignored in scope 4:.:.:qocsp.pro:else:
-# DESTDIR = "release"
+qt_internal_extend_target(tst_qocsp CONDITION QT_FEATURE_openssl_linked
+ LIBRARIES
+ WrapOpenSSL::WrapOpenSSL
+)
diff --git a/tests/auto/network/ssl/qocsp/tst_qocsp.cpp b/tests/auto/network/ssl/qocsp/tst_qocsp.cpp
index cde8d43257..81ce030be0 100644
--- a/tests/auto/network/ssl/qocsp/tst_qocsp.cpp
+++ b/tests/auto/network/ssl/qocsp/tst_qocsp.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
#include <QTestEventLoop>
@@ -28,6 +28,8 @@
#include <algorithm>
#include <utility>
+using namespace std::chrono_literals;
+
// NOTE: the word 'subject' in the code below means the subject of a status request,
// so in general it's our peer's certificate we are asking about.
@@ -386,7 +388,7 @@ private:
void (QSslSocket::*tlsErrorsSignal)(const QList<QSslError> &) = &QSslSocket::sslErrors;
void (QTestEventLoop::*exitLoopSlot)() = &QTestEventLoop::exitLoop;
- const int handshakeTimeoutMS = 500;
+ static constexpr auto HandshakeTimeout = 500ms;
QTestEventLoop loop;
std::vector<QSslError::SslError> ocspErrorCodes = {QSslError::OcspNoResponseFound,
@@ -462,7 +464,7 @@ void tst_QOcsp::connectSelfSigned()
auto roots = clientConfig.caCertificates();
setupOcspClient(clientSocket, issuerToChain(subjectChain), server.peerVerifyName());
clientSocket.connectToHostEncrypted(server.hostName(), server.serverPort());
- loop.enterLoopMSecs(handshakeTimeoutMS);
+ loop.enterLoop(HandshakeTimeout);
QVERIFY(!clientSocket.isEncrypted());
QCOMPARE_SINGLE_ERROR(clientSocket, expectedError);
@@ -478,7 +480,7 @@ void tst_QOcsp::connectSelfSigned()
QSslSocket clientSocket;
setupOcspClient(clientSocket, issuerToChain(subjectChain), server.peerVerifyName());
clientSocket.connectToHostEncrypted(server.hostName(), server.serverPort());
- loop.enterLoopMSecs(handshakeTimeoutMS);
+ loop.enterLoop(HandshakeTimeout);
QVERIFY_HANDSHAKE_WITHOUT_ERRORS(clientSocket);
@@ -543,7 +545,7 @@ void tst_QOcsp::badStatus()
QSslSocket clientSocket;
setupOcspClient(clientSocket, issuerToChain(subjectChain), server.peerVerifyName());
clientSocket.connectToHostEncrypted(server.hostName(), server.serverPort());
- loop.enterLoopMSecs(handshakeTimeoutMS);
+ loop.enterLoop(HandshakeTimeout);
QVERIFY(!clientSocket.isEncrypted());
QCOMPARE_SINGLE_ERROR(clientSocket, expectedError.error());
@@ -574,7 +576,7 @@ void tst_QOcsp::multipleSingleResponses()
QSslSocket clientSocket;
setupOcspClient(clientSocket, issuerToChain(responderChain), server.peerVerifyName());
clientSocket.connectToHostEncrypted(server.hostName(), server.serverPort());
- loop.enterLoopMSecs(handshakeTimeoutMS);
+ loop.enterLoop(HandshakeTimeout);
QVERIFY(!clientSocket.isEncrypted());
QCOMPARE_SINGLE_ERROR(clientSocket, expectedError);
@@ -594,7 +596,7 @@ void tst_QOcsp::malformedResponse()
QSslSocket clientSocket;
setupOcspClient(clientSocket, issuerToChain(serverChain), server.peerVerifyName());
clientSocket.connectToHostEncrypted(server.hostName(), server.serverPort());
- loop.enterLoopMSecs(handshakeTimeoutMS);
+ loop.enterLoop(HandshakeTimeout);
QVERIFY(!clientSocket.isEncrypted());
QCOMPARE(clientSocket.error(), QAbstractSocket::SslHandshakeFailedError);
@@ -633,7 +635,7 @@ void tst_QOcsp::expiredResponse()
QSslSocket clientSocket;
setupOcspClient(clientSocket, issuerToChain(subjectChain), server.peerVerifyName());
clientSocket.connectToHostEncrypted(server.hostName(), server.serverPort());
- loop.enterLoopMSecs(handshakeTimeoutMS);
+ loop.enterLoop(HandshakeTimeout);
QVERIFY(!clientSocket.isEncrypted());
QCOMPARE_SINGLE_ERROR(clientSocket, expectedError);
@@ -664,7 +666,7 @@ void tst_QOcsp::noNextUpdate()
QSslSocket clientSocket;
setupOcspClient(clientSocket, issuerToChain(subjectChain), server.peerVerifyName());
clientSocket.connectToHostEncrypted(server.hostName(), server.serverPort());
- loop.enterLoopMSecs(handshakeTimeoutMS);
+ loop.enterLoop(HandshakeTimeout);
QVERIFY_HANDSHAKE_WITHOUT_ERRORS(clientSocket);
}
@@ -710,7 +712,7 @@ void tst_QOcsp::wrongCertificateInResponse()
QSslSocket clientSocket;
setupOcspClient(clientSocket, issuerToChain(subjectChain), server.peerVerifyName());
clientSocket.connectToHostEncrypted(server.hostName(), server.serverPort());
- loop.enterLoopMSecs(handshakeTimeoutMS);
+ loop.enterLoop(HandshakeTimeout);
QVERIFY(!clientSocket.isEncrypted());
QVERIFY(containsError(clientSocket.sslHandshakeErrors(), expectedError));
@@ -735,7 +737,7 @@ void tst_QOcsp::untrustedResponder()
QSslSocket clientSocket;
setupOcspClient(clientSocket, {}, server.peerVerifyName());
clientSocket.connectToHostEncrypted(server.hostName(), server.serverPort());
- loop.enterLoopMSecs(handshakeTimeoutMS);
+ loop.enterLoop(HandshakeTimeout);
QVERIFY(!clientSocket.isEncrypted());
QVERIFY(containsError(clientSocket.sslHandshakeErrors(), expectedError));
diff --git a/tests/auto/network/ssl/qpassworddigestor/CMakeLists.txt b/tests/auto/network/ssl/qpassworddigestor/CMakeLists.txt
index bed1242b88..96491eada9 100644
--- a/tests/auto/network/ssl/qpassworddigestor/CMakeLists.txt
+++ b/tests/auto/network/ssl/qpassworddigestor/CMakeLists.txt
@@ -1,15 +1,20 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qpassworddigestor.pro.
-
#####################################################################
## tst_qpassworddigestor Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qpassworddigestor LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qpassworddigestor
SOURCES
tst_qpassworddigestor.cpp
LIBRARIES
Qt::Network
+ BUNDLE_ANDROID_OPENSSL_LIBS
)
diff --git a/tests/auto/network/ssl/qpassworddigestor/tst_qpassworddigestor.cpp b/tests/auto/network/ssl/qpassworddigestor/tst_qpassworddigestor.cpp
index 5047fac2dd..1876c955af 100644
--- a/tests/auto/network/ssl/qpassworddigestor/tst_qpassworddigestor.cpp
+++ b/tests/auto/network/ssl/qpassworddigestor/tst_qpassworddigestor.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
#include <QtNetwork/qpassworddigestor.h>
diff --git a/tests/auto/network/ssl/qsslcertificate/CMakeLists.txt b/tests/auto/network/ssl/qsslcertificate/CMakeLists.txt
index b12723b0c3..6f81a5e030 100644
--- a/tests/auto/network/ssl/qsslcertificate/CMakeLists.txt
+++ b/tests/auto/network/ssl/qsslcertificate/CMakeLists.txt
@@ -1,18 +1,20 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qsslcertificate.pro.
-
#####################################################################
## tst_qsslcertificate Test:
#####################################################################
-# special case begin
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qsslcertificate LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# This test requires private tests to properly build
if (NOT QT_FEATURE_private_tests)
return()
endif()
-# special case end
# Collect test data
file(GLOB_RECURSE test_data_glob
@@ -38,4 +40,5 @@ qt_internal_add_test(tst_qsslcertificate
LIBRARIES
Qt::Network
TESTDATA ${test_data}
+ BUNDLE_ANDROID_OPENSSL_LIBS
)
diff --git a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp
index d4a1f510a9..b51053effd 100644
--- a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp
+++ b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp
@@ -1,17 +1,19 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
#include <QtNetwork/qtnetworkglobal.h>
+
+#include <QtCore/qdatetime.h>
+#include <QtCore/qtimezone.h>
+#include <QtCore/qscopeguard.h>
#include <QtCore/qset.h>
#include <qsslcertificate.h>
#include <qsslkey.h>
#include <qsslsocket.h>
#include <qsslcertificateextension.h>
-#include <qscopeguard.h>
#ifndef QT_NO_OPENSSL
#include <openssl/opensslv.h>
@@ -100,7 +102,31 @@ private slots:
#endif // QT_CONFIG(ssl)
private:
QString testDataDir;
- bool isNonOpenSslTls = false;
+
+ enum class TLSBackend {
+ OpenSSL,
+ Schannel,
+ SecureTransport,
+ CertOnly,
+ Unknown,
+ };
+ static TLSBackend currentBackend()
+ {
+ static TLSBackend activeBackend = []() {
+ using namespace Qt::StringLiterals;
+ const QString active = QSslSocket::activeBackend();
+ if (active == "openssl"_L1)
+ return TLSBackend::OpenSSL;
+ if (active == "schannel")
+ return TLSBackend::Schannel;
+ if (active == "securetransport")
+ return TLSBackend::SecureTransport;
+ if (active == "cert-only")
+ return TLSBackend::CertOnly;
+ return TLSBackend::Unknown;
+ }();
+ return activeBackend;
+ }
};
void tst_QSslCertificate::initTestCase()
@@ -111,16 +137,14 @@ void tst_QSslCertificate::initTestCase()
if (!testDataDir.endsWith(QLatin1String("/")))
testDataDir += QLatin1String("/");
- isNonOpenSslTls = QSslSocket::activeBackend() != QStringLiteral("openssl");
-
QDir dir(testDataDir + "certificates");
- QFileInfoList fileInfoList = dir.entryInfoList(QDir::Files | QDir::Readable);
+ const QFileInfoList fileInfoList = dir.entryInfoList(QDir::Files | QDir::Readable);
QRegularExpression rxCert(QLatin1String("^.+\\.(pem|der)$"));
QRegularExpression rxSan(QLatin1String("^(.+\\.(?:pem|der))\\.san$"));
QRegularExpression rxPubKey(QLatin1String("^(.+\\.(?:pem|der))\\.pubkey$"));
QRegularExpression rxDigest(QLatin1String("^(.+\\.(?:pem|der))\\.digest-(md5|sha1)$"));
QRegularExpressionMatch match;
- foreach (QFileInfo fileInfo, fileInfoList) {
+ for (const QFileInfo &fileInfo : fileInfoList) {
if ((match = rxCert.match(fileInfo.fileName())).hasMatch())
certInfoList <<
CertInfo(fileInfo,
@@ -183,7 +207,7 @@ void tst_QSslCertificate::createTestRows()
{
QTest::addColumn<QString>("absFilePath");
QTest::addColumn<QSsl::EncodingFormat>("format");
- foreach (CertInfo certInfo, certInfoList) {
+ for (const CertInfo &certInfo : std::as_const(certInfoList)) {
QTest::newRow(certInfo.fileInfo.fileName().toLatin1())
<< certInfo.fileInfo.absoluteFilePath() << certInfo.format;
}
@@ -314,7 +338,7 @@ void tst_QSslCertificate::digest_data()
QTest::addColumn<QSsl::EncodingFormat>("format");
QTest::addColumn<QString>("absFilePath_digest_md5");
QTest::addColumn<QString>("absFilePath_digest_sha1");
- foreach (CertInfo certInfo, certInfoList) {
+ for (const CertInfo &certInfo : std::as_const(certInfoList)) {
QString certName = certInfo.fileInfo.fileName();
QTest::newRow(certName.toLatin1())
<< certInfo.fileInfo.absoluteFilePath()
@@ -367,7 +391,7 @@ void tst_QSslCertificate::subjectAlternativeNames_data()
QTest::addColumn<QSsl::EncodingFormat>("format");
QTest::addColumn<QString>("subjAltNameFilePath");
- foreach (CertInfo certInfo, certInfoList) {
+ for (const CertInfo &certInfo : std::as_const(certInfoList)) {
QString certName = certInfo.fileInfo.fileName();
if (subjAltNameMap.contains(certName))
QTest::newRow(certName.toLatin1())
@@ -449,7 +473,7 @@ void tst_QSslCertificate::subjectInfoToString()
QVERIFY(testInfo(QSslCertificate::DistinguishedNameQualifier, QString()));
QVERIFY(testInfo(QSslCertificate::SerialNumber, QString()));
// TODO: check why generic code does not handle this!
- if (!isNonOpenSslTls)
+ if (currentBackend() == TLSBackend::OpenSSL)
QVERIFY(testInfo(QSslCertificate::EmailAddress, QStringLiteral("ababic@trolltech.com")));
}
@@ -461,9 +485,8 @@ void tst_QSslCertificate::subjectIssuerDisplayName_data()
QTest::addRow("CommonName") << QStringLiteral("more-certificates/cert-cn.pem") << QStringLiteral("YOUR name");
QTest::addRow("OrganizationName") << QStringLiteral("more-certificates/cert-on.pem") << QStringLiteral("R&D");
QTest::addRow("OrganizationUnitName") << QStringLiteral("more-certificates/cert-oun.pem") << QStringLiteral("Foundations");
-#ifndef QT_NO_OPENSSL
- QTest::addRow("NoSubjectName") << QStringLiteral("more-certificates/cert-noname.pem") << QString();
-#endif
+ if (currentBackend() == TLSBackend::OpenSSL)
+ QTest::addRow("NoSubjectName") << QStringLiteral("more-certificates/cert-noname.pem") << QString();
}
void tst_QSslCertificate::subjectIssuerDisplayName()
@@ -493,7 +516,7 @@ void tst_QSslCertificate::utf8SubjectNames()
static const char *ou = "\xe3\x88\xa7" "A" "\xe3\x89\x81\xef\xbd\xab" "BC";
// the following two tests should help find "\x"-literal encoding bugs in the test itself
- QCOMPARE(cert.subjectInfo("O")[0].length(), QString::fromUtf8(o).length());
+ QCOMPARE(cert.subjectInfo("O")[0].size(), QString::fromUtf8(o).size());
QCOMPARE (cert.subjectInfo("O")[0].toUtf8().toHex(), QByteArray(o).toHex());
QCOMPARE(cert.subjectInfo("O")[0], QString::fromUtf8(o));
@@ -506,7 +529,7 @@ void tst_QSslCertificate::publicKey_data()
QTest::addColumn<QSsl::EncodingFormat>("format");
QTest::addColumn<QString>("pubkeyFilePath");
- foreach (CertInfo certInfo, certInfoList) {
+ for (const CertInfo &certInfo : std::as_const(certInfoList)) {
QString certName = certInfo.fileInfo.fileName();
if (pubkeyMap.contains(certName))
QTest::newRow(certName.toLatin1())
@@ -808,8 +831,10 @@ void tst_QSslCertificate::certInfo()
QCOMPARE(cert.digest(QCryptographicHash::Sha1),
QByteArray::fromHex("B6:D1:51:82:E0:29:CA:59:96:38:BD:B6:F9:40:05:91:6D:49:09:60"));
- QCOMPARE(cert.effectiveDate().toUTC(), QDateTime(QDate(2007, 4, 17), QTime(7,40,26), Qt::UTC));
- QCOMPARE(cert.expiryDate().toUTC(), QDateTime(QDate(2007, 5, 17), QTime(7,40,26), Qt::UTC));
+ QCOMPARE(cert.effectiveDate().toUTC(),
+ QDateTime(QDate(2007, 4, 17), QTime(7,40,26), QTimeZone::UTC));
+ QCOMPARE(cert.expiryDate().toUTC(),
+ QDateTime(QDate(2007, 5, 17), QTime(7,40,26), QTimeZone::UTC));
QVERIFY(cert.expiryDate() < QDateTime::currentDateTime()); // cert has expired
QSslCertificate copy = cert;
@@ -871,7 +896,7 @@ void tst_QSslCertificate::task256066toPem()
void tst_QSslCertificate::nulInCN()
{
- if (isNonOpenSslTls)
+ if (currentBackend() != TLSBackend::OpenSSL)
QSKIP("Generic QSslCertificatePrivate fails this test");
QList<QSslCertificate> certList =
@@ -891,7 +916,7 @@ void tst_QSslCertificate::nulInCN()
void tst_QSslCertificate::nulInSan()
{
- if (isNonOpenSslTls)
+ if (currentBackend() != TLSBackend::OpenSSL)
QSKIP("Generic QSslCertificatePrivate fails this test");
QList<QSslCertificate> certList =
@@ -933,16 +958,18 @@ void tst_QSslCertificate::largeExpirationDate() // QTBUG-12489
const QSslCertificate &cert = certList.at(0);
QVERIFY(!cert.isNull());
- QCOMPARE(cert.effectiveDate().toUTC(), QDateTime(QDate(2010, 8, 4), QTime(9, 53, 41), Qt::UTC));
+ QCOMPARE(cert.effectiveDate().toUTC(),
+ QDateTime(QDate(2010, 8, 4), QTime(9, 53, 41), QTimeZone::UTC));
// if the date is larger than 2049, then the generalized time format is used
- QCOMPARE(cert.expiryDate().toUTC(), QDateTime(QDate(2051, 8, 29), QTime(9, 53, 41), Qt::UTC));
+ QCOMPARE(cert.expiryDate().toUTC(),
+ QDateTime(QDate(2051, 8, 29), QTime(9, 53, 41), QTimeZone::UTC));
}
void tst_QSslCertificate::blacklistedCertificates()
{
QList<QSslCertificate> blacklistedCerts = QSslCertificate::fromPath(testDataDir + "more-certificates/blacklisted*.pem", QSsl::Pem, QSslCertificate::PatternSyntax::Wildcard);
- QVERIFY(blacklistedCerts.count() > 0);
- for (int a = 0; a < blacklistedCerts.count(); a++) {
+ QVERIFY(blacklistedCerts.size() > 0);
+ for (int a = 0; a < blacklistedCerts.size(); a++) {
QVERIFY(blacklistedCerts.at(a).isBlacklisted());
}
}
@@ -956,7 +983,7 @@ void tst_QSslCertificate::selfsignedCertificates()
void tst_QSslCertificate::toText()
{
- if (isNonOpenSslTls)
+ if (currentBackend() != TLSBackend::OpenSSL)
QSKIP("QSslCertificate::toText is not implemented on platforms which do not use openssl");
QList<QSslCertificate> certList =
@@ -984,7 +1011,7 @@ void tst_QSslCertificate::multipleCommonNames()
{
QList<QSslCertificate> certList =
QSslCertificate::fromPath(testDataDir + "more-certificates/test-cn-two-cns-cert.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString);
- QVERIFY(certList.count() > 0);
+ QVERIFY(certList.size() > 0);
QStringList commonNames = certList[0].subjectInfo(QSslCertificate::CommonName);
QVERIFY(commonNames.contains(QString("www.example.com")));
@@ -995,18 +1022,18 @@ void tst_QSslCertificate::subjectAndIssuerAttributes()
{
QList<QSslCertificate> certList =
QSslCertificate::fromPath(testDataDir + "more-certificates/test-cn-with-drink-cert.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString);
- QVERIFY(certList.count() > 0);
+ QVERIFY(certList.size() > 0);
QList<QByteArray> attributes = certList[0].subjectInfoAttributes();
QVERIFY(attributes.contains(QByteArray("favouriteDrink")));
attributes.clear();
certList = QSslCertificate::fromPath(testDataDir + "more-certificates/natwest-banking.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString);
- QVERIFY(certList.count() > 0);
+ QVERIFY(certList.size() > 0);
QByteArray shortName("1.3.6.1.4.1.311.60.2.1.3");
#if !defined(QT_NO_OPENSSL) && defined(SN_jurisdictionCountryName)
- if (!isNonOpenSslTls)
+ if (currentBackend() == TLSBackend::OpenSSL)
shortName = SN_jurisdictionCountryName;
#endif
attributes = certList[0].subjectInfoAttributes();
@@ -1015,8 +1042,8 @@ void tst_QSslCertificate::subjectAndIssuerAttributes()
void tst_QSslCertificate::verify()
{
- if (isNonOpenSslTls)
- QSKIP("Not implemented in SecureTransport or Schannel");
+ if (currentBackend() != TLSBackend::OpenSSL)
+ QSKIP("Only implemented for OpenSSL");
QList<QSslError> errors;
QList<QSslCertificate> toVerify;
@@ -1029,7 +1056,7 @@ void tst_QSslCertificate::verify()
// Empty chain is unspecified error
errors = QSslCertificate::verify(toVerify);
- VERIFY_VERBOSE(errors.count() == 1);
+ VERIFY_VERBOSE(errors.size() == 1);
VERIFY_VERBOSE(errors[0] == QSslError(QSslError::UnspecifiedError));
errors.clear();
@@ -1048,14 +1075,14 @@ void tst_QSslCertificate::verify()
toVerify = QSslCertificate::fromPath(testDataDir + "verify-certs/test-ocsp-good-cert.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString);
errors = QSslCertificate::verify(toVerify);
- VERIFY_VERBOSE(errors.count() == 0);
+ VERIFY_VERBOSE(errors.size() == 0);
errors.clear();
// Test a blacklisted certificate
toVerify = QSslCertificate::fromPath(testDataDir + "verify-certs/test-addons-mozilla-org-cert.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString);
errors = QSslCertificate::verify(toVerify);
bool foundBlack = false;
- foreach (const QSslError &error, errors) {
+ for (const QSslError &error : std::as_const(errors)) {
if (error.error() == QSslError::CertificateBlacklisted) {
foundBlack = true;
break;
@@ -1083,11 +1110,11 @@ void tst_QSslCertificate::verify()
toVerify << QSslCertificate::fromPath(testDataDir + "verify-certs/test-intermediate-is-ca-cert.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString).first();
toVerify << QSslCertificate::fromPath(testDataDir + "verify-certs/test-intermediate-ca-cert.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString).first();
errors = QSslCertificate::verify(toVerify);
- VERIFY_VERBOSE(errors.count() == 0);
+ VERIFY_VERBOSE(errors.size() == 0);
// Recheck the above with hostname validation
errors = QSslCertificate::verify(toVerify, QLatin1String("example.com"));
- VERIFY_VERBOSE(errors.count() == 0);
+ VERIFY_VERBOSE(errors.size() == 0);
// Recheck the above with a bad hostname
errors = QSslCertificate::verify(toVerify, QLatin1String("fail.example.com"));
@@ -1101,9 +1128,8 @@ QString tst_QSslCertificate::toString(const QList<QSslError>& errors)
{
QStringList errorStrings;
- foreach (const QSslError& error, errors) {
+ for (const QSslError &error : errors)
errorStrings.append(QLatin1Char('"') + error.errorString() + QLatin1Char('"'));
- }
return QLatin1String("[ ") + errorStrings.join(QLatin1String(", ")) + QLatin1String(" ]");
}
@@ -1112,11 +1138,11 @@ void tst_QSslCertificate::extensions()
{
QList<QSslCertificate> certList =
QSslCertificate::fromPath(testDataDir + "more-certificates/natwest-banking.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString);
- QVERIFY(certList.count() > 0);
+ QVERIFY(certList.size() > 0);
QSslCertificate cert = certList[0];
QList<QSslCertificateExtension> extensions = cert.extensions();
- QCOMPARE(extensions.count(), 9);
+ QCOMPARE(extensions.size(), 9);
int unknown_idx = -1;
int authority_info_idx = -1;
@@ -1124,7 +1150,7 @@ void tst_QSslCertificate::extensions()
int subject_key_idx = -1;
int auth_key_idx = -1;
- for (int i=0; i < extensions.length(); ++i) {
+ for (int i=0; i < extensions.size(); ++i) {
QSslCertificateExtension ext = extensions[i];
//qDebug() << i << ":" << ext.name() << ext.oid();
@@ -1210,16 +1236,16 @@ void tst_QSslCertificate::extensionsCritical()
{
QList<QSslCertificate> certList =
QSslCertificate::fromPath(testDataDir + "verify-certs/test-addons-mozilla-org-cert.pem", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString);
- QVERIFY(certList.count() > 0);
+ QVERIFY(certList.size() > 0);
QSslCertificate cert = certList[0];
QList<QSslCertificateExtension> extensions = cert.extensions();
- QCOMPARE(extensions.count(), 9);
+ QCOMPARE(extensions.size(), 9);
int basic_constraints_idx = -1;
int key_usage_idx = -1;
- for (int i=0; i < extensions.length(); ++i) {
+ for (int i=0; i < extensions.size(); ++i) {
QSslCertificateExtension ext = extensions[i];
if (ext.name() == QStringLiteral("basicConstraints"))
@@ -1357,9 +1383,8 @@ void tst_QSslCertificate::pkcs12()
return;
}
-#if !defined(QT_NO_OPENSSL) && OPENSSL_VERSION_MAJOR >= 3
- QSKIP("leaf.p12 is using RC2, which is disabled by default in OpenSSL v >= 3");
-#endif
+ if (currentBackend() == TLSBackend::OpenSSL && QSslSocket::sslLibraryVersionNumber() >= 0x30000000L)
+ QSKIP("leaf.p12 is using RC2, which is disabled by default in OpenSSL v >= 3");
QFile f(testDataDir + QLatin1String("pkcs12/leaf.p12"));
bool ok = f.open(QIODevice::ReadOnly);
@@ -1369,8 +1394,8 @@ void tst_QSslCertificate::pkcs12()
QSslCertificate cert;
QList<QSslCertificate> caCerts;
- if (isNonOpenSslTls)
- QEXPECT_FAIL("", "pkcs12 imports are only supported when openssl is used", Abort); // TODO?
+ if (currentBackend() != TLSBackend::OpenSSL)
+ QEXPECT_FAIL("", "pkcs12 imports are not available with the current TLS backend", Abort); // TODO?
ok = QSslCertificate::importPkcs12(&f, &key, &cert, &caCerts);
QVERIFY(ok);
@@ -1402,7 +1427,8 @@ void tst_QSslCertificate::pkcs12()
QFile nocert(testDataDir + QLatin1String("pkcs12/leaf-nokey.p12"));
ok = nocert.open(QIODevice::ReadOnly);
QVERIFY(ok);
- QTest::ignoreMessage(QtWarningMsg, "Unable to convert private key");
+ if (currentBackend() == TLSBackend::OpenSSL)
+ QTest::ignoreMessage(QtWarningMsg, "Unable to convert private key");
ok = QSslCertificate::importPkcs12(&nocert, &key, &cert, &caCerts);
QVERIFY(!ok);
nocert.close();
diff --git a/tests/auto/network/ssl/qsslcipher/CMakeLists.txt b/tests/auto/network/ssl/qsslcipher/CMakeLists.txt
index dca12a50b3..8538f56acd 100644
--- a/tests/auto/network/ssl/qsslcipher/CMakeLists.txt
+++ b/tests/auto/network/ssl/qsslcipher/CMakeLists.txt
@@ -1,24 +1,20 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qsslcipher.pro.
-
#####################################################################
## tst_qsslcipher Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qsslcipher LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qsslcipher
SOURCES
tst_qsslcipher.cpp
LIBRARIES
Qt::Network
+ BUNDLE_ANDROID_OPENSSL_LIBS
)
-
-## Scopes:
-#####################################################################
-
-#### Keys ignored in scope 3:.:.:qsslcipher.pro:(CMAKE_BUILD_TYPE STREQUAL Debug):
-# DESTDIR = "debug"
-
-#### Keys ignored in scope 4:.:.:qsslcipher.pro:else:
-# DESTDIR = "release"
diff --git a/tests/auto/network/ssl/qsslcipher/tst_qsslcipher.cpp b/tests/auto/network/ssl/qsslcipher/tst_qsslcipher.cpp
index 3b24dd0403..6810149c11 100644
--- a/tests/auto/network/ssl/qsslcipher/tst_qsslcipher.cpp
+++ b/tests/auto/network/ssl/qsslcipher/tst_qsslcipher.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
diff --git a/tests/auto/network/ssl/qssldiffiehellmanparameters/CMakeLists.txt b/tests/auto/network/ssl/qssldiffiehellmanparameters/CMakeLists.txt
index 486d1c8598..3ac34b2f6c 100644
--- a/tests/auto/network/ssl/qssldiffiehellmanparameters/CMakeLists.txt
+++ b/tests/auto/network/ssl/qssldiffiehellmanparameters/CMakeLists.txt
@@ -1,15 +1,20 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qssldiffiehellmanparameters.pro.
-
#####################################################################
## tst_qssldiffiehellmanparameters Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qssldiffiehellmanparameters LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qssldiffiehellmanparameters
SOURCES
tst_qssldiffiehellmanparameters.cpp
LIBRARIES
Qt::Network
+ BUNDLE_ANDROID_OPENSSL_LIBS
)
diff --git a/tests/auto/network/ssl/qssldiffiehellmanparameters/tst_qssldiffiehellmanparameters.cpp b/tests/auto/network/ssl/qssldiffiehellmanparameters/tst_qssldiffiehellmanparameters.cpp
index 8233d8883d..d8c6d9158a 100644
--- a/tests/auto/network/ssl/qssldiffiehellmanparameters/tst_qssldiffiehellmanparameters.cpp
+++ b/tests/auto/network/ssl/qssldiffiehellmanparameters/tst_qssldiffiehellmanparameters.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2015 Mikkel Krautz <mikkel@krautz.dk>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
diff --git a/tests/auto/network/ssl/qsslellipticcurve/CMakeLists.txt b/tests/auto/network/ssl/qsslellipticcurve/CMakeLists.txt
index f4e0ca6dfb..dd031a991b 100644
--- a/tests/auto/network/ssl/qsslellipticcurve/CMakeLists.txt
+++ b/tests/auto/network/ssl/qsslellipticcurve/CMakeLists.txt
@@ -1,15 +1,20 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qsslellipticcurve.pro.
-
#####################################################################
## tst_qsslellipticcurve Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qsslellipticcurve LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qsslellipticcurve
SOURCES
tst_qsslellipticcurve.cpp
LIBRARIES
Qt::Network
+ BUNDLE_ANDROID_OPENSSL_LIBS
)
diff --git a/tests/auto/network/ssl/qsslellipticcurve/tst_qsslellipticcurve.cpp b/tests/auto/network/ssl/qsslellipticcurve/tst_qsslellipticcurve.cpp
index ab4b457333..96ef7e9828 100644
--- a/tests/auto/network/ssl/qsslellipticcurve/tst_qsslellipticcurve.cpp
+++ b/tests/auto/network/ssl/qsslellipticcurve/tst_qsslellipticcurve.cpp
@@ -1,6 +1,5 @@
// Copyright (C) 2014 Governikus GmbH & Co. KG.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
@@ -66,7 +65,8 @@ void tst_QSslEllipticCurve::fromShortName_data()
QTest::newRow("QString()") << QString() << QSslEllipticCurve() << false;
QTest::newRow("\"\"") << QString("") << QSslEllipticCurve() << false;
QTest::newRow("does-not-exist") << QStringLiteral("does-not-exist") << QSslEllipticCurve() << false;
- Q_FOREACH (QSslEllipticCurve ec, QSslConfiguration::supportedEllipticCurves()) {
+ const auto supported = QSslConfiguration::supportedEllipticCurves();
+ for (QSslEllipticCurve ec : supported) {
const QString sN = ec.shortName();
QTest::newRow(qPrintable("supported EC \"" + sN + '"')) << sN << ec << true;
// At least in the OpenSSL impl, the short name is case-sensitive. That feels odd.
@@ -99,7 +99,8 @@ void tst_QSslEllipticCurve::fromLongName_data()
QTest::newRow("QString()") << QString() << QSslEllipticCurve() << false;
QTest::newRow("\"\"") << QString("") << QSslEllipticCurve() << false;
QTest::newRow("does-not-exist") << QStringLiteral("does-not-exist") << QSslEllipticCurve() << false;
- Q_FOREACH (QSslEllipticCurve ec, QSslConfiguration::supportedEllipticCurves()) {
+ const auto supported = QSslConfiguration::supportedEllipticCurves();
+ for (QSslEllipticCurve ec : supported) {
const QString lN = ec.longName();
QTest::newRow(qPrintable("supported EC \"" + lN + '"')) << lN << ec << true;
}
diff --git a/tests/auto/network/ssl/qsslerror/CMakeLists.txt b/tests/auto/network/ssl/qsslerror/CMakeLists.txt
index 29779add78..006bec3ef2 100644
--- a/tests/auto/network/ssl/qsslerror/CMakeLists.txt
+++ b/tests/auto/network/ssl/qsslerror/CMakeLists.txt
@@ -1,24 +1,20 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qsslerror.pro.
-
#####################################################################
## tst_qsslerror Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qsslerror LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qsslerror
SOURCES
tst_qsslerror.cpp
LIBRARIES
Qt::Network
+ BUNDLE_ANDROID_OPENSSL_LIBS
)
-
-## Scopes:
-#####################################################################
-
-#### Keys ignored in scope 3:.:.:qsslerror.pro:(CMAKE_BUILD_TYPE STREQUAL Debug):
-# DESTDIR = "debug"
-
-#### Keys ignored in scope 4:.:.:qsslerror.pro:else:
-# DESTDIR = "release"
diff --git a/tests/auto/network/ssl/qsslerror/tst_qsslerror.cpp b/tests/auto/network/ssl/qsslerror/tst_qsslerror.cpp
index 6cbcc30beb..981fe3a0d5 100644
--- a/tests/auto/network/ssl/qsslerror/tst_qsslerror.cpp
+++ b/tests/auto/network/ssl/qsslerror/tst_qsslerror.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtNetwork/qtnetworkglobal.h>
diff --git a/tests/auto/network/ssl/qsslkey/CMakeLists.txt b/tests/auto/network/ssl/qsslkey/CMakeLists.txt
index 0177ab7055..aae017562a 100644
--- a/tests/auto/network/ssl/qsslkey/CMakeLists.txt
+++ b/tests/auto/network/ssl/qsslkey/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qsslkey.pro.
-
#####################################################################
## tst_qsslkey Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qsslkey LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -23,12 +27,18 @@ qt_internal_add_test(tst_qsslkey
LIBRARIES
Qt::Network
TESTDATA ${test_data}
+ BUNDLE_ANDROID_OPENSSL_LIBS
+)
+
+qt_internal_extend_target(tst_qsslkey CONDITION QT_FEATURE_developer_build AND QT_FEATURE_openssl_linked
+ LIBRARIES
+ WrapOpenSSL::WrapOpenSSL
)
## Scopes:
#####################################################################
-qt_internal_extend_target(tst_qsslkey CONDITION QT_FEATURE_private_tests
+qt_internal_extend_target(tst_qsslkey CONDITION QT_FEATURE_developer_build
LIBRARIES
Qt::CorePrivate
Qt::NetworkPrivate
diff --git a/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp b/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp
index 627b6cca98..79bae3c270 100644
--- a/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp
+++ b/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
#include <qsslkey.h>
@@ -15,6 +15,8 @@
#include <QtCore/qdebug.h>
#include <QtCore/qlist.h>
+using namespace Qt::StringLiterals;
+
#ifdef QT_BUILD_INTERNAL
#if QT_CONFIG(ssl)
#include "private/qsslkey_p.h"
@@ -249,7 +251,7 @@ void tst_QSslKey::createPlainTestRows(bool pemOnly)
QTest::addColumn<QSsl::KeyType>("type");
QTest::addColumn<int>("length");
QTest::addColumn<QSsl::EncodingFormat>("format");
- foreach (KeyInfo keyInfo, keyInfoList) {
+ for (const KeyInfo &keyInfo : std::as_const(keyInfoList)) {
if (pemOnly && keyInfo.format != QSsl::EncodingFormat::Pem)
continue;
@@ -315,7 +317,7 @@ void tst_QSslKey::constructorHandle()
passphrase = "1234";
BIO* bio = q_BIO_new(q_BIO_s_mem());
- q_BIO_write(bio, pem.constData(), pem.length());
+ q_BIO_write(bio, pem.constData(), pem.size());
EVP_PKEY *origin = func(bio, nullptr, nullptr, static_cast<void *>(passphrase.data()));
Q_ASSERT(origin);
q_EVP_PKEY_up_ref(origin);
@@ -467,13 +469,18 @@ void tst_QSslKey::toEncryptedPemOrDer_data()
QTest::addColumn<QSsl::EncodingFormat>("format");
QTest::addColumn<QString>("password");
- QStringList passwords;
- passwords << " " << "foobar" << "foo bar"
- << "aAzZ`1234567890-=~!@#$%^&*()_+[]{}\\|;:'\",.<>/?"; // ### add more (?)
- foreach (KeyInfo keyInfo, keyInfoList) {
+ const QString passwords[] = {
+ u" "_s,
+ u"foobar"_s,
+ u"foo bar"_s,
+ u"aAzZ`1234567890-=~!@#$%^&*()_+[]{}\\|;:'\",.<>/?"_s,
+ // ### add more (?)
+ };
+
+ for (const KeyInfo &keyInfo : std::as_const(keyInfoList)) {
if (keyInfo.fileInfo.fileName().contains("pkcs8"))
continue; // pkcs8 keys are encrypted in a different way than the other keys
- foreach (QString password, passwords) {
+ for (const QString &password : passwords) {
const QByteArray testName = keyInfo.fileInfo.fileName().toLatin1()
+ '-' + (keyInfo.algorithm == QSsl::Rsa ? "RSA" :
(keyInfo.algorithm == QSsl::Dsa ? "DSA" : "EC"))
@@ -573,7 +580,7 @@ void tst_QSslKey::passphraseChecks()
QVERIFY(keyFile.exists());
{
if (!keyFile.isOpen())
- keyFile.open(QIODevice::ReadOnly);
+ QVERIFY(keyFile.open(QIODevice::ReadOnly));
else
keyFile.reset();
QSslKey key(&keyFile,QSsl::Rsa,QSsl::Pem, QSsl::PrivateKey);
@@ -581,7 +588,7 @@ void tst_QSslKey::passphraseChecks()
}
{
if (!keyFile.isOpen())
- keyFile.open(QIODevice::ReadOnly);
+ QVERIFY(keyFile.open(QIODevice::ReadOnly));
else
keyFile.reset();
QSslKey key(&keyFile,QSsl::Rsa,QSsl::Pem, QSsl::PrivateKey, "");
@@ -589,7 +596,7 @@ void tst_QSslKey::passphraseChecks()
}
{
if (!keyFile.isOpen())
- keyFile.open(QIODevice::ReadOnly);
+ QVERIFY(keyFile.open(QIODevice::ReadOnly));
else
keyFile.reset();
QSslKey key(&keyFile,QSsl::Rsa,QSsl::Pem, QSsl::PrivateKey, "WRONG!");
@@ -597,7 +604,7 @@ void tst_QSslKey::passphraseChecks()
}
{
if (!keyFile.isOpen())
- keyFile.open(QIODevice::ReadOnly);
+ QVERIFY(keyFile.open(QIODevice::ReadOnly));
else
keyFile.reset();
QSslKey key(&keyFile,QSsl::Rsa,QSsl::Pem, QSsl::PrivateKey, passphrase);
@@ -615,7 +622,7 @@ void tst_QSslKey::noPassphraseChecks()
QFile keyFile(fileName);
{
if (!keyFile.isOpen())
- keyFile.open(QIODevice::ReadOnly);
+ QVERIFY(keyFile.open(QIODevice::ReadOnly));
else
keyFile.reset();
QSslKey key(&keyFile,QSsl::Rsa,QSsl::Pem, QSsl::PrivateKey);
@@ -623,7 +630,7 @@ void tst_QSslKey::noPassphraseChecks()
}
{
if (!keyFile.isOpen())
- keyFile.open(QIODevice::ReadOnly);
+ QVERIFY(keyFile.open(QIODevice::ReadOnly));
else
keyFile.reset();
QSslKey key(&keyFile,QSsl::Rsa,QSsl::Pem, QSsl::PrivateKey, "");
@@ -631,7 +638,7 @@ void tst_QSslKey::noPassphraseChecks()
}
{
if (!keyFile.isOpen())
- keyFile.open(QIODevice::ReadOnly);
+ QVERIFY(keyFile.open(QIODevice::ReadOnly));
else
keyFile.reset();
QSslKey key(&keyFile,QSsl::Rsa,QSsl::Pem, QSsl::PrivateKey, "xxx");
diff --git a/tests/auto/network/ssl/qsslserver/CMakeLists.txt b/tests/auto/network/ssl/qsslserver/CMakeLists.txt
index 584a031622..5957b2720e 100644
--- a/tests/auto/network/ssl/qsslserver/CMakeLists.txt
+++ b/tests/auto/network/ssl/qsslserver/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qsslserver LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
if(NOT QT_FEATURE_private_tests)
return()
endif()
@@ -19,4 +25,5 @@ qt_internal_add_test(tst_qsslserver
Qt::CorePrivate
Qt::NetworkPrivate
TESTDATA ${test_data}
+ BUNDLE_ANDROID_OPENSSL_LIBS
)
diff --git a/tests/auto/network/ssl/qsslserver/tst_qsslserver.cpp b/tests/auto/network/ssl/qsslserver/tst_qsslserver.cpp
index 77a86ceac3..26d3a50a5b 100644
--- a/tests/auto/network/ssl/qsslserver/tst_qsslserver.cpp
+++ b/tests/auto/network/ssl/qsslserver/tst_qsslserver.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
#include <QDebug>
@@ -142,15 +142,15 @@ void tst_QSslServer::testOneSuccessfulConnection()
QVERIFY(server.startedEncryptionHandshakeSpy.isValid());
// Check that no connections has occurred
- QCOMPARE(server.sslErrorsSpy.count(), 0);
- QCOMPARE(server.peerVerifyErrorSpy.count(), 0);
- QCOMPARE(server.errorOccurredSpy.count(), 0);
- QCOMPARE(server.pendingConnectionAvailableSpy.count(), 0);
- QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.count(), 0);
- QCOMPARE(server.alertSentSpy.count(), 0);
- QCOMPARE(server.alertReceivedSpy.count(), 0);
- QCOMPARE(server.handshakeInterruptedOnErrorSpy.count(), 0);
- QCOMPARE(server.startedEncryptionHandshakeSpy.count(), 0);
+ QCOMPARE(server.sslErrorsSpy.size(), 0);
+ QCOMPARE(server.peerVerifyErrorSpy.size(), 0);
+ QCOMPARE(server.errorOccurredSpy.size(), 0);
+ QCOMPARE(server.pendingConnectionAvailableSpy.size(), 0);
+ QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.size(), 0);
+ QCOMPARE(server.alertSentSpy.size(), 0);
+ QCOMPARE(server.alertReceivedSpy.size(), 0);
+ QCOMPARE(server.handshakeInterruptedOnErrorSpy.size(), 0);
+ QCOMPARE(server.startedEncryptionHandshakeSpy.size(), 0);
// Connect client
QSslSocket client;
@@ -187,15 +187,15 @@ void tst_QSslServer::testOneSuccessfulConnection()
loop.exec();
// Check that one encrypted connection has occurred without error
- QCOMPARE(server.sslErrorsSpy.count(), 0);
- QCOMPARE(server.peerVerifyErrorSpy.count(), 0);
- QCOMPARE(server.errorOccurredSpy.count(), 0);
- QCOMPARE(server.pendingConnectionAvailableSpy.count(), 1);
- QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.count(), 0);
- QCOMPARE(server.alertSentSpy.count(), 0);
- QCOMPARE(server.alertReceivedSpy.count(), 0);
- QCOMPARE(server.handshakeInterruptedOnErrorSpy.count(), 0);
- QCOMPARE(server.startedEncryptionHandshakeSpy.count(), 1);
+ QCOMPARE(server.sslErrorsSpy.size(), 0);
+ QCOMPARE(server.peerVerifyErrorSpy.size(), 0);
+ QCOMPARE(server.errorOccurredSpy.size(), 0);
+ QCOMPARE(server.pendingConnectionAvailableSpy.size(), 1);
+ QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.size(), 0);
+ QCOMPARE(server.alertSentSpy.size(), 0);
+ QCOMPARE(server.alertReceivedSpy.size(), 0);
+ QCOMPARE(server.handshakeInterruptedOnErrorSpy.size(), 0);
+ QCOMPARE(server.startedEncryptionHandshakeSpy.size(), 1);
// Check client socket
QVERIFY(client.isEncrypted());
@@ -224,16 +224,16 @@ void tst_QSslServer::testSelfSignedCertificateRejectedByServer()
loop.exec();
// Check that one encrypted connection has failed
- QCOMPARE(server.sslErrorsSpy.count(), 1);
- QCOMPARE(server.peerVerifyErrorSpy.count(), 1);
- QCOMPARE(server.errorOccurredSpy.count(), 1);
- QCOMPARE(server.pendingConnectionAvailableSpy.count(), 0);
- QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.count(), 0);
- QCOMPARE(server.alertSentSpy.count(),
+ QCOMPARE(server.sslErrorsSpy.size(), 1);
+ QCOMPARE(server.peerVerifyErrorSpy.size(), 1);
+ QCOMPARE(server.errorOccurredSpy.size(), 1);
+ QCOMPARE(server.pendingConnectionAvailableSpy.size(), 0);
+ QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.size(), 0);
+ QCOMPARE(server.alertSentSpy.size(),
isTestingOpenSsl ? 1 : 0); // OpenSSL only signal
- QCOMPARE(server.alertReceivedSpy.count(), 0);
- QCOMPARE(server.handshakeInterruptedOnErrorSpy.count(), 0);
- QCOMPARE(server.startedEncryptionHandshakeSpy.count(), 1);
+ QCOMPARE(server.alertReceivedSpy.size(), 0);
+ QCOMPARE(server.handshakeInterruptedOnErrorSpy.size(), 0);
+ QCOMPARE(server.startedEncryptionHandshakeSpy.size(), 1);
// Type of certificate error to expect
const auto certificateError =
@@ -241,13 +241,13 @@ void tst_QSslServer::testSelfSignedCertificateRejectedByServer()
// Check the sslErrorsSpy
const auto sslErrorsSpyErrors =
- qvariant_cast<QList<QSslError>>(qAsConst(server.sslErrorsSpy).first()[1]);
+ qvariant_cast<QList<QSslError>>(std::as_const(server.sslErrorsSpy).first()[1]);
QCOMPARE(sslErrorsSpyErrors.size(), 1);
QCOMPARE(sslErrorsSpyErrors.first().error(), certificateError);
// Check the peerVerifyErrorSpy
const auto peerVerifyErrorSpyError =
- qvariant_cast<QSslError>(qAsConst(server.peerVerifyErrorSpy).first()[1]);
+ qvariant_cast<QSslError>(std::as_const(server.peerVerifyErrorSpy).first()[1]);
QCOMPARE(peerVerifyErrorSpyError.error(), certificateError);
// Check client socket
@@ -290,32 +290,32 @@ void tst_QSslServer::testSelfSignedCertificateRejectedByClient()
QTcpSocket *connection = server.server.nextPendingConnection();
if (connection == nullptr) {
// Client disconnected before connection accepted by server
- QCOMPARE(server.sslErrorsSpy.count(), 0);
- QCOMPARE(server.peerVerifyErrorSpy.count(), 0);
- QCOMPARE(server.errorOccurredSpy.count(), 1); // Client rejected first
- QCOMPARE(server.pendingConnectionAvailableSpy.count(), 0);
- QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.count(), 0);
- QCOMPARE(server.alertSentSpy.count(), 0);
- QCOMPARE(server.alertReceivedSpy.count(),
+ QCOMPARE(server.sslErrorsSpy.size(), 0);
+ QCOMPARE(server.peerVerifyErrorSpy.size(), 0);
+ QCOMPARE(server.errorOccurredSpy.size(), 1); // Client rejected first
+ QCOMPARE(server.pendingConnectionAvailableSpy.size(), 0);
+ QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.size(), 0);
+ QCOMPARE(server.alertSentSpy.size(), 0);
+ QCOMPARE(server.alertReceivedSpy.size(),
isTestingOpenSsl ? 1 : 0); // OpenSSL only signal
- QCOMPARE(server.handshakeInterruptedOnErrorSpy.count(), 0);
- QCOMPARE(server.startedEncryptionHandshakeSpy.count(), 1);
+ QCOMPARE(server.handshakeInterruptedOnErrorSpy.size(), 0);
+ QCOMPARE(server.startedEncryptionHandshakeSpy.size(), 1);
const auto errrOccuredSpyError = qvariant_cast<QAbstractSocket::SocketError>(
- qAsConst(server.errorOccurredSpy).first()[1]);
+ std::as_const(server.errorOccurredSpy).first()[1]);
QCOMPARE(errrOccuredSpyError, socketError);
} else {
// Client disconnected after connection accepted by server
- QCOMPARE(server.sslErrorsSpy.count(), 0);
- QCOMPARE(server.peerVerifyErrorSpy.count(), 0);
- QCOMPARE(server.errorOccurredSpy.count(), 0); // Server accepted first
- QCOMPARE(server.pendingConnectionAvailableSpy.count(), 1);
- QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.count(), 0);
- QCOMPARE(server.alertSentSpy.count(), 0);
- QCOMPARE(server.alertReceivedSpy.count(),
+ QCOMPARE(server.sslErrorsSpy.size(), 0);
+ QCOMPARE(server.peerVerifyErrorSpy.size(), 0);
+ QCOMPARE(server.errorOccurredSpy.size(), 0); // Server accepted first
+ QCOMPARE(server.pendingConnectionAvailableSpy.size(), 1);
+ QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.size(), 0);
+ QCOMPARE(server.alertSentSpy.size(), 0);
+ QCOMPARE(server.alertReceivedSpy.size(),
isTestingOpenSsl ? 1 : 0); // OpenSSL only signal
- QCOMPARE(server.handshakeInterruptedOnErrorSpy.count(), 0);
- QCOMPARE(server.startedEncryptionHandshakeSpy.count(), 1);
+ QCOMPARE(server.handshakeInterruptedOnErrorSpy.size(), 0);
+ QCOMPARE(server.startedEncryptionHandshakeSpy.size(), 1);
QCOMPARE(connection->state(), QAbstractSocket::UnconnectedState);
QCOMPARE(connection->error(), socketError);
@@ -325,12 +325,12 @@ void tst_QSslServer::testSelfSignedCertificateRejectedByClient()
}
// Check that client has rejected server
- QCOMPARE(clientConnectedSpy.count(), 1);
- QCOMPARE(clientHostFoundSpy.count(), 1);
- QCOMPARE(clientDisconnectedSpy.count(), 1);
- QCOMPARE(clientConnectionEncryptedSpy.count(), 0);
- QCOMPARE(clientSslErrorsSpy.count(), isTestingOpenSsl ? 0 : 1);
- QCOMPARE(clientErrorOccurredSpy.count(), 1);
+ QCOMPARE(clientConnectedSpy.size(), 1);
+ QCOMPARE(clientHostFoundSpy.size(), 1);
+ QCOMPARE(clientDisconnectedSpy.size(), 1);
+ QCOMPARE(clientConnectionEncryptedSpy.size(), 0);
+ QCOMPARE(clientSslErrorsSpy.size(), isTestingOpenSsl ? 0 : 1);
+ QCOMPARE(clientErrorOccurredSpy.size(), 1);
// Check client socket
QVERIFY(!client.isEncrypted());
@@ -364,15 +364,15 @@ void tst_QSslServer::testHandshakeInterruptedOnError()
loop.exec();
// Check that client certificate causes handshake interrupted signal to be emitted
- QCOMPARE(server.sslErrorsSpy.count(), 0);
- QCOMPARE(server.peerVerifyErrorSpy.count(), 0);
- QCOMPARE(server.errorOccurredSpy.count(), 1);
- QCOMPARE(server.pendingConnectionAvailableSpy.count(), 0);
- QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.count(), 0);
- QCOMPARE(server.alertSentSpy.count(), 1);
- QCOMPARE(server.alertReceivedSpy.count(), 0);
- QCOMPARE(server.handshakeInterruptedOnErrorSpy.count(), 1);
- QCOMPARE(server.startedEncryptionHandshakeSpy.count(), 1);
+ QCOMPARE(server.sslErrorsSpy.size(), 0);
+ QCOMPARE(server.peerVerifyErrorSpy.size(), 0);
+ QCOMPARE(server.errorOccurredSpy.size(), 1);
+ QCOMPARE(server.pendingConnectionAvailableSpy.size(), 0);
+ QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.size(), 0);
+ QCOMPARE(server.alertSentSpy.size(), 1);
+ QCOMPARE(server.alertReceivedSpy.size(), 0);
+ QCOMPARE(server.handshakeInterruptedOnErrorSpy.size(), 1);
+ QCOMPARE(server.startedEncryptionHandshakeSpy.size(), 1);
}
void tst_QSslServer::testPreSharedKeyAuthenticationRequired()
@@ -422,15 +422,15 @@ void tst_QSslServer::testPreSharedKeyAuthenticationRequired()
loop.exec();
// Check that server is connected
- QCOMPARE(server.sslErrorsSpy.count(), 1);
- QCOMPARE(server.peerVerifyErrorSpy.count(), 1);
- QCOMPARE(server.errorOccurredSpy.count(), 0);
- QCOMPARE(server.pendingConnectionAvailableSpy.count(), 1);
- QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.count(), 1);
- QCOMPARE(server.alertSentSpy.count(), 0);
- QCOMPARE(server.alertReceivedSpy.count(), 0);
- QCOMPARE(server.handshakeInterruptedOnErrorSpy.count(), 0);
- QCOMPARE(server.startedEncryptionHandshakeSpy.count(), 1);
+ QCOMPARE(server.sslErrorsSpy.size(), 1);
+ QCOMPARE(server.peerVerifyErrorSpy.size(), 1);
+ QCOMPARE(server.errorOccurredSpy.size(), 0);
+ QCOMPARE(server.pendingConnectionAvailableSpy.size(), 1);
+ QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.size(), 1);
+ QCOMPARE(server.alertSentSpy.size(), 0);
+ QCOMPARE(server.alertReceivedSpy.size(), 0);
+ QCOMPARE(server.handshakeInterruptedOnErrorSpy.size(), 0);
+ QCOMPARE(server.startedEncryptionHandshakeSpy.size(), 1);
// Check client socket
QVERIFY(client.isEncrypted());
@@ -457,7 +457,7 @@ void tst_QSslServer::plaintextClient()
socket.write("Hello World!");
socket.waitForBytesWritten();
// ... and quickly get disconnected:
- QTRY_COMPARE_GT(socketDisconnectedSpy.count(), 0);
+ QTRY_COMPARE_GT(socketDisconnectedSpy.size(), 0);
QCOMPARE(socket.state(), QAbstractSocket::SocketState::UnconnectedState);
}
diff --git a/tests/auto/network/ssl/qsslsocket/BLACKLIST b/tests/auto/network/ssl/qsslsocket/BLACKLIST
index 749c59d968..b990516676 100644
--- a/tests/auto/network/ssl/qsslsocket/BLACKLIST
+++ b/tests/auto/network/ssl/qsslsocket/BLACKLIST
@@ -1,11 +1,6 @@
[deprecatedProtocols]
windows
-[spontaneousWrite]
-windows-7sp1
[connectToHostEncrypted]
macos
-[setSslConfiguration]
-windows-10 msvc-2015
-windows-7sp1
[connectToHostEncryptedWithVerificationPeerName]
macos
diff --git a/tests/auto/network/ssl/qsslsocket/CMakeLists.txt b/tests/auto/network/ssl/qsslsocket/CMakeLists.txt
index 8a7a069edd..456deacb60 100644
--- a/tests/auto/network/ssl/qsslsocket/CMakeLists.txt
+++ b/tests/auto/network/ssl/qsslsocket/CMakeLists.txt
@@ -1,7 +1,11 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qsslsocket.pro.
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qsslsocket LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
if(NOT QT_FEATURE_private_tests)
return()
@@ -22,20 +26,11 @@ qt_internal_add_test(tst_qsslsocket
Qt::NetworkPrivate
Qt::TestPrivate
TESTDATA ${test_data}
- QT_TEST_SERVER_LIST "squid" "danted" "cyrus" "apache2" "echo" # special case
+ QT_TEST_SERVER_LIST "squid" "danted" "cyrus" "apache2" "echo"
+ BUNDLE_ANDROID_OPENSSL_LIBS
)
-#### Keys ignored in scope 1:.:.:qsslsocket.pro:<TRUE>:
-# _REQUIREMENTS = "qtConfig(private_tests)"
-
-## Scopes:
-#####################################################################
-
-#### Keys ignored in scope 3:.:.:qsslsocket.pro:(CMAKE_BUILD_TYPE STREQUAL Debug):
-# DESTDIR = "debug"
-
-#### Keys ignored in scope 4:.:.:qsslsocket.pro:else:
-# DESTDIR = "release"
-
-#### Keys ignored in scope 5:.:.:qsslsocket.pro:LINUX:
-# QT_TEST_SERVER_LIST = "squid" "danted" "cyrus" "apache2" "echo"
+qt_internal_extend_target(tst_qsslsocket CONDITION QT_FEATURE_private_tests AND QT_FEATURE_openssl_linked
+ LIBRARIES
+ WrapOpenSSL::WrapOpenSSL
+)
diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
index 3b0f315060..b45d6b5d8f 100644
--- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
+++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
@@ -1,6 +1,6 @@
// Copyright (C) 2021 The Qt Company Ltd.
// Copyright (C) 2014 Governikus GmbH & Co. KG.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtNetwork/private/qtnetworkglobal_p.h>
@@ -43,6 +43,8 @@
#include "private/qsslsocket_p.h"
#include "private/qsslconfiguration_p.h"
+using namespace std::chrono_literals;
+
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
// make these enum values available without causing deprecation warnings:
@@ -164,9 +166,7 @@ private slots:
void protocol();
void protocolServerSide_data();
void protocolServerSide();
-#if QT_CONFIG(openssl)
void serverCipherPreferences();
-#endif
void setCaCertificates();
void setLocalCertificate();
void localCertificateChain();
@@ -291,6 +291,7 @@ private:
QSslSocket *socket;
QList<QSslError> storedExpectedSslErrors;
bool isTestingOpenSsl = false;
+ bool isSecurityLevel0Required = false;
bool opensslResolved = false;
bool isTestingSecureTransport = false;
bool isTestingSchannel = false;
@@ -410,6 +411,9 @@ void tst_QSslSocket::initTestCase()
flukeCertificateError = QSslError::SelfSignedCertificate;
#if QT_CONFIG(openssl)
opensslResolved = qt_auto_test_resolve_OpenSSL_symbols();
+ // This is where OpenSSL moved several protocols under
+ // non-default (0) security level (the default is 1).
+ isSecurityLevel0Required = OPENSSL_VERSION_NUMBER >= 0x30100010;
#else
opensslResolved = false; // Not 'unused variable' anymore.
#endif
@@ -808,6 +812,10 @@ void tst_QSslSocket::simpleConnect()
if (!QSslSocket::supportsSsl())
return;
+ // Starting from OpenSSL v 3.1.1 deprecated protocol versions (we want to use when connecting) are not available by default.
+ if (isSecurityLevel0Required)
+ QSKIP("Testing with OpenSSL backend, but security level 0 is required for TLS v1.1 or earlier");
+
QFETCH_GLOBAL(bool, setProxy);
if (setProxy)
return;
@@ -836,30 +844,30 @@ void tst_QSslSocket::simpleConnect()
// Entered connecting state
QCOMPARE(socket.state(), QAbstractSocket::ConnectingState);
- QCOMPARE(connectedSpy.count(), 0);
- QCOMPARE(hostFoundSpy.count(), 1);
- QCOMPARE(disconnectedSpy.count(), 0);
+ QCOMPARE(connectedSpy.size(), 0);
+ QCOMPARE(hostFoundSpy.size(), 1);
+ QCOMPARE(disconnectedSpy.size(), 0);
enterLoop(10);
// Entered connected state
QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
QCOMPARE(socket.mode(), QSslSocket::UnencryptedMode);
QVERIFY(!socket.isEncrypted());
- QCOMPARE(connectedSpy.count(), 1);
- QCOMPARE(hostFoundSpy.count(), 1);
- QCOMPARE(disconnectedSpy.count(), 0);
+ QCOMPARE(connectedSpy.size(), 1);
+ QCOMPARE(hostFoundSpy.size(), 1);
+ QCOMPARE(disconnectedSpy.size(), 0);
// Enter encrypted mode
socket.startClientEncryption();
QCOMPARE(socket.mode(), QSslSocket::SslClientMode);
QVERIFY(!socket.isEncrypted());
- QCOMPARE(connectionEncryptedSpy.count(), 0);
- QCOMPARE(sslErrorsSpy.count(), 0);
+ QCOMPARE(connectionEncryptedSpy.size(), 0);
+ QCOMPARE(sslErrorsSpy.size(), 0);
// Starting handshake
enterLoop(10);
- QCOMPARE(sslErrorsSpy.count(), 1);
- QCOMPARE(connectionEncryptedSpy.count(), 0);
+ QCOMPARE(sslErrorsSpy.size(), 1);
+ QCOMPARE(connectionEncryptedSpy.size(), 0);
QVERIFY(!socket.isEncrypted());
QCOMPARE(socket.state(), QAbstractSocket::UnconnectedState);
}
@@ -869,6 +877,10 @@ void tst_QSslSocket::simpleConnectWithIgnore()
if (!QSslSocket::supportsSsl())
return;
+ // Starting from OpenSSL v 3.1.1 deprecated protocol versions (we want to use when connecting) are not available by default.
+ if (isSecurityLevel0Required)
+ QSKIP("Testing with OpenSSL backend, but security level 0 is required for TLS v1.1 or earlier");
+
QFETCH_GLOBAL(bool, setProxy);
if (setProxy)
return;
@@ -897,10 +909,10 @@ void tst_QSslSocket::simpleConnectWithIgnore()
enterLoop(10);
// Done; encryption should be enabled.
- QCOMPARE(sslErrorsSpy.count(), 1);
+ QCOMPARE(sslErrorsSpy.size(), 1);
QVERIFY(socket.isEncrypted());
QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
- QCOMPARE(encryptedSpy.count(), 1);
+ QCOMPARE(encryptedSpy.size(), 1);
// Wait for incoming data
if (!socket.canReadLine())
@@ -913,6 +925,10 @@ void tst_QSslSocket::simpleConnectWithIgnore()
void tst_QSslSocket::sslErrors_data()
{
+ // Starting from OpenSSL v 3.1.1 deprecated protocol versions (we want to use in 'sslErrors' test) are not available by default.
+ if (isSecurityLevel0Required)
+ QSKIP("Testing with OpenSSL backend, but security level 0 is required for TLS v1.1 or earlier");
+
QTest::addColumn<QString>("host");
QTest::addColumn<int>("port");
@@ -970,7 +986,7 @@ void tst_QSslSocket::sslErrors()
// check the same errors were emitted by sslErrors
QVERIFY(!sslErrorsSpy.isEmpty());
SslErrorList emittedErrors;
- const auto sslErrorsSpyErrors = qvariant_cast<QList<QSslError> >(qAsConst(sslErrorsSpy).first().first());
+ const auto sslErrorsSpyErrors = qvariant_cast<QList<QSslError> >(std::as_const(sslErrorsSpy).first().first());
for (const QSslError &err : sslErrorsSpyErrors)
emittedErrors << err.error();
std::sort(emittedErrors.begin(), emittedErrors.end());
@@ -1019,7 +1035,7 @@ void tst_QSslSocket::ciphers()
QString ciphersAsString;
const auto &supported = sslConfig.supportedCiphers();
for (const auto &cipher : supported) {
- if (cipher.isNull() || !cipher.name().length())
+ if (cipher.isNull() || !cipher.name().size())
continue;
if (ciphers.size() > 0)
ciphersAsString += QStringLiteral(":");
@@ -1233,7 +1249,7 @@ void tst_QSslSocket::peerCertificateChain()
QSslSocketPtr socket = newSocket();
this->socket = socket.data();
QList<QSslCertificate> caCertificates = QSslCertificate::fromPath(httpServerCertChainPath());
- QCOMPARE(caCertificates.count(), 1);
+ QCOMPARE(caCertificates.size(), 1);
auto config = socket->sslConfiguration();
config.addCaCertificates(caCertificates);
socket->setSslConfiguration(config);
@@ -1250,7 +1266,7 @@ void tst_QSslSocket::peerCertificateChain()
QSKIP("Skipping flaky test - See QTBUG-29941");
QList<QSslCertificate> certChain = socket->peerCertificateChain();
- QVERIFY(certChain.count() > 0);
+ QVERIFY(certChain.size() > 0);
QCOMPARE(certChain.first(), socket->peerCertificate());
socket->disconnectFromHost();
@@ -1294,6 +1310,7 @@ void tst_QSslSocket::privateKey()
#if QT_CONFIG(openssl)
void tst_QSslSocket::privateKeyOpaque()
{
+#ifndef OPENSSL_NO_DEPRECATED_3_0
if (!isTestingOpenSsl)
QSKIP("The active TLS backend does not support private opaque keys");
@@ -1327,6 +1344,7 @@ void tst_QSslSocket::privateKeyOpaque()
QFETCH_GLOBAL(bool, setProxy);
if (setProxy && !socket->waitForEncrypted(10000))
QSKIP("Skipping flaky test - See QTBUG-29941");
+#endif // OPENSSL_NO_DEPRECATED_3_0
}
#endif // Feature 'openssl'.
@@ -1643,8 +1661,6 @@ void tst_QSslSocket::protocolServerSide()
QCOMPARE(client.isEncrypted(), works);
}
-#if QT_CONFIG(openssl)
-
void tst_QSslSocket::serverCipherPreferences()
{
if (!isTestingOpenSsl)
@@ -1739,8 +1755,6 @@ void tst_QSslSocket::serverCipherPreferences()
}
}
-#endif // Feature 'openssl'.
-
void tst_QSslSocket::setCaCertificates()
{
@@ -1965,6 +1979,10 @@ void tst_QSslSocket::waitForConnectedEncryptedReadyRead()
if (!QSslSocket::supportsSsl())
return;
+ // Starting from OpenSSL v 3.1.1 deprecated protocol versions (we want to use here) are not available by default.
+ if (isSecurityLevel0Required)
+ QSKIP("Testing with OpenSSL backend, but security level 0 is required for TLS v1.1 or earlier");
+
QSslSocketPtr socket = newSocket();
this->socket = socket.data();
@@ -2818,10 +2836,10 @@ void tst_QSslSocket::closeWhileEmittingSocketError()
// Make sure we have some data buffered so that close will try to flush:
clientSocket.write(QByteArray(1000000, Qt::Uninitialized));
- QTestEventLoop::instance().enterLoopMSecs(1000);
+ QTestEventLoop::instance().enterLoop(1s);
QVERIFY(!QTestEventLoop::instance().timeout());
- QCOMPARE(socketErrorSpy.count(), 1);
+ QCOMPARE(socketErrorSpy.size(), 1);
}
#endif // Feature 'openssl'.
@@ -2918,7 +2936,7 @@ void tst_QSslSocket::ignoreSslErrorsList()
bool expectEncryptionSuccess = (expectedSslErrorSignalCount == 0);
if (socket.waitForEncrypted(10000) != expectEncryptionSuccess)
QSKIP("Skipping flaky test - See QTBUG-29941");
- QCOMPARE(sslErrorsSpy.count(), expectedSslErrorSignalCount);
+ QCOMPARE(sslErrorsSpy.size(), expectedSslErrorSignalCount);
}
void tst_QSslSocket::ignoreSslErrorsListWithSlot_data()
@@ -3076,9 +3094,16 @@ void tst_QSslSocket::blacklistedCertificates()
connect(receiver, SIGNAL(encrypted()), SLOT(exitLoop()));
enterLoop(1);
QList<QSslError> sslErrors = receiver->sslHandshakeErrors();
- QVERIFY(sslErrors.count() > 0);
+ QVERIFY(sslErrors.size() > 0);
// there are more errors (self signed cert and hostname mismatch), but we only care about the blacklist error
- QCOMPARE(sslErrors.at(0).error(), QSslError::CertificateBlacklisted);
+ std::optional<QSslError> blacklistedError;
+ for (const QSslError &error : sslErrors) {
+ if (error.error() == QSslError::CertificateBlacklisted) {
+ blacklistedError = error;
+ break;
+ }
+ }
+ QVERIFY2(blacklistedError, "CertificateBlacklisted error not found!");
}
void tst_QSslSocket::versionAccessors()
@@ -3104,6 +3129,10 @@ void tst_QSslSocket::encryptWithoutConnecting()
void tst_QSslSocket::resume_data()
{
+ // Starting from OpenSSL v 3.1.1 deprecated protocol versions (we want to use in 'resume' test) are not available by default.
+ if (isSecurityLevel0Required)
+ QSKIP("Testing with OpenSSL backend, but security level 0 is required for TLS v1.1 or earlier");
+
QTest::addColumn<bool>("ignoreErrorsAfterPause");
QTest::addColumn<QList<QSslError> >("errorsToIgnore");
QTest::addColumn<bool>("expectSuccess");
@@ -3160,9 +3189,9 @@ void tst_QSslSocket::resume()
QFETCH_GLOBAL(bool, setProxy);
if (setProxy && QTestEventLoop::instance().timeout())
QSKIP("Skipping flaky test - See QTBUG-29941");
- QCOMPARE(sslErrorSpy.count(), 1);
- QCOMPARE(errorSpy.count(), 0);
- QCOMPARE(encryptedSpy.count(), 0);
+ QCOMPARE(sslErrorSpy.size(), 1);
+ QCOMPARE(errorSpy.size(), 0);
+ QCOMPARE(encryptedSpy.size(), 0);
QVERIFY(!socket.isEncrypted());
if (ignoreErrorsAfterPause) {
if (errorsToIgnore.empty())
@@ -3174,15 +3203,15 @@ void tst_QSslSocket::resume()
QTestEventLoop::instance().enterLoop(10);
QVERIFY(!QTestEventLoop::instance().timeout()); // quit by encrypted() or error() signal
if (expectSuccess) {
- QCOMPARE(encryptedSpy.count(), 1);
+ QCOMPARE(encryptedSpy.size(), 1);
QVERIFY(socket.isEncrypted());
- QCOMPARE(errorSpy.count(), 0);
+ QCOMPARE(errorSpy.size(), 0);
socket.disconnectFromHost();
QVERIFY(socket.waitForDisconnected(10000));
} else {
- QCOMPARE(encryptedSpy.count(), 0);
+ QCOMPARE(encryptedSpy.size(), 0);
QVERIFY(!socket.isEncrypted());
- QCOMPARE(errorSpy.count(), 1);
+ QCOMPARE(errorSpy.size(), 1);
QCOMPARE(socket.error(), QAbstractSocket::SslHandshakeFailedError);
}
}
@@ -3369,17 +3398,17 @@ void tst_QSslSocket::qtbug18498_peek2()
bigblock.fill('#', QIODEVICE_BUFFERSIZE + 1024);
QVERIFY(client->write(QByteArray("head")));
QVERIFY(client->write(bigblock));
- QTRY_COMPARE(server->bytesAvailable(), bigblock.length() + 4);
+ QTRY_COMPARE(server->bytesAvailable(), bigblock.size() + 4);
QCOMPARE(server->read(4), QByteArray("head"));
- QCOMPARE(server->peek(bigblock.length()), bigblock);
- b.reserve(bigblock.length());
- b.resize(server->peek(b.data(), bigblock.length()));
+ QCOMPARE(server->peek(bigblock.size()), bigblock);
+ b.reserve(bigblock.size());
+ b.resize(server->peek(b.data(), bigblock.size()));
QCOMPARE(b, bigblock);
//check oversized peek
- QCOMPARE(server->peek(bigblock.length() * 3), bigblock);
- b.reserve(bigblock.length() * 3);
- b.resize(server->peek(b.data(), bigblock.length() * 3));
+ QCOMPARE(server->peek(bigblock.size() * 3), bigblock);
+ b.reserve(bigblock.size() * 3);
+ b.resize(server->peek(b.data(), bigblock.size() * 3));
QCOMPARE(b, bigblock);
QCOMPARE(server->readAll(), bigblock);
@@ -3447,7 +3476,13 @@ void tst_QSslSocket::dhServer()
return;
SslServer server;
- server.ciphers = {QSslCipher("DHE-RSA-AES256-SHA"), QSslCipher("DHE-DSS-AES256-SHA")};
+ QSslCipher rsaCipher("DHE-RSA-AES256-SHA");
+ QSslCipher dssCipher("DHE-DSS-AES256-SHA");
+ if (rsaCipher.isNull())
+ QSKIP("The current backend doesn't support DHE-RSA-AES256-SHA");
+ if (dssCipher.isNull())
+ QSKIP("The current backend doesn't support DHE-DSS-AES256-SHA");
+ server.ciphers = { rsaCipher, dssCipher };
QVERIFY(server.listen());
QEventLoop loop;
@@ -3475,9 +3510,10 @@ void tst_QSslSocket::dhServerCustomParamsNull()
if (setProxy)
return;
+ const QSslCipher cipherWithDH("DHE-RSA-AES256-SHA256");
SslServer server;
- server.ciphers = {QSslCipher("DHE-RSA-AES256-SHA"), QSslCipher("DHE-DSS-AES256-SHA")};
- server.protocol = Test::TlsV1_0;
+ server.ciphers = {cipherWithDH};
+ server.protocol = QSsl::TlsV1_2;
QSslConfiguration cfg = server.config;
cfg.setDiffieHellmanParameters(QSslDiffieHellmanParameters());
@@ -3490,7 +3526,6 @@ void tst_QSslSocket::dhServerCustomParamsNull()
QSslSocket client;
QSslConfiguration config = client.sslConfiguration();
- config.setProtocol(Test::TlsV1_0);
client.setSslConfiguration(config);
socket = &client;
connect(socket, SIGNAL(errorOccurred(QAbstractSocket::SocketError)), &loop, SLOT(quit()));
@@ -3501,20 +3536,25 @@ void tst_QSslSocket::dhServerCustomParamsNull()
loop.exec();
- QVERIFY(client.state() != QAbstractSocket::ConnectedState);
+ QCOMPARE(client.state(), QAbstractSocket::ConnectedState);
+ QCOMPARE(client.sessionCipher(), cipherWithDH);
}
void tst_QSslSocket::dhServerCustomParams()
{
if (!QSslSocket::supportsSsl())
QSKIP("No SSL support");
+ if (!QSslSocket::isClassImplemented(QSsl::ImplementedClass::DiffieHellman))
+ QSKIP("The current backend doesn't support diffie hellman parameters");
QFETCH_GLOBAL(bool, setProxy);
if (setProxy)
return;
SslServer server;
- server.ciphers = {QSslCipher("DHE-RSA-AES256-SHA"), QSslCipher("DHE-DSS-AES256-SHA")};
+ const QSslCipher cipherWithDH("DHE-RSA-AES256-SHA256");
+ server.ciphers = {cipherWithDH};
+ server.protocol = QSsl::TlsV1_2;
QSslConfiguration cfg = server.config;
@@ -3544,7 +3584,8 @@ void tst_QSslSocket::dhServerCustomParams()
loop.exec();
- QVERIFY(client.state() == QAbstractSocket::ConnectedState);
+ QCOMPARE(client.state(), QAbstractSocket::ConnectedState);
+ QCOMPARE(client.sessionCipher(), cipherWithDH);
}
#endif // QT_CONFIG(openssl)
@@ -3560,7 +3601,10 @@ void tst_QSslSocket::ecdhServer()
return;
SslServer server;
- server.ciphers = {QSslCipher("ECDHE-RSA-AES128-SHA")};
+ QSslCipher cipher("ECDHE-RSA-AES128-SHA");
+ if (cipher.isNull())
+ QSKIP("The current backend doesn't support ECDHE-RSA-AES128-SHA");
+ server.ciphers = {cipher};
QVERIFY(server.listen());
QEventLoop loop;
@@ -3715,7 +3759,7 @@ void tst_QSslSocket::verifyClientCertificate()
} else {
QCOMPARE(server.socket->peerCertificate(), clientCerts.first());
if (isTestingSchannel) {
- if (clientCerts.count() == 1 && server.socket->peerCertificateChain().count() == 2) {
+ if (clientCerts.size() == 1 && server.socket->peerCertificateChain().size() == 2) {
QEXPECT_FAIL("",
"Schannel includes the entire chain, not just the leaf and intermediates",
Continue);
@@ -4075,14 +4119,14 @@ void tst_QSslSocket::simplePskConnect()
case PskConnectWrongCredentials:
// provide totally wrong credentials
- provider.setIdentity(PSK_CLIENT_IDENTITY.left(PSK_CLIENT_IDENTITY.length() - 1));
- provider.setPreSharedKey(PSK_CLIENT_PRESHAREDKEY.left(PSK_CLIENT_PRESHAREDKEY.length() - 1));
+ provider.setIdentity(PSK_CLIENT_IDENTITY.left(PSK_CLIENT_IDENTITY.size() - 1));
+ provider.setPreSharedKey(PSK_CLIENT_PRESHAREDKEY.left(PSK_CLIENT_PRESHAREDKEY.size() - 1));
connect(&socket, SIGNAL(preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator*)), &provider, SLOT(providePsk(QSslPreSharedKeyAuthenticator*)));
break;
case PskConnectWrongIdentity:
// right PSK, wrong identity
- provider.setIdentity(PSK_CLIENT_IDENTITY.left(PSK_CLIENT_IDENTITY.length() - 1));
+ provider.setIdentity(PSK_CLIENT_IDENTITY.left(PSK_CLIENT_IDENTITY.size() - 1));
provider.setPreSharedKey(PSK_CLIENT_PRESHAREDKEY);
connect(&socket, SIGNAL(preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator*)), &provider, SLOT(providePsk(QSslPreSharedKeyAuthenticator*)));
break;
@@ -4090,7 +4134,7 @@ void tst_QSslSocket::simplePskConnect()
case PskConnectWrongPreSharedKey:
// right identity, wrong PSK
provider.setIdentity(PSK_CLIENT_IDENTITY);
- provider.setPreSharedKey(PSK_CLIENT_PRESHAREDKEY.left(PSK_CLIENT_PRESHAREDKEY.length() - 1));
+ provider.setPreSharedKey(PSK_CLIENT_PRESHAREDKEY.left(PSK_CLIENT_PRESHAREDKEY.size() - 1));
connect(&socket, SIGNAL(preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator*)), &provider, SLOT(providePsk(QSslPreSharedKeyAuthenticator*)));
break;
@@ -4142,32 +4186,32 @@ void tst_QSslSocket::simplePskConnect()
// Entered connecting state
QCOMPARE(socket.state(), QAbstractSocket::ConnectingState);
- QCOMPARE(connectedSpy.count(), 0);
- QCOMPARE(hostFoundSpy.count(), 1);
- QCOMPARE(disconnectedSpy.count(), 0);
+ QCOMPARE(connectedSpy.size(), 0);
+ QCOMPARE(hostFoundSpy.size(), 1);
+ QCOMPARE(disconnectedSpy.size(), 0);
enterLoop(10);
// Entered connected state
QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
QCOMPARE(socket.mode(), QSslSocket::UnencryptedMode);
QVERIFY(!socket.isEncrypted());
- QCOMPARE(connectedSpy.count(), 1);
- QCOMPARE(hostFoundSpy.count(), 1);
- QCOMPARE(disconnectedSpy.count(), 0);
+ QCOMPARE(connectedSpy.size(), 1);
+ QCOMPARE(hostFoundSpy.size(), 1);
+ QCOMPARE(disconnectedSpy.size(), 0);
// Enter encrypted mode
socket.startClientEncryption();
QCOMPARE(socket.mode(), QSslSocket::SslClientMode);
QVERIFY(!socket.isEncrypted());
- QCOMPARE(connectionEncryptedSpy.count(), 0);
- QCOMPARE(sslErrorsSpy.count(), 0);
- QCOMPARE(peerVerifyErrorSpy.count(), 0);
+ QCOMPARE(connectionEncryptedSpy.size(), 0);
+ QCOMPARE(sslErrorsSpy.size(), 0);
+ QCOMPARE(peerVerifyErrorSpy.size(), 0);
// Start handshake.
enterLoop(10);
// We must get the PSK signal in all cases
- QCOMPARE(pskAuthenticationRequiredSpy.count(), 1);
+ QCOMPARE(pskAuthenticationRequiredSpy.size(), 1);
switch (pskTestType) {
case PskConnectDoNotHandlePsk:
@@ -4176,40 +4220,40 @@ void tst_QSslSocket::simplePskConnect()
case PskConnectWrongIdentity:
case PskConnectWrongPreSharedKey:
// Handshake failure
- QCOMPARE(socketErrorsSpy.count(), 1);
+ QCOMPARE(socketErrorsSpy.size(), 1);
QCOMPARE(qvariant_cast<QAbstractSocket::SocketError>(socketErrorsSpy.at(0).at(0)), QAbstractSocket::SslHandshakeFailedError);
- QCOMPARE(sslErrorsSpy.count(), 0);
- QCOMPARE(peerVerifyErrorSpy.count(), 0);
- QCOMPARE(connectionEncryptedSpy.count(), 0);
+ QCOMPARE(sslErrorsSpy.size(), 0);
+ QCOMPARE(peerVerifyErrorSpy.size(), 0);
+ QCOMPARE(connectionEncryptedSpy.size(), 0);
QVERIFY(!socket.isEncrypted());
break;
case PskConnectRightCredentialsPeerVerifyFailure:
// Peer verification failure
- QCOMPARE(socketErrorsSpy.count(), 1);
+ QCOMPARE(socketErrorsSpy.size(), 1);
QCOMPARE(qvariant_cast<QAbstractSocket::SocketError>(socketErrorsSpy.at(0).at(0)), QAbstractSocket::SslHandshakeFailedError);
- QCOMPARE(sslErrorsSpy.count(), 1);
- QCOMPARE(peerVerifyErrorSpy.count(), 1);
- QCOMPARE(connectionEncryptedSpy.count(), 0);
+ QCOMPARE(sslErrorsSpy.size(), 1);
+ QCOMPARE(peerVerifyErrorSpy.size(), 1);
+ QCOMPARE(connectionEncryptedSpy.size(), 0);
QVERIFY(!socket.isEncrypted());
break;
case PskConnectRightCredentialsVerifyPeer:
// Peer verification failure, but ignore it and keep connecting
- QCOMPARE(socketErrorsSpy.count(), 0);
- QCOMPARE(sslErrorsSpy.count(), 1);
- QCOMPARE(peerVerifyErrorSpy.count(), 1);
- QCOMPARE(connectionEncryptedSpy.count(), 1);
+ QCOMPARE(socketErrorsSpy.size(), 0);
+ QCOMPARE(sslErrorsSpy.size(), 1);
+ QCOMPARE(peerVerifyErrorSpy.size(), 1);
+ QCOMPARE(connectionEncryptedSpy.size(), 1);
QVERIFY(socket.isEncrypted());
QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
break;
case PskConnectRightCredentialsDoNotVerifyPeer:
// No peer verification => no failure
- QCOMPARE(socketErrorsSpy.count(), 0);
- QCOMPARE(sslErrorsSpy.count(), 0);
- QCOMPARE(peerVerifyErrorSpy.count(), 0);
- QCOMPARE(connectionEncryptedSpy.count(), 1);
+ QCOMPARE(socketErrorsSpy.size(), 0);
+ QCOMPARE(sslErrorsSpy.size(), 0);
+ QCOMPARE(peerVerifyErrorSpy.size(), 0);
+ QCOMPARE(connectionEncryptedSpy.size(), 1);
QVERIFY(socket.isEncrypted());
QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
break;
@@ -4250,7 +4294,7 @@ void tst_QSslSocket::simplePskConnect()
}
QCOMPARE(socket.state(), QAbstractSocket::UnconnectedState);
- QCOMPARE(disconnectedSpy.count(), 1);
+ QCOMPARE(disconnectedSpy.size(), 1);
}
void tst_QSslSocket::ephemeralServerKey_data()
@@ -4283,7 +4327,7 @@ void tst_QSslSocket::ephemeralServerKey()
client->connectToHostEncrypted(QHostAddress(QHostAddress::LocalHost).toString(), server.serverPort());
spy.wait();
- QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.size(), 1);
QVERIFY(server.config.ephemeralServerKey().isNull());
QCOMPARE(client->sslConfiguration().ephemeralServerKey().isNull(), emptyKey);
}
@@ -4346,22 +4390,22 @@ void tst_QSslSocket::pskServer()
QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
QCOMPARE(socket.mode(), QSslSocket::UnencryptedMode);
QVERIFY(!socket.isEncrypted());
- QCOMPARE(connectedSpy.count(), 1);
- QCOMPARE(disconnectedSpy.count(), 0);
+ QCOMPARE(connectedSpy.size(), 1);
+ QCOMPARE(disconnectedSpy.size(), 0);
// Enter encrypted mode
socket.startClientEncryption();
QCOMPARE(socket.mode(), QSslSocket::SslClientMode);
QVERIFY(!socket.isEncrypted());
- QCOMPARE(connectionEncryptedSpy.count(), 0);
+ QCOMPARE(connectionEncryptedSpy.size(), 0);
// Start handshake.
enterLoop(10);
// We must get the PSK signal in all cases
- QCOMPARE(pskAuthenticationRequiredSpy.count(), 1);
+ QCOMPARE(pskAuthenticationRequiredSpy.size(), 1);
- QCOMPARE(connectionEncryptedSpy.count(), 1);
+ QCOMPARE(connectionEncryptedSpy.size(), 1);
QVERIFY(socket.isEncrypted());
QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
@@ -4374,7 +4418,7 @@ void tst_QSslSocket::pskServer()
enterLoop(10);
QCOMPARE(socket.state(), QAbstractSocket::UnconnectedState);
- QCOMPARE(disconnectedSpy.count(), 1);
+ QCOMPARE(disconnectedSpy.size(), 1);
}
void tst_QSslSocket::signatureAlgorithm_data()
@@ -4527,7 +4571,7 @@ void tst_QSslSocket::forwardReadChannelFinished()
&QTestEventLoop::instance(), &QTestEventLoop::exitLoop);
socket.connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
enterLoop(10);
- QVERIFY(readChannelFinishedSpy.count());
+ QVERIFY(readChannelFinishedSpy.size());
}
#endif // QT_CONFIG(openssl)
@@ -4549,7 +4593,7 @@ void tst_QSslSocket::unsupportedProtocols()
return;
QFETCH(const QSsl::SslProtocol, unsupportedProtocol);
- const int timeoutMS = 500;
+ constexpr auto timeout = 500ms;
// Test a client socket.
{
// 0. connectToHostEncrypted: client-side, non-blocking API, error is discovered
@@ -4571,7 +4615,7 @@ void tst_QSslSocket::unsupportedProtocols()
QCOMPARE(socket.error(), QAbstractSocket::UnknownSocketError);
socket.connectToHost(QHostAddress::LocalHost, server.serverPort());
- QVERIFY(socket.waitForConnected(timeoutMS));
+ QVERIFY(socket.waitForConnected(int(timeout.count())));
socket.setProtocol(unsupportedProtocol);
socket.startClientEncryption();
@@ -4596,7 +4640,7 @@ void tst_QSslSocket::unsupportedProtocols()
QTcpSocket client;
client.connectToHost(QHostAddress::LocalHost, server.serverPort());
- loop.enterLoopMSecs(timeoutMS);
+ loop.enterLoop(timeout);
QVERIFY(!loop.timeout());
QVERIFY(server.socket);
QCOMPARE(server.socket->error(), QAbstractSocket::SslInvalidUserDataError);
@@ -4703,7 +4747,7 @@ void tst_QSslSocket::alertMissingCertificate()
connect(&clientSocket, &QAbstractSocket::errorOccurred, earlyQuitter);
connect(&server, &SslServer::socketError, earlyQuitter);
- runner.enterLoopMSecs(1000);
+ runner.enterLoop(1s);
if (clientSocket.isEncrypted()) {
// When using TLS 1.3 the client side thinks it is connected very
@@ -4711,11 +4755,11 @@ void tst_QSslSocket::alertMissingCertificate()
// inevitable disconnect.
QCOMPARE(clientSocket.sessionProtocol(), QSsl::TlsV1_3);
connect(&clientSocket, &QSslSocket::disconnected, &runner, &QTestEventLoop::exitLoop);
- runner.enterLoopMSecs(10000);
+ runner.enterLoop(10s);
}
- QVERIFY(serverSpy.count() > 0);
- QVERIFY(clientSpy.count() > 0);
+ QVERIFY(serverSpy.size() > 0);
+ QVERIFY(clientSpy.size() > 0);
QVERIFY(server.socket && !server.socket->isEncrypted());
QVERIFY(!clientSocket.isEncrypted());
}
@@ -4766,11 +4810,11 @@ void tst_QSslSocket::alertInvalidCertificate()
connect(&clientSocket, &QAbstractSocket::errorOccurred, earlyQuitter);
connect(&server, &SslServer::socketError, earlyQuitter);
- runner.enterLoopMSecs(1000);
+ runner.enterLoop(1s);
- QVERIFY(serverSpy.count() > 0);
- QVERIFY(clientSpy.count() > 0);
- QVERIFY(interruptedSpy.count() > 0);
+ QVERIFY(serverSpy.size() > 0);
+ QVERIFY(clientSpy.size() > 0);
+ QVERIFY(interruptedSpy.size() > 0);
QVERIFY(server.socket && !server.socket->isEncrypted());
QVERIFY(!clientSocket.isEncrypted());
}
@@ -4894,17 +4938,17 @@ void tst_QSslSocket::selfSignedCertificates()
connect(&clientSocket, &QAbstractSocket::errorOccurred, earlyQuitter);
connect(&server, &SslServer::socketError, earlyQuitter);
- runner.enterLoopMSecs(1000);
+ runner.enterLoop(1s);
if (clientKnown) {
- QCOMPARE(serverSpy.count(), 0);
- QCOMPARE(clientSpy.count(), 0);
+ QCOMPARE(serverSpy.size(), 0);
+ QCOMPARE(clientSpy.size(), 0);
QVERIFY(server.socket && server.socket->isEncrypted());
QVERIFY(clientSocket.isEncrypted());
} else {
- QVERIFY(serverSpy.count() > 0);
+ QVERIFY(serverSpy.size() > 0);
QEXPECT_FAIL("", "Failing to trigger signal, QTBUG-81661", Continue);
- QVERIFY(clientSpy.count() > 0);
+ QVERIFY(clientSpy.size() > 0);
QVERIFY(server.socket && !server.socket->isEncrypted());
QVERIFY(!clientSocket.isEncrypted());
}
@@ -5032,18 +5076,18 @@ void tst_QSslSocket::pskHandshake()
connect(&clientSocket, &QAbstractSocket::errorOccurred, earlyQuitter);
connect(&server, &SslServer::socketError, earlyQuitter);
- runner.enterLoopMSecs(1000);
+ runner.enterLoop(1s);
if (pskRight) {
- QCOMPARE(serverSpy.count(), 0);
- QCOMPARE(clientSpy.count(), 0);
+ QCOMPARE(serverSpy.size(), 0);
+ QCOMPARE(clientSpy.size(), 0);
QVERIFY(server.socket && server.socket->isEncrypted());
QVERIFY(clientSocket.isEncrypted());
} else {
- QVERIFY(serverSpy.count() > 0);
+ QVERIFY(serverSpy.size() > 0);
QCOMPARE(serverSpy.first().at(0).toInt(), static_cast<int>(QSsl::AlertLevel::Fatal));
QCOMPARE(serverSpy.first().at(1).toInt(), static_cast<int>(QSsl::AlertType::BadRecordMac));
- QVERIFY(clientSpy.count() > 0);
+ QVERIFY(clientSpy.size() > 0);
QCOMPARE(clientSpy.first().at(0).toInt(), static_cast<int>(QSsl::AlertLevel::Fatal));
QCOMPARE(clientSpy.first().at(1).toInt(), static_cast<int>(QSsl::AlertType::BadRecordMac));
QVERIFY(server.socket && !server.socket->isEncrypted());
diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/BLACKLIST b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/BLACKLIST
index 4eea966b13..96d94bd935 100644
--- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/BLACKLIST
+++ b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/BLACKLIST
@@ -1,3 +1,7 @@
# QTBUG-101274
-[onDemandRootCertLoadingMemberMethods:WithoutProxy]
-qnx ci
+# [onDemandRootCertLoadingMemberMethods:WithoutProxy]
+# qnx ci
+
+# QTBUG-63481
+[onDemandRootCertLoadingMemberMethods]
+*
diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/CMakeLists.txt b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/CMakeLists.txt
index 77ebcfeee3..34e026cb8b 100644
--- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/CMakeLists.txt
+++ b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/CMakeLists.txt
@@ -1,7 +1,11 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qsslsocket_onDemandCertificates_member.pro.
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qsslsocket_onDemandCertificates_member LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
if(NOT QT_FEATURE_private_tests)
return()
@@ -17,21 +21,6 @@ qt_internal_add_test(tst_qsslsocket_onDemandCertificates_member
LIBRARIES
Qt::CorePrivate
Qt::NetworkPrivate
- QT_TEST_SERVER_LIST "squid" "danted" # special case
+ QT_TEST_SERVER_LIST "squid" "danted"
+ BUNDLE_ANDROID_OPENSSL_LIBS
)
-
-#### Keys ignored in scope 1:.:.:qsslsocket_onDemandCertificates_member.pro:<TRUE>:
-# _REQUIREMENTS = "qtConfig(private_tests)"
-# testcase.timeout = "300"
-
-## Scopes:
-#####################################################################
-
-#### Keys ignored in scope 3:.:.:qsslsocket_onDemandCertificates_member.pro:(CMAKE_BUILD_TYPE STREQUAL Debug):
-# DESTDIR = "debug"
-
-#### Keys ignored in scope 4:.:.:qsslsocket_onDemandCertificates_member.pro:else:
-# DESTDIR = "release"
-
-#### Keys ignored in scope 5:.:.:qsslsocket_onDemandCertificates_member.pro:LINUX:
-# QT_TEST_SERVER_LIST = "squid" "danted"
diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp
index 95901e7f1e..119891c916 100644
--- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp
+++ b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtNetwork>
@@ -194,6 +194,7 @@ static bool waitForEncrypted(QSslSocket *socket)
void tst_QSslSocket_onDemandCertificates_member::onDemandRootCertLoadingMemberMethods()
{
+#define ERR(socket) socket->errorString().toLatin1()
const QString host("www.qt.io");
// not using any root certs -> should not work
@@ -203,13 +204,13 @@ void tst_QSslSocket_onDemandCertificates_member::onDemandRootCertLoadingMemberMe
sslConfig.setCaCertificates(QList<QSslCertificate>());
socket2->setSslConfiguration(sslConfig);
socket2->connectToHostEncrypted(host, 443);
- QVERIFY(!waitForEncrypted(socket2.data()));
+ QVERIFY2(!waitForEncrypted(socket2.data()), ERR(socket2));
// default: using on demand loading -> should work
QSslSocketPtr socket = newSocket();
this->socket = socket.data();
socket->connectToHostEncrypted(host, 443);
- QVERIFY2(waitForEncrypted(socket.data()), qPrintable(socket->errorString()));
+ QVERIFY2(waitForEncrypted(socket.data()), ERR(socket));
// not using any root certs again -> should not work
QSslSocketPtr socket3 = newSocket();
@@ -218,7 +219,7 @@ void tst_QSslSocket_onDemandCertificates_member::onDemandRootCertLoadingMemberMe
sslConfig.setCaCertificates(QList<QSslCertificate>());
socket3->setSslConfiguration(sslConfig);
socket3->connectToHostEncrypted(host, 443);
- QVERIFY(!waitForEncrypted(socket3.data()));
+ QVERIFY2(!waitForEncrypted(socket3.data()), ERR(socket3));
// setting empty SSL configuration explicitly -> depends on on-demand loading
QSslSocketPtr socket4 = newSocket();
@@ -229,16 +230,20 @@ void tst_QSslSocket_onDemandCertificates_member::onDemandRootCertLoadingMemberMe
#ifdef QT_BUILD_INTERNAL
const bool works = QSslSocketPrivate::rootCertOnDemandLoadingSupported();
#if defined(Q_OS_LINUX) || defined(Q_OS_WIN)
- QCOMPARE(works, true);
+ QVERIFY2(works, ERR(socket4));
#elif defined(Q_OS_MAC)
- QCOMPARE(works, false);
+ QVERIFY2(!works, ERR(socket4));
#endif // other platforms: undecided.
// When we *allow* on-demand loading, we enable it by default; so, on Unix,
// it will work without setting any certificates. Otherwise, the configuration
// contains an empty set of certificates, so on-demand loading shall fail.
- QCOMPARE(waitForEncrypted(socket4.data()), works);
+ const bool result = waitForEncrypted(socket4.data());
+ if (result != works)
+ qDebug() << socket4->errorString();
+ QCOMPARE(waitForEncrypted(socket4.data()), works);
#endif // QT_BUILD_INTERNAL
}
+#undef ERR
#endif // QT_NO_OPENSSL
diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/CMakeLists.txt b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/CMakeLists.txt
index 62af5fb10c..696eec98ee 100644
--- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/CMakeLists.txt
+++ b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/CMakeLists.txt
@@ -1,7 +1,11 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qsslsocket_onDemandCertificates_static.pro.
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qsslsocket_onDemandCertificates_static LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
if(NOT QT_FEATURE_private_tests)
return()
@@ -17,20 +21,6 @@ qt_internal_add_test(tst_qsslsocket_onDemandCertificates_static
LIBRARIES
Qt::CorePrivate
Qt::NetworkPrivate
- QT_TEST_SERVER_LIST "squid" "danted" # special case
+ QT_TEST_SERVER_LIST "squid" "danted"
+ BUNDLE_ANDROID_OPENSSL_LIBS
)
-
-#### Keys ignored in scope 1:.:.:qsslsocket_onDemandCertificates_static.pro:<TRUE>:
-# _REQUIREMENTS = "qtConfig(private_tests)"
-
-## Scopes:
-#####################################################################
-
-#### Keys ignored in scope 3:.:.:qsslsocket_onDemandCertificates_static.pro:(CMAKE_BUILD_TYPE STREQUAL Debug):
-# DESTDIR = "debug"
-
-#### Keys ignored in scope 4:.:.:qsslsocket_onDemandCertificates_static.pro:else:
-# DESTDIR = "release"
-
-#### Keys ignored in scope 5:.:.:qsslsocket_onDemandCertificates_static.pro:LINUX:
-# QT_TEST_SERVER_LIST = "squid" "danted"
diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/tst_qsslsocket_onDemandCertificates_static.cpp b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/tst_qsslsocket_onDemandCertificates_static.cpp
index 95aba0b29c..c5475da581 100644
--- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/tst_qsslsocket_onDemandCertificates_static.cpp
+++ b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/tst_qsslsocket_onDemandCertificates_static.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtNetwork>
diff --git a/tests/auto/network/ssl/shared/qopenssl_symbols.h b/tests/auto/network/ssl/shared/qopenssl_symbols.h
index 13cacc5317..c98e90d424 100644
--- a/tests/auto/network/ssl/shared/qopenssl_symbols.h
+++ b/tests/auto/network/ssl/shared/qopenssl_symbols.h
@@ -1,6 +1,6 @@
// Copyright (C) 2021 The Qt Company Ltd.
// Copyright (C) 2014 BlackBerry Limited. All rights reserved.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
/****************************************************************************
**
@@ -405,7 +405,7 @@ struct LibGreaterThan
{
const auto lhsparts = lhs.split(QLatin1Char('.'));
const auto rhsparts = rhs.split(QLatin1Char('.'));
- Q_ASSERT(lhsparts.count() > 1 && rhsparts.count() > 1);
+ Q_ASSERT(lhsparts.size() > 1 && rhsparts.size() > 1);
// note: checking rhs < lhs, the same as lhs > rhs
return std::lexicographical_compare(rhsparts.begin() + 1, rhsparts.end(),
@@ -481,7 +481,7 @@ QStringList findAllLibs(QLatin1String filter)
QStringList entryList = dir.entryList(filters, QDir::Files);
std::sort(entryList.begin(), entryList.end(), LibGreaterThan());
- for (const QString &entry : qAsConst(entryList))
+ for (const QString &entry : std::as_const(entryList))
found << path + QLatin1Char('/') + entry;
}
@@ -502,6 +502,12 @@ QStringList findAllLibCrypto()
#ifdef Q_OS_WIN
+#if (OPENSSL_VERSION_NUMBER >> 28) < 3
+#define QT_OPENSSL_VERSION "1_1"
+#elif OPENSSL_VERSION_MAJOR == 3 // Starting with 3.0 this define is available
+#define QT_OPENSSL_VERSION "3"
+#endif // > 3 intentionally left undefined
+
struct LoadedOpenSsl {
std::unique_ptr<QSystemLibrary> ssl, crypto;
};
@@ -540,8 +546,9 @@ static LoadedOpenSsl loadOpenSsl()
#define QT_SSL_SUFFIX
#endif
- tryToLoadOpenSslWin32Library(QLatin1String("libssl-1_1" QT_SSL_SUFFIX),
- QLatin1String("libcrypto-1_1" QT_SSL_SUFFIX), result);
+ tryToLoadOpenSslWin32Library(QLatin1String("libssl-" QT_OPENSSL_VERSION QT_SSL_SUFFIX),
+ QLatin1String("libcrypto-" QT_OPENSSL_VERSION QT_SSL_SUFFIX),
+ result);
#undef QT_SSL_SUFFIX
return result;
diff --git a/tests/auto/network/ssl/shared/tlshelpers.h b/tests/auto/network/ssl/shared/tlshelpers.h
index aa5f2c3c58..de3c2ea51a 100644
--- a/tests/auto/network/ssl/shared/tlshelpers.h
+++ b/tests/auto/network/ssl/shared/tlshelpers.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtNetwork/qtnetworkglobal.h>
@@ -12,13 +12,8 @@
#include <QtCore/qstring.h>
#include <QtCore/qglobal.h>
-// TODO: these 'helpers' later to include OpenSSL resolver/sumbols
-// required by some auto-tests.
-
QT_BEGIN_NAMESPACE
-
-
namespace TlsAux {
inline bool classImplemented(QSsl::ImplementedClass cl)