blob: eaa2116768750a84458949e47e07f2d93e0dfa69 [file] [log] [blame]
#include <boost/asio.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(boost::asio::io_context& ioc, sdbusplus::asio::connection& bus,
sdbusplus::asio::object_server& objServer) :
ioc_(ioc),
bus_(bus), objServer_(objServer)
{
demo_ =
objServer_.add_unique_interface(demoObjectPath, demoInterfaceName);
demo_->register_property_r(propertyGrettingName, std::string(),
sdbusplus::vtable::property_::const_,
[this](const auto&) { return greetings_; });
demo_->register_property_rw(
propertyGoodbyesName, std::string(),
sdbusplus::vtable::property_::emits_change,
[this](const auto& newPropertyValue, const auto&) {
goodbyes_ = newPropertyValue;
return 1;
},
[this](const auto&) { return goodbyes_; });
demo_->register_property_r(
propertyValueName, uint32_t{42},
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 logBadProperty(const std::string& badProperty)
{
std::cerr << "BadProperty: " << badProperty << "\n";
++fatalErrors_;
}
void logExpectedException(
const sdbusplus::exception::UnpackPropertyError& error)
{
std::cout << "As expected " << error.what() << " => "
<< error.propertyName << " is missing because "
<< error.reason << "\n";
}
void asyncGetAllPropertiesStringTypeOnly()
{
sdbusplus::asio::getAllProperties(
bus_, demoServiceName, demoObjectPath, demoInterfaceName,
[this](boost::system::error_code ec,
std::vector<std::pair<
std::string, std::variant<std::monostate, std::string>>>&
properties) -> void {
if (ec)
{
logSystemErrorCode(ec);
return;
}
{
std::string greetings;
std::string goodbyes;
std::optional<std::string> badProperty =
sdbusplus::unpackPropertiesNoThrow(
properties, propertyGrettingName, greetings,
propertyGoodbyesName, goodbyes);
if (badProperty)
{
logBadProperty(*badProperty);
}
else
{
std::cout << "value of greetings: " << greetings
<< "\n";
std::cout << "value of goodbyes: " << goodbyes << "\n";
}
}
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](boost::system::error_code ec,
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:
boost::asio::io_context& ioc_;
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(ioc, *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();
}