// Copyright (c) Benjamin Kietzman (github.com/bkietz) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include #include #include #include #include #include TEST(AvahiTest, GetHostName) { dbus::endpoint test_daemon("org.freedesktop.Avahi", "/", "org.freedesktop.Avahi.Server"); boost::asio::io_service io; auto system_bus = std::make_shared(io, dbus::bus::system); dbus::message m = dbus::message::new_call(test_daemon, "GetHostName"); system_bus->async_send( m, [&](const boost::system::error_code ec, dbus::message r) { std::string avahi_hostname; std::string hostname; // get hostname from a system call char c[1024]; gethostname(c, 1024); hostname = c; r.unpack(avahi_hostname); // Get only the host name, not the fqdn auto unix_hostname = hostname.substr(0, hostname.find(".")); EXPECT_EQ(unix_hostname, avahi_hostname); io.stop(); }); boost::asio::deadline_timer t(io, boost::posix_time::seconds(10)); t.async_wait([&](const boost::system::error_code& /*e*/) { io.stop(); FAIL() << "Callback was never called\n"; }); io.run(); } TEST(AvahiTest, ServiceBrowser) { boost::asio::io_service io; auto system_bus = std::make_shared(io, dbus::bus::system); dbus::endpoint test_daemon("org.freedesktop.Avahi", "/", "org.freedesktop.Avahi.Server"); // create new service browser dbus::message m1 = dbus::message::new_call(test_daemon, "ServiceBrowserNew"); m1.pack(-1) .pack(-1) .pack("_http._tcp") .pack("local") .pack(0); dbus::message r = system_bus->send(m1); std::string browser_path; r.unpack(browser_path); testing::Test::RecordProperty("browserPath", browser_path); dbus::match ma(system_bus, "type='signal',path='" + browser_path + "'"); dbus::filter f(system_bus, [](dbus::message& m) { auto member = m.get_member(); return member == "NameAcquired"; }); std::function event_handler = [&](boost::system::error_code ec, dbus::message s) { testing::Test::RecordProperty("firstSignal", s.get_member()); std::string a = s.get_member(); std::string dude; s.unpack(dude); f.async_dispatch(event_handler); io.stop(); }; f.async_dispatch(event_handler); boost::asio::deadline_timer t(io, boost::posix_time::seconds(10)); t.async_wait([&](const boost::system::error_code& /*e*/) { io.stop(); FAIL() << "Callback was never called\n"; }); io.run(); } TEST(BOOST_DBUS, ListServices) { boost::asio::io_service io; boost::asio::deadline_timer t(io, boost::posix_time::seconds(10)); t.async_wait([&](const boost::system::error_code& /*e*/) { io.stop(); FAIL() << "Callback was never called\n"; }); auto system_bus = std::make_shared(io, dbus::bus::system); dbus::endpoint test_daemon("org.freedesktop.DBus", "/", "org.freedesktop.DBus"); // create new service browser dbus::message m = dbus::message::new_call(test_daemon, "ListNames"); system_bus->async_send( m, [&](const boost::system::error_code ec, dbus::message r) { io.stop(); std::vector services; r.unpack(services); // Test a couple things that should always be present.... adapt if // neccesary EXPECT_THAT(services, testing::Contains("org.freedesktop.DBus")); EXPECT_THAT(services, testing::Contains("org.freedesktop.Accounts")); }); io.run(); } void query_interfaces(dbus::connection_ptr system_bus, std::string& service_name, std::string& object_name) { dbus::endpoint service_daemon(service_name, object_name, "org.freedestop.DBus.Introspectable"); dbus::message m = dbus::message::new_call(service_daemon, "Introspect"); try { auto r = system_bus->send(m); std::vector names; // Todo(ed) figure out why we're occassionally getting access // denied errors // EXPECT_EQ(ec, boost::system::errc::success); std::string xml; r.unpack(xml); // TODO(ed) names needs lock for multithreaded access dbus::read_dbus_xml_names(xml, names); // loop over the newly added items for (auto name : names) { std::cout << name << "\n"; auto new_service_string = object_name + "/" + name; query_interfaces(system_bus, service_name, new_service_string); } } catch (boost::system::error_code e) { std::cout << e; } } TEST(BOOST_DBUS, SingleSensorChanged) { boost::asio::io_service io; auto system_bus = std::make_shared(io, dbus::bus::system); dbus::match ma(system_bus, "type='signal',path_namespace='/xyz/openbmc_project/sensors'"); dbus::filter f(system_bus, [](dbus::message& m) { auto member = m.get_member(); return member == "PropertiesChanged"; }); // std::function event_handler // = f.async_dispatch([&](boost::system::error_code ec, dbus::message s) { std::string object_name; EXPECT_EQ(s.get_path(), "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp"); std::vector> values; s.unpack(object_name).unpack(values); EXPECT_EQ(object_name, "xyz.openbmc_project.Sensor.Value"); EXPECT_EQ(values.size(), 1); auto expected = std::pair("Value", 42); EXPECT_EQ(values[0], expected); io.stop(); }); dbus::endpoint test_endpoint( "org.freedesktop.Avahi", "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp", "org.freedesktop.DBus.Properties"); auto signal_name = std::string("PropertiesChanged"); auto m = dbus::message::new_signal(test_endpoint, signal_name); m.pack("xyz.openbmc_project.Sensor.Value"); std::vector> map2; map2.emplace_back("Value", 42); m.pack(map2); auto removed = std::vector(); m.pack(removed); system_bus->async_send(m, [&](boost::system::error_code ec, dbus::message s) {}); io.run(); } TEST(BOOST_DBUS, MultipleSensorChanged) { boost::asio::io_service io; auto system_bus = std::make_shared(io, dbus::bus::system); dbus::match ma(system_bus, "type='signal',path_namespace='/xyz/openbmc_project/sensors'"); dbus::filter f(system_bus, [](dbus::message& m) { auto member = m.get_member(); return member == "PropertiesChanged"; }); int count = 0; std::function callback = [&]( boost::system::error_code ec, dbus::message s) { std::string object_name; EXPECT_EQ(s.get_path(), "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp"); std::vector> values; s.unpack(object_name).unpack(values); EXPECT_EQ(object_name, "xyz.openbmc_project.Sensor.Value"); EXPECT_EQ(values.size(), 1); auto expected = std::pair("Value", 42); EXPECT_EQ(values[0], expected); count++; if (count == 2) { io.stop(); } else { f.async_dispatch(callback); } }; f.async_dispatch(callback); dbus::endpoint test_endpoint( "org.freedesktop.Avahi", "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp", "org.freedesktop.DBus.Properties"); auto signal_name = std::string("PropertiesChanged"); auto m = dbus::message::new_signal(test_endpoint, signal_name); m.pack("xyz.openbmc_project.Sensor.Value"); std::vector> map2; map2.emplace_back("Value", 42); m.pack(map2); auto removed = std::vector(); m.pack(removed); system_bus->async_send(m, [&](boost::system::error_code ec, dbus::message s) {}); system_bus->async_send(m, [&](boost::system::error_code ec, dbus::message s) {}); io.run(); } TEST(BOOST_DBUS, MethodCall) { boost::asio::io_service io; boost::asio::deadline_timer t(io, boost::posix_time::seconds(30)); t.async_wait([&](const boost::system::error_code& /*e*/) { io.stop(); FAIL() << "Callback was never called\n"; }); auto system_bus = std::make_shared(io, dbus::bus::system); std::string requested_name = "xyz.openbmc_project.fwupdate1.server"; system_bus->request_name(requested_name); /* not sure we even need to add a match for method calls, * but this is how you might do it .... */ dbus::match ma(system_bus, "type='method_call',path_namespace='/xyz/openbmc_project/fwupdate1'"); dbus::filter f(system_bus, [](dbus::message& m) { // std::cerr << "filter called: " << m << std::endl; return (m.get_member() == "Get" && m.get_interface() == "org.freedesktop.DBus.Properties" && m.get_signature() == "ss"); }); std::function method_handler = [&](boost::system::error_code ec, dbus::message s) { std::string intf_name, prop_name; s.unpack(intf_name).unpack(prop_name); EXPECT_EQ(intf_name, "xyz.openbmc_project.fwupdate1"); EXPECT_EQ(prop_name, "State"); // send a reply so dbus doesn't get angry? auto r = system_bus->reply(s); r.pack("IDLE"); system_bus->async_send(r, [&](boost::system::error_code ec, dbus::message s) {} ); io.stop(); }; f.async_dispatch(method_handler); dbus::endpoint test_endpoint( requested_name, "/xyz/openbmc_project/fwupdate1", "org.freedesktop.DBus.Properties"); auto method_name = std::string("Get"); auto m = dbus::message::new_call(test_endpoint, method_name); m.pack("xyz.openbmc_project.fwupdate1"); m.pack("State"); system_bus->async_send(m, [&](boost::system::error_code ec, dbus::message s) { std::cerr <<"received s: " << s << std::endl; }); io.run(); }