mirror of https://github.com/qt/qtgrpc.git
QGrpcCallOptions: transform into implicitly shared value class
As this class is copyable and really looks like a implicitly shared value class transform it into such. Also provide the missing testcase to this class. Task-number: QTBUG-123625 Pick-to: 6.8 Change-Id: Ibdd24155a04b0ba8a622998cbc482428965e2288 Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
This commit is contained in:
parent
88342e4f19
commit
d70fd4b305
|
|
@ -1,10 +1,10 @@
|
||||||
// Copyright (C) 2023 The Qt Company Ltd.
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||||
|
|
||||||
#include <QtGrpc/private/qtgrpcglobal_p.h>
|
|
||||||
#include <QtGrpc/qgrpccalloptions.h>
|
#include <QtGrpc/qgrpccalloptions.h>
|
||||||
|
|
||||||
#include <QtCore/qdebug.h>
|
#include <QtCore/qdebug.h>
|
||||||
|
#include <QtCore/qvariant.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
|
@ -20,22 +20,19 @@ using namespace Qt::StringLiterals;
|
||||||
that are used by gRPC channels to communicate with the services.
|
that are used by gRPC channels to communicate with the services.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class QGrpcCallOptionsPrivate
|
class QGrpcCallOptionsPrivate : public QSharedData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::optional<QGrpcDuration> deadline;
|
std::optional<QGrpcDuration> deadline;
|
||||||
QGrpcMetadata metadata;
|
QGrpcMetadata metadata;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void dPtrDeleter(QGrpcCallOptionsPrivate *ptr)
|
QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QGrpcCallOptionsPrivate)
|
||||||
{
|
|
||||||
delete ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Constructs an empty QGrpcCallOptions object.
|
Constructs an empty QGrpcCallOptions object.
|
||||||
*/
|
*/
|
||||||
QGrpcCallOptions::QGrpcCallOptions() : dPtr(new QGrpcCallOptionsPrivate(), dPtrDeleter)
|
QGrpcCallOptions::QGrpcCallOptions() : d_ptr(new QGrpcCallOptionsPrivate())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,21 +44,13 @@ QGrpcCallOptions::~QGrpcCallOptions() = default;
|
||||||
/*!
|
/*!
|
||||||
Construct a copy of QGrpcCallOptions with \a other object.
|
Construct a copy of QGrpcCallOptions with \a other object.
|
||||||
*/
|
*/
|
||||||
QGrpcCallOptions::QGrpcCallOptions(const QGrpcCallOptions &other)
|
QGrpcCallOptions::QGrpcCallOptions(const QGrpcCallOptions &other) = default;
|
||||||
: dPtr(new QGrpcCallOptionsPrivate(*other.dPtr), dPtrDeleter)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Assigns \a other to this QGrpcCallOptions and returns a reference to this
|
Assigns \a other to this QGrpcCallOptions and returns a reference to this
|
||||||
QGrpcCallOptions.
|
QGrpcCallOptions.
|
||||||
*/
|
*/
|
||||||
QGrpcCallOptions &QGrpcCallOptions::operator=(const QGrpcCallOptions &other)
|
QGrpcCallOptions &QGrpcCallOptions::operator=(const QGrpcCallOptions &other) = default;
|
||||||
{
|
|
||||||
if (this != &other)
|
|
||||||
*dPtr = *other.dPtr;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn QGrpcCallOptions::QGrpcCallOptions(QGrpcCallOptions &&other) noexcept
|
\fn QGrpcCallOptions::QGrpcCallOptions(QGrpcCallOptions &&other) noexcept
|
||||||
|
|
@ -82,6 +71,15 @@ QGrpcCallOptions &QGrpcCallOptions::operator=(const QGrpcCallOptions &other)
|
||||||
value.
|
value.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\since 6.8
|
||||||
|
Constructs a new QVariant object from this QGrpcCallOptions.
|
||||||
|
*/
|
||||||
|
QGrpcCallOptions::operator QVariant() const
|
||||||
|
{
|
||||||
|
return QVariant::fromValue(*this);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\since 6.8
|
\since 6.8
|
||||||
\fn void QGrpcCallOptions::swap(QGrpcCallOptions &other) noexcept
|
\fn void QGrpcCallOptions::swap(QGrpcCallOptions &other) noexcept
|
||||||
|
|
@ -93,7 +91,11 @@ QGrpcCallOptions &QGrpcCallOptions::operator=(const QGrpcCallOptions &other)
|
||||||
*/
|
*/
|
||||||
QGrpcCallOptions &QGrpcCallOptions::setDeadline(QGrpcDuration deadline)
|
QGrpcCallOptions &QGrpcCallOptions::setDeadline(QGrpcDuration deadline)
|
||||||
{
|
{
|
||||||
dPtr->deadline = deadline;
|
if (d_ptr->deadline == deadline)
|
||||||
|
return *this;
|
||||||
|
d_ptr.detach();
|
||||||
|
Q_D(QGrpcCallOptions);
|
||||||
|
d->deadline = deadline;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -105,7 +107,11 @@ QGrpcCallOptions &QGrpcCallOptions::setDeadline(QGrpcDuration deadline)
|
||||||
*/
|
*/
|
||||||
QGrpcCallOptions &QGrpcCallOptions::setMetadata(const QGrpcMetadata &metadata)
|
QGrpcCallOptions &QGrpcCallOptions::setMetadata(const QGrpcMetadata &metadata)
|
||||||
{
|
{
|
||||||
dPtr->metadata = metadata;
|
if (d_ptr->metadata == metadata)
|
||||||
|
return *this;
|
||||||
|
d_ptr.detach();
|
||||||
|
Q_D(QGrpcCallOptions);
|
||||||
|
d->metadata = metadata;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,9 +120,13 @@ QGrpcCallOptions &QGrpcCallOptions::setMetadata(const QGrpcMetadata &metadata)
|
||||||
|
|
||||||
\sa setMetadata()
|
\sa setMetadata()
|
||||||
*/
|
*/
|
||||||
QGrpcCallOptions &QGrpcCallOptions::setMetadata(QGrpcMetadata &&metadata) noexcept
|
QGrpcCallOptions &QGrpcCallOptions::setMetadata(QGrpcMetadata &&metadata)
|
||||||
{
|
{
|
||||||
dPtr->metadata = std::move(metadata);
|
if (d_ptr->metadata == metadata)
|
||||||
|
return *this;
|
||||||
|
d_ptr.detach();
|
||||||
|
Q_D(QGrpcCallOptions);
|
||||||
|
d->metadata = std::move(metadata);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,7 +141,8 @@ QGrpcCallOptions &QGrpcCallOptions::setMetadata(QGrpcMetadata &&metadata) noexce
|
||||||
*/
|
*/
|
||||||
std::optional<QGrpcDuration> QGrpcCallOptions::deadline() const noexcept
|
std::optional<QGrpcDuration> QGrpcCallOptions::deadline() const noexcept
|
||||||
{
|
{
|
||||||
return dPtr->deadline;
|
Q_D(const QGrpcCallOptions);
|
||||||
|
return d->deadline;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -144,12 +155,16 @@ std::optional<QGrpcDuration> QGrpcCallOptions::deadline() const noexcept
|
||||||
*/
|
*/
|
||||||
const QGrpcMetadata &QGrpcCallOptions::metadata() const & noexcept
|
const QGrpcMetadata &QGrpcCallOptions::metadata() const & noexcept
|
||||||
{
|
{
|
||||||
return dPtr->metadata;
|
Q_D(const QGrpcCallOptions);
|
||||||
|
return d->metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
QGrpcMetadata QGrpcCallOptions::metadata() && noexcept
|
QGrpcMetadata QGrpcCallOptions::metadata() &&
|
||||||
{
|
{
|
||||||
return std::move(dPtr->metadata);
|
Q_D(QGrpcCallOptions);
|
||||||
|
if (d->ref.loadRelaxed() != 1) // return copy if shared
|
||||||
|
return { d->metadata };
|
||||||
|
return std::move(d->metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_DEBUG_STREAM
|
#ifndef QT_NO_DEBUG_STREAM
|
||||||
|
|
@ -160,9 +175,8 @@ QGrpcMetadata QGrpcCallOptions::metadata() && noexcept
|
||||||
*/
|
*/
|
||||||
QDebug operator<<(QDebug debug, const QGrpcCallOptions &callOpts)
|
QDebug operator<<(QDebug debug, const QGrpcCallOptions &callOpts)
|
||||||
{
|
{
|
||||||
QDebugStateSaver save(debug);
|
const QDebugStateSaver save(debug);
|
||||||
debug.nospace();
|
debug.nospace().noquote();
|
||||||
debug.noquote();
|
|
||||||
debug << "QGrpcCallOptions(deadline: " << callOpts.deadline()
|
debug << "QGrpcCallOptions(deadline: " << callOpts.deadline()
|
||||||
<< ", metadata: " << callOpts.metadata() << ')';
|
<< ", metadata: " << callOpts.metadata() << ')';
|
||||||
return debug;
|
return debug;
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,19 @@
|
||||||
#include <QtGrpc/qgrpcdefs.h>
|
#include <QtGrpc/qgrpcdefs.h>
|
||||||
#include <QtGrpc/qtgrpcglobal.h>
|
#include <QtGrpc/qtgrpcglobal.h>
|
||||||
|
|
||||||
|
#include <QtCore/qshareddata.h>
|
||||||
|
#include <QtCore/qstringfwd.h>
|
||||||
#include <QtCore/qtclasshelpermacros.h>
|
#include <QtCore/qtclasshelpermacros.h>
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QDebug;
|
class QDebug;
|
||||||
|
class QVariant;
|
||||||
|
|
||||||
class QGrpcCallOptionsPrivate;
|
class QGrpcCallOptionsPrivate;
|
||||||
|
QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QGrpcCallOptionsPrivate, Q_GRPC_EXPORT)
|
||||||
|
|
||||||
class QGrpcCallOptions final
|
class QGrpcCallOptions final
|
||||||
{
|
{
|
||||||
|
|
@ -27,26 +31,32 @@ public:
|
||||||
Q_GRPC_EXPORT QGrpcCallOptions &operator=(const QGrpcCallOptions &other);
|
Q_GRPC_EXPORT QGrpcCallOptions &operator=(const QGrpcCallOptions &other);
|
||||||
|
|
||||||
QGrpcCallOptions(QGrpcCallOptions &&other) noexcept = default;
|
QGrpcCallOptions(QGrpcCallOptions &&other) noexcept = default;
|
||||||
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QGrpcCallOptions)
|
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QGrpcCallOptions)
|
||||||
|
|
||||||
void swap(QGrpcCallOptions &other) noexcept { dPtr.swap(other.dPtr); }
|
Q_GRPC_EXPORT Q_IMPLICIT operator QVariant() const;
|
||||||
|
|
||||||
|
void swap(QGrpcCallOptions &other) noexcept { d_ptr.swap(other.d_ptr); }
|
||||||
|
|
||||||
Q_GRPC_EXPORT QGrpcCallOptions &setDeadline(QGrpcDuration deadline);
|
Q_GRPC_EXPORT QGrpcCallOptions &setDeadline(QGrpcDuration deadline);
|
||||||
Q_GRPC_EXPORT QGrpcCallOptions &setMetadata(const QGrpcMetadata &metadata);
|
Q_GRPC_EXPORT QGrpcCallOptions &setMetadata(const QGrpcMetadata &metadata);
|
||||||
Q_GRPC_EXPORT QGrpcCallOptions &setMetadata(QGrpcMetadata &&metadata) noexcept;
|
Q_GRPC_EXPORT QGrpcCallOptions &setMetadata(QGrpcMetadata &&metadata);
|
||||||
|
|
||||||
[[nodiscard]] Q_GRPC_EXPORT std::optional<QGrpcDuration> deadline() const noexcept;
|
[[nodiscard]] Q_GRPC_EXPORT std::optional<QGrpcDuration> deadline() const noexcept;
|
||||||
[[nodiscard]] Q_GRPC_EXPORT const QGrpcMetadata &metadata() const & noexcept;
|
[[nodiscard]] Q_GRPC_EXPORT const QGrpcMetadata &metadata() const & noexcept;
|
||||||
[[nodiscard]] Q_GRPC_EXPORT QGrpcMetadata metadata() && noexcept;
|
[[nodiscard]] Q_GRPC_EXPORT QGrpcMetadata metadata() &&;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<QGrpcCallOptionsPrivate, void (*)(QGrpcCallOptionsPrivate *)> dPtr;
|
QExplicitlySharedDataPointer<QGrpcCallOptionsPrivate> d_ptr;
|
||||||
|
|
||||||
#ifndef QT_NO_DEBUG_STREAM
|
#ifndef QT_NO_DEBUG_STREAM
|
||||||
friend Q_GRPC_EXPORT QDebug operator<<(QDebug debug, const QGrpcCallOptions &callOpts);
|
friend Q_GRPC_EXPORT QDebug operator<<(QDebug debug, const QGrpcCallOptions &callOpts);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Q_DECLARE_PRIVATE(QGrpcCallOptions)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_SHARED(QGrpcCallOptions)
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // QGRPCALLOPTIONS_H
|
#endif // QGRPCALLOPTIONS_H
|
||||||
|
|
|
||||||
|
|
@ -10,4 +10,5 @@ if(TARGET WrapgRPC::WrapLibgRPC)
|
||||||
add_subdirectory(qgrpchttp2channel)
|
add_subdirectory(qgrpchttp2channel)
|
||||||
add_subdirectory(qgrpcserializationformat)
|
add_subdirectory(qgrpcserializationformat)
|
||||||
add_subdirectory(qgrpcstatus)
|
add_subdirectory(qgrpcstatus)
|
||||||
|
add_subdirectory(qgrpccalloptions)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
# 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_qgrpccalloptions LANGUAGES CXX)
|
||||||
|
find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
qt_internal_add_test(tst_qgrpccalloptions
|
||||||
|
SOURCES
|
||||||
|
tst_qgrpccalloptions.cpp
|
||||||
|
LIBRARIES
|
||||||
|
Qt::Core
|
||||||
|
Qt::Test
|
||||||
|
Qt::Grpc
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,129 @@
|
||||||
|
// Copyright (C) 2024 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||||
|
|
||||||
|
#include <QtGrpc/qgrpccalloptions.h>
|
||||||
|
|
||||||
|
#include <QtTest/qtest.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
|
class QGrpcCallOptionsTest : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void hasSpecialMemberFunctions() const;
|
||||||
|
void hasImplicitQVariant() const;
|
||||||
|
void hasMemberSwap() const;
|
||||||
|
void propertyMetadata() const;
|
||||||
|
void propertyDeadline() const;
|
||||||
|
void streamsToDebug() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
void QGrpcCallOptionsTest::hasSpecialMemberFunctions() const
|
||||||
|
{
|
||||||
|
QGrpcCallOptions o1;
|
||||||
|
QVERIFY(!o1.deadline());
|
||||||
|
QVERIFY(o1.metadata().empty());
|
||||||
|
|
||||||
|
o1.setDeadline(100ms);
|
||||||
|
|
||||||
|
QGrpcCallOptions o2(o1);
|
||||||
|
QCOMPARE_EQ(o1.deadline(), o2.deadline());
|
||||||
|
|
||||||
|
QGrpcCallOptions o3 = o1;
|
||||||
|
QCOMPARE_EQ(o1.deadline(), o3.deadline());
|
||||||
|
|
||||||
|
QGrpcCallOptions o4(std::move(o1));
|
||||||
|
QCOMPARE_EQ(o4.deadline(), o2.deadline());
|
||||||
|
|
||||||
|
o1 = std::move(o4);
|
||||||
|
QCOMPARE_EQ(o1.deadline(), o2.deadline());
|
||||||
|
}
|
||||||
|
|
||||||
|
void QGrpcCallOptionsTest::hasImplicitQVariant() const
|
||||||
|
{
|
||||||
|
QGrpcCallOptions o1;
|
||||||
|
o1.setDeadline(250ms);
|
||||||
|
o1.setMetadata({
|
||||||
|
{ "keyA", "valA" },
|
||||||
|
{ "keyB", "valB" },
|
||||||
|
});
|
||||||
|
|
||||||
|
QVariant v = o1;
|
||||||
|
QCOMPARE_EQ(v.metaType(), QMetaType::fromType<QGrpcCallOptions>());
|
||||||
|
const auto o2 = v.value<QGrpcCallOptions>();
|
||||||
|
QCOMPARE_EQ(o1.metadata(), o2.metadata());
|
||||||
|
QCOMPARE_EQ(o1.deadline(), o2.deadline());
|
||||||
|
}
|
||||||
|
|
||||||
|
void QGrpcCallOptionsTest::hasMemberSwap() const
|
||||||
|
{
|
||||||
|
constexpr QGrpcDuration Dur = 50ms;
|
||||||
|
|
||||||
|
QGrpcCallOptions o1;
|
||||||
|
o1.setDeadline(Dur);
|
||||||
|
QGrpcCallOptions o2;
|
||||||
|
|
||||||
|
QCOMPARE_EQ(o1.deadline(), Dur);
|
||||||
|
QVERIFY(!o2.deadline());
|
||||||
|
o2.swap(o1);
|
||||||
|
QCOMPARE_EQ(o2.deadline(), Dur);
|
||||||
|
QVERIFY(!o1.deadline());
|
||||||
|
swap(o2, o1);
|
||||||
|
QCOMPARE_EQ(o1.deadline(), Dur);
|
||||||
|
QVERIFY(!o2.deadline());
|
||||||
|
}
|
||||||
|
|
||||||
|
void QGrpcCallOptionsTest::propertyMetadata() const
|
||||||
|
{
|
||||||
|
QGrpcMetadata md = {
|
||||||
|
{ "keyA", "valA" },
|
||||||
|
{ "keyB", "valB" },
|
||||||
|
};
|
||||||
|
|
||||||
|
QGrpcCallOptions o1;
|
||||||
|
auto o1Detach = o1;
|
||||||
|
o1.setMetadata(md);
|
||||||
|
QCOMPARE_EQ(o1.metadata(), md);
|
||||||
|
QCOMPARE_NE(o1.metadata(), o1Detach.metadata());
|
||||||
|
|
||||||
|
QGrpcCallOptions o2;
|
||||||
|
auto o2Detach = o2;
|
||||||
|
o2.setMetadata(std::move(md));
|
||||||
|
QCOMPARE_EQ(o2.metadata(), o1.metadata());
|
||||||
|
QCOMPARE_NE(o2.metadata(), o2Detach.metadata());
|
||||||
|
|
||||||
|
QCOMPARE_EQ(std::move(o1).metadata(), o2.metadata());
|
||||||
|
}
|
||||||
|
|
||||||
|
void QGrpcCallOptionsTest::propertyDeadline() const
|
||||||
|
{
|
||||||
|
constexpr QGrpcDuration Dur = 50ms;
|
||||||
|
|
||||||
|
QGrpcCallOptions o1;
|
||||||
|
auto o1Detach = o1;
|
||||||
|
o1.setDeadline(Dur);
|
||||||
|
QCOMPARE_EQ(o1.deadline(), Dur);
|
||||||
|
QCOMPARE_NE(o1.deadline(), o1Detach.deadline());
|
||||||
|
}
|
||||||
|
|
||||||
|
void QGrpcCallOptionsTest::streamsToDebug() const
|
||||||
|
{
|
||||||
|
QGrpcCallOptions o;
|
||||||
|
QString storage;
|
||||||
|
QDebug dbg(&storage);
|
||||||
|
dbg.noquote().nospace();
|
||||||
|
|
||||||
|
dbg << o;
|
||||||
|
QVERIFY(!storage.isEmpty());
|
||||||
|
|
||||||
|
std::unique_ptr<char[]> ustr(QTest::toString(o));
|
||||||
|
QCOMPARE_EQ(storage, QString::fromUtf8(ustr.get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
QTEST_MAIN(QGrpcCallOptionsTest)
|
||||||
|
|
||||||
|
#include "tst_qgrpccalloptions.moc"
|
||||||
Loading…
Reference in New Issue