xref: /openbmc/boost-dbus/test/avahi.cpp (revision b6e8327afa35f444bb681b5ae2122ae21e47c1bd)
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>
11*b6e8327aSEd Tanous #include <dbus/utility.hpp>
12da3eeb6aSEd Tanous #include <functional>
13b2c2467dSBenjamin Kietzman 
14a83e5951SBenjamin Kietzman #include <unistd.h>
15*b6e8327aSEd Tanous #include <gmock/gmock.h>
16da3eeb6aSEd Tanous #include <gtest/gtest.h>
17b2c2467dSBenjamin Kietzman 
18da3eeb6aSEd Tanous TEST(AvahiTest, GetHostName) {
19da3eeb6aSEd Tanous   dbus::endpoint test_daemon("org.freedesktop.Avahi", "/",
2016d80fe9SBenjamin Kietzman                              "org.freedesktop.Avahi.Server");
21da3eeb6aSEd Tanous   boost::asio::io_service io;
22da3eeb6aSEd Tanous   dbus::connection system_bus(io, dbus::bus::system);
23a83e5951SBenjamin Kietzman 
24da3eeb6aSEd Tanous   dbus::message m = dbus::message::new_call(test_daemon, "GetHostName");
25a83e5951SBenjamin Kietzman 
26da3eeb6aSEd Tanous   system_bus.async_send(
27da3eeb6aSEd Tanous       m, [&](const boost::system::error_code ec, dbus::message r) {
28a83e5951SBenjamin Kietzman 
29da3eeb6aSEd Tanous         std::string avahi_hostname;
30da3eeb6aSEd Tanous         std::string hostname;
31da3eeb6aSEd Tanous 
32a83e5951SBenjamin Kietzman         // get hostname from a system call
33a83e5951SBenjamin Kietzman         char c[1024];
34a83e5951SBenjamin Kietzman         gethostname(c, 1024);
35da3eeb6aSEd Tanous         hostname = c;
36a83e5951SBenjamin Kietzman 
37b2c2467dSBenjamin Kietzman         r.unpack(avahi_hostname);
38b2c2467dSBenjamin Kietzman 
39da3eeb6aSEd Tanous         // Get only the host name, not the fqdn
40da3eeb6aSEd Tanous         auto unix_hostname = hostname.substr(0, hostname.find("."));
41b2c2467dSBenjamin Kietzman         EXPECT_EQ(unix_hostname, avahi_hostname);
42b2c2467dSBenjamin Kietzman 
43b2c2467dSBenjamin Kietzman         io.stop();
44da3eeb6aSEd Tanous       });
45da3eeb6aSEd Tanous   boost::asio::deadline_timer t(io, boost::posix_time::seconds(10));
46da3eeb6aSEd Tanous   t.async_wait([&](const boost::system::error_code& /*e*/) {
47b2c2467dSBenjamin Kietzman     io.stop();
48da3eeb6aSEd Tanous     FAIL() << "Callback was never called\n";
49da3eeb6aSEd Tanous   });
50a83e5951SBenjamin Kietzman   io.run();
51a83e5951SBenjamin Kietzman }
52a83e5951SBenjamin Kietzman 
53da3eeb6aSEd Tanous TEST(AvahiTest, ServiceBrowser) {
54da3eeb6aSEd Tanous   boost::asio::io_service io;
55da3eeb6aSEd Tanous   dbus::connection system_bus(io, dbus::bus::system);
56a83e5951SBenjamin Kietzman 
57da3eeb6aSEd Tanous   dbus::endpoint test_daemon("org.freedesktop.Avahi", "/",
58da3eeb6aSEd Tanous                              "org.freedesktop.Avahi.Server");
59a83e5951SBenjamin Kietzman   // create new service browser
60da3eeb6aSEd Tanous   dbus::message m1 = dbus::message::new_call(test_daemon, "ServiceBrowserNew");
61da3eeb6aSEd Tanous   m1.pack<int32_t>(-1)
62da3eeb6aSEd Tanous       .pack<int32_t>(-1)
63da3eeb6aSEd Tanous       .pack<std::string>("_http._tcp")
64da3eeb6aSEd Tanous       .pack<std::string>("local")
65da3eeb6aSEd Tanous       .pack<uint32_t>(0);
66a83e5951SBenjamin Kietzman 
67da3eeb6aSEd Tanous   dbus::message r = system_bus.send(m1);
68da3eeb6aSEd Tanous   std::string browser_path;
69a83e5951SBenjamin Kietzman   r.unpack(browser_path);
70da3eeb6aSEd Tanous   testing::Test::RecordProperty("browserPath", browser_path);
71a83e5951SBenjamin Kietzman 
72da3eeb6aSEd Tanous   dbus::match ma(system_bus, "type='signal',path='" + browser_path + "'");
73da3eeb6aSEd Tanous   dbus::filter f(system_bus, [](dbus::message& m) {
74da3eeb6aSEd Tanous     auto member = m.get_member();
75da3eeb6aSEd Tanous     return member == "NameAcquired";
76da3eeb6aSEd Tanous   });
77a83e5951SBenjamin Kietzman 
78da3eeb6aSEd Tanous   std::function<void(boost::system::error_code, dbus::message)> event_handler =
79da3eeb6aSEd Tanous       [&](boost::system::error_code ec, dbus::message s) {
80da3eeb6aSEd Tanous         testing::Test::RecordProperty("firstSignal", s.get_member());
81da3eeb6aSEd Tanous         std::string a = s.get_member();
82da3eeb6aSEd Tanous         std::string dude;
83da3eeb6aSEd Tanous         s.unpack(dude);
84da3eeb6aSEd Tanous         f.async_dispatch(event_handler);
85da3eeb6aSEd Tanous         io.stop();
86da3eeb6aSEd Tanous       };
87da3eeb6aSEd Tanous   f.async_dispatch(event_handler);
88b2c2467dSBenjamin Kietzman 
89da3eeb6aSEd Tanous   boost::asio::deadline_timer t(io, boost::posix_time::seconds(10));
90da3eeb6aSEd Tanous   t.async_wait([&](const boost::system::error_code& /*e*/) {
91da3eeb6aSEd Tanous     io.stop();
92da3eeb6aSEd Tanous     FAIL() << "Callback was never called\n";
93da3eeb6aSEd Tanous   });
94a83e5951SBenjamin Kietzman   io.run();
95a83e5951SBenjamin Kietzman }
96*b6e8327aSEd Tanous 
97*b6e8327aSEd Tanous TEST(BOOST_DBUS, ListServices) {
98*b6e8327aSEd Tanous   boost::asio::io_service io;
99*b6e8327aSEd Tanous   boost::asio::deadline_timer t(io, boost::posix_time::seconds(10));
100*b6e8327aSEd Tanous   t.async_wait([&](const boost::system::error_code& /*e*/) {
101*b6e8327aSEd Tanous     io.stop();
102*b6e8327aSEd Tanous     FAIL() << "Callback was never called\n";
103*b6e8327aSEd Tanous   });
104*b6e8327aSEd Tanous 
105*b6e8327aSEd Tanous   dbus::connection system_bus(io, dbus::bus::system);
106*b6e8327aSEd Tanous 
107*b6e8327aSEd Tanous   dbus::endpoint test_daemon("org.freedesktop.DBus", "/",
108*b6e8327aSEd Tanous                              "org.freedesktop.DBus");
109*b6e8327aSEd Tanous   // create new service browser
110*b6e8327aSEd Tanous   dbus::message m = dbus::message::new_call(test_daemon, "ListNames");
111*b6e8327aSEd Tanous   system_bus.async_send(
112*b6e8327aSEd Tanous       m, [&](const boost::system::error_code ec, dbus::message r) {
113*b6e8327aSEd Tanous         io.stop();
114*b6e8327aSEd Tanous         std::vector<std::string> services;
115*b6e8327aSEd Tanous         r.unpack(services);
116*b6e8327aSEd Tanous         // Test a couple things that should always be present.... adapt if
117*b6e8327aSEd Tanous         // neccesary
118*b6e8327aSEd Tanous         EXPECT_THAT(services, testing::Contains("org.freedesktop.DBus"));
119*b6e8327aSEd Tanous         EXPECT_THAT(services, testing::Contains("org.freedesktop.Accounts"));
120*b6e8327aSEd Tanous 
121*b6e8327aSEd Tanous       });
122*b6e8327aSEd Tanous 
123*b6e8327aSEd Tanous   io.run();
124*b6e8327aSEd Tanous }
125*b6e8327aSEd Tanous 
126*b6e8327aSEd Tanous TEST(BOOST_DBUS, ListObjects) {
127*b6e8327aSEd Tanous   boost::asio::io_service io;
128*b6e8327aSEd Tanous   dbus::connection system_bus(io, dbus::bus::system);
129*b6e8327aSEd Tanous 
130*b6e8327aSEd Tanous   dbus::endpoint test_daemon("org.freedesktop.DBus", "/",
131*b6e8327aSEd Tanous                              "org.freedesktop.DBus");
132*b6e8327aSEd Tanous 
133*b6e8327aSEd Tanous   // create new service browser
134*b6e8327aSEd Tanous   dbus::message m = dbus::message::new_call(test_daemon, "ListNames");
135*b6e8327aSEd Tanous   system_bus.async_send(m, [&](const boost::system::error_code ec,
136*b6e8327aSEd Tanous                                dbus::message r) {
137*b6e8327aSEd Tanous     static std::vector<std::string> services;
138*b6e8327aSEd Tanous     r.unpack(services);
139*b6e8327aSEd Tanous     // todo(ed) find out why this needs to be atomic
140*b6e8327aSEd Tanous     static std::atomic<int> dbus_count(0);
141*b6e8327aSEd Tanous     std::cout << dbus_count << " Callers\n";
142*b6e8327aSEd Tanous     auto names = std::make_shared<std::vector<std::string>>();
143*b6e8327aSEd Tanous     for (auto& service : services) {
144*b6e8327aSEd Tanous       dbus::endpoint service_daemon(service, "/",
145*b6e8327aSEd Tanous                                     "org.freedesktop.DBus.Introspectable");
146*b6e8327aSEd Tanous       dbus::message m = dbus::message::new_call(service_daemon, "Introspect");
147*b6e8327aSEd Tanous       dbus_count++;
148*b6e8327aSEd Tanous       std::cout << dbus_count << " Callers\n";
149*b6e8327aSEd Tanous 
150*b6e8327aSEd Tanous       system_bus.async_send(m, [&io, &service, names](
151*b6e8327aSEd Tanous                                    const boost::system::error_code ec,
152*b6e8327aSEd Tanous                                    dbus::message r) {
153*b6e8327aSEd Tanous         dbus_count--;
154*b6e8327aSEd Tanous         std::cout << service << "\n";
155*b6e8327aSEd Tanous         // Todo(ed) figure out why we're occassionally getting access denied
156*b6e8327aSEd Tanous         // errors
157*b6e8327aSEd Tanous         // EXPECT_EQ(ec, boost::system::errc::success);
158*b6e8327aSEd Tanous         if (ec) {
159*b6e8327aSEd Tanous           std::cout << "Error:" << ec << " reading service " << service << "\n";
160*b6e8327aSEd Tanous         } else {
161*b6e8327aSEd Tanous           std::string xml;
162*b6e8327aSEd Tanous           r.unpack(xml);
163*b6e8327aSEd Tanous           size_t old_size = names->size();
164*b6e8327aSEd Tanous           // TODO(ed) names needs lock for multithreaded access
165*b6e8327aSEd Tanous           dbus::read_dbus_xml_names(xml, *names);
166*b6e8327aSEd Tanous           // loop over the newly added items
167*b6e8327aSEd Tanous           for (size_t name_index = old_size; name_index < names->size();
168*b6e8327aSEd Tanous                name_index++) {
169*b6e8327aSEd Tanous             // auto& name = names[name_index];
170*b6e8327aSEd Tanous           }
171*b6e8327aSEd Tanous         }
172*b6e8327aSEd Tanous         // if we're the last one, print the list and cancel the io_service
173*b6e8327aSEd Tanous         if (dbus_count == 0) {
174*b6e8327aSEd Tanous           for (auto& name : *names) {
175*b6e8327aSEd Tanous             std::cout << name << "\n";
176*b6e8327aSEd Tanous           }
177*b6e8327aSEd Tanous           io.stop();
178*b6e8327aSEd Tanous         }
179*b6e8327aSEd Tanous       });
180*b6e8327aSEd Tanous 
181*b6e8327aSEd Tanous       std::function<void(const boost::system::error_code ec, dbus::message r)>
182*b6e8327aSEd Tanous           event_handler =
183*b6e8327aSEd Tanous               [&](const boost::system::error_code ec, dbus::message r) {};
184*b6e8327aSEd Tanous       system_bus.async_send(m, event_handler);
185*b6e8327aSEd Tanous     }
186*b6e8327aSEd Tanous 
187*b6e8327aSEd Tanous   });
188*b6e8327aSEd Tanous 
189*b6e8327aSEd Tanous   io.run();
190*b6e8327aSEd Tanous }
191