xref: /openbmc/sdbusplus/test/server/object.cpp (revision d8a19ada)
1 #include "Test/server.hpp"
2 
3 #include <sdbusplus/bus.hpp>
4 #include <sdbusplus/server/manager.hpp>
5 #include <sdbusplus/test/sdbus_mock.hpp>
6 
7 #include <gtest/gtest.h>
8 
9 using ::testing::_;
10 using ::testing::StrEq;
11 
12 struct UselessInherit
13 {
14     template <typename... Args>
15     explicit UselessInherit(Args&&...)
16     {}
17 };
18 
19 // It isn't a particularly good idea to inherit from object_t twice, but some
20 // clients seem to do it.  Do it here to ensure that code compiles (avoiding
21 // diamond-inheritance problems) and that emit happens correctly when it is
22 // done.
23 using TestInherit = sdbusplus::server::object_t<
24     UselessInherit,
25     sdbusplus::server::object_t<sdbusplus::server::server::Test>>;
26 
27 class Object : public ::testing::Test
28 {
29   protected:
30     sdbusplus::SdBusMock sdbusMock;
31     sdbusplus::bus_t bus = sdbusplus::get_mocked_new(&sdbusMock);
32 
33     static constexpr auto busName = "xyz.openbmc_project.sdbusplus.test.Object";
34     static constexpr auto objPath = "/xyz/openbmc_project/sdbusplus/test";
35 };
36 
37 TEST_F(Object, InterfaceAddedOnly)
38 {
39     // Simulate the typical usage of a service
40     sdbusplus::server::manager_t objManager(bus, objPath);
41     bus.request_name(busName);
42 
43     EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
44         .Times(0);
45     EXPECT_CALL(sdbusMock,
46                 sd_bus_emit_interfaces_added_strv(_, StrEq(objPath), _))
47         .Times(1);
48 
49     // This only add interface to the existing object
50     auto test = std::make_unique<TestInherit>(
51         bus, objPath, TestInherit::action::emit_interface_added);
52 
53     // After destruction, the interface shall be removed
54     EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath)))
55         .Times(0);
56     EXPECT_CALL(sdbusMock,
57                 sd_bus_emit_interfaces_removed_strv(_, StrEq(objPath), _))
58         .Times(1);
59 }
60 
61 TEST_F(Object, DeferAddInterface)
62 {
63     // Simulate the typical usage of a service
64     sdbusplus::server::manager_t objManager(bus, objPath);
65     bus.request_name(busName);
66 
67     EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
68         .Times(0);
69     EXPECT_CALL(sdbusMock,
70                 sd_bus_emit_interfaces_added_strv(_, StrEq(objPath), _))
71         .Times(0);
72 
73     // It defers emit_object_added()
74     auto test = std::make_unique<TestInherit>(bus, objPath,
75                                               TestInherit::action::defer_emit);
76 
77     EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
78         .Times(1);
79     EXPECT_CALL(sdbusMock,
80                 sd_bus_emit_interfaces_added_strv(_, StrEq(objPath), _))
81         .Times(0);
82 
83     // Now invoke emit_object_added()
84     test->emit_object_added();
85 
86     // After destruction, the object will be removed
87     EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath)))
88         .Times(1);
89     EXPECT_CALL(sdbusMock,
90                 sd_bus_emit_interfaces_removed_strv(_, StrEq(objPath), _))
91         .Times(0);
92 }
93 
94 TEST_F(Object, ObjectAdded)
95 {
96     // Simulate the typical usage of a service
97     sdbusplus::server::manager_t objManager(bus, objPath);
98     bus.request_name(busName);
99 
100     EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
101         .Times(1);
102     EXPECT_CALL(sdbusMock,
103                 sd_bus_emit_interfaces_added_strv(_, StrEq(objPath), _))
104         .Times(0);
105 
106     // Note: this is the wrong usage!
107     // With the below code, the interface is added as expected, but after
108     // destruction of TestInherit, the whole object will be removed from DBus.
109     // Refer to InterfaceAddedOnly case for the correct usage.
110     auto test = std::make_unique<TestInherit>(bus, objPath);
111 
112     EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath)))
113         .Times(1);
114     EXPECT_CALL(sdbusMock,
115                 sd_bus_emit_interfaces_removed_strv(_, StrEq(objPath), _))
116         .Times(0);
117 }
118 
119 TEST_F(Object, DoubleHasDefaultValues)
120 {
121     // Simulate the typical usage of a service
122     sdbusplus::server::manager_t objManager(bus, objPath);
123     bus.request_name(busName);
124 
125     EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
126         .Times(1);
127     EXPECT_CALL(sdbusMock,
128                 sd_bus_emit_interfaces_added_strv(_, StrEq(objPath), _))
129         .Times(0);
130 
131     auto test = std::make_unique<TestInherit>(bus, objPath);
132     EXPECT_TRUE(std::isnan(test->doubleAsNAN()));
133     EXPECT_TRUE(std::isinf(test->doubleAsInf()) &&
134                 !std::signbit(test->doubleAsInf()));
135     EXPECT_TRUE(std::isinf(test->doubleAsNegInf()) &&
136                 std::signbit(test->doubleAsNegInf()));
137     EXPECT_EQ(std::numeric_limits<double>::epsilon(), test->doubleAsEpsilon());
138 }
139