1 #pragma once
2 #include "data_types.hpp"
3 #include "sdbusplus/bus/match.hpp"
4 
5 #include <string>
6 
7 #include <gmock/gmock.h>
8 #include <gtest/gtest.h>
9 
10 namespace phosphor
11 {
12 namespace dbus
13 {
14 namespace monitoring
15 {
16 
17 /** @class CallMethodAndRead
18  *  @brief GMock template member forwarding helper.
19  *
20  *  The code under test calls callMethodAndRead, which is a templated,
21  *  free function.  Enable this under GMock by forwarding calls to it
22  *  to functions that can be mocked.
23  *
24  *  @tparam DBusInterfaceType - The mock object type.
25  *  @tparam Ret - The return type of the method being called.
26  *  @tparam Args - The argument types of the method being called.
27  *
28  *  Specialize to implement new forwards.
29  */
30 template <typename DBusInterfaceType, typename Ret, typename... Args>
31 struct CallMethodAndRead
32 {
33     static Ret op(DBusInterfaceType& dbus, const std::string& busName,
34                   const std::string& path, const std::string& interface,
35                   const std::string& method, Args&&... args)
36     {
37         static_assert(true, "Missing CallMethodAndRead definition.");
38         return Ret();
39     }
40 };
41 
42 /** @brief CallMethodAndRead specialization for
43  *     xyz.openbmc_project.ObjectMapper.GetObject. */
44 template <typename DBusInterfaceType>
45 struct CallMethodAndRead<DBusInterfaceType, GetObject, const MapperPath&,
46                          const std::vector<std::string>&>
47 {
48     static GetObject op(DBusInterfaceType& dbus, const std::string& busName,
49                         const std::string& path, const std::string& interface,
50                         const std::string& method, const MapperPath& objectPath,
51                         const std::vector<std::string>& interfaces)
52     {
53         return dbus.mapperGetObject(busName, path, interface, method,
54                                     objectPath, interfaces);
55     }
56 };
57 
58 /** @brief CallMethodAndRead specialization for
59  *     org.freedesktop.DBus.Properties.GetAll(uint64_t). */
60 template <typename DBusInterfaceType>
61 struct CallMethodAndRead<DBusInterfaceType, PropertiesChanged<uint64_t>,
62                          const std::string&>
63 {
64     static PropertiesChanged<uint64_t>
65         op(DBusInterfaceType& dbus, const std::string& busName,
66            const std::string& path, const std::string& interface,
67            const std::string& method, const std::string& propertiesInterface)
68     {
69         return dbus.getPropertiesU64(busName, path, interface, method,
70                                      propertiesInterface);
71     }
72 };
73 
74 /** @brief CallMethodAndRead specialization for
75  *     org.freedesktop.DBus.Properties.GetAll(uint32_t). */
76 template <typename DBusInterfaceType>
77 struct CallMethodAndRead<DBusInterfaceType, PropertiesChanged<uint32_t>,
78                          const std::string&>
79 {
80     static PropertiesChanged<uint32_t>
81         op(DBusInterfaceType& dbus, const std::string& busName,
82            const std::string& path, const std::string& interface,
83            const std::string& method, const std::string& propertiesInterface)
84     {
85         return dbus.getPropertiesU32(busName, path, interface, method,
86                                      propertiesInterface);
87     }
88 };
89 
90 /** @brief CallMethodAndRead specialization for
91  *     org.freedesktop.DBus.Properties.GetAll(uint16_t). */
92 template <typename DBusInterfaceType>
93 struct CallMethodAndRead<DBusInterfaceType, PropertiesChanged<uint16_t>,
94                          const std::string&>
95 {
96     static PropertiesChanged<uint16_t>
97         op(DBusInterfaceType& dbus, const std::string& busName,
98            const std::string& path, const std::string& interface,
99            const std::string& method, const std::string& propertiesInterface)
100     {
101         return dbus.getPropertiesU16(busName, path, interface, method,
102                                      propertiesInterface);
103     }
104 };
105 
106 /** @brief CallMethodAndRead specialization for
107  *     org.freedesktop.DBus.Properties.GetAll(uint8_t). */
108 template <typename DBusInterfaceType>
109 struct CallMethodAndRead<DBusInterfaceType, PropertiesChanged<uint8_t>,
110                          const std::string&>
111 {
112     static PropertiesChanged<uint8_t>
113         op(DBusInterfaceType& dbus, const std::string& busName,
114            const std::string& path, const std::string& interface,
115            const std::string& method, const std::string& propertiesInterface)
116     {
117         return dbus.getPropertiesU8(busName, path, interface, method,
118                                     propertiesInterface);
119     }
120 };
121 
122 /** @brief CallMethodAndRead specialization for
123  *     org.freedesktop.DBus.Properties.GetAll(int64_t). */
124 template <typename DBusInterfaceType>
125 struct CallMethodAndRead<DBusInterfaceType, PropertiesChanged<int64_t>,
126                          const std::string&>
127 {
128     static PropertiesChanged<int64_t>
129         op(DBusInterfaceType& dbus, const std::string& busName,
130            const std::string& path, const std::string& interface,
131            const std::string& method, const std::string& propertiesInterface)
132     {
133         return dbus.getPropertiesU64(busName, path, interface, method,
134                                      propertiesInterface);
135     }
136 };
137 
138 /** @brief CallMethodAndRead specialization for
139  *     org.freedesktop.DBus.Properties.GetAll(int32_t). */
140 template <typename DBusInterfaceType>
141 struct CallMethodAndRead<DBusInterfaceType, PropertiesChanged<int32_t>,
142                          const std::string&>
143 {
144     static PropertiesChanged<int32_t>
145         op(DBusInterfaceType& dbus, const std::string& busName,
146            const std::string& path, const std::string& interface,
147            const std::string& method, const std::string& propertiesInterface)
148     {
149         return dbus.getPropertiesU32(busName, path, interface, method,
150                                      propertiesInterface);
151     }
152 };
153 
154 /** @brief CallMethodAndRead specialization for
155  *     org.freedesktop.DBus.Properties.GetAll(int16_t). */
156 template <typename DBusInterfaceType>
157 struct CallMethodAndRead<DBusInterfaceType, PropertiesChanged<int16_t>,
158                          const std::string&>
159 {
160     static PropertiesChanged<int16_t>
161         op(DBusInterfaceType& dbus, const std::string& busName,
162            const std::string& path, const std::string& interface,
163            const std::string& method, const std::string& propertiesInterface)
164     {
165         return dbus.getPropertiesU16(busName, path, interface, method,
166                                      propertiesInterface);
167     }
168 };
169 
170 /** @brief CallMethodAndRead specialization for
171  *     org.freedesktop.DBus.Properties.GetAll(int8_t). */
172 template <typename DBusInterfaceType>
173 struct CallMethodAndRead<DBusInterfaceType, PropertiesChanged<int8_t>,
174                          const std::string&>
175 {
176     static PropertiesChanged<int8_t>
177         op(DBusInterfaceType& dbus, const std::string& busName,
178            const std::string& path, const std::string& interface,
179            const std::string& method, const std::string& propertiesInterface)
180     {
181         return dbus.getPropertiesU8(busName, path, interface, method,
182                                     propertiesInterface);
183     }
184 };
185 
186 /** @brief CallMethodAndRead specialization for
187  *     org.freedesktop.DBus.Properties.GetAll(std::string). */
188 template <typename DBusInterfaceType>
189 struct CallMethodAndRead<DBusInterfaceType, PropertiesChanged<std::string>,
190                          const std::string&>
191 {
192     static PropertiesChanged<std::string>
193         op(DBusInterfaceType& dbus, const std::string& busName,
194            const std::string& path, const std::string& interface,
195            const std::string& method, const std::string& propertiesInterface)
196     {
197         return dbus.getPropertiesString(busName, path, interface, method,
198                                         propertiesInterface);
199     }
200 };
201 
202 /** @class MockDBusInterface
203  *  @brief DBus access delegate implementation for the property watch test
204  *  suite.
205  */
206 struct MockDBusInterface
207 {
208     MOCK_METHOD6(mapperGetObject,
209                  GetObject(const std::string&, const std::string&,
210                            const std::string&, const std::string&,
211                            const MapperPath&, const std::vector<std::string>&));
212 
213     MOCK_METHOD5(getPropertiesU64,
214                  PropertiesChanged<uint64_t>(
215                      const std::string&, const std::string&, const std::string&,
216                      const std::string&, const std::string&));
217 
218     MOCK_METHOD5(getPropertiesU32,
219                  PropertiesChanged<uint32_t>(
220                      const std::string&, const std::string&, const std::string&,
221                      const std::string&, const std::string&));
222 
223     MOCK_METHOD5(getPropertiesU16,
224                  PropertiesChanged<uint16_t>(
225                      const std::string&, const std::string&, const std::string&,
226                      const std::string&, const std::string&));
227 
228     MOCK_METHOD5(getPropertiesU8,
229                  PropertiesChanged<uint8_t>(
230                      const std::string&, const std::string&, const std::string&,
231                      const std::string&, const std::string&));
232 
233     MOCK_METHOD5(getPropertiesS64,
234                  PropertiesChanged<int64_t>(
235                      const std::string&, const std::string&, const std::string&,
236                      const std::string&, const std::string&));
237 
238     MOCK_METHOD5(getPropertiesS32,
239                  PropertiesChanged<int32_t>(
240                      const std::string&, const std::string&, const std::string&,
241                      const std::string&, const std::string&));
242 
243     MOCK_METHOD5(getPropertiesS16,
244                  PropertiesChanged<int16_t>(
245                      const std::string&, const std::string&, const std::string&,
246                      const std::string&, const std::string&));
247 
248     MOCK_METHOD5(getPropertiesS8,
249                  PropertiesChanged<int8_t>(
250                      const std::string&, const std::string&, const std::string&,
251                      const std::string&, const std::string&));
252 
253     MOCK_METHOD5(getPropertiesString,
254                  PropertiesChanged<std::string>(
255                      const std::string&, const std::string&, const std::string&,
256                      const std::string&, const std::string&));
257 
258     MOCK_METHOD2(fwdAddMatch,
259                  void(const std::string&,
260                       const sdbusplus::bus::match::match::callback_t&));
261 
262     static MockDBusInterface* ptr;
263     static MockDBusInterface& instance()
264     {
265         return *ptr;
266     }
267     static void instance(MockDBusInterface& p)
268     {
269         ptr = &p;
270     }
271 
272     /** @brief GMock member template/free function forward. */
273     template <typename Ret, typename... Args>
274     static auto callMethodAndRead(const std::string& busName,
275                                   const std::string& path,
276                                   const std::string& interface,
277                                   const std::string& method, Args&&... args)
278     {
279         return CallMethodAndRead<MockDBusInterface, Ret, Args...>::op(
280             instance(), busName, path, interface, method,
281             std::forward<Args>(args)...);
282     }
283 
284     /** @brief GMock free function forward. */
285     static auto
286         addMatch(const std::string& match,
287                  const sdbusplus::bus::match::match::callback_t& callback)
288     {
289         instance().fwdAddMatch(match, callback);
290     }
291 };
292 
293 /** @class Expect
294  *  @brief Enable use of EXPECT_CALL from a C++ template.
295  */
296 template <typename T>
297 struct Expect
298 {
299 };
300 
301 template <>
302 struct Expect<uint64_t>
303 {
304     template <typename MockObjType>
305     static auto& getProperties(MockObjType&& mockObj, const std::string& path,
306                                const std::string& interface)
307     {
308         return EXPECT_CALL(std::forward<MockObjType>(mockObj),
309                            getPropertiesU64(::testing::_, path,
310                                             "org.freedesktop.DBus.Properties",
311                                             "GetAll", interface));
312     }
313 };
314 
315 template <>
316 struct Expect<uint32_t>
317 {
318     template <typename MockObjType>
319     static auto& getProperties(MockObjType&& mockObj, const std::string& path,
320                                const std::string& interface)
321     {
322         return EXPECT_CALL(std::forward<MockObjType>(mockObj),
323                            getPropertiesU32(::testing::_, path,
324                                             "org.freedesktop.DBus.Properties",
325                                             "GetAll", interface));
326     }
327 };
328 
329 template <>
330 struct Expect<uint16_t>
331 {
332     template <typename MockObjType>
333     static auto& getProperties(MockObjType&& mockObj, const std::string& path,
334                                const std::string& interface)
335     {
336         return EXPECT_CALL(std::forward<MockObjType>(mockObj),
337                            getPropertiesU16(::testing::_, path,
338                                             "org.freedesktop.DBus.Properties",
339                                             "GetAll", interface));
340     }
341 };
342 
343 template <>
344 struct Expect<uint8_t>
345 {
346     template <typename MockObjType>
347     static auto& getProperties(MockObjType&& mockObj, const std::string& path,
348                                const std::string& interface)
349     {
350         return EXPECT_CALL(std::forward<MockObjType>(mockObj),
351                            getPropertiesU8(::testing::_, path,
352                                            "org.freedesktop.DBus.Properties",
353                                            "GetAll", interface));
354     }
355 };
356 
357 template <>
358 struct Expect<int64_t>
359 {
360     template <typename MockObjType>
361     static auto& getProperties(MockObjType&& mockObj, const std::string& path,
362                                const std::string& interface)
363     {
364         return EXPECT_CALL(std::forward<MockObjType>(mockObj),
365                            getPropertiesS64(::testing::_, path,
366                                             "org.freedesktop.DBus.Properties",
367                                             "GetAll", interface));
368     }
369 };
370 
371 template <>
372 struct Expect<int32_t>
373 {
374     template <typename MockObjType>
375     static auto& getProperties(MockObjType&& mockObj, const std::string& path,
376                                const std::string& interface)
377     {
378         return EXPECT_CALL(std::forward<MockObjType>(mockObj),
379                            getPropertiesS32(::testing::_, path,
380                                             "org.freedesktop.DBus.Properties",
381                                             "GetAll", interface));
382     }
383 };
384 
385 template <>
386 struct Expect<int16_t>
387 {
388     template <typename MockObjType>
389     static auto& getProperties(MockObjType&& mockObj, const std::string& path,
390                                const std::string& interface)
391     {
392         return EXPECT_CALL(std::forward<MockObjType>(mockObj),
393                            getPropertiesS16(::testing::_, path,
394                                             "org.freedesktop.DBus.Properties",
395                                             "GetAll", interface));
396     }
397 };
398 
399 template <>
400 struct Expect<int8_t>
401 {
402     template <typename MockObjType>
403     static auto& getProperties(MockObjType&& mockObj, const std::string& path,
404                                const std::string& interface)
405     {
406         return EXPECT_CALL(std::forward<MockObjType>(mockObj),
407                            getPropertiesS8(::testing::_, path,
408                                            "org.freedesktop.DBus.Properties",
409                                            "GetAll", interface));
410     }
411 };
412 
413 template <>
414 struct Expect<std::string>
415 {
416     template <typename MockObjType>
417     static auto& getProperties(MockObjType&& mockObj, const std::string& path,
418                                const std::string& interface)
419     {
420         return EXPECT_CALL(
421             std::forward<MockObjType>(mockObj),
422             getPropertiesString(::testing::_, path,
423                                 "org.freedesktop.DBus.Properties", "GetAll",
424                                 interface));
425     }
426 };
427 
428 } // namespace monitoring
429 } // namespace dbus
430 } // namespace phosphor
431