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> 11da3eeb6aSEd Tanous #include <functional> 12b2c2467dSBenjamin Kietzman 13a83e5951SBenjamin Kietzman #include <unistd.h> 14b6e8327aSEd Tanous #include <gmock/gmock.h> 15da3eeb6aSEd Tanous #include <gtest/gtest.h> 16b2c2467dSBenjamin Kietzman 17da3eeb6aSEd Tanous TEST(AvahiTest, GetHostName) { 18da3eeb6aSEd Tanous dbus::endpoint test_daemon("org.freedesktop.Avahi", "/", 1916d80fe9SBenjamin Kietzman "org.freedesktop.Avahi.Server"); 20da3eeb6aSEd Tanous boost::asio::io_service io; 21b573e22eSEd Tanous auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system); 22a83e5951SBenjamin Kietzman 23da3eeb6aSEd Tanous dbus::message m = dbus::message::new_call(test_daemon, "GetHostName"); 24a83e5951SBenjamin Kietzman 25b573e22eSEd Tanous system_bus->async_send( 26da3eeb6aSEd Tanous m, [&](const boost::system::error_code ec, dbus::message r) { 27a83e5951SBenjamin Kietzman 28da3eeb6aSEd Tanous std::string avahi_hostname; 29da3eeb6aSEd Tanous std::string hostname; 30da3eeb6aSEd Tanous 31a83e5951SBenjamin Kietzman // get hostname from a system call 32a83e5951SBenjamin Kietzman char c[1024]; 33a83e5951SBenjamin Kietzman gethostname(c, 1024); 34da3eeb6aSEd Tanous hostname = c; 35a83e5951SBenjamin Kietzman 36b2c2467dSBenjamin Kietzman r.unpack(avahi_hostname); 37b2c2467dSBenjamin Kietzman 38da3eeb6aSEd Tanous // Get only the host name, not the fqdn 39da3eeb6aSEd Tanous auto unix_hostname = hostname.substr(0, hostname.find(".")); 40b2c2467dSBenjamin Kietzman EXPECT_EQ(unix_hostname, avahi_hostname); 41b2c2467dSBenjamin Kietzman 42b2c2467dSBenjamin Kietzman io.stop(); 43da3eeb6aSEd Tanous }); 44da3eeb6aSEd Tanous boost::asio::deadline_timer t(io, boost::posix_time::seconds(10)); 45da3eeb6aSEd Tanous t.async_wait([&](const boost::system::error_code& /*e*/) { 46b2c2467dSBenjamin Kietzman io.stop(); 47da3eeb6aSEd Tanous FAIL() << "Callback was never called\n"; 48da3eeb6aSEd Tanous }); 49a83e5951SBenjamin Kietzman io.run(); 50a83e5951SBenjamin Kietzman } 51a83e5951SBenjamin Kietzman 52da3eeb6aSEd Tanous TEST(AvahiTest, ServiceBrowser) { 53da3eeb6aSEd Tanous boost::asio::io_service io; 54b573e22eSEd Tanous auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system); 55a83e5951SBenjamin Kietzman 56da3eeb6aSEd Tanous dbus::endpoint test_daemon("org.freedesktop.Avahi", "/", 57da3eeb6aSEd Tanous "org.freedesktop.Avahi.Server"); 58a83e5951SBenjamin Kietzman // create new service browser 59da3eeb6aSEd Tanous dbus::message m1 = dbus::message::new_call(test_daemon, "ServiceBrowserNew"); 60da3eeb6aSEd Tanous m1.pack<int32_t>(-1) 61da3eeb6aSEd Tanous .pack<int32_t>(-1) 62da3eeb6aSEd Tanous .pack<std::string>("_http._tcp") 63da3eeb6aSEd Tanous .pack<std::string>("local") 64da3eeb6aSEd Tanous .pack<uint32_t>(0); 65a83e5951SBenjamin Kietzman 66b573e22eSEd Tanous dbus::message r = system_bus->send(m1); 67da3eeb6aSEd Tanous std::string browser_path; 68a83e5951SBenjamin Kietzman r.unpack(browser_path); 69da3eeb6aSEd Tanous testing::Test::RecordProperty("browserPath", browser_path); 70a83e5951SBenjamin Kietzman 71da3eeb6aSEd Tanous dbus::match ma(system_bus, "type='signal',path='" + browser_path + "'"); 72da3eeb6aSEd Tanous dbus::filter f(system_bus, [](dbus::message& m) { 73da3eeb6aSEd Tanous auto member = m.get_member(); 74da3eeb6aSEd Tanous return member == "NameAcquired"; 75da3eeb6aSEd Tanous }); 76a83e5951SBenjamin Kietzman 77da3eeb6aSEd Tanous std::function<void(boost::system::error_code, dbus::message)> event_handler = 78da3eeb6aSEd Tanous [&](boost::system::error_code ec, dbus::message s) { 79da3eeb6aSEd Tanous testing::Test::RecordProperty("firstSignal", s.get_member()); 80da3eeb6aSEd Tanous std::string a = s.get_member(); 81da3eeb6aSEd Tanous std::string dude; 82da3eeb6aSEd Tanous s.unpack(dude); 83da3eeb6aSEd Tanous f.async_dispatch(event_handler); 84da3eeb6aSEd Tanous io.stop(); 85da3eeb6aSEd Tanous }; 86da3eeb6aSEd Tanous f.async_dispatch(event_handler); 87b2c2467dSBenjamin Kietzman 88da3eeb6aSEd Tanous boost::asio::deadline_timer t(io, boost::posix_time::seconds(10)); 89da3eeb6aSEd Tanous t.async_wait([&](const boost::system::error_code& /*e*/) { 90da3eeb6aSEd Tanous io.stop(); 91da3eeb6aSEd Tanous FAIL() << "Callback was never called\n"; 92da3eeb6aSEd Tanous }); 93a83e5951SBenjamin Kietzman io.run(); 94a83e5951SBenjamin Kietzman } 95b6e8327aSEd Tanous 96b6e8327aSEd Tanous TEST(BOOST_DBUS, ListServices) { 97b6e8327aSEd Tanous boost::asio::io_service io; 98b6e8327aSEd Tanous boost::asio::deadline_timer t(io, boost::posix_time::seconds(10)); 99b6e8327aSEd Tanous t.async_wait([&](const boost::system::error_code& /*e*/) { 100b6e8327aSEd Tanous io.stop(); 101b6e8327aSEd Tanous FAIL() << "Callback was never called\n"; 102b6e8327aSEd Tanous }); 103b6e8327aSEd Tanous 104b573e22eSEd Tanous auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system); 105b6e8327aSEd Tanous 106b6e8327aSEd Tanous dbus::endpoint test_daemon("org.freedesktop.DBus", "/", 107b6e8327aSEd Tanous "org.freedesktop.DBus"); 108b6e8327aSEd Tanous // create new service browser 109b6e8327aSEd Tanous dbus::message m = dbus::message::new_call(test_daemon, "ListNames"); 110b573e22eSEd Tanous system_bus->async_send( 111b6e8327aSEd Tanous m, [&](const boost::system::error_code ec, dbus::message r) { 112b6e8327aSEd Tanous io.stop(); 113b6e8327aSEd Tanous std::vector<std::string> services; 114b6e8327aSEd Tanous r.unpack(services); 115b6e8327aSEd Tanous // Test a couple things that should always be present.... adapt if 116b6e8327aSEd Tanous // neccesary 117b6e8327aSEd Tanous EXPECT_THAT(services, testing::Contains("org.freedesktop.DBus")); 118b6e8327aSEd Tanous EXPECT_THAT(services, testing::Contains("org.freedesktop.Accounts")); 119b6e8327aSEd Tanous 120b6e8327aSEd Tanous }); 121b6e8327aSEd Tanous 122b6e8327aSEd Tanous io.run(); 123b6e8327aSEd Tanous } 124b6e8327aSEd Tanous 1255d4bd2bdSEd Tanous TEST(BOOST_DBUS, SingleSensorChanged) { 126b6e8327aSEd Tanous boost::asio::io_service io; 127b6e8327aSEd Tanous 128b573e22eSEd Tanous auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system); 129b573e22eSEd Tanous 130b573e22eSEd Tanous dbus::match ma(system_bus, "type='signal',path_namespace='/xyz/openbmc_project/sensors'"); 131b573e22eSEd Tanous 13282a51ce2SEd Tanous dbus::filter f(system_bus, [](dbus::message& m) { 13382a51ce2SEd Tanous auto member = m.get_member(); 13482a51ce2SEd Tanous return member == "PropertiesChanged"; 13582a51ce2SEd Tanous }); 136b6e8327aSEd Tanous 1375d4bd2bdSEd Tanous // std::function<void(boost::system::error_code, dbus::message)> event_handler 1385d4bd2bdSEd Tanous // = 1395d4bd2bdSEd Tanous 1405d4bd2bdSEd Tanous f.async_dispatch([&](boost::system::error_code ec, dbus::message s) { 14182a51ce2SEd Tanous std::string object_name; 1425d4bd2bdSEd Tanous EXPECT_EQ(s.get_path(), 1435d4bd2bdSEd Tanous "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp"); 1445d4bd2bdSEd Tanous 14582a51ce2SEd Tanous std::vector<std::pair<std::string, dbus::dbus_variant>> values; 146*0d6f56d2SEd Tanous s.unpack(object_name, values); 14782a51ce2SEd Tanous EXPECT_EQ(object_name, "xyz.openbmc_project.Sensor.Value"); 14882a51ce2SEd Tanous 1495d4bd2bdSEd Tanous EXPECT_EQ(values.size(), 1); 15082a51ce2SEd Tanous auto expected = std::pair<std::string, dbus::dbus_variant>("Value", 42); 1515d4bd2bdSEd Tanous EXPECT_EQ(values[0], expected); 15282a51ce2SEd Tanous 153b6e8327aSEd Tanous io.stop(); 1545d4bd2bdSEd Tanous }); 155b6e8327aSEd Tanous 15682a51ce2SEd Tanous dbus::endpoint test_endpoint( 15782a51ce2SEd Tanous "org.freedesktop.Avahi", 15882a51ce2SEd Tanous "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp", 15982a51ce2SEd Tanous "org.freedesktop.DBus.Properties"); 160b6e8327aSEd Tanous 16182a51ce2SEd Tanous auto signal_name = std::string("PropertiesChanged"); 16282a51ce2SEd Tanous auto m = dbus::message::new_signal(test_endpoint, signal_name); 16382a51ce2SEd Tanous 16482a51ce2SEd Tanous m.pack("xyz.openbmc_project.Sensor.Value"); 16582a51ce2SEd Tanous 16682a51ce2SEd Tanous std::vector<std::pair<std::string, dbus::dbus_variant>> map2; 16782a51ce2SEd Tanous 16882a51ce2SEd Tanous map2.emplace_back("Value", 42); 16982a51ce2SEd Tanous 17082a51ce2SEd Tanous m.pack(map2); 17182a51ce2SEd Tanous 17282a51ce2SEd Tanous auto removed = std::vector<uint32_t>(); 17382a51ce2SEd Tanous m.pack(removed); 174b573e22eSEd Tanous system_bus->async_send(m, 17582a51ce2SEd Tanous [&](boost::system::error_code ec, dbus::message s) {}); 176b6e8327aSEd Tanous 177b6e8327aSEd Tanous io.run(); 178b6e8327aSEd Tanous } 1795d4bd2bdSEd Tanous 1805d4bd2bdSEd Tanous TEST(BOOST_DBUS, MultipleSensorChanged) { 1815d4bd2bdSEd Tanous boost::asio::io_service io; 182b573e22eSEd Tanous auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system); 1835d4bd2bdSEd Tanous 1845d4bd2bdSEd Tanous dbus::match ma(system_bus, 1855d4bd2bdSEd Tanous "type='signal',path_namespace='/xyz/openbmc_project/sensors'"); 1865d4bd2bdSEd Tanous dbus::filter f(system_bus, [](dbus::message& m) { 1875d4bd2bdSEd Tanous auto member = m.get_member(); 1885d4bd2bdSEd Tanous return member == "PropertiesChanged"; 1895d4bd2bdSEd Tanous }); 1905d4bd2bdSEd Tanous 1915d4bd2bdSEd Tanous int count = 0; 192b573e22eSEd Tanous std::function<void(boost::system::error_code, dbus::message)> callback = [&]( 193b573e22eSEd Tanous boost::system::error_code ec, dbus::message s) { 1945d4bd2bdSEd Tanous std::string object_name; 1955d4bd2bdSEd Tanous EXPECT_EQ(s.get_path(), 1965d4bd2bdSEd Tanous "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp"); 1975d4bd2bdSEd Tanous 1985d4bd2bdSEd Tanous std::vector<std::pair<std::string, dbus::dbus_variant>> values; 199*0d6f56d2SEd Tanous s.unpack(object_name, values); 2005d4bd2bdSEd Tanous EXPECT_EQ(object_name, "xyz.openbmc_project.Sensor.Value"); 2015d4bd2bdSEd Tanous 2025d4bd2bdSEd Tanous EXPECT_EQ(values.size(), 1); 2035d4bd2bdSEd Tanous auto expected = std::pair<std::string, dbus::dbus_variant>("Value", 42); 2045d4bd2bdSEd Tanous EXPECT_EQ(values[0], expected); 2055d4bd2bdSEd Tanous count++; 2065d4bd2bdSEd Tanous if (count == 2) { 2075d4bd2bdSEd Tanous io.stop(); 208b573e22eSEd Tanous } else { 209b573e22eSEd Tanous f.async_dispatch(callback); 2105d4bd2bdSEd Tanous } 211*0d6f56d2SEd Tanous s.unpack(object_name, values); 2125d4bd2bdSEd Tanous 213b573e22eSEd Tanous }; 214b573e22eSEd Tanous f.async_dispatch(callback); 2155d4bd2bdSEd Tanous 2165d4bd2bdSEd Tanous dbus::endpoint test_endpoint( 2175d4bd2bdSEd Tanous "org.freedesktop.Avahi", 2185d4bd2bdSEd Tanous "/xyz/openbmc_project/sensors/temperature/LR_Brd_Temp", 2195d4bd2bdSEd Tanous "org.freedesktop.DBus.Properties"); 2205d4bd2bdSEd Tanous 2215d4bd2bdSEd Tanous auto signal_name = std::string("PropertiesChanged"); 2225d4bd2bdSEd Tanous auto m = dbus::message::new_signal(test_endpoint, signal_name); 2235d4bd2bdSEd Tanous 2245d4bd2bdSEd Tanous m.pack("xyz.openbmc_project.Sensor.Value"); 2255d4bd2bdSEd Tanous 2265d4bd2bdSEd Tanous std::vector<std::pair<std::string, dbus::dbus_variant>> map2; 2275d4bd2bdSEd Tanous 2285d4bd2bdSEd Tanous map2.emplace_back("Value", 42); 2295d4bd2bdSEd Tanous 2305d4bd2bdSEd Tanous m.pack(map2); 2315d4bd2bdSEd Tanous 2325d4bd2bdSEd Tanous auto removed = std::vector<uint32_t>(); 2335d4bd2bdSEd Tanous m.pack(removed); 234b573e22eSEd Tanous system_bus->async_send(m, 2355d4bd2bdSEd Tanous [&](boost::system::error_code ec, dbus::message s) {}); 236b573e22eSEd Tanous system_bus->async_send(m, 2375d4bd2bdSEd Tanous [&](boost::system::error_code ec, dbus::message s) {}); 2385d4bd2bdSEd Tanous io.run(); 2395d4bd2bdSEd Tanous } 240458a9c10SVernon Mauery 241458a9c10SVernon Mauery TEST(BOOST_DBUS, MethodCall) { 242458a9c10SVernon Mauery boost::asio::io_service io; 243458a9c10SVernon Mauery boost::asio::deadline_timer t(io, boost::posix_time::seconds(30)); 244458a9c10SVernon Mauery t.async_wait([&](const boost::system::error_code& /*e*/) { 245458a9c10SVernon Mauery io.stop(); 246458a9c10SVernon Mauery FAIL() << "Callback was never called\n"; 247458a9c10SVernon Mauery }); 248458a9c10SVernon Mauery 249*0d6f56d2SEd Tanous auto system_bus = std::make_shared<dbus::connection>(io, dbus::bus::system); 250*0d6f56d2SEd Tanous std::string requested_name = system_bus->get_unique_name(); 251458a9c10SVernon Mauery 252458a9c10SVernon Mauery dbus::filter f(system_bus, [](dbus::message& m) { 253458a9c10SVernon Mauery return (m.get_member() == "Get" && 254458a9c10SVernon Mauery m.get_interface() == "org.freedesktop.DBus.Properties" && 255458a9c10SVernon Mauery m.get_signature() == "ss"); 256458a9c10SVernon Mauery }); 257458a9c10SVernon Mauery 258458a9c10SVernon Mauery std::function<void(boost::system::error_code, dbus::message)> method_handler = 259458a9c10SVernon Mauery [&](boost::system::error_code ec, dbus::message s) { 260*0d6f56d2SEd Tanous if (ec) { 261*0d6f56d2SEd Tanous FAIL() << ec; 262*0d6f56d2SEd Tanous } else { 263458a9c10SVernon Mauery std::string intf_name, prop_name; 264*0d6f56d2SEd Tanous s.unpack(intf_name, prop_name); 265458a9c10SVernon Mauery 266458a9c10SVernon Mauery EXPECT_EQ(intf_name, "xyz.openbmc_project.fwupdate1"); 267458a9c10SVernon Mauery EXPECT_EQ(prop_name, "State"); 268458a9c10SVernon Mauery 269458a9c10SVernon Mauery // send a reply so dbus doesn't get angry? 270b573e22eSEd Tanous auto r = system_bus->reply(s); 271458a9c10SVernon Mauery r.pack("IDLE"); 272*0d6f56d2SEd Tanous system_bus->async_send(r, [&](boost::system::error_code ec, 273*0d6f56d2SEd Tanous dbus::message s) { }); 274458a9c10SVernon Mauery io.stop(); 275*0d6f56d2SEd Tanous } 276458a9c10SVernon Mauery }; 277458a9c10SVernon Mauery f.async_dispatch(method_handler); 278458a9c10SVernon Mauery 279458a9c10SVernon Mauery dbus::endpoint test_endpoint( 280458a9c10SVernon Mauery requested_name, 281458a9c10SVernon Mauery "/xyz/openbmc_project/fwupdate1", 282458a9c10SVernon Mauery "org.freedesktop.DBus.Properties"); 283458a9c10SVernon Mauery 284458a9c10SVernon Mauery auto method_name = std::string("Get"); 285458a9c10SVernon Mauery auto m = dbus::message::new_call(test_endpoint, method_name); 286458a9c10SVernon Mauery 287*0d6f56d2SEd Tanous m.pack("xyz.openbmc_project.fwupdate1", "State"); 288b573e22eSEd Tanous system_bus->async_send(m, 289458a9c10SVernon Mauery [&](boost::system::error_code ec, dbus::message s) { 290458a9c10SVernon Mauery std::cerr <<"received s: " << s << std::endl; 291458a9c10SVernon Mauery }); 292458a9c10SVernon Mauery 293458a9c10SVernon Mauery io.run(); 294458a9c10SVernon Mauery } 295