blob: 13cd054eea3ac4870845d5eaabf445cac2d59f10 [file] [log] [blame]
#include <sdbusplus/bus.hpp>
#include <sdbusplus/server/manager.hpp>
#include <sdbusplus/test/sdbus_mock.hpp>
#include <server/Test/server.hpp>
#include <gtest/gtest.h>
using ::testing::_;
using ::testing::StrEq;
struct UselessInherit
{
template <typename... Args>
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<sdbusplus::server::server::Test>>;
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<TestInherit>(
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<TestInherit>(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<TestInherit>(
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<TestInherit>(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<TestInherit>(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<double>::epsilon(), test->doubleAsEpsilon());
}