mirror of
https://github.com/jbeder/yaml-cpp.git
synced 2025-09-09 12:41:17 +00:00
Compare commits
46 Commits
revert-984
...
0.8.0
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f732014112 | ||
![]() |
f6c8b17c3a | ||
![]() |
35b4498026 | ||
![]() |
b8882652fc | ||
![]() |
0e6e28d1a3 | ||
![]() |
74f63c1181 | ||
![]() |
987a604256 | ||
![]() |
55a8037daa | ||
![]() |
3ff7ab07ac | ||
![]() |
d7f672d141 | ||
![]() |
bdc5582b35 | ||
![]() |
1b50109f7b | ||
![]() |
4ae4cb7309 | ||
![]() |
97ebcf035a | ||
![]() |
85ad599d79 | ||
![]() |
c86a9e424c | ||
![]() |
255bf1f9bc | ||
![]() |
763b7d6c70 | ||
![]() |
e87ed7e5b1 | ||
![]() |
c73ee34704 | ||
![]() |
190ad502b5 | ||
![]() |
420c982310 | ||
![]() |
13626af92a | ||
![]() |
4c982d59dc | ||
![]() |
7d06655611 | ||
![]() |
0e6e98e8fb | ||
![]() |
4aad2b1666 | ||
![]() |
a6db7e32ac | ||
![]() |
669af4eb55 | ||
![]() |
edadfecdc6 | ||
![]() |
26e3b70407 | ||
![]() |
cdf89fa352 | ||
![]() |
f8e1a7be3b | ||
![]() |
bce601f2bf | ||
![]() |
d8d9419092 | ||
![]() |
974349d015 | ||
![]() |
5057a53293 | ||
![]() |
634578e477 | ||
![]() |
2b65c65e1b | ||
![]() |
328d2d85e8 | ||
![]() |
4564d9a131 | ||
![]() |
2f8997565b | ||
![]() |
1713859b05 | ||
![]() |
393a02a225 | ||
![]() |
0733aeb451 | ||
![]() |
0d9dbcfe8c |
72
.github/workflows/build.yml
vendored
Normal file
72
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
name: Github PR
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
workflow_dispatch:
|
||||
permissions: read-all
|
||||
jobs:
|
||||
cmake-build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
build: [static, shared]
|
||||
generator: ["Default Generator", "MinGW Makefiles"]
|
||||
exclude:
|
||||
- os: macos-latest
|
||||
build: shared
|
||||
- os: macos-latest
|
||||
generator: "MinGW Makefiles"
|
||||
- os: ubuntu-latest
|
||||
generator: "MinGW Makefiles"
|
||||
env:
|
||||
YAML_BUILD_SHARED_LIBS: ${{ matrix.build == 'shared' && 'ON' || 'OFF' }}
|
||||
YAML_CPP_BUILD_TESTS: 'ON'
|
||||
CMAKE_GENERATOR: >-
|
||||
${{format(matrix.generator != 'Default Generator' && '-G "{0}"' || '', matrix.generator)}}
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Get number of CPU cores
|
||||
uses: SimenB/github-actions-cpu-cores@v1
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: |
|
||||
cmake ${{ env.CMAKE_GENERATOR }} -S "${{ github.workspace }}" -B build -DYAML_BUILD_SHARED_LIBS=${{ env.YAML_BUILD_SHARED_LIBS }}
|
||||
cd build && cmake --build . --parallel ${{ steps.cpu-cores.outputs.count }}
|
||||
|
||||
- name: Build Tests
|
||||
shell: bash
|
||||
run: |
|
||||
cmake ${{ env.CMAKE_GENERATOR }} -S "${{ github.workspace }}" -B build -DYAML_BUILD_SHARED_LIBS=${{ env.YAML_BUILD_SHARED_LIBS }} -DYAML_CPP_BUILD_TESTS=${{ env.YAML_CPP_BUILD_TESTS }}
|
||||
cd build && cmake --build . --parallel ${{ steps.cpu-cores.outputs.count }}
|
||||
|
||||
- name: Run Tests
|
||||
shell: bash
|
||||
run: |
|
||||
cd build && ctest -C Debug --output-on-failure --verbose
|
||||
|
||||
bazel-build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: |
|
||||
cd "${{ github.workspace }}"
|
||||
bazel build :all
|
||||
|
||||
- name: Test
|
||||
shell: bash
|
||||
run: |
|
||||
cd "${{ github.workspace }}"
|
||||
bazel test test
|
||||
|
37
.travis.yml
37
.travis.yml
@@ -1,37 +0,0 @@
|
||||
language: c++
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
- os: osx
|
||||
compiler: clang
|
||||
- os: osx
|
||||
compiler: gcc
|
||||
env:
|
||||
- CTEST_OUTPUT_ON_FAILURE=1
|
||||
|
||||
before_script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake ..
|
||||
- cd ..
|
||||
script:
|
||||
- cmake --build build
|
||||
- cmake --build build --target test
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.9
|
||||
packages:
|
||||
- g++-4.9
|
||||
- clang-3.9
|
||||
update: true
|
||||
homebrew:
|
||||
packages:
|
||||
- ccache
|
||||
- gcc@4.9
|
||||
- llvm@4
|
||||
update: true
|
@@ -1,3 +1,9 @@
|
||||
yaml_cpp_defines = select({
|
||||
# On Windows, ensure static linking is used.
|
||||
"@platforms//os:windows": ["YAML_CPP_STATIC_DEFINE", "YAML_CPP_NO_CONTRIB"],
|
||||
"//conditions:default": [],
|
||||
})
|
||||
|
||||
cc_library(
|
||||
name = "yaml-cpp_internal",
|
||||
visibility = ["//:__subpackages__"],
|
||||
@@ -11,4 +17,5 @@ cc_library(
|
||||
includes = ["include"],
|
||||
hdrs = glob(["include/**/*.h"]),
|
||||
srcs = glob(["src/**/*.cpp", "src/**/*.h"]),
|
||||
defines = yaml_cpp_defines,
|
||||
)
|
||||
|
104
CMakeLists.txt
104
CMakeLists.txt
@@ -7,40 +7,41 @@ if(POLICY CMP0091)
|
||||
cmake_policy(SET CMP0091 NEW)
|
||||
endif()
|
||||
|
||||
project(YAML_CPP VERSION 0.7.0 LANGUAGES CXX)
|
||||
project(YAML_CPP VERSION 0.8.0 LANGUAGES CXX)
|
||||
|
||||
set(YAML_CPP_MAIN_PROJECT OFF)
|
||||
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
|
||||
set(YAML_CPP_MAIN_PROJECT ON)
|
||||
endif()
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(CMakeDependentOption)
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(GNUInstallDirs)
|
||||
include(CTest)
|
||||
include(GenerateExportHeader)
|
||||
|
||||
set(CMAKE_C_VISIBILITY_PRESET hidden)
|
||||
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
|
||||
set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
|
||||
|
||||
find_program(YAML_CPP_CLANG_FORMAT_EXE NAMES clang-format)
|
||||
|
||||
option(YAML_CPP_BUILD_CONTRIB "Enable yaml-cpp contrib in library" ON)
|
||||
option(YAML_CPP_BUILD_TOOLS "Enable parse tools" ON)
|
||||
option(YAML_BUILD_SHARED_LIBS "Build yaml-cpp shared library" ${BUILD_SHARED_LIBS})
|
||||
|
||||
option(YAML_CPP_INSTALL "Enable generation of yaml-cpp install targets" ${YAML_CPP_MAIN_PROJECT})
|
||||
option(YAML_CPP_FORMAT_SOURCE "Format source" ON)
|
||||
cmake_dependent_option(YAML_CPP_BUILD_TESTS
|
||||
"Enable yaml-cpp tests" ON
|
||||
"BUILD_TESTING;CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
|
||||
cmake_dependent_option(YAML_CPP_INSTALL
|
||||
"Enable generation of yaml-cpp install targets" ON
|
||||
"CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
|
||||
"Enable yaml-cpp tests" OFF
|
||||
"BUILD_TESTING;YAML_CPP_MAIN_PROJECT" OFF)
|
||||
cmake_dependent_option(YAML_MSVC_SHARED_RT
|
||||
"MSVC: Build yaml-cpp with shared runtime libs (/MD)" ON
|
||||
"MSVC" OFF)
|
||||
"CMAKE_SYSTEM_NAME MATCHES Windows" OFF)
|
||||
|
||||
if (YAML_CPP_FORMAT_SOURCE)
|
||||
find_program(YAML_CPP_CLANG_FORMAT_EXE NAMES clang-format)
|
||||
endif()
|
||||
|
||||
set(yaml-cpp-type STATIC)
|
||||
set(yaml-cpp-label-postfix "static")
|
||||
if (YAML_BUILD_SHARED_LIBS)
|
||||
set(yaml-cpp-type SHARED)
|
||||
set(yaml-cpp-label-postfix "shared")
|
||||
else()
|
||||
set(yaml-cpp-type STATIC)
|
||||
set(yaml-cpp-label-postfix "static")
|
||||
endif()
|
||||
|
||||
set(build-shared $<BOOL:${YAML_BUILD_SHARED_LIBS}>)
|
||||
@@ -83,10 +84,13 @@ set_property(TARGET yaml-cpp
|
||||
PROPERTY
|
||||
CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
if (NOT YAML_BUILD_SHARED_LIBS)
|
||||
set_property(TARGET yaml-cpp PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
endif()
|
||||
|
||||
target_include_directories(yaml-cpp
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
PRIVATE
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>)
|
||||
@@ -97,11 +101,15 @@ if (NOT DEFINED CMAKE_CXX_STANDARD)
|
||||
CXX_STANDARD 11)
|
||||
endif()
|
||||
|
||||
if(YAML_CPP_MAIN_PROJECT)
|
||||
target_compile_options(yaml-cpp
|
||||
PRIVATE
|
||||
$<${not-msvc}:-Wall -Wextra -Wshadow -Weffc++ -Wno-long-long>
|
||||
$<${not-msvc}:-pedantic -pedantic-errors>)
|
||||
endif()
|
||||
|
||||
target_compile_options(yaml-cpp
|
||||
PRIVATE
|
||||
$<${not-msvc}:-Wall -Wextra -Wshadow -Weffc++ -Wno-long-long>
|
||||
$<${not-msvc}:-pedantic -pedantic-errors>
|
||||
|
||||
$<$<AND:${backport-msvc-runtime},${msvc-rt-mtd-static}>:-MTd>
|
||||
$<$<AND:${backport-msvc-runtime},${msvc-rt-mt-static}>:-MT>
|
||||
$<$<AND:${backport-msvc-runtime},${msvc-rt-mtd-dll}>:-MDd>
|
||||
@@ -114,6 +122,8 @@ target_compile_options(yaml-cpp
|
||||
$<$<CXX_COMPILER_ID:MSVC>:/W3 /wd4127 /wd4355>)
|
||||
|
||||
target_compile_definitions(yaml-cpp
|
||||
PUBLIC
|
||||
$<$<NOT:$<BOOL:${YAML_BUILD_SHARED_LIBS}>>:YAML_CPP_STATIC_DEFINE>
|
||||
PRIVATE
|
||||
$<${build-windows-dll}:${PROJECT_NAME}_DLL>
|
||||
$<$<NOT:$<BOOL:${YAML_CPP_BUILD_CONTRIB}>>:YAML_CPP_NO_CONTRIB>)
|
||||
@@ -133,57 +143,65 @@ set_target_properties(yaml-cpp PROPERTIES
|
||||
PROJECT_LABEL "yaml-cpp ${yaml-cpp-label-postfix}"
|
||||
DEBUG_POSTFIX "${CMAKE_DEBUG_POSTFIX}")
|
||||
|
||||
set(CONFIG_EXPORT_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/yaml-cpp")
|
||||
set(EXPORT_TARGETS yaml-cpp)
|
||||
configure_package_config_file(
|
||||
"${PROJECT_SOURCE_DIR}/yaml-cpp-config.cmake.in"
|
||||
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake"
|
||||
INSTALL_DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/yaml-cpp")
|
||||
INSTALL_DESTINATION "${CONFIG_EXPORT_DIR}"
|
||||
PATH_VARS CMAKE_INSTALL_INCLUDEDIR CMAKE_INSTALL_LIBDIR CONFIG_EXPORT_DIR YAML_BUILD_SHARED_LIBS)
|
||||
unset(EXPORT_TARGETS)
|
||||
|
||||
write_basic_package_version_file(
|
||||
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake"
|
||||
COMPATIBILITY AnyNewerVersion)
|
||||
|
||||
generate_export_header(yaml-cpp
|
||||
BASE_NAME YAML_CPP
|
||||
EXPORT_FILE_NAME "${PROJECT_BINARY_DIR}/include/yaml-cpp/dll.h"
|
||||
EXPORT_MACRO_NAME YAML_CPP_API
|
||||
)
|
||||
|
||||
configure_file(yaml-cpp.pc.in yaml-cpp.pc @ONLY)
|
||||
|
||||
if (YAML_CPP_INSTALL)
|
||||
install(TARGETS yaml-cpp
|
||||
install(TARGETS yaml-cpp
|
||||
EXPORT yaml-cpp-targets
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/
|
||||
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
FILES_MATCHING PATTERN "*.h")
|
||||
install(DIRECTORY ${PROJECT_BINARY_DIR}/include/
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
FILES_MATCHING PATTERN "*.h")
|
||||
FILES_MATCHING PATTERN "*.h")
|
||||
install(EXPORT yaml-cpp-targets
|
||||
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/yaml-cpp")
|
||||
install(FILES
|
||||
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake"
|
||||
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake"
|
||||
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/yaml-cpp")
|
||||
NAMESPACE yaml-cpp::
|
||||
DESTINATION "${CONFIG_EXPORT_DIR}")
|
||||
install(FILES
|
||||
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake"
|
||||
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake"
|
||||
DESTINATION "${CONFIG_EXPORT_DIR}")
|
||||
install(FILES "${PROJECT_BINARY_DIR}/yaml-cpp.pc"
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/pkgconfig)
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
endif()
|
||||
unset(CONFIG_EXPORT_DIR)
|
||||
|
||||
if(YAML_CPP_BUILD_TESTS)
|
||||
add_subdirectory(test)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
if(YAML_CPP_BUILD_TOOLS)
|
||||
add_subdirectory(util)
|
||||
add_subdirectory(util)
|
||||
endif()
|
||||
|
||||
if (YAML_CPP_CLANG_FORMAT_EXE)
|
||||
if (YAML_CPP_FORMAT_SOURCE AND YAML_CPP_CLANG_FORMAT_EXE)
|
||||
add_custom_target(format
|
||||
COMMAND clang-format --style=file -i $<TARGET_PROPERTY:yaml-cpp,SOURCES>
|
||||
COMMAND_EXPAND_LISTS
|
||||
COMMENT "Running clang-format"
|
||||
VERBATIM)
|
||||
endif()
|
||||
|
||||
# uninstall target
|
||||
if(NOT TARGET uninstall)
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||
IMMEDIATE @ONLY)
|
||||
|
||||
add_custom_target(uninstall
|
||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
|
||||
endif()
|
||||
|
@@ -17,7 +17,7 @@ Commit messages should be in the imperative mood, as described in the [Git contr
|
||||
|
||||
# Tests
|
||||
|
||||
Please verify the tests pass by running the target `tests/run_tests`.
|
||||
Please verify the tests pass by running the target `test/yaml-cpp-tests`.
|
||||
|
||||
If you are adding functionality, add tests accordingly.
|
||||
|
||||
|
48
README.md
48
README.md
@@ -1,50 +1,46 @@
|
||||
# yaml-cpp [](https://travis-ci.org/jbeder/yaml-cpp) [](https://codedocs.xyz/jbeder/yaml-cpp/)
|
||||
# yaml-cpp  [](https://codedocs.xyz/jbeder/yaml-cpp/)
|
||||
|
||||
yaml-cpp is a [YAML](http://www.yaml.org/) parser and emitter in C++ matching the [YAML 1.2 spec](http://www.yaml.org/spec/1.2/spec.html).
|
||||
`yaml-cpp` is a [YAML](http://www.yaml.org/) parser and emitter in C++ matching the [YAML 1.2 spec](http://www.yaml.org/spec/1.2/spec.html).
|
||||
|
||||
To get a feel for how it can be used, see the [Tutorial](https://github.com/jbeder/yaml-cpp/wiki/Tutorial) or [How to Emit YAML](https://github.com/jbeder/yaml-cpp/wiki/How-To-Emit-YAML). For the old API (version < 0.5.0), see [How To Parse A Document](https://github.com/jbeder/yaml-cpp/wiki/How-To-Parse-A-Document-(Old-API)).
|
||||
## Usage
|
||||
|
||||
# Problems? #
|
||||
See [Tutorial](https://github.com/jbeder/yaml-cpp/wiki/Tutorial) and [How to Emit YAML](https://github.com/jbeder/yaml-cpp/wiki/How-To-Emit-YAML) for reference. For the old API (until 0.5.0), see [How To Parse A Document](https://github.com/jbeder/yaml-cpp/wiki/How-To-Parse-A-Document-(Old-API)).
|
||||
|
||||
## Any Problems?
|
||||
|
||||
If you find a bug, post an [issue](https://github.com/jbeder/yaml-cpp/issues)! If you have questions about how to use yaml-cpp, please post it on http://stackoverflow.com and tag it [`yaml-cpp`](http://stackoverflow.com/questions/tagged/yaml-cpp).
|
||||
|
||||
# How to Build #
|
||||
## How to Build
|
||||
|
||||
yaml-cpp uses [CMake](http://www.cmake.org) to support cross-platform building. The basic steps to build are:
|
||||
`yaml-cpp` uses [CMake](http://www.cmake.org) to support cross-platform building. Install [CMake](http://www.cmake.org) _(Resources -> Download)_ before proceeding. The basic steps to build are:
|
||||
|
||||
1. Download and install [CMake](http://www.cmake.org) (Resources -> Download).
|
||||
**Note:** If you don't use the provided installer for your platform, make sure that you add `CMake`'s bin folder to your path.
|
||||
|
||||
**Note:** If you don't use the provided installer for your platform, make sure that you add CMake's bin folder to your path.
|
||||
#### 1. Navigate into the source directory, create build folder and run `CMake`:
|
||||
|
||||
2. Navigate into the source directory, and type:
|
||||
|
||||
```
|
||||
```sh
|
||||
mkdir build
|
||||
cd build
|
||||
cmake [-G generator] [-DYAML_BUILD_SHARED_LIBS=on|OFF] ..
|
||||
```
|
||||
|
||||
3. Run CMake. The basic syntax is:
|
||||
* The `generator` option is the build system you'd like to use. Run `cmake` without arguments to see a full list of available generators.
|
||||
* On Windows, you might use "Visual Studio 12 2013" (VS 2013 32-bits), or "Visual Studio 14 2015 Win64" (VS 2015 64-bits).
|
||||
* On OS X, you might use "Xcode".
|
||||
* On a UNIX-like system, omit the option (for a Makefile).
|
||||
|
||||
```
|
||||
cmake [-G generator] [-DYAML_BUILD_SHARED_LIBS=ON|OFF] ..
|
||||
```
|
||||
|
||||
* The `generator` is whatever type of build system you'd like to use. To see a full list of generators on your platform, just run `cmake` (with no arguments). For example:
|
||||
* On Windows, you might use "Visual Studio 12 2013" to generate a Visual Studio 2013 solution or "Visual Studio 14 2015 Win64" to generate a 64-bit Visual Studio 2015 solution.
|
||||
* On OS X, you might use "Xcode" to generate an Xcode project
|
||||
* On a UNIX-y system, simply omit the option to generate a makefile
|
||||
|
||||
* yaml-cpp defaults to building a static library, but you may build a shared library by specifying `-DYAML_BUILD_SHARED_LIBS=ON`.
|
||||
* `yaml-cpp` builds a static library by default, you may want to build a shared library by specifying `-DYAML_BUILD_SHARED_LIBS=ON`.
|
||||
|
||||
* For more options on customizing the build, see the [CMakeLists.txt](https://github.com/jbeder/yaml-cpp/blob/master/CMakeLists.txt) file.
|
||||
|
||||
4. Build it!
|
||||
#### 2. Build it!
|
||||
* The command you'll need to run depends on the generator you chose earlier.
|
||||
|
||||
5. To clean up, just remove the `build` directory.
|
||||
**Note:** To clean up, just remove the `build` directory.
|
||||
|
||||
# Recent Release #
|
||||
## Recent Releases
|
||||
|
||||
[yaml-cpp 0.6.0](https://github.com/jbeder/yaml-cpp/releases/tag/yaml-cpp-0.6.0) has been released! This release requires C++11, and no longer depends on Boost.
|
||||
[yaml-cpp 0.6.0](https://github.com/jbeder/yaml-cpp/releases/tag/yaml-cpp-0.6.0) released! This release requires C++11, and no longer depends on Boost.
|
||||
|
||||
[yaml-cpp 0.3.0](https://github.com/jbeder/yaml-cpp/releases/tag/release-0.3.0) is still available if you want the old API.
|
||||
|
||||
|
13
SECURITY.md
Normal file
13
SECURITY.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Security updates are applied only to the latest release.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released.
|
||||
|
||||
Please disclose it at [security advisory](https://github.com/jbeder/yaml-cpp/security/advisories/new).
|
||||
|
||||
This project is maintained by a team of volunteers on a reasonable-effort basis. As such, vulnerabilities will be disclosed in a best effort base.
|
28
appveyor.yml
28
appveyor.yml
@@ -1,28 +0,0 @@
|
||||
version: 1.0.{build}
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CMAKE_GENERATOR: Visual Studio 14 2015
|
||||
CMAKE_PLATFORM: win32
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CMAKE_GENERATOR: Visual Studio 14 2015
|
||||
CMAKE_PLATFORM: x64
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
CMAKE_GENERATOR: Visual Studio 15 2017
|
||||
CMAKE_PLATFORM: win32
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
CMAKE_GENERATOR: Visual Studio 15 2017
|
||||
CMAKE_PLATFORM: x64
|
||||
|
||||
before_build:
|
||||
- cmd: mkdir build
|
||||
- cmd: cd build
|
||||
- cmd: cmake .. -G "%CMAKE_GENERATOR%" -DCMAKE_GENERATOR_PLATFORM=%CMAKE_PLATFORM%
|
||||
- cmd: cd ..
|
||||
|
||||
build_script:
|
||||
- cmake --build build
|
||||
test_script:
|
||||
- cmd: cd build
|
||||
- ctest
|
21
cmake_uninstall.cmake.in
Normal file
21
cmake_uninstall.cmake.in
Normal file
@@ -0,0 +1,21 @@
|
||||
if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
|
||||
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt")
|
||||
endif()
|
||||
|
||||
file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files)
|
||||
string(REGEX REPLACE "\n" ";" files "${files}")
|
||||
foreach(file ${files})
|
||||
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
|
||||
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||
exec_program(
|
||||
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
|
||||
OUTPUT_VARIABLE rm_out
|
||||
RETURN_VALUE rm_retval
|
||||
)
|
||||
if(NOT "${rm_retval}" STREQUAL 0)
|
||||
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
|
||||
endif()
|
||||
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
|
||||
endif()
|
||||
endforeach()
|
61
include/yaml-cpp/dll.h
Normal file
61
include/yaml-cpp/dll.h
Normal file
@@ -0,0 +1,61 @@
|
||||
#ifndef DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
// Definition YAML_CPP_STATIC_DEFINE using to building YAML-CPP as static
|
||||
// library (definition created by CMake or defined manually)
|
||||
|
||||
// Definition yaml_cpp_EXPORTS using to building YAML-CPP as dll/so library
|
||||
// (definition created by CMake or defined manually)
|
||||
|
||||
#ifdef YAML_CPP_STATIC_DEFINE
|
||||
# define YAML_CPP_API
|
||||
# define YAML_CPP_NO_EXPORT
|
||||
#else
|
||||
# if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)
|
||||
# ifndef YAML_CPP_API
|
||||
# ifdef yaml_cpp_EXPORTS
|
||||
/* We are building this library */
|
||||
# pragma message( "Defining YAML_CPP_API for DLL export" )
|
||||
# define YAML_CPP_API __declspec(dllexport)
|
||||
# else
|
||||
/* We are using this library */
|
||||
# pragma message( "Defining YAML_CPP_API for DLL import" )
|
||||
# define YAML_CPP_API __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
# ifndef YAML_CPP_NO_EXPORT
|
||||
# define YAML_CPP_NO_EXPORT
|
||||
# endif
|
||||
# else /* No _MSC_VER */
|
||||
# ifndef YAML_CPP_API
|
||||
# ifdef yaml_cpp_EXPORTS
|
||||
/* We are building this library */
|
||||
# define YAML_CPP_API __attribute__((visibility("default")))
|
||||
# else
|
||||
/* We are using this library */
|
||||
# define YAML_CPP_API __attribute__((visibility("default")))
|
||||
# endif
|
||||
# endif
|
||||
# ifndef YAML_CPP_NO_EXPORT
|
||||
# define YAML_CPP_NO_EXPORT __attribute__((visibility("hidden")))
|
||||
# endif
|
||||
# endif /* _MSC_VER */
|
||||
#endif /* YAML_CPP_STATIC_DEFINE */
|
||||
|
||||
#ifndef YAML_CPP_DEPRECATED
|
||||
# ifdef _MSC_VER
|
||||
# define YAML_CPP_DEPRECATED __declspec(deprecated)
|
||||
# else
|
||||
# define YAML_CPP_DEPRECATED __attribute__ ((__deprecated__))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef YAML_CPP_DEPRECATED_EXPORT
|
||||
# define YAML_CPP_DEPRECATED_EXPORT YAML_CPP_API YAML_CPP_DEPRECATED
|
||||
#endif
|
||||
|
||||
#ifndef YAML_CPP_DEPRECATED_NO_EXPORT
|
||||
# define YAML_CPP_DEPRECATED_NO_EXPORT YAML_CPP_NO_EXPORT YAML_CPP_DEPRECATED
|
||||
#endif
|
||||
|
||||
#endif /* DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 */
|
@@ -12,10 +12,16 @@
|
||||
#include <limits>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
#include <valarray>
|
||||
#include <vector>
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
#include <string_view>
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/binary.h"
|
||||
#include "yaml-cpp/node/impl.h"
|
||||
#include "yaml-cpp/node/iterator.h"
|
||||
@@ -87,6 +93,20 @@ struct convert<char[N]> {
|
||||
static Node encode(const char* rhs) { return Node(rhs); }
|
||||
};
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
template <>
|
||||
struct convert<std::string_view> {
|
||||
static Node encode(std::string_view rhs) { return Node(std::string(rhs)); }
|
||||
|
||||
static bool decode(const Node& node, std::string_view& rhs) {
|
||||
if (!node.IsScalar())
|
||||
return false;
|
||||
rhs = node.Scalar();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template <>
|
||||
struct convert<_Null> {
|
||||
static Node encode(const _Null& /* rhs */) { return Node(); }
|
||||
@@ -127,7 +147,7 @@ ConvertStreamTo(std::stringstream& stream, T& rhs) {
|
||||
if ((stream >> std::noskipws >> num) && (stream >> std::ws).eof()) {
|
||||
if (num >= (std::numeric_limits<T>::min)() &&
|
||||
num <= (std::numeric_limits<T>::max)()) {
|
||||
rhs = (T)num;
|
||||
rhs = static_cast<T>(num);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -251,6 +271,32 @@ struct convert<std::map<K, V, C, A>> {
|
||||
}
|
||||
};
|
||||
|
||||
// std::unordered_map
|
||||
template <typename K, typename V, typename H, typename P, typename A>
|
||||
struct convert<std::unordered_map<K, V, H, P, A>> {
|
||||
static Node encode(const std::unordered_map<K, V, H, P, A>& rhs) {
|
||||
Node node(NodeType::Map);
|
||||
for (const auto& element : rhs)
|
||||
node.force_insert(element.first, element.second);
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, std::unordered_map<K, V, H, P, A>& rhs) {
|
||||
if (!node.IsMap())
|
||||
return false;
|
||||
|
||||
rhs.clear();
|
||||
for (const auto& element : node)
|
||||
#if defined(__GNUC__) && __GNUC__ < 4
|
||||
// workaround for GCC 3:
|
||||
rhs[element.first.template as<K>()] = element.second.template as<V>();
|
||||
#else
|
||||
rhs[element.first.as<K>()] = element.second.as<V>();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// std::vector
|
||||
template <typename T, typename A>
|
||||
struct convert<std::vector<T, A>> {
|
||||
@@ -336,6 +382,37 @@ struct convert<std::array<T, N>> {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// std::valarray
|
||||
template <typename T>
|
||||
struct convert<std::valarray<T>> {
|
||||
static Node encode(const std::valarray<T>& rhs) {
|
||||
Node node(NodeType::Sequence);
|
||||
for (const auto& element : rhs) {
|
||||
node.push_back(element);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, std::valarray<T>& rhs) {
|
||||
if (!node.IsSequence()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
rhs.resize(node.size());
|
||||
for (auto i = 0u; i < node.size(); ++i) {
|
||||
#if defined(__GNUC__) && __GNUC__ < 4
|
||||
// workaround for GCC 3:
|
||||
rhs[i] = node[i].template as<T>();
|
||||
#else
|
||||
rhs[i] = node[i].as<T>();
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// std::pair
|
||||
template <typename T, typename U>
|
||||
struct convert<std::pair<T, U>> {
|
||||
|
@@ -169,7 +169,7 @@ class node {
|
||||
using nodes = std::set<node*, less>;
|
||||
nodes m_dependencies;
|
||||
size_t m_index;
|
||||
static std::atomic<size_t> m_amount;
|
||||
static YAML_CPP_API std::atomic<size_t> m_amount;
|
||||
};
|
||||
} // namespace detail
|
||||
} // namespace YAML
|
||||
|
@@ -7,7 +7,6 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/dll.h"
|
||||
#include <memory>
|
||||
|
||||
namespace YAML {
|
||||
|
@@ -107,9 +107,9 @@ struct disable_if : public disable_if_c<Cond::value, T> {};
|
||||
|
||||
template <typename S, typename T>
|
||||
struct is_streamable {
|
||||
template <typename SS, typename TT>
|
||||
template <typename StreamT, typename ValueT>
|
||||
static auto test(int)
|
||||
-> decltype(std::declval<SS&>() << std::declval<TT>(), std::true_type());
|
||||
-> decltype(std::declval<StreamT&>() << std::declval<ValueT>(), std::true_type());
|
||||
|
||||
template <typename, typename>
|
||||
static auto test(...) -> std::false_type;
|
||||
|
@@ -75,11 +75,11 @@ std::vector<unsigned char> DecodeBase64(const std::string &input) {
|
||||
|
||||
unsigned value = 0;
|
||||
for (std::size_t i = 0, cnt = 0; i < input.size(); i++) {
|
||||
if (std::isspace(input[i])) {
|
||||
if (std::isspace(static_cast<unsigned char>(input[i]))) {
|
||||
// skip newlines
|
||||
continue;
|
||||
}
|
||||
unsigned char d = decoding[static_cast<unsigned>(input[i])];
|
||||
unsigned char d = decoding[static_cast<unsigned char>(input[i])];
|
||||
if (d == 255)
|
||||
return ret_type();
|
||||
|
||||
|
@@ -13,7 +13,6 @@
|
||||
|
||||
#include "yaml-cpp/anchor.h"
|
||||
#include "yaml-cpp/contrib/anchordict.h"
|
||||
#include "yaml-cpp/contrib/graphbuilder.h"
|
||||
#include "yaml-cpp/emitterstyle.h"
|
||||
#include "yaml-cpp/eventhandler.h"
|
||||
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace YAML {
|
||||
Directives::Directives() : version{true, 1, 2}, tags{} {}
|
||||
|
||||
const std::string Directives::TranslateTagHandle(
|
||||
std::string Directives::TranslateTagHandle(
|
||||
const std::string& handle) const {
|
||||
auto it = tags.find(handle);
|
||||
if (it == tags.end()) {
|
||||
|
@@ -19,7 +19,7 @@ struct Version {
|
||||
struct Directives {
|
||||
Directives();
|
||||
|
||||
const std::string TranslateTagHandle(const std::string& handle) const;
|
||||
std::string TranslateTagHandle(const std::string& handle) const;
|
||||
|
||||
Version version;
|
||||
std::map<std::string, std::string> tags;
|
||||
|
@@ -533,7 +533,8 @@ void Emitter::BlockMapPrepareNode(EmitterNodeType::value child) {
|
||||
if (m_pState->GetMapKeyFormat() == LongKey)
|
||||
m_pState->SetLongKey();
|
||||
if (child == EmitterNodeType::BlockSeq ||
|
||||
child == EmitterNodeType::BlockMap)
|
||||
child == EmitterNodeType::BlockMap ||
|
||||
child == EmitterNodeType::Property)
|
||||
m_pState->SetLongKey();
|
||||
|
||||
if (m_pState->CurGroupLongKey())
|
||||
|
@@ -176,11 +176,11 @@ bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
|
||||
static const RegEx& disallowed_flow =
|
||||
Exp::EndScalarInFlow() | (Exp::BlankOrBreak() + Exp::Comment()) |
|
||||
Exp::NotPrintable() | Exp::Utf8_ByteOrderMark() | Exp::Break() |
|
||||
Exp::Tab();
|
||||
Exp::Tab() | Exp::Ampersand();
|
||||
static const RegEx& disallowed_block =
|
||||
Exp::EndScalar() | (Exp::BlankOrBreak() + Exp::Comment()) |
|
||||
Exp::NotPrintable() | Exp::Utf8_ByteOrderMark() | Exp::Break() |
|
||||
Exp::Tab();
|
||||
Exp::Tab() | Exp::Ampersand();
|
||||
const RegEx& disallowed =
|
||||
flowType == FlowType::Flow ? disallowed_flow : disallowed_block;
|
||||
|
||||
|
@@ -37,7 +37,7 @@ inline const RegEx& Blank() {
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& Break() {
|
||||
static const RegEx e = RegEx('\n') | RegEx("\r\n");
|
||||
static const RegEx e = RegEx('\n') | RegEx("\r\n") | RegEx('\r');
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& BlankOrBreak() {
|
||||
@@ -117,6 +117,10 @@ inline const RegEx& ValueInJSONFlow() {
|
||||
static const RegEx e = RegEx(':');
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& Ampersand() {
|
||||
static const RegEx e = RegEx('&');
|
||||
return e;
|
||||
}
|
||||
inline const RegEx Comment() {
|
||||
static const RegEx e = RegEx('#');
|
||||
return e;
|
||||
|
@@ -9,9 +9,7 @@
|
||||
|
||||
#include <cstddef>
|
||||
#include <ios>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
|
||||
|
@@ -29,7 +29,7 @@ Tag::Tag(const Token& token)
|
||||
}
|
||||
}
|
||||
|
||||
const std::string Tag::Translate(const Directives& directives) {
|
||||
std::string Tag::Translate(const Directives& directives) {
|
||||
switch (type) {
|
||||
case VERBATIM:
|
||||
return value;
|
||||
|
@@ -23,7 +23,7 @@ struct Tag {
|
||||
};
|
||||
|
||||
Tag(const Token& token);
|
||||
const std::string Translate(const Directives& directives);
|
||||
std::string Translate(const Directives& directives);
|
||||
|
||||
TYPE type;
|
||||
std::string handle, value;
|
||||
|
@@ -5,10 +5,10 @@ set(BUILD_MOCK ON CACHE BOOL "" FORCE)
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0048 NEW)
|
||||
|
||||
add_subdirectory(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.10.0"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.11.0"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/prefix")
|
||||
|
||||
include_directories(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.10.0/googletest/include")
|
||||
include_directories(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.11.0/googletest/include")
|
||||
|
||||
set(test-new-api-pattern "new-api/*.cpp")
|
||||
set(test-source-pattern "*.cpp" "integration/*.cpp" "node/*.cpp")
|
||||
@@ -46,4 +46,11 @@ if (NOT DEFINED CMAKE_CXX_STANDARD)
|
||||
endif()
|
||||
|
||||
|
||||
add_test(yaml-cpp::test yaml-cpp-tests)
|
||||
add_test(NAME yaml-cpp::test COMMAND yaml-cpp-tests)
|
||||
|
||||
if (build-windows-dll)
|
||||
add_custom_command(
|
||||
TARGET yaml-cpp-tests
|
||||
POST_BUILD COMMAND ${CMAKE_COMMAND} -E
|
||||
copy_if_different "$<TARGET_FILE:yaml-cpp>" "$<TARGET_FILE_DIR:yaml-cpp-tests>")
|
||||
endif()
|
||||
|
14
test/binary_test.cpp
Normal file
14
test/binary_test.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include <yaml-cpp/binary.h>
|
||||
|
||||
TEST(BinaryTest, DecodingSimple) {
|
||||
std::string input{90, 71, 86, 104, 90, 71, 74, 108, 90, 87, 89, 61};
|
||||
const std::vector<unsigned char> &result = YAML::DecodeBase64(input);
|
||||
EXPECT_EQ(std::string(result.begin(), result.end()), "deadbeef");
|
||||
}
|
||||
|
||||
TEST(BinaryTest, DecodingNoCrashOnNegative) {
|
||||
std::string input{-58, -1, -99, 109};
|
||||
const std::vector<unsigned char> &result = YAML::DecodeBase64(input);
|
||||
EXPECT_TRUE(result.empty());
|
||||
}
|
@@ -1,73 +0,0 @@
|
||||
# Build matrix / environment variable are explained on:
|
||||
# https://docs.travis-ci.com/user/customizing-the-build/
|
||||
# This file can be validated on:
|
||||
# http://lint.travis-ci.org/
|
||||
|
||||
language: cpp
|
||||
|
||||
# Define the matrix explicitly, manually expanding the combinations of (os, compiler, env).
|
||||
# It is more tedious, but grants us far more flexibility.
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
before_install: chmod -R +x ./ci/*platformio.sh
|
||||
install: ./ci/install-platformio.sh
|
||||
script: ./ci/build-platformio.sh
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: gcc
|
||||
install: ./ci/install-linux.sh && ./ci/log-config.sh
|
||||
script: ./ci/build-linux-bazel.sh
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: clang
|
||||
install: ./ci/install-linux.sh && ./ci/log-config.sh
|
||||
script: ./ci/build-linux-bazel.sh
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: BUILD_TYPE=Debug VERBOSE=1 CXX_FLAGS=-std=c++11
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 -Wgnu-zero-variadic-macro-arguments
|
||||
- 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
|
||||
compiler: gcc
|
||||
env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 HOMEBREW_LOGS=~/homebrew-logs HOMEBREW_TEMP=~/homebrew-temp
|
||||
- os: osx
|
||||
compiler: clang
|
||||
env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 HOMEBREW_LOGS=~/homebrew-logs HOMEBREW_TEMP=~/homebrew-temp
|
||||
|
||||
# These are the install and build (script) phases for the most common entries in the matrix. They could be included
|
||||
# in each entry in the matrix, but that is just repetitive.
|
||||
install:
|
||||
- ./ci/install-${TRAVIS_OS_NAME}.sh
|
||||
- . ./ci/env-${TRAVIS_OS_NAME}.sh
|
||||
- ./ci/log-config.sh
|
||||
|
||||
script: ./ci/travis.sh
|
||||
|
||||
# This section installs the necessary dependencies.
|
||||
addons:
|
||||
apt:
|
||||
# List of whitelisted in travis packages for ubuntu-precise can be found here:
|
||||
# https://github.com/travis-ci/apt-package-whitelist/blob/master/ubuntu-precise
|
||||
# List of whitelisted in travis apt-sources:
|
||||
# https://github.com/travis-ci/apt-source-whitelist/blob/master/ubuntu.json
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.9
|
||||
packages:
|
||||
- g++-4.9
|
||||
- clang-3.9
|
||||
update: true
|
||||
homebrew:
|
||||
packages:
|
||||
- ccache
|
||||
- gcc@4.9
|
||||
- llvm@4
|
||||
update: true
|
||||
|
||||
notifications:
|
||||
email: false
|
@@ -1,134 +0,0 @@
|
||||
# Google Test
|
||||
|
||||
#### OSS Builds Status:
|
||||
|
||||
[](https://travis-ci.org/google/googletest)
|
||||
[](https://ci.appveyor.com/project/GoogleTestAppVeyor/googletest/branch/master)
|
||||
|
||||
### Future Plans
|
||||
|
||||
#### 1.8.x Release:
|
||||
|
||||
[the 1.8.x](https://github.com/google/googletest/releases/tag/release-1.8.1) is
|
||||
the last release that works with pre-C++11 compilers. The 1.8.x will not accept
|
||||
any requests for any new features and any bugfix requests will only be accepted
|
||||
if proven "critical"
|
||||
|
||||
#### Post 1.8.x:
|
||||
|
||||
On-going 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
|
||||
|
||||
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!
|
||||
|
||||
This repository is a merger of the formerly separate GoogleTest and GoogleMock
|
||||
projects. These were so closely related that it makes sense to maintain and
|
||||
release them together.
|
||||
|
||||
Please subscribe to the mailing list at googletestframework@googlegroups.com for
|
||||
questions, discussions, and development.
|
||||
|
||||
### Getting started:
|
||||
|
||||
The information for **Google Test** is available in the
|
||||
[Google Test Primer](googletest/docs/primer.md) documentation.
|
||||
|
||||
**Google Mock** is an extension to Google Test for writing and using C++ mock
|
||||
classes. See the separate [Google Mock documentation](googlemock/README.md).
|
||||
|
||||
More detailed documentation for googletest is in its interior
|
||||
[googletest/README.md](googletest/README.md) file.
|
||||
|
||||
## Features
|
||||
|
||||
* An [xUnit](https://en.wikipedia.org/wiki/XUnit) test framework.
|
||||
* Test discovery.
|
||||
* A rich set of assertions.
|
||||
* User-defined assertions.
|
||||
* Death tests.
|
||||
* Fatal and non-fatal failures.
|
||||
* Value-parameterized tests.
|
||||
* Type-parameterized tests.
|
||||
* Various options for running the tests.
|
||||
* XML test report generation.
|
||||
|
||||
## Platforms
|
||||
|
||||
Google test has been used on a variety of platforms:
|
||||
|
||||
* Linux
|
||||
* Mac OS X
|
||||
* Windows
|
||||
* Cygwin
|
||||
* MinGW
|
||||
* Windows Mobile
|
||||
* Symbian
|
||||
* PlatformIO
|
||||
|
||||
## Who Is Using Google Test?
|
||||
|
||||
In addition to many internal projects at Google, Google Test is also used by the
|
||||
following notable projects:
|
||||
|
||||
* The [Chromium projects](http://www.chromium.org/) (behind the Chrome browser
|
||||
and Chrome OS).
|
||||
* The [LLVM](http://llvm.org/) compiler.
|
||||
* [Protocol Buffers](https://github.com/google/protobuf), Google's data
|
||||
interchange format.
|
||||
* The [OpenCV](http://opencv.org/) computer vision library.
|
||||
* [tiny-dnn](https://github.com/tiny-dnn/tiny-dnn): header only,
|
||||
dependency-free deep learning framework in C++11.
|
||||
|
||||
## Related Open Source Projects
|
||||
|
||||
[GTest Runner](https://github.com/nholthaus/gtest-runner) is a Qt5 based
|
||||
automated test-runner and Graphical User Interface with powerful features for
|
||||
Windows and Linux platforms.
|
||||
|
||||
[Google Test UI](https://github.com/ospector/gtest-gbar) is test runner that
|
||||
runs your test binary, allows you to track its progress via a progress bar, and
|
||||
displays a list of test failures. Clicking on one shows failure text. Google
|
||||
Test UI is written in C#.
|
||||
|
||||
[GTest TAP Listener](https://github.com/kinow/gtest-tap-listener) is an event
|
||||
listener for Google Test that implements the
|
||||
[TAP protocol](https://en.wikipedia.org/wiki/Test_Anything_Protocol) for test
|
||||
result output. If your test runner understands TAP, you may find it useful.
|
||||
|
||||
[gtest-parallel](https://github.com/google/gtest-parallel) is a test runner that
|
||||
runs tests from your binary in parallel to provide significant speed-up.
|
||||
|
||||
[GoogleTest Adapter](https://marketplace.visualstudio.com/items?itemName=DavidSchuldenfrei.gtest-adapter)
|
||||
is a VS Code extension allowing to view Google Tests in a tree view, and
|
||||
run/debug your tests.
|
||||
|
||||
## Requirements
|
||||
|
||||
Google Test is designed to have fairly minimal requirements to build and use
|
||||
with your projects, but there are some. If you notice any problems on your
|
||||
platform, please notify
|
||||
[googletestframework@googlegroups.com](https://groups.google.com/forum/#!forum/googletestframework).
|
||||
Patches for fixing them are welcome!
|
||||
|
||||
### Build Requirements
|
||||
|
||||
These are the base requirements to build and use Google Test from a source
|
||||
package:
|
||||
|
||||
* [Bazel](https://bazel.build/) or [CMake](https://cmake.org/). NOTE: Bazel is
|
||||
the build system that googletest is using internally and tests against.
|
||||
CMake is community-supported.
|
||||
|
||||
* a C++11-standard-compliant compiler
|
||||
|
||||
## Contributing change
|
||||
|
||||
Please read the [`CONTRIBUTING.md`](CONTRIBUTING.md) for details on how to
|
||||
contribute to this project.
|
||||
|
||||
Happy testing!
|
@@ -1,23 +0,0 @@
|
||||
workspace(name = "com_google_googletest")
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
# Abseil
|
||||
http_archive(
|
||||
name = "com_google_absl",
|
||||
urls = ["https://github.com/abseil/abseil-cpp/archive/master.zip"],
|
||||
strip_prefix = "abseil-cpp-master",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "rules_cc",
|
||||
strip_prefix = "rules_cc-master",
|
||||
urls = ["https://github.com/bazelbuild/rules_cc/archive/master.zip"],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "rules_python",
|
||||
strip_prefix = "rules_python-master",
|
||||
urls = ["https://github.com/bazelbuild/rules_python/archive/master.zip"],
|
||||
)
|
||||
|
@@ -1,154 +0,0 @@
|
||||
version: '{build}'
|
||||
|
||||
os: Visual Studio 2015
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- compiler: msvc-15-seh
|
||||
generator: "Visual Studio 15 2017"
|
||||
build_system: cmake
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
|
||||
- compiler: msvc-15-seh
|
||||
generator: "Visual Studio 15 2017 Win64"
|
||||
build_system: cmake
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
enabled_on_pr: yes
|
||||
|
||||
- compiler: msvc-15-seh
|
||||
build_system: bazel
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
enabled_on_pr: yes
|
||||
|
||||
- compiler: msvc-14-seh
|
||||
build_system: cmake
|
||||
generator: "Visual Studio 14 2015"
|
||||
enabled_on_pr: yes
|
||||
|
||||
- compiler: msvc-14-seh
|
||||
build_system: cmake
|
||||
generator: "Visual Studio 14 2015 Win64"
|
||||
|
||||
- compiler: gcc-6.3.0-posix
|
||||
build_system: cmake
|
||||
generator: "MinGW Makefiles"
|
||||
cxx_path: 'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin'
|
||||
enabled_on_pr: yes
|
||||
|
||||
configuration:
|
||||
- Debug
|
||||
|
||||
build:
|
||||
verbosity: minimal
|
||||
|
||||
install:
|
||||
- ps: |
|
||||
Write-Output "Compiler: $env:compiler"
|
||||
Write-Output "Generator: $env:generator"
|
||||
Write-Output "Env:Configuation: $env:configuration"
|
||||
Write-Output "Env: $env"
|
||||
if (-not (Test-Path env:APPVEYOR_PULL_REQUEST_NUMBER)) {
|
||||
Write-Output "This is *NOT* a pull request build"
|
||||
} else {
|
||||
Write-Output "This is a pull request build"
|
||||
if (-not (Test-Path env:enabled_on_pr) -or $env:enabled_on_pr -ne "yes") {
|
||||
Write-Output "PR builds are *NOT* explicitly enabled"
|
||||
}
|
||||
}
|
||||
|
||||
# install Bazel
|
||||
if ($env:build_system -eq "bazel") {
|
||||
appveyor DownloadFile https://github.com/bazelbuild/bazel/releases/download/0.28.1/bazel-0.28.1-windows-x86_64.exe -FileName bazel.exe
|
||||
}
|
||||
|
||||
if ($env:build_system -eq "cmake") {
|
||||
# git bash conflicts with MinGW makefiles
|
||||
if ($env:generator -eq "MinGW Makefiles") {
|
||||
$env:path = $env:path.replace("C:\Program Files\Git\usr\bin;", "")
|
||||
if ($env:cxx_path -ne "") {
|
||||
$env:path += ";$env:cxx_path"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
before_build:
|
||||
- ps: |
|
||||
$env:root=$env:APPVEYOR_BUILD_FOLDER
|
||||
Write-Output "env:root: $env:root"
|
||||
|
||||
build_script:
|
||||
- ps: |
|
||||
# Only enable some builds for pull requests, the AppVeyor queue is too long.
|
||||
if ((Test-Path env:APPVEYOR_PULL_REQUEST_NUMBER) -And (-not (Test-Path env:enabled_on_pr) -or $env:enabled_on_pr -ne "yes")) {
|
||||
return
|
||||
} else {
|
||||
# special case - build with Bazel
|
||||
if ($env:build_system -eq "bazel") {
|
||||
& $env:root\bazel.exe build -c opt //:gtest_samples
|
||||
if ($LastExitCode -eq 0) { # bazel writes to StdErr and PowerShell interprets it as an error
|
||||
$host.SetShouldExit(0)
|
||||
} else { # a real error
|
||||
throw "Exec: $ErrorMessage"
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
# by default build with CMake
|
||||
md _build -Force | Out-Null
|
||||
cd _build
|
||||
|
||||
$conf = if ($env:generator -eq "MinGW Makefiles") {"-DCMAKE_BUILD_TYPE=$env:configuration"} else {"-DCMAKE_CONFIGURATION_TYPES=Debug;Release"}
|
||||
# Disable test for MinGW (gtest tests fail, gmock tests can not build)
|
||||
$gtest_build_tests = if ($env:generator -eq "MinGW Makefiles") {"-Dgtest_build_tests=OFF"} else {"-Dgtest_build_tests=ON"}
|
||||
$gmock_build_tests = if ($env:generator -eq "MinGW Makefiles") {"-Dgmock_build_tests=OFF"} else {"-Dgmock_build_tests=ON"}
|
||||
& cmake -G "$env:generator" $conf -Dgtest_build_samples=ON $gtest_build_tests $gmock_build_tests ..
|
||||
if ($LastExitCode -ne 0) {
|
||||
throw "Exec: $ErrorMessage"
|
||||
}
|
||||
$cmake_parallel = if ($env:generator -eq "MinGW Makefiles") {"-j2"} else {"/m"}
|
||||
& cmake --build . --config $env:configuration -- $cmake_parallel
|
||||
if ($LastExitCode -ne 0) {
|
||||
throw "Exec: $ErrorMessage"
|
||||
}
|
||||
|
||||
|
||||
skip_commits:
|
||||
files:
|
||||
- '**/*.md'
|
||||
|
||||
test_script:
|
||||
- ps: |
|
||||
# Only enable some builds for pull requests, the AppVeyor queue is too long.
|
||||
if ((Test-Path env:APPVEYOR_PULL_REQUEST_NUMBER) -And (-not (Test-Path env:enabled_on_pr) -or $env:enabled_on_pr -ne "yes")) {
|
||||
return
|
||||
}
|
||||
if ($env:build_system -eq "bazel") {
|
||||
# special case - testing with Bazel
|
||||
& $env:root\bazel.exe test //:gtest_samples
|
||||
if ($LastExitCode -eq 0) { # bazel writes to StdErr and PowerShell interprets it as an error
|
||||
$host.SetShouldExit(0)
|
||||
} else { # a real error
|
||||
throw "Exec: $ErrorMessage"
|
||||
}
|
||||
}
|
||||
if ($env:build_system -eq "cmake") {
|
||||
# built with CMake - test with CTest
|
||||
if ($env:generator -eq "MinGW Makefiles") {
|
||||
return # No test available for MinGW
|
||||
}
|
||||
|
||||
& ctest -C $env:configuration --timeout 600 --output-on-failure
|
||||
if ($LastExitCode -ne 0) {
|
||||
throw "Exec: $ErrorMessage"
|
||||
}
|
||||
}
|
||||
|
||||
artifacts:
|
||||
- path: '_build/CMakeFiles/*.log'
|
||||
name: logs
|
||||
- path: '_build/Testing/**/*.xml'
|
||||
name: test_results
|
||||
- path: 'bazel-testlogs/**/test.log'
|
||||
name: test_logs
|
||||
- path: 'bazel-testlogs/**/test.xml'
|
||||
name: test_results
|
@@ -1,37 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2017 Google Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
set -e
|
||||
|
||||
bazel version
|
||||
bazel build --curses=no //...:all
|
||||
bazel test --curses=no //...:all
|
||||
bazel test --curses=no //...:all --define absl=1
|
@@ -1,2 +0,0 @@
|
||||
# run PlatformIO builds
|
||||
platformio run
|
@@ -1,41 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2017 Google Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#
|
||||
# This file should be sourced, and not executed as a standalone script.
|
||||
#
|
||||
|
||||
# TODO() - we can check if this is being sourced using $BASH_VERSION and $BASH_SOURCE[0] != ${0}.
|
||||
|
||||
if [ "${TRAVIS_OS_NAME}" = "linux" ]; then
|
||||
if [ "$CXX" = "g++" ]; then export CXX="g++-4.9" CC="gcc-4.9"; fi
|
||||
if [ "$CXX" = "clang++" ]; then export CXX="clang++-3.9" CC="clang-3.9"; fi
|
||||
fi
|
@@ -1,49 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2017 Google Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
set -eu
|
||||
|
||||
if [ "${TRAVIS_OS_NAME}" != linux ]; then
|
||||
echo "Not a Linux build; skipping installation"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
if [ "${TRAVIS_SUDO}" = "true" ]; then
|
||||
echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" | \
|
||||
sudo tee /etc/apt/sources.list.d/bazel.list
|
||||
curl https://bazel.build/bazel-release.pub.gpg | sudo apt-key add -
|
||||
sudo apt-get update && sudo apt-get install -y bazel gcc-4.9 g++-4.9 clang-3.9
|
||||
elif [ "${CXX}" = "clang++" ]; then
|
||||
# Use ccache, assuming $HOME/bin is in the path, which is true in the Travis build environment.
|
||||
ln -sf /usr/bin/ccache $HOME/bin/${CXX};
|
||||
ln -sf /usr/bin/ccache $HOME/bin/${CC};
|
||||
fi
|
@@ -1,40 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2017 Google Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
set -eu
|
||||
|
||||
if [ "${TRAVIS_OS_NAME}" != "osx" ]; then
|
||||
echo "Not a macOS build; skipping installation"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
brew update
|
||||
brew install ccache gcc@4.9
|
@@ -1,5 +0,0 @@
|
||||
# install PlatformIO
|
||||
sudo pip install -U platformio
|
||||
|
||||
# update PlatformIO
|
||||
platformio update
|
@@ -1,44 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
set -evx
|
||||
|
||||
. ci/get-nprocessors.sh
|
||||
|
||||
# if possible, ask for the precise number of processors,
|
||||
# otherwise take 2 processors as reasonable default; see
|
||||
# https://docs.travis-ci.com/user/speeding-up-the-build/#Makefile-optimization
|
||||
if [ -x /usr/bin/getconf ]; then
|
||||
NPROCESSORS=$(/usr/bin/getconf _NPROCESSORS_ONLN)
|
||||
else
|
||||
NPROCESSORS=2
|
||||
fi
|
||||
# as of 2017-09-04 Travis CI reports 32 processors, but GCC build
|
||||
# crashes if parallelized too much (maybe memory consumption problem),
|
||||
# so limit to 4 processors for the time being.
|
||||
if [ $NPROCESSORS -gt 4 ] ; then
|
||||
echo "$0:Note: Limiting processors to use by make from $NPROCESSORS to 4."
|
||||
NPROCESSORS=4
|
||||
fi
|
||||
# Tell make to use the processors. No preceding '-' required.
|
||||
MAKEFLAGS="j${NPROCESSORS}"
|
||||
export MAKEFLAGS
|
||||
|
||||
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
|
||||
cd build
|
||||
cmake -Dgtest_build_samples=ON \
|
||||
-Dgtest_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_BUILD_TYPE=$BUILD_TYPE \
|
||||
..
|
||||
make
|
||||
CTEST_OUTPUT_ON_FAILURE=1 make test
|
@@ -1,40 +0,0 @@
|
||||
# This file contains a list of people who've made non-trivial
|
||||
# contribution to the Google C++ Mocking Framework project. People
|
||||
# who commit code to the project are encouraged to add their names
|
||||
# here. Please keep the list sorted by first names.
|
||||
|
||||
Benoit Sigoure <tsuna@google.com>
|
||||
Bogdan Piloca <boo@google.com>
|
||||
Chandler Carruth <chandlerc@google.com>
|
||||
Dave MacLachlan <dmaclach@gmail.com>
|
||||
David Anderson <danderson@google.com>
|
||||
Dean Sturtevant
|
||||
Gene Volovich <gv@cite.com>
|
||||
Hal Burch <gmock@hburch.com>
|
||||
Jeffrey Yasskin <jyasskin@google.com>
|
||||
Jim Keller <jimkeller@google.com>
|
||||
Joe Walnes <joe@truemesh.com>
|
||||
Jon Wray <jwray@google.com>
|
||||
Keir Mierle <mierle@gmail.com>
|
||||
Keith Ray <keith.ray@gmail.com>
|
||||
Kostya Serebryany <kcc@google.com>
|
||||
Lev Makhlis
|
||||
Manuel Klimek <klimek@google.com>
|
||||
Mario Tanev <radix@google.com>
|
||||
Mark Paskin
|
||||
Markus Heule <markus.heule@gmail.com>
|
||||
Matthew Simmons <simmonmt@acm.org>
|
||||
Mike Bland <mbland@google.com>
|
||||
Neal Norwitz <nnorwitz@gmail.com>
|
||||
Nermin Ozkiranartli <nermin@google.com>
|
||||
Owen Carlsen <ocarlsen@google.com>
|
||||
Paneendra Ba <paneendra@google.com>
|
||||
Paul Menage <menage@google.com>
|
||||
Piotr Kaminski <piotrk@google.com>
|
||||
Russ Rufer <russ@pentad.com>
|
||||
Sverre Sundsdal <sundsdal@gmail.com>
|
||||
Takeshi Yoshino <tyoshino@google.com>
|
||||
Vadim Berman <vadimb@google.com>
|
||||
Vlad Losev <vladl@google.com>
|
||||
Wolfgang Klier <wklier@google.com>
|
||||
Zhanyong Wan <wan@google.com>
|
@@ -1,28 +0,0 @@
|
||||
Copyright 2008, Google Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@@ -1,44 +0,0 @@
|
||||
# Googletest Mocking (gMock) Framework
|
||||
|
||||
### Overview
|
||||
|
||||
Google's framework for writing and using C++ mock classes. It can help you
|
||||
derive better designs of your system and write better tests.
|
||||
|
||||
It is inspired by:
|
||||
|
||||
* [jMock](http://www.jmock.org/),
|
||||
* [EasyMock](http://www.easymock.org/), and
|
||||
* [Hamcrest](http://code.google.com/p/hamcrest/),
|
||||
|
||||
and designed with C++'s specifics in mind.
|
||||
|
||||
gMock:
|
||||
|
||||
- provides a declarative syntax for defining mocks,
|
||||
- can define partial (hybrid) mocks, which are a cross of real and mock
|
||||
objects,
|
||||
- handles functions of arbitrary types and overloaded functions,
|
||||
- comes with a rich set of matchers for validating function arguments,
|
||||
- uses an intuitive syntax for controlling the behavior of a mock,
|
||||
- does automatic verification of expectations (no record-and-replay needed),
|
||||
- allows arbitrary (partial) ordering constraints on function calls to be
|
||||
expressed,
|
||||
- lets a user extend it by defining new matchers and actions.
|
||||
- does not use exceptions, and
|
||||
- is easy to learn and use.
|
||||
|
||||
Details and examples can be found here:
|
||||
|
||||
* [gMock for Dummies](docs/for_dummies.md)
|
||||
* [Legacy gMock FAQ](docs/gmock_faq.md)
|
||||
* [gMock Cookbook](docs/cook_book.md)
|
||||
* [gMock Cheat Sheet](docs/cheat_sheet.md)
|
||||
|
||||
Please note that code under scripts/generator/ is from the [cppclean
|
||||
project](http://code.google.com/p/cppclean/) and under the Apache
|
||||
License, which is different from Google Mock's license.
|
||||
|
||||
Google Mock is a part of
|
||||
[Google Test C++ testing framework](http://github.com/google/googletest/) and a
|
||||
subject to the same requirements.
|
@@ -1,11 +0,0 @@
|
||||
prefix=${pcfiledir}/../..
|
||||
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
|
||||
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
|
||||
|
||||
Name: gmock
|
||||
Description: GoogleMock (without main() function)
|
||||
Version: @PROJECT_VERSION@
|
||||
URL: https://github.com/google/googletest
|
||||
Requires: gtest
|
||||
Libs: -L${libdir} -lgmock @CMAKE_THREAD_LIBS_INIT@
|
||||
Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ @CMAKE_THREAD_LIBS_INIT@
|
@@ -1,11 +0,0 @@
|
||||
prefix=${pcfiledir}/../..
|
||||
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
|
||||
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
|
||||
|
||||
Name: gmock_main
|
||||
Description: GoogleMock (with main() function)
|
||||
Version: @PROJECT_VERSION@
|
||||
URL: https://github.com/google/googletest
|
||||
Requires: gmock
|
||||
Libs: -L${libdir} -lgmock_main @CMAKE_THREAD_LIBS_INIT@
|
||||
Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ @CMAKE_THREAD_LIBS_INIT@
|
@@ -1,781 +0,0 @@
|
||||
## gMock Cheat Sheet
|
||||
|
||||
<!-- GOOGLETEST_CM0019 DO NOT DELETE -->
|
||||
|
||||
<!-- GOOGLETEST_CM0033 DO NOT DELETE -->
|
||||
|
||||
### Defining a Mock Class
|
||||
|
||||
#### Mocking a Normal Class {#MockClass}
|
||||
|
||||
Given
|
||||
|
||||
```cpp
|
||||
class Foo {
|
||||
...
|
||||
virtual ~Foo();
|
||||
virtual int GetSize() const = 0;
|
||||
virtual string Describe(const char* name) = 0;
|
||||
virtual string Describe(int type) = 0;
|
||||
virtual bool Process(Bar elem, int count) = 0;
|
||||
};
|
||||
```
|
||||
|
||||
(note that `~Foo()` **must** be virtual) we can define its mock as
|
||||
|
||||
```cpp
|
||||
#include "gmock/gmock.h"
|
||||
|
||||
class MockFoo : public Foo {
|
||||
...
|
||||
MOCK_METHOD(int, GetSize, (), (const, override));
|
||||
MOCK_METHOD(string, Describe, (const char* name), (override));
|
||||
MOCK_METHOD(string, Describe, (int type), (override));
|
||||
MOCK_METHOD(bool, Process, (Bar elem, int count), (override));
|
||||
};
|
||||
```
|
||||
|
||||
To create a "nice" mock, which ignores all uninteresting calls, a "naggy" mock,
|
||||
which warns on all uninteresting calls, or a "strict" mock, which treats them as
|
||||
failures:
|
||||
|
||||
```cpp
|
||||
using ::testing::NiceMock;
|
||||
using ::testing::NaggyMock;
|
||||
using ::testing::StrictMock;
|
||||
|
||||
NiceMock<MockFoo> nice_foo; // The type is a subclass of MockFoo.
|
||||
NaggyMock<MockFoo> naggy_foo; // The type is a subclass of MockFoo.
|
||||
StrictMock<MockFoo> strict_foo; // The type is a subclass of MockFoo.
|
||||
```
|
||||
|
||||
**Note:** A mock object is currently naggy by default. We may make it nice by
|
||||
default in the future.
|
||||
|
||||
#### Mocking a Class Template {#MockTemplate}
|
||||
|
||||
Class templates can be mocked just like any class.
|
||||
|
||||
To mock
|
||||
|
||||
```cpp
|
||||
template <typename Elem>
|
||||
class StackInterface {
|
||||
...
|
||||
virtual ~StackInterface();
|
||||
virtual int GetSize() const = 0;
|
||||
virtual void Push(const Elem& x) = 0;
|
||||
};
|
||||
```
|
||||
|
||||
(note that all member functions that are mocked, including `~StackInterface()`
|
||||
**must** be virtual).
|
||||
|
||||
```cpp
|
||||
template <typename Elem>
|
||||
class MockStack : public StackInterface<Elem> {
|
||||
...
|
||||
MOCK_METHOD(int, GetSize, (), (const, override));
|
||||
MOCK_METHOD(void, Push, (const Elem& x), (override));
|
||||
};
|
||||
```
|
||||
|
||||
#### Specifying Calling Conventions for Mock Functions
|
||||
|
||||
If your mock function doesn't use the default calling convention, you can
|
||||
specify it by adding `Calltype(convention)` to `MOCK_METHOD`'s 4th parameter.
|
||||
For example,
|
||||
|
||||
```cpp
|
||||
MOCK_METHOD(bool, Foo, (int n), (Calltype(STDMETHODCALLTYPE)));
|
||||
MOCK_METHOD(int, Bar, (double x, double y),
|
||||
(const, Calltype(STDMETHODCALLTYPE)));
|
||||
```
|
||||
|
||||
where `STDMETHODCALLTYPE` is defined by `<objbase.h>` on Windows.
|
||||
|
||||
### Using Mocks in Tests {#UsingMocks}
|
||||
|
||||
The typical work flow is:
|
||||
|
||||
1. Import the gMock names you need to use. All gMock symbols are in the
|
||||
`testing` namespace unless they are macros or otherwise noted.
|
||||
2. Create the mock objects.
|
||||
3. Optionally, set the default actions of the mock objects.
|
||||
4. Set your expectations on the mock objects (How will they be called? What
|
||||
will they do?).
|
||||
5. Exercise code that uses the mock objects; if necessary, check the result
|
||||
using googletest assertions.
|
||||
6. When a mock object is destructed, gMock automatically verifies that all
|
||||
expectations on it have been satisfied.
|
||||
|
||||
Here's an example:
|
||||
|
||||
```cpp
|
||||
using ::testing::Return; // #1
|
||||
|
||||
TEST(BarTest, DoesThis) {
|
||||
MockFoo foo; // #2
|
||||
|
||||
ON_CALL(foo, GetSize()) // #3
|
||||
.WillByDefault(Return(1));
|
||||
// ... other default actions ...
|
||||
|
||||
EXPECT_CALL(foo, Describe(5)) // #4
|
||||
.Times(3)
|
||||
.WillRepeatedly(Return("Category 5"));
|
||||
// ... other expectations ...
|
||||
|
||||
EXPECT_EQ("good", MyProductionFunction(&foo)); // #5
|
||||
} // #6
|
||||
```
|
||||
|
||||
### Setting Default Actions {#OnCall}
|
||||
|
||||
gMock has a **built-in default action** for any function that returns `void`,
|
||||
`bool`, a numeric value, or a pointer. In C++11, it will additionally returns
|
||||
the default-constructed value, if one exists for the given type.
|
||||
|
||||
To customize the default action for functions with return type *`T`*:
|
||||
|
||||
```cpp
|
||||
using ::testing::DefaultValue;
|
||||
|
||||
// Sets the default value to be returned. T must be CopyConstructible.
|
||||
DefaultValue<T>::Set(value);
|
||||
// Sets a factory. Will be invoked on demand. T must be MoveConstructible.
|
||||
// T MakeT();
|
||||
DefaultValue<T>::SetFactory(&MakeT);
|
||||
// ... use the mocks ...
|
||||
// Resets the default value.
|
||||
DefaultValue<T>::Clear();
|
||||
```
|
||||
|
||||
Example usage:
|
||||
|
||||
```cpp
|
||||
// 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");
|
||||
auto buzz2 = mock_buzzer_.MakeBuzz("hello");
|
||||
EXPECT_NE(nullptr, buzz1);
|
||||
EXPECT_NE(nullptr, buzz2);
|
||||
EXPECT_NE(buzz1, buzz2);
|
||||
|
||||
// Resets the default action for return type std::unique_ptr<Buzz>,
|
||||
// to avoid interfere with other tests.
|
||||
DefaultValue<std::unique_ptr<Buzz>>::Clear();
|
||||
```
|
||||
|
||||
To customize the default action for a particular method of a specific mock
|
||||
object, use `ON_CALL()`. `ON_CALL()` has a similar syntax to `EXPECT_CALL()`,
|
||||
but it is used for setting default behaviors (when you do not require that the
|
||||
mock method is called). See [here](cook_book.md#UseOnCall) for a more detailed
|
||||
discussion.
|
||||
|
||||
```cpp
|
||||
ON_CALL(mock-object, method(matchers))
|
||||
.With(multi-argument-matcher) ?
|
||||
.WillByDefault(action);
|
||||
```
|
||||
|
||||
### Setting Expectations {#ExpectCall}
|
||||
|
||||
`EXPECT_CALL()` sets **expectations** on a mock method (How will it be called?
|
||||
What will it do?):
|
||||
|
||||
```cpp
|
||||
EXPECT_CALL(mock-object, method (matchers)?)
|
||||
.With(multi-argument-matcher) ?
|
||||
.Times(cardinality) ?
|
||||
.InSequence(sequences) *
|
||||
.After(expectations) *
|
||||
.WillOnce(action) *
|
||||
.WillRepeatedly(action) ?
|
||||
.RetiresOnSaturation(); ?
|
||||
```
|
||||
|
||||
For each item above, `?` means it can be used at most once, while `*` means it
|
||||
can be used any number of times.
|
||||
|
||||
In order to pass, `EXPECT_CALL` must be used before the calls are actually made.
|
||||
|
||||
The `(matchers)` is a comma-separated list of matchers that correspond to each
|
||||
of the arguments of `method`, and sets the expectation only for calls of
|
||||
`method` that matches all of the matchers.
|
||||
|
||||
If `(matchers)` is omitted, the expectation is the same as if the matchers were
|
||||
set to anything matchers (for example, `(_, _, _, _)` for a four-arg method).
|
||||
|
||||
If `Times()` is omitted, the cardinality is assumed to be:
|
||||
|
||||
* `Times(1)` when there is neither `WillOnce()` nor `WillRepeatedly()`;
|
||||
* `Times(n)` when there are `n` `WillOnce()`s but no `WillRepeatedly()`, where
|
||||
`n` >= 1; or
|
||||
* `Times(AtLeast(n))` when there are `n` `WillOnce()`s and a
|
||||
`WillRepeatedly()`, where `n` >= 0.
|
||||
|
||||
A method with no `EXPECT_CALL()` is free to be invoked *any number of times*,
|
||||
and the default action will be taken each time.
|
||||
|
||||
### Matchers {#MatcherList}
|
||||
|
||||
<!-- GOOGLETEST_CM0020 DO NOT DELETE -->
|
||||
|
||||
A **matcher** matches a *single* argument. You can use it inside `ON_CALL()` or
|
||||
`EXPECT_CALL()`, or use it to validate a value directly using two macros:
|
||||
|
||||
<!-- mdformat off(github rendering does not support multiline tables) -->
|
||||
| Macro | Description |
|
||||
| :----------------------------------- | :------------------------------------ |
|
||||
| `EXPECT_THAT(actual_value, matcher)` | Asserts that `actual_value` matches `matcher`. |
|
||||
| `ASSERT_THAT(actual_value, matcher)` | The same as `EXPECT_THAT(actual_value, matcher)`, except that it generates a **fatal** failure. |
|
||||
<!-- mdformat on -->
|
||||
|
||||
Built-in matchers (where `argument` is the function argument, e.g.
|
||||
`actual_value` in the example above, or when used in the context of
|
||||
`EXPECT_CALL(mock_object, method(matchers))`, the arguments of `method`) are
|
||||
divided into several categories:
|
||||
|
||||
#### Wildcard
|
||||
|
||||
Matcher | Description
|
||||
:-------------------------- | :-----------------------------------------------
|
||||
`_` | `argument` can be any value of the correct type.
|
||||
`A<type>()` or `An<type>()` | `argument` can be any value of type `type`.
|
||||
|
||||
#### Generic Comparison
|
||||
|
||||
<!-- mdformat off(no multiline tables) -->
|
||||
| Matcher | Description |
|
||||
| :--------------------- | :-------------------------------------------------- |
|
||||
| `Eq(value)` or `value` | `argument == value` |
|
||||
| `Ge(value)` | `argument >= value` |
|
||||
| `Gt(value)` | `argument > value` |
|
||||
| `Le(value)` | `argument <= value` |
|
||||
| `Lt(value)` | `argument < value` |
|
||||
| `Ne(value)` | `argument != value` |
|
||||
| `IsFalse()` | `argument` evaluates to `false` in a Boolean context. |
|
||||
| `IsTrue()` | `argument` evaluates to `true` in a Boolean context. |
|
||||
| `IsNull()` | `argument` is a `NULL` pointer (raw or smart). |
|
||||
| `NotNull()` | `argument` is a non-null pointer (raw or smart). |
|
||||
| `Optional(m)` | `argument` is `optional<>` that contains a value matching `m`. |
|
||||
| `VariantWith<T>(m)` | `argument` is `variant<>` that holds the alternative of type T with a value matching `m`. |
|
||||
| `Ref(variable)` | `argument` is a reference to `variable`. |
|
||||
| `TypedEq<type>(value)` | `argument` has type `type` and is equal to `value`. You may need to use this instead of `Eq(value)` when the mock function is overloaded. |
|
||||
<!-- mdformat on -->
|
||||
|
||||
Except `Ref()`, these matchers make a *copy* of `value` in case it's modified or
|
||||
destructed later. If the compiler complains that `value` doesn't have a public
|
||||
copy constructor, try wrap it in `ByRef()`, e.g.
|
||||
`Eq(ByRef(non_copyable_value))`. If you do that, make sure `non_copyable_value`
|
||||
is not changed afterwards, or the meaning of your matcher will be changed.
|
||||
|
||||
#### Floating-Point Matchers {#FpMatchers}
|
||||
|
||||
<!-- mdformat off(no multiline tables) -->
|
||||
| Matcher | Description |
|
||||
| :------------------------------- | :--------------------------------- |
|
||||
| `DoubleEq(a_double)` | `argument` is a `double` value approximately equal to `a_double`, treating two NaNs as unequal. |
|
||||
| `FloatEq(a_float)` | `argument` is a `float` value approximately equal to `a_float`, treating two NaNs as unequal. |
|
||||
| `NanSensitiveDoubleEq(a_double)` | `argument` is a `double` value approximately equal to `a_double`, treating two NaNs as equal. |
|
||||
| `NanSensitiveFloatEq(a_float)` | `argument` is a `float` value approximately equal to `a_float`, treating two NaNs as equal. |
|
||||
<!-- mdformat on -->
|
||||
|
||||
The above matchers use ULP-based comparison (the same as used in googletest).
|
||||
They automatically pick a reasonable error bound based on the absolute value of
|
||||
the expected value. `DoubleEq()` and `FloatEq()` conform to the IEEE standard,
|
||||
which requires comparing two NaNs for equality to return false. The
|
||||
`NanSensitive*` version instead treats two NaNs as equal, which is often what a
|
||||
user wants.
|
||||
|
||||
<!-- mdformat off(no multiline tables) -->
|
||||
| Matcher | Description |
|
||||
| :------------------------------------------------ | :----------------------- |
|
||||
| `DoubleNear(a_double, max_abs_error)` | `argument` is a `double` value close to `a_double` (absolute error <= `max_abs_error`), treating two NaNs as unequal. |
|
||||
| `FloatNear(a_float, max_abs_error)` | `argument` is a `float` value close to `a_float` (absolute error <= `max_abs_error`), treating two NaNs as unequal. |
|
||||
| `NanSensitiveDoubleNear(a_double, max_abs_error)` | `argument` is a `double` value close to `a_double` (absolute error <= `max_abs_error`), treating two NaNs as equal. |
|
||||
| `NanSensitiveFloatNear(a_float, max_abs_error)` | `argument` is a `float` value close to `a_float` (absolute error <= `max_abs_error`), treating two NaNs as equal. |
|
||||
<!-- mdformat on -->
|
||||
|
||||
#### String Matchers
|
||||
|
||||
The `argument` can be either a C string or a C++ string object:
|
||||
|
||||
<!-- mdformat off(no multiline tables) -->
|
||||
| Matcher | Description |
|
||||
| :---------------------- | :------------------------------------------------- |
|
||||
| `ContainsRegex(string)` | `argument` matches the given regular expression. |
|
||||
| `EndsWith(suffix)` | `argument` ends with string `suffix`. |
|
||||
| `HasSubstr(string)` | `argument` contains `string` as a sub-string. |
|
||||
| `MatchesRegex(string)` | `argument` matches the given regular expression with the match starting at the first character and ending at the last character. |
|
||||
| `StartsWith(prefix)` | `argument` starts with string `prefix`. |
|
||||
| `StrCaseEq(string)` | `argument` is equal to `string`, ignoring case. |
|
||||
| `StrCaseNe(string)` | `argument` is not equal to `string`, ignoring case. |
|
||||
| `StrEq(string)` | `argument` is equal to `string`. |
|
||||
| `StrNe(string)` | `argument` is not equal to `string`. |
|
||||
<!-- mdformat on -->
|
||||
|
||||
`ContainsRegex()` and `MatchesRegex()` take ownership of the `RE` object. They
|
||||
use the regular expression syntax defined
|
||||
[here](../../googletest/docs/advanced.md#regular-expression-syntax).
|
||||
`StrCaseEq()`, `StrCaseNe()`, `StrEq()`, and `StrNe()` work for wide strings as
|
||||
well.
|
||||
|
||||
#### Container Matchers
|
||||
|
||||
Most STL-style containers support `==`, so you can use `Eq(expected_container)`
|
||||
or simply `expected_container` to match a container exactly. If you want to
|
||||
write the elements in-line, match them more flexibly, or get more informative
|
||||
messages, you can use:
|
||||
|
||||
<!-- mdformat off(no multiline tables) -->
|
||||
| Matcher | Description |
|
||||
| :---------------------------------------- | :------------------------------- |
|
||||
| `BeginEndDistanceIs(m)` | `argument` is a container whose `begin()` and `end()` iterators are separated by a number of increments matching `m`. E.g. `BeginEndDistanceIs(2)` or `BeginEndDistanceIs(Lt(2))`. For containers that define a `size()` method, `SizeIs(m)` may be more efficient. |
|
||||
| `ContainerEq(container)` | The same as `Eq(container)` except that the failure message also includes which elements are in one container but not the other. |
|
||||
| `Contains(e)` | `argument` contains an element that matches `e`, which can be either a value or a matcher. |
|
||||
| `Each(e)` | `argument` is a container where *every* element matches `e`, which can be either a value or a matcher. |
|
||||
| `ElementsAre(e0, e1, ..., en)` | `argument` has `n + 1` elements, where the *i*-th element matches `ei`, which can be a value or a matcher. |
|
||||
| `ElementsAreArray({e0, e1, ..., en})`, `ElementsAreArray(a_container)`, `ElementsAreArray(begin, end)`, `ElementsAreArray(array)`, or `ElementsAreArray(array, count)` | The same as `ElementsAre()` except that the expected element values/matchers come from an initializer list, STL-style container, iterator range, or C-style array. |
|
||||
| `IsEmpty()` | `argument` is an empty container (`container.empty()`). |
|
||||
| `IsSubsetOf({e0, e1, ..., en})`, `IsSubsetOf(a_container)`, `IsSubsetOf(begin, end)`, `IsSubsetOf(array)`, or `IsSubsetOf(array, count)` | `argument` matches `UnorderedElementsAre(x0, x1, ..., xk)` for some subset `{x0, x1, ..., xk}` of the expected matchers. |
|
||||
| `IsSupersetOf({e0, e1, ..., en})`, `IsSupersetOf(a_container)`, `IsSupersetOf(begin, end)`, `IsSupersetOf(array)`, or `IsSupersetOf(array, count)` | Some subset of `argument` matches `UnorderedElementsAre(`expected matchers`)`. |
|
||||
| `Pointwise(m, container)`, `Pointwise(m, {e0, e1, ..., en})` | `argument` contains the same number of elements as in `container`, and for all i, (the i-th element in `argument`, the i-th element in `container`) match `m`, which is a matcher on 2-tuples. E.g. `Pointwise(Le(), upper_bounds)` verifies that each element in `argument` doesn't exceed the corresponding element in `upper_bounds`. See more detail below. |
|
||||
| `SizeIs(m)` | `argument` is a container whose size matches `m`. E.g. `SizeIs(2)` or `SizeIs(Lt(2))`. |
|
||||
| `UnorderedElementsAre(e0, e1, ..., en)` | `argument` has `n + 1` elements, and under *some* permutation of the elements, each element matches an `ei` (for a different `i`), which can be a value or a matcher. |
|
||||
| `UnorderedElementsAreArray({e0, e1, ..., en})`, `UnorderedElementsAreArray(a_container)`, `UnorderedElementsAreArray(begin, end)`, `UnorderedElementsAreArray(array)`, or `UnorderedElementsAreArray(array, count)` | The same as `UnorderedElementsAre()` except that the expected element values/matchers come from an initializer list, STL-style container, iterator range, or C-style array. |
|
||||
| `UnorderedPointwise(m, container)`, `UnorderedPointwise(m, {e0, e1, ..., en})` | Like `Pointwise(m, container)`, but ignores the order of elements. |
|
||||
| `WhenSorted(m)` | When `argument` is sorted using the `<` operator, it matches container matcher `m`. E.g. `WhenSorted(ElementsAre(1, 2, 3))` verifies that `argument` contains elements 1, 2, and 3, ignoring order. |
|
||||
| `WhenSortedBy(comparator, m)` | The same as `WhenSorted(m)`, except that the given comparator instead of `<` is used to sort `argument`. E.g. `WhenSortedBy(std::greater(), ElementsAre(3, 2, 1))`. |
|
||||
<!-- mdformat on -->
|
||||
|
||||
**Notes:**
|
||||
|
||||
* These matchers can also match:
|
||||
1. a native array passed by reference (e.g. in `Foo(const int (&a)[5])`),
|
||||
and
|
||||
2. an array passed as a pointer and a count (e.g. in `Bar(const T* buffer,
|
||||
int len)` -- see [Multi-argument Matchers](#MultiArgMatchers)).
|
||||
* The array being matched may be multi-dimensional (i.e. its elements can be
|
||||
arrays).
|
||||
* `m` in `Pointwise(m, ...)` should be a matcher for `::std::tuple<T, U>`
|
||||
where `T` and `U` are the element type of the actual container and the
|
||||
expected container, respectively. For example, to compare two `Foo`
|
||||
containers where `Foo` doesn't support `operator==`, one might write:
|
||||
|
||||
```cpp
|
||||
using ::std::get;
|
||||
MATCHER(FooEq, "") {
|
||||
return std::get<0>(arg).Equals(std::get<1>(arg));
|
||||
}
|
||||
...
|
||||
EXPECT_THAT(actual_foos, Pointwise(FooEq(), expected_foos));
|
||||
```
|
||||
|
||||
#### Member Matchers
|
||||
|
||||
<!-- mdformat off(no multiline tables) -->
|
||||
| Matcher | Description |
|
||||
| :------------------------------ | :----------------------------------------- |
|
||||
| `Field(&class::field, m)` | `argument.field` (or `argument->field` when `argument` is a plain pointer) matches matcher `m`, where `argument` is an object of type _class_. |
|
||||
| `Key(e)` | `argument.first` matches `e`, which can be either a value or a matcher. E.g. `Contains(Key(Le(5)))` can verify that a `map` contains a key `<= 5`. |
|
||||
| `Pair(m1, m2)` | `argument` is an `std::pair` whose `first` field matches `m1` and `second` field matches `m2`. |
|
||||
| `Property(&class::property, m)` | `argument.property()` (or `argument->property()` when `argument` is a plain pointer) matches matcher `m`, where `argument` is an object of type _class_. |
|
||||
<!-- mdformat on -->
|
||||
|
||||
#### Matching the Result of a Function, Functor, or Callback
|
||||
|
||||
<!-- mdformat off(no multiline tables) -->
|
||||
| Matcher | Description |
|
||||
| :--------------- | :------------------------------------------------ |
|
||||
| `ResultOf(f, m)` | `f(argument)` matches matcher `m`, where `f` is a function or functor. |
|
||||
<!-- mdformat on -->
|
||||
|
||||
#### Pointer Matchers
|
||||
|
||||
<!-- mdformat off(no multiline tables) -->
|
||||
| Matcher | Description |
|
||||
| :------------------------ | :---------------------------------------------- |
|
||||
| `Pointee(m)` | `argument` (either a smart pointer or a raw pointer) points to a value that matches matcher `m`. |
|
||||
| `WhenDynamicCastTo<T>(m)` | when `argument` is passed through `dynamic_cast<T>()`, it matches matcher `m`. |
|
||||
<!-- mdformat on -->
|
||||
|
||||
<!-- GOOGLETEST_CM0026 DO NOT DELETE -->
|
||||
|
||||
<!-- GOOGLETEST_CM0027 DO NOT DELETE -->
|
||||
|
||||
#### Multi-argument Matchers {#MultiArgMatchers}
|
||||
|
||||
Technically, all matchers match a *single* value. A "multi-argument" matcher is
|
||||
just one that matches a *tuple*. The following matchers can be used to match a
|
||||
tuple `(x, y)`:
|
||||
|
||||
Matcher | Description
|
||||
:------ | :----------
|
||||
`Eq()` | `x == y`
|
||||
`Ge()` | `x >= y`
|
||||
`Gt()` | `x > y`
|
||||
`Le()` | `x <= y`
|
||||
`Lt()` | `x < y`
|
||||
`Ne()` | `x != y`
|
||||
|
||||
You can use the following selectors to pick a subset of the arguments (or
|
||||
reorder them) to participate in the matching:
|
||||
|
||||
<!-- mdformat off(no multiline tables) -->
|
||||
| Matcher | Description |
|
||||
| :------------------------- | :---------------------------------------------- |
|
||||
| `AllArgs(m)` | Equivalent to `m`. Useful as syntactic sugar in `.With(AllArgs(m))`. |
|
||||
| `Args<N1, N2, ..., Nk>(m)` | The tuple of the `k` selected (using 0-based indices) arguments matches `m`, e.g. `Args<1, 2>(Eq())`. |
|
||||
<!-- mdformat on -->
|
||||
|
||||
#### Composite Matchers
|
||||
|
||||
You can make a matcher from one or more other matchers:
|
||||
|
||||
<!-- mdformat off(no multiline tables) -->
|
||||
| Matcher | Description |
|
||||
| :------------------------------- | :-------------------------------------- |
|
||||
| `AllOf(m1, m2, ..., mn)` | `argument` matches all of the matchers `m1` to `mn`. |
|
||||
| `AllOfArray({m0, m1, ..., mn})`, `AllOfArray(a_container)`, `AllOfArray(begin, end)`, `AllOfArray(array)`, or `AllOfArray(array, count)` | The same as `AllOf()` except that the matchers come from an initializer list, STL-style container, iterator range, or C-style array. |
|
||||
| `AnyOf(m1, m2, ..., mn)` | `argument` matches at least one of the matchers `m1` to `mn`. |
|
||||
| `AnyOfArray({m0, m1, ..., mn})`, `AnyOfArray(a_container)`, `AnyOfArray(begin, end)`, `AnyOfArray(array)`, or `AnyOfArray(array, count)` | The same as `AnyOf()` except that the matchers come from an initializer list, STL-style container, iterator range, or C-style array. |
|
||||
| `Not(m)` | `argument` doesn't match matcher `m`. |
|
||||
<!-- mdformat on -->
|
||||
|
||||
<!-- GOOGLETEST_CM0028 DO NOT DELETE -->
|
||||
|
||||
#### Adapters for Matchers
|
||||
|
||||
<!-- mdformat off(no multiline tables) -->
|
||||
| Matcher | Description |
|
||||
| :---------------------- | :------------------------------------ |
|
||||
| `MatcherCast<T>(m)` | casts matcher `m` to type `Matcher<T>`. |
|
||||
| `SafeMatcherCast<T>(m)` | [safely casts](cook_book.md#casting-matchers) matcher `m` to type `Matcher<T>`. |
|
||||
| `Truly(predicate)` | `predicate(argument)` returns something considered by C++ to be true, where `predicate` is a function or functor. |
|
||||
<!-- mdformat on -->
|
||||
|
||||
`AddressSatisfies(callback)` and `Truly(callback)` take ownership of `callback`,
|
||||
which must be a permanent callback.
|
||||
|
||||
#### Using Matchers as Predicates {#MatchersAsPredicatesCheat}
|
||||
|
||||
<!-- mdformat off(no multiline tables) -->
|
||||
| Matcher | Description |
|
||||
| :---------------------------- | :------------------------------------------ |
|
||||
| `Matches(m)(value)` | evaluates to `true` if `value` matches `m`. You can use `Matches(m)` alone as a unary functor. |
|
||||
| `ExplainMatchResult(m, value, result_listener)` | evaluates to `true` if `value` matches `m`, explaining the result to `result_listener`. |
|
||||
| `Value(value, m)` | evaluates to `true` if `value` matches `m`. |
|
||||
<!-- mdformat on -->
|
||||
|
||||
#### Defining Matchers
|
||||
|
||||
<!-- mdformat off(no multiline tables) -->
|
||||
| Matcher | Description |
|
||||
| :----------------------------------- | :------------------------------------ |
|
||||
| `MATCHER(IsEven, "") { return (arg % 2) == 0; }` | Defines a matcher `IsEven()` to match an even number. |
|
||||
| `MATCHER_P(IsDivisibleBy, n, "") { *result_listener << "where the remainder is " << (arg % n); return (arg % n) == 0; }` | Defines a macher `IsDivisibleBy(n)` to match a number divisible by `n`. |
|
||||
| `MATCHER_P2(IsBetween, a, b, std::string(negation ? "isn't" : "is") + " between " + PrintToString(a) + " and " + PrintToString(b)) { return a <= arg && arg <= b; }` | Defines a matcher `IsBetween(a, b)` to match a value in the range [`a`, `b`]. |
|
||||
<!-- mdformat on -->
|
||||
|
||||
**Notes:**
|
||||
|
||||
1. The `MATCHER*` macros cannot be used inside a function or class.
|
||||
2. The matcher body must be *purely functional* (i.e. it cannot have any side
|
||||
effect, and the result must not depend on anything other than the value
|
||||
being matched and the matcher parameters).
|
||||
3. You can use `PrintToString(x)` to convert a value `x` of any type to a
|
||||
string.
|
||||
|
||||
### Actions {#ActionList}
|
||||
|
||||
**Actions** specify what a mock function should do when invoked.
|
||||
|
||||
#### Returning a Value
|
||||
|
||||
<!-- mdformat off(no multiline tables) -->
|
||||
| | |
|
||||
| :-------------------------- | :-------------------------------------------- |
|
||||
| `Return()` | Return from a `void` mock function. |
|
||||
| `Return(value)` | Return `value`. If the type of `value` is different to the mock function's return type, `value` is converted to the latter type <i>at the time the expectation is set</i>, not when the action is executed. |
|
||||
| `ReturnArg<N>()` | Return the `N`-th (0-based) argument. |
|
||||
| `ReturnNew<T>(a1, ..., ak)` | Return `new T(a1, ..., ak)`; a different object is created each time. |
|
||||
| `ReturnNull()` | Return a null pointer. |
|
||||
| `ReturnPointee(ptr)` | Return the value pointed to by `ptr`. |
|
||||
| `ReturnRef(variable)` | Return a reference to `variable`. |
|
||||
| `ReturnRefOfCopy(value)` | Return a reference to a copy of `value`; the copy lives as long as the action. |
|
||||
<!-- mdformat on -->
|
||||
|
||||
#### Side Effects
|
||||
|
||||
<!-- mdformat off(no multiline tables) -->
|
||||
| | |
|
||||
| :--------------------------------- | :-------------------------------------- |
|
||||
| `Assign(&variable, value)` | Assign `value` to variable. |
|
||||
| `DeleteArg<N>()` | Delete the `N`-th (0-based) argument, which must be a pointer. |
|
||||
| `SaveArg<N>(pointer)` | Save the `N`-th (0-based) argument to `*pointer`. |
|
||||
| `SaveArgPointee<N>(pointer)` | Save the value pointed to by the `N`-th (0-based) argument to `*pointer`. |
|
||||
| `SetArgReferee<N>(value)` | Assign value to the variable referenced by the `N`-th (0-based) argument. |
|
||||
| `SetArgPointee<N>(value)` | Assign `value` to the variable pointed by the `N`-th (0-based) argument. |
|
||||
| `SetArgumentPointee<N>(value)` | Same as `SetArgPointee<N>(value)`. Deprecated. Will be removed in v1.7.0. |
|
||||
| `SetArrayArgument<N>(first, last)` | Copies the elements in source range [`first`, `last`) to the array pointed to by the `N`-th (0-based) argument, which can be either a pointer or an iterator. The action does not take ownership of the elements in the source range. |
|
||||
| `SetErrnoAndReturn(error, value)` | Set `errno` to `error` and return `value`. |
|
||||
| `Throw(exception)` | Throws the given exception, which can be any copyable value. Available since v1.1.0. |
|
||||
<!-- mdformat on -->
|
||||
|
||||
#### Using a Function, Functor, or Lambda as an Action
|
||||
|
||||
In the following, by "callable" we mean a free function, `std::function`,
|
||||
functor, or lambda.
|
||||
|
||||
<!-- mdformat off(no multiline tables) -->
|
||||
| | |
|
||||
| :---------------------------------- | :------------------------------------- |
|
||||
| `f` | Invoke f with the arguments passed to the mock function, where f is a callable. |
|
||||
| `Invoke(f)` | Invoke `f` with the arguments passed to the mock function, where `f` can be a global/static function or a functor. |
|
||||
| `Invoke(object_pointer, &class::method)` | Invoke the method on the object with the arguments passed to the mock function. |
|
||||
| `InvokeWithoutArgs(f)` | Invoke `f`, which can be a global/static function or a functor. `f` must take no arguments. |
|
||||
| `InvokeWithoutArgs(object_pointer, &class::method)` | Invoke the method on the object, which takes no arguments. |
|
||||
| `InvokeArgument<N>(arg1, arg2, ..., argk)` | Invoke the mock function's `N`-th (0-based) argument, which must be a function or a functor, with the `k` arguments. |
|
||||
<!-- mdformat on -->
|
||||
|
||||
The return value of the invoked function is used as the return value of the
|
||||
action.
|
||||
|
||||
When defining a callable to be used with `Invoke*()`, you can declare any unused
|
||||
parameters as `Unused`:
|
||||
|
||||
```cpp
|
||||
using ::testing::Invoke;
|
||||
double Distance(Unused, double x, double y) { return sqrt(x*x + y*y); }
|
||||
...
|
||||
EXPECT_CALL(mock, Foo("Hi", _, _)).WillOnce(Invoke(Distance));
|
||||
```
|
||||
|
||||
`Invoke(callback)` and `InvokeWithoutArgs(callback)` take ownership of
|
||||
`callback`, which must be permanent. The type of `callback` must be a base
|
||||
callback type instead of a derived one, e.g.
|
||||
|
||||
```cpp
|
||||
BlockingClosure* done = new BlockingClosure;
|
||||
... Invoke(done) ...; // This won't compile!
|
||||
|
||||
Closure* done2 = new BlockingClosure;
|
||||
... Invoke(done2) ...; // This works.
|
||||
```
|
||||
|
||||
In `InvokeArgument<N>(...)`, if an argument needs to be passed by reference,
|
||||
wrap it inside `ByRef()`. For example,
|
||||
|
||||
```cpp
|
||||
using ::testing::ByRef;
|
||||
using ::testing::InvokeArgument;
|
||||
...
|
||||
InvokeArgument<2>(5, string("Hi"), ByRef(foo))
|
||||
```
|
||||
|
||||
calls the mock function's #2 argument, passing to it `5` and `string("Hi")` by
|
||||
value, and `foo` by reference.
|
||||
|
||||
#### Default Action
|
||||
|
||||
<!-- mdformat off(no multiline tables) -->
|
||||
| Matcher | Description |
|
||||
| :------------ | :----------------------------------------------------- |
|
||||
| `DoDefault()` | Do the default action (specified by `ON_CALL()` or the built-in one). |
|
||||
<!-- mdformat on -->
|
||||
|
||||
**Note:** due to technical reasons, `DoDefault()` cannot be used inside a
|
||||
composite action - trying to do so will result in a run-time error.
|
||||
|
||||
<!-- GOOGLETEST_CM0032 DO NOT DELETE -->
|
||||
|
||||
#### Composite Actions
|
||||
|
||||
<!-- mdformat off(no multiline tables) -->
|
||||
| | |
|
||||
| :----------------------------- | :------------------------------------------ |
|
||||
| `DoAll(a1, a2, ..., an)` | Do all actions `a1` to `an` and return the result of `an` in each invocation. The first `n - 1` sub-actions must return void. |
|
||||
| `IgnoreResult(a)` | Perform action `a` and ignore its result. `a` must not return void. |
|
||||
| `WithArg<N>(a)` | Pass the `N`-th (0-based) argument of the mock function to action `a` and perform it. |
|
||||
| `WithArgs<N1, N2, ..., Nk>(a)` | Pass the selected (0-based) arguments of the mock function to action `a` and perform it. |
|
||||
| `WithoutArgs(a)` | Perform action `a` without any arguments. |
|
||||
<!-- mdformat on -->
|
||||
|
||||
#### Defining Actions
|
||||
|
||||
<table border="1" cellspacing="0" cellpadding="1">
|
||||
<tr>
|
||||
<td>`struct SumAction {` <br>
|
||||
 `template <typename T>` <br>
|
||||
 `T operator()(T x, Ty) { return x + y; }` <br>
|
||||
`};`
|
||||
</td>
|
||||
<td> Defines a generic functor that can be used as an action summing its
|
||||
arguments. </td> </tr>
|
||||
<tr>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- mdformat off(no multiline tables) -->
|
||||
| | |
|
||||
| :--------------------------------- | :-------------------------------------- |
|
||||
| `ACTION(Sum) { return arg0 + arg1; }` | Defines an action `Sum()` to return the sum of the mock function's argument #0 and #1. |
|
||||
| `ACTION_P(Plus, n) { return arg0 + n; }` | Defines an action `Plus(n)` to return the sum of the mock function's argument #0 and `n`. |
|
||||
| `ACTION_Pk(Foo, p1, ..., pk) { statements; }` | Defines a parameterized action `Foo(p1, ..., pk)` to execute the given `statements`. |
|
||||
<!-- mdformat on -->
|
||||
|
||||
The `ACTION*` macros cannot be used inside a function or class.
|
||||
|
||||
### Cardinalities {#CardinalityList}
|
||||
|
||||
These are used in `Times()` to specify how many times a mock function will be
|
||||
called:
|
||||
|
||||
<!-- mdformat off(no multiline tables) -->
|
||||
| | |
|
||||
| :---------------- | :----------------------------------------------------- |
|
||||
| `AnyNumber()` | The function can be called any number of times. |
|
||||
| `AtLeast(n)` | The call is expected at least `n` times. |
|
||||
| `AtMost(n)` | The call is expected at most `n` times. |
|
||||
| `Between(m, n)` | The call is expected between `m` and `n` (inclusive) times. |
|
||||
| `Exactly(n) or n` | The call is expected exactly `n` times. In particular, the call should never happen when `n` is 0. |
|
||||
<!-- mdformat on -->
|
||||
|
||||
### Expectation Order
|
||||
|
||||
By default, the expectations can be matched in *any* order. If some or all
|
||||
expectations must be matched in a given order, there are two ways to specify it.
|
||||
They can be used either independently or together.
|
||||
|
||||
#### The After Clause {#AfterClause}
|
||||
|
||||
```cpp
|
||||
using ::testing::Expectation;
|
||||
...
|
||||
Expectation init_x = EXPECT_CALL(foo, InitX());
|
||||
Expectation init_y = EXPECT_CALL(foo, InitY());
|
||||
EXPECT_CALL(foo, Bar())
|
||||
.After(init_x, init_y);
|
||||
```
|
||||
|
||||
says that `Bar()` can be called only after both `InitX()` and `InitY()` have
|
||||
been called.
|
||||
|
||||
If you don't know how many pre-requisites an expectation has when you write it,
|
||||
you can use an `ExpectationSet` to collect them:
|
||||
|
||||
```cpp
|
||||
using ::testing::ExpectationSet;
|
||||
...
|
||||
ExpectationSet all_inits;
|
||||
for (int i = 0; i < element_count; i++) {
|
||||
all_inits += EXPECT_CALL(foo, InitElement(i));
|
||||
}
|
||||
EXPECT_CALL(foo, Bar())
|
||||
.After(all_inits);
|
||||
```
|
||||
|
||||
says that `Bar()` can be called only after all elements have been initialized
|
||||
(but we don't care about which elements get initialized before the others).
|
||||
|
||||
Modifying an `ExpectationSet` after using it in an `.After()` doesn't affect the
|
||||
meaning of the `.After()`.
|
||||
|
||||
#### Sequences {#UsingSequences}
|
||||
|
||||
When you have a long chain of sequential expectations, it's easier to specify
|
||||
the order using **sequences**, which don't require you to given each expectation
|
||||
in the chain a different name. *All expected calls* in the same sequence must
|
||||
occur in the order they are specified.
|
||||
|
||||
```cpp
|
||||
using ::testing::Return;
|
||||
using ::testing::Sequence;
|
||||
Sequence s1, s2;
|
||||
...
|
||||
EXPECT_CALL(foo, Reset())
|
||||
.InSequence(s1, s2)
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(foo, GetSize())
|
||||
.InSequence(s1)
|
||||
.WillOnce(Return(1));
|
||||
EXPECT_CALL(foo, Describe(A<const char*>()))
|
||||
.InSequence(s2)
|
||||
.WillOnce(Return("dummy"));
|
||||
```
|
||||
|
||||
says that `Reset()` must be called before *both* `GetSize()` *and* `Describe()`,
|
||||
and the latter two can occur in any order.
|
||||
|
||||
To put many expectations in a sequence conveniently:
|
||||
|
||||
```cpp
|
||||
using ::testing::InSequence;
|
||||
{
|
||||
InSequence seq;
|
||||
|
||||
EXPECT_CALL(...)...;
|
||||
EXPECT_CALL(...)...;
|
||||
...
|
||||
EXPECT_CALL(...)...;
|
||||
}
|
||||
```
|
||||
|
||||
says that all expected calls in the scope of `seq` must occur in strict order.
|
||||
The name `seq` is irrelevant.
|
||||
|
||||
### Verifying and Resetting a Mock
|
||||
|
||||
gMock will verify the expectations on a mock object when it is destructed, or
|
||||
you can do it earlier:
|
||||
|
||||
```cpp
|
||||
using ::testing::Mock;
|
||||
...
|
||||
// Verifies and removes the expectations on mock_obj;
|
||||
// returns true if and only if successful.
|
||||
Mock::VerifyAndClearExpectations(&mock_obj);
|
||||
...
|
||||
// Verifies and removes the expectations on mock_obj;
|
||||
// also removes the default actions set by ON_CALL();
|
||||
// returns true if and only if successful.
|
||||
Mock::VerifyAndClear(&mock_obj);
|
||||
```
|
||||
|
||||
You can also tell gMock that a mock object can be leaked and doesn't need to be
|
||||
verified:
|
||||
|
||||
```cpp
|
||||
Mock::AllowLeak(&mock_obj);
|
||||
```
|
||||
|
||||
### Mock Classes
|
||||
|
||||
gMock defines a convenient mock class template
|
||||
|
||||
```cpp
|
||||
class MockFunction<R(A1, ..., An)> {
|
||||
public:
|
||||
MOCK_METHOD(R, Call, (A1, ..., An));
|
||||
};
|
||||
```
|
||||
|
||||
See this [recipe](cook_book.md#using-check-points) for one application of it.
|
||||
|
||||
### Flags
|
||||
|
||||
<!-- mdformat off(no multiline tables) -->
|
||||
| Flag | Description |
|
||||
| :----------------------------- | :---------------------------------------- |
|
||||
| `--gmock_catch_leaked_mocks=0` | Don't report leaked mock objects as failures. |
|
||||
| `--gmock_verbose=LEVEL` | Sets the default verbosity level (`info`, `warning`, or `error`) of Google Mock messages. |
|
||||
<!-- mdformat on -->
|
@@ -1,253 +0,0 @@
|
||||
// Copyright 2007, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Google Mock - a framework for writing C++ mock classes.
|
||||
//
|
||||
// This file implements MOCK_METHOD.
|
||||
|
||||
// GOOGLETEST_CM0002 DO NOT DELETE
|
||||
|
||||
#ifndef THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_ // NOLINT
|
||||
#define THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_ // NOLINT
|
||||
|
||||
#include "gmock/gmock-generated-function-mockers.h" // NOLINT
|
||||
#include "gmock/internal/gmock-pp.h"
|
||||
|
||||
#define MOCK_METHOD(...) \
|
||||
GMOCK_PP_VARIADIC_CALL(GMOCK_INTERNAL_MOCK_METHOD_ARG_, __VA_ARGS__)
|
||||
|
||||
#define GMOCK_INTERNAL_MOCK_METHOD_ARG_1(...) \
|
||||
GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__)
|
||||
|
||||
#define GMOCK_INTERNAL_MOCK_METHOD_ARG_2(...) \
|
||||
GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__)
|
||||
|
||||
#define GMOCK_INTERNAL_MOCK_METHOD_ARG_3(_Ret, _MethodName, _Args) \
|
||||
GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, ())
|
||||
|
||||
#define GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, _Spec) \
|
||||
GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Args); \
|
||||
GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Spec); \
|
||||
GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE( \
|
||||
GMOCK_PP_NARG0 _Args, GMOCK_INTERNAL_SIGNATURE(_Ret, _Args)); \
|
||||
GMOCK_INTERNAL_ASSERT_VALID_SPEC(_Spec) \
|
||||
GMOCK_INTERNAL_MOCK_METHOD_IMPL( \
|
||||
GMOCK_PP_NARG0 _Args, _MethodName, GMOCK_INTERNAL_HAS_CONST(_Spec), \
|
||||
GMOCK_INTERNAL_HAS_OVERRIDE(_Spec), GMOCK_INTERNAL_HAS_FINAL(_Spec), \
|
||||
GMOCK_INTERNAL_HAS_NOEXCEPT(_Spec), GMOCK_INTERNAL_GET_CALLTYPE(_Spec), \
|
||||
(GMOCK_INTERNAL_SIGNATURE(_Ret, _Args)))
|
||||
|
||||
#define GMOCK_INTERNAL_MOCK_METHOD_ARG_5(...) \
|
||||
GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__)
|
||||
|
||||
#define GMOCK_INTERNAL_MOCK_METHOD_ARG_6(...) \
|
||||
GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__)
|
||||
|
||||
#define GMOCK_INTERNAL_MOCK_METHOD_ARG_7(...) \
|
||||
GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__)
|
||||
|
||||
#define GMOCK_INTERNAL_WRONG_ARITY(...) \
|
||||
static_assert( \
|
||||
false, \
|
||||
"MOCK_METHOD must be called with 3 or 4 arguments. _Ret, " \
|
||||
"_MethodName, _Args and optionally _Spec. _Args and _Spec must be " \
|
||||
"enclosed in parentheses. If _Ret is a type with unprotected commas, " \
|
||||
"it must also be enclosed in parentheses.")
|
||||
|
||||
#define GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Tuple) \
|
||||
static_assert( \
|
||||
GMOCK_PP_IS_ENCLOSED_PARENS(_Tuple), \
|
||||
GMOCK_PP_STRINGIZE(_Tuple) " should be enclosed in parentheses.")
|
||||
|
||||
#define GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE(_N, ...) \
|
||||
static_assert( \
|
||||
std::is_function<__VA_ARGS__>::value, \
|
||||
"Signature must be a function type, maybe return type contains " \
|
||||
"unprotected comma."); \
|
||||
static_assert( \
|
||||
::testing::tuple_size<typename ::testing::internal::Function< \
|
||||
__VA_ARGS__>::ArgumentTuple>::value == _N, \
|
||||
"This method does not take " GMOCK_PP_STRINGIZE( \
|
||||
_N) " arguments. Parenthesize all types with unproctected commas.")
|
||||
|
||||
#define GMOCK_INTERNAL_ASSERT_VALID_SPEC(_Spec) \
|
||||
GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT, ~, _Spec)
|
||||
|
||||
#define GMOCK_INTERNAL_MOCK_METHOD_IMPL(_N, _MethodName, _Constness, \
|
||||
_Override, _Final, _Noexcept, \
|
||||
_CallType, _Signature) \
|
||||
typename ::testing::internal::Function<GMOCK_PP_REMOVE_PARENS( \
|
||||
_Signature)>::Result \
|
||||
GMOCK_INTERNAL_EXPAND(_CallType) \
|
||||
_MethodName(GMOCK_PP_REPEAT(GMOCK_INTERNAL_PARAMETER, _Signature, _N)) \
|
||||
GMOCK_PP_IF(_Constness, const, ) GMOCK_PP_IF(_Noexcept, noexcept, ) \
|
||||
GMOCK_PP_IF(_Override, override, ) \
|
||||
GMOCK_PP_IF(_Final, final, ) { \
|
||||
GMOCK_MOCKER_(_N, _Constness, _MethodName) \
|
||||
.SetOwnerAndName(this, #_MethodName); \
|
||||
return GMOCK_MOCKER_(_N, _Constness, _MethodName) \
|
||||
.Invoke(GMOCK_PP_REPEAT(GMOCK_INTERNAL_FORWARD_ARG, _Signature, _N)); \
|
||||
} \
|
||||
::testing::MockSpec<GMOCK_PP_REMOVE_PARENS(_Signature)> gmock_##_MethodName( \
|
||||
GMOCK_PP_REPEAT(GMOCK_INTERNAL_MATCHER_PARAMETER, _Signature, _N)) \
|
||||
GMOCK_PP_IF(_Constness, const, ) { \
|
||||
GMOCK_MOCKER_(_N, _Constness, _MethodName).RegisterOwner(this); \
|
||||
return GMOCK_MOCKER_(_N, _Constness, _MethodName) \
|
||||
.With(GMOCK_PP_REPEAT(GMOCK_INTERNAL_MATCHER_ARGUMENT, , _N)); \
|
||||
} \
|
||||
::testing::MockSpec<GMOCK_PP_REMOVE_PARENS(_Signature)> gmock_##_MethodName( \
|
||||
const ::testing::internal::WithoutMatchers&, \
|
||||
GMOCK_PP_IF(_Constness, const, )::testing::internal::Function< \
|
||||
GMOCK_PP_REMOVE_PARENS(_Signature)>*) \
|
||||
const GMOCK_PP_IF(_Noexcept, noexcept, ) { \
|
||||
return GMOCK_PP_CAT(::testing::internal::AdjustConstness_, \
|
||||
GMOCK_PP_IF(_Constness, const, ))(this) \
|
||||
->gmock_##_MethodName(GMOCK_PP_REPEAT( \
|
||||
GMOCK_INTERNAL_A_MATCHER_ARGUMENT, _Signature, _N)); \
|
||||
} \
|
||||
mutable ::testing::FunctionMocker<GMOCK_PP_REMOVE_PARENS(_Signature)> \
|
||||
GMOCK_MOCKER_(_N, _Constness, _MethodName)
|
||||
|
||||
#define GMOCK_INTERNAL_EXPAND(...) __VA_ARGS__
|
||||
|
||||
// Five Valid modifiers.
|
||||
#define GMOCK_INTERNAL_HAS_CONST(_Tuple) \
|
||||
GMOCK_PP_HAS_COMMA(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_CONST, ~, _Tuple))
|
||||
|
||||
#define GMOCK_INTERNAL_HAS_OVERRIDE(_Tuple) \
|
||||
GMOCK_PP_HAS_COMMA( \
|
||||
GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_OVERRIDE, ~, _Tuple))
|
||||
|
||||
#define GMOCK_INTERNAL_HAS_FINAL(_Tuple) \
|
||||
GMOCK_PP_HAS_COMMA(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_FINAL, ~, _Tuple))
|
||||
|
||||
#define GMOCK_INTERNAL_HAS_NOEXCEPT(_Tuple) \
|
||||
GMOCK_PP_HAS_COMMA( \
|
||||
GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_NOEXCEPT, ~, _Tuple))
|
||||
|
||||
#define GMOCK_INTERNAL_GET_CALLTYPE(_Tuple) \
|
||||
GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_GET_CALLTYPE_IMPL, ~, _Tuple)
|
||||
|
||||
#define GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT(_i, _, _elem) \
|
||||
static_assert( \
|
||||
(GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_CONST(_i, _, _elem)) + \
|
||||
GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_OVERRIDE(_i, _, _elem)) + \
|
||||
GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_FINAL(_i, _, _elem)) + \
|
||||
GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem)) + \
|
||||
GMOCK_INTERNAL_IS_CALLTYPE(_elem)) == 1, \
|
||||
GMOCK_PP_STRINGIZE( \
|
||||
_elem) " cannot be recognized as a valid specification modifier.");
|
||||
|
||||
// Modifiers implementation.
|
||||
#define GMOCK_INTERNAL_DETECT_CONST(_i, _, _elem) \
|
||||
GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_CONST_I_, _elem)
|
||||
|
||||
#define GMOCK_INTERNAL_DETECT_CONST_I_const ,
|
||||
|
||||
#define GMOCK_INTERNAL_DETECT_OVERRIDE(_i, _, _elem) \
|
||||
GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_OVERRIDE_I_, _elem)
|
||||
|
||||
#define GMOCK_INTERNAL_DETECT_OVERRIDE_I_override ,
|
||||
|
||||
#define GMOCK_INTERNAL_DETECT_FINAL(_i, _, _elem) \
|
||||
GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_FINAL_I_, _elem)
|
||||
|
||||
#define GMOCK_INTERNAL_DETECT_FINAL_I_final ,
|
||||
|
||||
// TODO(iserna): Maybe noexcept should accept an argument here as well.
|
||||
#define GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem) \
|
||||
GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_NOEXCEPT_I_, _elem)
|
||||
|
||||
#define GMOCK_INTERNAL_DETECT_NOEXCEPT_I_noexcept ,
|
||||
|
||||
#define GMOCK_INTERNAL_GET_CALLTYPE_IMPL(_i, _, _elem) \
|
||||
GMOCK_PP_IF(GMOCK_INTERNAL_IS_CALLTYPE(_elem), \
|
||||
GMOCK_INTERNAL_GET_VALUE_CALLTYPE, GMOCK_PP_EMPTY) \
|
||||
(_elem)
|
||||
|
||||
// TODO(iserna): GMOCK_INTERNAL_IS_CALLTYPE and
|
||||
// GMOCK_INTERNAL_GET_VALUE_CALLTYPE needed more expansions to work on windows
|
||||
// maybe they can be simplified somehow.
|
||||
#define GMOCK_INTERNAL_IS_CALLTYPE(_arg) \
|
||||
GMOCK_INTERNAL_IS_CALLTYPE_I( \
|
||||
GMOCK_PP_CAT(GMOCK_INTERNAL_IS_CALLTYPE_HELPER_, _arg))
|
||||
#define GMOCK_INTERNAL_IS_CALLTYPE_I(_arg) GMOCK_PP_IS_ENCLOSED_PARENS(_arg)
|
||||
|
||||
#define GMOCK_INTERNAL_GET_VALUE_CALLTYPE(_arg) \
|
||||
GMOCK_INTERNAL_GET_VALUE_CALLTYPE_I( \
|
||||
GMOCK_PP_CAT(GMOCK_INTERNAL_IS_CALLTYPE_HELPER_, _arg))
|
||||
#define GMOCK_INTERNAL_GET_VALUE_CALLTYPE_I(_arg) \
|
||||
GMOCK_PP_CAT(GMOCK_PP_IDENTITY, _arg)
|
||||
|
||||
#define GMOCK_INTERNAL_IS_CALLTYPE_HELPER_Calltype
|
||||
|
||||
#define GMOCK_INTERNAL_SIGNATURE(_Ret, _Args) \
|
||||
GMOCK_PP_IF(GMOCK_PP_IS_BEGIN_PARENS(_Ret), GMOCK_PP_REMOVE_PARENS, \
|
||||
GMOCK_PP_IDENTITY) \
|
||||
(_Ret)(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_GET_TYPE, _, _Args))
|
||||
|
||||
#define GMOCK_INTERNAL_GET_TYPE(_i, _, _elem) \
|
||||
GMOCK_PP_COMMA_IF(_i) \
|
||||
GMOCK_PP_IF(GMOCK_PP_IS_BEGIN_PARENS(_elem), GMOCK_PP_REMOVE_PARENS, \
|
||||
GMOCK_PP_IDENTITY) \
|
||||
(_elem)
|
||||
|
||||
#define GMOCK_INTERNAL_PARAMETER(_i, _Signature, _) \
|
||||
GMOCK_PP_COMMA_IF(_i) \
|
||||
GMOCK_INTERNAL_ARG_O(typename, GMOCK_PP_INC(_i), \
|
||||
GMOCK_PP_REMOVE_PARENS(_Signature)) \
|
||||
gmock_a##_i
|
||||
|
||||
#define GMOCK_INTERNAL_FORWARD_ARG(_i, _Signature, _) \
|
||||
GMOCK_PP_COMMA_IF(_i) \
|
||||
::std::forward<GMOCK_INTERNAL_ARG_O(typename, GMOCK_PP_INC(_i), \
|
||||
GMOCK_PP_REMOVE_PARENS(_Signature))>( \
|
||||
gmock_a##_i)
|
||||
|
||||
#define GMOCK_INTERNAL_MATCHER_PARAMETER(_i, _Signature, _) \
|
||||
GMOCK_PP_COMMA_IF(_i) \
|
||||
GMOCK_INTERNAL_MATCHER_O(typename, GMOCK_PP_INC(_i), \
|
||||
GMOCK_PP_REMOVE_PARENS(_Signature)) \
|
||||
gmock_a##_i
|
||||
|
||||
#define GMOCK_INTERNAL_MATCHER_ARGUMENT(_i, _1, _2) \
|
||||
GMOCK_PP_COMMA_IF(_i) \
|
||||
gmock_a##_i
|
||||
|
||||
#define GMOCK_INTERNAL_A_MATCHER_ARGUMENT(_i, _Signature, _) \
|
||||
GMOCK_PP_COMMA_IF(_i) \
|
||||
::testing::A<GMOCK_INTERNAL_ARG_O(typename, GMOCK_PP_INC(_i), \
|
||||
GMOCK_PP_REMOVE_PARENS(_Signature))>()
|
||||
|
||||
#define GMOCK_INTERNAL_ARG_O(_tn, _i, ...) GMOCK_ARG_(_tn, _i, __VA_ARGS__)
|
||||
|
||||
#define GMOCK_INTERNAL_MATCHER_O(_tn, _i, ...) \
|
||||
GMOCK_MATCHER_(_tn, _i, __VA_ARGS__)
|
||||
|
||||
#endif // THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_
|
File diff suppressed because it is too large
Load Diff
@@ -1,627 +0,0 @@
|
||||
$$ -*- mode: c++; -*-
|
||||
$$ This is a Pump source file. Please use Pump to convert it to
|
||||
$$ gmock-generated-actions.h.
|
||||
$$
|
||||
$var n = 10 $$ The maximum arity we support.
|
||||
$$}} This meta comment fixes auto-indentation in editors.
|
||||
// Copyright 2007, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
// Google Mock - a framework for writing C++ mock classes.
|
||||
//
|
||||
// This file implements some commonly used variadic actions.
|
||||
|
||||
// GOOGLETEST_CM0002 DO NOT DELETE
|
||||
|
||||
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
|
||||
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "gmock/gmock-actions.h"
|
||||
#include "gmock/internal/gmock-port.h"
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
// A macro from the ACTION* family (defined later in this file)
|
||||
// defines an action that can be used in a mock function. Typically,
|
||||
// these actions only care about a subset of the arguments of the mock
|
||||
// function. For example, if such an action only uses the second
|
||||
// argument, it can be used in any mock function that takes >= 2
|
||||
// arguments where the type of the second argument is compatible.
|
||||
//
|
||||
// Therefore, the action implementation must be prepared to take more
|
||||
// arguments than it needs. The ExcessiveArg type is used to
|
||||
// represent those excessive arguments. In order to keep the compiler
|
||||
// error messages tractable, we define it in the testing namespace
|
||||
// instead of testing::internal. However, this is an INTERNAL TYPE
|
||||
// and subject to change without notice, so a user MUST NOT USE THIS
|
||||
// TYPE DIRECTLY.
|
||||
struct ExcessiveArg {};
|
||||
|
||||
// A helper class needed for implementing the ACTION* macros.
|
||||
template <typename Result, class Impl>
|
||||
class ActionHelper {
|
||||
public:
|
||||
$range i 0..n
|
||||
$for i
|
||||
|
||||
[[
|
||||
$var template = [[$if i==0 [[]] $else [[
|
||||
$range j 0..i-1
|
||||
template <$for j, [[typename A$j]]>
|
||||
]]]]
|
||||
$range j 0..i-1
|
||||
$var As = [[$for j, [[A$j]]]]
|
||||
$var as = [[$for j, [[std::get<$j>(args)]]]]
|
||||
$range k 1..n-i
|
||||
$var eas = [[$for k, [[ExcessiveArg()]]]]
|
||||
$var arg_list = [[$if (i==0) | (i==n) [[$as$eas]] $else [[$as, $eas]]]]
|
||||
$template
|
||||
static Result Perform(Impl* impl, const ::std::tuple<$As>& args) {
|
||||
return impl->template gmock_PerformImpl<$As>(args, $arg_list);
|
||||
}
|
||||
|
||||
]]
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
||||
// The ACTION* family of macros can be used in a namespace scope to
|
||||
// define custom actions easily. The syntax:
|
||||
//
|
||||
// ACTION(name) { statements; }
|
||||
//
|
||||
// will define an action with the given name that executes the
|
||||
// statements. The value returned by the statements will be used as
|
||||
// the return value of the action. Inside the statements, you can
|
||||
// refer to the K-th (0-based) argument of the mock function by
|
||||
// 'argK', and refer to its type by 'argK_type'. For example:
|
||||
//
|
||||
// ACTION(IncrementArg1) {
|
||||
// arg1_type temp = arg1;
|
||||
// return ++(*temp);
|
||||
// }
|
||||
//
|
||||
// allows you to write
|
||||
//
|
||||
// ...WillOnce(IncrementArg1());
|
||||
//
|
||||
// You can also refer to the entire argument tuple and its type by
|
||||
// 'args' and 'args_type', and refer to the mock function type and its
|
||||
// return type by 'function_type' and 'return_type'.
|
||||
//
|
||||
// Note that you don't need to specify the types of the mock function
|
||||
// arguments. However rest assured that your code is still type-safe:
|
||||
// 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, for example.
|
||||
//
|
||||
// Sometimes you'll want to parameterize the action. For that you can use
|
||||
// another macro:
|
||||
//
|
||||
// ACTION_P(name, param_name) { statements; }
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// ACTION_P(Add, n) { return arg0 + n; }
|
||||
//
|
||||
// will allow you to write:
|
||||
//
|
||||
// ...WillOnce(Add(5));
|
||||
//
|
||||
// Note that you don't need to provide the type of the parameter
|
||||
// either. If you need to reference the type of a parameter named
|
||||
// 'foo', you can write 'foo_type'. For example, in the body of
|
||||
// ACTION_P(Add, n) above, you can write 'n_type' to refer to the type
|
||||
// of 'n'.
|
||||
//
|
||||
// We also provide ACTION_P2, ACTION_P3, ..., up to ACTION_P$n to support
|
||||
// multi-parameter actions.
|
||||
//
|
||||
// For the purpose of typing, you can view
|
||||
//
|
||||
// ACTION_Pk(Foo, p1, ..., pk) { ... }
|
||||
//
|
||||
// as shorthand for
|
||||
//
|
||||
// template <typename p1_type, ..., typename pk_type>
|
||||
// FooActionPk<p1_type, ..., pk_type> Foo(p1_type p1, ..., pk_type pk) { ... }
|
||||
//
|
||||
// In particular, you can provide the template type arguments
|
||||
// explicitly when invoking Foo(), as in Foo<long, bool>(5, false);
|
||||
// although usually you can rely on the compiler to infer the types
|
||||
// for you automatically. You can assign the result of expression
|
||||
// Foo(p1, ..., pk) to a variable of type FooActionPk<p1_type, ...,
|
||||
// pk_type>. This can be useful when composing actions.
|
||||
//
|
||||
// You can also overload actions with different numbers of parameters:
|
||||
//
|
||||
// ACTION_P(Plus, a) { ... }
|
||||
// ACTION_P2(Plus, a, b) { ... }
|
||||
//
|
||||
// While it's tempting to always use the ACTION* macros when defining
|
||||
// a new action, you should also consider implementing ActionInterface
|
||||
// or using MakePolymorphicAction() instead, especially if you need to
|
||||
// use the action a lot. While these 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 based on the number of parameters).
|
||||
//
|
||||
// CAVEAT:
|
||||
//
|
||||
// ACTION*() can only be used in a namespace scope as templates cannot be
|
||||
// declared inside of a local class.
|
||||
// Users can, however, define any local functors (e.g. a lambda) that
|
||||
// can be used as actions.
|
||||
//
|
||||
// MORE INFORMATION:
|
||||
//
|
||||
// To learn more about using these macros, please search for 'ACTION' on
|
||||
// https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md
|
||||
|
||||
$range i 0..n
|
||||
$range k 0..n-1
|
||||
|
||||
// An internal macro needed for implementing ACTION*().
|
||||
#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_\
|
||||
const args_type& args GTEST_ATTRIBUTE_UNUSED_
|
||||
$for k [[, \
|
||||
const arg$k[[]]_type& arg$k GTEST_ATTRIBUTE_UNUSED_]]
|
||||
|
||||
|
||||
// Sometimes you want to give an action explicit template parameters
|
||||
// that cannot be inferred from its value parameters. ACTION() and
|
||||
// ACTION_P*() don't support that. ACTION_TEMPLATE() remedies that
|
||||
// and can be viewed as an extension to ACTION() and ACTION_P*().
|
||||
//
|
||||
// The syntax:
|
||||
//
|
||||
// ACTION_TEMPLATE(ActionName,
|
||||
// HAS_m_TEMPLATE_PARAMS(kind1, name1, ..., kind_m, name_m),
|
||||
// AND_n_VALUE_PARAMS(p1, ..., p_n)) { statements; }
|
||||
//
|
||||
// defines an action template that takes m explicit template
|
||||
// parameters and n value parameters. name_i is the name of the i-th
|
||||
// template parameter, and kind_i specifies whether it's a typename,
|
||||
// an integral constant, or a template. p_i is the name of the i-th
|
||||
// value parameter.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// // DuplicateArg<k, T>(output) converts the k-th argument of the mock
|
||||
// // function to type T and copies it to *output.
|
||||
// ACTION_TEMPLATE(DuplicateArg,
|
||||
// HAS_2_TEMPLATE_PARAMS(int, k, typename, T),
|
||||
// AND_1_VALUE_PARAMS(output)) {
|
||||
// *output = T(::std::get<k>(args));
|
||||
// }
|
||||
// ...
|
||||
// int n;
|
||||
// EXPECT_CALL(mock, Foo(_, _))
|
||||
// .WillOnce(DuplicateArg<1, unsigned char>(&n));
|
||||
//
|
||||
// To create an instance of an action template, write:
|
||||
//
|
||||
// ActionName<t1, ..., t_m>(v1, ..., v_n)
|
||||
//
|
||||
// where the ts are the template arguments and the vs are the value
|
||||
// arguments. The value argument types are inferred by the compiler.
|
||||
// If you want to explicitly specify the value argument types, you can
|
||||
// provide additional template arguments:
|
||||
//
|
||||
// ActionName<t1, ..., t_m, u1, ..., u_k>(v1, ..., v_n)
|
||||
//
|
||||
// where u_i is the desired type of v_i.
|
||||
//
|
||||
// ACTION_TEMPLATE and ACTION/ACTION_P* can be overloaded on the
|
||||
// number of value parameters, but not on the number of template
|
||||
// parameters. Without the restriction, the meaning of the following
|
||||
// is unclear:
|
||||
//
|
||||
// OverloadedAction<int, bool>(x);
|
||||
//
|
||||
// Are we using a single-template-parameter action where 'bool' refers
|
||||
// to the type of x, or are we using a two-template-parameter action
|
||||
// where the compiler is asked to infer the type of x?
|
||||
//
|
||||
// Implementation notes:
|
||||
//
|
||||
// GMOCK_INTERNAL_*_HAS_m_TEMPLATE_PARAMS and
|
||||
// GMOCK_INTERNAL_*_AND_n_VALUE_PARAMS are internal macros for
|
||||
// implementing ACTION_TEMPLATE. The main trick we use is to create
|
||||
// new macro invocations when expanding a macro. For example, we have
|
||||
//
|
||||
// #define ACTION_TEMPLATE(name, template_params, value_params)
|
||||
// ... GMOCK_INTERNAL_DECL_##template_params ...
|
||||
//
|
||||
// which causes ACTION_TEMPLATE(..., HAS_1_TEMPLATE_PARAMS(typename, T), ...)
|
||||
// to expand to
|
||||
//
|
||||
// ... GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS(typename, T) ...
|
||||
//
|
||||
// Since GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS is a macro, the
|
||||
// preprocessor will continue to expand it to
|
||||
//
|
||||
// ... typename T ...
|
||||
//
|
||||
// This technique conforms to the C++ standard and is portable. It
|
||||
// allows us to implement action templates using O(N) code, where N is
|
||||
// the maximum number of template/value parameters supported. Without
|
||||
// using it, we'd have to devote O(N^2) amount of code to implement all
|
||||
// combinations of m and n.
|
||||
|
||||
// Declares the template parameters.
|
||||
|
||||
$range j 1..n
|
||||
$for j [[
|
||||
$range m 0..j-1
|
||||
#define GMOCK_INTERNAL_DECL_HAS_$j[[]]
|
||||
_TEMPLATE_PARAMS($for m, [[kind$m, name$m]]) $for m, [[kind$m name$m]]
|
||||
|
||||
|
||||
]]
|
||||
|
||||
// Lists the template parameters.
|
||||
|
||||
$for j [[
|
||||
$range m 0..j-1
|
||||
#define GMOCK_INTERNAL_LIST_HAS_$j[[]]
|
||||
_TEMPLATE_PARAMS($for m, [[kind$m, name$m]]) $for m, [[name$m]]
|
||||
|
||||
|
||||
]]
|
||||
|
||||
// Declares the types of value parameters.
|
||||
|
||||
$for i [[
|
||||
$range j 0..i-1
|
||||
#define GMOCK_INTERNAL_DECL_TYPE_AND_$i[[]]
|
||||
_VALUE_PARAMS($for j, [[p$j]]) $for j [[, typename p$j##_type]]
|
||||
|
||||
|
||||
]]
|
||||
|
||||
// Initializes the value parameters.
|
||||
|
||||
$for i [[
|
||||
$range j 0..i-1
|
||||
#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(::std::move(gmock_p$j))]]
|
||||
|
||||
|
||||
]]
|
||||
|
||||
// Declares the fields for storing the value parameters.
|
||||
|
||||
$for i [[
|
||||
$range j 0..i-1
|
||||
#define GMOCK_INTERNAL_DEFN_AND_$i[[]]
|
||||
_VALUE_PARAMS($for j, [[p$j]]) $for j [[p$j##_type p$j; ]]
|
||||
|
||||
|
||||
]]
|
||||
|
||||
// Lists the value parameters.
|
||||
|
||||
$for i [[
|
||||
$range j 0..i-1
|
||||
#define GMOCK_INTERNAL_LIST_AND_$i[[]]
|
||||
_VALUE_PARAMS($for j, [[p$j]]) $for j, [[p$j]]
|
||||
|
||||
|
||||
]]
|
||||
|
||||
// Lists the value parameter types.
|
||||
|
||||
$for i [[
|
||||
$range j 0..i-1
|
||||
#define GMOCK_INTERNAL_LIST_TYPE_AND_$i[[]]
|
||||
_VALUE_PARAMS($for j, [[p$j]]) $for j [[, p$j##_type]]
|
||||
|
||||
|
||||
]]
|
||||
|
||||
// Declares the value parameters.
|
||||
|
||||
$for i [[
|
||||
$range j 0..i-1
|
||||
#define GMOCK_INTERNAL_DECL_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]]) [[]]
|
||||
$for j, [[p$j##_type p$j]]
|
||||
|
||||
|
||||
]]
|
||||
|
||||
// The suffix of the class template implementing the action template.
|
||||
$for i [[
|
||||
|
||||
|
||||
$range j 0..i-1
|
||||
#define GMOCK_INTERNAL_COUNT_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]]) [[]]
|
||||
$if i==1 [[P]] $elif i>=2 [[P$i]]
|
||||
]]
|
||||
|
||||
|
||||
// The name of the class template implementing the action template.
|
||||
#define GMOCK_ACTION_CLASS_(name, value_params)\
|
||||
GTEST_CONCAT_TOKEN_(name##Action, GMOCK_INTERNAL_COUNT_##value_params)
|
||||
|
||||
$range k 0..n-1
|
||||
|
||||
#define ACTION_TEMPLATE(name, template_params, value_params)\
|
||||
template <GMOCK_INTERNAL_DECL_##template_params\
|
||||
GMOCK_INTERNAL_DECL_TYPE_##value_params>\
|
||||
class GMOCK_ACTION_CLASS_(name, value_params) {\
|
||||
public:\
|
||||
explicit GMOCK_ACTION_CLASS_(name, value_params)\
|
||||
GMOCK_INTERNAL_INIT_##value_params {}\
|
||||
template <typename F>\
|
||||
class gmock_Impl : public ::testing::ActionInterface<F> {\
|
||||
public:\
|
||||
typedef F function_type;\
|
||||
typedef typename ::testing::internal::Function<F>::Result return_type;\
|
||||
typedef typename ::testing::internal::Function<F>::ArgumentTuple\
|
||||
args_type;\
|
||||
explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {}\
|
||||
virtual return_type Perform(const args_type& args) {\
|
||||
return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
|
||||
Perform(this, args);\
|
||||
}\
|
||||
template <$for k, [[typename arg$k[[]]_type]]>\
|
||||
return_type gmock_PerformImpl(const args_type& args[[]]
|
||||
$for k [[, const arg$k[[]]_type& arg$k]]) const;\
|
||||
GMOCK_INTERNAL_DEFN_##value_params\
|
||||
private:\
|
||||
GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
|
||||
};\
|
||||
template <typename F> operator ::testing::Action<F>() const {\
|
||||
return ::testing::Action<F>(\
|
||||
new gmock_Impl<F>(GMOCK_INTERNAL_LIST_##value_params));\
|
||||
}\
|
||||
GMOCK_INTERNAL_DEFN_##value_params\
|
||||
private:\
|
||||
GTEST_DISALLOW_ASSIGN_(GMOCK_ACTION_CLASS_(name, value_params));\
|
||||
};\
|
||||
template <GMOCK_INTERNAL_DECL_##template_params\
|
||||
GMOCK_INTERNAL_DECL_TYPE_##value_params>\
|
||||
inline GMOCK_ACTION_CLASS_(name, value_params)<\
|
||||
GMOCK_INTERNAL_LIST_##template_params\
|
||||
GMOCK_INTERNAL_LIST_TYPE_##value_params> name(\
|
||||
GMOCK_INTERNAL_DECL_##value_params) {\
|
||||
return GMOCK_ACTION_CLASS_(name, value_params)<\
|
||||
GMOCK_INTERNAL_LIST_##template_params\
|
||||
GMOCK_INTERNAL_LIST_TYPE_##value_params>(\
|
||||
GMOCK_INTERNAL_LIST_##value_params);\
|
||||
}\
|
||||
template <GMOCK_INTERNAL_DECL_##template_params\
|
||||
GMOCK_INTERNAL_DECL_TYPE_##value_params>\
|
||||
template <typename F>\
|
||||
template <typename arg0_type, typename arg1_type, typename arg2_type, \
|
||||
typename arg3_type, typename arg4_type, typename arg5_type, \
|
||||
typename arg6_type, typename arg7_type, typename arg8_type, \
|
||||
typename arg9_type>\
|
||||
typename ::testing::internal::Function<F>::Result\
|
||||
GMOCK_ACTION_CLASS_(name, value_params)<\
|
||||
GMOCK_INTERNAL_LIST_##template_params\
|
||||
GMOCK_INTERNAL_LIST_TYPE_##value_params>::gmock_Impl<F>::\
|
||||
gmock_PerformImpl(\
|
||||
GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
|
||||
|
||||
$for i
|
||||
|
||||
[[
|
||||
$var template = [[$if i==0 [[]] $else [[
|
||||
$range j 0..i-1
|
||||
|
||||
template <$for j, [[typename p$j##_type]]>\
|
||||
]]]]
|
||||
$var class_name = [[name##Action[[$if i==0 [[]] $elif i==1 [[P]]
|
||||
$else [[P$i]]]]]]
|
||||
$range j 0..i-1
|
||||
$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 inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(::std::forward<p$j##_type>(gmock_p$j))]]]]]]
|
||||
$var param_field_decls = [[$for j
|
||||
[[
|
||||
|
||||
p$j##_type p$j;\
|
||||
]]]]
|
||||
$var param_field_decls2 = [[$for j
|
||||
[[
|
||||
|
||||
p$j##_type p$j;\
|
||||
]]]]
|
||||
$var params = [[$for j, [[p$j]]]]
|
||||
$var param_types = [[$if i==0 [[]] $else [[<$for j, [[p$j##_type]]>]]]]
|
||||
$var typename_arg_types = [[$for k, [[typename arg$k[[]]_type]]]]
|
||||
$var arg_types_and_names = [[$for k, [[const arg$k[[]]_type& arg$k]]]]
|
||||
$var macro_name = [[$if i==0 [[ACTION]] $elif i==1 [[ACTION_P]]
|
||||
$else [[ACTION_P$i]]]]
|
||||
|
||||
#define $macro_name(name$for j [[, p$j]])\$template
|
||||
class $class_name {\
|
||||
public:\
|
||||
[[$if i==1 [[explicit ]]]]$class_name($ctor_param_list)$inits {}\
|
||||
template <typename F>\
|
||||
class gmock_Impl : public ::testing::ActionInterface<F> {\
|
||||
public:\
|
||||
typedef F function_type;\
|
||||
typedef typename ::testing::internal::Function<F>::Result return_type;\
|
||||
typedef typename ::testing::internal::Function<F>::ArgumentTuple\
|
||||
args_type;\
|
||||
[[$if i==1 [[explicit ]]]]gmock_Impl($ctor_param_list)$inits {}\
|
||||
virtual return_type Perform(const args_type& args) {\
|
||||
return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
|
||||
Perform(this, args);\
|
||||
}\
|
||||
template <$typename_arg_types>\
|
||||
return_type gmock_PerformImpl(const args_type& args, [[]]
|
||||
$arg_types_and_names) const;\$param_field_decls
|
||||
private:\
|
||||
GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
|
||||
};\
|
||||
template <typename F> operator ::testing::Action<F>() const {\
|
||||
return ::testing::Action<F>(new gmock_Impl<F>($params));\
|
||||
}\$param_field_decls2
|
||||
private:\
|
||||
GTEST_DISALLOW_ASSIGN_($class_name);\
|
||||
};\$template
|
||||
inline $class_name$param_types name($param_types_and_names) {\
|
||||
return $class_name$param_types($params);\
|
||||
}\$template
|
||||
template <typename F>\
|
||||
template <$typename_arg_types>\
|
||||
typename ::testing::internal::Function<F>::Result\
|
||||
$class_name$param_types::gmock_Impl<F>::gmock_PerformImpl(\
|
||||
GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
|
||||
]]
|
||||
$$ } // This meta comment fixes auto-indentation in Emacs. It won't
|
||||
$$ // show up in the generated code.
|
||||
|
||||
|
||||
namespace testing {
|
||||
|
||||
|
||||
// The ACTION*() macros trigger warning C4100 (unreferenced formal
|
||||
// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in
|
||||
// the macro definition, as the warnings are generated when the macro
|
||||
// is expanded and macro expansion cannot contain #pragma. Therefore
|
||||
// we suppress them here.
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4100)
|
||||
#endif
|
||||
|
||||
// Various overloads for InvokeArgument<N>().
|
||||
//
|
||||
// The InvokeArgument<N>(a1, a2, ..., a_k) action invokes the N-th
|
||||
// (0-based) argument, which must be a k-ary callable, of the mock
|
||||
// function, with arguments a1, a2, ..., a_k.
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// 1. The arguments are passed by value by default. If you need to
|
||||
// pass an argument by reference, wrap it inside ByRef(). For
|
||||
// example,
|
||||
//
|
||||
// InvokeArgument<1>(5, string("Hello"), ByRef(foo))
|
||||
//
|
||||
// passes 5 and string("Hello") by value, and passes foo by
|
||||
// reference.
|
||||
//
|
||||
// 2. If the callable takes an argument by reference but ByRef() is
|
||||
// not used, it will receive the reference to a copy of the value,
|
||||
// instead of the original value. For example, when the 0-th
|
||||
// argument of the mock function takes a const string&, the action
|
||||
//
|
||||
// InvokeArgument<0>(string("Hello"))
|
||||
//
|
||||
// makes a copy of the temporary string("Hello") object and passes a
|
||||
// reference of the copy, instead of the original temporary object,
|
||||
// to the callable. This makes it easy for a user to define an
|
||||
// InvokeArgument action from temporary values and have it performed
|
||||
// later.
|
||||
|
||||
namespace internal {
|
||||
namespace invoke_argument {
|
||||
|
||||
// Appears in InvokeArgumentAdl's argument list to help avoid
|
||||
// accidental calls to user functions of the same name.
|
||||
struct AdlTag {};
|
||||
|
||||
// InvokeArgumentAdl - a helper for InvokeArgument.
|
||||
// The basic overloads are provided here for generic functors.
|
||||
// Overloads for other custom-callables are provided in the
|
||||
// internal/custom/callback-actions.h header.
|
||||
|
||||
$range i 0..n
|
||||
$for i
|
||||
[[
|
||||
$range j 1..i
|
||||
|
||||
template <typename R, typename F[[$for j [[, typename A$j]]]]>
|
||||
R InvokeArgumentAdl(AdlTag, F f[[$for j [[, A$j a$j]]]]) {
|
||||
return f([[$for j, [[a$j]]]]);
|
||||
}
|
||||
]]
|
||||
|
||||
} // namespace invoke_argument
|
||||
} // namespace internal
|
||||
|
||||
$range i 0..n
|
||||
$for i [[
|
||||
$range j 0..i-1
|
||||
|
||||
ACTION_TEMPLATE(InvokeArgument,
|
||||
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||
AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]])) {
|
||||
using internal::invoke_argument::InvokeArgumentAdl;
|
||||
return InvokeArgumentAdl<return_type>(
|
||||
internal::invoke_argument::AdlTag(),
|
||||
::std::get<k>(args)$for j [[, p$j]]);
|
||||
}
|
||||
|
||||
]]
|
||||
|
||||
// Various overloads for ReturnNew<T>().
|
||||
//
|
||||
// The ReturnNew<T>(a1, a2, ..., a_k) action returns a pointer to a new
|
||||
// instance of type T, constructed on the heap with constructor arguments
|
||||
// a1, a2, ..., and a_k. The caller assumes ownership of the returned value.
|
||||
$range i 0..n
|
||||
$for i [[
|
||||
$range j 0..i-1
|
||||
$var ps = [[$for j, [[p$j]]]]
|
||||
|
||||
ACTION_TEMPLATE(ReturnNew,
|
||||
HAS_1_TEMPLATE_PARAMS(typename, T),
|
||||
AND_$i[[]]_VALUE_PARAMS($ps)) {
|
||||
return new T($ps);
|
||||
}
|
||||
|
||||
]]
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace testing
|
||||
|
||||
// Include any custom callback actions added by the local installation.
|
||||
// We must include this header at the end to make sure it can use the
|
||||
// declarations from this file.
|
||||
#include "gmock/internal/custom/gmock-generated-actions.h"
|
||||
|
||||
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
|
@@ -1,752 +0,0 @@
|
||||
// This file was GENERATED by command:
|
||||
// pump.py gmock-generated-function-mockers.h.pump
|
||||
// DO NOT EDIT BY HAND!!!
|
||||
|
||||
// Copyright 2007, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
// Google Mock - a framework for writing C++ mock classes.
|
||||
//
|
||||
// This file implements function mockers of various arities.
|
||||
|
||||
// GOOGLETEST_CM0002 DO NOT DELETE
|
||||
|
||||
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
||||
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
#include "gmock/gmock-spec-builders.h"
|
||||
#include "gmock/internal/gmock-internal-utils.h"
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
// 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
|
||||
|
||||
// The style guide prohibits "using" statements in a namespace scope
|
||||
// inside a header file. However, the FunctionMocker class template
|
||||
// is meant to be defined in the ::testing namespace. The following
|
||||
// line is just a trick for working around a bug in MSVC 8.0, which
|
||||
// cannot handle it if we define FunctionMocker in ::testing.
|
||||
using internal::FunctionMocker;
|
||||
|
||||
// GMOCK_RESULT_(tn, F) expands to the result type of function type F.
|
||||
// We define this as a variadic macro in case F contains unprotected
|
||||
// commas (the same reason that we use variadic macros in other places
|
||||
// in this file).
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_RESULT_(tn, ...) \
|
||||
tn ::testing::internal::Function<__VA_ARGS__>::Result
|
||||
|
||||
// The type of argument N of the given function type.
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_ARG_(tn, N, ...) \
|
||||
tn ::testing::internal::Function<__VA_ARGS__>::template Arg<N-1>::type
|
||||
|
||||
// The matcher type for argument N of the given function type.
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_MATCHER_(tn, N, ...) \
|
||||
const ::testing::Matcher<GMOCK_ARG_(tn, N, __VA_ARGS__)>&
|
||||
|
||||
// The variable for mocking the given method.
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_MOCKER_(arity, constness, Method) \
|
||||
GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__)
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_METHOD0_(tn, constness, ct, Method, ...) \
|
||||
static_assert(0 == \
|
||||
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
|
||||
"MOCK_METHOD<N> must match argument count.");\
|
||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||
) constness { \
|
||||
GMOCK_MOCKER_(0, constness, Method).SetOwnerAndName(this, #Method); \
|
||||
return GMOCK_MOCKER_(0, constness, Method).Invoke(); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> \
|
||||
gmock_##Method() constness { \
|
||||
GMOCK_MOCKER_(0, constness, Method).RegisterOwner(this); \
|
||||
return GMOCK_MOCKER_(0, constness, Method).With(); \
|
||||
} \
|
||||
::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(); \
|
||||
} \
|
||||
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(0, constness, \
|
||||
Method)
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_METHOD1_(tn, constness, ct, Method, ...) \
|
||||
static_assert(1 == \
|
||||
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
|
||||
"MOCK_METHOD<N> must match argument count.");\
|
||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1) constness { \
|
||||
GMOCK_MOCKER_(1, constness, Method).SetOwnerAndName(this, #Method); \
|
||||
return GMOCK_MOCKER_(1, constness, \
|
||||
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
|
||||
__VA_ARGS__)>(gmock_a1)); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> \
|
||||
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1) constness { \
|
||||
GMOCK_MOCKER_(1, constness, Method).RegisterOwner(this); \
|
||||
return GMOCK_MOCKER_(1, constness, Method).With(gmock_a1); \
|
||||
} \
|
||||
::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(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>()); \
|
||||
} \
|
||||
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(1, constness, \
|
||||
Method)
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_METHOD2_(tn, constness, ct, Method, ...) \
|
||||
static_assert(2 == \
|
||||
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
|
||||
"MOCK_METHOD<N> must match argument count.");\
|
||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
|
||||
__VA_ARGS__) gmock_a2) constness { \
|
||||
GMOCK_MOCKER_(2, constness, Method).SetOwnerAndName(this, #Method); \
|
||||
return GMOCK_MOCKER_(2, constness, \
|
||||
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
|
||||
__VA_ARGS__)>(gmock_a1), \
|
||||
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2)); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> \
|
||||
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2) constness { \
|
||||
GMOCK_MOCKER_(2, constness, Method).RegisterOwner(this); \
|
||||
return GMOCK_MOCKER_(2, constness, Method).With(gmock_a1, gmock_a2); \
|
||||
} \
|
||||
::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(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>()); \
|
||||
} \
|
||||
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(2, constness, \
|
||||
Method)
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_METHOD3_(tn, constness, ct, Method, ...) \
|
||||
static_assert(3 == \
|
||||
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
|
||||
"MOCK_METHOD<N> must match argument count.");\
|
||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
|
||||
__VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, \
|
||||
__VA_ARGS__) gmock_a3) constness { \
|
||||
GMOCK_MOCKER_(3, constness, Method).SetOwnerAndName(this, #Method); \
|
||||
return GMOCK_MOCKER_(3, constness, \
|
||||
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
|
||||
__VA_ARGS__)>(gmock_a1), \
|
||||
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \
|
||||
::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3)); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> \
|
||||
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3) constness { \
|
||||
GMOCK_MOCKER_(3, constness, Method).RegisterOwner(this); \
|
||||
return GMOCK_MOCKER_(3, constness, Method).With(gmock_a1, gmock_a2, \
|
||||
gmock_a3); \
|
||||
} \
|
||||
::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(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>()); \
|
||||
} \
|
||||
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(3, constness, \
|
||||
Method)
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_METHOD4_(tn, constness, ct, Method, ...) \
|
||||
static_assert(4 == \
|
||||
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
|
||||
"MOCK_METHOD<N> must match argument count.");\
|
||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
|
||||
__VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4) constness { \
|
||||
GMOCK_MOCKER_(4, constness, Method).SetOwnerAndName(this, #Method); \
|
||||
return GMOCK_MOCKER_(4, constness, \
|
||||
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
|
||||
__VA_ARGS__)>(gmock_a1), \
|
||||
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \
|
||||
::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \
|
||||
::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4)); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> \
|
||||
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4) constness { \
|
||||
GMOCK_MOCKER_(4, constness, Method).RegisterOwner(this); \
|
||||
return GMOCK_MOCKER_(4, constness, Method).With(gmock_a1, gmock_a2, \
|
||||
gmock_a3, gmock_a4); \
|
||||
} \
|
||||
::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(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>()); \
|
||||
} \
|
||||
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(4, constness, \
|
||||
Method)
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_METHOD5_(tn, constness, ct, Method, ...) \
|
||||
static_assert(5 == \
|
||||
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
|
||||
"MOCK_METHOD<N> must match argument count.");\
|
||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
|
||||
__VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \
|
||||
__VA_ARGS__) gmock_a5) constness { \
|
||||
GMOCK_MOCKER_(5, constness, Method).SetOwnerAndName(this, #Method); \
|
||||
return GMOCK_MOCKER_(5, constness, \
|
||||
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
|
||||
__VA_ARGS__)>(gmock_a1), \
|
||||
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \
|
||||
::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \
|
||||
::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4), \
|
||||
::std::forward<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(gmock_a5)); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> \
|
||||
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
|
||||
GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5) constness { \
|
||||
GMOCK_MOCKER_(5, constness, Method).RegisterOwner(this); \
|
||||
return GMOCK_MOCKER_(5, constness, Method).With(gmock_a1, gmock_a2, \
|
||||
gmock_a3, gmock_a4, gmock_a5); \
|
||||
} \
|
||||
::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(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 5, __VA_ARGS__)>()); \
|
||||
} \
|
||||
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(5, constness, \
|
||||
Method)
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_METHOD6_(tn, constness, ct, Method, ...) \
|
||||
static_assert(6 == \
|
||||
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
|
||||
"MOCK_METHOD<N> must match argument count.");\
|
||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
|
||||
__VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \
|
||||
__VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, \
|
||||
__VA_ARGS__) gmock_a6) constness { \
|
||||
GMOCK_MOCKER_(6, constness, Method).SetOwnerAndName(this, #Method); \
|
||||
return GMOCK_MOCKER_(6, constness, \
|
||||
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
|
||||
__VA_ARGS__)>(gmock_a1), \
|
||||
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \
|
||||
::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \
|
||||
::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4), \
|
||||
::std::forward<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(gmock_a5), \
|
||||
::std::forward<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(gmock_a6)); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> \
|
||||
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
|
||||
GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
|
||||
GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6) constness { \
|
||||
GMOCK_MOCKER_(6, constness, Method).RegisterOwner(this); \
|
||||
return GMOCK_MOCKER_(6, constness, Method).With(gmock_a1, gmock_a2, \
|
||||
gmock_a3, gmock_a4, gmock_a5, gmock_a6); \
|
||||
} \
|
||||
::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(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 6, __VA_ARGS__)>()); \
|
||||
} \
|
||||
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(6, constness, \
|
||||
Method)
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_METHOD7_(tn, constness, ct, Method, ...) \
|
||||
static_assert(7 == \
|
||||
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
|
||||
"MOCK_METHOD<N> must match argument count.");\
|
||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
|
||||
__VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \
|
||||
__VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \
|
||||
GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7) constness { \
|
||||
GMOCK_MOCKER_(7, constness, Method).SetOwnerAndName(this, #Method); \
|
||||
return GMOCK_MOCKER_(7, constness, \
|
||||
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
|
||||
__VA_ARGS__)>(gmock_a1), \
|
||||
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \
|
||||
::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \
|
||||
::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4), \
|
||||
::std::forward<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(gmock_a5), \
|
||||
::std::forward<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(gmock_a6), \
|
||||
::std::forward<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(gmock_a7)); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> \
|
||||
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
|
||||
GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
|
||||
GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \
|
||||
GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7) constness { \
|
||||
GMOCK_MOCKER_(7, constness, Method).RegisterOwner(this); \
|
||||
return GMOCK_MOCKER_(7, constness, Method).With(gmock_a1, gmock_a2, \
|
||||
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7); \
|
||||
} \
|
||||
::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(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 7, __VA_ARGS__)>()); \
|
||||
} \
|
||||
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(7, constness, \
|
||||
Method)
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_METHOD8_(tn, constness, ct, Method, ...) \
|
||||
static_assert(8 == \
|
||||
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
|
||||
"MOCK_METHOD<N> must match argument count.");\
|
||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
|
||||
__VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \
|
||||
__VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \
|
||||
GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7, GMOCK_ARG_(tn, 8, \
|
||||
__VA_ARGS__) gmock_a8) constness { \
|
||||
GMOCK_MOCKER_(8, constness, Method).SetOwnerAndName(this, #Method); \
|
||||
return GMOCK_MOCKER_(8, constness, \
|
||||
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
|
||||
__VA_ARGS__)>(gmock_a1), \
|
||||
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \
|
||||
::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \
|
||||
::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4), \
|
||||
::std::forward<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(gmock_a5), \
|
||||
::std::forward<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(gmock_a6), \
|
||||
::std::forward<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(gmock_a7), \
|
||||
::std::forward<GMOCK_ARG_(tn, 8, __VA_ARGS__)>(gmock_a8)); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> \
|
||||
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
|
||||
GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
|
||||
GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \
|
||||
GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7, \
|
||||
GMOCK_MATCHER_(tn, 8, __VA_ARGS__) gmock_a8) constness { \
|
||||
GMOCK_MOCKER_(8, constness, Method).RegisterOwner(this); \
|
||||
return GMOCK_MOCKER_(8, constness, Method).With(gmock_a1, gmock_a2, \
|
||||
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8); \
|
||||
} \
|
||||
::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(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 8, __VA_ARGS__)>()); \
|
||||
} \
|
||||
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(8, constness, \
|
||||
Method)
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_METHOD9_(tn, constness, ct, Method, ...) \
|
||||
static_assert(9 == \
|
||||
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
|
||||
"MOCK_METHOD<N> must match argument count.");\
|
||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
|
||||
__VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \
|
||||
__VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \
|
||||
GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7, GMOCK_ARG_(tn, 8, \
|
||||
__VA_ARGS__) gmock_a8, GMOCK_ARG_(tn, 9, \
|
||||
__VA_ARGS__) gmock_a9) constness { \
|
||||
GMOCK_MOCKER_(9, constness, Method).SetOwnerAndName(this, #Method); \
|
||||
return GMOCK_MOCKER_(9, constness, \
|
||||
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
|
||||
__VA_ARGS__)>(gmock_a1), \
|
||||
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \
|
||||
::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \
|
||||
::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4), \
|
||||
::std::forward<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(gmock_a5), \
|
||||
::std::forward<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(gmock_a6), \
|
||||
::std::forward<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(gmock_a7), \
|
||||
::std::forward<GMOCK_ARG_(tn, 8, __VA_ARGS__)>(gmock_a8), \
|
||||
::std::forward<GMOCK_ARG_(tn, 9, __VA_ARGS__)>(gmock_a9)); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> \
|
||||
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
|
||||
GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
|
||||
GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \
|
||||
GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7, \
|
||||
GMOCK_MATCHER_(tn, 8, __VA_ARGS__) gmock_a8, \
|
||||
GMOCK_MATCHER_(tn, 9, __VA_ARGS__) gmock_a9) constness { \
|
||||
GMOCK_MOCKER_(9, constness, Method).RegisterOwner(this); \
|
||||
return GMOCK_MOCKER_(9, constness, Method).With(gmock_a1, gmock_a2, \
|
||||
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, \
|
||||
gmock_a9); \
|
||||
} \
|
||||
::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(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 8, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 9, __VA_ARGS__)>()); \
|
||||
} \
|
||||
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(9, constness, \
|
||||
Method)
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_METHOD10_(tn, constness, ct, Method, ...) \
|
||||
static_assert(10 == \
|
||||
::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \
|
||||
"MOCK_METHOD<N> must match argument count.");\
|
||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||
GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \
|
||||
__VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \
|
||||
__VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \
|
||||
GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7, GMOCK_ARG_(tn, 8, \
|
||||
__VA_ARGS__) gmock_a8, GMOCK_ARG_(tn, 9, __VA_ARGS__) gmock_a9, \
|
||||
GMOCK_ARG_(tn, 10, __VA_ARGS__) gmock_a10) constness { \
|
||||
GMOCK_MOCKER_(10, constness, Method).SetOwnerAndName(this, #Method); \
|
||||
return GMOCK_MOCKER_(10, constness, \
|
||||
Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \
|
||||
__VA_ARGS__)>(gmock_a1), \
|
||||
::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \
|
||||
::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \
|
||||
::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4), \
|
||||
::std::forward<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(gmock_a5), \
|
||||
::std::forward<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(gmock_a6), \
|
||||
::std::forward<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(gmock_a7), \
|
||||
::std::forward<GMOCK_ARG_(tn, 8, __VA_ARGS__)>(gmock_a8), \
|
||||
::std::forward<GMOCK_ARG_(tn, 9, __VA_ARGS__)>(gmock_a9), \
|
||||
::std::forward<GMOCK_ARG_(tn, 10, __VA_ARGS__)>(gmock_a10)); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> \
|
||||
gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \
|
||||
GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \
|
||||
GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \
|
||||
GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \
|
||||
GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \
|
||||
GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \
|
||||
GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7, \
|
||||
GMOCK_MATCHER_(tn, 8, __VA_ARGS__) gmock_a8, \
|
||||
GMOCK_MATCHER_(tn, 9, __VA_ARGS__) gmock_a9, \
|
||||
GMOCK_MATCHER_(tn, 10, \
|
||||
__VA_ARGS__) gmock_a10) constness { \
|
||||
GMOCK_MOCKER_(10, constness, Method).RegisterOwner(this); \
|
||||
return GMOCK_MOCKER_(10, constness, Method).With(gmock_a1, gmock_a2, \
|
||||
gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9, \
|
||||
gmock_a10); \
|
||||
} \
|
||||
::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(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 8, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 9, __VA_ARGS__)>(), \
|
||||
::testing::A<GMOCK_ARG_(tn, 10, __VA_ARGS__)>()); \
|
||||
} \
|
||||
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(10, constness, \
|
||||
Method)
|
||||
|
||||
#define MOCK_METHOD0(m, ...) GMOCK_METHOD0_(, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD1(m, ...) GMOCK_METHOD1_(, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD2(m, ...) GMOCK_METHOD2_(, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD3(m, ...) GMOCK_METHOD3_(, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD4(m, ...) GMOCK_METHOD4_(, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD5(m, ...) GMOCK_METHOD5_(, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD6(m, ...) GMOCK_METHOD6_(, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD7(m, ...) GMOCK_METHOD7_(, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD8(m, ...) GMOCK_METHOD8_(, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD9(m, ...) GMOCK_METHOD9_(, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD10(m, ...) GMOCK_METHOD10_(, , , m, __VA_ARGS__)
|
||||
|
||||
#define MOCK_CONST_METHOD0(m, ...) GMOCK_METHOD0_(, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD1(m, ...) GMOCK_METHOD1_(, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD2(m, ...) GMOCK_METHOD2_(, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD3(m, ...) GMOCK_METHOD3_(, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD4(m, ...) GMOCK_METHOD4_(, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD5(m, ...) GMOCK_METHOD5_(, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD6(m, ...) GMOCK_METHOD6_(, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD7(m, ...) GMOCK_METHOD7_(, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD8(m, ...) GMOCK_METHOD8_(, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD9(m, ...) GMOCK_METHOD9_(, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD10(m, ...) GMOCK_METHOD10_(, const, , m, __VA_ARGS__)
|
||||
|
||||
#define MOCK_METHOD0_T(m, ...) GMOCK_METHOD0_(typename, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD1_T(m, ...) GMOCK_METHOD1_(typename, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD2_T(m, ...) GMOCK_METHOD2_(typename, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD3_T(m, ...) GMOCK_METHOD3_(typename, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD4_T(m, ...) GMOCK_METHOD4_(typename, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD5_T(m, ...) GMOCK_METHOD5_(typename, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD6_T(m, ...) GMOCK_METHOD6_(typename, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD7_T(m, ...) GMOCK_METHOD7_(typename, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD8_T(m, ...) GMOCK_METHOD8_(typename, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD9_T(m, ...) GMOCK_METHOD9_(typename, , , m, __VA_ARGS__)
|
||||
#define MOCK_METHOD10_T(m, ...) GMOCK_METHOD10_(typename, , , m, __VA_ARGS__)
|
||||
|
||||
#define MOCK_CONST_METHOD0_T(m, ...) \
|
||||
GMOCK_METHOD0_(typename, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD1_T(m, ...) \
|
||||
GMOCK_METHOD1_(typename, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD2_T(m, ...) \
|
||||
GMOCK_METHOD2_(typename, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD3_T(m, ...) \
|
||||
GMOCK_METHOD3_(typename, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD4_T(m, ...) \
|
||||
GMOCK_METHOD4_(typename, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD5_T(m, ...) \
|
||||
GMOCK_METHOD5_(typename, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD6_T(m, ...) \
|
||||
GMOCK_METHOD6_(typename, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD7_T(m, ...) \
|
||||
GMOCK_METHOD7_(typename, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD8_T(m, ...) \
|
||||
GMOCK_METHOD8_(typename, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD9_T(m, ...) \
|
||||
GMOCK_METHOD9_(typename, const, , m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD10_T(m, ...) \
|
||||
GMOCK_METHOD10_(typename, const, , m, __VA_ARGS__)
|
||||
|
||||
#define MOCK_METHOD0_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD0_(, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD1_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD1_(, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD2_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD2_(, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD3_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD3_(, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD4_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD4_(, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD5_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD5_(, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD6_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD6_(, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD7_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD7_(, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD8_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD8_(, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD9_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD9_(, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD10_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD10_(, , ct, m, __VA_ARGS__)
|
||||
|
||||
#define MOCK_CONST_METHOD0_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD0_(, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD1_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD1_(, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD2_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD2_(, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD3_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD3_(, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD4_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD4_(, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD5_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD5_(, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD6_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD6_(, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD7_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD7_(, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD8_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD8_(, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD9_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD9_(, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD10_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD10_(, const, ct, m, __VA_ARGS__)
|
||||
|
||||
#define MOCK_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD0_(typename, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD1_(typename, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD2_(typename, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD3_(typename, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD4_(typename, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD5_(typename, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD6_(typename, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD7_(typename, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD8_(typename, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD9_(typename, , ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD10_(typename, , ct, m, __VA_ARGS__)
|
||||
|
||||
#define MOCK_CONST_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD0_(typename, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD1_(typename, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD2_(typename, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD3_(typename, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD4_(typename, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD5_(typename, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD6_(typename, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD7_(typename, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD8_(typename, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD9_(typename, const, ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD10_(typename, const, ct, m, __VA_ARGS__)
|
||||
|
||||
} // namespace testing
|
||||
|
||||
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
@@ -1,227 +0,0 @@
|
||||
$$ -*- mode: c++; -*-
|
||||
$$ This is a Pump source file. Please use Pump to convert
|
||||
$$ it to gmock-generated-function-mockers.h.
|
||||
$$
|
||||
$var n = 10 $$ The maximum arity we support.
|
||||
// Copyright 2007, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
// Google Mock - a framework for writing C++ mock classes.
|
||||
//
|
||||
// This file implements function mockers of various arities.
|
||||
|
||||
// GOOGLETEST_CM0002 DO NOT DELETE
|
||||
|
||||
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
||||
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
#include "gmock/gmock-spec-builders.h"
|
||||
#include "gmock/internal/gmock-internal-utils.h"
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
$range i 0..n
|
||||
// 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
|
||||
|
||||
// The style guide prohibits "using" statements in a namespace scope
|
||||
// inside a header file. However, the FunctionMocker class template
|
||||
// is meant to be defined in the ::testing namespace. The following
|
||||
// line is just a trick for working around a bug in MSVC 8.0, which
|
||||
// cannot handle it if we define FunctionMocker in ::testing.
|
||||
using internal::FunctionMocker;
|
||||
|
||||
// GMOCK_RESULT_(tn, F) expands to the result type of function type F.
|
||||
// We define this as a variadic macro in case F contains unprotected
|
||||
// commas (the same reason that we use variadic macros in other places
|
||||
// in this file).
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_RESULT_(tn, ...) \
|
||||
tn ::testing::internal::Function<__VA_ARGS__>::Result
|
||||
|
||||
// The type of argument N of the given function type.
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_ARG_(tn, N, ...) \
|
||||
tn ::testing::internal::Function<__VA_ARGS__>::template Arg<N-1>::type
|
||||
|
||||
// The matcher type for argument N of the given function type.
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_MATCHER_(tn, N, ...) \
|
||||
const ::testing::Matcher<GMOCK_ARG_(tn, N, __VA_ARGS__)>&
|
||||
|
||||
// The variable for mocking the given method.
|
||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||
#define GMOCK_MOCKER_(arity, constness, Method) \
|
||||
GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__)
|
||||
|
||||
|
||||
$for i [[
|
||||
$range j 1..i
|
||||
$var arg_as = [[$for j, [[GMOCK_ARG_(tn, $j, __VA_ARGS__) gmock_a$j]]]]
|
||||
$var as = [[$for j, \
|
||||
[[::std::forward<GMOCK_ARG_(tn, $j, __VA_ARGS__)>(gmock_a$j)]]]]
|
||||
$var matcher_arg_as = [[$for 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!!!
|
||||
#define GMOCK_METHOD$i[[]]_(tn, constness, ct, Method, ...) \
|
||||
static_assert($i == ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, "MOCK_METHOD<N> must match argument count.");\
|
||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||
$arg_as) constness { \
|
||||
GMOCK_MOCKER_($i, constness, Method).SetOwnerAndName(this, #Method); \
|
||||
return GMOCK_MOCKER_($i, constness, Method).Invoke($as); \
|
||||
} \
|
||||
::testing::MockSpec<__VA_ARGS__> \
|
||||
gmock_##Method($matcher_arg_as) constness { \
|
||||
GMOCK_MOCKER_($i, constness, Method).RegisterOwner(this); \
|
||||
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)
|
||||
|
||||
|
||||
]]
|
||||
$for i [[
|
||||
#define MOCK_METHOD$i(m, ...) GMOCK_METHOD$i[[]]_(, , , m, __VA_ARGS__)
|
||||
|
||||
]]
|
||||
|
||||
|
||||
$for i [[
|
||||
#define MOCK_CONST_METHOD$i(m, ...) GMOCK_METHOD$i[[]]_(, const, , m, __VA_ARGS__)
|
||||
|
||||
]]
|
||||
|
||||
|
||||
$for i [[
|
||||
#define MOCK_METHOD$i[[]]_T(m, ...) GMOCK_METHOD$i[[]]_(typename, , , m, __VA_ARGS__)
|
||||
|
||||
]]
|
||||
|
||||
|
||||
$for i [[
|
||||
#define MOCK_CONST_METHOD$i[[]]_T(m, ...) \
|
||||
GMOCK_METHOD$i[[]]_(typename, const, , m, __VA_ARGS__)
|
||||
|
||||
]]
|
||||
|
||||
|
||||
$for i [[
|
||||
#define MOCK_METHOD$i[[]]_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD$i[[]]_(, , ct, m, __VA_ARGS__)
|
||||
|
||||
]]
|
||||
|
||||
|
||||
$for i [[
|
||||
#define MOCK_CONST_METHOD$i[[]]_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD$i[[]]_(, const, ct, m, __VA_ARGS__)
|
||||
|
||||
]]
|
||||
|
||||
|
||||
$for i [[
|
||||
#define MOCK_METHOD$i[[]]_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD$i[[]]_(typename, , ct, m, __VA_ARGS__)
|
||||
|
||||
]]
|
||||
|
||||
|
||||
$for i [[
|
||||
#define MOCK_CONST_METHOD$i[[]]_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_METHOD$i[[]]_(typename, const, ct, m, __VA_ARGS__)
|
||||
|
||||
]]
|
||||
|
||||
} // namespace testing
|
||||
|
||||
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
File diff suppressed because it is too large
Load Diff
@@ -1,346 +0,0 @@
|
||||
$$ -*- mode: c++; -*-
|
||||
$$ This is a Pump source file. Please use Pump to convert
|
||||
$$ it to gmock-generated-matchers.h.
|
||||
$$
|
||||
$var n = 10 $$ The maximum arity we support.
|
||||
$$ }} This line fixes auto-indentation of the following code in Emacs.
|
||||
// Copyright 2008, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Google Mock - a framework for writing C++ mock classes.
|
||||
//
|
||||
// This file implements some commonly used variadic matchers.
|
||||
|
||||
// GOOGLETEST_CM0002 DO NOT DELETE
|
||||
|
||||
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
|
||||
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
|
||||
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include "gmock/gmock-matchers.h"
|
||||
|
||||
// The MATCHER* family of macros can be used in a namespace scope to
|
||||
// define custom matchers easily.
|
||||
//
|
||||
// Basic Usage
|
||||
// ===========
|
||||
//
|
||||
// The syntax
|
||||
//
|
||||
// MATCHER(name, description_string) { statements; }
|
||||
//
|
||||
// defines a matcher with the given name that executes the statements,
|
||||
// which must return a bool to indicate if the match succeeds. Inside
|
||||
// the statements, you can refer to the value being matched by 'arg',
|
||||
// and refer to its type by 'arg_type'.
|
||||
//
|
||||
// The description string documents what the matcher does, and is used
|
||||
// to generate the failure message when the match fails. Since a
|
||||
// MATCHER() is usually defined in a header file shared by multiple
|
||||
// C++ source files, we require the description to be a C-string
|
||||
// literal to avoid possible side effects. It can be empty, in which
|
||||
// case we'll use the sequence of words in the matcher name as the
|
||||
// description.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// MATCHER(IsEven, "") { return (arg % 2) == 0; }
|
||||
//
|
||||
// allows you to write
|
||||
//
|
||||
// // Expects mock_foo.Bar(n) to be called where n is even.
|
||||
// EXPECT_CALL(mock_foo, Bar(IsEven()));
|
||||
//
|
||||
// or,
|
||||
//
|
||||
// // Verifies that the value of some_expression is even.
|
||||
// EXPECT_THAT(some_expression, IsEven());
|
||||
//
|
||||
// If the above assertion fails, it will print something like:
|
||||
//
|
||||
// Value of: some_expression
|
||||
// Expected: is even
|
||||
// Actual: 7
|
||||
//
|
||||
// where the description "is even" is automatically calculated from the
|
||||
// matcher name IsEven.
|
||||
//
|
||||
// Argument Type
|
||||
// =============
|
||||
//
|
||||
// Note that the type of the value being matched (arg_type) is
|
||||
// determined by the context in which you use the matcher and is
|
||||
// supplied to you by the compiler, so you don't need to worry about
|
||||
// declaring it (nor can you). This allows the matcher to be
|
||||
// polymorphic. For example, IsEven() can be used to match any type
|
||||
// where the value of "(arg % 2) == 0" can be implicitly converted to
|
||||
// a bool. In the "Bar(IsEven())" example above, if method Bar()
|
||||
// takes an int, 'arg_type' will be int; if it takes an unsigned long,
|
||||
// 'arg_type' will be unsigned long; and so on.
|
||||
//
|
||||
// Parameterizing Matchers
|
||||
// =======================
|
||||
//
|
||||
// Sometimes you'll want to parameterize the matcher. For that you
|
||||
// can use another macro:
|
||||
//
|
||||
// MATCHER_P(name, param_name, description_string) { statements; }
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; }
|
||||
//
|
||||
// will allow you to write:
|
||||
//
|
||||
// EXPECT_THAT(Blah("a"), HasAbsoluteValue(n));
|
||||
//
|
||||
// which may lead to this message (assuming n is 10):
|
||||
//
|
||||
// Value of: Blah("a")
|
||||
// Expected: has absolute value 10
|
||||
// Actual: -9
|
||||
//
|
||||
// Note that both the matcher description and its parameter are
|
||||
// printed, making the message human-friendly.
|
||||
//
|
||||
// In the matcher definition body, you can write 'foo_type' to
|
||||
// reference the type of a parameter named 'foo'. For example, in the
|
||||
// body of MATCHER_P(HasAbsoluteValue, value) above, you can write
|
||||
// 'value_type' to refer to the type of 'value'.
|
||||
//
|
||||
// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P$n to
|
||||
// support multi-parameter matchers.
|
||||
//
|
||||
// Describing Parameterized Matchers
|
||||
// =================================
|
||||
//
|
||||
// The last argument to MATCHER*() is a string-typed expression. The
|
||||
// expression can reference all of the matcher's parameters and a
|
||||
// special bool-typed variable named 'negation'. When 'negation' is
|
||||
// false, the expression should evaluate to the matcher's description;
|
||||
// otherwise it should evaluate to the description of the negation of
|
||||
// the matcher. For example,
|
||||
//
|
||||
// using testing::PrintToString;
|
||||
//
|
||||
// MATCHER_P2(InClosedRange, low, hi,
|
||||
// std::string(negation ? "is not" : "is") + " in range [" +
|
||||
// PrintToString(low) + ", " + PrintToString(hi) + "]") {
|
||||
// return low <= arg && arg <= hi;
|
||||
// }
|
||||
// ...
|
||||
// EXPECT_THAT(3, InClosedRange(4, 6));
|
||||
// EXPECT_THAT(3, Not(InClosedRange(2, 4)));
|
||||
//
|
||||
// would generate two failures that contain the text:
|
||||
//
|
||||
// Expected: is in range [4, 6]
|
||||
// ...
|
||||
// Expected: is not in range [2, 4]
|
||||
//
|
||||
// If you specify "" as the description, the failure message will
|
||||
// contain the sequence of words in the matcher name followed by the
|
||||
// parameter values printed as a tuple. For example,
|
||||
//
|
||||
// MATCHER_P2(InClosedRange, low, hi, "") { ... }
|
||||
// ...
|
||||
// EXPECT_THAT(3, InClosedRange(4, 6));
|
||||
// EXPECT_THAT(3, Not(InClosedRange(2, 4)));
|
||||
//
|
||||
// would generate two failures that contain the text:
|
||||
//
|
||||
// Expected: in closed range (4, 6)
|
||||
// ...
|
||||
// Expected: not (in closed range (2, 4))
|
||||
//
|
||||
// Types of Matcher Parameters
|
||||
// ===========================
|
||||
//
|
||||
// For the purpose of typing, you can view
|
||||
//
|
||||
// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... }
|
||||
//
|
||||
// as shorthand for
|
||||
//
|
||||
// template <typename p1_type, ..., typename pk_type>
|
||||
// FooMatcherPk<p1_type, ..., pk_type>
|
||||
// Foo(p1_type p1, ..., pk_type pk) { ... }
|
||||
//
|
||||
// When you write Foo(v1, ..., vk), the compiler infers the types of
|
||||
// the parameters v1, ..., and vk for you. If you are not happy with
|
||||
// the result of the type inference, you can specify the types by
|
||||
// explicitly instantiating the template, as in Foo<long, bool>(5,
|
||||
// false). As said earlier, you don't get to (or need to) specify
|
||||
// 'arg_type' as that's determined by the context in which the matcher
|
||||
// is used. You can assign the result of expression Foo(p1, ..., pk)
|
||||
// to a variable of type FooMatcherPk<p1_type, ..., pk_type>. This
|
||||
// can be useful when composing matchers.
|
||||
//
|
||||
// While you can instantiate a matcher template with reference types,
|
||||
// passing the parameters by pointer usually makes your code more
|
||||
// readable. If, however, you still want to pass a parameter by
|
||||
// reference, be aware that in the failure message generated by the
|
||||
// matcher you will see the value of the referenced object but not its
|
||||
// address.
|
||||
//
|
||||
// Explaining Match Results
|
||||
// ========================
|
||||
//
|
||||
// Sometimes the matcher description alone isn't enough to explain why
|
||||
// the match has failed or succeeded. For example, when expecting a
|
||||
// long string, it can be very helpful to also print the diff between
|
||||
// the expected string and the actual one. To achieve that, you can
|
||||
// optionally stream additional information to a special variable
|
||||
// named result_listener, whose type is a pointer to class
|
||||
// MatchResultListener:
|
||||
//
|
||||
// MATCHER_P(EqualsLongString, str, "") {
|
||||
// if (arg == str) return true;
|
||||
//
|
||||
// *result_listener << "the difference: "
|
||||
/// << DiffStrings(str, arg);
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// Overloading Matchers
|
||||
// ====================
|
||||
//
|
||||
// You can overload matchers with different numbers of parameters:
|
||||
//
|
||||
// MATCHER_P(Blah, a, description_string1) { ... }
|
||||
// MATCHER_P2(Blah, a, b, description_string2) { ... }
|
||||
//
|
||||
// Caveats
|
||||
// =======
|
||||
//
|
||||
// When defining a new matcher, you should also consider implementing
|
||||
// MatcherInterface or using MakePolymorphicMatcher(). These
|
||||
// approaches require more work than the MATCHER* macros, but also
|
||||
// give you more control on the types of the value being matched and
|
||||
// the matcher parameters, which may leads to better compiler error
|
||||
// messages when the matcher is used wrong. They also allow
|
||||
// overloading matchers based on parameter types (as opposed to just
|
||||
// based on the number of parameters).
|
||||
//
|
||||
// MATCHER*() can only be used in a namespace scope as templates cannot be
|
||||
// declared inside of a local class.
|
||||
//
|
||||
// More Information
|
||||
// ================
|
||||
//
|
||||
// To learn more about using these macros, please search for 'MATCHER'
|
||||
// on
|
||||
// https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md
|
||||
|
||||
$range i 0..n
|
||||
$for i
|
||||
|
||||
[[
|
||||
$var macro_name = [[$if i==0 [[MATCHER]] $elif i==1 [[MATCHER_P]]
|
||||
$else [[MATCHER_P$i]]]]
|
||||
$var class_name = [[name##Matcher[[$if i==0 [[]] $elif i==1 [[P]]
|
||||
$else [[P$i]]]]]]
|
||||
$range j 0..i-1
|
||||
$var template = [[$if i==0 [[]] $else [[
|
||||
|
||||
template <$for j, [[typename p$j##_type]]>\
|
||||
]]]]
|
||||
$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_inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(::std::move(gmock_p$j))]]]]]]
|
||||
$var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(::std::move(gmock_p$j))]]]]]]
|
||||
$var params = [[$for j, [[p$j]]]]
|
||||
$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_field_decls = [[$for j
|
||||
[[
|
||||
|
||||
p$j##_type const p$j;\
|
||||
]]]]
|
||||
$var param_field_decls2 = [[$for j
|
||||
[[
|
||||
|
||||
p$j##_type const p$j;\
|
||||
]]]]
|
||||
|
||||
#define $macro_name(name$for j [[, p$j]], description)\$template
|
||||
class $class_name {\
|
||||
public:\
|
||||
template <typename arg_type>\
|
||||
class gmock_Impl : public ::testing::MatcherInterface<\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type)> {\
|
||||
public:\
|
||||
[[$if i==1 [[explicit ]]]]gmock_Impl($impl_ctor_param_list)\
|
||||
$impl_inits {}\
|
||||
virtual bool MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener) const;\
|
||||
virtual void DescribeTo(::std::ostream* gmock_os) const {\
|
||||
*gmock_os << FormatDescription(false);\
|
||||
}\
|
||||
virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
|
||||
*gmock_os << FormatDescription(true);\
|
||||
}\$param_field_decls
|
||||
private:\
|
||||
::std::string FormatDescription(bool negation) const {\
|
||||
::std::string gmock_description = (description);\
|
||||
if (!gmock_description.empty()) {\
|
||||
return gmock_description;\
|
||||
}\
|
||||
return ::testing::internal::FormatMatcherDescription(\
|
||||
negation, #name, \
|
||||
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
|
||||
::std::tuple<$for j, [[p$j##_type]]>($for j, [[p$j]])));\
|
||||
}\
|
||||
};\
|
||||
template <typename arg_type>\
|
||||
operator ::testing::Matcher<arg_type>() const {\
|
||||
return ::testing::Matcher<arg_type>(\
|
||||
new gmock_Impl<arg_type>($params));\
|
||||
}\
|
||||
[[$if i==1 [[explicit ]]]]$class_name($ctor_param_list)$inits {\
|
||||
}\$param_field_decls2
|
||||
private:\
|
||||
};\$template
|
||||
inline $class_name$param_types name($param_types_and_names) {\
|
||||
return $class_name$param_types($params);\
|
||||
}\$template
|
||||
template <typename arg_type>\
|
||||
bool $class_name$param_types::gmock_Impl<arg_type>::MatchAndExplain(\
|
||||
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
|
||||
const
|
||||
]]
|
||||
|
||||
|
||||
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
|
@@ -1,162 +0,0 @@
|
||||
// Copyright 2007, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
// Google Mock - a framework for writing C++ mock classes.
|
||||
//
|
||||
// This file implements some actions that depend on gmock-generated-actions.h.
|
||||
|
||||
// GOOGLETEST_CM0002 DO NOT DELETE
|
||||
|
||||
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
|
||||
#define GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
|
||||
#include "gmock/gmock-generated-actions.h"
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
// An internal replacement for std::copy which mimics its behavior. This is
|
||||
// necessary because Visual Studio deprecates ::std::copy, issuing warning 4996.
|
||||
// However Visual Studio 2010 and later do not honor #pragmas which disable that
|
||||
// warning.
|
||||
template<typename InputIterator, typename OutputIterator>
|
||||
inline OutputIterator CopyElements(InputIterator first,
|
||||
InputIterator last,
|
||||
OutputIterator output) {
|
||||
for (; first != last; ++first, ++output) {
|
||||
*output = *first;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Various overloads for Invoke().
|
||||
|
||||
// The ACTION*() macros trigger warning C4100 (unreferenced formal
|
||||
// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in
|
||||
// the macro definition, as the warnings are generated when the macro
|
||||
// is expanded and macro expansion cannot contain #pragma. Therefore
|
||||
// we suppress them here.
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4100)
|
||||
#endif
|
||||
|
||||
// Action ReturnArg<k>() returns the k-th argument of the mock function.
|
||||
ACTION_TEMPLATE(ReturnArg,
|
||||
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||
AND_0_VALUE_PARAMS()) {
|
||||
return ::std::get<k>(args);
|
||||
}
|
||||
|
||||
// Action SaveArg<k>(pointer) saves the k-th (0-based) argument of the
|
||||
// mock function to *pointer.
|
||||
ACTION_TEMPLATE(SaveArg,
|
||||
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||
AND_1_VALUE_PARAMS(pointer)) {
|
||||
*pointer = ::std::get<k>(args);
|
||||
}
|
||||
|
||||
// Action SaveArgPointee<k>(pointer) saves the value pointed to
|
||||
// by the k-th (0-based) argument of the mock function to *pointer.
|
||||
ACTION_TEMPLATE(SaveArgPointee,
|
||||
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||
AND_1_VALUE_PARAMS(pointer)) {
|
||||
*pointer = *::std::get<k>(args);
|
||||
}
|
||||
|
||||
// Action SetArgReferee<k>(value) assigns 'value' to the variable
|
||||
// referenced by the k-th (0-based) argument of the mock function.
|
||||
ACTION_TEMPLATE(SetArgReferee,
|
||||
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||
AND_1_VALUE_PARAMS(value)) {
|
||||
typedef typename ::std::tuple_element<k, args_type>::type argk_type;
|
||||
// Ensures that argument #k is a reference. If you get a compiler
|
||||
// error on the next line, you are using SetArgReferee<k>(value) in
|
||||
// a mock function whose k-th (0-based) argument is not a reference.
|
||||
GTEST_COMPILE_ASSERT_(std::is_reference<argk_type>::value,
|
||||
SetArgReferee_must_be_used_with_a_reference_argument);
|
||||
::std::get<k>(args) = value;
|
||||
}
|
||||
|
||||
// Action SetArrayArgument<k>(first, last) copies the elements in
|
||||
// source range [first, last) to the array pointed to by the k-th
|
||||
// (0-based) argument, which can be either a pointer or an
|
||||
// iterator. The action does not take ownership of the elements in the
|
||||
// source range.
|
||||
ACTION_TEMPLATE(SetArrayArgument,
|
||||
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||
AND_2_VALUE_PARAMS(first, last)) {
|
||||
// Visual Studio deprecates ::std::copy, so we use our own copy in that case.
|
||||
#ifdef _MSC_VER
|
||||
internal::CopyElements(first, last, ::std::get<k>(args));
|
||||
#else
|
||||
::std::copy(first, last, ::std::get<k>(args));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Action DeleteArg<k>() deletes the k-th (0-based) argument of the mock
|
||||
// function.
|
||||
ACTION_TEMPLATE(DeleteArg,
|
||||
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||
AND_0_VALUE_PARAMS()) {
|
||||
delete ::std::get<k>(args);
|
||||
}
|
||||
|
||||
// This action returns the value pointed to by 'pointer'.
|
||||
ACTION_P(ReturnPointee, pointer) { return *pointer; }
|
||||
|
||||
// Action Throw(exception) can be used in a mock function of any type
|
||||
// to throw the given exception. Any copyable value can be thrown.
|
||||
#if GTEST_HAS_EXCEPTIONS
|
||||
|
||||
// Suppresses the 'unreachable code' warning that VC generates in opt modes.
|
||||
# ifdef _MSC_VER
|
||||
# pragma warning(push) // Saves the current warning state.
|
||||
# pragma warning(disable:4702) // Temporarily disables warning 4702.
|
||||
# endif
|
||||
ACTION_P(Throw, exception) { throw exception; }
|
||||
# ifdef _MSC_VER
|
||||
# pragma warning(pop) // Restores the warning state.
|
||||
# endif
|
||||
|
||||
#endif // GTEST_HAS_EXCEPTIONS
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace testing
|
||||
|
||||
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
|
@@ -1,10 +0,0 @@
|
||||
// This file was GENERATED by command:
|
||||
// pump.py gmock-generated-actions.h.pump
|
||||
// DO NOT EDIT BY HAND!!!
|
||||
|
||||
// GOOGLETEST_CM0002 DO NOT DELETE
|
||||
|
||||
#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
|
||||
#define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
|
||||
|
||||
#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
|
@@ -1,12 +0,0 @@
|
||||
$$ -*- mode: c++; -*-
|
||||
$$ This is a Pump source file. Please use Pump to convert
|
||||
$$ it to callback-actions.h.
|
||||
$$
|
||||
$var max_callback_arity = 5
|
||||
$$}} This meta comment fixes auto-indentation in editors.
|
||||
|
||||
// GOOGLETEST_CM0002 DO NOT DELETE
|
||||
#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
|
||||
#define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
|
||||
|
||||
#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
|
File diff suppressed because it is too large
Load Diff
@@ -1,303 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# These variables are automatically filled in by the configure script.
|
||||
name="@PACKAGE_TARNAME@"
|
||||
version="@PACKAGE_VERSION@"
|
||||
|
||||
show_usage()
|
||||
{
|
||||
echo "Usage: gmock-config [OPTIONS...]"
|
||||
}
|
||||
|
||||
show_help()
|
||||
{
|
||||
show_usage
|
||||
cat <<\EOF
|
||||
|
||||
The `gmock-config' script provides access to the necessary compile and linking
|
||||
flags to connect with Google C++ Mocking Framework, both in a build prior to
|
||||
installation, and on the system proper after installation. The installation
|
||||
overrides may be issued in combination with any other queries, but will only
|
||||
affect installation queries if called on a built but not installed gmock. The
|
||||
installation queries may not be issued with any other types of queries, and
|
||||
only one installation query may be made at a time. The version queries and
|
||||
compiler flag queries may be combined as desired but not mixed. Different
|
||||
version queries are always combined with logical "and" semantics, and only the
|
||||
last of any particular query is used while all previous ones ignored. All
|
||||
versions must be specified as a sequence of numbers separated by periods.
|
||||
Compiler flag queries output the union of the sets of flags when combined.
|
||||
|
||||
Examples:
|
||||
gmock-config --min-version=1.0 || echo "Insufficient Google Mock version."
|
||||
|
||||
g++ $(gmock-config --cppflags --cxxflags) -o foo.o -c foo.cpp
|
||||
g++ $(gmock-config --ldflags --libs) -o foo foo.o
|
||||
|
||||
# When using a built but not installed Google Mock:
|
||||
g++ $(../../my_gmock_build/scripts/gmock-config ...) ...
|
||||
|
||||
# When using an installed Google Mock, but with installation overrides:
|
||||
export GMOCK_PREFIX="/opt"
|
||||
g++ $(gmock-config --libdir="/opt/lib64" ...) ...
|
||||
|
||||
Help:
|
||||
--usage brief usage information
|
||||
--help display this help message
|
||||
|
||||
Installation Overrides:
|
||||
--prefix=<dir> overrides the installation prefix
|
||||
--exec-prefix=<dir> overrides the executable installation prefix
|
||||
--libdir=<dir> overrides the library installation prefix
|
||||
--includedir=<dir> overrides the header file installation prefix
|
||||
|
||||
Installation Queries:
|
||||
--prefix installation prefix
|
||||
--exec-prefix executable installation prefix
|
||||
--libdir library installation directory
|
||||
--includedir header file installation directory
|
||||
--version the version of the Google Mock installation
|
||||
|
||||
Version Queries:
|
||||
--min-version=VERSION return 0 if the version is at least VERSION
|
||||
--exact-version=VERSION return 0 if the version is exactly VERSION
|
||||
--max-version=VERSION return 0 if the version is at most VERSION
|
||||
|
||||
Compilation Flag Queries:
|
||||
--cppflags compile flags specific to the C-like preprocessors
|
||||
--cxxflags compile flags appropriate for C++ programs
|
||||
--ldflags linker flags
|
||||
--libs libraries for linking
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# This function bounds our version with a min and a max. It uses some clever
|
||||
# POSIX-compliant variable expansion to portably do all the work in the shell
|
||||
# and avoid any dependency on a particular "sed" or "awk" implementation.
|
||||
# Notable is that it will only ever compare the first 3 components of versions.
|
||||
# Further components will be cleanly stripped off. All versions must be
|
||||
# unadorned, so "v1.0" will *not* work. The minimum version must be in $1, and
|
||||
# the max in $2. TODO(chandlerc@google.com): If this ever breaks, we should
|
||||
# investigate expanding this via autom4te from AS_VERSION_COMPARE rather than
|
||||
# continuing to maintain our own shell version.
|
||||
check_versions()
|
||||
{
|
||||
major_version=${version%%.*}
|
||||
minor_version="0"
|
||||
point_version="0"
|
||||
if test "${version#*.}" != "${version}"; then
|
||||
minor_version=${version#*.}
|
||||
minor_version=${minor_version%%.*}
|
||||
fi
|
||||
if test "${version#*.*.}" != "${version}"; then
|
||||
point_version=${version#*.*.}
|
||||
point_version=${point_version%%.*}
|
||||
fi
|
||||
|
||||
min_version="$1"
|
||||
min_major_version=${min_version%%.*}
|
||||
min_minor_version="0"
|
||||
min_point_version="0"
|
||||
if test "${min_version#*.}" != "${min_version}"; then
|
||||
min_minor_version=${min_version#*.}
|
||||
min_minor_version=${min_minor_version%%.*}
|
||||
fi
|
||||
if test "${min_version#*.*.}" != "${min_version}"; then
|
||||
min_point_version=${min_version#*.*.}
|
||||
min_point_version=${min_point_version%%.*}
|
||||
fi
|
||||
|
||||
max_version="$2"
|
||||
max_major_version=${max_version%%.*}
|
||||
max_minor_version="0"
|
||||
max_point_version="0"
|
||||
if test "${max_version#*.}" != "${max_version}"; then
|
||||
max_minor_version=${max_version#*.}
|
||||
max_minor_version=${max_minor_version%%.*}
|
||||
fi
|
||||
if test "${max_version#*.*.}" != "${max_version}"; then
|
||||
max_point_version=${max_version#*.*.}
|
||||
max_point_version=${max_point_version%%.*}
|
||||
fi
|
||||
|
||||
test $(($major_version)) -lt $(($min_major_version)) && exit 1
|
||||
if test $(($major_version)) -eq $(($min_major_version)); then
|
||||
test $(($minor_version)) -lt $(($min_minor_version)) && exit 1
|
||||
if test $(($minor_version)) -eq $(($min_minor_version)); then
|
||||
test $(($point_version)) -lt $(($min_point_version)) && exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
test $(($major_version)) -gt $(($max_major_version)) && exit 1
|
||||
if test $(($major_version)) -eq $(($max_major_version)); then
|
||||
test $(($minor_version)) -gt $(($max_minor_version)) && exit 1
|
||||
if test $(($minor_version)) -eq $(($max_minor_version)); then
|
||||
test $(($point_version)) -gt $(($max_point_version)) && exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Show the usage line when no arguments are specified.
|
||||
if test $# -eq 0; then
|
||||
show_usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while test $# -gt 0; do
|
||||
case $1 in
|
||||
--usage) show_usage; exit 0;;
|
||||
--help) show_help; exit 0;;
|
||||
|
||||
# Installation overrides
|
||||
--prefix=*) GMOCK_PREFIX=${1#--prefix=};;
|
||||
--exec-prefix=*) GMOCK_EXEC_PREFIX=${1#--exec-prefix=};;
|
||||
--libdir=*) GMOCK_LIBDIR=${1#--libdir=};;
|
||||
--includedir=*) GMOCK_INCLUDEDIR=${1#--includedir=};;
|
||||
|
||||
# Installation queries
|
||||
--prefix|--exec-prefix|--libdir|--includedir|--version)
|
||||
if test -n "${do_query}"; then
|
||||
show_usage
|
||||
exit 1
|
||||
fi
|
||||
do_query=${1#--}
|
||||
;;
|
||||
|
||||
# Version checking
|
||||
--min-version=*)
|
||||
do_check_versions=yes
|
||||
min_version=${1#--min-version=}
|
||||
;;
|
||||
--max-version=*)
|
||||
do_check_versions=yes
|
||||
max_version=${1#--max-version=}
|
||||
;;
|
||||
--exact-version=*)
|
||||
do_check_versions=yes
|
||||
exact_version=${1#--exact-version=}
|
||||
;;
|
||||
|
||||
# Compiler flag output
|
||||
--cppflags) echo_cppflags=yes;;
|
||||
--cxxflags) echo_cxxflags=yes;;
|
||||
--ldflags) echo_ldflags=yes;;
|
||||
--libs) echo_libs=yes;;
|
||||
|
||||
# Everything else is an error
|
||||
*) show_usage; exit 1;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# These have defaults filled in by the configure script but can also be
|
||||
# overridden by environment variables or command line parameters.
|
||||
prefix="${GMOCK_PREFIX:-@prefix@}"
|
||||
exec_prefix="${GMOCK_EXEC_PREFIX:-@exec_prefix@}"
|
||||
libdir="${GMOCK_LIBDIR:-@libdir@}"
|
||||
includedir="${GMOCK_INCLUDEDIR:-@includedir@}"
|
||||
|
||||
# We try and detect if our binary is not located at its installed location. If
|
||||
# it's not, we provide variables pointing to the source and build tree rather
|
||||
# than to the install tree. We also locate Google Test using the configured
|
||||
# gtest-config script rather than searching the PATH and our bindir for one.
|
||||
# This allows building against a just-built gmock rather than an installed
|
||||
# gmock.
|
||||
bindir="@bindir@"
|
||||
this_relative_bindir=`dirname $0`
|
||||
this_bindir=`cd ${this_relative_bindir}; pwd -P`
|
||||
if test "${this_bindir}" = "${this_bindir%${bindir}}"; then
|
||||
# The path to the script doesn't end in the bindir sequence from Autoconf,
|
||||
# assume that we are in a build tree.
|
||||
build_dir=`dirname ${this_bindir}`
|
||||
src_dir=`cd ${this_bindir}/@top_srcdir@; pwd -P`
|
||||
|
||||
# TODO(chandlerc@google.com): This is a dangerous dependency on libtool, we
|
||||
# should work to remove it, and/or remove libtool altogether, replacing it
|
||||
# with direct references to the library and a link path.
|
||||
gmock_libs="${build_dir}/lib/libgmock.la"
|
||||
gmock_ldflags=""
|
||||
|
||||
# We provide hooks to include from either the source or build dir, where the
|
||||
# build dir is always preferred. This will potentially allow us to write
|
||||
# build rules for generated headers and have them automatically be preferred
|
||||
# over provided versions.
|
||||
gmock_cppflags="-I${build_dir}/include -I${src_dir}/include"
|
||||
gmock_cxxflags=""
|
||||
|
||||
# Directly invoke the gtest-config script used during the build process.
|
||||
gtest_config="@GTEST_CONFIG@"
|
||||
else
|
||||
# We're using an installed gmock, although it may be staged under some
|
||||
# prefix. Assume (as our own libraries do) that we can resolve the prefix,
|
||||
# and are present in the dynamic link paths.
|
||||
gmock_ldflags="-L${libdir}"
|
||||
gmock_libs="-l${name}"
|
||||
gmock_cppflags="-I${includedir}"
|
||||
gmock_cxxflags=""
|
||||
|
||||
# We also prefer any gtest-config script installed in our prefix. Lacking
|
||||
# one, we look in the PATH for one.
|
||||
gtest_config="${bindir}/gtest-config"
|
||||
if test ! -x "${gtest_config}"; then
|
||||
gtest_config=`which gtest-config`
|
||||
fi
|
||||
fi
|
||||
|
||||
# Ensure that we have located a Google Test to link against.
|
||||
if ! test -x "${gtest_config}"; then
|
||||
echo "Unable to locate Google Test, check your Google Mock configuration" \
|
||||
"and installation" >&2
|
||||
exit 1
|
||||
elif ! "${gtest_config}" "--exact-version=@GTEST_VERSION@"; then
|
||||
echo "The Google Test found is not the same version as Google Mock was " \
|
||||
"built against" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Add the necessary Google Test bits into the various flag variables
|
||||
gmock_cppflags="${gmock_cppflags} `${gtest_config} --cppflags`"
|
||||
gmock_cxxflags="${gmock_cxxflags} `${gtest_config} --cxxflags`"
|
||||
gmock_ldflags="${gmock_ldflags} `${gtest_config} --ldflags`"
|
||||
gmock_libs="${gmock_libs} `${gtest_config} --libs`"
|
||||
|
||||
# Do an installation query if requested.
|
||||
if test -n "$do_query"; then
|
||||
case $do_query in
|
||||
prefix) echo $prefix; exit 0;;
|
||||
exec-prefix) echo $exec_prefix; exit 0;;
|
||||
libdir) echo $libdir; exit 0;;
|
||||
includedir) echo $includedir; exit 0;;
|
||||
version) echo $version; exit 0;;
|
||||
*) show_usage; exit 1;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Do a version check if requested.
|
||||
if test "$do_check_versions" = "yes"; then
|
||||
# Make sure we didn't receive a bad combination of parameters.
|
||||
test "$echo_cppflags" = "yes" && show_usage && exit 1
|
||||
test "$echo_cxxflags" = "yes" && show_usage && exit 1
|
||||
test "$echo_ldflags" = "yes" && show_usage && exit 1
|
||||
test "$echo_libs" = "yes" && show_usage && exit 1
|
||||
|
||||
if test "$exact_version" != ""; then
|
||||
check_versions $exact_version $exact_version
|
||||
# unreachable
|
||||
else
|
||||
check_versions ${min_version:-0.0.0} ${max_version:-9999.9999.9999}
|
||||
# unreachable
|
||||
fi
|
||||
fi
|
||||
|
||||
# Do the output in the correct order so that these can be used in-line of
|
||||
# a compiler invocation.
|
||||
output=""
|
||||
test "$echo_cppflags" = "yes" && output="$output $gmock_cppflags"
|
||||
test "$echo_cxxflags" = "yes" && output="$output $gmock_cxxflags"
|
||||
test "$echo_ldflags" = "yes" && output="$output $gmock_ldflags"
|
||||
test "$echo_libs" = "yes" && output="$output $gmock_libs"
|
||||
echo $output
|
||||
|
||||
exit 0
|
@@ -1,640 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2008, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
"""Converts compiler's errors in code using Google Mock to plain English."""
|
||||
|
||||
__author__ = 'wan@google.com (Zhanyong Wan)'
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
_VERSION = '1.0.3'
|
||||
|
||||
_EMAIL = 'googlemock@googlegroups.com'
|
||||
|
||||
_COMMON_GMOCK_SYMBOLS = [
|
||||
# Matchers
|
||||
'_',
|
||||
'A',
|
||||
'AddressSatisfies',
|
||||
'AllOf',
|
||||
'An',
|
||||
'AnyOf',
|
||||
'ContainerEq',
|
||||
'Contains',
|
||||
'ContainsRegex',
|
||||
'DoubleEq',
|
||||
'ElementsAre',
|
||||
'ElementsAreArray',
|
||||
'EndsWith',
|
||||
'Eq',
|
||||
'Field',
|
||||
'FloatEq',
|
||||
'Ge',
|
||||
'Gt',
|
||||
'HasSubstr',
|
||||
'IsInitializedProto',
|
||||
'Le',
|
||||
'Lt',
|
||||
'MatcherCast',
|
||||
'Matches',
|
||||
'MatchesRegex',
|
||||
'NanSensitiveDoubleEq',
|
||||
'NanSensitiveFloatEq',
|
||||
'Ne',
|
||||
'Not',
|
||||
'NotNull',
|
||||
'Pointee',
|
||||
'Property',
|
||||
'Ref',
|
||||
'ResultOf',
|
||||
'SafeMatcherCast',
|
||||
'StartsWith',
|
||||
'StrCaseEq',
|
||||
'StrCaseNe',
|
||||
'StrEq',
|
||||
'StrNe',
|
||||
'Truly',
|
||||
'TypedEq',
|
||||
'Value',
|
||||
|
||||
# Actions
|
||||
'Assign',
|
||||
'ByRef',
|
||||
'DeleteArg',
|
||||
'DoAll',
|
||||
'DoDefault',
|
||||
'IgnoreResult',
|
||||
'Invoke',
|
||||
'InvokeArgument',
|
||||
'InvokeWithoutArgs',
|
||||
'Return',
|
||||
'ReturnNew',
|
||||
'ReturnNull',
|
||||
'ReturnRef',
|
||||
'SaveArg',
|
||||
'SetArgReferee',
|
||||
'SetArgPointee',
|
||||
'SetArgumentPointee',
|
||||
'SetArrayArgument',
|
||||
'SetErrnoAndReturn',
|
||||
'Throw',
|
||||
'WithArg',
|
||||
'WithArgs',
|
||||
'WithoutArgs',
|
||||
|
||||
# Cardinalities
|
||||
'AnyNumber',
|
||||
'AtLeast',
|
||||
'AtMost',
|
||||
'Between',
|
||||
'Exactly',
|
||||
|
||||
# Sequences
|
||||
'InSequence',
|
||||
'Sequence',
|
||||
|
||||
# Misc
|
||||
'DefaultValue',
|
||||
'Mock',
|
||||
]
|
||||
|
||||
# Regex for matching source file path and line number in the compiler's errors.
|
||||
_GCC_FILE_LINE_RE = r'(?P<file>.*):(?P<line>\d+):(\d+:)?\s+'
|
||||
_CLANG_FILE_LINE_RE = r'(?P<file>.*):(?P<line>\d+):(?P<column>\d+):\s+'
|
||||
_CLANG_NON_GMOCK_FILE_LINE_RE = (
|
||||
r'(?P<file>.*[/\\^](?!gmock-)[^/\\]+):(?P<line>\d+):(?P<column>\d+):\s+')
|
||||
|
||||
|
||||
def _FindAllMatches(regex, s):
|
||||
"""Generates all matches of regex in string s."""
|
||||
|
||||
r = re.compile(regex)
|
||||
return r.finditer(s)
|
||||
|
||||
|
||||
def _GenericDiagnoser(short_name, long_name, diagnoses, msg):
|
||||
"""Diagnoses the given disease by pattern matching.
|
||||
|
||||
Can provide different diagnoses for different patterns.
|
||||
|
||||
Args:
|
||||
short_name: Short name of the disease.
|
||||
long_name: Long name of the disease.
|
||||
diagnoses: A list of pairs (regex, pattern for formatting the diagnosis
|
||||
for matching regex).
|
||||
msg: Compiler's error messages.
|
||||
Yields:
|
||||
Tuples of the form
|
||||
(short name of disease, long name of disease, diagnosis).
|
||||
"""
|
||||
for regex, diagnosis in diagnoses:
|
||||
if re.search(regex, msg):
|
||||
diagnosis = '%(file)s:%(line)s:' + diagnosis
|
||||
for m in _FindAllMatches(regex, msg):
|
||||
yield (short_name, long_name, diagnosis % m.groupdict())
|
||||
|
||||
|
||||
def _NeedToReturnReferenceDiagnoser(msg):
|
||||
"""Diagnoses the NRR disease, given the error messages by the compiler."""
|
||||
|
||||
gcc_regex = (r'In member function \'testing::internal::ReturnAction<R>.*\n'
|
||||
+ _GCC_FILE_LINE_RE + r'instantiated from here\n'
|
||||
r'.*gmock-actions\.h.*error: creating array with negative size')
|
||||
clang_regex = (r'error:.*array.*negative.*\r?\n'
|
||||
r'(.*\n)*?' +
|
||||
_CLANG_NON_GMOCK_FILE_LINE_RE +
|
||||
r'note: in instantiation of function template specialization '
|
||||
r'\'testing::internal::ReturnAction<(?P<type>.*)>'
|
||||
r'::operator Action<.*>\' requested here')
|
||||
clang11_re = (r'use_ReturnRef_instead_of_Return_to_return_a_reference.*'
|
||||
r'(.*\n)*?' + _CLANG_NON_GMOCK_FILE_LINE_RE)
|
||||
|
||||
diagnosis = """
|
||||
You are using a Return() action in a function that returns a reference to
|
||||
%(type)s. Please use ReturnRef() instead."""
|
||||
return _GenericDiagnoser('NRR', 'Need to Return Reference',
|
||||
[(clang_regex, diagnosis),
|
||||
(clang11_re, diagnosis % {'type': 'a type'}),
|
||||
(gcc_regex, diagnosis % {'type': 'a type'})],
|
||||
msg)
|
||||
|
||||
|
||||
def _NeedToReturnSomethingDiagnoser(msg):
|
||||
"""Diagnoses the NRS disease, given the error messages by the compiler."""
|
||||
|
||||
gcc_regex = (_GCC_FILE_LINE_RE + r'(instantiated from here\n.'
|
||||
r'*gmock.*actions\.h.*error: void value not ignored)'
|
||||
r'|(error: control reaches end of non-void function)')
|
||||
clang_regex1 = (_CLANG_FILE_LINE_RE +
|
||||
r'error: cannot initialize return object '
|
||||
r'of type \'Result\' \(aka \'(?P<return_type>.*)\'\) '
|
||||
r'with an rvalue of type \'void\'')
|
||||
clang_regex2 = (_CLANG_FILE_LINE_RE +
|
||||
r'error: cannot initialize return object '
|
||||
r'of type \'(?P<return_type>.*)\' '
|
||||
r'with an rvalue of type \'void\'')
|
||||
diagnosis = """
|
||||
You are using an action that returns void, but it needs to return
|
||||
%(return_type)s. Please tell it *what* to return. Perhaps you can use
|
||||
the pattern DoAll(some_action, Return(some_value))?"""
|
||||
return _GenericDiagnoser(
|
||||
'NRS',
|
||||
'Need to Return Something',
|
||||
[(gcc_regex, diagnosis % {'return_type': '*something*'}),
|
||||
(clang_regex1, diagnosis),
|
||||
(clang_regex2, diagnosis)],
|
||||
msg)
|
||||
|
||||
|
||||
def _NeedToReturnNothingDiagnoser(msg):
|
||||
"""Diagnoses the NRN disease, given the error messages by the compiler."""
|
||||
|
||||
gcc_regex = (_GCC_FILE_LINE_RE + r'instantiated from here\n'
|
||||
r'.*gmock-actions\.h.*error: instantiation of '
|
||||
r'\'testing::internal::ReturnAction<R>::Impl<F>::value_\' '
|
||||
r'as type \'void\'')
|
||||
clang_regex1 = (r'error: field has incomplete type '
|
||||
r'\'Result\' \(aka \'void\'\)(\r)?\n'
|
||||
r'(.*\n)*?' +
|
||||
_CLANG_NON_GMOCK_FILE_LINE_RE + r'note: in instantiation '
|
||||
r'of function template specialization '
|
||||
r'\'testing::internal::ReturnAction<(?P<return_type>.*)>'
|
||||
r'::operator Action<void \(.*\)>\' requested here')
|
||||
clang_regex2 = (r'error: field has incomplete type '
|
||||
r'\'Result\' \(aka \'void\'\)(\r)?\n'
|
||||
r'(.*\n)*?' +
|
||||
_CLANG_NON_GMOCK_FILE_LINE_RE + r'note: in instantiation '
|
||||
r'of function template specialization '
|
||||
r'\'testing::internal::DoBothAction<.*>'
|
||||
r'::operator Action<(?P<return_type>.*) \(.*\)>\' '
|
||||
r'requested here')
|
||||
diagnosis = """
|
||||
You are using an action that returns %(return_type)s, but it needs to return
|
||||
void. Please use a void-returning action instead.
|
||||
|
||||
All actions but the last in DoAll(...) must return void. Perhaps you need
|
||||
to re-arrange the order of actions in a DoAll(), if you are using one?"""
|
||||
return _GenericDiagnoser(
|
||||
'NRN',
|
||||
'Need to Return Nothing',
|
||||
[(gcc_regex, diagnosis % {'return_type': '*something*'}),
|
||||
(clang_regex1, diagnosis),
|
||||
(clang_regex2, diagnosis)],
|
||||
msg)
|
||||
|
||||
|
||||
def _IncompleteByReferenceArgumentDiagnoser(msg):
|
||||
"""Diagnoses the IBRA disease, given the error messages by the compiler."""
|
||||
|
||||
gcc_regex = (_GCC_FILE_LINE_RE + r'instantiated from here\n'
|
||||
r'.*gtest-printers\.h.*error: invalid application of '
|
||||
r'\'sizeof\' to incomplete type \'(?P<type>.*)\'')
|
||||
|
||||
clang_regex = (r'.*gtest-printers\.h.*error: invalid application of '
|
||||
r'\'sizeof\' to an incomplete type '
|
||||
r'\'(?P<type>.*)( const)?\'\r?\n'
|
||||
r'(.*\n)*?' +
|
||||
_CLANG_NON_GMOCK_FILE_LINE_RE +
|
||||
r'note: in instantiation of member function '
|
||||
r'\'testing::internal2::TypeWithoutFormatter<.*>::'
|
||||
r'PrintValue\' requested here')
|
||||
diagnosis = """
|
||||
In order to mock this function, Google Mock needs to see the definition
|
||||
of type "%(type)s" - declaration alone is not enough. Either #include
|
||||
the header that defines it, or change the argument to be passed
|
||||
by pointer."""
|
||||
|
||||
return _GenericDiagnoser('IBRA', 'Incomplete By-Reference Argument Type',
|
||||
[(gcc_regex, diagnosis),
|
||||
(clang_regex, diagnosis)],
|
||||
msg)
|
||||
|
||||
|
||||
def _OverloadedFunctionMatcherDiagnoser(msg):
|
||||
"""Diagnoses the OFM disease, given the error messages by the compiler."""
|
||||
|
||||
gcc_regex = (_GCC_FILE_LINE_RE + r'error: no matching function for '
|
||||
r'call to \'Truly\(<unresolved overloaded function type>\)')
|
||||
clang_regex = (_CLANG_FILE_LINE_RE + r'error: no matching function for '
|
||||
r'call to \'Truly')
|
||||
diagnosis = """
|
||||
The argument you gave to Truly() is an overloaded function. Please tell
|
||||
your compiler which overloaded version you want to use.
|
||||
|
||||
For example, if you want to use the version whose signature is
|
||||
bool Foo(int n);
|
||||
you should write
|
||||
Truly(static_cast<bool (*)(int n)>(Foo))"""
|
||||
return _GenericDiagnoser('OFM', 'Overloaded Function Matcher',
|
||||
[(gcc_regex, diagnosis),
|
||||
(clang_regex, diagnosis)],
|
||||
msg)
|
||||
|
||||
|
||||
def _OverloadedFunctionActionDiagnoser(msg):
|
||||
"""Diagnoses the OFA disease, given the error messages by the compiler."""
|
||||
|
||||
gcc_regex = (_GCC_FILE_LINE_RE + r'error: no matching function for call to '
|
||||
r'\'Invoke\(<unresolved overloaded function type>')
|
||||
clang_regex = (_CLANG_FILE_LINE_RE + r'error: no matching '
|
||||
r'function for call to \'Invoke\'\r?\n'
|
||||
r'(.*\n)*?'
|
||||
r'.*\bgmock-generated-actions\.h:\d+:\d+:\s+'
|
||||
r'note: candidate template ignored:\s+'
|
||||
r'couldn\'t infer template argument \'FunctionImpl\'')
|
||||
diagnosis = """
|
||||
Function you are passing to Invoke is overloaded. Please tell your compiler
|
||||
which overloaded version you want to use.
|
||||
|
||||
For example, if you want to use the version whose signature is
|
||||
bool MyFunction(int n, double x);
|
||||
you should write something like
|
||||
Invoke(static_cast<bool (*)(int n, double x)>(MyFunction))"""
|
||||
return _GenericDiagnoser('OFA', 'Overloaded Function Action',
|
||||
[(gcc_regex, diagnosis),
|
||||
(clang_regex, diagnosis)],
|
||||
msg)
|
||||
|
||||
|
||||
def _OverloadedMethodActionDiagnoser(msg):
|
||||
"""Diagnoses the OMA disease, given the error messages by the compiler."""
|
||||
|
||||
gcc_regex = (_GCC_FILE_LINE_RE + r'error: no matching function for '
|
||||
r'call to \'Invoke\(.+, <unresolved overloaded function '
|
||||
r'type>\)')
|
||||
clang_regex = (_CLANG_FILE_LINE_RE + r'error: no matching function '
|
||||
r'for call to \'Invoke\'\r?\n'
|
||||
r'(.*\n)*?'
|
||||
r'.*\bgmock-generated-actions\.h:\d+:\d+: '
|
||||
r'note: candidate function template not viable: '
|
||||
r'requires .*, but 2 (arguments )?were provided')
|
||||
diagnosis = """
|
||||
The second argument you gave to Invoke() is an overloaded method. Please
|
||||
tell your compiler which overloaded version you want to use.
|
||||
|
||||
For example, if you want to use the version whose signature is
|
||||
class Foo {
|
||||
...
|
||||
bool Bar(int n, double x);
|
||||
};
|
||||
you should write something like
|
||||
Invoke(foo, static_cast<bool (Foo::*)(int n, double x)>(&Foo::Bar))"""
|
||||
return _GenericDiagnoser('OMA', 'Overloaded Method Action',
|
||||
[(gcc_regex, diagnosis),
|
||||
(clang_regex, diagnosis)],
|
||||
msg)
|
||||
|
||||
|
||||
def _MockObjectPointerDiagnoser(msg):
|
||||
"""Diagnoses the MOP disease, given the error messages by the compiler."""
|
||||
|
||||
gcc_regex = (_GCC_FILE_LINE_RE + r'error: request for member '
|
||||
r'\'gmock_(?P<method>.+)\' in \'(?P<mock_object>.+)\', '
|
||||
r'which is of non-class type \'(.*::)*(?P<class_name>.+)\*\'')
|
||||
clang_regex = (_CLANG_FILE_LINE_RE + r'error: member reference type '
|
||||
r'\'(?P<class_name>.*?) *\' is a pointer; '
|
||||
r'(did you mean|maybe you meant) to use \'->\'\?')
|
||||
diagnosis = """
|
||||
The first argument to ON_CALL() and EXPECT_CALL() must be a mock *object*,
|
||||
not a *pointer* to it. Please write '*(%(mock_object)s)' instead of
|
||||
'%(mock_object)s' as your first argument.
|
||||
|
||||
For example, given the mock class:
|
||||
|
||||
class %(class_name)s : public ... {
|
||||
...
|
||||
MOCK_METHOD0(%(method)s, ...);
|
||||
};
|
||||
|
||||
and the following mock instance:
|
||||
|
||||
%(class_name)s* mock_ptr = ...
|
||||
|
||||
you should use the EXPECT_CALL like this:
|
||||
|
||||
EXPECT_CALL(*mock_ptr, %(method)s(...));"""
|
||||
|
||||
return _GenericDiagnoser(
|
||||
'MOP',
|
||||
'Mock Object Pointer',
|
||||
[(gcc_regex, diagnosis),
|
||||
(clang_regex, diagnosis % {'mock_object': 'mock_object',
|
||||
'method': 'method',
|
||||
'class_name': '%(class_name)s'})],
|
||||
msg)
|
||||
|
||||
|
||||
def _NeedToUseSymbolDiagnoser(msg):
|
||||
"""Diagnoses the NUS disease, given the error messages by the compiler."""
|
||||
|
||||
gcc_regex = (_GCC_FILE_LINE_RE + r'error: \'(?P<symbol>.+)\' '
|
||||
r'(was not declared in this scope|has not been declared)')
|
||||
clang_regex = (_CLANG_FILE_LINE_RE +
|
||||
r'error: (use of undeclared identifier|unknown type name|'
|
||||
r'no template named) \'(?P<symbol>[^\']+)\'')
|
||||
diagnosis = """
|
||||
'%(symbol)s' is defined by Google Mock in the testing namespace.
|
||||
Did you forget to write
|
||||
using testing::%(symbol)s;
|
||||
?"""
|
||||
for m in (list(_FindAllMatches(gcc_regex, msg)) +
|
||||
list(_FindAllMatches(clang_regex, msg))):
|
||||
symbol = m.groupdict()['symbol']
|
||||
if symbol in _COMMON_GMOCK_SYMBOLS:
|
||||
yield ('NUS', 'Need to Use Symbol', diagnosis % m.groupdict())
|
||||
|
||||
|
||||
def _NeedToUseReturnNullDiagnoser(msg):
|
||||
"""Diagnoses the NRNULL disease, given the error messages by the compiler."""
|
||||
|
||||
gcc_regex = ('instantiated from \'testing::internal::ReturnAction<R>'
|
||||
'::operator testing::Action<Func>\(\) const.*\n' +
|
||||
_GCC_FILE_LINE_RE + r'instantiated from here\n'
|
||||
r'.*error: no matching function for call to \'ImplicitCast_\('
|
||||
r'(:?long )?int&\)')
|
||||
clang_regex = (r'\bgmock-actions.h:.* error: no matching function for '
|
||||
r'call to \'ImplicitCast_\'\r?\n'
|
||||
r'(.*\n)*?' +
|
||||
_CLANG_NON_GMOCK_FILE_LINE_RE + r'note: in instantiation '
|
||||
r'of function template specialization '
|
||||
r'\'testing::internal::ReturnAction<(int|long)>::operator '
|
||||
r'Action<(?P<type>.*)\(\)>\' requested here')
|
||||
diagnosis = """
|
||||
You are probably calling Return(NULL) and the compiler isn't sure how to turn
|
||||
NULL into %(type)s. Use ReturnNull() instead.
|
||||
Note: the line number may be off; please fix all instances of Return(NULL)."""
|
||||
return _GenericDiagnoser(
|
||||
'NRNULL', 'Need to use ReturnNull',
|
||||
[(clang_regex, diagnosis),
|
||||
(gcc_regex, diagnosis % {'type': 'the right type'})],
|
||||
msg)
|
||||
|
||||
|
||||
def _TypeInTemplatedBaseDiagnoser(msg):
|
||||
"""Diagnoses the TTB disease, given the error messages by the compiler."""
|
||||
|
||||
# This version works when the type is used as the mock function's return
|
||||
# type.
|
||||
gcc_4_3_1_regex_type_in_retval = (
|
||||
r'In member function \'int .*\n' + _GCC_FILE_LINE_RE +
|
||||
r'error: a function call cannot appear in a constant-expression')
|
||||
gcc_4_4_0_regex_type_in_retval = (
|
||||
r'error: a function call cannot appear in a constant-expression'
|
||||
+ _GCC_FILE_LINE_RE + r'error: template argument 1 is invalid\n')
|
||||
# This version works when the type is used as the mock function's sole
|
||||
# parameter type.
|
||||
gcc_regex_type_of_sole_param = (
|
||||
_GCC_FILE_LINE_RE +
|
||||
r'error: \'(?P<type>.+)\' was not declared in this scope\n'
|
||||
r'.*error: template argument 1 is invalid\n')
|
||||
# This version works when the type is used as a parameter of a mock
|
||||
# function that has multiple parameters.
|
||||
gcc_regex_type_of_a_param = (
|
||||
r'error: expected `;\' before \'::\' token\n'
|
||||
+ _GCC_FILE_LINE_RE +
|
||||
r'error: \'(?P<type>.+)\' was not declared in this scope\n'
|
||||
r'.*error: template argument 1 is invalid\n'
|
||||
r'.*error: \'.+\' was not declared in this scope')
|
||||
clang_regex_type_of_retval_or_sole_param = (
|
||||
_CLANG_FILE_LINE_RE +
|
||||
r'error: use of undeclared identifier \'(?P<type>.*)\'\n'
|
||||
r'(.*\n)*?'
|
||||
r'(?P=file):(?P=line):\d+: error: '
|
||||
r'non-friend class member \'Result\' cannot have a qualified name'
|
||||
)
|
||||
clang_regex_type_of_a_param = (
|
||||
_CLANG_FILE_LINE_RE +
|
||||
r'error: C\+\+ requires a type specifier for all declarations\n'
|
||||
r'(.*\n)*?'
|
||||
r'(?P=file):(?P=line):(?P=column): error: '
|
||||
r'C\+\+ requires a type specifier for all declarations'
|
||||
)
|
||||
clang_regex_unknown_type = (
|
||||
_CLANG_FILE_LINE_RE +
|
||||
r'error: unknown type name \'(?P<type>[^\']+)\''
|
||||
)
|
||||
|
||||
diagnosis = """
|
||||
In a mock class template, types or typedefs defined in the base class
|
||||
template are *not* automatically visible. This is how C++ works. Before
|
||||
you can use a type or typedef named %(type)s defined in base class Base<T>, you
|
||||
need to make it visible. One way to do it is:
|
||||
|
||||
typedef typename Base<T>::%(type)s %(type)s;"""
|
||||
|
||||
for diag in _GenericDiagnoser(
|
||||
'TTB', 'Type in Template Base',
|
||||
[(gcc_4_3_1_regex_type_in_retval, diagnosis % {'type': 'Foo'}),
|
||||
(gcc_4_4_0_regex_type_in_retval, diagnosis % {'type': 'Foo'}),
|
||||
(gcc_regex_type_of_sole_param, diagnosis),
|
||||
(gcc_regex_type_of_a_param, diagnosis),
|
||||
(clang_regex_type_of_retval_or_sole_param, diagnosis),
|
||||
(clang_regex_type_of_a_param, diagnosis % {'type': 'Foo'})],
|
||||
msg):
|
||||
yield diag
|
||||
# Avoid overlap with the NUS pattern.
|
||||
for m in _FindAllMatches(clang_regex_unknown_type, msg):
|
||||
type_ = m.groupdict()['type']
|
||||
if type_ not in _COMMON_GMOCK_SYMBOLS:
|
||||
yield ('TTB', 'Type in Template Base', diagnosis % m.groupdict())
|
||||
|
||||
|
||||
def _WrongMockMethodMacroDiagnoser(msg):
|
||||
"""Diagnoses the WMM disease, given the error messages by the compiler."""
|
||||
|
||||
gcc_regex = (_GCC_FILE_LINE_RE +
|
||||
r'.*this_method_does_not_take_(?P<wrong_args>\d+)_argument.*\n'
|
||||
r'.*\n'
|
||||
r'.*candidates are.*FunctionMocker<[^>]+A(?P<args>\d+)\)>')
|
||||
clang_regex = (_CLANG_NON_GMOCK_FILE_LINE_RE +
|
||||
r'error:.*array.*negative.*r?\n'
|
||||
r'(.*\n)*?'
|
||||
r'(?P=file):(?P=line):(?P=column): error: too few arguments '
|
||||
r'to function call, expected (?P<args>\d+), '
|
||||
r'have (?P<wrong_args>\d+)')
|
||||
clang11_re = (_CLANG_NON_GMOCK_FILE_LINE_RE +
|
||||
r'.*this_method_does_not_take_'
|
||||
r'(?P<wrong_args>\d+)_argument.*')
|
||||
diagnosis = """
|
||||
You are using MOCK_METHOD%(wrong_args)s to define a mock method that has
|
||||
%(args)s arguments. Use MOCK_METHOD%(args)s (or MOCK_CONST_METHOD%(args)s,
|
||||
MOCK_METHOD%(args)s_T, MOCK_CONST_METHOD%(args)s_T as appropriate) instead."""
|
||||
return _GenericDiagnoser('WMM', 'Wrong MOCK_METHODn Macro',
|
||||
[(gcc_regex, diagnosis),
|
||||
(clang11_re, diagnosis % {'wrong_args': 'm',
|
||||
'args': 'n'}),
|
||||
(clang_regex, diagnosis)],
|
||||
msg)
|
||||
|
||||
|
||||
def _WrongParenPositionDiagnoser(msg):
|
||||
"""Diagnoses the WPP disease, given the error messages by the compiler."""
|
||||
|
||||
gcc_regex = (_GCC_FILE_LINE_RE +
|
||||
r'error:.*testing::internal::MockSpec<.* has no member named \''
|
||||
r'(?P<method>\w+)\'')
|
||||
clang_regex = (_CLANG_NON_GMOCK_FILE_LINE_RE +
|
||||
r'error: no member named \'(?P<method>\w+)\' in '
|
||||
r'\'testing::internal::MockSpec<.*>\'')
|
||||
diagnosis = """
|
||||
The closing parenthesis of ON_CALL or EXPECT_CALL should be *before*
|
||||
".%(method)s". For example, you should write:
|
||||
EXPECT_CALL(my_mock, Foo(_)).%(method)s(...);
|
||||
instead of:
|
||||
EXPECT_CALL(my_mock, Foo(_).%(method)s(...));"""
|
||||
return _GenericDiagnoser('WPP', 'Wrong Parenthesis Position',
|
||||
[(gcc_regex, diagnosis),
|
||||
(clang_regex, diagnosis)],
|
||||
msg)
|
||||
|
||||
|
||||
_DIAGNOSERS = [
|
||||
_IncompleteByReferenceArgumentDiagnoser,
|
||||
_MockObjectPointerDiagnoser,
|
||||
_NeedToReturnNothingDiagnoser,
|
||||
_NeedToReturnReferenceDiagnoser,
|
||||
_NeedToReturnSomethingDiagnoser,
|
||||
_NeedToUseReturnNullDiagnoser,
|
||||
_NeedToUseSymbolDiagnoser,
|
||||
_OverloadedFunctionActionDiagnoser,
|
||||
_OverloadedFunctionMatcherDiagnoser,
|
||||
_OverloadedMethodActionDiagnoser,
|
||||
_TypeInTemplatedBaseDiagnoser,
|
||||
_WrongMockMethodMacroDiagnoser,
|
||||
_WrongParenPositionDiagnoser,
|
||||
]
|
||||
|
||||
|
||||
def Diagnose(msg):
|
||||
"""Generates all possible diagnoses given the compiler error message."""
|
||||
|
||||
msg = re.sub(r'\x1b\[[^m]*m', '', msg) # Strips all color formatting.
|
||||
# Assuming the string is using the UTF-8 encoding, replaces the left and
|
||||
# the right single quote characters with apostrophes.
|
||||
msg = re.sub(r'(\xe2\x80\x98|\xe2\x80\x99)', "'", msg)
|
||||
|
||||
diagnoses = []
|
||||
for diagnoser in _DIAGNOSERS:
|
||||
for diag in diagnoser(msg):
|
||||
diagnosis = '[%s - %s]\n%s' % diag
|
||||
if not diagnosis in diagnoses:
|
||||
diagnoses.append(diagnosis)
|
||||
return diagnoses
|
||||
|
||||
|
||||
def main():
|
||||
print ('Google Mock Doctor v%s - '
|
||||
'diagnoses problems in code using Google Mock.' % _VERSION)
|
||||
|
||||
if sys.stdin.isatty():
|
||||
print ('Please copy and paste the compiler errors here. Press c-D when '
|
||||
'you are done:')
|
||||
else:
|
||||
print ('Waiting for compiler errors on stdin . . .')
|
||||
|
||||
msg = sys.stdin.read().strip()
|
||||
diagnoses = Diagnose(msg)
|
||||
count = len(diagnoses)
|
||||
if not count:
|
||||
print ("""
|
||||
Your compiler complained:
|
||||
8<------------------------------------------------------------
|
||||
%s
|
||||
------------------------------------------------------------>8
|
||||
|
||||
Uh-oh, I'm not smart enough to figure out what the problem is. :-(
|
||||
However...
|
||||
If you send your source code and the compiler's error messages to
|
||||
%s, you can be helped and I can get smarter --
|
||||
win-win for us!""" % (msg, _EMAIL))
|
||||
else:
|
||||
print ('------------------------------------------------------------')
|
||||
print ('Your code appears to have the following',)
|
||||
if count > 1:
|
||||
print ('%s diseases:' % (count,))
|
||||
else:
|
||||
print ('disease:')
|
||||
i = 0
|
||||
for d in diagnoses:
|
||||
i += 1
|
||||
if count > 1:
|
||||
print ('\n#%s:' % (i,))
|
||||
print (d)
|
||||
print ("""
|
||||
How did I do? If you think I'm wrong or unhelpful, please send your
|
||||
source code and the compiler's error messages to %s.
|
||||
Then you can be helped and I can get smarter -- I promise I won't be upset!""" %
|
||||
_EMAIL)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
File diff suppressed because it is too large
Load Diff
@@ -1,16 +0,0 @@
|
||||
#include "gmock/gmock.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#if defined(TEST_MOCK_METHOD_INVALID_CONST_SPEC)
|
||||
|
||||
struct Base {
|
||||
MOCK_METHOD(int, F, (), (onst));
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
// Sanity check - this should compile.
|
||||
|
||||
#endif
|
@@ -1,43 +0,0 @@
|
||||
"""Negative compilation tests for Google Mock macro MOCK_METHOD."""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
IS_LINUX = os.name == "posix" and os.uname()[0] == "Linux"
|
||||
if not IS_LINUX:
|
||||
sys.stderr.write(
|
||||
"WARNING: Negative compilation tests are not supported on this platform")
|
||||
sys.exit(0)
|
||||
|
||||
# Suppresses the 'Import not at the top of the file' lint complaint.
|
||||
# pylint: disable-msg=C6204
|
||||
from google3.testing.pybase import fake_target_util
|
||||
from google3.testing.pybase import googletest
|
||||
|
||||
# pylint: enable-msg=C6204
|
||||
|
||||
|
||||
class GMockMethodNCTest(googletest.TestCase):
|
||||
"""Negative compilation tests for MOCK_METHOD."""
|
||||
|
||||
# The class body is intentionally empty. The actual test*() methods
|
||||
# will be defined at run time by a call to
|
||||
# DefineNegativeCompilationTests() later.
|
||||
pass
|
||||
|
||||
|
||||
# Defines a list of test specs, where each element is a tuple
|
||||
# (test name, list of regexes for matching the compiler errors).
|
||||
TEST_SPECS = [
|
||||
("MOCK_METHOD_INVALID_CONST_SPEC",
|
||||
[r"onst cannot be recognized as a valid specification modifier"]),
|
||||
]
|
||||
|
||||
# Define a test method in GMockNCTest for each element in TEST_SPECS.
|
||||
fake_target_util.DefineNegativeCompilationTests(
|
||||
GMockMethodNCTest,
|
||||
"google3/third_party/googletest/googlemock/test/gmock-function-mocker_nc",
|
||||
"gmock-function-mocker_nc.o", TEST_SPECS)
|
||||
|
||||
if __name__ == "__main__":
|
||||
googletest.main()
|
@@ -1,660 +0,0 @@
|
||||
// Copyright 2007, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
// Google Mock - a framework for writing C++ mock classes.
|
||||
//
|
||||
// This file tests the function mocker classes.
|
||||
#include "gmock/gmock-generated-function-mockers.h"
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
// MSDN says the header file to be included for STDMETHOD is BaseTyps.h but
|
||||
// we are getting compiler errors if we use basetyps.h, hence including
|
||||
// objbase.h for definition of STDMETHOD.
|
||||
# include <objbase.h>
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace testing {
|
||||
namespace gmock_function_mocker_test {
|
||||
|
||||
using testing::_;
|
||||
using testing::A;
|
||||
using testing::An;
|
||||
using testing::AnyNumber;
|
||||
using testing::Const;
|
||||
using testing::DoDefault;
|
||||
using testing::Eq;
|
||||
using testing::Lt;
|
||||
using testing::MockFunction;
|
||||
using testing::Ref;
|
||||
using testing::Return;
|
||||
using testing::ReturnRef;
|
||||
using testing::TypedEq;
|
||||
|
||||
template<typename T>
|
||||
class TemplatedCopyable {
|
||||
public:
|
||||
TemplatedCopyable() {}
|
||||
|
||||
template <typename U>
|
||||
TemplatedCopyable(const U& other) {} // NOLINT
|
||||
};
|
||||
|
||||
class FooInterface {
|
||||
public:
|
||||
virtual ~FooInterface() {}
|
||||
|
||||
virtual void VoidReturning(int x) = 0;
|
||||
|
||||
virtual int Nullary() = 0;
|
||||
virtual bool Unary(int x) = 0;
|
||||
virtual long Binary(short x, int y) = 0; // NOLINT
|
||||
virtual int Decimal(bool b, char c, short d, int e, long f, // NOLINT
|
||||
float g, double h, unsigned i, char* j,
|
||||
const std::string& k) = 0;
|
||||
|
||||
virtual bool TakesNonConstReference(int& n) = 0; // NOLINT
|
||||
virtual std::string TakesConstReference(const int& n) = 0;
|
||||
virtual bool TakesConst(const int x) = 0;
|
||||
|
||||
virtual int OverloadedOnArgumentNumber() = 0;
|
||||
virtual int OverloadedOnArgumentNumber(int n) = 0;
|
||||
|
||||
virtual int OverloadedOnArgumentType(int n) = 0;
|
||||
virtual char OverloadedOnArgumentType(char c) = 0;
|
||||
|
||||
virtual int OverloadedOnConstness() = 0;
|
||||
virtual char OverloadedOnConstness() const = 0;
|
||||
|
||||
virtual int TypeWithHole(int (*func)()) = 0;
|
||||
virtual int TypeWithComma(const std::map<int, std::string>& a_map) = 0;
|
||||
virtual int TypeWithTemplatedCopyCtor(const TemplatedCopyable<int>&) = 0;
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
STDMETHOD_(int, CTNullary)() = 0;
|
||||
STDMETHOD_(bool, CTUnary)(int x) = 0;
|
||||
STDMETHOD_(int, CTDecimal)
|
||||
(bool b, char c, short d, int e, long f, // NOLINT
|
||||
float g, double h, unsigned i, char* j, const std::string& k) = 0;
|
||||
STDMETHOD_(char, CTConst)(int x) const = 0;
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
};
|
||||
|
||||
// Const qualifiers on arguments were once (incorrectly) considered
|
||||
// significant in determining whether two virtual functions had the same
|
||||
// signature. This was fixed in Visual Studio 2008. However, the compiler
|
||||
// still emits a warning that alerts about this change in behavior.
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4373)
|
||||
#endif
|
||||
class MockFoo : public FooInterface {
|
||||
public:
|
||||
MockFoo() {}
|
||||
|
||||
// Makes sure that a mock function parameter can be named.
|
||||
MOCK_METHOD(void, VoidReturning, (int n)); // NOLINT
|
||||
|
||||
MOCK_METHOD(int, Nullary, ()); // NOLINT
|
||||
|
||||
// Makes sure that a mock function parameter can be unnamed.
|
||||
MOCK_METHOD(bool, Unary, (int)); // NOLINT
|
||||
MOCK_METHOD(long, Binary, (short, int)); // NOLINT
|
||||
MOCK_METHOD(int, Decimal,
|
||||
(bool, char, short, int, long, float, // NOLINT
|
||||
double, unsigned, char*, const std::string& str),
|
||||
(override));
|
||||
|
||||
MOCK_METHOD(bool, TakesNonConstReference, (int&)); // NOLINT
|
||||
MOCK_METHOD(std::string, TakesConstReference, (const int&));
|
||||
MOCK_METHOD(bool, TakesConst, (const int)); // NOLINT
|
||||
|
||||
// Tests that the function return type can contain unprotected comma.
|
||||
MOCK_METHOD((std::map<int, std::string>), ReturnTypeWithComma, (), ());
|
||||
MOCK_METHOD((std::map<int, std::string>), ReturnTypeWithComma, (int),
|
||||
(const)); // NOLINT
|
||||
|
||||
MOCK_METHOD(int, OverloadedOnArgumentNumber, ()); // NOLINT
|
||||
MOCK_METHOD(int, OverloadedOnArgumentNumber, (int)); // NOLINT
|
||||
|
||||
MOCK_METHOD(int, OverloadedOnArgumentType, (int)); // NOLINT
|
||||
MOCK_METHOD(char, OverloadedOnArgumentType, (char)); // NOLINT
|
||||
|
||||
MOCK_METHOD(int, OverloadedOnConstness, (), (override)); // NOLINT
|
||||
MOCK_METHOD(char, OverloadedOnConstness, (), (override, const)); // NOLINT
|
||||
|
||||
MOCK_METHOD(int, TypeWithHole, (int (*)()), ()); // NOLINT
|
||||
MOCK_METHOD(int, TypeWithComma, ((const std::map<int, std::string>&)));
|
||||
MOCK_METHOD(int, TypeWithTemplatedCopyCtor,
|
||||
(const TemplatedCopyable<int>&)); // NOLINT
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
MOCK_METHOD(int, CTNullary, (), (Calltype(STDMETHODCALLTYPE)));
|
||||
MOCK_METHOD(bool, CTUnary, (int), (Calltype(STDMETHODCALLTYPE)));
|
||||
MOCK_METHOD(int, CTDecimal,
|
||||
(bool b, char c, short d, int e, long f, float g, double h,
|
||||
unsigned i, char* j, const std::string& k),
|
||||
(Calltype(STDMETHODCALLTYPE)));
|
||||
MOCK_METHOD(char, CTConst, (int), (const, Calltype(STDMETHODCALLTYPE)));
|
||||
MOCK_METHOD((std::map<int, std::string>), CTReturnTypeWithComma, (),
|
||||
(Calltype(STDMETHODCALLTYPE)));
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFoo);
|
||||
};
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
class MockMethodFunctionMockerTest : public testing::Test {
|
||||
protected:
|
||||
MockMethodFunctionMockerTest() : foo_(&mock_foo_) {}
|
||||
|
||||
FooInterface* const foo_;
|
||||
MockFoo mock_foo_;
|
||||
};
|
||||
|
||||
// Tests mocking a void-returning function.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksVoidFunction) {
|
||||
EXPECT_CALL(mock_foo_, VoidReturning(Lt(100)));
|
||||
foo_->VoidReturning(0);
|
||||
}
|
||||
|
||||
// Tests mocking a nullary function.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksNullaryFunction) {
|
||||
EXPECT_CALL(mock_foo_, Nullary())
|
||||
.WillOnce(DoDefault())
|
||||
.WillOnce(Return(1));
|
||||
|
||||
EXPECT_EQ(0, foo_->Nullary());
|
||||
EXPECT_EQ(1, foo_->Nullary());
|
||||
}
|
||||
|
||||
// Tests mocking a unary function.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksUnaryFunction) {
|
||||
EXPECT_CALL(mock_foo_, Unary(Eq(2)))
|
||||
.Times(2)
|
||||
.WillOnce(Return(true));
|
||||
|
||||
EXPECT_TRUE(foo_->Unary(2));
|
||||
EXPECT_FALSE(foo_->Unary(2));
|
||||
}
|
||||
|
||||
// Tests mocking a binary function.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksBinaryFunction) {
|
||||
EXPECT_CALL(mock_foo_, Binary(2, _))
|
||||
.WillOnce(Return(3));
|
||||
|
||||
EXPECT_EQ(3, foo_->Binary(2, 1));
|
||||
}
|
||||
|
||||
// Tests mocking a decimal function.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksDecimalFunction) {
|
||||
EXPECT_CALL(mock_foo_, Decimal(true, 'a', 0, 0, 1L, A<float>(),
|
||||
Lt(100), 5U, NULL, "hi"))
|
||||
.WillOnce(Return(5));
|
||||
|
||||
EXPECT_EQ(5, foo_->Decimal(true, 'a', 0, 0, 1, 0, 0, 5, nullptr, "hi"));
|
||||
}
|
||||
|
||||
// Tests mocking a function that takes a non-const reference.
|
||||
TEST_F(MockMethodFunctionMockerTest,
|
||||
MocksFunctionWithNonConstReferenceArgument) {
|
||||
int a = 0;
|
||||
EXPECT_CALL(mock_foo_, TakesNonConstReference(Ref(a)))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
EXPECT_TRUE(foo_->TakesNonConstReference(a));
|
||||
}
|
||||
|
||||
// Tests mocking a function that takes a const reference.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksFunctionWithConstReferenceArgument) {
|
||||
int a = 0;
|
||||
EXPECT_CALL(mock_foo_, TakesConstReference(Ref(a)))
|
||||
.WillOnce(Return("Hello"));
|
||||
|
||||
EXPECT_EQ("Hello", foo_->TakesConstReference(a));
|
||||
}
|
||||
|
||||
// Tests mocking a function that takes a const variable.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksFunctionWithConstArgument) {
|
||||
EXPECT_CALL(mock_foo_, TakesConst(Lt(10)))
|
||||
.WillOnce(DoDefault());
|
||||
|
||||
EXPECT_FALSE(foo_->TakesConst(5));
|
||||
}
|
||||
|
||||
// Tests mocking functions overloaded on the number of arguments.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksFunctionsOverloadedOnArgumentNumber) {
|
||||
EXPECT_CALL(mock_foo_, OverloadedOnArgumentNumber())
|
||||
.WillOnce(Return(1));
|
||||
EXPECT_CALL(mock_foo_, OverloadedOnArgumentNumber(_))
|
||||
.WillOnce(Return(2));
|
||||
|
||||
EXPECT_EQ(2, foo_->OverloadedOnArgumentNumber(1));
|
||||
EXPECT_EQ(1, foo_->OverloadedOnArgumentNumber());
|
||||
}
|
||||
|
||||
// Tests mocking functions overloaded on the types of argument.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksFunctionsOverloadedOnArgumentType) {
|
||||
EXPECT_CALL(mock_foo_, OverloadedOnArgumentType(An<int>()))
|
||||
.WillOnce(Return(1));
|
||||
EXPECT_CALL(mock_foo_, OverloadedOnArgumentType(TypedEq<char>('a')))
|
||||
.WillOnce(Return('b'));
|
||||
|
||||
EXPECT_EQ(1, foo_->OverloadedOnArgumentType(0));
|
||||
EXPECT_EQ('b', foo_->OverloadedOnArgumentType('a'));
|
||||
}
|
||||
|
||||
// Tests mocking functions overloaded on the const-ness of this object.
|
||||
TEST_F(MockMethodFunctionMockerTest,
|
||||
MocksFunctionsOverloadedOnConstnessOfThis) {
|
||||
EXPECT_CALL(mock_foo_, OverloadedOnConstness());
|
||||
EXPECT_CALL(Const(mock_foo_), OverloadedOnConstness())
|
||||
.WillOnce(Return('a'));
|
||||
|
||||
EXPECT_EQ(0, foo_->OverloadedOnConstness());
|
||||
EXPECT_EQ('a', Const(*foo_).OverloadedOnConstness());
|
||||
}
|
||||
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksReturnTypeWithComma) {
|
||||
const std::map<int, std::string> a_map;
|
||||
EXPECT_CALL(mock_foo_, ReturnTypeWithComma())
|
||||
.WillOnce(Return(a_map));
|
||||
EXPECT_CALL(mock_foo_, ReturnTypeWithComma(42))
|
||||
.WillOnce(Return(a_map));
|
||||
|
||||
EXPECT_EQ(a_map, mock_foo_.ReturnTypeWithComma());
|
||||
EXPECT_EQ(a_map, mock_foo_.ReturnTypeWithComma(42));
|
||||
}
|
||||
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksTypeWithTemplatedCopyCtor) {
|
||||
EXPECT_CALL(mock_foo_, TypeWithTemplatedCopyCtor(_)).WillOnce(Return(true));
|
||||
EXPECT_TRUE(foo_->TypeWithTemplatedCopyCtor(TemplatedCopyable<int>()));
|
||||
}
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
// Tests mocking a nullary function with calltype.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksNullaryFunctionWithCallType) {
|
||||
EXPECT_CALL(mock_foo_, CTNullary())
|
||||
.WillOnce(Return(-1))
|
||||
.WillOnce(Return(0));
|
||||
|
||||
EXPECT_EQ(-1, foo_->CTNullary());
|
||||
EXPECT_EQ(0, foo_->CTNullary());
|
||||
}
|
||||
|
||||
// Tests mocking a unary function with calltype.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksUnaryFunctionWithCallType) {
|
||||
EXPECT_CALL(mock_foo_, CTUnary(Eq(2)))
|
||||
.Times(2)
|
||||
.WillOnce(Return(true))
|
||||
.WillOnce(Return(false));
|
||||
|
||||
EXPECT_TRUE(foo_->CTUnary(2));
|
||||
EXPECT_FALSE(foo_->CTUnary(2));
|
||||
}
|
||||
|
||||
// Tests mocking a decimal function with calltype.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksDecimalFunctionWithCallType) {
|
||||
EXPECT_CALL(mock_foo_, CTDecimal(true, 'a', 0, 0, 1L, A<float>(),
|
||||
Lt(100), 5U, NULL, "hi"))
|
||||
.WillOnce(Return(10));
|
||||
|
||||
EXPECT_EQ(10, foo_->CTDecimal(true, 'a', 0, 0, 1, 0, 0, 5, NULL, "hi"));
|
||||
}
|
||||
|
||||
// Tests mocking functions overloaded on the const-ness of this object.
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksFunctionsConstFunctionWithCallType) {
|
||||
EXPECT_CALL(Const(mock_foo_), CTConst(_))
|
||||
.WillOnce(Return('a'));
|
||||
|
||||
EXPECT_EQ('a', Const(*foo_).CTConst(0));
|
||||
}
|
||||
|
||||
TEST_F(MockMethodFunctionMockerTest, MocksReturnTypeWithCommaAndCallType) {
|
||||
const std::map<int, std::string> a_map;
|
||||
EXPECT_CALL(mock_foo_, CTReturnTypeWithComma())
|
||||
.WillOnce(Return(a_map));
|
||||
|
||||
EXPECT_EQ(a_map, mock_foo_.CTReturnTypeWithComma());
|
||||
}
|
||||
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
class MockB {
|
||||
public:
|
||||
MockB() {}
|
||||
|
||||
MOCK_METHOD(void, DoB, ());
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockB);
|
||||
};
|
||||
|
||||
// Tests that functions with no EXPECT_CALL() rules can be called any
|
||||
// number of times.
|
||||
TEST(MockMethodExpectCallTest, UnmentionedFunctionCanBeCalledAnyNumberOfTimes) {
|
||||
{
|
||||
MockB b;
|
||||
}
|
||||
|
||||
{
|
||||
MockB b;
|
||||
b.DoB();
|
||||
}
|
||||
|
||||
{
|
||||
MockB b;
|
||||
b.DoB();
|
||||
b.DoB();
|
||||
}
|
||||
}
|
||||
|
||||
// Tests mocking template interfaces.
|
||||
|
||||
template <typename T>
|
||||
class StackInterface {
|
||||
public:
|
||||
virtual ~StackInterface() {}
|
||||
|
||||
// Template parameter appears in function parameter.
|
||||
virtual void Push(const T& value) = 0;
|
||||
virtual void Pop() = 0;
|
||||
virtual int GetSize() const = 0;
|
||||
// Template parameter appears in function return type.
|
||||
virtual const T& GetTop() const = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class MockStack : public StackInterface<T> {
|
||||
public:
|
||||
MockStack() {}
|
||||
|
||||
MOCK_METHOD(void, Push, (const T& elem), ());
|
||||
MOCK_METHOD(void, Pop, (), (final));
|
||||
MOCK_METHOD(int, GetSize, (), (const, override));
|
||||
MOCK_METHOD(const T&, GetTop, (), (const));
|
||||
|
||||
// Tests that the function return type can contain unprotected comma.
|
||||
MOCK_METHOD((std::map<int, int>), ReturnTypeWithComma, (), ());
|
||||
MOCK_METHOD((std::map<int, int>), ReturnTypeWithComma, (int), (const));
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockStack);
|
||||
};
|
||||
|
||||
// Tests that template mock works.
|
||||
TEST(MockMethodTemplateMockTest, Works) {
|
||||
MockStack<int> mock;
|
||||
|
||||
EXPECT_CALL(mock, GetSize())
|
||||
.WillOnce(Return(0))
|
||||
.WillOnce(Return(1))
|
||||
.WillOnce(Return(0));
|
||||
EXPECT_CALL(mock, Push(_));
|
||||
int n = 5;
|
||||
EXPECT_CALL(mock, GetTop())
|
||||
.WillOnce(ReturnRef(n));
|
||||
EXPECT_CALL(mock, Pop())
|
||||
.Times(AnyNumber());
|
||||
|
||||
EXPECT_EQ(0, mock.GetSize());
|
||||
mock.Push(5);
|
||||
EXPECT_EQ(1, mock.GetSize());
|
||||
EXPECT_EQ(5, mock.GetTop());
|
||||
mock.Pop();
|
||||
EXPECT_EQ(0, mock.GetSize());
|
||||
}
|
||||
|
||||
TEST(MockMethodTemplateMockTest, MethodWithCommaInReturnTypeWorks) {
|
||||
MockStack<int> mock;
|
||||
|
||||
const std::map<int, int> a_map;
|
||||
EXPECT_CALL(mock, ReturnTypeWithComma())
|
||||
.WillOnce(Return(a_map));
|
||||
EXPECT_CALL(mock, ReturnTypeWithComma(1))
|
||||
.WillOnce(Return(a_map));
|
||||
|
||||
EXPECT_EQ(a_map, mock.ReturnTypeWithComma());
|
||||
EXPECT_EQ(a_map, mock.ReturnTypeWithComma(1));
|
||||
}
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
// Tests mocking template interfaces with calltype.
|
||||
|
||||
template <typename T>
|
||||
class StackInterfaceWithCallType {
|
||||
public:
|
||||
virtual ~StackInterfaceWithCallType() {}
|
||||
|
||||
// Template parameter appears in function parameter.
|
||||
STDMETHOD_(void, Push)(const T& value) = 0;
|
||||
STDMETHOD_(void, Pop)() = 0;
|
||||
STDMETHOD_(int, GetSize)() const = 0;
|
||||
// Template parameter appears in function return type.
|
||||
STDMETHOD_(const T&, GetTop)() const = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class MockStackWithCallType : public StackInterfaceWithCallType<T> {
|
||||
public:
|
||||
MockStackWithCallType() {}
|
||||
|
||||
MOCK_METHOD(void, Push, (const T& elem),
|
||||
(Calltype(STDMETHODCALLTYPE), override));
|
||||
MOCK_METHOD(void, Pop, (), (Calltype(STDMETHODCALLTYPE), override));
|
||||
MOCK_METHOD(int, GetSize, (), (Calltype(STDMETHODCALLTYPE), override, const));
|
||||
MOCK_METHOD(const T&, GetTop, (),
|
||||
(Calltype(STDMETHODCALLTYPE), override, const));
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockStackWithCallType);
|
||||
};
|
||||
|
||||
// Tests that template mock with calltype works.
|
||||
TEST(MockMethodTemplateMockTestWithCallType, Works) {
|
||||
MockStackWithCallType<int> mock;
|
||||
|
||||
EXPECT_CALL(mock, GetSize())
|
||||
.WillOnce(Return(0))
|
||||
.WillOnce(Return(1))
|
||||
.WillOnce(Return(0));
|
||||
EXPECT_CALL(mock, Push(_));
|
||||
int n = 5;
|
||||
EXPECT_CALL(mock, GetTop())
|
||||
.WillOnce(ReturnRef(n));
|
||||
EXPECT_CALL(mock, Pop())
|
||||
.Times(AnyNumber());
|
||||
|
||||
EXPECT_EQ(0, mock.GetSize());
|
||||
mock.Push(5);
|
||||
EXPECT_EQ(1, mock.GetSize());
|
||||
EXPECT_EQ(5, mock.GetTop());
|
||||
mock.Pop();
|
||||
EXPECT_EQ(0, mock.GetSize());
|
||||
}
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
#define MY_MOCK_METHODS1_ \
|
||||
MOCK_METHOD(void, Overloaded, ()); \
|
||||
MOCK_METHOD(int, Overloaded, (int), (const)); \
|
||||
MOCK_METHOD(bool, Overloaded, (bool f, int n))
|
||||
|
||||
class MockOverloadedOnArgNumber {
|
||||
public:
|
||||
MockOverloadedOnArgNumber() {}
|
||||
|
||||
MY_MOCK_METHODS1_;
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockOverloadedOnArgNumber);
|
||||
};
|
||||
|
||||
TEST(MockMethodOverloadedMockMethodTest, CanOverloadOnArgNumberInMacroBody) {
|
||||
MockOverloadedOnArgNumber mock;
|
||||
EXPECT_CALL(mock, Overloaded());
|
||||
EXPECT_CALL(mock, Overloaded(1)).WillOnce(Return(2));
|
||||
EXPECT_CALL(mock, Overloaded(true, 1)).WillOnce(Return(true));
|
||||
|
||||
mock.Overloaded();
|
||||
EXPECT_EQ(2, mock.Overloaded(1));
|
||||
EXPECT_TRUE(mock.Overloaded(true, 1));
|
||||
}
|
||||
|
||||
#define MY_MOCK_METHODS2_ \
|
||||
MOCK_CONST_METHOD1(Overloaded, int(int n)); \
|
||||
MOCK_METHOD1(Overloaded, int(int n))
|
||||
|
||||
class MockOverloadedOnConstness {
|
||||
public:
|
||||
MockOverloadedOnConstness() {}
|
||||
|
||||
MY_MOCK_METHODS2_;
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockOverloadedOnConstness);
|
||||
};
|
||||
|
||||
TEST(MockMethodOverloadedMockMethodTest, CanOverloadOnConstnessInMacroBody) {
|
||||
MockOverloadedOnConstness mock;
|
||||
const MockOverloadedOnConstness* const_mock = &mock;
|
||||
EXPECT_CALL(mock, Overloaded(1)).WillOnce(Return(2));
|
||||
EXPECT_CALL(*const_mock, Overloaded(1)).WillOnce(Return(3));
|
||||
|
||||
EXPECT_EQ(2, mock.Overloaded(1));
|
||||
EXPECT_EQ(3, const_mock->Overloaded(1));
|
||||
}
|
||||
|
||||
TEST(MockMethodMockFunctionTest, WorksForVoidNullary) {
|
||||
MockFunction<void()> foo;
|
||||
EXPECT_CALL(foo, Call());
|
||||
foo.Call();
|
||||
}
|
||||
|
||||
TEST(MockMethodMockFunctionTest, WorksForNonVoidNullary) {
|
||||
MockFunction<int()> foo;
|
||||
EXPECT_CALL(foo, Call())
|
||||
.WillOnce(Return(1))
|
||||
.WillOnce(Return(2));
|
||||
EXPECT_EQ(1, foo.Call());
|
||||
EXPECT_EQ(2, foo.Call());
|
||||
}
|
||||
|
||||
TEST(MockMethodMockFunctionTest, WorksForVoidUnary) {
|
||||
MockFunction<void(int)> foo;
|
||||
EXPECT_CALL(foo, Call(1));
|
||||
foo.Call(1);
|
||||
}
|
||||
|
||||
TEST(MockMethodMockFunctionTest, WorksForNonVoidBinary) {
|
||||
MockFunction<int(bool, int)> foo;
|
||||
EXPECT_CALL(foo, Call(false, 42))
|
||||
.WillOnce(Return(1))
|
||||
.WillOnce(Return(2));
|
||||
EXPECT_CALL(foo, Call(true, Ge(100)))
|
||||
.WillOnce(Return(3));
|
||||
EXPECT_EQ(1, foo.Call(false, 42));
|
||||
EXPECT_EQ(2, foo.Call(false, 42));
|
||||
EXPECT_EQ(3, foo.Call(true, 120));
|
||||
}
|
||||
|
||||
TEST(MockMethodMockFunctionTest, WorksFor10Arguments) {
|
||||
MockFunction<int(bool a0, char a1, int a2, int a3, int a4,
|
||||
int a5, int a6, char a7, int a8, bool a9)> foo;
|
||||
EXPECT_CALL(foo, Call(_, 'a', _, _, _, _, _, _, _, _))
|
||||
.WillOnce(Return(1))
|
||||
.WillOnce(Return(2));
|
||||
EXPECT_EQ(1, foo.Call(false, 'a', 0, 0, 0, 0, 0, 'b', 0, true));
|
||||
EXPECT_EQ(2, foo.Call(true, 'a', 0, 0, 0, 0, 0, 'b', 1, false));
|
||||
}
|
||||
|
||||
TEST(MockMethodMockFunctionTest, AsStdFunction) {
|
||||
MockFunction<int(int)> foo;
|
||||
auto call = [](const std::function<int(int)> &f, int i) {
|
||||
return f(i);
|
||||
};
|
||||
EXPECT_CALL(foo, Call(1)).WillOnce(Return(-1));
|
||||
EXPECT_CALL(foo, Call(2)).WillOnce(Return(-2));
|
||||
EXPECT_EQ(-1, call(foo.AsStdFunction(), 1));
|
||||
EXPECT_EQ(-2, call(foo.AsStdFunction(), 2));
|
||||
}
|
||||
|
||||
TEST(MockMethodMockFunctionTest, AsStdFunctionReturnsReference) {
|
||||
MockFunction<int&()> foo;
|
||||
int value = 1;
|
||||
EXPECT_CALL(foo, Call()).WillOnce(ReturnRef(value));
|
||||
int& ref = foo.AsStdFunction()();
|
||||
EXPECT_EQ(1, ref);
|
||||
value = 2;
|
||||
EXPECT_EQ(2, ref);
|
||||
}
|
||||
|
||||
TEST(MockMethodMockFunctionTest, AsStdFunctionWithReferenceParameter) {
|
||||
MockFunction<int(int &)> foo;
|
||||
auto call = [](const std::function<int(int& )> &f, int &i) {
|
||||
return f(i);
|
||||
};
|
||||
int i = 42;
|
||||
EXPECT_CALL(foo, Call(i)).WillOnce(Return(-1));
|
||||
EXPECT_EQ(-1, call(foo.AsStdFunction(), i));
|
||||
}
|
||||
|
||||
|
||||
struct MockMethodSizes0 {
|
||||
MOCK_METHOD(void, func, ());
|
||||
};
|
||||
struct MockMethodSizes1 {
|
||||
MOCK_METHOD(void, func, (int));
|
||||
};
|
||||
struct MockMethodSizes2 {
|
||||
MOCK_METHOD(void, func, (int, int));
|
||||
};
|
||||
struct MockMethodSizes3 {
|
||||
MOCK_METHOD(void, func, (int, int, int));
|
||||
};
|
||||
struct MockMethodSizes4 {
|
||||
MOCK_METHOD(void, func, (int, int, int, int));
|
||||
};
|
||||
|
||||
TEST(MockMethodMockFunctionTest, MockMethodSizeOverhead) {
|
||||
EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes1));
|
||||
EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes2));
|
||||
EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes3));
|
||||
EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes4));
|
||||
}
|
||||
|
||||
} // namespace gmock_function_mocker_test
|
||||
} // namespace testing
|
@@ -1,659 +0,0 @@
|
||||
// Copyright 2007, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
// Google Mock - a framework for writing C++ mock classes.
|
||||
//
|
||||
// This file tests the function mocker classes.
|
||||
|
||||
#include "gmock/gmock-generated-function-mockers.h"
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
// MSDN says the header file to be included for STDMETHOD is BaseTyps.h but
|
||||
// we are getting compiler errors if we use basetyps.h, hence including
|
||||
// objbase.h for definition of STDMETHOD.
|
||||
# include <objbase.h>
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace testing {
|
||||
namespace gmock_generated_function_mockers_test {
|
||||
|
||||
using testing::_;
|
||||
using testing::A;
|
||||
using testing::An;
|
||||
using testing::AnyNumber;
|
||||
using testing::Const;
|
||||
using testing::DoDefault;
|
||||
using testing::Eq;
|
||||
using testing::Lt;
|
||||
using testing::MockFunction;
|
||||
using testing::Ref;
|
||||
using testing::Return;
|
||||
using testing::ReturnRef;
|
||||
using testing::TypedEq;
|
||||
|
||||
template<typename T>
|
||||
class TemplatedCopyable {
|
||||
public:
|
||||
TemplatedCopyable() {}
|
||||
|
||||
template <typename U>
|
||||
TemplatedCopyable(const U& other) {} // NOLINT
|
||||
};
|
||||
|
||||
class FooInterface {
|
||||
public:
|
||||
virtual ~FooInterface() {}
|
||||
|
||||
virtual void VoidReturning(int x) = 0;
|
||||
|
||||
virtual int Nullary() = 0;
|
||||
virtual bool Unary(int x) = 0;
|
||||
virtual long Binary(short x, int y) = 0; // NOLINT
|
||||
virtual int Decimal(bool b, char c, short d, int e, long f, // NOLINT
|
||||
float g, double h, unsigned i, char* j,
|
||||
const std::string& k) = 0;
|
||||
|
||||
virtual bool TakesNonConstReference(int& n) = 0; // NOLINT
|
||||
virtual std::string TakesConstReference(const int& n) = 0;
|
||||
virtual bool TakesConst(const int x) = 0;
|
||||
|
||||
virtual int OverloadedOnArgumentNumber() = 0;
|
||||
virtual int OverloadedOnArgumentNumber(int n) = 0;
|
||||
|
||||
virtual int OverloadedOnArgumentType(int n) = 0;
|
||||
virtual char OverloadedOnArgumentType(char c) = 0;
|
||||
|
||||
virtual int OverloadedOnConstness() = 0;
|
||||
virtual char OverloadedOnConstness() const = 0;
|
||||
|
||||
virtual int TypeWithHole(int (*func)()) = 0;
|
||||
virtual int TypeWithComma(const std::map<int, std::string>& a_map) = 0;
|
||||
virtual int TypeWithTemplatedCopyCtor(
|
||||
const TemplatedCopyable<int>& a_vector) = 0;
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
STDMETHOD_(int, CTNullary)() = 0;
|
||||
STDMETHOD_(bool, CTUnary)(int x) = 0;
|
||||
STDMETHOD_(int, CTDecimal)
|
||||
(bool b, char c, short d, int e, long f, // NOLINT
|
||||
float g, double h, unsigned i, char* j, const std::string& k) = 0;
|
||||
STDMETHOD_(char, CTConst)(int x) const = 0;
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
};
|
||||
|
||||
// Const qualifiers on arguments were once (incorrectly) considered
|
||||
// significant in determining whether two virtual functions had the same
|
||||
// signature. This was fixed in Visual Studio 2008. However, the compiler
|
||||
// still emits a warning that alerts about this change in behavior.
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4373)
|
||||
#endif
|
||||
class MockFoo : public FooInterface {
|
||||
public:
|
||||
MockFoo() {}
|
||||
|
||||
// Makes sure that a mock function parameter can be named.
|
||||
MOCK_METHOD1(VoidReturning, void(int n)); // NOLINT
|
||||
|
||||
MOCK_METHOD0(Nullary, int()); // NOLINT
|
||||
|
||||
// Makes sure that a mock function parameter can be unnamed.
|
||||
MOCK_METHOD1(Unary, bool(int)); // NOLINT
|
||||
MOCK_METHOD2(Binary, long(short, int)); // NOLINT
|
||||
MOCK_METHOD10(Decimal, int(bool, char, short, int, long, float, // NOLINT
|
||||
double, unsigned, char*, const std::string& str));
|
||||
|
||||
MOCK_METHOD1(TakesNonConstReference, bool(int&)); // NOLINT
|
||||
MOCK_METHOD1(TakesConstReference, std::string(const int&));
|
||||
MOCK_METHOD1(TakesConst, bool(const int)); // NOLINT
|
||||
|
||||
// Tests that the function return type can contain unprotected comma.
|
||||
MOCK_METHOD0(ReturnTypeWithComma, std::map<int, std::string>());
|
||||
MOCK_CONST_METHOD1(ReturnTypeWithComma,
|
||||
std::map<int, std::string>(int)); // NOLINT
|
||||
|
||||
MOCK_METHOD0(OverloadedOnArgumentNumber, int()); // NOLINT
|
||||
MOCK_METHOD1(OverloadedOnArgumentNumber, int(int)); // NOLINT
|
||||
|
||||
MOCK_METHOD1(OverloadedOnArgumentType, int(int)); // NOLINT
|
||||
MOCK_METHOD1(OverloadedOnArgumentType, char(char)); // NOLINT
|
||||
|
||||
MOCK_METHOD0(OverloadedOnConstness, int()); // NOLINT
|
||||
MOCK_CONST_METHOD0(OverloadedOnConstness, char()); // NOLINT
|
||||
|
||||
MOCK_METHOD1(TypeWithHole, int(int (*)())); // NOLINT
|
||||
MOCK_METHOD1(TypeWithComma,
|
||||
int(const std::map<int, std::string>&)); // NOLINT
|
||||
MOCK_METHOD1(TypeWithTemplatedCopyCtor,
|
||||
int(const TemplatedCopyable<int>&)); // NOLINT
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, CTNullary, int());
|
||||
MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, CTUnary, bool(int));
|
||||
MOCK_METHOD10_WITH_CALLTYPE(STDMETHODCALLTYPE, CTDecimal,
|
||||
int(bool b, char c, short d, int e, long f,
|
||||
float g, double h, unsigned i, char* j,
|
||||
const std::string& k));
|
||||
MOCK_CONST_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, CTConst, char(int));
|
||||
|
||||
// Tests that the function return type can contain unprotected comma.
|
||||
MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, CTReturnTypeWithComma,
|
||||
std::map<int, std::string>());
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFoo);
|
||||
};
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
class FunctionMockerTest : public testing::Test {
|
||||
protected:
|
||||
FunctionMockerTest() : foo_(&mock_foo_) {}
|
||||
|
||||
FooInterface* const foo_;
|
||||
MockFoo mock_foo_;
|
||||
};
|
||||
|
||||
// Tests mocking a void-returning function.
|
||||
TEST_F(FunctionMockerTest, MocksVoidFunction) {
|
||||
EXPECT_CALL(mock_foo_, VoidReturning(Lt(100)));
|
||||
foo_->VoidReturning(0);
|
||||
}
|
||||
|
||||
// Tests mocking a nullary function.
|
||||
TEST_F(FunctionMockerTest, MocksNullaryFunction) {
|
||||
EXPECT_CALL(mock_foo_, Nullary())
|
||||
.WillOnce(DoDefault())
|
||||
.WillOnce(Return(1));
|
||||
|
||||
EXPECT_EQ(0, foo_->Nullary());
|
||||
EXPECT_EQ(1, foo_->Nullary());
|
||||
}
|
||||
|
||||
// Tests mocking a unary function.
|
||||
TEST_F(FunctionMockerTest, MocksUnaryFunction) {
|
||||
EXPECT_CALL(mock_foo_, Unary(Eq(2)))
|
||||
.Times(2)
|
||||
.WillOnce(Return(true));
|
||||
|
||||
EXPECT_TRUE(foo_->Unary(2));
|
||||
EXPECT_FALSE(foo_->Unary(2));
|
||||
}
|
||||
|
||||
// Tests mocking a binary function.
|
||||
TEST_F(FunctionMockerTest, MocksBinaryFunction) {
|
||||
EXPECT_CALL(mock_foo_, Binary(2, _))
|
||||
.WillOnce(Return(3));
|
||||
|
||||
EXPECT_EQ(3, foo_->Binary(2, 1));
|
||||
}
|
||||
|
||||
// Tests mocking a decimal function.
|
||||
TEST_F(FunctionMockerTest, MocksDecimalFunction) {
|
||||
EXPECT_CALL(mock_foo_, Decimal(true, 'a', 0, 0, 1L, A<float>(), Lt(100), 5U,
|
||||
nullptr, "hi"))
|
||||
.WillOnce(Return(5));
|
||||
|
||||
EXPECT_EQ(5, foo_->Decimal(true, 'a', 0, 0, 1, 0, 0, 5, nullptr, "hi"));
|
||||
}
|
||||
|
||||
// Tests mocking a function that takes a non-const reference.
|
||||
TEST_F(FunctionMockerTest, MocksFunctionWithNonConstReferenceArgument) {
|
||||
int a = 0;
|
||||
EXPECT_CALL(mock_foo_, TakesNonConstReference(Ref(a)))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
EXPECT_TRUE(foo_->TakesNonConstReference(a));
|
||||
}
|
||||
|
||||
// Tests mocking a function that takes a const reference.
|
||||
TEST_F(FunctionMockerTest, MocksFunctionWithConstReferenceArgument) {
|
||||
int a = 0;
|
||||
EXPECT_CALL(mock_foo_, TakesConstReference(Ref(a)))
|
||||
.WillOnce(Return("Hello"));
|
||||
|
||||
EXPECT_EQ("Hello", foo_->TakesConstReference(a));
|
||||
}
|
||||
|
||||
// Tests mocking a function that takes a const variable.
|
||||
TEST_F(FunctionMockerTest, MocksFunctionWithConstArgument) {
|
||||
EXPECT_CALL(mock_foo_, TakesConst(Lt(10)))
|
||||
.WillOnce(DoDefault());
|
||||
|
||||
EXPECT_FALSE(foo_->TakesConst(5));
|
||||
}
|
||||
|
||||
// Tests mocking functions overloaded on the number of arguments.
|
||||
TEST_F(FunctionMockerTest, MocksFunctionsOverloadedOnArgumentNumber) {
|
||||
EXPECT_CALL(mock_foo_, OverloadedOnArgumentNumber())
|
||||
.WillOnce(Return(1));
|
||||
EXPECT_CALL(mock_foo_, OverloadedOnArgumentNumber(_))
|
||||
.WillOnce(Return(2));
|
||||
|
||||
EXPECT_EQ(2, foo_->OverloadedOnArgumentNumber(1));
|
||||
EXPECT_EQ(1, foo_->OverloadedOnArgumentNumber());
|
||||
}
|
||||
|
||||
// Tests mocking functions overloaded on the types of argument.
|
||||
TEST_F(FunctionMockerTest, MocksFunctionsOverloadedOnArgumentType) {
|
||||
EXPECT_CALL(mock_foo_, OverloadedOnArgumentType(An<int>()))
|
||||
.WillOnce(Return(1));
|
||||
EXPECT_CALL(mock_foo_, OverloadedOnArgumentType(TypedEq<char>('a')))
|
||||
.WillOnce(Return('b'));
|
||||
|
||||
EXPECT_EQ(1, foo_->OverloadedOnArgumentType(0));
|
||||
EXPECT_EQ('b', foo_->OverloadedOnArgumentType('a'));
|
||||
}
|
||||
|
||||
// Tests mocking functions overloaded on the const-ness of this object.
|
||||
TEST_F(FunctionMockerTest, MocksFunctionsOverloadedOnConstnessOfThis) {
|
||||
EXPECT_CALL(mock_foo_, OverloadedOnConstness());
|
||||
EXPECT_CALL(Const(mock_foo_), OverloadedOnConstness())
|
||||
.WillOnce(Return('a'));
|
||||
|
||||
EXPECT_EQ(0, foo_->OverloadedOnConstness());
|
||||
EXPECT_EQ('a', Const(*foo_).OverloadedOnConstness());
|
||||
}
|
||||
|
||||
TEST_F(FunctionMockerTest, MocksReturnTypeWithComma) {
|
||||
const std::map<int, std::string> a_map;
|
||||
EXPECT_CALL(mock_foo_, ReturnTypeWithComma())
|
||||
.WillOnce(Return(a_map));
|
||||
EXPECT_CALL(mock_foo_, ReturnTypeWithComma(42))
|
||||
.WillOnce(Return(a_map));
|
||||
|
||||
EXPECT_EQ(a_map, mock_foo_.ReturnTypeWithComma());
|
||||
EXPECT_EQ(a_map, mock_foo_.ReturnTypeWithComma(42));
|
||||
}
|
||||
|
||||
TEST_F(FunctionMockerTest, MocksTypeWithTemplatedCopyCtor) {
|
||||
EXPECT_CALL(mock_foo_, TypeWithTemplatedCopyCtor(_)).WillOnce(Return(true));
|
||||
EXPECT_TRUE(foo_->TypeWithTemplatedCopyCtor(TemplatedCopyable<int>()));
|
||||
}
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
// Tests mocking a nullary function with calltype.
|
||||
TEST_F(FunctionMockerTest, MocksNullaryFunctionWithCallType) {
|
||||
EXPECT_CALL(mock_foo_, CTNullary())
|
||||
.WillOnce(Return(-1))
|
||||
.WillOnce(Return(0));
|
||||
|
||||
EXPECT_EQ(-1, foo_->CTNullary());
|
||||
EXPECT_EQ(0, foo_->CTNullary());
|
||||
}
|
||||
|
||||
// Tests mocking a unary function with calltype.
|
||||
TEST_F(FunctionMockerTest, MocksUnaryFunctionWithCallType) {
|
||||
EXPECT_CALL(mock_foo_, CTUnary(Eq(2)))
|
||||
.Times(2)
|
||||
.WillOnce(Return(true))
|
||||
.WillOnce(Return(false));
|
||||
|
||||
EXPECT_TRUE(foo_->CTUnary(2));
|
||||
EXPECT_FALSE(foo_->CTUnary(2));
|
||||
}
|
||||
|
||||
// Tests mocking a decimal function with calltype.
|
||||
TEST_F(FunctionMockerTest, MocksDecimalFunctionWithCallType) {
|
||||
EXPECT_CALL(mock_foo_, CTDecimal(true, 'a', 0, 0, 1L, A<float>(), Lt(100), 5U,
|
||||
nullptr, "hi"))
|
||||
.WillOnce(Return(10));
|
||||
|
||||
EXPECT_EQ(10, foo_->CTDecimal(true, 'a', 0, 0, 1, 0, 0, 5, nullptr, "hi"));
|
||||
}
|
||||
|
||||
// Tests mocking functions overloaded on the const-ness of this object.
|
||||
TEST_F(FunctionMockerTest, MocksFunctionsConstFunctionWithCallType) {
|
||||
EXPECT_CALL(Const(mock_foo_), CTConst(_))
|
||||
.WillOnce(Return('a'));
|
||||
|
||||
EXPECT_EQ('a', Const(*foo_).CTConst(0));
|
||||
}
|
||||
|
||||
TEST_F(FunctionMockerTest, MocksReturnTypeWithCommaAndCallType) {
|
||||
const std::map<int, std::string> a_map;
|
||||
EXPECT_CALL(mock_foo_, CTReturnTypeWithComma())
|
||||
.WillOnce(Return(a_map));
|
||||
|
||||
EXPECT_EQ(a_map, mock_foo_.CTReturnTypeWithComma());
|
||||
}
|
||||
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
class MockB {
|
||||
public:
|
||||
MockB() {}
|
||||
|
||||
MOCK_METHOD0(DoB, void());
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockB);
|
||||
};
|
||||
|
||||
// Tests that functions with no EXPECT_CALL() ruls can be called any
|
||||
// number of times.
|
||||
TEST(ExpectCallTest, UnmentionedFunctionCanBeCalledAnyNumberOfTimes) {
|
||||
{
|
||||
MockB b;
|
||||
}
|
||||
|
||||
{
|
||||
MockB b;
|
||||
b.DoB();
|
||||
}
|
||||
|
||||
{
|
||||
MockB b;
|
||||
b.DoB();
|
||||
b.DoB();
|
||||
}
|
||||
}
|
||||
|
||||
// Tests mocking template interfaces.
|
||||
|
||||
template <typename T>
|
||||
class StackInterface {
|
||||
public:
|
||||
virtual ~StackInterface() {}
|
||||
|
||||
// Template parameter appears in function parameter.
|
||||
virtual void Push(const T& value) = 0;
|
||||
virtual void Pop() = 0;
|
||||
virtual int GetSize() const = 0;
|
||||
// Template parameter appears in function return type.
|
||||
virtual const T& GetTop() const = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class MockStack : public StackInterface<T> {
|
||||
public:
|
||||
MockStack() {}
|
||||
|
||||
MOCK_METHOD1_T(Push, void(const T& elem));
|
||||
MOCK_METHOD0_T(Pop, void());
|
||||
MOCK_CONST_METHOD0_T(GetSize, int()); // NOLINT
|
||||
MOCK_CONST_METHOD0_T(GetTop, const T&());
|
||||
|
||||
// Tests that the function return type can contain unprotected comma.
|
||||
MOCK_METHOD0_T(ReturnTypeWithComma, std::map<int, int>());
|
||||
MOCK_CONST_METHOD1_T(ReturnTypeWithComma, std::map<int, int>(int)); // NOLINT
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockStack);
|
||||
};
|
||||
|
||||
// Tests that template mock works.
|
||||
TEST(TemplateMockTest, Works) {
|
||||
MockStack<int> mock;
|
||||
|
||||
EXPECT_CALL(mock, GetSize())
|
||||
.WillOnce(Return(0))
|
||||
.WillOnce(Return(1))
|
||||
.WillOnce(Return(0));
|
||||
EXPECT_CALL(mock, Push(_));
|
||||
int n = 5;
|
||||
EXPECT_CALL(mock, GetTop())
|
||||
.WillOnce(ReturnRef(n));
|
||||
EXPECT_CALL(mock, Pop())
|
||||
.Times(AnyNumber());
|
||||
|
||||
EXPECT_EQ(0, mock.GetSize());
|
||||
mock.Push(5);
|
||||
EXPECT_EQ(1, mock.GetSize());
|
||||
EXPECT_EQ(5, mock.GetTop());
|
||||
mock.Pop();
|
||||
EXPECT_EQ(0, mock.GetSize());
|
||||
}
|
||||
|
||||
TEST(TemplateMockTest, MethodWithCommaInReturnTypeWorks) {
|
||||
MockStack<int> mock;
|
||||
|
||||
const std::map<int, int> a_map;
|
||||
EXPECT_CALL(mock, ReturnTypeWithComma())
|
||||
.WillOnce(Return(a_map));
|
||||
EXPECT_CALL(mock, ReturnTypeWithComma(1))
|
||||
.WillOnce(Return(a_map));
|
||||
|
||||
EXPECT_EQ(a_map, mock.ReturnTypeWithComma());
|
||||
EXPECT_EQ(a_map, mock.ReturnTypeWithComma(1));
|
||||
}
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
// Tests mocking template interfaces with calltype.
|
||||
|
||||
template <typename T>
|
||||
class StackInterfaceWithCallType {
|
||||
public:
|
||||
virtual ~StackInterfaceWithCallType() {}
|
||||
|
||||
// Template parameter appears in function parameter.
|
||||
STDMETHOD_(void, Push)(const T& value) = 0;
|
||||
STDMETHOD_(void, Pop)() = 0;
|
||||
STDMETHOD_(int, GetSize)() const = 0;
|
||||
// Template parameter appears in function return type.
|
||||
STDMETHOD_(const T&, GetTop)() const = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class MockStackWithCallType : public StackInterfaceWithCallType<T> {
|
||||
public:
|
||||
MockStackWithCallType() {}
|
||||
|
||||
MOCK_METHOD1_T_WITH_CALLTYPE(STDMETHODCALLTYPE, Push, void(const T& elem));
|
||||
MOCK_METHOD0_T_WITH_CALLTYPE(STDMETHODCALLTYPE, Pop, void());
|
||||
MOCK_CONST_METHOD0_T_WITH_CALLTYPE(STDMETHODCALLTYPE, GetSize, int());
|
||||
MOCK_CONST_METHOD0_T_WITH_CALLTYPE(STDMETHODCALLTYPE, GetTop, const T&());
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockStackWithCallType);
|
||||
};
|
||||
|
||||
// Tests that template mock with calltype works.
|
||||
TEST(TemplateMockTestWithCallType, Works) {
|
||||
MockStackWithCallType<int> mock;
|
||||
|
||||
EXPECT_CALL(mock, GetSize())
|
||||
.WillOnce(Return(0))
|
||||
.WillOnce(Return(1))
|
||||
.WillOnce(Return(0));
|
||||
EXPECT_CALL(mock, Push(_));
|
||||
int n = 5;
|
||||
EXPECT_CALL(mock, GetTop())
|
||||
.WillOnce(ReturnRef(n));
|
||||
EXPECT_CALL(mock, Pop())
|
||||
.Times(AnyNumber());
|
||||
|
||||
EXPECT_EQ(0, mock.GetSize());
|
||||
mock.Push(5);
|
||||
EXPECT_EQ(1, mock.GetSize());
|
||||
EXPECT_EQ(5, mock.GetTop());
|
||||
mock.Pop();
|
||||
EXPECT_EQ(0, mock.GetSize());
|
||||
}
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
#define MY_MOCK_METHODS1_ \
|
||||
MOCK_METHOD0(Overloaded, void()); \
|
||||
MOCK_CONST_METHOD1(Overloaded, int(int n)); \
|
||||
MOCK_METHOD2(Overloaded, bool(bool f, int n))
|
||||
|
||||
class MockOverloadedOnArgNumber {
|
||||
public:
|
||||
MockOverloadedOnArgNumber() {}
|
||||
|
||||
MY_MOCK_METHODS1_;
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockOverloadedOnArgNumber);
|
||||
};
|
||||
|
||||
TEST(OverloadedMockMethodTest, CanOverloadOnArgNumberInMacroBody) {
|
||||
MockOverloadedOnArgNumber mock;
|
||||
EXPECT_CALL(mock, Overloaded());
|
||||
EXPECT_CALL(mock, Overloaded(1)).WillOnce(Return(2));
|
||||
EXPECT_CALL(mock, Overloaded(true, 1)).WillOnce(Return(true));
|
||||
|
||||
mock.Overloaded();
|
||||
EXPECT_EQ(2, mock.Overloaded(1));
|
||||
EXPECT_TRUE(mock.Overloaded(true, 1));
|
||||
}
|
||||
|
||||
#define MY_MOCK_METHODS2_ \
|
||||
MOCK_CONST_METHOD1(Overloaded, int(int n)); \
|
||||
MOCK_METHOD1(Overloaded, int(int n))
|
||||
|
||||
class MockOverloadedOnConstness {
|
||||
public:
|
||||
MockOverloadedOnConstness() {}
|
||||
|
||||
MY_MOCK_METHODS2_;
|
||||
|
||||
private:
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockOverloadedOnConstness);
|
||||
};
|
||||
|
||||
TEST(OverloadedMockMethodTest, CanOverloadOnConstnessInMacroBody) {
|
||||
MockOverloadedOnConstness mock;
|
||||
const MockOverloadedOnConstness* const_mock = &mock;
|
||||
EXPECT_CALL(mock, Overloaded(1)).WillOnce(Return(2));
|
||||
EXPECT_CALL(*const_mock, Overloaded(1)).WillOnce(Return(3));
|
||||
|
||||
EXPECT_EQ(2, mock.Overloaded(1));
|
||||
EXPECT_EQ(3, const_mock->Overloaded(1));
|
||||
}
|
||||
|
||||
TEST(MockFunctionTest, WorksForVoidNullary) {
|
||||
MockFunction<void()> foo;
|
||||
EXPECT_CALL(foo, Call());
|
||||
foo.Call();
|
||||
}
|
||||
|
||||
TEST(MockFunctionTest, WorksForNonVoidNullary) {
|
||||
MockFunction<int()> foo;
|
||||
EXPECT_CALL(foo, Call())
|
||||
.WillOnce(Return(1))
|
||||
.WillOnce(Return(2));
|
||||
EXPECT_EQ(1, foo.Call());
|
||||
EXPECT_EQ(2, foo.Call());
|
||||
}
|
||||
|
||||
TEST(MockFunctionTest, WorksForVoidUnary) {
|
||||
MockFunction<void(int)> foo;
|
||||
EXPECT_CALL(foo, Call(1));
|
||||
foo.Call(1);
|
||||
}
|
||||
|
||||
TEST(MockFunctionTest, WorksForNonVoidBinary) {
|
||||
MockFunction<int(bool, int)> foo;
|
||||
EXPECT_CALL(foo, Call(false, 42))
|
||||
.WillOnce(Return(1))
|
||||
.WillOnce(Return(2));
|
||||
EXPECT_CALL(foo, Call(true, Ge(100)))
|
||||
.WillOnce(Return(3));
|
||||
EXPECT_EQ(1, foo.Call(false, 42));
|
||||
EXPECT_EQ(2, foo.Call(false, 42));
|
||||
EXPECT_EQ(3, foo.Call(true, 120));
|
||||
}
|
||||
|
||||
TEST(MockFunctionTest, WorksFor10Arguments) {
|
||||
MockFunction<int(bool a0, char a1, int a2, int a3, int a4,
|
||||
int a5, int a6, char a7, int a8, bool a9)> foo;
|
||||
EXPECT_CALL(foo, Call(_, 'a', _, _, _, _, _, _, _, _))
|
||||
.WillOnce(Return(1))
|
||||
.WillOnce(Return(2));
|
||||
EXPECT_EQ(1, foo.Call(false, 'a', 0, 0, 0, 0, 0, 'b', 0, true));
|
||||
EXPECT_EQ(2, foo.Call(true, 'a', 0, 0, 0, 0, 0, 'b', 1, false));
|
||||
}
|
||||
|
||||
TEST(MockFunctionTest, AsStdFunction) {
|
||||
MockFunction<int(int)> foo;
|
||||
auto call = [](const std::function<int(int)> &f, int i) {
|
||||
return f(i);
|
||||
};
|
||||
EXPECT_CALL(foo, Call(1)).WillOnce(Return(-1));
|
||||
EXPECT_CALL(foo, Call(2)).WillOnce(Return(-2));
|
||||
EXPECT_EQ(-1, call(foo.AsStdFunction(), 1));
|
||||
EXPECT_EQ(-2, call(foo.AsStdFunction(), 2));
|
||||
}
|
||||
|
||||
TEST(MockFunctionTest, AsStdFunctionReturnsReference) {
|
||||
MockFunction<int&()> foo;
|
||||
int value = 1;
|
||||
EXPECT_CALL(foo, Call()).WillOnce(ReturnRef(value));
|
||||
int& ref = foo.AsStdFunction()();
|
||||
EXPECT_EQ(1, ref);
|
||||
value = 2;
|
||||
EXPECT_EQ(2, ref);
|
||||
}
|
||||
|
||||
TEST(MockFunctionTest, AsStdFunctionWithReferenceParameter) {
|
||||
MockFunction<int(int &)> foo;
|
||||
auto call = [](const std::function<int(int& )> &f, int &i) {
|
||||
return f(i);
|
||||
};
|
||||
int i = 42;
|
||||
EXPECT_CALL(foo, Call(i)).WillOnce(Return(-1));
|
||||
EXPECT_EQ(-1, call(foo.AsStdFunction(), i));
|
||||
}
|
||||
|
||||
|
||||
struct MockMethodSizes0 {
|
||||
MOCK_METHOD0(func, void());
|
||||
};
|
||||
struct MockMethodSizes1 {
|
||||
MOCK_METHOD1(func, void(int));
|
||||
};
|
||||
struct MockMethodSizes2 {
|
||||
MOCK_METHOD2(func, void(int, int));
|
||||
};
|
||||
struct MockMethodSizes3 {
|
||||
MOCK_METHOD3(func, void(int, int, int));
|
||||
};
|
||||
struct MockMethodSizes4 {
|
||||
MOCK_METHOD4(func, void(int, int, int, int));
|
||||
};
|
||||
|
||||
TEST(MockFunctionTest, MockMethodSizeOverhead) {
|
||||
EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes1));
|
||||
EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes2));
|
||||
EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes3));
|
||||
EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes4));
|
||||
}
|
||||
|
||||
} // namespace gmock_generated_function_mockers_test
|
||||
} // namespace testing
|
File diff suppressed because it is too large
Load Diff
@@ -1,698 +0,0 @@
|
||||
// Copyright 2007, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
// Google Mock - a framework for writing C++ mock classes.
|
||||
//
|
||||
// This file tests the built-in actions in gmock-more-actions.h.
|
||||
|
||||
#include "gmock/gmock-more-actions.h"
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace testing {
|
||||
namespace gmock_more_actions_test {
|
||||
|
||||
using ::std::plus;
|
||||
using ::std::string;
|
||||
using testing::_;
|
||||
using testing::Action;
|
||||
using testing::ActionInterface;
|
||||
using testing::DeleteArg;
|
||||
using testing::Invoke;
|
||||
using testing::Return;
|
||||
using testing::ReturnArg;
|
||||
using testing::ReturnPointee;
|
||||
using testing::SaveArg;
|
||||
using testing::SaveArgPointee;
|
||||
using testing::SetArgReferee;
|
||||
using testing::Unused;
|
||||
using testing::WithArg;
|
||||
using testing::WithoutArgs;
|
||||
|
||||
// For suppressing compiler warnings on conversion possibly losing precision.
|
||||
inline short Short(short n) { return n; } // NOLINT
|
||||
inline char Char(char ch) { return ch; }
|
||||
|
||||
// Sample functions and functors for testing Invoke() and etc.
|
||||
int Nullary() { return 1; }
|
||||
|
||||
class NullaryFunctor {
|
||||
public:
|
||||
int operator()() { return 2; }
|
||||
};
|
||||
|
||||
bool g_done = false;
|
||||
void VoidNullary() { g_done = true; }
|
||||
|
||||
class VoidNullaryFunctor {
|
||||
public:
|
||||
void operator()() { g_done = true; }
|
||||
};
|
||||
|
||||
bool Unary(int x) { return x < 0; }
|
||||
|
||||
const char* Plus1(const char* s) { return s + 1; }
|
||||
|
||||
void VoidUnary(int /* n */) { g_done = true; }
|
||||
|
||||
bool ByConstRef(const std::string& s) { return s == "Hi"; }
|
||||
|
||||
const double g_double = 0;
|
||||
bool ReferencesGlobalDouble(const double& x) { return &x == &g_double; }
|
||||
|
||||
std::string ByNonConstRef(std::string& s) { return s += "+"; } // NOLINT
|
||||
|
||||
struct UnaryFunctor {
|
||||
int operator()(bool x) { return x ? 1 : -1; }
|
||||
};
|
||||
|
||||
const char* Binary(const char* input, short n) { return input + n; } // NOLINT
|
||||
|
||||
void VoidBinary(int, char) { g_done = true; }
|
||||
|
||||
int Ternary(int x, char y, short z) { return x + y + z; } // NOLINT
|
||||
|
||||
void VoidTernary(int, char, bool) { g_done = true; }
|
||||
|
||||
int SumOf4(int a, int b, int c, int d) { return a + b + c + d; }
|
||||
|
||||
int SumOfFirst2(int a, int b, Unused, Unused) { return a + b; }
|
||||
|
||||
void VoidFunctionWithFourArguments(char, int, float, double) { g_done = true; }
|
||||
|
||||
std::string Concat4(const char* s1, const char* s2, const char* s3,
|
||||
const char* s4) {
|
||||
return std::string(s1) + s2 + s3 + s4;
|
||||
}
|
||||
|
||||
int SumOf5(int a, int b, int c, int d, int e) { return a + b + c + d + e; }
|
||||
|
||||
struct SumOf5Functor {
|
||||
int operator()(int a, int b, int c, int d, int e) {
|
||||
return a + b + c + d + e;
|
||||
}
|
||||
};
|
||||
|
||||
std::string Concat5(const char* s1, const char* s2, const char* s3,
|
||||
const char* s4, const char* s5) {
|
||||
return std::string(s1) + s2 + s3 + s4 + s5;
|
||||
}
|
||||
|
||||
int SumOf6(int a, int b, int c, int d, int e, int f) {
|
||||
return a + b + c + d + e + f;
|
||||
}
|
||||
|
||||
struct SumOf6Functor {
|
||||
int operator()(int a, int b, int c, int d, int e, int f) {
|
||||
return a + b + c + d + e + f;
|
||||
}
|
||||
};
|
||||
|
||||
std::string Concat6(const char* s1, const char* s2, const char* s3,
|
||||
const char* s4, const char* s5, const char* s6) {
|
||||
return std::string(s1) + s2 + s3 + s4 + s5 + s6;
|
||||
}
|
||||
|
||||
std::string Concat7(const char* s1, const char* s2, const char* s3,
|
||||
const char* s4, const char* s5, const char* s6,
|
||||
const char* s7) {
|
||||
return std::string(s1) + s2 + s3 + s4 + s5 + s6 + s7;
|
||||
}
|
||||
|
||||
std::string Concat8(const char* s1, const char* s2, const char* s3,
|
||||
const char* s4, const char* s5, const char* s6,
|
||||
const char* s7, const char* s8) {
|
||||
return std::string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8;
|
||||
}
|
||||
|
||||
std::string Concat9(const char* s1, const char* s2, const char* s3,
|
||||
const char* s4, const char* s5, const char* s6,
|
||||
const char* s7, const char* s8, const char* s9) {
|
||||
return std::string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9;
|
||||
}
|
||||
|
||||
std::string Concat10(const char* s1, const char* s2, const char* s3,
|
||||
const char* s4, const char* s5, const char* s6,
|
||||
const char* s7, const char* s8, const char* s9,
|
||||
const char* s10) {
|
||||
return std::string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10;
|
||||
}
|
||||
|
||||
class Foo {
|
||||
public:
|
||||
Foo() : value_(123) {}
|
||||
|
||||
int Nullary() const { return value_; }
|
||||
|
||||
short Unary(long x) { return static_cast<short>(value_ + x); } // NOLINT
|
||||
|
||||
std::string Binary(const std::string& str, char c) const { return str + c; }
|
||||
|
||||
int Ternary(int x, bool y, char z) { return value_ + x + y*z; }
|
||||
|
||||
int SumOf4(int a, int b, int c, int d) const {
|
||||
return a + b + c + d + value_;
|
||||
}
|
||||
|
||||
int SumOfLast2(Unused, Unused, int a, int b) const { return a + b; }
|
||||
|
||||
int SumOf5(int a, int b, int c, int d, int e) { return a + b + c + d + e; }
|
||||
|
||||
int SumOf6(int a, int b, int c, int d, int e, int f) {
|
||||
return a + b + c + d + e + f;
|
||||
}
|
||||
|
||||
std::string Concat7(const char* s1, const char* s2, const char* s3,
|
||||
const char* s4, const char* s5, const char* s6,
|
||||
const char* s7) {
|
||||
return std::string(s1) + s2 + s3 + s4 + s5 + s6 + s7;
|
||||
}
|
||||
|
||||
std::string Concat8(const char* s1, const char* s2, const char* s3,
|
||||
const char* s4, const char* s5, const char* s6,
|
||||
const char* s7, const char* s8) {
|
||||
return std::string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8;
|
||||
}
|
||||
|
||||
std::string Concat9(const char* s1, const char* s2, const char* s3,
|
||||
const char* s4, const char* s5, const char* s6,
|
||||
const char* s7, const char* s8, const char* s9) {
|
||||
return std::string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9;
|
||||
}
|
||||
|
||||
std::string Concat10(const char* s1, const char* s2, const char* s3,
|
||||
const char* s4, const char* s5, const char* s6,
|
||||
const char* s7, const char* s8, const char* s9,
|
||||
const char* s10) {
|
||||
return std::string(s1) + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10;
|
||||
}
|
||||
|
||||
private:
|
||||
int value_;
|
||||
};
|
||||
|
||||
// Tests using Invoke() with a nullary function.
|
||||
TEST(InvokeTest, Nullary) {
|
||||
Action<int()> a = Invoke(Nullary); // NOLINT
|
||||
EXPECT_EQ(1, a.Perform(std::make_tuple()));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a unary function.
|
||||
TEST(InvokeTest, Unary) {
|
||||
Action<bool(int)> a = Invoke(Unary); // NOLINT
|
||||
EXPECT_FALSE(a.Perform(std::make_tuple(1)));
|
||||
EXPECT_TRUE(a.Perform(std::make_tuple(-1)));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a binary function.
|
||||
TEST(InvokeTest, Binary) {
|
||||
Action<const char*(const char*, short)> a = Invoke(Binary); // NOLINT
|
||||
const char* p = "Hello";
|
||||
EXPECT_EQ(p + 2, a.Perform(std::make_tuple(p, Short(2))));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a ternary function.
|
||||
TEST(InvokeTest, Ternary) {
|
||||
Action<int(int, char, short)> a = Invoke(Ternary); // NOLINT
|
||||
EXPECT_EQ(6, a.Perform(std::make_tuple(1, '\2', Short(3))));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a 4-argument function.
|
||||
TEST(InvokeTest, FunctionThatTakes4Arguments) {
|
||||
Action<int(int, int, int, int)> a = Invoke(SumOf4); // NOLINT
|
||||
EXPECT_EQ(1234, a.Perform(std::make_tuple(1000, 200, 30, 4)));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a 5-argument function.
|
||||
TEST(InvokeTest, FunctionThatTakes5Arguments) {
|
||||
Action<int(int, int, int, int, int)> a = Invoke(SumOf5); // NOLINT
|
||||
EXPECT_EQ(12345, a.Perform(std::make_tuple(10000, 2000, 300, 40, 5)));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a 6-argument function.
|
||||
TEST(InvokeTest, FunctionThatTakes6Arguments) {
|
||||
Action<int(int, int, int, int, int, int)> a = Invoke(SumOf6); // NOLINT
|
||||
EXPECT_EQ(123456,
|
||||
a.Perform(std::make_tuple(100000, 20000, 3000, 400, 50, 6)));
|
||||
}
|
||||
|
||||
// A helper that turns the type of a C-string literal from const
|
||||
// char[N] to const char*.
|
||||
inline const char* CharPtr(const char* s) { return s; }
|
||||
|
||||
// Tests using Invoke() with a 7-argument function.
|
||||
TEST(InvokeTest, FunctionThatTakes7Arguments) {
|
||||
Action<std::string(const char*, const char*, const char*, const char*,
|
||||
const char*, const char*, const char*)>
|
||||
a = Invoke(Concat7);
|
||||
EXPECT_EQ("1234567",
|
||||
a.Perform(std::make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
||||
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
||||
CharPtr("7"))));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a 8-argument function.
|
||||
TEST(InvokeTest, FunctionThatTakes8Arguments) {
|
||||
Action<std::string(const char*, const char*, const char*, const char*,
|
||||
const char*, const char*, const char*, const char*)>
|
||||
a = Invoke(Concat8);
|
||||
EXPECT_EQ("12345678",
|
||||
a.Perform(std::make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
||||
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
||||
CharPtr("7"), CharPtr("8"))));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a 9-argument function.
|
||||
TEST(InvokeTest, FunctionThatTakes9Arguments) {
|
||||
Action<std::string(const char*, const char*, const char*, const char*,
|
||||
const char*, const char*, const char*, const char*,
|
||||
const char*)>
|
||||
a = Invoke(Concat9);
|
||||
EXPECT_EQ("123456789", a.Perform(std::make_tuple(
|
||||
CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
||||
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
||||
CharPtr("7"), CharPtr("8"), CharPtr("9"))));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a 10-argument function.
|
||||
TEST(InvokeTest, FunctionThatTakes10Arguments) {
|
||||
Action<std::string(const char*, const char*, const char*, const char*,
|
||||
const char*, const char*, const char*, const char*,
|
||||
const char*, const char*)>
|
||||
a = Invoke(Concat10);
|
||||
EXPECT_EQ("1234567890",
|
||||
a.Perform(std::make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
||||
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
||||
CharPtr("7"), CharPtr("8"), CharPtr("9"),
|
||||
CharPtr("0"))));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with functions with parameters declared as Unused.
|
||||
TEST(InvokeTest, FunctionWithUnusedParameters) {
|
||||
Action<int(int, int, double, const std::string&)> a1 = Invoke(SumOfFirst2);
|
||||
std::tuple<int, int, double, std::string> dummy =
|
||||
std::make_tuple(10, 2, 5.6, std::string("hi"));
|
||||
EXPECT_EQ(12, a1.Perform(dummy));
|
||||
|
||||
Action<int(int, int, bool, int*)> a2 =
|
||||
Invoke(SumOfFirst2);
|
||||
EXPECT_EQ(
|
||||
23, a2.Perform(std::make_tuple(20, 3, true, static_cast<int*>(nullptr))));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with methods with parameters declared as Unused.
|
||||
TEST(InvokeTest, MethodWithUnusedParameters) {
|
||||
Foo foo;
|
||||
Action<int(std::string, bool, int, int)> a1 = Invoke(&foo, &Foo::SumOfLast2);
|
||||
EXPECT_EQ(12, a1.Perform(std::make_tuple(CharPtr("hi"), true, 10, 2)));
|
||||
|
||||
Action<int(char, double, int, int)> a2 =
|
||||
Invoke(&foo, &Foo::SumOfLast2);
|
||||
EXPECT_EQ(23, a2.Perform(std::make_tuple('a', 2.5, 20, 3)));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a functor.
|
||||
TEST(InvokeTest, Functor) {
|
||||
Action<long(long, int)> a = Invoke(plus<long>()); // NOLINT
|
||||
EXPECT_EQ(3L, a.Perform(std::make_tuple(1, 2)));
|
||||
}
|
||||
|
||||
// Tests using Invoke(f) as an action of a compatible type.
|
||||
TEST(InvokeTest, FunctionWithCompatibleType) {
|
||||
Action<long(int, short, char, bool)> a = Invoke(SumOf4); // NOLINT
|
||||
EXPECT_EQ(4321, a.Perform(std::make_tuple(4000, Short(300), Char(20), true)));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with an object pointer and a method pointer.
|
||||
|
||||
// Tests using Invoke() with a nullary method.
|
||||
TEST(InvokeMethodTest, Nullary) {
|
||||
Foo foo;
|
||||
Action<int()> a = Invoke(&foo, &Foo::Nullary); // NOLINT
|
||||
EXPECT_EQ(123, a.Perform(std::make_tuple()));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a unary method.
|
||||
TEST(InvokeMethodTest, Unary) {
|
||||
Foo foo;
|
||||
Action<short(long)> a = Invoke(&foo, &Foo::Unary); // NOLINT
|
||||
EXPECT_EQ(4123, a.Perform(std::make_tuple(4000)));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a binary method.
|
||||
TEST(InvokeMethodTest, Binary) {
|
||||
Foo foo;
|
||||
Action<std::string(const std::string&, char)> a = Invoke(&foo, &Foo::Binary);
|
||||
std::string s("Hell");
|
||||
std::tuple<std::string, char> dummy = std::make_tuple(s, 'o');
|
||||
EXPECT_EQ("Hello", a.Perform(dummy));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a ternary method.
|
||||
TEST(InvokeMethodTest, Ternary) {
|
||||
Foo foo;
|
||||
Action<int(int, bool, char)> a = Invoke(&foo, &Foo::Ternary); // NOLINT
|
||||
EXPECT_EQ(1124, a.Perform(std::make_tuple(1000, true, Char(1))));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a 4-argument method.
|
||||
TEST(InvokeMethodTest, MethodThatTakes4Arguments) {
|
||||
Foo foo;
|
||||
Action<int(int, int, int, int)> a = Invoke(&foo, &Foo::SumOf4); // NOLINT
|
||||
EXPECT_EQ(1357, a.Perform(std::make_tuple(1000, 200, 30, 4)));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a 5-argument method.
|
||||
TEST(InvokeMethodTest, MethodThatTakes5Arguments) {
|
||||
Foo foo;
|
||||
Action<int(int, int, int, int, int)> a = Invoke(&foo, &Foo::SumOf5); // NOLINT
|
||||
EXPECT_EQ(12345, a.Perform(std::make_tuple(10000, 2000, 300, 40, 5)));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a 6-argument method.
|
||||
TEST(InvokeMethodTest, MethodThatTakes6Arguments) {
|
||||
Foo foo;
|
||||
Action<int(int, int, int, int, int, int)> a = // NOLINT
|
||||
Invoke(&foo, &Foo::SumOf6);
|
||||
EXPECT_EQ(123456,
|
||||
a.Perform(std::make_tuple(100000, 20000, 3000, 400, 50, 6)));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a 7-argument method.
|
||||
TEST(InvokeMethodTest, MethodThatTakes7Arguments) {
|
||||
Foo foo;
|
||||
Action<std::string(const char*, const char*, const char*, const char*,
|
||||
const char*, const char*, const char*)>
|
||||
a = Invoke(&foo, &Foo::Concat7);
|
||||
EXPECT_EQ("1234567",
|
||||
a.Perform(std::make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
||||
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
||||
CharPtr("7"))));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a 8-argument method.
|
||||
TEST(InvokeMethodTest, MethodThatTakes8Arguments) {
|
||||
Foo foo;
|
||||
Action<std::string(const char*, const char*, const char*, const char*,
|
||||
const char*, const char*, const char*, const char*)>
|
||||
a = Invoke(&foo, &Foo::Concat8);
|
||||
EXPECT_EQ("12345678",
|
||||
a.Perform(std::make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
||||
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
||||
CharPtr("7"), CharPtr("8"))));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a 9-argument method.
|
||||
TEST(InvokeMethodTest, MethodThatTakes9Arguments) {
|
||||
Foo foo;
|
||||
Action<std::string(const char*, const char*, const char*, const char*,
|
||||
const char*, const char*, const char*, const char*,
|
||||
const char*)>
|
||||
a = Invoke(&foo, &Foo::Concat9);
|
||||
EXPECT_EQ("123456789", a.Perform(std::make_tuple(
|
||||
CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
||||
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
||||
CharPtr("7"), CharPtr("8"), CharPtr("9"))));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a 10-argument method.
|
||||
TEST(InvokeMethodTest, MethodThatTakes10Arguments) {
|
||||
Foo foo;
|
||||
Action<std::string(const char*, const char*, const char*, const char*,
|
||||
const char*, const char*, const char*, const char*,
|
||||
const char*, const char*)>
|
||||
a = Invoke(&foo, &Foo::Concat10);
|
||||
EXPECT_EQ("1234567890",
|
||||
a.Perform(std::make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
||||
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
||||
CharPtr("7"), CharPtr("8"), CharPtr("9"),
|
||||
CharPtr("0"))));
|
||||
}
|
||||
|
||||
// Tests using Invoke(f) as an action of a compatible type.
|
||||
TEST(InvokeMethodTest, MethodWithCompatibleType) {
|
||||
Foo foo;
|
||||
Action<long(int, short, char, bool)> a = // NOLINT
|
||||
Invoke(&foo, &Foo::SumOf4);
|
||||
EXPECT_EQ(4444, a.Perform(std::make_tuple(4000, Short(300), Char(20), true)));
|
||||
}
|
||||
|
||||
// Tests using WithoutArgs with an action that takes no argument.
|
||||
TEST(WithoutArgsTest, NoArg) {
|
||||
Action<int(int n)> a = WithoutArgs(Invoke(Nullary)); // NOLINT
|
||||
EXPECT_EQ(1, a.Perform(std::make_tuple(2)));
|
||||
}
|
||||
|
||||
// Tests using WithArg with an action that takes 1 argument.
|
||||
TEST(WithArgTest, OneArg) {
|
||||
Action<bool(double x, int n)> b = WithArg<1>(Invoke(Unary)); // NOLINT
|
||||
EXPECT_TRUE(b.Perform(std::make_tuple(1.5, -1)));
|
||||
EXPECT_FALSE(b.Perform(std::make_tuple(1.5, 1)));
|
||||
}
|
||||
|
||||
TEST(ReturnArgActionTest, WorksForOneArgIntArg0) {
|
||||
const Action<int(int)> a = ReturnArg<0>();
|
||||
EXPECT_EQ(5, a.Perform(std::make_tuple(5)));
|
||||
}
|
||||
|
||||
TEST(ReturnArgActionTest, WorksForMultiArgBoolArg0) {
|
||||
const Action<bool(bool, bool, bool)> a = ReturnArg<0>();
|
||||
EXPECT_TRUE(a.Perform(std::make_tuple(true, false, false)));
|
||||
}
|
||||
|
||||
TEST(ReturnArgActionTest, WorksForMultiArgStringArg2) {
|
||||
const Action<std::string(int, int, std::string, int)> a = ReturnArg<2>();
|
||||
EXPECT_EQ("seven", a.Perform(std::make_tuple(5, 6, std::string("seven"), 8)));
|
||||
}
|
||||
|
||||
TEST(SaveArgActionTest, WorksForSameType) {
|
||||
int result = 0;
|
||||
const Action<void(int n)> a1 = SaveArg<0>(&result);
|
||||
a1.Perform(std::make_tuple(5));
|
||||
EXPECT_EQ(5, result);
|
||||
}
|
||||
|
||||
TEST(SaveArgActionTest, WorksForCompatibleType) {
|
||||
int result = 0;
|
||||
const Action<void(bool, char)> a1 = SaveArg<1>(&result);
|
||||
a1.Perform(std::make_tuple(true, 'a'));
|
||||
EXPECT_EQ('a', result);
|
||||
}
|
||||
|
||||
TEST(SaveArgPointeeActionTest, WorksForSameType) {
|
||||
int result = 0;
|
||||
const int value = 5;
|
||||
const Action<void(const int*)> a1 = SaveArgPointee<0>(&result);
|
||||
a1.Perform(std::make_tuple(&value));
|
||||
EXPECT_EQ(5, result);
|
||||
}
|
||||
|
||||
TEST(SaveArgPointeeActionTest, WorksForCompatibleType) {
|
||||
int result = 0;
|
||||
char value = 'a';
|
||||
const Action<void(bool, char*)> a1 = SaveArgPointee<1>(&result);
|
||||
a1.Perform(std::make_tuple(true, &value));
|
||||
EXPECT_EQ('a', result);
|
||||
}
|
||||
|
||||
TEST(SetArgRefereeActionTest, WorksForSameType) {
|
||||
int value = 0;
|
||||
const Action<void(int&)> a1 = SetArgReferee<0>(1);
|
||||
a1.Perform(std::tuple<int&>(value));
|
||||
EXPECT_EQ(1, value);
|
||||
}
|
||||
|
||||
TEST(SetArgRefereeActionTest, WorksForCompatibleType) {
|
||||
int value = 0;
|
||||
const Action<void(int, int&)> a1 = SetArgReferee<1>('a');
|
||||
a1.Perform(std::tuple<int, int&>(0, value));
|
||||
EXPECT_EQ('a', value);
|
||||
}
|
||||
|
||||
TEST(SetArgRefereeActionTest, WorksWithExtraArguments) {
|
||||
int value = 0;
|
||||
const Action<void(bool, int, int&, const char*)> a1 = SetArgReferee<2>('a');
|
||||
a1.Perform(std::tuple<bool, int, int&, const char*>(true, 0, value, "hi"));
|
||||
EXPECT_EQ('a', value);
|
||||
}
|
||||
|
||||
// A class that can be used to verify that its destructor is called: it will set
|
||||
// the bool provided to the constructor to true when destroyed.
|
||||
class DeletionTester {
|
||||
public:
|
||||
explicit DeletionTester(bool* is_deleted)
|
||||
: is_deleted_(is_deleted) {
|
||||
// Make sure the bit is set to false.
|
||||
*is_deleted_ = false;
|
||||
}
|
||||
|
||||
~DeletionTester() {
|
||||
*is_deleted_ = true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool* is_deleted_;
|
||||
};
|
||||
|
||||
TEST(DeleteArgActionTest, OneArg) {
|
||||
bool is_deleted = false;
|
||||
DeletionTester* t = new DeletionTester(&is_deleted);
|
||||
const Action<void(DeletionTester*)> a1 = DeleteArg<0>(); // NOLINT
|
||||
EXPECT_FALSE(is_deleted);
|
||||
a1.Perform(std::make_tuple(t));
|
||||
EXPECT_TRUE(is_deleted);
|
||||
}
|
||||
|
||||
TEST(DeleteArgActionTest, TenArgs) {
|
||||
bool is_deleted = false;
|
||||
DeletionTester* t = new DeletionTester(&is_deleted);
|
||||
const Action<void(bool, int, int, const char*, bool,
|
||||
int, int, int, int, DeletionTester*)> a1 = DeleteArg<9>();
|
||||
EXPECT_FALSE(is_deleted);
|
||||
a1.Perform(std::make_tuple(true, 5, 6, CharPtr("hi"), false, 7, 8, 9, 10, t));
|
||||
EXPECT_TRUE(is_deleted);
|
||||
}
|
||||
|
||||
#if GTEST_HAS_EXCEPTIONS
|
||||
|
||||
TEST(ThrowActionTest, ThrowsGivenExceptionInVoidFunction) {
|
||||
const Action<void(int n)> a = Throw('a');
|
||||
EXPECT_THROW(a.Perform(std::make_tuple(0)), char);
|
||||
}
|
||||
|
||||
class MyException {};
|
||||
|
||||
TEST(ThrowActionTest, ThrowsGivenExceptionInNonVoidFunction) {
|
||||
const Action<double(char ch)> a = Throw(MyException());
|
||||
EXPECT_THROW(a.Perform(std::make_tuple('0')), MyException);
|
||||
}
|
||||
|
||||
TEST(ThrowActionTest, ThrowsGivenExceptionInNullaryFunction) {
|
||||
const Action<double()> a = Throw(MyException());
|
||||
EXPECT_THROW(a.Perform(std::make_tuple()), MyException);
|
||||
}
|
||||
|
||||
#endif // GTEST_HAS_EXCEPTIONS
|
||||
|
||||
// Tests that SetArrayArgument<N>(first, last) sets the elements of the array
|
||||
// pointed to by the N-th (0-based) argument to values in range [first, last).
|
||||
TEST(SetArrayArgumentTest, SetsTheNthArray) {
|
||||
typedef void MyFunction(bool, int*, char*);
|
||||
int numbers[] = { 1, 2, 3 };
|
||||
Action<MyFunction> a = SetArrayArgument<1>(numbers, numbers + 3);
|
||||
|
||||
int n[4] = {};
|
||||
int* pn = n;
|
||||
char ch[4] = {};
|
||||
char* pch = ch;
|
||||
a.Perform(std::make_tuple(true, pn, pch));
|
||||
EXPECT_EQ(1, n[0]);
|
||||
EXPECT_EQ(2, n[1]);
|
||||
EXPECT_EQ(3, n[2]);
|
||||
EXPECT_EQ(0, n[3]);
|
||||
EXPECT_EQ('\0', ch[0]);
|
||||
EXPECT_EQ('\0', ch[1]);
|
||||
EXPECT_EQ('\0', ch[2]);
|
||||
EXPECT_EQ('\0', ch[3]);
|
||||
|
||||
// Tests first and last are iterators.
|
||||
std::string letters = "abc";
|
||||
a = SetArrayArgument<2>(letters.begin(), letters.end());
|
||||
std::fill_n(n, 4, 0);
|
||||
std::fill_n(ch, 4, '\0');
|
||||
a.Perform(std::make_tuple(true, pn, pch));
|
||||
EXPECT_EQ(0, n[0]);
|
||||
EXPECT_EQ(0, n[1]);
|
||||
EXPECT_EQ(0, n[2]);
|
||||
EXPECT_EQ(0, n[3]);
|
||||
EXPECT_EQ('a', ch[0]);
|
||||
EXPECT_EQ('b', ch[1]);
|
||||
EXPECT_EQ('c', ch[2]);
|
||||
EXPECT_EQ('\0', ch[3]);
|
||||
}
|
||||
|
||||
// Tests SetArrayArgument<N>(first, last) where first == last.
|
||||
TEST(SetArrayArgumentTest, SetsTheNthArrayWithEmptyRange) {
|
||||
typedef void MyFunction(bool, int*);
|
||||
int numbers[] = { 1, 2, 3 };
|
||||
Action<MyFunction> a = SetArrayArgument<1>(numbers, numbers);
|
||||
|
||||
int n[4] = {};
|
||||
int* pn = n;
|
||||
a.Perform(std::make_tuple(true, pn));
|
||||
EXPECT_EQ(0, n[0]);
|
||||
EXPECT_EQ(0, n[1]);
|
||||
EXPECT_EQ(0, n[2]);
|
||||
EXPECT_EQ(0, n[3]);
|
||||
}
|
||||
|
||||
// Tests SetArrayArgument<N>(first, last) where *first is convertible
|
||||
// (but not equal) to the argument type.
|
||||
TEST(SetArrayArgumentTest, SetsTheNthArrayWithConvertibleType) {
|
||||
typedef void MyFunction(bool, int*);
|
||||
char chars[] = { 97, 98, 99 };
|
||||
Action<MyFunction> a = SetArrayArgument<1>(chars, chars + 3);
|
||||
|
||||
int codes[4] = { 111, 222, 333, 444 };
|
||||
int* pcodes = codes;
|
||||
a.Perform(std::make_tuple(true, pcodes));
|
||||
EXPECT_EQ(97, codes[0]);
|
||||
EXPECT_EQ(98, codes[1]);
|
||||
EXPECT_EQ(99, codes[2]);
|
||||
EXPECT_EQ(444, codes[3]);
|
||||
}
|
||||
|
||||
// Test SetArrayArgument<N>(first, last) with iterator as argument.
|
||||
TEST(SetArrayArgumentTest, SetsTheNthArrayWithIteratorArgument) {
|
||||
typedef void MyFunction(bool, std::back_insert_iterator<std::string>);
|
||||
std::string letters = "abc";
|
||||
Action<MyFunction> a = SetArrayArgument<1>(letters.begin(), letters.end());
|
||||
|
||||
std::string s;
|
||||
a.Perform(std::make_tuple(true, back_inserter(s)));
|
||||
EXPECT_EQ(letters, s);
|
||||
}
|
||||
|
||||
TEST(ReturnPointeeTest, Works) {
|
||||
int n = 42;
|
||||
const Action<int()> a = ReturnPointee(&n);
|
||||
EXPECT_EQ(42, a.Perform(std::make_tuple()));
|
||||
|
||||
n = 43;
|
||||
EXPECT_EQ(43, a.Perform(std::make_tuple()));
|
||||
}
|
||||
|
||||
} // namespace gmock_generated_actions_test
|
||||
} // namespace testing
|
@@ -1,28 +0,0 @@
|
||||
Copyright 2008, Google Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@@ -1,244 +0,0 @@
|
||||
### Generic Build Instructions
|
||||
|
||||
#### Setup
|
||||
|
||||
To build Google Test and your tests that use it, you need to tell your build
|
||||
system where to find its headers and source files. The exact way to do it
|
||||
depends on which build system you use, and is usually straightforward.
|
||||
|
||||
### Build with CMake
|
||||
|
||||
Google Test comes with a CMake build script (
|
||||
[CMakeLists.txt](https://github.com/google/googletest/blob/master/CMakeLists.txt))
|
||||
that can be used on a wide range of platforms ("C" stands for cross-platform.).
|
||||
If you don't have CMake installed already, you can download it for free from
|
||||
<http://www.cmake.org/>.
|
||||
|
||||
CMake works by generating native makefiles or build projects that can be used in
|
||||
the compiler environment of your choice. You can either build Google Test as a
|
||||
standalone project or it can be incorporated into an existing CMake build for
|
||||
another project.
|
||||
|
||||
#### Standalone CMake Project
|
||||
|
||||
When building Google Test as a standalone project, the typical workflow starts
|
||||
with:
|
||||
|
||||
mkdir mybuild # Create a directory to hold the build output.
|
||||
cd mybuild
|
||||
cmake ${GTEST_DIR} # Generate native build scripts.
|
||||
|
||||
If you want to build Google Test's samples, you should replace the last command
|
||||
with
|
||||
|
||||
cmake -Dgtest_build_samples=ON ${GTEST_DIR}
|
||||
|
||||
If you are on a \*nix system, you should now see a Makefile in the current
|
||||
directory. Just type 'make' to build gtest.
|
||||
|
||||
If you use Windows and have Visual Studio installed, a `gtest.sln` file and
|
||||
several `.vcproj` files will be created. You can then build them using Visual
|
||||
Studio.
|
||||
|
||||
On Mac OS X with Xcode installed, a `.xcodeproj` file will be generated.
|
||||
|
||||
#### Incorporating Into An Existing CMake Project
|
||||
|
||||
If you want to use gtest in a project which already uses CMake, then a more
|
||||
robust and flexible approach is to build gtest as part of that project directly.
|
||||
This is done by making the GoogleTest source code available to the main build
|
||||
and adding it using CMake's `add_subdirectory()` command. This has the
|
||||
significant advantage that the same compiler and linker settings are used
|
||||
between gtest and the rest of your project, so issues associated with using
|
||||
incompatible libraries (eg debug/release), etc. are avoided. This is
|
||||
particularly useful on Windows. Making GoogleTest's source code available to the
|
||||
main build can be done a few different ways:
|
||||
|
||||
* Download the GoogleTest source code manually and place it at a known
|
||||
location. This is the least flexible approach and can make it more difficult
|
||||
to use with continuous integration systems, etc.
|
||||
* Embed the GoogleTest source code as a direct copy in the main project's
|
||||
source tree. This is often the simplest approach, but is also the hardest to
|
||||
keep up to date. Some organizations may not permit this method.
|
||||
* Add GoogleTest as a git submodule or equivalent. This may not always be
|
||||
possible or appropriate. Git submodules, for example, have their own set of
|
||||
advantages and drawbacks.
|
||||
* Use CMake to download GoogleTest as part of the build's configure step. This
|
||||
is just a little more complex, but doesn't have the limitations of the other
|
||||
methods.
|
||||
|
||||
The last of the above methods is implemented with a small piece of CMake code in
|
||||
a separate file (e.g. `CMakeLists.txt.in`) which is copied to the build area and
|
||||
then invoked as a sub-build _during the CMake stage_. That directory is then
|
||||
pulled into the main build with `add_subdirectory()`. For example:
|
||||
|
||||
New file `CMakeLists.txt.in`:
|
||||
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 2.8.2)
|
||||
|
||||
project(googletest-download NONE)
|
||||
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(googletest
|
||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||
GIT_TAG master
|
||||
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src"
|
||||
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
)
|
||||
```
|
||||
|
||||
Existing build's `CMakeLists.txt`:
|
||||
|
||||
```cmake
|
||||
# Download and unpack googletest at configure time
|
||||
configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
|
||||
RESULT_VARIABLE result
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )
|
||||
if(result)
|
||||
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
|
||||
endif()
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} --build .
|
||||
RESULT_VARIABLE result
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )
|
||||
if(result)
|
||||
message(FATAL_ERROR "Build step for googletest failed: ${result}")
|
||||
endif()
|
||||
|
||||
# Prevent overriding the parent project's compiler/linker
|
||||
# settings on Windows
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
|
||||
# Add googletest directly to our build. This defines
|
||||
# the gtest and gtest_main targets.
|
||||
add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src
|
||||
${CMAKE_CURRENT_BINARY_DIR}/googletest-build
|
||||
EXCLUDE_FROM_ALL)
|
||||
|
||||
# The gtest/gtest_main targets carry header search path
|
||||
# dependencies automatically when using CMake 2.8.11 or
|
||||
# later. Otherwise we have to add them here ourselves.
|
||||
if (CMAKE_VERSION VERSION_LESS 2.8.11)
|
||||
include_directories("${gtest_SOURCE_DIR}/include")
|
||||
endif()
|
||||
|
||||
# Now simply link against gtest or gtest_main as needed. Eg
|
||||
add_executable(example example.cpp)
|
||||
target_link_libraries(example gtest_main)
|
||||
add_test(NAME example_test COMMAND example)
|
||||
```
|
||||
|
||||
Note that this approach requires CMake 2.8.2 or later due to its use of the
|
||||
`ExternalProject_Add()` command. The above technique is discussed in more detail
|
||||
in [this separate article](http://crascit.com/2015/07/25/cmake-gtest/) which
|
||||
also contains a link to a fully generalized implementation of the technique.
|
||||
|
||||
##### Visual Studio Dynamic vs Static Runtimes
|
||||
|
||||
By default, new Visual Studio projects link the C runtimes dynamically but
|
||||
Google Test links them statically. This will generate an error that looks
|
||||
something like the following: gtest.lib(gtest-all.obj) : error LNK2038: mismatch
|
||||
detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value
|
||||
'MDd_DynamicDebug' in main.obj
|
||||
|
||||
Google Test already has a CMake option for this: `gtest_force_shared_crt`
|
||||
|
||||
Enabling this option will make gtest link the runtimes dynamically too, and
|
||||
match the project in which it is included.
|
||||
|
||||
#### C++ Standard Version
|
||||
|
||||
An environment that supports C++11 is required in order to successfully build
|
||||
Google Test. One way to ensure this is to specify the standard in the top-level
|
||||
project, for example by using the `set(CMAKE_CXX_STANDARD 11)` command. If this
|
||||
is not feasible, for example in a C project using Google Test for validation,
|
||||
then it can be specified by adding it to the options for cmake via the
|
||||
`DCMAKE_CXX_FLAGS` option.
|
||||
|
||||
### Tweaking Google Test
|
||||
|
||||
Google Test can be used in diverse environments. The default configuration may
|
||||
not work (or may not work well) out of the box in some environments. However,
|
||||
you can easily tweak Google Test by defining control macros on the compiler
|
||||
command line. Generally, these macros are named like `GTEST_XYZ` and you define
|
||||
them to either 1 or 0 to enable or disable a certain feature.
|
||||
|
||||
We list the most frequently used macros below. For a complete list, see file
|
||||
[include/gtest/internal/gtest-port.h](https://github.com/google/googletest/blob/master/googletest/include/gtest/internal/gtest-port.h).
|
||||
|
||||
### Multi-threaded Tests
|
||||
|
||||
Google Test is thread-safe where the pthread library is available. After
|
||||
`#include "gtest/gtest.h"`, you can check the
|
||||
`GTEST_IS_THREADSAFE` macro to see whether this is the case (yes if the macro is
|
||||
`#defined` to 1, no if it's undefined.).
|
||||
|
||||
If Google Test doesn't correctly detect whether pthread is available in your
|
||||
environment, you can force it with
|
||||
|
||||
-DGTEST_HAS_PTHREAD=1
|
||||
|
||||
or
|
||||
|
||||
-DGTEST_HAS_PTHREAD=0
|
||||
|
||||
When Google Test uses pthread, you may need to add flags to your compiler and/or
|
||||
linker to select the pthread library, or you'll get link errors. If you use the
|
||||
CMake script or the deprecated Autotools script, this is taken care of for you.
|
||||
If you use your own build script, you'll need to read your compiler and linker's
|
||||
manual to figure out what flags to add.
|
||||
|
||||
### As a Shared Library (DLL)
|
||||
|
||||
Google Test is compact, so most users can build and link it as a static library
|
||||
for the simplicity. You can choose to use Google Test as a shared library (known
|
||||
as a DLL on Windows) if you prefer.
|
||||
|
||||
To compile *gtest* as a shared library, add
|
||||
|
||||
-DGTEST_CREATE_SHARED_LIBRARY=1
|
||||
|
||||
to the compiler flags. You'll also need to tell the linker to produce a shared
|
||||
library instead - consult your linker's manual for how to do it.
|
||||
|
||||
To compile your *tests* that use the gtest shared library, add
|
||||
|
||||
-DGTEST_LINKED_AS_SHARED_LIBRARY=1
|
||||
|
||||
to the compiler flags.
|
||||
|
||||
Note: while the above steps aren't technically necessary today when using some
|
||||
compilers (e.g. GCC), they may become necessary in the future, if we decide to
|
||||
improve the speed of loading the library (see
|
||||
<http://gcc.gnu.org/wiki/Visibility> for details). Therefore you are recommended
|
||||
to always add the above flags when using Google Test as a shared library.
|
||||
Otherwise a future release of Google Test may break your build script.
|
||||
|
||||
### Avoiding Macro Name Clashes
|
||||
|
||||
In C++, macros don't obey namespaces. Therefore two libraries that both define a
|
||||
macro of the same name will clash if you `#include` both definitions. In case a
|
||||
Google Test macro clashes with another library, you can force Google Test to
|
||||
rename its macro to avoid the conflict.
|
||||
|
||||
Specifically, if both Google Test and some other code define macro FOO, you can
|
||||
add
|
||||
|
||||
-DGTEST_DONT_DEFINE_FOO=1
|
||||
|
||||
to the compiler flags to tell Google Test to change the macro's name from `FOO`
|
||||
to `GTEST_FOO`. Currently `FOO` can be `FAIL`, `SUCCEED`, or `TEST`. For
|
||||
example, with `-DGTEST_DONT_DEFINE_TEST=1`, you'll need to write
|
||||
|
||||
GTEST_TEST(SomeTest, DoesThis) { ... }
|
||||
|
||||
instead of
|
||||
|
||||
TEST(SomeTest, DoesThis) { ... }
|
||||
|
||||
in order to define a test.
|
@@ -1,10 +0,0 @@
|
||||
prefix=${pcfiledir}/../..
|
||||
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
|
||||
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
|
||||
|
||||
Name: gtest
|
||||
Description: GoogleTest (without main() function)
|
||||
Version: @PROJECT_VERSION@
|
||||
URL: https://github.com/google/googletest
|
||||
Libs: -L${libdir} -lgtest @CMAKE_THREAD_LIBS_INIT@
|
||||
Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ @CMAKE_THREAD_LIBS_INIT@
|
@@ -1,11 +0,0 @@
|
||||
prefix=${pcfiledir}/../..
|
||||
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
|
||||
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
|
||||
|
||||
Name: gtest_main
|
||||
Description: GoogleTest (with main() function)
|
||||
Version: @PROJECT_VERSION@
|
||||
URL: https://github.com/google/googletest
|
||||
Requires: gtest
|
||||
Libs: -L${libdir} -lgtest_main @CMAKE_THREAD_LIBS_INIT@
|
||||
Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ @CMAKE_THREAD_LIBS_INIT@
|
@@ -1,190 +0,0 @@
|
||||
<b>P</b>ump is <b>U</b>seful for <b>M</b>eta <b>P</b>rogramming.
|
||||
|
||||
# The Problem
|
||||
|
||||
Template and macro libraries often need to define many classes, functions, or
|
||||
macros that vary only (or almost only) in the number of arguments they take.
|
||||
It's a lot of repetitive, mechanical, and error-prone work.
|
||||
|
||||
Variadic templates and variadic macros can alleviate the problem. However, while
|
||||
both are being considered by the C++ committee, neither is in the standard yet
|
||||
or widely supported by compilers. Thus they are often not a good choice,
|
||||
especially when your code needs to be portable. And their capabilities are still
|
||||
limited.
|
||||
|
||||
As a result, authors of such libraries often have to write scripts to generate
|
||||
their implementation. However, our experience is that it's tedious to write such
|
||||
scripts, which tend to reflect the structure of the generated code poorly and
|
||||
are often hard to read and edit. For example, a small change needed in the
|
||||
generated code may require some non-intuitive, non-trivial changes in the
|
||||
script. This is especially painful when experimenting with the code.
|
||||
|
||||
# Our Solution
|
||||
|
||||
Pump (for Pump is Useful for Meta Programming, Pretty Useful for Meta
|
||||
Programming, or Practical Utility for Meta Programming, whichever you prefer) is
|
||||
a simple meta-programming tool for C++. The idea is that a programmer writes a
|
||||
`foo.pump` file which contains C++ code plus meta code that manipulates the C++
|
||||
code. The meta code can handle iterations over a range, nested iterations, local
|
||||
meta variable definitions, simple arithmetic, and conditional expressions. You
|
||||
can view it as a small Domain-Specific Language. The meta language is designed
|
||||
to be non-intrusive (s.t. it won't confuse Emacs' C++ mode, for example) and
|
||||
concise, making Pump code intuitive and easy to maintain.
|
||||
|
||||
## Highlights
|
||||
|
||||
* The implementation is in a single Python script and thus ultra portable: no
|
||||
build or installation is needed and it works cross platforms.
|
||||
* Pump tries to be smart with respect to
|
||||
[Google's style guide](https://github.com/google/styleguide): it breaks long
|
||||
lines (easy to have when they are generated) at acceptable places to fit
|
||||
within 80 columns and indent the continuation lines correctly.
|
||||
* The format is human-readable and more concise than XML.
|
||||
* The format works relatively well with Emacs' C++ mode.
|
||||
|
||||
## Examples
|
||||
|
||||
The following Pump code (where meta keywords start with `$`, `[[` and `]]` are
|
||||
meta brackets, and `$$` starts a meta comment that ends with the line):
|
||||
|
||||
```
|
||||
$var n = 3 $$ Defines a meta variable n.
|
||||
$range i 0..n $$ Declares the range of meta iterator i (inclusive).
|
||||
$for i [[
|
||||
$$ Meta loop.
|
||||
// Foo$i does blah for $i-ary predicates.
|
||||
$range j 1..i
|
||||
template <size_t N $for j [[, typename A$j]]>
|
||||
class Foo$i {
|
||||
$if i == 0 [[
|
||||
blah a;
|
||||
]] $elif i <= 2 [[
|
||||
blah b;
|
||||
]] $else [[
|
||||
blah c;
|
||||
]]
|
||||
};
|
||||
|
||||
]]
|
||||
```
|
||||
|
||||
will be translated by the Pump compiler to:
|
||||
|
||||
```cpp
|
||||
// Foo0 does blah for 0-ary predicates.
|
||||
template <size_t N>
|
||||
class Foo0 {
|
||||
blah a;
|
||||
};
|
||||
|
||||
// Foo1 does blah for 1-ary predicates.
|
||||
template <size_t N, typename A1>
|
||||
class Foo1 {
|
||||
blah b;
|
||||
};
|
||||
|
||||
// Foo2 does blah for 2-ary predicates.
|
||||
template <size_t N, typename A1, typename A2>
|
||||
class Foo2 {
|
||||
blah b;
|
||||
};
|
||||
|
||||
// Foo3 does blah for 3-ary predicates.
|
||||
template <size_t N, typename A1, typename A2, typename A3>
|
||||
class Foo3 {
|
||||
blah c;
|
||||
};
|
||||
```
|
||||
|
||||
In another example,
|
||||
|
||||
```
|
||||
$range i 1..n
|
||||
Func($for i + [[a$i]]);
|
||||
$$ The text between i and [[ is the separator between iterations.
|
||||
```
|
||||
|
||||
will generate one of the following lines (without the comments), depending on
|
||||
the value of `n`:
|
||||
|
||||
```cpp
|
||||
Func(); // If n is 0.
|
||||
Func(a1); // If n is 1.
|
||||
Func(a1 + a2); // If n is 2.
|
||||
Func(a1 + a2 + a3); // If n is 3.
|
||||
// And so on...
|
||||
```
|
||||
|
||||
## Constructs
|
||||
|
||||
We support the following meta programming constructs:
|
||||
|
||||
| `$var id = exp` | Defines a named constant value. `$id` is |
|
||||
: : valid util the end of the current meta :
|
||||
: : lexical block. :
|
||||
| :------------------------------- | :--------------------------------------- |
|
||||
| `$range id exp..exp` | Sets the range of an iteration variable, |
|
||||
: : which can be reused in multiple loops :
|
||||
: : later. :
|
||||
| `$for id sep [[ code ]]` | Iteration. The range of `id` must have |
|
||||
: : been defined earlier. `$id` is valid in :
|
||||
: : `code`. :
|
||||
| `$($)` | Generates a single `$` character. |
|
||||
| `$id` | Value of the named constant or iteration |
|
||||
: : variable. :
|
||||
| `$(exp)` | Value of the expression. |
|
||||
| `$if exp [[ code ]] else_branch` | Conditional. |
|
||||
| `[[ code ]]` | Meta lexical block. |
|
||||
| `cpp_code` | Raw C++ code. |
|
||||
| `$$ comment` | Meta comment. |
|
||||
|
||||
**Note:** To give the user some freedom in formatting the Pump source code, Pump
|
||||
ignores a new-line character if it's right after `$for foo` or next to `[[` or
|
||||
`]]`. Without this rule you'll often be forced to write very long lines to get
|
||||
the desired output. Therefore sometimes you may need to insert an extra new-line
|
||||
in such places for a new-line to show up in your output.
|
||||
|
||||
## Grammar
|
||||
|
||||
```ebnf
|
||||
code ::= atomic_code*
|
||||
atomic_code ::= $var id = exp
|
||||
| $var id = [[ code ]]
|
||||
| $range id exp..exp
|
||||
| $for id sep [[ code ]]
|
||||
| $($)
|
||||
| $id
|
||||
| $(exp)
|
||||
| $if exp [[ code ]] else_branch
|
||||
| [[ code ]]
|
||||
| cpp_code
|
||||
sep ::= cpp_code | empty_string
|
||||
else_branch ::= $else [[ code ]]
|
||||
| $elif exp [[ code ]] else_branch
|
||||
| empty_string
|
||||
exp ::= simple_expression_in_Python_syntax
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
You can find the source code of Pump in [scripts/pump.py](../scripts/pump.py).
|
||||
It is still very unpolished and lacks automated tests, although it has been
|
||||
successfully used many times. If you find a chance to use it in your project,
|
||||
please let us know what you think! We also welcome help on improving Pump.
|
||||
|
||||
## Real Examples
|
||||
|
||||
You can find real-world applications of Pump in
|
||||
[Google Test](https://github.com/google/googletest/tree/master/googletest) and
|
||||
[Google Mock](https://github.com/google/googletest/tree/master/googlemock). The
|
||||
source file `foo.h.pump` generates `foo.h`.
|
||||
|
||||
## Tips
|
||||
|
||||
* If a meta variable is followed by a letter or digit, you can separate them
|
||||
using `[[]]`, which inserts an empty string. For example `Foo$j[[]]Helper`
|
||||
generate `Foo1Helper` when `j` is 1.
|
||||
* To avoid extra-long Pump source lines, you can break a line anywhere you
|
||||
want by inserting `[[]]` followed by a new line. Since any new-line
|
||||
character next to `[[` or `]]` is ignored, the generated code won't contain
|
||||
this new line.
|
File diff suppressed because it is too large
Load Diff
@@ -1,302 +0,0 @@
|
||||
$$ -*- mode: c++; -*-
|
||||
$var n = 50 $$ Maximum length of type lists we want to support.
|
||||
// Copyright 2008 Google Inc.
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
// Type utilities needed for implementing typed and type-parameterized
|
||||
// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
|
||||
//
|
||||
// Currently we support at most $n types in a list, and at most $n
|
||||
// type-parameterized tests in one type-parameterized test suite.
|
||||
// Please contact googletestframework@googlegroups.com if you need
|
||||
// more.
|
||||
|
||||
// GOOGLETEST_CM0001 DO NOT DELETE
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
||||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
||||
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
|
||||
// #ifdef __GNUC__ is too general here. It is possible to use gcc without using
|
||||
// libstdc++ (which is where cxxabi.h comes from).
|
||||
# if GTEST_HAS_CXXABI_H_
|
||||
# include <cxxabi.h>
|
||||
# elif defined(__HP_aCC)
|
||||
# include <acxx_demangle.h>
|
||||
# endif // GTEST_HASH_CXXABI_H_
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
// Canonicalizes a given name with respect to the Standard C++ Library.
|
||||
// This handles removing the inline namespace within `std` that is
|
||||
// used by various standard libraries (e.g., `std::__1`). Names outside
|
||||
// of namespace std are returned unmodified.
|
||||
inline std::string CanonicalizeForStdLibVersioning(std::string s) {
|
||||
static const char prefix[] = "std::__";
|
||||
if (s.compare(0, strlen(prefix), prefix) == 0) {
|
||||
std::string::size_type end = s.find("::", strlen(prefix));
|
||||
if (end != s.npos) {
|
||||
// Erase everything between the initial `std` and the second `::`.
|
||||
s.erase(strlen("std"), end - strlen("std"));
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
// GetTypeName<T>() returns a human-readable name of type T.
|
||||
// NB: This function is also used in Google Mock, so don't move it inside of
|
||||
// the typed-test-only section below.
|
||||
template <typename T>
|
||||
std::string GetTypeName() {
|
||||
# if GTEST_HAS_RTTI
|
||||
|
||||
const char* const name = typeid(T).name();
|
||||
# if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
|
||||
int status = 0;
|
||||
// gcc's implementation of typeid(T).name() mangles the type name,
|
||||
// so we have to demangle it.
|
||||
# if GTEST_HAS_CXXABI_H_
|
||||
using abi::__cxa_demangle;
|
||||
# endif // GTEST_HAS_CXXABI_H_
|
||||
char* const readable_name = __cxa_demangle(name, nullptr, nullptr, &status);
|
||||
const std::string name_str(status == 0 ? readable_name : name);
|
||||
free(readable_name);
|
||||
return CanonicalizeForStdLibVersioning(name_str);
|
||||
# else
|
||||
return name;
|
||||
# endif // GTEST_HAS_CXXABI_H_ || __HP_aCC
|
||||
|
||||
# else
|
||||
|
||||
return "<type>";
|
||||
|
||||
# endif // GTEST_HAS_RTTI
|
||||
}
|
||||
|
||||
#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
|
||||
|
||||
// A unique type used as the default value for the arguments of class
|
||||
// template Types. This allows us to simulate variadic templates
|
||||
// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
|
||||
// support directly.
|
||||
struct None {};
|
||||
|
||||
// The following family of struct and struct templates are used to
|
||||
// represent type lists. In particular, TypesN<T1, T2, ..., TN>
|
||||
// represents a type list with N types (T1, T2, ..., and TN) in it.
|
||||
// Except for Types0, every struct in the family has two member types:
|
||||
// Head for the first type in the list, and Tail for the rest of the
|
||||
// list.
|
||||
|
||||
// The empty type list.
|
||||
struct Types0 {};
|
||||
|
||||
// Type lists of length 1, 2, 3, and so on.
|
||||
|
||||
template <typename T1>
|
||||
struct Types1 {
|
||||
typedef T1 Head;
|
||||
typedef Types0 Tail;
|
||||
};
|
||||
|
||||
$range i 2..n
|
||||
|
||||
$for i [[
|
||||
$range j 1..i
|
||||
$range k 2..i
|
||||
template <$for j, [[typename T$j]]>
|
||||
struct Types$i {
|
||||
typedef T1 Head;
|
||||
typedef Types$(i-1)<$for k, [[T$k]]> Tail;
|
||||
};
|
||||
|
||||
|
||||
]]
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// We don't want to require the users to write TypesN<...> directly,
|
||||
// as that would require them to count the length. Types<...> is much
|
||||
// easier to write, but generates horrible messages when there is a
|
||||
// compiler error, as gcc insists on printing out each template
|
||||
// argument, even if it has the default value (this means Types<int>
|
||||
// will appear as Types<int, None, None, ..., None> in the compiler
|
||||
// errors).
|
||||
//
|
||||
// Our solution is to combine the best part of the two approaches: a
|
||||
// user would write Types<T1, ..., TN>, and Google Test will translate
|
||||
// that to TypesN<T1, ..., TN> internally to make error messages
|
||||
// readable. The translation is done by the 'type' member of the
|
||||
// Types template.
|
||||
|
||||
$range i 1..n
|
||||
template <$for i, [[typename T$i = internal::None]]>
|
||||
struct Types {
|
||||
typedef internal::Types$n<$for i, [[T$i]]> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Types<$for i, [[internal::None]]> {
|
||||
typedef internal::Types0 type;
|
||||
};
|
||||
|
||||
$range i 1..n-1
|
||||
$for i [[
|
||||
$range j 1..i
|
||||
$range k i+1..n
|
||||
template <$for j, [[typename T$j]]>
|
||||
struct Types<$for j, [[T$j]]$for k[[, internal::None]]> {
|
||||
typedef internal::Types$i<$for j, [[T$j]]> type;
|
||||
};
|
||||
|
||||
]]
|
||||
|
||||
namespace internal {
|
||||
|
||||
# define GTEST_TEMPLATE_ template <typename T> class
|
||||
|
||||
// The template "selector" struct TemplateSel<Tmpl> is used to
|
||||
// represent Tmpl, which must be a class template with one type
|
||||
// parameter, as a type. TemplateSel<Tmpl>::Bind<T>::type is defined
|
||||
// as the type Tmpl<T>. This allows us to actually instantiate the
|
||||
// template "selected" by TemplateSel<Tmpl>.
|
||||
//
|
||||
// This trick is necessary for simulating typedef for class templates,
|
||||
// which C++ doesn't support directly.
|
||||
template <GTEST_TEMPLATE_ Tmpl>
|
||||
struct TemplateSel {
|
||||
template <typename T>
|
||||
struct Bind {
|
||||
typedef Tmpl<T> type;
|
||||
};
|
||||
};
|
||||
|
||||
# define GTEST_BIND_(TmplSel, T) \
|
||||
TmplSel::template Bind<T>::type
|
||||
|
||||
// A unique struct template used as the default value for the
|
||||
// arguments of class template Templates. This allows us to simulate
|
||||
// variadic templates (e.g. Templates<int>, Templates<int, double>,
|
||||
// and etc), which C++ doesn't support directly.
|
||||
template <typename T>
|
||||
struct NoneT {};
|
||||
|
||||
// The following family of struct and struct templates are used to
|
||||
// represent template lists. In particular, TemplatesN<T1, T2, ...,
|
||||
// TN> represents a list of N templates (T1, T2, ..., and TN). Except
|
||||
// for Templates0, every struct in the family has two member types:
|
||||
// Head for the selector of the first template in the list, and Tail
|
||||
// for the rest of the list.
|
||||
|
||||
// The empty template list.
|
||||
struct Templates0 {};
|
||||
|
||||
// Template lists of length 1, 2, 3, and so on.
|
||||
|
||||
template <GTEST_TEMPLATE_ T1>
|
||||
struct Templates1 {
|
||||
typedef TemplateSel<T1> Head;
|
||||
typedef Templates0 Tail;
|
||||
};
|
||||
|
||||
$range i 2..n
|
||||
|
||||
$for i [[
|
||||
$range j 1..i
|
||||
$range k 2..i
|
||||
template <$for j, [[GTEST_TEMPLATE_ T$j]]>
|
||||
struct Templates$i {
|
||||
typedef TemplateSel<T1> Head;
|
||||
typedef Templates$(i-1)<$for k, [[T$k]]> Tail;
|
||||
};
|
||||
|
||||
|
||||
]]
|
||||
|
||||
// We don't want to require the users to write TemplatesN<...> directly,
|
||||
// as that would require them to count the length. Templates<...> is much
|
||||
// easier to write, but generates horrible messages when there is a
|
||||
// compiler error, as gcc insists on printing out each template
|
||||
// argument, even if it has the default value (this means Templates<list>
|
||||
// will appear as Templates<list, NoneT, NoneT, ..., NoneT> in the compiler
|
||||
// errors).
|
||||
//
|
||||
// Our solution is to combine the best part of the two approaches: a
|
||||
// user would write Templates<T1, ..., TN>, and Google Test will translate
|
||||
// that to TemplatesN<T1, ..., TN> internally to make error messages
|
||||
// readable. The translation is done by the 'type' member of the
|
||||
// Templates template.
|
||||
|
||||
$range i 1..n
|
||||
template <$for i, [[GTEST_TEMPLATE_ T$i = NoneT]]>
|
||||
struct Templates {
|
||||
typedef Templates$n<$for i, [[T$i]]> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Templates<$for i, [[NoneT]]> {
|
||||
typedef Templates0 type;
|
||||
};
|
||||
|
||||
$range i 1..n-1
|
||||
$for i [[
|
||||
$range j 1..i
|
||||
$range k i+1..n
|
||||
template <$for j, [[GTEST_TEMPLATE_ T$j]]>
|
||||
struct Templates<$for j, [[T$j]]$for k[[, NoneT]]> {
|
||||
typedef Templates$i<$for j, [[T$j]]> type;
|
||||
};
|
||||
|
||||
]]
|
||||
|
||||
// The TypeList template makes it possible to use either a single type
|
||||
// or a Types<...> list in TYPED_TEST_SUITE() and
|
||||
// INSTANTIATE_TYPED_TEST_SUITE_P().
|
||||
|
||||
template <typename T>
|
||||
struct TypeList {
|
||||
typedef Types1<T> type;
|
||||
};
|
||||
|
||||
|
||||
$range i 1..n
|
||||
template <$for i, [[typename T$i]]>
|
||||
struct TypeList<Types<$for i, [[T$i]]> > {
|
||||
typedef typename Types<$for i, [[T$i]]>::type type;
|
||||
};
|
||||
|
||||
#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
|
||||
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
|
@@ -1,855 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2008, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
"""pump v0.2.0 - Pretty Useful for Meta Programming.
|
||||
|
||||
A tool for preprocessor meta programming. Useful for generating
|
||||
repetitive boilerplate code. Especially useful for writing C++
|
||||
classes, functions, macros, and templates that need to work with
|
||||
various number of arguments.
|
||||
|
||||
USAGE:
|
||||
pump.py SOURCE_FILE
|
||||
|
||||
EXAMPLES:
|
||||
pump.py foo.cc.pump
|
||||
Converts foo.cc.pump to foo.cc.
|
||||
|
||||
GRAMMAR:
|
||||
CODE ::= ATOMIC_CODE*
|
||||
ATOMIC_CODE ::= $var ID = EXPRESSION
|
||||
| $var ID = [[ CODE ]]
|
||||
| $range ID EXPRESSION..EXPRESSION
|
||||
| $for ID SEPARATOR [[ CODE ]]
|
||||
| $($)
|
||||
| $ID
|
||||
| $(EXPRESSION)
|
||||
| $if EXPRESSION [[ CODE ]] ELSE_BRANCH
|
||||
| [[ CODE ]]
|
||||
| RAW_CODE
|
||||
SEPARATOR ::= RAW_CODE | EMPTY
|
||||
ELSE_BRANCH ::= $else [[ CODE ]]
|
||||
| $elif EXPRESSION [[ CODE ]] ELSE_BRANCH
|
||||
| EMPTY
|
||||
EXPRESSION has Python syntax.
|
||||
"""
|
||||
|
||||
__author__ = 'wan@google.com (Zhanyong Wan)'
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
TOKEN_TABLE = [
|
||||
(re.compile(r'\$var\s+'), '$var'),
|
||||
(re.compile(r'\$elif\s+'), '$elif'),
|
||||
(re.compile(r'\$else\s+'), '$else'),
|
||||
(re.compile(r'\$for\s+'), '$for'),
|
||||
(re.compile(r'\$if\s+'), '$if'),
|
||||
(re.compile(r'\$range\s+'), '$range'),
|
||||
(re.compile(r'\$[_A-Za-z]\w*'), '$id'),
|
||||
(re.compile(r'\$\(\$\)'), '$($)'),
|
||||
(re.compile(r'\$'), '$'),
|
||||
(re.compile(r'\[\[\n?'), '[['),
|
||||
(re.compile(r'\]\]\n?'), ']]'),
|
||||
]
|
||||
|
||||
|
||||
class Cursor:
|
||||
"""Represents a position (line and column) in a text file."""
|
||||
|
||||
def __init__(self, line=-1, column=-1):
|
||||
self.line = line
|
||||
self.column = column
|
||||
|
||||
def __eq__(self, rhs):
|
||||
return self.line == rhs.line and self.column == rhs.column
|
||||
|
||||
def __ne__(self, rhs):
|
||||
return not self == rhs
|
||||
|
||||
def __lt__(self, rhs):
|
||||
return self.line < rhs.line or (
|
||||
self.line == rhs.line and self.column < rhs.column)
|
||||
|
||||
def __le__(self, rhs):
|
||||
return self < rhs or self == rhs
|
||||
|
||||
def __gt__(self, rhs):
|
||||
return rhs < self
|
||||
|
||||
def __ge__(self, rhs):
|
||||
return rhs <= self
|
||||
|
||||
def __str__(self):
|
||||
if self == Eof():
|
||||
return 'EOF'
|
||||
else:
|
||||
return '%s(%s)' % (self.line + 1, self.column)
|
||||
|
||||
def __add__(self, offset):
|
||||
return Cursor(self.line, self.column + offset)
|
||||
|
||||
def __sub__(self, offset):
|
||||
return Cursor(self.line, self.column - offset)
|
||||
|
||||
def Clone(self):
|
||||
"""Returns a copy of self."""
|
||||
|
||||
return Cursor(self.line, self.column)
|
||||
|
||||
|
||||
# Special cursor to indicate the end-of-file.
|
||||
def Eof():
|
||||
"""Returns the special cursor to denote the end-of-file."""
|
||||
return Cursor(-1, -1)
|
||||
|
||||
|
||||
class Token:
|
||||
"""Represents a token in a Pump source file."""
|
||||
|
||||
def __init__(self, start=None, end=None, value=None, token_type=None):
|
||||
if start is None:
|
||||
self.start = Eof()
|
||||
else:
|
||||
self.start = start
|
||||
if end is None:
|
||||
self.end = Eof()
|
||||
else:
|
||||
self.end = end
|
||||
self.value = value
|
||||
self.token_type = token_type
|
||||
|
||||
def __str__(self):
|
||||
return 'Token @%s: \'%s\' type=%s' % (
|
||||
self.start, self.value, self.token_type)
|
||||
|
||||
def Clone(self):
|
||||
"""Returns a copy of self."""
|
||||
|
||||
return Token(self.start.Clone(), self.end.Clone(), self.value,
|
||||
self.token_type)
|
||||
|
||||
|
||||
def StartsWith(lines, pos, string):
|
||||
"""Returns True iff the given position in lines starts with 'string'."""
|
||||
|
||||
return lines[pos.line][pos.column:].startswith(string)
|
||||
|
||||
|
||||
def FindFirstInLine(line, token_table):
|
||||
best_match_start = -1
|
||||
for (regex, token_type) in token_table:
|
||||
m = regex.search(line)
|
||||
if m:
|
||||
# We found regex in lines
|
||||
if best_match_start < 0 or m.start() < best_match_start:
|
||||
best_match_start = m.start()
|
||||
best_match_length = m.end() - m.start()
|
||||
best_match_token_type = token_type
|
||||
|
||||
if best_match_start < 0:
|
||||
return None
|
||||
|
||||
return (best_match_start, best_match_length, best_match_token_type)
|
||||
|
||||
|
||||
def FindFirst(lines, token_table, cursor):
|
||||
"""Finds the first occurrence of any string in strings in lines."""
|
||||
|
||||
start = cursor.Clone()
|
||||
cur_line_number = cursor.line
|
||||
for line in lines[start.line:]:
|
||||
if cur_line_number == start.line:
|
||||
line = line[start.column:]
|
||||
m = FindFirstInLine(line, token_table)
|
||||
if m:
|
||||
# We found a regex in line.
|
||||
(start_column, length, token_type) = m
|
||||
if cur_line_number == start.line:
|
||||
start_column += start.column
|
||||
found_start = Cursor(cur_line_number, start_column)
|
||||
found_end = found_start + length
|
||||
return MakeToken(lines, found_start, found_end, token_type)
|
||||
cur_line_number += 1
|
||||
# We failed to find str in lines
|
||||
return None
|
||||
|
||||
|
||||
def SubString(lines, start, end):
|
||||
"""Returns a substring in lines."""
|
||||
|
||||
if end == Eof():
|
||||
end = Cursor(len(lines) - 1, len(lines[-1]))
|
||||
|
||||
if start >= end:
|
||||
return ''
|
||||
|
||||
if start.line == end.line:
|
||||
return lines[start.line][start.column:end.column]
|
||||
|
||||
result_lines = ([lines[start.line][start.column:]] +
|
||||
lines[start.line + 1:end.line] +
|
||||
[lines[end.line][:end.column]])
|
||||
return ''.join(result_lines)
|
||||
|
||||
|
||||
def StripMetaComments(str):
|
||||
"""Strip meta comments from each line in the given string."""
|
||||
|
||||
# First, completely remove lines containing nothing but a meta
|
||||
# comment, including the trailing \n.
|
||||
str = re.sub(r'^\s*\$\$.*\n', '', str)
|
||||
|
||||
# Then, remove meta comments from contentful lines.
|
||||
return re.sub(r'\s*\$\$.*', '', str)
|
||||
|
||||
|
||||
def MakeToken(lines, start, end, token_type):
|
||||
"""Creates a new instance of Token."""
|
||||
|
||||
return Token(start, end, SubString(lines, start, end), token_type)
|
||||
|
||||
|
||||
def ParseToken(lines, pos, regex, token_type):
|
||||
line = lines[pos.line][pos.column:]
|
||||
m = regex.search(line)
|
||||
if m and not m.start():
|
||||
return MakeToken(lines, pos, pos + m.end(), token_type)
|
||||
else:
|
||||
print 'ERROR: %s expected at %s.' % (token_type, pos)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
ID_REGEX = re.compile(r'[_A-Za-z]\w*')
|
||||
EQ_REGEX = re.compile(r'=')
|
||||
REST_OF_LINE_REGEX = re.compile(r'.*?(?=$|\$\$)')
|
||||
OPTIONAL_WHITE_SPACES_REGEX = re.compile(r'\s*')
|
||||
WHITE_SPACE_REGEX = re.compile(r'\s')
|
||||
DOT_DOT_REGEX = re.compile(r'\.\.')
|
||||
|
||||
|
||||
def Skip(lines, pos, regex):
|
||||
line = lines[pos.line][pos.column:]
|
||||
m = re.search(regex, line)
|
||||
if m and not m.start():
|
||||
return pos + m.end()
|
||||
else:
|
||||
return pos
|
||||
|
||||
|
||||
def SkipUntil(lines, pos, regex, token_type):
|
||||
line = lines[pos.line][pos.column:]
|
||||
m = re.search(regex, line)
|
||||
if m:
|
||||
return pos + m.start()
|
||||
else:
|
||||
print ('ERROR: %s expected on line %s after column %s.' %
|
||||
(token_type, pos.line + 1, pos.column))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def ParseExpTokenInParens(lines, pos):
|
||||
def ParseInParens(pos):
|
||||
pos = Skip(lines, pos, OPTIONAL_WHITE_SPACES_REGEX)
|
||||
pos = Skip(lines, pos, r'\(')
|
||||
pos = Parse(pos)
|
||||
pos = Skip(lines, pos, r'\)')
|
||||
return pos
|
||||
|
||||
def Parse(pos):
|
||||
pos = SkipUntil(lines, pos, r'\(|\)', ')')
|
||||
if SubString(lines, pos, pos + 1) == '(':
|
||||
pos = Parse(pos + 1)
|
||||
pos = Skip(lines, pos, r'\)')
|
||||
return Parse(pos)
|
||||
else:
|
||||
return pos
|
||||
|
||||
start = pos.Clone()
|
||||
pos = ParseInParens(pos)
|
||||
return MakeToken(lines, start, pos, 'exp')
|
||||
|
||||
|
||||
def RStripNewLineFromToken(token):
|
||||
if token.value.endswith('\n'):
|
||||
return Token(token.start, token.end, token.value[:-1], token.token_type)
|
||||
else:
|
||||
return token
|
||||
|
||||
|
||||
def TokenizeLines(lines, pos):
|
||||
while True:
|
||||
found = FindFirst(lines, TOKEN_TABLE, pos)
|
||||
if not found:
|
||||
yield MakeToken(lines, pos, Eof(), 'code')
|
||||
return
|
||||
|
||||
if found.start == pos:
|
||||
prev_token = None
|
||||
prev_token_rstripped = None
|
||||
else:
|
||||
prev_token = MakeToken(lines, pos, found.start, 'code')
|
||||
prev_token_rstripped = RStripNewLineFromToken(prev_token)
|
||||
|
||||
if found.token_type == '$var':
|
||||
if prev_token_rstripped:
|
||||
yield prev_token_rstripped
|
||||
yield found
|
||||
id_token = ParseToken(lines, found.end, ID_REGEX, 'id')
|
||||
yield id_token
|
||||
pos = Skip(lines, id_token.end, OPTIONAL_WHITE_SPACES_REGEX)
|
||||
|
||||
eq_token = ParseToken(lines, pos, EQ_REGEX, '=')
|
||||
yield eq_token
|
||||
pos = Skip(lines, eq_token.end, r'\s*')
|
||||
|
||||
if SubString(lines, pos, pos + 2) != '[[':
|
||||
exp_token = ParseToken(lines, pos, REST_OF_LINE_REGEX, 'exp')
|
||||
yield exp_token
|
||||
pos = Cursor(exp_token.end.line + 1, 0)
|
||||
elif found.token_type == '$for':
|
||||
if prev_token_rstripped:
|
||||
yield prev_token_rstripped
|
||||
yield found
|
||||
id_token = ParseToken(lines, found.end, ID_REGEX, 'id')
|
||||
yield id_token
|
||||
pos = Skip(lines, id_token.end, WHITE_SPACE_REGEX)
|
||||
elif found.token_type == '$range':
|
||||
if prev_token_rstripped:
|
||||
yield prev_token_rstripped
|
||||
yield found
|
||||
id_token = ParseToken(lines, found.end, ID_REGEX, 'id')
|
||||
yield id_token
|
||||
pos = Skip(lines, id_token.end, OPTIONAL_WHITE_SPACES_REGEX)
|
||||
|
||||
dots_pos = SkipUntil(lines, pos, DOT_DOT_REGEX, '..')
|
||||
yield MakeToken(lines, pos, dots_pos, 'exp')
|
||||
yield MakeToken(lines, dots_pos, dots_pos + 2, '..')
|
||||
pos = dots_pos + 2
|
||||
new_pos = Cursor(pos.line + 1, 0)
|
||||
yield MakeToken(lines, pos, new_pos, 'exp')
|
||||
pos = new_pos
|
||||
elif found.token_type == '$':
|
||||
if prev_token:
|
||||
yield prev_token
|
||||
yield found
|
||||
exp_token = ParseExpTokenInParens(lines, found.end)
|
||||
yield exp_token
|
||||
pos = exp_token.end
|
||||
elif (found.token_type == ']]' or found.token_type == '$if' or
|
||||
found.token_type == '$elif' or found.token_type == '$else'):
|
||||
if prev_token_rstripped:
|
||||
yield prev_token_rstripped
|
||||
yield found
|
||||
pos = found.end
|
||||
else:
|
||||
if prev_token:
|
||||
yield prev_token
|
||||
yield found
|
||||
pos = found.end
|
||||
|
||||
|
||||
def Tokenize(s):
|
||||
"""A generator that yields the tokens in the given string."""
|
||||
if s != '':
|
||||
lines = s.splitlines(True)
|
||||
for token in TokenizeLines(lines, Cursor(0, 0)):
|
||||
yield token
|
||||
|
||||
|
||||
class CodeNode:
|
||||
def __init__(self, atomic_code_list=None):
|
||||
self.atomic_code = atomic_code_list
|
||||
|
||||
|
||||
class VarNode:
|
||||
def __init__(self, identifier=None, atomic_code=None):
|
||||
self.identifier = identifier
|
||||
self.atomic_code = atomic_code
|
||||
|
||||
|
||||
class RangeNode:
|
||||
def __init__(self, identifier=None, exp1=None, exp2=None):
|
||||
self.identifier = identifier
|
||||
self.exp1 = exp1
|
||||
self.exp2 = exp2
|
||||
|
||||
|
||||
class ForNode:
|
||||
def __init__(self, identifier=None, sep=None, code=None):
|
||||
self.identifier = identifier
|
||||
self.sep = sep
|
||||
self.code = code
|
||||
|
||||
|
||||
class ElseNode:
|
||||
def __init__(self, else_branch=None):
|
||||
self.else_branch = else_branch
|
||||
|
||||
|
||||
class IfNode:
|
||||
def __init__(self, exp=None, then_branch=None, else_branch=None):
|
||||
self.exp = exp
|
||||
self.then_branch = then_branch
|
||||
self.else_branch = else_branch
|
||||
|
||||
|
||||
class RawCodeNode:
|
||||
def __init__(self, token=None):
|
||||
self.raw_code = token
|
||||
|
||||
|
||||
class LiteralDollarNode:
|
||||
def __init__(self, token):
|
||||
self.token = token
|
||||
|
||||
|
||||
class ExpNode:
|
||||
def __init__(self, token, python_exp):
|
||||
self.token = token
|
||||
self.python_exp = python_exp
|
||||
|
||||
|
||||
def PopFront(a_list):
|
||||
head = a_list[0]
|
||||
a_list[:1] = []
|
||||
return head
|
||||
|
||||
|
||||
def PushFront(a_list, elem):
|
||||
a_list[:0] = [elem]
|
||||
|
||||
|
||||
def PopToken(a_list, token_type=None):
|
||||
token = PopFront(a_list)
|
||||
if token_type is not None and token.token_type != token_type:
|
||||
print 'ERROR: %s expected at %s' % (token_type, token.start)
|
||||
print 'ERROR: %s found instead' % (token,)
|
||||
sys.exit(1)
|
||||
|
||||
return token
|
||||
|
||||
|
||||
def PeekToken(a_list):
|
||||
if not a_list:
|
||||
return None
|
||||
|
||||
return a_list[0]
|
||||
|
||||
|
||||
def ParseExpNode(token):
|
||||
python_exp = re.sub(r'([_A-Za-z]\w*)', r'self.GetValue("\1")', token.value)
|
||||
return ExpNode(token, python_exp)
|
||||
|
||||
|
||||
def ParseElseNode(tokens):
|
||||
def Pop(token_type=None):
|
||||
return PopToken(tokens, token_type)
|
||||
|
||||
next = PeekToken(tokens)
|
||||
if not next:
|
||||
return None
|
||||
if next.token_type == '$else':
|
||||
Pop('$else')
|
||||
Pop('[[')
|
||||
code_node = ParseCodeNode(tokens)
|
||||
Pop(']]')
|
||||
return code_node
|
||||
elif next.token_type == '$elif':
|
||||
Pop('$elif')
|
||||
exp = Pop('code')
|
||||
Pop('[[')
|
||||
code_node = ParseCodeNode(tokens)
|
||||
Pop(']]')
|
||||
inner_else_node = ParseElseNode(tokens)
|
||||
return CodeNode([IfNode(ParseExpNode(exp), code_node, inner_else_node)])
|
||||
elif not next.value.strip():
|
||||
Pop('code')
|
||||
return ParseElseNode(tokens)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def ParseAtomicCodeNode(tokens):
|
||||
def Pop(token_type=None):
|
||||
return PopToken(tokens, token_type)
|
||||
|
||||
head = PopFront(tokens)
|
||||
t = head.token_type
|
||||
if t == 'code':
|
||||
return RawCodeNode(head)
|
||||
elif t == '$var':
|
||||
id_token = Pop('id')
|
||||
Pop('=')
|
||||
next = PeekToken(tokens)
|
||||
if next.token_type == 'exp':
|
||||
exp_token = Pop()
|
||||
return VarNode(id_token, ParseExpNode(exp_token))
|
||||
Pop('[[')
|
||||
code_node = ParseCodeNode(tokens)
|
||||
Pop(']]')
|
||||
return VarNode(id_token, code_node)
|
||||
elif t == '$for':
|
||||
id_token = Pop('id')
|
||||
next_token = PeekToken(tokens)
|
||||
if next_token.token_type == 'code':
|
||||
sep_token = next_token
|
||||
Pop('code')
|
||||
else:
|
||||
sep_token = None
|
||||
Pop('[[')
|
||||
code_node = ParseCodeNode(tokens)
|
||||
Pop(']]')
|
||||
return ForNode(id_token, sep_token, code_node)
|
||||
elif t == '$if':
|
||||
exp_token = Pop('code')
|
||||
Pop('[[')
|
||||
code_node = ParseCodeNode(tokens)
|
||||
Pop(']]')
|
||||
else_node = ParseElseNode(tokens)
|
||||
return IfNode(ParseExpNode(exp_token), code_node, else_node)
|
||||
elif t == '$range':
|
||||
id_token = Pop('id')
|
||||
exp1_token = Pop('exp')
|
||||
Pop('..')
|
||||
exp2_token = Pop('exp')
|
||||
return RangeNode(id_token, ParseExpNode(exp1_token),
|
||||
ParseExpNode(exp2_token))
|
||||
elif t == '$id':
|
||||
return ParseExpNode(Token(head.start + 1, head.end, head.value[1:], 'id'))
|
||||
elif t == '$($)':
|
||||
return LiteralDollarNode(head)
|
||||
elif t == '$':
|
||||
exp_token = Pop('exp')
|
||||
return ParseExpNode(exp_token)
|
||||
elif t == '[[':
|
||||
code_node = ParseCodeNode(tokens)
|
||||
Pop(']]')
|
||||
return code_node
|
||||
else:
|
||||
PushFront(tokens, head)
|
||||
return None
|
||||
|
||||
|
||||
def ParseCodeNode(tokens):
|
||||
atomic_code_list = []
|
||||
while True:
|
||||
if not tokens:
|
||||
break
|
||||
atomic_code_node = ParseAtomicCodeNode(tokens)
|
||||
if atomic_code_node:
|
||||
atomic_code_list.append(atomic_code_node)
|
||||
else:
|
||||
break
|
||||
return CodeNode(atomic_code_list)
|
||||
|
||||
|
||||
def ParseToAST(pump_src_text):
|
||||
"""Convert the given Pump source text into an AST."""
|
||||
tokens = list(Tokenize(pump_src_text))
|
||||
code_node = ParseCodeNode(tokens)
|
||||
return code_node
|
||||
|
||||
|
||||
class Env:
|
||||
def __init__(self):
|
||||
self.variables = []
|
||||
self.ranges = []
|
||||
|
||||
def Clone(self):
|
||||
clone = Env()
|
||||
clone.variables = self.variables[:]
|
||||
clone.ranges = self.ranges[:]
|
||||
return clone
|
||||
|
||||
def PushVariable(self, var, value):
|
||||
# If value looks like an int, store it as an int.
|
||||
try:
|
||||
int_value = int(value)
|
||||
if ('%s' % int_value) == value:
|
||||
value = int_value
|
||||
except Exception:
|
||||
pass
|
||||
self.variables[:0] = [(var, value)]
|
||||
|
||||
def PopVariable(self):
|
||||
self.variables[:1] = []
|
||||
|
||||
def PushRange(self, var, lower, upper):
|
||||
self.ranges[:0] = [(var, lower, upper)]
|
||||
|
||||
def PopRange(self):
|
||||
self.ranges[:1] = []
|
||||
|
||||
def GetValue(self, identifier):
|
||||
for (var, value) in self.variables:
|
||||
if identifier == var:
|
||||
return value
|
||||
|
||||
print 'ERROR: meta variable %s is undefined.' % (identifier,)
|
||||
sys.exit(1)
|
||||
|
||||
def EvalExp(self, exp):
|
||||
try:
|
||||
result = eval(exp.python_exp)
|
||||
except Exception, e:
|
||||
print 'ERROR: caught exception %s: %s' % (e.__class__.__name__, e)
|
||||
print ('ERROR: failed to evaluate meta expression %s at %s' %
|
||||
(exp.python_exp, exp.token.start))
|
||||
sys.exit(1)
|
||||
return result
|
||||
|
||||
def GetRange(self, identifier):
|
||||
for (var, lower, upper) in self.ranges:
|
||||
if identifier == var:
|
||||
return (lower, upper)
|
||||
|
||||
print 'ERROR: range %s is undefined.' % (identifier,)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
class Output:
|
||||
def __init__(self):
|
||||
self.string = ''
|
||||
|
||||
def GetLastLine(self):
|
||||
index = self.string.rfind('\n')
|
||||
if index < 0:
|
||||
return ''
|
||||
|
||||
return self.string[index + 1:]
|
||||
|
||||
def Append(self, s):
|
||||
self.string += s
|
||||
|
||||
|
||||
def RunAtomicCode(env, node, output):
|
||||
if isinstance(node, VarNode):
|
||||
identifier = node.identifier.value.strip()
|
||||
result = Output()
|
||||
RunAtomicCode(env.Clone(), node.atomic_code, result)
|
||||
value = result.string
|
||||
env.PushVariable(identifier, value)
|
||||
elif isinstance(node, RangeNode):
|
||||
identifier = node.identifier.value.strip()
|
||||
lower = int(env.EvalExp(node.exp1))
|
||||
upper = int(env.EvalExp(node.exp2))
|
||||
env.PushRange(identifier, lower, upper)
|
||||
elif isinstance(node, ForNode):
|
||||
identifier = node.identifier.value.strip()
|
||||
if node.sep is None:
|
||||
sep = ''
|
||||
else:
|
||||
sep = node.sep.value
|
||||
(lower, upper) = env.GetRange(identifier)
|
||||
for i in range(lower, upper + 1):
|
||||
new_env = env.Clone()
|
||||
new_env.PushVariable(identifier, i)
|
||||
RunCode(new_env, node.code, output)
|
||||
if i != upper:
|
||||
output.Append(sep)
|
||||
elif isinstance(node, RawCodeNode):
|
||||
output.Append(node.raw_code.value)
|
||||
elif isinstance(node, IfNode):
|
||||
cond = env.EvalExp(node.exp)
|
||||
if cond:
|
||||
RunCode(env.Clone(), node.then_branch, output)
|
||||
elif node.else_branch is not None:
|
||||
RunCode(env.Clone(), node.else_branch, output)
|
||||
elif isinstance(node, ExpNode):
|
||||
value = env.EvalExp(node)
|
||||
output.Append('%s' % (value,))
|
||||
elif isinstance(node, LiteralDollarNode):
|
||||
output.Append('$')
|
||||
elif isinstance(node, CodeNode):
|
||||
RunCode(env.Clone(), node, output)
|
||||
else:
|
||||
print 'BAD'
|
||||
print node
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def RunCode(env, code_node, output):
|
||||
for atomic_code in code_node.atomic_code:
|
||||
RunAtomicCode(env, atomic_code, output)
|
||||
|
||||
|
||||
def IsSingleLineComment(cur_line):
|
||||
return '//' in cur_line
|
||||
|
||||
|
||||
def IsInPreprocessorDirective(prev_lines, cur_line):
|
||||
if cur_line.lstrip().startswith('#'):
|
||||
return True
|
||||
return prev_lines and prev_lines[-1].endswith('\\')
|
||||
|
||||
|
||||
def WrapComment(line, output):
|
||||
loc = line.find('//')
|
||||
before_comment = line[:loc].rstrip()
|
||||
if before_comment == '':
|
||||
indent = loc
|
||||
else:
|
||||
output.append(before_comment)
|
||||
indent = len(before_comment) - len(before_comment.lstrip())
|
||||
prefix = indent*' ' + '// '
|
||||
max_len = 80 - len(prefix)
|
||||
comment = line[loc + 2:].strip()
|
||||
segs = [seg for seg in re.split(r'(\w+\W*)', comment) if seg != '']
|
||||
cur_line = ''
|
||||
for seg in segs:
|
||||
if len((cur_line + seg).rstrip()) < max_len:
|
||||
cur_line += seg
|
||||
else:
|
||||
if cur_line.strip() != '':
|
||||
output.append(prefix + cur_line.rstrip())
|
||||
cur_line = seg.lstrip()
|
||||
if cur_line.strip() != '':
|
||||
output.append(prefix + cur_line.strip())
|
||||
|
||||
|
||||
def WrapCode(line, line_concat, output):
|
||||
indent = len(line) - len(line.lstrip())
|
||||
prefix = indent*' ' # Prefix of the current line
|
||||
max_len = 80 - indent - len(line_concat) # Maximum length of the current line
|
||||
new_prefix = prefix + 4*' ' # Prefix of a continuation line
|
||||
new_max_len = max_len - 4 # Maximum length of a continuation line
|
||||
# Prefers to wrap a line after a ',' or ';'.
|
||||
segs = [seg for seg in re.split(r'([^,;]+[,;]?)', line.strip()) if seg != '']
|
||||
cur_line = '' # The current line without leading spaces.
|
||||
for seg in segs:
|
||||
# If the line is still too long, wrap at a space.
|
||||
while cur_line == '' and len(seg.strip()) > max_len:
|
||||
seg = seg.lstrip()
|
||||
split_at = seg.rfind(' ', 0, max_len)
|
||||
output.append(prefix + seg[:split_at].strip() + line_concat)
|
||||
seg = seg[split_at + 1:]
|
||||
prefix = new_prefix
|
||||
max_len = new_max_len
|
||||
|
||||
if len((cur_line + seg).rstrip()) < max_len:
|
||||
cur_line = (cur_line + seg).lstrip()
|
||||
else:
|
||||
output.append(prefix + cur_line.rstrip() + line_concat)
|
||||
prefix = new_prefix
|
||||
max_len = new_max_len
|
||||
cur_line = seg.lstrip()
|
||||
if cur_line.strip() != '':
|
||||
output.append(prefix + cur_line.strip())
|
||||
|
||||
|
||||
def WrapPreprocessorDirective(line, output):
|
||||
WrapCode(line, ' \\', output)
|
||||
|
||||
|
||||
def WrapPlainCode(line, output):
|
||||
WrapCode(line, '', output)
|
||||
|
||||
|
||||
def IsMultiLineIWYUPragma(line):
|
||||
return re.search(r'/\* IWYU pragma: ', line)
|
||||
|
||||
|
||||
def IsHeaderGuardIncludeOrOneLineIWYUPragma(line):
|
||||
return (re.match(r'^#(ifndef|define|endif\s*//)\s*[\w_]+\s*$', line) or
|
||||
re.match(r'^#include\s', line) or
|
||||
# Don't break IWYU pragmas, either; that causes iwyu.py problems.
|
||||
re.search(r'// IWYU pragma: ', line))
|
||||
|
||||
|
||||
def WrapLongLine(line, output):
|
||||
line = line.rstrip()
|
||||
if len(line) <= 80:
|
||||
output.append(line)
|
||||
elif IsSingleLineComment(line):
|
||||
if IsHeaderGuardIncludeOrOneLineIWYUPragma(line):
|
||||
# The style guide made an exception to allow long header guard lines,
|
||||
# includes and IWYU pragmas.
|
||||
output.append(line)
|
||||
else:
|
||||
WrapComment(line, output)
|
||||
elif IsInPreprocessorDirective(output, line):
|
||||
if IsHeaderGuardIncludeOrOneLineIWYUPragma(line):
|
||||
# The style guide made an exception to allow long header guard lines,
|
||||
# includes and IWYU pragmas.
|
||||
output.append(line)
|
||||
else:
|
||||
WrapPreprocessorDirective(line, output)
|
||||
elif IsMultiLineIWYUPragma(line):
|
||||
output.append(line)
|
||||
else:
|
||||
WrapPlainCode(line, output)
|
||||
|
||||
|
||||
def BeautifyCode(string):
|
||||
lines = string.splitlines()
|
||||
output = []
|
||||
for line in lines:
|
||||
WrapLongLine(line, output)
|
||||
output2 = [line.rstrip() for line in output]
|
||||
return '\n'.join(output2) + '\n'
|
||||
|
||||
|
||||
def ConvertFromPumpSource(src_text):
|
||||
"""Return the text generated from the given Pump source text."""
|
||||
ast = ParseToAST(StripMetaComments(src_text))
|
||||
output = Output()
|
||||
RunCode(Env(), ast, output)
|
||||
return BeautifyCode(output.string)
|
||||
|
||||
|
||||
def main(argv):
|
||||
if len(argv) == 1:
|
||||
print __doc__
|
||||
sys.exit(1)
|
||||
|
||||
file_path = argv[-1]
|
||||
output_str = ConvertFromPumpSource(file(file_path, 'r').read())
|
||||
if file_path.endswith('.pump'):
|
||||
output_file_path = file_path[:-5]
|
||||
else:
|
||||
output_file_path = '-'
|
||||
if output_file_path == '-':
|
||||
print output_str,
|
||||
else:
|
||||
output_file = file(output_file_path, 'w')
|
||||
output_file.write('// This file was GENERATED by command:\n')
|
||||
output_file.write('// %s %s\n' %
|
||||
(os.path.basename(__file__), os.path.basename(file_path)))
|
||||
output_file.write('// DO NOT EDIT BY HAND!!!\n\n')
|
||||
output_file.write(output_str)
|
||||
output_file.close()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv)
|
@@ -1,61 +0,0 @@
|
||||
// Copyright 2008, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// Tests for Google Test itself. This verifies that the basic constructs of
|
||||
// Google Test work.
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "googletest-param-test-test.h"
|
||||
|
||||
using ::testing::Values;
|
||||
using ::testing::internal::ParamGenerator;
|
||||
|
||||
// Tests that generators defined in a different translation unit
|
||||
// are functional. The test using extern_gen_2 is defined
|
||||
// in googletest-param-test-test.cc.
|
||||
ParamGenerator<int> extern_gen_2 = Values(33);
|
||||
|
||||
// Tests that a parameterized test case can be defined in one translation unit
|
||||
// and instantiated in another. The test is defined in
|
||||
// googletest-param-test-test.cc and ExternalInstantiationTest fixture class is
|
||||
// defined in gtest-param-test_test.h.
|
||||
INSTANTIATE_TEST_SUITE_P(MultiplesOf33,
|
||||
ExternalInstantiationTest,
|
||||
Values(33, 66));
|
||||
|
||||
// Tests that a parameterized test case can be instantiated
|
||||
// in multiple translation units. Another instantiation is defined
|
||||
// in googletest-param-test-test.cc and
|
||||
// InstantiationInMultipleTranslationUnitsTest fixture is defined in
|
||||
// gtest-param-test_test.h
|
||||
INSTANTIATE_TEST_SUITE_P(Sequence2,
|
||||
InstantiationInMultipleTranslationUnitsTest,
|
||||
Values(42*3, 42*4, 42*5));
|
||||
|
@@ -1,31 +0,0 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; http://docs.platformio.org/page/projectconf.html
|
||||
|
||||
|
||||
[platformio]
|
||||
#src_dir = ./googlemock
|
||||
#src_dir = ./googletest
|
||||
src_dir = .
|
||||
|
||||
[env:googletest_esp32]
|
||||
platform = espressif32
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
build_flags = -I./googletest/include -I./googletest
|
||||
src_filter = +<*> -<.git/> -<googlemock> -<googletest/codegear/> -<googletest/samples> -<googletest/test/> -<googletest/xcode> -<googletest/src> +<googletest/src/gtest-all.cc> +<googletest/src/gtest_main.cc>
|
||||
upload_speed = 921600
|
||||
|
||||
[env:googlemock_esp32]
|
||||
platform = espressif32
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
build_flags = -I./googlemock/include -I./googletest/include -I./googletest -I./googlemock
|
||||
src_filter = +<*> -<.git/> -<googletest> -<googlemock/test/> -<googlemock/src> +<googlemock/src/gmock-all.cc> +<googlemock/src/gmock_main.cc> +<googletest/src/gtest-all.cc>
|
||||
upload_speed = 921600
|
43
test/gtest-1.11.0/.github/ISSUE_TEMPLATE/00-bug_report.md
vendored
Normal file
43
test/gtest-1.11.0/.github/ISSUE_TEMPLATE/00-bug_report.md
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: 'bug'
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
|
||||
Include a clear and concise description of what the problem is, including what
|
||||
you expected to happen, and what actually happened.
|
||||
|
||||
**Steps to reproduce the bug**
|
||||
|
||||
It's important that we are able to reproduce the problem that you are
|
||||
experiencing. Please provide all code and relevant steps to reproduce the
|
||||
problem, including your `BUILD`/`CMakeLists.txt` file and build commands. Links
|
||||
to a GitHub branch or [godbolt.org](https://godbolt.org/) that demonstrate the
|
||||
problem are also helpful.
|
||||
|
||||
**Does the bug persist in the most recent commit?**
|
||||
|
||||
We recommend using the latest commit in the master branch in your projects.
|
||||
|
||||
**What operating system and version are you using?**
|
||||
|
||||
If you are using a Linux distribution please include the name and version of the
|
||||
distribution as well.
|
||||
|
||||
**What compiler and version are you using?**
|
||||
|
||||
Please include the output of `gcc -v` or `clang -v`, or the equivalent for your
|
||||
compiler.
|
||||
|
||||
**What build system are you using?**
|
||||
|
||||
Please include the output of `bazel --version` or `cmake --version`, or the
|
||||
equivalent for your build system.
|
||||
|
||||
**Additional context**
|
||||
|
||||
Add any other context about the problem here.
|
24
test/gtest-1.11.0/.github/ISSUE_TEMPLATE/10-feature_request.md
vendored
Normal file
24
test/gtest-1.11.0/.github/ISSUE_TEMPLATE/10-feature_request.md
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Propose a new feature
|
||||
title: ''
|
||||
labels: 'enhancement'
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
**Does the feature exist in the most recent commit?**
|
||||
|
||||
We recommend using the latest commit from GitHub in your projects.
|
||||
|
||||
**Why do we need this feature?**
|
||||
|
||||
Ideally, explain why a combination of existing features cannot be used instead.
|
||||
|
||||
**Describe the proposal**
|
||||
|
||||
Include a detailed description of the feature, with usage examples.
|
||||
|
||||
**Is the feature specific to an operating system, compiler, or build system version?**
|
||||
|
||||
If it is, please specify which versions.
|
||||
|
1
test/gtest-1.11.0/.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
1
test/gtest-1.11.0/.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
blank_issues_enabled: false
|
@@ -36,9 +36,19 @@ package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
exports_files(["LICENSE"])
|
||||
|
||||
config_setting(
|
||||
name = "windows",
|
||||
constraint_values = ["@bazel_tools//platforms:windows"],
|
||||
constraint_values = ["@platforms//os:windows"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "msvc_compiler",
|
||||
flag_values = {
|
||||
"@bazel_tools//tools/cpp:compiler": "msvc-cl",
|
||||
},
|
||||
visibility = [":__subpackages__"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
@@ -103,6 +113,7 @@ cc_library(
|
||||
"@com_google_absl//absl/debugging:stacktrace",
|
||||
"@com_google_absl//absl/debugging:symbolize",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/types:any",
|
||||
"@com_google_absl//absl/types:optional",
|
||||
"@com_google_absl//absl/types:variant",
|
||||
],
|
@@ -1,21 +1,17 @@
|
||||
# Note: CMake support is community-based. The maintainers do not use CMake
|
||||
# internally.
|
||||
|
||||
cmake_minimum_required(VERSION 2.9)
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
|
||||
if (POLICY CMP0048)
|
||||
cmake_policy(SET CMP0048 NEW)
|
||||
endif (POLICY CMP0048)
|
||||
|
||||
project(googletest-distribution)
|
||||
set(GOOGLETEST_VERSION 1.10.0)
|
||||
set(GOOGLETEST_VERSION 1.11.0)
|
||||
|
||||
if (CMAKE_VERSION VERSION_LESS "3.1")
|
||||
add_definitions(-std=c++11)
|
||||
else()
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
if(NOT CYGWIN)
|
||||
if (CMAKE_VERSION VERSION_GREATER "3.0.2")
|
||||
if(NOT CYGWIN AND NOT MSYS AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL QNX)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
endif()
|
||||
endif()
|
@@ -28,7 +28,7 @@ PR is acceptable as an alternative.
|
||||
## Contributing A Patch
|
||||
|
||||
1. Submit an issue describing your proposed change to the
|
||||
[issue tracker](https://github.com/google/googletest).
|
||||
[issue tracker](https://github.com/google/googletest/issues).
|
||||
2. Please don't mix more than one logical change per submittal, because it
|
||||
makes the history hard to follow. If you want to make a change that doesn't
|
||||
have a corresponding issue in the issue tracker, please create one.
|
||||
@@ -80,7 +80,7 @@ fairly rigid coding style, as defined by the
|
||||
will be expected to conform to the style outlined
|
||||
[here](https://google.github.io/styleguide/cppguide.html). Use
|
||||
[.clang-format](https://github.com/google/googletest/blob/master/.clang-format)
|
||||
to check your formatting
|
||||
to check your formatting.
|
||||
|
||||
## Requirements for Contributors
|
||||
|
||||
@@ -89,7 +89,7 @@ and their own tests from a git checkout, which has further requirements:
|
||||
|
||||
* [Python](https://www.python.org/) v2.3 or newer (for running some of the
|
||||
tests and re-generating certain source files from templates)
|
||||
* [CMake](https://cmake.org/) v2.6.4 or newer
|
||||
* [CMake](https://cmake.org/) v2.8.12 or newer
|
||||
|
||||
## Developing Google Test and Google Mock
|
||||
|
||||
@@ -128,15 +128,3 @@ To run the tests, do
|
||||
make test
|
||||
|
||||
All tests should pass.
|
||||
|
||||
### Regenerating Source Files
|
||||
|
||||
Some of Google Test's source files are generated from templates (not in the C++
|
||||
sense) using a script. For example, the file
|
||||
include/gtest/internal/gtest-type-util.h.pump is used to generate
|
||||
gtest-type-util.h in the same directory.
|
||||
|
||||
You don't need to worry about regenerating the source files unless you need to
|
||||
modify them. You would then modify the corresponding `.pump` files and run the
|
||||
'[pump.py](googletest/scripts/pump.py)' generator script. See the
|
||||
[Pump Manual](googletest/docs/pump_manual.md).
|
@@ -5,33 +5,59 @@
|
||||
|
||||
Ajay Joshi <jaj@google.com>
|
||||
Balázs Dán <balazs.dan@gmail.com>
|
||||
Benoit Sigoure <tsuna@google.com>
|
||||
Bharat Mediratta <bharat@menalto.com>
|
||||
Bogdan Piloca <boo@google.com>
|
||||
Chandler Carruth <chandlerc@google.com>
|
||||
Chris Prince <cprince@google.com>
|
||||
Chris Taylor <taylorc@google.com>
|
||||
Dan Egnor <egnor@google.com>
|
||||
Dave MacLachlan <dmaclach@gmail.com>
|
||||
David Anderson <danderson@google.com>
|
||||
Dean Sturtevant
|
||||
Eric Roman <eroman@chromium.org>
|
||||
Gene Volovich <gv@cite.com>
|
||||
Hady Zalek <hady.zalek@gmail.com>
|
||||
Hal Burch <gmock@hburch.com>
|
||||
Jeffrey Yasskin <jyasskin@google.com>
|
||||
Jim Keller <jimkeller@google.com>
|
||||
Joe Walnes <joe@truemesh.com>
|
||||
Jon Wray <jwray@google.com>
|
||||
Jói Sigurðsson <joi@google.com>
|
||||
Keir Mierle <mierle@gmail.com>
|
||||
Keith Ray <keith.ray@gmail.com>
|
||||
Kenton Varda <kenton@google.com>
|
||||
Kostya Serebryany <kcc@google.com>
|
||||
Krystian Kuzniarek <krystian.kuzniarek@gmail.com>
|
||||
Lev Makhlis
|
||||
Manuel Klimek <klimek@google.com>
|
||||
Mario Tanev <radix@google.com>
|
||||
Mark Paskin
|
||||
Markus Heule <markus.heule@gmail.com>
|
||||
Matthew Simmons <simmonmt@acm.org>
|
||||
Mika Raento <mikie@iki.fi>
|
||||
Mike Bland <mbland@google.com>
|
||||
Miklós Fazekas <mfazekas@szemafor.com>
|
||||
Neal Norwitz <nnorwitz@gmail.com>
|
||||
Nermin Ozkiranartli <nermin@google.com>
|
||||
Owen Carlsen <ocarlsen@google.com>
|
||||
Paneendra Ba <paneendra@google.com>
|
||||
Pasi Valminen <pasi.valminen@gmail.com>
|
||||
Patrick Hanna <phanna@google.com>
|
||||
Patrick Riley <pfr@google.com>
|
||||
Paul Menage <menage@google.com>
|
||||
Peter Kaminski <piotrk@google.com>
|
||||
Piotr Kaminski <piotrk@google.com>
|
||||
Preston Jackson <preston.a.jackson@gmail.com>
|
||||
Rainer Klaffenboeck <rainer.klaffenboeck@dynatrace.com>
|
||||
Russ Cox <rsc@google.com>
|
||||
Russ Rufer <russ@pentad.com>
|
||||
Sean Mcafee <eefacm@gmail.com>
|
||||
Sigurður Ásgeirsson <siggi@google.com>
|
||||
Sverre Sundsdal <sundsdal@gmail.com>
|
||||
Takeshi Yoshino <tyoshino@google.com>
|
||||
Tracy Bialik <tracy@pentad.com>
|
||||
Vadim Berman <vadimb@google.com>
|
||||
Vlad Losev <vladl@google.com>
|
||||
Wolfgang Klier <wklier@google.com>
|
||||
Zhanyong Wan <wan@google.com>
|
140
test/gtest-1.11.0/README.md
Normal file
140
test/gtest-1.11.0/README.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# GoogleTest
|
||||
|
||||
### Announcements
|
||||
|
||||
#### Live at Head
|
||||
|
||||
GoogleTest now follows the
|
||||
[Abseil Live at Head philosophy](https://abseil.io/about/philosophy#upgrade-support).
|
||||
We recommend using the latest commit in the `master` branch in your projects.
|
||||
|
||||
#### Documentation Updates
|
||||
|
||||
Our documentation is now live on GitHub Pages at
|
||||
https://google.github.io/googletest/. We recommend browsing the documentation on
|
||||
GitHub Pages rather than directly in the repository.
|
||||
|
||||
#### Release 1.10.x
|
||||
|
||||
[Release 1.10.x](https://github.com/google/googletest/releases/tag/release-1.10.0)
|
||||
is now available.
|
||||
|
||||
#### Coming Soon
|
||||
|
||||
* We are planning to take a dependency on
|
||||
[Abseil](https://github.com/abseil/abseil-cpp).
|
||||
* More documentation improvements are planned.
|
||||
|
||||
## Welcome to **GoogleTest**, Google's C++ test framework!
|
||||
|
||||
This repository is a merger of the formerly separate GoogleTest and GoogleMock
|
||||
projects. These were so closely related that it makes sense to maintain and
|
||||
release them together.
|
||||
|
||||
### Getting Started
|
||||
|
||||
See the [GoogleTest User's Guide](https://google.github.io/googletest/) for
|
||||
documentation. We recommend starting with the
|
||||
[GoogleTest Primer](https://google.github.io/googletest/primer.html).
|
||||
|
||||
More information about building GoogleTest can be found at
|
||||
[googletest/README.md](googletest/README.md).
|
||||
|
||||
## Features
|
||||
|
||||
* An [xUnit](https://en.wikipedia.org/wiki/XUnit) test framework.
|
||||
* Test discovery.
|
||||
* A rich set of assertions.
|
||||
* User-defined assertions.
|
||||
* Death tests.
|
||||
* Fatal and non-fatal failures.
|
||||
* Value-parameterized tests.
|
||||
* Type-parameterized tests.
|
||||
* Various options for running the tests.
|
||||
* XML test report generation.
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
GoogleTest requires a codebase and compiler compliant with the C++11 standard or
|
||||
newer.
|
||||
|
||||
The GoogleTest code is officially supported on the following platforms.
|
||||
Operating systems or tools not listed below are community-supported. For
|
||||
community-supported platforms, patches that do not complicate the code may be
|
||||
considered.
|
||||
|
||||
If you notice any problems on your platform, please file an issue on the
|
||||
[GoogleTest GitHub Issue Tracker](https://github.com/google/googletest/issues).
|
||||
Pull requests containing fixes are welcome!
|
||||
|
||||
### Operating Systems
|
||||
|
||||
* Linux
|
||||
* macOS
|
||||
* Windows
|
||||
|
||||
### Compilers
|
||||
|
||||
* gcc 5.0+
|
||||
* clang 5.0+
|
||||
* MSVC 2015+
|
||||
|
||||
**macOS users:** Xcode 9.3+ provides clang 5.0+.
|
||||
|
||||
### Build Systems
|
||||
|
||||
* [Bazel](https://bazel.build/)
|
||||
* [CMake](https://cmake.org/)
|
||||
|
||||
**Note:** Bazel is the build system used by the team internally and in tests.
|
||||
CMake is supported on a best-effort basis and by the community.
|
||||
|
||||
## Who Is Using GoogleTest?
|
||||
|
||||
In addition to many internal projects at Google, GoogleTest is also used by the
|
||||
following notable projects:
|
||||
|
||||
* The [Chromium projects](http://www.chromium.org/) (behind the Chrome browser
|
||||
and Chrome OS).
|
||||
* The [LLVM](http://llvm.org/) compiler.
|
||||
* [Protocol Buffers](https://github.com/google/protobuf), Google's data
|
||||
interchange format.
|
||||
* The [OpenCV](http://opencv.org/) computer vision library.
|
||||
|
||||
## Related Open Source Projects
|
||||
|
||||
[GTest Runner](https://github.com/nholthaus/gtest-runner) is a Qt5 based
|
||||
automated test-runner and Graphical User Interface with powerful features for
|
||||
Windows and Linux platforms.
|
||||
|
||||
[GoogleTest UI](https://github.com/ospector/gtest-gbar) is a test runner that
|
||||
runs your test binary, allows you to track its progress via a progress bar, and
|
||||
displays a list of test failures. Clicking on one shows failure text. Google
|
||||
Test UI is written in C#.
|
||||
|
||||
[GTest TAP Listener](https://github.com/kinow/gtest-tap-listener) is an event
|
||||
listener for GoogleTest that implements the
|
||||
[TAP protocol](https://en.wikipedia.org/wiki/Test_Anything_Protocol) for test
|
||||
result output. If your test runner understands TAP, you may find it useful.
|
||||
|
||||
[gtest-parallel](https://github.com/google/gtest-parallel) is a test runner that
|
||||
runs tests from your binary in parallel to provide significant speed-up.
|
||||
|
||||
[GoogleTest Adapter](https://marketplace.visualstudio.com/items?itemName=DavidSchuldenfrei.gtest-adapter)
|
||||
is a VS Code extension allowing to view GoogleTest in a tree view, and run/debug
|
||||
your tests.
|
||||
|
||||
[C++ TestMate](https://github.com/matepek/vscode-catch2-test-adapter) is a VS
|
||||
Code extension allowing to view GoogleTest in a tree view, and run/debug your
|
||||
tests.
|
||||
|
||||
[Cornichon](https://pypi.org/project/cornichon/) is a small Gherkin DSL parser
|
||||
that generates stub code for GoogleTest.
|
||||
|
||||
## Contributing Changes
|
||||
|
||||
Please read
|
||||
[`CONTRIBUTING.md`](https://github.com/google/googletest/blob/master/CONTRIBUTING.md)
|
||||
for details on how to contribute to this project.
|
||||
|
||||
Happy testing!
|
24
test/gtest-1.11.0/WORKSPACE
Normal file
24
test/gtest-1.11.0/WORKSPACE
Normal file
@@ -0,0 +1,24 @@
|
||||
workspace(name = "com_google_googletest")
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
http_archive(
|
||||
name = "com_google_absl",
|
||||
urls = ["https://github.com/abseil/abseil-cpp/archive/7971fb358ae376e016d2d4fc9327aad95659b25e.zip"], # 2021-05-20T02:59:16Z
|
||||
strip_prefix = "abseil-cpp-7971fb358ae376e016d2d4fc9327aad95659b25e",
|
||||
sha256 = "aeba534f7307e36fe084b452299e49b97420667a8d28102cf9a0daeed340b859",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "rules_cc",
|
||||
urls = ["https://github.com/bazelbuild/rules_cc/archive/68cb652a71e7e7e2858c50593e5a9e3b94e5b9a9.zip"], # 2021-05-14T14:51:14Z
|
||||
strip_prefix = "rules_cc-68cb652a71e7e7e2858c50593e5a9e3b94e5b9a9",
|
||||
sha256 = "1e19e9a3bc3d4ee91d7fcad00653485ee6c798efbbf9588d40b34cbfbded143d",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "rules_python",
|
||||
urls = ["https://github.com/bazelbuild/rules_python/archive/ed6cc8f2c3692a6a7f013ff8bc185ba77eb9b4d2.zip"], # 2021-05-17T00:24:16Z
|
||||
strip_prefix = "rules_python-ed6cc8f2c3692a6a7f013ff8bc185ba77eb9b4d2",
|
||||
sha256 = "98b3c592faea9636ac8444bfd9de7f3fb4c60590932d6e6ac5946e3f8dbd5ff6",
|
||||
)
|
126
test/gtest-1.11.0/ci/linux-presubmit.sh
Normal file
126
test/gtest-1.11.0/ci/linux-presubmit.sh
Normal file
@@ -0,0 +1,126 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright 2020, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
set -euox pipefail
|
||||
|
||||
readonly LINUX_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20210525"
|
||||
readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20201015"
|
||||
|
||||
if [[ -z ${GTEST_ROOT:-} ]]; then
|
||||
GTEST_ROOT="$(realpath $(dirname ${0})/..)"
|
||||
fi
|
||||
|
||||
if [[ -z ${STD:-} ]]; then
|
||||
STD="c++11 c++14 c++17 c++20"
|
||||
fi
|
||||
|
||||
# Test the CMake build
|
||||
for cc in /usr/local/bin/gcc /opt/llvm/clang/bin/clang; do
|
||||
for cmake_off_on in OFF ON; do
|
||||
time docker run \
|
||||
--volume="${GTEST_ROOT}:/src:ro" \
|
||||
--tmpfs="/build:exec" \
|
||||
--workdir="/build" \
|
||||
--rm \
|
||||
--env="CC=${cc}" \
|
||||
--env="CXX_FLAGS=\"-Werror -Wdeprecated\"" \
|
||||
${LINUX_LATEST_CONTAINER} \
|
||||
/bin/bash -c "
|
||||
cmake /src \
|
||||
-DCMAKE_CXX_STANDARD=11 \
|
||||
-Dgtest_build_samples=ON \
|
||||
-Dgtest_build_tests=ON \
|
||||
-Dgmock_build_tests=ON \
|
||||
-Dcxx_no_exception=${cmake_off_on} \
|
||||
-Dcxx_no_rtti=${cmake_off_on} && \
|
||||
make -j$(nproc) && \
|
||||
ctest -j$(nproc) --output-on-failure"
|
||||
done
|
||||
done
|
||||
|
||||
# Do one test with an older version of GCC
|
||||
time docker run \
|
||||
--volume="${GTEST_ROOT}:/src:ro" \
|
||||
--workdir="/src" \
|
||||
--rm \
|
||||
--env="CC=/usr/local/bin/gcc" \
|
||||
${LINUX_GCC_FLOOR_CONTAINER} \
|
||||
/usr/local/bin/bazel test ... \
|
||||
--copt="-Wall" \
|
||||
--copt="-Werror" \
|
||||
--copt="-Wno-error=pragmas" \
|
||||
--keep_going \
|
||||
--show_timestamps \
|
||||
--test_output=errors
|
||||
|
||||
# Test GCC
|
||||
for std in ${STD}; do
|
||||
for absl in 0 1; do
|
||||
time docker run \
|
||||
--volume="${GTEST_ROOT}:/src:ro" \
|
||||
--workdir="/src" \
|
||||
--rm \
|
||||
--env="CC=/usr/local/bin/gcc" \
|
||||
--env="BAZEL_CXXOPTS=-std=${std}" \
|
||||
${LINUX_LATEST_CONTAINER} \
|
||||
/usr/local/bin/bazel test ... \
|
||||
--copt="-Wall" \
|
||||
--copt="-Werror" \
|
||||
--define="absl=${absl}" \
|
||||
--distdir="/bazel-distdir" \
|
||||
--keep_going \
|
||||
--show_timestamps \
|
||||
--test_output=errors
|
||||
done
|
||||
done
|
||||
|
||||
# Test Clang
|
||||
for std in ${STD}; do
|
||||
for absl in 0 1; do
|
||||
time docker run \
|
||||
--volume="${GTEST_ROOT}:/src:ro" \
|
||||
--workdir="/src" \
|
||||
--rm \
|
||||
--env="CC=/opt/llvm/clang/bin/clang" \
|
||||
--env="BAZEL_CXXOPTS=-std=${std}" \
|
||||
${LINUX_LATEST_CONTAINER} \
|
||||
/usr/local/bin/bazel test ... \
|
||||
--copt="--gcc-toolchain=/usr/local" \
|
||||
--copt="-Wall" \
|
||||
--copt="-Werror" \
|
||||
--define="absl=${absl}" \
|
||||
--distdir="/bazel-distdir" \
|
||||
--keep_going \
|
||||
--linkopt="--gcc-toolchain=/usr/local" \
|
||||
--show_timestamps \
|
||||
--test_output=errors
|
||||
done
|
||||
done
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2017 Google Inc.
|
||||
# All Rights Reserved.
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright 2020, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
@@ -29,20 +29,45 @@
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# This file is typically sourced by another script.
|
||||
# if possible, ask for the precise number of processors,
|
||||
# otherwise take 2 processors as reasonable default; see
|
||||
# https://docs.travis-ci.com/user/speeding-up-the-build/#Makefile-optimization
|
||||
if [ -x /usr/bin/getconf ]; then
|
||||
NPROCESSORS=$(/usr/bin/getconf _NPROCESSORS_ONLN)
|
||||
else
|
||||
NPROCESSORS=2
|
||||
set -euox pipefail
|
||||
|
||||
if [[ -z ${GTEST_ROOT:-} ]]; then
|
||||
GTEST_ROOT="$(realpath $(dirname ${0})/..)"
|
||||
fi
|
||||
|
||||
# as of 2017-09-04 Travis CI reports 32 processors, but GCC build
|
||||
# crashes if parallelized too much (maybe memory consumption problem),
|
||||
# so limit to 4 processors for the time being.
|
||||
if [ $NPROCESSORS -gt 4 ] ; then
|
||||
echo "$0:Note: Limiting processors to use by make from $NPROCESSORS to 4."
|
||||
NPROCESSORS=4
|
||||
# Test the CMake build
|
||||
for cmake_off_on in OFF ON; do
|
||||
BUILD_DIR=$(mktemp -d build_dir.XXXXXXXX)
|
||||
cd ${BUILD_DIR}
|
||||
time cmake ${GTEST_ROOT} \
|
||||
-DCMAKE_CXX_STANDARD=11 \
|
||||
-Dgtest_build_samples=ON \
|
||||
-Dgtest_build_tests=ON \
|
||||
-Dgmock_build_tests=ON \
|
||||
-Dcxx_no_exception=${cmake_off_on} \
|
||||
-Dcxx_no_rtti=${cmake_off_on}
|
||||
time make
|
||||
time ctest -j$(nproc) --output-on-failure
|
||||
done
|
||||
|
||||
# Test the Bazel build
|
||||
|
||||
# If we are running on Kokoro, check for a versioned Bazel binary.
|
||||
KOKORO_GFILE_BAZEL_BIN="bazel-3.7.0-darwin-x86_64"
|
||||
if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]]; then
|
||||
BAZEL_BIN="${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN}"
|
||||
chmod +x ${BAZEL_BIN}
|
||||
else
|
||||
BAZEL_BIN="bazel"
|
||||
fi
|
||||
|
||||
cd ${GTEST_ROOT}
|
||||
for absl in 0 1; do
|
||||
${BAZEL_BIN} test ... \
|
||||
--copt="-Wall" \
|
||||
--copt="-Werror" \
|
||||
--define="absl=${absl}" \
|
||||
--keep_going \
|
||||
--show_timestamps \
|
||||
--test_output=errors
|
||||
done
|
1
test/gtest-1.11.0/docs/_config.yml
Normal file
1
test/gtest-1.11.0/docs/_config.yml
Normal file
@@ -0,0 +1 @@
|
||||
title: GoogleTest
|
43
test/gtest-1.11.0/docs/_data/navigation.yml
Normal file
43
test/gtest-1.11.0/docs/_data/navigation.yml
Normal file
@@ -0,0 +1,43 @@
|
||||
nav:
|
||||
- section: "Get Started"
|
||||
items:
|
||||
- title: "Supported Platforms"
|
||||
url: "/platforms.html"
|
||||
- title: "Quickstart: Bazel"
|
||||
url: "/quickstart-bazel.html"
|
||||
- title: "Quickstart: CMake"
|
||||
url: "/quickstart-cmake.html"
|
||||
- section: "Guides"
|
||||
items:
|
||||
- title: "GoogleTest Primer"
|
||||
url: "/primer.html"
|
||||
- title: "Advanced Topics"
|
||||
url: "/advanced.html"
|
||||
- title: "Mocking for Dummies"
|
||||
url: "/gmock_for_dummies.html"
|
||||
- title: "Mocking Cookbook"
|
||||
url: "/gmock_cook_book.html"
|
||||
- title: "Mocking Cheat Sheet"
|
||||
url: "/gmock_cheat_sheet.html"
|
||||
- section: "References"
|
||||
items:
|
||||
- title: "Testing Reference"
|
||||
url: "/reference/testing.html"
|
||||
- title: "Mocking Reference"
|
||||
url: "/reference/mocking.html"
|
||||
- title: "Assertions"
|
||||
url: "/reference/assertions.html"
|
||||
- title: "Matchers"
|
||||
url: "/reference/matchers.html"
|
||||
- title: "Actions"
|
||||
url: "/reference/actions.html"
|
||||
- title: "Testing FAQ"
|
||||
url: "/faq.html"
|
||||
- title: "Mocking FAQ"
|
||||
url: "/gmock_faq.html"
|
||||
- title: "Code Samples"
|
||||
url: "/samples.html"
|
||||
- title: "Using pkg-config"
|
||||
url: "/pkgconfig.html"
|
||||
- title: "Community Documentation"
|
||||
url: "/community_created_documentation.html"
|
58
test/gtest-1.11.0/docs/_layouts/default.html
Normal file
58
test/gtest-1.11.0/docs/_layouts/default.html
Normal file
@@ -0,0 +1,58 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ site.lang | default: "en-US" }}">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
{% seo %}
|
||||
<link rel="stylesheet" href="{{ "/assets/css/style.css?v=" | append: site.github.build_revision | relative_url }}">
|
||||
<script>
|
||||
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
|
||||
ga('create', 'UA-197576187-1', { 'storage': 'none' });
|
||||
ga('set', 'referrer', document.referrer.split('?')[0]);
|
||||
ga('set', 'location', window.location.href.split('?')[0]);
|
||||
ga('set', 'anonymizeIp', true);
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
<script async src='https://www.google-analytics.com/analytics.js'></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="sidebar">
|
||||
<div class="header">
|
||||
<h1><a href="{{ "/" | relative_url }}">{{ site.title | default: "Documentation" }}</a></h1>
|
||||
</div>
|
||||
<input type="checkbox" id="nav-toggle" class="nav-toggle">
|
||||
<label for="nav-toggle" class="expander">
|
||||
<span class="arrow"></span>
|
||||
</label>
|
||||
<nav>
|
||||
{% for item in site.data.navigation.nav %}
|
||||
<h2>{{ item.section }}</h2>
|
||||
<ul>
|
||||
{% for subitem in item.items %}
|
||||
<a href="{{subitem.url | relative_url }}">
|
||||
<li class="{% if subitem.url == page.url %}active{% endif %}">
|
||||
{{ subitem.title }}
|
||||
</li>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endfor %}
|
||||
</nav>
|
||||
</div>
|
||||
<div class="main markdown-body">
|
||||
<div class="main-inner">
|
||||
{{ content }}
|
||||
</div>
|
||||
<div class="footer">
|
||||
GoogleTest ·
|
||||
<a href="https://github.com/google/googletest">GitHub Repository</a> ·
|
||||
<a href="https://github.com/google/googletest/blob/master/LICENSE">License</a> ·
|
||||
<a href="https://policies.google.com/privacy">Privacy Policy</a>
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/anchor-js/4.1.0/anchor.min.js" integrity="sha256-lZaRhKri35AyJSypXXs4o6OPFTbTmUoltBbDCbdzegg=" crossorigin="anonymous"></script>
|
||||
<script>anchors.add('.main h2, .main h3, .main h4, .main h5, .main h6');</script>
|
||||
</body>
|
||||
</html>
|
200
test/gtest-1.11.0/docs/_sass/main.scss
Normal file
200
test/gtest-1.11.0/docs/_sass/main.scss
Normal file
@@ -0,0 +1,200 @@
|
||||
// Styles for GoogleTest docs website on GitHub Pages.
|
||||
// Color variables are defined in
|
||||
// https://github.com/pages-themes/primer/tree/master/_sass/primer-support/lib/variables
|
||||
|
||||
$sidebar-width: 260px;
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
background: $black;
|
||||
color: $text-white;
|
||||
flex-shrink: 0;
|
||||
height: 100vh;
|
||||
overflow: auto;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
width: $sidebar-width;
|
||||
}
|
||||
|
||||
.sidebar h1 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
.sidebar h2 {
|
||||
color: $gray-light;
|
||||
font-size: 0.8em;
|
||||
font-weight: normal;
|
||||
margin-bottom: 0.8em;
|
||||
padding-left: 2.5em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.sidebar .header {
|
||||
background: $black;
|
||||
padding: 2em;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sidebar .header a {
|
||||
color: $text-white;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.sidebar .nav-toggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sidebar .expander {
|
||||
cursor: pointer;
|
||||
display: none;
|
||||
height: 3em;
|
||||
position: absolute;
|
||||
right: 1em;
|
||||
top: 1.5em;
|
||||
width: 3em;
|
||||
}
|
||||
|
||||
.sidebar .expander .arrow {
|
||||
border: solid $white;
|
||||
border-width: 0 3px 3px 0;
|
||||
display: block;
|
||||
height: 0.7em;
|
||||
margin: 1em auto;
|
||||
transform: rotate(45deg);
|
||||
transition: transform 0.5s;
|
||||
width: 0.7em;
|
||||
}
|
||||
|
||||
.sidebar nav {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sidebar nav ul {
|
||||
list-style-type: none;
|
||||
margin-bottom: 1em;
|
||||
padding: 0;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
li {
|
||||
color: $text-white;
|
||||
padding-left: 2em;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
li.active {
|
||||
background: $border-gray-darker;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
li:hover {
|
||||
background: $border-gray-darker;
|
||||
}
|
||||
}
|
||||
|
||||
.main {
|
||||
background-color: $bg-gray;
|
||||
width: calc(100% - #{$sidebar-width});
|
||||
}
|
||||
|
||||
.main .main-inner {
|
||||
background-color: $white;
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
.main .footer {
|
||||
margin: 0;
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
.main table th {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.main .callout {
|
||||
border-left: 0.25em solid $white;
|
||||
padding: 1em;
|
||||
|
||||
a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
&.important {
|
||||
background-color: $bg-yellow-light;
|
||||
border-color: $bg-yellow;
|
||||
color: $black;
|
||||
}
|
||||
|
||||
&.note {
|
||||
background-color: $bg-blue-light;
|
||||
border-color: $text-blue;
|
||||
color: $text-blue;
|
||||
}
|
||||
|
||||
&.tip {
|
||||
background-color: $green-000;
|
||||
border-color: $green-700;
|
||||
color: $green-700;
|
||||
}
|
||||
|
||||
&.warning {
|
||||
background-color: $red-000;
|
||||
border-color: $text-red;
|
||||
color: $text-red;
|
||||
}
|
||||
}
|
||||
|
||||
.main .good pre {
|
||||
background-color: $bg-green-light;
|
||||
}
|
||||
|
||||
.main .bad pre {
|
||||
background-color: $red-000;
|
||||
}
|
||||
|
||||
@media all and (max-width: 768px) {
|
||||
body {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
height: auto;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sidebar .expander {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.sidebar nav {
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.sidebar .nav-toggle:checked {
|
||||
& ~ nav {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
& + .expander .arrow {
|
||||
transform: rotate(-135deg);
|
||||
}
|
||||
}
|
||||
|
||||
.main {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
5
test/gtest-1.11.0/docs/assets/css/style.scss
Normal file
5
test/gtest-1.11.0/docs/assets/css/style.scss
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
---
|
||||
|
||||
@import "jekyll-theme-primer";
|
||||
@import "main";
|
@@ -0,0 +1,7 @@
|
||||
# Community-Created Documentation
|
||||
|
||||
The following is a list, in no particular order, of links to documentation
|
||||
created by the Googletest community.
|
||||
|
||||
* [Googlemock Insights](https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles/blob/master/googletest/insights.md),
|
||||
by [ElectricRCAircraftGuy](https://github.com/ElectricRCAircraftGuy)
|
@@ -1,9 +1,12 @@
|
||||
# Googletest FAQ
|
||||
|
||||
<!-- GOOGLETEST_CM0014 DO NOT DELETE -->
|
||||
|
||||
## Why should test suite names and test names not contain underscore?
|
||||
|
||||
{: .callout .note}
|
||||
Note: Googletest reserves underscore (`_`) for special purpose keywords, such as
|
||||
[the `DISABLED_` prefix](advanced.md#temporarily-disabling-tests), in addition
|
||||
to the following rationale.
|
||||
|
||||
Underscore (`_`) is special, as C++ reserves the following to be used by the
|
||||
compiler and the standard library:
|
||||
|
||||
@@ -57,9 +60,10 @@ the rule.
|
||||
|
||||
## Why does googletest support `EXPECT_EQ(NULL, ptr)` and `ASSERT_EQ(NULL, ptr)` but not `EXPECT_NE(NULL, ptr)` and `ASSERT_NE(NULL, ptr)`?
|
||||
|
||||
First of all you can use `EXPECT_NE(nullptr, ptr)` and `ASSERT_NE(nullptr,
|
||||
ptr)`. This is the preferred syntax in the style guide because nullptr does not
|
||||
have the type problems that NULL does. Which is why NULL does not work.
|
||||
First of all, you can use `nullptr` with each of these macros, e.g.
|
||||
`EXPECT_EQ(ptr, nullptr)`, `EXPECT_NE(ptr, nullptr)`, `ASSERT_EQ(ptr, nullptr)`,
|
||||
`ASSERT_NE(ptr, nullptr)`. This is the preferred syntax in the style guide
|
||||
because `nullptr` does not have the type problems that `NULL` does.
|
||||
|
||||
Due to some peculiarity of C++, it requires some non-trivial template meta
|
||||
programming tricks to support using `NULL` as an argument of the `EXPECT_XX()`
|
||||
@@ -67,22 +71,21 @@ and `ASSERT_XX()` macros. Therefore we only do it where it's most needed
|
||||
(otherwise we make the implementation of googletest harder to maintain and more
|
||||
error-prone than necessary).
|
||||
|
||||
The `EXPECT_EQ()` macro takes the *expected* value as its first argument and the
|
||||
*actual* value as the second. It's reasonable that someone wants to write
|
||||
`EXPECT_EQ(NULL, some_expression)`, and this indeed was requested several times.
|
||||
Therefore we implemented it.
|
||||
Historically, the `EXPECT_EQ()` macro took the *expected* value as its first
|
||||
argument and the *actual* value as the second, though this argument order is now
|
||||
discouraged. It was reasonable that someone wanted
|
||||
to write `EXPECT_EQ(NULL, some_expression)`, and this indeed was requested
|
||||
several times. Therefore we implemented it.
|
||||
|
||||
The need for `EXPECT_NE(NULL, ptr)` isn't nearly as strong. When the assertion
|
||||
The need for `EXPECT_NE(NULL, ptr)` wasn't nearly as strong. When the assertion
|
||||
fails, you already know that `ptr` must be `NULL`, so it doesn't add any
|
||||
information to print `ptr` in this case. That means `EXPECT_TRUE(ptr != NULL)`
|
||||
works just as well.
|
||||
|
||||
If we were to support `EXPECT_NE(NULL, ptr)`, for consistency we'll have to
|
||||
support `EXPECT_NE(ptr, NULL)` as well, as unlike `EXPECT_EQ`, we don't have a
|
||||
convention on the order of the two arguments for `EXPECT_NE`. This means using
|
||||
the template meta programming tricks twice in the implementation, making it even
|
||||
harder to understand and maintain. We believe the benefit doesn't justify the
|
||||
cost.
|
||||
If we were to support `EXPECT_NE(NULL, ptr)`, for consistency we'd have to
|
||||
support `EXPECT_NE(ptr, NULL)` as well. This means using the template meta
|
||||
programming tricks twice in the implementation, making it even harder to
|
||||
understand and maintain. We believe the benefit doesn't justify the cost.
|
||||
|
||||
Finally, with the growth of the gMock matcher library, we are encouraging people
|
||||
to use the unified `EXPECT_THAT(value, matcher)` syntax more often in tests. One
|
||||
@@ -127,6 +130,7 @@ can much more easily decide which one to use the next time.
|
||||
|
||||
## I got some run-time errors about invalid proto descriptors when using `ProtocolMessageEquals`. Help!
|
||||
|
||||
{: .callout .note}
|
||||
**Note:** `ProtocolMessageEquals` and `ProtocolMessageEquiv` are *deprecated*
|
||||
now. Please use `EqualsProto`, etc instead.
|
||||
|
||||
@@ -176,18 +180,6 @@ template argument, and thus doesn't compile in opt mode when `a` contains a call
|
||||
to `htonl()`. It is difficult to make `EXPECT_EQ` bypass the `htonl()` bug, as
|
||||
the solution must work with different compilers on various platforms.
|
||||
|
||||
`htonl()` has some other problems as described in `//util/endian/endian.h`,
|
||||
which defines `ghtonl()` to replace it. `ghtonl()` does the same thing `htonl()`
|
||||
does, only without its problems. We suggest you to use `ghtonl()` instead of
|
||||
`htonl()`, both in your tests and production code.
|
||||
|
||||
`//util/endian/endian.h` also defines `ghtons()`, which solves similar problems
|
||||
in `htons()`.
|
||||
|
||||
Don't forget to add `//util/endian` to the list of dependencies in the `BUILD`
|
||||
file wherever `ghtonl()` and `ghtons()` are used. The library consists of a
|
||||
single header file and will not bloat your binary.
|
||||
|
||||
## The compiler complains about "undefined references" to some static const member variables, but I did define them in the class body. What's wrong?
|
||||
|
||||
If your class has a static data member:
|
||||
@@ -211,6 +203,18 @@ particular, using it in googletest comparison assertions (`EXPECT_EQ`, etc) will
|
||||
generate an "undefined reference" linker error. The fact that "it used to work"
|
||||
doesn't mean it's valid. It just means that you were lucky. :-)
|
||||
|
||||
If the declaration of the static data member is `constexpr` then it is
|
||||
implicitly an `inline` definition, and a separate definition in `foo.cc` is not
|
||||
needed:
|
||||
|
||||
```c++
|
||||
// foo.h
|
||||
class Foo {
|
||||
...
|
||||
static constexpr int kBar = 100; // Defines kBar, no need to do it in foo.cc.
|
||||
};
|
||||
```
|
||||
|
||||
## Can I derive a test fixture from another?
|
||||
|
||||
Yes.
|
||||
@@ -263,7 +267,7 @@ If necessary, you can continue to derive test fixtures from a derived fixture.
|
||||
googletest has no limit on how deep the hierarchy can be.
|
||||
|
||||
For a complete example using derived test fixtures, see
|
||||
[sample5_unittest.cc](../samples/sample5_unittest.cc).
|
||||
[sample5_unittest.cc](https://github.com/google/googletest/blob/master/googletest/samples/sample5_unittest.cc).
|
||||
|
||||
## My compiler complains "void value not ignored as it ought to be." What does this mean?
|
||||
|
||||
@@ -275,8 +279,9 @@ disabled by our build system. Please see more details
|
||||
## My death test hangs (or seg-faults). How do I fix it?
|
||||
|
||||
In googletest, death tests are run in a child process and the way they work is
|
||||
delicate. To write death tests you really need to understand how they work.
|
||||
Please make sure you have read [this](advanced.md#how-it-works).
|
||||
delicate. To write death tests you really need to understand how they work—see
|
||||
the details at [Death Assertions](reference/assertions.md#death) in the
|
||||
Assertions Reference.
|
||||
|
||||
In particular, death tests don't like having multiple threads in the parent
|
||||
process. So the first thing you can try is to eliminate creating threads outside
|
||||
@@ -295,7 +300,7 @@ program from the beginning in the child process. Therefore make sure your
|
||||
program can run side-by-side with itself and is deterministic.
|
||||
|
||||
In the end, this boils down to good concurrent programming. You have to make
|
||||
sure that there is no race conditions or dead locks in your program. No silver
|
||||
sure that there are no race conditions or deadlocks in your program. No silver
|
||||
bullet - sorry!
|
||||
|
||||
## Should I use the constructor/destructor of the test fixture or SetUp()/TearDown()? {#CtorVsSetUp}
|
||||
@@ -332,8 +337,8 @@ You may still want to use `SetUp()/TearDown()` in the following cases:
|
||||
* In the body of a constructor (or destructor), it's not possible to use the
|
||||
`ASSERT_xx` macros. Therefore, if the set-up operation could cause a fatal
|
||||
test failure that should prevent the test from running, it's necessary to
|
||||
use `abort` <!-- GOOGLETEST_CM0015 DO NOT DELETE --> and abort the whole test executable,
|
||||
or to use `SetUp()` instead of a constructor.
|
||||
use `abort` and abort the whole test
|
||||
executable, or to use `SetUp()` instead of a constructor.
|
||||
* If the tear-down operation could throw an exception, you must use
|
||||
`TearDown()` as opposed to the destructor, as throwing in a destructor leads
|
||||
to undefined behavior and usually will kill your program right away. Note
|
||||
@@ -349,72 +354,8 @@ You may still want to use `SetUp()/TearDown()` in the following cases:
|
||||
|
||||
## The compiler complains "no matching function to call" when I use ASSERT_PRED*. How do I fix it?
|
||||
|
||||
If the predicate function you use in `ASSERT_PRED*` or `EXPECT_PRED*` is
|
||||
overloaded or a template, the compiler will have trouble figuring out which
|
||||
overloaded version it should use. `ASSERT_PRED_FORMAT*` and
|
||||
`EXPECT_PRED_FORMAT*` don't have this problem.
|
||||
|
||||
If you see this error, you might want to switch to
|
||||
`(ASSERT|EXPECT)_PRED_FORMAT*`, which will also give you a better failure
|
||||
message. If, however, that is not an option, you can resolve the problem by
|
||||
explicitly telling the compiler which version to pick.
|
||||
|
||||
For example, suppose you have
|
||||
|
||||
```c++
|
||||
bool IsPositive(int n) {
|
||||
return n > 0;
|
||||
}
|
||||
|
||||
bool IsPositive(double x) {
|
||||
return x > 0;
|
||||
}
|
||||
```
|
||||
|
||||
you will get a compiler error if you write
|
||||
|
||||
```c++
|
||||
EXPECT_PRED1(IsPositive, 5);
|
||||
```
|
||||
|
||||
However, this will work:
|
||||
|
||||
```c++
|
||||
EXPECT_PRED1(static_cast<bool (*)(int)>(IsPositive), 5);
|
||||
```
|
||||
|
||||
(The stuff inside the angled brackets for the `static_cast` operator is the type
|
||||
of the function pointer for the `int`-version of `IsPositive()`.)
|
||||
|
||||
As another example, when you have a template function
|
||||
|
||||
```c++
|
||||
template <typename T>
|
||||
bool IsNegative(T x) {
|
||||
return x < 0;
|
||||
}
|
||||
```
|
||||
|
||||
you can use it in a predicate assertion like this:
|
||||
|
||||
```c++
|
||||
ASSERT_PRED1(IsNegative<int>, -5);
|
||||
```
|
||||
|
||||
Things are more interesting if your template has more than one parameters. The
|
||||
following won't compile:
|
||||
|
||||
```c++
|
||||
ASSERT_PRED2(GreaterThan<int, int>, 5, 0);
|
||||
```
|
||||
|
||||
as the C++ pre-processor thinks you are giving `ASSERT_PRED2` 4 arguments, which
|
||||
is one more than expected. The workaround is to wrap the predicate function in
|
||||
parentheses:
|
||||
|
||||
```c++
|
||||
ASSERT_PRED2((GreaterThan<int, int>), 5, 0);
|
||||
```
|
||||
See details for [`EXPECT_PRED*`](reference/assertions.md#EXPECT_PRED) in the
|
||||
Assertions Reference.
|
||||
|
||||
## My compiler complains about "ignoring return value" when I call RUN_ALL_TESTS(). Why?
|
||||
|
||||
@@ -531,8 +472,8 @@ There are several good reasons:
|
||||
|
||||
## What can the statement argument in ASSERT_DEATH() be?
|
||||
|
||||
`ASSERT_DEATH(*statement*, *regex*)` (or any death assertion macro) can be used
|
||||
wherever `*statement*` is valid. So basically `*statement*` can be any C++
|
||||
`ASSERT_DEATH(statement, matcher)` (or any death assertion macro) can be used
|
||||
wherever *`statement`* is valid. So basically *`statement`* can be any C++
|
||||
statement that makes sense in the current context. In particular, it can
|
||||
reference global and/or local variables, and can be:
|
||||
|
||||
@@ -555,7 +496,7 @@ TEST(MyDeathTest, ComplexExpression) {
|
||||
"(Func1|Method) failed");
|
||||
}
|
||||
|
||||
// Death assertions can be used any where in a function. In
|
||||
// Death assertions can be used anywhere in a function. In
|
||||
// particular, they can be inside a loop.
|
||||
TEST(MyDeathTest, InsideLoop) {
|
||||
// Verifies that Foo(0), Foo(1), ..., and Foo(4) all die.
|
||||
@@ -578,8 +519,6 @@ TEST(MyDeathTest, CompoundStatement) {
|
||||
}
|
||||
```
|
||||
|
||||
gtest-death-test_test.cc contains more examples if you are interested.
|
||||
|
||||
## I have a fixture class `FooTest`, but `TEST_F(FooTest, Bar)` gives me error ``"no matching function for call to `FooTest::FooTest()'"``. Why?
|
||||
|
||||
Googletest needs to be able to create objects of your test fixture class, so it
|
||||
@@ -597,7 +536,7 @@ However, there are cases where you have to define your own:
|
||||
## Why does ASSERT_DEATH complain about previous threads that were already joined?
|
||||
|
||||
With the Linux pthread library, there is no turning back once you cross the line
|
||||
from single thread to multiple threads. The first time you create a thread, a
|
||||
from a single thread to multiple threads. The first time you create a thread, a
|
||||
manager thread is created in addition, so you get 3, not 2, threads. Later when
|
||||
the thread you create joins the main thread, the thread count decrements by 1,
|
||||
but the manager thread will never be killed, so you still have 2 threads, which
|
||||
@@ -612,7 +551,7 @@ runs on, you shouldn't depend on this.
|
||||
googletest does not interleave tests from different test suites. That is, it
|
||||
runs all tests in one test suite first, and then runs all tests in the next test
|
||||
suite, and so on. googletest does this because it needs to set up a test suite
|
||||
before the first test in it is run, and tear it down afterwords. Splitting up
|
||||
before the first test in it is run, and tear it down afterwards. Splitting up
|
||||
the test case would require multiple set-up and tear-down processes, which is
|
||||
inefficient and makes the semantics unclean.
|
||||
|
||||
@@ -661,14 +600,15 @@ break the death test (e.g. by changing the regex pattern it is expected to
|
||||
match). Admittedly, this is a hack. We'll consider a more permanent solution
|
||||
after the fork-and-exec-style death tests are implemented.
|
||||
|
||||
## The compiler complains about "no match for 'operator<<'" when I use an assertion. What gives?
|
||||
## The compiler complains about `no match for 'operator<<'` when I use an assertion. What gives?
|
||||
|
||||
If you use a user-defined type `FooType` in an assertion, you must make sure
|
||||
there is an `std::ostream& operator<<(std::ostream&, const FooType&)` function
|
||||
defined such that we can print a value of `FooType`.
|
||||
|
||||
In addition, if `FooType` is declared in a name space, the `<<` operator also
|
||||
needs to be defined in the *same* name space. See https://abseil.io/tips/49 for details.
|
||||
needs to be defined in the *same* name space. See
|
||||
[Tip of the Week #49](http://abseil.io/tips/49) for details.
|
||||
|
||||
## How do I suppress the memory leak messages on Windows?
|
||||
|
||||
@@ -689,10 +629,10 @@ mistake in production. Such cleverness also leads to
|
||||
advise against the practice, and googletest doesn't provide a way to do it.
|
||||
|
||||
In general, the recommended way to cause the code to behave differently under
|
||||
test is [Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection). You can inject
|
||||
test is [Dependency Injection](http://en.wikipedia.org/wiki/Dependency_injection). You can inject
|
||||
different functionality from the test and from the production code. Since your
|
||||
production code doesn't link in the for-test logic at all (the
|
||||
[`testonly`](https://docs.bazel.build/versions/master/be/common-definitions.html#common.testonly) attribute for BUILD targets helps to ensure
|
||||
[`testonly`](http://docs.bazel.build/versions/master/be/common-definitions.html#common.testonly) attribute for BUILD targets helps to ensure
|
||||
that), there is no danger in accidentally running it.
|
||||
|
||||
However, if you *really*, *really*, *really* have no choice, and if you follow
|
||||
@@ -703,12 +643,12 @@ whether the code is under test.
|
||||
## How do I temporarily disable a test?
|
||||
|
||||
If you have a broken test that you cannot fix right away, you can add the
|
||||
DISABLED_ prefix to its name. This will exclude it from execution. This is
|
||||
better than commenting out the code or using #if 0, as disabled tests are still
|
||||
compiled (and thus won't rot).
|
||||
`DISABLED_` prefix to its name. This will exclude it from execution. This is
|
||||
better than commenting out the code or using `#if 0`, as disabled tests are
|
||||
still compiled (and thus won't rot).
|
||||
|
||||
To include disabled tests in test execution, just invoke the test program with
|
||||
the --gtest_also_run_disabled_tests flag.
|
||||
the `--gtest_also_run_disabled_tests` flag.
|
||||
|
||||
## Is it OK if I have two separate `TEST(Foo, Bar)` test methods defined in different namespaces?
|
||||
|
241
test/gtest-1.11.0/docs/gmock_cheat_sheet.md
Normal file
241
test/gtest-1.11.0/docs/gmock_cheat_sheet.md
Normal file
@@ -0,0 +1,241 @@
|
||||
# gMock Cheat Sheet
|
||||
|
||||
## Defining a Mock Class
|
||||
|
||||
### Mocking a Normal Class {#MockClass}
|
||||
|
||||
Given
|
||||
|
||||
```cpp
|
||||
class Foo {
|
||||
...
|
||||
virtual ~Foo();
|
||||
virtual int GetSize() const = 0;
|
||||
virtual string Describe(const char* name) = 0;
|
||||
virtual string Describe(int type) = 0;
|
||||
virtual bool Process(Bar elem, int count) = 0;
|
||||
};
|
||||
```
|
||||
|
||||
(note that `~Foo()` **must** be virtual) we can define its mock as
|
||||
|
||||
```cpp
|
||||
#include "gmock/gmock.h"
|
||||
|
||||
class MockFoo : public Foo {
|
||||
...
|
||||
MOCK_METHOD(int, GetSize, (), (const, override));
|
||||
MOCK_METHOD(string, Describe, (const char* name), (override));
|
||||
MOCK_METHOD(string, Describe, (int type), (override));
|
||||
MOCK_METHOD(bool, Process, (Bar elem, int count), (override));
|
||||
};
|
||||
```
|
||||
|
||||
To create a "nice" mock, which ignores all uninteresting calls, a "naggy" mock,
|
||||
which warns on all uninteresting calls, or a "strict" mock, which treats them as
|
||||
failures:
|
||||
|
||||
```cpp
|
||||
using ::testing::NiceMock;
|
||||
using ::testing::NaggyMock;
|
||||
using ::testing::StrictMock;
|
||||
|
||||
NiceMock<MockFoo> nice_foo; // The type is a subclass of MockFoo.
|
||||
NaggyMock<MockFoo> naggy_foo; // The type is a subclass of MockFoo.
|
||||
StrictMock<MockFoo> strict_foo; // The type is a subclass of MockFoo.
|
||||
```
|
||||
|
||||
{: .callout .note}
|
||||
**Note:** A mock object is currently naggy by default. We may make it nice by
|
||||
default in the future.
|
||||
|
||||
### Mocking a Class Template {#MockTemplate}
|
||||
|
||||
Class templates can be mocked just like any class.
|
||||
|
||||
To mock
|
||||
|
||||
```cpp
|
||||
template <typename Elem>
|
||||
class StackInterface {
|
||||
...
|
||||
virtual ~StackInterface();
|
||||
virtual int GetSize() const = 0;
|
||||
virtual void Push(const Elem& x) = 0;
|
||||
};
|
||||
```
|
||||
|
||||
(note that all member functions that are mocked, including `~StackInterface()`
|
||||
**must** be virtual).
|
||||
|
||||
```cpp
|
||||
template <typename Elem>
|
||||
class MockStack : public StackInterface<Elem> {
|
||||
...
|
||||
MOCK_METHOD(int, GetSize, (), (const, override));
|
||||
MOCK_METHOD(void, Push, (const Elem& x), (override));
|
||||
};
|
||||
```
|
||||
|
||||
### Specifying Calling Conventions for Mock Functions
|
||||
|
||||
If your mock function doesn't use the default calling convention, you can
|
||||
specify it by adding `Calltype(convention)` to `MOCK_METHOD`'s 4th parameter.
|
||||
For example,
|
||||
|
||||
```cpp
|
||||
MOCK_METHOD(bool, Foo, (int n), (Calltype(STDMETHODCALLTYPE)));
|
||||
MOCK_METHOD(int, Bar, (double x, double y),
|
||||
(const, Calltype(STDMETHODCALLTYPE)));
|
||||
```
|
||||
|
||||
where `STDMETHODCALLTYPE` is defined by `<objbase.h>` on Windows.
|
||||
|
||||
## Using Mocks in Tests {#UsingMocks}
|
||||
|
||||
The typical work flow is:
|
||||
|
||||
1. Import the gMock names you need to use. All gMock symbols are in the
|
||||
`testing` namespace unless they are macros or otherwise noted.
|
||||
2. Create the mock objects.
|
||||
3. Optionally, set the default actions of the mock objects.
|
||||
4. Set your expectations on the mock objects (How will they be called? What
|
||||
will they do?).
|
||||
5. Exercise code that uses the mock objects; if necessary, check the result
|
||||
using googletest assertions.
|
||||
6. When a mock object is destructed, gMock automatically verifies that all
|
||||
expectations on it have been satisfied.
|
||||
|
||||
Here's an example:
|
||||
|
||||
```cpp
|
||||
using ::testing::Return; // #1
|
||||
|
||||
TEST(BarTest, DoesThis) {
|
||||
MockFoo foo; // #2
|
||||
|
||||
ON_CALL(foo, GetSize()) // #3
|
||||
.WillByDefault(Return(1));
|
||||
// ... other default actions ...
|
||||
|
||||
EXPECT_CALL(foo, Describe(5)) // #4
|
||||
.Times(3)
|
||||
.WillRepeatedly(Return("Category 5"));
|
||||
// ... other expectations ...
|
||||
|
||||
EXPECT_EQ(MyProductionFunction(&foo), "good"); // #5
|
||||
} // #6
|
||||
```
|
||||
|
||||
## Setting Default Actions {#OnCall}
|
||||
|
||||
gMock has a **built-in default action** for any function that returns `void`,
|
||||
`bool`, a numeric value, or a pointer. In C++11, it will additionally returns
|
||||
the default-constructed value, if one exists for the given type.
|
||||
|
||||
To customize the default action for functions with return type `T`, use
|
||||
[`DefaultValue<T>`](reference/mocking.md#DefaultValue). For example:
|
||||
|
||||
```cpp
|
||||
// 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");
|
||||
auto buzz2 = mock_buzzer_.MakeBuzz("hello");
|
||||
EXPECT_NE(buzz1, nullptr);
|
||||
EXPECT_NE(buzz2, nullptr);
|
||||
EXPECT_NE(buzz1, buzz2);
|
||||
|
||||
// Resets the default action for return type std::unique_ptr<Buzz>,
|
||||
// to avoid interfere with other tests.
|
||||
DefaultValue<std::unique_ptr<Buzz>>::Clear();
|
||||
```
|
||||
|
||||
To customize the default action for a particular method of a specific mock
|
||||
object, use [`ON_CALL`](reference/mocking.md#ON_CALL). `ON_CALL` has a similar
|
||||
syntax to `EXPECT_CALL`, but it is used for setting default behaviors when you
|
||||
do not require that the mock method is called. See
|
||||
[Knowing When to Expect](gmock_cook_book.md#UseOnCall) for a more detailed
|
||||
discussion.
|
||||
|
||||
## Setting Expectations {#ExpectCall}
|
||||
|
||||
See [`EXPECT_CALL`](reference/mocking.md#EXPECT_CALL) in the Mocking Reference.
|
||||
|
||||
## Matchers {#MatcherList}
|
||||
|
||||
See the [Matchers Reference](reference/matchers.md).
|
||||
|
||||
## Actions {#ActionList}
|
||||
|
||||
See the [Actions Reference](reference/actions.md).
|
||||
|
||||
## Cardinalities {#CardinalityList}
|
||||
|
||||
See the [`Times` clause](reference/mocking.md#EXPECT_CALL.Times) of
|
||||
`EXPECT_CALL` in the Mocking Reference.
|
||||
|
||||
## Expectation Order
|
||||
|
||||
By default, expectations can be matched in *any* order. If some or all
|
||||
expectations must be matched in a given order, you can use the
|
||||
[`After` clause](reference/mocking.md#EXPECT_CALL.After) or
|
||||
[`InSequence` clause](reference/mocking.md#EXPECT_CALL.InSequence) of
|
||||
`EXPECT_CALL`, or use an [`InSequence` object](reference/mocking.md#InSequence).
|
||||
|
||||
## Verifying and Resetting a Mock
|
||||
|
||||
gMock will verify the expectations on a mock object when it is destructed, or
|
||||
you can do it earlier:
|
||||
|
||||
```cpp
|
||||
using ::testing::Mock;
|
||||
...
|
||||
// Verifies and removes the expectations on mock_obj;
|
||||
// returns true if and only if successful.
|
||||
Mock::VerifyAndClearExpectations(&mock_obj);
|
||||
...
|
||||
// Verifies and removes the expectations on mock_obj;
|
||||
// also removes the default actions set by ON_CALL();
|
||||
// returns true if and only if successful.
|
||||
Mock::VerifyAndClear(&mock_obj);
|
||||
```
|
||||
|
||||
Do not set new expectations after verifying and clearing a mock after its use.
|
||||
Setting expectations after code that exercises the mock has undefined behavior.
|
||||
See [Using Mocks in Tests](gmock_for_dummies.md#using-mocks-in-tests) for more
|
||||
information.
|
||||
|
||||
You can also tell gMock that a mock object can be leaked and doesn't need to be
|
||||
verified:
|
||||
|
||||
```cpp
|
||||
Mock::AllowLeak(&mock_obj);
|
||||
```
|
||||
|
||||
## Mock Classes
|
||||
|
||||
gMock defines a convenient mock class template
|
||||
|
||||
```cpp
|
||||
class MockFunction<R(A1, ..., An)> {
|
||||
public:
|
||||
MOCK_METHOD(R, Call, (A1, ..., An));
|
||||
};
|
||||
```
|
||||
|
||||
See this [recipe](gmock_cook_book.md#using-check-points) for one application of
|
||||
it.
|
||||
|
||||
## Flags
|
||||
|
||||
| Flag | Description |
|
||||
| :----------------------------- | :---------------------------------------- |
|
||||
| `--gmock_catch_leaked_mocks=0` | Don't report leaked mock objects as failures. |
|
||||
| `--gmock_verbose=LEVEL` | Sets the default verbosity level (`info`, `warning`, or `error`) of Google Mock messages. |
|
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,9 @@
|
||||
## Legacy gMock FAQ {#GMockFaq}
|
||||
|
||||
<!-- GOOGLETEST_CM0021 DO NOT DELETE -->
|
||||
# Legacy gMock FAQ
|
||||
|
||||
### When I call a method on my mock object, the method for the real object is invoked instead. What's the problem?
|
||||
|
||||
In order for a method to be mocked, it must be *virtual*, unless you use the
|
||||
[high-perf dependency injection technique](#MockingNonVirtualMethods).
|
||||
[high-perf dependency injection technique](gmock_cook_book.md#MockingNonVirtualMethods).
|
||||
|
||||
### Can I mock a variadic function?
|
||||
|
||||
@@ -81,8 +79,6 @@ void Bar(int* p); // Neither p nor *p is const.
|
||||
void Bar(const int* p); // p is not const, but *p is.
|
||||
```
|
||||
|
||||
<!-- GOOGLETEST_CM0030 DO NOT DELETE -->
|
||||
|
||||
### I can't figure out why gMock thinks my expectations are not satisfied. What should I do?
|
||||
|
||||
You might want to run your test with `--gmock_verbose=info`. This flag lets
|
||||
@@ -91,7 +87,7 @@ trace, you'll gain insights on why the expectations you set are not met.
|
||||
|
||||
If you see the message "The mock function has no default action set, and its
|
||||
return type has no default value set.", then try
|
||||
[adding a default action](for_dummies.md#DefaultValue). Due to a known issue,
|
||||
[adding a default action](gmock_cheat_sheet.md#OnCall). Due to a known issue,
|
||||
unexpected calls on mocks without default actions don't print out a detailed
|
||||
comparison between the actual arguments and the expected arguments.
|
||||
|
||||
@@ -126,8 +122,6 @@ using ::testing::_;
|
||||
.Times(0);
|
||||
```
|
||||
|
||||
<!-- GOOGLETEST_CM0031 DO NOT DELETE -->
|
||||
|
||||
### I have a failed test where gMock tells me TWICE that a particular expectation is not satisfied. Isn't this redundant?
|
||||
|
||||
When gMock detects a failure, it prints relevant information (the mock function
|
||||
@@ -386,8 +380,8 @@ doesn't say what the return value should be. You need `DoAll()` to chain a
|
||||
`SetArgPointee()` with a `Return()` that provides a value appropriate to the API
|
||||
being mocked.
|
||||
|
||||
See this [recipe](cook_book.md#mocking-side-effects) for more details and an
|
||||
example.
|
||||
See this [recipe](gmock_cook_book.md#mocking-side-effects) for more details and
|
||||
an example.
|
||||
|
||||
### I have a huge mock class, and Microsoft Visual C++ runs out of memory when compiling it. What can I do?
|
||||
|
@@ -1,8 +1,6 @@
|
||||
## gMock for Dummies {#GMockForDummies}
|
||||
# gMock for Dummies
|
||||
|
||||
<!-- GOOGLETEST_CM0013 DO NOT DELETE -->
|
||||
|
||||
### What Is gMock?
|
||||
## What Is gMock?
|
||||
|
||||
When you write a prototype or test, often it's not feasible or wise to rely on
|
||||
real objects entirely. A **mock object** implements the same interface as a real
|
||||
@@ -10,9 +8,9 @@ object (so it can be used as one), but lets you specify at run time how it will
|
||||
be used and what it should do (which methods will be called? in which order? how
|
||||
many times? with what arguments? what will they return? etc).
|
||||
|
||||
**Note:** It is easy to confuse the term *fake objects* with mock objects. Fakes
|
||||
and mocks actually mean very different things in the Test-Driven Development
|
||||
(TDD) community:
|
||||
It is easy to confuse the term *fake objects* with mock objects. Fakes and mocks
|
||||
actually mean very different things in the Test-Driven Development (TDD)
|
||||
community:
|
||||
|
||||
* **Fake** objects have working implementations, but usually take some
|
||||
shortcut (perhaps to make the operations less expensive), which makes them
|
||||
@@ -39,7 +37,7 @@ When using gMock,
|
||||
3. then you exercise code that uses the mock objects. gMock will catch any
|
||||
violation to the expectations as soon as it arises.
|
||||
|
||||
### Why gMock?
|
||||
## Why gMock?
|
||||
|
||||
While mock objects help you remove unnecessary dependencies in tests and make
|
||||
them fast and reliable, using mocks manually in C++ is *hard*:
|
||||
@@ -53,9 +51,9 @@ them fast and reliable, using mocks manually in C++ is *hard*:
|
||||
one.
|
||||
|
||||
In contrast, Java and Python programmers have some fine mock frameworks (jMock,
|
||||
EasyMock, [Mox](http://wtf/mox), etc), which automate the creation of mocks. As
|
||||
a result, mocking is a proven effective technique and widely adopted practice in
|
||||
those communities. Having the right tool absolutely makes the difference.
|
||||
EasyMock, etc), which automate the creation of mocks. As a result, mocking is a
|
||||
proven effective technique and widely adopted practice in those communities.
|
||||
Having the right tool absolutely makes the difference.
|
||||
|
||||
gMock was built to help C++ programmers. It was inspired by jMock and EasyMock,
|
||||
but designed with C++'s specifics in mind. It is your friend if any of the
|
||||
@@ -85,11 +83,11 @@ We encourage you to use gMock as
|
||||
* a *testing* tool to cut your tests' outbound dependencies and probe the
|
||||
interaction between your module and its collaborators.
|
||||
|
||||
### Getting Started
|
||||
## Getting Started
|
||||
|
||||
gMock is bundled with googletest.
|
||||
|
||||
### A Case for Mock Turtles
|
||||
## A Case for Mock Turtles
|
||||
|
||||
Let's look at an example. Suppose you are developing a graphics program that
|
||||
relies on a [LOGO](http://en.wikipedia.org/wiki/Logo_programming_language)-like
|
||||
@@ -106,7 +104,7 @@ the API in an interface (say, `Turtle`) and code to that interface:
|
||||
```cpp
|
||||
class Turtle {
|
||||
...
|
||||
virtual ~Turtle() {};
|
||||
virtual ~Turtle() {}
|
||||
virtual void PenUp() = 0;
|
||||
virtual void PenDown() = 0;
|
||||
virtual void Forward(int distance) = 0;
|
||||
@@ -135,20 +133,20 @@ because your new machine does anti-aliasing differently), easier to read and
|
||||
maintain (the intent of a test is expressed in the code, not in some binary
|
||||
images), and run *much, much faster*.
|
||||
|
||||
### Writing the Mock Class
|
||||
## Writing the Mock Class
|
||||
|
||||
If you are lucky, the mocks you need to use have already been implemented by
|
||||
some nice people. If, however, you find yourself in the position to write a mock
|
||||
class, relax - gMock turns this task into a fun game! (Well, almost.)
|
||||
|
||||
#### How to Define It
|
||||
### How to Define It
|
||||
|
||||
Using the `Turtle` interface as example, here are the simple steps you need to
|
||||
follow:
|
||||
|
||||
* Derive a class `MockTurtle` from `Turtle`.
|
||||
* Take a *virtual* function of `Turtle` (while it's possible to
|
||||
[mock non-virtual methods using templates](cook_book.md#MockingNonVirtualMethods),
|
||||
[mock non-virtual methods using templates](gmock_cook_book.md#MockingNonVirtualMethods),
|
||||
it's much more involved).
|
||||
* In the `public:` section of the child class, write `MOCK_METHOD();`
|
||||
* Now comes the fun part: you take the function signature, cut-and-paste it
|
||||
@@ -184,7 +182,7 @@ class MockTurtle : public Turtle {
|
||||
You don't need to define these mock methods somewhere else - the `MOCK_METHOD`
|
||||
macro will generate the definitions for you. It's that simple!
|
||||
|
||||
#### Where to Put It
|
||||
### Where to Put It
|
||||
|
||||
When you define a mock class, you need to decide where to put its definition.
|
||||
Some people put it in a `_test.cc`. This is fine when the interface being mocked
|
||||
@@ -206,14 +204,12 @@ choosing the adaptor interface can make your code easier to write and more
|
||||
readable (a net win in the long run), as you can choose `FooAdaptor` to fit your
|
||||
specific domain much better than `Foo` does.
|
||||
|
||||
<!-- GOOGLETEST_CM0029 DO NOT DELETE -->
|
||||
|
||||
### Using Mocks in Tests
|
||||
## Using Mocks in Tests
|
||||
|
||||
Once you have a mock class, using it is easy. The typical work flow is:
|
||||
|
||||
1. Import the gMock names from the `testing` namespace such that you can use
|
||||
them unqualified (You only have to do it once per file. Remember that
|
||||
them unqualified (You only have to do it once per file). Remember that
|
||||
namespaces are a good idea.
|
||||
2. Create some mock objects.
|
||||
3. Specify your expectations on them (How many times will a method be called?
|
||||
@@ -257,8 +253,8 @@ Stack trace:
|
||||
...
|
||||
```
|
||||
|
||||
**Tip 1:** If you run the test from an Emacs buffer, you can hit <Enter> on the
|
||||
line number to jump right to the failed expectation.
|
||||
**Tip 1:** If you run the test from an Emacs buffer, you can hit `<Enter>` on
|
||||
the line number to jump right to the failed expectation.
|
||||
|
||||
**Tip 2:** If your mock objects are never deleted, the final verification won't
|
||||
happen. Therefore it's a good idea to turn on the heap checker in your tests
|
||||
@@ -266,8 +262,9 @@ when you allocate mocks on the heap. You get that automatically if you use the
|
||||
`gtest_main` library already.
|
||||
|
||||
**Important note:** gMock requires expectations to be set **before** the mock
|
||||
functions are called, otherwise the behavior is **undefined**. In particular,
|
||||
you mustn't interleave `EXPECT_CALL()s` and calls to the mock functions.
|
||||
functions are called, otherwise the behavior is **undefined**. Do not alternate
|
||||
between calls to `EXPECT_CALL()` and calls to the mock functions, and do not set
|
||||
any expectations on a mock after passing the mock to an API.
|
||||
|
||||
This means `EXPECT_CALL()` should be read as expecting that a call will occur
|
||||
*in the future*, not that a call has occurred. Why does gMock work like that?
|
||||
@@ -279,7 +276,7 @@ Admittedly, this test is contrived and doesn't do much. You can easily achieve
|
||||
the same effect without using gMock. However, as we shall reveal soon, gMock
|
||||
allows you to do *so much more* with the mocks.
|
||||
|
||||
### Setting Expectations
|
||||
## Setting Expectations
|
||||
|
||||
The key to using a mock object successfully is to set the *right expectations*
|
||||
on it. If you set the expectations too strict, your test will fail as the result
|
||||
@@ -288,7 +285,7 @@ to do it just right such that your test can catch exactly the kind of bugs you
|
||||
intend it to catch. gMock provides the necessary means for you to do it "just
|
||||
right."
|
||||
|
||||
#### General Syntax
|
||||
### General Syntax
|
||||
|
||||
In gMock we use the `EXPECT_CALL()` macro to set an expectation on a mock
|
||||
method. The general syntax is:
|
||||
@@ -314,8 +311,8 @@ EXPECT_CALL(mock_object, non-overloaded-method)
|
||||
|
||||
This syntax allows the test writer to specify "called with any arguments"
|
||||
without explicitly specifying the number or types of arguments. To avoid
|
||||
unintended ambiguity, this syntax may only be used for methods which are not
|
||||
overloaded
|
||||
unintended ambiguity, this syntax may only be used for methods that are not
|
||||
overloaded.
|
||||
|
||||
Either form of the macro can be followed by some optional *clauses* that provide
|
||||
more information about the expectation. We'll discuss how each clause works in
|
||||
@@ -338,12 +335,13 @@ says that the `turtle` object's `GetX()` method will be called five times, it
|
||||
will return 100 the first time, 150 the second time, and then 200 every time.
|
||||
Some people like to call this style of syntax a Domain-Specific Language (DSL).
|
||||
|
||||
{: .callout .note}
|
||||
**Note:** Why do we use a macro to do this? Well it serves two purposes: first
|
||||
it makes expectations easily identifiable (either by `gsearch` or by a human
|
||||
it makes expectations easily identifiable (either by `grep` or by a human
|
||||
reader), and second it allows gMock to include the source file location of a
|
||||
failed expectation in messages, making debugging easier.
|
||||
|
||||
#### Matchers: What Arguments Do We Expect?
|
||||
### Matchers: What Arguments Do We Expect?
|
||||
|
||||
When a mock function takes arguments, we may specify what arguments we are
|
||||
expecting, for example:
|
||||
@@ -374,8 +372,8 @@ convenient way of saying "any value".
|
||||
In the above examples, `100` and `50` are also matchers; implicitly, they are
|
||||
the same as `Eq(100)` and `Eq(50)`, which specify that the argument must be
|
||||
equal (using `operator==`) to the matcher argument. There are many
|
||||
[built-in matchers](#MatcherList) for common types (as well as
|
||||
[custom matchers](cook_book.md#NewMatchers)); for example:
|
||||
[built-in matchers](reference/matchers.md) for common types (as well as
|
||||
[custom matchers](gmock_cook_book.md#NewMatchers)); for example:
|
||||
|
||||
```cpp
|
||||
using ::testing::Ge;
|
||||
@@ -397,9 +395,9 @@ EXPECT_CALL(turtle, GoTo);
|
||||
This works for all non-overloaded methods; if a method is overloaded, you need
|
||||
to help gMock resolve which overload is expected by specifying the number of
|
||||
arguments and possibly also the
|
||||
[types of the arguments](cook_book.md#SelectOverload).
|
||||
[types of the arguments](gmock_cook_book.md#SelectOverload).
|
||||
|
||||
#### Cardinalities: How Many Times Will It Be Called?
|
||||
### Cardinalities: How Many Times Will It Be Called?
|
||||
|
||||
The first clause we can specify following an `EXPECT_CALL()` is `Times()`. We
|
||||
call its argument a **cardinality** as it tells *how many times* the call should
|
||||
@@ -414,7 +412,7 @@ called.
|
||||
|
||||
We've seen `AtLeast(n)` as an example of fuzzy cardinalities earlier. For the
|
||||
list of built-in cardinalities you can use, see
|
||||
[here](cheat_sheet.md#CardinalityList).
|
||||
[here](gmock_cheat_sheet.md#CardinalityList).
|
||||
|
||||
The `Times()` clause can be omitted. **If you omit `Times()`, gMock will infer
|
||||
the cardinality for you.** The rules are easy to remember:
|
||||
@@ -429,7 +427,7 @@ the cardinality for you.** The rules are easy to remember:
|
||||
**Quick quiz:** what do you think will happen if a function is expected to be
|
||||
called twice but actually called four times?
|
||||
|
||||
#### Actions: What Should It Do?
|
||||
### Actions: What Should It Do?
|
||||
|
||||
Remember that a mock object doesn't really have a working implementation? We as
|
||||
users have to tell it what to do when a method is invoked. This is easy in
|
||||
@@ -483,7 +481,7 @@ the *default* action for the function every time (unless, of course, you have a
|
||||
|
||||
What can we do inside `WillOnce()` besides `Return()`? You can return a
|
||||
reference using `ReturnRef(*variable*)`, or invoke a pre-defined function, among
|
||||
[others](cook_book.md#using-actions).
|
||||
[others](gmock_cook_book.md#using-actions).
|
||||
|
||||
**Important note:** The `EXPECT_CALL()` statement evaluates the action clause
|
||||
only once, even though the action may be performed many times. Therefore you
|
||||
@@ -503,7 +501,7 @@ always return 100 as `n++` is only evaluated once. Similarly, `Return(new Foo)`
|
||||
will create a new `Foo` object when the `EXPECT_CALL()` is executed, and will
|
||||
return the same pointer every time. If you want the side effect to happen every
|
||||
time, you need to define a custom action, which we'll teach in the
|
||||
[cook book](http://<!-- GOOGLETEST_CM0012 DO NOT DELETE -->).
|
||||
[cook book](gmock_cook_book.md).
|
||||
|
||||
Time for another quiz! What do you think the following means?
|
||||
|
||||
@@ -522,7 +520,7 @@ will be taken afterwards. So the right answer is that `turtle.GetY()` will
|
||||
return 100 the first time, but **return 0 from the second time on**, as
|
||||
returning 0 is the default action for `int` functions.
|
||||
|
||||
#### Using Multiple Expectations {#MultiExpectations}
|
||||
### Using Multiple Expectations {#MultiExpectations}
|
||||
|
||||
So far we've only shown examples where you have a single expectation. More
|
||||
realistically, you'll specify expectations on multiple mock methods which may be
|
||||
@@ -547,6 +545,7 @@ error, as the last matching expectation (#2) has been saturated. If, however,
|
||||
the third `Forward(10)` call is replaced by `Forward(20)`, then it would be OK,
|
||||
as now #1 will be the matching expectation.
|
||||
|
||||
{: .callout .note}
|
||||
**Note:** Why does gMock search for a match in the *reverse* order of the
|
||||
expectations? The reason is that this allows a user to set up the default
|
||||
expectations in a mock object's constructor or the test fixture's set-up phase
|
||||
@@ -555,15 +554,16 @@ body. So, if you have two expectations on the same method, you want to put the
|
||||
one with more specific matchers **after** the other, or the more specific rule
|
||||
would be shadowed by the more general one that comes after it.
|
||||
|
||||
{: .callout .tip}
|
||||
**Tip:** It is very common to start with a catch-all expectation for a method
|
||||
and `Times(AnyNumber())` (omitting arguments, or with `_` for all arguments, if
|
||||
overloaded). This makes any calls to the method expected. This is not necessary
|
||||
for methods that are not mentioned at all (these are "uninteresting"), but is
|
||||
useful for methods that have some expectations, but for which other calls are
|
||||
ok. See
|
||||
[Understanding Uninteresting vs Unexpected Calls](cook_book.md#uninteresting-vs-unexpected).
|
||||
[Understanding Uninteresting vs Unexpected Calls](gmock_cook_book.md#uninteresting-vs-unexpected).
|
||||
|
||||
#### Ordered vs Unordered Calls {#OrderedCalls}
|
||||
### Ordered vs Unordered Calls {#OrderedCalls}
|
||||
|
||||
By default, an expectation can match a call even though an earlier expectation
|
||||
hasn't been satisfied. In other words, the calls don't have to occur in the
|
||||
@@ -598,9 +598,9 @@ order as written. If a call is made out-of-order, it will be an error.
|
||||
|
||||
(What if you care about the relative order of some of the calls, but not all of
|
||||
them? Can you specify an arbitrary partial order? The answer is ... yes! The
|
||||
details can be found [here](cook_book.md#OrderedCalls).)
|
||||
details can be found [here](gmock_cook_book.md#OrderedCalls).)
|
||||
|
||||
#### All Expectations Are Sticky (Unless Said Otherwise) {#StickyExpectations}
|
||||
### All Expectations Are Sticky (Unless Said Otherwise) {#StickyExpectations}
|
||||
|
||||
Now let's do a quick quiz to see how well you can use this mock stuff already.
|
||||
How would you test that the turtle is asked to go to the origin *exactly twice*
|
||||
@@ -688,7 +688,7 @@ it's in a sequence - as soon as another expectation that comes after it in the
|
||||
sequence has been used, it automatically retires (and will never be used to
|
||||
match any call).
|
||||
|
||||
#### Uninteresting Calls
|
||||
### Uninteresting Calls
|
||||
|
||||
A mock object may have many methods, and not all of them are that interesting.
|
||||
For example, in some tests we may not care about how many times `GetX()` and
|
||||
@@ -697,4 +697,4 @@ For example, in some tests we may not care about how many times `GetX()` and
|
||||
In gMock, if you are not interested in a method, just don't say anything about
|
||||
it. If a call to this method occurs, you'll see a warning in the test output,
|
||||
but it won't be a failure. This is called "naggy" behavior; to change, see
|
||||
[The Nice, the Strict, and the Naggy](cook_book.md#NiceStrictNaggy).
|
||||
[The Nice, the Strict, and the Naggy](gmock_cook_book.md#NiceStrictNaggy).
|
22
test/gtest-1.11.0/docs/index.md
Normal file
22
test/gtest-1.11.0/docs/index.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# GoogleTest User's Guide
|
||||
|
||||
## Welcome to GoogleTest!
|
||||
|
||||
GoogleTest is Google's C++ testing and mocking framework. This user's guide has
|
||||
the following contents:
|
||||
|
||||
* [GoogleTest Primer](primer.md) - Teaches you how to write simple tests using
|
||||
GoogleTest. Read this first if you are new to GoogleTest.
|
||||
* [GoogleTest Advanced](advanced.md) - Read this when you've finished the
|
||||
Primer and want to utilize GoogleTest to its full potential.
|
||||
* [GoogleTest Samples](samples.md) - Describes some GoogleTest samples.
|
||||
* [GoogleTest FAQ](faq.md) - Have a question? Want some tips? Check here
|
||||
first.
|
||||
* [Mocking for Dummies](gmock_for_dummies.md) - Teaches you how to create mock
|
||||
objects and use them in tests.
|
||||
* [Mocking Cookbook](gmock_cook_book.md) - Includes tips and approaches to
|
||||
common mocking use cases.
|
||||
* [Mocking Cheat Sheet](gmock_cheat_sheet.md) - A handy reference for
|
||||
matchers, actions, invariants, and more.
|
||||
* [Mocking FAQ](gmock_faq.md) - Contains answers to some mocking-specific
|
||||
questions.
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user