113481Sgiacomo.travaglini@arm.com// Copyright 2007, Google Inc.
213481Sgiacomo.travaglini@arm.com// All rights reserved.
313481Sgiacomo.travaglini@arm.com//
413481Sgiacomo.travaglini@arm.com// Redistribution and use in source and binary forms, with or without
513481Sgiacomo.travaglini@arm.com// modification, are permitted provided that the following conditions are
613481Sgiacomo.travaglini@arm.com// met:
713481Sgiacomo.travaglini@arm.com//
813481Sgiacomo.travaglini@arm.com//     * Redistributions of source code must retain the above copyright
913481Sgiacomo.travaglini@arm.com// notice, this list of conditions and the following disclaimer.
1013481Sgiacomo.travaglini@arm.com//     * Redistributions in binary form must reproduce the above
1113481Sgiacomo.travaglini@arm.com// copyright notice, this list of conditions and the following disclaimer
1213481Sgiacomo.travaglini@arm.com// in the documentation and/or other materials provided with the
1313481Sgiacomo.travaglini@arm.com// distribution.
1413481Sgiacomo.travaglini@arm.com//     * Neither the name of Google Inc. nor the names of its
1513481Sgiacomo.travaglini@arm.com// contributors may be used to endorse or promote products derived from
1613481Sgiacomo.travaglini@arm.com// this software without specific prior written permission.
1713481Sgiacomo.travaglini@arm.com//
1813481Sgiacomo.travaglini@arm.com// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1913481Sgiacomo.travaglini@arm.com// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2013481Sgiacomo.travaglini@arm.com// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2113481Sgiacomo.travaglini@arm.com// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2213481Sgiacomo.travaglini@arm.com// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2313481Sgiacomo.travaglini@arm.com// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2413481Sgiacomo.travaglini@arm.com// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2513481Sgiacomo.travaglini@arm.com// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2613481Sgiacomo.travaglini@arm.com// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2713481Sgiacomo.travaglini@arm.com// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2813481Sgiacomo.travaglini@arm.com// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2913481Sgiacomo.travaglini@arm.com//
3013481Sgiacomo.travaglini@arm.com// Author: wan@google.com (Zhanyong Wan)
3113481Sgiacomo.travaglini@arm.com
3213481Sgiacomo.travaglini@arm.com// Google Mock - a framework for writing C++ mock classes.
3313481Sgiacomo.travaglini@arm.com//
3413481Sgiacomo.travaglini@arm.com// This file implements some actions that depend on gmock-generated-actions.h.
3513481Sgiacomo.travaglini@arm.com
3613481Sgiacomo.travaglini@arm.com#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
3713481Sgiacomo.travaglini@arm.com#define GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
3813481Sgiacomo.travaglini@arm.com
3913481Sgiacomo.travaglini@arm.com#include <algorithm>
4013481Sgiacomo.travaglini@arm.com
4113481Sgiacomo.travaglini@arm.com#include "gmock/gmock-generated-actions.h"
4213481Sgiacomo.travaglini@arm.com
4313481Sgiacomo.travaglini@arm.comnamespace testing {
4413481Sgiacomo.travaglini@arm.comnamespace internal {
4513481Sgiacomo.travaglini@arm.com
4613481Sgiacomo.travaglini@arm.com// Implements the Invoke(f) action.  The template argument
4713481Sgiacomo.travaglini@arm.com// FunctionImpl is the implementation type of f, which can be either a
4813481Sgiacomo.travaglini@arm.com// function pointer or a functor.  Invoke(f) can be used as an
4913481Sgiacomo.travaglini@arm.com// Action<F> as long as f's type is compatible with F (i.e. f can be
5013481Sgiacomo.travaglini@arm.com// assigned to a tr1::function<F>).
5113481Sgiacomo.travaglini@arm.comtemplate <typename FunctionImpl>
5213481Sgiacomo.travaglini@arm.comclass InvokeAction {
5313481Sgiacomo.travaglini@arm.com public:
5413481Sgiacomo.travaglini@arm.com  // The c'tor makes a copy of function_impl (either a function
5513481Sgiacomo.travaglini@arm.com  // pointer or a functor).
5613481Sgiacomo.travaglini@arm.com  explicit InvokeAction(FunctionImpl function_impl)
5713481Sgiacomo.travaglini@arm.com      : function_impl_(function_impl) {}
5813481Sgiacomo.travaglini@arm.com
5913481Sgiacomo.travaglini@arm.com  template <typename Result, typename ArgumentTuple>
6013481Sgiacomo.travaglini@arm.com  Result Perform(const ArgumentTuple& args) {
6113481Sgiacomo.travaglini@arm.com    return InvokeHelper<Result, ArgumentTuple>::Invoke(function_impl_, args);
6213481Sgiacomo.travaglini@arm.com  }
6313481Sgiacomo.travaglini@arm.com
6413481Sgiacomo.travaglini@arm.com private:
6513481Sgiacomo.travaglini@arm.com  FunctionImpl function_impl_;
6613481Sgiacomo.travaglini@arm.com
6713481Sgiacomo.travaglini@arm.com  GTEST_DISALLOW_ASSIGN_(InvokeAction);
6813481Sgiacomo.travaglini@arm.com};
6913481Sgiacomo.travaglini@arm.com
7013481Sgiacomo.travaglini@arm.com// Implements the Invoke(object_ptr, &Class::Method) action.
7113481Sgiacomo.travaglini@arm.comtemplate <class Class, typename MethodPtr>
7213481Sgiacomo.travaglini@arm.comclass InvokeMethodAction {
7313481Sgiacomo.travaglini@arm.com public:
7413481Sgiacomo.travaglini@arm.com  InvokeMethodAction(Class* obj_ptr, MethodPtr method_ptr)
7513481Sgiacomo.travaglini@arm.com      : method_ptr_(method_ptr), obj_ptr_(obj_ptr) {}
7613481Sgiacomo.travaglini@arm.com
7713481Sgiacomo.travaglini@arm.com  template <typename Result, typename ArgumentTuple>
7813481Sgiacomo.travaglini@arm.com  Result Perform(const ArgumentTuple& args) const {
7913481Sgiacomo.travaglini@arm.com    return InvokeHelper<Result, ArgumentTuple>::InvokeMethod(
8013481Sgiacomo.travaglini@arm.com        obj_ptr_, method_ptr_, args);
8113481Sgiacomo.travaglini@arm.com  }
8213481Sgiacomo.travaglini@arm.com
8313481Sgiacomo.travaglini@arm.com private:
8413481Sgiacomo.travaglini@arm.com  // The order of these members matters.  Reversing the order can trigger
8513481Sgiacomo.travaglini@arm.com  // warning C4121 in MSVC (see
8613481Sgiacomo.travaglini@arm.com  // http://computer-programming-forum.com/7-vc.net/6fbc30265f860ad1.htm ).
8713481Sgiacomo.travaglini@arm.com  const MethodPtr method_ptr_;
8813481Sgiacomo.travaglini@arm.com  Class* const obj_ptr_;
8913481Sgiacomo.travaglini@arm.com
9013481Sgiacomo.travaglini@arm.com  GTEST_DISALLOW_ASSIGN_(InvokeMethodAction);
9113481Sgiacomo.travaglini@arm.com};
9213481Sgiacomo.travaglini@arm.com
9313481Sgiacomo.travaglini@arm.com// An internal replacement for std::copy which mimics its behavior. This is
9413481Sgiacomo.travaglini@arm.com// necessary because Visual Studio deprecates ::std::copy, issuing warning 4996.
9513481Sgiacomo.travaglini@arm.com// However Visual Studio 2010 and later do not honor #pragmas which disable that
9613481Sgiacomo.travaglini@arm.com// warning.
9713481Sgiacomo.travaglini@arm.comtemplate<typename InputIterator, typename OutputIterator>
9813481Sgiacomo.travaglini@arm.cominline OutputIterator CopyElements(InputIterator first,
9913481Sgiacomo.travaglini@arm.com                                   InputIterator last,
10013481Sgiacomo.travaglini@arm.com                                   OutputIterator output) {
10113481Sgiacomo.travaglini@arm.com  for (; first != last; ++first, ++output) {
10213481Sgiacomo.travaglini@arm.com    *output = *first;
10313481Sgiacomo.travaglini@arm.com  }
10413481Sgiacomo.travaglini@arm.com  return output;
10513481Sgiacomo.travaglini@arm.com}
10613481Sgiacomo.travaglini@arm.com
10713481Sgiacomo.travaglini@arm.com}  // namespace internal
10813481Sgiacomo.travaglini@arm.com
10913481Sgiacomo.travaglini@arm.com// Various overloads for Invoke().
11013481Sgiacomo.travaglini@arm.com
11113481Sgiacomo.travaglini@arm.com// Creates an action that invokes 'function_impl' with the mock
11213481Sgiacomo.travaglini@arm.com// function's arguments.
11313481Sgiacomo.travaglini@arm.comtemplate <typename FunctionImpl>
11413481Sgiacomo.travaglini@arm.comPolymorphicAction<internal::InvokeAction<FunctionImpl> > Invoke(
11513481Sgiacomo.travaglini@arm.com    FunctionImpl function_impl) {
11613481Sgiacomo.travaglini@arm.com  return MakePolymorphicAction(
11713481Sgiacomo.travaglini@arm.com      internal::InvokeAction<FunctionImpl>(function_impl));
11813481Sgiacomo.travaglini@arm.com}
11913481Sgiacomo.travaglini@arm.com
12013481Sgiacomo.travaglini@arm.com// Creates an action that invokes the given method on the given object
12113481Sgiacomo.travaglini@arm.com// with the mock function's arguments.
12213481Sgiacomo.travaglini@arm.comtemplate <class Class, typename MethodPtr>
12313481Sgiacomo.travaglini@arm.comPolymorphicAction<internal::InvokeMethodAction<Class, MethodPtr> > Invoke(
12413481Sgiacomo.travaglini@arm.com    Class* obj_ptr, MethodPtr method_ptr) {
12513481Sgiacomo.travaglini@arm.com  return MakePolymorphicAction(
12613481Sgiacomo.travaglini@arm.com      internal::InvokeMethodAction<Class, MethodPtr>(obj_ptr, method_ptr));
12713481Sgiacomo.travaglini@arm.com}
12813481Sgiacomo.travaglini@arm.com
12913481Sgiacomo.travaglini@arm.com// WithoutArgs(inner_action) can be used in a mock function with a
13013481Sgiacomo.travaglini@arm.com// non-empty argument list to perform inner_action, which takes no
13113481Sgiacomo.travaglini@arm.com// argument.  In other words, it adapts an action accepting no
13213481Sgiacomo.travaglini@arm.com// argument to one that accepts (and ignores) arguments.
13313481Sgiacomo.travaglini@arm.comtemplate <typename InnerAction>
13413481Sgiacomo.travaglini@arm.cominline internal::WithArgsAction<InnerAction>
13513481Sgiacomo.travaglini@arm.comWithoutArgs(const InnerAction& action) {
13613481Sgiacomo.travaglini@arm.com  return internal::WithArgsAction<InnerAction>(action);
13713481Sgiacomo.travaglini@arm.com}
13813481Sgiacomo.travaglini@arm.com
13913481Sgiacomo.travaglini@arm.com// WithArg<k>(an_action) creates an action that passes the k-th
14013481Sgiacomo.travaglini@arm.com// (0-based) argument of the mock function to an_action and performs
14113481Sgiacomo.travaglini@arm.com// it.  It adapts an action accepting one argument to one that accepts
14213481Sgiacomo.travaglini@arm.com// multiple arguments.  For convenience, we also provide
14313481Sgiacomo.travaglini@arm.com// WithArgs<k>(an_action) (defined below) as a synonym.
14413481Sgiacomo.travaglini@arm.comtemplate <int k, typename InnerAction>
14513481Sgiacomo.travaglini@arm.cominline internal::WithArgsAction<InnerAction, k>
14613481Sgiacomo.travaglini@arm.comWithArg(const InnerAction& action) {
14713481Sgiacomo.travaglini@arm.com  return internal::WithArgsAction<InnerAction, k>(action);
14813481Sgiacomo.travaglini@arm.com}
14913481Sgiacomo.travaglini@arm.com
15013481Sgiacomo.travaglini@arm.com// The ACTION*() macros trigger warning C4100 (unreferenced formal
15113481Sgiacomo.travaglini@arm.com// parameter) in MSVC with -W4.  Unfortunately they cannot be fixed in
15213481Sgiacomo.travaglini@arm.com// the macro definition, as the warnings are generated when the macro
15313481Sgiacomo.travaglini@arm.com// is expanded and macro expansion cannot contain #pragma.  Therefore
15413481Sgiacomo.travaglini@arm.com// we suppress them here.
15513481Sgiacomo.travaglini@arm.com#ifdef _MSC_VER
15613481Sgiacomo.travaglini@arm.com# pragma warning(push)
15713481Sgiacomo.travaglini@arm.com# pragma warning(disable:4100)
15813481Sgiacomo.travaglini@arm.com#endif
15913481Sgiacomo.travaglini@arm.com
16013481Sgiacomo.travaglini@arm.com// Action ReturnArg<k>() returns the k-th argument of the mock function.
16113481Sgiacomo.travaglini@arm.comACTION_TEMPLATE(ReturnArg,
16213481Sgiacomo.travaglini@arm.com                HAS_1_TEMPLATE_PARAMS(int, k),
16313481Sgiacomo.travaglini@arm.com                AND_0_VALUE_PARAMS()) {
16413481Sgiacomo.travaglini@arm.com  return ::testing::get<k>(args);
16513481Sgiacomo.travaglini@arm.com}
16613481Sgiacomo.travaglini@arm.com
16713481Sgiacomo.travaglini@arm.com// Action SaveArg<k>(pointer) saves the k-th (0-based) argument of the
16813481Sgiacomo.travaglini@arm.com// mock function to *pointer.
16913481Sgiacomo.travaglini@arm.comACTION_TEMPLATE(SaveArg,
17013481Sgiacomo.travaglini@arm.com                HAS_1_TEMPLATE_PARAMS(int, k),
17113481Sgiacomo.travaglini@arm.com                AND_1_VALUE_PARAMS(pointer)) {
17213481Sgiacomo.travaglini@arm.com  *pointer = ::testing::get<k>(args);
17313481Sgiacomo.travaglini@arm.com}
17413481Sgiacomo.travaglini@arm.com
17513481Sgiacomo.travaglini@arm.com// Action SaveArgPointee<k>(pointer) saves the value pointed to
17613481Sgiacomo.travaglini@arm.com// by the k-th (0-based) argument of the mock function to *pointer.
17713481Sgiacomo.travaglini@arm.comACTION_TEMPLATE(SaveArgPointee,
17813481Sgiacomo.travaglini@arm.com                HAS_1_TEMPLATE_PARAMS(int, k),
17913481Sgiacomo.travaglini@arm.com                AND_1_VALUE_PARAMS(pointer)) {
18013481Sgiacomo.travaglini@arm.com  *pointer = *::testing::get<k>(args);
18113481Sgiacomo.travaglini@arm.com}
18213481Sgiacomo.travaglini@arm.com
18313481Sgiacomo.travaglini@arm.com// Action SetArgReferee<k>(value) assigns 'value' to the variable
18413481Sgiacomo.travaglini@arm.com// referenced by the k-th (0-based) argument of the mock function.
18513481Sgiacomo.travaglini@arm.comACTION_TEMPLATE(SetArgReferee,
18613481Sgiacomo.travaglini@arm.com                HAS_1_TEMPLATE_PARAMS(int, k),
18713481Sgiacomo.travaglini@arm.com                AND_1_VALUE_PARAMS(value)) {
18813481Sgiacomo.travaglini@arm.com  typedef typename ::testing::tuple_element<k, args_type>::type argk_type;
18913481Sgiacomo.travaglini@arm.com  // Ensures that argument #k is a reference.  If you get a compiler
19013481Sgiacomo.travaglini@arm.com  // error on the next line, you are using SetArgReferee<k>(value) in
19113481Sgiacomo.travaglini@arm.com  // a mock function whose k-th (0-based) argument is not a reference.
19213481Sgiacomo.travaglini@arm.com  GTEST_COMPILE_ASSERT_(internal::is_reference<argk_type>::value,
19313481Sgiacomo.travaglini@arm.com                        SetArgReferee_must_be_used_with_a_reference_argument);
19413481Sgiacomo.travaglini@arm.com  ::testing::get<k>(args) = value;
19513481Sgiacomo.travaglini@arm.com}
19613481Sgiacomo.travaglini@arm.com
19713481Sgiacomo.travaglini@arm.com// Action SetArrayArgument<k>(first, last) copies the elements in
19813481Sgiacomo.travaglini@arm.com// source range [first, last) to the array pointed to by the k-th
19913481Sgiacomo.travaglini@arm.com// (0-based) argument, which can be either a pointer or an
20013481Sgiacomo.travaglini@arm.com// iterator. The action does not take ownership of the elements in the
20113481Sgiacomo.travaglini@arm.com// source range.
20213481Sgiacomo.travaglini@arm.comACTION_TEMPLATE(SetArrayArgument,
20313481Sgiacomo.travaglini@arm.com                HAS_1_TEMPLATE_PARAMS(int, k),
20413481Sgiacomo.travaglini@arm.com                AND_2_VALUE_PARAMS(first, last)) {
20513481Sgiacomo.travaglini@arm.com  // Visual Studio deprecates ::std::copy, so we use our own copy in that case.
20613481Sgiacomo.travaglini@arm.com#ifdef _MSC_VER
20713481Sgiacomo.travaglini@arm.com  internal::CopyElements(first, last, ::testing::get<k>(args));
20813481Sgiacomo.travaglini@arm.com#else
20913481Sgiacomo.travaglini@arm.com  ::std::copy(first, last, ::testing::get<k>(args));
21013481Sgiacomo.travaglini@arm.com#endif
21113481Sgiacomo.travaglini@arm.com}
21213481Sgiacomo.travaglini@arm.com
21313481Sgiacomo.travaglini@arm.com// Action DeleteArg<k>() deletes the k-th (0-based) argument of the mock
21413481Sgiacomo.travaglini@arm.com// function.
21513481Sgiacomo.travaglini@arm.comACTION_TEMPLATE(DeleteArg,
21613481Sgiacomo.travaglini@arm.com                HAS_1_TEMPLATE_PARAMS(int, k),
21713481Sgiacomo.travaglini@arm.com                AND_0_VALUE_PARAMS()) {
21813481Sgiacomo.travaglini@arm.com  delete ::testing::get<k>(args);
21913481Sgiacomo.travaglini@arm.com}
22013481Sgiacomo.travaglini@arm.com
22113481Sgiacomo.travaglini@arm.com// This action returns the value pointed to by 'pointer'.
22213481Sgiacomo.travaglini@arm.comACTION_P(ReturnPointee, pointer) { return *pointer; }
22313481Sgiacomo.travaglini@arm.com
22413481Sgiacomo.travaglini@arm.com// Action Throw(exception) can be used in a mock function of any type
22513481Sgiacomo.travaglini@arm.com// to throw the given exception.  Any copyable value can be thrown.
22613481Sgiacomo.travaglini@arm.com#if GTEST_HAS_EXCEPTIONS
22713481Sgiacomo.travaglini@arm.com
22813481Sgiacomo.travaglini@arm.com// Suppresses the 'unreachable code' warning that VC generates in opt modes.
22913481Sgiacomo.travaglini@arm.com# ifdef _MSC_VER
23013481Sgiacomo.travaglini@arm.com#  pragma warning(push)          // Saves the current warning state.
23113481Sgiacomo.travaglini@arm.com#  pragma warning(disable:4702)  // Temporarily disables warning 4702.
23213481Sgiacomo.travaglini@arm.com# endif
23313481Sgiacomo.travaglini@arm.comACTION_P(Throw, exception) { throw exception; }
23413481Sgiacomo.travaglini@arm.com# ifdef _MSC_VER
23513481Sgiacomo.travaglini@arm.com#  pragma warning(pop)           // Restores the warning state.
23613481Sgiacomo.travaglini@arm.com# endif
23713481Sgiacomo.travaglini@arm.com
23813481Sgiacomo.travaglini@arm.com#endif  // GTEST_HAS_EXCEPTIONS
23913481Sgiacomo.travaglini@arm.com
24013481Sgiacomo.travaglini@arm.com#ifdef _MSC_VER
24113481Sgiacomo.travaglini@arm.com# pragma warning(pop)
24213481Sgiacomo.travaglini@arm.com#endif
24313481Sgiacomo.travaglini@arm.com
24413481Sgiacomo.travaglini@arm.com}  // namespace testing
24513481Sgiacomo.travaglini@arm.com
24613481Sgiacomo.travaglini@arm.com#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
247