Home | History | Annotate | Download | only in docs
      1 This page discusses the design of new Google Mock features.
      2 
      3 
      4 
      5 # Macros for Defining Actions #
      6 
      7 ## Problem ##
      8 
      9 Due to the lack of closures in C++, it currently requires some
     10 non-trivial effort to define a custom action in Google Mock.  For
     11 example, suppose you want to "increment the value pointed to by the
     12 second argument of the mock function and return it", you could write:
     13 
     14 ```cpp
     15 int IncrementArg1(Unused, int* p, Unused) {
     16   return ++(*p);
     17 }
     18 
     19 ... WillOnce(Invoke(IncrementArg1));
     20 ```
     21 
     22 There are several things unsatisfactory about this approach:
     23 
     24   * Even though the action only cares about the second argument of the mock function, its definition needs to list other arguments as dummies.  This is tedious.
     25   * The defined action is usable only in mock functions that takes exactly 3 arguments - an unnecessary restriction.
     26   * To use the action, one has to say `Invoke(IncrementArg1)`, which isn't as nice as `IncrementArg1()`.
     27 
     28 The latter two problems can be overcome using `MakePolymorphicAction()`,
     29 but it requires much more boilerplate code:
     30 
     31 ```cpp
     32 class IncrementArg1Action {
     33  public:
     34   template <typename Result, typename ArgumentTuple>
     35   Result Perform(const ArgumentTuple& args) const {
     36     return ++(*tr1::get<1>(args));
     37   }
     38 };
     39 
     40 PolymorphicAction<IncrementArg1Action> IncrementArg1() {
     41   return MakePolymorphicAction(IncrementArg1Action());
     42 }
     43 
     44 ... WillOnce(IncrementArg1());
     45 ```
     46 
     47 Our goal is to allow defining custom actions with the least amount of
     48 boiler-plate C++ requires.
     49 
     50 ## Solution ##
     51 
     52 We propose to introduce a new macro:
     53 ```cpp
     54 ACTION(name) { statements; }
     55 ```
     56 
     57 Using this in a namespace scope will define an action with the given
     58 name that executes the statements.  Inside the statements, you can
     59 refer to the K-th (0-based) argument of the mock function as `argK`.
     60 For example:
     61 ```cpp
     62 ACTION(IncrementArg1) { return ++(*arg1); }
     63 ```
     64 allows you to write
     65 ```cpp
     66 ... WillOnce(IncrementArg1());
     67 ```
     68 
     69 Note that you don't need to specify the types of the mock function
     70 arguments, as brevity is a top design goal here.  Rest assured that
     71 your code is still type-safe though: you'll get a compiler error if
     72 `*arg1` doesn't support the `++` operator, or if the type of
     73 `++(*arg1)` isn't compatible with the mock function's return type.
     74 
     75 Another example:
     76 ```cpp
     77 ACTION(Foo) {
     78   (*arg2)(5);
     79   Blah();
     80   *arg1 = 0;
     81   return arg0;
     82 }
     83 ```
     84 defines an action `Foo()` that invokes argument #2 (a function pointer)
     85 with 5, calls function `Blah()`, sets the value pointed to by argument
     86 #1 to 0, and returns argument #0.
     87 
     88 For more convenience and flexibility, you can also use the following
     89 pre-defined symbols in the body of `ACTION`:
     90 
     91 | Argument        | Description                                                  |
     92 |:----------------|:-------------------------------------------------------------|
     93 | `argK_type`     | The type of the K-th (0-based) argument of the mock function |
     94 | `args`          | All arguments of the mock function as a tuple                |
     95 | `args_type`     | The type of all arguments of the mock function as a tuple    |
     96 | `return_type`   | The return type of the mock function                         |
     97 | `function_type` | The type of the mock function                                |
     98 
     99 For example, when using an `ACTION` as a stub action for mock function:
    100 ```cpp
    101 int DoSomething(bool flag, int* ptr);
    102 ```
    103 we have:
    104 
    105 | **Pre-defined Symbol** | **Is Bound To** |
    106 |:-----------------------|:----------------|
    107 | `arg0`                 | the value of `flag` |
    108 | `arg0_type`            | the type `bool` |
    109 | `arg1`                 | the value of `ptr` |
    110 | `arg1_type`            | the type `int*` |
    111 | `args`                 | the tuple `(flag, ptr)` |
    112 | `args_type`            | the type `std::tr1::tuple<bool, int*>` |
    113 | `return_type`          | the type `int`  |
    114 | `function_type`        | the type `int(bool, int*)` |
    115 
    116 ## Parameterized actions ##
    117 
    118 Sometimes you'll want to parameterize the action.   For that we propose
    119 another macro
    120 ```cpp
    121 ACTION_P(name, param) { statements; }
    122 ```
    123 
    124 For example,
    125 ```cpp
    126 ACTION_P(Add, n) { return arg0 + n; }
    127 ```
    128 will allow you to write
    129 ```cpp
    130 // Returns argument #0 + 5.
    131 ... WillOnce(Add(5));
    132 ```
    133 
    134 For convenience, we use the term _arguments_ for the values used to
    135 invoke the mock function, and the term _parameters_ for the values
    136 used to instantiate an action.
    137 
    138 Note that you don't need to provide the type of the parameter either.
    139 Suppose the parameter is named `param`, you can also use the
    140 Google-Mock-defined symbol `param_type` to refer to the type of the
    141 parameter as inferred by the compiler.
    142 
    143 We will also provide `ACTION_P2`, `ACTION_P3`, and etc to support
    144 multi-parameter actions.  For example,
    145 ```cpp
    146 ACTION_P2(ReturnDistanceTo, x, y) {
    147   double dx = arg0 - x;
    148   double dy = arg1 - y;
    149   return sqrt(dx*dx + dy*dy);
    150 }
    151 ```
    152 lets you write
    153 ```cpp
    154 ... WillOnce(ReturnDistanceTo(5.0, 26.5));
    155 ```
    156 
    157 You can view `ACTION` as a degenerated parameterized action where the
    158 number of parameters is 0.
    159 
    160 ## Advanced Usages ##
    161 
    162 ### Overloading Actions ###
    163 
    164 You can easily define actions overloaded on the number of parameters:
    165 ```cpp
    166 ACTION_P(Plus, a) { ... }
    167 ACTION_P2(Plus, a, b) { ... }
    168 ```
    169 
    170 ### Restricting the Type of an Argument or Parameter ###
    171 
    172 For maximum brevity and reusability, the `ACTION*` macros don't let
    173 you specify the types of the mock function arguments and the action
    174 parameters.  Instead, we let the compiler infer the types for us.
    175 
    176 Sometimes, however, we may want to be more explicit about the types.
    177 There are several tricks to do that.  For example:
    178 ```cpp
    179 ACTION(Foo) {
    180   // Makes sure arg0 can be converted to int.
    181   int n = arg0;
    182   ... use n instead of arg0 here ...
    183 }
    184 
    185 ACTION_P(Bar, param) {
    186   // Makes sure the type of arg1 is const char*.
    187   ::testing::StaticAssertTypeEq<const char*, arg1_type>();
    188 
    189   // Makes sure param can be converted to bool.
    190   bool flag = param;
    191 }
    192 ```
    193 where `StaticAssertTypeEq` is a compile-time assertion we plan to add to
    194 Google Test (the name is chosen to match `static_assert` in C++0x).
    195 
    196 ### Using the ACTION Object's Type ###
    197 
    198 If you are writing a function that returns an `ACTION` object, you'll
    199 need to know its type.  The type depends on the macro used to define
    200 the action and the parameter types.  The rule is relatively simple:
    201 | **Given Definition**     | **Expression**               | **Has Type**             |
    202 |:-------------------------|:-----------------------------|:-------------------------|
    203 | `ACTION(Foo)`            | `Foo()`                      | `FooAction`              |
    204 | `ACTION_P(Bar, param)`   | `Bar(int_value)`             | `BarActionP<int>`        |
    205 | `ACTION_P2(Baz, p1, p2)` | `Baz(bool_value, int_value)` | `BazActionP2<bool, int>` |
    206 | ...                      | ...                          | ...                      |
    207 
    208 Note that we have to pick different suffixes (`Action`, `ActionP`,
    209 `ActionP2`, and etc) for actions with different numbers of parameters,
    210 or the action definitions cannot be overloaded on the number of
    211 parameters.
    212 
    213 ## When to Use ##
    214 
    215 While the new macros are very convenient, please also consider other
    216 means of implementing actions (e.g. via `ActionInterface` or
    217 `MakePolymorphicAction()`), especially if you need to use the defined
    218 action a lot.  While the other approaches require more work, they give
    219 you more control on the types of the mock function arguments and the
    220 action parameters, which in general leads to better compiler error
    221 messages that pay off in the long run.  They also allow overloading
    222 actions based on parameter types, as opposed to just the number of
    223 parameters.
    224 
    225 ## Related Work ##
    226 
    227 As you may have realized, the `ACTION*` macros resemble closures (also
    228 known as lambda expressions or anonymous functions).  Indeed, both of
    229 them seek to lower the syntactic overhead for defining a function.
    230 
    231 C++0x will support lambdas, but they are not part of C++ right now.
    232 Some non-standard libraries (most notably BLL or Boost Lambda Library)
    233 try to alleviate this problem.  However, they are not a good choice
    234 for defining actions as:
    235 
    236   * They are non-standard and not widely installed.  Google Mock only depends on standard libraries and `tr1::tuple`, which is part of the new C++ standard and comes with gcc 4+.  We want to keep it that way.
    237   * They are not trivial to learn.
    238   * They will become obsolete when C++0x's lambda feature is widely supported.  We don't want to make our users use a dying library.
    239   * Since they are based on operators, they are rather ad hoc: you cannot use statements, and you cannot pass the lambda arguments to a function, for example.
    240   * They have subtle semantics that easily confuses new users.  For example, in expression `_1++ + foo++`, `foo` will be incremented only once where the expression is evaluated, while `_1` will be incremented every time the unnamed function is invoked.  This is far from intuitive.
    241 
    242 `ACTION*` avoid all these problems.
    243 
    244 ## Future Improvements ##
    245 
    246 There may be a need for composing `ACTION*` definitions (i.e. invoking
    247 another `ACTION` inside the definition of one `ACTION*`).  We are not
    248 sure we want it yet, as one can get a similar effect by putting
    249 `ACTION` definitions in function templates and composing the function
    250 templates.  We'll revisit this based on user feedback.
    251 
    252 The reason we don't allow `ACTION*()` inside a function body is that
    253 the current C++ standard doesn't allow function-local types to be used
    254 to instantiate templates.  The upcoming C++0x standard will lift this
    255 restriction.  Once this feature is widely supported by compilers, we
    256 can revisit the implementation and add support for using `ACTION*()`
    257 inside a function.
    258 
    259 C++0x will also support lambda expressions.  When they become
    260 available, we may want to support using lambdas as actions.
    261 
    262 # Macros for Defining Matchers #
    263 
    264 Once the macros for defining actions are implemented, we plan to do
    265 the same for matchers:
    266 
    267 ```cpp
    268 MATCHER(name) { statements; }
    269 ```
    270 
    271 where you can refer to the value being matched as `arg`.  For example,
    272 given:
    273 
    274 ```cpp
    275 MATCHER(IsPositive) { return arg > 0; }
    276 ```
    277 
    278 you can use `IsPositive()` as a matcher that matches a value iff it is
    279 greater than 0.
    280 
    281 We will also add `MATCHER_P`, `MATCHER_P2`, and etc for parameterized
    282 matchers.
    283