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 <
30     typename DBusInterfaceType,
31     typename Ret,
32     typename ...Args >
33 struct CallMethodAndRead
34 {
35     static Ret op(
36         DBusInterfaceType& dbus,
37         const std::string& busName,
38         const std::string& path,
39         const std::string& interface,
40         const std::string& method,
41         Args&& ... args)
42     {
43         static_assert(true, "Missing CallMethodAndRead definition.");
44         return Ret();
45     }
46 };
47 
48 /** @brief CallMethodAndRead specialization for
49  *     xyz.openbmc_project.ObjectMapper.GetObject. */
50 template <typename DBusInterfaceType>
51 struct CallMethodAndRead <
52     DBusInterfaceType,
53     GetObject,
54     const MapperPath&,
55     const std::vector<std::string>& >
56 {
57     static GetObject op(
58         DBusInterfaceType& dbus,
59         const std::string& busName,
60         const std::string& path,
61         const std::string& interface,
62         const std::string& method,
63         const MapperPath& objectPath,
64         const std::vector<std::string>& interfaces)
65     {
66         return dbus.mapperGetObject(
67                    busName,
68                    path,
69                    interface,
70                    method,
71                    objectPath,
72                    interfaces);
73     }
74 };
75 
76 /** @brief CallMethodAndRead specialization for
77  *     org.freedesktop.DBus.Properties.GetAll(uint64_t). */
78 template <typename DBusInterfaceType>
79 struct CallMethodAndRead <
80     DBusInterfaceType,
81     PropertiesChanged<uint64_t>,
82     const std::string& >
83 {
84     static PropertiesChanged<uint64_t> op(
85         DBusInterfaceType& dbus,
86         const std::string& busName,
87         const std::string& path,
88         const std::string& interface,
89         const std::string& method,
90         const std::string& propertiesInterface)
91     {
92         return dbus.getPropertiesU64(
93                    busName,
94                    path,
95                    interface,
96                    method,
97                    propertiesInterface);
98     }
99 };
100 
101 /** @brief CallMethodAndRead specialization for
102  *     org.freedesktop.DBus.Properties.GetAll(uint32_t). */
103 template <typename DBusInterfaceType>
104 struct CallMethodAndRead <
105     DBusInterfaceType,
106     PropertiesChanged<uint32_t>,
107     const std::string& >
108 {
109     static PropertiesChanged<uint32_t> op(
110         DBusInterfaceType& dbus,
111         const std::string& busName,
112         const std::string& path,
113         const std::string& interface,
114         const std::string& method,
115         const std::string& propertiesInterface)
116     {
117         return dbus.getPropertiesU32(
118                    busName,
119                    path,
120                    interface,
121                    method,
122                    propertiesInterface);
123     }
124 };
125 
126 /** @brief CallMethodAndRead specialization for
127  *     org.freedesktop.DBus.Properties.GetAll(uint16_t). */
128 template <typename DBusInterfaceType>
129 struct CallMethodAndRead <
130     DBusInterfaceType,
131     PropertiesChanged<uint16_t>,
132     const std::string& >
133 {
134     static PropertiesChanged<uint16_t> op(
135         DBusInterfaceType& dbus,
136         const std::string& busName,
137         const std::string& path,
138         const std::string& interface,
139         const std::string& method,
140         const std::string& propertiesInterface)
141     {
142         return dbus.getPropertiesU16(
143                    busName,
144                    path,
145                    interface,
146                    method,
147                    propertiesInterface);
148     }
149 };
150 
151 /** @brief CallMethodAndRead specialization for
152  *     org.freedesktop.DBus.Properties.GetAll(uint8_t). */
153 template <typename DBusInterfaceType>
154 struct CallMethodAndRead <
155     DBusInterfaceType,
156     PropertiesChanged<uint8_t>,
157     const std::string& >
158 {
159     static PropertiesChanged<uint8_t> op(
160         DBusInterfaceType& dbus,
161         const std::string& busName,
162         const std::string& path,
163         const std::string& interface,
164         const std::string& method,
165         const std::string& propertiesInterface)
166     {
167         return dbus.getPropertiesU8(
168                    busName,
169                    path,
170                    interface,
171                    method,
172                    propertiesInterface);
173     }
174 };
175 
176 /** @brief CallMethodAndRead specialization for
177  *     org.freedesktop.DBus.Properties.GetAll(int64_t). */
178 template <typename DBusInterfaceType>
179 struct CallMethodAndRead <
180     DBusInterfaceType,
181     PropertiesChanged<int64_t>,
182     const std::string& >
183 {
184     static PropertiesChanged<int64_t> op(
185         DBusInterfaceType& dbus,
186         const std::string& busName,
187         const std::string& path,
188         const std::string& interface,
189         const std::string& method,
190         const std::string& propertiesInterface)
191     {
192         return dbus.getPropertiesU64(
193                    busName,
194                    path,
195                    interface,
196                    method,
197                    propertiesInterface);
198     }
199 };
200 
201 /** @brief CallMethodAndRead specialization for
202  *     org.freedesktop.DBus.Properties.GetAll(int32_t). */
203 template <typename DBusInterfaceType>
204 struct CallMethodAndRead <
205     DBusInterfaceType,
206     PropertiesChanged<int32_t>,
207     const std::string& >
208 {
209     static PropertiesChanged<int32_t> op(
210         DBusInterfaceType& dbus,
211         const std::string& busName,
212         const std::string& path,
213         const std::string& interface,
214         const std::string& method,
215         const std::string& propertiesInterface)
216     {
217         return dbus.getPropertiesU32(
218                    busName,
219                    path,
220                    interface,
221                    method,
222                    propertiesInterface);
223     }
224 };
225 
226 /** @brief CallMethodAndRead specialization for
227  *     org.freedesktop.DBus.Properties.GetAll(int16_t). */
228 template <typename DBusInterfaceType>
229 struct CallMethodAndRead <
230     DBusInterfaceType,
231     PropertiesChanged<int16_t>,
232     const std::string& >
233 {
234     static PropertiesChanged<int16_t> op(
235         DBusInterfaceType& dbus,
236         const std::string& busName,
237         const std::string& path,
238         const std::string& interface,
239         const std::string& method,
240         const std::string& propertiesInterface)
241     {
242         return dbus.getPropertiesU16(
243                    busName,
244                    path,
245                    interface,
246                    method,
247                    propertiesInterface);
248     }
249 };
250 
251 /** @brief CallMethodAndRead specialization for
252  *     org.freedesktop.DBus.Properties.GetAll(int8_t). */
253 template <typename DBusInterfaceType>
254 struct CallMethodAndRead <
255     DBusInterfaceType,
256     PropertiesChanged<int8_t>,
257     const std::string& >
258 {
259     static PropertiesChanged<int8_t> op(
260         DBusInterfaceType& dbus,
261         const std::string& busName,
262         const std::string& path,
263         const std::string& interface,
264         const std::string& method,
265         const std::string& propertiesInterface)
266     {
267         return dbus.getPropertiesU8(
268                    busName,
269                    path,
270                    interface,
271                    method,
272                    propertiesInterface);
273     }
274 };
275 
276 /** @brief CallMethodAndRead specialization for
277  *     org.freedesktop.DBus.Properties.GetAll(std::string). */
278 template <typename DBusInterfaceType>
279 struct CallMethodAndRead <
280     DBusInterfaceType,
281     PropertiesChanged<std::string>,
282     const std::string& >
283 {
284     static PropertiesChanged<std::string> op(
285         DBusInterfaceType& dbus,
286         const std::string& busName,
287         const std::string& path,
288         const std::string& interface,
289         const std::string& method,
290         const std::string& propertiesInterface)
291     {
292         return dbus.getPropertiesString(
293                    busName,
294                    path,
295                    interface,
296                    method,
297                    propertiesInterface);
298     }
299 };
300 
301 /** @class MockDBusInterface
302  *  @brief DBus access delegate implementation for the property watch test
303  *  suite.
304  */
305 struct MockDBusInterface
306 {
307     MOCK_METHOD6(
308         mapperGetObject,
309         GetObject(
310             const std::string&,
311             const std::string&,
312             const std::string&,
313             const std::string&,
314             const MapperPath&,
315             const std::vector<std::string>&));
316 
317     MOCK_METHOD5(
318         getPropertiesU64,
319         PropertiesChanged<uint64_t>(
320             const std::string&,
321             const std::string&,
322             const std::string&,
323             const std::string&,
324             const std::string&));
325 
326     MOCK_METHOD5(
327         getPropertiesU32,
328         PropertiesChanged<uint32_t>(
329             const std::string&,
330             const std::string&,
331             const std::string&,
332             const std::string&,
333             const std::string&));
334 
335     MOCK_METHOD5(
336         getPropertiesU16,
337         PropertiesChanged<uint16_t>(
338             const std::string&,
339             const std::string&,
340             const std::string&,
341             const std::string&,
342             const std::string&));
343 
344     MOCK_METHOD5(
345         getPropertiesU8,
346         PropertiesChanged<uint8_t>(
347             const std::string&,
348             const std::string&,
349             const std::string&,
350             const std::string&,
351             const std::string&));
352 
353     MOCK_METHOD5(
354         getPropertiesS64,
355         PropertiesChanged<int64_t>(
356             const std::string&,
357             const std::string&,
358             const std::string&,
359             const std::string&,
360             const std::string&));
361 
362     MOCK_METHOD5(
363         getPropertiesS32,
364         PropertiesChanged<int32_t>(
365             const std::string&,
366             const std::string&,
367             const std::string&,
368             const std::string&,
369             const std::string&));
370 
371     MOCK_METHOD5(
372         getPropertiesS16,
373         PropertiesChanged<int16_t>(
374             const std::string&,
375             const std::string&,
376             const std::string&,
377             const std::string&,
378             const std::string&));
379 
380     MOCK_METHOD5(
381         getPropertiesS8,
382         PropertiesChanged<int8_t>(
383             const std::string&,
384             const std::string&,
385             const std::string&,
386             const std::string&,
387             const std::string&));
388 
389     MOCK_METHOD5(
390         getPropertiesString,
391         PropertiesChanged<std::string>(
392             const std::string&,
393             const std::string&,
394             const std::string&,
395             const std::string&,
396             const std::string&));
397 
398     MOCK_METHOD2(
399         fwdAddMatch,
400         void(
401             const std::string&,
402             const sdbusplus::bus::match::match::callback_t&));
403 
404     static MockDBusInterface* ptr;
405     static MockDBusInterface& instance()
406     {
407         return *ptr;
408     }
409     static void instance(MockDBusInterface& p)
410     {
411         ptr = &p;
412     }
413 
414     /** @brief GMock member template/free function forward. */
415     template <typename Ret, typename ...Args>
416     static auto callMethodAndRead(
417         const std::string& busName,
418         const std::string& path,
419         const std::string& interface,
420         const std::string& method,
421         Args&& ... args)
422     {
423         return CallMethodAndRead <MockDBusInterface, Ret, Args... >::op(
424                    instance(),
425                    busName,
426                    path,
427                    interface,
428                    method,
429                    std::forward<Args>(args)...);
430     }
431 
432     /** @brief GMock free function forward. */
433     static auto addMatch(
434         const std::string& match,
435         const sdbusplus::bus::match::match::callback_t& callback)
436     {
437         instance().fwdAddMatch(match, callback);
438     }
439 };
440 
441 /** @class Expect
442  *  @brief Enable use of EXPECT_CALL from a C++ template.
443  */
444 template <typename T> struct Expect {};
445 
446 template <>
447 struct Expect<uint64_t>
448 {
449     template <typename MockObjType>
450     static auto& getProperties(
451         MockObjType&& mockObj,
452         const std::string& path,
453         const std::string& interface)
454     {
455         return EXPECT_CALL(
456                    std::forward<MockObjType>(mockObj),
457                    getPropertiesU64(
458                        ::testing::_,
459                        path,
460                        "org.freedesktop.DBus.Properties",
461                        "GetAll",
462                        interface));
463     }
464 };
465 
466 template <>
467 struct Expect<uint32_t>
468 {
469     template <typename MockObjType>
470     static auto& getProperties(
471         MockObjType&& mockObj,
472         const std::string& path,
473         const std::string& interface)
474     {
475         return EXPECT_CALL(
476                    std::forward<MockObjType>(mockObj),
477                    getPropertiesU32(
478                        ::testing::_,
479                        path,
480                        "org.freedesktop.DBus.Properties",
481                        "GetAll",
482                        interface));
483     }
484 };
485 
486 template <>
487 struct Expect<uint16_t>
488 {
489     template <typename MockObjType>
490     static auto& getProperties(
491         MockObjType&& mockObj,
492         const std::string& path,
493         const std::string& interface)
494     {
495         return EXPECT_CALL(
496                    std::forward<MockObjType>(mockObj),
497                    getPropertiesU16(
498                        ::testing::_,
499                        path,
500                        "org.freedesktop.DBus.Properties",
501                        "GetAll",
502                        interface));
503     }
504 };
505 
506 template <>
507 struct Expect<uint8_t>
508 {
509     template <typename MockObjType>
510     static auto& getProperties(
511         MockObjType&& mockObj,
512         const std::string& path,
513         const std::string& interface)
514     {
515         return EXPECT_CALL(
516                    std::forward<MockObjType>(mockObj),
517                    getPropertiesU8(
518                        ::testing::_,
519                        path,
520                        "org.freedesktop.DBus.Properties",
521                        "GetAll",
522                        interface));
523     }
524 };
525 
526 template <>
527 struct Expect<int64_t>
528 {
529     template <typename MockObjType>
530     static auto& getProperties(
531         MockObjType&& mockObj,
532         const std::string& path,
533         const std::string& interface)
534     {
535         return EXPECT_CALL(
536                    std::forward<MockObjType>(mockObj),
537                    getPropertiesS64(
538                        ::testing::_,
539                        path,
540                        "org.freedesktop.DBus.Properties",
541                        "GetAll",
542                        interface));
543     }
544 };
545 
546 template <>
547 struct Expect<int32_t>
548 {
549     template <typename MockObjType>
550     static auto& getProperties(
551         MockObjType&& mockObj,
552         const std::string& path,
553         const std::string& interface)
554     {
555         return EXPECT_CALL(
556                    std::forward<MockObjType>(mockObj),
557                    getPropertiesS32(
558                        ::testing::_,
559                        path,
560                        "org.freedesktop.DBus.Properties",
561                        "GetAll",
562                        interface));
563     }
564 };
565 
566 template <>
567 struct Expect<int16_t>
568 {
569     template <typename MockObjType>
570     static auto& getProperties(
571         MockObjType&& mockObj,
572         const std::string& path,
573         const std::string& interface)
574     {
575         return EXPECT_CALL(
576                    std::forward<MockObjType>(mockObj),
577                    getPropertiesS16(
578                        ::testing::_,
579                        path,
580                        "org.freedesktop.DBus.Properties",
581                        "GetAll",
582                        interface));
583     }
584 };
585 
586 template <>
587 struct Expect<int8_t>
588 {
589     template <typename MockObjType>
590     static auto& getProperties(
591         MockObjType&& mockObj,
592         const std::string& path,
593         const std::string& interface)
594     {
595         return EXPECT_CALL(
596                    std::forward<MockObjType>(mockObj),
597                    getPropertiesS8(
598                        ::testing::_,
599                        path,
600                        "org.freedesktop.DBus.Properties",
601                        "GetAll",
602                        interface));
603     }
604 };
605 
606 template <>
607 struct Expect<std::string>
608 {
609     template <typename MockObjType>
610     static auto& getProperties(
611         MockObjType&& mockObj,
612         const std::string& path,
613         const std::string& interface)
614     {
615         return EXPECT_CALL(
616                    std::forward<MockObjType>(mockObj),
617                    getPropertiesString(
618                        ::testing::_,
619                        path,
620                        "org.freedesktop.DBus.Properties",
621                        "GetAll",
622                        interface));
623     }
624 };
625 
626 } // namespace monitoring
627 } // namespace dbus
628 } // namespace phosphor
629