#include #include #include #include #include using ::testing::_; using ::testing::StrEq; struct UselessInherit { template explicit UselessInherit(Args&&...) {} }; // It isn't a particularly good idea to inherit from object_t twice, but some // clients seem to do it. Do it here to ensure that code compiles (avoiding // diamond-inheritance problems) and that emit happens correctly when it is // done. using TestInherit = sdbusplus::server::object_t< UselessInherit, sdbusplus::server::object_t>; class Object : public ::testing::Test { protected: sdbusplus::SdBusMock sdbusMock; sdbusplus::bus_t bus = sdbusplus::get_mocked_new(&sdbusMock); static constexpr auto busName = "xyz.openbmc_project.sdbusplus.test.Object"; static constexpr auto objPath = "/xyz/openbmc_project/sdbusplus/test"; }; TEST_F(Object, InterfaceAddedOnly) { // Simulate the typical usage of a service sdbusplus::server::manager_t objManager(bus, objPath); bus.request_name(busName); EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath))) .Times(0); EXPECT_CALL(sdbusMock, sd_bus_emit_interfaces_added_strv(_, StrEq(objPath), _)) .Times(1); // This only add interface to the existing object auto test = std::make_unique( bus, objPath, TestInherit::action::emit_interface_added); // After destruction, the interface shall be removed EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath))) .Times(0); EXPECT_CALL(sdbusMock, sd_bus_emit_interfaces_removed_strv(_, StrEq(objPath), _)) .Times(1); } TEST_F(Object, DeferAddInterface) { // Simulate the typical usage of a service sdbusplus::server::manager_t objManager(bus, objPath); bus.request_name(busName); EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath))) .Times(0); EXPECT_CALL(sdbusMock, sd_bus_emit_interfaces_added_strv(_, StrEq(objPath), _)) .Times(0); // It defers emit_object_added() auto test = std::make_unique(bus, objPath, TestInherit::action::defer_emit); EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath))) .Times(1); EXPECT_CALL(sdbusMock, sd_bus_emit_interfaces_added_strv(_, StrEq(objPath), _)) .Times(0); // Now invoke emit_object_added() test->emit_object_added(); EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath))) .Times(1); EXPECT_CALL(sdbusMock, sd_bus_emit_interfaces_removed_strv(_, StrEq(objPath), _)) .Times(0); } TEST_F(Object, NeverAddInterface) { // Simulate the typical usage of a service sdbusplus::server::manager_t objManager(bus, objPath); bus.request_name(busName); EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath))) .Times(0); EXPECT_CALL(sdbusMock, sd_bus_emit_interfaces_added_strv(_, StrEq(objPath), _)) .Times(0); // It defers emit_object_added() auto test = std::make_unique( bus, objPath, TestInherit::action::emit_no_signals); EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath))) .Times(0); EXPECT_CALL(sdbusMock, sd_bus_emit_interfaces_added_strv(_, StrEq(objPath), _)) .Times(0); // After destruction, the object will be removed EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath))) .Times(0); EXPECT_CALL(sdbusMock, sd_bus_emit_interfaces_removed_strv(_, StrEq(objPath), _)) .Times(0); } TEST_F(Object, ObjectAdded) { // Simulate the typical usage of a service sdbusplus::server::manager_t objManager(bus, objPath); bus.request_name(busName); EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath))) .Times(1); EXPECT_CALL(sdbusMock, sd_bus_emit_interfaces_added_strv(_, StrEq(objPath), _)) .Times(0); // Note: this is the wrong usage! // With the below code, the interface is added as expected, but after // destruction of TestInherit, the whole object will be removed from DBus. // Refer to InterfaceAddedOnly case for the correct usage. auto test = std::make_unique(bus, objPath); EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath))) .Times(1); EXPECT_CALL(sdbusMock, sd_bus_emit_interfaces_removed_strv(_, StrEq(objPath), _)) .Times(0); } TEST_F(Object, DoubleHasDefaultValues) { // Simulate the typical usage of a service sdbusplus::server::manager_t objManager(bus, objPath); bus.request_name(busName); EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath))) .Times(1); EXPECT_CALL(sdbusMock, sd_bus_emit_interfaces_added_strv(_, StrEq(objPath), _)) .Times(0); auto test = std::make_unique(bus, objPath); EXPECT_TRUE(std::isnan(test->doubleAsNAN())); EXPECT_TRUE(std::isinf(test->doubleAsInf()) && !std::signbit(test->doubleAsInf())); EXPECT_TRUE(std::isinf(test->doubleAsNegInf()) && std::signbit(test->doubleAsNegInf())); EXPECT_EQ(std::numeric_limits::epsilon(), test->doubleAsEpsilon()); }