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 <functional> 12 13 #include <unistd.h> 14 #include <gmock/gmock.h> 15 #include <gtest/gtest.h> 16 17 TEST(AvahiTest, GetHostName) { 18 dbus::endpoint test_daemon("org.freedesktop.Avahi", "/", 19 "org.freedesktop.Avahi.Server"); 20 boost::asio::io_service io; 21 auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system); 22 23 dbus::message m = dbus::message::new_call(test_daemon, "GetHostName"); 24 25 system_bus->async_send( 26 m, [&](const boost::system::error_code ec, dbus::message r) { 27 28 std::string avahi_hostname; 29 std::string hostname; 30 31 // get hostname from a system call 32 char c[1024]; 33 gethostname(c, 1024); 34 hostname = c; 35 36 r.unpack(avahi_hostname); 37 38 // Get only the host name, not the fqdn 39 auto unix_hostname = hostname.substr(0, hostname.find(".")); 40 EXPECT_EQ(unix_hostname, avahi_hostname); 41 42 io.stop(); 43 }); 44 boost::asio::deadline_timer t(io, boost::posix_time::seconds(10)); 45 t.async_wait([&](const boost::system::error_code& /*e*/) { 46 io.stop(); 47 FAIL() << "Callback was never called\n"; 48 }); 49 io.run(); 50 } 51 52 TEST(AvahiTest, ServiceBrowser) { 53 boost::asio::io_service io; 54 auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system); 55 56 dbus::endpoint test_daemon("org.freedesktop.Avahi", "/", 57 "org.freedesktop.Avahi.Server"); 58 // create new service browser 59 dbus::message m1 = dbus::message::new_call(test_daemon, "ServiceBrowserNew"); 60 m1.pack<int32_t>(-1) 61 .pack<int32_t>(-1) 62 .pack<std::string>("_http._tcp") 63 .pack<std::string>("local") 64 .pack<uint32_t>(0); 65 66 dbus::message r = system_bus->send(m1); 67 std::string browser_path; 68 r.unpack(browser_path); 69 testing::Test::RecordProperty("browserPath", browser_path); 70 71 dbus::match ma(system_bus, "type='signal',path='" + browser_path + "'"); 72 dbus::filter f(system_bus, [](dbus::message& m) { 73 auto member = m.get_member(); 74 return member == "NameAcquired"; 75 }); 76 77 std::function<void(boost::system::error_code, dbus::message)> event_handler = 78 [&](boost::system::error_code ec, dbus::message s) { 79 testing::Test::RecordProperty("firstSignal", s.get_member()); 80 std::string a = s.get_member(); 81 std::string dude; 82 s.unpack(dude); 83 f.async_dispatch(event_handler); 84 io.stop(); 85 }; 86 f.async_dispatch(event_handler); 87 88 boost::asio::deadline_timer t(io, boost::posix_time::seconds(10)); 89 t.async_wait([&](const boost::system::error_code& /*e*/) { 90 io.stop(); 91 FAIL() << "Callback was never called\n"; 92 }); 93 io.run(); 94 } 95 96 TEST(BOOST_DBUS, ListServices) { 97 boost::asio::io_service io; 98 boost::asio::deadline_timer t(io, boost::posix_time::seconds(10)); 99 t.async_wait([&](const boost::system::error_code& /*e*/) { 100 io.stop(); 101 FAIL() << "Callback was never called\n"; 102 }); 103 104 auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system); 105 106 dbus::endpoint test_daemon("org.freedesktop.DBus", "/", 107 "org.freedesktop.DBus"); 108 // create new service browser 109 dbus::message m = dbus::message::new_call(test_daemon, "ListNames"); 110 system_bus->async_send( 111 m, [&](const boost::system::error_code ec, dbus::message r) { 112 io.stop(); 113 std::vector<std::string> services; 114 r.unpack(services); 115 // Test a couple things that should always be present.... adapt if 116 // neccesary 117 EXPECT_THAT(services, testing::Contains("org.freedesktop.DBus")); 118 EXPECT_THAT(services, testing::Contains("org.freedesktop.Accounts")); 119 120 }); 121 122 io.run(); 123 } 124 125 TEST(BOOST_DBUS, SingleSensorChanged) { 126 boost::asio::io_service io; 127 128 auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system); 129 130 dbus::match ma(system_bus, "type='signal',path_namespace='/xyz/openbmc_project/sensors'"); 131 132 dbus::filter f(system_bus, [](dbus::message& m) { 133 auto member = m.get_member(); 134 return member == "PropertiesChanged"; 135 }); 136 137 // std::function<void(boost::system::error_code, dbus::message)> event_handler 138 // = 139 140 f.async_dispatch([&](boost::system::error_code ec, dbus::message s) { 141 std::string object_name; 142 EXPECT_EQ(s.get_path(), 143 "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp"); 144 145 std::vector<std::pair<std::string, dbus::dbus_variant>> values; 146 s.unpack(object_name, values); 147 EXPECT_EQ(object_name, "xyz.openbmc_project.Sensor.Value"); 148 149 EXPECT_EQ(values.size(), 1); 150 auto expected = std::pair<std::string, dbus::dbus_variant>("Value", 42); 151 EXPECT_EQ(values[0], expected); 152 153 io.stop(); 154 }); 155 156 dbus::endpoint test_endpoint( 157 "org.freedesktop.Avahi", 158 "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp", 159 "org.freedesktop.DBus.Properties"); 160 161 auto signal_name = std::string("PropertiesChanged"); 162 auto m = dbus::message::new_signal(test_endpoint, signal_name); 163 164 m.pack("xyz.openbmc_project.Sensor.Value"); 165 166 std::vector<std::pair<std::string, dbus::dbus_variant>> map2; 167 168 map2.emplace_back("Value", 42); 169 170 m.pack(map2); 171 172 auto removed = std::vector<uint32_t>(); 173 m.pack(removed); 174 system_bus->async_send(m, 175 [&](boost::system::error_code ec, dbus::message s) {}); 176 177 io.run(); 178 } 179 180 TEST(BOOST_DBUS, MultipleSensorChanged) { 181 boost::asio::io_service io; 182 auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system); 183 184 dbus::match ma(system_bus, 185 "type='signal',path_namespace='/xyz/openbmc_project/sensors'"); 186 dbus::filter f(system_bus, [](dbus::message& m) { 187 auto member = m.get_member(); 188 return member == "PropertiesChanged"; 189 }); 190 191 int count = 0; 192 std::function<void(boost::system::error_code, dbus::message)> callback = [&]( 193 boost::system::error_code ec, dbus::message s) { 194 std::string object_name; 195 EXPECT_EQ(s.get_path(), 196 "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp"); 197 198 std::vector<std::pair<std::string, dbus::dbus_variant>> values; 199 s.unpack(object_name, values); 200 EXPECT_EQ(object_name, "xyz.openbmc_project.Sensor.Value"); 201 202 EXPECT_EQ(values.size(), 1); 203 auto expected = std::pair<std::string, dbus::dbus_variant>("Value", 42); 204 EXPECT_EQ(values[0], expected); 205 count++; 206 if (count == 2) { 207 io.stop(); 208 } else { 209 f.async_dispatch(callback); 210 } 211 s.unpack(object_name, values); 212 213 }; 214 f.async_dispatch(callback); 215 216 dbus::endpoint test_endpoint( 217 "org.freedesktop.Avahi", 218 "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp", 219 "org.freedesktop.DBus.Properties"); 220 221 auto signal_name = std::string("PropertiesChanged"); 222 auto m = dbus::message::new_signal(test_endpoint, signal_name); 223 224 m.pack("xyz.openbmc_project.Sensor.Value"); 225 226 std::vector<std::pair<std::string, dbus::dbus_variant>> map2; 227 228 map2.emplace_back("Value", 42); 229 230 m.pack(map2); 231 232 auto removed = std::vector<uint32_t>(); 233 m.pack(removed); 234 system_bus->async_send(m, 235 [&](boost::system::error_code ec, dbus::message s) {}); 236 system_bus->async_send(m, 237 [&](boost::system::error_code ec, dbus::message s) {}); 238 io.run(); 239 } 240 241 TEST(BOOST_DBUS, MethodCall) { 242 boost::asio::io_service io; 243 boost::asio::deadline_timer t(io, boost::posix_time::seconds(30)); 244 t.async_wait([&](const boost::system::error_code& /*e*/) { 245 io.stop(); 246 FAIL() << "Callback was never called\n"; 247 }); 248 249 auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system); 250 std::string requested_name = system_bus->get_unique_name(); 251 252 dbus::filter f(system_bus, [](dbus::message& m) { 253 return (m.get_member() == "Get" && 254 m.get_interface() == "org.freedesktop.DBus.Properties" && 255 m.get_signature() == "ss"); 256 }); 257 258 std::function<void(boost::system::error_code, dbus::message)> method_handler = 259 [&](boost::system::error_code ec, dbus::message s) { 260 if (ec) { 261 FAIL() << ec; 262 } else { 263 std::string intf_name, prop_name; 264 s.unpack(intf_name, prop_name); 265 266 EXPECT_EQ(intf_name, "xyz.openbmc_project.fwupdate1"); 267 EXPECT_EQ(prop_name, "State"); 268 269 // send a reply so dbus doesn't get angry? 270 auto r = system_bus->reply(s); 271 r.pack("IDLE"); 272 system_bus->async_send(r, [&](boost::system::error_code ec, 273 dbus::message s) { }); 274 io.stop(); 275 } 276 }; 277 f.async_dispatch(method_handler); 278 279 dbus::endpoint test_endpoint( 280 requested_name, 281 "/xyz/openbmc_project/fwupdate1", 282 "org.freedesktop.DBus.Properties"); 283 284 auto method_name = std::string("Get"); 285 auto m = dbus::message::new_call(test_endpoint, method_name); 286 287 m.pack("xyz.openbmc_project.fwupdate1", "State"); 288 system_bus->async_send(m, 289 [&](boost::system::error_code ec, dbus::message s) { 290 std::cerr <<"received s: " << s << std::endl; 291 }); 292 293 io.run(); 294 } 295