QDecompressHelper: Add brotli support
Task-number: QTBUG-83269 Change-Id: If23b098ee76a4892e4c2c6ce5c635688d8d9138d Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
This commit is contained in:
parent
af1544bda2
commit
ad1a5bf63f
43
cmake/FindWrapBrotli.cmake
Normal file
43
cmake/FindWrapBrotli.cmake
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
if(TARGET WrapBrotli::WrapBrotliDec)
|
||||||
|
set(WrapBrotli_FOUND ON)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# From VCPKG
|
||||||
|
find_package(unofficial-brotli CONFIG QUIET)
|
||||||
|
if (unofficial-brotli_FOUND)
|
||||||
|
add_library(WrapBrotli::WrapBrotliDec INTERFACE IMPORTED)
|
||||||
|
target_link_libraries(WrapBrotli::WrapBrotliDec INTERFACE unofficial::brotli::brotlidec)
|
||||||
|
|
||||||
|
add_library(WrapBrotli::WrapBrotliEnc INTERFACE IMPORTED)
|
||||||
|
target_link_libraries(WrapBrotli::WrapBrotliEnc INTERFACE unofficial::brotli::brotlienc)
|
||||||
|
|
||||||
|
add_library(WrapBrotli::WrapBrotliCommon INTERFACE IMPORTED)
|
||||||
|
target_link_libraries(WrapBrotli::WrapBrotliCommon INTERFACE unofficial::brotli::brotlicommon)
|
||||||
|
|
||||||
|
set(WrapBrotli_FOUND ON)
|
||||||
|
else()
|
||||||
|
find_package(PkgConfig QUIET)
|
||||||
|
if (PKG_CONFIG_FOUND)
|
||||||
|
pkg_check_modules(libbrotlidec QUIET libbrotlidec IMPORTED_TARGET)
|
||||||
|
if (libbrotlidec_FOUND)
|
||||||
|
add_library(WrapBrotli::WrapBrotliDec INTERFACE IMPORTED)
|
||||||
|
target_link_libraries(WrapBrotli::WrapBrotliDec INTERFACE PkgConfig::libbrotlidec)
|
||||||
|
set(WrapBrotli_FOUND ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
pkg_check_modules(libbrotlienc QUIET libbrotlienc IMPORTED_TARGET)
|
||||||
|
if (libbrotlienc_FOUND)
|
||||||
|
add_library(WrapBrotli::WrapBrotliEnc INTERFACE IMPORTED)
|
||||||
|
target_link_libraries(WrapBrotli::WrapBrotliEnc INTERFACE PkgConfig::libbrotlienc)
|
||||||
|
set(WrapBrotli_FOUND ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
pkg_check_modules(libbrotlicommon QUIET libbrotlicommon IMPORTED_TARGET)
|
||||||
|
if (libbrotlicommon_FOUND)
|
||||||
|
add_library(WrapBrotli::WrapBrotliCommon INTERFACE IMPORTED)
|
||||||
|
target_link_libraries(WrapBrotli::WrapBrotliCommon INTERFACE PkgConfig::libbrotlicommon)
|
||||||
|
set(WrapBrotli_FOUND ON)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
@ -123,6 +123,11 @@ qt_extend_target(Network CONDITION QT_FEATURE_http
|
|||||||
socket/qhttpsocketengine.cpp socket/qhttpsocketengine_p.h
|
socket/qhttpsocketengine.cpp socket/qhttpsocketengine_p.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
qt_extend_target(Network CONDITION QT_FEATURE_brotli AND QT_FEATURE_http
|
||||||
|
LIBRARIES
|
||||||
|
WrapBrotli::WrapBrotliDec
|
||||||
|
)
|
||||||
|
|
||||||
qt_extend_target(Network CONDITION QT_FEATURE_system_zlib
|
qt_extend_target(Network CONDITION QT_FEATURE_system_zlib
|
||||||
LIBRARIES
|
LIBRARIES
|
||||||
ZLIB::ZLIB
|
ZLIB::ZLIB
|
||||||
|
@ -123,6 +123,11 @@ qt_extend_target(Network CONDITION QT_FEATURE_http
|
|||||||
socket/qhttpsocketengine.cpp socket/qhttpsocketengine_p.h
|
socket/qhttpsocketengine.cpp socket/qhttpsocketengine_p.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
qt_extend_target(Network CONDITION QT_FEATURE_brotli AND QT_FEATURE_http
|
||||||
|
LIBRARIES
|
||||||
|
WrapBrotli::WrapBrotliDec
|
||||||
|
)
|
||||||
|
|
||||||
qt_extend_target(Network CONDITION QT_FEATURE_system_zlib
|
qt_extend_target(Network CONDITION QT_FEATURE_system_zlib
|
||||||
LIBRARIES
|
LIBRARIES
|
||||||
ZLIB::ZLIB
|
ZLIB::ZLIB
|
||||||
|
@ -116,4 +116,8 @@ qtConfig(http) {
|
|||||||
access/qhttpthreaddelegate_p.h \
|
access/qhttpthreaddelegate_p.h \
|
||||||
access/qnetworkreplyhttpimpl_p.h \
|
access/qnetworkreplyhttpimpl_p.h \
|
||||||
access/qhttp2configuration.h
|
access/qhttp2configuration.h
|
||||||
|
|
||||||
|
qtConfig(brotli) {
|
||||||
|
QMAKE_USE_PRIVATE += brotli
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,10 @@
|
|||||||
|
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
|
#if QT_CONFIG(brotli)
|
||||||
|
# include <brotli/decode.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@ -57,6 +61,9 @@ struct ContentEncodingMapping
|
|||||||
constexpr ContentEncodingMapping contentEncodingMapping[] {
|
constexpr ContentEncodingMapping contentEncodingMapping[] {
|
||||||
{ "deflate", QDecompressHelper::Deflate },
|
{ "deflate", QDecompressHelper::Deflate },
|
||||||
{ "gzip", QDecompressHelper::GZip },
|
{ "gzip", QDecompressHelper::GZip },
|
||||||
|
#if QT_CONFIG(brotli)
|
||||||
|
{ "br", QDecompressHelper::Brotli },
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
QDecompressHelper::ContentEncoding encodingFromByteArray(const QByteArray &ce) noexcept
|
QDecompressHelper::ContentEncoding encodingFromByteArray(const QByteArray &ce) noexcept
|
||||||
@ -72,6 +79,13 @@ z_stream *toZlibPointer(void *ptr)
|
|||||||
{
|
{
|
||||||
return static_cast<z_stream_s *>(ptr);
|
return static_cast<z_stream_s *>(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if QT_CONFIG(brotli)
|
||||||
|
BrotliDecoderState *toBrotliPointer(void *ptr)
|
||||||
|
{
|
||||||
|
return static_cast<BrotliDecoderState *>(ptr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QDecompressHelper::isSupportedEncoding(const QByteArray &encoding)
|
bool QDecompressHelper::isSupportedEncoding(const QByteArray &encoding)
|
||||||
@ -134,6 +148,13 @@ bool QDecompressHelper::setEncoding(ContentEncoding ce)
|
|||||||
decoderPointer = inflateStream;
|
decoderPointer = inflateStream;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Brotli:
|
||||||
|
#if QT_CONFIG(brotli)
|
||||||
|
decoderPointer = BrotliDecoderCreateInstance(nullptr, nullptr, nullptr);
|
||||||
|
#else
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (!decoderPointer) {
|
if (!decoderPointer) {
|
||||||
qWarning("Failed to initialize the decoder.");
|
qWarning("Failed to initialize the decoder.");
|
||||||
@ -325,6 +346,9 @@ qsizetype QDecompressHelper::read(char *data, qsizetype maxSize)
|
|||||||
case GZip:
|
case GZip:
|
||||||
bytesRead = readZLib(data, maxSize);
|
bytesRead = readZLib(data, maxSize);
|
||||||
break;
|
break;
|
||||||
|
case Brotli:
|
||||||
|
bytesRead = readBrotli(data, maxSize);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (bytesRead == -1)
|
if (bytesRead == -1)
|
||||||
clear();
|
clear();
|
||||||
@ -369,6 +393,14 @@ void QDecompressHelper::clear()
|
|||||||
delete inflateStream;
|
delete inflateStream;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Brotli: {
|
||||||
|
#if QT_CONFIG(brotli)
|
||||||
|
BrotliDecoderState *brotliDecoderState = toBrotliPointer(decoderPointer);
|
||||||
|
if (brotliDecoderState)
|
||||||
|
BrotliDecoderDestroyInstance(brotliDecoderState);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
decoderPointer = nullptr;
|
decoderPointer = nullptr;
|
||||||
contentEncoding = None;
|
contentEncoding = None;
|
||||||
@ -489,4 +521,87 @@ qsizetype QDecompressHelper::readZLib(char *data, const qsizetype maxSize)
|
|||||||
return bytesDecoded;
|
return bytesDecoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qsizetype QDecompressHelper::readBrotli(char *data, const qsizetype maxSize)
|
||||||
|
{
|
||||||
|
#if !QT_CONFIG(brotli)
|
||||||
|
Q_UNUSED(data);
|
||||||
|
Q_UNUSED(maxSize);
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
#else
|
||||||
|
qint64 bytesDecoded = 0;
|
||||||
|
|
||||||
|
BrotliDecoderState *brotliDecoderState = toBrotliPointer(decoderPointer);
|
||||||
|
|
||||||
|
while (decoderHasData && bytesDecoded < maxSize) {
|
||||||
|
Q_ASSERT(brotliUnconsumedDataPtr || BrotliDecoderHasMoreOutput(brotliDecoderState));
|
||||||
|
if (brotliUnconsumedDataPtr) {
|
||||||
|
Q_ASSERT(brotliUnconsumedAmount);
|
||||||
|
size_t toRead = std::min(size_t(maxSize - bytesDecoded), brotliUnconsumedAmount);
|
||||||
|
memcpy(data + bytesDecoded, brotliUnconsumedDataPtr, toRead);
|
||||||
|
bytesDecoded += toRead;
|
||||||
|
brotliUnconsumedAmount -= toRead;
|
||||||
|
brotliUnconsumedDataPtr += toRead;
|
||||||
|
if (brotliUnconsumedAmount == 0) {
|
||||||
|
brotliUnconsumedDataPtr = nullptr;
|
||||||
|
decoderHasData = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (BrotliDecoderHasMoreOutput(brotliDecoderState) == BROTLI_TRUE) {
|
||||||
|
brotliUnconsumedDataPtr =
|
||||||
|
BrotliDecoderTakeOutput(brotliDecoderState, &brotliUnconsumedAmount);
|
||||||
|
decoderHasData = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bytesDecoded == maxSize)
|
||||||
|
return bytesDecoded;
|
||||||
|
Q_ASSERT(bytesDecoded < maxSize);
|
||||||
|
|
||||||
|
QByteArray input;
|
||||||
|
if (!compressedDataBuffer.isEmpty())
|
||||||
|
input = compressedDataBuffer.read();
|
||||||
|
const uint8_t *encodedPtr = reinterpret_cast<const uint8_t *>(input.constData());
|
||||||
|
size_t encodedBytesRemaining = input.size();
|
||||||
|
|
||||||
|
uint8_t *decodedPtr = reinterpret_cast<uint8_t *>(data + bytesDecoded);
|
||||||
|
size_t unusedDecodedSize = size_t(maxSize - bytesDecoded);
|
||||||
|
while (unusedDecodedSize > 0) {
|
||||||
|
auto previousUnusedDecodedSize = unusedDecodedSize;
|
||||||
|
BrotliDecoderResult result = BrotliDecoderDecompressStream(
|
||||||
|
brotliDecoderState, &encodedBytesRemaining, &encodedPtr, &unusedDecodedSize,
|
||||||
|
&decodedPtr, nullptr);
|
||||||
|
bytesDecoded += previousUnusedDecodedSize - unusedDecodedSize;
|
||||||
|
|
||||||
|
switch (result) {
|
||||||
|
case BROTLI_DECODER_RESULT_ERROR:
|
||||||
|
qWarning("Brotli error: %s",
|
||||||
|
BrotliDecoderErrorString(BrotliDecoderGetErrorCode(brotliDecoderState)));
|
||||||
|
return -1;
|
||||||
|
case BROTLI_DECODER_RESULT_SUCCESS:
|
||||||
|
BrotliDecoderDestroyInstance(brotliDecoderState);
|
||||||
|
decoderPointer = nullptr;
|
||||||
|
return bytesDecoded;
|
||||||
|
case BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT:
|
||||||
|
if (!compressedDataBuffer.isEmpty()) {
|
||||||
|
input = compressedDataBuffer.read();
|
||||||
|
encodedPtr = reinterpret_cast<const uint8_t *>(input.constData());
|
||||||
|
encodedBytesRemaining = input.size();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return bytesDecoded;
|
||||||
|
case BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT:
|
||||||
|
// Some data is leftover inside the brotli decoder, remember for next time
|
||||||
|
decoderHasData = BrotliDecoderHasMoreOutput(brotliDecoderState);
|
||||||
|
Q_ASSERT(unusedDecodedSize == 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (encodedBytesRemaining) {
|
||||||
|
// Some input was left unused; move back to the buffer
|
||||||
|
input = input.right(QByteArray::size_type(encodedBytesRemaining));
|
||||||
|
compressedDataBuffer.prepend(input);
|
||||||
|
}
|
||||||
|
return bytesDecoded;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -66,6 +66,7 @@ public:
|
|||||||
None,
|
None,
|
||||||
Deflate,
|
Deflate,
|
||||||
GZip,
|
GZip,
|
||||||
|
Brotli,
|
||||||
};
|
};
|
||||||
|
|
||||||
QDecompressHelper() = default;
|
QDecompressHelper() = default;
|
||||||
@ -101,6 +102,7 @@ private:
|
|||||||
qint64 encodedBytesAvailable() const;
|
qint64 encodedBytesAvailable() const;
|
||||||
|
|
||||||
qsizetype readZLib(char *data, qsizetype maxSize);
|
qsizetype readZLib(char *data, qsizetype maxSize);
|
||||||
|
qsizetype readBrotli(char *data, qsizetype maxSize);
|
||||||
|
|
||||||
QByteDataBuffer compressedDataBuffer;
|
QByteDataBuffer compressedDataBuffer;
|
||||||
bool decoderHasData = false;
|
bool decoderHasData = false;
|
||||||
@ -112,6 +114,10 @@ private:
|
|||||||
ContentEncoding contentEncoding = None;
|
ContentEncoding contentEncoding = None;
|
||||||
|
|
||||||
void *decoderPointer = nullptr;
|
void *decoderPointer = nullptr;
|
||||||
|
#if QT_CONFIG(brotli)
|
||||||
|
const uint8_t *brotliUnconsumedDataPtr = nullptr;
|
||||||
|
size_t brotliUnconsumedAmount = 0;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#### Libraries
|
#### Libraries
|
||||||
|
|
||||||
|
qt_find_package(WrapBrotli PROVIDED_TARGETS WrapBrotli::WrapBrotliDec)
|
||||||
qt_find_package(Libproxy PROVIDED_TARGETS PkgConfig::Libproxy MODULE_NAME network QMAKE_LIB libproxy)
|
qt_find_package(Libproxy PROVIDED_TARGETS PkgConfig::Libproxy MODULE_NAME network QMAKE_LIB libproxy)
|
||||||
qt_find_package(WrapOpenSSLHeaders PROVIDED_TARGETS WrapOpenSSLHeaders::WrapOpenSSLHeaders MODULE_NAME network QMAKE_LIB openssl_headers)
|
qt_find_package(WrapOpenSSLHeaders PROVIDED_TARGETS WrapOpenSSLHeaders::WrapOpenSSLHeaders MODULE_NAME network QMAKE_LIB openssl_headers)
|
||||||
# openssl_headers
|
# openssl_headers
|
||||||
@ -366,6 +367,13 @@ qt_feature("networkdiskcache" PUBLIC
|
|||||||
CONDITION QT_FEATURE_temporaryfile
|
CONDITION QT_FEATURE_temporaryfile
|
||||||
)
|
)
|
||||||
qt_feature_definition("networkdiskcache" "QT_NO_NETWORKDISKCACHE" NEGATE VALUE "1")
|
qt_feature_definition("networkdiskcache" "QT_NO_NETWORKDISKCACHE" NEGATE VALUE "1")
|
||||||
|
qt_feature("brotli" PUBLIC
|
||||||
|
SECTION "Networking"
|
||||||
|
LABEL "Brotli Decompression Support"
|
||||||
|
PURPOSE "Support for downloading and decompressing resources compressed with Brotli through QNetworkAccessManager."
|
||||||
|
CONDITION WrapBrotli_FOUND
|
||||||
|
)
|
||||||
|
qt_feature_definition("brotli" "QT_NO_BROTLI" NEGATE VALUE "1")
|
||||||
qt_feature("localserver" PUBLIC
|
qt_feature("localserver" PUBLIC
|
||||||
SECTION "Networking"
|
SECTION "Networking"
|
||||||
LABEL "QLocalServer"
|
LABEL "QLocalServer"
|
||||||
@ -432,6 +440,7 @@ qt_configure_add_summary_entry(ARGS "ftp")
|
|||||||
qt_configure_add_summary_entry(ARGS "sctp")
|
qt_configure_add_summary_entry(ARGS "sctp")
|
||||||
qt_configure_add_summary_entry(ARGS "system-proxies")
|
qt_configure_add_summary_entry(ARGS "system-proxies")
|
||||||
qt_configure_add_summary_entry(ARGS "gssapi")
|
qt_configure_add_summary_entry(ARGS "gssapi")
|
||||||
|
qt_configure_add_summary_entry(ARGS "brotli")
|
||||||
qt_configure_end_summary_section() # end of "Qt Network" section
|
qt_configure_end_summary_section() # end of "Qt Network" section
|
||||||
qt_configure_add_report_entry(
|
qt_configure_add_report_entry(
|
||||||
TYPE NOTE
|
TYPE NOTE
|
||||||
|
@ -25,6 +25,21 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"libraries": {
|
"libraries": {
|
||||||
|
"brotli": {
|
||||||
|
"label": "Brotli Decompression",
|
||||||
|
"test": {
|
||||||
|
"main": [
|
||||||
|
"BrotliDecoderState *state = BrotliDecoderCreateInstance(nullptr, nullptr, nullptr);"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"headers": [
|
||||||
|
"brotli/decode.h"
|
||||||
|
],
|
||||||
|
"sources": [
|
||||||
|
{ "type": "pkgConfig", "args": "libbrotlidec" },
|
||||||
|
"-lbrotlidec"
|
||||||
|
]
|
||||||
|
},
|
||||||
"corewlan": {
|
"corewlan": {
|
||||||
"label": "CoreWLan",
|
"label": "CoreWLan",
|
||||||
"export": "",
|
"export": "",
|
||||||
@ -387,6 +402,13 @@
|
|||||||
"condition": "features.temporaryfile",
|
"condition": "features.temporaryfile",
|
||||||
"output": [ "publicFeature", "feature" ]
|
"output": [ "publicFeature", "feature" ]
|
||||||
},
|
},
|
||||||
|
"brotli": {
|
||||||
|
"label": "Brotli Decompression Support",
|
||||||
|
"purpose": "Support for downloading and decompressing resources compressed with Brotli through QNetworkAccessManager.",
|
||||||
|
"section": "Networking",
|
||||||
|
"condition": "libs.brotli",
|
||||||
|
"output": [ "publicFeature", "feature" ]
|
||||||
|
},
|
||||||
"localserver": {
|
"localserver": {
|
||||||
"label": "QLocalServer",
|
"label": "QLocalServer",
|
||||||
"purpose": "Provides a local socket based server.",
|
"purpose": "Provides a local socket based server.",
|
||||||
@ -479,7 +501,8 @@ For example:
|
|||||||
"ftp",
|
"ftp",
|
||||||
"sctp",
|
"sctp",
|
||||||
"system-proxies",
|
"system-proxies",
|
||||||
"gssapi"
|
"gssapi",
|
||||||
|
"brotli"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -796,6 +796,11 @@ void tst_Http2::contentEncoding_data()
|
|||||||
contentEncodingData.emplace_back(
|
contentEncodingData.emplace_back(
|
||||||
"deflate", QByteArray::fromBase64("eJzLSM3JyVcozy/KSQEAGgsEXQ=="), "hello world");
|
"deflate", QByteArray::fromBase64("eJzLSM3JyVcozy/KSQEAGgsEXQ=="), "hello world");
|
||||||
|
|
||||||
|
#if QT_CONFIG(brotli)
|
||||||
|
contentEncodingData.emplace_back("br", QByteArray::fromBase64("DwWAaGVsbG8gd29ybGQD"),
|
||||||
|
"hello world");
|
||||||
|
#endif
|
||||||
|
|
||||||
// Loop through and add the data...
|
// Loop through and add the data...
|
||||||
for (const auto &data : contentEncodingData) {
|
for (const auto &data : contentEncodingData) {
|
||||||
const char *name = data.contentEncoding.data();
|
const char *name = data.contentEncoding.data();
|
||||||
|
BIN
tests/auto/network/access/qdecompresshelper/4G.br
Normal file
BIN
tests/auto/network/access/qdecompresshelper/4G.br
Normal file
Binary file not shown.
@ -90,6 +90,12 @@ void tst_QDecompressHelper::encodingSupported()
|
|||||||
QVERIFY(accepted.contains("gzip"));
|
QVERIFY(accepted.contains("gzip"));
|
||||||
int expected = 2;
|
int expected = 2;
|
||||||
|
|
||||||
|
#if QT_CONFIG(brotli)
|
||||||
|
QVERIFY(QDecompressHelper::isSupportedEncoding("br"));
|
||||||
|
QVERIFY(accepted.contains("br"));
|
||||||
|
++expected;
|
||||||
|
#endif
|
||||||
|
|
||||||
QCOMPARE(expected, accepted.size());
|
QCOMPARE(expected, accepted.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,6 +121,12 @@ void tst_QDecompressHelper::sharedDecompress_data()
|
|||||||
QTest::newRow("deflate-hello-world")
|
QTest::newRow("deflate-hello-world")
|
||||||
<< QByteArray("deflate") << QByteArray::fromBase64("eJzLSM3JyVcozy/KSQEAGgsEXQ==")
|
<< QByteArray("deflate") << QByteArray::fromBase64("eJzLSM3JyVcozy/KSQEAGgsEXQ==")
|
||||||
<< QByteArray("hello world");
|
<< QByteArray("hello world");
|
||||||
|
|
||||||
|
#if QT_CONFIG(brotli)
|
||||||
|
QTest::newRow("brotli-hello-world")
|
||||||
|
<< QByteArray("br") << QByteArray::fromBase64("DwWAaGVsbG8gd29ybGQD")
|
||||||
|
<< QByteArray("hello world");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QDecompressHelper::decompress_data()
|
void tst_QDecompressHelper::decompress_data()
|
||||||
@ -322,6 +334,10 @@ void tst_QDecompressHelper::decompressBigData_data()
|
|||||||
QTest::newRow("gzip-4G") << QByteArray("gzip") << QString(":/4G.gz") << fourGiB;
|
QTest::newRow("gzip-4G") << QByteArray("gzip") << QString(":/4G.gz") << fourGiB;
|
||||||
QTest::newRow("deflate-5G") << QByteArray("deflate") << QString(":/5GiB.txt.inflate")
|
QTest::newRow("deflate-5G") << QByteArray("deflate") << QString(":/5GiB.txt.inflate")
|
||||||
<< fiveGiB;
|
<< fiveGiB;
|
||||||
|
|
||||||
|
#if QT_CONFIG(brotli)
|
||||||
|
QTest::newRow("brotli-4G") << QByteArray("br") << (srcDir + "/4G.br") << fourGiB;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QDecompressHelper::decompressBigData()
|
void tst_QDecompressHelper::decompressBigData()
|
||||||
|
@ -9264,6 +9264,12 @@ void tst_QNetworkReply::contentEncoding_data()
|
|||||||
QTest::newRow("deflate-hello-world")
|
QTest::newRow("deflate-hello-world")
|
||||||
<< QByteArray("deflate") << QByteArray::fromBase64("eJzLSM3JyVcozy/KSQEAGgsEXQ==")
|
<< QByteArray("deflate") << QByteArray::fromBase64("eJzLSM3JyVcozy/KSQEAGgsEXQ==")
|
||||||
<< QByteArray("hello world");
|
<< QByteArray("hello world");
|
||||||
|
|
||||||
|
#if QT_CONFIG(brotli)
|
||||||
|
QTest::newRow("brotli-hello-world")
|
||||||
|
<< QByteArray("br") << QByteArray::fromBase64("DwWAaGVsbG8gd29ybGQD")
|
||||||
|
<< QByteArray("hello world");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QNetworkReply::contentEncoding()
|
void tst_QNetworkReply::contentEncoding()
|
||||||
|
BIN
tests/benchmarks/network/access/qdecompresshelper/50mb.txt.br
Normal file
BIN
tests/benchmarks/network/access/qdecompresshelper/50mb.txt.br
Normal file
Binary file not shown.
@ -34,7 +34,6 @@ class tst_QDecompressHelper : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void decompress_data();
|
void decompress_data();
|
||||||
void decompress();
|
void decompress();
|
||||||
};
|
};
|
||||||
@ -53,6 +52,10 @@ void tst_QDecompressHelper::decompress_data()
|
|||||||
#ifndef QT_NO_COMPRESS
|
#ifndef QT_NO_COMPRESS
|
||||||
QTest::addRow("gzip") << QByteArray("gzip") << srcDir + QString("50mb.txt.gz");
|
QTest::addRow("gzip") << QByteArray("gzip") << srcDir + QString("50mb.txt.gz");
|
||||||
dataAdded = true;
|
dataAdded = true;
|
||||||
|
#endif
|
||||||
|
#if QT_CONFIG(brotli)
|
||||||
|
QTest::addRow("brotli") << QByteArray("br") << srcDir + QString("50mb.txt.br");
|
||||||
|
dataAdded = true;
|
||||||
#endif
|
#endif
|
||||||
if (!dataAdded)
|
if (!dataAdded)
|
||||||
QSKIP("There's no decompression support");
|
QSKIP("There's no decompression support");
|
||||||
|
@ -372,6 +372,7 @@ _library_map = [
|
|||||||
# 3rd party:
|
# 3rd party:
|
||||||
LibraryMapping("atspi", "ATSPI2", "PkgConfig::ATSPI2"),
|
LibraryMapping("atspi", "ATSPI2", "PkgConfig::ATSPI2"),
|
||||||
LibraryMapping("bluez", "BlueZ", "PkgConfig::BlueZ"),
|
LibraryMapping("bluez", "BlueZ", "PkgConfig::BlueZ"),
|
||||||
|
LibraryMapping("brotli", "WrapBrotli", "WrapBrotli::WrapBrotliDec"),
|
||||||
LibraryMapping("corewlan", None, None),
|
LibraryMapping("corewlan", None, None),
|
||||||
LibraryMapping("cups", "Cups", "Cups::Cups"),
|
LibraryMapping("cups", "Cups", "Cups::Cups"),
|
||||||
LibraryMapping("directfb", "DirectFB", "PkgConfig::DirectFB"),
|
LibraryMapping("directfb", "DirectFB", "PkgConfig::DirectFB"),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user