blob: 5d2deb805c278e786ada24782b409bf5bf24fc96 [file] [log] [blame]
Ed Tanousc9b55212017-06-12 13:25:51 -07001// 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 <dbus/utility.hpp>
12#include <functional>
13
14#include <unistd.h>
15#include <gmock/gmock.h>
16#include <gtest/gtest.h>
17
18TEST(AvahiTest, GetHostName) {
19 dbus::endpoint test_daemon("org.freedesktop.Avahi", "/",
20 "org.freedesktop.Avahi.Server");
21 boost::asio::io_service io;
Ed Tanous5fceeb42017-06-28 09:43:09 -070022 auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
Ed Tanousc9b55212017-06-12 13:25:51 -070023
24 dbus::message m = dbus::message::new_call(test_daemon, "GetHostName");
25
Ed Tanous5fceeb42017-06-28 09:43:09 -070026 system_bus->async_send(
Ed Tanousc9b55212017-06-12 13:25:51 -070027 m, [&](const boost::system::error_code ec, dbus::message r) {
28
29 std::string avahi_hostname;
30 std::string hostname;
31
32 // get hostname from a system call
33 char c[1024];
34 gethostname(c, 1024);
35 hostname = c;
36
37 r.unpack(avahi_hostname);
38
39 // Get only the host name, not the fqdn
40 auto unix_hostname = hostname.substr(0, hostname.find("."));
41 EXPECT_EQ(unix_hostname, avahi_hostname);
42
43 io.stop();
44 });
45 boost::asio::deadline_timer t(io, boost::posix_time::seconds(10));
46 t.async_wait([&](const boost::system::error_code& /*e*/) {
47 io.stop();
48 FAIL() << "Callback was never called\n";
49 });
50 io.run();
51}
52
53TEST(AvahiTest, ServiceBrowser) {
54 boost::asio::io_service io;
Ed Tanous5fceeb42017-06-28 09:43:09 -070055 auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
Ed Tanousc9b55212017-06-12 13:25:51 -070056
57 dbus::endpoint test_daemon("org.freedesktop.Avahi", "/",
58 "org.freedesktop.Avahi.Server");
59 // create new service browser
60 dbus::message m1 = dbus::message::new_call(test_daemon, "ServiceBrowserNew");
61 m1.pack<int32_t>(-1)
62 .pack<int32_t>(-1)
63 .pack<std::string>("_http._tcp")
64 .pack<std::string>("local")
65 .pack<uint32_t>(0);
66
Ed Tanous5fceeb42017-06-28 09:43:09 -070067 dbus::message r = system_bus->send(m1);
Ed Tanousc9b55212017-06-12 13:25:51 -070068 std::string browser_path;
69 r.unpack(browser_path);
70 testing::Test::RecordProperty("browserPath", browser_path);
71
72 dbus::match ma(system_bus, "type='signal',path='" + browser_path + "'");
73 dbus::filter f(system_bus, [](dbus::message& m) {
74 auto member = m.get_member();
75 return member == "NameAcquired";
76 });
77
78 std::function<void(boost::system::error_code, dbus::message)> event_handler =
79 [&](boost::system::error_code ec, dbus::message s) {
80 testing::Test::RecordProperty("firstSignal", s.get_member());
81 std::string a = s.get_member();
82 std::string dude;
83 s.unpack(dude);
84 f.async_dispatch(event_handler);
85 io.stop();
86 };
87 f.async_dispatch(event_handler);
88
89 boost::asio::deadline_timer t(io, boost::posix_time::seconds(10));
90 t.async_wait([&](const boost::system::error_code& /*e*/) {
91 io.stop();
92 FAIL() << "Callback was never called\n";
93 });
94 io.run();
95}
96
97TEST(BOOST_DBUS, ListServices) {
98 boost::asio::io_service io;
99 boost::asio::deadline_timer t(io, boost::posix_time::seconds(10));
100 t.async_wait([&](const boost::system::error_code& /*e*/) {
101 io.stop();
102 FAIL() << "Callback was never called\n";
103 });
104
Ed Tanous5fceeb42017-06-28 09:43:09 -0700105 auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
Ed Tanousc9b55212017-06-12 13:25:51 -0700106
107 dbus::endpoint test_daemon("org.freedesktop.DBus", "/",
108 "org.freedesktop.DBus");
109 // create new service browser
110 dbus::message m = dbus::message::new_call(test_daemon, "ListNames");
Ed Tanous5fceeb42017-06-28 09:43:09 -0700111 system_bus->async_send(
Ed Tanousc9b55212017-06-12 13:25:51 -0700112 m, [&](const boost::system::error_code ec, dbus::message r) {
113 io.stop();
114 std::vector<std::string> services;
115 r.unpack(services);
116 // Test a couple things that should always be present.... adapt if
117 // neccesary
118 EXPECT_THAT(services, testing::Contains("org.freedesktop.DBus"));
119 EXPECT_THAT(services, testing::Contains("org.freedesktop.Accounts"));
120
121 });
122
123 io.run();
124}
125
Ed Tanous5fceeb42017-06-28 09:43:09 -0700126void query_interfaces(dbus::connection_ptr system_bus,
127 std::string& service_name, std::string& object_name) {
Ed Tanousc9b55212017-06-12 13:25:51 -0700128 dbus::endpoint service_daemon(service_name, object_name,
129 "org.freedestop.DBus.Introspectable");
130 dbus::message m = dbus::message::new_call(service_daemon, "Introspect");
131 try {
Ed Tanous5fceeb42017-06-28 09:43:09 -0700132 auto r = system_bus->send(m);
Ed Tanousc9b55212017-06-12 13:25:51 -0700133 std::vector<std::string> names;
134 // Todo(ed) figure out why we're occassionally getting access
135 // denied errors
136 // EXPECT_EQ(ec, boost::system::errc::success);
137
138 std::string xml;
139 r.unpack(xml);
140 // TODO(ed) names needs lock for multithreaded access
141 dbus::read_dbus_xml_names(xml, names);
142 // loop over the newly added items
143 for (auto name : names) {
144 std::cout << name << "\n";
145 auto new_service_string = object_name + "/" + name;
146 query_interfaces(system_bus, service_name, new_service_string);
147 }
148 } catch (boost::system::error_code e) {
149 std::cout << e;
150 }
151}
152
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700153TEST(BOOST_DBUS, SingleSensorChanged) {
Ed Tanousc9b55212017-06-12 13:25:51 -0700154 boost::asio::io_service io;
Ed Tanous5fceeb42017-06-28 09:43:09 -0700155
156 auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
Ed Tanousc9b55212017-06-12 13:25:51 -0700157
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700158 dbus::match ma(system_bus,
159 "type='signal',path_namespace='/xyz/openbmc_project/sensors'");
Ed Tanous5fceeb42017-06-28 09:43:09 -0700160
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700161 dbus::filter f(system_bus, [](dbus::message& m) {
162 auto member = m.get_member();
163 return member == "PropertiesChanged";
164 });
Ed Tanousc9b55212017-06-12 13:25:51 -0700165
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700166 // std::function<void(boost::system::error_code, dbus::message)> event_handler
167 // =
Ed Tanousc9b55212017-06-12 13:25:51 -0700168
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700169 f.async_dispatch([&](boost::system::error_code ec, dbus::message s) {
170 std::string object_name;
171 EXPECT_EQ(s.get_path(),
172 "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp");
173
174 std::vector<std::pair<std::string, dbus::dbus_variant>> values;
175 s.unpack(object_name).unpack(values);
176
177 EXPECT_EQ(object_name, "xyz.openbmc_project.Sensor.Value");
178
179 EXPECT_EQ(values.size(), 1);
180 auto expected = std::pair<std::string, dbus::dbus_variant>("Value", 42);
181 EXPECT_EQ(values[0], expected);
182
183 io.stop();
184 });
185
186 dbus::endpoint test_endpoint(
187 "org.freedesktop.Avahi",
188 "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp",
189 "org.freedesktop.DBus.Properties");
190
191 auto signal_name = std::string("PropertiesChanged");
192 auto m = dbus::message::new_signal(test_endpoint, signal_name);
193
194 m.pack("xyz.openbmc_project.Sensor.Value");
195
196 std::vector<std::pair<std::string, dbus::dbus_variant>> map2;
197
198 map2.emplace_back("Value", 42);
199
200 m.pack(map2);
201
202 auto removed = std::vector<uint32_t>();
203 m.pack(removed);
Ed Tanous5fceeb42017-06-28 09:43:09 -0700204 system_bus->async_send(m,
205 [&](boost::system::error_code ec, dbus::message s) {});
Ed Tanousc9b55212017-06-12 13:25:51 -0700206
207 io.run();
208}
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700209
210TEST(BOOST_DBUS, MultipleSensorChanged) {
211 boost::asio::io_service io;
Ed Tanous5fceeb42017-06-28 09:43:09 -0700212 auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700213
214 dbus::match ma(system_bus,
215 "type='signal',path_namespace='/xyz/openbmc_project/sensors'");
216 dbus::filter f(system_bus, [](dbus::message& m) {
217 auto member = m.get_member();
218 return member == "PropertiesChanged";
219 });
220
221 int count = 0;
Ed Tanous5fceeb42017-06-28 09:43:09 -0700222 std::function<void(boost::system::error_code, dbus::message)> callback = [&](
223 boost::system::error_code ec, dbus::message s) {
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700224 std::string object_name;
225 EXPECT_EQ(s.get_path(),
226 "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp");
227
228 std::vector<std::pair<std::string, dbus::dbus_variant>> values;
229 s.unpack(object_name).unpack(values);
230
231 EXPECT_EQ(object_name, "xyz.openbmc_project.Sensor.Value");
232
233 EXPECT_EQ(values.size(), 1);
234 auto expected = std::pair<std::string, dbus::dbus_variant>("Value", 42);
235 EXPECT_EQ(values[0], expected);
236 count++;
237 if (count == 2) {
238 io.stop();
Ed Tanous5fceeb42017-06-28 09:43:09 -0700239 } else {
240 f.async_dispatch(callback);
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700241 }
242
Ed Tanous5fceeb42017-06-28 09:43:09 -0700243 };
244 f.async_dispatch(callback);
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700245
246 dbus::endpoint test_endpoint(
247 "org.freedesktop.Avahi",
248 "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp",
249 "org.freedesktop.DBus.Properties");
250
251 auto signal_name = std::string("PropertiesChanged");
252 auto m = dbus::message::new_signal(test_endpoint, signal_name);
253
254 m.pack("xyz.openbmc_project.Sensor.Value");
255
256 std::vector<std::pair<std::string, dbus::dbus_variant>> map2;
257
258 map2.emplace_back("Value", 42);
259
260 m.pack(map2);
261
262 auto removed = std::vector<uint32_t>();
263 m.pack(removed);
Ed Tanous5fceeb42017-06-28 09:43:09 -0700264 system_bus->async_send(m,
265 [&](boost::system::error_code ec, dbus::message s) {});
266 system_bus->async_send(m,
267 [&](boost::system::error_code ec, dbus::message s) {});
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700268 io.run();
Ed Tanous5fceeb42017-06-28 09:43:09 -0700269}
270
271TEST(BOOST_DBUS, MethodCall) {
272 boost::asio::io_service io;
273 boost::asio::deadline_timer t(io, boost::posix_time::seconds(30));
274 t.async_wait([&](const boost::system::error_code& /*e*/) {
275 io.stop();
276 FAIL() << "Callback was never called\n";
277 });
278 std::string requested_name = "xyz.openbmc_project.fwupdate1.server";
279 auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
280 //system_bus->request_name(requested_name);
281
282 /* not sure we even need to add a match for method calls,
283 * but this is how you might do it .... */
284 dbus::match ma(
285 system_bus,
286 "type='method_call',path_namespace='/xyz/openbmc_project/fwupdate1'");
287
288 dbus::filter f(system_bus, [](dbus::message& m) {
289 // std::cerr << "filter called: " << m << std::endl;
290 return (m.get_member() == "Get" &&
291 m.get_interface() == "org.freedesktop.DBus.Properties" &&
292 m.get_signature() == "ss");
293 });
294
295 std::function<void(boost::system::error_code, dbus::message)> method_handler =
296 [&](boost::system::error_code ec, dbus::message s) {
297 if (ec) {
298 FAIL() << ec;
299 } else {
300 std::string intf_name, prop_name;
301 s.unpack(intf_name).unpack(prop_name);
302
303 EXPECT_EQ(intf_name, "xyz.openbmc_project.fwupdate1");
304 EXPECT_EQ(prop_name, "State");
305
306 // send a reply so dbus doesn't get angry?
307 auto r = system_bus->reply(s);
308 r.pack("IDLE");
309 system_bus->async_send(
310 r, [&](boost::system::error_code ec, dbus::message s) {});
311 io.stop();
312 }
313 };
314 f.async_dispatch(method_handler);
315
316 dbus::endpoint test_endpoint(requested_name, "/xyz/openbmc_project/fwupdate1",
317 "org.freedesktop.DBus.Properties");
318
319 auto method_name = std::string("Get");
320 auto m = dbus::message::new_call(test_endpoint, method_name);
321
322 m.pack("xyz.openbmc_project.fwupdate1");
323 m.pack("State");
324
325 system_bus->async_send(m, [&](boost::system::error_code ec, dbus::message s) {
326 std::cerr << "received s: " << s << std::endl;
327 });
328
329 io.run();
330}