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