xref: /openbmc/boost-dbus/test/avahi.cpp (revision 0d6f56d2a51a2f37c41f95937c0709b12fabdf1b)
1 // Copyright (c) Benjamin Kietzman (github.com/bkietz)
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #include <dbus/connection.hpp>
7 #include <dbus/endpoint.hpp>
8 #include <dbus/filter.hpp>
9 #include <dbus/match.hpp>
10 #include <dbus/message.hpp>
11 #include <functional>
12 
13 #include <unistd.h>
14 #include <gmock/gmock.h>
15 #include <gtest/gtest.h>
16 
17 TEST(AvahiTest, GetHostName) {
18   dbus::endpoint test_daemon("org.freedesktop.Avahi", "/",
19                              "org.freedesktop.Avahi.Server");
20   boost::asio::io_service io;
21   auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
22 
23   dbus::message m = dbus::message::new_call(test_daemon, "GetHostName");
24 
25   system_bus->async_send(
26       m, [&](const boost::system::error_code ec, dbus::message r) {
27 
28         std::string avahi_hostname;
29         std::string hostname;
30 
31         // get hostname from a system call
32         char c[1024];
33         gethostname(c, 1024);
34         hostname = c;
35 
36         r.unpack(avahi_hostname);
37 
38         // Get only the host name, not the fqdn
39         auto unix_hostname = hostname.substr(0, hostname.find("."));
40         EXPECT_EQ(unix_hostname, avahi_hostname);
41 
42         io.stop();
43       });
44   boost::asio::deadline_timer t(io, boost::posix_time::seconds(10));
45   t.async_wait([&](const boost::system::error_code& /*e*/) {
46     io.stop();
47     FAIL() << "Callback was never called\n";
48   });
49   io.run();
50 }
51 
52 TEST(AvahiTest, ServiceBrowser) {
53   boost::asio::io_service io;
54   auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
55 
56   dbus::endpoint test_daemon("org.freedesktop.Avahi", "/",
57                              "org.freedesktop.Avahi.Server");
58   // create new service browser
59   dbus::message m1 = dbus::message::new_call(test_daemon, "ServiceBrowserNew");
60   m1.pack<int32_t>(-1)
61       .pack<int32_t>(-1)
62       .pack<std::string>("_http._tcp")
63       .pack<std::string>("local")
64       .pack<uint32_t>(0);
65 
66   dbus::message r = system_bus->send(m1);
67   std::string browser_path;
68   r.unpack(browser_path);
69   testing::Test::RecordProperty("browserPath", browser_path);
70 
71   dbus::match ma(system_bus, "type='signal',path='" + browser_path + "'");
72   dbus::filter f(system_bus, [](dbus::message& m) {
73     auto member = m.get_member();
74     return member == "NameAcquired";
75   });
76 
77   std::function<void(boost::system::error_code, dbus::message)> event_handler =
78       [&](boost::system::error_code ec, dbus::message s) {
79         testing::Test::RecordProperty("firstSignal", s.get_member());
80         std::string a = s.get_member();
81         std::string dude;
82         s.unpack(dude);
83         f.async_dispatch(event_handler);
84         io.stop();
85       };
86   f.async_dispatch(event_handler);
87 
88   boost::asio::deadline_timer t(io, boost::posix_time::seconds(10));
89   t.async_wait([&](const boost::system::error_code& /*e*/) {
90     io.stop();
91     FAIL() << "Callback was never called\n";
92   });
93   io.run();
94 }
95 
96 TEST(BOOST_DBUS, ListServices) {
97   boost::asio::io_service io;
98   boost::asio::deadline_timer t(io, boost::posix_time::seconds(10));
99   t.async_wait([&](const boost::system::error_code& /*e*/) {
100     io.stop();
101     FAIL() << "Callback was never called\n";
102   });
103 
104   auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
105 
106   dbus::endpoint test_daemon("org.freedesktop.DBus", "/",
107                              "org.freedesktop.DBus");
108   // create new service browser
109   dbus::message m = dbus::message::new_call(test_daemon, "ListNames");
110   system_bus->async_send(
111       m, [&](const boost::system::error_code ec, dbus::message r) {
112         io.stop();
113         std::vector<std::string> services;
114         r.unpack(services);
115         // Test a couple things that should always be present.... adapt if
116         // neccesary
117         EXPECT_THAT(services, testing::Contains("org.freedesktop.DBus"));
118         EXPECT_THAT(services, testing::Contains("org.freedesktop.Accounts"));
119 
120       });
121 
122   io.run();
123 }
124 
125 TEST(BOOST_DBUS, SingleSensorChanged) {
126   boost::asio::io_service io;
127 
128   auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
129 
130   dbus::match ma(system_bus, "type='signal',path_namespace='/xyz/openbmc_project/sensors'");
131 
132   dbus::filter f(system_bus, [](dbus::message& m) {
133     auto member = m.get_member();
134     return member == "PropertiesChanged";
135   });
136 
137   // std::function<void(boost::system::error_code, dbus::message)> event_handler
138   // =
139 
140   f.async_dispatch([&](boost::system::error_code ec, dbus::message s) {
141     std::string object_name;
142     EXPECT_EQ(s.get_path(),
143               "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp");
144 
145     std::vector<std::pair<std::string, dbus::dbus_variant>> values;
146     s.unpack(object_name, values);
147     EXPECT_EQ(object_name, "xyz.openbmc_project.Sensor.Value");
148 
149     EXPECT_EQ(values.size(), 1);
150     auto expected = std::pair<std::string, dbus::dbus_variant>("Value", 42);
151     EXPECT_EQ(values[0], expected);
152 
153     io.stop();
154   });
155 
156   dbus::endpoint test_endpoint(
157       "org.freedesktop.Avahi",
158       "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp",
159       "org.freedesktop.DBus.Properties");
160 
161   auto signal_name = std::string("PropertiesChanged");
162   auto m = dbus::message::new_signal(test_endpoint, signal_name);
163 
164   m.pack("xyz.openbmc_project.Sensor.Value");
165 
166   std::vector<std::pair<std::string, dbus::dbus_variant>> map2;
167 
168   map2.emplace_back("Value", 42);
169 
170   m.pack(map2);
171 
172   auto removed = std::vector<uint32_t>();
173   m.pack(removed);
174   system_bus->async_send(m,
175                          [&](boost::system::error_code ec, dbus::message s) {});
176 
177   io.run();
178 }
179 
180 TEST(BOOST_DBUS, MultipleSensorChanged) {
181   boost::asio::io_service io;
182   auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
183 
184   dbus::match ma(system_bus,
185                  "type='signal',path_namespace='/xyz/openbmc_project/sensors'");
186   dbus::filter f(system_bus, [](dbus::message& m) {
187     auto member = m.get_member();
188     return member == "PropertiesChanged";
189   });
190 
191   int count = 0;
192   std::function<void(boost::system::error_code, dbus::message)> callback = [&](
193       boost::system::error_code ec, dbus::message s) {
194     std::string object_name;
195     EXPECT_EQ(s.get_path(),
196               "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp");
197 
198     std::vector<std::pair<std::string, dbus::dbus_variant>> values;
199     s.unpack(object_name, values);
200     EXPECT_EQ(object_name, "xyz.openbmc_project.Sensor.Value");
201 
202     EXPECT_EQ(values.size(), 1);
203     auto expected = std::pair<std::string, dbus::dbus_variant>("Value", 42);
204     EXPECT_EQ(values[0], expected);
205     count++;
206     if (count == 2) {
207       io.stop();
208     } else {
209       f.async_dispatch(callback);
210     }
211     s.unpack(object_name, values);
212 
213   };
214   f.async_dispatch(callback);
215 
216   dbus::endpoint test_endpoint(
217       "org.freedesktop.Avahi",
218       "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp",
219       "org.freedesktop.DBus.Properties");
220 
221   auto signal_name = std::string("PropertiesChanged");
222   auto m = dbus::message::new_signal(test_endpoint, signal_name);
223 
224   m.pack("xyz.openbmc_project.Sensor.Value");
225 
226   std::vector<std::pair<std::string, dbus::dbus_variant>> map2;
227 
228   map2.emplace_back("Value", 42);
229 
230   m.pack(map2);
231 
232   auto removed = std::vector<uint32_t>();
233   m.pack(removed);
234   system_bus->async_send(m,
235                          [&](boost::system::error_code ec, dbus::message s) {});
236   system_bus->async_send(m,
237                          [&](boost::system::error_code ec, dbus::message s) {});
238   io.run();
239 }
240 
241 TEST(BOOST_DBUS, MethodCall) {
242   boost::asio::io_service io;
243   boost::asio::deadline_timer t(io, boost::posix_time::seconds(30));
244   t.async_wait([&](const boost::system::error_code& /*e*/) {
245     io.stop();
246     FAIL() << "Callback was never called\n";
247   });
248 
249   auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
250   std::string requested_name = system_bus->get_unique_name();
251 
252   dbus::filter f(system_bus, [](dbus::message& m) {
253     return (m.get_member() == "Get" &&
254             m.get_interface() == "org.freedesktop.DBus.Properties" &&
255             m.get_signature() == "ss");
256   });
257 
258   std::function<void(boost::system::error_code, dbus::message)> method_handler =
259       [&](boost::system::error_code ec, dbus::message s) {
260         if (ec) {
261           FAIL() << ec;
262         } else {
263           std::string intf_name, prop_name;
264           s.unpack(intf_name, prop_name);
265 
266           EXPECT_EQ(intf_name, "xyz.openbmc_project.fwupdate1");
267           EXPECT_EQ(prop_name, "State");
268 
269           // send a reply so dbus doesn't get angry?
270           auto r = system_bus->reply(s);
271           r.pack("IDLE");
272           system_bus->async_send(r, [&](boost::system::error_code ec,
273                                         dbus::message s) { });
274            io.stop();
275         }
276      };
277   f.async_dispatch(method_handler);
278 
279   dbus::endpoint test_endpoint(
280       requested_name,
281       "/xyz/openbmc_project/fwupdate1",
282       "org.freedesktop.DBus.Properties");
283 
284   auto method_name = std::string("Get");
285   auto m = dbus::message::new_call(test_endpoint, method_name);
286 
287   m.pack("xyz.openbmc_project.fwupdate1", "State");
288   system_bus->async_send(m,
289                         [&](boost::system::error_code ec, dbus::message s) {
290                         std::cerr <<"received s: " << s << std::endl;
291                         });
292 
293   io.run();
294 }
295