mirror of
https://github.com/jbeder/yaml-cpp.git
synced 2025-09-10 13:01:18 +00:00
Compare commits
35 Commits
yaml-cpp-0
...
travis-upd
Author | SHA1 | Date | |
---|---|---|---|
![]() |
33bdf167e0 | ||
![]() |
b43575f89c | ||
![]() |
6f7ead5171 | ||
![]() |
cf93f4c57b | ||
![]() |
26faac387c | ||
![]() |
120863ba5a | ||
![]() |
b2f89386d8 | ||
![]() |
1bfbd2be4c | ||
![]() |
de8253fcb0 | ||
![]() |
29dcf92f87 | ||
![]() |
ce056acab7 | ||
![]() |
9ab22ef493 | ||
![]() |
1928bca4a4 | ||
![]() |
c9460110e0 | ||
![]() |
3dca8668b1 | ||
![]() |
587b24e2ee | ||
![]() |
5b3e30bfe9 | ||
![]() |
72f699f5ce | ||
![]() |
a8ba6a8dca | ||
![]() |
14c87258cd | ||
![]() |
f531f8a8c3 | ||
![]() |
52a1378e48 | ||
![]() |
c9a0077024 | ||
![]() |
b650bc8287 | ||
![]() |
21d75fa4cd | ||
![]() |
848091124d | ||
![]() |
6e87b37034 | ||
![]() |
0fddd1e5bd | ||
![]() |
99d95d8edc | ||
![]() |
a6ed66abca | ||
![]() |
e6b3a92e67 | ||
![]() |
47d32aadf0 | ||
![]() |
9d7e556ed5 | ||
![]() |
62ff351432 | ||
![]() |
5e9cb0128d |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
build/
|
build/
|
||||||
/tags
|
/tags
|
||||||
|
/bazel-*
|
||||||
|
51
.travis.yml
51
.travis.yml
@@ -1,28 +1,37 @@
|
|||||||
language: c++
|
language: c++
|
||||||
os:
|
|
||||||
- linux
|
matrix:
|
||||||
- osx
|
include:
|
||||||
compiler:
|
- os: linux
|
||||||
- clang
|
compiler: gcc
|
||||||
- gcc
|
- os: osx
|
||||||
before_install:
|
compiler: clang
|
||||||
- |
|
- os: osx
|
||||||
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
compiler: gcc
|
||||||
sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y \
|
env:
|
||||||
&& sudo apt-get update -qq \
|
- CTEST_OUTPUT_ON_FAILURE=1
|
||||||
&& if [ "$CXX" == "g++" ]; then
|
|
||||||
sudo apt-get install -qq g++-4.7 && export CXX="g++-4.7" CC="gcc-4.7"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
before_script:
|
before_script:
|
||||||
- mkdir build
|
- mkdir build
|
||||||
- cd build
|
- cd build
|
||||||
- cmake ..
|
- cmake ..
|
||||||
|
- cd ..
|
||||||
script:
|
script:
|
||||||
- make
|
- cmake --build build
|
||||||
- test/run-tests
|
- cmake --build build --target test
|
||||||
|
|
||||||
matrix:
|
addons:
|
||||||
exclude:
|
apt:
|
||||||
- os: linux
|
sources:
|
||||||
compiler: clang
|
- 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
|
||||||
|
14
BUILD.bazel
Normal file
14
BUILD.bazel
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
cc_library(
|
||||||
|
name = "yaml-cpp_internal",
|
||||||
|
visibility = ["//:__subpackages__"],
|
||||||
|
strip_include_prefix = "src",
|
||||||
|
hdrs = glob(["src/**/*.h"]),
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "yaml-cpp",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
includes = ["include"],
|
||||||
|
hdrs = glob(["include/**/*.h"]),
|
||||||
|
srcs = glob(["src/**/*.cpp", "src/**/*.h"]),
|
||||||
|
)
|
452
CMakeLists.txt
452
CMakeLists.txt
@@ -1,367 +1,161 @@
|
|||||||
###
|
# 3.5 is actually available almost everywhere, but this a good minimum
|
||||||
### CMake settings
|
cmake_minimum_required(VERSION 3.4)
|
||||||
###
|
project(YAML_CPP VERSION 0.7.0 LANGUAGES CXX)
|
||||||
# see http://www.cmake.org/Wiki/CMake_Policies
|
|
||||||
cmake_minimum_required(VERSION 3.1)
|
|
||||||
|
|
||||||
|
include(CMakePackageConfigHelpers)
|
||||||
|
include(CMakeDependentOption)
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
include(CTest)
|
||||||
|
|
||||||
###
|
find_program(YAML_CPP_CLANG_FORMAT_EXE NAMES clang-format)
|
||||||
### Project settings
|
|
||||||
###
|
|
||||||
project(YAML_CPP VERSION 0.6.3)
|
|
||||||
|
|
||||||
###
|
option(YAML_CPP_BUILD_CONTRIB "Enable yaml-cpp contrib in library" ON)
|
||||||
### Project options
|
|
||||||
###
|
|
||||||
## Project stuff
|
|
||||||
option(YAML_CPP_BUILD_TESTS "Enable testing" ON)
|
|
||||||
option(YAML_CPP_BUILD_TOOLS "Enable parse tools" ON)
|
option(YAML_CPP_BUILD_TOOLS "Enable parse tools" ON)
|
||||||
option(YAML_CPP_BUILD_CONTRIB "Enable contrib stuff in library" ON)
|
option(YAML_BUILD_SHARED_LIBS "Build yaml-cpp shared library" ${BUILD_SHARED_LIBS})
|
||||||
option(YAML_CPP_INSTALL "Enable generation of install target" ON)
|
|
||||||
|
|
||||||
## Build options
|
cmake_dependent_option(YAML_CPP_BUILD_TESTS
|
||||||
# --> General
|
"Enable yaml-cpp tests" ON
|
||||||
# see http://www.cmake.org/cmake/help/cmake2.6docs.html#variable:BUILD_SHARED_LIBS
|
"BUILD_TESTING;CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
|
||||||
# http://www.cmake.org/cmake/help/cmake2.6docs.html#command:add_library
|
cmake_dependent_option(YAML_CPP_INSTALL
|
||||||
option(YAML_BUILD_SHARED_LIBS "Build Shared Libraries" OFF)
|
"Enable generation of yaml-cpp install targets" ON
|
||||||
|
"CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
|
||||||
|
cmake_dependent_option(YAML_MSVC_SHARED_RT
|
||||||
|
"MSVC: Build yaml-cpp with shared runtime libs (/MD)" ON
|
||||||
|
"MSVC" OFF)
|
||||||
|
|
||||||
# --> Apple
|
set(yaml-cpp-type STATIC)
|
||||||
if(APPLE)
|
set(yaml-cpp-label-postfix "static")
|
||||||
option(YAML_APPLE_UNIVERSAL_BIN "Apple: Build universal binary" OFF)
|
if (YAML_BUILD_SHARED_LIBS)
|
||||||
|
set(yaml-cpp-type SHARED)
|
||||||
|
set(yaml-cpp-label-postfix "shared")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# --> Microsoft Visual C++
|
set(build-shared $<BOOL:${YAML_BUILD_SHARED_LIBS}>)
|
||||||
# see http://msdn.microsoft.com/en-us/library/aa278396(v=VS.60).aspx
|
set(build-windows-dll $<AND:$<BOOL:${CMAKE_HOST_WIN32}>,${build-shared}>)
|
||||||
# http://msdn.microsoft.com/en-us/library/2kzt1wy3(v=VS.71).aspx
|
set(not-msvc $<NOT:$<CXX_COMPILER_ID:MSVC>>)
|
||||||
if(MSVC)
|
|
||||||
option(YAML_MSVC_SHARED_RT "MSVC: Build with shared runtime libs (/MD)" ON)
|
if (NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY)
|
||||||
option(YAML_MSVC_STHREADED_RT "MSVC: Build with single-threaded static runtime libs (/ML until VS .NET 2003)" OFF)
|
set(CMAKE_MSVC_RUNTIME_LIBRARY
|
||||||
|
MultiThreaded$<$<CONFIG:Debug>:Debug>$<${build-shared}:DLL>)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
###
|
set(contrib-pattern "src/contrib/*.cpp")
|
||||||
### Sources, headers, directories and libs
|
set(src-pattern "src/*.cpp")
|
||||||
###
|
if (CMAKE_VERSION VERSION_GREATER 3.12)
|
||||||
|
list(INSERT contrib-pattern 0 CONFIGURE_DEPENDS)
|
||||||
# From http://www.cmake.org/pipermail/cmake/2010-March/035992.html:
|
list(INSERT src-pattern 0 CONFIGURE_DEPENDS)
|
||||||
# function to collect all the sources from sub-directories
|
|
||||||
# into a single list
|
|
||||||
function(add_sources)
|
|
||||||
get_property(is_defined GLOBAL PROPERTY SRCS_LIST DEFINED)
|
|
||||||
if(NOT is_defined)
|
|
||||||
define_property(GLOBAL PROPERTY SRCS_LIST
|
|
||||||
BRIEF_DOCS "List of source files"
|
|
||||||
FULL_DOCS "List of all source files in the entire project")
|
|
||||||
endif()
|
|
||||||
# make absolute paths
|
|
||||||
set(SRCS)
|
|
||||||
foreach(s IN LISTS ARGN)
|
|
||||||
if(NOT IS_ABSOLUTE "${s}")
|
|
||||||
get_filename_component(s "${s}" ABSOLUTE)
|
|
||||||
endif()
|
|
||||||
list(APPEND SRCS "${s}")
|
|
||||||
endforeach()
|
|
||||||
# append to global list
|
|
||||||
set_property(GLOBAL APPEND PROPERTY SRCS_LIST "${SRCS}")
|
|
||||||
endfunction(add_sources)
|
|
||||||
|
|
||||||
set(header_directory "include/yaml-cpp/")
|
|
||||||
|
|
||||||
file(GLOB sources "src/[a-zA-Z]*.cpp")
|
|
||||||
file(GLOB_RECURSE public_headers "include/yaml-cpp/[a-zA-Z]*.h")
|
|
||||||
file(GLOB private_headers "src/[a-zA-Z]*.h")
|
|
||||||
|
|
||||||
if(YAML_CPP_BUILD_CONTRIB)
|
|
||||||
file(GLOB contrib_sources "src/contrib/[a-zA-Z]*.cpp")
|
|
||||||
file(GLOB contrib_public_headers "include/yaml-cpp/contrib/[a-zA-Z]*.h")
|
|
||||||
file(GLOB contrib_private_headers "src/contrib/[a-zA-Z]*.h")
|
|
||||||
else()
|
|
||||||
add_definitions(-DYAML_CPP_NO_CONTRIB)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(library_sources
|
file(GLOB yaml-cpp-contrib-sources ${contrib-pattern})
|
||||||
${sources}
|
file(GLOB yaml-cpp-sources ${src-pattern})
|
||||||
${public_headers}
|
|
||||||
${private_headers}
|
|
||||||
${contrib_sources}
|
|
||||||
${contrib_public_headers}
|
|
||||||
${contrib_private_headers}
|
|
||||||
)
|
|
||||||
add_sources(${library_sources})
|
|
||||||
|
|
||||||
if(VERBOSE)
|
set(msvc-rt $<TARGET_PROPERTY:MSVC_RUNTIME_LIBRARY>)
|
||||||
message(STATUS "sources: ${sources}")
|
|
||||||
message(STATUS "public_headers: ${public_headers}")
|
set(msvc-rt-mtd-static $<STREQUAL:${msvc-rt},MultiThreadedDebug>)
|
||||||
message(STATUS "private_headers: ${private_headers}")
|
set(msvc-rt-mt-static $<STREQUAL:${msvc-rt},MultiThreaded>)
|
||||||
message(STATUS "contrib_sources: ${contrib_sources}")
|
|
||||||
message(STATUS "contrib_public_headers: ${contrib_public_headers}")
|
set(msvc-rt-mtd-dll $<STREQUAL:${msvc-rt},MultiThreadedDebugDLL>)
|
||||||
message(STATUS "contrib_private_headers: ${contrib_private_headers}")
|
set(msvc-rt-mt-dll $<STREQUAL:${msvc-rt},MultiThreadedDLL>)
|
||||||
|
|
||||||
|
set(backport-msvc-runtime $<VERSION_LESS:${CMAKE_VERSION},3.15>)
|
||||||
|
|
||||||
|
add_library(yaml-cpp ${yaml-cpp-type} "")
|
||||||
|
add_library(yaml-cpp::yaml-cpp ALIAS yaml-cpp)
|
||||||
|
|
||||||
|
set_property(TARGET yaml-cpp
|
||||||
|
PROPERTY
|
||||||
|
MSVC_RUNTIME_LIBRARY ${CMAKE_MSVC_RUNTIME_LIBRARY})
|
||||||
|
set_property(TARGET yaml-cpp
|
||||||
|
PROPERTY
|
||||||
|
CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
target_include_directories(yaml-cpp
|
||||||
|
PUBLIC
|
||||||
|
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||||
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||||
|
PRIVATE
|
||||||
|
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>)
|
||||||
|
|
||||||
|
if (NOT DEFINED CMAKE_CXX_STANDARD)
|
||||||
|
set_target_properties(yaml-cpp
|
||||||
|
PROPERTIES
|
||||||
|
CXX_STANDARD 11)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (CMAKE_VERSION VERSION_LESS 2.8.12)
|
target_compile_options(yaml-cpp
|
||||||
include_directories(${YAML_CPP_SOURCE_DIR}/src)
|
PRIVATE
|
||||||
include_directories(${YAML_CPP_SOURCE_DIR}/include)
|
$<${not-msvc}:-Wall -Wextra -Wshadow -Weffc++ -Wno-long-long>
|
||||||
endif()
|
$<${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>
|
||||||
|
$<$<AND:${backport-msvc-runtime},${msvc-rt-mt-dll}>:-MD>
|
||||||
|
|
||||||
###
|
# /wd4127 = disable warning C4127 "conditional expression is constant"
|
||||||
### General compilation settings
|
# http://msdn.microsoft.com/en-us/library/6t66728h.aspx
|
||||||
###
|
# /wd4355 = disable warning C4355 "'this' : used in base member initializer list
|
||||||
set(yaml_c_flags ${CMAKE_C_FLAGS})
|
# http://msdn.microsoft.com/en-us/library/3c594ae3.aspx
|
||||||
set(yaml_cxx_flags ${CMAKE_CXX_FLAGS})
|
$<$<CXX_COMPILER_ID:MSVC>:/W3 /wd4127 /wd4355>)
|
||||||
|
|
||||||
if(YAML_BUILD_SHARED_LIBS)
|
target_compile_definitions(yaml-cpp
|
||||||
set(LABEL_SUFFIX "shared")
|
PRIVATE
|
||||||
else()
|
$<${build-windows-dll}:${PROJECT_NAME}_DLL>
|
||||||
set(LABEL_SUFFIX "static")
|
$<$<NOT:$<BOOL:${YAML_CPP_BUILD_CONTRIB}>>:YAML_CPP_NO_CONTRIB>)
|
||||||
endif()
|
|
||||||
|
|
||||||
if(APPLE)
|
target_sources(yaml-cpp
|
||||||
if(YAML_APPLE_UNIVERSAL_BIN)
|
PRIVATE
|
||||||
set(CMAKE_OSX_ARCHITECTURES ppc;i386)
|
$<$<BOOL:${YAML_CPP_BUILD_CONTRIB}>:${yaml-cpp-contrib-sources}>
|
||||||
endif()
|
${yaml-cpp-sources})
|
||||||
endif()
|
|
||||||
|
|
||||||
if(IPHONE)
|
|
||||||
set(CMAKE_OSX_SYSROOT "iphoneos4.2")
|
|
||||||
set(CMAKE_OSX_ARCHITECTURES "armv6;armv7")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WIN32)
|
|
||||||
if(YAML_BUILD_SHARED_LIBS)
|
|
||||||
add_definitions(-D${PROJECT_NAME}_DLL) # use or build Windows DLL
|
|
||||||
endif()
|
|
||||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
|
||||||
set(CMAKE_INSTALL_PREFIX "C:/")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# GCC or Clang or Intel Compiler specialities
|
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR
|
|
||||||
(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") OR
|
|
||||||
CMAKE_CXX_COMPILER_ID MATCHES "Intel")
|
|
||||||
|
|
||||||
### General stuff
|
|
||||||
if(WIN32)
|
|
||||||
set(CMAKE_SHARED_LIBRARY_PREFIX "") # DLLs do not have a "lib" prefix
|
|
||||||
set(CMAKE_IMPORT_LIBRARY_PREFIX "") # same for DLL import libs
|
|
||||||
set(CMAKE_LINK_DEF_FILE_FLAG "") # CMake workaround (2.8.3)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
### Project stuff
|
|
||||||
if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
|
|
||||||
set(CMAKE_BUILD_TYPE Release)
|
|
||||||
endif()
|
|
||||||
#
|
|
||||||
set(GCC_EXTRA_OPTIONS "")
|
|
||||||
#
|
|
||||||
if(YAML_BUILD_SHARED_LIBS)
|
|
||||||
set(GCC_EXTRA_OPTIONS "${GCC_EXTRA_OPTIONS} -fPIC")
|
|
||||||
endif()
|
|
||||||
#
|
|
||||||
set(FLAG_TESTED "-Wextra -Wshadow -Weffc++ -pedantic -pedantic-errors")
|
|
||||||
check_cxx_compiler_flag(${FLAG_TESTED} FLAG_WEXTRA)
|
|
||||||
if(FLAG_WEXTRA)
|
|
||||||
set(GCC_EXTRA_OPTIONS "${GCC_EXTRA_OPTIONS} ${FLAG_TESTED}")
|
|
||||||
endif()
|
|
||||||
#
|
|
||||||
set(yaml_cxx_flags "-Wall ${GCC_EXTRA_OPTIONS} -pedantic -Wno-long-long ${yaml_cxx_flags}")
|
|
||||||
|
|
||||||
### Make specific
|
|
||||||
if(${CMAKE_BUILD_TOOL} MATCHES make OR ${CMAKE_BUILD_TOOL} MATCHES gmake)
|
|
||||||
add_custom_target(debuggable ${CMAKE_MAKE_PROGRAM} clean
|
|
||||||
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${CMAKE_SOURCE_DIR}
|
|
||||||
COMMENT "Adjusting settings for debug compilation"
|
|
||||||
VERBATIM)
|
|
||||||
add_custom_target(releasable ${CMAKE_MAKE_PROGRAM} clean
|
|
||||||
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Release ${CMAKE_SOURCE_DIR}
|
|
||||||
COMMENT "Adjusting settings for release compilation"
|
|
||||||
VERBATIM)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Microsoft VisualC++ specialities
|
|
||||||
if(MSVC)
|
|
||||||
### General stuff
|
|
||||||
# a) Change MSVC runtime library settings (/MD[d], /MT[d], /ML[d] (single-threaded until VS 2003))
|
|
||||||
# plus set lib suffix for later use and project label accordingly
|
|
||||||
# see http://msdn.microsoft.com/en-us/library/aa278396(v=VS.60).aspx
|
|
||||||
# http://msdn.microsoft.com/en-us/library/2kzt1wy3(v=VS.71).aspx
|
|
||||||
set(LIB_RT_SUFFIX "md") # CMake defaults to /MD for MSVC
|
|
||||||
set(LIB_RT_OPTION "/MD")
|
|
||||||
#
|
|
||||||
if(NOT YAML_MSVC_SHARED_RT) # User wants to have static runtime libraries (/MT, /ML)
|
|
||||||
if(YAML_MSVC_STHREADED_RT) # User wants to have old single-threaded static runtime libraries
|
|
||||||
set(LIB_RT_SUFFIX "ml")
|
|
||||||
set(LIB_RT_OPTION "/ML")
|
|
||||||
if(NOT ${MSVC_VERSION} LESS 1400)
|
|
||||||
message(FATAL_ERROR "Single-threaded static runtime libraries (/ML) only available until VS .NET 2003 (7.1).")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
set(LIB_RT_SUFFIX "mt")
|
|
||||||
set(LIB_RT_OPTION "/MT")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# correct linker options
|
|
||||||
foreach(flag_var CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
|
||||||
foreach(config_name "" DEBUG RELEASE MINSIZEREL RELWITHDEBINFO)
|
|
||||||
set(var_name "${flag_var}")
|
|
||||||
if(NOT "${config_name}" STREQUAL "")
|
|
||||||
set(var_name "${var_name}_${config_name}")
|
|
||||||
endif()
|
|
||||||
string(REPLACE "/MD" "${LIB_RT_OPTION}" ${var_name} "${${var_name}}")
|
|
||||||
set(${var_name} "${${var_name}}" CACHE STRING "" FORCE)
|
|
||||||
endforeach()
|
|
||||||
endforeach()
|
|
||||||
endif()
|
|
||||||
#
|
|
||||||
set(LABEL_SUFFIX "${LABEL_SUFFIX} ${LIB_RT_SUFFIX}")
|
|
||||||
|
|
||||||
# b) Change prefix for static libraries
|
|
||||||
set(CMAKE_STATIC_LIBRARY_PREFIX "lib") # to distinguish static libraries from DLL import libs
|
|
||||||
|
|
||||||
# c) Correct suffixes for static libraries
|
|
||||||
if(NOT YAML_BUILD_SHARED_LIBS)
|
|
||||||
### General stuff
|
|
||||||
set(LIB_TARGET_SUFFIX "${LIB_SUFFIX}${LIB_RT_SUFFIX}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
### Project stuff
|
|
||||||
# /W3 = set warning level; see http://msdn.microsoft.com/en-us/library/thxezb7y.aspx
|
|
||||||
# /wd4127 = disable warning C4127 "conditional expression is constant"; see http://msdn.microsoft.com/en-us/library/6t66728h.aspx
|
|
||||||
# /wd4355 = disable warning C4355 "'this' : used in base member initializer list"; http://msdn.microsoft.com/en-us/library/3c594ae3.aspx
|
|
||||||
set(yaml_cxx_flags "/W3 /wd4127 /wd4355 ${yaml_cxx_flags}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
###
|
|
||||||
### General install settings
|
|
||||||
###
|
|
||||||
set(INCLUDE_INSTALL_ROOT_DIR include)
|
|
||||||
|
|
||||||
set(INCLUDE_INSTALL_DIR ${INCLUDE_INSTALL_ROOT_DIR}/yaml-cpp)
|
|
||||||
set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}")
|
|
||||||
|
|
||||||
set(_INSTALL_DESTINATIONS
|
|
||||||
RUNTIME DESTINATION bin
|
|
||||||
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
|
|
||||||
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
###
|
|
||||||
### Library
|
|
||||||
###
|
|
||||||
if(YAML_BUILD_SHARED_LIBS)
|
|
||||||
add_library(yaml-cpp SHARED ${library_sources})
|
|
||||||
else()
|
|
||||||
add_library(yaml-cpp STATIC ${library_sources})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (NOT CMAKE_VERSION VERSION_LESS 2.8.12)
|
|
||||||
target_include_directories(yaml-cpp
|
|
||||||
PUBLIC $<BUILD_INTERFACE:${YAML_CPP_SOURCE_DIR}/include>
|
|
||||||
$<INSTALL_INTERFACE:${INCLUDE_INSTALL_ROOT_DIR}>
|
|
||||||
PRIVATE $<BUILD_INTERFACE:${YAML_CPP_SOURCE_DIR}/src>)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set_target_properties(yaml-cpp PROPERTIES
|
set_target_properties(yaml-cpp PROPERTIES
|
||||||
CXX_STANDARD 11
|
VERSION "${PROJECT_VERSION}"
|
||||||
CXX_STANDARD_REQUIRED ON
|
SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
|
||||||
)
|
PROJECT_LABEL "yaml-cpp ${yaml-cpp-label-postfix}"
|
||||||
|
DEBUG_POSTFIX d)
|
||||||
|
|
||||||
set_target_properties(yaml-cpp PROPERTIES
|
configure_package_config_file(
|
||||||
COMPILE_FLAGS "${yaml_c_flags} ${yaml_cxx_flags}"
|
"${PROJECT_SOURCE_DIR}/yaml-cpp-config.cmake.in"
|
||||||
)
|
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake"
|
||||||
|
INSTALL_DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/yaml-cpp")
|
||||||
|
|
||||||
set_target_properties(yaml-cpp PROPERTIES
|
write_basic_package_version_file(
|
||||||
VERSION "${YAML_CPP_VERSION}"
|
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake"
|
||||||
SOVERSION "${YAML_CPP_VERSION_MAJOR}.${YAML_CPP_VERSION_MINOR}"
|
COMPATIBILITY AnyNewerVersion)
|
||||||
PROJECT_LABEL "yaml-cpp ${LABEL_SUFFIX}"
|
|
||||||
)
|
|
||||||
|
|
||||||
if(IPHONE)
|
configure_file(yaml-cpp.pc.in yaml-cpp.pc @ONLY)
|
||||||
set_target_properties(yaml-cpp PROPERTIES
|
|
||||||
XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "3.0"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(MSVC)
|
|
||||||
if(NOT YAML_BUILD_SHARED_LIBS)
|
|
||||||
# correct library names
|
|
||||||
set_target_properties(yaml-cpp PROPERTIES
|
|
||||||
DEBUG_POSTFIX "${LIB_TARGET_SUFFIX}d"
|
|
||||||
RELEASE_POSTFIX "${LIB_TARGET_SUFFIX}"
|
|
||||||
MINSIZEREL_POSTFIX "${LIB_TARGET_SUFFIX}"
|
|
||||||
RELWITHDEBINFO_POSTFIX "${LIB_TARGET_SUFFIX}"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (YAML_CPP_INSTALL)
|
|
||||||
install(TARGETS yaml-cpp EXPORT yaml-cpp-targets ${_INSTALL_DESTINATIONS})
|
|
||||||
install(
|
|
||||||
DIRECTORY ${header_directory}
|
|
||||||
DESTINATION ${INCLUDE_INSTALL_DIR}
|
|
||||||
FILES_MATCHING PATTERN "*.h"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
export(
|
|
||||||
TARGETS yaml-cpp
|
|
||||||
FILE "${PROJECT_BINARY_DIR}/yaml-cpp-targets.cmake")
|
|
||||||
export(PACKAGE yaml-cpp)
|
|
||||||
set(EXPORT_TARGETS yaml-cpp CACHE INTERNAL "export targets")
|
|
||||||
|
|
||||||
set(CONFIG_INCLUDE_DIRS "${YAML_CPP_SOURCE_DIR}/include")
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/yaml-cpp-config.cmake.in
|
|
||||||
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake" @ONLY)
|
|
||||||
|
|
||||||
if(WIN32 AND NOT CYGWIN)
|
|
||||||
set(INSTALL_CMAKE_DIR CMake)
|
|
||||||
else()
|
|
||||||
set(INSTALL_CMAKE_DIR ${LIB_INSTALL_DIR}/cmake/yaml-cpp)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
file(RELATIVE_PATH REL_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/${INSTALL_CMAKE_DIR}" "${CMAKE_INSTALL_PREFIX}/${INCLUDE_INSTALL_ROOT_DIR}")
|
|
||||||
set(CONFIG_INCLUDE_DIRS "\${YAML_CPP_CMAKE_DIR}/${REL_INCLUDE_DIR}")
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/yaml-cpp-config.cmake.in
|
|
||||||
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/yaml-cpp-config.cmake" @ONLY)
|
|
||||||
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/yaml-cpp-config-version.cmake.in
|
|
||||||
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake" @ONLY)
|
|
||||||
|
|
||||||
if (YAML_CPP_INSTALL)
|
if (YAML_CPP_INSTALL)
|
||||||
|
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/
|
||||||
|
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||||
|
FILES_MATCHING PATTERN "*.h")
|
||||||
|
install(EXPORT yaml-cpp-targets
|
||||||
|
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/yaml-cpp")
|
||||||
install(FILES
|
install(FILES
|
||||||
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/yaml-cpp-config.cmake"
|
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake"
|
||||||
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake"
|
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake"
|
||||||
DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev)
|
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/yaml-cpp")
|
||||||
install(EXPORT yaml-cpp-targets DESTINATION ${INSTALL_CMAKE_DIR})
|
install(FILES "${PROJECT_BINARY_DIR}/yaml-cpp.pc"
|
||||||
|
DESTINATION ${CMAKE_INSTALL_DATADIR}/pkgconfig)
|
||||||
if(UNIX)
|
|
||||||
set(PC_FILE ${CMAKE_BINARY_DIR}/yaml-cpp.pc)
|
|
||||||
configure_file("yaml-cpp.pc.cmake" ${PC_FILE} @ONLY)
|
|
||||||
install(FILES ${PC_FILE} DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
###
|
|
||||||
### Extras
|
|
||||||
###
|
|
||||||
if(YAML_CPP_BUILD_TESTS)
|
if(YAML_CPP_BUILD_TESTS)
|
||||||
enable_testing()
|
|
||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(YAML_CPP_BUILD_TOOLS)
|
if(YAML_CPP_BUILD_TOOLS)
|
||||||
add_subdirectory(util)
|
add_subdirectory(util)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
### Formatting
|
if (YAML_CPP_CLANG_FORMAT_EXE)
|
||||||
get_property(all_sources GLOBAL PROPERTY SRCS_LIST)
|
add_custom_target(format
|
||||||
add_custom_target(format
|
COMMAND clang-format --style=file -i $<TARGET_PROPERTY:yaml-cpp,SOURCES>
|
||||||
COMMAND clang-format --style=file -i ${all_sources}
|
COMMENT "Running clang-format"
|
||||||
COMMENT "Running clang-format"
|
VERBATIM)
|
||||||
VERBATIM)
|
endif()
|
||||||
|
@@ -49,3 +49,7 @@ cmake [-G generator] [-DYAML_BUILD_SHARED_LIBS=ON|OFF] ..
|
|||||||
[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.
|
[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.
|
||||||
|
|
||||||
**The old API will continue to be supported, and will still receive bugfixes!** The 0.3.x and 0.4.x versions will be old API releases, and 0.5.x and above will all be new API releases.
|
**The old API will continue to be supported, and will still receive bugfixes!** The 0.3.x and 0.4.x versions will be old API releases, and 0.5.x and above will all be new API releases.
|
||||||
|
|
||||||
|
# API Documentation
|
||||||
|
|
||||||
|
The autogenerated API reference is hosted on [CodeDocs](https://codedocs.xyz/jbeder/yaml-cpp/index.html)
|
||||||
|
10
WORKSPACE
Normal file
10
WORKSPACE
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
workspace(name = "com_github_jbeder_yaml_cpp")
|
||||||
|
|
||||||
|
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||||
|
|
||||||
|
http_archive(
|
||||||
|
name = "com_google_googletest",
|
||||||
|
strip_prefix = "googletest-release-1.8.1",
|
||||||
|
url = "https://github.com/google/googletest/archive/release-1.8.1.tar.gz",
|
||||||
|
sha256 = "9bf1fe5182a604b4135edc1a425ae356c9ad15e9b23f9f12a02e80184c3a249c",
|
||||||
|
)
|
@@ -10,7 +10,7 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
typedef std::size_t anchor_t;
|
using anchor_t = std::size_t;
|
||||||
const anchor_t NullAnchor = 0;
|
const anchor_t NullAnchor = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -15,7 +15,7 @@ class Parser;
|
|||||||
|
|
||||||
// GraphBuilderInterface
|
// GraphBuilderInterface
|
||||||
// . Abstraction of node creation
|
// . Abstraction of node creation
|
||||||
// . pParentNode is always NULL or the return value of one of the NewXXX()
|
// . pParentNode is always nullptr or the return value of one of the NewXXX()
|
||||||
// functions.
|
// functions.
|
||||||
class GraphBuilderInterface {
|
class GraphBuilderInterface {
|
||||||
public:
|
public:
|
||||||
@@ -73,9 +73,9 @@ class GraphBuilder : public GraphBuilderInterface {
|
|||||||
typedef typename Impl::Map Map;
|
typedef typename Impl::Map Map;
|
||||||
|
|
||||||
GraphBuilder(Impl &impl) : m_impl(impl) {
|
GraphBuilder(Impl &impl) : m_impl(impl) {
|
||||||
Map *pMap = NULL;
|
Map *pMap = nullptr;
|
||||||
Sequence *pSeq = NULL;
|
Sequence *pSeq = nullptr;
|
||||||
Node *pNode = NULL;
|
Node *pNode = nullptr;
|
||||||
|
|
||||||
// Type consistency checks
|
// Type consistency checks
|
||||||
pNode = pMap;
|
pNode = pMap;
|
||||||
|
@@ -24,21 +24,21 @@ class EmitFromEvents : public EventHandler {
|
|||||||
public:
|
public:
|
||||||
EmitFromEvents(Emitter& emitter);
|
EmitFromEvents(Emitter& emitter);
|
||||||
|
|
||||||
virtual void OnDocumentStart(const Mark& mark);
|
void OnDocumentStart(const Mark& mark) override;
|
||||||
virtual void OnDocumentEnd();
|
void OnDocumentEnd() override;
|
||||||
|
|
||||||
virtual void OnNull(const Mark& mark, anchor_t anchor);
|
void OnNull(const Mark& mark, anchor_t anchor) override;
|
||||||
virtual void OnAlias(const Mark& mark, anchor_t anchor);
|
void OnAlias(const Mark& mark, anchor_t anchor) override;
|
||||||
virtual void OnScalar(const Mark& mark, const std::string& tag,
|
void OnScalar(const Mark& mark, const std::string& tag,
|
||||||
anchor_t anchor, const std::string& value);
|
anchor_t anchor, const std::string& value) override;
|
||||||
|
|
||||||
virtual void OnSequenceStart(const Mark& mark, const std::string& tag,
|
void OnSequenceStart(const Mark& mark, const std::string& tag,
|
||||||
anchor_t anchor, EmitterStyle::value style);
|
anchor_t anchor, EmitterStyle::value style) override;
|
||||||
virtual void OnSequenceEnd();
|
void OnSequenceEnd() override;
|
||||||
|
|
||||||
virtual void OnMapStart(const Mark& mark, const std::string& tag,
|
void OnMapStart(const Mark& mark, const std::string& tag,
|
||||||
anchor_t anchor, EmitterStyle::value style);
|
anchor_t anchor, EmitterStyle::value style) override;
|
||||||
virtual void OnMapEnd();
|
void OnMapEnd() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void BeginNode();
|
void BeginNode();
|
||||||
|
@@ -164,13 +164,12 @@ inline Emitter& Emitter::WriteStreamable(T value) {
|
|||||||
std::isnan(value)) {
|
std::isnan(value)) {
|
||||||
special = true;
|
special = true;
|
||||||
stream << ".nan";
|
stream << ".nan";
|
||||||
} else if (std::numeric_limits<T>::has_infinity) {
|
} else if (std::numeric_limits<T>::has_infinity && std::isinf(value)) {
|
||||||
if (value == std::numeric_limits<T>::infinity()) {
|
special = true;
|
||||||
special = true;
|
if (std::signbit(value)) {
|
||||||
stream << ".inf";
|
|
||||||
} else if (value == -std::numeric_limits<T>::infinity()) {
|
|
||||||
special = true;
|
|
||||||
stream << "-.inf";
|
stream << "-.inf";
|
||||||
|
} else {
|
||||||
|
stream << ".inf";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -74,14 +74,14 @@ struct _Alias {
|
|||||||
std::string content;
|
std::string content;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline _Alias Alias(const std::string content) { return _Alias(content); }
|
inline _Alias Alias(const std::string& content) { return _Alias(content); }
|
||||||
|
|
||||||
struct _Anchor {
|
struct _Anchor {
|
||||||
_Anchor(const std::string& content_) : content(content_) {}
|
_Anchor(const std::string& content_) : content(content_) {}
|
||||||
std::string content;
|
std::string content;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline _Anchor Anchor(const std::string content) { return _Anchor(content); }
|
inline _Anchor Anchor(const std::string& content) { return _Anchor(content); }
|
||||||
|
|
||||||
struct _Tag {
|
struct _Tag {
|
||||||
struct Type {
|
struct Type {
|
||||||
@@ -96,11 +96,11 @@ struct _Tag {
|
|||||||
Type::value type;
|
Type::value type;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline _Tag VerbatimTag(const std::string content) {
|
inline _Tag VerbatimTag(const std::string& content) {
|
||||||
return _Tag("", content, _Tag::Type::Verbatim);
|
return _Tag("", content, _Tag::Type::Verbatim);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline _Tag LocalTag(const std::string content) {
|
inline _Tag LocalTag(const std::string& content) {
|
||||||
return _Tag("", content, _Tag::Type::PrimaryHandle);
|
return _Tag("", content, _Tag::Type::PrimaryHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@ inline _Tag LocalTag(const std::string& prefix, const std::string content) {
|
|||||||
return _Tag(prefix, content, _Tag::Type::NamedHandle);
|
return _Tag(prefix, content, _Tag::Type::NamedHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline _Tag SecondaryTag(const std::string content) {
|
inline _Tag SecondaryTag(const std::string& content) {
|
||||||
return _Tag("", content, _Tag::Type::NamedHandle);
|
return _Tag("", content, _Tag::Type::NamedHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ struct _Comment {
|
|||||||
std::string content;
|
std::string content;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline _Comment Comment(const std::string content) { return _Comment(content); }
|
inline _Comment Comment(const std::string& content) { return _Comment(content); }
|
||||||
|
|
||||||
struct _Precision {
|
struct _Precision {
|
||||||
_Precision(int floatPrecision_, int doublePrecision_)
|
_Precision(int floatPrecision_, int doublePrecision_)
|
||||||
|
@@ -17,7 +17,7 @@ struct Mark;
|
|||||||
|
|
||||||
class EventHandler {
|
class EventHandler {
|
||||||
public:
|
public:
|
||||||
virtual ~EventHandler() {}
|
virtual ~EventHandler() = default;
|
||||||
|
|
||||||
virtual void OnDocumentStart(const Mark& mark) = 0;
|
virtual void OnDocumentStart(const Mark& mark) = 0;
|
||||||
virtual void OnDocumentEnd() = 0;
|
virtual void OnDocumentEnd() = 0;
|
||||||
|
@@ -8,19 +8,12 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "yaml-cpp/mark.h"
|
#include "yaml-cpp/mark.h"
|
||||||
|
#include "yaml-cpp/noexcept.h"
|
||||||
#include "yaml-cpp/traits.h"
|
#include "yaml-cpp/traits.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
// This is here for compatibility with older versions of Visual Studio
|
|
||||||
// which don't support noexcept
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
|
||||||
#define YAML_CPP_NOEXCEPT _NOEXCEPT
|
|
||||||
#else
|
|
||||||
#define YAML_CPP_NOEXCEPT noexcept
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
// error messages
|
// error messages
|
||||||
namespace ErrorMsg {
|
namespace ErrorMsg {
|
||||||
@@ -149,7 +142,7 @@ class YAML_CPP_API Exception : public std::runtime_error {
|
|||||||
public:
|
public:
|
||||||
Exception(const Mark& mark_, const std::string& msg_)
|
Exception(const Mark& mark_, const std::string& msg_)
|
||||||
: std::runtime_error(build_what(mark_, msg_)), mark(mark_), msg(msg_) {}
|
: std::runtime_error(build_what(mark_, msg_)), mark(mark_), msg(msg_) {}
|
||||||
virtual ~Exception() YAML_CPP_NOEXCEPT;
|
~Exception() YAML_CPP_NOEXCEPT override;
|
||||||
|
|
||||||
Exception(const Exception&) = default;
|
Exception(const Exception&) = default;
|
||||||
|
|
||||||
@@ -175,7 +168,7 @@ class YAML_CPP_API ParserException : public Exception {
|
|||||||
ParserException(const Mark& mark_, const std::string& msg_)
|
ParserException(const Mark& mark_, const std::string& msg_)
|
||||||
: Exception(mark_, msg_) {}
|
: Exception(mark_, msg_) {}
|
||||||
ParserException(const ParserException&) = default;
|
ParserException(const ParserException&) = default;
|
||||||
virtual ~ParserException() YAML_CPP_NOEXCEPT;
|
~ParserException() YAML_CPP_NOEXCEPT override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class YAML_CPP_API RepresentationException : public Exception {
|
class YAML_CPP_API RepresentationException : public Exception {
|
||||||
@@ -183,7 +176,7 @@ class YAML_CPP_API RepresentationException : public Exception {
|
|||||||
RepresentationException(const Mark& mark_, const std::string& msg_)
|
RepresentationException(const Mark& mark_, const std::string& msg_)
|
||||||
: Exception(mark_, msg_) {}
|
: Exception(mark_, msg_) {}
|
||||||
RepresentationException(const RepresentationException&) = default;
|
RepresentationException(const RepresentationException&) = default;
|
||||||
virtual ~RepresentationException() YAML_CPP_NOEXCEPT;
|
~RepresentationException() YAML_CPP_NOEXCEPT override;
|
||||||
};
|
};
|
||||||
|
|
||||||
// representation exceptions
|
// representation exceptions
|
||||||
@@ -192,7 +185,7 @@ class YAML_CPP_API InvalidScalar : public RepresentationException {
|
|||||||
InvalidScalar(const Mark& mark_)
|
InvalidScalar(const Mark& mark_)
|
||||||
: RepresentationException(mark_, ErrorMsg::INVALID_SCALAR) {}
|
: RepresentationException(mark_, ErrorMsg::INVALID_SCALAR) {}
|
||||||
InvalidScalar(const InvalidScalar&) = default;
|
InvalidScalar(const InvalidScalar&) = default;
|
||||||
virtual ~InvalidScalar() YAML_CPP_NOEXCEPT;
|
~InvalidScalar() YAML_CPP_NOEXCEPT override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class YAML_CPP_API KeyNotFound : public RepresentationException {
|
class YAML_CPP_API KeyNotFound : public RepresentationException {
|
||||||
@@ -202,7 +195,7 @@ class YAML_CPP_API KeyNotFound : public RepresentationException {
|
|||||||
: RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND_WITH_KEY(key_)) {
|
: RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND_WITH_KEY(key_)) {
|
||||||
}
|
}
|
||||||
KeyNotFound(const KeyNotFound&) = default;
|
KeyNotFound(const KeyNotFound&) = default;
|
||||||
virtual ~KeyNotFound() YAML_CPP_NOEXCEPT;
|
~KeyNotFound() YAML_CPP_NOEXCEPT override;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -210,7 +203,7 @@ class YAML_CPP_API TypedKeyNotFound : public KeyNotFound {
|
|||||||
public:
|
public:
|
||||||
TypedKeyNotFound(const Mark& mark_, const T& key_)
|
TypedKeyNotFound(const Mark& mark_, const T& key_)
|
||||||
: KeyNotFound(mark_, key_), key(key_) {}
|
: KeyNotFound(mark_, key_), key(key_) {}
|
||||||
virtual ~TypedKeyNotFound() YAML_CPP_NOEXCEPT {}
|
~TypedKeyNotFound() YAML_CPP_NOEXCEPT override = default;
|
||||||
|
|
||||||
T key;
|
T key;
|
||||||
};
|
};
|
||||||
@@ -223,11 +216,11 @@ inline TypedKeyNotFound<T> MakeTypedKeyNotFound(const Mark& mark,
|
|||||||
|
|
||||||
class YAML_CPP_API InvalidNode : public RepresentationException {
|
class YAML_CPP_API InvalidNode : public RepresentationException {
|
||||||
public:
|
public:
|
||||||
InvalidNode(std::string key)
|
InvalidNode(const std::string& key)
|
||||||
: RepresentationException(Mark::null_mark(),
|
: RepresentationException(Mark::null_mark(),
|
||||||
ErrorMsg::INVALID_NODE_WITH_KEY(key)) {}
|
ErrorMsg::INVALID_NODE_WITH_KEY(key)) {}
|
||||||
InvalidNode(const InvalidNode&) = default;
|
InvalidNode(const InvalidNode&) = default;
|
||||||
virtual ~InvalidNode() YAML_CPP_NOEXCEPT;
|
~InvalidNode() YAML_CPP_NOEXCEPT override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class YAML_CPP_API BadConversion : public RepresentationException {
|
class YAML_CPP_API BadConversion : public RepresentationException {
|
||||||
@@ -235,7 +228,7 @@ class YAML_CPP_API BadConversion : public RepresentationException {
|
|||||||
explicit BadConversion(const Mark& mark_)
|
explicit BadConversion(const Mark& mark_)
|
||||||
: RepresentationException(mark_, ErrorMsg::BAD_CONVERSION) {}
|
: RepresentationException(mark_, ErrorMsg::BAD_CONVERSION) {}
|
||||||
BadConversion(const BadConversion&) = default;
|
BadConversion(const BadConversion&) = default;
|
||||||
virtual ~BadConversion() YAML_CPP_NOEXCEPT;
|
~BadConversion() YAML_CPP_NOEXCEPT override;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -249,17 +242,17 @@ class YAML_CPP_API BadDereference : public RepresentationException {
|
|||||||
BadDereference()
|
BadDereference()
|
||||||
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_DEREFERENCE) {}
|
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_DEREFERENCE) {}
|
||||||
BadDereference(const BadDereference&) = default;
|
BadDereference(const BadDereference&) = default;
|
||||||
virtual ~BadDereference() YAML_CPP_NOEXCEPT;
|
~BadDereference() YAML_CPP_NOEXCEPT override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class YAML_CPP_API BadSubscript : public RepresentationException {
|
class YAML_CPP_API BadSubscript : public RepresentationException {
|
||||||
public:
|
public:
|
||||||
template <typename Key>
|
template <typename Key>
|
||||||
BadSubscript(const Key& key)
|
BadSubscript(const Mark& mark_, const Key& key)
|
||||||
: RepresentationException(Mark::null_mark(),
|
: RepresentationException(mark_,
|
||||||
ErrorMsg::BAD_SUBSCRIPT_WITH_KEY(key)) {}
|
ErrorMsg::BAD_SUBSCRIPT_WITH_KEY(key)) {}
|
||||||
BadSubscript(const BadSubscript&) = default;
|
BadSubscript(const BadSubscript&) = default;
|
||||||
virtual ~BadSubscript() YAML_CPP_NOEXCEPT;
|
~BadSubscript() YAML_CPP_NOEXCEPT override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class YAML_CPP_API BadPushback : public RepresentationException {
|
class YAML_CPP_API BadPushback : public RepresentationException {
|
||||||
@@ -267,7 +260,7 @@ class YAML_CPP_API BadPushback : public RepresentationException {
|
|||||||
BadPushback()
|
BadPushback()
|
||||||
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_PUSHBACK) {}
|
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_PUSHBACK) {}
|
||||||
BadPushback(const BadPushback&) = default;
|
BadPushback(const BadPushback&) = default;
|
||||||
virtual ~BadPushback() YAML_CPP_NOEXCEPT;
|
~BadPushback() YAML_CPP_NOEXCEPT override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class YAML_CPP_API BadInsert : public RepresentationException {
|
class YAML_CPP_API BadInsert : public RepresentationException {
|
||||||
@@ -275,7 +268,7 @@ class YAML_CPP_API BadInsert : public RepresentationException {
|
|||||||
BadInsert()
|
BadInsert()
|
||||||
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_INSERT) {}
|
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_INSERT) {}
|
||||||
BadInsert(const BadInsert&) = default;
|
BadInsert(const BadInsert&) = default;
|
||||||
virtual ~BadInsert() YAML_CPP_NOEXCEPT;
|
~BadInsert() YAML_CPP_NOEXCEPT override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class YAML_CPP_API EmitterException : public Exception {
|
class YAML_CPP_API EmitterException : public Exception {
|
||||||
@@ -283,17 +276,15 @@ class YAML_CPP_API EmitterException : public Exception {
|
|||||||
EmitterException(const std::string& msg_)
|
EmitterException(const std::string& msg_)
|
||||||
: Exception(Mark::null_mark(), msg_) {}
|
: Exception(Mark::null_mark(), msg_) {}
|
||||||
EmitterException(const EmitterException&) = default;
|
EmitterException(const EmitterException&) = default;
|
||||||
virtual ~EmitterException() YAML_CPP_NOEXCEPT;
|
~EmitterException() YAML_CPP_NOEXCEPT override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class YAML_CPP_API BadFile : public Exception {
|
class YAML_CPP_API BadFile : public Exception {
|
||||||
public:
|
public:
|
||||||
BadFile() : Exception(Mark::null_mark(), ErrorMsg::BAD_FILE) {}
|
BadFile() : Exception(Mark::null_mark(), ErrorMsg::BAD_FILE) {}
|
||||||
BadFile(const BadFile&) = default;
|
BadFile(const BadFile&) = default;
|
||||||
virtual ~BadFile() YAML_CPP_NOEXCEPT;
|
~BadFile() YAML_CPP_NOEXCEPT override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef YAML_CPP_NOEXCEPT
|
|
||||||
|
|
||||||
#endif // EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
@@ -8,10 +8,12 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <cmath>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "yaml-cpp/binary.h"
|
#include "yaml-cpp/binary.h"
|
||||||
@@ -21,6 +23,7 @@
|
|||||||
#include "yaml-cpp/node/type.h"
|
#include "yaml-cpp/node/type.h"
|
||||||
#include "yaml-cpp/null.h"
|
#include "yaml-cpp/null.h"
|
||||||
|
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
class Binary;
|
class Binary;
|
||||||
struct _Null;
|
struct _Null;
|
||||||
@@ -88,43 +91,70 @@ struct convert<_Null> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op) \
|
namespace conversion {
|
||||||
template <> \
|
template <typename T>
|
||||||
struct convert<type> { \
|
typename std::enable_if< std::is_floating_point<T>::value, void>::type
|
||||||
static Node encode(const type& rhs) { \
|
inner_encode(const T& rhs, std::stringstream& stream){
|
||||||
std::stringstream stream; \
|
if (std::isnan(rhs)) {
|
||||||
stream.precision(std::numeric_limits<type>::max_digits10); \
|
stream << ".nan";
|
||||||
stream << rhs; \
|
} else if (std::isinf(rhs)) {
|
||||||
return Node(stream.str()); \
|
if (std::signbit(rhs)) {
|
||||||
} \
|
stream << "-.inf";
|
||||||
\
|
} else {
|
||||||
static bool decode(const Node& node, type& rhs) { \
|
stream << ".inf";
|
||||||
if (node.Type() != NodeType::Scalar) \
|
}
|
||||||
return false; \
|
} else {
|
||||||
const std::string& input = node.Scalar(); \
|
stream << rhs;
|
||||||
std::stringstream stream(input); \
|
}
|
||||||
stream.unsetf(std::ios::dec); \
|
}
|
||||||
if ((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof()) \
|
|
||||||
return true; \
|
template <typename T>
|
||||||
if (std::numeric_limits<type>::has_infinity) { \
|
typename std::enable_if<!std::is_floating_point<T>::value, void>::type
|
||||||
if (conversion::IsInfinity(input)) { \
|
inner_encode(const T& rhs, std::stringstream& stream){
|
||||||
rhs = std::numeric_limits<type>::infinity(); \
|
stream << rhs;
|
||||||
return true; \
|
}
|
||||||
} else if (conversion::IsNegativeInfinity(input)) { \
|
}
|
||||||
rhs = negative_op std::numeric_limits<type>::infinity(); \
|
|
||||||
return true; \
|
#define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op) \
|
||||||
} \
|
template <> \
|
||||||
} \
|
struct convert<type> { \
|
||||||
\
|
\
|
||||||
if (std::numeric_limits<type>::has_quiet_NaN) { \
|
static Node encode(const type& rhs) { \
|
||||||
if (conversion::IsNaN(input)) { \
|
std::stringstream stream; \
|
||||||
rhs = std::numeric_limits<type>::quiet_NaN(); \
|
stream.precision(std::numeric_limits<type>::max_digits10); \
|
||||||
return true; \
|
conversion::inner_encode(rhs, stream); \
|
||||||
} \
|
return Node(stream.str()); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
return false; \
|
static bool decode(const Node& node, type& rhs) { \
|
||||||
} \
|
if (node.Type() != NodeType::Scalar) { \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
const std::string& input = node.Scalar(); \
|
||||||
|
std::stringstream stream(input); \
|
||||||
|
stream.unsetf(std::ios::dec); \
|
||||||
|
if ((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof()) { \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
|
if (std::numeric_limits<type>::has_infinity) { \
|
||||||
|
if (conversion::IsInfinity(input)) { \
|
||||||
|
rhs = std::numeric_limits<type>::infinity(); \
|
||||||
|
return true; \
|
||||||
|
} else if (conversion::IsNegativeInfinity(input)) { \
|
||||||
|
rhs = negative_op std::numeric_limits<type>::infinity(); \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
if (std::numeric_limits<type>::has_quiet_NaN) { \
|
||||||
|
if (conversion::IsNaN(input)) { \
|
||||||
|
rhs = std::numeric_limits<type>::quiet_NaN(); \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(type) \
|
#define YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(type) \
|
||||||
|
@@ -1,26 +0,0 @@
|
|||||||
#ifndef NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
|
||||||
#define NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) || \
|
|
||||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
|
||||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
|
||||||
#pragma once
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace YAML {
|
|
||||||
namespace detail {
|
|
||||||
struct unspecified_bool {
|
|
||||||
struct NOT_ALLOWED;
|
|
||||||
static void true_value(NOT_ALLOWED*) {}
|
|
||||||
};
|
|
||||||
typedef void (*unspecified_bool_type)(unspecified_bool::NOT_ALLOWED*);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define YAML_CPP_OPERATOR_BOOL() \
|
|
||||||
operator YAML::detail::unspecified_bool_type() const { \
|
|
||||||
return this->operator!() ? 0 \
|
|
||||||
: &YAML::detail::unspecified_bool::true_value; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
|
@@ -33,7 +33,7 @@ struct get_idx<Key,
|
|||||||
static node* get(std::vector<node*>& sequence, const Key& key,
|
static node* get(std::vector<node*>& sequence, const Key& key,
|
||||||
shared_memory_holder pMemory) {
|
shared_memory_holder pMemory) {
|
||||||
if (key > sequence.size() || (key > 0 && !sequence[key - 1]->is_defined()))
|
if (key > sequence.size() || (key > 0 && !sequence[key - 1]->is_defined()))
|
||||||
return 0;
|
return nullptr;
|
||||||
if (key == sequence.size())
|
if (key == sequence.size())
|
||||||
sequence.push_back(&pMemory->create_node());
|
sequence.push_back(&pMemory->create_node());
|
||||||
return sequence[key];
|
return sequence[key];
|
||||||
@@ -58,7 +58,9 @@ struct get_idx<Key, typename std::enable_if<std::is_signed<Key>::value>::type> {
|
|||||||
|
|
||||||
template <typename Key, typename Enable = void>
|
template <typename Key, typename Enable = void>
|
||||||
struct remove_idx {
|
struct remove_idx {
|
||||||
static bool remove(std::vector<node*>&, const Key&) { return false; }
|
static bool remove(std::vector<node*>&, const Key&, std::size_t&) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Key>
|
template <typename Key>
|
||||||
@@ -66,11 +68,15 @@ struct remove_idx<
|
|||||||
Key, typename std::enable_if<std::is_unsigned<Key>::value &&
|
Key, typename std::enable_if<std::is_unsigned<Key>::value &&
|
||||||
!std::is_same<Key, bool>::value>::type> {
|
!std::is_same<Key, bool>::value>::type> {
|
||||||
|
|
||||||
static bool remove(std::vector<node*>& sequence, const Key& key) {
|
static bool remove(std::vector<node*>& sequence, const Key& key,
|
||||||
|
std::size_t& seqSize) {
|
||||||
if (key >= sequence.size()) {
|
if (key >= sequence.size()) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
sequence.erase(sequence.begin() + key);
|
sequence.erase(sequence.begin() + key);
|
||||||
|
if (seqSize > key) {
|
||||||
|
--seqSize;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,9 +86,10 @@ template <typename Key>
|
|||||||
struct remove_idx<Key,
|
struct remove_idx<Key,
|
||||||
typename std::enable_if<std::is_signed<Key>::value>::type> {
|
typename std::enable_if<std::is_signed<Key>::value>::type> {
|
||||||
|
|
||||||
static bool remove(std::vector<node*>& sequence, const Key& key) {
|
static bool remove(std::vector<node*>& sequence, const Key& key,
|
||||||
|
std::size_t& seqSize) {
|
||||||
return key >= 0 ? remove_idx<std::size_t>::remove(
|
return key >= 0 ? remove_idx<std::size_t>::remove(
|
||||||
sequence, static_cast<std::size_t>(key))
|
sequence, static_cast<std::size_t>(key), seqSize)
|
||||||
: false;
|
: false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -115,7 +122,7 @@ inline node* node_data::get(const Key& key,
|
|||||||
return pNode;
|
return pNode;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
case NodeType::Scalar:
|
case NodeType::Scalar:
|
||||||
throw BadSubscript(key);
|
throw BadSubscript(m_mark, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||||
@@ -143,7 +150,7 @@ inline node& node_data::get(const Key& key, shared_memory_holder pMemory) {
|
|||||||
convert_to_map(pMemory);
|
convert_to_map(pMemory);
|
||||||
break;
|
break;
|
||||||
case NodeType::Scalar:
|
case NodeType::Scalar:
|
||||||
throw BadSubscript(key);
|
throw BadSubscript(m_mark, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||||
@@ -161,7 +168,7 @@ inline node& node_data::get(const Key& key, shared_memory_holder pMemory) {
|
|||||||
template <typename Key>
|
template <typename Key>
|
||||||
inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) {
|
inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) {
|
||||||
if (m_type == NodeType::Sequence) {
|
if (m_type == NodeType::Sequence) {
|
||||||
return remove_idx<Key>::remove(m_sequence, key);
|
return remove_idx<Key>::remove(m_sequence, key, m_seqSize);
|
||||||
} else if (m_type == NodeType::Map) {
|
} else if (m_type == NodeType::Map) {
|
||||||
kv_pairs::iterator it = m_undefinedPairs.begin();
|
kv_pairs::iterator it = m_undefinedPairs.begin();
|
||||||
while (it != m_undefinedPairs.end()) {
|
while (it != m_undefinedPairs.end()) {
|
||||||
|
@@ -26,7 +26,7 @@ class iterator_base {
|
|||||||
template <typename>
|
template <typename>
|
||||||
friend class iterator_base;
|
friend class iterator_base;
|
||||||
struct enabler {};
|
struct enabler {};
|
||||||
typedef node_iterator base_type;
|
using base_type = node_iterator;
|
||||||
|
|
||||||
struct proxy {
|
struct proxy {
|
||||||
explicit proxy(const V& x) : m_ref(x) {}
|
explicit proxy(const V& x) : m_ref(x) {}
|
||||||
|
@@ -20,8 +20,8 @@ template <typename V>
|
|||||||
class iterator_base;
|
class iterator_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef detail::iterator_base<detail::iterator_value> iterator;
|
using iterator = detail::iterator_base<detail::iterator_value>;
|
||||||
typedef detail::iterator_base<const detail::iterator_value> const_iterator;
|
using const_iterator = detail::iterator_base<const detail::iterator_value>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
@@ -27,7 +27,7 @@ class YAML_CPP_API memory {
|
|||||||
void merge(const memory& rhs);
|
void merge(const memory& rhs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::set<shared_node> Nodes;
|
using Nodes = std::set<shared_node>;
|
||||||
Nodes m_nodes;
|
Nodes m_nodes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -13,10 +13,16 @@
|
|||||||
#include "yaml-cpp/node/ptr.h"
|
#include "yaml-cpp/node/ptr.h"
|
||||||
#include "yaml-cpp/node/type.h"
|
#include "yaml-cpp/node/type.h"
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
class node {
|
class node {
|
||||||
|
private:
|
||||||
|
struct less {
|
||||||
|
bool operator ()(const node* l, const node* r) {return l->m_index < r->m_index;}
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
node() : m_pRef(new node_ref), m_dependencies{} {}
|
node() : m_pRef(new node_ref), m_dependencies{} {}
|
||||||
node(const node&) = delete;
|
node(const node&) = delete;
|
||||||
@@ -42,9 +48,8 @@ class node {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
m_pRef->mark_defined();
|
m_pRef->mark_defined();
|
||||||
for (nodes::iterator it = m_dependencies.begin();
|
for (node* dependency : m_dependencies)
|
||||||
it != m_dependencies.end(); ++it)
|
dependency->mark_defined();
|
||||||
(*it)->mark_defined();
|
|
||||||
m_dependencies.clear();
|
m_dependencies.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,6 +114,7 @@ class node {
|
|||||||
void push_back(node& input, shared_memory_holder pMemory) {
|
void push_back(node& input, shared_memory_holder pMemory) {
|
||||||
m_pRef->push_back(input, pMemory);
|
m_pRef->push_back(input, pMemory);
|
||||||
input.add_dependency(*this);
|
input.add_dependency(*this);
|
||||||
|
m_index = m_amount.fetch_add(1);
|
||||||
}
|
}
|
||||||
void insert(node& key, node& value, shared_memory_holder pMemory) {
|
void insert(node& key, node& value, shared_memory_holder pMemory) {
|
||||||
m_pRef->insert(key, value, pMemory);
|
m_pRef->insert(key, value, pMemory);
|
||||||
@@ -120,7 +126,7 @@ class node {
|
|||||||
template <typename Key>
|
template <typename Key>
|
||||||
node* get(const Key& key, shared_memory_holder pMemory) const {
|
node* get(const Key& key, shared_memory_holder pMemory) const {
|
||||||
// NOTE: this returns a non-const node so that the top-level Node can wrap
|
// NOTE: this returns a non-const node so that the top-level Node can wrap
|
||||||
// it, and returns a pointer so that it can be NULL (if there is no such
|
// it, and returns a pointer so that it can be nullptr (if there is no such
|
||||||
// key).
|
// key).
|
||||||
return static_cast<const node_ref&>(*m_pRef).get(key, pMemory);
|
return static_cast<const node_ref&>(*m_pRef).get(key, pMemory);
|
||||||
}
|
}
|
||||||
@@ -137,7 +143,7 @@ class node {
|
|||||||
|
|
||||||
node* get(node& key, shared_memory_holder pMemory) const {
|
node* get(node& key, shared_memory_holder pMemory) const {
|
||||||
// NOTE: this returns a non-const node so that the top-level Node can wrap
|
// NOTE: this returns a non-const node so that the top-level Node can wrap
|
||||||
// it, and returns a pointer so that it can be NULL (if there is no such
|
// it, and returns a pointer so that it can be nullptr (if there is no such
|
||||||
// key).
|
// key).
|
||||||
return static_cast<const node_ref&>(*m_pRef).get(key, pMemory);
|
return static_cast<const node_ref&>(*m_pRef).get(key, pMemory);
|
||||||
}
|
}
|
||||||
@@ -160,8 +166,10 @@ class node {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
shared_node_ref m_pRef;
|
shared_node_ref m_pRef;
|
||||||
typedef std::set<node*> nodes;
|
using nodes = std::set<node*, less>;
|
||||||
nodes m_dependencies;
|
nodes m_dependencies;
|
||||||
|
size_t m_index;
|
||||||
|
static std::atomic<size_t> m_amount;
|
||||||
};
|
};
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace YAML
|
} // namespace YAML
|
||||||
|
@@ -108,17 +108,17 @@ class YAML_CPP_API node_data {
|
|||||||
std::string m_scalar;
|
std::string m_scalar;
|
||||||
|
|
||||||
// sequence
|
// sequence
|
||||||
typedef std::vector<node*> node_seq;
|
using node_seq = std::vector<node *>;
|
||||||
node_seq m_sequence;
|
node_seq m_sequence;
|
||||||
|
|
||||||
mutable std::size_t m_seqSize;
|
mutable std::size_t m_seqSize;
|
||||||
|
|
||||||
// map
|
// map
|
||||||
typedef std::vector<std::pair<node*, node*>> node_map;
|
using node_map = std::vector<std::pair<node*, node*>>;
|
||||||
node_map m_map;
|
node_map m_map;
|
||||||
|
|
||||||
typedef std::pair<node*, node*> kv_pair;
|
using kv_pair = std::pair<node*, node*>;
|
||||||
typedef std::list<kv_pair> kv_pairs;
|
using kv_pairs = std::list<kv_pair>;
|
||||||
mutable kv_pairs m_undefinedPairs;
|
mutable kv_pairs m_undefinedPairs;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -24,7 +24,7 @@ struct iterator_type {
|
|||||||
|
|
||||||
template <typename V>
|
template <typename V>
|
||||||
struct node_iterator_value : public std::pair<V*, V*> {
|
struct node_iterator_value : public std::pair<V*, V*> {
|
||||||
typedef std::pair<V*, V*> kv;
|
using kv = std::pair<V*, V*>;
|
||||||
|
|
||||||
node_iterator_value() : kv(), pNode(nullptr) {}
|
node_iterator_value() : kv(), pNode(nullptr) {}
|
||||||
explicit node_iterator_value(V& rhs) : kv(), pNode(&rhs) {}
|
explicit node_iterator_value(V& rhs) : kv(), pNode(&rhs) {}
|
||||||
@@ -36,26 +36,23 @@ struct node_iterator_value : public std::pair<V*, V*> {
|
|||||||
V* pNode;
|
V* pNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<node*> node_seq;
|
using node_seq = std::vector<node *>;
|
||||||
typedef std::vector<std::pair<node*, node*>> node_map;
|
using node_map = std::vector<std::pair<node*, node*>>;
|
||||||
|
|
||||||
template <typename V>
|
template <typename V>
|
||||||
struct node_iterator_type {
|
struct node_iterator_type {
|
||||||
typedef node_seq::iterator seq;
|
using seq = node_seq::iterator;
|
||||||
typedef node_map::iterator map;
|
using map = node_map::iterator;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename V>
|
template <typename V>
|
||||||
struct node_iterator_type<const V> {
|
struct node_iterator_type<const V> {
|
||||||
typedef node_seq::const_iterator seq;
|
using seq = node_seq::const_iterator;
|
||||||
typedef node_map::const_iterator map;
|
using map = node_map::const_iterator;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename V>
|
template <typename V>
|
||||||
class node_iterator_base
|
class node_iterator_base {
|
||||||
: public std::iterator<std::forward_iterator_tag, node_iterator_value<V>,
|
|
||||||
std::ptrdiff_t, node_iterator_value<V>*,
|
|
||||||
node_iterator_value<V>> {
|
|
||||||
private:
|
private:
|
||||||
struct enabler {};
|
struct enabler {};
|
||||||
|
|
||||||
@@ -68,9 +65,13 @@ class node_iterator_base
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef typename node_iterator_type<V>::seq SeqIter;
|
using iterator_category = std::forward_iterator_tag;
|
||||||
typedef typename node_iterator_type<V>::map MapIter;
|
using value_type = node_iterator_value<V>;
|
||||||
typedef node_iterator_value<V> value_type;
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using pointer = node_iterator_value<V>*;
|
||||||
|
using reference = node_iterator_value<V>;
|
||||||
|
using SeqIter = typename node_iterator_type<V>::seq;
|
||||||
|
using MapIter = typename node_iterator_type<V>::map;
|
||||||
|
|
||||||
node_iterator_base()
|
node_iterator_base()
|
||||||
: m_type(iterator_type::NoneType), m_seqIt(), m_mapIt(), m_mapEnd() {}
|
: m_type(iterator_type::NoneType), m_seqIt(), m_mapIt(), m_mapEnd() {}
|
||||||
@@ -172,8 +173,8 @@ class node_iterator_base
|
|||||||
MapIter m_mapIt, m_mapEnd;
|
MapIter m_mapIt, m_mapEnd;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef node_iterator_base<node> node_iterator;
|
using node_iterator = node_iterator_base<node>;
|
||||||
typedef node_iterator_base<const node> const_node_iterator;
|
using const_node_iterator = node_iterator_base<const node>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -42,11 +42,7 @@ inline Node::Node(const detail::iterator_value& rhs)
|
|||||||
m_pMemory(rhs.m_pMemory),
|
m_pMemory(rhs.m_pMemory),
|
||||||
m_pNode(rhs.m_pNode) {}
|
m_pNode(rhs.m_pNode) {}
|
||||||
|
|
||||||
inline Node::Node(const Node& rhs)
|
inline Node::Node(const Node& rhs) = default;
|
||||||
: m_isValid(rhs.m_isValid),
|
|
||||||
m_invalidKey(rhs.m_invalidKey),
|
|
||||||
m_pMemory(rhs.m_pMemory),
|
|
||||||
m_pNode(rhs.m_pNode) {}
|
|
||||||
|
|
||||||
inline Node::Node(Zombie)
|
inline Node::Node(Zombie)
|
||||||
: m_isValid(false), m_invalidKey{}, m_pMemory{}, m_pNode(nullptr) {}
|
: m_isValid(false), m_invalidKey{}, m_pMemory{}, m_pNode(nullptr) {}
|
||||||
@@ -57,7 +53,7 @@ inline Node::Node(Zombie, const std::string& key)
|
|||||||
inline Node::Node(detail::node& node, detail::shared_memory_holder pMemory)
|
inline Node::Node(detail::node& node, detail::shared_memory_holder pMemory)
|
||||||
: m_isValid(true), m_invalidKey{}, m_pMemory(pMemory), m_pNode(&node) {}
|
: m_isValid(true), m_invalidKey{}, m_pMemory(pMemory), m_pNode(&node) {}
|
||||||
|
|
||||||
inline Node::~Node() {}
|
inline Node::~Node() = default;
|
||||||
|
|
||||||
inline void Node::EnsureNodeExists() const {
|
inline void Node::EnsureNodeExists() const {
|
||||||
if (!m_isValid)
|
if (!m_isValid)
|
||||||
@@ -176,8 +172,6 @@ inline const std::string& Node::Tag() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void Node::SetTag(const std::string& tag) {
|
inline void Node::SetTag(const std::string& tag) {
|
||||||
if (!m_isValid)
|
|
||||||
throw InvalidNode(m_invalidKey);
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
m_pNode->set_tag(tag);
|
m_pNode->set_tag(tag);
|
||||||
}
|
}
|
||||||
@@ -189,8 +183,6 @@ inline EmitterStyle::value Node::Style() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void Node::SetStyle(EmitterStyle::value style) {
|
inline void Node::SetStyle(EmitterStyle::value style) {
|
||||||
if (!m_isValid)
|
|
||||||
throw InvalidNode(m_invalidKey);
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
m_pNode->set_style(style);
|
m_pNode->set_style(style);
|
||||||
}
|
}
|
||||||
@@ -206,15 +198,11 @@ inline bool Node::is(const Node& rhs) const {
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline Node& Node::operator=(const T& rhs) {
|
inline Node& Node::operator=(const T& rhs) {
|
||||||
if (!m_isValid)
|
|
||||||
throw InvalidNode(m_invalidKey);
|
|
||||||
Assign(rhs);
|
Assign(rhs);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Node& Node::operator=(const Node& rhs) {
|
inline Node& Node::operator=(const Node& rhs) {
|
||||||
if (!m_isValid || !rhs.m_isValid)
|
|
||||||
throw InvalidNode(m_invalidKey);
|
|
||||||
if (is(rhs))
|
if (is(rhs))
|
||||||
return *this;
|
return *this;
|
||||||
AssignNode(rhs);
|
AssignNode(rhs);
|
||||||
@@ -237,29 +225,21 @@ inline void Node::Assign(const T& rhs) {
|
|||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline void Node::Assign(const std::string& rhs) {
|
inline void Node::Assign(const std::string& rhs) {
|
||||||
if (!m_isValid)
|
|
||||||
throw InvalidNode(m_invalidKey);
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
m_pNode->set_scalar(rhs);
|
m_pNode->set_scalar(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Node::Assign(const char* rhs) {
|
inline void Node::Assign(const char* rhs) {
|
||||||
if (!m_isValid)
|
|
||||||
throw InvalidNode(m_invalidKey);
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
m_pNode->set_scalar(rhs);
|
m_pNode->set_scalar(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Node::Assign(char* rhs) {
|
inline void Node::Assign(char* rhs) {
|
||||||
if (!m_isValid)
|
|
||||||
throw InvalidNode(m_invalidKey);
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
m_pNode->set_scalar(rhs);
|
m_pNode->set_scalar(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Node::AssignData(const Node& rhs) {
|
inline void Node::AssignData(const Node& rhs) {
|
||||||
if (!m_isValid || !rhs.m_isValid)
|
|
||||||
throw InvalidNode(m_invalidKey);
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
rhs.EnsureNodeExists();
|
rhs.EnsureNodeExists();
|
||||||
|
|
||||||
@@ -268,7 +248,7 @@ inline void Node::AssignData(const Node& rhs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void Node::AssignNode(const Node& rhs) {
|
inline void Node::AssignNode(const Node& rhs) {
|
||||||
if (!m_isValid || !rhs.m_isValid)
|
if (!m_isValid)
|
||||||
throw InvalidNode(m_invalidKey);
|
throw InvalidNode(m_invalidKey);
|
||||||
rhs.EnsureNodeExists();
|
rhs.EnsureNodeExists();
|
||||||
|
|
||||||
@@ -324,8 +304,6 @@ inline void Node::push_back(const T& rhs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void Node::push_back(const Node& rhs) {
|
inline void Node::push_back(const Node& rhs) {
|
||||||
if (!m_isValid || !rhs.m_isValid)
|
|
||||||
throw InvalidNode(m_invalidKey);
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
rhs.EnsureNodeExists();
|
rhs.EnsureNodeExists();
|
||||||
|
|
||||||
@@ -339,7 +317,7 @@ template <typename T>
|
|||||||
struct to_value_t {
|
struct to_value_t {
|
||||||
explicit to_value_t(const T& t_) : t(t_) {}
|
explicit to_value_t(const T& t_) : t(t_) {}
|
||||||
const T& t;
|
const T& t;
|
||||||
typedef const T& return_type;
|
using return_type = const T &;
|
||||||
|
|
||||||
const T& operator()() const { return t; }
|
const T& operator()() const { return t; }
|
||||||
};
|
};
|
||||||
@@ -348,7 +326,7 @@ template <>
|
|||||||
struct to_value_t<const char*> {
|
struct to_value_t<const char*> {
|
||||||
explicit to_value_t(const char* t_) : t(t_) {}
|
explicit to_value_t(const char* t_) : t(t_) {}
|
||||||
const char* t;
|
const char* t;
|
||||||
typedef std::string return_type;
|
using return_type = std::string;
|
||||||
|
|
||||||
const std::string operator()() const { return t; }
|
const std::string operator()() const { return t; }
|
||||||
};
|
};
|
||||||
@@ -357,7 +335,7 @@ template <>
|
|||||||
struct to_value_t<char*> {
|
struct to_value_t<char*> {
|
||||||
explicit to_value_t(char* t_) : t(t_) {}
|
explicit to_value_t(char* t_) : t(t_) {}
|
||||||
const char* t;
|
const char* t;
|
||||||
typedef std::string return_type;
|
using return_type = std::string;
|
||||||
|
|
||||||
const std::string operator()() const { return t; }
|
const std::string operator()() const { return t; }
|
||||||
};
|
};
|
||||||
@@ -366,7 +344,7 @@ template <std::size_t N>
|
|||||||
struct to_value_t<char[N]> {
|
struct to_value_t<char[N]> {
|
||||||
explicit to_value_t(const char* t_) : t(t_) {}
|
explicit to_value_t(const char* t_) : t(t_) {}
|
||||||
const char* t;
|
const char* t;
|
||||||
typedef std::string return_type;
|
using return_type = std::string;
|
||||||
|
|
||||||
const std::string operator()() const { return t; }
|
const std::string operator()() const { return t; }
|
||||||
};
|
};
|
||||||
@@ -386,8 +364,6 @@ std::string key_to_string(const Key& key) {
|
|||||||
// indexing
|
// indexing
|
||||||
template <typename Key>
|
template <typename Key>
|
||||||
inline const Node Node::operator[](const Key& key) const {
|
inline const Node Node::operator[](const Key& key) const {
|
||||||
if (!m_isValid)
|
|
||||||
throw InvalidNode(m_invalidKey);
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
detail::node* value = static_cast<const detail::node&>(*m_pNode).get(
|
detail::node* value = static_cast<const detail::node&>(*m_pNode).get(
|
||||||
detail::to_value(key), m_pMemory);
|
detail::to_value(key), m_pMemory);
|
||||||
@@ -399,8 +375,6 @@ inline const Node Node::operator[](const Key& key) const {
|
|||||||
|
|
||||||
template <typename Key>
|
template <typename Key>
|
||||||
inline Node Node::operator[](const Key& key) {
|
inline Node Node::operator[](const Key& key) {
|
||||||
if (!m_isValid)
|
|
||||||
throw InvalidNode(m_invalidKey);
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
detail::node& value = m_pNode->get(detail::to_value(key), m_pMemory);
|
detail::node& value = m_pNode->get(detail::to_value(key), m_pMemory);
|
||||||
return Node(value, m_pMemory);
|
return Node(value, m_pMemory);
|
||||||
@@ -408,15 +382,11 @@ inline Node Node::operator[](const Key& key) {
|
|||||||
|
|
||||||
template <typename Key>
|
template <typename Key>
|
||||||
inline bool Node::remove(const Key& key) {
|
inline bool Node::remove(const Key& key) {
|
||||||
if (!m_isValid)
|
|
||||||
throw InvalidNode(m_invalidKey);
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
return m_pNode->remove(detail::to_value(key), m_pMemory);
|
return m_pNode->remove(detail::to_value(key), m_pMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const Node Node::operator[](const Node& key) const {
|
inline const Node Node::operator[](const Node& key) const {
|
||||||
if (!m_isValid || !key.m_isValid)
|
|
||||||
throw InvalidNode(m_invalidKey);
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
key.EnsureNodeExists();
|
key.EnsureNodeExists();
|
||||||
m_pMemory->merge(*key.m_pMemory);
|
m_pMemory->merge(*key.m_pMemory);
|
||||||
@@ -429,8 +399,6 @@ inline const Node Node::operator[](const Node& key) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline Node Node::operator[](const Node& key) {
|
inline Node Node::operator[](const Node& key) {
|
||||||
if (!m_isValid || !key.m_isValid)
|
|
||||||
throw InvalidNode(m_invalidKey);
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
key.EnsureNodeExists();
|
key.EnsureNodeExists();
|
||||||
m_pMemory->merge(*key.m_pMemory);
|
m_pMemory->merge(*key.m_pMemory);
|
||||||
@@ -439,8 +407,6 @@ inline Node Node::operator[](const Node& key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool Node::remove(const Node& key) {
|
inline bool Node::remove(const Node& key) {
|
||||||
if (!m_isValid || !key.m_isValid)
|
|
||||||
throw InvalidNode(m_invalidKey);
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
key.EnsureNodeExists();
|
key.EnsureNodeExists();
|
||||||
return m_pNode->remove(*key.m_pNode, m_pMemory);
|
return m_pNode->remove(*key.m_pNode, m_pMemory);
|
||||||
@@ -449,8 +415,6 @@ inline bool Node::remove(const Node& key) {
|
|||||||
// map
|
// map
|
||||||
template <typename Key, typename Value>
|
template <typename Key, typename Value>
|
||||||
inline void Node::force_insert(const Key& key, const Value& value) {
|
inline void Node::force_insert(const Key& key, const Value& value) {
|
||||||
if (!m_isValid)
|
|
||||||
throw InvalidNode(m_invalidKey);
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
m_pNode->force_insert(detail::to_value(key), detail::to_value(value),
|
m_pNode->force_insert(detail::to_value(key), detail::to_value(value),
|
||||||
m_pMemory);
|
m_pMemory);
|
||||||
|
@@ -18,7 +18,7 @@
|
|||||||
namespace YAML {
|
namespace YAML {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
struct iterator_value : public Node, std::pair<Node, Node> {
|
struct iterator_value : public Node, std::pair<Node, Node> {
|
||||||
iterator_value() {}
|
iterator_value() = default;
|
||||||
explicit iterator_value(const Node& rhs)
|
explicit iterator_value(const Node& rhs)
|
||||||
: Node(rhs),
|
: Node(rhs),
|
||||||
std::pair<Node, Node>(Node(Node::ZombieNode), Node(Node::ZombieNode)) {}
|
std::pair<Node, Node>(Node(Node::ZombieNode), Node(Node::ZombieNode)) {}
|
||||||
|
@@ -13,7 +13,6 @@
|
|||||||
#include "yaml-cpp/dll.h"
|
#include "yaml-cpp/dll.h"
|
||||||
#include "yaml-cpp/emitterstyle.h"
|
#include "yaml-cpp/emitterstyle.h"
|
||||||
#include "yaml-cpp/mark.h"
|
#include "yaml-cpp/mark.h"
|
||||||
#include "yaml-cpp/node/detail/bool_type.h"
|
|
||||||
#include "yaml-cpp/node/detail/iterator_fwd.h"
|
#include "yaml-cpp/node/detail/iterator_fwd.h"
|
||||||
#include "yaml-cpp/node/ptr.h"
|
#include "yaml-cpp/node/ptr.h"
|
||||||
#include "yaml-cpp/node/type.h"
|
#include "yaml-cpp/node/type.h"
|
||||||
@@ -39,8 +38,8 @@ class YAML_CPP_API Node {
|
|||||||
template <typename T, typename S>
|
template <typename T, typename S>
|
||||||
friend struct as_if;
|
friend struct as_if;
|
||||||
|
|
||||||
typedef YAML::iterator iterator;
|
using iterator = YAML::iterator;
|
||||||
typedef YAML::const_iterator const_iterator;
|
using const_iterator = YAML::const_iterator;
|
||||||
|
|
||||||
Node();
|
Node();
|
||||||
explicit Node(NodeType::value type);
|
explicit Node(NodeType::value type);
|
||||||
@@ -59,7 +58,7 @@ class YAML_CPP_API Node {
|
|||||||
bool IsMap() const { return Type() == NodeType::Map; }
|
bool IsMap() const { return Type() == NodeType::Map; }
|
||||||
|
|
||||||
// bool conversions
|
// bool conversions
|
||||||
YAML_CPP_OPERATOR_BOOL()
|
explicit operator bool() const { return IsDefined(); }
|
||||||
bool operator!() const { return !IsDefined(); }
|
bool operator!() const { return !IsDefined(); }
|
||||||
|
|
||||||
// access
|
// access
|
||||||
|
@@ -18,11 +18,11 @@ class node_data;
|
|||||||
class memory;
|
class memory;
|
||||||
class memory_holder;
|
class memory_holder;
|
||||||
|
|
||||||
typedef std::shared_ptr<node> shared_node;
|
using shared_node = std::shared_ptr<node>;
|
||||||
typedef std::shared_ptr<node_ref> shared_node_ref;
|
using shared_node_ref = std::shared_ptr<node_ref>;
|
||||||
typedef std::shared_ptr<node_data> shared_node_data;
|
using shared_node_data = std::shared_ptr<node_data>;
|
||||||
typedef std::shared_ptr<memory_holder> shared_memory_holder;
|
using shared_memory_holder = std::shared_ptr<memory_holder>;
|
||||||
typedef std::shared_ptr<memory> shared_memory;
|
using shared_memory = std::shared_ptr<memory>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
18
include/yaml-cpp/noexcept.h
Normal file
18
include/yaml-cpp/noexcept.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef NOEXCEPT_H_768872DA_476C_11EA_88B8_90B11C0C0FF8
|
||||||
|
#define NOEXCEPT_H_768872DA_476C_11EA_88B8_90B11C0C0FF8
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// This is here for compatibility with older versions of Visual Studio
|
||||||
|
// which don't support noexcept.
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||||
|
#define YAML_CPP_NOEXCEPT _NOEXCEPT
|
||||||
|
#else
|
||||||
|
#define YAML_CPP_NOEXCEPT noexcept
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@@ -84,7 +84,7 @@ struct is_numeric<long double> {
|
|||||||
|
|
||||||
template <bool, class T = void>
|
template <bool, class T = void>
|
||||||
struct enable_if_c {
|
struct enable_if_c {
|
||||||
typedef T type;
|
using type = T;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
@@ -95,7 +95,7 @@ struct enable_if : public enable_if_c<Cond::value, T> {};
|
|||||||
|
|
||||||
template <bool, class T = void>
|
template <bool, class T = void>
|
||||||
struct disable_if_c {
|
struct disable_if_c {
|
||||||
typedef T type;
|
using type = T;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@@ -66,7 +66,7 @@ static const unsigned char decoding[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::vector<unsigned char> DecodeBase64(const std::string &input) {
|
std::vector<unsigned char> DecodeBase64(const std::string &input) {
|
||||||
typedef std::vector<unsigned char> ret_type;
|
using ret_type = std::vector<unsigned char>;
|
||||||
if (input.empty())
|
if (input.empty())
|
||||||
return ret_type();
|
return ret_type();
|
||||||
|
|
||||||
|
@@ -16,8 +16,8 @@ std::string tolower(const std::string& str) {
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool IsEntirely(const std::string& str, T func) {
|
bool IsEntirely(const std::string& str, T func) {
|
||||||
for (std::size_t i = 0; i < str.size(); i++)
|
for (char ch : str)
|
||||||
if (!func(str[i]))
|
if (!func(ch))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -39,7 +39,7 @@ bool IsFlexibleCase(const std::string& str) {
|
|||||||
std::string rest = str.substr(1);
|
std::string rest = str.substr(1);
|
||||||
return firstcaps && (IsEntirely(rest, IsLower) || IsEntirely(rest, IsUpper));
|
return firstcaps && (IsEntirely(rest, IsLower) || IsEntirely(rest, IsUpper));
|
||||||
}
|
}
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
bool convert<bool>::decode(const Node& node, bool& rhs) {
|
bool convert<bool>::decode(const Node& node, bool& rhs) {
|
||||||
@@ -52,19 +52,22 @@ bool convert<bool>::decode(const Node& node, bool& rhs) {
|
|||||||
static const struct {
|
static const struct {
|
||||||
std::string truename, falsename;
|
std::string truename, falsename;
|
||||||
} names[] = {
|
} names[] = {
|
||||||
{"y", "n"}, {"yes", "no"}, {"true", "false"}, {"on", "off"},
|
{"y", "n"},
|
||||||
|
{"yes", "no"},
|
||||||
|
{"true", "false"},
|
||||||
|
{"on", "off"},
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!IsFlexibleCase(node.Scalar()))
|
if (!IsFlexibleCase(node.Scalar()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (unsigned i = 0; i < sizeof(names) / sizeof(names[0]); i++) {
|
for (const auto& name : names) {
|
||||||
if (names[i].truename == tolower(node.Scalar())) {
|
if (name.truename == tolower(node.Scalar())) {
|
||||||
rhs = true;
|
rhs = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (names[i].falsename == tolower(node.Scalar())) {
|
if (name.falsename == tolower(node.Scalar())) {
|
||||||
rhs = false;
|
rhs = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -72,4 +75,4 @@ bool convert<bool>::decode(const Node& node, bool& rhs) {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
} // namespace YAML
|
||||||
|
@@ -16,7 +16,7 @@ Emitter::Emitter() : m_pState(new EmitterState), m_stream{} {}
|
|||||||
Emitter::Emitter(std::ostream& stream)
|
Emitter::Emitter(std::ostream& stream)
|
||||||
: m_pState(new EmitterState), m_stream(stream) {}
|
: m_pState(new EmitterState), m_stream(stream) {}
|
||||||
|
|
||||||
Emitter::~Emitter() {}
|
Emitter::~Emitter() = default;
|
||||||
|
|
||||||
const char* Emitter::c_str() const { return m_stream.str(); }
|
const char* Emitter::c_str() const { return m_stream.str(); }
|
||||||
|
|
||||||
|
@@ -32,7 +32,7 @@ EmitterState::EmitterState()
|
|||||||
m_hasNonContent(false),
|
m_hasNonContent(false),
|
||||||
m_docCount(0) {}
|
m_docCount(0) {}
|
||||||
|
|
||||||
EmitterState::~EmitterState() {}
|
EmitterState::~EmitterState() = default;
|
||||||
|
|
||||||
// SetLocalValue
|
// SetLocalValue
|
||||||
// . We blindly tries to set all possible formatters to this value
|
// . We blindly tries to set all possible formatters to this value
|
||||||
|
@@ -199,11 +199,11 @@ bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
|
|||||||
|
|
||||||
bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii) {
|
bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii) {
|
||||||
// TODO: check for non-printable characters?
|
// TODO: check for non-printable characters?
|
||||||
for (std::size_t i = 0; i < str.size(); i++) {
|
for (char ch : str) {
|
||||||
if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i]))) {
|
if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (str[i] == '\n') {
|
if (ch == '\n') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -217,8 +217,8 @@ bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check for non-printable characters?
|
// TODO: check for non-printable characters?
|
||||||
for (std::size_t i = 0; i < str.size(); i++) {
|
for (char ch : str) {
|
||||||
if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i]))) {
|
if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,31 +1,20 @@
|
|||||||
#include "yaml-cpp/exceptions.h"
|
#include "yaml-cpp/exceptions.h"
|
||||||
|
#include "yaml-cpp/noexcept.h"
|
||||||
// This is here for compatibility with older versions of Visual Studio
|
|
||||||
// which don't support noexcept
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
|
||||||
#define YAML_CPP_NOEXCEPT _NOEXCEPT
|
|
||||||
#else
|
|
||||||
#define YAML_CPP_NOEXCEPT noexcept
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
|
|
||||||
// These destructors are defined out-of-line so the vtable is only emitted once.
|
// These destructors are defined out-of-line so the vtable is only emitted once.
|
||||||
Exception::~Exception() YAML_CPP_NOEXCEPT {}
|
Exception::~Exception() YAML_CPP_NOEXCEPT = default;
|
||||||
ParserException::~ParserException() YAML_CPP_NOEXCEPT {}
|
ParserException::~ParserException() YAML_CPP_NOEXCEPT = default;
|
||||||
RepresentationException::~RepresentationException() YAML_CPP_NOEXCEPT {}
|
RepresentationException::~RepresentationException() YAML_CPP_NOEXCEPT = default;
|
||||||
InvalidScalar::~InvalidScalar() YAML_CPP_NOEXCEPT {}
|
InvalidScalar::~InvalidScalar() YAML_CPP_NOEXCEPT = default;
|
||||||
KeyNotFound::~KeyNotFound() YAML_CPP_NOEXCEPT {}
|
KeyNotFound::~KeyNotFound() YAML_CPP_NOEXCEPT = default;
|
||||||
InvalidNode::~InvalidNode() YAML_CPP_NOEXCEPT {}
|
InvalidNode::~InvalidNode() YAML_CPP_NOEXCEPT = default;
|
||||||
BadConversion::~BadConversion() YAML_CPP_NOEXCEPT {}
|
BadConversion::~BadConversion() YAML_CPP_NOEXCEPT = default;
|
||||||
BadDereference::~BadDereference() YAML_CPP_NOEXCEPT {}
|
BadDereference::~BadDereference() YAML_CPP_NOEXCEPT = default;
|
||||||
BadSubscript::~BadSubscript() YAML_CPP_NOEXCEPT {}
|
BadSubscript::~BadSubscript() YAML_CPP_NOEXCEPT = default;
|
||||||
BadPushback::~BadPushback() YAML_CPP_NOEXCEPT {}
|
BadPushback::~BadPushback() YAML_CPP_NOEXCEPT = default;
|
||||||
BadInsert::~BadInsert() YAML_CPP_NOEXCEPT {}
|
BadInsert::~BadInsert() YAML_CPP_NOEXCEPT = default;
|
||||||
EmitterException::~EmitterException() YAML_CPP_NOEXCEPT {}
|
EmitterException::~EmitterException() YAML_CPP_NOEXCEPT = default;
|
||||||
BadFile::~BadFile() YAML_CPP_NOEXCEPT {}
|
BadFile::~BadFile() YAML_CPP_NOEXCEPT = default;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef YAML_CPP_NOEXCEPT
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -12,8 +12,7 @@ namespace YAML {
|
|||||||
namespace Exp {
|
namespace Exp {
|
||||||
unsigned ParseHex(const std::string& str, const Mark& mark) {
|
unsigned ParseHex(const std::string& str, const Mark& mark) {
|
||||||
unsigned value = 0;
|
unsigned value = 0;
|
||||||
for (std::size_t i = 0; i < str.size(); i++) {
|
for (char ch : str) {
|
||||||
char ch = str[i];
|
|
||||||
int digit = 0;
|
int digit = 0;
|
||||||
if ('a' <= ch && ch <= 'f')
|
if ('a' <= ch && ch <= 'f')
|
||||||
digit = ch - 'a' + 10;
|
digit = ch - 'a' + 10;
|
||||||
@@ -132,5 +131,5 @@ std::string Escape(Stream& in) {
|
|||||||
std::stringstream msg;
|
std::stringstream msg;
|
||||||
throw ParserException(in.mark(), std::string(ErrorMsg::INVALID_ESCAPE) + ch);
|
throw ParserException(in.mark(), std::string(ErrorMsg::INVALID_ESCAPE) + ch);
|
||||||
}
|
}
|
||||||
}
|
} // namespace Exp
|
||||||
}
|
} // namespace YAML
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
#include <assert.h>
|
#include <cassert>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
std::atomic<size_t> node::m_amount{0};
|
||||||
|
|
||||||
const std::string& node_data::empty_scalar() {
|
const std::string& node_data::empty_scalar() {
|
||||||
static const std::string svalue;
|
static const std::string svalue;
|
||||||
@@ -196,7 +197,7 @@ void node_data::insert(node& key, node& value, shared_memory_holder pMemory) {
|
|||||||
convert_to_map(pMemory);
|
convert_to_map(pMemory);
|
||||||
break;
|
break;
|
||||||
case NodeType::Scalar:
|
case NodeType::Scalar:
|
||||||
throw BadSubscript(key);
|
throw BadSubscript(m_mark, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
insert_map_pair(key, value);
|
insert_map_pair(key, value);
|
||||||
@@ -226,7 +227,7 @@ node& node_data::get(node& key, shared_memory_holder pMemory) {
|
|||||||
convert_to_map(pMemory);
|
convert_to_map(pMemory);
|
||||||
break;
|
break;
|
||||||
case NodeType::Scalar:
|
case NodeType::Scalar:
|
||||||
throw BadSubscript(key);
|
throw BadSubscript(m_mark, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
#include <assert.h>
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "nodebuilder.h"
|
#include "nodebuilder.h"
|
||||||
@@ -20,7 +19,7 @@ NodeBuilder::NodeBuilder()
|
|||||||
m_anchors.push_back(nullptr); // since the anchors start at 1
|
m_anchors.push_back(nullptr); // since the anchors start at 1
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeBuilder::~NodeBuilder() {}
|
NodeBuilder::~NodeBuilder() = default;
|
||||||
|
|
||||||
Node NodeBuilder::Root() {
|
Node NodeBuilder::Root() {
|
||||||
if (!m_pRoot)
|
if (!m_pRoot)
|
||||||
|
@@ -31,25 +31,25 @@ class NodeBuilder : public EventHandler {
|
|||||||
NodeBuilder(NodeBuilder&&) = delete;
|
NodeBuilder(NodeBuilder&&) = delete;
|
||||||
NodeBuilder& operator=(const NodeBuilder&) = delete;
|
NodeBuilder& operator=(const NodeBuilder&) = delete;
|
||||||
NodeBuilder& operator=(NodeBuilder&&) = delete;
|
NodeBuilder& operator=(NodeBuilder&&) = delete;
|
||||||
virtual ~NodeBuilder();
|
~NodeBuilder() override;
|
||||||
|
|
||||||
Node Root();
|
Node Root();
|
||||||
|
|
||||||
virtual void OnDocumentStart(const Mark& mark);
|
void OnDocumentStart(const Mark& mark) override;
|
||||||
virtual void OnDocumentEnd();
|
void OnDocumentEnd() override;
|
||||||
|
|
||||||
virtual void OnNull(const Mark& mark, anchor_t anchor);
|
void OnNull(const Mark& mark, anchor_t anchor) override;
|
||||||
virtual void OnAlias(const Mark& mark, anchor_t anchor);
|
void OnAlias(const Mark& mark, anchor_t anchor) override;
|
||||||
virtual void OnScalar(const Mark& mark, const std::string& tag,
|
void OnScalar(const Mark& mark, const std::string& tag,
|
||||||
anchor_t anchor, const std::string& value);
|
anchor_t anchor, const std::string& value) override;
|
||||||
|
|
||||||
virtual void OnSequenceStart(const Mark& mark, const std::string& tag,
|
void OnSequenceStart(const Mark& mark, const std::string& tag,
|
||||||
anchor_t anchor, EmitterStyle::value style);
|
anchor_t anchor, EmitterStyle::value style) override;
|
||||||
virtual void OnSequenceEnd();
|
void OnSequenceEnd() override;
|
||||||
|
|
||||||
virtual void OnMapStart(const Mark& mark, const std::string& tag,
|
void OnMapStart(const Mark& mark, const std::string& tag,
|
||||||
anchor_t anchor, EmitterStyle::value style);
|
anchor_t anchor, EmitterStyle::value style) override;
|
||||||
virtual void OnMapEnd();
|
void OnMapEnd() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
detail::node& Push(const Mark& mark, anchor_t anchor);
|
detail::node& Push(const Mark& mark, anchor_t anchor);
|
||||||
@@ -61,11 +61,11 @@ class NodeBuilder : public EventHandler {
|
|||||||
detail::shared_memory_holder m_pMemory;
|
detail::shared_memory_holder m_pMemory;
|
||||||
detail::node* m_pRoot;
|
detail::node* m_pRoot;
|
||||||
|
|
||||||
typedef std::vector<detail::node*> Nodes;
|
using Nodes = std::vector<detail::node *>;
|
||||||
Nodes m_stack;
|
Nodes m_stack;
|
||||||
Nodes m_anchors;
|
Nodes m_anchors;
|
||||||
|
|
||||||
typedef std::pair<detail::node*, bool> PushedKey;
|
using PushedKey = std::pair<detail::node*, bool>;
|
||||||
std::vector<PushedKey> m_keys;
|
std::vector<PushedKey> m_keys;
|
||||||
std::size_t m_mapDepth;
|
std::size_t m_mapDepth;
|
||||||
};
|
};
|
||||||
|
@@ -45,7 +45,7 @@ class NodeEvents {
|
|||||||
anchor_t _CreateNewAnchor() { return ++m_curAnchor; }
|
anchor_t _CreateNewAnchor() { return ++m_curAnchor; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::map<const detail::node_ref*, anchor_t> AnchorByIdentity;
|
using AnchorByIdentity = std::map<const detail::node_ref*, anchor_t>;
|
||||||
AnchorByIdentity m_anchorByIdentity;
|
AnchorByIdentity m_anchorByIdentity;
|
||||||
|
|
||||||
anchor_t m_curAnchor;
|
anchor_t m_curAnchor;
|
||||||
@@ -60,7 +60,7 @@ class NodeEvents {
|
|||||||
detail::shared_memory_holder m_pMemory;
|
detail::shared_memory_holder m_pMemory;
|
||||||
detail::node* m_root;
|
detail::node* m_root;
|
||||||
|
|
||||||
typedef std::map<const detail::node_ref*, int> RefCount;
|
using RefCount = std::map<const detail::node_ref*, int>;
|
||||||
RefCount m_refCount;
|
RefCount m_refCount;
|
||||||
};
|
};
|
||||||
} // namespace YAML
|
} // namespace YAML
|
||||||
|
@@ -21,7 +21,7 @@ ostream_wrapper::ostream_wrapper(std::ostream& stream)
|
|||||||
m_col(0),
|
m_col(0),
|
||||||
m_comment(false) {}
|
m_comment(false) {}
|
||||||
|
|
||||||
ostream_wrapper::~ostream_wrapper() {}
|
ostream_wrapper::~ostream_wrapper() = default;
|
||||||
|
|
||||||
void ostream_wrapper::write(const std::string& str) {
|
void ostream_wrapper::write(const std::string& str) {
|
||||||
if (m_pStream) {
|
if (m_pStream) {
|
||||||
@@ -31,8 +31,8 @@ void ostream_wrapper::write(const std::string& str) {
|
|||||||
std::copy(str.begin(), str.end(), m_buffer.begin() + m_pos);
|
std::copy(str.begin(), str.end(), m_buffer.begin() + m_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::size_t i = 0; i < str.size(); i++) {
|
for (char ch : str) {
|
||||||
update_pos(str[i]);
|
update_pos(ch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -15,10 +15,10 @@ Parser::Parser() : m_pScanner{}, m_pDirectives{} {}
|
|||||||
|
|
||||||
Parser::Parser(std::istream& in) : Parser() { Load(in); }
|
Parser::Parser(std::istream& in) : Parser() { Load(in); }
|
||||||
|
|
||||||
Parser::~Parser() {}
|
Parser::~Parser() = default;
|
||||||
|
|
||||||
Parser::operator bool() const {
|
Parser::operator bool() const {
|
||||||
return m_pScanner.get() && !m_pScanner->empty();
|
return m_pScanner && !m_pScanner->empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parser::Load(std::istream& in) {
|
void Parser::Load(std::istream& in) {
|
||||||
@@ -27,7 +27,7 @@ void Parser::Load(std::istream& in) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Parser::HandleNextDocument(EventHandler& eventHandler) {
|
bool Parser::HandleNextDocument(EventHandler& eventHandler) {
|
||||||
if (!m_pScanner.get())
|
if (!m_pScanner)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ParseDirectives();
|
ParseDirectives();
|
||||||
@@ -43,11 +43,7 @@ bool Parser::HandleNextDocument(EventHandler& eventHandler) {
|
|||||||
void Parser::ParseDirectives() {
|
void Parser::ParseDirectives() {
|
||||||
bool readDirective = false;
|
bool readDirective = false;
|
||||||
|
|
||||||
while (1) {
|
while (!m_pScanner->empty()) {
|
||||||
if (m_pScanner->empty()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Token& token = m_pScanner->peek();
|
Token& token = m_pScanner->peek();
|
||||||
if (token.type != Token::DIRECTIVE) {
|
if (token.type != Token::DIRECTIVE) {
|
||||||
break;
|
break;
|
||||||
@@ -113,15 +109,11 @@ void Parser::HandleTagDirective(const Token& token) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Parser::PrintTokens(std::ostream& out) {
|
void Parser::PrintTokens(std::ostream& out) {
|
||||||
if (!m_pScanner.get()) {
|
if (!m_pScanner) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (!m_pScanner->empty()) {
|
||||||
if (m_pScanner->empty()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
out << m_pScanner->peek() << "\n";
|
out << m_pScanner->peek() << "\n";
|
||||||
m_pScanner->pop();
|
m_pScanner->pop();
|
||||||
}
|
}
|
||||||
|
@@ -34,7 +34,7 @@ class YAML_CPP_API RegEx {
|
|||||||
explicit RegEx(char ch);
|
explicit RegEx(char ch);
|
||||||
RegEx(char a, char z);
|
RegEx(char a, char z);
|
||||||
RegEx(const std::string& str, REGEX_OP op = REGEX_SEQ);
|
RegEx(const std::string& str, REGEX_OP op = REGEX_SEQ);
|
||||||
~RegEx() {}
|
~RegEx() = default;
|
||||||
|
|
||||||
friend YAML_CPP_API RegEx operator!(const RegEx& ex);
|
friend YAML_CPP_API RegEx operator!(const RegEx& ex);
|
||||||
friend YAML_CPP_API RegEx operator|(const RegEx& ex1, const RegEx& ex2);
|
friend YAML_CPP_API RegEx operator|(const RegEx& ex1, const RegEx& ex2);
|
||||||
|
@@ -8,8 +8,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
#include "stringsource.h"
|
|
||||||
#include "streamcharsource.h"
|
#include "streamcharsource.h"
|
||||||
|
#include "stringsource.h"
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
// query matches
|
// query matches
|
||||||
@@ -106,9 +106,8 @@ inline int RegEx::MatchOpEmpty(const Source& source) const {
|
|||||||
template <>
|
template <>
|
||||||
inline int RegEx::MatchOpEmpty<StringCharSource>(
|
inline int RegEx::MatchOpEmpty<StringCharSource>(
|
||||||
const StringCharSource& source) const {
|
const StringCharSource& source) const {
|
||||||
return !source
|
return !source ? 0 : -1; // the empty regex only is successful on the empty
|
||||||
? 0
|
// string
|
||||||
: -1; // the empty regex only is successful on the empty string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MatchOperator
|
// MatchOperator
|
||||||
@@ -130,8 +129,8 @@ inline int RegEx::MatchOpRange(const Source& source) const {
|
|||||||
// OrOperator
|
// OrOperator
|
||||||
template <typename Source>
|
template <typename Source>
|
||||||
inline int RegEx::MatchOpOr(const Source& source) const {
|
inline int RegEx::MatchOpOr(const Source& source) const {
|
||||||
for (std::size_t i = 0; i < m_params.size(); i++) {
|
for (const RegEx& param : m_params) {
|
||||||
int n = m_params[i].MatchUnchecked(source);
|
int n = param.MatchUnchecked(source);
|
||||||
if (n >= 0)
|
if (n >= 0)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
@@ -169,11 +168,11 @@ inline int RegEx::MatchOpNot(const Source& source) const {
|
|||||||
template <typename Source>
|
template <typename Source>
|
||||||
inline int RegEx::MatchOpSeq(const Source& source) const {
|
inline int RegEx::MatchOpSeq(const Source& source) const {
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
for (std::size_t i = 0; i < m_params.size(); i++) {
|
for (const RegEx& param : m_params) {
|
||||||
int n = m_params[i].Match(source + offset); // note Match, not
|
int n = param.Match(source + offset); // note Match, not
|
||||||
// MatchUnchecked because we
|
// MatchUnchecked because we
|
||||||
// need to check validity after
|
// need to check validity after
|
||||||
// the offset
|
// the offset
|
||||||
if (n == -1)
|
if (n == -1)
|
||||||
return -1;
|
return -1;
|
||||||
offset += n;
|
offset += n;
|
||||||
@@ -181,6 +180,6 @@ inline int RegEx::MatchOpSeq(const Source& source) const {
|
|||||||
|
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
}
|
} // namespace YAML
|
||||||
|
|
||||||
#endif // REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
@@ -19,7 +19,7 @@ Scanner::Scanner(std::istream& in)
|
|||||||
m_indentRefs{},
|
m_indentRefs{},
|
||||||
m_flows{} {}
|
m_flows{} {}
|
||||||
|
|
||||||
Scanner::~Scanner() {}
|
Scanner::~Scanner() = default;
|
||||||
|
|
||||||
bool Scanner::empty() {
|
bool Scanner::empty() {
|
||||||
EnsureTokensInQueue();
|
EnsureTokensInQueue();
|
||||||
|
@@ -7,12 +7,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "yaml-cpp/noexcept.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
class SettingChangeBase;
|
|
||||||
|
class SettingChangeBase {
|
||||||
|
public:
|
||||||
|
virtual ~SettingChangeBase() = default;
|
||||||
|
virtual void pop() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Setting {
|
class Setting {
|
||||||
@@ -28,12 +34,6 @@ class Setting {
|
|||||||
T m_value;
|
T m_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SettingChangeBase {
|
|
||||||
public:
|
|
||||||
virtual ~SettingChangeBase() {}
|
|
||||||
virtual void pop() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class SettingChange : public SettingChangeBase {
|
class SettingChange : public SettingChangeBase {
|
||||||
public:
|
public:
|
||||||
@@ -46,7 +46,7 @@ class SettingChange : public SettingChangeBase {
|
|||||||
SettingChange& operator=(const SettingChange&) = delete;
|
SettingChange& operator=(const SettingChange&) = delete;
|
||||||
SettingChange& operator=(SettingChange&&) = delete;
|
SettingChange& operator=(SettingChange&&) = delete;
|
||||||
|
|
||||||
virtual void pop() { m_pCurSetting->restore(m_oldSetting); }
|
void pop() override { m_pCurSetting->restore(m_oldSetting); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Setting<T>* m_pCurSetting;
|
Setting<T>* m_pCurSetting;
|
||||||
@@ -64,16 +64,25 @@ class SettingChanges {
|
|||||||
public:
|
public:
|
||||||
SettingChanges() : m_settingChanges{} {}
|
SettingChanges() : m_settingChanges{} {}
|
||||||
SettingChanges(const SettingChanges&) = delete;
|
SettingChanges(const SettingChanges&) = delete;
|
||||||
SettingChanges(SettingChanges&&) = default;
|
SettingChanges(SettingChanges&&) YAML_CPP_NOEXCEPT = default;
|
||||||
SettingChanges& operator=(const SettingChanges&) = delete;
|
SettingChanges& operator=(const SettingChanges&) = delete;
|
||||||
|
SettingChanges& operator=(SettingChanges&& rhs) YAML_CPP_NOEXCEPT {
|
||||||
|
if (this == &rhs)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
clear();
|
||||||
|
std::swap(m_settingChanges, rhs.m_settingChanges);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
~SettingChanges() { clear(); }
|
~SettingChanges() { clear(); }
|
||||||
|
|
||||||
void clear() {
|
void clear() YAML_CPP_NOEXCEPT {
|
||||||
restore();
|
restore();
|
||||||
m_settingChanges.clear();
|
m_settingChanges.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void restore() {
|
void restore() YAML_CPP_NOEXCEPT {
|
||||||
for (setting_changes::const_iterator it = m_settingChanges.begin();
|
for (setting_changes::const_iterator it = m_settingChanges.begin();
|
||||||
it != m_settingChanges.end(); ++it)
|
it != m_settingChanges.end(); ++it)
|
||||||
(*it)->pop();
|
(*it)->pop();
|
||||||
@@ -83,19 +92,8 @@ class SettingChanges {
|
|||||||
m_settingChanges.push_back(std::move(pSettingChange));
|
m_settingChanges.push_back(std::move(pSettingChange));
|
||||||
}
|
}
|
||||||
|
|
||||||
// like std::unique_ptr - assignment is transfer of ownership
|
|
||||||
SettingChanges& operator=(SettingChanges&& rhs) {
|
|
||||||
if (this == &rhs)
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
clear();
|
|
||||||
std::swap(m_settingChanges, rhs.m_settingChanges);
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::vector<std::unique_ptr<SettingChangeBase>> setting_changes;
|
using setting_changes = std::vector<std::unique_ptr<SettingChangeBase>>;
|
||||||
setting_changes m_settingChanges;
|
setting_changes m_settingChanges;
|
||||||
};
|
};
|
||||||
} // namespace YAML
|
} // namespace YAML
|
||||||
|
@@ -21,7 +21,7 @@ SingleDocParser::SingleDocParser(Scanner& scanner, const Directives& directives)
|
|||||||
m_anchors{},
|
m_anchors{},
|
||||||
m_curAnchor(0) {}
|
m_curAnchor(0) {}
|
||||||
|
|
||||||
SingleDocParser::~SingleDocParser() {}
|
SingleDocParser::~SingleDocParser() = default;
|
||||||
|
|
||||||
// HandleDocument
|
// HandleDocument
|
||||||
// . Handles the next document
|
// . Handles the next document
|
||||||
@@ -79,6 +79,12 @@ void SingleDocParser::HandleNode(EventHandler& eventHandler) {
|
|||||||
if (!anchor_name.empty())
|
if (!anchor_name.empty())
|
||||||
eventHandler.OnAnchor(mark, anchor_name);
|
eventHandler.OnAnchor(mark, anchor_name);
|
||||||
|
|
||||||
|
// after parsing properties, an empty node is again a possibility
|
||||||
|
if (m_scanner.empty()) {
|
||||||
|
eventHandler.OnNull(mark, anchor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const Token& token = m_scanner.peek();
|
const Token& token = m_scanner.peek();
|
||||||
|
|
||||||
if (token.type == Token::PLAIN_SCALAR && IsNullString(token.value)) {
|
if (token.type == Token::PLAIN_SCALAR && IsNullString(token.value)) {
|
||||||
|
@@ -59,7 +59,7 @@ class SingleDocParser {
|
|||||||
const Directives& m_directives;
|
const Directives& m_directives;
|
||||||
std::unique_ptr<CollectionStack> m_pCollectionStack;
|
std::unique_ptr<CollectionStack> m_pCollectionStack;
|
||||||
|
|
||||||
typedef std::map<std::string, anchor_t> Anchors;
|
using Anchors = std::map<std::string, anchor_t>;
|
||||||
Anchors m_anchors;
|
Anchors m_anchors;
|
||||||
|
|
||||||
anchor_t m_curAnchor;
|
anchor_t m_curAnchor;
|
||||||
|
@@ -151,7 +151,7 @@ inline UtfIntroCharType IntroCharTypeOf(std::istream::int_type ch) {
|
|||||||
|
|
||||||
inline char Utf8Adjust(unsigned long ch, unsigned char lead_bits,
|
inline char Utf8Adjust(unsigned long ch, unsigned char lead_bits,
|
||||||
unsigned char rshift) {
|
unsigned char rshift) {
|
||||||
const unsigned char header = ((1 << lead_bits) - 1) << (8 - lead_bits);
|
const unsigned char header = static_cast<unsigned char>(((1 << lead_bits) - 1) << (8 - lead_bits));
|
||||||
const unsigned char mask = (0xFF >> (lead_bits + 1));
|
const unsigned char mask = (0xFF >> (lead_bits + 1));
|
||||||
return static_cast<char>(
|
return static_cast<char>(
|
||||||
static_cast<unsigned char>(header | ((ch >> rshift) & mask)));
|
static_cast<unsigned char>(header | ((ch >> rshift) & mask)));
|
||||||
@@ -189,14 +189,14 @@ Stream::Stream(std::istream& input)
|
|||||||
m_pPrefetched(new unsigned char[YAML_PREFETCH_SIZE]),
|
m_pPrefetched(new unsigned char[YAML_PREFETCH_SIZE]),
|
||||||
m_nPrefetchedAvailable(0),
|
m_nPrefetchedAvailable(0),
|
||||||
m_nPrefetchedUsed(0) {
|
m_nPrefetchedUsed(0) {
|
||||||
typedef std::istream::traits_type char_traits;
|
using char_traits = std::istream::traits_type;
|
||||||
|
|
||||||
if (!input)
|
if (!input)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Determine (or guess) the character-set by reading the BOM, if any. See
|
// Determine (or guess) the character-set by reading the BOM, if any. See
|
||||||
// the YAML specification for the determination algorithm.
|
// the YAML specification for the determination algorithm.
|
||||||
char_traits::int_type intro[4];
|
char_traits::int_type intro[4]{};
|
||||||
int nIntroUsed = 0;
|
int nIntroUsed = 0;
|
||||||
UtfIntroState state = uis_start;
|
UtfIntroState state = uis_start;
|
||||||
for (; !s_introFinalState[state];) {
|
for (; !s_introFinalState[state];) {
|
||||||
@@ -273,9 +273,11 @@ char Stream::get() {
|
|||||||
// . Extracts 'n' characters from the stream and updates our position
|
// . Extracts 'n' characters from the stream and updates our position
|
||||||
std::string Stream::get(int n) {
|
std::string Stream::get(int n) {
|
||||||
std::string ret;
|
std::string ret;
|
||||||
ret.reserve(n);
|
if(n > 0) {
|
||||||
for (int i = 0; i < n; i++)
|
ret.reserve(static_cast<std::string::size_type>(n));
|
||||||
ret += get();
|
for (int i = 0; i < n; i++)
|
||||||
|
ret += get();
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,7 +328,7 @@ bool Stream::_ReadAheadTo(size_t i) const {
|
|||||||
void Stream::StreamInUtf8() const {
|
void Stream::StreamInUtf8() const {
|
||||||
unsigned char b = GetNextByte();
|
unsigned char b = GetNextByte();
|
||||||
if (m_input.good()) {
|
if (m_input.good()) {
|
||||||
m_readahead.push_back(b);
|
m_readahead.push_back(static_cast<char>(b));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,6 +16,9 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
|
|
||||||
|
class StreamCharSource;
|
||||||
|
|
||||||
class Stream {
|
class Stream {
|
||||||
public:
|
public:
|
||||||
friend class StreamCharSource;
|
friend class StreamCharSource;
|
||||||
|
@@ -7,18 +7,20 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "yaml-cpp/noexcept.h"
|
||||||
|
#include "stream.h"
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
|
|
||||||
class StreamCharSource {
|
class StreamCharSource {
|
||||||
public:
|
public:
|
||||||
StreamCharSource(const Stream& stream) : m_offset(0), m_stream(stream) {}
|
StreamCharSource(const Stream& stream) : m_offset(0), m_stream(stream) {}
|
||||||
StreamCharSource(const StreamCharSource& source)
|
StreamCharSource(const StreamCharSource& source) = default;
|
||||||
: m_offset(source.m_offset), m_stream(source.m_stream) {}
|
StreamCharSource(StreamCharSource&&) YAML_CPP_NOEXCEPT = default;
|
||||||
StreamCharSource(StreamCharSource&&) = default;
|
|
||||||
StreamCharSource& operator=(const StreamCharSource&) = delete;
|
StreamCharSource& operator=(const StreamCharSource&) = delete;
|
||||||
StreamCharSource& operator=(StreamCharSource&&) = delete;
|
StreamCharSource& operator=(StreamCharSource&&) = delete;
|
||||||
~StreamCharSource() {}
|
~StreamCharSource() = default;
|
||||||
|
|
||||||
operator bool() const;
|
operator bool() const;
|
||||||
char operator[](std::size_t i) const { return m_stream.CharAt(m_offset + i); }
|
char operator[](std::size_t i) const { return m_stream.CharAt(m_offset + i); }
|
||||||
@@ -38,7 +40,7 @@ inline StreamCharSource::operator bool() const {
|
|||||||
inline const StreamCharSource StreamCharSource::operator+(int i) const {
|
inline const StreamCharSource StreamCharSource::operator+(int i) const {
|
||||||
StreamCharSource source(*this);
|
StreamCharSource source(*this);
|
||||||
if (static_cast<int>(source.m_offset) + i >= 0)
|
if (static_cast<int>(source.m_offset) + i >= 0)
|
||||||
source.m_offset += i;
|
source.m_offset += static_cast<std::size_t>(i);
|
||||||
else
|
else
|
||||||
source.m_offset = 0;
|
source.m_offset = 0;
|
||||||
return source;
|
return source;
|
||||||
|
@@ -53,8 +53,8 @@ struct Token {
|
|||||||
|
|
||||||
friend std::ostream& operator<<(std::ostream& out, const Token& token) {
|
friend std::ostream& operator<<(std::ostream& out, const Token& token) {
|
||||||
out << TokenNames[token.type] << std::string(": ") << token.value;
|
out << TokenNames[token.type] << std::string(": ") << token.value;
|
||||||
for (std::size_t i = 0; i < token.params.size(); i++)
|
for (const std::string& param : token.params)
|
||||||
out << std::string(" ") << token.params[i];
|
out << std::string(" ") << param;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
test/BUILD.bazel
Normal file
14
test/BUILD.bazel
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
cc_test(
|
||||||
|
name = "test",
|
||||||
|
srcs = glob([
|
||||||
|
"*.cpp",
|
||||||
|
"*.h",
|
||||||
|
"integrations/*.cpp",
|
||||||
|
"node/*.cpp",
|
||||||
|
]),
|
||||||
|
deps = [
|
||||||
|
"//:yaml-cpp",
|
||||||
|
"//:yaml-cpp_internal",
|
||||||
|
"@com_google_googletest//:gtest_main",
|
||||||
|
],
|
||||||
|
)
|
@@ -1,69 +1,49 @@
|
|||||||
include(ExternalProject)
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
if(MSVC)
|
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||||
# MS Visual Studio expects lib prefix on static libraries,
|
set(BUILD_MOCK ON CACHE BOOL "" FORCE)
|
||||||
# but CMake compiles them without prefix
|
set(CMAKE_POLICY_DEFAULT_CMP0048 NEW)
|
||||||
# See https://gitlab.kitware.com/cmake/cmake/issues/17338
|
|
||||||
set(CMAKE_STATIC_LIBRARY_PREFIX "")
|
add_subdirectory(
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.10.0"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/prefix")
|
||||||
|
|
||||||
|
include_directories(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.10.0/googletest/include")
|
||||||
|
|
||||||
|
set(test-new-api-pattern "new-api/*.cpp")
|
||||||
|
set(test-source-pattern "*.cpp" "integration/*.cpp" "node/*.cpp")
|
||||||
|
if (CMAKE_VERSION VERSION_GREATER 3.11)
|
||||||
|
list(INSERT test-new-api-pattern 0 CONFIGURE_DEPENDS)
|
||||||
|
list(INSERT test-source-pattern 0 CONFIGURE_DEPENDS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
ExternalProject_Add(
|
file(GLOB test-new-api-sources ${test-new-api-pattern})
|
||||||
googletest_project
|
file(GLOB test-sources ${test-source-pattern})
|
||||||
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.8.0"
|
|
||||||
INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/prefix"
|
|
||||||
CMAKE_ARGS
|
|
||||||
-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
|
|
||||||
-DBUILD_GMOCK=ON
|
|
||||||
-Dgtest_force_shared_crt=ON
|
|
||||||
)
|
|
||||||
|
|
||||||
add_library(gmock UNKNOWN IMPORTED)
|
add_executable(yaml-cpp-tests "")
|
||||||
set_target_properties(gmock PROPERTIES
|
target_sources(yaml-cpp-tests
|
||||||
IMPORTED_LOCATION
|
PRIVATE
|
||||||
${PROJECT_BINARY_DIR}/test/prefix/lib/${CMAKE_STATIC_LIBRARY_PREFIX}gmock${CMAKE_STATIC_LIBRARY_SUFFIX}
|
${test-new-api-sources}
|
||||||
)
|
${test-sources})
|
||||||
|
target_include_directories(yaml-cpp-tests
|
||||||
find_package(Threads)
|
PRIVATE
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/integration
|
||||||
include_directories(SYSTEM "${PROJECT_BINARY_DIR}/test/prefix/include")
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
${PROJECT_SOURCE_DIR}/src)
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR
|
target_compile_options(yaml-cpp-tests
|
||||||
CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
PRIVATE
|
||||||
set(yaml_test_flags "-Wno-variadic-macros -Wno-sign-compare")
|
$<$<CXX_COMPILER_ID:Clang>:-Wno-c99-extensions -Wno-variadic-macros -Wno-sign-compare>
|
||||||
|
$<$<CXX_COMPILER_ID:GNU>:-Wno-variadic-macros -Wno-sign-compare>)
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
target_link_libraries(yaml-cpp-tests
|
||||||
set(yaml_test_flags "${yaml_test_flags} -Wno-c99-extensions")
|
PRIVATE
|
||||||
endif()
|
Threads::Threads
|
||||||
endif()
|
|
||||||
|
|
||||||
file(GLOB test_headers [a-z_]*.h)
|
|
||||||
file(GLOB test_sources [a-z_]*.cpp integration/[a-z_]*.cpp node/[a-z_]*.cpp)
|
|
||||||
file(GLOB test_new_api_sources new-api/[a-z]*.cpp)
|
|
||||||
|
|
||||||
list(APPEND test_sources ${test_new_api_sources})
|
|
||||||
add_sources(${test_sources} ${test_headers})
|
|
||||||
|
|
||||||
include_directories(${YAML_CPP_SOURCE_DIR}/src)
|
|
||||||
include_directories(${YAML_CPP_SOURCE_DIR}/test)
|
|
||||||
|
|
||||||
add_executable(run-tests
|
|
||||||
${test_sources}
|
|
||||||
${test_headers}
|
|
||||||
)
|
|
||||||
|
|
||||||
set_target_properties(run-tests PROPERTIES
|
|
||||||
CXX_STANDARD 11
|
|
||||||
CXX_STANDARD_REQUIRED ON
|
|
||||||
)
|
|
||||||
|
|
||||||
add_dependencies(run-tests googletest_project)
|
|
||||||
|
|
||||||
set_target_properties(run-tests PROPERTIES
|
|
||||||
COMPILE_FLAGS "${yaml_c_flags} ${yaml_cxx_flags} ${yaml_test_flags}"
|
|
||||||
)
|
|
||||||
target_link_libraries(run-tests
|
|
||||||
yaml-cpp
|
yaml-cpp
|
||||||
gmock
|
gmock)
|
||||||
${CMAKE_THREAD_LIBS_INIT})
|
|
||||||
|
|
||||||
add_test(yaml-test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/run-tests)
|
set_property(TARGET yaml-cpp-tests PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||||
|
if (NOT DEFINED CMAKE_CXX_STANDARD)
|
||||||
|
set_target_properties(yaml-cpp-tests PROPERTIES CXX_STANDARD 11)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
add_test(yaml-cpp::test yaml-cpp-tests)
|
||||||
|
4
test/gtest-1.10.0/.clang-format
Normal file
4
test/gtest-1.10.0/.clang-format
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# Run manually to reformat a file:
|
||||||
|
# clang-format -i --style=file <file>
|
||||||
|
Language: Cpp
|
||||||
|
BasedOnStyle: Google
|
84
test/gtest-1.10.0/.gitignore
vendored
Normal file
84
test/gtest-1.10.0/.gitignore
vendored
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
# Ignore CI build directory
|
||||||
|
build/
|
||||||
|
xcuserdata
|
||||||
|
cmake-build-debug/
|
||||||
|
.idea/
|
||||||
|
bazel-bin
|
||||||
|
bazel-genfiles
|
||||||
|
bazel-googletest
|
||||||
|
bazel-out
|
||||||
|
bazel-testlogs
|
||||||
|
# python
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Visual Studio files
|
||||||
|
.vs
|
||||||
|
*.sdf
|
||||||
|
*.opensdf
|
||||||
|
*.VC.opendb
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
_ReSharper.Caches/
|
||||||
|
Win32-Debug/
|
||||||
|
Win32-Release/
|
||||||
|
x64-Debug/
|
||||||
|
x64-Release/
|
||||||
|
|
||||||
|
# Ignore autoconf / automake files
|
||||||
|
Makefile.in
|
||||||
|
aclocal.m4
|
||||||
|
configure
|
||||||
|
build-aux/
|
||||||
|
autom4te.cache/
|
||||||
|
googletest/m4/libtool.m4
|
||||||
|
googletest/m4/ltoptions.m4
|
||||||
|
googletest/m4/ltsugar.m4
|
||||||
|
googletest/m4/ltversion.m4
|
||||||
|
googletest/m4/lt~obsolete.m4
|
||||||
|
googlemock/m4
|
||||||
|
|
||||||
|
# Ignore generated directories.
|
||||||
|
googlemock/fused-src/
|
||||||
|
googletest/fused-src/
|
||||||
|
|
||||||
|
# macOS files
|
||||||
|
.DS_Store
|
||||||
|
googletest/.DS_Store
|
||||||
|
googletest/xcode/.DS_Store
|
||||||
|
|
||||||
|
# Ignore cmake generated directories and files.
|
||||||
|
CMakeFiles
|
||||||
|
CTestTestfile.cmake
|
||||||
|
Makefile
|
||||||
|
cmake_install.cmake
|
||||||
|
googlemock/CMakeFiles
|
||||||
|
googlemock/CTestTestfile.cmake
|
||||||
|
googlemock/Makefile
|
||||||
|
googlemock/cmake_install.cmake
|
||||||
|
googlemock/gtest
|
||||||
|
/bin
|
||||||
|
/googlemock/gmock.dir
|
||||||
|
/googlemock/gmock_main.dir
|
||||||
|
/googlemock/RUN_TESTS.vcxproj.filters
|
||||||
|
/googlemock/RUN_TESTS.vcxproj
|
||||||
|
/googlemock/INSTALL.vcxproj.filters
|
||||||
|
/googlemock/INSTALL.vcxproj
|
||||||
|
/googlemock/gmock_main.vcxproj.filters
|
||||||
|
/googlemock/gmock_main.vcxproj
|
||||||
|
/googlemock/gmock.vcxproj.filters
|
||||||
|
/googlemock/gmock.vcxproj
|
||||||
|
/googlemock/gmock.sln
|
||||||
|
/googlemock/ALL_BUILD.vcxproj.filters
|
||||||
|
/googlemock/ALL_BUILD.vcxproj
|
||||||
|
/lib
|
||||||
|
/Win32
|
||||||
|
/ZERO_CHECK.vcxproj.filters
|
||||||
|
/ZERO_CHECK.vcxproj
|
||||||
|
/RUN_TESTS.vcxproj.filters
|
||||||
|
/RUN_TESTS.vcxproj
|
||||||
|
/INSTALL.vcxproj.filters
|
||||||
|
/INSTALL.vcxproj
|
||||||
|
/googletest-distribution.sln
|
||||||
|
/CMakeCache.txt
|
||||||
|
/ALL_BUILD.vcxproj.filters
|
||||||
|
/ALL_BUILD.vcxproj
|
73
test/gtest-1.10.0/.travis.yml
Normal file
73
test/gtest-1.10.0/.travis.yml
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
# 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
|
179
test/gtest-1.10.0/BUILD.bazel
Normal file
179
test/gtest-1.10.0/BUILD.bazel
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# Bazel Build for Google C++ Testing Framework(Google Test)
|
||||||
|
|
||||||
|
load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
|
||||||
|
|
||||||
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
|
licenses(["notice"])
|
||||||
|
|
||||||
|
config_setting(
|
||||||
|
name = "windows",
|
||||||
|
constraint_values = ["@bazel_tools//platforms:windows"],
|
||||||
|
)
|
||||||
|
|
||||||
|
config_setting(
|
||||||
|
name = "has_absl",
|
||||||
|
values = {"define": "absl=1"},
|
||||||
|
)
|
||||||
|
|
||||||
|
# Library that defines the FRIEND_TEST macro.
|
||||||
|
cc_library(
|
||||||
|
name = "gtest_prod",
|
||||||
|
hdrs = ["googletest/include/gtest/gtest_prod.h"],
|
||||||
|
includes = ["googletest/include"],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Google Test including Google Mock
|
||||||
|
cc_library(
|
||||||
|
name = "gtest",
|
||||||
|
srcs = glob(
|
||||||
|
include = [
|
||||||
|
"googletest/src/*.cc",
|
||||||
|
"googletest/src/*.h",
|
||||||
|
"googletest/include/gtest/**/*.h",
|
||||||
|
"googlemock/src/*.cc",
|
||||||
|
"googlemock/include/gmock/**/*.h",
|
||||||
|
],
|
||||||
|
exclude = [
|
||||||
|
"googletest/src/gtest-all.cc",
|
||||||
|
"googletest/src/gtest_main.cc",
|
||||||
|
"googlemock/src/gmock-all.cc",
|
||||||
|
"googlemock/src/gmock_main.cc",
|
||||||
|
],
|
||||||
|
),
|
||||||
|
hdrs = glob([
|
||||||
|
"googletest/include/gtest/*.h",
|
||||||
|
"googlemock/include/gmock/*.h",
|
||||||
|
]),
|
||||||
|
copts = select({
|
||||||
|
":windows": [],
|
||||||
|
"//conditions:default": ["-pthread"],
|
||||||
|
}),
|
||||||
|
defines = select({
|
||||||
|
":has_absl": ["GTEST_HAS_ABSL=1"],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}),
|
||||||
|
features = select({
|
||||||
|
":windows": ["windows_export_all_symbols"],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}),
|
||||||
|
includes = [
|
||||||
|
"googlemock",
|
||||||
|
"googlemock/include",
|
||||||
|
"googletest",
|
||||||
|
"googletest/include",
|
||||||
|
],
|
||||||
|
linkopts = select({
|
||||||
|
":windows": [],
|
||||||
|
"//conditions:default": ["-pthread"],
|
||||||
|
}),
|
||||||
|
deps = select({
|
||||||
|
":has_absl": [
|
||||||
|
"@com_google_absl//absl/debugging:failure_signal_handler",
|
||||||
|
"@com_google_absl//absl/debugging:stacktrace",
|
||||||
|
"@com_google_absl//absl/debugging:symbolize",
|
||||||
|
"@com_google_absl//absl/strings",
|
||||||
|
"@com_google_absl//absl/types:optional",
|
||||||
|
"@com_google_absl//absl/types:variant",
|
||||||
|
],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "gtest_main",
|
||||||
|
srcs = ["googlemock/src/gmock_main.cc"],
|
||||||
|
features = select({
|
||||||
|
":windows": ["windows_export_all_symbols"],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}),
|
||||||
|
deps = [":gtest"],
|
||||||
|
)
|
||||||
|
|
||||||
|
# The following rules build samples of how to use gTest.
|
||||||
|
cc_library(
|
||||||
|
name = "gtest_sample_lib",
|
||||||
|
srcs = [
|
||||||
|
"googletest/samples/sample1.cc",
|
||||||
|
"googletest/samples/sample2.cc",
|
||||||
|
"googletest/samples/sample4.cc",
|
||||||
|
],
|
||||||
|
hdrs = [
|
||||||
|
"googletest/samples/prime_tables.h",
|
||||||
|
"googletest/samples/sample1.h",
|
||||||
|
"googletest/samples/sample2.h",
|
||||||
|
"googletest/samples/sample3-inl.h",
|
||||||
|
"googletest/samples/sample4.h",
|
||||||
|
],
|
||||||
|
features = select({
|
||||||
|
":windows": ["windows_export_all_symbols"],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_test(
|
||||||
|
name = "gtest_samples",
|
||||||
|
size = "small",
|
||||||
|
# All Samples except:
|
||||||
|
# sample9 (main)
|
||||||
|
# sample10 (main and takes a command line option and needs to be separate)
|
||||||
|
srcs = [
|
||||||
|
"googletest/samples/sample1_unittest.cc",
|
||||||
|
"googletest/samples/sample2_unittest.cc",
|
||||||
|
"googletest/samples/sample3_unittest.cc",
|
||||||
|
"googletest/samples/sample4_unittest.cc",
|
||||||
|
"googletest/samples/sample5_unittest.cc",
|
||||||
|
"googletest/samples/sample6_unittest.cc",
|
||||||
|
"googletest/samples/sample7_unittest.cc",
|
||||||
|
"googletest/samples/sample8_unittest.cc",
|
||||||
|
],
|
||||||
|
linkstatic = 0,
|
||||||
|
deps = [
|
||||||
|
"gtest_sample_lib",
|
||||||
|
":gtest_main",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_test(
|
||||||
|
name = "sample9_unittest",
|
||||||
|
size = "small",
|
||||||
|
srcs = ["googletest/samples/sample9_unittest.cc"],
|
||||||
|
deps = [":gtest"],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_test(
|
||||||
|
name = "sample10_unittest",
|
||||||
|
size = "small",
|
||||||
|
srcs = ["googletest/samples/sample10_unittest.cc"],
|
||||||
|
deps = [":gtest"],
|
||||||
|
)
|
36
test/gtest-1.10.0/CMakeLists.txt
Normal file
36
test/gtest-1.10.0/CMakeLists.txt
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# Note: CMake support is community-based. The maintainers do not use CMake
|
||||||
|
# internally.
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 2.8.8)
|
||||||
|
|
||||||
|
if (POLICY CMP0048)
|
||||||
|
cmake_policy(SET CMP0048 NEW)
|
||||||
|
endif (POLICY CMP0048)
|
||||||
|
|
||||||
|
project(googletest-distribution)
|
||||||
|
set(GOOGLETEST_VERSION 1.10.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)
|
||||||
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
enable_testing()
|
||||||
|
|
||||||
|
include(CMakeDependentOption)
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
|
#Note that googlemock target already builds googletest
|
||||||
|
option(BUILD_GMOCK "Builds the googlemock subproject" ON)
|
||||||
|
option(INSTALL_GTEST "Enable installation of googletest. (Projects embedding googletest may want to turn this OFF.)" ON)
|
||||||
|
|
||||||
|
if(BUILD_GMOCK)
|
||||||
|
add_subdirectory( googlemock )
|
||||||
|
else()
|
||||||
|
add_subdirectory( googletest )
|
||||||
|
endif()
|
142
test/gtest-1.10.0/CONTRIBUTING.md
Normal file
142
test/gtest-1.10.0/CONTRIBUTING.md
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
# How to become a contributor and submit your own code
|
||||||
|
|
||||||
|
## Contributor License Agreements
|
||||||
|
|
||||||
|
We'd love to accept your patches! Before we can take them, we have to jump a
|
||||||
|
couple of legal hurdles.
|
||||||
|
|
||||||
|
Please fill out either the individual or corporate Contributor License Agreement
|
||||||
|
(CLA).
|
||||||
|
|
||||||
|
* If you are an individual writing original source code and you're sure you
|
||||||
|
own the intellectual property, then you'll need to sign an
|
||||||
|
[individual CLA](https://developers.google.com/open-source/cla/individual).
|
||||||
|
* If you work for a company that wants to allow you to contribute your work,
|
||||||
|
then you'll need to sign a
|
||||||
|
[corporate CLA](https://developers.google.com/open-source/cla/corporate).
|
||||||
|
|
||||||
|
Follow either of the two links above to access the appropriate CLA and
|
||||||
|
instructions for how to sign and return it. Once we receive it, we'll be able to
|
||||||
|
accept your pull requests.
|
||||||
|
|
||||||
|
## Are you a Googler?
|
||||||
|
|
||||||
|
If you are a Googler, please make an attempt to submit an internal change rather
|
||||||
|
than a GitHub Pull Request. If you are not able to submit an internal change a
|
||||||
|
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).
|
||||||
|
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.
|
||||||
|
3. Also, coordinate with team members that are listed on the issue in question.
|
||||||
|
This ensures that work isn't being duplicated and communicating your plan
|
||||||
|
early also generally leads to better patches.
|
||||||
|
4. If your proposed change is accepted, and you haven't already done so, sign a
|
||||||
|
Contributor License Agreement (see details above).
|
||||||
|
5. Fork the desired repo, develop and test your code changes.
|
||||||
|
6. Ensure that your code adheres to the existing style in the sample to which
|
||||||
|
you are contributing.
|
||||||
|
7. Ensure that your code has an appropriate set of unit tests which all pass.
|
||||||
|
8. Submit a pull request.
|
||||||
|
|
||||||
|
## The Google Test and Google Mock Communities
|
||||||
|
|
||||||
|
The Google Test community exists primarily through the
|
||||||
|
[discussion group](http://groups.google.com/group/googletestframework) and the
|
||||||
|
GitHub repository. Likewise, the Google Mock community exists primarily through
|
||||||
|
their own [discussion group](http://groups.google.com/group/googlemock). You are
|
||||||
|
definitely encouraged to contribute to the discussion and you can also help us
|
||||||
|
to keep the effectiveness of the group high by following and promoting the
|
||||||
|
guidelines listed here.
|
||||||
|
|
||||||
|
### Please Be Friendly
|
||||||
|
|
||||||
|
Showing courtesy and respect to others is a vital part of the Google culture,
|
||||||
|
and we strongly encourage everyone participating in Google Test development to
|
||||||
|
join us in accepting nothing less. Of course, being courteous is not the same as
|
||||||
|
failing to constructively disagree with each other, but it does mean that we
|
||||||
|
should be respectful of each other when enumerating the 42 technical reasons
|
||||||
|
that a particular proposal may not be the best choice. There's never a reason to
|
||||||
|
be antagonistic or dismissive toward anyone who is sincerely trying to
|
||||||
|
contribute to a discussion.
|
||||||
|
|
||||||
|
Sure, C++ testing is serious business and all that, but it's also a lot of fun.
|
||||||
|
Let's keep it that way. Let's strive to be one of the friendliest communities in
|
||||||
|
all of open source.
|
||||||
|
|
||||||
|
As always, discuss Google Test in the official GoogleTest discussion group. You
|
||||||
|
don't have to actually submit code in order to sign up. Your participation
|
||||||
|
itself is a valuable contribution.
|
||||||
|
|
||||||
|
## Style
|
||||||
|
|
||||||
|
To keep the source consistent, readable, diffable and easy to merge, we use a
|
||||||
|
fairly rigid coding style, as defined by the
|
||||||
|
[google-styleguide](https://github.com/google/styleguide) project. All patches
|
||||||
|
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
|
||||||
|
|
||||||
|
## Requirements for Contributors
|
||||||
|
|
||||||
|
If you plan to contribute a patch, you need to build Google Test, Google Mock,
|
||||||
|
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
|
||||||
|
|
||||||
|
## Developing Google Test and Google Mock
|
||||||
|
|
||||||
|
This section discusses how to make your own changes to the Google Test project.
|
||||||
|
|
||||||
|
### Testing Google Test and Google Mock Themselves
|
||||||
|
|
||||||
|
To make sure your changes work as intended and don't break existing
|
||||||
|
functionality, you'll want to compile and run Google Test and GoogleMock's own
|
||||||
|
tests. For that you can use CMake:
|
||||||
|
|
||||||
|
mkdir mybuild
|
||||||
|
cd mybuild
|
||||||
|
cmake -Dgtest_build_tests=ON -Dgmock_build_tests=ON ${GTEST_REPO_DIR}
|
||||||
|
|
||||||
|
To choose between building only Google Test or Google Mock, you may modify your
|
||||||
|
cmake command to be one of each
|
||||||
|
|
||||||
|
cmake -Dgtest_build_tests=ON ${GTEST_DIR} # sets up Google Test tests
|
||||||
|
cmake -Dgmock_build_tests=ON ${GMOCK_DIR} # sets up Google Mock tests
|
||||||
|
|
||||||
|
Make sure you have Python installed, as some of Google Test's tests are written
|
||||||
|
in Python. If the cmake command complains about not being able to find Python
|
||||||
|
(`Could NOT find PythonInterp (missing: PYTHON_EXECUTABLE)`), try telling it
|
||||||
|
explicitly where your Python executable can be found:
|
||||||
|
|
||||||
|
cmake -DPYTHON_EXECUTABLE=path/to/python ...
|
||||||
|
|
||||||
|
Next, you can build Google Test and / or Google Mock and all desired tests. On
|
||||||
|
\*nix, this is usually done by
|
||||||
|
|
||||||
|
make
|
||||||
|
|
||||||
|
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).
|
134
test/gtest-1.10.0/README.md
Normal file
134
test/gtest-1.10.0/README.md
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
# 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!
|
23
test/gtest-1.10.0/WORKSPACE
Normal file
23
test/gtest-1.10.0/WORKSPACE
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
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"],
|
||||||
|
)
|
||||||
|
|
154
test/gtest-1.10.0/appveyor.yml
Normal file
154
test/gtest-1.10.0/appveyor.yml
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
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
|
37
test/gtest-1.10.0/ci/build-linux-bazel.sh
Normal file
37
test/gtest-1.10.0/ci/build-linux-bazel.sh
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#!/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
|
2
test/gtest-1.10.0/ci/build-platformio.sh
Normal file
2
test/gtest-1.10.0/ci/build-platformio.sh
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# run PlatformIO builds
|
||||||
|
platformio run
|
41
test/gtest-1.10.0/ci/env-linux.sh
Normal file
41
test/gtest-1.10.0/ci/env-linux.sh
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#!/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,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
|
# Copyright 2017 Google Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Copyright 2008, Google Inc.
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without
|
# Redistribution and use in source and binary forms, with or without
|
||||||
# modification, are permitted provided that the following conditions are
|
# modification, are permitted provided that the following conditions are
|
||||||
@@ -29,34 +29,19 @@
|
|||||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
# Executes the samples and tests for the Google Test Framework.
|
#
|
||||||
|
# This file should be sourced, and not executed as a standalone script.
|
||||||
|
#
|
||||||
|
|
||||||
# Help the dynamic linker find the path to the libraries.
|
# TODO() - we can check if this is being sourced using $BASH_VERSION and $BASH_SOURCE[0] != ${0}.
|
||||||
export DYLD_FRAMEWORK_PATH=$BUILT_PRODUCTS_DIR
|
#
|
||||||
export DYLD_LIBRARY_PATH=$BUILT_PRODUCTS_DIR
|
|
||||||
|
|
||||||
# Create some executables.
|
if [ "${TRAVIS_OS_NAME}" = "osx" ]; then
|
||||||
test_executables=$@
|
if [ "$CXX" = "clang++" ]; then
|
||||||
|
# $PATH needs to be adjusted because the llvm tap doesn't install the
|
||||||
# Now execute each one in turn keeping track of how many succeeded and failed.
|
# package to /usr/local/bin, etc, like the gcc tap does.
|
||||||
succeeded=0
|
# See: https://github.com/Homebrew/legacy-homebrew/issues/29733
|
||||||
failed=0
|
clang_version=3.9
|
||||||
failed_list=()
|
export PATH="/usr/local/opt/llvm@${clang_version}/bin:$PATH";
|
||||||
for test in ${test_executables[*]}; do
|
fi
|
||||||
"$test"
|
|
||||||
result=$?
|
|
||||||
if [ $result -eq 0 ]; then
|
|
||||||
succeeded=$(( $succeeded + 1 ))
|
|
||||||
else
|
|
||||||
failed=$(( failed + 1 ))
|
|
||||||
failed_list="$failed_list $test"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# Report the successes and failures to the console.
|
|
||||||
echo "Tests complete with $succeeded successes and $failed failures."
|
|
||||||
if [ $failed -ne 0 ]; then
|
|
||||||
echo "The following tests failed:"
|
|
||||||
echo $failed_list
|
|
||||||
fi
|
fi
|
||||||
exit $failed
|
|
48
test/gtest-1.10.0/ci/get-nprocessors.sh
Normal file
48
test/gtest-1.10.0/ci/get-nprocessors.sh
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#!/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 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
|
||||||
|
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
|
49
test/gtest-1.10.0/ci/install-linux.sh
Normal file
49
test/gtest-1.10.0/ci/install-linux.sh
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#!/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
|
40
test/gtest-1.10.0/ci/install-osx.sh
Normal file
40
test/gtest-1.10.0/ci/install-osx.sh
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#!/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
|
5
test/gtest-1.10.0/ci/install-platformio.sh
Normal file
5
test/gtest-1.10.0/ci/install-platformio.sh
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# install PlatformIO
|
||||||
|
sudo pip install -U platformio
|
||||||
|
|
||||||
|
# update PlatformIO
|
||||||
|
platformio update
|
51
test/gtest-1.10.0/ci/log-config.sh
Normal file
51
test/gtest-1.10.0/ci/log-config.sh
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
#!/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
|
||||||
|
|
||||||
|
# ccache on OS X needs installation first
|
||||||
|
# reset ccache statistics
|
||||||
|
ccache --zero-stats
|
||||||
|
|
||||||
|
echo PATH=${PATH}
|
||||||
|
|
||||||
|
echo "Compiler configuration:"
|
||||||
|
echo CXX=${CXX}
|
||||||
|
echo CC=${CC}
|
||||||
|
echo CXXFLAGS=${CXXFLAGS}
|
||||||
|
|
||||||
|
echo "C++ compiler version:"
|
||||||
|
${CXX} --version || echo "${CXX} does not seem to support the --version flag"
|
||||||
|
${CXX} -v || echo "${CXX} does not seem to support the -v flag"
|
||||||
|
|
||||||
|
echo "C compiler version:"
|
||||||
|
${CC} --version || echo "${CXX} does not seem to support the --version flag"
|
||||||
|
${CC} -v || echo "${CXX} does not seem to support the -v flag"
|
44
test/gtest-1.10.0/ci/travis.sh
Normal file
44
test/gtest-1.10.0/ci/travis.sh
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#!/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,14 +1,13 @@
|
|||||||
########################################################################
|
########################################################################
|
||||||
|
# Note: CMake support is community-based. The maintainers do not use CMake
|
||||||
|
# internally.
|
||||||
|
#
|
||||||
# CMake build script for Google Mock.
|
# CMake build script for Google Mock.
|
||||||
#
|
#
|
||||||
# To run the tests for Google Mock itself on Linux, use 'make test' or
|
# To run the tests for Google Mock itself on Linux, use 'make test' or
|
||||||
# ctest. You can select which tests to run using 'ctest -R regex'.
|
# ctest. You can select which tests to run using 'ctest -R regex'.
|
||||||
# For more options, run 'ctest --help'.
|
# For more options, run 'ctest --help'.
|
||||||
|
|
||||||
# BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to
|
|
||||||
# make it prominent in the GUI.
|
|
||||||
option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)." OFF)
|
|
||||||
|
|
||||||
option(gmock_build_tests "Build all of Google Mock's own tests." OFF)
|
option(gmock_build_tests "Build all of Google Mock's own tests." OFF)
|
||||||
|
|
||||||
# A directory to find Google Test sources.
|
# A directory to find Google Test sources.
|
||||||
@@ -37,8 +36,13 @@ endif()
|
|||||||
# as ${gmock_SOURCE_DIR} and to the root binary directory as
|
# as ${gmock_SOURCE_DIR} and to the root binary directory as
|
||||||
# ${gmock_BINARY_DIR}.
|
# ${gmock_BINARY_DIR}.
|
||||||
# Language "C" is required for find_package(Threads).
|
# Language "C" is required for find_package(Threads).
|
||||||
project(gmock CXX C)
|
if (CMAKE_VERSION VERSION_LESS 3.0)
|
||||||
cmake_minimum_required(VERSION 2.6.2)
|
project(gmock CXX C)
|
||||||
|
else()
|
||||||
|
cmake_policy(SET CMP0048 NEW)
|
||||||
|
project(gmock VERSION ${GOOGLETEST_VERSION} LANGUAGES CXX C)
|
||||||
|
endif()
|
||||||
|
cmake_minimum_required(VERSION 2.6.4)
|
||||||
|
|
||||||
if (COMMAND set_up_hermetic_build)
|
if (COMMAND set_up_hermetic_build)
|
||||||
set_up_hermetic_build()
|
set_up_hermetic_build()
|
||||||
@@ -48,7 +52,17 @@ endif()
|
|||||||
# targets to the current scope. We are placing Google Test's binary
|
# targets to the current scope. We are placing Google Test's binary
|
||||||
# directory in a subdirectory of our own as VC compilation may break
|
# directory in a subdirectory of our own as VC compilation may break
|
||||||
# if they are the same (the default).
|
# if they are the same (the default).
|
||||||
add_subdirectory("${gtest_dir}" "${gmock_BINARY_DIR}/gtest")
|
add_subdirectory("${gtest_dir}" "${gmock_BINARY_DIR}/${gtest_dir}")
|
||||||
|
|
||||||
|
|
||||||
|
# These commands only run if this is the main project
|
||||||
|
if(CMAKE_PROJECT_NAME STREQUAL "gmock" OR CMAKE_PROJECT_NAME STREQUAL "googletest-distribution")
|
||||||
|
# BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to
|
||||||
|
# make it prominent in the GUI.
|
||||||
|
option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)." OFF)
|
||||||
|
else()
|
||||||
|
mark_as_advanced(gmock_build_tests)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Although Google Test's CMakeLists.txt calls this function, the
|
# Although Google Test's CMakeLists.txt calls this function, the
|
||||||
# changes there don't affect the current scope. Therefore we have to
|
# changes there don't affect the current scope. Therefore we have to
|
||||||
@@ -56,22 +70,13 @@ add_subdirectory("${gtest_dir}" "${gmock_BINARY_DIR}/gtest")
|
|||||||
config_compiler_and_linker() # from ${gtest_dir}/cmake/internal_utils.cmake
|
config_compiler_and_linker() # from ${gtest_dir}/cmake/internal_utils.cmake
|
||||||
|
|
||||||
# Adds Google Mock's and Google Test's header directories to the search path.
|
# Adds Google Mock's and Google Test's header directories to the search path.
|
||||||
include_directories("${gmock_SOURCE_DIR}/include"
|
set(gmock_build_include_dirs
|
||||||
"${gmock_SOURCE_DIR}"
|
"${gmock_SOURCE_DIR}/include"
|
||||||
"${gtest_SOURCE_DIR}/include"
|
"${gmock_SOURCE_DIR}"
|
||||||
# This directory is needed to build directly from Google
|
"${gtest_SOURCE_DIR}/include"
|
||||||
# Test sources.
|
# This directory is needed to build directly from Google Test sources.
|
||||||
"${gtest_SOURCE_DIR}")
|
"${gtest_SOURCE_DIR}")
|
||||||
|
include_directories(${gmock_build_include_dirs})
|
||||||
# Summary of tuple support for Microsoft Visual Studio:
|
|
||||||
# Compiler version(MS) version(cmake) Support
|
|
||||||
# ---------- ----------- -------------- -----------------------------
|
|
||||||
# <= VS 2010 <= 10 <= 1600 Use Google Tests's own tuple.
|
|
||||||
# VS 2012 11 1700 std::tr1::tuple + _VARIADIC_MAX=10
|
|
||||||
# VS 2013 12 1800 std::tr1::tuple
|
|
||||||
if (MSVC AND MSVC_VERSION EQUAL 1700)
|
|
||||||
add_definitions(/D _VARIADIC_MAX=10)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
#
|
#
|
||||||
@@ -81,32 +86,39 @@ endif()
|
|||||||
# Google Mock libraries. We build them using more strict warnings than what
|
# Google Mock libraries. We build them using more strict warnings than what
|
||||||
# are used for other targets, to ensure that Google Mock can be compiled by
|
# are used for other targets, to ensure that Google Mock can be compiled by
|
||||||
# a user aggressive about warnings.
|
# a user aggressive about warnings.
|
||||||
cxx_library(gmock
|
if (MSVC)
|
||||||
"${cxx_strict}"
|
cxx_library(gmock
|
||||||
"${gtest_dir}/src/gtest-all.cc"
|
"${cxx_strict}"
|
||||||
src/gmock-all.cc)
|
"${gtest_dir}/src/gtest-all.cc"
|
||||||
|
src/gmock-all.cc)
|
||||||
cxx_library(gmock_main
|
|
||||||
"${cxx_strict}"
|
|
||||||
"${gtest_dir}/src/gtest-all.cc"
|
|
||||||
src/gmock-all.cc
|
|
||||||
src/gmock_main.cc)
|
|
||||||
|
|
||||||
|
cxx_library(gmock_main
|
||||||
|
"${cxx_strict}"
|
||||||
|
"${gtest_dir}/src/gtest-all.cc"
|
||||||
|
src/gmock-all.cc
|
||||||
|
src/gmock_main.cc)
|
||||||
|
else()
|
||||||
|
cxx_library(gmock "${cxx_strict}" src/gmock-all.cc)
|
||||||
|
target_link_libraries(gmock PUBLIC gtest)
|
||||||
|
cxx_library(gmock_main "${cxx_strict}" src/gmock_main.cc)
|
||||||
|
target_link_libraries(gmock_main PUBLIC gmock)
|
||||||
|
endif()
|
||||||
# If the CMake version supports it, attach header directory information
|
# If the CMake version supports it, attach header directory information
|
||||||
# to the targets for when we are part of a parent build (ie being pulled
|
# to the targets for when we are part of a parent build (ie being pulled
|
||||||
# in via add_subdirectory() rather than being a standalone build).
|
# in via add_subdirectory() rather than being a standalone build).
|
||||||
if (DEFINED CMAKE_VERSION AND NOT "${CMAKE_VERSION}" VERSION_LESS "2.8.11")
|
if (DEFINED CMAKE_VERSION AND NOT "${CMAKE_VERSION}" VERSION_LESS "2.8.11")
|
||||||
target_include_directories(gmock INTERFACE "${gmock_SOURCE_DIR}/include")
|
target_include_directories(gmock SYSTEM INTERFACE
|
||||||
target_include_directories(gmock_main INTERFACE "${gmock_SOURCE_DIR}/include")
|
"$<BUILD_INTERFACE:${gmock_build_include_dirs}>"
|
||||||
|
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
|
||||||
|
target_include_directories(gmock_main SYSTEM INTERFACE
|
||||||
|
"$<BUILD_INTERFACE:${gmock_build_include_dirs}>"
|
||||||
|
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
#
|
#
|
||||||
# Install rules
|
# Install rules
|
||||||
install(TARGETS gmock gmock_main
|
install_project(gmock gmock_main)
|
||||||
DESTINATION lib)
|
|
||||||
install(DIRECTORY ${gmock_SOURCE_DIR}/include/gmock
|
|
||||||
DESTINATION include)
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
#
|
#
|
||||||
@@ -124,15 +136,37 @@ if (gmock_build_tests)
|
|||||||
# 'make test' or ctest.
|
# 'make test' or ctest.
|
||||||
enable_testing()
|
enable_testing()
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/RunTest.ps1"
|
||||||
|
CONTENT
|
||||||
|
"$project_bin = \"${CMAKE_BINARY_DIR}/bin/$<CONFIG>\"
|
||||||
|
$env:Path = \"$project_bin;$env:Path\"
|
||||||
|
& $args")
|
||||||
|
elseif (MINGW OR CYGWIN)
|
||||||
|
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/RunTest.ps1"
|
||||||
|
CONTENT
|
||||||
|
"$project_bin = (cygpath --windows ${CMAKE_BINARY_DIR}/bin)
|
||||||
|
$env:Path = \"$project_bin;$env:Path\"
|
||||||
|
& $args")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (MINGW OR CYGWIN)
|
||||||
|
if (CMAKE_VERSION VERSION_LESS "2.8.12")
|
||||||
|
add_compile_options("-Wa,-mbig-obj")
|
||||||
|
else()
|
||||||
|
add_definitions("-Wa,-mbig-obj")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
# C++ tests built with standard compiler flags.
|
# C++ tests built with standard compiler flags.
|
||||||
|
|
||||||
cxx_test(gmock-actions_test gmock_main)
|
cxx_test(gmock-actions_test gmock_main)
|
||||||
cxx_test(gmock-cardinalities_test gmock_main)
|
cxx_test(gmock-cardinalities_test gmock_main)
|
||||||
cxx_test(gmock_ex_test gmock_main)
|
cxx_test(gmock_ex_test gmock_main)
|
||||||
|
cxx_test(gmock-function-mocker_test gmock_main)
|
||||||
cxx_test(gmock-generated-actions_test gmock_main)
|
cxx_test(gmock-generated-actions_test gmock_main)
|
||||||
cxx_test(gmock-generated-function-mockers_test gmock_main)
|
cxx_test(gmock-generated-function-mockers_test gmock_main)
|
||||||
cxx_test(gmock-generated-internal-utils_test gmock_main)
|
|
||||||
cxx_test(gmock-generated-matchers_test gmock_main)
|
cxx_test(gmock-generated-matchers_test gmock_main)
|
||||||
cxx_test(gmock-internal-utils_test gmock_main)
|
cxx_test(gmock-internal-utils_test gmock_main)
|
||||||
cxx_test(gmock-matchers_test gmock_main)
|
cxx_test(gmock-matchers_test gmock_main)
|
||||||
@@ -143,7 +177,7 @@ if (gmock_build_tests)
|
|||||||
cxx_test(gmock_link_test gmock_main test/gmock_link2_test.cc)
|
cxx_test(gmock_link_test gmock_main test/gmock_link2_test.cc)
|
||||||
cxx_test(gmock_test gmock_main)
|
cxx_test(gmock_test gmock_main)
|
||||||
|
|
||||||
if (CMAKE_USE_PTHREADS_INIT)
|
if (DEFINED GTEST_HAS_PTHREAD)
|
||||||
cxx_test(gmock_stress_test gmock)
|
cxx_test(gmock_stress_test gmock)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -154,23 +188,20 @@ if (gmock_build_tests)
|
|||||||
############################################################
|
############################################################
|
||||||
# C++ tests built with non-standard compiler flags.
|
# C++ tests built with non-standard compiler flags.
|
||||||
|
|
||||||
cxx_library(gmock_main_no_exception "${cxx_no_exception}"
|
if (MSVC)
|
||||||
"${gtest_dir}/src/gtest-all.cc" src/gmock-all.cc src/gmock_main.cc)
|
cxx_library(gmock_main_no_exception "${cxx_no_exception}"
|
||||||
|
|
||||||
cxx_library(gmock_main_no_rtti "${cxx_no_rtti}"
|
|
||||||
"${gtest_dir}/src/gtest-all.cc" src/gmock-all.cc src/gmock_main.cc)
|
|
||||||
|
|
||||||
if (NOT MSVC OR MSVC_VERSION LESS 1600) # 1600 is Visual Studio 2010.
|
|
||||||
# Visual Studio 2010, 2012, and 2013 define symbols in std::tr1 that
|
|
||||||
# conflict with our own definitions. Therefore using our own tuple does not
|
|
||||||
# work on those compilers.
|
|
||||||
cxx_library(gmock_main_use_own_tuple "${cxx_use_own_tuple}"
|
|
||||||
"${gtest_dir}/src/gtest-all.cc" src/gmock-all.cc src/gmock_main.cc)
|
"${gtest_dir}/src/gtest-all.cc" src/gmock-all.cc src/gmock_main.cc)
|
||||||
|
|
||||||
cxx_test_with_flags(gmock_use_own_tuple_test "${cxx_use_own_tuple}"
|
cxx_library(gmock_main_no_rtti "${cxx_no_rtti}"
|
||||||
gmock_main_use_own_tuple test/gmock-spec-builders_test.cc)
|
"${gtest_dir}/src/gtest-all.cc" src/gmock-all.cc src/gmock_main.cc)
|
||||||
endif()
|
|
||||||
|
|
||||||
|
else()
|
||||||
|
cxx_library(gmock_main_no_exception "${cxx_no_exception}" src/gmock_main.cc)
|
||||||
|
target_link_libraries(gmock_main_no_exception PUBLIC gmock)
|
||||||
|
|
||||||
|
cxx_library(gmock_main_no_rtti "${cxx_no_rtti}" src/gmock_main.cc)
|
||||||
|
target_link_libraries(gmock_main_no_rtti PUBLIC gmock)
|
||||||
|
endif()
|
||||||
cxx_test_with_flags(gmock-more-actions_no_exception_test "${cxx_no_exception}"
|
cxx_test_with_flags(gmock-more-actions_no_exception_test "${cxx_no_exception}"
|
||||||
gmock_main_no_exception test/gmock-more-actions_test.cc)
|
gmock_main_no_exception test/gmock-more-actions_test.cc)
|
||||||
|
|
44
test/gtest-1.10.0/googlemock/README.md
Normal file
44
test/gtest-1.10.0/googlemock/README.md
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# 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.
|
11
test/gtest-1.10.0/googlemock/cmake/gmock.pc.in
Normal file
11
test/gtest-1.10.0/googlemock/cmake/gmock.pc.in
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
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@
|
11
test/gtest-1.10.0/googlemock/cmake/gmock_main.pc.in
Normal file
11
test/gtest-1.10.0/googlemock/cmake/gmock_main.pc.in
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
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@
|
781
test/gtest-1.10.0/googlemock/docs/cheat_sheet.md
Normal file
781
test/gtest-1.10.0/googlemock/docs/cheat_sheet.md
Normal file
@@ -0,0 +1,781 @@
|
|||||||
|
## 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 -->
|
4270
test/gtest-1.10.0/googlemock/docs/cook_book.md
Normal file
4270
test/gtest-1.10.0/googlemock/docs/cook_book.md
Normal file
File diff suppressed because it is too large
Load Diff
700
test/gtest-1.10.0/googlemock/docs/for_dummies.md
Normal file
700
test/gtest-1.10.0/googlemock/docs/for_dummies.md
Normal file
@@ -0,0 +1,700 @@
|
|||||||
|
## gMock for Dummies {#GMockForDummies}
|
||||||
|
|
||||||
|
<!-- GOOGLETEST_CM0013 DO NOT DELETE -->
|
||||||
|
|
||||||
|
### 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
|
||||||
|
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:
|
||||||
|
|
||||||
|
* **Fake** objects have working implementations, but usually take some
|
||||||
|
shortcut (perhaps to make the operations less expensive), which makes them
|
||||||
|
not suitable for production. An in-memory file system would be an example of
|
||||||
|
a fake.
|
||||||
|
* **Mocks** are objects pre-programmed with *expectations*, which form a
|
||||||
|
specification of the calls they are expected to receive.
|
||||||
|
|
||||||
|
If all this seems too abstract for you, don't worry - the most important thing
|
||||||
|
to remember is that a mock allows you to check the *interaction* between itself
|
||||||
|
and code that uses it. The difference between fakes and mocks shall become much
|
||||||
|
clearer once you start to use mocks.
|
||||||
|
|
||||||
|
**gMock** is a library (sometimes we also call it a "framework" to make it sound
|
||||||
|
cool) for creating mock classes and using them. It does to C++ what
|
||||||
|
jMock/EasyMock does to Java (well, more or less).
|
||||||
|
|
||||||
|
When using gMock,
|
||||||
|
|
||||||
|
1. first, you use some simple macros to describe the interface you want to
|
||||||
|
mock, and they will expand to the implementation of your mock class;
|
||||||
|
2. next, you create some mock objects and specify its expectations and behavior
|
||||||
|
using an intuitive syntax;
|
||||||
|
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?
|
||||||
|
|
||||||
|
While mock objects help you remove unnecessary dependencies in tests and make
|
||||||
|
them fast and reliable, using mocks manually in C++ is *hard*:
|
||||||
|
|
||||||
|
* Someone has to implement the mocks. The job is usually tedious and
|
||||||
|
error-prone. No wonder people go great distance to avoid it.
|
||||||
|
* The quality of those manually written mocks is a bit, uh, unpredictable. You
|
||||||
|
may see some really polished ones, but you may also see some that were
|
||||||
|
hacked up in a hurry and have all sorts of ad hoc restrictions.
|
||||||
|
* The knowledge you gained from using one mock doesn't transfer to the next
|
||||||
|
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.
|
||||||
|
|
||||||
|
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
|
||||||
|
following problems is bothering you:
|
||||||
|
|
||||||
|
* You are stuck with a sub-optimal design and wish you had done more
|
||||||
|
prototyping before it was too late, but prototyping in C++ is by no means
|
||||||
|
"rapid".
|
||||||
|
* Your tests are slow as they depend on too many libraries or use expensive
|
||||||
|
resources (e.g. a database).
|
||||||
|
* Your tests are brittle as some resources they use are unreliable (e.g. the
|
||||||
|
network).
|
||||||
|
* You want to test how your code handles a failure (e.g. a file checksum
|
||||||
|
error), but it's not easy to cause one.
|
||||||
|
* You need to make sure that your module interacts with other modules in the
|
||||||
|
right way, but it's hard to observe the interaction; therefore you resort to
|
||||||
|
observing the side effects at the end of the action, but it's awkward at
|
||||||
|
best.
|
||||||
|
* You want to "mock out" your dependencies, except that they don't have mock
|
||||||
|
implementations yet; and, frankly, you aren't thrilled by some of those
|
||||||
|
hand-written mocks.
|
||||||
|
|
||||||
|
We encourage you to use gMock as
|
||||||
|
|
||||||
|
* a *design* tool, for it lets you experiment with your interface design early
|
||||||
|
and often. More iterations lead to better designs!
|
||||||
|
* a *testing* tool to cut your tests' outbound dependencies and probe the
|
||||||
|
interaction between your module and its collaborators.
|
||||||
|
|
||||||
|
### Getting Started
|
||||||
|
|
||||||
|
gMock is bundled with googletest.
|
||||||
|
|
||||||
|
### 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
|
||||||
|
API for drawing. How would you test that it does the right thing? Well, you can
|
||||||
|
run it and compare the screen with a golden screen snapshot, but let's admit it:
|
||||||
|
tests like this are expensive to run and fragile (What if you just upgraded to a
|
||||||
|
shiny new graphics card that has better anti-aliasing? Suddenly you have to
|
||||||
|
update all your golden images.). It would be too painful if all your tests are
|
||||||
|
like this. Fortunately, you learned about
|
||||||
|
[Dependency Injection](http://en.wikipedia.org/wiki/Dependency_injection) and know the right thing
|
||||||
|
to do: instead of having your application talk to the system API directly, wrap
|
||||||
|
the API in an interface (say, `Turtle`) and code to that interface:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Turtle {
|
||||||
|
...
|
||||||
|
virtual ~Turtle() {};
|
||||||
|
virtual void PenUp() = 0;
|
||||||
|
virtual void PenDown() = 0;
|
||||||
|
virtual void Forward(int distance) = 0;
|
||||||
|
virtual void Turn(int degrees) = 0;
|
||||||
|
virtual void GoTo(int x, int y) = 0;
|
||||||
|
virtual int GetX() const = 0;
|
||||||
|
virtual int GetY() const = 0;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
(Note that the destructor of `Turtle` **must** be virtual, as is the case for
|
||||||
|
**all** classes you intend to inherit from - otherwise the destructor of the
|
||||||
|
derived class will not be called when you delete an object through a base
|
||||||
|
pointer, and you'll get corrupted program states like memory leaks.)
|
||||||
|
|
||||||
|
You can control whether the turtle's movement will leave a trace using `PenUp()`
|
||||||
|
and `PenDown()`, and control its movement using `Forward()`, `Turn()`, and
|
||||||
|
`GoTo()`. Finally, `GetX()` and `GetY()` tell you the current position of the
|
||||||
|
turtle.
|
||||||
|
|
||||||
|
Your program will normally use a real implementation of this interface. In
|
||||||
|
tests, you can use a mock implementation instead. This allows you to easily
|
||||||
|
check what drawing primitives your program is calling, with what arguments, and
|
||||||
|
in which order. Tests written this way are much more robust (they won't break
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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),
|
||||||
|
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
|
||||||
|
into the macro, and add two commas - one between the return type and the
|
||||||
|
name, another between the name and the argument list.
|
||||||
|
* If you're mocking a const method, add a 4th parameter containing `(const)`
|
||||||
|
(the parentheses are required).
|
||||||
|
* Since you're overriding a virtual method, we suggest adding the `override`
|
||||||
|
keyword. For const methods the 4th parameter becomes `(const, override)`,
|
||||||
|
for non-const methods just `(override)`. This isn't mandatory.
|
||||||
|
* Repeat until all virtual functions you want to mock are done. (It goes
|
||||||
|
without saying that *all* pure virtual methods in your abstract class must
|
||||||
|
be either mocked or overridden.)
|
||||||
|
|
||||||
|
After the process, you should have something like:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include "gmock/gmock.h" // Brings in gMock.
|
||||||
|
|
||||||
|
class MockTurtle : public Turtle {
|
||||||
|
public:
|
||||||
|
...
|
||||||
|
MOCK_METHOD(void, PenUp, (), (override));
|
||||||
|
MOCK_METHOD(void, PenDown, (), (override));
|
||||||
|
MOCK_METHOD(void, Forward, (int distance), (override));
|
||||||
|
MOCK_METHOD(void, Turn, (int degrees), (override));
|
||||||
|
MOCK_METHOD(void, GoTo, (int x, int y), (override));
|
||||||
|
MOCK_METHOD(int, GetX, (), (const, override));
|
||||||
|
MOCK_METHOD(int, GetY, (), (const, override));
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
(say, `Foo`) is owned by the same person or team. Otherwise, when the owner of
|
||||||
|
`Foo` changes it, your test could break. (You can't really expect `Foo`'s
|
||||||
|
maintainer to fix every test that uses `Foo`, can you?)
|
||||||
|
|
||||||
|
So, the rule of thumb is: if you need to mock `Foo` and it's owned by others,
|
||||||
|
define the mock class in `Foo`'s package (better, in a `testing` sub-package
|
||||||
|
such that you can clearly separate production code and testing utilities), put
|
||||||
|
it in a `.h` and a `cc_library`. Then everyone can reference them from their
|
||||||
|
tests. If `Foo` ever changes, there is only one copy of `MockFoo` to change, and
|
||||||
|
only tests that depend on the changed methods need to be fixed.
|
||||||
|
|
||||||
|
Another way to do it: you can introduce a thin layer `FooAdaptor` on top of
|
||||||
|
`Foo` and code to this new interface. Since you own `FooAdaptor`, you can absorb
|
||||||
|
changes in `Foo` much more easily. While this is more work initially, carefully
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
namespaces are a good idea.
|
||||||
|
2. Create some mock objects.
|
||||||
|
3. Specify your expectations on them (How many times will a method be called?
|
||||||
|
With what arguments? What should it do? etc.).
|
||||||
|
4. Exercise some code that uses the mocks; optionally, check the result using
|
||||||
|
googletest assertions. If a mock method is called more than expected or with
|
||||||
|
wrong arguments, you'll get an error immediately.
|
||||||
|
5. When a mock is destructed, gMock will automatically check whether all
|
||||||
|
expectations on it have been satisfied.
|
||||||
|
|
||||||
|
Here's an example:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include "path/to/mock-turtle.h"
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
using ::testing::AtLeast; // #1
|
||||||
|
|
||||||
|
TEST(PainterTest, CanDrawSomething) {
|
||||||
|
MockTurtle turtle; // #2
|
||||||
|
EXPECT_CALL(turtle, PenDown()) // #3
|
||||||
|
.Times(AtLeast(1));
|
||||||
|
|
||||||
|
Painter painter(&turtle); // #4
|
||||||
|
|
||||||
|
EXPECT_TRUE(painter.DrawCircle(0, 0, 10)); // #5
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
As you might have guessed, this test checks that `PenDown()` is called at least
|
||||||
|
once. If the `painter` object didn't call this method, your test will fail with
|
||||||
|
a message like this:
|
||||||
|
|
||||||
|
```text
|
||||||
|
path/to/my_test.cc:119: Failure
|
||||||
|
Actual function call count doesn't match this expectation:
|
||||||
|
Actually: never called;
|
||||||
|
Expected: called at least once.
|
||||||
|
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 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
|
||||||
|
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.
|
||||||
|
|
||||||
|
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?
|
||||||
|
Well, specifying the expectation beforehand allows gMock to report a violation
|
||||||
|
as soon as it rises, when the context (stack trace, etc) is still available.
|
||||||
|
This makes debugging much easier.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
of unrelated changes. If you set them too loose, bugs can slip through. You want
|
||||||
|
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
|
||||||
|
|
||||||
|
In gMock we use the `EXPECT_CALL()` macro to set an expectation on a mock
|
||||||
|
method. The general syntax is:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
EXPECT_CALL(mock_object, method(matchers))
|
||||||
|
.Times(cardinality)
|
||||||
|
.WillOnce(action)
|
||||||
|
.WillRepeatedly(action);
|
||||||
|
```
|
||||||
|
|
||||||
|
The macro has two arguments: first the mock object, and then the method and its
|
||||||
|
arguments. Note that the two are separated by a comma (`,`), not a period (`.`).
|
||||||
|
(Why using a comma? The answer is that it was necessary for technical reasons.)
|
||||||
|
If the method is not overloaded, the macro can also be called without matchers:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
EXPECT_CALL(mock_object, non-overloaded-method)
|
||||||
|
.Times(cardinality)
|
||||||
|
.WillOnce(action)
|
||||||
|
.WillRepeatedly(action);
|
||||||
|
```
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
the coming sections.
|
||||||
|
|
||||||
|
This syntax is designed to make an expectation read like English. For example,
|
||||||
|
you can probably guess that
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using ::testing::Return;
|
||||||
|
...
|
||||||
|
EXPECT_CALL(turtle, GetX())
|
||||||
|
.Times(5)
|
||||||
|
.WillOnce(Return(100))
|
||||||
|
.WillOnce(Return(150))
|
||||||
|
.WillRepeatedly(Return(200));
|
||||||
|
```
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
|
**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
|
||||||
|
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?
|
||||||
|
|
||||||
|
When a mock function takes arguments, we may specify what arguments we are
|
||||||
|
expecting, for example:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Expects the turtle to move forward by 100 units.
|
||||||
|
EXPECT_CALL(turtle, Forward(100));
|
||||||
|
```
|
||||||
|
|
||||||
|
Oftentimes you do not want to be too specific. Remember that talk about tests
|
||||||
|
being too rigid? Over specification leads to brittle tests and obscures the
|
||||||
|
intent of tests. Therefore we encourage you to specify only what's necessary—no
|
||||||
|
more, no less. If you aren't interested in the value of an argument, write `_`
|
||||||
|
as the argument, which means "anything goes":
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using ::testing::_;
|
||||||
|
...
|
||||||
|
// Expects that the turtle jumps to somewhere on the x=50 line.
|
||||||
|
EXPECT_CALL(turtle, GoTo(50, _));
|
||||||
|
```
|
||||||
|
|
||||||
|
`_` is an instance of what we call **matchers**. A matcher is like a predicate
|
||||||
|
and can test whether an argument is what we'd expect. You can use a matcher
|
||||||
|
inside `EXPECT_CALL()` wherever a function argument is expected. `_` is a
|
||||||
|
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:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using ::testing::Ge;
|
||||||
|
...
|
||||||
|
// Expects the turtle moves forward by at least 100.
|
||||||
|
EXPECT_CALL(turtle, Forward(Ge(100)));
|
||||||
|
```
|
||||||
|
|
||||||
|
If you don't care about *any* arguments, rather than specify `_` for each of
|
||||||
|
them you may instead omit the parameter list:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// Expects the turtle to move forward.
|
||||||
|
EXPECT_CALL(turtle, Forward);
|
||||||
|
// Expects the turtle to jump somewhere.
|
||||||
|
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).
|
||||||
|
|
||||||
|
#### 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
|
||||||
|
occur. It allows us to repeat an expectation many times without actually writing
|
||||||
|
it as many times. More importantly, a cardinality can be "fuzzy", just like a
|
||||||
|
matcher can be. This allows a user to express the intent of a test exactly.
|
||||||
|
|
||||||
|
An interesting special case is when we say `Times(0)`. You may have guessed - it
|
||||||
|
means that the function shouldn't be called with the given arguments at all, and
|
||||||
|
gMock will report a googletest failure whenever the function is (wrongfully)
|
||||||
|
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).
|
||||||
|
|
||||||
|
The `Times()` clause can be omitted. **If you omit `Times()`, gMock will infer
|
||||||
|
the cardinality for you.** The rules are easy to remember:
|
||||||
|
|
||||||
|
* If **neither** `WillOnce()` **nor** `WillRepeatedly()` is in the
|
||||||
|
`EXPECT_CALL()`, the inferred cardinality is `Times(1)`.
|
||||||
|
* If there are *n* `WillOnce()`'s but **no** `WillRepeatedly()`, where *n* >=
|
||||||
|
1, the cardinality is `Times(n)`.
|
||||||
|
* If there are *n* `WillOnce()`'s and **one** `WillRepeatedly()`, where *n* >=
|
||||||
|
0, the cardinality is `Times(AtLeast(n))`.
|
||||||
|
|
||||||
|
**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?
|
||||||
|
|
||||||
|
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
|
||||||
|
gMock.
|
||||||
|
|
||||||
|
First, if the return type of a mock function is a built-in type or a pointer,
|
||||||
|
the function has a **default action** (a `void` function will just return, a
|
||||||
|
`bool` function will return `false`, and other functions will return 0). In
|
||||||
|
addition, in C++ 11 and above, a mock function whose return type is
|
||||||
|
default-constructible (i.e. has a default constructor) has a default action of
|
||||||
|
returning a default-constructed value. If you don't say anything, this behavior
|
||||||
|
will be used.
|
||||||
|
|
||||||
|
Second, if a mock function doesn't have a default action, or the default action
|
||||||
|
doesn't suit you, you can specify the action to be taken each time the
|
||||||
|
expectation matches using a series of `WillOnce()` clauses followed by an
|
||||||
|
optional `WillRepeatedly()`. For example,
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using ::testing::Return;
|
||||||
|
...
|
||||||
|
EXPECT_CALL(turtle, GetX())
|
||||||
|
.WillOnce(Return(100))
|
||||||
|
.WillOnce(Return(200))
|
||||||
|
.WillOnce(Return(300));
|
||||||
|
```
|
||||||
|
|
||||||
|
says that `turtle.GetX()` will be called *exactly three times* (gMock inferred
|
||||||
|
this from how many `WillOnce()` clauses we've written, since we didn't
|
||||||
|
explicitly write `Times()`), and will return 100, 200, and 300 respectively.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using ::testing::Return;
|
||||||
|
...
|
||||||
|
EXPECT_CALL(turtle, GetY())
|
||||||
|
.WillOnce(Return(100))
|
||||||
|
.WillOnce(Return(200))
|
||||||
|
.WillRepeatedly(Return(300));
|
||||||
|
```
|
||||||
|
|
||||||
|
says that `turtle.GetY()` will be called *at least twice* (gMock knows this as
|
||||||
|
we've written two `WillOnce()` clauses and a `WillRepeatedly()` while having no
|
||||||
|
explicit `Times()`), will return 100 and 200 respectively the first two times,
|
||||||
|
and 300 from the third time on.
|
||||||
|
|
||||||
|
Of course, if you explicitly write a `Times()`, gMock will not try to infer the
|
||||||
|
cardinality itself. What if the number you specified is larger than there are
|
||||||
|
`WillOnce()` clauses? Well, after all `WillOnce()`s are used up, gMock will do
|
||||||
|
the *default* action for the function every time (unless, of course, you have a
|
||||||
|
`WillRepeatedly()`.).
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
|
**Important note:** The `EXPECT_CALL()` statement evaluates the action clause
|
||||||
|
only once, even though the action may be performed many times. Therefore you
|
||||||
|
must be careful about side effects. The following may not do what you want:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using ::testing::Return;
|
||||||
|
...
|
||||||
|
int n = 100;
|
||||||
|
EXPECT_CALL(turtle, GetX())
|
||||||
|
.Times(4)
|
||||||
|
.WillRepeatedly(Return(n++));
|
||||||
|
```
|
||||||
|
|
||||||
|
Instead of returning 100, 101, 102, ..., consecutively, this mock function will
|
||||||
|
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 -->).
|
||||||
|
|
||||||
|
Time for another quiz! What do you think the following means?
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using ::testing::Return;
|
||||||
|
...
|
||||||
|
EXPECT_CALL(turtle, GetY())
|
||||||
|
.Times(4)
|
||||||
|
.WillOnce(Return(100));
|
||||||
|
```
|
||||||
|
|
||||||
|
Obviously `turtle.GetY()` is expected to be called four times. But if you think
|
||||||
|
it will return 100 every time, think twice! Remember that one `WillOnce()`
|
||||||
|
clause will be consumed each time the function is invoked and the default action
|
||||||
|
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}
|
||||||
|
|
||||||
|
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
|
||||||
|
from multiple mock objects.
|
||||||
|
|
||||||
|
By default, when a mock method is invoked, gMock will search the expectations in
|
||||||
|
the **reverse order** they are defined, and stop when an active expectation that
|
||||||
|
matches the arguments is found (you can think of it as "newer rules override
|
||||||
|
older ones."). If the matching expectation cannot take any more calls, you will
|
||||||
|
get an upper-bound-violated failure. Here's an example:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using ::testing::_;
|
||||||
|
...
|
||||||
|
EXPECT_CALL(turtle, Forward(_)); // #1
|
||||||
|
EXPECT_CALL(turtle, Forward(10)) // #2
|
||||||
|
.Times(2);
|
||||||
|
```
|
||||||
|
|
||||||
|
If `Forward(10)` is called three times in a row, the third time it will be an
|
||||||
|
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.
|
||||||
|
|
||||||
|
**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
|
||||||
|
and then customize the mock by writing more specific expectations in the test
|
||||||
|
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.
|
||||||
|
|
||||||
|
**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).
|
||||||
|
|
||||||
|
#### 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
|
||||||
|
order the expectations are specified.
|
||||||
|
|
||||||
|
Sometimes, you may want all the expected calls to occur in a strict order. To
|
||||||
|
say this in gMock is easy:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using ::testing::InSequence;
|
||||||
|
...
|
||||||
|
TEST(FooTest, DrawsLineSegment) {
|
||||||
|
...
|
||||||
|
{
|
||||||
|
InSequence seq;
|
||||||
|
|
||||||
|
EXPECT_CALL(turtle, PenDown());
|
||||||
|
EXPECT_CALL(turtle, Forward(100));
|
||||||
|
EXPECT_CALL(turtle, PenUp());
|
||||||
|
}
|
||||||
|
Foo();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
By creating an object of type `InSequence`, all expectations in its scope are
|
||||||
|
put into a *sequence* and have to occur *sequentially*. Since we are just
|
||||||
|
relying on the constructor and destructor of this object to do the actual work,
|
||||||
|
its name is really irrelevant.
|
||||||
|
|
||||||
|
In this example, we test that `Foo()` calls the three expected functions in the
|
||||||
|
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).)
|
||||||
|
|
||||||
|
#### 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*
|
||||||
|
(you want to ignore any other instructions it receives)?
|
||||||
|
|
||||||
|
After you've come up with your answer, take a look at ours and compare notes
|
||||||
|
(solve it yourself first - don't cheat!):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using ::testing::_;
|
||||||
|
using ::testing::AnyNumber;
|
||||||
|
...
|
||||||
|
EXPECT_CALL(turtle, GoTo(_, _)) // #1
|
||||||
|
.Times(AnyNumber());
|
||||||
|
EXPECT_CALL(turtle, GoTo(0, 0)) // #2
|
||||||
|
.Times(2);
|
||||||
|
```
|
||||||
|
|
||||||
|
Suppose `turtle.GoTo(0, 0)` is called three times. In the third time, gMock will
|
||||||
|
see that the arguments match expectation #2 (remember that we always pick the
|
||||||
|
last matching expectation). Now, since we said that there should be only two
|
||||||
|
such calls, gMock will report an error immediately. This is basically what we've
|
||||||
|
told you in the [Using Multiple Expectations](#MultiExpectations) section above.
|
||||||
|
|
||||||
|
This example shows that **expectations in gMock are "sticky" by default**, in
|
||||||
|
the sense that they remain active even after we have reached their invocation
|
||||||
|
upper bounds. This is an important rule to remember, as it affects the meaning
|
||||||
|
of the spec, and is **different** to how it's done in many other mocking
|
||||||
|
frameworks (Why'd we do that? Because we think our rule makes the common cases
|
||||||
|
easier to express and understand.).
|
||||||
|
|
||||||
|
Simple? Let's see if you've really understood it: what does the following code
|
||||||
|
say?
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using ::testing::Return;
|
||||||
|
...
|
||||||
|
for (int i = n; i > 0; i--) {
|
||||||
|
EXPECT_CALL(turtle, GetX())
|
||||||
|
.WillOnce(Return(10*i));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you think it says that `turtle.GetX()` will be called `n` times and will
|
||||||
|
return 10, 20, 30, ..., consecutively, think twice! The problem is that, as we
|
||||||
|
said, expectations are sticky. So, the second time `turtle.GetX()` is called,
|
||||||
|
the last (latest) `EXPECT_CALL()` statement will match, and will immediately
|
||||||
|
lead to an "upper bound violated" error - this piece of code is not very useful!
|
||||||
|
|
||||||
|
One correct way of saying that `turtle.GetX()` will return 10, 20, 30, ..., is
|
||||||
|
to explicitly say that the expectations are *not* sticky. In other words, they
|
||||||
|
should *retire* as soon as they are saturated:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using ::testing::Return;
|
||||||
|
...
|
||||||
|
for (int i = n; i > 0; i--) {
|
||||||
|
EXPECT_CALL(turtle, GetX())
|
||||||
|
.WillOnce(Return(10*i))
|
||||||
|
.RetiresOnSaturation();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
And, there's a better way to do it: in this case, we expect the calls to occur
|
||||||
|
in a specific order, and we line up the actions to match the order. Since the
|
||||||
|
order is important here, we should make it explicit using a sequence:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using ::testing::InSequence;
|
||||||
|
using ::testing::Return;
|
||||||
|
...
|
||||||
|
{
|
||||||
|
InSequence s;
|
||||||
|
|
||||||
|
for (int i = 1; i <= n; i++) {
|
||||||
|
EXPECT_CALL(turtle, GetX())
|
||||||
|
.WillOnce(Return(10*i))
|
||||||
|
.RetiresOnSaturation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
By the way, the other situation where an expectation may *not* be sticky is when
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
`GetY()` get called.
|
||||||
|
|
||||||
|
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).
|
396
test/gtest-1.10.0/googlemock/docs/gmock_faq.md
Normal file
396
test/gtest-1.10.0/googlemock/docs/gmock_faq.md
Normal file
@@ -0,0 +1,396 @@
|
|||||||
|
## Legacy gMock FAQ {#GMockFaq}
|
||||||
|
|
||||||
|
<!-- GOOGLETEST_CM0021 DO NOT DELETE -->
|
||||||
|
|
||||||
|
### 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).
|
||||||
|
|
||||||
|
### Can I mock a variadic function?
|
||||||
|
|
||||||
|
You cannot mock a variadic function (i.e. a function taking ellipsis (`...`)
|
||||||
|
arguments) directly in gMock.
|
||||||
|
|
||||||
|
The problem is that in general, there is *no way* for a mock object to know how
|
||||||
|
many arguments are passed to the variadic method, and what the arguments' types
|
||||||
|
are. Only the *author of the base class* knows the protocol, and we cannot look
|
||||||
|
into his or her head.
|
||||||
|
|
||||||
|
Therefore, to mock such a function, the *user* must teach the mock object how to
|
||||||
|
figure out the number of arguments and their types. One way to do it is to
|
||||||
|
provide overloaded versions of the function.
|
||||||
|
|
||||||
|
Ellipsis arguments are inherited from C and not really a C++ feature. They are
|
||||||
|
unsafe to use and don't work with arguments that have constructors or
|
||||||
|
destructors. Therefore we recommend to avoid them in C++ as much as possible.
|
||||||
|
|
||||||
|
### MSVC gives me warning C4301 or C4373 when I define a mock method with a const parameter. Why?
|
||||||
|
|
||||||
|
If you compile this using Microsoft Visual C++ 2005 SP1:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Foo {
|
||||||
|
...
|
||||||
|
virtual void Bar(const int i) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MockFoo : public Foo {
|
||||||
|
...
|
||||||
|
MOCK_METHOD(void, Bar, (const int i), (override));
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
You may get the following warning:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
warning C4301: 'MockFoo::Bar': overriding virtual function only differs from 'Foo::Bar' by const/volatile qualifier
|
||||||
|
```
|
||||||
|
|
||||||
|
This is a MSVC bug. The same code compiles fine with gcc, for example. If you
|
||||||
|
use Visual C++ 2008 SP1, you would get the warning:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
warning C4373: 'MockFoo::Bar': virtual function overrides 'Foo::Bar', previous versions of the compiler did not override when parameters only differed by const/volatile qualifiers
|
||||||
|
```
|
||||||
|
|
||||||
|
In C++, if you *declare* a function with a `const` parameter, the `const`
|
||||||
|
modifier is ignored. Therefore, the `Foo` base class above is equivalent to:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Foo {
|
||||||
|
...
|
||||||
|
virtual void Bar(int i) = 0; // int or const int? Makes no difference.
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
In fact, you can *declare* `Bar()` with an `int` parameter, and define it with a
|
||||||
|
`const int` parameter. The compiler will still match them up.
|
||||||
|
|
||||||
|
Since making a parameter `const` is meaningless in the method declaration, we
|
||||||
|
recommend to remove it in both `Foo` and `MockFoo`. That should workaround the
|
||||||
|
VC bug.
|
||||||
|
|
||||||
|
Note that we are talking about the *top-level* `const` modifier here. If the
|
||||||
|
function parameter is passed by pointer or reference, declaring the pointee or
|
||||||
|
referee as `const` is still meaningful. For example, the following two
|
||||||
|
declarations are *not* equivalent:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
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
|
||||||
|
gMock print a trace of every mock function call it receives. By studying the
|
||||||
|
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,
|
||||||
|
unexpected calls on mocks without default actions don't print out a detailed
|
||||||
|
comparison between the actual arguments and the expected arguments.
|
||||||
|
|
||||||
|
### My program crashed and `ScopedMockLog` spit out tons of messages. Is it a gMock bug?
|
||||||
|
|
||||||
|
gMock and `ScopedMockLog` are likely doing the right thing here.
|
||||||
|
|
||||||
|
When a test crashes, the failure signal handler will try to log a lot of
|
||||||
|
information (the stack trace, and the address map, for example). The messages
|
||||||
|
are compounded if you have many threads with depth stacks. When `ScopedMockLog`
|
||||||
|
intercepts these messages and finds that they don't match any expectations, it
|
||||||
|
prints an error for each of them.
|
||||||
|
|
||||||
|
You can learn to ignore the errors, or you can rewrite your expectations to make
|
||||||
|
your test more robust, for example, by adding something like:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using ::testing::AnyNumber;
|
||||||
|
using ::testing::Not;
|
||||||
|
...
|
||||||
|
// Ignores any log not done by us.
|
||||||
|
EXPECT_CALL(log, Log(_, Not(EndsWith("/my_file.cc")), _))
|
||||||
|
.Times(AnyNumber());
|
||||||
|
```
|
||||||
|
|
||||||
|
### How can I assert that a function is NEVER called?
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using ::testing::_;
|
||||||
|
...
|
||||||
|
EXPECT_CALL(foo, Bar(_))
|
||||||
|
.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
|
||||||
|
arguments, the state of relevant expectations, and etc) to help the user debug.
|
||||||
|
If another failure is detected, gMock will do the same, including printing the
|
||||||
|
state of relevant expectations.
|
||||||
|
|
||||||
|
Sometimes an expectation's state didn't change between two failures, and you'll
|
||||||
|
see the same description of the state twice. They are however *not* redundant,
|
||||||
|
as they refer to *different points in time*. The fact they are the same *is*
|
||||||
|
interesting information.
|
||||||
|
|
||||||
|
### I get a heapcheck failure when using a mock object, but using a real object is fine. What can be wrong?
|
||||||
|
|
||||||
|
Does the class (hopefully a pure interface) you are mocking have a virtual
|
||||||
|
destructor?
|
||||||
|
|
||||||
|
Whenever you derive from a base class, make sure its destructor is virtual.
|
||||||
|
Otherwise Bad Things will happen. Consider the following code:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
class Base {
|
||||||
|
public:
|
||||||
|
// Not virtual, but should be.
|
||||||
|
~Base() { ... }
|
||||||
|
...
|
||||||
|
};
|
||||||
|
|
||||||
|
class Derived : public Base {
|
||||||
|
public:
|
||||||
|
...
|
||||||
|
private:
|
||||||
|
std::string value_;
|
||||||
|
};
|
||||||
|
|
||||||
|
...
|
||||||
|
Base* p = new Derived;
|
||||||
|
...
|
||||||
|
delete p; // Surprise! ~Base() will be called, but ~Derived() will not
|
||||||
|
// - value_ is leaked.
|
||||||
|
```
|
||||||
|
|
||||||
|
By changing `~Base()` to virtual, `~Derived()` will be correctly called when
|
||||||
|
`delete p` is executed, and the heap checker will be happy.
|
||||||
|
|
||||||
|
### The "newer expectations override older ones" rule makes writing expectations awkward. Why does gMock do that?
|
||||||
|
|
||||||
|
When people complain about this, often they are referring to code like:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using ::testing::Return;
|
||||||
|
...
|
||||||
|
// foo.Bar() should be called twice, return 1 the first time, and return
|
||||||
|
// 2 the second time. However, I have to write the expectations in the
|
||||||
|
// reverse order. This sucks big time!!!
|
||||||
|
EXPECT_CALL(foo, Bar())
|
||||||
|
.WillOnce(Return(2))
|
||||||
|
.RetiresOnSaturation();
|
||||||
|
EXPECT_CALL(foo, Bar())
|
||||||
|
.WillOnce(Return(1))
|
||||||
|
.RetiresOnSaturation();
|
||||||
|
```
|
||||||
|
|
||||||
|
The problem, is that they didn't pick the **best** way to express the test's
|
||||||
|
intent.
|
||||||
|
|
||||||
|
By default, expectations don't have to be matched in *any* particular order. If
|
||||||
|
you want them to match in a certain order, you need to be explicit. This is
|
||||||
|
gMock's (and jMock's) fundamental philosophy: it's easy to accidentally
|
||||||
|
over-specify your tests, and we want to make it harder to do so.
|
||||||
|
|
||||||
|
There are two better ways to write the test spec. You could either put the
|
||||||
|
expectations in sequence:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using ::testing::Return;
|
||||||
|
...
|
||||||
|
// foo.Bar() should be called twice, return 1 the first time, and return
|
||||||
|
// 2 the second time. Using a sequence, we can write the expectations
|
||||||
|
// in their natural order.
|
||||||
|
{
|
||||||
|
InSequence s;
|
||||||
|
EXPECT_CALL(foo, Bar())
|
||||||
|
.WillOnce(Return(1))
|
||||||
|
.RetiresOnSaturation();
|
||||||
|
EXPECT_CALL(foo, Bar())
|
||||||
|
.WillOnce(Return(2))
|
||||||
|
.RetiresOnSaturation();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
or you can put the sequence of actions in the same expectation:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using ::testing::Return;
|
||||||
|
...
|
||||||
|
// foo.Bar() should be called twice, return 1 the first time, and return
|
||||||
|
// 2 the second time.
|
||||||
|
EXPECT_CALL(foo, Bar())
|
||||||
|
.WillOnce(Return(1))
|
||||||
|
.WillOnce(Return(2))
|
||||||
|
.RetiresOnSaturation();
|
||||||
|
```
|
||||||
|
|
||||||
|
Back to the original questions: why does gMock search the expectations (and
|
||||||
|
`ON_CALL`s) from back to front? Because this allows a user to set up a mock's
|
||||||
|
behavior for the common case early (e.g. in the mock's constructor or the test
|
||||||
|
fixture's set-up phase) and customize it with more specific rules later. If
|
||||||
|
gMock searches from front to back, this very useful pattern won't be possible.
|
||||||
|
|
||||||
|
### gMock prints a warning when a function without EXPECT_CALL is called, even if I have set its behavior using ON_CALL. Would it be reasonable not to show the warning in this case?
|
||||||
|
|
||||||
|
When choosing between being neat and being safe, we lean toward the latter. So
|
||||||
|
the answer is that we think it's better to show the warning.
|
||||||
|
|
||||||
|
Often people write `ON_CALL`s in the mock object's constructor or `SetUp()`, as
|
||||||
|
the default behavior rarely changes from test to test. Then in the test body
|
||||||
|
they set the expectations, which are often different for each test. Having an
|
||||||
|
`ON_CALL` in the set-up part of a test doesn't mean that the calls are expected.
|
||||||
|
If there's no `EXPECT_CALL` and the method is called, it's possibly an error. If
|
||||||
|
we quietly let the call go through without notifying the user, bugs may creep in
|
||||||
|
unnoticed.
|
||||||
|
|
||||||
|
If, however, you are sure that the calls are OK, you can write
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using ::testing::_;
|
||||||
|
...
|
||||||
|
EXPECT_CALL(foo, Bar(_))
|
||||||
|
.WillRepeatedly(...);
|
||||||
|
```
|
||||||
|
|
||||||
|
instead of
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using ::testing::_;
|
||||||
|
...
|
||||||
|
ON_CALL(foo, Bar(_))
|
||||||
|
.WillByDefault(...);
|
||||||
|
```
|
||||||
|
|
||||||
|
This tells gMock that you do expect the calls and no warning should be printed.
|
||||||
|
|
||||||
|
Also, you can control the verbosity by specifying `--gmock_verbose=error`. Other
|
||||||
|
values are `info` and `warning`. If you find the output too noisy when
|
||||||
|
debugging, just choose a less verbose level.
|
||||||
|
|
||||||
|
### How can I delete the mock function's argument in an action?
|
||||||
|
|
||||||
|
If your mock function takes a pointer argument and you want to delete that
|
||||||
|
argument, you can use testing::DeleteArg<N>() to delete the N'th (zero-indexed)
|
||||||
|
argument:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using ::testing::_;
|
||||||
|
...
|
||||||
|
MOCK_METHOD(void, Bar, (X* x, const Y& y));
|
||||||
|
...
|
||||||
|
EXPECT_CALL(mock_foo_, Bar(_, _))
|
||||||
|
.WillOnce(testing::DeleteArg<0>()));
|
||||||
|
```
|
||||||
|
|
||||||
|
### How can I perform an arbitrary action on a mock function's argument?
|
||||||
|
|
||||||
|
If you find yourself needing to perform some action that's not supported by
|
||||||
|
gMock directly, remember that you can define your own actions using
|
||||||
|
[`MakeAction()`](#NewMonoActions) or
|
||||||
|
[`MakePolymorphicAction()`](#NewPolyActions), or you can write a stub function
|
||||||
|
and invoke it using [`Invoke()`](#FunctionsAsActions).
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
using ::testing::_;
|
||||||
|
using ::testing::Invoke;
|
||||||
|
...
|
||||||
|
MOCK_METHOD(void, Bar, (X* p));
|
||||||
|
...
|
||||||
|
EXPECT_CALL(mock_foo_, Bar(_))
|
||||||
|
.WillOnce(Invoke(MyAction(...)));
|
||||||
|
```
|
||||||
|
|
||||||
|
### My code calls a static/global function. Can I mock it?
|
||||||
|
|
||||||
|
You can, but you need to make some changes.
|
||||||
|
|
||||||
|
In general, if you find yourself needing to mock a static function, it's a sign
|
||||||
|
that your modules are too tightly coupled (and less flexible, less reusable,
|
||||||
|
less testable, etc). You are probably better off defining a small interface and
|
||||||
|
call the function through that interface, which then can be easily mocked. It's
|
||||||
|
a bit of work initially, but usually pays for itself quickly.
|
||||||
|
|
||||||
|
This Google Testing Blog
|
||||||
|
[post](https://testing.googleblog.com/2008/06/defeat-static-cling.html) says it
|
||||||
|
excellently. Check it out.
|
||||||
|
|
||||||
|
### My mock object needs to do complex stuff. It's a lot of pain to specify the actions. gMock sucks!
|
||||||
|
|
||||||
|
I know it's not a question, but you get an answer for free any way. :-)
|
||||||
|
|
||||||
|
With gMock, you can create mocks in C++ easily. And people might be tempted to
|
||||||
|
use them everywhere. Sometimes they work great, and sometimes you may find them,
|
||||||
|
well, a pain to use. So, what's wrong in the latter case?
|
||||||
|
|
||||||
|
When you write a test without using mocks, you exercise the code and assert that
|
||||||
|
it returns the correct value or that the system is in an expected state. This is
|
||||||
|
sometimes called "state-based testing".
|
||||||
|
|
||||||
|
Mocks are great for what some call "interaction-based" testing: instead of
|
||||||
|
checking the system state at the very end, mock objects verify that they are
|
||||||
|
invoked the right way and report an error as soon as it arises, giving you a
|
||||||
|
handle on the precise context in which the error was triggered. This is often
|
||||||
|
more effective and economical to do than state-based testing.
|
||||||
|
|
||||||
|
If you are doing state-based testing and using a test double just to simulate
|
||||||
|
the real object, you are probably better off using a fake. Using a mock in this
|
||||||
|
case causes pain, as it's not a strong point for mocks to perform complex
|
||||||
|
actions. If you experience this and think that mocks suck, you are just not
|
||||||
|
using the right tool for your problem. Or, you might be trying to solve the
|
||||||
|
wrong problem. :-)
|
||||||
|
|
||||||
|
### I got a warning "Uninteresting function call encountered - default action taken.." Should I panic?
|
||||||
|
|
||||||
|
By all means, NO! It's just an FYI. :-)
|
||||||
|
|
||||||
|
What it means is that you have a mock function, you haven't set any expectations
|
||||||
|
on it (by gMock's rule this means that you are not interested in calls to this
|
||||||
|
function and therefore it can be called any number of times), and it is called.
|
||||||
|
That's OK - you didn't say it's not OK to call the function!
|
||||||
|
|
||||||
|
What if you actually meant to disallow this function to be called, but forgot to
|
||||||
|
write `EXPECT_CALL(foo, Bar()).Times(0)`? While one can argue that it's the
|
||||||
|
user's fault, gMock tries to be nice and prints you a note.
|
||||||
|
|
||||||
|
So, when you see the message and believe that there shouldn't be any
|
||||||
|
uninteresting calls, you should investigate what's going on. To make your life
|
||||||
|
easier, gMock dumps the stack trace when an uninteresting call is encountered.
|
||||||
|
From that you can figure out which mock function it is, and how it is called.
|
||||||
|
|
||||||
|
### I want to define a custom action. Should I use Invoke() or implement the ActionInterface interface?
|
||||||
|
|
||||||
|
Either way is fine - you want to choose the one that's more convenient for your
|
||||||
|
circumstance.
|
||||||
|
|
||||||
|
Usually, if your action is for a particular function type, defining it using
|
||||||
|
`Invoke()` should be easier; if your action can be used in functions of
|
||||||
|
different types (e.g. if you are defining `Return(*value*)`),
|
||||||
|
`MakePolymorphicAction()` is easiest. Sometimes you want precise control on what
|
||||||
|
types of functions the action can be used in, and implementing `ActionInterface`
|
||||||
|
is the way to go here. See the implementation of `Return()` in
|
||||||
|
`testing/base/public/gmock-actions.h` for an example.
|
||||||
|
|
||||||
|
### I use SetArgPointee() in WillOnce(), but gcc complains about "conflicting return type specified". What does it mean?
|
||||||
|
|
||||||
|
You got this error as gMock has no idea what value it should return when the
|
||||||
|
mock method is called. `SetArgPointee()` says what the side effect is, but
|
||||||
|
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.
|
||||||
|
|
||||||
|
### I have a huge mock class, and Microsoft Visual C++ runs out of memory when compiling it. What can I do?
|
||||||
|
|
||||||
|
We've noticed that when the `/clr` compiler flag is used, Visual C++ uses 5~6
|
||||||
|
times as much memory when compiling a mock class. We suggest to avoid `/clr`
|
||||||
|
when compiling native C++ mocks.
|
@@ -26,13 +26,14 @@
|
|||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
|
||||||
// Author: wan@google.com (Zhanyong Wan)
|
|
||||||
|
|
||||||
// Google Mock - a framework for writing C++ mock classes.
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
//
|
//
|
||||||
// This file implements some commonly used actions.
|
// This file implements some commonly used actions.
|
||||||
|
|
||||||
|
// GOOGLETEST_CM0002 DO NOT DELETE
|
||||||
|
|
||||||
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_
|
||||||
#define GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_
|
||||||
|
|
||||||
@@ -41,13 +42,18 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "gmock/internal/gmock-internal-utils.h"
|
#include "gmock/internal/gmock-internal-utils.h"
|
||||||
#include "gmock/internal/gmock-port.h"
|
#include "gmock/internal/gmock-port.h"
|
||||||
|
|
||||||
#if GTEST_HAS_STD_TYPE_TRAITS_ // Defined by gtest-port.h via gmock-port.h.
|
#ifdef _MSC_VER
|
||||||
#include <type_traits>
|
# pragma warning(push)
|
||||||
|
# pragma warning(disable:4100)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
@@ -63,9 +69,6 @@ namespace testing {
|
|||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template <typename F1, typename F2>
|
|
||||||
class ActionAdaptor;
|
|
||||||
|
|
||||||
// BuiltInDefaultValueGetter<T, true>::Get() returns a
|
// BuiltInDefaultValueGetter<T, true>::Get() returns a
|
||||||
// default-constructed T value. BuiltInDefaultValueGetter<T,
|
// default-constructed T value. BuiltInDefaultValueGetter<T,
|
||||||
// false>::Get() crashes with an error.
|
// false>::Get() crashes with an error.
|
||||||
@@ -96,8 +99,8 @@ struct BuiltInDefaultValueGetter<T, false> {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
class BuiltInDefaultValue {
|
class BuiltInDefaultValue {
|
||||||
public:
|
public:
|
||||||
#if GTEST_HAS_STD_TYPE_TRAITS_
|
// This function returns true if and only if type T has a built-in default
|
||||||
// This function returns true iff type T has a built-in default value.
|
// value.
|
||||||
static bool Exists() {
|
static bool Exists() {
|
||||||
return ::std::is_default_constructible<T>::value;
|
return ::std::is_default_constructible<T>::value;
|
||||||
}
|
}
|
||||||
@@ -106,18 +109,6 @@ class BuiltInDefaultValue {
|
|||||||
return BuiltInDefaultValueGetter<
|
return BuiltInDefaultValueGetter<
|
||||||
T, ::std::is_default_constructible<T>::value>::Get();
|
T, ::std::is_default_constructible<T>::value>::Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // GTEST_HAS_STD_TYPE_TRAITS_
|
|
||||||
// This function returns true iff type T has a built-in default value.
|
|
||||||
static bool Exists() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static T Get() {
|
|
||||||
return BuiltInDefaultValueGetter<T, false>::Get();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // GTEST_HAS_STD_TYPE_TRAITS_
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// This partial specialization says that we use the same built-in
|
// This partial specialization says that we use the same built-in
|
||||||
@@ -135,7 +126,7 @@ template <typename T>
|
|||||||
class BuiltInDefaultValue<T*> {
|
class BuiltInDefaultValue<T*> {
|
||||||
public:
|
public:
|
||||||
static bool Exists() { return true; }
|
static bool Exists() { return true; }
|
||||||
static T* Get() { return NULL; }
|
static T* Get() { return nullptr; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// The following specializations define the default values for
|
// The following specializations define the default values for
|
||||||
@@ -149,9 +140,6 @@ class BuiltInDefaultValue<T*> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(void, ); // NOLINT
|
GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(void, ); // NOLINT
|
||||||
#if GTEST_HAS_GLOBAL_STRING
|
|
||||||
GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(::string, "");
|
|
||||||
#endif // GTEST_HAS_GLOBAL_STRING
|
|
||||||
GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(::std::string, "");
|
GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(::std::string, "");
|
||||||
GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(bool, false);
|
GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(bool, false);
|
||||||
GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned char, '\0');
|
GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned char, '\0');
|
||||||
@@ -218,11 +206,11 @@ class DefaultValue {
|
|||||||
// Unsets the default value for type T.
|
// Unsets the default value for type T.
|
||||||
static void Clear() {
|
static void Clear() {
|
||||||
delete producer_;
|
delete producer_;
|
||||||
producer_ = NULL;
|
producer_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true iff the user has set the default value for type T.
|
// Returns true if and only if the user has set the default value for type T.
|
||||||
static bool IsSet() { return producer_ != NULL; }
|
static bool IsSet() { return producer_ != nullptr; }
|
||||||
|
|
||||||
// Returns true if T has a default return value set by the user or there
|
// Returns true if T has a default return value set by the user or there
|
||||||
// exists a built-in default value.
|
// exists a built-in default value.
|
||||||
@@ -234,8 +222,8 @@ class DefaultValue {
|
|||||||
// otherwise returns the built-in default value. Requires that Exists()
|
// otherwise returns the built-in default value. Requires that Exists()
|
||||||
// is true, which ensures that the return value is well-defined.
|
// is true, which ensures that the return value is well-defined.
|
||||||
static T Get() {
|
static T Get() {
|
||||||
return producer_ == NULL ?
|
return producer_ == nullptr ? internal::BuiltInDefaultValue<T>::Get()
|
||||||
internal::BuiltInDefaultValue<T>::Get() : producer_->Produce();
|
: producer_->Produce();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -248,7 +236,7 @@ class DefaultValue {
|
|||||||
class FixedValueProducer : public ValueProducer {
|
class FixedValueProducer : public ValueProducer {
|
||||||
public:
|
public:
|
||||||
explicit FixedValueProducer(T value) : value_(value) {}
|
explicit FixedValueProducer(T value) : value_(value) {}
|
||||||
virtual T Produce() { return value_; }
|
T Produce() override { return value_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const T value_;
|
const T value_;
|
||||||
@@ -259,7 +247,7 @@ class DefaultValue {
|
|||||||
public:
|
public:
|
||||||
explicit FactoryValueProducer(FactoryFunction factory)
|
explicit FactoryValueProducer(FactoryFunction factory)
|
||||||
: factory_(factory) {}
|
: factory_(factory) {}
|
||||||
virtual T Produce() { return factory_(); }
|
T Produce() override { return factory_(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const FactoryFunction factory_;
|
const FactoryFunction factory_;
|
||||||
@@ -280,12 +268,10 @@ class DefaultValue<T&> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unsets the default value for type T&.
|
// Unsets the default value for type T&.
|
||||||
static void Clear() {
|
static void Clear() { address_ = nullptr; }
|
||||||
address_ = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true iff the user has set the default value for type T&.
|
// Returns true if and only if the user has set the default value for type T&.
|
||||||
static bool IsSet() { return address_ != NULL; }
|
static bool IsSet() { return address_ != nullptr; }
|
||||||
|
|
||||||
// Returns true if T has a default return value set by the user or there
|
// Returns true if T has a default return value set by the user or there
|
||||||
// exists a built-in default value.
|
// exists a built-in default value.
|
||||||
@@ -297,8 +283,8 @@ class DefaultValue<T&> {
|
|||||||
// otherwise returns the built-in default value if there is one;
|
// otherwise returns the built-in default value if there is one;
|
||||||
// otherwise aborts the process.
|
// otherwise aborts the process.
|
||||||
static T& Get() {
|
static T& Get() {
|
||||||
return address_ == NULL ?
|
return address_ == nullptr ? internal::BuiltInDefaultValue<T&>::Get()
|
||||||
internal::BuiltInDefaultValue<T&>::Get() : *address_;
|
: *address_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -316,11 +302,11 @@ class DefaultValue<void> {
|
|||||||
|
|
||||||
// Points to the user-set default value for type T.
|
// Points to the user-set default value for type T.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename DefaultValue<T>::ValueProducer* DefaultValue<T>::producer_ = NULL;
|
typename DefaultValue<T>::ValueProducer* DefaultValue<T>::producer_ = nullptr;
|
||||||
|
|
||||||
// Points to the user-set default value for type T&.
|
// Points to the user-set default value for type T&.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T* DefaultValue<T&>::address_ = NULL;
|
T* DefaultValue<T&>::address_ = nullptr;
|
||||||
|
|
||||||
// Implement this interface to define an action for function type F.
|
// Implement this interface to define an action for function type F.
|
||||||
template <typename F>
|
template <typename F>
|
||||||
@@ -345,38 +331,53 @@ class ActionInterface {
|
|||||||
// An Action<F> is a copyable and IMMUTABLE (except by assignment)
|
// An Action<F> is a copyable and IMMUTABLE (except by assignment)
|
||||||
// object that represents an action to be taken when a mock function
|
// object that represents an action to be taken when a mock function
|
||||||
// of type F is called. The implementation of Action<T> is just a
|
// of type F is called. The implementation of Action<T> is just a
|
||||||
// linked_ptr to const ActionInterface<T>, so copying is fairly cheap.
|
// std::shared_ptr to const ActionInterface<T>. Don't inherit from Action!
|
||||||
// Don't inherit from Action!
|
|
||||||
//
|
|
||||||
// You can view an object implementing ActionInterface<F> as a
|
// You can view an object implementing ActionInterface<F> as a
|
||||||
// concrete action (including its current state), and an Action<F>
|
// concrete action (including its current state), and an Action<F>
|
||||||
// object as a handle to it.
|
// object as a handle to it.
|
||||||
template <typename F>
|
template <typename F>
|
||||||
class Action {
|
class Action {
|
||||||
|
// Adapter class to allow constructing Action from a legacy ActionInterface.
|
||||||
|
// New code should create Actions from functors instead.
|
||||||
|
struct ActionAdapter {
|
||||||
|
// Adapter must be copyable to satisfy std::function requirements.
|
||||||
|
::std::shared_ptr<ActionInterface<F>> impl_;
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
typename internal::Function<F>::Result operator()(Args&&... args) {
|
||||||
|
return impl_->Perform(
|
||||||
|
::std::forward_as_tuple(::std::forward<Args>(args)...));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef typename internal::Function<F>::Result Result;
|
typedef typename internal::Function<F>::Result Result;
|
||||||
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
// Constructs a null Action. Needed for storing Action objects in
|
// Constructs a null Action. Needed for storing Action objects in
|
||||||
// STL containers.
|
// STL containers.
|
||||||
Action() : impl_(NULL) {}
|
Action() {}
|
||||||
|
|
||||||
// Constructs an Action from its implementation. A NULL impl is
|
// Construct an Action from a specified callable.
|
||||||
// used to represent the "do-default" action.
|
// This cannot take std::function directly, because then Action would not be
|
||||||
explicit Action(ActionInterface<F>* impl) : impl_(impl) {}
|
// directly constructible from lambda (it would require two conversions).
|
||||||
|
template <typename G,
|
||||||
|
typename = typename ::std::enable_if<
|
||||||
|
::std::is_constructible<::std::function<F>, G>::value>::type>
|
||||||
|
Action(G&& fun) : fun_(::std::forward<G>(fun)) {} // NOLINT
|
||||||
|
|
||||||
// Copy constructor.
|
// Constructs an Action from its implementation.
|
||||||
Action(const Action& action) : impl_(action.impl_) {}
|
explicit Action(ActionInterface<F>* impl)
|
||||||
|
: fun_(ActionAdapter{::std::shared_ptr<ActionInterface<F>>(impl)}) {}
|
||||||
|
|
||||||
// This constructor allows us to turn an Action<Func> object into an
|
// This constructor allows us to turn an Action<Func> object into an
|
||||||
// Action<F>, as long as F's arguments can be implicitly converted
|
// Action<F>, as long as F's arguments can be implicitly converted
|
||||||
// to Func's and Func's return type can be implicitly converted to
|
// to Func's and Func's return type can be implicitly converted to F's.
|
||||||
// F's.
|
|
||||||
template <typename Func>
|
template <typename Func>
|
||||||
explicit Action(const Action<Func>& action);
|
explicit Action(const Action<Func>& action) : fun_(action.fun_) {}
|
||||||
|
|
||||||
// Returns true iff this is the DoDefault() action.
|
// Returns true if and only if this is the DoDefault() action.
|
||||||
bool IsDoDefault() const { return impl_.get() == NULL; }
|
bool IsDoDefault() const { return fun_ == nullptr; }
|
||||||
|
|
||||||
// Performs the action. Note that this method is const even though
|
// Performs the action. Note that this method is const even though
|
||||||
// the corresponding method in ActionInterface is not. The reason
|
// the corresponding method in ActionInterface is not. The reason
|
||||||
@@ -384,22 +385,19 @@ class Action {
|
|||||||
// another concrete action, not that the concrete action it binds to
|
// another concrete action, not that the concrete action it binds to
|
||||||
// cannot change state. (Think of the difference between a const
|
// cannot change state. (Think of the difference between a const
|
||||||
// pointer and a pointer to const.)
|
// pointer and a pointer to const.)
|
||||||
Result Perform(const ArgumentTuple& args) const {
|
Result Perform(ArgumentTuple args) const {
|
||||||
internal::Assert(
|
if (IsDoDefault()) {
|
||||||
!IsDoDefault(), __FILE__, __LINE__,
|
internal::IllegalDoDefault(__FILE__, __LINE__);
|
||||||
"You are using DoDefault() inside a composite action like "
|
}
|
||||||
"DoAll() or WithArgs(). This is not supported for technical "
|
return internal::Apply(fun_, ::std::move(args));
|
||||||
"reasons. Please instead spell out the default action, or "
|
|
||||||
"assign the default action to an Action variable and use "
|
|
||||||
"the variable in various places.");
|
|
||||||
return impl_->Perform(args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename F1, typename F2>
|
template <typename G>
|
||||||
friend class internal::ActionAdaptor;
|
friend class Action;
|
||||||
|
|
||||||
internal::linked_ptr<ActionInterface<F> > impl_;
|
// fun_ is an empty function if and only if this is the DoDefault() action.
|
||||||
|
::std::function<F> fun_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// The PolymorphicAction class template makes it easy to implement a
|
// The PolymorphicAction class template makes it easy to implement a
|
||||||
@@ -414,7 +412,7 @@ class Action {
|
|||||||
// template <typename Result, typename ArgumentTuple>
|
// template <typename Result, typename ArgumentTuple>
|
||||||
// Result Perform(const ArgumentTuple& args) const {
|
// Result Perform(const ArgumentTuple& args) const {
|
||||||
// // Processes the arguments and returns a result, using
|
// // Processes the arguments and returns a result, using
|
||||||
// // tr1::get<N>(args) to get the N-th (0-based) argument in the tuple.
|
// // std::get<N>(args) to get the N-th (0-based) argument in the tuple.
|
||||||
// }
|
// }
|
||||||
// ...
|
// ...
|
||||||
// };
|
// };
|
||||||
@@ -442,7 +440,7 @@ class PolymorphicAction {
|
|||||||
|
|
||||||
explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {}
|
explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {}
|
||||||
|
|
||||||
virtual Result Perform(const ArgumentTuple& args) {
|
Result Perform(const ArgumentTuple& args) override {
|
||||||
return impl_.template Perform<Result>(args);
|
return impl_.template Perform<Result>(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,31 +476,11 @@ inline PolymorphicAction<Impl> MakePolymorphicAction(const Impl& impl) {
|
|||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
// Allows an Action<F2> object to pose as an Action<F1>, as long as F2
|
|
||||||
// and F1 are compatible.
|
|
||||||
template <typename F1, typename F2>
|
|
||||||
class ActionAdaptor : public ActionInterface<F1> {
|
|
||||||
public:
|
|
||||||
typedef typename internal::Function<F1>::Result Result;
|
|
||||||
typedef typename internal::Function<F1>::ArgumentTuple ArgumentTuple;
|
|
||||||
|
|
||||||
explicit ActionAdaptor(const Action<F2>& from) : impl_(from.impl_) {}
|
|
||||||
|
|
||||||
virtual Result Perform(const ArgumentTuple& args) {
|
|
||||||
return impl_->Perform(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const internal::linked_ptr<ActionInterface<F2> > impl_;
|
|
||||||
|
|
||||||
GTEST_DISALLOW_ASSIGN_(ActionAdaptor);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Helper struct to specialize ReturnAction to execute a move instead of a copy
|
// Helper struct to specialize ReturnAction to execute a move instead of a copy
|
||||||
// on return. Useful for move-only types, but could be used on any type.
|
// on return. Useful for move-only types, but could be used on any type.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct ByMoveWrapper {
|
struct ByMoveWrapper {
|
||||||
explicit ByMoveWrapper(T value) : payload(internal::move(value)) {}
|
explicit ByMoveWrapper(T value) : payload(std::move(value)) {}
|
||||||
T payload;
|
T payload;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -530,18 +508,21 @@ struct ByMoveWrapper {
|
|||||||
// statement, and conversion of the result of Return to Action<T(U)> is a
|
// statement, and conversion of the result of Return to Action<T(U)> is a
|
||||||
// good place for that.
|
// good place for that.
|
||||||
//
|
//
|
||||||
|
// The real life example of the above scenario happens when an invocation
|
||||||
|
// of gtl::Container() is passed into Return.
|
||||||
|
//
|
||||||
template <typename R>
|
template <typename R>
|
||||||
class ReturnAction {
|
class ReturnAction {
|
||||||
public:
|
public:
|
||||||
// Constructs a ReturnAction object from the value to be returned.
|
// Constructs a ReturnAction object from the value to be returned.
|
||||||
// 'value' is passed by value instead of by const reference in order
|
// 'value' is passed by value instead of by const reference in order
|
||||||
// to allow Return("string literal") to compile.
|
// to allow Return("string literal") to compile.
|
||||||
explicit ReturnAction(R value) : value_(new R(internal::move(value))) {}
|
explicit ReturnAction(R value) : value_(new R(std::move(value))) {}
|
||||||
|
|
||||||
// This template type conversion operator allows Return(x) to be
|
// This template type conversion operator allows Return(x) to be
|
||||||
// used in ANY function that returns x's type.
|
// used in ANY function that returns x's type.
|
||||||
template <typename F>
|
template <typename F>
|
||||||
operator Action<F>() const {
|
operator Action<F>() const { // NOLINT
|
||||||
// Assert statement belongs here because this is the best place to verify
|
// Assert statement belongs here because this is the best place to verify
|
||||||
// conditions on F. It produces the clearest error messages
|
// conditions on F. It produces the clearest error messages
|
||||||
// in most compilers.
|
// in most compilers.
|
||||||
@@ -552,8 +533,10 @@ class ReturnAction {
|
|||||||
// in the Impl class. But both definitions must be the same.
|
// in the Impl class. But both definitions must be the same.
|
||||||
typedef typename Function<F>::Result Result;
|
typedef typename Function<F>::Result Result;
|
||||||
GTEST_COMPILE_ASSERT_(
|
GTEST_COMPILE_ASSERT_(
|
||||||
!is_reference<Result>::value,
|
!std::is_reference<Result>::value,
|
||||||
use_ReturnRef_instead_of_Return_to_return_a_reference);
|
use_ReturnRef_instead_of_Return_to_return_a_reference);
|
||||||
|
static_assert(!std::is_void<Result>::value,
|
||||||
|
"Can't use Return() on an action expected to return `void`.");
|
||||||
return Action<F>(new Impl<R, F>(value_));
|
return Action<F>(new Impl<R, F>(value_));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -572,14 +555,14 @@ class ReturnAction {
|
|||||||
// Result to call. ImplicitCast_ forces the compiler to convert R to
|
// Result to call. ImplicitCast_ forces the compiler to convert R to
|
||||||
// Result without considering explicit constructors, thus resolving the
|
// Result without considering explicit constructors, thus resolving the
|
||||||
// ambiguity. value_ is then initialized using its copy constructor.
|
// ambiguity. value_ is then initialized using its copy constructor.
|
||||||
explicit Impl(const linked_ptr<R>& value)
|
explicit Impl(const std::shared_ptr<R>& value)
|
||||||
: value_before_cast_(*value),
|
: value_before_cast_(*value),
|
||||||
value_(ImplicitCast_<Result>(value_before_cast_)) {}
|
value_(ImplicitCast_<Result>(value_before_cast_)) {}
|
||||||
|
|
||||||
virtual Result Perform(const ArgumentTuple&) { return value_; }
|
Result Perform(const ArgumentTuple&) override { return value_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GTEST_COMPILE_ASSERT_(!is_reference<Result>::value,
|
GTEST_COMPILE_ASSERT_(!std::is_reference<Result>::value,
|
||||||
Result_cannot_be_a_reference_type);
|
Result_cannot_be_a_reference_type);
|
||||||
// We save the value before casting just in case it is being cast to a
|
// We save the value before casting just in case it is being cast to a
|
||||||
// wrapper type.
|
// wrapper type.
|
||||||
@@ -597,24 +580,24 @@ class ReturnAction {
|
|||||||
typedef typename Function<F>::Result Result;
|
typedef typename Function<F>::Result Result;
|
||||||
typedef typename Function<F>::ArgumentTuple ArgumentTuple;
|
typedef typename Function<F>::ArgumentTuple ArgumentTuple;
|
||||||
|
|
||||||
explicit Impl(const linked_ptr<R>& wrapper)
|
explicit Impl(const std::shared_ptr<R>& wrapper)
|
||||||
: performed_(false), wrapper_(wrapper) {}
|
: performed_(false), wrapper_(wrapper) {}
|
||||||
|
|
||||||
virtual Result Perform(const ArgumentTuple&) {
|
Result Perform(const ArgumentTuple&) override {
|
||||||
GTEST_CHECK_(!performed_)
|
GTEST_CHECK_(!performed_)
|
||||||
<< "A ByMove() action should only be performed once.";
|
<< "A ByMove() action should only be performed once.";
|
||||||
performed_ = true;
|
performed_ = true;
|
||||||
return internal::move(wrapper_->payload);
|
return std::move(wrapper_->payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool performed_;
|
bool performed_;
|
||||||
const linked_ptr<R> wrapper_;
|
const std::shared_ptr<R> wrapper_;
|
||||||
|
|
||||||
GTEST_DISALLOW_ASSIGN_(Impl);
|
GTEST_DISALLOW_ASSIGN_(Impl);
|
||||||
};
|
};
|
||||||
|
|
||||||
const linked_ptr<R> value_;
|
const std::shared_ptr<R> value_;
|
||||||
|
|
||||||
GTEST_DISALLOW_ASSIGN_(ReturnAction);
|
GTEST_DISALLOW_ASSIGN_(ReturnAction);
|
||||||
};
|
};
|
||||||
@@ -627,13 +610,7 @@ class ReturnNullAction {
|
|||||||
// pointer type on compile time.
|
// pointer type on compile time.
|
||||||
template <typename Result, typename ArgumentTuple>
|
template <typename Result, typename ArgumentTuple>
|
||||||
static Result Perform(const ArgumentTuple&) {
|
static Result Perform(const ArgumentTuple&) {
|
||||||
#if GTEST_LANG_CXX11
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
#else
|
|
||||||
GTEST_COMPILE_ASSERT_(internal::is_pointer<Result>::value,
|
|
||||||
ReturnNull_can_be_used_to_return_a_pointer_only);
|
|
||||||
return NULL;
|
|
||||||
#endif // GTEST_LANG_CXX11
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -643,7 +620,7 @@ class ReturnVoidAction {
|
|||||||
// Allows Return() to be used in any void-returning function.
|
// Allows Return() to be used in any void-returning function.
|
||||||
template <typename Result, typename ArgumentTuple>
|
template <typename Result, typename ArgumentTuple>
|
||||||
static void Perform(const ArgumentTuple&) {
|
static void Perform(const ArgumentTuple&) {
|
||||||
CompileAssertTypesEqual<void, Result>();
|
static_assert(std::is_void<Result>::value, "Result should be void.");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -664,7 +641,7 @@ class ReturnRefAction {
|
|||||||
// Asserts that the function return type is a reference. This
|
// Asserts that the function return type is a reference. This
|
||||||
// catches the user error of using ReturnRef(x) when Return(x)
|
// catches the user error of using ReturnRef(x) when Return(x)
|
||||||
// should be used, and generates some helpful error message.
|
// should be used, and generates some helpful error message.
|
||||||
GTEST_COMPILE_ASSERT_(internal::is_reference<Result>::value,
|
GTEST_COMPILE_ASSERT_(std::is_reference<Result>::value,
|
||||||
use_Return_instead_of_ReturnRef_to_return_a_value);
|
use_Return_instead_of_ReturnRef_to_return_a_value);
|
||||||
return Action<F>(new Impl<F>(ref_));
|
return Action<F>(new Impl<F>(ref_));
|
||||||
}
|
}
|
||||||
@@ -679,9 +656,7 @@ class ReturnRefAction {
|
|||||||
|
|
||||||
explicit Impl(T& ref) : ref_(ref) {} // NOLINT
|
explicit Impl(T& ref) : ref_(ref) {} // NOLINT
|
||||||
|
|
||||||
virtual Result Perform(const ArgumentTuple&) {
|
Result Perform(const ArgumentTuple&) override { return ref_; }
|
||||||
return ref_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T& ref_;
|
T& ref_;
|
||||||
@@ -713,7 +688,7 @@ class ReturnRefOfCopyAction {
|
|||||||
// catches the user error of using ReturnRefOfCopy(x) when Return(x)
|
// catches the user error of using ReturnRefOfCopy(x) when Return(x)
|
||||||
// should be used, and generates some helpful error message.
|
// should be used, and generates some helpful error message.
|
||||||
GTEST_COMPILE_ASSERT_(
|
GTEST_COMPILE_ASSERT_(
|
||||||
internal::is_reference<Result>::value,
|
std::is_reference<Result>::value,
|
||||||
use_Return_instead_of_ReturnRefOfCopy_to_return_a_value);
|
use_Return_instead_of_ReturnRefOfCopy_to_return_a_value);
|
||||||
return Action<F>(new Impl<F>(value_));
|
return Action<F>(new Impl<F>(value_));
|
||||||
}
|
}
|
||||||
@@ -728,9 +703,7 @@ class ReturnRefOfCopyAction {
|
|||||||
|
|
||||||
explicit Impl(const T& value) : value_(value) {} // NOLINT
|
explicit Impl(const T& value) : value_(value) {} // NOLINT
|
||||||
|
|
||||||
virtual Result Perform(const ArgumentTuple&) {
|
Result Perform(const ArgumentTuple&) override { return value_; }
|
||||||
return value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T value_;
|
T value_;
|
||||||
@@ -749,7 +722,7 @@ class DoDefaultAction {
|
|||||||
// This template type conversion operator allows DoDefault() to be
|
// This template type conversion operator allows DoDefault() to be
|
||||||
// used in any function.
|
// used in any function.
|
||||||
template <typename F>
|
template <typename F>
|
||||||
operator Action<F>() const { return Action<F>(NULL); }
|
operator Action<F>() const { return Action<F>(); } // NOLINT
|
||||||
};
|
};
|
||||||
|
|
||||||
// Implements the Assign action to set a given pointer referent to a
|
// Implements the Assign action to set a given pointer referent to a
|
||||||
@@ -797,92 +770,58 @@ class SetErrnoAndReturnAction {
|
|||||||
#endif // !GTEST_OS_WINDOWS_MOBILE
|
#endif // !GTEST_OS_WINDOWS_MOBILE
|
||||||
|
|
||||||
// Implements the SetArgumentPointee<N>(x) action for any function
|
// Implements the SetArgumentPointee<N>(x) action for any function
|
||||||
// whose N-th argument (0-based) is a pointer to x's type. The
|
// whose N-th argument (0-based) is a pointer to x's type.
|
||||||
// template parameter kIsProto is true iff type A is ProtocolMessage,
|
template <size_t N, typename A, typename = void>
|
||||||
// proto2::Message, or a sub-class of those.
|
struct SetArgumentPointeeAction {
|
||||||
template <size_t N, typename A, bool kIsProto>
|
A value;
|
||||||
class SetArgumentPointeeAction {
|
|
||||||
public:
|
|
||||||
// Constructs an action that sets the variable pointed to by the
|
|
||||||
// N-th function argument to 'value'.
|
|
||||||
explicit SetArgumentPointeeAction(const A& value) : value_(value) {}
|
|
||||||
|
|
||||||
template <typename Result, typename ArgumentTuple>
|
template <typename... Args>
|
||||||
void Perform(const ArgumentTuple& args) const {
|
void operator()(const Args&... args) const {
|
||||||
CompileAssertTypesEqual<void, Result>();
|
*::std::get<N>(std::tie(args...)) = value;
|
||||||
*::testing::get<N>(args) = value_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
const A value_;
|
|
||||||
|
|
||||||
GTEST_DISALLOW_ASSIGN_(SetArgumentPointeeAction);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <size_t N, typename Proto>
|
// Implements the Invoke(object_ptr, &Class::Method) action.
|
||||||
class SetArgumentPointeeAction<N, Proto, true> {
|
template <class Class, typename MethodPtr>
|
||||||
public:
|
struct InvokeMethodAction {
|
||||||
// Constructs an action that sets the variable pointed to by the
|
Class* const obj_ptr;
|
||||||
// N-th function argument to 'proto'. Both ProtocolMessage and
|
const MethodPtr method_ptr;
|
||||||
// proto2::Message have the CopyFrom() method, so the same
|
|
||||||
// implementation works for both.
|
template <typename... Args>
|
||||||
explicit SetArgumentPointeeAction(const Proto& proto) : proto_(new Proto) {
|
auto operator()(Args&&... args) const
|
||||||
proto_->CopyFrom(proto);
|
-> decltype((obj_ptr->*method_ptr)(std::forward<Args>(args)...)) {
|
||||||
|
return (obj_ptr->*method_ptr)(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Result, typename ArgumentTuple>
|
|
||||||
void Perform(const ArgumentTuple& args) const {
|
|
||||||
CompileAssertTypesEqual<void, Result>();
|
|
||||||
::testing::get<N>(args)->CopyFrom(*proto_);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const internal::linked_ptr<Proto> proto_;
|
|
||||||
|
|
||||||
GTEST_DISALLOW_ASSIGN_(SetArgumentPointeeAction);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Implements the InvokeWithoutArgs(f) action. The template argument
|
// Implements the InvokeWithoutArgs(f) action. The template argument
|
||||||
// FunctionImpl is the implementation type of f, which can be either a
|
// FunctionImpl is the implementation type of f, which can be either a
|
||||||
// function pointer or a functor. InvokeWithoutArgs(f) can be used as an
|
// function pointer or a functor. InvokeWithoutArgs(f) can be used as an
|
||||||
// Action<F> as long as f's type is compatible with F (i.e. f can be
|
// Action<F> as long as f's type is compatible with F.
|
||||||
// assigned to a tr1::function<F>).
|
|
||||||
template <typename FunctionImpl>
|
template <typename FunctionImpl>
|
||||||
class InvokeWithoutArgsAction {
|
struct InvokeWithoutArgsAction {
|
||||||
public:
|
FunctionImpl function_impl;
|
||||||
// The c'tor makes a copy of function_impl (either a function
|
|
||||||
// pointer or a functor).
|
|
||||||
explicit InvokeWithoutArgsAction(FunctionImpl function_impl)
|
|
||||||
: function_impl_(function_impl) {}
|
|
||||||
|
|
||||||
// Allows InvokeWithoutArgs(f) to be used as any action whose type is
|
// Allows InvokeWithoutArgs(f) to be used as any action whose type is
|
||||||
// compatible with f.
|
// compatible with f.
|
||||||
template <typename Result, typename ArgumentTuple>
|
template <typename... Args>
|
||||||
Result Perform(const ArgumentTuple&) { return function_impl_(); }
|
auto operator()(const Args&...) -> decltype(function_impl()) {
|
||||||
|
return function_impl();
|
||||||
private:
|
}
|
||||||
FunctionImpl function_impl_;
|
|
||||||
|
|
||||||
GTEST_DISALLOW_ASSIGN_(InvokeWithoutArgsAction);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Implements the InvokeWithoutArgs(object_ptr, &Class::Method) action.
|
// Implements the InvokeWithoutArgs(object_ptr, &Class::Method) action.
|
||||||
template <class Class, typename MethodPtr>
|
template <class Class, typename MethodPtr>
|
||||||
class InvokeMethodWithoutArgsAction {
|
struct InvokeMethodWithoutArgsAction {
|
||||||
public:
|
Class* const obj_ptr;
|
||||||
InvokeMethodWithoutArgsAction(Class* obj_ptr, MethodPtr method_ptr)
|
const MethodPtr method_ptr;
|
||||||
: obj_ptr_(obj_ptr), method_ptr_(method_ptr) {}
|
|
||||||
|
|
||||||
template <typename Result, typename ArgumentTuple>
|
using ReturnType = typename std::result_of<MethodPtr(Class*)>::type;
|
||||||
Result Perform(const ArgumentTuple&) const {
|
|
||||||
return (obj_ptr_->*method_ptr_)();
|
template <typename... Args>
|
||||||
|
ReturnType operator()(const Args&...) const {
|
||||||
|
return (obj_ptr->*method_ptr)();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
Class* const obj_ptr_;
|
|
||||||
const MethodPtr method_ptr_;
|
|
||||||
|
|
||||||
GTEST_DISALLOW_ASSIGN_(InvokeMethodWithoutArgsAction);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Implements the IgnoreResult(action) action.
|
// Implements the IgnoreResult(action) action.
|
||||||
@@ -904,7 +843,7 @@ class IgnoreResultAction {
|
|||||||
typedef typename internal::Function<F>::Result Result;
|
typedef typename internal::Function<F>::Result Result;
|
||||||
|
|
||||||
// Asserts at compile time that F returns void.
|
// Asserts at compile time that F returns void.
|
||||||
CompileAssertTypesEqual<void, Result>();
|
static_assert(std::is_void<Result>::value, "Result type should be void.");
|
||||||
|
|
||||||
return Action<F>(new Impl<F>(action_));
|
return Action<F>(new Impl<F>(action_));
|
||||||
}
|
}
|
||||||
@@ -918,7 +857,7 @@ class IgnoreResultAction {
|
|||||||
|
|
||||||
explicit Impl(const A& action) : action_(action) {}
|
explicit Impl(const A& action) : action_(action) {}
|
||||||
|
|
||||||
virtual void Perform(const ArgumentTuple& args) {
|
void Perform(const ArgumentTuple& args) override {
|
||||||
// Performs the action and ignores its result.
|
// Performs the action and ignores its result.
|
||||||
action_.Perform(args);
|
action_.Perform(args);
|
||||||
}
|
}
|
||||||
@@ -939,76 +878,51 @@ class IgnoreResultAction {
|
|||||||
GTEST_DISALLOW_ASSIGN_(IgnoreResultAction);
|
GTEST_DISALLOW_ASSIGN_(IgnoreResultAction);
|
||||||
};
|
};
|
||||||
|
|
||||||
// A ReferenceWrapper<T> object represents a reference to type T,
|
template <typename InnerAction, size_t... I>
|
||||||
// which can be either const or not. It can be explicitly converted
|
struct WithArgsAction {
|
||||||
// from, and implicitly converted to, a T&. Unlike a reference,
|
InnerAction action;
|
||||||
// ReferenceWrapper<T> can be copied and can survive template type
|
|
||||||
// inference. This is used to support by-reference arguments in the
|
|
||||||
// InvokeArgument<N>(...) action. The idea was from "reference
|
|
||||||
// wrappers" in tr1, which we don't have in our source tree yet.
|
|
||||||
template <typename T>
|
|
||||||
class ReferenceWrapper {
|
|
||||||
public:
|
|
||||||
// Constructs a ReferenceWrapper<T> object from a T&.
|
|
||||||
explicit ReferenceWrapper(T& l_value) : pointer_(&l_value) {} // NOLINT
|
|
||||||
|
|
||||||
// Allows a ReferenceWrapper<T> object to be implicitly converted to
|
// The inner action could be anything convertible to Action<X>.
|
||||||
// a T&.
|
// We use the conversion operator to detect the signature of the inner Action.
|
||||||
operator T&() const { return *pointer_; }
|
template <typename R, typename... Args>
|
||||||
private:
|
operator Action<R(Args...)>() const { // NOLINT
|
||||||
T* pointer_;
|
Action<R(typename std::tuple_element<I, std::tuple<Args...>>::type...)>
|
||||||
|
converted(action);
|
||||||
|
|
||||||
|
return [converted](Args... args) -> R {
|
||||||
|
return converted.Perform(std::forward_as_tuple(
|
||||||
|
std::get<I>(std::forward_as_tuple(std::forward<Args>(args)...))...));
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Allows the expression ByRef(x) to be printed as a reference to x.
|
template <typename... Actions>
|
||||||
template <typename T>
|
struct DoAllAction {
|
||||||
void PrintTo(const ReferenceWrapper<T>& ref, ::std::ostream* os) {
|
private:
|
||||||
T& value = ref;
|
template <typename... Args, size_t... I>
|
||||||
UniversalPrinter<T&>::Print(value, os);
|
std::vector<Action<void(Args...)>> Convert(IndexSequence<I...>) const {
|
||||||
}
|
return {std::get<I>(actions)...};
|
||||||
|
|
||||||
// Does two actions sequentially. Used for implementing the DoAll(a1,
|
|
||||||
// a2, ...) action.
|
|
||||||
template <typename Action1, typename Action2>
|
|
||||||
class DoBothAction {
|
|
||||||
public:
|
|
||||||
DoBothAction(Action1 action1, Action2 action2)
|
|
||||||
: action1_(action1), action2_(action2) {}
|
|
||||||
|
|
||||||
// This template type conversion operator allows DoAll(a1, ..., a_n)
|
|
||||||
// to be used in ANY function of compatible type.
|
|
||||||
template <typename F>
|
|
||||||
operator Action<F>() const {
|
|
||||||
return Action<F>(new Impl<F>(action1_, action2_));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
public:
|
||||||
// Implements the DoAll(...) action for a particular function type F.
|
std::tuple<Actions...> actions;
|
||||||
template <typename F>
|
|
||||||
class Impl : public ActionInterface<F> {
|
|
||||||
public:
|
|
||||||
typedef typename Function<F>::Result Result;
|
|
||||||
typedef typename Function<F>::ArgumentTuple ArgumentTuple;
|
|
||||||
typedef typename Function<F>::MakeResultVoid VoidResult;
|
|
||||||
|
|
||||||
Impl(const Action<VoidResult>& action1, const Action<F>& action2)
|
template <typename R, typename... Args>
|
||||||
: action1_(action1), action2_(action2) {}
|
operator Action<R(Args...)>() const { // NOLINT
|
||||||
|
struct Op {
|
||||||
virtual Result Perform(const ArgumentTuple& args) {
|
std::vector<Action<void(Args...)>> converted;
|
||||||
action1_.Perform(args);
|
Action<R(Args...)> last;
|
||||||
return action2_.Perform(args);
|
R operator()(Args... args) const {
|
||||||
}
|
auto tuple_args = std::forward_as_tuple(std::forward<Args>(args)...);
|
||||||
|
for (auto& a : converted) {
|
||||||
private:
|
a.Perform(tuple_args);
|
||||||
const Action<VoidResult> action1_;
|
}
|
||||||
const Action<F> action2_;
|
return last.Perform(tuple_args);
|
||||||
|
}
|
||||||
GTEST_DISALLOW_ASSIGN_(Impl);
|
};
|
||||||
};
|
return Op{Convert<Args...>(MakeIndexSequence<sizeof...(Actions) - 1>()),
|
||||||
|
std::get<sizeof...(Actions) - 1>(actions)};
|
||||||
Action1 action1_;
|
}
|
||||||
Action2 action2_;
|
|
||||||
|
|
||||||
GTEST_DISALLOW_ASSIGN_(DoBothAction);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
@@ -1029,9 +943,9 @@ class DoBothAction {
|
|||||||
// return sqrt(x*x + y*y);
|
// return sqrt(x*x + y*y);
|
||||||
// }
|
// }
|
||||||
// ...
|
// ...
|
||||||
// EXEPCT_CALL(mock, Foo("abc", _, _))
|
// EXPECT_CALL(mock, Foo("abc", _, _))
|
||||||
// .WillOnce(Invoke(DistanceToOriginWithLabel));
|
// .WillOnce(Invoke(DistanceToOriginWithLabel));
|
||||||
// EXEPCT_CALL(mock, Bar(5, _, _))
|
// EXPECT_CALL(mock, Bar(5, _, _))
|
||||||
// .WillOnce(Invoke(DistanceToOriginWithIndex));
|
// .WillOnce(Invoke(DistanceToOriginWithIndex));
|
||||||
//
|
//
|
||||||
// you could write
|
// you could write
|
||||||
@@ -1041,25 +955,55 @@ class DoBothAction {
|
|||||||
// return sqrt(x*x + y*y);
|
// return sqrt(x*x + y*y);
|
||||||
// }
|
// }
|
||||||
// ...
|
// ...
|
||||||
// EXEPCT_CALL(mock, Foo("abc", _, _)).WillOnce(Invoke(DistanceToOrigin));
|
// EXPECT_CALL(mock, Foo("abc", _, _)).WillOnce(Invoke(DistanceToOrigin));
|
||||||
// EXEPCT_CALL(mock, Bar(5, _, _)).WillOnce(Invoke(DistanceToOrigin));
|
// EXPECT_CALL(mock, Bar(5, _, _)).WillOnce(Invoke(DistanceToOrigin));
|
||||||
typedef internal::IgnoredValue Unused;
|
typedef internal::IgnoredValue Unused;
|
||||||
|
|
||||||
// This constructor allows us to turn an Action<From> object into an
|
// Creates an action that does actions a1, a2, ..., sequentially in
|
||||||
// Action<To>, as long as To's arguments can be implicitly converted
|
// each invocation.
|
||||||
// to From's and From's return type cann be implicitly converted to
|
template <typename... Action>
|
||||||
// To's.
|
internal::DoAllAction<typename std::decay<Action>::type...> DoAll(
|
||||||
template <typename To>
|
Action&&... action) {
|
||||||
template <typename From>
|
return {std::forward_as_tuple(std::forward<Action>(action)...)};
|
||||||
Action<To>::Action(const Action<From>& from)
|
}
|
||||||
: impl_(new internal::ActionAdaptor<To, From>(from)) {}
|
|
||||||
|
// WithArg<k>(an_action) creates an action that passes the k-th
|
||||||
|
// (0-based) argument of the mock function to an_action and performs
|
||||||
|
// it. It adapts an action accepting one argument to one that accepts
|
||||||
|
// multiple arguments. For convenience, we also provide
|
||||||
|
// WithArgs<k>(an_action) (defined below) as a synonym.
|
||||||
|
template <size_t k, typename InnerAction>
|
||||||
|
internal::WithArgsAction<typename std::decay<InnerAction>::type, k>
|
||||||
|
WithArg(InnerAction&& action) {
|
||||||
|
return {std::forward<InnerAction>(action)};
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithArgs<N1, N2, ..., Nk>(an_action) creates an action that passes
|
||||||
|
// the selected arguments of the mock function to an_action and
|
||||||
|
// performs it. It serves as an adaptor between actions with
|
||||||
|
// different argument lists.
|
||||||
|
template <size_t k, size_t... ks, typename InnerAction>
|
||||||
|
internal::WithArgsAction<typename std::decay<InnerAction>::type, k, ks...>
|
||||||
|
WithArgs(InnerAction&& action) {
|
||||||
|
return {std::forward<InnerAction>(action)};
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithoutArgs(inner_action) can be used in a mock function with a
|
||||||
|
// non-empty argument list to perform inner_action, which takes no
|
||||||
|
// argument. In other words, it adapts an action accepting no
|
||||||
|
// argument to one that accepts (and ignores) arguments.
|
||||||
|
template <typename InnerAction>
|
||||||
|
internal::WithArgsAction<typename std::decay<InnerAction>::type>
|
||||||
|
WithoutArgs(InnerAction&& action) {
|
||||||
|
return {std::forward<InnerAction>(action)};
|
||||||
|
}
|
||||||
|
|
||||||
// Creates an action that returns 'value'. 'value' is passed by value
|
// Creates an action that returns 'value'. 'value' is passed by value
|
||||||
// instead of const reference - otherwise Return("string literal")
|
// instead of const reference - otherwise Return("string literal")
|
||||||
// will trigger a compiler error about using array as initializer.
|
// will trigger a compiler error about using array as initializer.
|
||||||
template <typename R>
|
template <typename R>
|
||||||
internal::ReturnAction<R> Return(R value) {
|
internal::ReturnAction<R> Return(R value) {
|
||||||
return internal::ReturnAction<R>(internal::move(value));
|
return internal::ReturnAction<R>(std::move(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates an action that returns NULL.
|
// Creates an action that returns NULL.
|
||||||
@@ -1092,7 +1036,7 @@ inline internal::ReturnRefOfCopyAction<R> ReturnRefOfCopy(const R& x) {
|
|||||||
// invariant.
|
// invariant.
|
||||||
template <typename R>
|
template <typename R>
|
||||||
internal::ByMoveWrapper<R> ByMove(R x) {
|
internal::ByMoveWrapper<R> ByMove(R x) {
|
||||||
return internal::ByMoveWrapper<R>(internal::move(x));
|
return internal::ByMoveWrapper<R>(std::move(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates an action that does the default action for the give mock function.
|
// Creates an action that does the default action for the give mock function.
|
||||||
@@ -1103,43 +1047,14 @@ inline internal::DoDefaultAction DoDefault() {
|
|||||||
// Creates an action that sets the variable pointed by the N-th
|
// Creates an action that sets the variable pointed by the N-th
|
||||||
// (0-based) function argument to 'value'.
|
// (0-based) function argument to 'value'.
|
||||||
template <size_t N, typename T>
|
template <size_t N, typename T>
|
||||||
PolymorphicAction<
|
internal::SetArgumentPointeeAction<N, T> SetArgPointee(T x) {
|
||||||
internal::SetArgumentPointeeAction<
|
return {std::move(x)};
|
||||||
N, T, internal::IsAProtocolMessage<T>::value> >
|
|
||||||
SetArgPointee(const T& x) {
|
|
||||||
return MakePolymorphicAction(internal::SetArgumentPointeeAction<
|
|
||||||
N, T, internal::IsAProtocolMessage<T>::value>(x));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !((GTEST_GCC_VER_ && GTEST_GCC_VER_ < 40000) || GTEST_OS_SYMBIAN)
|
|
||||||
// This overload allows SetArgPointee() to accept a string literal.
|
|
||||||
// GCC prior to the version 4.0 and Symbian C++ compiler cannot distinguish
|
|
||||||
// this overload from the templated version and emit a compile error.
|
|
||||||
template <size_t N>
|
|
||||||
PolymorphicAction<
|
|
||||||
internal::SetArgumentPointeeAction<N, const char*, false> >
|
|
||||||
SetArgPointee(const char* p) {
|
|
||||||
return MakePolymorphicAction(internal::SetArgumentPointeeAction<
|
|
||||||
N, const char*, false>(p));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <size_t N>
|
|
||||||
PolymorphicAction<
|
|
||||||
internal::SetArgumentPointeeAction<N, const wchar_t*, false> >
|
|
||||||
SetArgPointee(const wchar_t* p) {
|
|
||||||
return MakePolymorphicAction(internal::SetArgumentPointeeAction<
|
|
||||||
N, const wchar_t*, false>(p));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// The following version is DEPRECATED.
|
// The following version is DEPRECATED.
|
||||||
template <size_t N, typename T>
|
template <size_t N, typename T>
|
||||||
PolymorphicAction<
|
internal::SetArgumentPointeeAction<N, T> SetArgumentPointee(T x) {
|
||||||
internal::SetArgumentPointeeAction<
|
return {std::move(x)};
|
||||||
N, T, internal::IsAProtocolMessage<T>::value> >
|
|
||||||
SetArgumentPointee(const T& x) {
|
|
||||||
return MakePolymorphicAction(internal::SetArgumentPointeeAction<
|
|
||||||
N, T, internal::IsAProtocolMessage<T>::value>(x));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates an action that sets a pointer referent to a given value.
|
// Creates an action that sets a pointer referent to a given value.
|
||||||
@@ -1160,24 +1075,38 @@ SetErrnoAndReturn(int errval, T result) {
|
|||||||
|
|
||||||
#endif // !GTEST_OS_WINDOWS_MOBILE
|
#endif // !GTEST_OS_WINDOWS_MOBILE
|
||||||
|
|
||||||
// Various overloads for InvokeWithoutArgs().
|
// Various overloads for Invoke().
|
||||||
|
|
||||||
|
// Legacy function.
|
||||||
|
// Actions can now be implicitly constructed from callables. No need to create
|
||||||
|
// wrapper objects.
|
||||||
|
// This function exists for backwards compatibility.
|
||||||
|
template <typename FunctionImpl>
|
||||||
|
typename std::decay<FunctionImpl>::type Invoke(FunctionImpl&& function_impl) {
|
||||||
|
return std::forward<FunctionImpl>(function_impl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates an action that invokes the given method on the given object
|
||||||
|
// with the mock function's arguments.
|
||||||
|
template <class Class, typename MethodPtr>
|
||||||
|
internal::InvokeMethodAction<Class, MethodPtr> Invoke(Class* obj_ptr,
|
||||||
|
MethodPtr method_ptr) {
|
||||||
|
return {obj_ptr, method_ptr};
|
||||||
|
}
|
||||||
|
|
||||||
// Creates an action that invokes 'function_impl' with no argument.
|
// Creates an action that invokes 'function_impl' with no argument.
|
||||||
template <typename FunctionImpl>
|
template <typename FunctionImpl>
|
||||||
PolymorphicAction<internal::InvokeWithoutArgsAction<FunctionImpl> >
|
internal::InvokeWithoutArgsAction<typename std::decay<FunctionImpl>::type>
|
||||||
InvokeWithoutArgs(FunctionImpl function_impl) {
|
InvokeWithoutArgs(FunctionImpl function_impl) {
|
||||||
return MakePolymorphicAction(
|
return {std::move(function_impl)};
|
||||||
internal::InvokeWithoutArgsAction<FunctionImpl>(function_impl));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates an action that invokes the given method on the given object
|
// Creates an action that invokes the given method on the given object
|
||||||
// with no argument.
|
// with no argument.
|
||||||
template <class Class, typename MethodPtr>
|
template <class Class, typename MethodPtr>
|
||||||
PolymorphicAction<internal::InvokeMethodWithoutArgsAction<Class, MethodPtr> >
|
internal::InvokeMethodWithoutArgsAction<Class, MethodPtr> InvokeWithoutArgs(
|
||||||
InvokeWithoutArgs(Class* obj_ptr, MethodPtr method_ptr) {
|
Class* obj_ptr, MethodPtr method_ptr) {
|
||||||
return MakePolymorphicAction(
|
return {obj_ptr, method_ptr};
|
||||||
internal::InvokeMethodWithoutArgsAction<Class, MethodPtr>(
|
|
||||||
obj_ptr, method_ptr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates an action that performs an_action and throws away its
|
// Creates an action that performs an_action and throws away its
|
||||||
@@ -1195,11 +1124,19 @@ inline internal::IgnoreResultAction<A> IgnoreResult(const A& an_action) {
|
|||||||
// where Base is a base class of Derived, just write:
|
// where Base is a base class of Derived, just write:
|
||||||
//
|
//
|
||||||
// ByRef<const Base>(derived)
|
// ByRef<const Base>(derived)
|
||||||
|
//
|
||||||
|
// N.B. ByRef is redundant with std::ref, std::cref and std::reference_wrapper.
|
||||||
|
// However, it may still be used for consistency with ByMove().
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline internal::ReferenceWrapper<T> ByRef(T& l_value) { // NOLINT
|
inline ::std::reference_wrapper<T> ByRef(T& l_value) { // NOLINT
|
||||||
return internal::ReferenceWrapper<T>(l_value);
|
return ::std::reference_wrapper<T>(l_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_
|
@@ -26,8 +26,7 @@
|
|||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
|
||||||
// Author: wan@google.com (Zhanyong Wan)
|
|
||||||
|
|
||||||
// Google Mock - a framework for writing C++ mock classes.
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
//
|
//
|
||||||
@@ -35,14 +34,20 @@
|
|||||||
// cardinalities can be defined by the user implementing the
|
// cardinalities can be defined by the user implementing the
|
||||||
// CardinalityInterface interface if necessary.
|
// CardinalityInterface interface if necessary.
|
||||||
|
|
||||||
|
// GOOGLETEST_CM0002 DO NOT DELETE
|
||||||
|
|
||||||
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
|
||||||
#define GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <memory>
|
||||||
#include <ostream> // NOLINT
|
#include <ostream> // NOLINT
|
||||||
#include "gmock/internal/gmock-port.h"
|
#include "gmock/internal/gmock-port.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
|
||||||
|
/* class A needs to have dll-interface to be used by clients of class B */)
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
// To implement a cardinality Foo, define:
|
// To implement a cardinality Foo, define:
|
||||||
@@ -65,10 +70,12 @@ class CardinalityInterface {
|
|||||||
virtual int ConservativeLowerBound() const { return 0; }
|
virtual int ConservativeLowerBound() const { return 0; }
|
||||||
virtual int ConservativeUpperBound() const { return INT_MAX; }
|
virtual int ConservativeUpperBound() const { return INT_MAX; }
|
||||||
|
|
||||||
// Returns true iff call_count calls will satisfy this cardinality.
|
// Returns true if and only if call_count calls will satisfy this
|
||||||
|
// cardinality.
|
||||||
virtual bool IsSatisfiedByCallCount(int call_count) const = 0;
|
virtual bool IsSatisfiedByCallCount(int call_count) const = 0;
|
||||||
|
|
||||||
// Returns true iff call_count calls will saturate this cardinality.
|
// Returns true if and only if call_count calls will saturate this
|
||||||
|
// cardinality.
|
||||||
virtual bool IsSaturatedByCallCount(int call_count) const = 0;
|
virtual bool IsSaturatedByCallCount(int call_count) const = 0;
|
||||||
|
|
||||||
// Describes self to an ostream.
|
// Describes self to an ostream.
|
||||||
@@ -77,9 +84,8 @@ class CardinalityInterface {
|
|||||||
|
|
||||||
// A Cardinality is a copyable and IMMUTABLE (except by assignment)
|
// A Cardinality is a copyable and IMMUTABLE (except by assignment)
|
||||||
// object that specifies how many times a mock function is expected to
|
// object that specifies how many times a mock function is expected to
|
||||||
// be called. The implementation of Cardinality is just a linked_ptr
|
// be called. The implementation of Cardinality is just a std::shared_ptr
|
||||||
// to const CardinalityInterface, so copying is fairly cheap.
|
// to const CardinalityInterface. Don't inherit from Cardinality!
|
||||||
// Don't inherit from Cardinality!
|
|
||||||
class GTEST_API_ Cardinality {
|
class GTEST_API_ Cardinality {
|
||||||
public:
|
public:
|
||||||
// Constructs a null cardinality. Needed for storing Cardinality
|
// Constructs a null cardinality. Needed for storing Cardinality
|
||||||
@@ -94,17 +100,19 @@ class GTEST_API_ Cardinality {
|
|||||||
int ConservativeLowerBound() const { return impl_->ConservativeLowerBound(); }
|
int ConservativeLowerBound() const { return impl_->ConservativeLowerBound(); }
|
||||||
int ConservativeUpperBound() const { return impl_->ConservativeUpperBound(); }
|
int ConservativeUpperBound() const { return impl_->ConservativeUpperBound(); }
|
||||||
|
|
||||||
// Returns true iff call_count calls will satisfy this cardinality.
|
// Returns true if and only if call_count calls will satisfy this
|
||||||
|
// cardinality.
|
||||||
bool IsSatisfiedByCallCount(int call_count) const {
|
bool IsSatisfiedByCallCount(int call_count) const {
|
||||||
return impl_->IsSatisfiedByCallCount(call_count);
|
return impl_->IsSatisfiedByCallCount(call_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true iff call_count calls will saturate this cardinality.
|
// Returns true if and only if call_count calls will saturate this
|
||||||
|
// cardinality.
|
||||||
bool IsSaturatedByCallCount(int call_count) const {
|
bool IsSaturatedByCallCount(int call_count) const {
|
||||||
return impl_->IsSaturatedByCallCount(call_count);
|
return impl_->IsSaturatedByCallCount(call_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true iff call_count calls will over-saturate this
|
// Returns true if and only if call_count calls will over-saturate this
|
||||||
// cardinality, i.e. exceed the maximum number of allowed calls.
|
// cardinality, i.e. exceed the maximum number of allowed calls.
|
||||||
bool IsOverSaturatedByCallCount(int call_count) const {
|
bool IsOverSaturatedByCallCount(int call_count) const {
|
||||||
return impl_->IsSaturatedByCallCount(call_count) &&
|
return impl_->IsSaturatedByCallCount(call_count) &&
|
||||||
@@ -119,7 +127,7 @@ class GTEST_API_ Cardinality {
|
|||||||
::std::ostream* os);
|
::std::ostream* os);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
internal::linked_ptr<const CardinalityInterface> impl_;
|
std::shared_ptr<const CardinalityInterface> impl_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Creates a cardinality that allows at least n calls.
|
// Creates a cardinality that allows at least n calls.
|
||||||
@@ -144,4 +152,6 @@ inline Cardinality MakeCardinality(const CardinalityInterface* c) {
|
|||||||
|
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
|
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||||
|
|
||||||
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
|
@@ -0,0 +1,253 @@
|
|||||||
|
// 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,5 +1,5 @@
|
|||||||
$$ -*- mode: c++; -*-
|
$$ -*- mode: c++; -*-
|
||||||
$$ This is a Pump source file. Please use Pump to convert it to
|
$$ This is a Pump source file. Please use Pump to convert it to
|
||||||
$$ gmock-generated-actions.h.
|
$$ gmock-generated-actions.h.
|
||||||
$$
|
$$
|
||||||
$var n = 10 $$ The maximum arity we support.
|
$var n = 10 $$ The maximum arity we support.
|
||||||
@@ -32,145 +32,26 @@ $$}} This meta comment fixes auto-indentation in editors.
|
|||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
|
||||||
// Author: wan@google.com (Zhanyong Wan)
|
|
||||||
|
|
||||||
// Google Mock - a framework for writing C++ mock classes.
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
//
|
//
|
||||||
// This file implements some commonly used variadic actions.
|
// This file implements some commonly used variadic actions.
|
||||||
|
|
||||||
|
// GOOGLETEST_CM0002 DO NOT DELETE
|
||||||
|
|
||||||
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
|
||||||
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "gmock/gmock-actions.h"
|
#include "gmock/gmock-actions.h"
|
||||||
#include "gmock/internal/gmock-port.h"
|
#include "gmock/internal/gmock-port.h"
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
// InvokeHelper<F> knows how to unpack an N-tuple and invoke an N-ary
|
|
||||||
// function or method with the unpacked values, where F is a function
|
|
||||||
// type that takes N arguments.
|
|
||||||
template <typename Result, typename ArgumentTuple>
|
|
||||||
class InvokeHelper;
|
|
||||||
|
|
||||||
|
|
||||||
$range i 0..n
|
|
||||||
$for i [[
|
|
||||||
$range j 1..i
|
|
||||||
$var types = [[$for j [[, typename A$j]]]]
|
|
||||||
$var as = [[$for j, [[A$j]]]]
|
|
||||||
$var args = [[$if i==0 [[]] $else [[ args]]]]
|
|
||||||
$var gets = [[$for j, [[get<$(j - 1)>(args)]]]]
|
|
||||||
template <typename R$types>
|
|
||||||
class InvokeHelper<R, ::testing::tuple<$as> > {
|
|
||||||
public:
|
|
||||||
template <typename Function>
|
|
||||||
static R Invoke(Function function, const ::testing::tuple<$as>&$args) {
|
|
||||||
return function($gets);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Class, typename MethodPtr>
|
|
||||||
static R InvokeMethod(Class* obj_ptr,
|
|
||||||
MethodPtr method_ptr,
|
|
||||||
const ::testing::tuple<$as>&$args) {
|
|
||||||
return (obj_ptr->*method_ptr)($gets);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
]]
|
|
||||||
// An INTERNAL macro for extracting the type of a tuple field. It's
|
|
||||||
// subject to change without notice - DO NOT USE IN USER CODE!
|
|
||||||
#define GMOCK_FIELD_(Tuple, N) \
|
|
||||||
typename ::testing::tuple_element<N, Tuple>::type
|
|
||||||
|
|
||||||
$range i 1..n
|
|
||||||
|
|
||||||
// SelectArgs<Result, ArgumentTuple, k1, k2, ..., k_n>::type is the
|
|
||||||
// type of an n-ary function whose i-th (1-based) argument type is the
|
|
||||||
// k{i}-th (0-based) field of ArgumentTuple, which must be a tuple
|
|
||||||
// type, and whose return type is Result. For example,
|
|
||||||
// SelectArgs<int, ::testing::tuple<bool, char, double, long>, 0, 3>::type
|
|
||||||
// is int(bool, long).
|
|
||||||
//
|
|
||||||
// SelectArgs<Result, ArgumentTuple, k1, k2, ..., k_n>::Select(args)
|
|
||||||
// returns the selected fields (k1, k2, ..., k_n) of args as a tuple.
|
|
||||||
// For example,
|
|
||||||
// SelectArgs<int, tuple<bool, char, double>, 2, 0>::Select(
|
|
||||||
// ::testing::make_tuple(true, 'a', 2.5))
|
|
||||||
// returns tuple (2.5, true).
|
|
||||||
//
|
|
||||||
// The numbers in list k1, k2, ..., k_n must be >= 0, where n can be
|
|
||||||
// in the range [0, $n]. Duplicates are allowed and they don't have
|
|
||||||
// to be in an ascending or descending order.
|
|
||||||
|
|
||||||
template <typename Result, typename ArgumentTuple, $for i, [[int k$i]]>
|
|
||||||
class SelectArgs {
|
|
||||||
public:
|
|
||||||
typedef Result type($for i, [[GMOCK_FIELD_(ArgumentTuple, k$i)]]);
|
|
||||||
typedef typename Function<type>::ArgumentTuple SelectedArgs;
|
|
||||||
static SelectedArgs Select(const ArgumentTuple& args) {
|
|
||||||
return SelectedArgs($for i, [[get<k$i>(args)]]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
$for i [[
|
|
||||||
$range j 1..n
|
|
||||||
$range j1 1..i-1
|
|
||||||
template <typename Result, typename ArgumentTuple$for j1[[, int k$j1]]>
|
|
||||||
class SelectArgs<Result, ArgumentTuple,
|
|
||||||
$for j, [[$if j <= i-1 [[k$j]] $else [[-1]]]]> {
|
|
||||||
public:
|
|
||||||
typedef Result type($for j1, [[GMOCK_FIELD_(ArgumentTuple, k$j1)]]);
|
|
||||||
typedef typename Function<type>::ArgumentTuple SelectedArgs;
|
|
||||||
static SelectedArgs Select(const ArgumentTuple& [[]]
|
|
||||||
$if i == 1 [[/* args */]] $else [[args]]) {
|
|
||||||
return SelectedArgs($for j1, [[get<k$j1>(args)]]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
]]
|
|
||||||
#undef GMOCK_FIELD_
|
|
||||||
|
|
||||||
$var ks = [[$for i, [[k$i]]]]
|
|
||||||
|
|
||||||
// Implements the WithArgs action.
|
|
||||||
template <typename InnerAction, $for i, [[int k$i = -1]]>
|
|
||||||
class WithArgsAction {
|
|
||||||
public:
|
|
||||||
explicit WithArgsAction(const InnerAction& action) : action_(action) {}
|
|
||||||
|
|
||||||
template <typename F>
|
|
||||||
operator Action<F>() const { return MakeAction(new Impl<F>(action_)); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
template <typename F>
|
|
||||||
class Impl : public ActionInterface<F> {
|
|
||||||
public:
|
|
||||||
typedef typename Function<F>::Result Result;
|
|
||||||
typedef typename Function<F>::ArgumentTuple ArgumentTuple;
|
|
||||||
|
|
||||||
explicit Impl(const InnerAction& action) : action_(action) {}
|
|
||||||
|
|
||||||
virtual Result Perform(const ArgumentTuple& args) {
|
|
||||||
return action_.Perform(SelectArgs<Result, ArgumentTuple, $ks>::Select(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef typename SelectArgs<Result, ArgumentTuple,
|
|
||||||
$ks>::type InnerFunctionType;
|
|
||||||
|
|
||||||
Action<InnerFunctionType> action_;
|
|
||||||
};
|
|
||||||
|
|
||||||
const InnerAction action_;
|
|
||||||
|
|
||||||
GTEST_DISALLOW_ASSIGN_(WithArgsAction);
|
|
||||||
};
|
|
||||||
|
|
||||||
// A macro from the ACTION* family (defined later in this file)
|
// A macro from the ACTION* family (defined later in this file)
|
||||||
// defines an action that can be used in a mock function. Typically,
|
// 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
|
// these actions only care about a subset of the arguments of the mock
|
||||||
@@ -201,12 +82,12 @@ $range j 0..i-1
|
|||||||
]]]]
|
]]]]
|
||||||
$range j 0..i-1
|
$range j 0..i-1
|
||||||
$var As = [[$for j, [[A$j]]]]
|
$var As = [[$for j, [[A$j]]]]
|
||||||
$var as = [[$for j, [[get<$j>(args)]]]]
|
$var as = [[$for j, [[std::get<$j>(args)]]]]
|
||||||
$range k 1..n-i
|
$range k 1..n-i
|
||||||
$var eas = [[$for k, [[ExcessiveArg()]]]]
|
$var eas = [[$for k, [[ExcessiveArg()]]]]
|
||||||
$var arg_list = [[$if (i==0) | (i==n) [[$as$eas]] $else [[$as, $eas]]]]
|
$var arg_list = [[$if (i==0) | (i==n) [[$as$eas]] $else [[$as, $eas]]]]
|
||||||
$template
|
$template
|
||||||
static Result Perform(Impl* impl, const ::testing::tuple<$As>& args) {
|
static Result Perform(Impl* impl, const ::std::tuple<$As>& args) {
|
||||||
return impl->template gmock_PerformImpl<$As>(args, $arg_list);
|
return impl->template gmock_PerformImpl<$As>(args, $arg_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,53 +95,6 @@ $template
|
|||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
// Various overloads for Invoke().
|
|
||||||
|
|
||||||
// WithArgs<N1, N2, ..., Nk>(an_action) creates an action that passes
|
|
||||||
// the selected arguments of the mock function to an_action and
|
|
||||||
// performs it. It serves as an adaptor between actions with
|
|
||||||
// different argument lists. C++ doesn't support default arguments for
|
|
||||||
// function templates, so we have to overload it.
|
|
||||||
|
|
||||||
$range i 1..n
|
|
||||||
$for i [[
|
|
||||||
$range j 1..i
|
|
||||||
template <$for j [[int k$j, ]]typename InnerAction>
|
|
||||||
inline internal::WithArgsAction<InnerAction$for j [[, k$j]]>
|
|
||||||
WithArgs(const InnerAction& action) {
|
|
||||||
return internal::WithArgsAction<InnerAction$for j [[, k$j]]>(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
]]
|
|
||||||
// Creates an action that does actions a1, a2, ..., sequentially in
|
|
||||||
// each invocation.
|
|
||||||
$range i 2..n
|
|
||||||
$for i [[
|
|
||||||
$range j 2..i
|
|
||||||
$var types = [[$for j, [[typename Action$j]]]]
|
|
||||||
$var Aas = [[$for j [[, Action$j a$j]]]]
|
|
||||||
|
|
||||||
template <typename Action1, $types>
|
|
||||||
$range k 1..i-1
|
|
||||||
|
|
||||||
inline $for k [[internal::DoBothAction<Action$k, ]]Action$i$for k [[>]]
|
|
||||||
|
|
||||||
DoAll(Action1 a1$Aas) {
|
|
||||||
$if i==2 [[
|
|
||||||
|
|
||||||
return internal::DoBothAction<Action1, Action2>(a1, a2);
|
|
||||||
]] $else [[
|
|
||||||
$range j2 2..i
|
|
||||||
|
|
||||||
return DoAll(a1, DoAll($for j2, [[a$j2]]));
|
|
||||||
]]
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
]]
|
|
||||||
|
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
// The ACTION* family of macros can be used in a namespace scope to
|
// The ACTION* family of macros can be used in a namespace scope to
|
||||||
@@ -348,16 +182,15 @@ $range j2 2..i
|
|||||||
//
|
//
|
||||||
// CAVEAT:
|
// CAVEAT:
|
||||||
//
|
//
|
||||||
// ACTION*() can only be used in a namespace scope. The reason is
|
// ACTION*() can only be used in a namespace scope as templates cannot be
|
||||||
// that C++ doesn't yet allow function-local types to be used to
|
// declared inside of a local class.
|
||||||
// instantiate templates. The up-coming C++0x standard will fix this.
|
// Users can, however, define any local functors (e.g. a lambda) that
|
||||||
// Once that's done, we'll consider supporting using ACTION*() inside
|
// can be used as actions.
|
||||||
// a function.
|
|
||||||
//
|
//
|
||||||
// MORE INFORMATION:
|
// MORE INFORMATION:
|
||||||
//
|
//
|
||||||
// To learn more about using these macros, please search for 'ACTION'
|
// To learn more about using these macros, please search for 'ACTION' on
|
||||||
// on http://code.google.com/p/googlemock/wiki/CookBook.
|
// https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md
|
||||||
|
|
||||||
$range i 0..n
|
$range i 0..n
|
||||||
$range k 0..n-1
|
$range k 0..n-1
|
||||||
@@ -366,7 +199,7 @@ $range k 0..n-1
|
|||||||
#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_\
|
#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_\
|
||||||
const args_type& args GTEST_ATTRIBUTE_UNUSED_
|
const args_type& args GTEST_ATTRIBUTE_UNUSED_
|
||||||
$for k [[, \
|
$for k [[, \
|
||||||
arg$k[[]]_type arg$k GTEST_ATTRIBUTE_UNUSED_]]
|
const arg$k[[]]_type& arg$k GTEST_ATTRIBUTE_UNUSED_]]
|
||||||
|
|
||||||
|
|
||||||
// Sometimes you want to give an action explicit template parameters
|
// Sometimes you want to give an action explicit template parameters
|
||||||
@@ -393,7 +226,7 @@ $for k [[, \
|
|||||||
// ACTION_TEMPLATE(DuplicateArg,
|
// ACTION_TEMPLATE(DuplicateArg,
|
||||||
// HAS_2_TEMPLATE_PARAMS(int, k, typename, T),
|
// HAS_2_TEMPLATE_PARAMS(int, k, typename, T),
|
||||||
// AND_1_VALUE_PARAMS(output)) {
|
// AND_1_VALUE_PARAMS(output)) {
|
||||||
// *output = T(::testing::get<k>(args));
|
// *output = T(::std::get<k>(args));
|
||||||
// }
|
// }
|
||||||
// ...
|
// ...
|
||||||
// int n;
|
// int n;
|
||||||
@@ -486,7 +319,7 @@ _VALUE_PARAMS($for j, [[p$j]]) $for j [[, typename p$j##_type]]
|
|||||||
$for i [[
|
$for i [[
|
||||||
$range j 0..i-1
|
$range j 0..i-1
|
||||||
#define GMOCK_INTERNAL_INIT_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]])\
|
#define GMOCK_INTERNAL_INIT_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]])\
|
||||||
($for j, [[p$j##_type gmock_p$j]])$if i>0 [[ : ]]$for j, [[p$j(gmock_p$j)]]
|
($for j, [[p$j##_type gmock_p$j]])$if i>0 [[ : ]]$for j, [[p$j(::std::move(gmock_p$j))]]
|
||||||
|
|
||||||
|
|
||||||
]]
|
]]
|
||||||
@@ -568,7 +401,7 @@ $range k 0..n-1
|
|||||||
}\
|
}\
|
||||||
template <$for k, [[typename arg$k[[]]_type]]>\
|
template <$for k, [[typename arg$k[[]]_type]]>\
|
||||||
return_type gmock_PerformImpl(const args_type& args[[]]
|
return_type gmock_PerformImpl(const args_type& args[[]]
|
||||||
$for k [[, arg$k[[]]_type arg$k]]) const;\
|
$for k [[, const arg$k[[]]_type& arg$k]]) const;\
|
||||||
GMOCK_INTERNAL_DEFN_##value_params\
|
GMOCK_INTERNAL_DEFN_##value_params\
|
||||||
private:\
|
private:\
|
||||||
GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
|
GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
|
||||||
@@ -619,7 +452,7 @@ $var class_name = [[name##Action[[$if i==0 [[]] $elif i==1 [[P]]
|
|||||||
$range j 0..i-1
|
$range j 0..i-1
|
||||||
$var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]]
|
$var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]]
|
||||||
$var param_types_and_names = [[$for j, [[p$j##_type p$j]]]]
|
$var param_types_and_names = [[$for j, [[p$j##_type p$j]]]]
|
||||||
$var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(gmock_p$j)]]]]]]
|
$var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(::std::forward<p$j##_type>(gmock_p$j))]]]]]]
|
||||||
$var param_field_decls = [[$for j
|
$var param_field_decls = [[$for j
|
||||||
[[
|
[[
|
||||||
|
|
||||||
@@ -633,7 +466,7 @@ $var param_field_decls2 = [[$for j
|
|||||||
$var params = [[$for j, [[p$j]]]]
|
$var params = [[$for j, [[p$j]]]]
|
||||||
$var param_types = [[$if i==0 [[]] $else [[<$for j, [[p$j##_type]]>]]]]
|
$var param_types = [[$if i==0 [[]] $else [[<$for j, [[p$j##_type]]>]]]]
|
||||||
$var typename_arg_types = [[$for k, [[typename arg$k[[]]_type]]]]
|
$var typename_arg_types = [[$for k, [[typename arg$k[[]]_type]]]]
|
||||||
$var arg_types_and_names = [[$for k, [[arg$k[[]]_type arg$k]]]]
|
$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]]
|
$var macro_name = [[$if i==0 [[ACTION]] $elif i==1 [[ACTION_P]]
|
||||||
$else [[ACTION_P$i]]]]
|
$else [[ACTION_P$i]]]]
|
||||||
|
|
||||||
@@ -757,7 +590,7 @@ ACTION_TEMPLATE(InvokeArgument,
|
|||||||
using internal::invoke_argument::InvokeArgumentAdl;
|
using internal::invoke_argument::InvokeArgumentAdl;
|
||||||
return InvokeArgumentAdl<return_type>(
|
return InvokeArgumentAdl<return_type>(
|
||||||
internal::invoke_argument::AdlTag(),
|
internal::invoke_argument::AdlTag(),
|
||||||
::testing::get<k>(args)$for j [[, p$j]]);
|
::std::get<k>(args)$for j [[, p$j]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
]]
|
]]
|
@@ -0,0 +1,752 @@
|
|||||||
|
// 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,6 +1,6 @@
|
|||||||
$$ -*- mode: c++; -*-
|
$$ -*- mode: c++; -*-
|
||||||
$$ This is a Pump source file. Please use Pump to convert it to
|
$$ This is a Pump source file. Please use Pump to convert
|
||||||
$$ gmock-generated-function-mockers.h.
|
$$ it to gmock-generated-function-mockers.h.
|
||||||
$$
|
$$
|
||||||
$var n = 10 $$ The maximum arity we support.
|
$var n = 10 $$ The maximum arity we support.
|
||||||
// Copyright 2007, Google Inc.
|
// Copyright 2007, Google Inc.
|
||||||
@@ -31,74 +31,79 @@ $var n = 10 $$ The maximum arity we support.
|
|||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
|
||||||
// Author: wan@google.com (Zhanyong Wan)
|
|
||||||
|
|
||||||
// Google Mock - a framework for writing C++ mock classes.
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
//
|
//
|
||||||
// This file implements function mockers of various arities.
|
// This file implements function mockers of various arities.
|
||||||
|
|
||||||
|
// GOOGLETEST_CM0002 DO NOT DELETE
|
||||||
|
|
||||||
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
||||||
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "gmock/gmock-spec-builders.h"
|
#include "gmock/gmock-spec-builders.h"
|
||||||
#include "gmock/internal/gmock-internal-utils.h"
|
#include "gmock/internal/gmock-internal-utils.h"
|
||||||
|
|
||||||
#if GTEST_HAS_STD_FUNCTION_
|
|
||||||
# include <functional>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template <typename F>
|
|
||||||
class FunctionMockerBase;
|
|
||||||
|
|
||||||
// Note: class FunctionMocker really belongs to the ::testing
|
|
||||||
// namespace. However if we define it in ::testing, MSVC will
|
|
||||||
// complain when classes in ::testing::internal declare it as a
|
|
||||||
// friend class template. To workaround this compiler bug, we define
|
|
||||||
// FunctionMocker in ::testing::internal and import it into ::testing.
|
|
||||||
template <typename F>
|
|
||||||
class FunctionMocker;
|
|
||||||
|
|
||||||
|
|
||||||
$range i 0..n
|
$range i 0..n
|
||||||
$for i [[
|
// Removes the given pointer; this is a helper for the expectation setter method
|
||||||
$range j 1..i
|
// for parameterless matchers.
|
||||||
$var typename_As = [[$for j [[, typename A$j]]]]
|
//
|
||||||
$var As = [[$for j, [[A$j]]]]
|
// We want to make sure that the user cannot set a parameterless expectation on
|
||||||
$var as = [[$for j, [[a$j]]]]
|
// overloaded methods, including methods which are overloaded on const. Example:
|
||||||
$var Aas = [[$for j, [[A$j a$j]]]]
|
//
|
||||||
$var ms = [[$for j, [[m$j]]]]
|
// class MockClass {
|
||||||
$var matchers = [[$for j, [[const Matcher<A$j>& m$j]]]]
|
// MOCK_METHOD0(GetName, string&());
|
||||||
template <typename R$typename_As>
|
// MOCK_CONST_METHOD0(GetName, const string&());
|
||||||
class FunctionMocker<R($As)> : public
|
// };
|
||||||
internal::FunctionMockerBase<R($As)> {
|
//
|
||||||
public:
|
// TEST() {
|
||||||
typedef R F($As);
|
// // This should be an error, as it's not clear which overload is expected.
|
||||||
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
MockSpec<F>& With($matchers) {
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
$if i >= 1 [[
|
|
||||||
this->current_spec().SetMatchers(::testing::make_tuple($ms));
|
|
||||||
|
|
||||||
]]
|
|
||||||
return this->current_spec();
|
|
||||||
}
|
|
||||||
|
|
||||||
R Invoke($Aas) {
|
|
||||||
// Even though gcc and MSVC don't enforce it, 'this->' is required
|
|
||||||
// by the C++ standard [14.6.4] here, as the base class type is
|
|
||||||
// dependent on the template argument (and thus shouldn't be
|
|
||||||
// looked into when resolving InvokeWith).
|
|
||||||
return this->InvokeWith(ArgumentTuple($as));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
]]
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
// The style guide prohibits "using" statements in a namespace scope
|
// The style guide prohibits "using" statements in a namespace scope
|
||||||
@@ -119,7 +124,7 @@ using internal::FunctionMocker;
|
|||||||
// The type of argument N of the given function type.
|
// The type of argument N of the given function type.
|
||||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
#define GMOCK_ARG_(tn, N, ...) \
|
#define GMOCK_ARG_(tn, N, ...) \
|
||||||
tn ::testing::internal::Function<__VA_ARGS__>::Argument##N
|
tn ::testing::internal::Function<__VA_ARGS__>::template Arg<N-1>::type
|
||||||
|
|
||||||
// The matcher type for argument N of the given function type.
|
// The matcher type for argument N of the given function type.
|
||||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
@@ -134,26 +139,33 @@ using internal::FunctionMocker;
|
|||||||
|
|
||||||
$for i [[
|
$for i [[
|
||||||
$range j 1..i
|
$range j 1..i
|
||||||
$var arg_as = [[$for j, \
|
$var arg_as = [[$for j, [[GMOCK_ARG_(tn, $j, __VA_ARGS__) gmock_a$j]]]]
|
||||||
[[GMOCK_ARG_(tn, $j, __VA_ARGS__) gmock_a$j]]]]
|
$var as = [[$for j, \
|
||||||
$var as = [[$for j, [[gmock_a$j]]]]
|
[[::std::forward<GMOCK_ARG_(tn, $j, __VA_ARGS__)>(gmock_a$j)]]]]
|
||||||
$var matcher_as = [[$for j, \
|
$var matcher_arg_as = [[$for j, \
|
||||||
[[GMOCK_MATCHER_(tn, $j, __VA_ARGS__) gmock_a$j]]]]
|
[[GMOCK_MATCHER_(tn, $j, __VA_ARGS__) gmock_a$j]]]]
|
||||||
|
$var matcher_as = [[$for j, [[gmock_a$j]]]]
|
||||||
|
$var anything_matchers = [[$for j, \
|
||||||
|
[[::testing::A<GMOCK_ARG_(tn, $j, __VA_ARGS__)>()]]]]
|
||||||
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
|
||||||
#define GMOCK_METHOD$i[[]]_(tn, constness, ct, Method, ...) \
|
#define GMOCK_METHOD$i[[]]_(tn, constness, ct, Method, ...) \
|
||||||
|
static_assert($i == ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, "MOCK_METHOD<N> must match argument count.");\
|
||||||
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \
|
||||||
$arg_as) constness { \
|
$arg_as) constness { \
|
||||||
GTEST_COMPILE_ASSERT_((::testing::tuple_size< \
|
|
||||||
tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value == $i), \
|
|
||||||
this_method_does_not_take_$i[[]]_argument[[$if i != 1 [[s]]]]); \
|
|
||||||
GMOCK_MOCKER_($i, constness, Method).SetOwnerAndName(this, #Method); \
|
GMOCK_MOCKER_($i, constness, Method).SetOwnerAndName(this, #Method); \
|
||||||
return GMOCK_MOCKER_($i, constness, Method).Invoke($as); \
|
return GMOCK_MOCKER_($i, constness, Method).Invoke($as); \
|
||||||
} \
|
} \
|
||||||
::testing::MockSpec<__VA_ARGS__>& \
|
::testing::MockSpec<__VA_ARGS__> \
|
||||||
gmock_##Method($matcher_as) constness { \
|
gmock_##Method($matcher_arg_as) constness { \
|
||||||
GMOCK_MOCKER_($i, constness, Method).RegisterOwner(this); \
|
GMOCK_MOCKER_($i, constness, Method).RegisterOwner(this); \
|
||||||
return GMOCK_MOCKER_($i, constness, Method).With($as); \
|
return GMOCK_MOCKER_($i, constness, Method).With($matcher_as); \
|
||||||
} \
|
} \
|
||||||
|
::testing::MockSpec<__VA_ARGS__> gmock_##Method( \
|
||||||
|
const ::testing::internal::WithoutMatchers&, \
|
||||||
|
constness ::testing::internal::Function<__VA_ARGS__>* ) const { \
|
||||||
|
return ::testing::internal::AdjustConstness_##constness(this)-> \
|
||||||
|
gmock_##Method($anything_matchers); \
|
||||||
|
} \
|
||||||
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_($i, constness, Method)
|
mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_($i, constness, Method)
|
||||||
|
|
||||||
|
|
||||||
@@ -210,82 +222,6 @@ $for i [[
|
|||||||
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
// A MockFunction<F> class has one mock method whose type is F. It is
|
|
||||||
// useful when you just want your test code to emit some messages and
|
|
||||||
// have Google Mock verify the right messages are sent (and perhaps at
|
|
||||||
// the right times). For example, if you are exercising code:
|
|
||||||
//
|
|
||||||
// Foo(1);
|
|
||||||
// Foo(2);
|
|
||||||
// Foo(3);
|
|
||||||
//
|
|
||||||
// and want to verify that Foo(1) and Foo(3) both invoke
|
|
||||||
// mock.Bar("a"), but Foo(2) doesn't invoke anything, you can write:
|
|
||||||
//
|
|
||||||
// TEST(FooTest, InvokesBarCorrectly) {
|
|
||||||
// MyMock mock;
|
|
||||||
// MockFunction<void(string check_point_name)> check;
|
|
||||||
// {
|
|
||||||
// InSequence s;
|
|
||||||
//
|
|
||||||
// EXPECT_CALL(mock, Bar("a"));
|
|
||||||
// EXPECT_CALL(check, Call("1"));
|
|
||||||
// EXPECT_CALL(check, Call("2"));
|
|
||||||
// EXPECT_CALL(mock, Bar("a"));
|
|
||||||
// }
|
|
||||||
// Foo(1);
|
|
||||||
// check.Call("1");
|
|
||||||
// Foo(2);
|
|
||||||
// check.Call("2");
|
|
||||||
// Foo(3);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// The expectation spec says that the first Bar("a") must happen
|
|
||||||
// before check point "1", the second Bar("a") must happen after check
|
|
||||||
// point "2", and nothing should happen between the two check
|
|
||||||
// points. The explicit check points make it easy to tell which
|
|
||||||
// Bar("a") is called by which call to Foo().
|
|
||||||
//
|
|
||||||
// MockFunction<F> can also be used to exercise code that accepts
|
|
||||||
// std::function<F> callbacks. To do so, use AsStdFunction() method
|
|
||||||
// to create std::function proxy forwarding to original object's Call.
|
|
||||||
// Example:
|
|
||||||
//
|
|
||||||
// TEST(FooTest, RunsCallbackWithBarArgument) {
|
|
||||||
// MockFunction<int(string)> callback;
|
|
||||||
// EXPECT_CALL(callback, Call("bar")).WillOnce(Return(1));
|
|
||||||
// Foo(callback.AsStdFunction());
|
|
||||||
// }
|
|
||||||
template <typename F>
|
|
||||||
class MockFunction;
|
|
||||||
|
|
||||||
|
|
||||||
$for i [[
|
|
||||||
$range j 0..i-1
|
|
||||||
$var ArgTypes = [[$for j, [[A$j]]]]
|
|
||||||
$var ArgNames = [[$for j, [[a$j]]]]
|
|
||||||
$var ArgDecls = [[$for j, [[A$j a$j]]]]
|
|
||||||
template <typename R$for j [[, typename A$j]]>
|
|
||||||
class MockFunction<R($ArgTypes)> {
|
|
||||||
public:
|
|
||||||
MockFunction() {}
|
|
||||||
|
|
||||||
MOCK_METHOD$i[[]]_T(Call, R($ArgTypes));
|
|
||||||
|
|
||||||
#if GTEST_HAS_STD_FUNCTION_
|
|
||||||
std::function<R($ArgTypes)> AsStdFunction() {
|
|
||||||
return [this]($ArgDecls) -> R {
|
|
||||||
return this->Call($ArgNames);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif // GTEST_HAS_STD_FUNCTION_
|
|
||||||
|
|
||||||
private:
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
]]
|
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
|
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
$$ -*- mode: c++; -*-
|
$$ -*- mode: c++; -*-
|
||||||
$$ This is a Pump source file. Please use Pump to convert it to
|
$$ This is a Pump source file. Please use Pump to convert
|
||||||
$$ gmock-generated-actions.h.
|
$$ it to gmock-generated-matchers.h.
|
||||||
$$
|
$$
|
||||||
$var n = 10 $$ The maximum arity we support.
|
$var n = 10 $$ The maximum arity we support.
|
||||||
$$ }} This line fixes auto-indentation of the following code in Emacs.
|
$$ }} This line fixes auto-indentation of the following code in Emacs.
|
||||||
@@ -37,343 +37,18 @@ $$ }} This line fixes auto-indentation of the following code in Emacs.
|
|||||||
//
|
//
|
||||||
// This file implements some commonly used variadic matchers.
|
// This file implements some commonly used variadic matchers.
|
||||||
|
|
||||||
|
// GOOGLETEST_CM0002 DO NOT DELETE
|
||||||
|
|
||||||
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
|
||||||
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
|
||||||
|
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "gmock/gmock-matchers.h"
|
#include "gmock/gmock-matchers.h"
|
||||||
|
|
||||||
namespace testing {
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
$range i 0..n-1
|
|
||||||
|
|
||||||
// The type of the i-th (0-based) field of Tuple.
|
|
||||||
#define GMOCK_FIELD_TYPE_(Tuple, i) \
|
|
||||||
typename ::testing::tuple_element<i, Tuple>::type
|
|
||||||
|
|
||||||
// TupleFields<Tuple, k0, ..., kn> is for selecting fields from a
|
|
||||||
// tuple of type Tuple. It has two members:
|
|
||||||
//
|
|
||||||
// type: a tuple type whose i-th field is the ki-th field of Tuple.
|
|
||||||
// GetSelectedFields(t): returns fields k0, ..., and kn of t as a tuple.
|
|
||||||
//
|
|
||||||
// For example, in class TupleFields<tuple<bool, char, int>, 2, 0>, we have:
|
|
||||||
//
|
|
||||||
// type is tuple<int, bool>, and
|
|
||||||
// GetSelectedFields(make_tuple(true, 'a', 42)) is (42, true).
|
|
||||||
|
|
||||||
template <class Tuple$for i [[, int k$i = -1]]>
|
|
||||||
class TupleFields;
|
|
||||||
|
|
||||||
// This generic version is used when there are $n selectors.
|
|
||||||
template <class Tuple$for i [[, int k$i]]>
|
|
||||||
class TupleFields {
|
|
||||||
public:
|
|
||||||
typedef ::testing::tuple<$for i, [[GMOCK_FIELD_TYPE_(Tuple, k$i)]]> type;
|
|
||||||
static type GetSelectedFields(const Tuple& t) {
|
|
||||||
return type($for i, [[get<k$i>(t)]]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// The following specialization is used for 0 ~ $(n-1) selectors.
|
|
||||||
|
|
||||||
$for i [[
|
|
||||||
$$ }}}
|
|
||||||
$range j 0..i-1
|
|
||||||
$range k 0..n-1
|
|
||||||
|
|
||||||
template <class Tuple$for j [[, int k$j]]>
|
|
||||||
class TupleFields<Tuple, $for k, [[$if k < i [[k$k]] $else [[-1]]]]> {
|
|
||||||
public:
|
|
||||||
typedef ::testing::tuple<$for j, [[GMOCK_FIELD_TYPE_(Tuple, k$j)]]> type;
|
|
||||||
static type GetSelectedFields(const Tuple& $if i==0 [[/* t */]] $else [[t]]) {
|
|
||||||
return type($for j, [[get<k$j>(t)]]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
]]
|
|
||||||
|
|
||||||
#undef GMOCK_FIELD_TYPE_
|
|
||||||
|
|
||||||
// Implements the Args() matcher.
|
|
||||||
|
|
||||||
$var ks = [[$for i, [[k$i]]]]
|
|
||||||
template <class ArgsTuple$for i [[, int k$i = -1]]>
|
|
||||||
class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> {
|
|
||||||
public:
|
|
||||||
// ArgsTuple may have top-level const or reference modifiers.
|
|
||||||
typedef GTEST_REMOVE_REFERENCE_AND_CONST_(ArgsTuple) RawArgsTuple;
|
|
||||||
typedef typename internal::TupleFields<RawArgsTuple, $ks>::type SelectedArgs;
|
|
||||||
typedef Matcher<const SelectedArgs&> MonomorphicInnerMatcher;
|
|
||||||
|
|
||||||
template <typename InnerMatcher>
|
|
||||||
explicit ArgsMatcherImpl(const InnerMatcher& inner_matcher)
|
|
||||||
: inner_matcher_(SafeMatcherCast<const SelectedArgs&>(inner_matcher)) {}
|
|
||||||
|
|
||||||
virtual bool MatchAndExplain(ArgsTuple args,
|
|
||||||
MatchResultListener* listener) const {
|
|
||||||
const SelectedArgs& selected_args = GetSelectedArgs(args);
|
|
||||||
if (!listener->IsInterested())
|
|
||||||
return inner_matcher_.Matches(selected_args);
|
|
||||||
|
|
||||||
PrintIndices(listener->stream());
|
|
||||||
*listener << "are " << PrintToString(selected_args);
|
|
||||||
|
|
||||||
StringMatchResultListener inner_listener;
|
|
||||||
const bool match = inner_matcher_.MatchAndExplain(selected_args,
|
|
||||||
&inner_listener);
|
|
||||||
PrintIfNotEmpty(inner_listener.str(), listener->stream());
|
|
||||||
return match;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void DescribeTo(::std::ostream* os) const {
|
|
||||||
*os << "are a tuple ";
|
|
||||||
PrintIndices(os);
|
|
||||||
inner_matcher_.DescribeTo(os);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void DescribeNegationTo(::std::ostream* os) const {
|
|
||||||
*os << "are a tuple ";
|
|
||||||
PrintIndices(os);
|
|
||||||
inner_matcher_.DescribeNegationTo(os);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static SelectedArgs GetSelectedArgs(ArgsTuple args) {
|
|
||||||
return TupleFields<RawArgsTuple, $ks>::GetSelectedFields(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prints the indices of the selected fields.
|
|
||||||
static void PrintIndices(::std::ostream* os) {
|
|
||||||
*os << "whose fields (";
|
|
||||||
const int indices[$n] = { $ks };
|
|
||||||
for (int i = 0; i < $n; i++) {
|
|
||||||
if (indices[i] < 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (i >= 1)
|
|
||||||
*os << ", ";
|
|
||||||
|
|
||||||
*os << "#" << indices[i];
|
|
||||||
}
|
|
||||||
*os << ") ";
|
|
||||||
}
|
|
||||||
|
|
||||||
const MonomorphicInnerMatcher inner_matcher_;
|
|
||||||
|
|
||||||
GTEST_DISALLOW_ASSIGN_(ArgsMatcherImpl);
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class InnerMatcher$for i [[, int k$i = -1]]>
|
|
||||||
class ArgsMatcher {
|
|
||||||
public:
|
|
||||||
explicit ArgsMatcher(const InnerMatcher& inner_matcher)
|
|
||||||
: inner_matcher_(inner_matcher) {}
|
|
||||||
|
|
||||||
template <typename ArgsTuple>
|
|
||||||
operator Matcher<ArgsTuple>() const {
|
|
||||||
return MakeMatcher(new ArgsMatcherImpl<ArgsTuple, $ks>(inner_matcher_));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const InnerMatcher inner_matcher_;
|
|
||||||
|
|
||||||
GTEST_DISALLOW_ASSIGN_(ArgsMatcher);
|
|
||||||
};
|
|
||||||
|
|
||||||
// A set of metafunctions for computing the result type of AllOf.
|
|
||||||
// AllOf(m1, ..., mN) returns
|
|
||||||
// AllOfResultN<decltype(m1), ..., decltype(mN)>::type.
|
|
||||||
|
|
||||||
// Although AllOf isn't defined for one argument, AllOfResult1 is defined
|
|
||||||
// to simplify the implementation.
|
|
||||||
template <typename M1>
|
|
||||||
struct AllOfResult1 {
|
|
||||||
typedef M1 type;
|
|
||||||
};
|
|
||||||
|
|
||||||
$range i 1..n
|
|
||||||
|
|
||||||
$range i 2..n
|
|
||||||
$for i [[
|
|
||||||
$range j 2..i
|
|
||||||
$var m = i/2
|
|
||||||
$range k 1..m
|
|
||||||
$range t m+1..i
|
|
||||||
|
|
||||||
template <typename M1$for j [[, typename M$j]]>
|
|
||||||
struct AllOfResult$i {
|
|
||||||
typedef BothOfMatcher<
|
|
||||||
typename AllOfResult$m<$for k, [[M$k]]>::type,
|
|
||||||
typename AllOfResult$(i-m)<$for t, [[M$t]]>::type
|
|
||||||
> type;
|
|
||||||
};
|
|
||||||
|
|
||||||
]]
|
|
||||||
|
|
||||||
// A set of metafunctions for computing the result type of AnyOf.
|
|
||||||
// AnyOf(m1, ..., mN) returns
|
|
||||||
// AnyOfResultN<decltype(m1), ..., decltype(mN)>::type.
|
|
||||||
|
|
||||||
// Although AnyOf isn't defined for one argument, AnyOfResult1 is defined
|
|
||||||
// to simplify the implementation.
|
|
||||||
template <typename M1>
|
|
||||||
struct AnyOfResult1 {
|
|
||||||
typedef M1 type;
|
|
||||||
};
|
|
||||||
|
|
||||||
$range i 1..n
|
|
||||||
|
|
||||||
$range i 2..n
|
|
||||||
$for i [[
|
|
||||||
$range j 2..i
|
|
||||||
$var m = i/2
|
|
||||||
$range k 1..m
|
|
||||||
$range t m+1..i
|
|
||||||
|
|
||||||
template <typename M1$for j [[, typename M$j]]>
|
|
||||||
struct AnyOfResult$i {
|
|
||||||
typedef EitherOfMatcher<
|
|
||||||
typename AnyOfResult$m<$for k, [[M$k]]>::type,
|
|
||||||
typename AnyOfResult$(i-m)<$for t, [[M$t]]>::type
|
|
||||||
> type;
|
|
||||||
};
|
|
||||||
|
|
||||||
]]
|
|
||||||
|
|
||||||
} // namespace internal
|
|
||||||
|
|
||||||
// Args<N1, N2, ..., Nk>(a_matcher) matches a tuple if the selected
|
|
||||||
// fields of it matches a_matcher. C++ doesn't support default
|
|
||||||
// arguments for function templates, so we have to overload it.
|
|
||||||
|
|
||||||
$range i 0..n
|
|
||||||
$for i [[
|
|
||||||
$range j 1..i
|
|
||||||
template <$for j [[int k$j, ]]typename InnerMatcher>
|
|
||||||
inline internal::ArgsMatcher<InnerMatcher$for j [[, k$j]]>
|
|
||||||
Args(const InnerMatcher& matcher) {
|
|
||||||
return internal::ArgsMatcher<InnerMatcher$for j [[, k$j]]>(matcher);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
]]
|
|
||||||
// ElementsAre(e_1, e_2, ... e_n) matches an STL-style container with
|
|
||||||
// n elements, where the i-th element in the container must
|
|
||||||
// match the i-th argument in the list. Each argument of
|
|
||||||
// ElementsAre() can be either a value or a matcher. We support up to
|
|
||||||
// $n arguments.
|
|
||||||
//
|
|
||||||
// The use of DecayArray in the implementation allows ElementsAre()
|
|
||||||
// to accept string literals, whose type is const char[N], but we
|
|
||||||
// want to treat them as const char*.
|
|
||||||
//
|
|
||||||
// NOTE: Since ElementsAre() cares about the order of the elements, it
|
|
||||||
// must not be used with containers whose elements's order is
|
|
||||||
// undefined (e.g. hash_map).
|
|
||||||
|
|
||||||
$range i 0..n
|
|
||||||
$for i [[
|
|
||||||
|
|
||||||
$range j 1..i
|
|
||||||
|
|
||||||
$if i>0 [[
|
|
||||||
|
|
||||||
template <$for j, [[typename T$j]]>
|
|
||||||
]]
|
|
||||||
|
|
||||||
inline internal::ElementsAreMatcher<
|
|
||||||
::testing::tuple<
|
|
||||||
$for j, [[
|
|
||||||
|
|
||||||
typename internal::DecayArray<T$j[[]]>::type]]> >
|
|
||||||
ElementsAre($for j, [[const T$j& e$j]]) {
|
|
||||||
typedef ::testing::tuple<
|
|
||||||
$for j, [[
|
|
||||||
|
|
||||||
typename internal::DecayArray<T$j[[]]>::type]]> Args;
|
|
||||||
return internal::ElementsAreMatcher<Args>(Args($for j, [[e$j]]));
|
|
||||||
}
|
|
||||||
|
|
||||||
]]
|
|
||||||
|
|
||||||
// UnorderedElementsAre(e_1, e_2, ..., e_n) is an ElementsAre extension
|
|
||||||
// that matches n elements in any order. We support up to n=$n arguments.
|
|
||||||
|
|
||||||
$range i 0..n
|
|
||||||
$for i [[
|
|
||||||
|
|
||||||
$range j 1..i
|
|
||||||
|
|
||||||
$if i>0 [[
|
|
||||||
|
|
||||||
template <$for j, [[typename T$j]]>
|
|
||||||
]]
|
|
||||||
|
|
||||||
inline internal::UnorderedElementsAreMatcher<
|
|
||||||
::testing::tuple<
|
|
||||||
$for j, [[
|
|
||||||
|
|
||||||
typename internal::DecayArray<T$j[[]]>::type]]> >
|
|
||||||
UnorderedElementsAre($for j, [[const T$j& e$j]]) {
|
|
||||||
typedef ::testing::tuple<
|
|
||||||
$for j, [[
|
|
||||||
|
|
||||||
typename internal::DecayArray<T$j[[]]>::type]]> Args;
|
|
||||||
return internal::UnorderedElementsAreMatcher<Args>(Args($for j, [[e$j]]));
|
|
||||||
}
|
|
||||||
|
|
||||||
]]
|
|
||||||
|
|
||||||
// AllOf(m1, m2, ..., mk) matches any value that matches all of the given
|
|
||||||
// sub-matchers. AllOf is called fully qualified to prevent ADL from firing.
|
|
||||||
|
|
||||||
$range i 2..n
|
|
||||||
$for i [[
|
|
||||||
$range j 1..i
|
|
||||||
$var m = i/2
|
|
||||||
$range k 1..m
|
|
||||||
$range t m+1..i
|
|
||||||
|
|
||||||
template <$for j, [[typename M$j]]>
|
|
||||||
inline typename internal::AllOfResult$i<$for j, [[M$j]]>::type
|
|
||||||
AllOf($for j, [[M$j m$j]]) {
|
|
||||||
return typename internal::AllOfResult$i<$for j, [[M$j]]>::type(
|
|
||||||
$if m == 1 [[m1]] $else [[::testing::AllOf($for k, [[m$k]])]],
|
|
||||||
$if m+1 == i [[m$i]] $else [[::testing::AllOf($for t, [[m$t]])]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
]]
|
|
||||||
|
|
||||||
// AnyOf(m1, m2, ..., mk) matches any value that matches any of the given
|
|
||||||
// sub-matchers. AnyOf is called fully qualified to prevent ADL from firing.
|
|
||||||
|
|
||||||
$range i 2..n
|
|
||||||
$for i [[
|
|
||||||
$range j 1..i
|
|
||||||
$var m = i/2
|
|
||||||
$range k 1..m
|
|
||||||
$range t m+1..i
|
|
||||||
|
|
||||||
template <$for j, [[typename M$j]]>
|
|
||||||
inline typename internal::AnyOfResult$i<$for j, [[M$j]]>::type
|
|
||||||
AnyOf($for j, [[M$j m$j]]) {
|
|
||||||
return typename internal::AnyOfResult$i<$for j, [[M$j]]>::type(
|
|
||||||
$if m == 1 [[m1]] $else [[::testing::AnyOf($for k, [[m$k]])]],
|
|
||||||
$if m+1 == i [[m$i]] $else [[::testing::AnyOf($for t, [[m$t]])]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
]]
|
|
||||||
|
|
||||||
} // namespace testing
|
|
||||||
$$ } // This Pump meta comment fixes auto-indentation in Emacs. It will not
|
|
||||||
$$ // show up in the generated code.
|
|
||||||
|
|
||||||
|
|
||||||
// The MATCHER* family of macros can be used in a namespace scope to
|
// The MATCHER* family of macros can be used in a namespace scope to
|
||||||
// define custom matchers easily.
|
// define custom matchers easily.
|
||||||
//
|
//
|
||||||
@@ -479,7 +154,7 @@ $$ // show up in the generated code.
|
|||||||
// using testing::PrintToString;
|
// using testing::PrintToString;
|
||||||
//
|
//
|
||||||
// MATCHER_P2(InClosedRange, low, hi,
|
// MATCHER_P2(InClosedRange, low, hi,
|
||||||
// string(negation ? "is not" : "is") + " in range [" +
|
// std::string(negation ? "is not" : "is") + " in range [" +
|
||||||
// PrintToString(low) + ", " + PrintToString(hi) + "]") {
|
// PrintToString(low) + ", " + PrintToString(hi) + "]") {
|
||||||
// return low <= arg && arg <= hi;
|
// return low <= arg && arg <= hi;
|
||||||
// }
|
// }
|
||||||
@@ -577,17 +252,15 @@ $$ // show up in the generated code.
|
|||||||
// overloading matchers based on parameter types (as opposed to just
|
// overloading matchers based on parameter types (as opposed to just
|
||||||
// based on the number of parameters).
|
// based on the number of parameters).
|
||||||
//
|
//
|
||||||
// MATCHER*() can only be used in a namespace scope. The reason is
|
// MATCHER*() can only be used in a namespace scope as templates cannot be
|
||||||
// that C++ doesn't yet allow function-local types to be used to
|
// declared inside of a local class.
|
||||||
// instantiate templates. The up-coming C++0x standard will fix this.
|
|
||||||
// Once that's done, we'll consider supporting using MATCHER*() inside
|
|
||||||
// a function.
|
|
||||||
//
|
//
|
||||||
// More Information
|
// More Information
|
||||||
// ================
|
// ================
|
||||||
//
|
//
|
||||||
// To learn more about using these macros, please search for 'MATCHER'
|
// To learn more about using these macros, please search for 'MATCHER'
|
||||||
// on http://code.google.com/p/googlemock/wiki/CookBook.
|
// on
|
||||||
|
// https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md
|
||||||
|
|
||||||
$range i 0..n
|
$range i 0..n
|
||||||
$for i
|
$for i
|
||||||
@@ -604,32 +277,34 @@ $var template = [[$if i==0 [[]] $else [[
|
|||||||
]]]]
|
]]]]
|
||||||
$var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]]
|
$var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]]
|
||||||
$var impl_ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]]
|
$var impl_ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]]
|
||||||
$var impl_inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(gmock_p$j)]]]]]]
|
$var impl_inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(::std::move(gmock_p$j))]]]]]]
|
||||||
$var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(gmock_p$j)]]]]]]
|
$var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(::std::move(gmock_p$j))]]]]]]
|
||||||
$var params = [[$for j, [[p$j]]]]
|
$var params = [[$for j, [[p$j]]]]
|
||||||
$var param_types = [[$if i==0 [[]] $else [[<$for j, [[p$j##_type]]>]]]]
|
$var param_types = [[$if i==0 [[]] $else [[<$for j, [[p$j##_type]]>]]]]
|
||||||
$var param_types_and_names = [[$for j, [[p$j##_type p$j]]]]
|
$var param_types_and_names = [[$for j, [[p$j##_type p$j]]]]
|
||||||
$var param_field_decls = [[$for j
|
$var param_field_decls = [[$for j
|
||||||
[[
|
[[
|
||||||
|
|
||||||
p$j##_type p$j;\
|
p$j##_type const p$j;\
|
||||||
]]]]
|
]]]]
|
||||||
$var param_field_decls2 = [[$for j
|
$var param_field_decls2 = [[$for j
|
||||||
[[
|
[[
|
||||||
|
|
||||||
p$j##_type p$j;\
|
p$j##_type const p$j;\
|
||||||
]]]]
|
]]]]
|
||||||
|
|
||||||
#define $macro_name(name$for j [[, p$j]], description)\$template
|
#define $macro_name(name$for j [[, p$j]], description)\$template
|
||||||
class $class_name {\
|
class $class_name {\
|
||||||
public:\
|
public:\
|
||||||
template <typename arg_type>\
|
template <typename arg_type>\
|
||||||
class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
|
class gmock_Impl : public ::testing::MatcherInterface<\
|
||||||
|
GTEST_REFERENCE_TO_CONST_(arg_type)> {\
|
||||||
public:\
|
public:\
|
||||||
[[$if i==1 [[explicit ]]]]gmock_Impl($impl_ctor_param_list)\
|
[[$if i==1 [[explicit ]]]]gmock_Impl($impl_ctor_param_list)\
|
||||||
$impl_inits {}\
|
$impl_inits {}\
|
||||||
virtual bool MatchAndExplain(\
|
virtual bool MatchAndExplain(\
|
||||||
arg_type arg, ::testing::MatchResultListener* result_listener) const;\
|
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||||
|
::testing::MatchResultListener* result_listener) const;\
|
||||||
virtual void DescribeTo(::std::ostream* gmock_os) const {\
|
virtual void DescribeTo(::std::ostream* gmock_os) const {\
|
||||||
*gmock_os << FormatDescription(false);\
|
*gmock_os << FormatDescription(false);\
|
||||||
}\
|
}\
|
||||||
@@ -637,16 +312,16 @@ $var param_field_decls2 = [[$for j
|
|||||||
*gmock_os << FormatDescription(true);\
|
*gmock_os << FormatDescription(true);\
|
||||||
}\$param_field_decls
|
}\$param_field_decls
|
||||||
private:\
|
private:\
|
||||||
::testing::internal::string FormatDescription(bool negation) const {\
|
::std::string FormatDescription(bool negation) const {\
|
||||||
const ::testing::internal::string gmock_description = (description);\
|
::std::string gmock_description = (description);\
|
||||||
if (!gmock_description.empty())\
|
if (!gmock_description.empty()) {\
|
||||||
return gmock_description;\
|
return gmock_description;\
|
||||||
|
}\
|
||||||
return ::testing::internal::FormatMatcherDescription(\
|
return ::testing::internal::FormatMatcherDescription(\
|
||||||
negation, #name, \
|
negation, #name, \
|
||||||
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
|
::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
|
||||||
::testing::tuple<$for j, [[p$j##_type]]>($for j, [[p$j]])));\
|
::std::tuple<$for j, [[p$j##_type]]>($for j, [[p$j]])));\
|
||||||
}\
|
}\
|
||||||
GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
|
|
||||||
};\
|
};\
|
||||||
template <typename arg_type>\
|
template <typename arg_type>\
|
||||||
operator ::testing::Matcher<arg_type>() const {\
|
operator ::testing::Matcher<arg_type>() const {\
|
||||||
@@ -656,14 +331,13 @@ $var param_field_decls2 = [[$for j
|
|||||||
[[$if i==1 [[explicit ]]]]$class_name($ctor_param_list)$inits {\
|
[[$if i==1 [[explicit ]]]]$class_name($ctor_param_list)$inits {\
|
||||||
}\$param_field_decls2
|
}\$param_field_decls2
|
||||||
private:\
|
private:\
|
||||||
GTEST_DISALLOW_ASSIGN_($class_name);\
|
|
||||||
};\$template
|
};\$template
|
||||||
inline $class_name$param_types name($param_types_and_names) {\
|
inline $class_name$param_types name($param_types_and_names) {\
|
||||||
return $class_name$param_types($params);\
|
return $class_name$param_types($params);\
|
||||||
}\$template
|
}\$template
|
||||||
template <typename arg_type>\
|
template <typename arg_type>\
|
||||||
bool $class_name$param_types::gmock_Impl<arg_type>::MatchAndExplain(\
|
bool $class_name$param_types::gmock_Impl<arg_type>::MatchAndExplain(\
|
||||||
arg_type arg, \
|
GTEST_REFERENCE_TO_CONST_(arg_type) arg,\
|
||||||
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
|
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
|
||||||
const
|
const
|
||||||
]]
|
]]
|
File diff suppressed because it is too large
Load Diff
@@ -26,70 +26,25 @@
|
|||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
|
||||||
// Author: wan@google.com (Zhanyong Wan)
|
|
||||||
|
|
||||||
// Google Mock - a framework for writing C++ mock classes.
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
//
|
//
|
||||||
// This file implements some actions that depend on gmock-generated-actions.h.
|
// 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_
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
|
||||||
#define GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
#include "gmock/gmock-generated-actions.h"
|
#include "gmock/gmock-generated-actions.h"
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
// Implements the Invoke(f) action. The template argument
|
|
||||||
// FunctionImpl is the implementation type of f, which can be either a
|
|
||||||
// function pointer or a functor. Invoke(f) can be used as an
|
|
||||||
// Action<F> as long as f's type is compatible with F (i.e. f can be
|
|
||||||
// assigned to a tr1::function<F>).
|
|
||||||
template <typename FunctionImpl>
|
|
||||||
class InvokeAction {
|
|
||||||
public:
|
|
||||||
// The c'tor makes a copy of function_impl (either a function
|
|
||||||
// pointer or a functor).
|
|
||||||
explicit InvokeAction(FunctionImpl function_impl)
|
|
||||||
: function_impl_(function_impl) {}
|
|
||||||
|
|
||||||
template <typename Result, typename ArgumentTuple>
|
|
||||||
Result Perform(const ArgumentTuple& args) {
|
|
||||||
return InvokeHelper<Result, ArgumentTuple>::Invoke(function_impl_, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
FunctionImpl function_impl_;
|
|
||||||
|
|
||||||
GTEST_DISALLOW_ASSIGN_(InvokeAction);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Implements the Invoke(object_ptr, &Class::Method) action.
|
|
||||||
template <class Class, typename MethodPtr>
|
|
||||||
class InvokeMethodAction {
|
|
||||||
public:
|
|
||||||
InvokeMethodAction(Class* obj_ptr, MethodPtr method_ptr)
|
|
||||||
: method_ptr_(method_ptr), obj_ptr_(obj_ptr) {}
|
|
||||||
|
|
||||||
template <typename Result, typename ArgumentTuple>
|
|
||||||
Result Perform(const ArgumentTuple& args) const {
|
|
||||||
return InvokeHelper<Result, ArgumentTuple>::InvokeMethod(
|
|
||||||
obj_ptr_, method_ptr_, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// The order of these members matters. Reversing the order can trigger
|
|
||||||
// warning C4121 in MSVC (see
|
|
||||||
// http://computer-programming-forum.com/7-vc.net/6fbc30265f860ad1.htm ).
|
|
||||||
const MethodPtr method_ptr_;
|
|
||||||
Class* const obj_ptr_;
|
|
||||||
|
|
||||||
GTEST_DISALLOW_ASSIGN_(InvokeMethodAction);
|
|
||||||
};
|
|
||||||
|
|
||||||
// An internal replacement for std::copy which mimics its behavior. This is
|
// An internal replacement for std::copy which mimics its behavior. This is
|
||||||
// necessary because Visual Studio deprecates ::std::copy, issuing warning 4996.
|
// necessary because Visual Studio deprecates ::std::copy, issuing warning 4996.
|
||||||
// However Visual Studio 2010 and later do not honor #pragmas which disable that
|
// However Visual Studio 2010 and later do not honor #pragmas which disable that
|
||||||
@@ -108,45 +63,6 @@ inline OutputIterator CopyElements(InputIterator first,
|
|||||||
|
|
||||||
// Various overloads for Invoke().
|
// Various overloads for Invoke().
|
||||||
|
|
||||||
// Creates an action that invokes 'function_impl' with the mock
|
|
||||||
// function's arguments.
|
|
||||||
template <typename FunctionImpl>
|
|
||||||
PolymorphicAction<internal::InvokeAction<FunctionImpl> > Invoke(
|
|
||||||
FunctionImpl function_impl) {
|
|
||||||
return MakePolymorphicAction(
|
|
||||||
internal::InvokeAction<FunctionImpl>(function_impl));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates an action that invokes the given method on the given object
|
|
||||||
// with the mock function's arguments.
|
|
||||||
template <class Class, typename MethodPtr>
|
|
||||||
PolymorphicAction<internal::InvokeMethodAction<Class, MethodPtr> > Invoke(
|
|
||||||
Class* obj_ptr, MethodPtr method_ptr) {
|
|
||||||
return MakePolymorphicAction(
|
|
||||||
internal::InvokeMethodAction<Class, MethodPtr>(obj_ptr, method_ptr));
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithoutArgs(inner_action) can be used in a mock function with a
|
|
||||||
// non-empty argument list to perform inner_action, which takes no
|
|
||||||
// argument. In other words, it adapts an action accepting no
|
|
||||||
// argument to one that accepts (and ignores) arguments.
|
|
||||||
template <typename InnerAction>
|
|
||||||
inline internal::WithArgsAction<InnerAction>
|
|
||||||
WithoutArgs(const InnerAction& action) {
|
|
||||||
return internal::WithArgsAction<InnerAction>(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithArg<k>(an_action) creates an action that passes the k-th
|
|
||||||
// (0-based) argument of the mock function to an_action and performs
|
|
||||||
// it. It adapts an action accepting one argument to one that accepts
|
|
||||||
// multiple arguments. For convenience, we also provide
|
|
||||||
// WithArgs<k>(an_action) (defined below) as a synonym.
|
|
||||||
template <int k, typename InnerAction>
|
|
||||||
inline internal::WithArgsAction<InnerAction, k>
|
|
||||||
WithArg(const InnerAction& action) {
|
|
||||||
return internal::WithArgsAction<InnerAction, k>(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The ACTION*() macros trigger warning C4100 (unreferenced formal
|
// The ACTION*() macros trigger warning C4100 (unreferenced formal
|
||||||
// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in
|
// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in
|
||||||
// the macro definition, as the warnings are generated when the macro
|
// the macro definition, as the warnings are generated when the macro
|
||||||
@@ -161,7 +77,7 @@ WithArg(const InnerAction& action) {
|
|||||||
ACTION_TEMPLATE(ReturnArg,
|
ACTION_TEMPLATE(ReturnArg,
|
||||||
HAS_1_TEMPLATE_PARAMS(int, k),
|
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||||
AND_0_VALUE_PARAMS()) {
|
AND_0_VALUE_PARAMS()) {
|
||||||
return ::testing::get<k>(args);
|
return ::std::get<k>(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Action SaveArg<k>(pointer) saves the k-th (0-based) argument of the
|
// Action SaveArg<k>(pointer) saves the k-th (0-based) argument of the
|
||||||
@@ -169,7 +85,7 @@ ACTION_TEMPLATE(ReturnArg,
|
|||||||
ACTION_TEMPLATE(SaveArg,
|
ACTION_TEMPLATE(SaveArg,
|
||||||
HAS_1_TEMPLATE_PARAMS(int, k),
|
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||||
AND_1_VALUE_PARAMS(pointer)) {
|
AND_1_VALUE_PARAMS(pointer)) {
|
||||||
*pointer = ::testing::get<k>(args);
|
*pointer = ::std::get<k>(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Action SaveArgPointee<k>(pointer) saves the value pointed to
|
// Action SaveArgPointee<k>(pointer) saves the value pointed to
|
||||||
@@ -177,7 +93,7 @@ ACTION_TEMPLATE(SaveArg,
|
|||||||
ACTION_TEMPLATE(SaveArgPointee,
|
ACTION_TEMPLATE(SaveArgPointee,
|
||||||
HAS_1_TEMPLATE_PARAMS(int, k),
|
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||||
AND_1_VALUE_PARAMS(pointer)) {
|
AND_1_VALUE_PARAMS(pointer)) {
|
||||||
*pointer = *::testing::get<k>(args);
|
*pointer = *::std::get<k>(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Action SetArgReferee<k>(value) assigns 'value' to the variable
|
// Action SetArgReferee<k>(value) assigns 'value' to the variable
|
||||||
@@ -185,13 +101,13 @@ ACTION_TEMPLATE(SaveArgPointee,
|
|||||||
ACTION_TEMPLATE(SetArgReferee,
|
ACTION_TEMPLATE(SetArgReferee,
|
||||||
HAS_1_TEMPLATE_PARAMS(int, k),
|
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||||
AND_1_VALUE_PARAMS(value)) {
|
AND_1_VALUE_PARAMS(value)) {
|
||||||
typedef typename ::testing::tuple_element<k, args_type>::type argk_type;
|
typedef typename ::std::tuple_element<k, args_type>::type argk_type;
|
||||||
// Ensures that argument #k is a reference. If you get a compiler
|
// Ensures that argument #k is a reference. If you get a compiler
|
||||||
// error on the next line, you are using SetArgReferee<k>(value) in
|
// 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.
|
// a mock function whose k-th (0-based) argument is not a reference.
|
||||||
GTEST_COMPILE_ASSERT_(internal::is_reference<argk_type>::value,
|
GTEST_COMPILE_ASSERT_(std::is_reference<argk_type>::value,
|
||||||
SetArgReferee_must_be_used_with_a_reference_argument);
|
SetArgReferee_must_be_used_with_a_reference_argument);
|
||||||
::testing::get<k>(args) = value;
|
::std::get<k>(args) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Action SetArrayArgument<k>(first, last) copies the elements in
|
// Action SetArrayArgument<k>(first, last) copies the elements in
|
||||||
@@ -204,9 +120,9 @@ ACTION_TEMPLATE(SetArrayArgument,
|
|||||||
AND_2_VALUE_PARAMS(first, last)) {
|
AND_2_VALUE_PARAMS(first, last)) {
|
||||||
// Visual Studio deprecates ::std::copy, so we use our own copy in that case.
|
// Visual Studio deprecates ::std::copy, so we use our own copy in that case.
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
internal::CopyElements(first, last, ::testing::get<k>(args));
|
internal::CopyElements(first, last, ::std::get<k>(args));
|
||||||
#else
|
#else
|
||||||
::std::copy(first, last, ::testing::get<k>(args));
|
::std::copy(first, last, ::std::get<k>(args));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,7 +131,7 @@ ACTION_TEMPLATE(SetArrayArgument,
|
|||||||
ACTION_TEMPLATE(DeleteArg,
|
ACTION_TEMPLATE(DeleteArg,
|
||||||
HAS_1_TEMPLATE_PARAMS(int, k),
|
HAS_1_TEMPLATE_PARAMS(int, k),
|
||||||
AND_0_VALUE_PARAMS()) {
|
AND_0_VALUE_PARAMS()) {
|
||||||
delete ::testing::get<k>(args);
|
delete ::std::get<k>(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This action returns the value pointed to by 'pointer'.
|
// This action returns the value pointed to by 'pointer'.
|
@@ -26,8 +26,7 @@
|
|||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
|
||||||
// Author: marcus.boerger@google.com (Marcus Boerger)
|
|
||||||
|
|
||||||
// Google Mock - a framework for writing C++ mock classes.
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
//
|
//
|
||||||
@@ -36,13 +35,27 @@
|
|||||||
// Note that tests are implemented in gmock-matchers_test.cc rather than
|
// Note that tests are implemented in gmock-matchers_test.cc rather than
|
||||||
// gmock-more-matchers-test.cc.
|
// gmock-more-matchers-test.cc.
|
||||||
|
|
||||||
#ifndef GMOCK_GMOCK_MORE_MATCHERS_H_
|
// GOOGLETEST_CM0002 DO NOT DELETE
|
||||||
#define GMOCK_GMOCK_MORE_MATCHERS_H_
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_MORE_MATCHERS_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_MORE_MATCHERS_H_
|
||||||
|
|
||||||
#include "gmock/gmock-generated-matchers.h"
|
#include "gmock/gmock-generated-matchers.h"
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
|
// Silence C4100 (unreferenced formal
|
||||||
|
// parameter) for MSVC
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(push)
|
||||||
|
# pragma warning(disable:4100)
|
||||||
|
#if (_MSC_VER == 1900)
|
||||||
|
// and silence C4800 (C4800: 'int *const ': forcing value
|
||||||
|
// to bool 'true' or 'false') for MSVC 14
|
||||||
|
# pragma warning(disable:4800)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
// Defines a matcher that matches an empty container. The container must
|
// Defines a matcher that matches an empty container. The container must
|
||||||
// support both size() and empty(), which all STL-like containers provide.
|
// support both size() and empty(), which all STL-like containers provide.
|
||||||
MATCHER(IsEmpty, negation ? "isn't empty" : "is empty") {
|
MATCHER(IsEmpty, negation ? "isn't empty" : "is empty") {
|
||||||
@@ -53,6 +66,27 @@ MATCHER(IsEmpty, negation ? "isn't empty" : "is empty") {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Define a matcher that matches a value that evaluates in boolean
|
||||||
|
// context to true. Useful for types that define "explicit operator
|
||||||
|
// bool" operators and so can't be compared for equality with true
|
||||||
|
// and false.
|
||||||
|
MATCHER(IsTrue, negation ? "is false" : "is true") {
|
||||||
|
return static_cast<bool>(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define a matcher that matches a value that evaluates in boolean
|
||||||
|
// context to false. Useful for types that define "explicit operator
|
||||||
|
// bool" operators and so can't be compared for equality with true
|
||||||
|
// and false.
|
||||||
|
MATCHER(IsFalse, negation ? "is true" : "is false") {
|
||||||
|
return !static_cast<bool>(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
#endif // GMOCK_GMOCK_MORE_MATCHERS_H_
|
#endif // GMOCK_INCLUDE_GMOCK_MORE_MATCHERS_H_
|
@@ -1,8 +1,3 @@
|
|||||||
$$ -*- mode: c++; -*-
|
|
||||||
$$ This is a Pump source file. Please use Pump to convert it to
|
|
||||||
$$ gmock-generated-nice-strict.h.
|
|
||||||
$$
|
|
||||||
$var n = 10 $$ The maximum arity we support.
|
|
||||||
// Copyright 2008, Google Inc.
|
// Copyright 2008, Google Inc.
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
@@ -31,8 +26,7 @@ $var n = 10 $$ The maximum arity we support.
|
|||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
|
||||||
// Author: wan@google.com (Zhanyong Wan)
|
|
||||||
|
|
||||||
// Implements class templates NiceMock, NaggyMock, and StrictMock.
|
// Implements class templates NiceMock, NaggyMock, and StrictMock.
|
||||||
//
|
//
|
||||||
@@ -52,10 +46,9 @@ $var n = 10 $$ The maximum arity we support.
|
|||||||
// NiceMock<MockFoo>.
|
// NiceMock<MockFoo>.
|
||||||
//
|
//
|
||||||
// NiceMock, NaggyMock, and StrictMock "inherit" the constructors of
|
// NiceMock, NaggyMock, and StrictMock "inherit" the constructors of
|
||||||
// their respective base class, with up-to $n arguments. Therefore
|
// their respective base class. Therefore you can write
|
||||||
// you can write NiceMock<MockFoo>(5, "a") to construct a nice mock
|
// NiceMock<MockFoo>(5, "a") to construct a nice mock where MockFoo
|
||||||
// where MockFoo has a constructor that accepts (int, const char*),
|
// has a constructor that accepts (int, const char*), for example.
|
||||||
// for example.
|
|
||||||
//
|
//
|
||||||
// A known limitation is that NiceMock<MockFoo>, NaggyMock<MockFoo>,
|
// A known limitation is that NiceMock<MockFoo>, NaggyMock<MockFoo>,
|
||||||
// and StrictMock<MockFoo> only works for mock methods defined using
|
// and StrictMock<MockFoo> only works for mock methods defined using
|
||||||
@@ -64,69 +57,130 @@ $var n = 10 $$ The maximum arity we support.
|
|||||||
// or "strict" modifier may not affect it, depending on the compiler.
|
// or "strict" modifier may not affect it, depending on the compiler.
|
||||||
// In particular, nesting NiceMock, NaggyMock, and StrictMock is NOT
|
// In particular, nesting NiceMock, NaggyMock, and StrictMock is NOT
|
||||||
// supported.
|
// supported.
|
||||||
//
|
|
||||||
// Another known limitation is that the constructors of the base mock
|
|
||||||
// cannot have arguments passed by non-const reference, which are
|
|
||||||
// banned by the Google C++ style guide anyway.
|
|
||||||
|
|
||||||
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
|
// GOOGLETEST_CM0002 DO NOT DELETE
|
||||||
#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
|
|
||||||
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_NICE_STRICT_H_
|
||||||
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_NICE_STRICT_H_
|
||||||
|
|
||||||
#include "gmock/gmock-spec-builders.h"
|
#include "gmock/gmock-spec-builders.h"
|
||||||
#include "gmock/internal/gmock-port.h"
|
#include "gmock/internal/gmock-port.h"
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
$range kind 0..2
|
|
||||||
$for kind [[
|
|
||||||
|
|
||||||
$var clazz=[[$if kind==0 [[NiceMock]]
|
|
||||||
$elif kind==1 [[NaggyMock]]
|
|
||||||
$else [[StrictMock]]]]
|
|
||||||
|
|
||||||
$var method=[[$if kind==0 [[AllowUninterestingCalls]]
|
|
||||||
$elif kind==1 [[WarnUninterestingCalls]]
|
|
||||||
$else [[FailUninterestingCalls]]]]
|
|
||||||
|
|
||||||
template <class MockClass>
|
template <class MockClass>
|
||||||
class $clazz : public MockClass {
|
class NiceMock : public MockClass {
|
||||||
public:
|
public:
|
||||||
// We don't factor out the constructor body to a common method, as
|
NiceMock() : MockClass() {
|
||||||
// we have to avoid a possible clash with members of MockClass.
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
$clazz() {
|
|
||||||
::testing::Mock::$method(
|
|
||||||
internal::ImplicitCast_<MockClass*>(this));
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
// C++ doesn't (yet) allow inheritance of constructors, so we have
|
// Ideally, we would inherit base class's constructors through a using
|
||||||
// to define it for each arity.
|
// declaration, which would preserve their visibility. However, many existing
|
||||||
template <typename A1>
|
// tests rely on the fact that current implementation reexports protected
|
||||||
explicit $clazz(const A1& a1) : MockClass(a1) {
|
// constructors as public. These tests would need to be cleaned up first.
|
||||||
::testing::Mock::$method(
|
|
||||||
|
// Single argument constructor is special-cased so that it can be
|
||||||
|
// made explicit.
|
||||||
|
template <typename A>
|
||||||
|
explicit NiceMock(A&& arg) : MockClass(std::forward<A>(arg)) {
|
||||||
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
internal::ImplicitCast_<MockClass*>(this));
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
$range i 2..n
|
template <typename A1, typename A2, typename... An>
|
||||||
$for i [[
|
NiceMock(A1&& arg1, A2&& arg2, An&&... args)
|
||||||
$range j 1..i
|
: MockClass(std::forward<A1>(arg1), std::forward<A2>(arg2),
|
||||||
template <$for j, [[typename A$j]]>
|
std::forward<An>(args)...) {
|
||||||
$clazz($for j, [[const A$j& a$j]]) : MockClass($for j, [[a$j]]) {
|
::testing::Mock::AllowUninterestingCalls(
|
||||||
::testing::Mock::$method(
|
|
||||||
internal::ImplicitCast_<MockClass*>(this));
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~NiceMock() { // NOLINT
|
||||||
]]
|
|
||||||
virtual ~$clazz() {
|
|
||||||
::testing::Mock::UnregisterCallReaction(
|
::testing::Mock::UnregisterCallReaction(
|
||||||
internal::ImplicitCast_<MockClass*>(this));
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_($clazz);
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(NiceMock);
|
||||||
};
|
};
|
||||||
|
|
||||||
]]
|
template <class MockClass>
|
||||||
|
class NaggyMock : public MockClass {
|
||||||
|
public:
|
||||||
|
NaggyMock() : MockClass() {
|
||||||
|
::testing::Mock::WarnUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ideally, we would inherit base class's constructors through a using
|
||||||
|
// declaration, which would preserve their visibility. However, many existing
|
||||||
|
// tests rely on the fact that current implementation reexports protected
|
||||||
|
// constructors as public. These tests would need to be cleaned up first.
|
||||||
|
|
||||||
|
// Single argument constructor is special-cased so that it can be
|
||||||
|
// made explicit.
|
||||||
|
template <typename A>
|
||||||
|
explicit NaggyMock(A&& arg) : MockClass(std::forward<A>(arg)) {
|
||||||
|
::testing::Mock::WarnUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename... An>
|
||||||
|
NaggyMock(A1&& arg1, A2&& arg2, An&&... args)
|
||||||
|
: MockClass(std::forward<A1>(arg1), std::forward<A2>(arg2),
|
||||||
|
std::forward<An>(args)...) {
|
||||||
|
::testing::Mock::WarnUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
~NaggyMock() { // NOLINT
|
||||||
|
::testing::Mock::UnregisterCallReaction(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(NaggyMock);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class MockClass>
|
||||||
|
class StrictMock : public MockClass {
|
||||||
|
public:
|
||||||
|
StrictMock() : MockClass() {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ideally, we would inherit base class's constructors through a using
|
||||||
|
// declaration, which would preserve their visibility. However, many existing
|
||||||
|
// tests rely on the fact that current implementation reexports protected
|
||||||
|
// constructors as public. These tests would need to be cleaned up first.
|
||||||
|
|
||||||
|
// Single argument constructor is special-cased so that it can be
|
||||||
|
// made explicit.
|
||||||
|
template <typename A>
|
||||||
|
explicit StrictMock(A&& arg) : MockClass(std::forward<A>(arg)) {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A1, typename A2, typename... An>
|
||||||
|
StrictMock(A1&& arg1, A2&& arg2, An&&... args)
|
||||||
|
: MockClass(std::forward<A1>(arg1), std::forward<A2>(arg2),
|
||||||
|
std::forward<An>(args)...) {
|
||||||
|
::testing::Mock::FailUninterestingCalls(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
~StrictMock() { // NOLINT
|
||||||
|
::testing::Mock::UnregisterCallReaction(
|
||||||
|
internal::ImplicitCast_<MockClass*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(StrictMock);
|
||||||
|
};
|
||||||
|
|
||||||
// The following specializations catch some (relatively more common)
|
// The following specializations catch some (relatively more common)
|
||||||
// user errors of nesting nice and strict mocks. They do NOT catch
|
// user errors of nesting nice and strict mocks. They do NOT catch
|
||||||
@@ -158,4 +212,4 @@ class StrictMock<StrictMock<MockClass> >;
|
|||||||
|
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_NICE_STRICT_H_
|
File diff suppressed because it is too large
Load Diff
@@ -26,26 +26,27 @@
|
|||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
|
||||||
// Author: wan@google.com (Zhanyong Wan)
|
|
||||||
|
|
||||||
// Google Mock - a framework for writing C++ mock classes.
|
// Google Mock - a framework for writing C++ mock classes.
|
||||||
//
|
//
|
||||||
// This is the main header file a user should include.
|
// This is the main header file a user should include.
|
||||||
|
|
||||||
|
// GOOGLETEST_CM0002 DO NOT DELETE
|
||||||
|
|
||||||
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_H_
|
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_H_
|
||||||
#define GMOCK_INCLUDE_GMOCK_GMOCK_H_
|
#define GMOCK_INCLUDE_GMOCK_GMOCK_H_
|
||||||
|
|
||||||
// This file implements the following syntax:
|
// This file implements the following syntax:
|
||||||
//
|
//
|
||||||
// ON_CALL(mock_object.Method(...))
|
// ON_CALL(mock_object, Method(...))
|
||||||
// .With(...) ?
|
// .With(...) ?
|
||||||
// .WillByDefault(...);
|
// .WillByDefault(...);
|
||||||
//
|
//
|
||||||
// where With() is optional and WillByDefault() must appear exactly
|
// where With() is optional and WillByDefault() must appear exactly
|
||||||
// once.
|
// once.
|
||||||
//
|
//
|
||||||
// EXPECT_CALL(mock_object.Method(...))
|
// EXPECT_CALL(mock_object, Method(...))
|
||||||
// .With(...) ?
|
// .With(...) ?
|
||||||
// .Times(...) ?
|
// .Times(...) ?
|
||||||
// .InSequence(...) *
|
// .InSequence(...) *
|
||||||
@@ -57,13 +58,14 @@
|
|||||||
|
|
||||||
#include "gmock/gmock-actions.h"
|
#include "gmock/gmock-actions.h"
|
||||||
#include "gmock/gmock-cardinalities.h"
|
#include "gmock/gmock-cardinalities.h"
|
||||||
|
#include "gmock/gmock-function-mocker.h"
|
||||||
#include "gmock/gmock-generated-actions.h"
|
#include "gmock/gmock-generated-actions.h"
|
||||||
#include "gmock/gmock-generated-function-mockers.h"
|
#include "gmock/gmock-generated-function-mockers.h"
|
||||||
#include "gmock/gmock-generated-nice-strict.h"
|
|
||||||
#include "gmock/gmock-generated-matchers.h"
|
#include "gmock/gmock-generated-matchers.h"
|
||||||
#include "gmock/gmock-matchers.h"
|
#include "gmock/gmock-matchers.h"
|
||||||
#include "gmock/gmock-more-actions.h"
|
#include "gmock/gmock-more-actions.h"
|
||||||
#include "gmock/gmock-more-matchers.h"
|
#include "gmock/gmock-more-matchers.h"
|
||||||
|
#include "gmock/gmock-nice-strict.h"
|
||||||
#include "gmock/internal/gmock-internal-utils.h"
|
#include "gmock/internal/gmock-internal-utils.h"
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
@@ -71,6 +73,7 @@ namespace testing {
|
|||||||
// Declares Google Mock flags that we want a user to use programmatically.
|
// Declares Google Mock flags that we want a user to use programmatically.
|
||||||
GMOCK_DECLARE_bool_(catch_leaked_mocks);
|
GMOCK_DECLARE_bool_(catch_leaked_mocks);
|
||||||
GMOCK_DECLARE_string_(verbose);
|
GMOCK_DECLARE_string_(verbose);
|
||||||
|
GMOCK_DECLARE_int32_(default_mock_behavior);
|
||||||
|
|
||||||
// Initializes Google Mock. This must be called before running the
|
// Initializes Google Mock. This must be called before running the
|
||||||
// tests. In particular, it parses the command line for the flags
|
// tests. In particular, it parses the command line for the flags
|
||||||
@@ -89,6 +92,10 @@ GTEST_API_ void InitGoogleMock(int* argc, char** argv);
|
|||||||
// UNICODE mode.
|
// UNICODE mode.
|
||||||
GTEST_API_ void InitGoogleMock(int* argc, wchar_t** argv);
|
GTEST_API_ void InitGoogleMock(int* argc, wchar_t** argv);
|
||||||
|
|
||||||
|
// This overloaded version can be used on Arduino/embedded platforms where
|
||||||
|
// there is no argc/argv.
|
||||||
|
GTEST_API_ void InitGoogleMock();
|
||||||
|
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_H_
|
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_H_
|
@@ -0,0 +1,16 @@
|
|||||||
|
# Customization Points
|
||||||
|
|
||||||
|
The custom directory is an injection point for custom user configurations.
|
||||||
|
|
||||||
|
## Header `gmock-port.h`
|
||||||
|
|
||||||
|
The following macros can be defined:
|
||||||
|
|
||||||
|
### Flag related macros:
|
||||||
|
|
||||||
|
* `GMOCK_DECLARE_bool_(name)`
|
||||||
|
* `GMOCK_DECLARE_int32_(name)`
|
||||||
|
* `GMOCK_DECLARE_string_(name)`
|
||||||
|
* `GMOCK_DEFINE_bool_(name, default_val, doc)`
|
||||||
|
* `GMOCK_DEFINE_int32_(name, default_val, doc)`
|
||||||
|
* `GMOCK_DEFINE_string_(name, default_val, doc)`
|
@@ -2,6 +2,8 @@
|
|||||||
// pump.py gmock-generated-actions.h.pump
|
// pump.py gmock-generated-actions.h.pump
|
||||||
// DO NOT EDIT BY HAND!!!
|
// DO NOT EDIT BY HAND!!!
|
||||||
|
|
||||||
|
// GOOGLETEST_CM0002 DO NOT DELETE
|
||||||
|
|
||||||
#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
|
#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
|
||||||
#define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
|
#define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user