1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <functional>
20 #include <tuple>
21 #include <type_traits>
22 #include <utility>
23 
24 #include <VtsHalHidlTargetTestBase.h>
25 
26 namespace {
27 namespace detail {
28 template <typename>
29 struct functionArgSaver;
30 
31 // Provides a std::function that takes one argument, and a buffer
32 // wherein the function will store its argument. The buffer has
33 // the same type as the argument, but with const and reference
34 // modifiers removed.
35 template <typename ArgT>
36 struct functionArgSaver<std::function<void(ArgT)>> final {
37     using StorageT = typename std::remove_const<
38         typename std::remove_reference<ArgT>::type>::type;
39 
40     std::function<void(ArgT)> saveArgs = [this](ArgT arg) {
41         this->saved_values = arg;
42     };
43 
44     StorageT saved_values;
45 };
46 
47 // Provides a std::function that takes two arguments, and a buffer
48 // wherein the function will store its arguments. The buffer is a
49 // std::pair, whose elements have the same types as the arguments
50 // (but with const and reference modifiers removed).
51 template <typename Arg1T, typename Arg2T>
52 struct functionArgSaver<std::function<void(Arg1T, Arg2T)>> final {
53     using StorageT =
54         std::pair<typename std::remove_const<
55                       typename std::remove_reference<Arg1T>::type>::type,
56                   typename std::remove_const<
57                       typename std::remove_reference<Arg2T>::type>::type>;
58 
59     std::function<void(Arg1T, Arg2T)> saveArgs = [this](Arg1T arg1,
60                                                         Arg2T arg2) {
61         this->saved_values = {arg1, arg2};
62     };
63 
64     StorageT saved_values;
65 };
66 
67 // Provides a std::function that takes three or more arguments, and a
68 // buffer wherein the function will store its arguments. The buffer is a
69 // std::tuple whose elements have the same types as the arguments (but
70 // with const and reference modifiers removed).
71 template <typename... ArgT>
72 struct functionArgSaver<std::function<void(ArgT...)>> final {
73     using StorageT = std::tuple<typename std::remove_const<
74         typename std::remove_reference<ArgT>::type>::type...>;
75 
76     std::function<void(ArgT...)> saveArgs = [this](ArgT... arg) {
77         this->saved_values = {arg...};
78     };
79 
80     StorageT saved_values;
81 };
82 
83 // Invokes |method| on |object|, providing |method| a CallbackT as the
84 // final argument. Returns a copy of the parameters that |method| provided
85 // to CallbackT. (The parameters are returned by value.)
86 template <typename CallbackT, typename MethodT, typename ObjectT,
87           typename... ArgT>
88 typename functionArgSaver<CallbackT>::StorageT invokeMethod(
89     MethodT method, ObjectT object, ArgT&&... methodArg) {
90     functionArgSaver<CallbackT> result_buffer;
91     const auto& res = ((*object).*method)(std::forward<ArgT>(methodArg)...,
92                                           result_buffer.saveArgs);
93     EXPECT_TRUE(res.isOk());
94     return result_buffer.saved_values;
95 }
96 }  // namespace detail
97 }  // namespace
98 
99 // Invokes |method| on |strong_pointer|, passing provided arguments through to
100 // |method|.
101 //
102 // Returns either:
103 // - A copy of the result callback parameter (for callbacks with a single
104 //   parameter), OR
105 // - A pair containing a copy of the result callback parameters (for callbacks
106 //   with two parameters), OR
107 // - A tuple containing a copy of the result callback paramters (for callbacks
108 //   with three or more parameters).
109 //
110 // Example usage:
111 //   EXPECT_EQ(WifiStatusCode::SUCCESS,
112 //       HIDL_INVOKE(strong_pointer, methodReturningWifiStatus).code);
113 //   EXPECT_EQ(WifiStatusCode::SUCCESS,
114 //       HIDL_INVOKE(strong_pointer, methodReturningWifiStatusAndOneMore)
115 //         .first.code);
116 //   EXPECT_EQ(WifiStatusCode::SUCCESS, std::get<0>(
117 //       HIDL_INVOKE(strong_pointer, methodReturningWifiStatusAndTwoMore))
118 //         .code);
119 #define HIDL_INVOKE(strong_pointer, method, ...)                              \
120     (detail::invokeMethod<                                                    \
121         std::remove_reference<decltype(*strong_pointer)>::type::method##_cb>( \
122         &std::remove_reference<decltype(*strong_pointer)>::type::method,      \
123         strong_pointer, ##__VA_ARGS__))
124