1 #include "../interface_ops.hpp"
2 
3 #include <sdbusplus/test/sdbus_mock.hpp>
4 
5 #include <gtest/gtest.h>
6 
7 using namespace phosphor::inventory::manager;
8 using namespace testing;
9 using namespace std::string_literals;
10 
11 struct MockInterface;
12 struct DummyInterfaceWithProperties;
13 
14 MockInterface* g_currentMock = nullptr;
15 
16 using FakeVariantType = int;
17 using InterfaceVariant = std::map<std::string, FakeVariantType>;
18 
19 struct MockInterface
20 {
21     MockInterface()
22     {
23         g_currentMock = this;
24     }
25     ~MockInterface()
26     {
27         g_currentMock = nullptr;
28     }
29     MockInterface(const MockInterface&) = delete;
30     MockInterface& operator=(const MockInterface&) = delete;
31     // Not supporting move semantics simply because they aren't needed.
32     MockInterface(MockInterface&&) = delete;
33     MockInterface& operator=(MockInterface&&) = delete;
34 
35     // We'll be getting calls proxyed through other objects.
36     MOCK_METHOD2(constructWithProperties,
37                  void(const char*, const InterfaceVariant& i));
38     MOCK_METHOD1(constructWithoutProperties, void(const char*));
39     MOCK_METHOD2(setPropertyByName, void(std::string, FakeVariantType));
40 
41     MOCK_METHOD2(serializeTwoArgs,
42                  void(const std::string&, const std::string&));
43     MOCK_METHOD3(serializeThreeArgs,
44                  void(const std::string&, const std::string&,
45                       const DummyInterfaceWithProperties&));
46 
47     MOCK_METHOD0(deserializeNoop, void());
48     MOCK_METHOD3(deserializeThreeArgs,
49                  void(const std::string&, const std::string&,
50                       DummyInterfaceWithProperties&));
51 };
52 
53 struct DummyInterfaceWithoutProperties
54 {
55     DummyInterfaceWithoutProperties(sdbusplus::bus::bus&, const char* name)
56     {
57         g_currentMock->constructWithoutProperties(name);
58     }
59 };
60 
61 struct DummyInterfaceWithProperties
62 {
63     using PropertiesVariant = FakeVariantType;
64 
65     DummyInterfaceWithProperties(sdbusplus::bus::bus&, const char* name,
66                                  const InterfaceVariant& i)
67     {
68         g_currentMock->constructWithProperties(name, i);
69     }
70 
71     void setPropertyByName(std::string name, PropertiesVariant val)
72     {
73         g_currentMock->setPropertyByName(name, val);
74     }
75 };
76 
77 struct SerialForwarder
78 {
79     static void serialize(const std::string& path, const std::string& iface)
80     {
81         g_currentMock->serializeTwoArgs(path, iface);
82     }
83 
84     static void serialize(const std::string& path, const std::string& iface,
85                           const DummyInterfaceWithProperties& obj)
86     {
87         g_currentMock->serializeThreeArgs(path, iface, obj);
88     }
89 
90     static void deserialize(const std::string& path, const std::string& iface)
91     {
92         g_currentMock->deserializeNoop();
93     }
94 
95     static void deserialize(const std::string& path, const std::string& iface,
96                             DummyInterfaceWithProperties& obj)
97     {
98         g_currentMock->deserializeThreeArgs(path, iface, obj);
99     }
100 };
101 
102 TEST(InterfaceOpsTest, TestHasPropertiesNoProperties)
103 {
104     EXPECT_FALSE(HasProperties<DummyInterfaceWithoutProperties>::value);
105 }
106 
107 TEST(InterfaceOpsTest, TestHasPropertiesHasProperties)
108 {
109     EXPECT_TRUE(HasProperties<DummyInterfaceWithProperties>::value);
110 }
111 
112 TEST(InterfaceOpsTest, TestMakePropertylessInterfaceWithoutArguments)
113 {
114     MockInterface mock;
115     Interface i;
116     sdbusplus::SdBusMock interface;
117 
118     EXPECT_CALL(mock, constructWithoutProperties("foo")).Times(1);
119     EXPECT_CALL(mock, constructWithProperties(_, _)).Times(0);
120 
121     auto b = sdbusplus::get_mocked_new(&interface);
122     auto r = MakeInterface<DummyInterfaceWithoutProperties>::op(b, "foo", i);
123 
124     EXPECT_NO_THROW(
125         std::any_cast<std::shared_ptr<DummyInterfaceWithoutProperties>>(r));
126 }
127 
128 TEST(InterfaceOpsTest, TestMakePropertylessInterfaceWithOneArgument)
129 {
130     MockInterface mock;
131     Interface i{{"foo"s, static_cast<int64_t>(1ll)}};
132     sdbusplus::SdBusMock interface;
133 
134     EXPECT_CALL(mock, constructWithoutProperties("foo")).Times(1);
135     EXPECT_CALL(mock, constructWithProperties(_, _)).Times(0);
136 
137     auto b = sdbusplus::get_mocked_new(&interface);
138     auto r = MakeInterface<DummyInterfaceWithoutProperties>::op(b, "foo", i);
139 
140     EXPECT_NO_THROW(
141         std::any_cast<std::shared_ptr<DummyInterfaceWithoutProperties>>(r));
142 }
143 
144 TEST(InterfaceOpsTest, TestMakeInterfaceWithWithoutArguments)
145 {
146     MockInterface mock;
147     Interface i;
148     sdbusplus::SdBusMock interface;
149 
150     EXPECT_CALL(mock, constructWithoutProperties(_)).Times(0);
151     EXPECT_CALL(mock, constructWithProperties("bar", _)).Times(1);
152 
153     auto b = sdbusplus::get_mocked_new(&interface);
154     auto r = MakeInterface<DummyInterfaceWithProperties>::op(b, "bar", i);
155 
156     EXPECT_NO_THROW(
157         std::any_cast<std::shared_ptr<DummyInterfaceWithProperties>>(r));
158 }
159 
160 TEST(InterfaceOpsTest, TestMakeInterfaceWithOneArgument)
161 {
162     MockInterface mock;
163     Interface i{{"foo"s, static_cast<int64_t>(1ll)}};
164     sdbusplus::SdBusMock interface;
165 
166     EXPECT_CALL(mock, constructWithoutProperties(_)).Times(0);
167     EXPECT_CALL(mock, constructWithProperties("foo", _)).Times(1);
168 
169     auto b = sdbusplus::get_mocked_new(&interface);
170     auto r = MakeInterface<DummyInterfaceWithProperties>::op(b, "foo", i);
171 
172     EXPECT_NO_THROW(
173         std::any_cast<std::shared_ptr<DummyInterfaceWithProperties>>(r));
174 }
175 
176 TEST(InterfaceOpsTest, TestAssignPropertylessInterfaceWithoutArguments)
177 {
178     MockInterface mock;
179     Interface i;
180     sdbusplus::SdBusMock interface;
181 
182     EXPECT_CALL(mock, setPropertyByName(_, _)).Times(0);
183 
184     auto b = sdbusplus::get_mocked_new(&interface);
185     auto r = MakeInterface<DummyInterfaceWithoutProperties>::op(b, "foo", i);
186 
187     AssignInterface<DummyInterfaceWithoutProperties>::op(i, r);
188 }
189 
190 TEST(InterfaceOpsTest, TestAssignPropertylessInterfaceWithOneArgument)
191 {
192     MockInterface mock;
193     Interface i{{"foo"s, static_cast<int64_t>(1ll)}};
194     sdbusplus::SdBusMock interface;
195 
196     EXPECT_CALL(mock, setPropertyByName(_, _)).Times(0);
197 
198     auto b = sdbusplus::get_mocked_new(&interface);
199     auto r = MakeInterface<DummyInterfaceWithoutProperties>::op(b, "foo", i);
200 
201     AssignInterface<DummyInterfaceWithoutProperties>::op(i, r);
202 }
203 
204 TEST(InterfaceOpsTest, TestAssignInterfaceWithoutArguments)
205 {
206     MockInterface mock;
207     Interface i;
208     sdbusplus::SdBusMock interface;
209 
210     EXPECT_CALL(mock, setPropertyByName(_, _)).Times(0);
211 
212     auto b = sdbusplus::get_mocked_new(&interface);
213     auto r = MakeInterface<DummyInterfaceWithProperties>::op(b, "foo", i);
214 
215     AssignInterface<DummyInterfaceWithProperties>::op(i, r);
216 }
217 
218 TEST(InterfaceOpsTest, TestAssignInterfaceWithOneArgument)
219 {
220     MockInterface mock;
221     Interface i{{"foo"s, static_cast<int64_t>(1ll)}};
222     sdbusplus::SdBusMock interface;
223 
224     EXPECT_CALL(mock, setPropertyByName("foo"s, 1ll)).Times(1);
225 
226     auto b = sdbusplus::get_mocked_new(&interface);
227     auto r = MakeInterface<DummyInterfaceWithProperties>::op(b, "bar", i);
228 
229     AssignInterface<DummyInterfaceWithProperties>::op(i, r);
230 }
231 
232 TEST(InterfaceOpsTest, TestSerializePropertylessInterfaceWithoutArguments)
233 {
234     MockInterface mock;
235     Interface i;
236     sdbusplus::SdBusMock interface;
237 
238     auto b = sdbusplus::get_mocked_new(&interface);
239     auto r = MakeInterface<DummyInterfaceWithoutProperties>::op(b, "foo", i);
240 
241     EXPECT_CALL(mock, serializeTwoArgs("/foo"s, "bar"s)).Times(1);
242 
243     SerializeInterface<DummyInterfaceWithoutProperties, SerialForwarder>::op(
244         "/foo"s, "bar"s, r);
245 }
246 
247 TEST(InterfaceOpsTest, TestSerializePropertylessInterfaceWithOneArgument)
248 {
249     MockInterface mock;
250     Interface i{{"foo"s, static_cast<int64_t>(1ll)}};
251     sdbusplus::SdBusMock interface;
252 
253     auto b = sdbusplus::get_mocked_new(&interface);
254     auto r = MakeInterface<DummyInterfaceWithoutProperties>::op(b, "foo", i);
255 
256     EXPECT_CALL(mock, serializeTwoArgs("/foo"s, "bar"s)).Times(1);
257 
258     SerializeInterface<DummyInterfaceWithoutProperties, SerialForwarder>::op(
259         "/foo"s, "bar"s, r);
260 }
261 
262 TEST(InterfaceOpsTest, TestSerializeInterfaceWithNoArguments)
263 {
264     MockInterface mock;
265     Interface i;
266     sdbusplus::SdBusMock interface;
267 
268     auto b = sdbusplus::get_mocked_new(&interface);
269     auto r = MakeInterface<DummyInterfaceWithProperties>::op(b, "foo", i);
270 
271     EXPECT_CALL(mock, serializeThreeArgs("/foo"s, "bar"s, _)).Times(1);
272 
273     SerializeInterface<DummyInterfaceWithProperties, SerialForwarder>::op(
274         "/foo"s, "bar"s, r);
275 }
276 
277 TEST(InterfaceOpsTest, TestSerializeInterfaceWithOneArgument)
278 {
279     MockInterface mock;
280     Interface i{{"foo"s, static_cast<int64_t>(1ll)}};
281     sdbusplus::SdBusMock interface;
282 
283     auto b = sdbusplus::get_mocked_new(&interface);
284     auto r = MakeInterface<DummyInterfaceWithProperties>::op(b, "foo", i);
285 
286     EXPECT_CALL(mock, serializeThreeArgs("/foo"s, "bar"s, _)).Times(1);
287 
288     SerializeInterface<DummyInterfaceWithProperties, SerialForwarder>::op(
289         "/foo"s, "bar"s, r);
290 }
291 
292 TEST(InterfaceOpsTest, TestDeserializePropertylessInterfaceWithoutArguments)
293 {
294     MockInterface mock;
295     Interface i;
296     sdbusplus::SdBusMock interface;
297 
298     auto b = sdbusplus::get_mocked_new(&interface);
299     auto r = MakeInterface<DummyInterfaceWithoutProperties>::op(b, "foo", i);
300 
301     EXPECT_CALL(mock, deserializeNoop()).Times(1);
302 
303     DeserializeInterface<DummyInterfaceWithoutProperties, SerialForwarder>::op(
304         "/foo"s, "bar"s, r);
305 }
306 
307 TEST(InterfaceOpsTest, TestDeserializePropertylessInterfaceWithOneArgument)
308 {
309     MockInterface mock;
310     Interface i{{"foo"s, static_cast<int64_t>(1ll)}};
311     sdbusplus::SdBusMock interface;
312 
313     auto b = sdbusplus::get_mocked_new(&interface);
314     auto r = MakeInterface<DummyInterfaceWithoutProperties>::op(b, "foo", i);
315 
316     EXPECT_CALL(mock, deserializeNoop()).Times(1);
317 
318     DeserializeInterface<DummyInterfaceWithoutProperties, SerialForwarder>::op(
319         "/foo"s, "bar"s, r);
320 }
321 
322 TEST(InterfaceOpsTest, TestDeserializeInterfaceWithNoArguments)
323 {
324     MockInterface mock;
325     Interface i;
326     sdbusplus::SdBusMock interface;
327 
328     auto b = sdbusplus::get_mocked_new(&interface);
329     auto r = MakeInterface<DummyInterfaceWithProperties>::op(b, "foo", i);
330 
331     EXPECT_CALL(mock, deserializeThreeArgs("/foo"s, "bar"s, _)).Times(1);
332 
333     DeserializeInterface<DummyInterfaceWithProperties, SerialForwarder>::op(
334         "/foo"s, "bar"s, r);
335 }
336 
337 TEST(InterfaceOpsTest, TestDeserializeInterfaceWithOneArgument)
338 {
339     MockInterface mock;
340     Interface i{{"foo"s, static_cast<int64_t>(1ll)}};
341     sdbusplus::SdBusMock interface;
342 
343     auto b = sdbusplus::get_mocked_new(&interface);
344     auto r = MakeInterface<DummyInterfaceWithProperties>::op(b, "foo", i);
345 
346     EXPECT_CALL(mock, deserializeThreeArgs("/foo"s, "bar"s, _)).Times(1);
347 
348     DeserializeInterface<DummyInterfaceWithProperties, SerialForwarder>::op(
349         "/foo"s, "bar"s, r);
350 }
351