xref: /openbmc/boost-dbus/test/avahi.cpp (revision 77e62c83)
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,
131                  "type='signal',path_namespace='/xyz/openbmc_project/sensors'");
132 
133   dbus::filter f(system_bus, [](dbus::message& m) {
134     auto member = m.get_member();
135     return member == "PropertiesChanged";
136   });
137 
138   f.async_dispatch([&](boost::system::error_code ec, dbus::message s) {
139     std::string object_name;
140     EXPECT_EQ(s.get_path(),
141               "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp");
142 
143     std::vector<std::pair<std::string, dbus::dbus_variant>> values;
144     s.unpack(object_name, values);
145     EXPECT_EQ(object_name, "xyz.openbmc_project.Sensor.Value");
146 
147     EXPECT_EQ(values.size(), 1);
148     auto expected = std::pair<std::string, dbus::dbus_variant>("Value", 42);
149     EXPECT_EQ(values[0], expected);
150 
151     io.stop();
152   });
153 
154   dbus::endpoint test_endpoint(
155       "org.freedesktop.Avahi",
156       "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp",
157       "org.freedesktop.DBus.Properties");
158 
159   auto signal_name = std::string("PropertiesChanged");
160   auto m = dbus::message::new_signal(test_endpoint, signal_name);
161 
162   m.pack("xyz.openbmc_project.Sensor.Value");
163 
164   std::vector<std::pair<std::string, dbus::dbus_variant>> map2;
165 
166   map2.emplace_back("Value", 42);
167 
168   m.pack(map2);
169 
170   auto removed = std::vector<uint32_t>();
171   m.pack(removed);
172   system_bus->async_send(m,
173                          [&](boost::system::error_code ec, dbus::message s) {});
174 
175   io.run();
176 }
177 
178 TEST(BOOST_DBUS, MultipleSensorChanged) {
179   boost::asio::io_service io;
180   auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
181 
182   dbus::match ma(system_bus,
183                  "type='signal',path_namespace='/xyz/openbmc_project/sensors'");
184   dbus::filter f(system_bus, [](dbus::message& m) {
185     auto member = m.get_member();
186     return member == "PropertiesChanged";
187   });
188 
189   int count = 0;
190   std::function<void(boost::system::error_code, dbus::message)> callback = [&](
191       boost::system::error_code ec, dbus::message s) {
192     std::string object_name;
193     EXPECT_EQ(s.get_path(),
194               "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp");
195 
196     std::vector<std::pair<std::string, dbus::dbus_variant>> values;
197     s.unpack(object_name, values);
198     EXPECT_EQ(object_name, "xyz.openbmc_project.Sensor.Value");
199 
200     EXPECT_EQ(values.size(), 1);
201     auto expected = std::pair<std::string, dbus::dbus_variant>("Value", 42);
202     EXPECT_EQ(values[0], expected);
203     count++;
204     if (count == 2) {
205       io.stop();
206     } else {
207       f.async_dispatch(callback);
208     }
209     s.unpack(object_name, values);
210 
211   };
212   f.async_dispatch(callback);
213 
214   dbus::endpoint test_endpoint(
215       "org.freedesktop.Avahi",
216       "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp",
217       "org.freedesktop.DBus.Properties");
218 
219   auto signal_name = std::string("PropertiesChanged");
220 
221   std::vector<std::pair<std::string, dbus::dbus_variant>> map2;
222 
223   map2.emplace_back("Value", 42);
224 
225   static auto removed = std::vector<uint32_t>();
226 
227   auto m = dbus::message::new_signal(test_endpoint, signal_name);
228   m.pack("xyz.openbmc_project.Sensor.Value", map2, removed);
229 
230   system_bus->send(m, std::chrono::seconds(0));
231   system_bus->send(m, std::chrono::seconds(0));
232 
233   io.run();
234 }
235 
236 TEST(BOOST_DBUS, MethodCall) {
237   boost::asio::io_service io;
238 
239   boost::asio::deadline_timer t(io, boost::posix_time::seconds(2));
240   t.async_wait([&](const boost::system::error_code&) {
241     io.stop();
242     FAIL() << "Callback was never called\n";
243   });
244 
245   auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
246   std::string requested_name = system_bus->get_unique_name();
247 
248   dbus::filter f(system_bus, [](dbus::message& m) {
249     return (m.get_member() == "Get" &&
250             m.get_interface() == "org.freedesktop.DBus.Properties" &&
251             m.get_signature() == "ss");
252   });
253 
254   std::function<void(boost::system::error_code, dbus::message)> method_handler =
255       [&](boost::system::error_code ec, dbus::message s) {
256         if (ec) {
257           FAIL() << ec;
258         } else {
259           std::string intf_name, prop_name;
260           s.unpack(intf_name, prop_name);
261 
262           EXPECT_EQ(intf_name, "xyz.openbmc_project.fwupdate1");
263           EXPECT_EQ(prop_name, "State");
264 
265           // send a reply so dbus doesn't get angry?
266           auto r = system_bus->reply(s);
267           r.pack("IDLE");
268           system_bus->async_send(
269               r, [&](boost::system::error_code ec, dbus::message s) {});
270           io.stop();
271         }
272       };
273   f.async_dispatch(method_handler);
274 
275   dbus::endpoint test_endpoint(requested_name, "/xyz/openbmc_project/fwupdate1",
276                                "org.freedesktop.DBus.Properties");
277 
278   auto method_name = std::string("Get");
279   auto m = dbus::message::new_call(test_endpoint, method_name);
280 
281   m.pack("xyz.openbmc_project.fwupdate1", "State");
282   system_bus->async_send(m, [&](boost::system::error_code ec, dbus::message s) {
283     std::cerr << "received s: " << s << std::endl;
284   });
285 
286   // system_bus->send(m, std::chrono::seconds(0));
287 
288   io.run();
289 }
290