1 #include <boost/asio/io_context.hpp>
2 #include <boost/asio/signal_set.hpp>
3 #include <sdbusplus/asio/connection.hpp>
4 #include <sdbusplus/asio/object_server.hpp>
5 #include <sdbusplus/asio/property.hpp>
6 #include <sdbusplus/bus.hpp>
7 
8 #include <iostream>
9 
10 const std::string demoServiceName = "demo.service";
11 const std::string demoObjectPath = "/xyz/demo";
12 const std::string demoInterfaceName = "xyz.demo";
13 const std::string propertyGrettingName = "Greetings";
14 const std::string propertyGoodbyesName = "Goodbyes";
15 
16 class Application
17 {
18   public:
Application(boost::asio::io_context & ioc,sdbusplus::asio::connection & bus,sdbusplus::asio::object_server & objServer)19     Application(boost::asio::io_context& ioc, sdbusplus::asio::connection& bus,
20                 sdbusplus::asio::object_server& objServer) :
21         ioc_(ioc),
22         bus_(bus), objServer_(objServer)
23     {
24         demo_ = objServer_.add_unique_interface(
25             demoObjectPath, demoInterfaceName,
26             [this](sdbusplus::asio::dbus_interface& demo) {
27             demo.register_property_r<std::string>(
28                 propertyGrettingName, sdbusplus::vtable::property_::const_,
29                 [this](const auto&) { return greetings_; });
30 
31             demo.register_property_rw<std::string>(
32                 propertyGoodbyesName,
33                 sdbusplus::vtable::property_::emits_change,
34                 [this](const auto& newPropertyValue, const auto&) {
35                 goodbyes_ = newPropertyValue;
36                 return true;
37             },
38                 [this](const auto&) { return goodbyes_; });
39         });
40     }
41 
fatalErrors() const42     uint32_t fatalErrors() const
43     {
44         return fatalErrors_;
45     }
46 
getFailed()47     auto getFailed()
48     {
49         return [this](boost::system::error_code error) {
50             std::cerr << "Error: getProperty failed " << error << "\n";
51             ++fatalErrors_;
52         };
53     }
54 
asyncReadPropertyWithIncorrectType()55     void asyncReadPropertyWithIncorrectType()
56     {
57         sdbusplus::asio::getProperty<uint32_t>(
58             bus_, demoServiceName, demoObjectPath, demoInterfaceName,
59             propertyGrettingName,
60             [this](boost::system::error_code ec, uint32_t) {
61             if (ec)
62             {
63                 std::cout
64                     << "As expected failed to getProperty with wrong type: "
65                     << ec << "\n";
66                 return;
67             }
68 
69             std::cerr << "Error: it was expected to fail getProperty due "
70                          "to wrong type\n";
71             ++fatalErrors_;
72         });
73     }
74 
asyncReadProperties()75     void asyncReadProperties()
76     {
77         sdbusplus::asio::getProperty<std::string>(
78             bus_, demoServiceName, demoObjectPath, demoInterfaceName,
79             propertyGrettingName,
80             [this](boost::system::error_code ec, std::string value) {
81             if (ec)
82             {
83                 getFailed();
84                 return;
85             }
86             std::cout << "Greetings value is: " << value << "\n";
87         });
88 
89         sdbusplus::asio::getProperty<std::string>(
90             bus_, demoServiceName, demoObjectPath, demoInterfaceName,
91             propertyGoodbyesName,
92             [this](boost::system::error_code ec, std::string value) {
93             if (ec)
94             {
95                 getFailed();
96                 return;
97             }
98             std::cout << "Goodbyes value is: " << value << "\n";
99         });
100     }
101 
asyncChangeProperty()102     void asyncChangeProperty()
103     {
104         sdbusplus::asio::setProperty(
105             bus_, demoServiceName, demoObjectPath, demoInterfaceName,
106             propertyGrettingName, "Hi, hey, hello",
107             [this](const boost::system::error_code& ec) {
108             if (ec)
109             {
110                 std::cout << "As expected, failed to set greetings property: "
111                           << ec << "\n";
112                 return;
113             }
114 
115             std::cout << "Error: it was expected to fail to change greetings\n";
116             ++fatalErrors_;
117         });
118 
119         sdbusplus::asio::setProperty(
120             bus_, demoServiceName, demoObjectPath, demoInterfaceName,
121             propertyGoodbyesName, "Bye bye",
122             [this](const boost::system::error_code& ec) {
123             if (ec)
124             {
125                 std::cout << "Error: it supposed to be ok to change goodbyes "
126                              "property: "
127                           << ec << "\n";
128                 ++fatalErrors_;
129                 return;
130             }
131             std::cout << "Changed goodbyes property as expected\n";
132             boost::asio::post(ioc_, [this] { asyncReadProperties(); });
133         });
134     }
135 
syncChangeGoodbyes(std::string_view value)136     void syncChangeGoodbyes(std::string_view value)
137     {
138         goodbyes_ = value;
139         demo_->signal_property(propertyGoodbyesName);
140     }
141 
142   private:
143     boost::asio::io_context& ioc_;
144     sdbusplus::asio::connection& bus_;
145     sdbusplus::asio::object_server& objServer_;
146 
147     std::unique_ptr<sdbusplus::asio::dbus_interface> demo_;
148     std::string greetings_ = "Hello";
149     std::string goodbyes_ = "Bye";
150 
151     uint32_t fatalErrors_ = 0u;
152 };
153 
main(int,char **)154 int main(int, char**)
155 {
156     boost::asio::io_context ioc;
157     boost::asio::signal_set signals(ioc, SIGINT, SIGTERM);
158 
159     signals.async_wait(
160         [&ioc](const boost::system::error_code&, const int&) { ioc.stop(); });
161 
162     auto bus = std::make_shared<sdbusplus::asio::connection>(ioc);
163     auto objServer = std::make_unique<sdbusplus::asio::object_server>(bus);
164 
165     bus->request_name(demoServiceName.c_str());
166 
167     Application app(ioc, *bus, *objServer);
168 
169     app.syncChangeGoodbyes("Good bye");
170 
171     boost::asio::post(ioc,
172                       [&app] { app.asyncReadPropertyWithIncorrectType(); });
173     boost::asio::post(ioc, [&app] { app.asyncReadProperties(); });
174     boost::asio::post(ioc, [&app] { app.asyncChangeProperty(); });
175 
176     ioc.run();
177 
178     std::cout << "Fatal errors count: " << app.fatalErrors() << "\n";
179 
180     return app.fatalErrors();
181 }
182