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