Unverified Commit 1246e580 authored by Gennadiy Civil's avatar Gennadiy Civil Committed by GitHub
Browse files

Merge branch 'master' into cleanup-cmake

parents 4b6a7a49 2172c08c
...@@ -38,3 +38,17 @@ googletest/m4/lt~obsolete.m4 ...@@ -38,3 +38,17 @@ googletest/m4/lt~obsolete.m4
# Ignore generated directories. # Ignore generated directories.
googlemock/fused-src/ googlemock/fused-src/
googletest/fused-src/ googletest/fused-src/
# macOS files
.DS_Store
# Ignore cmake generated directories and files.
CMakeFiles
CTestTestfile.cmake
Makefile
cmake_install.cmake
googlemock/CMakeFiles
googlemock/CTestTestfile.cmake
googlemock/Makefile
googlemock/cmake_install.cmake
googlemock/gtest
# Build matrix / environment variable are explained on: # Build matrix / environment variable are explained on:
# http://about.travis-ci.org/docs/user/build-configuration/ # https://docs.travis-ci.com/user/customizing-the-build/
# This file can be validated on: # This file can be validated on:
# http://lint.travis-ci.org/ # http://lint.travis-ci.org/
...@@ -37,13 +37,15 @@ matrix: ...@@ -37,13 +37,15 @@ matrix:
group: deprecated-2017Q4 group: deprecated-2017Q4
compiler: clang compiler: clang
env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11
- os: linux
compiler: clang
env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 NO_EXCEPTION=ON NO_RTTI=ON COMPILER_IS_GNUCXX=ON
- os: osx - os: osx
compiler: gcc compiler: gcc
env: BUILD_TYPE=Debug VERBOSE=1 env: BUILD_TYPE=Debug VERBOSE=1
- os: osx - os: osx
compiler: gcc compiler: gcc
env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11
if: type != pull_request
- os: osx - os: osx
compiler: clang compiler: clang
env: BUILD_TYPE=Debug VERBOSE=1 env: BUILD_TYPE=Debug VERBOSE=1
......
...@@ -38,7 +38,7 @@ licenses(["notice"]) ...@@ -38,7 +38,7 @@ licenses(["notice"])
config_setting( config_setting(
name = "windows", name = "windows",
values = { "cpu": "x64_windows" }, values = {"cpu": "x64_windows"},
) )
config_setting( config_setting(
...@@ -51,7 +51,6 @@ config_setting( ...@@ -51,7 +51,6 @@ config_setting(
values = {"define": "absl=1"}, values = {"define": "absl=1"},
) )
# Google Test including Google Mock # Google Test including Google Mock
cc_library( cc_library(
name = "gtest", name = "gtest",
...@@ -70,7 +69,7 @@ cc_library( ...@@ -70,7 +69,7 @@ cc_library(
"googlemock/src/gmock_main.cc", "googlemock/src/gmock_main.cc",
], ],
), ),
hdrs =glob([ hdrs = glob([
"googletest/include/gtest/*.h", "googletest/include/gtest/*.h",
"googlemock/include/gmock/*.h", "googlemock/include/gmock/*.h",
]), ]),
...@@ -81,6 +80,14 @@ cc_library( ...@@ -81,6 +80,14 @@ cc_library(
"//conditions:default": ["-pthread"], "//conditions:default": ["-pthread"],
}, },
), ),
defines = select(
{
":has_absl": [
"GTEST_HAS_ABSL=1",
],
"//conditions:default": [],
},
),
includes = [ includes = [
"googlemock", "googlemock",
"googlemock/include", "googlemock/include",
...@@ -94,21 +101,19 @@ cc_library( ...@@ -94,21 +101,19 @@ cc_library(
"-pthread", "-pthread",
], ],
}), }),
defines = select ({ deps = select(
":has_absl": [ {
"GTEST_HAS_ABSL=1", ":has_absl": [
], "@com_google_absl//absl/debugging:failure_signal_handler",
"//conditions:default": [], "@com_google_absl//absl/debugging:stacktrace",
} "@com_google_absl//absl/debugging:symbolize",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/types:optional",
"@com_google_absl//absl/types:variant",
],
"//conditions:default": [],
},
), ),
deps = select ({
":has_absl": [
"@com_google_absl//absl/types:optional",
"@com_google_absl//absl/strings"
],
"//conditions:default": [],
}
)
) )
cc_library( cc_library(
......
...@@ -4,6 +4,12 @@ ...@@ -4,6 +4,12 @@
[![Build Status](https://travis-ci.org/google/googletest.svg?branch=master)](https://travis-ci.org/google/googletest) [![Build Status](https://travis-ci.org/google/googletest.svg?branch=master)](https://travis-ci.org/google/googletest)
[![Build status](https://ci.appveyor.com/api/projects/status/4o38plt0xbo1ubc8/branch/master?svg=true)](https://ci.appveyor.com/project/GoogleTestAppVeyor/googletest/branch/master) [![Build status](https://ci.appveyor.com/api/projects/status/4o38plt0xbo1ubc8/branch/master?svg=true)](https://ci.appveyor.com/project/GoogleTestAppVeyor/googletest/branch/master)
**Future Plans**:
* 1.8.x Release - the 1.8.x will be the last release that works with pre-C++11 compilers. The 1.8.1 will not accept any requests for any new features and any bugfix requests will only be accepted if proven "critical"
* Post 1.8.x - work to improve/cleanup/pay technical debt. When this work is completed there will be a 1.9.x tagged release
* Post 1.9.x googletest will follow [Abseil Live at Head philosophy](https://abseil.io/about/philosophy)
Welcome to **Google Test**, Google's C++ test framework! Welcome to **Google Test**, Google's C++ test framework!
This repository is a merger of the formerly separate GoogleTest and This repository is a merger of the formerly separate GoogleTest and
...@@ -15,8 +21,8 @@ mailing list for questions, discussions, and development. There is ...@@ -15,8 +21,8 @@ mailing list for questions, discussions, and development. There is
also an IRC channel on [OFTC](https://webchat.oftc.net/) (irc.oftc.net) #gtest available. Please also an IRC channel on [OFTC](https://webchat.oftc.net/) (irc.oftc.net) #gtest available. Please
join us! join us!
Getting started information for **Google Test** is available in the Getting started information for **Google Test** is available in the
[Google Test Primer](googletest/docs/Primer.md) documentation. [Google Test Primer](googletest/docs/primer.md) documentation.
**Google Mock** is an extension to Google Test for writing and using C++ mock **Google Mock** is an extension to Google Test for writing and using C++ mock
classes. See the separate [Google Mock documentation](googlemock/README.md). classes. See the separate [Google Mock documentation](googlemock/README.md).
......
...@@ -78,6 +78,11 @@ build_script: ...@@ -78,6 +78,11 @@ build_script:
throw "Exec: $ErrorMessage" throw "Exec: $ErrorMessage"
} }
skip_commits:
files:
- '**/*.md'
test_script: test_script:
- ps: | - ps: |
# Only enable some builds for pull requests, the AppVeyor queue is too long. # Only enable some builds for pull requests, the AppVeyor queue is too long.
......
...@@ -24,11 +24,19 @@ export MAKEFLAGS ...@@ -24,11 +24,19 @@ export MAKEFLAGS
env | sort env | sort
# Set default values to OFF for these variables if not specified.
: "${NO_EXCEPTION:=OFF}"
: "${NO_RTTI:=OFF}"
: "${COMPILER_IS_GNUCXX:=OFF}"
mkdir build || true mkdir build || true
cd build cd build
cmake -Dgtest_build_samples=ON \ cmake -Dgtest_build_samples=ON \
-Dgtest_build_tests=ON \ -Dgtest_build_tests=ON \
-Dgmock_build_tests=ON \ -Dgmock_build_tests=ON \
-Dcxx_no_exception=$NO_EXCEPTION \
-Dcxx_no_rtti=$NO_RTTI \
-DCMAKE_COMPILER_IS_GNUCXX=$COMPILER_IS_GNUCXX \
-DCMAKE_CXX_FLAGS=$CXX_FLAGS \ -DCMAKE_CXX_FLAGS=$CXX_FLAGS \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \ -DCMAKE_BUILD_TYPE=$BUILD_TYPE \
.. ..
......
...@@ -138,13 +138,13 @@ if(INSTALL_GMOCK) ...@@ -138,13 +138,13 @@ if(INSTALL_GMOCK)
# configure and install pkgconfig files # configure and install pkgconfig files
configure_file( configure_file(
cmake/gmock.pc.in cmake/gmock.pc.in
"${CMAKE_BINARY_DIR}/gmock.pc" "${gmock_BINARY_DIR}/gmock.pc"
@ONLY) @ONLY)
configure_file( configure_file(
cmake/gmock_main.pc.in cmake/gmock_main.pc.in
"${CMAKE_BINARY_DIR}/gmock_main.pc" "${gmock_BINARY_DIR}/gmock_main.pc"
@ONLY) @ONLY)
install(FILES "${CMAKE_BINARY_DIR}/gmock.pc" "${CMAKE_BINARY_DIR}/gmock_main.pc" install(FILES "${gmock_BINARY_DIR}/gmock.pc" "${gmock_BINARY_DIR}/gmock_main.pc"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
endif() endif()
......
...@@ -53,7 +53,7 @@ the Apache License, which is different from Google Mock's license. ...@@ -53,7 +53,7 @@ the Apache License, which is different from Google Mock's license.
If you are new to the project, we suggest that you read the user If you are new to the project, we suggest that you read the user
documentation in the following order: documentation in the following order:
* Learn the [basics](../../master/googletest/docs/Primer.md) of * Learn the [basics](../../master/googletest/docs/primer.md) of
Google Test, if you choose to use Google Mock with it (recommended). Google Test, if you choose to use Google Mock with it (recommended).
* Read [Google Mock for Dummies](../../master/googlemock/docs/ForDummies.md). * Read [Google Mock for Dummies](../../master/googlemock/docs/ForDummies.md).
* Read the instructions below on how to build Google Mock. * Read the instructions below on how to build Google Mock.
...@@ -129,20 +129,20 @@ build Google Mock and its tests, which has further requirements: ...@@ -129,20 +129,20 @@ build Google Mock and its tests, which has further requirements:
If you have CMake available, it is recommended that you follow the If you have CMake available, it is recommended that you follow the
[build instructions][gtest_cmakebuild] [build instructions][gtest_cmakebuild]
as described for Google Test. as described for Google Test.
If are using Google Mock with an If are using Google Mock with an
existing CMake project, the section existing CMake project, the section
[Incorporating Into An Existing CMake Project][gtest_incorpcmake] [Incorporating Into An Existing CMake Project][gtest_incorpcmake]
may be of particular interest. may be of particular interest.
To make it work for Google Mock you will need to change To make it work for Google Mock you will need to change
target_link_libraries(example gtest_main) target_link_libraries(example gtest_main)
to to
target_link_libraries(example gmock_main) target_link_libraries(example gmock_main)
This works because `gmock_main` library is compiled with Google Test. This works because `gmock_main` library is compiled with Google Test.
However, it does not automatically add Google Test includes. However, it does not automatically add Google Test includes.
Therefore you will also have to change Therefore you will also have to change
...@@ -161,8 +161,8 @@ to ...@@ -161,8 +161,8 @@ to
"${gtest_SOURCE_DIR}/include" "${gmock_SOURCE_DIR}/include") "${gtest_SOURCE_DIR}/include" "${gmock_SOURCE_DIR}/include")
endif() endif()
This will addtionally mark Google Mock includes as system, which will This will addtionally mark Google Mock includes as system, which will
silence compiler warnings when compiling your tests using clang with silence compiler warnings when compiling your tests using clang with
`-Wpedantic -Wall -Wextra -Wconversion`. `-Wpedantic -Wall -Wextra -Wconversion`.
......
...@@ -229,7 +229,7 @@ The `argument` can be either a C string or a C++ string object: ...@@ -229,7 +229,7 @@ The `argument` can be either a C string or a C++ string object:
`ContainsRegex()` and `MatchesRegex()` use the regular expression `ContainsRegex()` and `MatchesRegex()` use the regular expression
syntax defined syntax defined
[here](../../googletest/docs/AdvancedGuide.md#regular-expression-syntax). [here](../../googletest/docs/advanced.md#regular-expression-syntax).
`StrCaseEq()`, `StrCaseNe()`, `StrEq()`, and `StrNe()` work for wide `StrCaseEq()`, `StrCaseNe()`, `StrEq()`, and `StrNe()` work for wide
strings as well. strings as well.
...@@ -349,7 +349,7 @@ You can make a matcher from one or more other matchers: ...@@ -349,7 +349,7 @@ You can make a matcher from one or more other matchers:
## Matchers as Test Assertions ## ## Matchers as Test Assertions ##
|`ASSERT_THAT(expression, m)`|Generates a [fatal failure](../../googletest/docs/Primer.md#assertions) if the value of `expression` doesn't match matcher `m`.| |`ASSERT_THAT(expression, m)`|Generates a [fatal failure](../../googletest/docs/primer.md#assertions) if the value of `expression` doesn't match matcher `m`.|
|:---------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------| |:---------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------|
|`EXPECT_THAT(expression, m)`|Generates a non-fatal failure if the value of `expression` doesn't match matcher `m`. | |`EXPECT_THAT(expression, m)`|Generates a non-fatal failure if the value of `expression` doesn't match matcher `m`. |
......
...@@ -2229,77 +2229,71 @@ versus ...@@ -2229,77 +2229,71 @@ versus
## Mocking Methods That Use Move-Only Types ## ## Mocking Methods That Use Move-Only Types ##
C++11 introduced <em>move-only types</em>. A move-only-typed value can be moved from one object to another, but cannot be copied. `std::unique_ptr<T>` is probably the most commonly used move-only type. C++11 introduced *move-only types*. A move-only-typed value can be moved from
one object to another, but cannot be copied. `std::unique_ptr<T>` is
probably the most commonly used move-only type.
Mocking a method that takes and/or returns move-only types presents some challenges, but nothing insurmountable. This recipe shows you how you can do it. Mocking a method that takes and/or returns move-only types presents some
challenges, but nothing insurmountable. This recipe shows you how you can do it.
Note that the support for move-only method arguments was only introduced to
gMock in April 2017; in older code, you may find more complex
[workarounds](#LegacyMoveOnly) for lack of this feature.
Let’s say we are working on a fictional project that lets one post and share snippets called “buzzes”. Your code uses these types: Let’s say we are working on a fictional project that lets one post and share
snippets called “buzzes”. Your code uses these types:
``` ```cpp
enum class AccessLevel { kInternal, kPublic }; enum class AccessLevel { kInternal, kPublic };
class Buzz { class Buzz {
public: public:
explicit Buzz(AccessLevel access) { } explicit Buzz(AccessLevel access) { ... }
... ...
}; };
class Buzzer { class Buzzer {
public: public:
virtual ~Buzzer() {} virtual ~Buzzer() {}
virtual std::unique_ptr<Buzz> MakeBuzz(const std::string& text) = 0; virtual std::unique_ptr<Buzz> MakeBuzz(StringPiece text) = 0;
virtual bool ShareBuzz(std::unique_ptr<Buzz> buzz, Time timestamp) = 0; virtual bool ShareBuzz(std::unique_ptr<Buzz> buzz, int64_t timestamp) = 0;
... ...
}; };
``` ```
A `Buzz` object represents a snippet being posted. A class that implements the `Buzzer` interface is capable of creating and sharing `Buzz`. Methods in `Buzzer` may return a `unique_ptr<Buzz>` or take a `unique_ptr<Buzz>`. Now we need to mock `Buzzer` in our tests. A `Buzz` object represents a snippet being posted. A class that implements the
`Buzzer` interface is capable of creating and sharing `Buzz`es. Methods in
To mock a method that returns a move-only type, you just use the familiar `MOCK_METHOD` syntax as usual: `Buzzer` may return a `unique_ptr<Buzz>` or take a
`unique_ptr<Buzz>`. Now we need to mock `Buzzer` in our tests.
```
class MockBuzzer : public Buzzer {
public:
MOCK_METHOD1(MakeBuzz, std::unique_ptr<Buzz>(const std::string& text));
};
```
However, if you attempt to use the same `MOCK_METHOD` pattern to mock a method that takes a move-only parameter, you’ll get a compiler error currently:
```
// Does NOT compile!
MOCK_METHOD2(ShareBuzz, bool(std::unique_ptr<Buzz> buzz, Time timestamp));
```
While it’s highly desirable to make this syntax just work, it’s not trivial and the work hasn’t been done yet. Fortunately, there is a trick you can apply today to get something that works nearly as well as this.
The trick, is to delegate the `ShareBuzz()` method to a mock method (let’s call it `DoShareBuzz()`) that does not take move-only parameters: To mock a method that accepts or returns move-only types, you just use the
familiar `MOCK_METHOD` syntax as usual:
``` ```cpp
class MockBuzzer : public Buzzer { class MockBuzzer : public Buzzer {
public: public:
MOCK_METHOD1(MakeBuzz, std::unique_ptr<Buzz>(const std::string& text)); MOCK_METHOD1(MakeBuzz, std::unique_ptr<Buzz>(StringPiece text));
MOCK_METHOD2(DoShareBuzz, bool(Buzz* buzz, Time timestamp)); MOCK_METHOD2(ShareBuzz, bool(std::unique_ptr<Buzz> buzz, int64_t timestamp));
bool ShareBuzz(std::unique_ptr<Buzz> buzz, Time timestamp) {
return DoShareBuzz(buzz.get(), timestamp);
}
}; };
``` ```
Note that there's no need to define or declare `DoShareBuzz()` in a base class. You only need to define it as a `MOCK_METHOD` in the mock class. Now that we have the mock class defined, we can use it in tests. In the
following code examples, we assume that we have defined a `MockBuzzer` object
Now that we have the mock class defined, we can use it in tests. In the following code examples, we assume that we have defined a `MockBuzzer` object named `mock_buzzer_`: named `mock_buzzer_`:
``` ```cpp
MockBuzzer mock_buzzer_; MockBuzzer mock_buzzer_;
``` ```
First let’s see how we can set expectations on the `MakeBuzz()` method, which returns a `unique_ptr<Buzz>`. First let’s see how we can set expectations on the `MakeBuzz()` method, which
returns a `unique_ptr<Buzz>`.
As usual, if you set an expectation without an action (i.e. the `.WillOnce()` or `.WillRepeated()` clause), when that expectation fires, the default action for that method will be taken. Since `unique_ptr<>` has a default constructor that returns a null `unique_ptr`, that’s what you’ll get if you don’t specify an action: As usual, if you set an expectation without an action (i.e. the `.WillOnce()` or
`.WillRepeated()` clause), when that expectation fires, the default action for
that method will be taken. Since `unique_ptr<>` has a default constructor
that returns a null `unique_ptr`, that’s what you’ll get if you don’t specify an
action:
``` ```cpp
// Use the default action. // Use the default action.
EXPECT_CALL(mock_buzzer_, MakeBuzz("hello")); EXPECT_CALL(mock_buzzer_, MakeBuzz("hello"));
...@@ -2307,32 +2301,13 @@ As usual, if you set an expectation without an action (i.e. the `.WillOnce()` or ...@@ -2307,32 +2301,13 @@ As usual, if you set an expectation without an action (i.e. the `.WillOnce()` or
EXPECT_EQ(nullptr, mock_buzzer_.MakeBuzz("hello")); EXPECT_EQ(nullptr, mock_buzzer_.MakeBuzz("hello"));
``` ```
If you are not happy with the default action, you can tweak it. Depending on what you need, you may either tweak the default action for a specific (mock object, mock method) combination using `ON_CALL()`, or you may tweak the default action for all mock methods that return a specific type. The usage of `ON_CALL()` is similar to `EXPECT_CALL()`, so we’ll skip it and just explain how to do the latter (tweaking the default action for a specific return type). You do this via the `DefaultValue<>::SetFactory()` and `DefaultValue<>::Clear()` API: If you are not happy with the default action, you can tweak it as usual; see
[Setting Default Actions](#OnCall).
```
// Sets the default action for return type std::unique_ptr<Buzz> to
// creating a new Buzz every time.
DefaultValue<std::unique_ptr<Buzz>>::SetFactory(
[] { return MakeUnique<Buzz>(AccessLevel::kInternal); });
// When this fires, the default action of MakeBuzz() will run, which
// will return a new Buzz object.
EXPECT_CALL(mock_buzzer_, MakeBuzz("hello")).Times(AnyNumber());
auto buzz1 = mock_buzzer_.MakeBuzz("hello"); If you just need to return a pre-defined move-only value, you can use the
auto buzz2 = mock_buzzer_.MakeBuzz("hello"); `Return(ByMove(...))` action:
EXPECT_NE(nullptr, buzz1);
EXPECT_NE(nullptr, buzz2);
EXPECT_NE(buzz1, buzz2);
// Resets the default action for return type std::unique_ptr<Buzz>, ```cpp
// to avoid interfere with other tests.
DefaultValue<std::unique_ptr<Buzz>>::Clear();
```
What if you want the method to do something other than the default action? If you just need to return a pre-defined move-only value, you can use the `Return(ByMove(...))` action:
```
// When this fires, the unique_ptr<> specified by ByMove(...) will // When this fires, the unique_ptr<> specified by ByMove(...) will
// be returned. // be returned.
EXPECT_CALL(mock_buzzer_, MakeBuzz("world")) EXPECT_CALL(mock_buzzer_, MakeBuzz("world"))
...@@ -2343,81 +2318,87 @@ What if you want the method to do something other than the default action? If y ...@@ -2343,81 +2318,87 @@ What if you want the method to do something other than the default action? If y
Note that `ByMove()` is essential here - if you drop it, the code won’t compile. Note that `ByMove()` is essential here - if you drop it, the code won’t compile.
Quiz time! What do you think will happen if a `Return(ByMove(...))` action is performed more than once (e.g. you write `….WillRepeatedly(Return(ByMove(...)));`)? Come think of it, after the first time the action runs, the source value will be consumed (since it’s a move-only value), so the next time around, there’s no value to move from -- you’ll get a run-time error that `Return(ByMove(...))` can only be run once. Quiz time! What do you think will happen if a `Return(ByMove(...))` action is
performed more than once (e.g. you write
`.WillRepeatedly(Return(ByMove(...)));`)? Come think of it, after the first
time the action runs, the source value will be consumed (since it’s a move-only
value), so the next time around, there’s no value to move from -- you’ll get a
run-time error that `Return(ByMove(...))` can only be run once.
If you need your mock method to do more than just moving a pre-defined value, remember that you can always use `Invoke()` to call a lambda or a callable object, which can do pretty much anything you want: If you need your mock method to do more than just moving a pre-defined value,
remember that you can always use a lambda or a callable object, which can do
pretty much anything you want:
``` ```cpp
EXPECT_CALL(mock_buzzer_, MakeBuzz("x")) EXPECT_CALL(mock_buzzer_, MakeBuzz("x"))
.WillRepeatedly(Invoke([](const std::string& text) { .WillRepeatedly([](StringPiece text) {
return std::make_unique<Buzz>(AccessLevel::kInternal); return MakeUnique<Buzz>(AccessLevel::kInternal);
})); });
EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("x")); EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("x"));
EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("x")); EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("x"));
``` ```
Every time this `EXPECT_CALL` fires, a new `unique_ptr<Buzz>` will be created and returned. You cannot do this with `Return(ByMove(...))`. Every time this `EXPECT_CALL` fires, a new `unique_ptr<Buzz>` will be
created and returned. You cannot do this with `Return(ByMove(...))`.
Now there’s one topic we haven’t covered: how do you set expectations on `ShareBuzz()`, which takes a move-only-typed parameter? The answer is you don’t. Instead, you set expectations on the `DoShareBuzz()` mock method (remember that we defined a `MOCK_METHOD` for `DoShareBuzz()`, not `ShareBuzz()`): That covers returning move-only values; but how do we work with methods
accepting move-only arguments? The answer is that they work normally, although
some actions will not compile when any of method's arguments are move-only. You
can always use `Return`, or a [lambda or functor](#FunctionsAsActions):
``` ```cpp
EXPECT_CALL(mock_buzzer_, DoShareBuzz(NotNull(), _)); using ::testing::Unused;
// When one calls ShareBuzz() on the MockBuzzer like this, the call is EXPECT_CALL(mock_buzzer_, ShareBuzz(NotNull(), _)) .WillOnce(Return(true));
// forwarded to DoShareBuzz(), which is mocked. Therefore this statement EXPECT_TRUE(mock_buzzer_.ShareBuzz(MakeUnique<Buzz>(AccessLevel::kInternal)),
// will trigger the above EXPECT_CALL. 0);
mock_buzzer_.ShareBuzz(MakeUnique<Buzz>(AccessLevel::kInternal),
::base::Now()); EXPECT_CALL(mock_buzzer_, ShareBuzz(_, _)) .WillOnce(
[](std::unique_ptr<Buzz> buzz, Unused) { return buzz != nullptr; });
EXPECT_FALSE(mock_buzzer_.ShareBuzz(nullptr, 0));
``` ```
Some of you may have spotted one problem with this approach: the `DoShareBuzz()` mock method differs from the real `ShareBuzz()` method in that it cannot take ownership of the buzz parameter - `ShareBuzz()` will always delete buzz after `DoShareBuzz()` returns. What if you need to save the buzz object somewhere for later use when `ShareBuzz()` is called? Indeed, you'd be stuck. Many built-in actions (`WithArgs`, `WithoutArgs`,`DeleteArg`, `SaveArg`, ...)
could in principle support move-only arguments, but the support for this is not
implemented yet. If this is blocking you, please file a bug.
Another problem with the `DoShareBuzz()` we had is that it can surprise people reading or maintaining the test, as one would expect that `DoShareBuzz()` has (logically) the same contract as `ShareBuzz()`. A few actions (e.g. `DoAll`) copy their arguments internally, so they can never
work with non-copyable objects; you'll have to use functors instead.
Fortunately, these problems can be fixed with a bit more code. Let's try to get it right this time: ##### Legacy workarounds for move-only types {#LegacyMoveOnly}
``` Support for move-only function arguments was only introduced to gMock in April
2017. In older code, you may encounter the following workaround for the lack of
this feature (it is no longer necessary - we're including it just for
reference):
```cpp
class MockBuzzer : public Buzzer { class MockBuzzer : public Buzzer {
public: public:
MockBuzzer() {
// Since DoShareBuzz(buzz, time) is supposed to take ownership of
// buzz, define a default behavior for DoShareBuzz(buzz, time) to
// delete buzz.
ON_CALL(*this, DoShareBuzz(_, _))
.WillByDefault(Invoke([](Buzz* buzz, Time timestamp) {
delete buzz;
return true;
}));
}
MOCK_METHOD1(MakeBuzz, std::unique_ptr<Buzz>(const std::string& text));
// Takes ownership of buzz.
MOCK_METHOD2(DoShareBuzz, bool(Buzz* buzz, Time timestamp)); MOCK_METHOD2(DoShareBuzz, bool(Buzz* buzz, Time timestamp));
bool ShareBuzz(std::unique_ptr<Buzz> buzz, Time timestamp) { bool ShareBuzz(std::unique_ptr<Buzz> buzz, Time timestamp) override {
return DoShareBuzz(buzz.release(), timestamp); return DoShareBuzz(buzz.get(), timestamp);
} }
}; };
``` ```
Now, the mock `DoShareBuzz()` method is free to save the buzz argument for later use if this is what you want: The trick is to delegate the `ShareBuzz()` method to a mock method (let’s call
it `DoShareBuzz()`) that does not take move-only parameters. Then, instead of
setting expectations on `ShareBuzz()`, you set them on the `DoShareBuzz()` mock
method:
``` ```cpp
std::unique_ptr<Buzz> intercepted_buzz; MockBuzzer mock_buzzer_;
EXPECT_CALL(mock_buzzer_, DoShareBuzz(NotNull(), _)) EXPECT_CALL(mock_buzzer_, DoShareBuzz(NotNull(), _));
.WillOnce(Invoke([&intercepted_buzz](Buzz* buzz, Time timestamp) {
// Save buzz in intercepted_buzz for analysis later.
intercepted_buzz.reset(buzz);
return false;
}));
mock_buzzer_.ShareBuzz(std::make_unique<Buzz>(AccessLevel::kInternal), // When one calls ShareBuzz() on the MockBuzzer like this, the call is
Now()); // forwarded to DoShareBuzz(), which is mocked. Therefore this statement
EXPECT_NE(nullptr, intercepted_buzz); // will trigger the above EXPECT_CALL.
mock_buzzer_.ShareBuzz(MakeUnique<Buzz>(AccessLevel::kInternal), 0);
``` ```
Using the tricks covered in this recipe, you are now able to mock methods that take and/or return move-only types. Put your newly-acquired power to good use - when you design a new API, you can now feel comfortable using `unique_ptrs` as appropriate, without fearing that doing so will compromise your tests.
## Making the Compilation Faster ## ## Making the Compilation Faster ##
...@@ -3674,6 +3655,6 @@ This printer knows how to print built-in C++ types, native arrays, STL ...@@ -3674,6 +3655,6 @@ This printer knows how to print built-in C++ types, native arrays, STL
containers, and any type that supports the `<<` operator. For other containers, and any type that supports the `<<` operator. For other
types, it prints the raw bytes in the value and hopes that you the types, it prints the raw bytes in the value and hopes that you the
user can figure it out. user can figure it out.
[Google Test's advanced guide](../../googletest/docs/AdvancedGuide.md#teaching-google-test-how-to-print-your-values) [Google Test's advanced guide](../../googletest/docs/advanced.md#teaching-google-test-how-to-print-your-values)
explains how to extend the printer to do a better job at explains how to extend the printer to do a better job at
printing your particular type than to dump the bytes. printing your particular type than to dump the bytes.
...@@ -170,7 +170,7 @@ Admittedly, this test is contrived and doesn't do much. You can easily achieve t ...@@ -170,7 +170,7 @@ Admittedly, this test is contrived and doesn't do much. You can easily achieve t
## Using Google Mock with Any Testing Framework ## ## Using Google Mock with Any Testing Framework ##
If you want to use something other than Google Test (e.g. [CppUnit](http://sourceforge.net/projects/cppunit/) or If you want to use something other than Google Test (e.g. [CppUnit](http://sourceforge.net/projects/cppunit/) or
[CxxTest](http://cxxtest.tigris.org/)) as your testing framework, just change the `main()` function in the previous section to: [CxxTest](https://cxxtest.com/)) as your testing framework, just change the `main()` function in the previous section to:
``` ```
int main(int argc, char** argv) { int main(int argc, char** argv) {
// The following line causes Google Mock to throw an exception on failure, // The following line causes Google Mock to throw an exception on failure,
...@@ -187,7 +187,7 @@ sometimes causes the test program to crash. You'll still be able to ...@@ -187,7 +187,7 @@ sometimes causes the test program to crash. You'll still be able to
notice that the test has failed, but it's not a graceful failure. notice that the test has failed, but it's not a graceful failure.
A better solution is to use Google Test's A better solution is to use Google Test's
[event listener API](../../googletest/docs/AdvancedGuide.md#extending-google-test-by-handling-test-events) [event listener API](../../googletest/docs/advanced.md#extending-google-test-by-handling-test-events)
to report a test failure to your testing framework properly. You'll need to to report a test failure to your testing framework properly. You'll need to
implement the `OnTestPartResult()` method of the event listener interface, but it implement the `OnTestPartResult()` method of the event listener interface, but it
should be straightforward. should be straightforward.
......
...@@ -528,7 +528,7 @@ interface, which then can be easily mocked. It's a bit of work ...@@ -528,7 +528,7 @@ interface, which then can be easily mocked. It's a bit of work
initially, but usually pays for itself quickly. initially, but usually pays for itself quickly.
This Google Testing Blog This Google Testing Blog
[post](http://googletesting.blogspot.com/2008/06/defeat-static-cling.html) [post](https://testing.googleblog.com/2008/06/defeat-static-cling.html)
says it excellently. Check it out. says it excellently. Check it out.
## My mock object needs to do complex stuff. It's a lot of pain to specify the actions. Google Mock sucks! ## ## My mock object needs to do complex stuff. It's a lot of pain to specify the actions. Google Mock sucks! ##
...@@ -607,7 +607,6 @@ See this [recipe](CookBook.md#mocking_side_effects) for more details and an exam ...@@ -607,7 +607,6 @@ See this [recipe](CookBook.md#mocking_side_effects) for more details and an exam
If you cannot find the answer to your question in this FAQ, there are If you cannot find the answer to your question in this FAQ, there are
some other resources you can use: some other resources you can use:
1. read other [documentation](Documentation.md),
1. search the mailing list [archive](http://groups.google.com/group/googlemock/topics), 1. search the mailing list [archive](http://groups.google.com/group/googlemock/topics),
1. ask it on [googlemock@googlegroups.com](mailto:googlemock@googlegroups.com) and someone will answer it (to prevent spam, we require you to join the [discussion group](http://groups.google.com/group/googlemock) before you can post.). 1. ask it on [googlemock@googlegroups.com](mailto:googlemock@googlegroups.com) and someone will answer it (to prevent spam, we require you to join the [discussion group](http://groups.google.com/group/googlemock) before you can post.).
......
...@@ -26,13 +26,14 @@ ...@@ -26,13 +26,14 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
// Google Mock - a framework for writing C++ mock classes. // Google Mock - a framework for writing C++ mock classes.
// //
// This file implements some commonly used actions. // This file implements some commonly used actions.
// GOOGLETEST_CM0002 DO NOT DELETE
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_ #ifndef GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_
#define GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_ #define GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_
...@@ -360,14 +361,20 @@ class Action { ...@@ -360,14 +361,20 @@ class Action {
// Constructs a null Action. Needed for storing Action objects in // Constructs a null Action. Needed for storing Action objects in
// STL containers. // STL containers.
Action() : impl_(NULL) {} Action() {}
// Constructs an Action from its implementation. A NULL impl is #if GTEST_LANG_CXX11
// used to represent the "do-default" action. // Construct an Action from a specified callable.
explicit Action(ActionInterface<F>* impl) : impl_(impl) {} // This cannot take std::function directly, because then Action would not be
// directly constructible from lambda (it would require two conversions).
template <typename G,
typename = typename ::std::enable_if<
::std::is_constructible<::std::function<F>, G>::value>::type>
Action(G&& fun) : fun_(::std::forward<G>(fun)) {} // NOLINT
#endif
// Copy constructor. // Constructs an Action from its implementation.
Action(const Action& action) : impl_(action.impl_) {} explicit Action(ActionInterface<F>* impl) : impl_(impl) {}
// This constructor allows us to turn an Action<Func> object into an // This constructor allows us to turn an Action<Func> object into an
// Action<F>, as long as F's arguments can be implicitly converted // Action<F>, as long as F's arguments can be implicitly converted
...@@ -377,7 +384,13 @@ class Action { ...@@ -377,7 +384,13 @@ class Action {
explicit Action(const Action<Func>& action); explicit Action(const Action<Func>& action);
// Returns true iff this is the DoDefault() action. // Returns true iff this is the DoDefault() action.
bool IsDoDefault() const { return impl_.get() == NULL; } bool IsDoDefault() const {
#if GTEST_LANG_CXX11
return impl_ == nullptr && fun_ == nullptr;
#else
return impl_ == NULL;
#endif
}
// Performs the action. Note that this method is const even though // Performs the action. Note that this method is const even though
// the corresponding method in ActionInterface is not. The reason // the corresponding method in ActionInterface is not. The reason
...@@ -385,14 +398,15 @@ class Action { ...@@ -385,14 +398,15 @@ class Action {
// another concrete action, not that the concrete action it binds to // another concrete action, not that the concrete action it binds to
// cannot change state. (Think of the difference between a const // cannot change state. (Think of the difference between a const
// pointer and a pointer to const.) // pointer and a pointer to const.)
Result Perform(const ArgumentTuple& args) const { Result Perform(ArgumentTuple args) const {
internal::Assert( if (IsDoDefault()) {
!IsDoDefault(), __FILE__, __LINE__, internal::IllegalDoDefault(__FILE__, __LINE__);
"You are using DoDefault() inside a composite action like " }
"DoAll() or WithArgs(). This is not supported for technical " #if GTEST_LANG_CXX11
"reasons. Please instead spell out the default action, or " if (fun_ != nullptr) {
"assign the default action to an Action variable and use " return internal::Apply(fun_, ::std::move(args));
"the variable in various places."); }
#endif
return impl_->Perform(args); return impl_->Perform(args);
} }
...@@ -400,6 +414,18 @@ class Action { ...@@ -400,6 +414,18 @@ class Action {
template <typename F1, typename F2> template <typename F1, typename F2>
friend class internal::ActionAdaptor; friend class internal::ActionAdaptor;
template <typename G>
friend class Action;
// In C++11, Action can be implemented either as a generic functor (through
// std::function), or legacy ActionInterface. In C++98, only ActionInterface
// is available. The invariants are as follows:
// * in C++98, impl_ is null iff this is the default action
// * in C++11, at most one of fun_ & impl_ may be nonnull; both are null iff
// this is the default action
#if GTEST_LANG_CXX11
::std::function<F> fun_;
#endif
internal::linked_ptr<ActionInterface<F> > impl_; internal::linked_ptr<ActionInterface<F> > impl_;
}; };
...@@ -531,6 +557,9 @@ struct ByMoveWrapper { ...@@ -531,6 +557,9 @@ struct ByMoveWrapper {
// statement, and conversion of the result of Return to Action<T(U)> is a // statement, and conversion of the result of Return to Action<T(U)> is a
// good place for that. // good place for that.
// //
// The real life example of the above scenario happens when an invocation
// of gtl::Container() is passed into Return.
//
template <typename R> template <typename R>
class ReturnAction { class ReturnAction {
public: public:
...@@ -750,7 +779,7 @@ class DoDefaultAction { ...@@ -750,7 +779,7 @@ class DoDefaultAction {
// This template type conversion operator allows DoDefault() to be // This template type conversion operator allows DoDefault() to be
// used in any function. // used in any function.
template <typename F> template <typename F>
operator Action<F>() const { return Action<F>(NULL); } operator Action<F>() const { return Action<F>(); } // NOLINT
}; };
// Implements the Assign action to set a given pointer referent to a // Implements the Assign action to set a given pointer referent to a
...@@ -886,6 +915,28 @@ class InvokeMethodWithoutArgsAction { ...@@ -886,6 +915,28 @@ class InvokeMethodWithoutArgsAction {
GTEST_DISALLOW_ASSIGN_(InvokeMethodWithoutArgsAction); GTEST_DISALLOW_ASSIGN_(InvokeMethodWithoutArgsAction);
}; };
// Implements the InvokeWithoutArgs(callback) action.
template <typename CallbackType>
class InvokeCallbackWithoutArgsAction {
public:
// The c'tor takes ownership of the callback.
explicit InvokeCallbackWithoutArgsAction(CallbackType* callback)
: callback_(callback) {
callback->CheckIsRepeatable(); // Makes sure the callback is permanent.
}
// This type conversion operator template allows Invoke(callback) to
// be used wherever the callback's return type can be implicitly
// converted to that of the mock function.
template <typename Result, typename ArgumentTuple>
Result Perform(const ArgumentTuple&) const { return callback_->Run(); }
private:
const internal::linked_ptr<CallbackType> callback_;
GTEST_DISALLOW_ASSIGN_(InvokeCallbackWithoutArgsAction);
};
// Implements the IgnoreResult(action) action. // Implements the IgnoreResult(action) action.
template <typename A> template <typename A>
class IgnoreResultAction { class IgnoreResultAction {
...@@ -1053,7 +1104,13 @@ typedef internal::IgnoredValue Unused; ...@@ -1053,7 +1104,13 @@ typedef internal::IgnoredValue Unused;
template <typename To> template <typename To>
template <typename From> template <typename From>
Action<To>::Action(const Action<From>& from) Action<To>::Action(const Action<From>& from)
: impl_(new internal::ActionAdaptor<To, From>(from)) {} :
#if GTEST_LANG_CXX11
fun_(from.fun_),
#endif
impl_(from.impl_ == NULL ? NULL
: new internal::ActionAdaptor<To, From>(from)) {
}
// Creates an action that returns 'value'. 'value' is passed by value // Creates an action that returns 'value'. 'value' is passed by value
// instead of const reference - otherwise Return("string literal") // instead of const reference - otherwise Return("string literal")
......
...@@ -26,8 +26,7 @@ ...@@ -26,8 +26,7 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
// Google Mock - a framework for writing C++ mock classes. // Google Mock - a framework for writing C++ mock classes.
// //
...@@ -35,6 +34,8 @@ ...@@ -35,6 +34,8 @@
// cardinalities can be defined by the user implementing the // cardinalities can be defined by the user implementing the
// CardinalityInterface interface if necessary. // CardinalityInterface interface if necessary.
// GOOGLETEST_CM0002 DO NOT DELETE
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_ #ifndef GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
#define GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_ #define GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
......
$$ -*- mode: c++; -*- $$ -*- mode: c++; -*-
$$ This is a Pump source file. Please use Pump to convert it to $$ This is a Pump source file. Please use Pump to convert it to
$$ gmock-generated-actions.h. $$ gmock-generated-actions.h.
$$ $$
$var n = 10 $$ The maximum arity we support. $var n = 10 $$ The maximum arity we support.
...@@ -32,13 +32,14 @@ $$}} This meta comment fixes auto-indentation in editors. ...@@ -32,13 +32,14 @@ $$}} This meta comment fixes auto-indentation in editors.
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
// Google Mock - a framework for writing C++ mock classes. // Google Mock - a framework for writing C++ mock classes.
// //
// This file implements some commonly used variadic actions. // This file implements some commonly used variadic actions.
// GOOGLETEST_CM0002 DO NOT DELETE
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_ #ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_ #define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
...@@ -49,12 +50,13 @@ namespace testing { ...@@ -49,12 +50,13 @@ namespace testing {
namespace internal { namespace internal {
// InvokeHelper<F> knows how to unpack an N-tuple and invoke an N-ary // InvokeHelper<F> knows how to unpack an N-tuple and invoke an N-ary
// function or method with the unpacked values, where F is a function // function, method, or callback with the unpacked values, where F is
// type that takes N arguments. // a function type that takes N arguments.
template <typename Result, typename ArgumentTuple> template <typename Result, typename ArgumentTuple>
class InvokeHelper; class InvokeHelper;
$var max_callback_arity = 5
$range i 0..n $range i 0..n
$for i [[ $for i [[
$range j 1..i $range j 1..i
...@@ -76,10 +78,47 @@ class InvokeHelper<R, ::testing::tuple<$as> > { ...@@ -76,10 +78,47 @@ class InvokeHelper<R, ::testing::tuple<$as> > {
const ::testing::tuple<$as>&$args) { const ::testing::tuple<$as>&$args) {
return (obj_ptr->*method_ptr)($gets); return (obj_ptr->*method_ptr)($gets);
} }
$if i <= max_callback_arity [[
template <typename CallbackType>
static R InvokeCallback(CallbackType* callback,
const ::testing::tuple<$as>&$args) {
return callback->Run($gets);
}
]] $else [[
// There is no InvokeCallback() for $i-tuples
]]
}; };
]] ]]
// Implements the Invoke(callback) action.
template <typename CallbackType>
class InvokeCallbackAction {
public:
// The c'tor takes ownership of the callback.
explicit InvokeCallbackAction(CallbackType* callback)
: callback_(callback) {
callback->CheckIsRepeatable(); // Makes sure the callback is permanent.
}
// This type conversion operator template allows Invoke(callback) to
// be used wherever the callback's type is compatible with that of
// the mock function, i.e. if the mock function's arguments can be
// implicitly converted to the callback's arguments and the
// callback's result can be implicitly converted to the mock
// function's result.
template <typename Result, typename ArgumentTuple>
Result Perform(const ArgumentTuple& args) const {
return InvokeHelper<Result, ArgumentTuple>::InvokeCallback(
callback_.get(), args);
}
private:
const linked_ptr<CallbackType> callback_;
};
// An INTERNAL macro for extracting the type of a tuple field. It's // An INTERNAL macro for extracting the type of a tuple field. It's
// subject to change without notice - DO NOT USE IN USER CODE! // subject to change without notice - DO NOT USE IN USER CODE!
#define GMOCK_FIELD_(Tuple, N) \ #define GMOCK_FIELD_(Tuple, N) \
...@@ -486,7 +525,7 @@ _VALUE_PARAMS($for j, [[p$j]]) $for j [[, typename p$j##_type]] ...@@ -486,7 +525,7 @@ _VALUE_PARAMS($for j, [[p$j]]) $for j [[, typename p$j##_type]]
$for i [[ $for i [[
$range j 0..i-1 $range j 0..i-1
#define GMOCK_INTERNAL_INIT_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]])\ #define GMOCK_INTERNAL_INIT_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]])\
($for j, [[p$j##_type gmock_p$j]])$if i>0 [[ : ]]$for j, [[p$j(gmock_p$j)]] ($for j, [[p$j##_type gmock_p$j]])$if i>0 [[ : ]]$for j, [[p$j(::testing::internal::move(gmock_p$j))]]
]] ]]
...@@ -619,7 +658,7 @@ $var class_name = [[name##Action[[$if i==0 [[]] $elif i==1 [[P]] ...@@ -619,7 +658,7 @@ $var class_name = [[name##Action[[$if i==0 [[]] $elif i==1 [[P]]
$range j 0..i-1 $range j 0..i-1
$var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]] $var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]]
$var param_types_and_names = [[$for j, [[p$j##_type p$j]]]] $var param_types_and_names = [[$for j, [[p$j##_type p$j]]]]
$var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(gmock_p$j)]]]]]] $var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(::testing::internal::forward<p$j##_type>(gmock_p$j))]]]]]]
$var param_field_decls = [[$for j $var param_field_decls = [[$for j
[[ [[
......
...@@ -31,13 +31,14 @@ $var n = 10 $$ The maximum arity we support. ...@@ -31,13 +31,14 @@ $var n = 10 $$ The maximum arity we support.
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: wan@google.com (Zhanyong Wan)
// Google Mock - a framework for writing C++ mock classes. // Google Mock - a framework for writing C++ mock classes.
// //
// This file implements function mockers of various arities. // This file implements function mockers of various arities.
// GOOGLETEST_CM0002 DO NOT DELETE
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ #ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ #define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
...@@ -68,7 +69,7 @@ $for i [[ ...@@ -68,7 +69,7 @@ $for i [[
$range j 1..i $range j 1..i
$var typename_As = [[$for j [[, typename A$j]]]] $var typename_As = [[$for j [[, typename A$j]]]]
$var As = [[$for j, [[A$j]]]] $var As = [[$for j, [[A$j]]]]
$var as = [[$for j, [[a$j]]]] $var as = [[$for j, [[internal::forward<A$j>(a$j)]]]]
$var Aas = [[$for j, [[A$j a$j]]]] $var Aas = [[$for j, [[A$j a$j]]]]
$var ms = [[$for j, [[m$j]]]] $var ms = [[$for j, [[m$j]]]]
$var matchers = [[$for j, [[const Matcher<A$j>& m$j]]]] $var matchers = [[$for j, [[const Matcher<A$j>& m$j]]]]
...@@ -79,13 +80,8 @@ class FunctionMocker<R($As)> : public ...@@ -79,13 +80,8 @@ class FunctionMocker<R($As)> : public
typedef R F($As); typedef R F($As);
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple; typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
MockSpec<F>& With($matchers) { MockSpec<F> With($matchers) {
return MockSpec<F>(this, ::testing::make_tuple($ms));
$if i >= 1 [[
this->current_spec().SetMatchers(::testing::make_tuple($ms));
]]
return this->current_spec();
} }
R Invoke($Aas) { R Invoke($Aas) {
...@@ -99,6 +95,58 @@ $if i >= 1 [[ ...@@ -99,6 +95,58 @@ $if i >= 1 [[
]] ]]
// Removes the given pointer; this is a helper for the expectation setter method
// for parameterless matchers.
//
// We want to make sure that the user cannot set a parameterless expectation on
// overloaded methods, including methods which are overloaded on const. Example:
//
// class MockClass {
// MOCK_METHOD0(GetName, string&());
// MOCK_CONST_METHOD0(GetName, const string&());
// };
//
// TEST() {
// // This should be an error, as it's not clear which overload is expected.
// EXPECT_CALL(mock, GetName).WillOnce(ReturnRef(value));
// }
//
// Here are the generated expectation-setter methods:
//
// class MockClass {
// // Overload 1
// MockSpec<string&()> gmock_GetName() { ... }
// // Overload 2. Declared const so that the compiler will generate an
// // error when trying to resolve between this and overload 4 in
// // 'gmock_GetName(WithoutMatchers(), nullptr)'.
// MockSpec<string&()> gmock_GetName(
// const WithoutMatchers&, const Function<string&()>*) const {
// // Removes const from this, calls overload 1
// return AdjustConstness_(this)->gmock_GetName();
// }
//
// // Overload 3
// const string& gmock_GetName() const { ... }
// // Overload 4
// MockSpec<const string&()> gmock_GetName(
// const WithoutMatchers&, const Function<const string&()>*) const {
// // Does not remove const, calls overload 3
// return AdjustConstness_const(this)->gmock_GetName();
// }
// }
//
template <typename MockType>
const MockType* AdjustConstness_const(const MockType* mock) {
return mock;
}
// Removes const from and returns the given pointer; this is a helper for the
// expectation setter method for parameterless matchers.
template <typename MockType>
MockType* AdjustConstness_(const MockType* mock) {
return const_cast<MockType*>(mock);
}
} // namespace internal } // namespace internal
// The style guide prohibits "using" statements in a namespace scope // The style guide prohibits "using" statements in a namespace scope
...@@ -134,11 +182,14 @@ using internal::FunctionMocker; ...@@ -134,11 +182,14 @@ using internal::FunctionMocker;
$for i [[ $for i [[
$range j 1..i $range j 1..i
$var arg_as = [[$for j, \ $var arg_as = [[$for j, [[GMOCK_ARG_(tn, $j, __VA_ARGS__) gmock_a$j]]]]
[[GMOCK_ARG_(tn, $j, __VA_ARGS__) gmock_a$j]]]] $var as = [[$for j, \
$var as = [[$for j, [[gmock_a$j]]]] [[::testing::internal::forward<GMOCK_ARG_(tn, $j, __VA_ARGS__)>(gmock_a$j)]]]]
$var matcher_as = [[$for j, \ $var matcher_arg_as = [[$for j, \
[[GMOCK_MATCHER_(tn, $j, __VA_ARGS__) gmock_a$j]]]] [[GMOCK_MATCHER_(tn, $j, __VA_ARGS__) gmock_a$j]]]]
$var matcher_as = [[$for j, [[gmock_a$j]]]]
$var anything_matchers = [[$for j, \
[[::testing::A<GMOCK_ARG_(tn, $j, __VA_ARGS__)>()]]]]
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! // INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
#define GMOCK_METHOD$i[[]]_(tn, constness, ct, Method, ...) \ #define GMOCK_METHOD$i[[]]_(tn, constness, ct, Method, ...) \
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
...@@ -149,11 +200,17 @@ $var matcher_as = [[$for j, \ ...@@ -149,11 +200,17 @@ $var matcher_as = [[$for j, \
GMOCK_MOCKER_($i, constness, Method).SetOwnerAndName(this, #Method); \ GMOCK_MOCKER_($i, constness, Method).SetOwnerAndName(this, #Method); \
return GMOCK_MOCKER_($i, constness, Method).Invoke($as); \ return GMOCK_MOCKER_($i, constness, Method).Invoke($as); \
} \ } \
::testing::MockSpec<__VA_ARGS__>& \ ::testing::MockSpec<__VA_ARGS__> \
gmock_##Method($matcher_as) constness { \ gmock_##Method($matcher_arg_as) constness { \
GMOCK_MOCKER_($i, constness, Method).RegisterOwner(this); \ GMOCK_MOCKER_($i, constness, Method).RegisterOwner(this); \
return GMOCK_MOCKER_($i, constness, Method).With($as); \ return GMOCK_MOCKER_($i, constness, Method).With($matcher_as); \
} \ } \
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
const ::testing::internal::WithoutMatchers&, \
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
return ::testing::internal::AdjustConstness_##constness(this)-> \
gmock_##Method($anything_matchers); \
} \
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_($i, constness, Method) mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_($i, constness, Method)
...@@ -263,7 +320,7 @@ class MockFunction; ...@@ -263,7 +320,7 @@ class MockFunction;
$for i [[ $for i [[
$range j 0..i-1 $range j 0..i-1
$var ArgTypes = [[$for j, [[A$j]]]] $var ArgTypes = [[$for j, [[A$j]]]]
$var ArgNames = [[$for j, [[a$j]]]] $var ArgValues = [[$for j, [[::std::move(a$j)]]]]
$var ArgDecls = [[$for j, [[A$j a$j]]]] $var ArgDecls = [[$for j, [[A$j a$j]]]]
template <typename R$for j [[, typename A$j]]> template <typename R$for j [[, typename A$j]]>
class MockFunction<R($ArgTypes)> { class MockFunction<R($ArgTypes)> {
...@@ -273,9 +330,9 @@ class MockFunction<R($ArgTypes)> { ...@@ -273,9 +330,9 @@ class MockFunction<R($ArgTypes)> {
MOCK_METHOD$i[[]]_T(Call, R($ArgTypes)); MOCK_METHOD$i[[]]_T(Call, R($ArgTypes));
#if GTEST_HAS_STD_FUNCTION_ #if GTEST_HAS_STD_FUNCTION_
std::function<R($ArgTypes)> AsStdFunction() { ::std::function<R($ArgTypes)> AsStdFunction() {
return [this]($ArgDecls) -> R { return [this]($ArgDecls) -> R {
return this->Call($ArgNames); return this->Call($ArgValues);
}; };
} }
#endif // GTEST_HAS_STD_FUNCTION_ #endif // GTEST_HAS_STD_FUNCTION_
......
$$ -*- mode: c++; -*- $$ -*- mode: c++; -*-
$$ This is a Pump source file. Please use Pump to convert it to $$ This is a Pump source file. Please use Pump to convert
$$ gmock-generated-actions.h. $$ it to gmock-generated-matchers.h.
$$ $$
$var n = 10 $$ The maximum arity we support. $var n = 10 $$ The maximum arity we support.
$$ }} This line fixes auto-indentation of the following code in Emacs. $$ }} This line fixes auto-indentation of the following code in Emacs.
...@@ -37,6 +37,8 @@ $$ }} This line fixes auto-indentation of the following code in Emacs. ...@@ -37,6 +37,8 @@ $$ }} This line fixes auto-indentation of the following code in Emacs.
// //
// This file implements some commonly used variadic matchers. // This file implements some commonly used variadic matchers.
// GOOGLETEST_CM0002 DO NOT DELETE
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ #ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ #define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
...@@ -303,6 +305,9 @@ $for j, [[ ...@@ -303,6 +305,9 @@ $for j, [[
// UnorderedElementsAre(e_1, e_2, ..., e_n) is an ElementsAre extension // UnorderedElementsAre(e_1, e_2, ..., e_n) is an ElementsAre extension
// that matches n elements in any order. We support up to n=$n arguments. // that matches n elements in any order. We support up to n=$n arguments.
//
// If you have >$n elements, consider UnorderedElementsAreArray() or
// UnorderedPointwise() instead.
$range i 0..n $range i 0..n
$for i [[ $for i [[
...@@ -479,7 +484,7 @@ $$ // show up in the generated code. ...@@ -479,7 +484,7 @@ $$ // show up in the generated code.
// using testing::PrintToString; // using testing::PrintToString;
// //
// MATCHER_P2(InClosedRange, low, hi, // MATCHER_P2(InClosedRange, low, hi,
// string(negation ? "is not" : "is") + " in range [" + // std::string(negation ? "is not" : "is") + " in range [" +
// PrintToString(low) + ", " + PrintToString(hi) + "]") { // PrintToString(low) + ", " + PrintToString(hi) + "]") {
// return low <= arg && arg <= hi; // return low <= arg && arg <= hi;
// } // }
...@@ -604,32 +609,34 @@ $var template = [[$if i==0 [[]] $else [[ ...@@ -604,32 +609,34 @@ $var template = [[$if i==0 [[]] $else [[
]]]] ]]]]
$var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]] $var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]]
$var impl_ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]] $var impl_ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]]
$var impl_inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(gmock_p$j)]]]]]] $var impl_inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(::testing::internal::move(gmock_p$j))]]]]]]
$var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(gmock_p$j)]]]]]] $var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(::testing::internal::move(gmock_p$j))]]]]]]
$var params = [[$for j, [[p$j]]]] $var params = [[$for j, [[p$j]]]]
$var param_types = [[$if i==0 [[]] $else [[<$for j, [[p$j##_type]]>]]]] $var param_types = [[$if i==0 [[]] $else [[<$for j, [[p$j##_type]]>]]]]
$var param_types_and_names = [[$for j, [[p$j##_type p$j]]]] $var param_types_and_names = [[$for j, [[p$j##_type p$j]]]]
$var param_field_decls = [[$for j $var param_field_decls = [[$for j
[[ [[
p$j##_type p$j;\ p$j##_type const p$j;\
]]]] ]]]]
$var param_field_decls2 = [[$for j $var param_field_decls2 = [[$for j
[[ [[
p$j##_type p$j;\ p$j##_type const p$j;\
]]]] ]]]]
#define $macro_name(name$for j [[, p$j]], description)\$template #define $macro_name(name$for j [[, p$j]], description)\$template
class $class_name {\ class $class_name {\
public:\ public:\
template <typename arg_type>\ template <typename arg_type>\
class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\ class gmock_Impl : public ::testing::MatcherInterface<\
GTEST_REFERENCE_TO_CONST_(arg_type)> {\
public:\ public:\
[[$if i==1 [[explicit ]]]]gmock_Impl($impl_ctor_param_list)\ [[$if i==1 [[explicit ]]]]gmock_Impl($impl_ctor_param_list)\
$impl_inits {}\ $impl_inits {}\
virtual bool MatchAndExplain(\ virtual bool MatchAndExplain(\
arg_type arg, ::testing::MatchResultListener* result_listener) const;\ GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
::testing::MatchResultListener* result_listener) const;\
virtual void DescribeTo(::std::ostream* gmock_os) const {\ virtual void DescribeTo(::std::ostream* gmock_os) const {\
*gmock_os << FormatDescription(false);\ *gmock_os << FormatDescription(false);\
}\ }\
...@@ -637,17 +644,15 @@ $var param_field_decls2 = [[$for j ...@@ -637,17 +644,15 @@ $var param_field_decls2 = [[$for j
*gmock_os << FormatDescription(true);\ *gmock_os << FormatDescription(true);\
}\$param_field_decls }\$param_field_decls
private:\ private:\
::testing::internal::string FormatDescription(bool negation) const {\ ::std::string FormatDescription(bool negation) const {\
const ::testing::internal::string gmock_description = (description);\ ::std::string gmock_description = (description);\
if (!gmock_description.empty()) {\ if (!gmock_description.empty())\
return gmock_description;\ return gmock_description;\
}\
return ::testing::internal::FormatMatcherDescription(\ return ::testing::internal::FormatMatcherDescription(\
negation, #name, \ negation, #name, \
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
::testing::tuple<$for j, [[p$j##_type]]>($for j, [[p$j]])));\ ::testing::tuple<$for j, [[p$j##_type]]>($for j, [[p$j]])));\
}\ }\
GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
};\ };\
template <typename arg_type>\ template <typename arg_type>\
operator ::testing::Matcher<arg_type>() const {\ operator ::testing::Matcher<arg_type>() const {\
...@@ -657,14 +662,13 @@ $var param_field_decls2 = [[$for j ...@@ -657,14 +662,13 @@ $var param_field_decls2 = [[$for j
[[$if i==1 [[explicit ]]]]$class_name($ctor_param_list)$inits {\ [[$if i==1 [[explicit ]]]]$class_name($ctor_param_list)$inits {\
}\$param_field_decls2 }\$param_field_decls2
private:\ private:\
GTEST_DISALLOW_ASSIGN_($class_name);\
};\$template };\$template
inline $class_name$param_types name($param_types_and_names) {\ inline $class_name$param_types name($param_types_and_names) {\
return $class_name$param_types($params);\ return $class_name$param_types($params);\
}\$template }\$template
template <typename arg_type>\ template <typename arg_type>\
bool $class_name$param_types::gmock_Impl<arg_type>::MatchAndExplain(\ bool $class_name$param_types::gmock_Impl<arg_type>::MatchAndExplain(\
arg_type arg, \ GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
const const
]] ]]
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment