xref: /openbmc/boost-dbus/test/avahi.cpp (revision 0d6f56d2a51a2f37c41f95937c0709b12fabdf1b)
1a83e5951SBenjamin Kietzman // Copyright (c) Benjamin Kietzman (github.com/bkietz)
2a83e5951SBenjamin Kietzman //
3a83e5951SBenjamin Kietzman // Distributed under the Boost Software License, Version 1.0. (See accompanying
4a83e5951SBenjamin Kietzman // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5a83e5951SBenjamin Kietzman 
6a83e5951SBenjamin Kietzman #include <dbus/connection.hpp>
716d80fe9SBenjamin Kietzman #include <dbus/endpoint.hpp>
8a83e5951SBenjamin Kietzman #include <dbus/filter.hpp>
9a83e5951SBenjamin Kietzman #include <dbus/match.hpp>
10da3eeb6aSEd Tanous #include <dbus/message.hpp>
11da3eeb6aSEd Tanous #include <functional>
12b2c2467dSBenjamin Kietzman 
13a83e5951SBenjamin Kietzman #include <unistd.h>
14b6e8327aSEd Tanous #include <gmock/gmock.h>
15da3eeb6aSEd Tanous #include <gtest/gtest.h>
16b2c2467dSBenjamin Kietzman 
17da3eeb6aSEd Tanous TEST(AvahiTest, GetHostName) {
18da3eeb6aSEd Tanous   dbus::endpoint test_daemon("org.freedesktop.Avahi", "/",
1916d80fe9SBenjamin Kietzman                              "org.freedesktop.Avahi.Server");
20da3eeb6aSEd Tanous   boost::asio::io_service io;
21b573e22eSEd Tanous   auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
22a83e5951SBenjamin Kietzman 
23da3eeb6aSEd Tanous   dbus::message m = dbus::message::new_call(test_daemon, "GetHostName");
24a83e5951SBenjamin Kietzman 
25b573e22eSEd Tanous   system_bus->async_send(
26da3eeb6aSEd Tanous       m, [&](const boost::system::error_code ec, dbus::message r) {
27a83e5951SBenjamin Kietzman 
28da3eeb6aSEd Tanous         std::string avahi_hostname;
29da3eeb6aSEd Tanous         std::string hostname;
30da3eeb6aSEd Tanous 
31a83e5951SBenjamin Kietzman         // get hostname from a system call
32a83e5951SBenjamin Kietzman         char c[1024];
33a83e5951SBenjamin Kietzman         gethostname(c, 1024);
34da3eeb6aSEd Tanous         hostname = c;
35a83e5951SBenjamin Kietzman 
36b2c2467dSBenjamin Kietzman         r.unpack(avahi_hostname);
37b2c2467dSBenjamin Kietzman 
38da3eeb6aSEd Tanous         // Get only the host name, not the fqdn
39da3eeb6aSEd Tanous         auto unix_hostname = hostname.substr(0, hostname.find("."));
40b2c2467dSBenjamin Kietzman         EXPECT_EQ(unix_hostname, avahi_hostname);
41b2c2467dSBenjamin Kietzman 
42b2c2467dSBenjamin Kietzman         io.stop();
43da3eeb6aSEd Tanous       });
44da3eeb6aSEd Tanous   boost::asio::deadline_timer t(io, boost::posix_time::seconds(10));
45da3eeb6aSEd Tanous   t.async_wait([&](const boost::system::error_code& /*e*/) {
46b2c2467dSBenjamin Kietzman     io.stop();
47da3eeb6aSEd Tanous     FAIL() << "Callback was never called\n";
48da3eeb6aSEd Tanous   });
49a83e5951SBenjamin Kietzman   io.run();
50a83e5951SBenjamin Kietzman }
51a83e5951SBenjamin Kietzman 
52da3eeb6aSEd Tanous TEST(AvahiTest, ServiceBrowser) {
53da3eeb6aSEd Tanous   boost::asio::io_service io;
54b573e22eSEd Tanous   auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
55a83e5951SBenjamin Kietzman 
56da3eeb6aSEd Tanous   dbus::endpoint test_daemon("org.freedesktop.Avahi", "/",
57da3eeb6aSEd Tanous                              "org.freedesktop.Avahi.Server");
58a83e5951SBenjamin Kietzman   // create new service browser
59da3eeb6aSEd Tanous   dbus::message m1 = dbus::message::new_call(test_daemon, "ServiceBrowserNew");
60da3eeb6aSEd Tanous   m1.pack<int32_t>(-1)
61da3eeb6aSEd Tanous       .pack<int32_t>(-1)
62da3eeb6aSEd Tanous       .pack<std::string>("_http._tcp")
63da3eeb6aSEd Tanous       .pack<std::string>("local")
64da3eeb6aSEd Tanous       .pack<uint32_t>(0);
65a83e5951SBenjamin Kietzman 
66b573e22eSEd Tanous   dbus::message r = system_bus->send(m1);
67da3eeb6aSEd Tanous   std::string browser_path;
68a83e5951SBenjamin Kietzman   r.unpack(browser_path);
69da3eeb6aSEd Tanous   testing::Test::RecordProperty("browserPath", browser_path);
70a83e5951SBenjamin Kietzman 
71da3eeb6aSEd Tanous   dbus::match ma(system_bus, "type='signal',path='" + browser_path + "'");
72da3eeb6aSEd Tanous   dbus::filter f(system_bus, [](dbus::message& m) {
73da3eeb6aSEd Tanous     auto member = m.get_member();
74da3eeb6aSEd Tanous     return member == "NameAcquired";
75da3eeb6aSEd Tanous   });
76a83e5951SBenjamin Kietzman 
77da3eeb6aSEd Tanous   std::function<void(boost::system::error_code, dbus::message)> event_handler =
78da3eeb6aSEd Tanous       [&](boost::system::error_code ec, dbus::message s) {
79da3eeb6aSEd Tanous         testing::Test::RecordProperty("firstSignal", s.get_member());
80da3eeb6aSEd Tanous         std::string a = s.get_member();
81da3eeb6aSEd Tanous         std::string dude;
82da3eeb6aSEd Tanous         s.unpack(dude);
83da3eeb6aSEd Tanous         f.async_dispatch(event_handler);
84da3eeb6aSEd Tanous         io.stop();
85da3eeb6aSEd Tanous       };
86da3eeb6aSEd Tanous   f.async_dispatch(event_handler);
87b2c2467dSBenjamin Kietzman 
88da3eeb6aSEd Tanous   boost::asio::deadline_timer t(io, boost::posix_time::seconds(10));
89da3eeb6aSEd Tanous   t.async_wait([&](const boost::system::error_code& /*e*/) {
90da3eeb6aSEd Tanous     io.stop();
91da3eeb6aSEd Tanous     FAIL() << "Callback was never called\n";
92da3eeb6aSEd Tanous   });
93a83e5951SBenjamin Kietzman   io.run();
94a83e5951SBenjamin Kietzman }
95b6e8327aSEd Tanous 
96b6e8327aSEd Tanous TEST(BOOST_DBUS, ListServices) {
97b6e8327aSEd Tanous   boost::asio::io_service io;
98b6e8327aSEd Tanous   boost::asio::deadline_timer t(io, boost::posix_time::seconds(10));
99b6e8327aSEd Tanous   t.async_wait([&](const boost::system::error_code& /*e*/) {
100b6e8327aSEd Tanous     io.stop();
101b6e8327aSEd Tanous     FAIL() << "Callback was never called\n";
102b6e8327aSEd Tanous   });
103b6e8327aSEd Tanous 
104b573e22eSEd Tanous   auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
105b6e8327aSEd Tanous 
106b6e8327aSEd Tanous   dbus::endpoint test_daemon("org.freedesktop.DBus", "/",
107b6e8327aSEd Tanous                              "org.freedesktop.DBus");
108b6e8327aSEd Tanous   // create new service browser
109b6e8327aSEd Tanous   dbus::message m = dbus::message::new_call(test_daemon, "ListNames");
110b573e22eSEd Tanous   system_bus->async_send(
111b6e8327aSEd Tanous       m, [&](const boost::system::error_code ec, dbus::message r) {
112b6e8327aSEd Tanous         io.stop();
113b6e8327aSEd Tanous         std::vector<std::string> services;
114b6e8327aSEd Tanous         r.unpack(services);
115b6e8327aSEd Tanous         // Test a couple things that should always be present.... adapt if
116b6e8327aSEd Tanous         // neccesary
117b6e8327aSEd Tanous         EXPECT_THAT(services, testing::Contains("org.freedesktop.DBus"));
118b6e8327aSEd Tanous         EXPECT_THAT(services, testing::Contains("org.freedesktop.Accounts"));
119b6e8327aSEd Tanous 
120b6e8327aSEd Tanous       });
121b6e8327aSEd Tanous 
122b6e8327aSEd Tanous   io.run();
123b6e8327aSEd Tanous }
124b6e8327aSEd Tanous 
1255d4bd2bdSEd Tanous TEST(BOOST_DBUS, SingleSensorChanged) {
126b6e8327aSEd Tanous   boost::asio::io_service io;
127b6e8327aSEd Tanous 
128b573e22eSEd Tanous   auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
129b573e22eSEd Tanous 
130b573e22eSEd Tanous   dbus::match ma(system_bus, "type='signal',path_namespace='/xyz/openbmc_project/sensors'");
131b573e22eSEd Tanous 
13282a51ce2SEd Tanous   dbus::filter f(system_bus, [](dbus::message& m) {
13382a51ce2SEd Tanous     auto member = m.get_member();
13482a51ce2SEd Tanous     return member == "PropertiesChanged";
13582a51ce2SEd Tanous   });
136b6e8327aSEd Tanous 
1375d4bd2bdSEd Tanous   // std::function<void(boost::system::error_code, dbus::message)> event_handler
1385d4bd2bdSEd Tanous   // =
1395d4bd2bdSEd Tanous 
1405d4bd2bdSEd Tanous   f.async_dispatch([&](boost::system::error_code ec, dbus::message s) {
14182a51ce2SEd Tanous     std::string object_name;
1425d4bd2bdSEd Tanous     EXPECT_EQ(s.get_path(),
1435d4bd2bdSEd Tanous               "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp");
1445d4bd2bdSEd Tanous 
14582a51ce2SEd Tanous     std::vector<std::pair<std::string, dbus::dbus_variant>> values;
146*0d6f56d2SEd Tanous     s.unpack(object_name, values);
14782a51ce2SEd Tanous     EXPECT_EQ(object_name, "xyz.openbmc_project.Sensor.Value");
14882a51ce2SEd Tanous 
1495d4bd2bdSEd Tanous     EXPECT_EQ(values.size(), 1);
15082a51ce2SEd Tanous     auto expected = std::pair<std::string, dbus::dbus_variant>("Value", 42);
1515d4bd2bdSEd Tanous     EXPECT_EQ(values[0], expected);
15282a51ce2SEd Tanous 
153b6e8327aSEd Tanous     io.stop();
1545d4bd2bdSEd Tanous   });
155b6e8327aSEd Tanous 
15682a51ce2SEd Tanous   dbus::endpoint test_endpoint(
15782a51ce2SEd Tanous       "org.freedesktop.Avahi",
15882a51ce2SEd Tanous       "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp",
15982a51ce2SEd Tanous       "org.freedesktop.DBus.Properties");
160b6e8327aSEd Tanous 
16182a51ce2SEd Tanous   auto signal_name = std::string("PropertiesChanged");
16282a51ce2SEd Tanous   auto m = dbus::message::new_signal(test_endpoint, signal_name);
16382a51ce2SEd Tanous 
16482a51ce2SEd Tanous   m.pack("xyz.openbmc_project.Sensor.Value");
16582a51ce2SEd Tanous 
16682a51ce2SEd Tanous   std::vector<std::pair<std::string, dbus::dbus_variant>> map2;
16782a51ce2SEd Tanous 
16882a51ce2SEd Tanous   map2.emplace_back("Value", 42);
16982a51ce2SEd Tanous 
17082a51ce2SEd Tanous   m.pack(map2);
17182a51ce2SEd Tanous 
17282a51ce2SEd Tanous   auto removed = std::vector<uint32_t>();
17382a51ce2SEd Tanous   m.pack(removed);
174b573e22eSEd Tanous   system_bus->async_send(m,
17582a51ce2SEd Tanous                          [&](boost::system::error_code ec, dbus::message s) {});
176b6e8327aSEd Tanous 
177b6e8327aSEd Tanous   io.run();
178b6e8327aSEd Tanous }
1795d4bd2bdSEd Tanous 
1805d4bd2bdSEd Tanous TEST(BOOST_DBUS, MultipleSensorChanged) {
1815d4bd2bdSEd Tanous   boost::asio::io_service io;
182b573e22eSEd Tanous   auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
1835d4bd2bdSEd Tanous 
1845d4bd2bdSEd Tanous   dbus::match ma(system_bus,
1855d4bd2bdSEd Tanous                  "type='signal',path_namespace='/xyz/openbmc_project/sensors'");
1865d4bd2bdSEd Tanous   dbus::filter f(system_bus, [](dbus::message& m) {
1875d4bd2bdSEd Tanous     auto member = m.get_member();
1885d4bd2bdSEd Tanous     return member == "PropertiesChanged";
1895d4bd2bdSEd Tanous   });
1905d4bd2bdSEd Tanous 
1915d4bd2bdSEd Tanous   int count = 0;
192b573e22eSEd Tanous   std::function<void(boost::system::error_code, dbus::message)> callback = [&](
193b573e22eSEd Tanous       boost::system::error_code ec, dbus::message s) {
1945d4bd2bdSEd Tanous     std::string object_name;
1955d4bd2bdSEd Tanous     EXPECT_EQ(s.get_path(),
1965d4bd2bdSEd Tanous               "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp");
1975d4bd2bdSEd Tanous 
1985d4bd2bdSEd Tanous     std::vector<std::pair<std::string, dbus::dbus_variant>> values;
199*0d6f56d2SEd Tanous     s.unpack(object_name, values);
2005d4bd2bdSEd Tanous     EXPECT_EQ(object_name, "xyz.openbmc_project.Sensor.Value");
2015d4bd2bdSEd Tanous 
2025d4bd2bdSEd Tanous     EXPECT_EQ(values.size(), 1);
2035d4bd2bdSEd Tanous     auto expected = std::pair<std::string, dbus::dbus_variant>("Value", 42);
2045d4bd2bdSEd Tanous     EXPECT_EQ(values[0], expected);
2055d4bd2bdSEd Tanous     count++;
2065d4bd2bdSEd Tanous     if (count == 2) {
2075d4bd2bdSEd Tanous       io.stop();
208b573e22eSEd Tanous     } else {
209b573e22eSEd Tanous       f.async_dispatch(callback);
2105d4bd2bdSEd Tanous     }
211*0d6f56d2SEd Tanous     s.unpack(object_name, values);
2125d4bd2bdSEd Tanous 
213b573e22eSEd Tanous   };
214b573e22eSEd Tanous   f.async_dispatch(callback);
2155d4bd2bdSEd Tanous 
2165d4bd2bdSEd Tanous   dbus::endpoint test_endpoint(
2175d4bd2bdSEd Tanous       "org.freedesktop.Avahi",
2185d4bd2bdSEd Tanous       "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp",
2195d4bd2bdSEd Tanous       "org.freedesktop.DBus.Properties");
2205d4bd2bdSEd Tanous 
2215d4bd2bdSEd Tanous   auto signal_name = std::string("PropertiesChanged");
2225d4bd2bdSEd Tanous   auto m = dbus::message::new_signal(test_endpoint, signal_name);
2235d4bd2bdSEd Tanous 
2245d4bd2bdSEd Tanous   m.pack("xyz.openbmc_project.Sensor.Value");
2255d4bd2bdSEd Tanous 
2265d4bd2bdSEd Tanous   std::vector<std::pair<std::string, dbus::dbus_variant>> map2;
2275d4bd2bdSEd Tanous 
2285d4bd2bdSEd Tanous   map2.emplace_back("Value", 42);
2295d4bd2bdSEd Tanous 
2305d4bd2bdSEd Tanous   m.pack(map2);
2315d4bd2bdSEd Tanous 
2325d4bd2bdSEd Tanous   auto removed = std::vector<uint32_t>();
2335d4bd2bdSEd Tanous   m.pack(removed);
234b573e22eSEd Tanous   system_bus->async_send(m,
2355d4bd2bdSEd Tanous                          [&](boost::system::error_code ec, dbus::message s) {});
236b573e22eSEd Tanous   system_bus->async_send(m,
2375d4bd2bdSEd Tanous                          [&](boost::system::error_code ec, dbus::message s) {});
2385d4bd2bdSEd Tanous   io.run();
2395d4bd2bdSEd Tanous }
240458a9c10SVernon Mauery 
241458a9c10SVernon Mauery TEST(BOOST_DBUS, MethodCall) {
242458a9c10SVernon Mauery   boost::asio::io_service io;
243458a9c10SVernon Mauery   boost::asio::deadline_timer t(io, boost::posix_time::seconds(30));
244458a9c10SVernon Mauery   t.async_wait([&](const boost::system::error_code& /*e*/) {
245458a9c10SVernon Mauery     io.stop();
246458a9c10SVernon Mauery     FAIL() << "Callback was never called\n";
247458a9c10SVernon Mauery   });
248458a9c10SVernon Mauery 
249*0d6f56d2SEd Tanous   auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system);
250*0d6f56d2SEd Tanous   std::string requested_name = system_bus->get_unique_name();
251458a9c10SVernon Mauery 
252458a9c10SVernon Mauery   dbus::filter f(system_bus, [](dbus::message& m) {
253458a9c10SVernon Mauery     return (m.get_member() == "Get" &&
254458a9c10SVernon Mauery             m.get_interface() == "org.freedesktop.DBus.Properties" &&
255458a9c10SVernon Mauery             m.get_signature() == "ss");
256458a9c10SVernon Mauery   });
257458a9c10SVernon Mauery 
258458a9c10SVernon Mauery   std::function<void(boost::system::error_code, dbus::message)> method_handler =
259458a9c10SVernon Mauery       [&](boost::system::error_code ec, dbus::message s) {
260*0d6f56d2SEd Tanous         if (ec) {
261*0d6f56d2SEd Tanous           FAIL() << ec;
262*0d6f56d2SEd Tanous         } else {
263458a9c10SVernon Mauery           std::string intf_name, prop_name;
264*0d6f56d2SEd Tanous           s.unpack(intf_name, prop_name);
265458a9c10SVernon Mauery 
266458a9c10SVernon Mauery           EXPECT_EQ(intf_name, "xyz.openbmc_project.fwupdate1");
267458a9c10SVernon Mauery           EXPECT_EQ(prop_name, "State");
268458a9c10SVernon Mauery 
269458a9c10SVernon Mauery           // send a reply so dbus doesn't get angry?
270b573e22eSEd Tanous           auto r = system_bus->reply(s);
271458a9c10SVernon Mauery           r.pack("IDLE");
272*0d6f56d2SEd Tanous           system_bus->async_send(r, [&](boost::system::error_code ec,
273*0d6f56d2SEd Tanous                                         dbus::message s) { });
274458a9c10SVernon Mauery            io.stop();
275*0d6f56d2SEd Tanous         }
276458a9c10SVernon Mauery      };
277458a9c10SVernon Mauery   f.async_dispatch(method_handler);
278458a9c10SVernon Mauery 
279458a9c10SVernon Mauery   dbus::endpoint test_endpoint(
280458a9c10SVernon Mauery       requested_name,
281458a9c10SVernon Mauery       "/xyz/openbmc_project/fwupdate1",
282458a9c10SVernon Mauery       "org.freedesktop.DBus.Properties");
283458a9c10SVernon Mauery 
284458a9c10SVernon Mauery   auto method_name = std::string("Get");
285458a9c10SVernon Mauery   auto m = dbus::message::new_call(test_endpoint, method_name);
286458a9c10SVernon Mauery 
287*0d6f56d2SEd Tanous   m.pack("xyz.openbmc_project.fwupdate1", "State");
288b573e22eSEd Tanous   system_bus->async_send(m,
289458a9c10SVernon Mauery                         [&](boost::system::error_code ec, dbus::message s) {
290458a9c10SVernon Mauery                         std::cerr <<"received s: " << s << std::endl;
291458a9c10SVernon Mauery                         });
292458a9c10SVernon Mauery 
293458a9c10SVernon Mauery   io.run();
294458a9c10SVernon Mauery }
295