xref: /openbmc/boost-dbus/test/avahi.cpp (revision b6e8327a)
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 TEST(BOOST_DBUS, ListObjects) {
127   boost::asio::io_service io;
128   dbus::connection system_bus(io, dbus::bus::system);
129 
130   dbus::endpoint test_daemon("org.freedesktop.DBus", "/",
131                              "org.freedesktop.DBus");
132 
133   // create new service browser
134   dbus::message m = dbus::message::new_call(test_daemon, "ListNames");
135   system_bus.async_send(m, [&](const boost::system::error_code ec,
136                                dbus::message r) {
137     static std::vector<std::string> services;
138     r.unpack(services);
139     // todo(ed) find out why this needs to be atomic
140     static std::atomic<int> dbus_count(0);
141     std::cout << dbus_count << " Callers\n";
142     auto names = std::make_shared<std::vector<std::string>>();
143     for (auto& service : services) {
144       dbus::endpoint service_daemon(service, "/",
145                                     "org.freedesktop.DBus.Introspectable");
146       dbus::message m = dbus::message::new_call(service_daemon, "Introspect");
147       dbus_count++;
148       std::cout << dbus_count << " Callers\n";
149 
150       system_bus.async_send(m, [&io, &service, names](
151                                    const boost::system::error_code ec,
152                                    dbus::message r) {
153         dbus_count--;
154         std::cout << service << "\n";
155         // Todo(ed) figure out why we're occassionally getting access denied
156         // errors
157         // EXPECT_EQ(ec, boost::system::errc::success);
158         if (ec) {
159           std::cout << "Error:" << ec << " reading service " << service << "\n";
160         } else {
161           std::string xml;
162           r.unpack(xml);
163           size_t old_size = names->size();
164           // TODO(ed) names needs lock for multithreaded access
165           dbus::read_dbus_xml_names(xml, *names);
166           // loop over the newly added items
167           for (size_t name_index = old_size; name_index < names->size();
168                name_index++) {
169             // auto& name = names[name_index];
170           }
171         }
172         // if we're the last one, print the list and cancel the io_service
173         if (dbus_count == 0) {
174           for (auto& name : *names) {
175             std::cout << name << "\n";
176           }
177           io.stop();
178         }
179       });
180 
181       std::function<void(const boost::system::error_code ec, dbus::message r)>
182           event_handler =
183               [&](const boost::system::error_code ec, dbus::message r) {};
184       system_bus.async_send(m, event_handler);
185     }
186 
187   });
188 
189   io.run();
190 }
191