283 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			283 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
This page discusses the design of new Google Mock features.
 | 
						|
 | 
						|
 | 
						|
 | 
						|
# Macros for Defining Actions #
 | 
						|
 | 
						|
## Problem ##
 | 
						|
 | 
						|
Due to the lack of closures in C++, it currently requires some
 | 
						|
non-trivial effort to define a custom action in Google Mock.  For
 | 
						|
example, suppose you want to "increment the value pointed to by the
 | 
						|
second argument of the mock function and return it", you could write:
 | 
						|
 | 
						|
```cpp
 | 
						|
int IncrementArg1(Unused, int* p, Unused) {
 | 
						|
  return ++(*p);
 | 
						|
}
 | 
						|
 | 
						|
... WillOnce(Invoke(IncrementArg1));
 | 
						|
```
 | 
						|
 | 
						|
There are several things unsatisfactory about this approach:
 | 
						|
 | 
						|
  * 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.
 | 
						|
  * The defined action is usable only in mock functions that takes exactly 3 arguments - an unnecessary restriction.
 | 
						|
  * To use the action, one has to say `Invoke(IncrementArg1)`, which isn't as nice as `IncrementArg1()`.
 | 
						|
 | 
						|
The latter two problems can be overcome using `MakePolymorphicAction()`,
 | 
						|
but it requires much more boilerplate code:
 | 
						|
 | 
						|
```cpp
 | 
						|
class IncrementArg1Action {
 | 
						|
 public:
 | 
						|
  template <typename Result, typename ArgumentTuple>
 | 
						|
  Result Perform(const ArgumentTuple& args) const {
 | 
						|
    return ++(*tr1::get<1>(args));
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
PolymorphicAction<IncrementArg1Action> IncrementArg1() {
 | 
						|
  return MakePolymorphicAction(IncrementArg1Action());
 | 
						|
}
 | 
						|
 | 
						|
... WillOnce(IncrementArg1());
 | 
						|
```
 | 
						|
 | 
						|
Our goal is to allow defining custom actions with the least amount of
 | 
						|
boiler-plate C++ requires.
 | 
						|
 | 
						|
## Solution ##
 | 
						|
 | 
						|
We propose to introduce a new macro:
 | 
						|
```cpp
 | 
						|
ACTION(name) { statements; }
 | 
						|
```
 | 
						|
 | 
						|
Using this in a namespace scope will define an action with the given
 | 
						|
name that executes the statements.  Inside the statements, you can
 | 
						|
refer to the K-th (0-based) argument of the mock function as `argK`.
 | 
						|
For example:
 | 
						|
```cpp
 | 
						|
ACTION(IncrementArg1) { return ++(*arg1); }
 | 
						|
```
 | 
						|
allows you to write
 | 
						|
```cpp
 | 
						|
... WillOnce(IncrementArg1());
 | 
						|
```
 | 
						|
 | 
						|
Note that you don't need to specify the types of the mock function
 | 
						|
arguments, as brevity is a top design goal here.  Rest assured that
 | 
						|
your code is still type-safe though: you'll get a compiler error if
 | 
						|
`*arg1` doesn't support the `++` operator, or if the type of
 | 
						|
`++(*arg1)` isn't compatible with the mock function's return type.
 | 
						|
 | 
						|
Another example:
 | 
						|
```cpp
 | 
						|
ACTION(Foo) {
 | 
						|
  (*arg2)(5);
 | 
						|
  Blah();
 | 
						|
  *arg1 = 0;
 | 
						|
  return arg0;
 | 
						|
}
 | 
						|
```
 | 
						|
defines an action `Foo()` that invokes argument #2 (a function pointer)
 | 
						|
with 5, calls function `Blah()`, sets the value pointed to by argument
 | 
						|
#1 to 0, and returns argument #0.
 | 
						|
 | 
						|
For more convenience and flexibility, you can also use the following
 | 
						|
pre-defined symbols in the body of `ACTION`:
 | 
						|
 | 
						|
| Argument        | Description                                                  |
 | 
						|
|:----------------|:-------------------------------------------------------------|
 | 
						|
| `argK_type`     | The type of the K-th (0-based) argument of the mock function |
 | 
						|
| `args`          | All arguments of the mock function as a tuple                |
 | 
						|
| `args_type`     | The type of all arguments of the mock function as a tuple    |
 | 
						|
| `return_type`   | The return type of the mock function                         |
 | 
						|
| `function_type` | The type of the mock function                                |
 | 
						|
 | 
						|
For example, when using an `ACTION` as a stub action for mock function:
 | 
						|
```cpp
 | 
						|
int DoSomething(bool flag, int* ptr);
 | 
						|
```
 | 
						|
we have:
 | 
						|
 | 
						|
| **Pre-defined Symbol** | **Is Bound To** |
 | 
						|
|:-----------------------|:----------------|
 | 
						|
| `arg0`                 | the value of `flag` |
 | 
						|
| `arg0_type`            | the type `bool` |
 | 
						|
| `arg1`                 | the value of `ptr` |
 | 
						|
| `arg1_type`            | the type `int*` |
 | 
						|
| `args`                 | the tuple `(flag, ptr)` |
 | 
						|
| `args_type`            | the type `std::tr1::tuple<bool, int*>` |
 | 
						|
| `return_type`          | the type `int`  |
 | 
						|
| `function_type`        | the type `int(bool, int*)` |
 | 
						|
 | 
						|
## Parameterized actions ##
 | 
						|
 | 
						|
Sometimes you'll want to parameterize the action.   For that we propose
 | 
						|
another macro
 | 
						|
```cpp
 | 
						|
ACTION_P(name, param) { statements; }
 | 
						|
```
 | 
						|
 | 
						|
For example,
 | 
						|
```cpp
 | 
						|
ACTION_P(Add, n) { return arg0 + n; }
 | 
						|
```
 | 
						|
will allow you to write
 | 
						|
```cpp
 | 
						|
// Returns argument #0 + 5.
 | 
						|
... WillOnce(Add(5));
 | 
						|
```
 | 
						|
 | 
						|
For convenience, we use the term _arguments_ for the values used to
 | 
						|
invoke the mock function, and the term _parameters_ for the values
 | 
						|
used to instantiate an action.
 | 
						|
 | 
						|
Note that you don't need to provide the type of the parameter either.
 | 
						|
Suppose the parameter is named `param`, you can also use the
 | 
						|
Google-Mock-defined symbol `param_type` to refer to the type of the
 | 
						|
parameter as inferred by the compiler.
 | 
						|
 | 
						|
We will also provide `ACTION_P2`, `ACTION_P3`, and etc to support
 | 
						|
multi-parameter actions.  For example,
 | 
						|
```cpp
 | 
						|
ACTION_P2(ReturnDistanceTo, x, y) {
 | 
						|
  double dx = arg0 - x;
 | 
						|
  double dy = arg1 - y;
 | 
						|
  return sqrt(dx*dx + dy*dy);
 | 
						|
}
 | 
						|
```
 | 
						|
lets you write
 | 
						|
```cpp
 | 
						|
... WillOnce(ReturnDistanceTo(5.0, 26.5));
 | 
						|
```
 | 
						|
 | 
						|
You can view `ACTION` as a degenerated parameterized action where the
 | 
						|
number of parameters is 0.
 | 
						|
 | 
						|
## Advanced Usages ##
 | 
						|
 | 
						|
### Overloading Actions ###
 | 
						|
 | 
						|
You can easily define actions overloaded on the number of parameters:
 | 
						|
```cpp
 | 
						|
ACTION_P(Plus, a) { ... }
 | 
						|
ACTION_P2(Plus, a, b) { ... }
 | 
						|
```
 | 
						|
 | 
						|
### Restricting the Type of an Argument or Parameter ###
 | 
						|
 | 
						|
For maximum brevity and reusability, the `ACTION*` macros don't let
 | 
						|
you specify the types of the mock function arguments and the action
 | 
						|
parameters.  Instead, we let the compiler infer the types for us.
 | 
						|
 | 
						|
Sometimes, however, we may want to be more explicit about the types.
 | 
						|
There are several tricks to do that.  For example:
 | 
						|
```cpp
 | 
						|
ACTION(Foo) {
 | 
						|
  // Makes sure arg0 can be converted to int.
 | 
						|
  int n = arg0;
 | 
						|
  ... use n instead of arg0 here ...
 | 
						|
}
 | 
						|
 | 
						|
ACTION_P(Bar, param) {
 | 
						|
  // Makes sure the type of arg1 is const char*.
 | 
						|
  ::testing::StaticAssertTypeEq<const char*, arg1_type>();
 | 
						|
 | 
						|
  // Makes sure param can be converted to bool.
 | 
						|
  bool flag = param;
 | 
						|
}
 | 
						|
```
 | 
						|
where `StaticAssertTypeEq` is a compile-time assertion we plan to add to
 | 
						|
Google Test (the name is chosen to match `static_assert` in C++0x).
 | 
						|
 | 
						|
### Using the ACTION Object's Type ###
 | 
						|
 | 
						|
If you are writing a function that returns an `ACTION` object, you'll
 | 
						|
need to know its type.  The type depends on the macro used to define
 | 
						|
the action and the parameter types.  The rule is relatively simple:
 | 
						|
| **Given Definition**     | **Expression**               | **Has Type**             |
 | 
						|
|:-------------------------|:-----------------------------|:-------------------------|
 | 
						|
| `ACTION(Foo)`            | `Foo()`                      | `FooAction`              |
 | 
						|
| `ACTION_P(Bar, param)`   | `Bar(int_value)`             | `BarActionP<int>`        |
 | 
						|
| `ACTION_P2(Baz, p1, p2)` | `Baz(bool_value, int_value)` | `BazActionP2<bool, int>` |
 | 
						|
| ...                      | ...                          | ...                      |
 | 
						|
 | 
						|
Note that we have to pick different suffixes (`Action`, `ActionP`,
 | 
						|
`ActionP2`, and etc) for actions with different numbers of parameters,
 | 
						|
or the action definitions cannot be overloaded on the number of
 | 
						|
parameters.
 | 
						|
 | 
						|
## When to Use ##
 | 
						|
 | 
						|
While the new macros are very convenient, please also consider other
 | 
						|
means of implementing actions (e.g. via `ActionInterface` or
 | 
						|
`MakePolymorphicAction()`), especially if you need to use the defined
 | 
						|
action a lot.  While the other approaches require more work, they give
 | 
						|
you more control on the types of the mock function arguments and the
 | 
						|
action parameters, which in general leads to better compiler error
 | 
						|
messages that pay off in the long run.  They also allow overloading
 | 
						|
actions based on parameter types, as opposed to just the number of
 | 
						|
parameters.
 | 
						|
 | 
						|
## Related Work ##
 | 
						|
 | 
						|
As you may have realized, the `ACTION*` macros resemble closures (also
 | 
						|
known as lambda expressions or anonymous functions).  Indeed, both of
 | 
						|
them seek to lower the syntactic overhead for defining a function.
 | 
						|
 | 
						|
C++0x will support lambdas, but they are not part of C++ right now.
 | 
						|
Some non-standard libraries (most notably BLL or Boost Lambda Library)
 | 
						|
try to alleviate this problem.  However, they are not a good choice
 | 
						|
for defining actions as:
 | 
						|
 | 
						|
  * 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.
 | 
						|
  * They are not trivial to learn.
 | 
						|
  * 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.
 | 
						|
  * 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.
 | 
						|
  * 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.
 | 
						|
 | 
						|
`ACTION*` avoid all these problems.
 | 
						|
 | 
						|
## Future Improvements ##
 | 
						|
 | 
						|
There may be a need for composing `ACTION*` definitions (i.e. invoking
 | 
						|
another `ACTION` inside the definition of one `ACTION*`).  We are not
 | 
						|
sure we want it yet, as one can get a similar effect by putting
 | 
						|
`ACTION` definitions in function templates and composing the function
 | 
						|
templates.  We'll revisit this based on user feedback.
 | 
						|
 | 
						|
The reason we don't allow `ACTION*()` inside a function body is that
 | 
						|
the current C++ standard doesn't allow function-local types to be used
 | 
						|
to instantiate templates.  The upcoming C++0x standard will lift this
 | 
						|
restriction.  Once this feature is widely supported by compilers, we
 | 
						|
can revisit the implementation and add support for using `ACTION*()`
 | 
						|
inside a function.
 | 
						|
 | 
						|
C++0x will also support lambda expressions.  When they become
 | 
						|
available, we may want to support using lambdas as actions.
 | 
						|
 | 
						|
# Macros for Defining Matchers #
 | 
						|
 | 
						|
Once the macros for defining actions are implemented, we plan to do
 | 
						|
the same for matchers:
 | 
						|
 | 
						|
```cpp
 | 
						|
MATCHER(name) { statements; }
 | 
						|
```
 | 
						|
 | 
						|
where you can refer to the value being matched as `arg`.  For example,
 | 
						|
given:
 | 
						|
 | 
						|
```cpp
 | 
						|
MATCHER(IsPositive) { return arg > 0; }
 | 
						|
```
 | 
						|
 | 
						|
you can use `IsPositive()` as a matcher that matches a value iff it is
 | 
						|
greater than 0.
 | 
						|
 | 
						|
We will also add `MATCHER_P`, `MATCHER_P2`, and etc for parameterized
 | 
						|
matchers.
 |