mirror of
https://github.com/Kistler-Group/sdbus-cpp.git
synced 2025-07-30 18:17:14 +02:00
fix: add missing c-tor for nesting Variants (#467)
This allows nesting variants, i.e. allows a variant to contain another variant as its value. Until now, there was no such possibility, since the default generated copy constructor would be invoked which would create a copy of source variant instead of embed the source variant as a value in the destination variant. The default generated copy constructor is kept, for it makes sense too, but a new tag-based overload is added for embedding the source variant into the destination variant.
This commit is contained in:
committed by
GitHub
parent
02ca7212d1
commit
a1419ee45d
@ -106,6 +106,9 @@ namespace sdbus {
|
||||
// Tag denoting a call where the reply shouldn't be waited for
|
||||
struct dont_expect_reply_t { explicit dont_expect_reply_t() = default; };
|
||||
inline constexpr dont_expect_reply_t dont_expect_reply{};
|
||||
// Tag denoting that the variant shall embed the other variant as its value, instead of creating a copy
|
||||
struct embed_variant_t { explicit embed_variant_t() = default; };
|
||||
inline constexpr embed_variant_t embed_variant{};
|
||||
|
||||
// Helper for static assert
|
||||
template <class... _T> constexpr bool always_false = false;
|
||||
|
@ -67,6 +67,14 @@ namespace sdbus {
|
||||
msg_.seal();
|
||||
}
|
||||
|
||||
Variant(const Variant& value, embed_variant_t) : Variant()
|
||||
{
|
||||
msg_.openVariant<Variant>();
|
||||
msg_ << value;
|
||||
msg_.closeVariant();
|
||||
msg_.seal();
|
||||
}
|
||||
|
||||
template <typename _Struct>
|
||||
explicit Variant(const as_dictionary<_Struct>& value) : Variant()
|
||||
{
|
||||
|
@ -81,3 +81,12 @@ TYPED_TEST(SdbusTestObject, CanAccessAssociatedPropertySetMessageInPropertySetHa
|
||||
ASSERT_THAT(this->m_adaptor->m_propertySetMsg, NotNull());
|
||||
ASSERT_THAT(this->m_adaptor->m_propertySetSender, Not(IsEmpty()));
|
||||
}
|
||||
|
||||
TYPED_TEST(SdbusTestObject, WritesAndReadsReadWriteVariantPropertySuccessfully)
|
||||
{
|
||||
sdbus::Variant newActionValue{5678};
|
||||
|
||||
this->m_proxy->actionVariant(newActionValue);
|
||||
|
||||
ASSERT_THAT(this->m_proxy->actionVariant().template get<int>(), Eq(5678));
|
||||
}
|
||||
|
@ -141,9 +141,10 @@ TYPED_TEST(SdbusTestObject, GetsAllPropertiesViaPropertiesInterface)
|
||||
{
|
||||
const auto properties = this->m_proxy->GetAll(INTERFACE_NAME);
|
||||
|
||||
ASSERT_THAT(properties, SizeIs(3));
|
||||
ASSERT_THAT(properties, SizeIs(4));
|
||||
EXPECT_THAT(properties.at(STATE_PROPERTY).template get<std::string>(), Eq(DEFAULT_STATE_VALUE));
|
||||
EXPECT_THAT(properties.at(ACTION_PROPERTY).template get<uint32_t>(), Eq(DEFAULT_ACTION_VALUE));
|
||||
EXPECT_THAT(properties.at(ACTION_VARIANT_PROPERTY).template get<sdbus::Variant>().template get<std::string>(), Eq(DEFAULT_ACTION_VARIANT_VALUE));
|
||||
EXPECT_THAT(properties.at(BLOCKING_PROPERTY).template get<bool>(), Eq(DEFAULT_BLOCKING_VALUE));
|
||||
}
|
||||
|
||||
@ -161,9 +162,10 @@ TYPED_TEST(SdbusTestObject, GetsAllPropertiesAsynchronouslyViaPropertiesInterfac
|
||||
});
|
||||
const auto properties = future.get();
|
||||
|
||||
ASSERT_THAT(properties, SizeIs(3));
|
||||
ASSERT_THAT(properties, SizeIs(4));
|
||||
EXPECT_THAT(properties.at(STATE_PROPERTY).get<std::string>(), Eq(DEFAULT_STATE_VALUE));
|
||||
EXPECT_THAT(properties.at(ACTION_PROPERTY).get<uint32_t>(), Eq(DEFAULT_ACTION_VALUE));
|
||||
EXPECT_THAT(properties.at(ACTION_VARIANT_PROPERTY).template get<sdbus::Variant>().template get<std::string>(), Eq(DEFAULT_ACTION_VARIANT_VALUE));
|
||||
EXPECT_THAT(properties.at(BLOCKING_PROPERTY).get<bool>(), Eq(DEFAULT_BLOCKING_VALUE));
|
||||
}
|
||||
|
||||
@ -173,9 +175,10 @@ TYPED_TEST(SdbusTestObject, GetsAllPropertiesAsynchronouslyViaPropertiesInterfac
|
||||
|
||||
auto properties = future.get();
|
||||
|
||||
ASSERT_THAT(properties, SizeIs(3));
|
||||
ASSERT_THAT(properties, SizeIs(4));
|
||||
EXPECT_THAT(properties.at(STATE_PROPERTY).template get<std::string>(), Eq(DEFAULT_STATE_VALUE));
|
||||
EXPECT_THAT(properties.at(ACTION_PROPERTY).template get<uint32_t>(), Eq(DEFAULT_ACTION_VALUE));
|
||||
EXPECT_THAT(properties.at(ACTION_VARIANT_PROPERTY).template get<sdbus::Variant>().template get<std::string>(), Eq(DEFAULT_ACTION_VARIANT_VALUE));
|
||||
EXPECT_THAT(properties.at(BLOCKING_PROPERTY).template get<bool>(), Eq(DEFAULT_BLOCKING_VALUE));
|
||||
}
|
||||
|
||||
@ -252,17 +255,19 @@ TYPED_TEST(SdbusTestObject, EmitsInterfacesAddedSignalForSelectedObjectInterface
|
||||
EXPECT_THAT(interfacesAndProperties.count(INTERFACE_NAME), Eq(1));
|
||||
#if LIBSYSTEMD_VERSION<=244
|
||||
// Up to sd-bus v244, all properties are added to the list, i.e. `state', `action', and `blocking' in this case.
|
||||
EXPECT_THAT(interfacesAndProperties.at(INTERFACE_NAME), SizeIs(3));
|
||||
EXPECT_THAT(interfacesAndProperties.at(INTERFACE_NAME), SizeIs(4));
|
||||
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(STATE_PROPERTY));
|
||||
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(ACTION_PROPERTY));
|
||||
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(ACTION_VARIANT_PROPERTY));
|
||||
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(BLOCKING_PROPERTY));
|
||||
#else
|
||||
// Since v245 sd-bus does not add to the InterfacesAdded signal message the values of properties marked only
|
||||
// for invalidation on change, which makes the behavior consistent with the PropertiesChangedSignal.
|
||||
// So in this specific instance, `action' property is no more added to the list.
|
||||
EXPECT_THAT(interfacesAndProperties.at(INTERFACE_NAME), SizeIs(2));
|
||||
EXPECT_THAT(interfacesAndProperties.at(INTERFACE_NAME), SizeIs(3));
|
||||
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(STATE_PROPERTY));
|
||||
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(BLOCKING_PROPERTY));
|
||||
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(ACTION_VARIANT_PROPERTY));
|
||||
#endif
|
||||
signalReceived = true;
|
||||
};
|
||||
@ -288,17 +293,19 @@ TYPED_TEST(SdbusTestObject, EmitsInterfacesAddedSignalForAllObjectInterfaces)
|
||||
#endif
|
||||
#if LIBSYSTEMD_VERSION<=244
|
||||
// Up to sd-bus v244, all properties are added to the list, i.e. `state', `action', and `blocking' in this case.
|
||||
EXPECT_THAT(interfacesAndProperties.at(INTERFACE_NAME), SizeIs(3));
|
||||
EXPECT_THAT(interfacesAndProperties.at(INTERFACE_NAME), SizeIs(4));
|
||||
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(STATE_PROPERTY));
|
||||
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(ACTION_PROPERTY));
|
||||
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(ACTION_VARIANT_PROPERTY));
|
||||
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(BLOCKING_PROPERTY));
|
||||
#else
|
||||
// Since v245 sd-bus does not add to the InterfacesAdded signal message the values of properties marked only
|
||||
// for invalidation on change, which makes the behavior consistent with the PropertiesChangedSignal.
|
||||
// So in this specific instance, `action' property is no more added to the list.
|
||||
EXPECT_THAT(interfacesAndProperties.at(INTERFACE_NAME), SizeIs(2));
|
||||
EXPECT_THAT(interfacesAndProperties.at(INTERFACE_NAME), SizeIs(3));
|
||||
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(STATE_PROPERTY));
|
||||
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(BLOCKING_PROPERTY));
|
||||
EXPECT_TRUE(interfacesAndProperties.at(INTERFACE_NAME).count(ACTION_VARIANT_PROPERTY));
|
||||
#endif
|
||||
signalReceived = true;
|
||||
};
|
||||
|
@ -42,6 +42,7 @@ const ObjectPath OBJECT_PATH {"/org/sdbuscpp/integrationtests/ObjectA1"};
|
||||
const ObjectPath OBJECT_PATH_2{"/org/sdbuscpp/integrationtests/ObjectB1"};
|
||||
const PropertyName STATE_PROPERTY{"state"};
|
||||
const PropertyName ACTION_PROPERTY{"action"};
|
||||
const PropertyName ACTION_VARIANT_PROPERTY{"actionVariant"};
|
||||
const PropertyName BLOCKING_PROPERTY{"blocking"};
|
||||
const std::string DIRECT_CONNECTION_SOCKET_PATH{std::filesystem::temp_directory_path() / "sdbus-cpp-direct-connection-test"};
|
||||
|
||||
@ -58,6 +59,7 @@ const int UNIX_FD_VALUE = 0;
|
||||
|
||||
const std::string DEFAULT_STATE_VALUE{"default-state-value"};
|
||||
const uint32_t DEFAULT_ACTION_VALUE{999};
|
||||
const std::string DEFAULT_ACTION_VARIANT_VALUE{"ahoj"};
|
||||
const bool DEFAULT_BLOCKING_VALUE{true};
|
||||
|
||||
constexpr const double DOUBLE_VALUE{3.24L};
|
||||
|
@ -266,6 +266,16 @@ void TestAdaptor::action(const uint32_t& value)
|
||||
m_action = value;
|
||||
}
|
||||
|
||||
sdbus::Variant TestAdaptor::actionVariant()
|
||||
{
|
||||
return m_actionVariant;
|
||||
}
|
||||
|
||||
void TestAdaptor::actionVariant(const sdbus::Variant& value)
|
||||
{
|
||||
m_actionVariant = value;
|
||||
}
|
||||
|
||||
bool TestAdaptor::blocking()
|
||||
{
|
||||
return m_blocking;
|
||||
|
@ -89,6 +89,8 @@ protected:
|
||||
|
||||
uint32_t action() override;
|
||||
void action(const uint32_t& value) override;
|
||||
sdbus::Variant actionVariant() override;
|
||||
void actionVariant(const sdbus::Variant& value) override;
|
||||
bool blocking() override;
|
||||
void blocking(const bool& value) override;
|
||||
std::string state() override;
|
||||
@ -101,6 +103,7 @@ private:
|
||||
const std::string m_state{DEFAULT_STATE_VALUE};
|
||||
uint32_t m_action{DEFAULT_ACTION_VALUE};
|
||||
bool m_blocking{DEFAULT_BLOCKING_VALUE};
|
||||
sdbus::Variant m_actionVariant{"ahoj"};
|
||||
|
||||
public: // for tests
|
||||
// For dont-expect-reply method call verifications
|
||||
@ -152,6 +155,8 @@ protected:
|
||||
|
||||
uint32_t action() override { return {}; }
|
||||
void action(const uint32_t&) override {}
|
||||
sdbus::Variant actionVariant() override { return {}; }
|
||||
void actionVariant(const sdbus::Variant&) override {}
|
||||
bool blocking() override { return {}; }
|
||||
void blocking(const bool&) override {}
|
||||
std::string state() override { return {}; }
|
||||
|
@ -63,6 +63,7 @@ protected:
|
||||
, sdbus::registerSignal("signalWithMap").withParameters<std::map<int32_t, std::string>>("aMap")
|
||||
, sdbus::registerSignal("signalWithVariant").withParameters<sdbus::Variant>("aVariant")
|
||||
, sdbus::registerProperty("action").withGetter([this](){ return this->action(); }).withSetter([this](const uint32_t& value){ this->action(value); }).withUpdateBehavior(sdbus::Flags::EMITS_INVALIDATION_SIGNAL)
|
||||
, sdbus::registerProperty("actionVariant").withGetter([this](){ return this->actionVariant(); }).withSetter([this](const sdbus::Variant& value){ this->actionVariant(value); }).withUpdateBehavior(sdbus::Flags::EMITS_NO_SIGNAL)
|
||||
, sdbus::registerProperty("blocking").withGetter([this](){ return this->blocking(); }).withSetter([this](const bool& value){ this->blocking(value); })
|
||||
, sdbus::registerProperty("state").withGetter([this](){ return this->state(); }).markAsDeprecated().withUpdateBehavior(sdbus::Flags::CONST_PROPERTY_VALUE)
|
||||
).forInterface(INTERFACE_NAME);
|
||||
@ -113,7 +114,9 @@ private:
|
||||
|
||||
private:
|
||||
virtual uint32_t action() = 0;
|
||||
virtual sdbus::Variant actionVariant() = 0;
|
||||
virtual void action(const uint32_t& value) = 0;
|
||||
virtual void actionVariant(const sdbus::Variant& value) = 0;
|
||||
virtual bool blocking() = 0;
|
||||
virtual void blocking(const bool& value) = 0;
|
||||
virtual std::string state() = 0;
|
||||
|
@ -225,6 +225,16 @@ public:
|
||||
m_proxy.setProperty("action").onInterface(INTERFACE_NAME).toValue(value);
|
||||
}
|
||||
|
||||
sdbus::Variant actionVariant()
|
||||
{
|
||||
return m_proxy.getProperty("actionVariant").onInterface(INTERFACE_NAME).get<sdbus::Variant>();
|
||||
}
|
||||
|
||||
void actionVariant(const sdbus::Variant& value)
|
||||
{
|
||||
m_proxy.setProperty("actionVariant").onInterface(INTERFACE_NAME).toValue({value, sdbus::embed_variant});
|
||||
}
|
||||
|
||||
bool blocking()
|
||||
{
|
||||
return m_proxy.getProperty("blocking").onInterface(INTERFACE_NAME).get<bool>();
|
||||
|
@ -375,6 +375,9 @@ std::tuple<std::string, std::string> ProxyGenerator::processProperties(const Nod
|
||||
|
||||
if (propertyAccess == "readwrite" || propertyAccess == "write")
|
||||
{
|
||||
if (propertySignature == "v")
|
||||
propertyArg = "{" + propertyArg + ", sdbus::embed_variant}";
|
||||
|
||||
const std::string realRetType = (asyncSet ? (futureSet ? "std::future<void>" : "sdbus::PendingAsyncCall") : "void");
|
||||
|
||||
propertySS << tab << realRetType << " " << propertyNameSafe << "(" << propertyTypeArg << ")" << endl
|
||||
|
Reference in New Issue
Block a user