Home | History | Annotate | Download | only in functional
      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 // This file is copied from
     18 // hardware/interfaces/wifi/1.0/vts/functional/wifi_hidl_call_util.h
     19 // Please make sure these two file are consistent.
     20 
     21 #pragma once
     22 
     23 #include <functional>
     24 #include <tuple>
     25 #include <type_traits>
     26 #include <utility>
     27 
     28 #include <VtsHalHidlTargetTestBase.h>
     29 
     30 namespace {
     31 namespace detail {
     32 template <typename>
     33 struct functionArgSaver;
     34 
     35 // Provides a std::function that takes one argument, and a buffer
     36 // wherein the function will store its argument. The buffer has
     37 // the same type as the argument, but with const and reference
     38 // modifiers removed.
     39 template <typename ArgT>
     40 struct functionArgSaver<std::function<void(ArgT)>> final {
     41     using StorageT = typename std::remove_const<
     42         typename std::remove_reference<ArgT>::type>::type;
     43 
     44     std::function<void(ArgT)> saveArgs = [this](ArgT arg) {
     45         this->saved_values = arg;
     46     };
     47 
     48     StorageT saved_values;
     49 };
     50 
     51 // Provides a std::function that takes two arguments, and a buffer
     52 // wherein the function will store its arguments. The buffer is a
     53 // std::pair, whose elements have the same types as the arguments
     54 // (but with const and reference modifiers removed).
     55 template <typename Arg1T, typename Arg2T>
     56 struct functionArgSaver<std::function<void(Arg1T, Arg2T)>> final {
     57     using StorageT =
     58         std::pair<typename std::remove_const<
     59                       typename std::remove_reference<Arg1T>::type>::type,
     60                   typename std::remove_const<
     61                       typename std::remove_reference<Arg2T>::type>::type>;
     62 
     63     std::function<void(Arg1T, Arg2T)> saveArgs = [this](Arg1T arg1,
     64                                                         Arg2T arg2) {
     65         this->saved_values = {arg1, arg2};
     66     };
     67 
     68     StorageT saved_values;
     69 };
     70 
     71 // Provides a std::function that takes three or more arguments, and a
     72 // buffer wherein the function will store its arguments. The buffer is a
     73 // std::tuple whose elements have the same types as the arguments (but
     74 // with const and reference modifiers removed).
     75 template <typename... ArgT>
     76 struct functionArgSaver<std::function<void(ArgT...)>> final {
     77     using StorageT = std::tuple<typename std::remove_const<
     78         typename std::remove_reference<ArgT>::type>::type...>;
     79 
     80     std::function<void(ArgT...)> saveArgs = [this](ArgT... arg) {
     81         this->saved_values = {arg...};
     82     };
     83 
     84     StorageT saved_values;
     85 };
     86 
     87 // Invokes |method| on |object|, providing |method| a CallbackT as the
     88 // final argument. Returns a copy of the parameters that |method| provided
     89 // to CallbackT. (The parameters are returned by value.)
     90 template <typename CallbackT, typename MethodT, typename ObjectT,
     91           typename... ArgT>
     92 typename functionArgSaver<CallbackT>::StorageT invokeMethod(
     93     MethodT method, ObjectT object, ArgT&&... methodArg) {
     94     functionArgSaver<CallbackT> result_buffer;
     95     const auto& res = ((*object).*method)(std::forward<ArgT>(methodArg)...,
     96                                           result_buffer.saveArgs);
     97     EXPECT_TRUE(res.isOk());
     98     return result_buffer.saved_values;
     99 }
    100 }  // namespace detail
    101 }  // namespace
    102 
    103 // Invokes |method| on |strong_pointer|, passing provided arguments through to
    104 // |method|.
    105 //
    106 // Returns either:
    107 // - A copy of the result callback parameter (for callbacks with a single
    108 //   parameter), OR
    109 // - A pair containing a copy of the result callback parameters (for callbacks
    110 //   with two parameters), OR
    111 // - A tuple containing a copy of the result callback paramters (for callbacks
    112 //   with three or more parameters).
    113 //
    114 // Example usage:
    115 //   EXPECT_EQ(WifiStatusCode::SUCCESS,
    116 //       HIDL_INVOKE(strong_pointer, methodReturningWifiStatus).code);
    117 //   EXPECT_EQ(WifiStatusCode::SUCCESS,
    118 //       HIDL_INVOKE(strong_pointer, methodReturningWifiStatusAndOneMore)
    119 //         .first.code);
    120 //   EXPECT_EQ(WifiStatusCode::SUCCESS, std::get<0>(
    121 //       HIDL_INVOKE(strong_pointer, methodReturningWifiStatusAndTwoMore))
    122 //         .code);
    123 #define HIDL_INVOKE(strong_pointer, method, ...)                              \
    124     (detail::invokeMethod<                                                    \
    125         std::remove_reference<decltype(*strong_pointer)>::type::method##_cb>( \
    126         &std::remove_reference<decltype(*strong_pointer)>::type::method,      \
    127         strong_pointer, ##__VA_ARGS__))
    128