mirror of
https://github.com/google/googletest.git
synced 2024-12-27 10:11:03 +08:00
Googletest export
Upgrade WithArgs family of actions to C++11. PiperOrigin-RevId: 221671690
This commit is contained in:
parent
e46e87bb1f
commit
aac18185eb
@ -1061,6 +1061,24 @@ class DoBothAction {
|
||||
GTEST_DISALLOW_ASSIGN_(DoBothAction);
|
||||
};
|
||||
|
||||
template <typename InnerAction, size_t... I>
|
||||
struct WithArgsAction {
|
||||
InnerAction action;
|
||||
|
||||
// The inner action could be anything convertible to Action<X>.
|
||||
// We use the conversion operator to detect the signature of the inner Action.
|
||||
template <typename R, typename... Args>
|
||||
operator Action<R(Args...)>() const { // NOLINT
|
||||
Action<R(typename std::tuple_element<I, std::tuple<Args...>>::type...)>
|
||||
converted(action);
|
||||
|
||||
return [converted](Args... args) -> R {
|
||||
return converted.Perform(std::forward_as_tuple(
|
||||
std::get<I>(std::forward_as_tuple(std::forward<Args>(args)...))...));
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// An Unused object can be implicitly constructed from ANY value.
|
||||
@ -1111,6 +1129,37 @@ Action<To>::Action(const Action<From>& from)
|
||||
: new internal::ActionAdaptor<To, From>(from)) {
|
||||
}
|
||||
|
||||
// WithArg<k>(an_action) creates an action that passes the k-th
|
||||
// (0-based) argument of the mock function to an_action and performs
|
||||
// it. It adapts an action accepting one argument to one that accepts
|
||||
// multiple arguments. For convenience, we also provide
|
||||
// WithArgs<k>(an_action) (defined below) as a synonym.
|
||||
template <size_t k, typename InnerAction>
|
||||
internal::WithArgsAction<typename std::decay<InnerAction>::type, k>
|
||||
WithArg(InnerAction&& action) {
|
||||
return {std::forward<InnerAction>(action)};
|
||||
}
|
||||
|
||||
// WithArgs<N1, N2, ..., Nk>(an_action) creates an action that passes
|
||||
// the selected arguments of the mock function to an_action and
|
||||
// performs it. It serves as an adaptor between actions with
|
||||
// different argument lists.
|
||||
template <size_t k, size_t... ks, typename InnerAction>
|
||||
internal::WithArgsAction<typename std::decay<InnerAction>::type, k, ks...>
|
||||
WithArgs(InnerAction&& action) {
|
||||
return {std::forward<InnerAction>(action)};
|
||||
}
|
||||
|
||||
// WithoutArgs(inner_action) can be used in a mock function with a
|
||||
// non-empty argument list to perform inner_action, which takes no
|
||||
// argument. In other words, it adapts an action accepting no
|
||||
// argument to one that accepts (and ignores) arguments.
|
||||
template <typename InnerAction>
|
||||
internal::WithArgsAction<typename std::decay<InnerAction>::type>
|
||||
WithoutArgs(InnerAction&& action) {
|
||||
return {std::forward<InnerAction>(action)};
|
||||
}
|
||||
|
||||
// Creates an action that returns 'value'. 'value' is passed by value
|
||||
// instead of const reference - otherwise Return("string literal")
|
||||
// will trigger a compiler error about using array as initializer.
|
||||
|
@ -352,235 +352,6 @@ class InvokeCallbackAction {
|
||||
const std::shared_ptr<CallbackType> callback_;
|
||||
};
|
||||
|
||||
// An INTERNAL macro for extracting the type of a tuple field. It's
|
||||
// subject to change without notice - DO NOT USE IN USER CODE!
|
||||
#define GMOCK_FIELD_(Tuple, N) \
|
||||
typename ::std::tuple_element<N, Tuple>::type
|
||||
|
||||
// SelectArgs<Result, ArgumentTuple, k1, k2, ..., k_n>::type is the
|
||||
// type of an n-ary function whose i-th (1-based) argument type is the
|
||||
// k{i}-th (0-based) field of ArgumentTuple, which must be a tuple
|
||||
// type, and whose return type is Result. For example,
|
||||
// SelectArgs<int, ::std::tuple<bool, char, double, long>, 0, 3>::type
|
||||
// is int(bool, long).
|
||||
//
|
||||
// SelectArgs<Result, ArgumentTuple, k1, k2, ..., k_n>::Select(args)
|
||||
// returns the selected fields (k1, k2, ..., k_n) of args as a tuple.
|
||||
// For example,
|
||||
// SelectArgs<int, std::tuple<bool, char, double>, 2, 0>::Select(
|
||||
// ::std::make_tuple(true, 'a', 2.5))
|
||||
// returns tuple (2.5, true).
|
||||
//
|
||||
// The numbers in list k1, k2, ..., k_n must be >= 0, where n can be
|
||||
// in the range [0, 10]. Duplicates are allowed and they don't have
|
||||
// to be in an ascending or descending order.
|
||||
|
||||
template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
|
||||
int k4, int k5, int k6, int k7, int k8, int k9, int k10>
|
||||
class SelectArgs {
|
||||
public:
|
||||
typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
|
||||
GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
|
||||
GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5),
|
||||
GMOCK_FIELD_(ArgumentTuple, k6), GMOCK_FIELD_(ArgumentTuple, k7),
|
||||
GMOCK_FIELD_(ArgumentTuple, k8), GMOCK_FIELD_(ArgumentTuple, k9),
|
||||
GMOCK_FIELD_(ArgumentTuple, k10));
|
||||
typedef typename Function<type>::ArgumentTuple SelectedArgs;
|
||||
static SelectedArgs Select(const ArgumentTuple& args) {
|
||||
return SelectedArgs(std::get<k1>(args), std::get<k2>(args),
|
||||
std::get<k3>(args), std::get<k4>(args), std::get<k5>(args),
|
||||
std::get<k6>(args), std::get<k7>(args), std::get<k8>(args),
|
||||
std::get<k9>(args), std::get<k10>(args));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Result, typename ArgumentTuple>
|
||||
class SelectArgs<Result, ArgumentTuple,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1> {
|
||||
public:
|
||||
typedef Result type();
|
||||
typedef typename Function<type>::ArgumentTuple SelectedArgs;
|
||||
static SelectedArgs Select(const ArgumentTuple& /* args */) {
|
||||
return SelectedArgs();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Result, typename ArgumentTuple, int k1>
|
||||
class SelectArgs<Result, ArgumentTuple,
|
||||
k1, -1, -1, -1, -1, -1, -1, -1, -1, -1> {
|
||||
public:
|
||||
typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1));
|
||||
typedef typename Function<type>::ArgumentTuple SelectedArgs;
|
||||
static SelectedArgs Select(const ArgumentTuple& args) {
|
||||
return SelectedArgs(std::get<k1>(args));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Result, typename ArgumentTuple, int k1, int k2>
|
||||
class SelectArgs<Result, ArgumentTuple,
|
||||
k1, k2, -1, -1, -1, -1, -1, -1, -1, -1> {
|
||||
public:
|
||||
typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
|
||||
GMOCK_FIELD_(ArgumentTuple, k2));
|
||||
typedef typename Function<type>::ArgumentTuple SelectedArgs;
|
||||
static SelectedArgs Select(const ArgumentTuple& args) {
|
||||
return SelectedArgs(std::get<k1>(args), std::get<k2>(args));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Result, typename ArgumentTuple, int k1, int k2, int k3>
|
||||
class SelectArgs<Result, ArgumentTuple,
|
||||
k1, k2, k3, -1, -1, -1, -1, -1, -1, -1> {
|
||||
public:
|
||||
typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
|
||||
GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3));
|
||||
typedef typename Function<type>::ArgumentTuple SelectedArgs;
|
||||
static SelectedArgs Select(const ArgumentTuple& args) {
|
||||
return SelectedArgs(std::get<k1>(args), std::get<k2>(args),
|
||||
std::get<k3>(args));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
|
||||
int k4>
|
||||
class SelectArgs<Result, ArgumentTuple,
|
||||
k1, k2, k3, k4, -1, -1, -1, -1, -1, -1> {
|
||||
public:
|
||||
typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
|
||||
GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
|
||||
GMOCK_FIELD_(ArgumentTuple, k4));
|
||||
typedef typename Function<type>::ArgumentTuple SelectedArgs;
|
||||
static SelectedArgs Select(const ArgumentTuple& args) {
|
||||
return SelectedArgs(std::get<k1>(args), std::get<k2>(args),
|
||||
std::get<k3>(args), std::get<k4>(args));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
|
||||
int k4, int k5>
|
||||
class SelectArgs<Result, ArgumentTuple,
|
||||
k1, k2, k3, k4, k5, -1, -1, -1, -1, -1> {
|
||||
public:
|
||||
typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
|
||||
GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
|
||||
GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5));
|
||||
typedef typename Function<type>::ArgumentTuple SelectedArgs;
|
||||
static SelectedArgs Select(const ArgumentTuple& args) {
|
||||
return SelectedArgs(std::get<k1>(args), std::get<k2>(args),
|
||||
std::get<k3>(args), std::get<k4>(args), std::get<k5>(args));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
|
||||
int k4, int k5, int k6>
|
||||
class SelectArgs<Result, ArgumentTuple,
|
||||
k1, k2, k3, k4, k5, k6, -1, -1, -1, -1> {
|
||||
public:
|
||||
typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
|
||||
GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
|
||||
GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5),
|
||||
GMOCK_FIELD_(ArgumentTuple, k6));
|
||||
typedef typename Function<type>::ArgumentTuple SelectedArgs;
|
||||
static SelectedArgs Select(const ArgumentTuple& args) {
|
||||
return SelectedArgs(std::get<k1>(args), std::get<k2>(args),
|
||||
std::get<k3>(args), std::get<k4>(args), std::get<k5>(args),
|
||||
std::get<k6>(args));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
|
||||
int k4, int k5, int k6, int k7>
|
||||
class SelectArgs<Result, ArgumentTuple,
|
||||
k1, k2, k3, k4, k5, k6, k7, -1, -1, -1> {
|
||||
public:
|
||||
typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
|
||||
GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
|
||||
GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5),
|
||||
GMOCK_FIELD_(ArgumentTuple, k6), GMOCK_FIELD_(ArgumentTuple, k7));
|
||||
typedef typename Function<type>::ArgumentTuple SelectedArgs;
|
||||
static SelectedArgs Select(const ArgumentTuple& args) {
|
||||
return SelectedArgs(std::get<k1>(args), std::get<k2>(args),
|
||||
std::get<k3>(args), std::get<k4>(args), std::get<k5>(args),
|
||||
std::get<k6>(args), std::get<k7>(args));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
|
||||
int k4, int k5, int k6, int k7, int k8>
|
||||
class SelectArgs<Result, ArgumentTuple,
|
||||
k1, k2, k3, k4, k5, k6, k7, k8, -1, -1> {
|
||||
public:
|
||||
typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
|
||||
GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
|
||||
GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5),
|
||||
GMOCK_FIELD_(ArgumentTuple, k6), GMOCK_FIELD_(ArgumentTuple, k7),
|
||||
GMOCK_FIELD_(ArgumentTuple, k8));
|
||||
typedef typename Function<type>::ArgumentTuple SelectedArgs;
|
||||
static SelectedArgs Select(const ArgumentTuple& args) {
|
||||
return SelectedArgs(std::get<k1>(args), std::get<k2>(args),
|
||||
std::get<k3>(args), std::get<k4>(args), std::get<k5>(args),
|
||||
std::get<k6>(args), std::get<k7>(args), std::get<k8>(args));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
|
||||
int k4, int k5, int k6, int k7, int k8, int k9>
|
||||
class SelectArgs<Result, ArgumentTuple,
|
||||
k1, k2, k3, k4, k5, k6, k7, k8, k9, -1> {
|
||||
public:
|
||||
typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
|
||||
GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
|
||||
GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5),
|
||||
GMOCK_FIELD_(ArgumentTuple, k6), GMOCK_FIELD_(ArgumentTuple, k7),
|
||||
GMOCK_FIELD_(ArgumentTuple, k8), GMOCK_FIELD_(ArgumentTuple, k9));
|
||||
typedef typename Function<type>::ArgumentTuple SelectedArgs;
|
||||
static SelectedArgs Select(const ArgumentTuple& args) {
|
||||
return SelectedArgs(std::get<k1>(args), std::get<k2>(args),
|
||||
std::get<k3>(args), std::get<k4>(args), std::get<k5>(args),
|
||||
std::get<k6>(args), std::get<k7>(args), std::get<k8>(args),
|
||||
std::get<k9>(args));
|
||||
}
|
||||
};
|
||||
|
||||
#undef GMOCK_FIELD_
|
||||
|
||||
// Implements the WithArgs action.
|
||||
template <typename InnerAction, int k1 = -1, int k2 = -1, int k3 = -1,
|
||||
int k4 = -1, int k5 = -1, int k6 = -1, int k7 = -1, int k8 = -1,
|
||||
int k9 = -1, int k10 = -1>
|
||||
class WithArgsAction {
|
||||
public:
|
||||
explicit WithArgsAction(const InnerAction& action) : action_(action) {}
|
||||
|
||||
template <typename F>
|
||||
operator Action<F>() const { return MakeAction(new Impl<F>(action_)); }
|
||||
|
||||
private:
|
||||
template <typename F>
|
||||
class Impl : public ActionInterface<F> {
|
||||
public:
|
||||
typedef typename Function<F>::Result Result;
|
||||
typedef typename Function<F>::ArgumentTuple ArgumentTuple;
|
||||
|
||||
explicit Impl(const InnerAction& action) : action_(action) {}
|
||||
|
||||
virtual Result Perform(const ArgumentTuple& args) {
|
||||
return action_.Perform(SelectArgs<Result, ArgumentTuple, k1, k2, k3, k4,
|
||||
k5, k6, k7, k8, k9, k10>::Select(args));
|
||||
}
|
||||
|
||||
private:
|
||||
typedef typename SelectArgs<Result, ArgumentTuple,
|
||||
k1, k2, k3, k4, k5, k6, k7, k8, k9, k10>::type InnerFunctionType;
|
||||
|
||||
Action<InnerFunctionType> action_;
|
||||
};
|
||||
|
||||
const InnerAction action_;
|
||||
|
||||
GTEST_DISALLOW_ASSIGN_(WithArgsAction);
|
||||
};
|
||||
|
||||
// A macro from the ACTION* family (defined later in this file)
|
||||
// defines an action that can be used in a mock function. Typically,
|
||||
// these actions only care about a subset of the arguments of the mock
|
||||
@ -704,82 +475,6 @@ class ActionHelper {
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Various overloads for Invoke().
|
||||
|
||||
// WithArgs<N1, N2, ..., Nk>(an_action) creates an action that passes
|
||||
// the selected arguments of the mock function to an_action and
|
||||
// performs it. It serves as an adaptor between actions with
|
||||
// different argument lists. C++ doesn't support default arguments for
|
||||
// function templates, so we have to overload it.
|
||||
template <int k1, typename InnerAction>
|
||||
inline internal::WithArgsAction<InnerAction, k1>
|
||||
WithArgs(const InnerAction& action) {
|
||||
return internal::WithArgsAction<InnerAction, k1>(action);
|
||||
}
|
||||
|
||||
template <int k1, int k2, typename InnerAction>
|
||||
inline internal::WithArgsAction<InnerAction, k1, k2>
|
||||
WithArgs(const InnerAction& action) {
|
||||
return internal::WithArgsAction<InnerAction, k1, k2>(action);
|
||||
}
|
||||
|
||||
template <int k1, int k2, int k3, typename InnerAction>
|
||||
inline internal::WithArgsAction<InnerAction, k1, k2, k3>
|
||||
WithArgs(const InnerAction& action) {
|
||||
return internal::WithArgsAction<InnerAction, k1, k2, k3>(action);
|
||||
}
|
||||
|
||||
template <int k1, int k2, int k3, int k4, typename InnerAction>
|
||||
inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4>
|
||||
WithArgs(const InnerAction& action) {
|
||||
return internal::WithArgsAction<InnerAction, k1, k2, k3, k4>(action);
|
||||
}
|
||||
|
||||
template <int k1, int k2, int k3, int k4, int k5, typename InnerAction>
|
||||
inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5>
|
||||
WithArgs(const InnerAction& action) {
|
||||
return internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5>(action);
|
||||
}
|
||||
|
||||
template <int k1, int k2, int k3, int k4, int k5, int k6, typename InnerAction>
|
||||
inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6>
|
||||
WithArgs(const InnerAction& action) {
|
||||
return internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6>(action);
|
||||
}
|
||||
|
||||
template <int k1, int k2, int k3, int k4, int k5, int k6, int k7,
|
||||
typename InnerAction>
|
||||
inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7>
|
||||
WithArgs(const InnerAction& action) {
|
||||
return internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6,
|
||||
k7>(action);
|
||||
}
|
||||
|
||||
template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8,
|
||||
typename InnerAction>
|
||||
inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7, k8>
|
||||
WithArgs(const InnerAction& action) {
|
||||
return internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7,
|
||||
k8>(action);
|
||||
}
|
||||
|
||||
template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8,
|
||||
int k9, typename InnerAction>
|
||||
inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7, k8, k9>
|
||||
WithArgs(const InnerAction& action) {
|
||||
return internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7, k8,
|
||||
k9>(action);
|
||||
}
|
||||
|
||||
template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8,
|
||||
int k9, int k10, typename InnerAction>
|
||||
inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7, k8,
|
||||
k9, k10>
|
||||
WithArgs(const InnerAction& action) {
|
||||
return internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7, k8,
|
||||
k9, k10>(action);
|
||||
}
|
||||
|
||||
// Creates an action that does actions a1, a2, ..., sequentially in
|
||||
// each invocation.
|
||||
template <typename Action1, typename Action2>
|
||||
|
@ -122,97 +122,6 @@ class InvokeCallbackAction {
|
||||
const std::shared_ptr<CallbackType> callback_;
|
||||
};
|
||||
|
||||
// An INTERNAL macro for extracting the type of a tuple field. It's
|
||||
// subject to change without notice - DO NOT USE IN USER CODE!
|
||||
#define GMOCK_FIELD_(Tuple, N) \
|
||||
typename ::std::tuple_element<N, Tuple>::type
|
||||
|
||||
$range i 1..n
|
||||
|
||||
// SelectArgs<Result, ArgumentTuple, k1, k2, ..., k_n>::type is the
|
||||
// type of an n-ary function whose i-th (1-based) argument type is the
|
||||
// k{i}-th (0-based) field of ArgumentTuple, which must be a tuple
|
||||
// type, and whose return type is Result. For example,
|
||||
// SelectArgs<int, ::std::tuple<bool, char, double, long>, 0, 3>::type
|
||||
// is int(bool, long).
|
||||
//
|
||||
// SelectArgs<Result, ArgumentTuple, k1, k2, ..., k_n>::Select(args)
|
||||
// returns the selected fields (k1, k2, ..., k_n) of args as a tuple.
|
||||
// For example,
|
||||
// SelectArgs<int, std::tuple<bool, char, double>, 2, 0>::Select(
|
||||
// ::std::make_tuple(true, 'a', 2.5))
|
||||
// returns tuple (2.5, true).
|
||||
//
|
||||
// The numbers in list k1, k2, ..., k_n must be >= 0, where n can be
|
||||
// in the range [0, $n]. Duplicates are allowed and they don't have
|
||||
// to be in an ascending or descending order.
|
||||
|
||||
template <typename Result, typename ArgumentTuple, $for i, [[int k$i]]>
|
||||
class SelectArgs {
|
||||
public:
|
||||
typedef Result type($for i, [[GMOCK_FIELD_(ArgumentTuple, k$i)]]);
|
||||
typedef typename Function<type>::ArgumentTuple SelectedArgs;
|
||||
static SelectedArgs Select(const ArgumentTuple& args) {
|
||||
return SelectedArgs($for i, [[std::get<k$i>(args)]]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
$for i [[
|
||||
$range j 1..n
|
||||
$range j1 1..i-1
|
||||
template <typename Result, typename ArgumentTuple$for j1[[, int k$j1]]>
|
||||
class SelectArgs<Result, ArgumentTuple,
|
||||
$for j, [[$if j <= i-1 [[k$j]] $else [[-1]]]]> {
|
||||
public:
|
||||
typedef Result type($for j1, [[GMOCK_FIELD_(ArgumentTuple, k$j1)]]);
|
||||
typedef typename Function<type>::ArgumentTuple SelectedArgs;
|
||||
static SelectedArgs Select(const ArgumentTuple& [[]]
|
||||
$if i == 1 [[/* args */]] $else [[args]]) {
|
||||
return SelectedArgs($for j1, [[std::get<k$j1>(args)]]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
]]
|
||||
#undef GMOCK_FIELD_
|
||||
|
||||
$var ks = [[$for i, [[k$i]]]]
|
||||
|
||||
// Implements the WithArgs action.
|
||||
template <typename InnerAction, $for i, [[int k$i = -1]]>
|
||||
class WithArgsAction {
|
||||
public:
|
||||
explicit WithArgsAction(const InnerAction& action) : action_(action) {}
|
||||
|
||||
template <typename F>
|
||||
operator Action<F>() const { return MakeAction(new Impl<F>(action_)); }
|
||||
|
||||
private:
|
||||
template <typename F>
|
||||
class Impl : public ActionInterface<F> {
|
||||
public:
|
||||
typedef typename Function<F>::Result Result;
|
||||
typedef typename Function<F>::ArgumentTuple ArgumentTuple;
|
||||
|
||||
explicit Impl(const InnerAction& action) : action_(action) {}
|
||||
|
||||
virtual Result Perform(const ArgumentTuple& args) {
|
||||
return action_.Perform(SelectArgs<Result, ArgumentTuple, $ks>::Select(args));
|
||||
}
|
||||
|
||||
private:
|
||||
typedef typename SelectArgs<Result, ArgumentTuple,
|
||||
$ks>::type InnerFunctionType;
|
||||
|
||||
Action<InnerFunctionType> action_;
|
||||
};
|
||||
|
||||
const InnerAction action_;
|
||||
|
||||
GTEST_DISALLOW_ASSIGN_(WithArgsAction);
|
||||
};
|
||||
|
||||
// A macro from the ACTION* family (defined later in this file)
|
||||
// defines an action that can be used in a mock function. Typically,
|
||||
// these actions only care about a subset of the arguments of the mock
|
||||
@ -257,25 +166,6 @@ $template
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Various overloads for Invoke().
|
||||
|
||||
// WithArgs<N1, N2, ..., Nk>(an_action) creates an action that passes
|
||||
// the selected arguments of the mock function to an_action and
|
||||
// performs it. It serves as an adaptor between actions with
|
||||
// different argument lists. C++ doesn't support default arguments for
|
||||
// function templates, so we have to overload it.
|
||||
|
||||
$range i 1..n
|
||||
$for i [[
|
||||
$range j 1..i
|
||||
template <$for j [[int k$j, ]]typename InnerAction>
|
||||
inline internal::WithArgsAction<InnerAction$for j [[, k$j]]>
|
||||
WithArgs(const InnerAction& action) {
|
||||
return internal::WithArgsAction<InnerAction$for j [[, k$j]]>(action);
|
||||
}
|
||||
|
||||
|
||||
]]
|
||||
// Creates an action that does actions a1, a2, ..., sequentially in
|
||||
// each invocation.
|
||||
$range i 2..n
|
||||
|
@ -127,27 +127,6 @@ PolymorphicAction<internal::InvokeMethodAction<Class, MethodPtr> > Invoke(
|
||||
internal::InvokeMethodAction<Class, MethodPtr>(obj_ptr, method_ptr));
|
||||
}
|
||||
|
||||
// WithoutArgs(inner_action) can be used in a mock function with a
|
||||
// non-empty argument list to perform inner_action, which takes no
|
||||
// argument. In other words, it adapts an action accepting no
|
||||
// argument to one that accepts (and ignores) arguments.
|
||||
template <typename InnerAction>
|
||||
inline internal::WithArgsAction<InnerAction>
|
||||
WithoutArgs(const InnerAction& action) {
|
||||
return internal::WithArgsAction<InnerAction>(action);
|
||||
}
|
||||
|
||||
// WithArg<k>(an_action) creates an action that passes the k-th
|
||||
// (0-based) argument of the mock function to an_action and performs
|
||||
// it. It adapts an action accepting one argument to one that accepts
|
||||
// multiple arguments. For convenience, we also provide
|
||||
// WithArgs<k>(an_action) (defined below) as a synonym.
|
||||
template <int k, typename InnerAction>
|
||||
inline internal::WithArgsAction<InnerAction, k>
|
||||
WithArg(const InnerAction& action) {
|
||||
return internal::WithArgsAction<InnerAction, k>(action);
|
||||
}
|
||||
|
||||
// The ACTION*() macros trigger warning C4100 (unreferenced formal
|
||||
// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in
|
||||
// the macro definition, as the warnings are generated when the macro
|
||||
|
@ -74,6 +74,7 @@ using testing::ReturnRefOfCopy;
|
||||
using testing::SetArgPointee;
|
||||
using testing::SetArgumentPointee;
|
||||
using testing::Unused;
|
||||
using testing::WithArgs;
|
||||
using testing::_;
|
||||
using testing::internal::BuiltInDefaultValue;
|
||||
using testing::internal::Int64;
|
||||
@ -926,6 +927,21 @@ class VoidNullaryFunctor {
|
||||
void operator()() { g_done = true; }
|
||||
};
|
||||
|
||||
short Short(short n) { return n; } // NOLINT
|
||||
char Char(char ch) { return ch; }
|
||||
|
||||
const char* CharPtr(const char* s) { return s; }
|
||||
|
||||
bool Unary(int x) { return x < 0; }
|
||||
|
||||
const char* Binary(const char* input, short n) { return input + n; } // NOLINT
|
||||
|
||||
void VoidBinary(int, char) { g_done = true; }
|
||||
|
||||
int Ternary(int x, char y, short z) { return x + y + z; } // NOLINT
|
||||
|
||||
int SumOf4(int a, int b, int c, int d) { return a + b + c + d; }
|
||||
|
||||
class Foo {
|
||||
public:
|
||||
Foo() : value_(123) {}
|
||||
@ -1035,6 +1051,108 @@ TEST(AssignTest, CompatibleTypes) {
|
||||
EXPECT_DOUBLE_EQ(5, x);
|
||||
}
|
||||
|
||||
|
||||
// Tests using WithArgs and with an action that takes 1 argument.
|
||||
TEST(WithArgsTest, OneArg) {
|
||||
Action<bool(double x, int n)> a = WithArgs<1>(Invoke(Unary)); // NOLINT
|
||||
EXPECT_TRUE(a.Perform(std::make_tuple(1.5, -1)));
|
||||
EXPECT_FALSE(a.Perform(std::make_tuple(1.5, 1)));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with an action that takes 2 arguments.
|
||||
TEST(WithArgsTest, TwoArgs) {
|
||||
Action<const char*(const char* s, double x, short n)> a = // NOLINT
|
||||
WithArgs<0, 2>(Invoke(Binary));
|
||||
const char s[] = "Hello";
|
||||
EXPECT_EQ(s + 2, a.Perform(std::make_tuple(CharPtr(s), 0.5, Short(2))));
|
||||
}
|
||||
|
||||
struct ConcatAll {
|
||||
std::string operator()() const { return {}; }
|
||||
template <typename... I>
|
||||
std::string operator()(const char* a, I... i) const {
|
||||
return a + ConcatAll()(i...);
|
||||
}
|
||||
};
|
||||
|
||||
// Tests using WithArgs with an action that takes 10 arguments.
|
||||
TEST(WithArgsTest, TenArgs) {
|
||||
Action<std::string(const char*, const char*, const char*, const char*)> a =
|
||||
WithArgs<0, 1, 2, 3, 2, 1, 0, 1, 2, 3>(Invoke(ConcatAll{}));
|
||||
EXPECT_EQ("0123210123",
|
||||
a.Perform(std::make_tuple(CharPtr("0"), CharPtr("1"), CharPtr("2"),
|
||||
CharPtr("3"))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with an action that is not Invoke().
|
||||
class SubtractAction : public ActionInterface<int(int, int)> {
|
||||
public:
|
||||
virtual int Perform(const std::tuple<int, int>& args) {
|
||||
return std::get<0>(args) - std::get<1>(args);
|
||||
}
|
||||
};
|
||||
|
||||
TEST(WithArgsTest, NonInvokeAction) {
|
||||
Action<int(const std::string&, int, int)> a =
|
||||
WithArgs<2, 1>(MakeAction(new SubtractAction));
|
||||
std::tuple<std::string, int, int> dummy =
|
||||
std::make_tuple(std::string("hi"), 2, 10);
|
||||
EXPECT_EQ(8, a.Perform(dummy));
|
||||
}
|
||||
|
||||
// Tests using WithArgs to pass all original arguments in the original order.
|
||||
TEST(WithArgsTest, Identity) {
|
||||
Action<int(int x, char y, short z)> a = // NOLINT
|
||||
WithArgs<0, 1, 2>(Invoke(Ternary));
|
||||
EXPECT_EQ(123, a.Perform(std::make_tuple(100, Char(20), Short(3))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with repeated arguments.
|
||||
TEST(WithArgsTest, RepeatedArguments) {
|
||||
Action<int(bool, int m, int n)> a = // NOLINT
|
||||
WithArgs<1, 1, 1, 1>(Invoke(SumOf4));
|
||||
EXPECT_EQ(4, a.Perform(std::make_tuple(false, 1, 10)));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with reversed argument order.
|
||||
TEST(WithArgsTest, ReversedArgumentOrder) {
|
||||
Action<const char*(short n, const char* input)> a = // NOLINT
|
||||
WithArgs<1, 0>(Invoke(Binary));
|
||||
const char s[] = "Hello";
|
||||
EXPECT_EQ(s + 2, a.Perform(std::make_tuple(Short(2), CharPtr(s))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with compatible, but not identical, argument types.
|
||||
TEST(WithArgsTest, ArgsOfCompatibleTypes) {
|
||||
Action<long(short x, char y, double z, char c)> a = // NOLINT
|
||||
WithArgs<0, 1, 3>(Invoke(Ternary));
|
||||
EXPECT_EQ(123,
|
||||
a.Perform(std::make_tuple(Short(100), Char(20), 5.6, Char(3))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with an action that returns void.
|
||||
TEST(WithArgsTest, VoidAction) {
|
||||
Action<void(double x, char c, int n)> a = WithArgs<2, 1>(Invoke(VoidBinary));
|
||||
g_done = false;
|
||||
a.Perform(std::make_tuple(1.5, 'a', 3));
|
||||
EXPECT_TRUE(g_done);
|
||||
}
|
||||
|
||||
TEST(WithArgsTest, ReturnReference) {
|
||||
Action<int&(int&, void*)> a = WithArgs<0>([](int& a) -> int& { return a; });
|
||||
int i = 0;
|
||||
const int& res = a.Perform(std::forward_as_tuple(i, nullptr));
|
||||
EXPECT_EQ(&i, &res);
|
||||
}
|
||||
|
||||
TEST(WithArgsTest, InnerActionWithConversion) {
|
||||
struct Base {};
|
||||
struct Derived : Base {};
|
||||
Action<Derived*()> inner = [] { return nullptr; };
|
||||
Action<Base*(double)> a = testing::WithoutArgs(inner);
|
||||
EXPECT_EQ(nullptr, a.Perform(std::make_tuple(1.1)));
|
||||
}
|
||||
|
||||
#if !GTEST_OS_WINDOWS_MOBILE
|
||||
|
||||
class SetErrnoAndReturnTest : public testing::Test {
|
||||
|
@ -57,7 +57,6 @@ using testing::ReturnNew;
|
||||
using testing::SetArgPointee;
|
||||
using testing::StaticAssertTypeEq;
|
||||
using testing::Unused;
|
||||
using testing::WithArgs;
|
||||
|
||||
// For suppressing compiler warnings on conversion possibly losing precision.
|
||||
inline short Short(short n) { return n; } // NOLINT
|
||||
@ -66,43 +65,19 @@ inline char Char(char ch) { return ch; }
|
||||
// Sample functions and functors for testing various actions.
|
||||
int Nullary() { return 1; }
|
||||
|
||||
class NullaryFunctor {
|
||||
public:
|
||||
int operator()() { return 2; }
|
||||
};
|
||||
|
||||
bool g_done = false;
|
||||
|
||||
bool Unary(int x) { return x < 0; }
|
||||
|
||||
const char* Plus1(const char* s) { return s + 1; }
|
||||
|
||||
bool ByConstRef(const std::string& s) { return s == "Hi"; }
|
||||
|
||||
const double g_double = 0;
|
||||
bool ReferencesGlobalDouble(const double& x) { return &x == &g_double; }
|
||||
|
||||
std::string ByNonConstRef(std::string& s) { return s += "+"; } // NOLINT
|
||||
|
||||
struct UnaryFunctor {
|
||||
int operator()(bool x) { return x ? 1 : -1; }
|
||||
};
|
||||
|
||||
const char* Binary(const char* input, short n) { return input + n; } // NOLINT
|
||||
|
||||
void VoidBinary(int, char) { g_done = true; }
|
||||
|
||||
int Ternary(int x, char y, short z) { return x + y + z; } // NOLINT
|
||||
|
||||
void VoidTernary(int, char, bool) { g_done = true; }
|
||||
|
||||
int SumOf4(int a, int b, int c, int d) { return a + b + c + d; }
|
||||
|
||||
std::string Concat4(const char* s1, const char* s2, const char* s3,
|
||||
const char* s4) {
|
||||
return std::string(s1) + s2 + s3 + s4;
|
||||
}
|
||||
|
||||
int SumOf5(int a, int b, int c, int d, int e) { return a + b + c + d + e; }
|
||||
|
||||
struct SumOf5Functor {
|
||||
@ -276,143 +251,6 @@ TEST(InvokeArgumentTest, ByExplicitConstReferenceFunction) {
|
||||
EXPECT_FALSE(a.Perform(std::make_tuple(&ReferencesGlobalDouble)));
|
||||
}
|
||||
|
||||
// Tests using WithArgs and with an action that takes 1 argument.
|
||||
TEST(WithArgsTest, OneArg) {
|
||||
Action<bool(double x, int n)> a = WithArgs<1>(Invoke(Unary)); // NOLINT
|
||||
EXPECT_TRUE(a.Perform(std::make_tuple(1.5, -1)));
|
||||
EXPECT_FALSE(a.Perform(std::make_tuple(1.5, 1)));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with an action that takes 2 arguments.
|
||||
TEST(WithArgsTest, TwoArgs) {
|
||||
Action<const char*(const char* s, double x, short n)> a =
|
||||
WithArgs<0, 2>(Invoke(Binary));
|
||||
const char s[] = "Hello";
|
||||
EXPECT_EQ(s + 2, a.Perform(std::make_tuple(CharPtr(s), 0.5, Short(2))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with an action that takes 3 arguments.
|
||||
TEST(WithArgsTest, ThreeArgs) {
|
||||
Action<int(int, double, char, short)> a = // NOLINT
|
||||
WithArgs<0, 2, 3>(Invoke(Ternary));
|
||||
EXPECT_EQ(123, a.Perform(std::make_tuple(100, 6.5, Char(20), Short(3))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with an action that takes 4 arguments.
|
||||
TEST(WithArgsTest, FourArgs) {
|
||||
Action<std::string(const char*, const char*, double, const char*,
|
||||
const char*)>
|
||||
a = WithArgs<4, 3, 1, 0>(Invoke(Concat4));
|
||||
EXPECT_EQ("4310", a.Perform(std::make_tuple(CharPtr("0"), CharPtr("1"), 2.5,
|
||||
CharPtr("3"), CharPtr("4"))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with an action that takes 5 arguments.
|
||||
TEST(WithArgsTest, FiveArgs) {
|
||||
Action<std::string(const char*, const char*, const char*, const char*,
|
||||
const char*)>
|
||||
a = WithArgs<4, 3, 2, 1, 0>(Invoke(Concat5));
|
||||
EXPECT_EQ("43210",
|
||||
a.Perform(std::make_tuple(CharPtr("0"), CharPtr("1"), CharPtr("2"),
|
||||
CharPtr("3"), CharPtr("4"))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with an action that takes 6 arguments.
|
||||
TEST(WithArgsTest, SixArgs) {
|
||||
Action<std::string(const char*, const char*, const char*)> a =
|
||||
WithArgs<0, 1, 2, 2, 1, 0>(Invoke(Concat6));
|
||||
EXPECT_EQ("012210", a.Perform(std::make_tuple(CharPtr("0"), CharPtr("1"),
|
||||
CharPtr("2"))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with an action that takes 7 arguments.
|
||||
TEST(WithArgsTest, SevenArgs) {
|
||||
Action<std::string(const char*, const char*, const char*, const char*)> a =
|
||||
WithArgs<0, 1, 2, 3, 2, 1, 0>(Invoke(Concat7));
|
||||
EXPECT_EQ("0123210", a.Perform(std::make_tuple(CharPtr("0"), CharPtr("1"),
|
||||
CharPtr("2"), CharPtr("3"))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with an action that takes 8 arguments.
|
||||
TEST(WithArgsTest, EightArgs) {
|
||||
Action<std::string(const char*, const char*, const char*, const char*)> a =
|
||||
WithArgs<0, 1, 2, 3, 0, 1, 2, 3>(Invoke(Concat8));
|
||||
EXPECT_EQ("01230123", a.Perform(std::make_tuple(CharPtr("0"), CharPtr("1"),
|
||||
CharPtr("2"), CharPtr("3"))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with an action that takes 9 arguments.
|
||||
TEST(WithArgsTest, NineArgs) {
|
||||
Action<std::string(const char*, const char*, const char*, const char*)> a =
|
||||
WithArgs<0, 1, 2, 3, 1, 2, 3, 2, 3>(Invoke(Concat9));
|
||||
EXPECT_EQ("012312323",
|
||||
a.Perform(std::make_tuple(CharPtr("0"), CharPtr("1"), CharPtr("2"),
|
||||
CharPtr("3"))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with an action that takes 10 arguments.
|
||||
TEST(WithArgsTest, TenArgs) {
|
||||
Action<std::string(const char*, const char*, const char*, const char*)> a =
|
||||
WithArgs<0, 1, 2, 3, 2, 1, 0, 1, 2, 3>(Invoke(Concat10));
|
||||
EXPECT_EQ("0123210123",
|
||||
a.Perform(std::make_tuple(CharPtr("0"), CharPtr("1"), CharPtr("2"),
|
||||
CharPtr("3"))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with an action that is not Invoke().
|
||||
class SubstractAction : public ActionInterface<int(int, int)> { // NOLINT
|
||||
public:
|
||||
virtual int Perform(const std::tuple<int, int>& args) {
|
||||
return std::get<0>(args) - std::get<1>(args);
|
||||
}
|
||||
};
|
||||
|
||||
TEST(WithArgsTest, NonInvokeAction) {
|
||||
Action<int(const std::string&, int, int)> a = // NOLINT
|
||||
WithArgs<2, 1>(MakeAction(new SubstractAction));
|
||||
std::tuple<std::string, int, int> dummy =
|
||||
std::make_tuple(std::string("hi"), 2, 10);
|
||||
EXPECT_EQ(8, a.Perform(dummy));
|
||||
}
|
||||
|
||||
// Tests using WithArgs to pass all original arguments in the original order.
|
||||
TEST(WithArgsTest, Identity) {
|
||||
Action<int(int x, char y, short z)> a = // NOLINT
|
||||
WithArgs<0, 1, 2>(Invoke(Ternary));
|
||||
EXPECT_EQ(123, a.Perform(std::make_tuple(100, Char(20), Short(3))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with repeated arguments.
|
||||
TEST(WithArgsTest, RepeatedArguments) {
|
||||
Action<int(bool, int m, int n)> a = // NOLINT
|
||||
WithArgs<1, 1, 1, 1>(Invoke(SumOf4));
|
||||
EXPECT_EQ(4, a.Perform(std::make_tuple(false, 1, 10)));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with reversed argument order.
|
||||
TEST(WithArgsTest, ReversedArgumentOrder) {
|
||||
Action<const char*(short n, const char* input)> a = // NOLINT
|
||||
WithArgs<1, 0>(Invoke(Binary));
|
||||
const char s[] = "Hello";
|
||||
EXPECT_EQ(s + 2, a.Perform(std::make_tuple(Short(2), CharPtr(s))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with compatible, but not identical, argument types.
|
||||
TEST(WithArgsTest, ArgsOfCompatibleTypes) {
|
||||
Action<long(short x, char y, double z, char c)> a = // NOLINT
|
||||
WithArgs<0, 1, 3>(Invoke(Ternary));
|
||||
EXPECT_EQ(123,
|
||||
a.Perform(std::make_tuple(Short(100), Char(20), 5.6, Char(3))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with an action that returns void.
|
||||
TEST(WithArgsTest, VoidAction) {
|
||||
Action<void(double x, char c, int n)> a = WithArgs<2, 1>(Invoke(VoidBinary));
|
||||
g_done = false;
|
||||
a.Perform(std::make_tuple(1.5, 'a', 3));
|
||||
EXPECT_TRUE(g_done);
|
||||
}
|
||||
|
||||
// Tests DoAll(a1, a2).
|
||||
TEST(DoAllTest, TwoActions) {
|
||||
int n = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user