xref: /openbmc/boost-dbus/test/avahi.cpp (revision a8b4eac4)
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 
TEST(AvahiTest,GetHostName)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 
TEST(AvahiTest,ServiceBrowser)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, (int32_t)-1, "_http._tcp", "local", (uint32_t)(0));
61 
62   dbus::message r = system_bus->send(m1);
63   dbus::object_path browser_path;
64   EXPECT_TRUE(r.unpack(browser_path));
65   testing::Test::RecordProperty("browserPath", browser_path.value);
66 
67   dbus::match ma(system_bus, "type='signal',path='" + browser_path.value + "'");
68   dbus::filter f(system_bus, [](dbus::message& m) {
69     auto member = m.get_member();
70     return member == "NameAcquired";
71   });
72 
73   std::function<void(boost::system::error_code, dbus::message)> event_handler =
74       [&](boost::system::error_code ec, dbus::message s) {
75         testing::Test::RecordProperty("firstSignal", s.get_member());
76         std::string a = s.get_member();
77         std::string dude;
78         s.unpack(dude);
79         f.async_dispatch(event_handler);
80         io.stop();
81       };
82   f.async_dispatch(event_handler);
83 
84   boost::asio::deadline_timer t(io, boost::posix_time::seconds(10));
85   t.async_wait([&](const boost::system::error_code& /*e*/) {
86     io.stop();
87     FAIL() << "Callback was never called\n";
88   });
89   io.run();
90 }
91 
TEST(BOOST_DBUS,ListServices)92 TEST(BOOST_DBUS, ListServices) {
93   boost::asio::io_service io;
94   boost::asio::deadline_timer t(io, boost::posix_time::seconds(10));
95   t.async_wait([&](const boost::system::error_code& /*e*/) {
96     io.stop();
97     FAIL() << "Callback was never called\n";
98   });
99 
100   auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
101 
102   dbus::endpoint test_daemon("org.freedesktop.DBus", "/",
103                              "org.freedesktop.DBus");
104   // create new service browser
105   dbus::message m = dbus::message::new_call(test_daemon, "ListNames");
106   system_bus->async_send(
107       m, [&](const boost::system::error_code ec, dbus::message r) {
108         io.stop();
109         std::vector<std::string> services;
110         r.unpack(services);
111         // Test a couple things that should always be present.... adapt if
112         // neccesary
113         EXPECT_THAT(services, testing::Contains("org.freedesktop.DBus"));
114         EXPECT_THAT(services, testing::Contains("org.freedesktop.Accounts"));
115 
116       });
117 
118   io.run();
119 }
120 
TEST(BOOST_DBUS,SingleSensorChanged)121 TEST(BOOST_DBUS, SingleSensorChanged) {
122   boost::asio::io_service io;
123 
124   auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
125 
126   dbus::match ma(system_bus,
127                  "type='signal',path_namespace='/xyz/openbmc_project/sensors'");
128 
129   dbus::filter f(system_bus, [](dbus::message& m) {
130     auto member = m.get_member();
131     return member == "PropertiesChanged";
132   });
133 
134   f.async_dispatch([&](boost::system::error_code ec, dbus::message s) {
135     std::string object_name;
136     EXPECT_EQ(s.get_path(),
137               "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp");
138 
139     std::vector<std::pair<std::string, dbus::dbus_variant>> values;
140     s.unpack(object_name, values);
141     EXPECT_EQ(object_name, "xyz.openbmc_project.Sensor.Value");
142 
143     EXPECT_EQ(values.size(), std::size_t{1});
144     auto expected = std::pair<std::string, dbus::dbus_variant>("Value", 42);
145     EXPECT_EQ(values[0], expected);
146 
147     io.stop();
148   });
149 
150   dbus::endpoint test_endpoint(
151       "org.freedesktop.Avahi",
152       "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp",
153       "org.freedesktop.DBus.Properties");
154 
155   auto signal_name = std::string("PropertiesChanged");
156   auto m = dbus::message::new_signal(test_endpoint, signal_name);
157 
158   std::vector<std::pair<std::string, dbus::dbus_variant>> map2;
159 
160   map2.emplace_back("Value", 42);
161 
162   auto removed = std::vector<std::string>();
163   EXPECT_EQ(m.pack("xyz.openbmc_project.Sensor.Value", map2, removed), true);
164 
165   system_bus->async_send(m,
166                          [&](boost::system::error_code ec, dbus::message s) {});
167 
168   io.run();
169 }
170 
TEST(BOOST_DBUS,MultipleSensorChanged)171 TEST(BOOST_DBUS, MultipleSensorChanged) {
172   boost::asio::io_service io;
173   auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
174 
175   dbus::match ma(system_bus,
176                  "type='signal',path_namespace='/xyz/openbmc_project/sensors'");
177   dbus::filter f(system_bus, [](dbus::message& m) {
178     auto member = m.get_member();
179     return member == "PropertiesChanged";
180   });
181 
182   int count = 0;
183   std::function<void(boost::system::error_code, dbus::message)> callback = [&](
184       boost::system::error_code ec, dbus::message s) {
185     std::string object_name;
186     EXPECT_EQ(s.get_path(),
187               "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp");
188 
189     std::vector<std::pair<std::string, dbus::dbus_variant>> values;
190     s.unpack(object_name, values);
191     EXPECT_EQ(object_name, "xyz.openbmc_project.Sensor.Value");
192 
193     EXPECT_EQ(values.size(), std::size_t{1});
194     auto expected = std::pair<std::string, dbus::dbus_variant>("Value", 42);
195     EXPECT_EQ(values[0], expected);
196     count++;
197     if (count == 2) {
198       io.stop();
199     } else {
200       f.async_dispatch(callback);
201     }
202     s.unpack(object_name, values);
203 
204   };
205   f.async_dispatch(callback);
206 
207   dbus::endpoint test_endpoint(
208       "org.freedesktop.Avahi",
209       "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp",
210       "org.freedesktop.DBus.Properties");
211 
212   auto signal_name = std::string("PropertiesChanged");
213 
214   std::vector<std::pair<std::string, dbus::dbus_variant>> map2;
215 
216   map2.emplace_back("Value", 42);
217 
218   static auto removed = std::vector<uint32_t>();
219 
220   auto m = dbus::message::new_signal(test_endpoint, signal_name);
221   m.pack("xyz.openbmc_project.Sensor.Value", map2, removed);
222 
223   system_bus->send(m, std::chrono::seconds(0));
224   system_bus->send(m, std::chrono::seconds(0));
225 
226   io.run();
227 }
228 
TEST(BOOST_DBUS,MethodCallEx)229 TEST(BOOST_DBUS, MethodCallEx) {
230   boost::asio::io_service io;
231   // Expiration timer to stop tests if they fail
232   boost::asio::deadline_timer t(io, boost::posix_time::seconds(10));
233   t.async_wait([&](const boost::system::error_code&) {
234     io.stop();
235     FAIL() << "Callback was never called\n";
236   });
237 
238   auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::session);
239   std::string requested_name = system_bus->get_unique_name();
240 
241   dbus::filter f(system_bus, [requested_name](dbus::message& m) {
242     return m.get_sender() == requested_name;
243   });
244 
245   std::function<void(boost::system::error_code, dbus::message)> method_handler =
246       [&](boost::system::error_code ec, dbus::message s) {
247         if (ec) {
248           FAIL() << ec;
249         } else {
250           std::string intf_name, prop_name;
251           EXPECT_EQ(s.get_signature(), "ss");
252           EXPECT_EQ(s.get_member(), "Get");
253           EXPECT_EQ(s.get_interface(), "org.freedesktop.DBus.Properties");
254           s.unpack(intf_name, prop_name);
255 
256           EXPECT_EQ(intf_name, "xyz.openbmc_project.fwupdate1");
257           EXPECT_EQ(prop_name, "State");
258 
259           // send a reply
260           auto r = system_bus->reply(s);
261           r.pack("IDLE");
262           system_bus->async_send(
263               r, [&](boost::system::error_code ec, dbus::message s) {});
264           io.stop();
265         }
266       };
267   f.async_dispatch(method_handler);
268 
269   dbus::endpoint test_endpoint(requested_name, "/xyz/openbmc_project/fwupdate1",
270                                "org.freedesktop.DBus.Properties", "Get");
271   system_bus->async_method_call(
272       [&](const boost::system::error_code ec,
273           const dbus::dbus_variant& status) {
274         if (ec) {
275           FAIL();
276         } else {
277           EXPECT_EQ(boost::get<std::string>(status), "IDLE");
278         }
279       },
280       test_endpoint, "xyz.openbmc_project.fwupdate1", "State");
281 
282   io.run();
283 }
284 
TEST(BOOST_DBUS,MethodCall)285 TEST(BOOST_DBUS, MethodCall) {
286   boost::asio::io_service io;
287 
288   boost::asio::deadline_timer t(io, boost::posix_time::seconds(2));
289   t.async_wait([&](const boost::system::error_code&) {
290     io.stop();
291     FAIL() << "Callback was never called\n";
292   });
293 
294   auto bus = std::make_shared<dbus::connection>(io, dbus::bus::session);
295   std::string requested_name = bus->get_unique_name();
296 
297   dbus::filter f(bus, [](dbus::message& m) {
298     return (m.get_member() == "Get" &&
299             m.get_interface() == "org.freedesktop.DBus.Properties" &&
300             m.get_signature() == "ss");
301   });
302 
303   std::function<void(boost::system::error_code, dbus::message)> method_handler =
304       [&](boost::system::error_code ec, dbus::message s) {
305         if (ec) {
306           FAIL() << ec;
307         } else {
308           std::string intf_name, prop_name;
309           s.unpack(intf_name, prop_name);
310 
311           EXPECT_EQ(intf_name, "xyz.openbmc_project.fwupdate1");
312           EXPECT_EQ(prop_name, "State");
313 
314           // send a reply so dbus doesn't get angry?
315           auto r = bus->reply(s);
316           r.pack("IDLE");
317           bus->async_send(
318               r, [&](boost::system::error_code ec, dbus::message s) {});
319           io.stop();
320         }
321       };
322   f.async_dispatch(method_handler);
323 
324   dbus::endpoint test_endpoint(requested_name, "/xyz/openbmc_project/fwupdate1",
325                                "org.freedesktop.DBus.Properties");
326 
327   auto method_name = std::string("Get");
328   auto m = dbus::message::new_call(test_endpoint, method_name);
329 
330   m.pack("xyz.openbmc_project.fwupdate1", "State");
331   bus->async_send(m, [&](boost::system::error_code ec, dbus::message s) {
332     std::cerr << "received s: " << s << std::endl;
333   });
334 
335   // system_bus->send(m, std::chrono::seconds(0));
336 
337   io.run();
338 }
339