xref: /openbmc/boost-dbus/test/avahi.cpp (revision 82a51ce2)
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 <dbus/utility.hpp>
12 #include <functional>
13 
14 #include <unistd.h>
15 #include <gmock/gmock.h>
16 #include <gtest/gtest.h>
17 
18 TEST(AvahiTest, GetHostName) {
19   dbus::endpoint test_daemon("org.freedesktop.Avahi", "/",
20                              "org.freedesktop.Avahi.Server");
21   boost::asio::io_service io;
22   dbus::connection system_bus(io, dbus::bus::system);
23 
24   dbus::message m = dbus::message::new_call(test_daemon, "GetHostName");
25 
26   system_bus.async_send(
27       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 
53 TEST(AvahiTest, ServiceBrowser) {
54   boost::asio::io_service io;
55   dbus::connection system_bus(io, dbus::bus::system);
56 
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 
67   dbus::message r = system_bus.send(m1);
68   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 
97 TEST(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 
105   dbus::connection system_bus(io, dbus::bus::system);
106 
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");
111   system_bus.async_send(
112       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 
126 void query_interfaces(dbus::connection& system_bus, std::string& service_name,
127                       std::string& object_name) {
128   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 {
132     auto r = system_bus.send(m);
133     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 
153 TEST(BOOST_DBUS, ObjectManager) {
154   boost::asio::io_service io;
155   dbus::connection system_bus(io, dbus::bus::system);
156 
157   dbus::match ma(system_bus,
158                  "type='signal',path_namespace='/xyz/openbmc_project/sensors'");
159   dbus::filter f(system_bus, [](dbus::message& m) {
160     auto member = m.get_member();
161     return member == "PropertiesChanged";
162   });
163 
164   std::function<void(boost::system::error_code, dbus::message)> event_handler =
165       [&](boost::system::error_code ec, dbus::message s) {
166         std::string object_name;
167         std::vector<std::pair<std::string, dbus::dbus_variant>> values;
168         s.unpack(object_name).unpack(values);
169 
170         EXPECT_EQ(object_name, "xyz.openbmc_project.Sensor.Value");
171 
172         //EXPECT_EQ(values.size(), 1);
173         auto expected = std::pair<std::string, dbus::dbus_variant>("Value", 42);
174         //EXPECT_EQ(values[0], expected);
175         //s.unpack(values);
176 
177         //f.async_dispatch(event_handler);
178         io.stop();
179       };
180   f.async_dispatch(event_handler);
181 
182   dbus::endpoint test_endpoint(
183       "org.freedesktop.Avahi",
184       "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp",
185       "org.freedesktop.DBus.Properties");
186 
187   auto signal_name = std::string("PropertiesChanged");
188   auto m = dbus::message::new_signal(test_endpoint, signal_name);
189 
190   m.pack("xyz.openbmc_project.Sensor.Value");
191 
192   std::vector<std::pair<std::string, dbus::dbus_variant>> map2;
193 
194   map2.emplace_back("Value", 42);
195 
196   m.pack(map2);
197 
198   auto removed = std::vector<uint32_t>();
199   m.pack(removed);
200   system_bus.async_send(m,
201                         [&](boost::system::error_code ec, dbus::message s) {});
202 
203   io.run();
204 }
205