xref: /openbmc/sdbusplus/test/server/object.cpp (revision cff540a9)
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     EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath)))
87         .Times(1);
88     EXPECT_CALL(sdbusMock,
89                 sd_bus_emit_interfaces_removed_strv(_, StrEq(objPath), _))
90         .Times(0);
91 }
92 
93 TEST_F(Object, NeverAddInterface)
94 {
95     // Simulate the typical usage of a service
96     sdbusplus::server::manager_t objManager(bus, objPath);
97     bus.request_name(busName);
98 
99     EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
100         .Times(0);
101     EXPECT_CALL(sdbusMock,
102                 sd_bus_emit_interfaces_added_strv(_, StrEq(objPath), _))
103         .Times(0);
104 
105     // It defers emit_object_added()
106     auto test = std::make_unique<TestInherit>(
107         bus, objPath, TestInherit::action::emit_no_signals);
108 
109     EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
110         .Times(0);
111     EXPECT_CALL(sdbusMock,
112                 sd_bus_emit_interfaces_added_strv(_, StrEq(objPath), _))
113         .Times(0);
114 
115     // After destruction, the object will be removed
116     EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath)))
117         .Times(0);
118     EXPECT_CALL(sdbusMock,
119                 sd_bus_emit_interfaces_removed_strv(_, StrEq(objPath), _))
120         .Times(0);
121 }
122 
123 TEST_F(Object, ObjectAdded)
124 {
125     // Simulate the typical usage of a service
126     sdbusplus::server::manager_t objManager(bus, objPath);
127     bus.request_name(busName);
128 
129     EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
130         .Times(1);
131     EXPECT_CALL(sdbusMock,
132                 sd_bus_emit_interfaces_added_strv(_, StrEq(objPath), _))
133         .Times(0);
134 
135     // Note: this is the wrong usage!
136     // With the below code, the interface is added as expected, but after
137     // destruction of TestInherit, the whole object will be removed from DBus.
138     // Refer to InterfaceAddedOnly case for the correct usage.
139     auto test = std::make_unique<TestInherit>(bus, objPath);
140 
141     EXPECT_CALL(sdbusMock, sd_bus_emit_object_removed(_, StrEq(objPath)))
142         .Times(1);
143     EXPECT_CALL(sdbusMock,
144                 sd_bus_emit_interfaces_removed_strv(_, StrEq(objPath), _))
145         .Times(0);
146 }
147 
148 TEST_F(Object, DoubleHasDefaultValues)
149 {
150     // Simulate the typical usage of a service
151     sdbusplus::server::manager_t objManager(bus, objPath);
152     bus.request_name(busName);
153 
154     EXPECT_CALL(sdbusMock, sd_bus_emit_object_added(_, StrEq(objPath)))
155         .Times(1);
156     EXPECT_CALL(sdbusMock,
157                 sd_bus_emit_interfaces_added_strv(_, StrEq(objPath), _))
158         .Times(0);
159 
160     auto test = std::make_unique<TestInherit>(bus, objPath);
161     EXPECT_TRUE(std::isnan(test->doubleAsNAN()));
162     EXPECT_TRUE(std::isinf(test->doubleAsInf()) &&
163                 !std::signbit(test->doubleAsInf()));
164     EXPECT_TRUE(std::isinf(test->doubleAsNegInf()) &&
165                 std::signbit(test->doubleAsNegInf()));
166     EXPECT_EQ(std::numeric_limits<double>::epsilon(), test->doubleAsEpsilon());
167 }
168