From ac1e88f58a21aea2faef134c8fd8dd6d55e49cd9 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 18 Jun 2024 22:26:51 +0200 Subject: [PATCH] tst_QFormDataBuilder: DRY the moveSemantics() test Packages everything needed to build the actual serialization into a helper function that's parametrized with a function_ref. Said helper provides the function_ref with a default-constructed QFormDataBuilder as an argument to the function, but since we're checking move semantics here, it also expects to receive, via the return type, the builder object to eventually use for building. This need not be the same as the one it originally supplied. If this looks a bit complicated, it's a necessary evil for conveniently rolling out this way of performing the test to the rest of the test functions, to eventually, finally get rid of using QDebug to introspect individual QHttpParts when, in reality, we're only interested in the QHttpMultiPart's wire serialization (iow: the observable behavior). Centralize the QSKIP in the helper function. This increases compile coverage of the rest of the code, but requires QTEST_THROW_ON_SKIP, so add a check for that alongside the QTEST_THROW_ON_FAIL one. Task-number: QTBUG-125985 Change-Id: Ib6217a02159c79f48f0036e90d7bbbf43e69d0ba Reviewed-by: Juha Vuolle (cherry picked from commit 9fcafa715ecb1c6e45fc51d599178bbde3cc1b12) Reviewed-by: Qt Cherry-pick Bot --- .../qformdatabuilder/tst_qformdatabuilder.cpp | 77 ++++++++++++------- 1 file changed, 48 insertions(+), 29 deletions(-) diff --git a/tests/auto/network/access/qformdatabuilder/tst_qformdatabuilder.cpp b/tests/auto/network/access/qformdatabuilder/tst_qformdatabuilder.cpp index af1a581ac5b..e3af27747fd 100644 --- a/tests/auto/network/access/qformdatabuilder/tst_qformdatabuilder.cpp +++ b/tests/auto/network/access/qformdatabuilder/tst_qformdatabuilder.cpp @@ -13,8 +13,44 @@ # error This test requires QTEST_THROW_ON_FAIL being active. #endif +#ifndef QTEST_THROW_ON_SKIP +# error This test requires QTEST_THROW_ON_SKIP being active. +#endif + +#include +#include + using namespace Qt::StringLiterals; +Q_NEVER_INLINE static QByteArray +serialized_impl([[maybe_unused]] qxp::function_ref operations) +{ +#if defined(QT_UNDEFINED_SANITIZER) && !defined(QT_BUILD_INTERNAL) + QSKIP("This test requires -developer-build when --sanitize=undefined is active."); +#else + QFormDataBuilder builder; + + const std::unique_ptr mp = operations(builder).buildMultiPart(); + + auto *device = QHttpMultiPartPrivate::get(mp.get())->device; + QVERIFY(device->open(QIODeviceBase::ReadOnly)); + return device->readAll(); +#endif // QT_BUILD_INTERNAL || !QT_UNDEFINED_SANITIZER +} + +template +static QByteArray serialized(Callable operation) +{ + if constexpr (std::is_void_v>) { + return serialized_impl([&](auto &builder) { + operation(builder); + return std::ref(builder); + }); + } else { + return serialized_impl(std::move(operation)); + } +} + class tst_QFormDataBuilder : public QObject { Q_OBJECT @@ -385,7 +421,6 @@ void tst_QFormDataBuilder::picksUtf8NameEncodingIfAsciiDoesNotSuffice() void tst_QFormDataBuilder::moveSemantics() { -#if defined(QT_BUILD_INTERNAL) || !defined(QT_UNDEFINED_SANITIZER) constexpr QByteArrayView expected = "--boundary_.oOo._4SUrZy7x9lPHMF3fbRSsE15hiWu5Sbmy\r\n" "content-type: text/plain\r\ncontent-disposition: form-data; name=\"text\"; filename=\"rfc3252.txt\"\r\n\r\n" "some text for reference\r\n" @@ -398,13 +433,9 @@ void tst_QFormDataBuilder::moveSemantics() QFile data_file(testData); QVERIFY2(data_file.open(QIODeviceBase::ReadOnly), qPrintable(data_file.errorString())); - QFormDataBuilder qfdb; - qfdb.part("text"_L1).setBodyDevice(&data_file, "rfc3252.txt"); - std::unique_ptr mp = qfdb.buildMultiPart(); - - auto mp_priv = QHttpMultiPartPrivate::get(mp.get()); - QVERIFY(mp_priv->device->open(QIODeviceBase::ReadOnly)); - const QByteArray actual = mp_priv->device->readAll(); + const QByteArray actual = serialized([&](auto &builder) { + builder.part("text"_L1).setBodyDevice(&data_file, "rfc3252.txt"); + }); checkBodyPartsAreEquivalent(expected, actual); } @@ -416,14 +447,10 @@ void tst_QFormDataBuilder::moveSemantics() QFormDataBuilder qfdb; auto &p = qfdb.part("text"_L1); - auto qfdb_moved = std::move(qfdb); - - p.setBodyDevice(&data_file, "rfc3252.txt"); - std::unique_ptr mp = qfdb_moved.buildMultiPart(); - - auto mp_priv = QHttpMultiPartPrivate::get(mp.get()); - QVERIFY(mp_priv->device->open(QIODeviceBase::ReadOnly)); - const QByteArray actual = mp_priv->device->readAll(); + const QByteArray actual = serialized([&, moved = std::move(qfdb)](auto &) mutable { + p.setBodyDevice(&data_file, "rfc3252.txt"); + return std::ref(moved); + }); checkBodyPartsAreEquivalent(expected, actual); } @@ -433,23 +460,15 @@ void tst_QFormDataBuilder::moveSemantics() QFile data_file(testData); QVERIFY2(data_file.open(QIODeviceBase::ReadOnly), qPrintable(data_file.errorString())); - QFormDataBuilder qfdb; - QFormDataBuilder qfdb_moved; + QFormDataBuilder moved; - qfdb.part("text"_L1).setBodyDevice(&data_file, "rfc3252.txt"); - - qfdb_moved = std::move(qfdb); - std::unique_ptr mp = qfdb_moved.buildMultiPart(); - - auto mp_priv = QHttpMultiPartPrivate::get(mp.get()); - QVERIFY(mp_priv->device->open(QIODeviceBase::ReadOnly)); - const QByteArray actual = mp_priv->device->readAll(); + const QByteArray actual = serialized([&](auto &builder) { + builder.part("text"_L1).setBodyDevice(&data_file, "rfc3252.txt"); + return std::ref(moved = std::move(builder)); + }); checkBodyPartsAreEquivalent(expected, actual); } -#else - QSKIP("This test requires -developer-build when --sanitize=undefined is active."); -#endif } QTEST_MAIN(tst_QFormDataBuilder)