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