blob: 35e9783d8f5f646731b2b6cbd2433c1dba6aa6e8 [file] [log] [blame]
#include <boost/asio/io_context.hpp>
#include <boost/asio/signal_set.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <sdbusplus/asio/property.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/unpack_properties.hpp>
#include <iostream>
const std::string demoServiceName = "demo.service";
const std::string demoObjectPath = "/xyz/demo";
const std::string demoInterfaceName = "xyz.demo";
const std::string propertyGrettingName = "Greetings";
const std::string propertyGoodbyesName = "Goodbyes";
const std::string propertyValueName = "Value";
class Application
{
public:
Application(sdbusplus::asio::connection& bus,
sdbusplus::asio::object_server& objServer) :
bus_(bus),
objServer_(objServer)
{
demo_ = objServer_.add_unique_interface(demoObjectPath,
demoInterfaceName);
demo_->register_property_r<std::string>(
propertyGrettingName, sdbusplus::vtable::property_::const_,
[this](const auto&) { return greetings_; });
demo_->register_property_rw<std::string>(
propertyGoodbyesName, sdbusplus::vtable::property_::emits_change,
[this](const auto& newPropertyValue, const auto&) {
goodbyes_ = newPropertyValue;
return true;
},
[this](const auto&) { return goodbyes_; });
demo_->register_property_r<uint32_t>(
propertyValueName, sdbusplus::vtable::property_::const_,
[](const auto& value) -> uint32_t { return value; });
demo_->initialize();
}
uint32_t fatalErrors() const
{
return fatalErrors_;
}
auto logSystemErrorCode(boost::system::error_code ec)
{
std::cerr << "Error: " << ec << "\n";
++fatalErrors_;
}
void logException(const std::exception& e)
{
std::cerr << "Error: " << e.what() << "\n";
++fatalErrors_;
}
void logUnpackError(const sdbusplus::UnpackErrorReason reason,
const std::string& property)
{
std::cerr << "UnpackError: " << static_cast<int>(reason) << ", "
<< property << "\n";
++fatalErrors_;
}
void logExpectedException(
const sdbusplus::exception::UnpackPropertyError& error)
{
std::cout << "As expected " << error.what() << "\n";
}
void asyncGetAllPropertiesStringTypeOnly()
{
sdbusplus::asio::getAllProperties(
bus_, demoServiceName, demoObjectPath, demoInterfaceName,
[this](const boost::system::error_code ec,
const std::vector<std::pair<
std::string, std::variant<std::monostate, std::string>>>&
properties) -> void {
if (ec)
{
logSystemErrorCode(ec);
return;
}
{
const std::string* greetings = nullptr;
const std::string* goodbyes = nullptr;
const bool success = sdbusplus::unpackPropertiesNoThrow(
[this](const sdbusplus::UnpackErrorReason reason,
const std::string& property) {
logUnpackError(reason, property);
},
properties, propertyGrettingName, greetings,
propertyGoodbyesName, goodbyes);
if (success)
{
std::cout << "value of greetings: " << *greetings << "\n";
std::cout << "value of goodbyes: " << *goodbyes << "\n";
}
else
{
++fatalErrors_;
}
}
try
{
std::string value;
sdbusplus::unpackProperties(properties, propertyValueName,
value);
std::cerr << "Error: it should fail because of "
"not matched type\n";
++fatalErrors_;
}
catch (const sdbusplus::exception::UnpackPropertyError& error)
{
logExpectedException(error);
}
});
}
void asyncGetAllProperties()
{
sdbusplus::asio::getAllProperties(
bus_, demoServiceName, demoObjectPath, demoInterfaceName,
[this](const boost::system::error_code ec,
const std::vector<std::pair<
std::string,
std::variant<std::monostate, std::string, uint32_t>>>&
properties) -> void {
if (ec)
{
logSystemErrorCode(ec);
return;
}
try
{
std::string greetings;
std::string goodbyes;
uint32_t value = 0u;
sdbusplus::unpackProperties(properties, propertyGrettingName,
greetings, propertyGoodbyesName,
goodbyes, propertyValueName, value);
std::cout << "value of greetings: " << greetings << "\n";
std::cout << "value of goodbyes: " << goodbyes << "\n";
std::cout << "value of value: " << value << "\n";
}
catch (const sdbusplus::exception::UnpackPropertyError& error)
{
logException(error);
}
try
{
std::string unknownProperty;
sdbusplus::unpackProperties(properties, "UnknownPropertyName",
unknownProperty);
std::cerr << "Error: it should fail because of "
"missing property\n";
++fatalErrors_;
}
catch (const sdbusplus::exception::UnpackPropertyError& error)
{
logExpectedException(error);
}
try
{
uint32_t notMatchingType;
sdbusplus::unpackProperties(properties, propertyGrettingName,
notMatchingType);
std::cerr << "Error: it should fail because of "
"not matched type\n";
++fatalErrors_;
}
catch (const sdbusplus::exception::UnpackPropertyError& error)
{
logExpectedException(error);
}
});
}
private:
sdbusplus::asio::connection& bus_;
sdbusplus::asio::object_server& objServer_;
std::unique_ptr<sdbusplus::asio::dbus_interface> demo_;
std::string greetings_ = "Hello";
std::string goodbyes_ = "Bye";
uint32_t fatalErrors_ = 0u;
};
int main(int, char**)
{
boost::asio::io_context ioc;
boost::asio::signal_set signals(ioc, SIGINT, SIGTERM);
signals.async_wait(
[&ioc](const boost::system::error_code&, const int&) { ioc.stop(); });
auto bus = std::make_shared<sdbusplus::asio::connection>(ioc);
auto objServer = std::make_unique<sdbusplus::asio::object_server>(bus);
bus->request_name(demoServiceName.c_str());
Application app(*bus, *objServer);
boost::asio::post(ioc,
[&app] { app.asyncGetAllPropertiesStringTypeOnly(); });
boost::asio::post(ioc, [&app] { app.asyncGetAllProperties(); });
ioc.run();
std::cout << "Fatal errors count: " << app.fatalErrors() << "\n";
return app.fatalErrors();
}