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