diff --git a/googlemock/include/gmock/gmock-actions.h b/googlemock/include/gmock/gmock-actions.h index e4af9d2d..37d0d53d 100644 --- a/googlemock/include/gmock/gmock-actions.h +++ b/googlemock/include/gmock/gmock-actions.h @@ -1061,6 +1061,24 @@ class DoBothAction { GTEST_DISALLOW_ASSIGN_(DoBothAction); }; +template +struct WithArgsAction { + InnerAction action; + + // The inner action could be anything convertible to Action. + // We use the conversion operator to detect the signature of the inner Action. + template + operator Action() const { // NOLINT + Action>::type...)> + converted(action); + + return [converted](Args... args) -> R { + return converted.Perform(std::forward_as_tuple( + std::get(std::forward_as_tuple(std::forward(args)...))...)); + }; + } +}; + } // namespace internal // An Unused object can be implicitly constructed from ANY value. @@ -1111,6 +1129,37 @@ Action::Action(const Action& from) : new internal::ActionAdaptor(from)) { } +// WithArg(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(an_action) (defined below) as a synonym. +template +internal::WithArgsAction::type, k> +WithArg(InnerAction&& action) { + return {std::forward(action)}; +} + +// WithArgs(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 +internal::WithArgsAction::type, k, ks...> +WithArgs(InnerAction&& action) { + return {std::forward(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 +internal::WithArgsAction::type> +WithoutArgs(InnerAction&& action) { + return {std::forward(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. diff --git a/googlemock/include/gmock/gmock-generated-actions.h b/googlemock/include/gmock/gmock-generated-actions.h index 8966f05c..fac491b7 100644 --- a/googlemock/include/gmock/gmock-generated-actions.h +++ b/googlemock/include/gmock/gmock-generated-actions.h @@ -352,235 +352,6 @@ class InvokeCallbackAction { const std::shared_ptr 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::type - -// SelectArgs::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, 0, 3>::type -// is int(bool, long). -// -// SelectArgs::Select(args) -// returns the selected fields (k1, k2, ..., k_n) of args as a tuple. -// For example, -// SelectArgs, 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 -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::ArgumentTuple SelectedArgs; - static SelectedArgs Select(const ArgumentTuple& args) { - return SelectedArgs(std::get(args), std::get(args), - std::get(args), std::get(args), std::get(args), - std::get(args), std::get(args), std::get(args), - std::get(args), std::get(args)); - } -}; - -template -class SelectArgs { - public: - typedef Result type(); - typedef typename Function::ArgumentTuple SelectedArgs; - static SelectedArgs Select(const ArgumentTuple& /* args */) { - return SelectedArgs(); - } -}; - -template -class SelectArgs { - public: - typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1)); - typedef typename Function::ArgumentTuple SelectedArgs; - static SelectedArgs Select(const ArgumentTuple& args) { - return SelectedArgs(std::get(args)); - } -}; - -template -class SelectArgs { - public: - typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1), - GMOCK_FIELD_(ArgumentTuple, k2)); - typedef typename Function::ArgumentTuple SelectedArgs; - static SelectedArgs Select(const ArgumentTuple& args) { - return SelectedArgs(std::get(args), std::get(args)); - } -}; - -template -class SelectArgs { - public: - typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1), - GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3)); - typedef typename Function::ArgumentTuple SelectedArgs; - static SelectedArgs Select(const ArgumentTuple& args) { - return SelectedArgs(std::get(args), std::get(args), - std::get(args)); - } -}; - -template -class SelectArgs { - public: - typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1), - GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3), - GMOCK_FIELD_(ArgumentTuple, k4)); - typedef typename Function::ArgumentTuple SelectedArgs; - static SelectedArgs Select(const ArgumentTuple& args) { - return SelectedArgs(std::get(args), std::get(args), - std::get(args), std::get(args)); - } -}; - -template -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)); - typedef typename Function::ArgumentTuple SelectedArgs; - static SelectedArgs Select(const ArgumentTuple& args) { - return SelectedArgs(std::get(args), std::get(args), - std::get(args), std::get(args), std::get(args)); - } -}; - -template -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)); - typedef typename Function::ArgumentTuple SelectedArgs; - static SelectedArgs Select(const ArgumentTuple& args) { - return SelectedArgs(std::get(args), std::get(args), - std::get(args), std::get(args), std::get(args), - std::get(args)); - } -}; - -template -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)); - typedef typename Function::ArgumentTuple SelectedArgs; - static SelectedArgs Select(const ArgumentTuple& args) { - return SelectedArgs(std::get(args), std::get(args), - std::get(args), std::get(args), std::get(args), - std::get(args), std::get(args)); - } -}; - -template -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)); - typedef typename Function::ArgumentTuple SelectedArgs; - static SelectedArgs Select(const ArgumentTuple& args) { - return SelectedArgs(std::get(args), std::get(args), - std::get(args), std::get(args), std::get(args), - std::get(args), std::get(args), std::get(args)); - } -}; - -template -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)); - typedef typename Function::ArgumentTuple SelectedArgs; - static SelectedArgs Select(const ArgumentTuple& args) { - return SelectedArgs(std::get(args), std::get(args), - std::get(args), std::get(args), std::get(args), - std::get(args), std::get(args), std::get(args), - std::get(args)); - } -}; - -#undef GMOCK_FIELD_ - -// Implements the WithArgs action. -template -class WithArgsAction { - public: - explicit WithArgsAction(const InnerAction& action) : action_(action) {} - - template - operator Action() const { return MakeAction(new Impl(action_)); } - - private: - template - class Impl : public ActionInterface { - public: - typedef typename Function::Result Result; - typedef typename Function::ArgumentTuple ArgumentTuple; - - explicit Impl(const InnerAction& action) : action_(action) {} - - virtual Result Perform(const ArgumentTuple& args) { - return action_.Perform(SelectArgs::Select(args)); - } - - private: - typedef typename SelectArgs::type InnerFunctionType; - - Action 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(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 -inline internal::WithArgsAction -WithArgs(const InnerAction& action) { - return internal::WithArgsAction(action); -} - -template -inline internal::WithArgsAction -WithArgs(const InnerAction& action) { - return internal::WithArgsAction(action); -} - -template -inline internal::WithArgsAction -WithArgs(const InnerAction& action) { - return internal::WithArgsAction(action); -} - -template -inline internal::WithArgsAction -WithArgs(const InnerAction& action) { - return internal::WithArgsAction(action); -} - -template -inline internal::WithArgsAction -WithArgs(const InnerAction& action) { - return internal::WithArgsAction(action); -} - -template -inline internal::WithArgsAction -WithArgs(const InnerAction& action) { - return internal::WithArgsAction(action); -} - -template -inline internal::WithArgsAction -WithArgs(const InnerAction& action) { - return internal::WithArgsAction(action); -} - -template -inline internal::WithArgsAction -WithArgs(const InnerAction& action) { - return internal::WithArgsAction(action); -} - -template -inline internal::WithArgsAction -WithArgs(const InnerAction& action) { - return internal::WithArgsAction(action); -} - -template -inline internal::WithArgsAction -WithArgs(const InnerAction& action) { - return internal::WithArgsAction(action); -} - // Creates an action that does actions a1, a2, ..., sequentially in // each invocation. template diff --git a/googlemock/include/gmock/gmock-generated-actions.h.pump b/googlemock/include/gmock/gmock-generated-actions.h.pump index 09a39ca8..d38b1f92 100644 --- a/googlemock/include/gmock/gmock-generated-actions.h.pump +++ b/googlemock/include/gmock/gmock-generated-actions.h.pump @@ -122,97 +122,6 @@ class InvokeCallbackAction { const std::shared_ptr 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::type - -$range i 1..n - -// SelectArgs::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, 0, 3>::type -// is int(bool, long). -// -// SelectArgs::Select(args) -// returns the selected fields (k1, k2, ..., k_n) of args as a tuple. -// For example, -// SelectArgs, 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 -class SelectArgs { - public: - typedef Result type($for i, [[GMOCK_FIELD_(ArgumentTuple, k$i)]]); - typedef typename Function::ArgumentTuple SelectedArgs; - static SelectedArgs Select(const ArgumentTuple& args) { - return SelectedArgs($for i, [[std::get(args)]]); - } -}; - - -$for i [[ -$range j 1..n -$range j1 1..i-1 -template -class SelectArgs { - public: - typedef Result type($for j1, [[GMOCK_FIELD_(ArgumentTuple, k$j1)]]); - typedef typename Function::ArgumentTuple SelectedArgs; - static SelectedArgs Select(const ArgumentTuple& [[]] -$if i == 1 [[/* args */]] $else [[args]]) { - return SelectedArgs($for j1, [[std::get(args)]]); - } -}; - - -]] -#undef GMOCK_FIELD_ - -$var ks = [[$for i, [[k$i]]]] - -// Implements the WithArgs action. -template -class WithArgsAction { - public: - explicit WithArgsAction(const InnerAction& action) : action_(action) {} - - template - operator Action() const { return MakeAction(new Impl(action_)); } - - private: - template - class Impl : public ActionInterface { - public: - typedef typename Function::Result Result; - typedef typename Function::ArgumentTuple ArgumentTuple; - - explicit Impl(const InnerAction& action) : action_(action) {} - - virtual Result Perform(const ArgumentTuple& args) { - return action_.Perform(SelectArgs::Select(args)); - } - - private: - typedef typename SelectArgs::type InnerFunctionType; - - Action 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(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 -WithArgs(const InnerAction& action) { - return internal::WithArgsAction(action); -} - - -]] // Creates an action that does actions a1, a2, ..., sequentially in // each invocation. $range i 2..n diff --git a/googlemock/include/gmock/gmock-more-actions.h b/googlemock/include/gmock/gmock-more-actions.h index 5c6dc8bb..10984081 100644 --- a/googlemock/include/gmock/gmock-more-actions.h +++ b/googlemock/include/gmock/gmock-more-actions.h @@ -127,27 +127,6 @@ PolymorphicAction > Invoke( internal::InvokeMethodAction(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 -inline internal::WithArgsAction -WithoutArgs(const InnerAction& action) { - return internal::WithArgsAction(action); -} - -// WithArg(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(an_action) (defined below) as a synonym. -template -inline internal::WithArgsAction -WithArg(const InnerAction& action) { - return internal::WithArgsAction(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 diff --git a/googlemock/test/gmock-actions_test.cc b/googlemock/test/gmock-actions_test.cc index 5b9f3dd6..976f56d7 100644 --- a/googlemock/test/gmock-actions_test.cc +++ b/googlemock/test/gmock-actions_test.cc @@ -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 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 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 + 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 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 { + public: + virtual int Perform(const std::tuple& args) { + return std::get<0>(args) - std::get<1>(args); + } +}; + +TEST(WithArgsTest, NonInvokeAction) { + Action a = + WithArgs<2, 1>(MakeAction(new SubtractAction)); + std::tuple 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 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 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 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 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 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 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 inner = [] { return nullptr; }; + Action a = testing::WithoutArgs(inner); + EXPECT_EQ(nullptr, a.Perform(std::make_tuple(1.1))); +} + #if !GTEST_OS_WINDOWS_MOBILE class SetErrnoAndReturnTest : public testing::Test { diff --git a/googlemock/test/gmock-generated-actions_test.cc b/googlemock/test/gmock-generated-actions_test.cc index 3111d859..0fe43ab3 100644 --- a/googlemock/test/gmock-generated-actions_test.cc +++ b/googlemock/test/gmock-generated-actions_test.cc @@ -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 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 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 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 - 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 - 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 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 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 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 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 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 { // NOLINT - public: - virtual int Perform(const std::tuple& args) { - return std::get<0>(args) - std::get<1>(args); - } -}; - -TEST(WithArgsTest, NonInvokeAction) { - Action a = // NOLINT - WithArgs<2, 1>(MakeAction(new SubstractAction)); - std::tuple 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 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 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 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 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 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;