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