mirror of
https://github.com/jbeder/yaml-cpp.git
synced 2025-09-09 12:41:17 +00:00
Compare commits
1 Commits
master
...
revert-984
Author | SHA1 | Date | |
---|---|---|---|
![]() |
54e63e3f8c |
@@ -1 +0,0 @@
|
||||
test/googletest-1.13.0
|
@@ -8,7 +8,7 @@ EXAMPLE_PATH =
|
||||
|
||||
# One or more directories and files to exclude from documentation generation.
|
||||
# Use relative paths with respect to the repository root directory.
|
||||
EXCLUDE = test/googletest-1.13.0/
|
||||
EXCLUDE = test/gtest-1.8.0/
|
||||
|
||||
# One or more wildcard patterns to exclude files and directories from document
|
||||
# generation.
|
||||
|
11
.github/dependabot.yml
vendored
11
.github/dependabot.yml
vendored
@@ -1,11 +0,0 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
groups:
|
||||
github-actions:
|
||||
patterns:
|
||||
- "*"
|
||||
|
141
.github/workflows/build.yml
vendored
141
.github/workflows/build.yml
vendored
@@ -1,141 +0,0 @@
|
||||
name: Github PR
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
workflow_dispatch:
|
||||
permissions: read-all
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
jobs:
|
||||
cmake-build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
cxx_standard: [11, 17, 20]
|
||||
build: [static, shared]
|
||||
googletest: [build, system]
|
||||
generator: ["Default Generator", "MinGW Makefiles"]
|
||||
exclude:
|
||||
- os: ubuntu-latest
|
||||
cxx_standard: 11
|
||||
googletest: system
|
||||
- os: macos-latest
|
||||
build: shared
|
||||
- os: macos-latest
|
||||
generator: "MinGW Makefiles"
|
||||
- os: ubuntu-latest
|
||||
generator: "MinGW Makefiles"
|
||||
- os: macos-latest
|
||||
googletest: system
|
||||
- os: windows-latest
|
||||
googletest: system
|
||||
env:
|
||||
YAML_BUILD_SHARED_LIBS: ${{ matrix.build == 'shared' && 'ON' || 'OFF' }}
|
||||
YAML_USE_SYSTEM_GTEST: ${{ matrix.googletest == 'system' && 'ON' || 'OFF' }}
|
||||
CMAKE_GENERATOR: >-
|
||||
${{format(matrix.generator != 'Default Generator' && '-G "{0}"' || '', matrix.generator)}}
|
||||
CMAKE_INSTALL_PREFIX: "${{ github.workspace }}/install-prefix"
|
||||
CMAKE_BUILD_TYPE: Debug
|
||||
CMAKE_CXX_FLAGS_DEBUG: ${{ matrix.googletest == 'build' && '-g -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC' || '-g' }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
|
||||
- uses: awalsh128/cache-apt-pkgs-action@latest
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
with:
|
||||
packages: googletest libgmock-dev libgtest-dev
|
||||
version: 1.0
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
cmake \
|
||||
${{ env.CMAKE_GENERATOR }} \
|
||||
-S "${{ github.workspace }}" \
|
||||
-B build \
|
||||
-D CMAKE_CXX_STANDARD=${{ matrix.cxx_standard }} \
|
||||
-D CMAKE_INSTALL_PREFIX="${{ env.CMAKE_INSTALL_PREFIX }}" \
|
||||
-D CMAKE_BUILD_TYPE=${{ env.CMAKE_BUILD_TYPE }} \
|
||||
-D CMAKE_CXX_FLAGS_DEBUG="${{ env.CMAKE_CXX_FLAGS_DEBUG }}" \
|
||||
-D YAML_BUILD_SHARED_LIBS=${{ env.YAML_BUILD_SHARED_LIBS }} \
|
||||
-D YAML_USE_SYSTEM_GTEST=${{ env.YAML_USE_SYSTEM_GTEST }} \
|
||||
-D YAML_CPP_BUILD_TESTS=ON
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cmake \
|
||||
--build build \
|
||||
--config ${{ env.CMAKE_BUILD_TYPE }} \
|
||||
--verbose \
|
||||
--parallel
|
||||
|
||||
- name: Run Tests
|
||||
shell: bash
|
||||
run: |
|
||||
ctest \
|
||||
--test-dir build \
|
||||
--build-config ${{ env.CMAKE_BUILD_TYPE }} \
|
||||
--output-on-failure \
|
||||
--verbose
|
||||
|
||||
- name: Install
|
||||
run: cmake --install build --config ${{ env.CMAKE_BUILD_TYPE }}
|
||||
|
||||
- name: Configure CMake package test
|
||||
run: |
|
||||
cmake \
|
||||
${{ env.CMAKE_GENERATOR }} \
|
||||
-S "${{ github.workspace }}/test/cmake" \
|
||||
-B consumer-build \
|
||||
-D CMAKE_BUILD_TYPE=${{ env.CMAKE_BUILD_TYPE }} \
|
||||
-D CMAKE_PREFIX_PATH="${{ env.CMAKE_INSTALL_PREFIX }}"
|
||||
|
||||
- name: Build CMake package test
|
||||
run: |
|
||||
cmake \
|
||||
--build consumer-build \
|
||||
--config ${{ env.CMAKE_BUILD_TYPE }} \
|
||||
--verbose
|
||||
|
||||
bazel-build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cd "${{ github.workspace }}"
|
||||
bazel build :all
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
cd "${{ github.workspace }}"
|
||||
bazel test test
|
||||
|
||||
bzlmod-build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: |
|
||||
cd "${{ github.workspace }}"
|
||||
bazel build --enable_bzlmod :all
|
||||
|
||||
- name: Test
|
||||
shell: bash
|
||||
run: |
|
||||
cd "${{ github.workspace }}"
|
||||
bazel test --enable_bzlmod test
|
19
.github/workflows/bzlmod-archive.yml
vendored
19
.github/workflows/bzlmod-archive.yml
vendored
@@ -1,19 +0,0 @@
|
||||
name: Bazel Release
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
# A release archive is required for bzlmod
|
||||
# See: https://blog.bazel.build/2023/02/15/github-archive-checksum.html
|
||||
bazel-release-archive:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- run: git archive $GITHUB_REF -o "yaml-cpp-${GITHUB_REF:10}.tar.gz"
|
||||
- run: gh release upload ${GITHUB_REF:10} "yaml-cpp-${GITHUB_REF:10}.tar.gz"
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
37
.travis.yml
Normal file
37
.travis.yml
Normal file
@@ -0,0 +1,37 @@
|
||||
language: c++
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
- os: osx
|
||||
compiler: clang
|
||||
- os: osx
|
||||
compiler: gcc
|
||||
env:
|
||||
- CTEST_OUTPUT_ON_FAILURE=1
|
||||
|
||||
before_script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake ..
|
||||
- cd ..
|
||||
script:
|
||||
- cmake --build build
|
||||
- cmake --build build --target test
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.9
|
||||
packages:
|
||||
- g++-4.9
|
||||
- clang-3.9
|
||||
update: true
|
||||
homebrew:
|
||||
packages:
|
||||
- ccache
|
||||
- gcc@4.9
|
||||
- llvm@4
|
||||
update: true
|
@@ -1,9 +1,3 @@
|
||||
yaml_cpp_defines = select({
|
||||
# On Windows, ensure static linking is used.
|
||||
"@platforms//os:windows": ["YAML_CPP_STATIC_DEFINE", "YAML_CPP_NO_CONTRIB"],
|
||||
"//conditions:default": [],
|
||||
})
|
||||
|
||||
cc_library(
|
||||
name = "yaml-cpp_internal",
|
||||
visibility = ["//:__subpackages__"],
|
||||
@@ -17,5 +11,4 @@ cc_library(
|
||||
includes = ["include"],
|
||||
hdrs = glob(["include/**/*.h"]),
|
||||
srcs = glob(["src/**/*.cpp", "src/**/*.h"]),
|
||||
defines = yaml_cpp_defines,
|
||||
)
|
||||
|
@@ -1,6 +1,5 @@
|
||||
# 3.5 is actually available almost everywhere.
|
||||
# 3.30 as the upper policy limit avoids CMake deprecation warnings.
|
||||
cmake_minimum_required(VERSION 3.5...3.30)
|
||||
# 3.5 is actually available almost everywhere, but this a good minimum
|
||||
cmake_minimum_required(VERSION 3.4)
|
||||
|
||||
# enable MSVC_RUNTIME_LIBRARY target property
|
||||
# see https://cmake.org/cmake/help/latest/policy/CMP0091.html
|
||||
@@ -8,12 +7,7 @@ if(POLICY CMP0091)
|
||||
cmake_policy(SET CMP0091 NEW)
|
||||
endif()
|
||||
|
||||
project(YAML_CPP VERSION 0.8.0 LANGUAGES CXX)
|
||||
|
||||
set(YAML_CPP_MAIN_PROJECT OFF)
|
||||
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
|
||||
set(YAML_CPP_MAIN_PROJECT ON)
|
||||
endif()
|
||||
project(YAML_CPP VERSION 0.7.0 LANGUAGES CXX)
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(CMakeDependentOption)
|
||||
@@ -21,34 +15,27 @@ include(CheckCXXCompilerFlag)
|
||||
include(GNUInstallDirs)
|
||||
include(CTest)
|
||||
|
||||
find_program(YAML_CPP_CLANG_FORMAT_EXE NAMES clang-format)
|
||||
|
||||
option(YAML_CPP_BUILD_CONTRIB "Enable yaml-cpp contrib in library" ON)
|
||||
option(YAML_CPP_BUILD_TOOLS "Enable parse tools" ON)
|
||||
option(YAML_BUILD_SHARED_LIBS "Build yaml-cpp shared library" ${BUILD_SHARED_LIBS})
|
||||
option(YAML_CPP_INSTALL "Enable generation of yaml-cpp install targets" ${YAML_CPP_MAIN_PROJECT})
|
||||
option(YAML_CPP_FORMAT_SOURCE "Format source" ${YAML_CPP_MAIN_PROJECT})
|
||||
option(YAML_CPP_DISABLE_UNINSTALL "Disable uninstallation of yaml-cpp" OFF)
|
||||
option(YAML_USE_SYSTEM_GTEST "Use system googletest if found" OFF)
|
||||
option(YAML_ENABLE_PIC "Use Position-Independent Code " ON)
|
||||
|
||||
cmake_dependent_option(YAML_CPP_BUILD_TESTS
|
||||
"Enable yaml-cpp tests" OFF
|
||||
"BUILD_TESTING;YAML_CPP_MAIN_PROJECT" OFF)
|
||||
"Enable yaml-cpp tests" ON
|
||||
"BUILD_TESTING;CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
|
||||
cmake_dependent_option(YAML_CPP_INSTALL
|
||||
"Enable generation of yaml-cpp install targets" ON
|
||||
"CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
|
||||
cmake_dependent_option(YAML_MSVC_SHARED_RT
|
||||
"MSVC: Build yaml-cpp with shared runtime libs (/MD)" ON
|
||||
"CMAKE_SYSTEM_NAME MATCHES Windows" OFF)
|
||||
set(YAML_CPP_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/yaml-cpp"
|
||||
CACHE STRING "Path to install the CMake package to")
|
||||
|
||||
if (YAML_CPP_FORMAT_SOURCE)
|
||||
find_program(YAML_CPP_CLANG_FORMAT_EXE NAMES clang-format)
|
||||
endif()
|
||||
"MSVC" OFF)
|
||||
|
||||
set(yaml-cpp-type STATIC)
|
||||
set(yaml-cpp-label-postfix "static")
|
||||
if (YAML_BUILD_SHARED_LIBS)
|
||||
set(yaml-cpp-type SHARED)
|
||||
set(yaml-cpp-label-postfix "shared")
|
||||
else()
|
||||
set(yaml-cpp-type STATIC)
|
||||
set(yaml-cpp-label-postfix "static")
|
||||
endif()
|
||||
|
||||
set(build-shared $<BOOL:${YAML_BUILD_SHARED_LIBS}>)
|
||||
@@ -91,10 +78,6 @@ set_property(TARGET yaml-cpp
|
||||
PROPERTY
|
||||
CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
if (NOT YAML_BUILD_SHARED_LIBS)
|
||||
set_property(TARGET yaml-cpp PROPERTY POSITION_INDEPENDENT_CODE ${YAML_ENABLE_PIC})
|
||||
endif()
|
||||
|
||||
target_include_directories(yaml-cpp
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||
@@ -108,15 +91,11 @@ if (NOT DEFINED CMAKE_CXX_STANDARD)
|
||||
CXX_STANDARD 11)
|
||||
endif()
|
||||
|
||||
if(YAML_CPP_MAIN_PROJECT)
|
||||
target_compile_options(yaml-cpp
|
||||
PRIVATE
|
||||
$<${not-msvc}:-Wall -Wextra -Wshadow -Weffc++ -Wno-long-long>
|
||||
$<${not-msvc}:-pedantic -pedantic-errors>)
|
||||
endif()
|
||||
|
||||
target_compile_options(yaml-cpp
|
||||
PRIVATE
|
||||
$<${not-msvc}:-Wall -Wextra -Wshadow -Weffc++ -Wno-long-long>
|
||||
$<${not-msvc}:-pedantic -pedantic-errors>
|
||||
|
||||
$<$<AND:${backport-msvc-runtime},${msvc-rt-mtd-static}>:-MTd>
|
||||
$<$<AND:${backport-msvc-runtime},${msvc-rt-mt-static}>:-MT>
|
||||
$<$<AND:${backport-msvc-runtime},${msvc-rt-mtd-dll}>:-MDd>
|
||||
@@ -129,8 +108,6 @@ target_compile_options(yaml-cpp
|
||||
$<$<CXX_COMPILER_ID:MSVC>:/W3 /wd4127 /wd4355>)
|
||||
|
||||
target_compile_definitions(yaml-cpp
|
||||
PUBLIC
|
||||
$<$<NOT:$<BOOL:${YAML_BUILD_SHARED_LIBS}>>:YAML_CPP_STATIC_DEFINE>
|
||||
PRIVATE
|
||||
$<${build-windows-dll}:${PROJECT_NAME}_DLL>
|
||||
$<$<NOT:$<BOOL:${YAML_CPP_BUILD_CONTRIB}>>:YAML_CPP_NO_CONTRIB>)
|
||||
@@ -150,13 +127,10 @@ set_target_properties(yaml-cpp PROPERTIES
|
||||
PROJECT_LABEL "yaml-cpp ${yaml-cpp-label-postfix}"
|
||||
DEBUG_POSTFIX "${CMAKE_DEBUG_POSTFIX}")
|
||||
|
||||
set(EXPORT_TARGETS yaml-cpp::yaml-cpp)
|
||||
configure_package_config_file(
|
||||
"${PROJECT_SOURCE_DIR}/yaml-cpp-config.cmake.in"
|
||||
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake"
|
||||
INSTALL_DESTINATION "${YAML_CPP_INSTALL_CMAKEDIR}"
|
||||
PATH_VARS CMAKE_INSTALL_INCLUDEDIR CMAKE_INSTALL_LIBDIR)
|
||||
unset(EXPORT_TARGETS)
|
||||
INSTALL_DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/yaml-cpp")
|
||||
|
||||
write_basic_package_version_file(
|
||||
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake"
|
||||
@@ -165,49 +139,36 @@ write_basic_package_version_file(
|
||||
configure_file(yaml-cpp.pc.in yaml-cpp.pc @ONLY)
|
||||
|
||||
if (YAML_CPP_INSTALL)
|
||||
install(TARGETS yaml-cpp
|
||||
install(TARGETS yaml-cpp
|
||||
EXPORT yaml-cpp-targets
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/
|
||||
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
FILES_MATCHING PATTERN "*.h")
|
||||
FILES_MATCHING PATTERN "*.h")
|
||||
install(EXPORT yaml-cpp-targets
|
||||
NAMESPACE yaml-cpp::
|
||||
DESTINATION "${YAML_CPP_INSTALL_CMAKEDIR}")
|
||||
install(FILES
|
||||
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake"
|
||||
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake"
|
||||
DESTINATION "${YAML_CPP_INSTALL_CMAKEDIR}")
|
||||
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/yaml-cpp")
|
||||
install(FILES
|
||||
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake"
|
||||
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake"
|
||||
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/yaml-cpp")
|
||||
install(FILES "${PROJECT_BINARY_DIR}/yaml-cpp.pc"
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/pkgconfig)
|
||||
endif()
|
||||
|
||||
if(YAML_CPP_BUILD_TESTS)
|
||||
add_subdirectory(test)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
if(YAML_CPP_BUILD_TOOLS)
|
||||
add_subdirectory(util)
|
||||
add_subdirectory(util)
|
||||
endif()
|
||||
|
||||
if (YAML_CPP_FORMAT_SOURCE AND YAML_CPP_CLANG_FORMAT_EXE)
|
||||
if (YAML_CPP_CLANG_FORMAT_EXE)
|
||||
add_custom_target(format
|
||||
COMMAND clang-format --style=file -i $<TARGET_PROPERTY:yaml-cpp,SOURCES>
|
||||
COMMAND_EXPAND_LISTS
|
||||
COMMENT "Running clang-format"
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
|
||||
VERBATIM)
|
||||
endif()
|
||||
|
||||
# uninstall target
|
||||
if(YAML_CPP_INSTALL AND NOT YAML_CPP_DISABLE_UNINSTALL AND NOT TARGET uninstall)
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||
IMMEDIATE @ONLY)
|
||||
|
||||
add_custom_target(uninstall
|
||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
|
||||
endif()
|
||||
|
@@ -17,9 +17,9 @@ Commit messages should be in the imperative mood, as described in the [Git contr
|
||||
|
||||
# Tests
|
||||
|
||||
Please verify the tests pass by configuring CMake with `-D YAML_CPP_BUILD_TESTS=ON` and running the target `test/yaml-cpp-tests`.
|
||||
Please verify the tests pass by running the target `tests/run_tests`.
|
||||
|
||||
If you are adding functionality, add tests accordingly. Note that the "spec tests" are reserved for examples directly from the YAML spec, so if you have new examples, put them in other test files.
|
||||
If you are adding functionality, add tests accordingly.
|
||||
|
||||
# Pull request process
|
||||
|
||||
|
14
MODULE.bazel
14
MODULE.bazel
@@ -1,14 +0,0 @@
|
||||
"""
|
||||
yaml-cpp is a YAML parser and emitter in c++ matching the YAML specification.
|
||||
"""
|
||||
|
||||
module(
|
||||
name = "yaml-cpp",
|
||||
compatibility_level = 1,
|
||||
version = "0.8.0",
|
||||
)
|
||||
|
||||
bazel_dep(name = "platforms", version = "0.0.7")
|
||||
bazel_dep(name = "rules_cc", version = "0.0.8")
|
||||
|
||||
bazel_dep(name = "googletest", version = "1.14.0", dev_dependency = True)
|
114
MODULE.bazel.lock
generated
114
MODULE.bazel.lock
generated
@@ -1,114 +0,0 @@
|
||||
{
|
||||
"lockFileVersion": 11,
|
||||
"registryFileHashes": {
|
||||
"https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497",
|
||||
"https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2",
|
||||
"https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589",
|
||||
"https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0",
|
||||
"https://bcr.bazel.build/modules/abseil-cpp/20230125.1/source.json": "06cc0842d241da0c5edc755edb3c7d0d008d304330e57ecf2d6449fb0b633a82",
|
||||
"https://bcr.bazel.build/modules/apple_support/1.5.0/MODULE.bazel": "50341a62efbc483e8a2a6aec30994a58749bd7b885e18dd96aa8c33031e558ef",
|
||||
"https://bcr.bazel.build/modules/apple_support/1.5.0/source.json": "eb98a7627c0bc486b57f598ad8da50f6625d974c8f723e9ea71bd39f709c9862",
|
||||
"https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8",
|
||||
"https://bcr.bazel.build/modules/bazel_features/1.11.0/source.json": "c9320aa53cd1c441d24bd6b716da087ad7e4ff0d9742a9884587596edfe53015",
|
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8",
|
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a",
|
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5",
|
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d",
|
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917",
|
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.6.1/source.json": "082ed5f9837901fada8c68c2f3ddc958bb22b6d654f71dd73f3df30d45d4b749",
|
||||
"https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84",
|
||||
"https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8",
|
||||
"https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4",
|
||||
"https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f",
|
||||
"https://bcr.bazel.build/modules/googletest/1.14.0/source.json": "2478949479000fdd7de9a3d0107ba2c85bb5f961c3ecb1aa448f52549ce310b5",
|
||||
"https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee",
|
||||
"https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37",
|
||||
"https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615",
|
||||
"https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814",
|
||||
"https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc",
|
||||
"https://bcr.bazel.build/modules/platforms/0.0.9/source.json": "cd74d854bf16a9e002fb2ca7b1a421f4403cda29f824a765acd3a8c56f8d43e6",
|
||||
"https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7",
|
||||
"https://bcr.bazel.build/modules/protobuf/21.7/source.json": "bbe500720421e582ff2d18b0802464205138c06056f443184de39fbb8187b09b",
|
||||
"https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0",
|
||||
"https://bcr.bazel.build/modules/protobuf/3.19.6/MODULE.bazel": "9233edc5e1f2ee276a60de3eaa47ac4132302ef9643238f23128fea53ea12858",
|
||||
"https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647",
|
||||
"https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c",
|
||||
"https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f",
|
||||
"https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e",
|
||||
"https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5",
|
||||
"https://bcr.bazel.build/modules/rules_cc/0.0.9/source.json": "1f1ba6fea244b616de4a554a0f4983c91a9301640c8fe0dd1d410254115c8430",
|
||||
"https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74",
|
||||
"https://bcr.bazel.build/modules/rules_java/7.6.5/MODULE.bazel": "481164be5e02e4cab6e77a36927683263be56b7e36fef918b458d7a8a1ebadb1",
|
||||
"https://bcr.bazel.build/modules/rules_java/7.6.5/source.json": "a805b889531d1690e3c72a7a7e47a870d00323186a9904b36af83aa3d053ee8d",
|
||||
"https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7",
|
||||
"https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/source.json": "a075731e1b46bc8425098512d038d416e966ab19684a10a34f4741295642fc35",
|
||||
"https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0",
|
||||
"https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d",
|
||||
"https://bcr.bazel.build/modules/rules_license/0.0.7/source.json": "355cc5737a0f294e560d52b1b7a6492d4fff2caf0bef1a315df5a298fca2d34a",
|
||||
"https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc",
|
||||
"https://bcr.bazel.build/modules/rules_pkg/0.7.0/source.json": "c2557066e0c0342223ba592510ad3d812d4963b9024831f7f66fd0584dd8c66c",
|
||||
"https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06",
|
||||
"https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7",
|
||||
"https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/source.json": "d57902c052424dfda0e71646cb12668d39c4620ee0544294d9d941e7d12bc3a9",
|
||||
"https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f",
|
||||
"https://bcr.bazel.build/modules/rules_python/0.22.1/MODULE.bazel": "26114f0c0b5e93018c0c066d6673f1a2c3737c7e90af95eff30cfee38d0bbac7",
|
||||
"https://bcr.bazel.build/modules/rules_python/0.22.1/source.json": "57226905e783bae7c37c2dd662be078728e48fa28ee4324a7eabcafb5a43d014",
|
||||
"https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c",
|
||||
"https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8",
|
||||
"https://bcr.bazel.build/modules/stardoc/0.5.1/source.json": "a96f95e02123320aa015b956f29c00cb818fa891ef823d55148e1a362caacf29",
|
||||
"https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43",
|
||||
"https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/source.json": "f1ef7d3f9e0e26d4b23d1c39b5f5de71f584dd7d1b4ef83d9bbba6ec7a6a6459",
|
||||
"https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0",
|
||||
"https://bcr.bazel.build/modules/zlib/1.2.12/MODULE.bazel": "3b1a8834ada2a883674be8cbd36ede1b6ec481477ada359cd2d3ddc562340b27",
|
||||
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/MODULE.bazel": "af322bc08976524477c79d1e45e241b6efbeb918c497e8840b8ab116802dda79",
|
||||
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/source.json": "2be409ac3c7601245958cd4fcdff4288be79ed23bd690b4b951f500d54ee6e7d"
|
||||
},
|
||||
"selectedYankedVersions": {},
|
||||
"moduleExtensions": {
|
||||
"@@apple_support~//crosstool:setup.bzl%apple_cc_configure_extension": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "PjIds3feoYE8SGbbIq2SFTZy3zmxeO2tQevJZNDo7iY=",
|
||||
"usagesDigest": "+hz7IHWN6A1oVJJWNDB6yZRG+RYhF76wAYItpAeIUIg=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
"generatedRepoSpecs": {
|
||||
"local_config_apple_cc_toolchains": {
|
||||
"bzlFile": "@@apple_support~//crosstool:setup.bzl",
|
||||
"ruleClassName": "_apple_cc_autoconf_toolchains",
|
||||
"attributes": {}
|
||||
},
|
||||
"local_config_apple_cc": {
|
||||
"bzlFile": "@@apple_support~//crosstool:setup.bzl",
|
||||
"ruleClassName": "_apple_cc_autoconf",
|
||||
"attributes": {}
|
||||
}
|
||||
},
|
||||
"recordedRepoMappingEntries": [
|
||||
[
|
||||
"apple_support~",
|
||||
"bazel_tools",
|
||||
"bazel_tools"
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"@@platforms//host:extension.bzl%host_platform": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "xelQcPZH8+tmuOHVjL9vDxMnnQNMlwj0SlvgoqBkm4U=",
|
||||
"usagesDigest": "pCYpDQmqMbmiiPI1p2Kd3VLm5T48rRAht5WdW0X2GlA=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
"generatedRepoSpecs": {
|
||||
"host_platform": {
|
||||
"bzlFile": "@@platforms//host:extension.bzl",
|
||||
"ruleClassName": "host_platform_repo",
|
||||
"attributes": {}
|
||||
}
|
||||
},
|
||||
"recordedRepoMappingEntries": []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
74
README.md
74
README.md
@@ -1,78 +1,54 @@
|
||||
# yaml-cpp  [](https://codedocs.xyz/jbeder/yaml-cpp/)
|
||||
# yaml-cpp [](https://travis-ci.org/jbeder/yaml-cpp) [](https://codedocs.xyz/jbeder/yaml-cpp/)
|
||||
|
||||
`yaml-cpp` is a [YAML](http://www.yaml.org/) parser and emitter in C++ matching the [YAML 1.2 spec](http://www.yaml.org/spec/1.2/spec.html).
|
||||
yaml-cpp is a [YAML](http://www.yaml.org/) parser and emitter in C++ matching the [YAML 1.2 spec](http://www.yaml.org/spec/1.2/spec.html).
|
||||
|
||||
## Usage
|
||||
To get a feel for how it can be used, see the [Tutorial](https://github.com/jbeder/yaml-cpp/wiki/Tutorial) or [How to Emit YAML](https://github.com/jbeder/yaml-cpp/wiki/How-To-Emit-YAML). For the old API (version < 0.5.0), see [How To Parse A Document](https://github.com/jbeder/yaml-cpp/wiki/How-To-Parse-A-Document-(Old-API)).
|
||||
|
||||
See [Tutorial](https://github.com/jbeder/yaml-cpp/wiki/Tutorial) and [How to Emit YAML](https://github.com/jbeder/yaml-cpp/wiki/How-To-Emit-YAML) for reference. For the old API (until 0.5.0), see [How To Parse A Document](https://github.com/jbeder/yaml-cpp/wiki/How-To-Parse-A-Document-(Old-API)).
|
||||
|
||||
## Any Problems?
|
||||
# Problems? #
|
||||
|
||||
If you find a bug, post an [issue](https://github.com/jbeder/yaml-cpp/issues)! If you have questions about how to use yaml-cpp, please post it on http://stackoverflow.com and tag it [`yaml-cpp`](http://stackoverflow.com/questions/tagged/yaml-cpp).
|
||||
|
||||
## How to Build
|
||||
# How to Build #
|
||||
|
||||
`yaml-cpp` uses [CMake](http://www.cmake.org) to support cross-platform building. Install [CMake](http://www.cmake.org) _(Resources -> Download)_ before proceeding. The basic steps to build are:
|
||||
yaml-cpp uses [CMake](http://www.cmake.org) to support cross-platform building. The basic steps to build are:
|
||||
|
||||
**Note:** If you don't use the provided installer for your platform, make sure that you add `CMake`'s bin folder to your path.
|
||||
1. Download and install [CMake](http://www.cmake.org) (Resources -> Download).
|
||||
|
||||
#### 1. Navigate into the source directory, create build folder and run `CMake`:
|
||||
**Note:** If you don't use the provided installer for your platform, make sure that you add CMake's bin folder to your path.
|
||||
|
||||
```sh
|
||||
2. Navigate into the source directory, and type:
|
||||
|
||||
```
|
||||
mkdir build
|
||||
cd build
|
||||
cmake [-G generator] [-DYAML_BUILD_SHARED_LIBS=on|OFF] ..
|
||||
```
|
||||
|
||||
* The `generator` option is the build system you'd like to use. Run `cmake` without arguments to see a full list of available generators.
|
||||
* On Windows, you might use "Visual Studio 12 2013" (VS 2013 32-bits), or "Visual Studio 14 2015 Win64" (VS 2015 64-bits).
|
||||
* On OS X, you might use "Xcode".
|
||||
* On a UNIX-like system, omit the option (for a Makefile).
|
||||
3. Run CMake. The basic syntax is:
|
||||
|
||||
* `yaml-cpp` builds a static library by default, you may want to build a shared library by specifying `-DYAML_BUILD_SHARED_LIBS=ON`.
|
||||
```
|
||||
cmake [-G generator] [-DYAML_BUILD_SHARED_LIBS=ON|OFF] ..
|
||||
```
|
||||
|
||||
* [Debug mode of the GNU standard C++
|
||||
library](https://gcc.gnu.org/onlinedocs/libstdc++/manual/debug_mode.html)
|
||||
can be used when both `yaml-cpp` and client code is compiled with the
|
||||
`_GLIBCXX_DEBUG` flag (e.g. by calling CMake with `-D
|
||||
CMAKE_CXX_FLAGS_DEBUG='-g -D_GLIBCXX_DEBUG'` option).
|
||||
* The `generator` is whatever type of build system you'd like to use. To see a full list of generators on your platform, just run `cmake` (with no arguments). For example:
|
||||
* On Windows, you might use "Visual Studio 12 2013" to generate a Visual Studio 2013 solution or "Visual Studio 14 2015 Win64" to generate a 64-bit Visual Studio 2015 solution.
|
||||
* On OS X, you might use "Xcode" to generate an Xcode project
|
||||
* On a UNIX-y system, simply omit the option to generate a makefile
|
||||
|
||||
Note that for `yaml-cpp` unit tests to run successfully, the _GoogleTest_
|
||||
library also must be built with this flag, i.e. the system one cannot be
|
||||
used (the _YAML_USE_SYSTEM_GTEST_ CMake option must be _OFF_, which is the
|
||||
default).
|
||||
* yaml-cpp defaults to building a static library, but you may build a shared library by specifying `-DYAML_BUILD_SHARED_LIBS=ON`.
|
||||
|
||||
* For more options on customizing the build, see the [CMakeLists.txt](https://github.com/jbeder/yaml-cpp/blob/master/CMakeLists.txt) file.
|
||||
|
||||
#### 2. Build it!
|
||||
* The command you'll need to run depends on the generator you chose earlier.
|
||||
4. Build it!
|
||||
|
||||
**Note:** To clean up, just remove the `build` directory.
|
||||
5. To clean up, just remove the `build` directory.
|
||||
|
||||
## How to Integrate it within your project using CMake
|
||||
# Recent Release #
|
||||
|
||||
You can use for example FetchContent :
|
||||
|
||||
```cmake
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
yaml-cpp
|
||||
GIT_REPOSITORY https://github.com/jbeder/yaml-cpp.git
|
||||
GIT_TAG <tag_name> # Can be a tag (yaml-cpp-x.x.x), a commit hash, or a branch name (master)
|
||||
)
|
||||
FetchContent_MakeAvailable(yaml-cpp)
|
||||
|
||||
target_link_libraries(YOUR_LIBRARY PUBLIC yaml-cpp::yaml-cpp) # The library or executable that require yaml-cpp library
|
||||
```
|
||||
|
||||
## Recent Releases
|
||||
|
||||
[yaml-cpp 0.8.0](https://github.com/jbeder/yaml-cpp/releases/tag/0.8.0) released!
|
||||
[yaml-cpp 0.6.0](https://github.com/jbeder/yaml-cpp/releases/tag/yaml-cpp-0.6.0) has been released! This release requires C++11, and no longer depends on Boost.
|
||||
|
||||
[yaml-cpp 0.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 stop receiving bugfixes in 2026.** The 0.3.x versions provide the old API, and 0.5.x and above all provide the new 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.
|
||||
|
||||
# API Documentation
|
||||
|
||||
|
13
SECURITY.md
13
SECURITY.md
@@ -1,13 +0,0 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Security updates are applied only to the latest release.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released.
|
||||
|
||||
Please disclose it at [security advisory](https://github.com/jbeder/yaml-cpp/security/advisories/new).
|
||||
|
||||
This project is maintained by a team of volunteers on a reasonable-effort basis. As such, vulnerabilities will be disclosed in a best effort base.
|
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",
|
||||
)
|
28
appveyor.yml
Normal file
28
appveyor.yml
Normal file
@@ -0,0 +1,28 @@
|
||||
version: 1.0.{build}
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CMAKE_GENERATOR: Visual Studio 14 2015
|
||||
CMAKE_PLATFORM: win32
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CMAKE_GENERATOR: Visual Studio 14 2015
|
||||
CMAKE_PLATFORM: x64
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
CMAKE_GENERATOR: Visual Studio 15 2017
|
||||
CMAKE_PLATFORM: win32
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
CMAKE_GENERATOR: Visual Studio 15 2017
|
||||
CMAKE_PLATFORM: x64
|
||||
|
||||
before_build:
|
||||
- cmd: mkdir build
|
||||
- cmd: cd build
|
||||
- cmd: cmake .. -G "%CMAKE_GENERATOR%" -DCMAKE_GENERATOR_PLATFORM=%CMAKE_PLATFORM%
|
||||
- cmd: cd ..
|
||||
|
||||
build_script:
|
||||
- cmake --build build
|
||||
test_script:
|
||||
- cmd: cd build
|
||||
- ctest
|
@@ -1,21 +0,0 @@
|
||||
if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
|
||||
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt")
|
||||
endif()
|
||||
|
||||
file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files)
|
||||
string(REGEX REPLACE "\n" ";" files "${files}")
|
||||
foreach(file ${files})
|
||||
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
|
||||
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||
exec_program(
|
||||
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
|
||||
OUTPUT_VARIABLE rm_out
|
||||
RETURN_VALUE rm_retval
|
||||
)
|
||||
if(NOT "${rm_retval}" STREQUAL 0)
|
||||
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
|
||||
endif()
|
||||
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
|
||||
endif()
|
||||
endforeach()
|
@@ -154,11 +154,16 @@ produces
|
||||
# STL Containers, and Other Overloads #
|
||||
We overload `operator <<` for `std::vector`, `std::list`, and `std::map`, so you can write stuff like:
|
||||
|
||||
{% raw %}
|
||||
```cpp
|
||||
std::vector <int> squares = {1, 4, 9, 16};
|
||||
std::vector <int> squares;
|
||||
squares.push_back(1);
|
||||
squares.push_back(4);
|
||||
squares.push_back(9);
|
||||
squares.push_back(16);
|
||||
|
||||
std::map <std::string, int> ages = {{"Daniel", 26}, {"Jesse", 24}};
|
||||
std::map <std::string, int> ages;
|
||||
ages["Daniel"] = 26;
|
||||
ages["Jesse"] = 24;
|
||||
|
||||
YAML::Emitter out;
|
||||
out << YAML::BeginSeq;
|
||||
@@ -166,7 +171,6 @@ out << YAML::Flow << squares;
|
||||
out << ages;
|
||||
out << YAML::EndSeq;
|
||||
```
|
||||
{% endraw %}
|
||||
|
||||
produces
|
||||
|
||||
@@ -223,4 +227,4 @@ assert(out.good());
|
||||
out << YAML::Key;
|
||||
assert(!out.good());
|
||||
std::cout << "Emitter error: " << out.GetLastError() << "\n";
|
||||
```
|
||||
```
|
@@ -1,59 +1,33 @@
|
||||
#ifndef DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
// Definition YAML_CPP_STATIC_DEFINE using to building YAML-CPP as static
|
||||
// library (definition created by CMake or defined manually)
|
||||
|
||||
// Definition yaml_cpp_EXPORTS using to building YAML-CPP as dll/so library
|
||||
// (definition created by CMake or defined manually)
|
||||
|
||||
#ifdef YAML_CPP_STATIC_DEFINE
|
||||
# define YAML_CPP_API
|
||||
# define YAML_CPP_NO_EXPORT
|
||||
#else
|
||||
# if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)
|
||||
# ifndef YAML_CPP_API
|
||||
# ifdef yaml_cpp_EXPORTS
|
||||
/* We are building this library */
|
||||
# define YAML_CPP_API __declspec(dllexport)
|
||||
# else
|
||||
/* We are using this library */
|
||||
# define YAML_CPP_API __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
# ifndef YAML_CPP_NO_EXPORT
|
||||
# define YAML_CPP_NO_EXPORT
|
||||
# endif
|
||||
# else /* No _MSC_VER */
|
||||
# ifndef YAML_CPP_API
|
||||
# ifdef yaml_cpp_EXPORTS
|
||||
/* We are building this library */
|
||||
# define YAML_CPP_API __attribute__((visibility("default")))
|
||||
# else
|
||||
/* We are using this library */
|
||||
# define YAML_CPP_API __attribute__((visibility("default")))
|
||||
# endif
|
||||
# endif
|
||||
# ifndef YAML_CPP_NO_EXPORT
|
||||
# define YAML_CPP_NO_EXPORT __attribute__((visibility("hidden")))
|
||||
# endif
|
||||
# endif /* _MSC_VER */
|
||||
#endif /* YAML_CPP_STATIC_DEFINE */
|
||||
|
||||
#ifndef YAML_CPP_DEPRECATED
|
||||
# ifdef _MSC_VER
|
||||
# define YAML_CPP_DEPRECATED __declspec(deprecated)
|
||||
# else
|
||||
# define YAML_CPP_DEPRECATED __attribute__ ((__deprecated__))
|
||||
# endif
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef YAML_CPP_DEPRECATED_EXPORT
|
||||
# define YAML_CPP_DEPRECATED_EXPORT YAML_CPP_API YAML_CPP_DEPRECATED
|
||||
#endif
|
||||
// The following ifdef block is the standard way of creating macros which make
|
||||
// exporting from a DLL simpler. All files within this DLL are compiled with the
|
||||
// yaml_cpp_EXPORTS symbol defined on the command line. This symbol should not
|
||||
// be defined on any project that uses this DLL. This way any other project
|
||||
// whose source files include this file see YAML_CPP_API functions as being
|
||||
// imported from a DLL, whereas this DLL sees symbols defined with this macro as
|
||||
// being exported.
|
||||
#undef YAML_CPP_API
|
||||
|
||||
#ifndef YAML_CPP_DEPRECATED_NO_EXPORT
|
||||
# define YAML_CPP_DEPRECATED_NO_EXPORT YAML_CPP_NO_EXPORT YAML_CPP_DEPRECATED
|
||||
#endif
|
||||
#ifdef YAML_CPP_DLL // Using or Building YAML-CPP DLL (definition defined
|
||||
// manually)
|
||||
#ifdef yaml_cpp_EXPORTS // Building YAML-CPP DLL (definition created by CMake
|
||||
// or defined manually)
|
||||
// #pragma message( "Defining YAML_CPP_API for DLL export" )
|
||||
#define YAML_CPP_API __declspec(dllexport)
|
||||
#else // yaml_cpp_EXPORTS
|
||||
// #pragma message( "Defining YAML_CPP_API for DLL import" )
|
||||
#define YAML_CPP_API __declspec(dllimport)
|
||||
#endif // yaml_cpp_EXPORTS
|
||||
#else // YAML_CPP_DLL
|
||||
#define YAML_CPP_API
|
||||
#endif // YAML_CPP_DLL
|
||||
|
||||
#endif /* DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 */
|
||||
#endif // DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
@@ -23,7 +23,6 @@ class Emitter;
|
||||
class EmitFromEvents : public EventHandler {
|
||||
public:
|
||||
EmitFromEvents(Emitter& emitter);
|
||||
~EmitFromEvents() override = default;
|
||||
|
||||
void OnDocumentStart(const Mark& mark) override;
|
||||
void OnDocumentEnd() override;
|
||||
|
@@ -9,24 +9,18 @@
|
||||
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
|
||||
#include <string_view>
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/binary.h"
|
||||
#include "yaml-cpp/dll.h"
|
||||
#include "yaml-cpp/emitterdef.h"
|
||||
#include "yaml-cpp/emittermanip.h"
|
||||
#include "yaml-cpp/null.h"
|
||||
#include "yaml-cpp/ostream_wrapper.h"
|
||||
#include "yaml-cpp/fptostring.h"
|
||||
|
||||
namespace YAML {
|
||||
class Binary;
|
||||
@@ -73,7 +67,6 @@ class YAML_CPP_API Emitter {
|
||||
Emitter& SetLocalPrecision(const _Precision& precision);
|
||||
|
||||
// overloads of write
|
||||
Emitter& Write(const char* str, std::size_t size);
|
||||
Emitter& Write(const std::string& str);
|
||||
Emitter& Write(bool b);
|
||||
Emitter& Write(char ch);
|
||||
@@ -148,7 +141,6 @@ inline Emitter& Emitter::WriteIntegralType(T value) {
|
||||
PrepareNode(EmitterNodeType::Scalar);
|
||||
|
||||
std::stringstream stream;
|
||||
stream.imbue(std::locale("C"));
|
||||
PrepareIntegralStream(stream);
|
||||
stream << value;
|
||||
m_stream << stream.str();
|
||||
@@ -166,7 +158,6 @@ inline Emitter& Emitter::WriteStreamable(T value) {
|
||||
PrepareNode(EmitterNodeType::Scalar);
|
||||
|
||||
std::stringstream stream;
|
||||
stream.imbue(std::locale("C"));
|
||||
SetStreamablePrecision<T>(stream);
|
||||
|
||||
bool special = false;
|
||||
@@ -187,7 +178,7 @@ inline Emitter& Emitter::WriteStreamable(T value) {
|
||||
}
|
||||
|
||||
if (!special) {
|
||||
stream << FpToString(value, stream.precision());
|
||||
stream << value;
|
||||
}
|
||||
m_stream << stream.str();
|
||||
|
||||
@@ -207,13 +198,8 @@ inline void Emitter::SetStreamablePrecision<double>(std::stringstream& stream) {
|
||||
}
|
||||
|
||||
// overloads of insertion
|
||||
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
|
||||
inline Emitter& operator<<(Emitter& emitter, const std::string_view& v) {
|
||||
return emitter.Write(v.data(), v.size());
|
||||
}
|
||||
#endif
|
||||
inline Emitter& operator<<(Emitter& emitter, const std::string& v) {
|
||||
return emitter.Write(v.data(), v.size());
|
||||
return emitter.Write(v);
|
||||
}
|
||||
inline Emitter& operator<<(Emitter& emitter, bool v) {
|
||||
return emitter.Write(v);
|
||||
@@ -244,7 +230,7 @@ inline Emitter& operator<<(Emitter& emitter, const Binary& b) {
|
||||
}
|
||||
|
||||
inline Emitter& operator<<(Emitter& emitter, const char* v) {
|
||||
return emitter.Write(v, std::strlen(v));
|
||||
return emitter.Write(std::string(v));
|
||||
}
|
||||
|
||||
inline Emitter& operator<<(Emitter& emitter, int v) {
|
||||
|
@@ -8,10 +8,9 @@
|
||||
#endif
|
||||
|
||||
namespace YAML {
|
||||
namespace EmitterStyle {
|
||||
enum value { Default, Block, Flow };
|
||||
}
|
||||
|
||||
struct EmitterStyle {
|
||||
enum value { Default, Block, Flow };
|
||||
};
|
||||
}
|
||||
|
||||
#endif // EMITTERSTYLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
@@ -48,8 +48,6 @@ const char* const UNKNOWN_TOKEN = "unknown token";
|
||||
const char* const DOC_IN_SCALAR = "illegal document indicator in scalar";
|
||||
const char* const EOF_IN_SCALAR = "illegal EOF in scalar";
|
||||
const char* const CHAR_IN_SCALAR = "illegal character in scalar";
|
||||
const char* const UNEXPECTED_SCALAR = "unexpected scalar";
|
||||
const char* const UNEXPECTED_FLOW = "plain value cannot start with flow indicator character";
|
||||
const char* const TAB_IN_INDENTATION =
|
||||
"illegal tab when looking for indentation";
|
||||
const char* const FLOW_END = "illegal flow end";
|
||||
|
@@ -1,15 +0,0 @@
|
||||
#ifndef YAML_H_FPTOSTRING
|
||||
#define YAML_H_FPTOSTRING
|
||||
|
||||
#include "yaml-cpp/dll.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace YAML {
|
||||
// "precision = 0" refers to shortest known unique representation of the value
|
||||
YAML_CPP_API std::string FpToString(float v, size_t precision = 0);
|
||||
YAML_CPP_API std::string FpToString(double v, size_t precision = 0);
|
||||
YAML_CPP_API std::string FpToString(long double v, size_t precision = 0);
|
||||
}
|
||||
|
||||
#endif
|
@@ -12,23 +12,16 @@
|
||||
#include <limits>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
#include <valarray>
|
||||
#include <vector>
|
||||
|
||||
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
|
||||
#include <string_view>
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/binary.h"
|
||||
#include "yaml-cpp/node/impl.h"
|
||||
#include "yaml-cpp/node/iterator.h"
|
||||
#include "yaml-cpp/node/node.h"
|
||||
#include "yaml-cpp/node/type.h"
|
||||
#include "yaml-cpp/null.h"
|
||||
#include "yaml-cpp/fptostring.h"
|
||||
|
||||
|
||||
namespace YAML {
|
||||
@@ -94,20 +87,6 @@ struct convert<char[N]> {
|
||||
static Node encode(const char* rhs) { return Node(rhs); }
|
||||
};
|
||||
|
||||
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
|
||||
template <>
|
||||
struct convert<std::string_view> {
|
||||
static Node encode(std::string_view rhs) { return Node(std::string(rhs)); }
|
||||
|
||||
static bool decode(const Node& node, std::string_view& rhs) {
|
||||
if (!node.IsScalar())
|
||||
return false;
|
||||
rhs = node.Scalar();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template <>
|
||||
struct convert<_Null> {
|
||||
static Node encode(const _Null& /* rhs */) { return Node(); }
|
||||
@@ -130,7 +109,7 @@ inner_encode(const T& rhs, std::stringstream& stream){
|
||||
stream << ".inf";
|
||||
}
|
||||
} else {
|
||||
stream << FpToString(rhs, stream.precision());
|
||||
stream << rhs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,7 +127,7 @@ ConvertStreamTo(std::stringstream& stream, T& rhs) {
|
||||
if ((stream >> std::noskipws >> num) && (stream >> std::ws).eof()) {
|
||||
if (num >= (std::numeric_limits<T>::min)() &&
|
||||
num <= (std::numeric_limits<T>::max)()) {
|
||||
rhs = static_cast<T>(num);
|
||||
rhs = (T)num;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -172,7 +151,6 @@ ConvertStreamTo(std::stringstream& stream, T& rhs) {
|
||||
\
|
||||
static Node encode(const type& rhs) { \
|
||||
std::stringstream stream; \
|
||||
stream.imbue(std::locale("C")); \
|
||||
stream.precision(std::numeric_limits<type>::max_digits10); \
|
||||
conversion::inner_encode(rhs, stream); \
|
||||
return Node(stream.str()); \
|
||||
@@ -184,7 +162,6 @@ ConvertStreamTo(std::stringstream& stream, T& rhs) {
|
||||
} \
|
||||
const std::string& input = node.Scalar(); \
|
||||
std::stringstream stream(input); \
|
||||
stream.imbue(std::locale("C")); \
|
||||
stream.unsetf(std::ios::dec); \
|
||||
if ((stream.peek() == '-') && std::is_unsigned<type>::value) { \
|
||||
return false; \
|
||||
@@ -274,32 +251,6 @@ struct convert<std::map<K, V, C, A>> {
|
||||
}
|
||||
};
|
||||
|
||||
// std::unordered_map
|
||||
template <typename K, typename V, typename H, typename P, typename A>
|
||||
struct convert<std::unordered_map<K, V, H, P, A>> {
|
||||
static Node encode(const std::unordered_map<K, V, H, P, A>& rhs) {
|
||||
Node node(NodeType::Map);
|
||||
for (const auto& element : rhs)
|
||||
node.force_insert(element.first, element.second);
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, std::unordered_map<K, V, H, P, A>& rhs) {
|
||||
if (!node.IsMap())
|
||||
return false;
|
||||
|
||||
rhs.clear();
|
||||
for (const auto& element : node)
|
||||
#if defined(__GNUC__) && __GNUC__ < 4
|
||||
// workaround for GCC 3:
|
||||
rhs[element.first.template as<K>()] = element.second.template as<V>();
|
||||
#else
|
||||
rhs[element.first.as<K>()] = element.second.as<V>();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// std::vector
|
||||
template <typename T, typename A>
|
||||
struct convert<std::vector<T, A>> {
|
||||
@@ -385,37 +336,6 @@ struct convert<std::array<T, N>> {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// std::valarray
|
||||
template <typename T>
|
||||
struct convert<std::valarray<T>> {
|
||||
static Node encode(const std::valarray<T>& rhs) {
|
||||
Node node(NodeType::Sequence);
|
||||
for (const auto& element : rhs) {
|
||||
node.push_back(element);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, std::valarray<T>& rhs) {
|
||||
if (!node.IsSequence()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
rhs.resize(node.size());
|
||||
for (auto i = 0u; i < node.size(); ++i) {
|
||||
#if defined(__GNUC__) && __GNUC__ < 4
|
||||
// workaround for GCC 3:
|
||||
rhs[i] = node[i].template as<T>();
|
||||
#else
|
||||
rhs[i] = node[i].as<T>();
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// std::pair
|
||||
template <typename T, typename U>
|
||||
struct convert<std::pair<T, U>> {
|
||||
|
@@ -41,7 +41,7 @@ class iterator_base {
|
||||
using value_type = V;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = V*;
|
||||
using reference = V&;
|
||||
using reference = V;
|
||||
|
||||
public:
|
||||
iterator_base() : m_iterator(), m_pMemory() {}
|
||||
|
@@ -25,7 +25,6 @@ class YAML_CPP_API memory {
|
||||
memory() : m_nodes{} {}
|
||||
node& create_node();
|
||||
void merge(const memory& rhs);
|
||||
size_t size() const;
|
||||
|
||||
private:
|
||||
using Nodes = std::set<shared_node>;
|
||||
|
@@ -169,7 +169,7 @@ class node {
|
||||
using nodes = std::set<node*, less>;
|
||||
nodes m_dependencies;
|
||||
size_t m_index;
|
||||
static YAML_CPP_API std::atomic<size_t> m_amount;
|
||||
static std::atomic<size_t> m_amount;
|
||||
};
|
||||
} // namespace detail
|
||||
} // namespace YAML
|
||||
|
@@ -69,7 +69,7 @@ class node_iterator_base {
|
||||
using value_type = node_iterator_value<V>;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = node_iterator_value<V>*;
|
||||
using reference = 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;
|
||||
|
||||
|
@@ -97,7 +97,7 @@ struct as_if {
|
||||
if (!node.m_pNode)
|
||||
return fallback;
|
||||
|
||||
T t = fallback;
|
||||
T t;
|
||||
if (convert<T>::decode(node, t))
|
||||
return t;
|
||||
return fallback;
|
||||
@@ -124,8 +124,8 @@ struct as_if<T, void> {
|
||||
const Node& node;
|
||||
|
||||
T operator()() const {
|
||||
if (!node.m_pNode) // no fallback
|
||||
throw InvalidNode(node.m_invalidKey);
|
||||
if (!node.m_pNode)
|
||||
throw TypedBadConversion<T>(node.Mark());
|
||||
|
||||
T t;
|
||||
if (convert<T>::decode(node, t))
|
||||
@@ -140,8 +140,6 @@ struct as_if<std::string, void> {
|
||||
const Node& node;
|
||||
|
||||
std::string operator()() const {
|
||||
if (node.Type() == NodeType::Undefined) // no fallback
|
||||
throw InvalidNode(node.m_invalidKey);
|
||||
if (node.Type() == NodeType::Null)
|
||||
return "null";
|
||||
if (node.Type() != NodeType::Scalar)
|
||||
|
@@ -7,6 +7,7 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/dll.h"
|
||||
#include <memory>
|
||||
|
||||
namespace YAML {
|
||||
|
@@ -8,10 +8,9 @@
|
||||
#endif
|
||||
|
||||
namespace YAML {
|
||||
namespace NodeType {
|
||||
enum value { Undefined, Null, Scalar, Sequence, Map };
|
||||
}
|
||||
|
||||
struct NodeType {
|
||||
enum value { Undefined, Null, Scalar, Sequence, Map };
|
||||
};
|
||||
}
|
||||
|
||||
#endif // VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
@@ -8,7 +8,7 @@
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/dll.h"
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
|
||||
namespace YAML {
|
||||
class Node;
|
||||
@@ -18,7 +18,7 @@ inline bool operator==(const _Null&, const _Null&) { return true; }
|
||||
inline bool operator!=(const _Null&, const _Null&) { return false; }
|
||||
|
||||
YAML_CPP_API bool IsNull(const Node& node); // old API only
|
||||
YAML_CPP_API bool IsNullString(const char* str, std::size_t size);
|
||||
YAML_CPP_API bool IsNullString(const std::string& str);
|
||||
|
||||
extern YAML_CPP_API _Null Null;
|
||||
}
|
||||
|
@@ -107,9 +107,9 @@ struct disable_if : public disable_if_c<Cond::value, T> {};
|
||||
|
||||
template <typename S, typename T>
|
||||
struct is_streamable {
|
||||
template <typename StreamT, typename ValueT>
|
||||
template <typename SS, typename TT>
|
||||
static auto test(int)
|
||||
-> decltype(std::declval<StreamT&>() << std::declval<ValueT>(), std::true_type());
|
||||
-> decltype(std::declval<SS&>() << std::declval<TT>(), std::true_type());
|
||||
|
||||
template <typename, typename>
|
||||
static auto test(...) -> std::false_type;
|
||||
@@ -121,7 +121,6 @@ template<typename Key, bool Streamable>
|
||||
struct streamable_to_string {
|
||||
static std::string impl(const Key& key) {
|
||||
std::stringstream ss;
|
||||
ss.imbue(std::locale("C"));
|
||||
ss << key;
|
||||
return ss.str();
|
||||
}
|
||||
|
@@ -75,11 +75,11 @@ std::vector<unsigned char> DecodeBase64(const std::string &input) {
|
||||
|
||||
unsigned value = 0;
|
||||
for (std::size_t i = 0, cnt = 0; i < input.size(); i++) {
|
||||
if (std::isspace(static_cast<unsigned char>(input[i]))) {
|
||||
if (std::isspace(input[i])) {
|
||||
// skip newlines
|
||||
continue;
|
||||
}
|
||||
unsigned char d = decoding[static_cast<unsigned char>(input[i])];
|
||||
unsigned char d = decoding[static_cast<unsigned>(input[i])];
|
||||
if (d == 255)
|
||||
return ret_type();
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "yaml-cpp/anchor.h"
|
||||
#include "yaml-cpp/contrib/anchordict.h"
|
||||
#include "yaml-cpp/contrib/graphbuilder.h"
|
||||
#include "yaml-cpp/emitterstyle.h"
|
||||
#include "yaml-cpp/eventhandler.h"
|
||||
|
||||
|
@@ -3,7 +3,7 @@
|
||||
namespace YAML {
|
||||
Directives::Directives() : version{true, 1, 2}, tags{} {}
|
||||
|
||||
std::string Directives::TranslateTagHandle(
|
||||
const std::string Directives::TranslateTagHandle(
|
||||
const std::string& handle) const {
|
||||
auto it = tags.find(handle);
|
||||
if (it == tags.end()) {
|
||||
|
@@ -19,7 +19,7 @@ struct Version {
|
||||
struct Directives {
|
||||
Directives();
|
||||
|
||||
std::string TranslateTagHandle(const std::string& handle) const;
|
||||
const std::string TranslateTagHandle(const std::string& handle) const;
|
||||
|
||||
Version version;
|
||||
std::map<std::string, std::string> tags;
|
||||
|
@@ -116,13 +116,8 @@ void EmitFromEvents::BeginNode() {
|
||||
}
|
||||
|
||||
void EmitFromEvents::EmitProps(const std::string& tag, anchor_t anchor) {
|
||||
if (!tag.empty() && tag != "?" && tag != "!"){
|
||||
if (tag[0] == '!') {
|
||||
m_emitter << LocalTag(std::string(tag.begin()+1, tag.end()));
|
||||
} else {
|
||||
m_emitter << VerbatimTag(tag);
|
||||
}
|
||||
}
|
||||
if (!tag.empty() && tag != "?" && tag != "!")
|
||||
m_emitter << VerbatimTag(tag);
|
||||
if (anchor)
|
||||
m_emitter << Anchor(ToString(anchor));
|
||||
}
|
||||
|
@@ -213,8 +213,7 @@ void Emitter::EmitEndSeq() {
|
||||
if (m_pState->CurGroupFlowType() == FlowType::Flow) {
|
||||
if (m_stream.comment())
|
||||
m_stream << "\n";
|
||||
if (originalType == FlowType::Block || m_pState->HasBegunNode())
|
||||
m_stream << IndentTo(m_pState->CurIndent());
|
||||
m_stream << IndentTo(m_pState->CurIndent());
|
||||
if (originalType == FlowType::Block) {
|
||||
m_stream << "[";
|
||||
} else {
|
||||
@@ -534,8 +533,7 @@ void Emitter::BlockMapPrepareNode(EmitterNodeType::value child) {
|
||||
if (m_pState->GetMapKeyFormat() == LongKey)
|
||||
m_pState->SetLongKey();
|
||||
if (child == EmitterNodeType::BlockSeq ||
|
||||
child == EmitterNodeType::BlockMap ||
|
||||
child == EmitterNodeType::Property)
|
||||
child == EmitterNodeType::BlockMap)
|
||||
m_pState->SetLongKey();
|
||||
|
||||
if (m_pState->CurGroupLongKey())
|
||||
@@ -716,33 +714,33 @@ StringEscaping::value GetStringEscapingStyle(const EMITTER_MANIP emitterManip) {
|
||||
}
|
||||
}
|
||||
|
||||
Emitter& Emitter::Write(const char* str, std::size_t size) {
|
||||
Emitter& Emitter::Write(const std::string& str) {
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
StringEscaping::value stringEscaping = GetStringEscapingStyle(m_pState->GetOutputCharset());
|
||||
|
||||
const StringFormat::value strFormat =
|
||||
Utils::ComputeStringFormat(str, size, m_pState->GetStringFormat(),
|
||||
Utils::ComputeStringFormat(str, m_pState->GetStringFormat(),
|
||||
m_pState->CurGroupFlowType(), stringEscaping == StringEscaping::NonAscii);
|
||||
|
||||
if (strFormat == StringFormat::Literal || size > 1024)
|
||||
if (strFormat == StringFormat::Literal || str.size() > 1024)
|
||||
m_pState->SetMapKeyFormat(YAML::LongKey, FmtScope::Local);
|
||||
|
||||
PrepareNode(EmitterNodeType::Scalar);
|
||||
|
||||
switch (strFormat) {
|
||||
case StringFormat::Plain:
|
||||
m_stream.write(str, size);
|
||||
m_stream << str;
|
||||
break;
|
||||
case StringFormat::SingleQuoted:
|
||||
Utils::WriteSingleQuotedString(m_stream, str, size);
|
||||
Utils::WriteSingleQuotedString(m_stream, str);
|
||||
break;
|
||||
case StringFormat::DoubleQuoted:
|
||||
Utils::WriteDoubleQuotedString(m_stream, str, size, stringEscaping);
|
||||
Utils::WriteDoubleQuotedString(m_stream, str, stringEscaping);
|
||||
break;
|
||||
case StringFormat::Literal:
|
||||
Utils::WriteLiteralString(m_stream, str, size,
|
||||
Utils::WriteLiteralString(m_stream, str,
|
||||
m_pState->CurIndent() + m_pState->GetIndent());
|
||||
break;
|
||||
}
|
||||
@@ -752,10 +750,6 @@ Emitter& Emitter::Write(const char* str, std::size_t size) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Emitter& Emitter::Write(const std::string& str) {
|
||||
return Write(str.data(), str.size());
|
||||
}
|
||||
|
||||
std::size_t Emitter::GetFloatPrecision() const {
|
||||
return m_pState->GetFloatPrecision();
|
||||
}
|
||||
@@ -869,7 +863,7 @@ Emitter& Emitter::Write(const _Alias& alias) {
|
||||
|
||||
PrepareNode(EmitterNodeType::Scalar);
|
||||
|
||||
if (!Utils::WriteAlias(m_stream, alias.content.data(), alias.content.size())) {
|
||||
if (!Utils::WriteAlias(m_stream, alias.content)) {
|
||||
m_pState->SetError(ErrorMsg::INVALID_ALIAS);
|
||||
return *this;
|
||||
}
|
||||
@@ -892,7 +886,7 @@ Emitter& Emitter::Write(const _Anchor& anchor) {
|
||||
|
||||
PrepareNode(EmitterNodeType::Property);
|
||||
|
||||
if (!Utils::WriteAnchor(m_stream, anchor.content.data(), anchor.content.size())) {
|
||||
if (!Utils::WriteAnchor(m_stream, anchor.content)) {
|
||||
m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
|
||||
return *this;
|
||||
}
|
||||
@@ -941,7 +935,7 @@ Emitter& Emitter::Write(const _Comment& comment) {
|
||||
|
||||
if (m_stream.col() > 0)
|
||||
m_stream << Indentation(m_pState->GetPreCommentIndent());
|
||||
Utils::WriteComment(m_stream, comment.content.data(), comment.content.size(),
|
||||
Utils::WriteComment(m_stream, comment.content,
|
||||
m_pState->GetPostCommentIndent());
|
||||
|
||||
m_pState->SetNonContent();
|
||||
|
@@ -1,5 +1,4 @@
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
@@ -89,8 +88,8 @@ int Utf8BytesIndicated(char ch) {
|
||||
bool IsTrailingByte(char ch) { return (ch & 0xC0) == 0x80; }
|
||||
|
||||
bool GetNextCodePointAndAdvance(int& codePoint,
|
||||
const char*& first,
|
||||
const char* last) {
|
||||
std::string::const_iterator& first,
|
||||
std::string::const_iterator last) {
|
||||
if (first == last)
|
||||
return false;
|
||||
|
||||
@@ -153,39 +152,39 @@ void WriteCodePoint(ostream_wrapper& out, int codePoint) {
|
||||
}
|
||||
}
|
||||
|
||||
bool IsValidPlainScalar(const char* str, std::size_t size, FlowType::value flowType,
|
||||
bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
|
||||
bool allowOnlyAscii) {
|
||||
// check against null
|
||||
if (IsNullString(str, size)) {
|
||||
if (IsNullString(str)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check the start
|
||||
const RegEx& start = (flowType == FlowType::Flow ? Exp::PlainScalarInFlow()
|
||||
: Exp::PlainScalar());
|
||||
if (!start.Matches(StringCharSource(str, size))) {
|
||||
if (!start.Matches(str)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// and check the end for plain whitespace (which can't be faithfully kept in a
|
||||
// plain scalar)
|
||||
if (size != 0 && str[size - 1] == ' ') {
|
||||
if (!str.empty() && *str.rbegin() == ' ') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// then check until something is disallowed
|
||||
static const RegEx disallowed_flow =
|
||||
static const RegEx& disallowed_flow =
|
||||
Exp::EndScalarInFlow() | (Exp::BlankOrBreak() + Exp::Comment()) |
|
||||
Exp::NotPrintable() | Exp::Utf8_ByteOrderMark() | Exp::Break() |
|
||||
Exp::Tab() | Exp::Ampersand();
|
||||
static const RegEx disallowed_block =
|
||||
Exp::Tab();
|
||||
static const RegEx& disallowed_block =
|
||||
Exp::EndScalar() | (Exp::BlankOrBreak() + Exp::Comment()) |
|
||||
Exp::NotPrintable() | Exp::Utf8_ByteOrderMark() | Exp::Break() |
|
||||
Exp::Tab() | Exp::Ampersand();
|
||||
Exp::Tab();
|
||||
const RegEx& disallowed =
|
||||
flowType == FlowType::Flow ? disallowed_flow : disallowed_block;
|
||||
|
||||
StringCharSource buffer(str, size);
|
||||
StringCharSource buffer(str.c_str(), str.size());
|
||||
while (buffer) {
|
||||
if (disallowed.Matches(buffer)) {
|
||||
return false;
|
||||
@@ -199,22 +198,22 @@ bool IsValidPlainScalar(const char* str, std::size_t size, FlowType::value flowT
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsValidSingleQuotedScalar(const char* str, std::size_t size, bool escapeNonAscii) {
|
||||
bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii) {
|
||||
// TODO: check for non-printable characters?
|
||||
return std::none_of(str, str + size, [=](char ch) {
|
||||
return std::none_of(str.begin(), str.end(), [=](char ch) {
|
||||
return (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch))) ||
|
||||
(ch == '\n');
|
||||
});
|
||||
}
|
||||
|
||||
bool IsValidLiteralScalar(const char* str, std::size_t size, FlowType::value flowType,
|
||||
bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType,
|
||||
bool escapeNonAscii) {
|
||||
if (flowType == FlowType::Flow) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: check for non-printable characters?
|
||||
return std::none_of(str, str + size, [=](char ch) {
|
||||
return std::none_of(str.begin(), str.end(), [=](char ch) {
|
||||
return (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch)));
|
||||
});
|
||||
}
|
||||
@@ -254,10 +253,10 @@ void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint, StringE
|
||||
out << hexDigits[(codePoint >> (4 * (digits - 1))) & 0xF];
|
||||
}
|
||||
|
||||
bool WriteAliasName(ostream_wrapper& out, const char* str, std::size_t size) {
|
||||
bool WriteAliasName(ostream_wrapper& out, const std::string& str) {
|
||||
int codePoint;
|
||||
for (const char* i = str;
|
||||
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
|
||||
for (std::string::const_iterator i = str.begin();
|
||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
||||
if (!IsAnchorChar(codePoint)) {
|
||||
return false;
|
||||
}
|
||||
@@ -268,25 +267,25 @@ bool WriteAliasName(ostream_wrapper& out, const char* str, std::size_t size) {
|
||||
}
|
||||
} // namespace
|
||||
|
||||
StringFormat::value ComputeStringFormat(const char* str, std::size_t size,
|
||||
StringFormat::value ComputeStringFormat(const std::string& str,
|
||||
EMITTER_MANIP strFormat,
|
||||
FlowType::value flowType,
|
||||
bool escapeNonAscii) {
|
||||
switch (strFormat) {
|
||||
case Auto:
|
||||
if (IsValidPlainScalar(str, size, flowType, escapeNonAscii)) {
|
||||
if (IsValidPlainScalar(str, flowType, escapeNonAscii)) {
|
||||
return StringFormat::Plain;
|
||||
}
|
||||
return StringFormat::DoubleQuoted;
|
||||
case SingleQuoted:
|
||||
if (IsValidSingleQuotedScalar(str, size, escapeNonAscii)) {
|
||||
if (IsValidSingleQuotedScalar(str, escapeNonAscii)) {
|
||||
return StringFormat::SingleQuoted;
|
||||
}
|
||||
return StringFormat::DoubleQuoted;
|
||||
case DoubleQuoted:
|
||||
return StringFormat::DoubleQuoted;
|
||||
case Literal:
|
||||
if (IsValidLiteralScalar(str, size, flowType, escapeNonAscii)) {
|
||||
if (IsValidLiteralScalar(str, flowType, escapeNonAscii)) {
|
||||
return StringFormat::Literal;
|
||||
}
|
||||
return StringFormat::DoubleQuoted;
|
||||
@@ -297,11 +296,11 @@ StringFormat::value ComputeStringFormat(const char* str, std::size_t size,
|
||||
return StringFormat::DoubleQuoted;
|
||||
}
|
||||
|
||||
bool WriteSingleQuotedString(ostream_wrapper& out, const char* str, std::size_t size) {
|
||||
bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str) {
|
||||
out << "'";
|
||||
int codePoint;
|
||||
for (const char* i = str;
|
||||
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
|
||||
for (std::string::const_iterator i = str.begin();
|
||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
||||
if (codePoint == '\n') {
|
||||
return false; // We can't handle a new line and the attendant indentation
|
||||
// yet
|
||||
@@ -317,12 +316,12 @@ bool WriteSingleQuotedString(ostream_wrapper& out, const char* str, std::size_t
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteDoubleQuotedString(ostream_wrapper& out, const char* str, std::size_t size,
|
||||
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
|
||||
StringEscaping::value stringEscaping) {
|
||||
out << "\"";
|
||||
int codePoint;
|
||||
for (const char* i = str;
|
||||
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
|
||||
for (std::string::const_iterator i = str.begin();
|
||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
||||
switch (codePoint) {
|
||||
case '\"':
|
||||
out << "\\\"";
|
||||
@@ -364,12 +363,12 @@ bool WriteDoubleQuotedString(ostream_wrapper& out, const char* str, std::size_t
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteLiteralString(ostream_wrapper& out, const char* str, std::size_t size,
|
||||
bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
|
||||
std::size_t indent) {
|
||||
out << "|\n";
|
||||
int codePoint;
|
||||
for (const char* i = str;
|
||||
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
|
||||
for (std::string::const_iterator i = str.begin();
|
||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
||||
if (codePoint == '\n') {
|
||||
out << "\n";
|
||||
} else {
|
||||
@@ -407,14 +406,14 @@ bool WriteChar(ostream_wrapper& out, char ch, StringEscaping::value stringEscapi
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteComment(ostream_wrapper& out, const char* str, std::size_t size,
|
||||
bool WriteComment(ostream_wrapper& out, const std::string& str,
|
||||
std::size_t postCommentIndent) {
|
||||
const std::size_t curIndent = out.col();
|
||||
out << "#" << Indentation(postCommentIndent);
|
||||
out.set_comment();
|
||||
int codePoint;
|
||||
for (const char* i = str;
|
||||
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
|
||||
for (std::string::const_iterator i = str.begin();
|
||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
||||
if (codePoint == '\n') {
|
||||
out << "\n"
|
||||
<< IndentTo(curIndent) << "#" << Indentation(postCommentIndent);
|
||||
@@ -426,14 +425,14 @@ bool WriteComment(ostream_wrapper& out, const char* str, std::size_t size,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteAlias(ostream_wrapper& out, const char* str, std::size_t size) {
|
||||
bool WriteAlias(ostream_wrapper& out, const std::string& str) {
|
||||
out << "*";
|
||||
return WriteAliasName(out, str, size);
|
||||
return WriteAliasName(out, str);
|
||||
}
|
||||
|
||||
bool WriteAnchor(ostream_wrapper& out, const char* str, std::size_t size) {
|
||||
bool WriteAnchor(ostream_wrapper& out, const std::string& str) {
|
||||
out << "&";
|
||||
return WriteAliasName(out, str, size);
|
||||
return WriteAliasName(out, str);
|
||||
}
|
||||
|
||||
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim) {
|
||||
@@ -490,8 +489,7 @@ bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
|
||||
}
|
||||
|
||||
bool WriteBinary(ostream_wrapper& out, const Binary& binary) {
|
||||
std::string encoded = EncodeBase64(binary.data(), binary.size());
|
||||
WriteDoubleQuotedString(out, encoded.data(), encoded.size(),
|
||||
WriteDoubleQuotedString(out, EncodeBase64(binary.data(), binary.size()),
|
||||
StringEscaping::None);
|
||||
return true;
|
||||
}
|
||||
|
@@ -29,22 +29,22 @@ struct StringEscaping {
|
||||
};
|
||||
|
||||
namespace Utils {
|
||||
StringFormat::value ComputeStringFormat(const char* str, std::size_t size,
|
||||
StringFormat::value ComputeStringFormat(const std::string& str,
|
||||
EMITTER_MANIP strFormat,
|
||||
FlowType::value flowType,
|
||||
bool escapeNonAscii);
|
||||
|
||||
bool WriteSingleQuotedString(ostream_wrapper& out, const char* str, std::size_t size);
|
||||
bool WriteDoubleQuotedString(ostream_wrapper& out, const char* str, std::size_t size,
|
||||
bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str);
|
||||
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
|
||||
StringEscaping::value stringEscaping);
|
||||
bool WriteLiteralString(ostream_wrapper& out, const char* str, std::size_t size,
|
||||
bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
|
||||
std::size_t indent);
|
||||
bool WriteChar(ostream_wrapper& out, char ch,
|
||||
StringEscaping::value stringEscapingStyle);
|
||||
bool WriteComment(ostream_wrapper& out, const char* str, std::size_t size,
|
||||
bool WriteComment(ostream_wrapper& out, const std::string& str,
|
||||
std::size_t postCommentIndent);
|
||||
bool WriteAlias(ostream_wrapper& out, const char* str, std::size_t size);
|
||||
bool WriteAnchor(ostream_wrapper& out, const char* str, std::size_t size);
|
||||
bool WriteAlias(ostream_wrapper& out, const std::string& str);
|
||||
bool WriteAnchor(ostream_wrapper& out, const std::string& str);
|
||||
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim);
|
||||
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
|
||||
const std::string& tag);
|
||||
|
@@ -37,7 +37,7 @@ inline const RegEx& Blank() {
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& Break() {
|
||||
static const RegEx e = RegEx('\n') | RegEx("\r\n") | RegEx('\r');
|
||||
static const RegEx e = RegEx('\n') | RegEx("\r\n");
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& BlankOrBreak() {
|
||||
@@ -117,10 +117,6 @@ inline const RegEx& ValueInJSONFlow() {
|
||||
static const RegEx e = RegEx(':');
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& Ampersand() {
|
||||
static const RegEx e = RegEx('&');
|
||||
return e;
|
||||
}
|
||||
inline const RegEx Comment() {
|
||||
static const RegEx e = RegEx('#');
|
||||
return e;
|
||||
|
@@ -1,238 +0,0 @@
|
||||
#include "yaml-cpp/fptostring.h"
|
||||
#include "contrib/dragonbox.h"
|
||||
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <tuple>
|
||||
|
||||
namespace YAML {
|
||||
namespace detail {
|
||||
namespace fp_formatting {
|
||||
|
||||
/**
|
||||
* Converts a integer into its ASCII digits.
|
||||
*
|
||||
* @param begin/end - a buffer, must be at least 20bytes long.
|
||||
* @param value - input value.
|
||||
* @param width - minimum number of digits, fill with '0' to the left. Must be equal or smaller than the buffer size.
|
||||
* @return - number of digits filled into the buffer (or -1 if preconditions are not meet)
|
||||
*
|
||||
* Example:
|
||||
* std::array<char, 20> buffer;
|
||||
* auto ct = ConvertToChars(buffer.begin(), buffer.end(), 23, 3);
|
||||
* assert(ct = 3);
|
||||
* assert(buffer[0] == '0');
|
||||
* assert(buffer[1] == '2');
|
||||
* assert(buffer[2] == '3');
|
||||
*/
|
||||
int ConvertToChars(char* begin, char* end, size_t value, int width=1) {
|
||||
// precondition of this function (will trigger in debug build)
|
||||
assert(width >= 1);
|
||||
assert(end >= begin); // end must be after begin
|
||||
assert(end-begin >= width); // Buffer must be large enough
|
||||
assert(end-begin >= 20); // 2^64 has 20digits, so at least 20 digits must be available
|
||||
|
||||
// defensive programming, abort if precondition are not met (will trigger in release build)
|
||||
if (width < 1) {
|
||||
return -1;
|
||||
}
|
||||
if (end < begin) {
|
||||
return -1;
|
||||
}
|
||||
if (end-begin < width) {
|
||||
return -1;
|
||||
}
|
||||
if (end-begin < 20) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// count number of digits, and fill digits array accordingly
|
||||
int digits_ct{};
|
||||
while (value > 0) {
|
||||
char c = value % 10 + '0';
|
||||
value = value / 10;
|
||||
digits_ct += 1;
|
||||
*(end-digits_ct) = c;
|
||||
}
|
||||
while(digits_ct < width) {
|
||||
assert(digits_ct < 64);
|
||||
digits_ct += 1;
|
||||
*(end-digits_ct) = '0';
|
||||
}
|
||||
// move data to the front of the array
|
||||
std::memmove(begin, end-digits_ct, digits_ct);
|
||||
return digits_ct;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a float or double to a string.
|
||||
*
|
||||
* converts a value 'v' to a string. Uses dragonbox for formatting.
|
||||
*/
|
||||
template <typename T>
|
||||
std::string FpToString(T v, int precision = 0) {
|
||||
// hard coded constant, at which exponent should switch to a scientific notation
|
||||
int const lowerExponentThreshold = -5;
|
||||
int const upperExponentThreshold = (precision==0)?6:precision;
|
||||
if (precision == 0) {
|
||||
precision = 6;
|
||||
}
|
||||
|
||||
// dragonbox/to_decimal does not handle value 0, inf, NaN
|
||||
if (v == 0 || std::isinf(v) || std::isnan(v)) {
|
||||
std::stringstream ss;
|
||||
ss.imbue(std::locale("C"));
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
auto r = jkj::dragonbox::to_decimal(v);
|
||||
|
||||
auto digits = std::array<char, 20>{}; // max digits of size_t is 20.
|
||||
auto digits_ct = ConvertToChars(digits.data(), digits.data() + digits.size(), r.significand);
|
||||
|
||||
// defensive programming, ConvertToChars arguments are invalid
|
||||
if (digits_ct == -1) {
|
||||
std::stringstream ss;
|
||||
ss.imbue(std::locale("C"));
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// check if requested precision is lower than
|
||||
// required digits for exact representation
|
||||
if (digits_ct > precision) {
|
||||
auto diff = digits_ct - precision;
|
||||
r.exponent += diff;
|
||||
digits_ct = precision;
|
||||
|
||||
// round numbers if required
|
||||
if (digits[digits_ct] >= '5') {
|
||||
int i{digits_ct-1};
|
||||
digits[i] += 1;
|
||||
while (digits[i] == '9'+1) {
|
||||
digits_ct -= 1;
|
||||
r.exponent += 1;
|
||||
if (i > 0) {
|
||||
digits[i-1] += 1;
|
||||
i -= 1;
|
||||
} else {
|
||||
digits_ct = 1;
|
||||
digits[0] = '1';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::array<char, 28> output_buffer; // max digits of size_t plus sign, a dot and 2 letters for 'e+' or 'e-' and 4 letters for the exponent
|
||||
auto output_ptr = &output_buffer[0];
|
||||
|
||||
// print '-' symbol for negative numbers
|
||||
if (r.is_negative) {
|
||||
*(output_ptr++) = '-';
|
||||
}
|
||||
|
||||
// exponent if only a single non-zero digit is before the decimal point
|
||||
int const exponent = r.exponent + digits_ct - 1;
|
||||
|
||||
// case 1: scientific notation
|
||||
if (exponent >= upperExponentThreshold || exponent <= lowerExponentThreshold) {
|
||||
// print first digit
|
||||
*(output_ptr++) = digits[0];
|
||||
|
||||
// print digits after decimal point
|
||||
if (digits_ct > 1) {
|
||||
*(output_ptr++) = '.';
|
||||
// print significant numbers after decimal point
|
||||
for (int i{1}; i < digits_ct; ++i) {
|
||||
*(output_ptr++) = digits[i];
|
||||
}
|
||||
}
|
||||
*(output_ptr++) = 'e';
|
||||
*(output_ptr++) = (exponent>=0)?'+':'-';
|
||||
auto exp_digits = std::array<char, 20>{};
|
||||
auto exp_digits_ct = ConvertToChars(exp_digits.data(), exp_digits.data() + exp_digits.size(), std::abs(exponent), /*.precision=*/ 2);
|
||||
|
||||
// defensive programming, ConvertToChars arguments are invalid
|
||||
if (exp_digits_ct == -1) {
|
||||
std::stringstream ss;
|
||||
ss.imbue(std::locale("C"));
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
for (int i{0}; i < exp_digits_ct; ++i) {
|
||||
*(output_ptr++) = exp_digits[i];
|
||||
}
|
||||
|
||||
// case 2: default notation
|
||||
} else {
|
||||
auto const digits_end = digits.begin() + digits_ct;
|
||||
auto digits_iter = digits.begin();
|
||||
|
||||
// print digits before point
|
||||
int const before_decimal_digits = digits_ct + r.exponent;
|
||||
if (before_decimal_digits > 0) {
|
||||
// print digits before point
|
||||
for (int i{0}; i < std::min(before_decimal_digits, digits_ct); ++i) {
|
||||
*(output_ptr++) = *(digits_iter++);
|
||||
}
|
||||
// print trailing zeros before point
|
||||
for (int i{0}; i < before_decimal_digits - digits_ct; ++i) {
|
||||
*(output_ptr++) = '0';
|
||||
}
|
||||
|
||||
// print 0 before point if none where printed before
|
||||
} else {
|
||||
*(output_ptr++) = '0';
|
||||
}
|
||||
|
||||
if (digits_iter != digits_end) {
|
||||
*(output_ptr++) = '.';
|
||||
// print 0 after decimal point, to fill until first digits
|
||||
int const after_decimal_zeros = -digits_ct - r.exponent;
|
||||
for (int i{0}; i < after_decimal_zeros; ++i) {
|
||||
*(output_ptr++) = '0';
|
||||
}
|
||||
|
||||
// print significant numbers after decimal point
|
||||
for (;digits_iter < digits_end; ++digits_iter) {
|
||||
*(output_ptr++) = *digits_iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
*output_ptr = '\0';
|
||||
return std::string{&output_buffer[0], output_ptr};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
std::string FpToString(float v, size_t precision) {
|
||||
return detail::fp_formatting::FpToString(v, precision);
|
||||
}
|
||||
|
||||
std::string FpToString(double v, size_t precision) {
|
||||
return detail::fp_formatting::FpToString(v, precision);
|
||||
}
|
||||
|
||||
/**
|
||||
* dragonbox only works for floats/doubles not long double
|
||||
*/
|
||||
std::string FpToString(long double v, size_t precision) {
|
||||
std::stringstream ss;
|
||||
ss.imbue(std::locale("C"));
|
||||
if (precision == 0) {
|
||||
precision = std::numeric_limits<long double>::max_digits10;
|
||||
}
|
||||
ss.precision(precision);
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
}
|
@@ -7,6 +7,7 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <cstddef>
|
||||
|
||||
#include "yaml-cpp/ostream_wrapper.h"
|
||||
|
@@ -9,10 +9,6 @@ void memory_holder::merge(memory_holder& rhs) {
|
||||
if (m_pMemory == rhs.m_pMemory)
|
||||
return;
|
||||
|
||||
if (m_pMemory->size() < rhs.m_pMemory->size()) {
|
||||
std::swap(m_pMemory, rhs.m_pMemory);
|
||||
}
|
||||
|
||||
m_pMemory->merge(*rhs.m_pMemory);
|
||||
rhs.m_pMemory = m_pMemory;
|
||||
}
|
||||
@@ -26,9 +22,5 @@ node& memory::create_node() {
|
||||
void memory::merge(const memory& rhs) {
|
||||
m_nodes.insert(rhs.m_nodes.begin(), rhs.m_nodes.end());
|
||||
}
|
||||
|
||||
size_t memory::size() const {
|
||||
return m_nodes.size();
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace YAML
|
||||
|
@@ -13,7 +13,7 @@
|
||||
|
||||
namespace YAML {
|
||||
namespace detail {
|
||||
YAML_CPP_API std::atomic<size_t> node::m_amount{0};
|
||||
std::atomic<size_t> node::m_amount{0};
|
||||
|
||||
const std::string& node_data::empty_scalar() {
|
||||
static const std::string svalue;
|
||||
@@ -310,7 +310,6 @@ void node_data::convert_sequence_to_map(const shared_memory_holder& pMemory) {
|
||||
reset_map();
|
||||
for (std::size_t i = 0; i < m_sequence.size(); i++) {
|
||||
std::stringstream stream;
|
||||
stream.imbue(std::locale("C"));
|
||||
stream << i;
|
||||
|
||||
node& key = pMemory->create_node();
|
||||
|
13
src/null.cpp
13
src/null.cpp
@@ -1,17 +1,10 @@
|
||||
#include "yaml-cpp/null.h"
|
||||
#include <cstring>
|
||||
|
||||
namespace YAML {
|
||||
_Null Null;
|
||||
|
||||
template <std::size_t N>
|
||||
static bool same(const char* str, std::size_t size, const char (&literal)[N]) {
|
||||
constexpr int literalSize = N - 1; // minus null terminator
|
||||
return size == literalSize && std::strncmp(str, literal, literalSize) == 0;
|
||||
}
|
||||
|
||||
bool IsNullString(const char* str, std::size_t size) {
|
||||
return size == 0 || same(str, size, "~") || same(str, size, "null") ||
|
||||
same(str, size, "Null") || same(str, size, "NULL");
|
||||
bool IsNullString(const std::string& str) {
|
||||
return str.empty() || str == "~" || str == "null" || str == "Null" ||
|
||||
str == "NULL";
|
||||
}
|
||||
} // namespace YAML
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <ostream>
|
||||
#include <iostream>
|
||||
|
||||
namespace YAML {
|
||||
ostream_wrapper::ostream_wrapper()
|
||||
|
@@ -53,7 +53,7 @@ std::vector<Node> LoadAll(std::istream& input) {
|
||||
Parser parser(input);
|
||||
while (true) {
|
||||
NodeBuilder builder;
|
||||
if (!parser.HandleNextDocument(builder) || builder.Root().IsNull()) {
|
||||
if (!parser.HandleNextDocument(builder)) {
|
||||
break;
|
||||
}
|
||||
docs.push_back(builder.Root());
|
||||
|
@@ -77,7 +77,6 @@ void Parser::HandleYamlDirective(const Token& token) {
|
||||
}
|
||||
|
||||
std::stringstream str(token.params[0]);
|
||||
str.imbue(std::locale("C"));
|
||||
str >> m_pDirectives->version.major;
|
||||
str.get();
|
||||
str >> m_pDirectives->version.minor;
|
||||
|
@@ -27,10 +27,6 @@ inline bool RegEx::Matches(const Stream& in) const { return Match(in) >= 0; }
|
||||
|
||||
template <typename Source>
|
||||
inline bool RegEx::Matches(const Source& source) const {
|
||||
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201103L) || __cplusplus >= 201103L)
|
||||
static_assert(!std::is_same<Source, const char*>::value,
|
||||
#endif
|
||||
"Must use StringCharSource instead of plain C-string");
|
||||
return Match(source) >= 0;
|
||||
}
|
||||
|
||||
|
@@ -13,7 +13,6 @@ Scanner::Scanner(std::istream& in)
|
||||
m_startedStream(false),
|
||||
m_endedStream(false),
|
||||
m_simpleKeyAllowed(false),
|
||||
m_scalarValueAllowed(false),
|
||||
m_canBeJSONFlow(false),
|
||||
m_simpleKeys{},
|
||||
m_indents{},
|
||||
@@ -128,17 +127,6 @@ void Scanner::ScanNextToken() {
|
||||
}
|
||||
|
||||
if (INPUT.peek() == Keys::FlowEntry) {
|
||||
// values starting with `,` are not allowed.
|
||||
// eg: reject `,foo`
|
||||
if (INPUT.column() == 0) {
|
||||
throw ParserException(INPUT.mark(), ErrorMsg::UNEXPECTED_FLOW);
|
||||
}
|
||||
// if we already parsed a quoted scalar value and we are not in a flow,
|
||||
// then `,` is not a valid character.
|
||||
// eg: reject `"foo",`
|
||||
if (!m_scalarValueAllowed) {
|
||||
throw ParserException(INPUT.mark(), ErrorMsg::UNEXPECTED_SCALAR);
|
||||
}
|
||||
return ScanFlowEntry();
|
||||
}
|
||||
|
||||
@@ -171,13 +159,6 @@ void Scanner::ScanNextToken() {
|
||||
return ScanBlockScalar();
|
||||
}
|
||||
|
||||
// if we already parsed a quoted scalar value in this line,
|
||||
// another scalar value is an error.
|
||||
// eg: reject `"foo" "bar"`
|
||||
if (!m_scalarValueAllowed) {
|
||||
throw ParserException(INPUT.mark(), ErrorMsg::UNEXPECTED_SCALAR);
|
||||
}
|
||||
|
||||
if (INPUT.peek() == '\'' || INPUT.peek() == '\"') {
|
||||
return ScanQuotedScalar();
|
||||
}
|
||||
@@ -222,9 +203,6 @@ void Scanner::ScanToNextToken() {
|
||||
// oh yeah, and let's get rid of that simple key
|
||||
InvalidateSimpleKey();
|
||||
|
||||
// new line - we accept a scalar value now
|
||||
m_scalarValueAllowed = true;
|
||||
|
||||
// new line - we may be able to accept a simple key now
|
||||
if (InBlockContext()) {
|
||||
m_simpleKeyAllowed = true;
|
||||
@@ -267,7 +245,6 @@ const RegEx& Scanner::GetValueRegex() const {
|
||||
void Scanner::StartStream() {
|
||||
m_startedStream = true;
|
||||
m_simpleKeyAllowed = true;
|
||||
m_scalarValueAllowed = true;
|
||||
std::unique_ptr<IndentMarker> pIndent(
|
||||
new IndentMarker(-1, IndentMarker::NONE));
|
||||
m_indentRefs.push_back(std::move(pIndent));
|
||||
@@ -284,7 +261,6 @@ void Scanner::EndStream() {
|
||||
PopAllSimpleKeys();
|
||||
|
||||
m_simpleKeyAllowed = false;
|
||||
m_scalarValueAllowed = false;
|
||||
m_endedStream = true;
|
||||
}
|
||||
|
||||
|
@@ -9,7 +9,9 @@
|
||||
|
||||
#include <cstddef>
|
||||
#include <ios>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
|
||||
@@ -177,7 +179,6 @@ class Scanner {
|
||||
// state info
|
||||
bool m_startedStream, m_endedStream;
|
||||
bool m_simpleKeyAllowed;
|
||||
bool m_scalarValueAllowed;
|
||||
bool m_canBeJSONFlow;
|
||||
std::stack<SimpleKey> m_simpleKeys;
|
||||
std::stack<IndentMarker *> m_indents;
|
||||
|
@@ -211,9 +211,6 @@ void Scanner::ScanValue() {
|
||||
m_simpleKeyAllowed = InBlockContext();
|
||||
}
|
||||
|
||||
// we are parsing a `key: value` pair; scalars are always allowed
|
||||
m_scalarValueAllowed = true;
|
||||
|
||||
// eat
|
||||
Mark mark = INPUT.mark();
|
||||
INPUT.eat(1);
|
||||
@@ -363,10 +360,6 @@ void Scanner::ScanQuotedScalar() {
|
||||
// and scan
|
||||
scalar = ScanScalar(INPUT, params);
|
||||
m_simpleKeyAllowed = false;
|
||||
// we just scanned a quoted scalar;
|
||||
// we can only have another scalar in this line
|
||||
// if we are in a flow, eg: `[ "foo", "bar" ]` is ok, but `"foo", "bar"` isn't.
|
||||
m_scalarValueAllowed = InFlowContext();
|
||||
m_canBeJSONFlow = true;
|
||||
|
||||
Token token(Token::NON_PLAIN_SCALAR, mark);
|
||||
|
@@ -1,3 +1,4 @@
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
|
||||
@@ -92,9 +93,9 @@ void SingleDocParser::HandleNode(EventHandler& eventHandler) {
|
||||
// add non-specific tags
|
||||
if (tag.empty())
|
||||
tag = (token.type == Token::NON_PLAIN_SCALAR ? "!" : "?");
|
||||
|
||||
if (token.type == Token::PLAIN_SCALAR
|
||||
&& tag.compare("?") == 0 && IsNullString(token.value.data(), token.value.size())) {
|
||||
|
||||
if (token.type == Token::PLAIN_SCALAR
|
||||
&& tag.compare("?") == 0 && IsNullString(token.value)) {
|
||||
eventHandler.OnNull(mark, anchor);
|
||||
m_scanner.pop();
|
||||
return;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
#include <istream>
|
||||
#include <iostream>
|
||||
|
||||
#include "stream.h"
|
||||
|
||||
@@ -262,24 +262,7 @@ char Stream::get() {
|
||||
AdvanceCurrent();
|
||||
m_mark.column++;
|
||||
|
||||
// if line ending symbol is unknown, set it to the first
|
||||
// encountered line ending.
|
||||
// if line ending '\r' set ending symbol to '\r'
|
||||
// other wise set it to '\n'
|
||||
if (!m_lineEndingSymbol) {
|
||||
if (ch == '\n') { // line ending is '\n'
|
||||
m_lineEndingSymbol = '\n';
|
||||
} else if (ch == '\r') {
|
||||
auto ch2 = peek();
|
||||
if (ch2 == '\n') { // line ending is '\r\n'
|
||||
m_lineEndingSymbol = '\n';
|
||||
} else { // line ending is '\r'
|
||||
m_lineEndingSymbol = '\r';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ch == m_lineEndingSymbol) {
|
||||
if (ch == '\n') {
|
||||
m_mark.column = 0;
|
||||
m_mark.line++;
|
||||
}
|
||||
|
@@ -11,7 +11,7 @@
|
||||
#include <cstddef>
|
||||
#include <deque>
|
||||
#include <ios>
|
||||
#include <istream>
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
@@ -53,7 +53,6 @@ class Stream {
|
||||
Mark m_mark;
|
||||
|
||||
CharacterSet m_charSet;
|
||||
char m_lineEndingSymbol{}; // 0 means it is not determined yet, must be '\n' or '\r'
|
||||
mutable std::deque<char> m_readahead;
|
||||
unsigned char* const m_pPrefetched;
|
||||
mutable size_t m_nPrefetchedAvailable;
|
||||
|
@@ -29,7 +29,7 @@ Tag::Tag(const Token& token)
|
||||
}
|
||||
}
|
||||
|
||||
std::string Tag::Translate(const Directives& directives) {
|
||||
const std::string Tag::Translate(const Directives& directives) {
|
||||
switch (type) {
|
||||
case VERBATIM:
|
||||
return value;
|
||||
|
@@ -23,7 +23,7 @@ struct Tag {
|
||||
};
|
||||
|
||||
Tag(const Token& token);
|
||||
std::string Translate(const Directives& directives);
|
||||
const std::string Translate(const Directives& directives);
|
||||
|
||||
TYPE type;
|
||||
std::string handle, value;
|
||||
|
@@ -8,18 +8,17 @@
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/mark.h"
|
||||
#include <ostream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace YAML {
|
||||
constexpr const char* TokenNames[] = {
|
||||
const std::string TokenNames[] = {
|
||||
"DIRECTIVE", "DOC_START", "DOC_END", "BLOCK_SEQ_START",
|
||||
"BLOCK_MAP_START", "BLOCK_SEQ_END", "BLOCK_MAP_END", "BLOCK_ENTRY",
|
||||
"FLOW_SEQ_START", "FLOW_MAP_START", "FLOW_SEQ_END", "FLOW_MAP_END",
|
||||
"FLOW_MAP_COMPACT", "FLOW_ENTRY", "KEY", "VALUE",
|
||||
"ANCHOR", "ALIAS", "TAG", "SCALAR",
|
||||
"NON_PLAIN_SCALAR"};
|
||||
"ANCHOR", "ALIAS", "TAG", "SCALAR"};
|
||||
|
||||
struct Token {
|
||||
// enums
|
||||
|
@@ -1,28 +1,14 @@
|
||||
package(default_visibility = ["//test:__subpackages__"])
|
||||
|
||||
cc_library(
|
||||
name = "mock_event_handler",
|
||||
hdrs = ["mock_event_handler.h"],
|
||||
strip_include_prefix = "//test",
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "specexamples",
|
||||
hdrs = ["specexamples.h"],
|
||||
strip_include_prefix = "//test",
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "test",
|
||||
srcs = glob([
|
||||
"*.cpp",
|
||||
"*.h",
|
||||
"integrations/*.cpp",
|
||||
"node/*.cpp",
|
||||
]),
|
||||
deps = [
|
||||
":mock_event_handler",
|
||||
":specexamples",
|
||||
"//:yaml-cpp",
|
||||
"//:yaml-cpp_internal",
|
||||
"@googletest//:gtest_main",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
@@ -2,19 +2,13 @@ find_package(Threads REQUIRED)
|
||||
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
set(BUILD_MOCK ON CACHE BOOL "" FORCE)
|
||||
set(INSTALL_GTEST OFF CACHE BOOL "" FORCE)
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0048 NEW)
|
||||
|
||||
if(YAML_USE_SYSTEM_GTEST)
|
||||
find_package(GTest)
|
||||
if (NOT GTEST_FOUND)
|
||||
message(FATAL_ERROR "system googletest was requested but not found")
|
||||
endif()
|
||||
else()
|
||||
add_subdirectory(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/googletest-1.13.0"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/prefix")
|
||||
include_directories(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/googletest-1.13.0/googletest/include")
|
||||
endif()
|
||||
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")
|
||||
@@ -39,12 +33,11 @@ target_include_directories(yaml-cpp-tests
|
||||
target_compile_options(yaml-cpp-tests
|
||||
PRIVATE
|
||||
$<$<CXX_COMPILER_ID:Clang>:-Wno-c99-extensions -Wno-variadic-macros -Wno-sign-compare>
|
||||
$<$<CXX_COMPILER_ID:GNU>:-Wno-variadic-macros -Wno-sign-compare -Wno-narrowing>)
|
||||
$<$<CXX_COMPILER_ID:GNU>:-Wno-variadic-macros -Wno-sign-compare>)
|
||||
target_link_libraries(yaml-cpp-tests
|
||||
PRIVATE
|
||||
Threads::Threads
|
||||
yaml-cpp
|
||||
gtest
|
||||
gmock)
|
||||
|
||||
set_property(TARGET yaml-cpp-tests PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||
@@ -53,11 +46,4 @@ if (NOT DEFINED CMAKE_CXX_STANDARD)
|
||||
endif()
|
||||
|
||||
|
||||
add_test(NAME yaml-cpp::test COMMAND yaml-cpp-tests)
|
||||
|
||||
if (build-windows-dll)
|
||||
add_custom_command(
|
||||
TARGET yaml-cpp-tests
|
||||
POST_BUILD COMMAND ${CMAKE_COMMAND} -E
|
||||
copy_if_different "$<TARGET_FILE:yaml-cpp>" "$<TARGET_FILE_DIR:yaml-cpp-tests>")
|
||||
endif()
|
||||
add_test(yaml-cpp::test yaml-cpp-tests)
|
||||
|
@@ -1,14 +0,0 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include <yaml-cpp/binary.h>
|
||||
|
||||
TEST(BinaryTest, DecodingSimple) {
|
||||
std::string input{90, 71, 86, 104, 90, 71, 74, 108, 90, 87, 89, 61};
|
||||
const std::vector<unsigned char> &result = YAML::DecodeBase64(input);
|
||||
EXPECT_EQ(std::string(result.begin(), result.end()), "deadbeef");
|
||||
}
|
||||
|
||||
TEST(BinaryTest, DecodingNoCrashOnNegative) {
|
||||
std::string input{-58, -1, -99, 109};
|
||||
const std::vector<unsigned char> &result = YAML::DecodeBase64(input);
|
||||
EXPECT_TRUE(result.empty());
|
||||
}
|
@@ -1,21 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(yaml-cpp-consumer LANGUAGES CXX)
|
||||
|
||||
find_package(yaml-cpp CONFIG REQUIRED)
|
||||
get_target_property(LIBRARY_TYPE yaml-cpp::yaml-cpp TYPE)
|
||||
|
||||
if(LIBRARY_TYPE STREQUAL "SHARED_LIBRARY")
|
||||
if(NOT YAML_CPP_SHARED_LIBS_BUILT)
|
||||
message(FATAL_ERROR "Library type (${LIBRARY_TYPE}) contradicts config: ${YAML_CPP_SHARED_LIBS_BUILT}")
|
||||
endif()
|
||||
else()
|
||||
if(YAML_CPP_SHARED_LIBS_BUILT)
|
||||
message(FATAL_ERROR "Library type (${LIBRARY_TYPE}) contradicts config: ${YAML_CPP_SHARED_LIBS_BUILT}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_executable(main main.cpp)
|
||||
if (NOT DEFINED CMAKE_CXX_STANDARD)
|
||||
set_target_properties(main PROPERTIES CXX_STANDARD 11)
|
||||
endif()
|
||||
target_link_libraries(main PRIVATE ${YAML_CPP_LIBRARIES})
|
@@ -1,3 +0,0 @@
|
||||
#include "yaml-cpp/yaml.h"
|
||||
|
||||
int main(int, char**) { YAML::Parser foo{}; }
|
@@ -1,242 +0,0 @@
|
||||
#include "yaml-cpp/fptostring.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace YAML {
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* Helper function, that converts double to string as std::stringstream would do
|
||||
*/
|
||||
template <typename T>
|
||||
static std::string convert_with_stringstream(T v, size_t precision = 0) {
|
||||
std::stringstream ss;
|
||||
if (precision > 0) {
|
||||
ss << std::setprecision(precision);
|
||||
}
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// Caution: Test involving 'convert_with_stringstream' are based on std::stringstream
|
||||
// having certain printing behavior, if these changes, the unit test might fail.
|
||||
// This is not a fault of FpToString just a weakness of the way these
|
||||
// tests are constructed
|
||||
|
||||
TEST(FpToStringTest, conversion_double) {
|
||||
// Issue motivating FpToString function,
|
||||
// https://github.com/jbeder/yaml-cpp/issues/1289
|
||||
// Original problem at hand:
|
||||
EXPECT_EQ("34.34", FpToString(34.34));
|
||||
EXPECT_EQ("56.56", FpToString(56.56));
|
||||
EXPECT_EQ("12.12", FpToString(12.12));
|
||||
EXPECT_EQ("78.78", FpToString(78.78));
|
||||
|
||||
// Special challenge with rounding
|
||||
// https://github.com/jbeder/yaml-cpp/issues/1289#issuecomment-2211705536
|
||||
EXPECT_EQ("1.54743e+26", FpToString(1.5474250491e+26f));
|
||||
EXPECT_EQ(convert_with_stringstream(1.5474250491e+26f), FpToString(1.5474250491e+26f));
|
||||
EXPECT_EQ("1.5474251e+26", FpToString(1.5474250491e+26f, 8));
|
||||
|
||||
// prints the same way as std::stringstream
|
||||
EXPECT_EQ(convert_with_stringstream(1.), FpToString(1.));
|
||||
EXPECT_EQ(convert_with_stringstream(1e0), FpToString(1e0));
|
||||
EXPECT_EQ(convert_with_stringstream(1e1), FpToString(1e1));
|
||||
EXPECT_EQ(convert_with_stringstream(1e2), FpToString(1e2));
|
||||
EXPECT_EQ(convert_with_stringstream(1e3), FpToString(1e3));
|
||||
EXPECT_EQ(convert_with_stringstream(1e4), FpToString(1e4));
|
||||
EXPECT_EQ(convert_with_stringstream(1e5), FpToString(1e5));
|
||||
EXPECT_EQ(convert_with_stringstream(1e6), FpToString(1e6));
|
||||
EXPECT_EQ(convert_with_stringstream(1e7), FpToString(1e7));
|
||||
EXPECT_EQ(convert_with_stringstream(1e8), FpToString(1e8));
|
||||
EXPECT_EQ(convert_with_stringstream(1e9), FpToString(1e9));
|
||||
|
||||
// Print by default values below 1e6 without scientific notation
|
||||
EXPECT_EQ("1", FpToString(1.));
|
||||
EXPECT_EQ("1", FpToString(1e0));
|
||||
EXPECT_EQ("10", FpToString(1e1));
|
||||
EXPECT_EQ("100", FpToString(1e2));
|
||||
EXPECT_EQ("1000", FpToString(1e3));
|
||||
EXPECT_EQ("10000", FpToString(1e4));
|
||||
EXPECT_EQ("100000", FpToString(1e5));
|
||||
EXPECT_EQ("1e+06", FpToString(1e6));
|
||||
EXPECT_EQ("1e+07", FpToString(1e7));
|
||||
EXPECT_EQ("1e+08", FpToString(1e8));
|
||||
EXPECT_EQ("1e+09", FpToString(1e9));
|
||||
|
||||
// prints the same way as std::stringstream
|
||||
EXPECT_EQ(convert_with_stringstream(1.), FpToString(1.));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-0), FpToString(1e-0));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-1), FpToString(1e-1));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-2), FpToString(1e-2));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-3), FpToString(1e-3));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-4), FpToString(1e-4));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-5), FpToString(1e-5));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-6), FpToString(1e-6));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-7), FpToString(1e-7));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-8), FpToString(1e-8));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-9), FpToString(1e-9));
|
||||
|
||||
// Print by default values above 1e-5 without scientific notation
|
||||
EXPECT_EQ("1", FpToString(1.));
|
||||
EXPECT_EQ("1", FpToString(1e-0));
|
||||
EXPECT_EQ("0.1", FpToString(1e-1));
|
||||
EXPECT_EQ("0.01", FpToString(1e-2));
|
||||
EXPECT_EQ("0.001", FpToString(1e-3));
|
||||
EXPECT_EQ("0.0001", FpToString(1e-4));
|
||||
EXPECT_EQ("1e-05", FpToString(1e-5));
|
||||
EXPECT_EQ("1e-06", FpToString(1e-6));
|
||||
EXPECT_EQ("1e-07", FpToString(1e-7));
|
||||
EXPECT_EQ("1e-08", FpToString(1e-8));
|
||||
EXPECT_EQ("1e-09", FpToString(1e-9));
|
||||
|
||||
// changing precision has the same effect as std::stringstream
|
||||
EXPECT_EQ(convert_with_stringstream(123., 1), FpToString(123., 1));
|
||||
EXPECT_EQ(convert_with_stringstream(1234567., 7), FpToString(1234567., 7));
|
||||
EXPECT_EQ(convert_with_stringstream(12345.67, 7), FpToString(12345.67, 7));
|
||||
EXPECT_EQ(convert_with_stringstream(1234567e-9, 7), FpToString(1234567e-9, 7));
|
||||
EXPECT_EQ(convert_with_stringstream(1234567e-9, 1), FpToString(1234567e-9, 1));
|
||||
|
||||
// known example that is difficult to round
|
||||
EXPECT_EQ("1", FpToString(0.9999, 2));
|
||||
EXPECT_EQ("-1", FpToString(-0.9999, 2));
|
||||
|
||||
// some more random tests
|
||||
EXPECT_EQ("1.25", FpToString(1.25));
|
||||
EXPECT_EQ("34.34", FpToString(34.34));
|
||||
EXPECT_EQ("1e+20", FpToString(1e+20));
|
||||
EXPECT_EQ("1.1e+20", FpToString(1.1e+20));
|
||||
EXPECT_EQ("1e-20", FpToString(1e-20));
|
||||
EXPECT_EQ("1.1e-20", FpToString(1.1e-20));
|
||||
EXPECT_EQ("1e-20", FpToString(0.1e-19));
|
||||
EXPECT_EQ("1.1e-20", FpToString(0.11e-19));
|
||||
|
||||
EXPECT_EQ("19", FpToString(18.9, 2));
|
||||
EXPECT_EQ("20", FpToString(19.9, 2));
|
||||
EXPECT_EQ("2e+01", FpToString(19.9, 1));
|
||||
EXPECT_EQ("1.2e-05", FpToString(1.234e-5, 2));
|
||||
EXPECT_EQ("1.3e-05", FpToString(1.299e-5, 2));
|
||||
|
||||
EXPECT_EQ("-1", FpToString(-1.));
|
||||
EXPECT_EQ("-1.25", FpToString(-1.25));
|
||||
EXPECT_EQ("-34.34", FpToString(-34.34));
|
||||
EXPECT_EQ("-1e+20", FpToString(-1e+20));
|
||||
EXPECT_EQ("-1.1e+20", FpToString(-1.1e+20));
|
||||
EXPECT_EQ("-1e-20", FpToString(-1e-20));
|
||||
EXPECT_EQ("-1.1e-20", FpToString(-1.1e-20));
|
||||
EXPECT_EQ("-1e-20", FpToString(-0.1e-19));
|
||||
EXPECT_EQ("-1.1e-20", FpToString(-0.11e-19));
|
||||
|
||||
EXPECT_EQ("-19", FpToString(-18.9, 2));
|
||||
EXPECT_EQ("-20", FpToString(-19.9, 2));
|
||||
EXPECT_EQ("-2e+01", FpToString(-19.9, 1));
|
||||
EXPECT_EQ("-1.2e-05", FpToString(-1.234e-5, 2));
|
||||
EXPECT_EQ("-1.3e-05", FpToString(-1.299e-5, 2));
|
||||
}
|
||||
|
||||
TEST(FpToStringTest, conversion_float) {
|
||||
// Issue motivating FpToString function,
|
||||
// https://github.com/jbeder/yaml-cpp/issues/1289
|
||||
// Original problem at hand:
|
||||
EXPECT_EQ("34.34", FpToString(34.34f));
|
||||
EXPECT_EQ("56.56", FpToString(56.56f));
|
||||
EXPECT_EQ("12.12", FpToString(12.12f));
|
||||
EXPECT_EQ("78.78", FpToString(78.78f));
|
||||
|
||||
// prints the same way as std::stringstream
|
||||
EXPECT_EQ(convert_with_stringstream(1.f), FpToString(1.f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e0f), FpToString(1e0f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e1f), FpToString(1e1f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e2f), FpToString(1e2f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e3f), FpToString(1e3f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e4f), FpToString(1e4f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e5f), FpToString(1e5f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e6f), FpToString(1e6f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e7f), FpToString(1e7f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e8f), FpToString(1e8f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e9f), FpToString(1e9f));
|
||||
|
||||
// Print by default values below 1e6 without scientific notation
|
||||
EXPECT_EQ("1", FpToString(1.f));
|
||||
EXPECT_EQ("1", FpToString(1e0f));
|
||||
EXPECT_EQ("10", FpToString(1e1f));
|
||||
EXPECT_EQ("100", FpToString(1e2f));
|
||||
EXPECT_EQ("1000", FpToString(1e3f));
|
||||
EXPECT_EQ("10000", FpToString(1e4f));
|
||||
EXPECT_EQ("100000", FpToString(1e5f));
|
||||
EXPECT_EQ("1e+06", FpToString(1e6f));
|
||||
EXPECT_EQ("1e+07", FpToString(1e7f));
|
||||
EXPECT_EQ("1e+08", FpToString(1e8f));
|
||||
EXPECT_EQ("1e+09", FpToString(1e9f));
|
||||
|
||||
// prints the same way as std::stringstream
|
||||
EXPECT_EQ(convert_with_stringstream(1.f), FpToString(1.f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-0f), FpToString(1e-0f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-1f), FpToString(1e-1f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-2f), FpToString(1e-2f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-3f), FpToString(1e-3f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-4f), FpToString(1e-4f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-5f), FpToString(1e-5f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-6f), FpToString(1e-6f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-7f), FpToString(1e-7f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-8f), FpToString(1e-8f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-9f), FpToString(1e-9f));
|
||||
|
||||
// Print by default values above 1e-5 without scientific notation
|
||||
EXPECT_EQ("1", FpToString(1.f));
|
||||
EXPECT_EQ("1", FpToString(1e-0f));
|
||||
EXPECT_EQ("0.1", FpToString(1e-1f));
|
||||
EXPECT_EQ("0.01", FpToString(1e-2f));
|
||||
EXPECT_EQ("0.001", FpToString(1e-3f));
|
||||
EXPECT_EQ("0.0001", FpToString(1e-4f));
|
||||
EXPECT_EQ("1e-05", FpToString(1e-5f));
|
||||
EXPECT_EQ("1e-06", FpToString(1e-6f));
|
||||
EXPECT_EQ("1e-07", FpToString(1e-7f));
|
||||
EXPECT_EQ("1e-08", FpToString(1e-8f));
|
||||
EXPECT_EQ("1e-09", FpToString(1e-9f));
|
||||
|
||||
// changing precision has the same effect as std::stringstream
|
||||
EXPECT_EQ(convert_with_stringstream(123.f, 1), FpToString(123.f, 1));
|
||||
EXPECT_EQ(convert_with_stringstream(1234567.f, 7), FpToString(1234567.f, 7));
|
||||
EXPECT_EQ(convert_with_stringstream(12345.67f, 7), FpToString(12345.67f, 7));
|
||||
EXPECT_EQ(convert_with_stringstream(1234567e-9f, 7), FpToString(1234567e-9f, 7));
|
||||
EXPECT_EQ(convert_with_stringstream(1234567e-9f, 1), FpToString(1234567e-9f, 1));
|
||||
|
||||
// known example that is difficult to round
|
||||
EXPECT_EQ("1", FpToString(0.9999f, 2));
|
||||
EXPECT_EQ("-1", FpToString(-0.9999f, 2));
|
||||
|
||||
// some more random tests
|
||||
EXPECT_EQ("1.25", FpToString(1.25f));
|
||||
EXPECT_EQ("34.34", FpToString(34.34f));
|
||||
EXPECT_EQ("1e+20", FpToString(1e+20f));
|
||||
EXPECT_EQ("1.1e+20", FpToString(1.1e+20f));
|
||||
EXPECT_EQ("1e-20", FpToString(1e-20f));
|
||||
EXPECT_EQ("1.1e-20", FpToString(1.1e-20f));
|
||||
EXPECT_EQ("1e-20", FpToString(0.1e-19f));
|
||||
EXPECT_EQ("1.1e-20", FpToString(0.11e-19f));
|
||||
|
||||
EXPECT_EQ("19", FpToString(18.9f, 2));
|
||||
EXPECT_EQ("20", FpToString(19.9f, 2));
|
||||
EXPECT_EQ("2e+01", FpToString(19.9f, 1));
|
||||
EXPECT_EQ("1.2e-05", FpToString(1.234e-5f, 2));
|
||||
EXPECT_EQ("1.3e-05", FpToString(1.299e-5f, 2));
|
||||
|
||||
EXPECT_EQ("-1", FpToString(-1.f));
|
||||
EXPECT_EQ("-1.25", FpToString(-1.25f));
|
||||
EXPECT_EQ("-34.34", FpToString(-34.34f));
|
||||
EXPECT_EQ("-1e+20", FpToString(-1e+20f));
|
||||
EXPECT_EQ("-1.1e+20", FpToString(-1.1e+20f));
|
||||
EXPECT_EQ("-1e-20", FpToString(-1e-20f));
|
||||
EXPECT_EQ("-1.1e-20", FpToString(-1.1e-20f));
|
||||
EXPECT_EQ("-1e-20", FpToString(-0.1e-19f));
|
||||
EXPECT_EQ("-1.1e-20", FpToString(-0.11e-19f));
|
||||
|
||||
EXPECT_EQ("-19", FpToString(-18.9f, 2));
|
||||
EXPECT_EQ("-20", FpToString(-19.9f, 2));
|
||||
EXPECT_EQ("-2e+01", FpToString(-19.9f, 1));
|
||||
EXPECT_EQ("-1.2e-05", FpToString(-1.234e-5f, 2));
|
||||
EXPECT_EQ("-1.3e-05", FpToString(-1.299e-5f, 2));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace YAML
|
@@ -1,53 +0,0 @@
|
||||
name: Bug Report
|
||||
description: Let us know that something does not work as expected.
|
||||
title: "[Bug]: Please title this bug report"
|
||||
body:
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: Describe the issue
|
||||
description: What happened, and what did you expect to happen?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: steps
|
||||
attributes:
|
||||
label: Steps to reproduce the problem
|
||||
description: It is important that we are able to reproduce the problem that you are experiencing. Please provide all code and relevant steps to reproduce the problem, including your `BUILD`/`CMakeLists.txt` file and build commands. Links to a GitHub branch or [godbolt.org](https://godbolt.org/) that demonstrate the problem are also helpful.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: version
|
||||
attributes:
|
||||
label: What version of GoogleTest are you using?
|
||||
description: Please include the output of `git rev-parse HEAD` or the GoogleTest release version number that you are using.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: os
|
||||
attributes:
|
||||
label: What operating system and version are you using?
|
||||
description: If you are using a Linux distribution please include the name and version of the distribution as well.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: compiler
|
||||
attributes:
|
||||
label: What compiler and version are you using?
|
||||
description: Please include the output of `gcc -v` or `clang -v`, or the equivalent for your compiler.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: buildsystem
|
||||
attributes:
|
||||
label: What build system are you using?
|
||||
description: Please include the output of `bazel --version` or `cmake --version`, or the equivalent for your build system.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: Add any other context about the problem here.
|
||||
validations:
|
||||
required: false
|
@@ -1,33 +0,0 @@
|
||||
name: Feature request
|
||||
description: Propose a new feature.
|
||||
title: "[FR]: Please title this feature request"
|
||||
labels: "enhancement"
|
||||
body:
|
||||
- type: textarea
|
||||
id: version
|
||||
attributes:
|
||||
label: Does the feature exist in the most recent commit?
|
||||
description: We recommend using the latest commit from GitHub in your projects.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: why
|
||||
attributes:
|
||||
label: Why do we need this feature?
|
||||
description: Ideally, explain why a combination of existing features cannot be used instead.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: proposal
|
||||
attributes:
|
||||
label: Describe the proposal.
|
||||
description: Include a detailed description of the feature, with usage examples.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: platform
|
||||
attributes:
|
||||
label: Is the feature specific to an operating system, compiler, or build system version?
|
||||
description: If it is, please specify which versions.
|
||||
validations:
|
||||
required: true
|
@@ -1,5 +0,0 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Get Help
|
||||
url: https://github.com/google/googletest/discussions
|
||||
about: Please ask and answer questions here.
|
@@ -1,43 +0,0 @@
|
||||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
BAZEL_CXXOPTS: -std=c++14
|
||||
|
||||
jobs:
|
||||
Linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Tests
|
||||
run: bazel test --cxxopt=-std=c++14 --features=external_include_paths --test_output=errors ...
|
||||
|
||||
macOS:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Tests
|
||||
run: bazel test --cxxopt=-std=c++14 --features=external_include_paths --test_output=errors ...
|
||||
|
||||
|
||||
Windows:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Tests
|
||||
run: bazel test --cxxopt=/std:c++14 --features=external_include_paths --test_output=errors ...
|
@@ -1,117 +0,0 @@
|
||||
# GoogleTest
|
||||
|
||||
### Announcements
|
||||
|
||||
#### Live at Head
|
||||
|
||||
GoogleTest now follows the
|
||||
[Abseil Live at Head philosophy](https://abseil.io/about/philosophy#upgrade-support).
|
||||
We recommend
|
||||
[updating to the latest commit in the `main` branch as often as possible](https://github.com/abseil/abseil-cpp/blob/master/FAQ.md#what-is-live-at-head-and-how-do-i-do-it).
|
||||
|
||||
#### Documentation Updates
|
||||
|
||||
Our documentation is now live on GitHub Pages at
|
||||
https://google.github.io/googletest/. We recommend browsing the documentation on
|
||||
GitHub Pages rather than directly in the repository.
|
||||
|
||||
#### Release 1.12.1
|
||||
|
||||
[Release 1.12.1](https://github.com/google/googletest/releases/tag/release-1.12.1)
|
||||
is now available.
|
||||
|
||||
The 1.12.x branch will be the last to support C++11. Future releases will
|
||||
require at least C++14.
|
||||
|
||||
#### Coming Soon
|
||||
|
||||
* We are planning to take a dependency on
|
||||
[Abseil](https://github.com/abseil/abseil-cpp).
|
||||
* More documentation improvements are planned.
|
||||
|
||||
## Welcome to **GoogleTest**, Google's C++ test framework!
|
||||
|
||||
This repository is a merger of the formerly separate GoogleTest and GoogleMock
|
||||
projects. These were so closely related that it makes sense to maintain and
|
||||
release them together.
|
||||
|
||||
### Getting Started
|
||||
|
||||
See the [GoogleTest User's Guide](https://google.github.io/googletest/) for
|
||||
documentation. We recommend starting with the
|
||||
[GoogleTest Primer](https://google.github.io/googletest/primer.html).
|
||||
|
||||
More information about building GoogleTest can be found at
|
||||
[googletest/README.md](googletest/README.md).
|
||||
|
||||
## Features
|
||||
|
||||
* An [xUnit](https://en.wikipedia.org/wiki/XUnit) test framework.
|
||||
* Test discovery.
|
||||
* A rich set of assertions.
|
||||
* User-defined assertions.
|
||||
* Death tests.
|
||||
* Fatal and non-fatal failures.
|
||||
* Value-parameterized tests.
|
||||
* Type-parameterized tests.
|
||||
* Various options for running the tests.
|
||||
* XML test report generation.
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
GoogleTest follows Google's
|
||||
[Foundational C++ Support Policy](https://opensource.google/documentation/policies/cplusplus-support).
|
||||
See
|
||||
[this table](https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md)
|
||||
for a list of currently supported versions compilers, platforms, and build
|
||||
tools.
|
||||
|
||||
## Who Is Using GoogleTest?
|
||||
|
||||
In addition to many internal projects at Google, GoogleTest is also used by the
|
||||
following notable projects:
|
||||
|
||||
* The [Chromium projects](http://www.chromium.org/) (behind the Chrome browser
|
||||
and Chrome OS).
|
||||
* The [LLVM](http://llvm.org/) compiler.
|
||||
* [Protocol Buffers](https://github.com/google/protobuf), Google's data
|
||||
interchange format.
|
||||
* The [OpenCV](http://opencv.org/) computer vision library.
|
||||
|
||||
## Related Open Source Projects
|
||||
|
||||
[GTest Runner](https://github.com/nholthaus/gtest-runner) is a Qt5 based
|
||||
automated test-runner and Graphical User Interface with powerful features for
|
||||
Windows and Linux platforms.
|
||||
|
||||
[GoogleTest UI](https://github.com/ospector/gtest-gbar) is a test runner that
|
||||
runs your test binary, allows you to track its progress via a progress bar, and
|
||||
displays a list of test failures. Clicking on one shows failure text. GoogleTest
|
||||
UI is written in C#.
|
||||
|
||||
[GTest TAP Listener](https://github.com/kinow/gtest-tap-listener) is an event
|
||||
listener for GoogleTest that implements the
|
||||
[TAP protocol](https://en.wikipedia.org/wiki/Test_Anything_Protocol) for test
|
||||
result output. If your test runner understands TAP, you may find it useful.
|
||||
|
||||
[gtest-parallel](https://github.com/google/gtest-parallel) is a test runner that
|
||||
runs tests from your binary in parallel to provide significant speed-up.
|
||||
|
||||
[GoogleTest Adapter](https://marketplace.visualstudio.com/items?itemName=DavidSchuldenfrei.gtest-adapter)
|
||||
is a VS Code extension allowing to view GoogleTest in a tree view and run/debug
|
||||
your tests.
|
||||
|
||||
[C++ TestMate](https://github.com/matepek/vscode-catch2-test-adapter) is a VS
|
||||
Code extension allowing to view GoogleTest in a tree view and run/debug your
|
||||
tests.
|
||||
|
||||
[Cornichon](https://pypi.org/project/cornichon/) is a small Gherkin DSL parser
|
||||
that generates stub code for GoogleTest.
|
||||
|
||||
## Contributing Changes
|
||||
|
||||
Please read
|
||||
[`CONTRIBUTING.md`](https://github.com/google/googletest/blob/main/CONTRIBUTING.md)
|
||||
for details on how to contribute to this project.
|
||||
|
||||
Happy testing!
|
@@ -1,40 +0,0 @@
|
||||
workspace(name = "com_google_googletest")
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
http_archive(
|
||||
name = "com_google_absl", # 2023-01-10T21:08:25Z
|
||||
sha256 = "f9a4e749f42c386a32a90fddf0e2913ed408d10c42f7f33ccf4c59ac4f0d1d05",
|
||||
strip_prefix = "abseil-cpp-52835439ca90d86b27bf8cd1708296e95604d724",
|
||||
urls = ["https://github.com/abseil/abseil-cpp/archive/52835439ca90d86b27bf8cd1708296e95604d724.zip"],
|
||||
)
|
||||
|
||||
# Note this must use a commit from the `abseil` branch of the RE2 project.
|
||||
# https://github.com/google/re2/tree/abseil
|
||||
http_archive(
|
||||
name = "com_googlesource_code_re2", # 2022-12-21T14:29:10Z
|
||||
sha256 = "b9ce3a51beebb38534d11d40f8928d40509b9e18a735f6a4a97ad3d014c87cb5",
|
||||
strip_prefix = "re2-d0b1f8f2ecc2ea74956c7608b6f915175314ff0e",
|
||||
urls = ["https://github.com/google/re2/archive/d0b1f8f2ecc2ea74956c7608b6f915175314ff0e.zip"],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "rules_python", # 2023-01-10T22:00:51Z
|
||||
sha256 = "5de54486a60ad8948dabe49605bb1c08053e04001a431ab3e96745b4d97a4419",
|
||||
strip_prefix = "rules_python-70cce26432187a60b4e950118791385e6fb3c26f",
|
||||
urls = ["https://github.com/bazelbuild/rules_python/archive/70cce26432187a60b4e950118791385e6fb3c26f.zip"],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "bazel_skylib", # 2022-11-16T18:29:32Z
|
||||
sha256 = "a22290c26d29d3ecca286466f7f295ac6cbe32c0a9da3a91176a90e0725e3649",
|
||||
strip_prefix = "bazel-skylib-5bfcb1a684550626ce138fe0fe8f5f702b3764c3",
|
||||
urls = ["https://github.com/bazelbuild/bazel-skylib/archive/5bfcb1a684550626ce138fe0fe8f5f702b3764c3.zip"],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "platforms", # 2022-11-09T19:18:22Z
|
||||
sha256 = "b4a3b45dc4202e2b3e34e3bc49d2b5b37295fc23ea58d88fb9e01f3642ad9b55",
|
||||
strip_prefix = "platforms-3fbc687756043fb58a407c2ea8c944bc2fe1d922",
|
||||
urls = ["https://github.com/bazelbuild/platforms/archive/3fbc687756043fb58a407c2ea8c944bc2fe1d922.zip"],
|
||||
)
|
@@ -1,134 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright 2020, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
set -euox pipefail
|
||||
|
||||
readonly LINUX_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20220217"
|
||||
readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20220621"
|
||||
|
||||
if [[ -z ${GTEST_ROOT:-} ]]; then
|
||||
GTEST_ROOT="$(realpath $(dirname ${0})/..)"
|
||||
fi
|
||||
|
||||
if [[ -z ${STD:-} ]]; then
|
||||
STD="c++14 c++17 c++20"
|
||||
fi
|
||||
|
||||
# Test the CMake build
|
||||
for cc in /usr/local/bin/gcc /opt/llvm/clang/bin/clang; do
|
||||
for cmake_off_on in OFF ON; do
|
||||
time docker run \
|
||||
--volume="${GTEST_ROOT}:/src:ro" \
|
||||
--tmpfs="/build:exec" \
|
||||
--workdir="/build" \
|
||||
--rm \
|
||||
--env="CC=${cc}" \
|
||||
--env="CXX_FLAGS=\"-Werror -Wdeprecated\"" \
|
||||
${LINUX_LATEST_CONTAINER} \
|
||||
/bin/bash -c "
|
||||
cmake /src \
|
||||
-DCMAKE_CXX_STANDARD=14 \
|
||||
-Dgtest_build_samples=ON \
|
||||
-Dgtest_build_tests=ON \
|
||||
-Dgmock_build_tests=ON \
|
||||
-Dcxx_no_exception=${cmake_off_on} \
|
||||
-Dcxx_no_rtti=${cmake_off_on} && \
|
||||
make -j$(nproc) && \
|
||||
ctest -j$(nproc) --output-on-failure"
|
||||
done
|
||||
done
|
||||
|
||||
# Do one test with an older version of GCC
|
||||
time docker run \
|
||||
--volume="${GTEST_ROOT}:/src:ro" \
|
||||
--workdir="/src" \
|
||||
--rm \
|
||||
--env="CC=/usr/local/bin/gcc" \
|
||||
--env="BAZEL_CXXOPTS=-std=c++14" \
|
||||
${LINUX_GCC_FLOOR_CONTAINER} \
|
||||
/usr/local/bin/bazel test ... \
|
||||
--copt="-Wall" \
|
||||
--copt="-Werror" \
|
||||
--copt="-Wuninitialized" \
|
||||
--copt="-Wno-error=pragmas" \
|
||||
--distdir="/bazel-distdir" \
|
||||
--features=external_include_paths \
|
||||
--keep_going \
|
||||
--show_timestamps \
|
||||
--test_output=errors
|
||||
|
||||
# Test GCC
|
||||
for std in ${STD}; do
|
||||
for absl in 0 1; do
|
||||
time docker run \
|
||||
--volume="${GTEST_ROOT}:/src:ro" \
|
||||
--workdir="/src" \
|
||||
--rm \
|
||||
--env="CC=/usr/local/bin/gcc" \
|
||||
--env="BAZEL_CXXOPTS=-std=${std}" \
|
||||
${LINUX_LATEST_CONTAINER} \
|
||||
/usr/local/bin/bazel test ... \
|
||||
--copt="-Wall" \
|
||||
--copt="-Werror" \
|
||||
--copt="-Wuninitialized" \
|
||||
--define="absl=${absl}" \
|
||||
--distdir="/bazel-distdir" \
|
||||
--features=external_include_paths \
|
||||
--keep_going \
|
||||
--show_timestamps \
|
||||
--test_output=errors
|
||||
done
|
||||
done
|
||||
|
||||
# Test Clang
|
||||
for std in ${STD}; do
|
||||
for absl in 0 1; do
|
||||
time docker run \
|
||||
--volume="${GTEST_ROOT}:/src:ro" \
|
||||
--workdir="/src" \
|
||||
--rm \
|
||||
--env="CC=/opt/llvm/clang/bin/clang" \
|
||||
--env="BAZEL_CXXOPTS=-std=${std}" \
|
||||
${LINUX_LATEST_CONTAINER} \
|
||||
/usr/local/bin/bazel test ... \
|
||||
--copt="--gcc-toolchain=/usr/local" \
|
||||
--copt="-Wall" \
|
||||
--copt="-Werror" \
|
||||
--copt="-Wuninitialized" \
|
||||
--define="absl=${absl}" \
|
||||
--distdir="/bazel-distdir" \
|
||||
--features=external_include_paths \
|
||||
--keep_going \
|
||||
--linkopt="--gcc-toolchain=/usr/local" \
|
||||
--show_timestamps \
|
||||
--test_output=errors
|
||||
done
|
||||
done
|
@@ -1,56 +0,0 @@
|
||||
SETLOCAL ENABLEDELAYEDEXPANSION
|
||||
|
||||
SET BAZEL_EXE=%KOKORO_GFILE_DIR%\bazel-5.1.1-windows-x86_64.exe
|
||||
|
||||
SET PATH=C:\Python37;%PATH%
|
||||
SET BAZEL_PYTHON=C:\python37\python.exe
|
||||
SET BAZEL_SH=C:\tools\msys64\usr\bin\bash.exe
|
||||
SET CMAKE_BIN="C:\Program Files\CMake\bin\cmake.exe"
|
||||
SET CTEST_BIN="C:\Program Files\CMake\bin\ctest.exe"
|
||||
SET CTEST_OUTPUT_ON_FAILURE=1
|
||||
|
||||
IF EXIST git\googletest (
|
||||
CD git\googletest
|
||||
) ELSE IF EXIST github\googletest (
|
||||
CD github\googletest
|
||||
)
|
||||
|
||||
IF %errorlevel% neq 0 EXIT /B 1
|
||||
|
||||
:: ----------------------------------------------------------------------------
|
||||
:: CMake Visual Studio 15 2017 Win64
|
||||
MKDIR cmake_msvc2017
|
||||
CD cmake_msvc2017
|
||||
|
||||
%CMAKE_BIN% .. ^
|
||||
-G "Visual Studio 15 2017 Win64" ^
|
||||
-DPYTHON_EXECUTABLE:FILEPATH=c:\python37\python.exe ^
|
||||
-DPYTHON_INCLUDE_DIR:PATH=c:\python37\include ^
|
||||
-DPYTHON_LIBRARY:FILEPATH=c:\python37\lib\site-packages\pip ^
|
||||
-Dgtest_build_samples=ON ^
|
||||
-Dgtest_build_tests=ON ^
|
||||
-Dgmock_build_tests=ON
|
||||
IF %errorlevel% neq 0 EXIT /B 1
|
||||
|
||||
%CMAKE_BIN% --build . --target ALL_BUILD --config Debug -- -maxcpucount
|
||||
IF %errorlevel% neq 0 EXIT /B 1
|
||||
|
||||
%CTEST_BIN% -C Debug --timeout 600
|
||||
IF %errorlevel% neq 0 EXIT /B 1
|
||||
|
||||
CD ..
|
||||
RMDIR /S /Q cmake_msvc2017
|
||||
|
||||
:: ----------------------------------------------------------------------------
|
||||
:: Bazel Visual Studio 15 2017 Win64
|
||||
|
||||
SET BAZEL_VC=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC
|
||||
%BAZEL_EXE% test ... ^
|
||||
--compilation_mode=dbg ^
|
||||
--copt=/std:c++14 ^
|
||||
--copt=/WX ^
|
||||
--features=external_include_paths ^
|
||||
--keep_going ^
|
||||
--test_output=errors ^
|
||||
--test_tag_filters=-no_test_msvc2017
|
||||
IF %errorlevel% neq 0 EXIT /B 1
|
@@ -1 +0,0 @@
|
||||
title: GoogleTest
|
@@ -1,43 +0,0 @@
|
||||
nav:
|
||||
- section: "Get Started"
|
||||
items:
|
||||
- title: "Supported Platforms"
|
||||
url: "/platforms.html"
|
||||
- title: "Quickstart: Bazel"
|
||||
url: "/quickstart-bazel.html"
|
||||
- title: "Quickstart: CMake"
|
||||
url: "/quickstart-cmake.html"
|
||||
- section: "Guides"
|
||||
items:
|
||||
- title: "GoogleTest Primer"
|
||||
url: "/primer.html"
|
||||
- title: "Advanced Topics"
|
||||
url: "/advanced.html"
|
||||
- title: "Mocking for Dummies"
|
||||
url: "/gmock_for_dummies.html"
|
||||
- title: "Mocking Cookbook"
|
||||
url: "/gmock_cook_book.html"
|
||||
- title: "Mocking Cheat Sheet"
|
||||
url: "/gmock_cheat_sheet.html"
|
||||
- section: "References"
|
||||
items:
|
||||
- title: "Testing Reference"
|
||||
url: "/reference/testing.html"
|
||||
- title: "Mocking Reference"
|
||||
url: "/reference/mocking.html"
|
||||
- title: "Assertions"
|
||||
url: "/reference/assertions.html"
|
||||
- title: "Matchers"
|
||||
url: "/reference/matchers.html"
|
||||
- title: "Actions"
|
||||
url: "/reference/actions.html"
|
||||
- title: "Testing FAQ"
|
||||
url: "/faq.html"
|
||||
- title: "Mocking FAQ"
|
||||
url: "/gmock_faq.html"
|
||||
- title: "Code Samples"
|
||||
url: "/samples.html"
|
||||
- title: "Using pkg-config"
|
||||
url: "/pkgconfig.html"
|
||||
- title: "Community Documentation"
|
||||
url: "/community_created_documentation.html"
|
@@ -1,58 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ site.lang | default: "en-US" }}">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
{% seo %}
|
||||
<link rel="stylesheet" href="{{ "/assets/css/style.css?v=" | append: site.github.build_revision | relative_url }}">
|
||||
<script>
|
||||
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
|
||||
ga('create', 'UA-197576187-1', { 'storage': 'none' });
|
||||
ga('set', 'referrer', document.referrer.split('?')[0]);
|
||||
ga('set', 'location', window.location.href.split('?')[0]);
|
||||
ga('set', 'anonymizeIp', true);
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
<script async src='https://www.google-analytics.com/analytics.js'></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="sidebar">
|
||||
<div class="header">
|
||||
<h1><a href="{{ "/" | relative_url }}">{{ site.title | default: "Documentation" }}</a></h1>
|
||||
</div>
|
||||
<input type="checkbox" id="nav-toggle" class="nav-toggle">
|
||||
<label for="nav-toggle" class="expander">
|
||||
<span class="arrow"></span>
|
||||
</label>
|
||||
<nav>
|
||||
{% for item in site.data.navigation.nav %}
|
||||
<h2>{{ item.section }}</h2>
|
||||
<ul>
|
||||
{% for subitem in item.items %}
|
||||
<a href="{{subitem.url | relative_url }}">
|
||||
<li class="{% if subitem.url == page.url %}active{% endif %}">
|
||||
{{ subitem.title }}
|
||||
</li>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endfor %}
|
||||
</nav>
|
||||
</div>
|
||||
<div class="main markdown-body">
|
||||
<div class="main-inner">
|
||||
{{ content }}
|
||||
</div>
|
||||
<div class="footer">
|
||||
GoogleTest ·
|
||||
<a href="https://github.com/google/googletest">GitHub Repository</a> ·
|
||||
<a href="https://github.com/google/googletest/blob/main/LICENSE">License</a> ·
|
||||
<a href="https://policies.google.com/privacy">Privacy Policy</a>
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/anchor-js/4.1.0/anchor.min.js" integrity="sha256-lZaRhKri35AyJSypXXs4o6OPFTbTmUoltBbDCbdzegg=" crossorigin="anonymous"></script>
|
||||
<script>anchors.add('.main h2, .main h3, .main h4, .main h5, .main h6');</script>
|
||||
</body>
|
||||
</html>
|
@@ -1,200 +0,0 @@
|
||||
// Styles for GoogleTest docs website on GitHub Pages.
|
||||
// Color variables are defined in
|
||||
// https://github.com/pages-themes/primer/tree/master/_sass/primer-support/lib/variables
|
||||
|
||||
$sidebar-width: 260px;
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
background: $black;
|
||||
color: $text-white;
|
||||
flex-shrink: 0;
|
||||
height: 100vh;
|
||||
overflow: auto;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
width: $sidebar-width;
|
||||
}
|
||||
|
||||
.sidebar h1 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
.sidebar h2 {
|
||||
color: $gray-light;
|
||||
font-size: 0.8em;
|
||||
font-weight: normal;
|
||||
margin-bottom: 0.8em;
|
||||
padding-left: 2.5em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.sidebar .header {
|
||||
background: $black;
|
||||
padding: 2em;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sidebar .header a {
|
||||
color: $text-white;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.sidebar .nav-toggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sidebar .expander {
|
||||
cursor: pointer;
|
||||
display: none;
|
||||
height: 3em;
|
||||
position: absolute;
|
||||
right: 1em;
|
||||
top: 1.5em;
|
||||
width: 3em;
|
||||
}
|
||||
|
||||
.sidebar .expander .arrow {
|
||||
border: solid $white;
|
||||
border-width: 0 3px 3px 0;
|
||||
display: block;
|
||||
height: 0.7em;
|
||||
margin: 1em auto;
|
||||
transform: rotate(45deg);
|
||||
transition: transform 0.5s;
|
||||
width: 0.7em;
|
||||
}
|
||||
|
||||
.sidebar nav {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sidebar nav ul {
|
||||
list-style-type: none;
|
||||
margin-bottom: 1em;
|
||||
padding: 0;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
li {
|
||||
color: $text-white;
|
||||
padding-left: 2em;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
li.active {
|
||||
background: $border-gray-darker;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
li:hover {
|
||||
background: $border-gray-darker;
|
||||
}
|
||||
}
|
||||
|
||||
.main {
|
||||
background-color: $bg-gray;
|
||||
width: calc(100% - #{$sidebar-width});
|
||||
}
|
||||
|
||||
.main .main-inner {
|
||||
background-color: $white;
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
.main .footer {
|
||||
margin: 0;
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
.main table th {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.main .callout {
|
||||
border-left: 0.25em solid $white;
|
||||
padding: 1em;
|
||||
|
||||
a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
&.important {
|
||||
background-color: $bg-yellow-light;
|
||||
border-color: $bg-yellow;
|
||||
color: $black;
|
||||
}
|
||||
|
||||
&.note {
|
||||
background-color: $bg-blue-light;
|
||||
border-color: $text-blue;
|
||||
color: $text-blue;
|
||||
}
|
||||
|
||||
&.tip {
|
||||
background-color: $green-000;
|
||||
border-color: $green-700;
|
||||
color: $green-700;
|
||||
}
|
||||
|
||||
&.warning {
|
||||
background-color: $red-000;
|
||||
border-color: $text-red;
|
||||
color: $text-red;
|
||||
}
|
||||
}
|
||||
|
||||
.main .good pre {
|
||||
background-color: $bg-green-light;
|
||||
}
|
||||
|
||||
.main .bad pre {
|
||||
background-color: $red-000;
|
||||
}
|
||||
|
||||
@media all and (max-width: 768px) {
|
||||
body {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
height: auto;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sidebar .expander {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.sidebar nav {
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.sidebar .nav-toggle:checked {
|
||||
& ~ nav {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
& + .expander .arrow {
|
||||
transform: rotate(-135deg);
|
||||
}
|
||||
}
|
||||
|
||||
.main {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
---
|
||||
---
|
||||
|
||||
@import "jekyll-theme-primer";
|
||||
@import "main";
|
@@ -1,7 +0,0 @@
|
||||
# Community-Created Documentation
|
||||
|
||||
The following is a list, in no particular order, of links to documentation
|
||||
created by the Googletest community.
|
||||
|
||||
* [Googlemock Insights](https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles/blob/master/googletest/insights.md),
|
||||
by [ElectricRCAircraftGuy](https://github.com/ElectricRCAircraftGuy)
|
@@ -1,241 +0,0 @@
|
||||
# gMock Cheat Sheet
|
||||
|
||||
## Defining a Mock Class
|
||||
|
||||
### Mocking a Normal Class {#MockClass}
|
||||
|
||||
Given
|
||||
|
||||
```cpp
|
||||
class Foo {
|
||||
public:
|
||||
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 {
|
||||
public:
|
||||
MOCK_METHOD(int, GetSize, (), (const, override));
|
||||
MOCK_METHOD(string, Describe, (const char* name), (override));
|
||||
MOCK_METHOD(string, Describe, (int type), (override));
|
||||
MOCK_METHOD(bool, Process, (Bar elem, int count), (override));
|
||||
};
|
||||
```
|
||||
|
||||
To create a "nice" mock, which ignores all uninteresting calls, a "naggy" mock,
|
||||
which warns on all uninteresting calls, or a "strict" mock, which treats them as
|
||||
failures:
|
||||
|
||||
```cpp
|
||||
using ::testing::NiceMock;
|
||||
using ::testing::NaggyMock;
|
||||
using ::testing::StrictMock;
|
||||
|
||||
NiceMock<MockFoo> nice_foo; // The type is a subclass of MockFoo.
|
||||
NaggyMock<MockFoo> naggy_foo; // The type is a subclass of MockFoo.
|
||||
StrictMock<MockFoo> strict_foo; // The type is a subclass of MockFoo.
|
||||
```
|
||||
|
||||
{: .callout .note}
|
||||
**Note:** A mock object is currently naggy by default. We may make it nice by
|
||||
default in the future.
|
||||
|
||||
### Mocking a Class Template {#MockTemplate}
|
||||
|
||||
Class templates can be mocked just like any class.
|
||||
|
||||
To mock
|
||||
|
||||
```cpp
|
||||
template <typename Elem>
|
||||
class StackInterface {
|
||||
public:
|
||||
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> {
|
||||
public:
|
||||
MOCK_METHOD(int, GetSize, (), (const, override));
|
||||
MOCK_METHOD(void, Push, (const Elem& x), (override));
|
||||
};
|
||||
```
|
||||
|
||||
### Specifying Calling Conventions for Mock Functions
|
||||
|
||||
If your mock function doesn't use the default calling convention, you can
|
||||
specify it by adding `Calltype(convention)` to `MOCK_METHOD`'s 4th parameter.
|
||||
For example,
|
||||
|
||||
```cpp
|
||||
MOCK_METHOD(bool, Foo, (int n), (Calltype(STDMETHODCALLTYPE)));
|
||||
MOCK_METHOD(int, Bar, (double x, double y),
|
||||
(const, Calltype(STDMETHODCALLTYPE)));
|
||||
```
|
||||
|
||||
where `STDMETHODCALLTYPE` is defined by `<objbase.h>` on Windows.
|
||||
|
||||
## Using Mocks in Tests {#UsingMocks}
|
||||
|
||||
The typical work flow is:
|
||||
|
||||
1. Import the gMock names you need to use. All gMock symbols are in the
|
||||
`testing` namespace unless they are macros or otherwise noted.
|
||||
2. Create the mock objects.
|
||||
3. Optionally, set the default actions of the mock objects.
|
||||
4. Set your expectations on the mock objects (How will they be called? What
|
||||
will they do?).
|
||||
5. Exercise code that uses the mock objects; if necessary, check the result
|
||||
using googletest assertions.
|
||||
6. When a mock object is destructed, gMock automatically verifies that all
|
||||
expectations on it have been satisfied.
|
||||
|
||||
Here's an example:
|
||||
|
||||
```cpp
|
||||
using ::testing::Return; // #1
|
||||
|
||||
TEST(BarTest, DoesThis) {
|
||||
MockFoo foo; // #2
|
||||
|
||||
ON_CALL(foo, GetSize()) // #3
|
||||
.WillByDefault(Return(1));
|
||||
// ... other default actions ...
|
||||
|
||||
EXPECT_CALL(foo, Describe(5)) // #4
|
||||
.Times(3)
|
||||
.WillRepeatedly(Return("Category 5"));
|
||||
// ... other expectations ...
|
||||
|
||||
EXPECT_EQ(MyProductionFunction(&foo), "good"); // #5
|
||||
} // #6
|
||||
```
|
||||
|
||||
## Setting Default Actions {#OnCall}
|
||||
|
||||
gMock has a **built-in default action** for any function that returns `void`,
|
||||
`bool`, a numeric value, or a pointer. In C++11, it will additionally returns
|
||||
the default-constructed value, if one exists for the given type.
|
||||
|
||||
To customize the default action for functions with return type `T`, use
|
||||
[`DefaultValue<T>`](reference/mocking.md#DefaultValue). For example:
|
||||
|
||||
```cpp
|
||||
// Sets the default action for return type std::unique_ptr<Buzz> to
|
||||
// creating a new Buzz every time.
|
||||
DefaultValue<std::unique_ptr<Buzz>>::SetFactory(
|
||||
[] { return std::make_unique<Buzz>(AccessLevel::kInternal); });
|
||||
|
||||
// When this fires, the default action of MakeBuzz() will run, which
|
||||
// will return a new Buzz object.
|
||||
EXPECT_CALL(mock_buzzer_, MakeBuzz("hello")).Times(AnyNumber());
|
||||
|
||||
auto buzz1 = mock_buzzer_.MakeBuzz("hello");
|
||||
auto buzz2 = mock_buzzer_.MakeBuzz("hello");
|
||||
EXPECT_NE(buzz1, nullptr);
|
||||
EXPECT_NE(buzz2, nullptr);
|
||||
EXPECT_NE(buzz1, buzz2);
|
||||
|
||||
// Resets the default action for return type std::unique_ptr<Buzz>,
|
||||
// to avoid interfere with other tests.
|
||||
DefaultValue<std::unique_ptr<Buzz>>::Clear();
|
||||
```
|
||||
|
||||
To customize the default action for a particular method of a specific mock
|
||||
object, use [`ON_CALL`](reference/mocking.md#ON_CALL). `ON_CALL` has a similar
|
||||
syntax to `EXPECT_CALL`, but it is used for setting default behaviors when you
|
||||
do not require that the mock method is called. See
|
||||
[Knowing When to Expect](gmock_cook_book.md#UseOnCall) for a more detailed
|
||||
discussion.
|
||||
|
||||
## Setting Expectations {#ExpectCall}
|
||||
|
||||
See [`EXPECT_CALL`](reference/mocking.md#EXPECT_CALL) in the Mocking Reference.
|
||||
|
||||
## Matchers {#MatcherList}
|
||||
|
||||
See the [Matchers Reference](reference/matchers.md).
|
||||
|
||||
## Actions {#ActionList}
|
||||
|
||||
See the [Actions Reference](reference/actions.md).
|
||||
|
||||
## Cardinalities {#CardinalityList}
|
||||
|
||||
See the [`Times` clause](reference/mocking.md#EXPECT_CALL.Times) of
|
||||
`EXPECT_CALL` in the Mocking Reference.
|
||||
|
||||
## Expectation Order
|
||||
|
||||
By default, expectations can be matched in *any* order. If some or all
|
||||
expectations must be matched in a given order, you can use the
|
||||
[`After` clause](reference/mocking.md#EXPECT_CALL.After) or
|
||||
[`InSequence` clause](reference/mocking.md#EXPECT_CALL.InSequence) of
|
||||
`EXPECT_CALL`, or use an [`InSequence` object](reference/mocking.md#InSequence).
|
||||
|
||||
## Verifying and Resetting a Mock
|
||||
|
||||
gMock will verify the expectations on a mock object when it is destructed, or
|
||||
you can do it earlier:
|
||||
|
||||
```cpp
|
||||
using ::testing::Mock;
|
||||
...
|
||||
// Verifies and removes the expectations on mock_obj;
|
||||
// returns true if and only if successful.
|
||||
Mock::VerifyAndClearExpectations(&mock_obj);
|
||||
...
|
||||
// Verifies and removes the expectations on mock_obj;
|
||||
// also removes the default actions set by ON_CALL();
|
||||
// returns true if and only if successful.
|
||||
Mock::VerifyAndClear(&mock_obj);
|
||||
```
|
||||
|
||||
Do not set new expectations after verifying and clearing a mock after its use.
|
||||
Setting expectations after code that exercises the mock has undefined behavior.
|
||||
See [Using Mocks in Tests](gmock_for_dummies.md#using-mocks-in-tests) for more
|
||||
information.
|
||||
|
||||
You can also tell gMock that a mock object can be leaked and doesn't need to be
|
||||
verified:
|
||||
|
||||
```cpp
|
||||
Mock::AllowLeak(&mock_obj);
|
||||
```
|
||||
|
||||
## Mock Classes
|
||||
|
||||
gMock defines a convenient mock class template
|
||||
|
||||
```cpp
|
||||
class MockFunction<R(A1, ..., An)> {
|
||||
public:
|
||||
MOCK_METHOD(R, Call, (A1, ..., An));
|
||||
};
|
||||
```
|
||||
|
||||
See this [recipe](gmock_cook_book.md#UsingCheckPoints) for one application of
|
||||
it.
|
||||
|
||||
## Flags
|
||||
|
||||
| Flag | Description |
|
||||
| :----------------------------- | :---------------------------------------- |
|
||||
| `--gmock_catch_leaked_mocks=0` | Don't report leaked mock objects as failures. |
|
||||
| `--gmock_verbose=LEVEL` | Sets the default verbosity level (`info`, `warning`, or `error`) of Google Mock messages. |
|
@@ -1,22 +0,0 @@
|
||||
# GoogleTest User's Guide
|
||||
|
||||
## Welcome to GoogleTest!
|
||||
|
||||
GoogleTest is Google's C++ testing and mocking framework. This user's guide has
|
||||
the following contents:
|
||||
|
||||
* [GoogleTest Primer](primer.md) - Teaches you how to write simple tests using
|
||||
GoogleTest. Read this first if you are new to GoogleTest.
|
||||
* [GoogleTest Advanced](advanced.md) - Read this when you've finished the
|
||||
Primer and want to utilize GoogleTest to its full potential.
|
||||
* [GoogleTest Samples](samples.md) - Describes some GoogleTest samples.
|
||||
* [GoogleTest FAQ](faq.md) - Have a question? Want some tips? Check here
|
||||
first.
|
||||
* [Mocking for Dummies](gmock_for_dummies.md) - Teaches you how to create mock
|
||||
objects and use them in tests.
|
||||
* [Mocking Cookbook](gmock_cook_book.md) - Includes tips and approaches to
|
||||
common mocking use cases.
|
||||
* [Mocking Cheat Sheet](gmock_cheat_sheet.md) - A handy reference for
|
||||
matchers, actions, invariants, and more.
|
||||
* [Mocking FAQ](gmock_faq.md) - Contains answers to some mocking-specific
|
||||
questions.
|
@@ -1,35 +0,0 @@
|
||||
# Supported Platforms
|
||||
|
||||
GoogleTest requires a codebase and compiler compliant with the C++11 standard or
|
||||
newer.
|
||||
|
||||
The GoogleTest code is officially supported on the following platforms.
|
||||
Operating systems or tools not listed below are community-supported. For
|
||||
community-supported platforms, patches that do not complicate the code may be
|
||||
considered.
|
||||
|
||||
If you notice any problems on your platform, please file an issue on the
|
||||
[GoogleTest GitHub Issue Tracker](https://github.com/google/googletest/issues).
|
||||
Pull requests containing fixes are welcome!
|
||||
|
||||
### Operating systems
|
||||
|
||||
* Linux
|
||||
* macOS
|
||||
* Windows
|
||||
|
||||
### Compilers
|
||||
|
||||
* gcc 5.0+
|
||||
* clang 5.0+
|
||||
* MSVC 2015+
|
||||
|
||||
**macOS users:** Xcode 9.3+ provides clang 5.0+.
|
||||
|
||||
### Build systems
|
||||
|
||||
* [Bazel](https://bazel.build/)
|
||||
* [CMake](https://cmake.org/)
|
||||
|
||||
Bazel is the build system used by the team internally and in tests. CMake is
|
||||
supported on a best-effort basis and by the community.
|
@@ -1,146 +0,0 @@
|
||||
# Quickstart: Building with Bazel
|
||||
|
||||
This tutorial aims to get you up and running with GoogleTest using the Bazel
|
||||
build system. If you're using GoogleTest for the first time or need a refresher,
|
||||
we recommend this tutorial as a starting point.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
To complete this tutorial, you'll need:
|
||||
|
||||
* A compatible operating system (e.g. Linux, macOS, Windows).
|
||||
* A compatible C++ compiler that supports at least C++14.
|
||||
* [Bazel](https://bazel.build/), the preferred build system used by the
|
||||
GoogleTest team.
|
||||
|
||||
See [Supported Platforms](platforms.md) for more information about platforms
|
||||
compatible with GoogleTest.
|
||||
|
||||
If you don't already have Bazel installed, see the
|
||||
[Bazel installation guide](https://bazel.build/install).
|
||||
|
||||
{: .callout .note} Note: The terminal commands in this tutorial show a Unix
|
||||
shell prompt, but the commands work on the Windows command line as well.
|
||||
|
||||
## Set up a Bazel workspace
|
||||
|
||||
A
|
||||
[Bazel workspace](https://docs.bazel.build/versions/main/build-ref.html#workspace)
|
||||
is a directory on your filesystem that you use to manage source files for the
|
||||
software you want to build. Each workspace directory has a text file named
|
||||
`WORKSPACE` which may be empty, or may contain references to external
|
||||
dependencies required to build the outputs.
|
||||
|
||||
First, create a directory for your workspace:
|
||||
|
||||
```
|
||||
$ mkdir my_workspace && cd my_workspace
|
||||
```
|
||||
|
||||
Next, you’ll create the `WORKSPACE` file to specify dependencies. A common and
|
||||
recommended way to depend on GoogleTest is to use a
|
||||
[Bazel external dependency](https://docs.bazel.build/versions/main/external.html)
|
||||
via the
|
||||
[`http_archive` rule](https://docs.bazel.build/versions/main/repo/http.html#http_archive).
|
||||
To do this, in the root directory of your workspace (`my_workspace/`), create a
|
||||
file named `WORKSPACE` with the following contents:
|
||||
|
||||
```
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
http_archive(
|
||||
name = "com_google_googletest",
|
||||
urls = ["https://github.com/google/googletest/archive/5ab508a01f9eb089207ee87fd547d290da39d015.zip"],
|
||||
strip_prefix = "googletest-5ab508a01f9eb089207ee87fd547d290da39d015",
|
||||
)
|
||||
```
|
||||
|
||||
The above configuration declares a dependency on GoogleTest which is downloaded
|
||||
as a ZIP archive from GitHub. In the above example,
|
||||
`5ab508a01f9eb089207ee87fd547d290da39d015` is the Git commit hash of the
|
||||
GoogleTest version to use; we recommend updating the hash often to point to the
|
||||
latest version. Use a recent hash on the `main` branch.
|
||||
|
||||
Now you're ready to build C++ code that uses GoogleTest.
|
||||
|
||||
## Create and run a binary
|
||||
|
||||
With your Bazel workspace set up, you can now use GoogleTest code within your
|
||||
own project.
|
||||
|
||||
As an example, create a file named `hello_test.cc` in your `my_workspace`
|
||||
directory with the following contents:
|
||||
|
||||
```cpp
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
// Demonstrate some basic assertions.
|
||||
TEST(HelloTest, BasicAssertions) {
|
||||
// Expect two strings not to be equal.
|
||||
EXPECT_STRNE("hello", "world");
|
||||
// Expect equality.
|
||||
EXPECT_EQ(7 * 6, 42);
|
||||
}
|
||||
```
|
||||
|
||||
GoogleTest provides [assertions](primer.md#assertions) that you use to test the
|
||||
behavior of your code. The above sample includes the main GoogleTest header file
|
||||
and demonstrates some basic assertions.
|
||||
|
||||
To build the code, create a file named `BUILD` in the same directory with the
|
||||
following contents:
|
||||
|
||||
```
|
||||
cc_test(
|
||||
name = "hello_test",
|
||||
size = "small",
|
||||
srcs = ["hello_test.cc"],
|
||||
deps = ["@com_google_googletest//:gtest_main"],
|
||||
)
|
||||
```
|
||||
|
||||
This `cc_test` rule declares the C++ test binary you want to build, and links to
|
||||
GoogleTest (`//:gtest_main`) using the prefix you specified in the `WORKSPACE`
|
||||
file (`@com_google_googletest`). For more information about Bazel `BUILD` files,
|
||||
see the
|
||||
[Bazel C++ Tutorial](https://docs.bazel.build/versions/main/tutorial/cpp.html).
|
||||
|
||||
Now you can build and run your test:
|
||||
|
||||
<pre>
|
||||
<strong>my_workspace$ bazel test --test_output=all //:hello_test</strong>
|
||||
INFO: Analyzed target //:hello_test (26 packages loaded, 362 targets configured).
|
||||
INFO: Found 1 test target...
|
||||
INFO: From Testing //:hello_test:
|
||||
==================== Test output for //:hello_test:
|
||||
Running main() from gmock_main.cc
|
||||
[==========] Running 1 test from 1 test suite.
|
||||
[----------] Global test environment set-up.
|
||||
[----------] 1 test from HelloTest
|
||||
[ RUN ] HelloTest.BasicAssertions
|
||||
[ OK ] HelloTest.BasicAssertions (0 ms)
|
||||
[----------] 1 test from HelloTest (0 ms total)
|
||||
|
||||
[----------] Global test environment tear-down
|
||||
[==========] 1 test from 1 test suite ran. (0 ms total)
|
||||
[ PASSED ] 1 test.
|
||||
================================================================================
|
||||
Target //:hello_test up-to-date:
|
||||
bazel-bin/hello_test
|
||||
INFO: Elapsed time: 4.190s, Critical Path: 3.05s
|
||||
INFO: 27 processes: 8 internal, 19 linux-sandbox.
|
||||
INFO: Build completed successfully, 27 total actions
|
||||
//:hello_test PASSED in 0.1s
|
||||
|
||||
INFO: Build completed successfully, 27 total actions
|
||||
</pre>
|
||||
|
||||
Congratulations! You've successfully built and run a test binary using
|
||||
GoogleTest.
|
||||
|
||||
## Next steps
|
||||
|
||||
* [Check out the Primer](primer.md) to start learning how to write simple
|
||||
tests.
|
||||
* [See the code samples](samples.md) for more examples showing how to use a
|
||||
variety of GoogleTest features.
|
@@ -1,156 +0,0 @@
|
||||
# Quickstart: Building with CMake
|
||||
|
||||
This tutorial aims to get you up and running with GoogleTest using CMake. If
|
||||
you're using GoogleTest for the first time or need a refresher, we recommend
|
||||
this tutorial as a starting point. If your project uses Bazel, see the
|
||||
[Quickstart for Bazel](quickstart-bazel.md) instead.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
To complete this tutorial, you'll need:
|
||||
|
||||
* A compatible operating system (e.g. Linux, macOS, Windows).
|
||||
* A compatible C++ compiler that supports at least C++14.
|
||||
* [CMake](https://cmake.org/) and a compatible build tool for building the
|
||||
project.
|
||||
* Compatible build tools include
|
||||
[Make](https://www.gnu.org/software/make/),
|
||||
[Ninja](https://ninja-build.org/), and others - see
|
||||
[CMake Generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html)
|
||||
for more information.
|
||||
|
||||
See [Supported Platforms](platforms.md) for more information about platforms
|
||||
compatible with GoogleTest.
|
||||
|
||||
If you don't already have CMake installed, see the
|
||||
[CMake installation guide](https://cmake.org/install).
|
||||
|
||||
{: .callout .note}
|
||||
Note: The terminal commands in this tutorial show a Unix shell prompt, but the
|
||||
commands work on the Windows command line as well.
|
||||
|
||||
## Set up a project
|
||||
|
||||
CMake uses a file named `CMakeLists.txt` to configure the build system for a
|
||||
project. You'll use this file to set up your project and declare a dependency on
|
||||
GoogleTest.
|
||||
|
||||
First, create a directory for your project:
|
||||
|
||||
```
|
||||
$ mkdir my_project && cd my_project
|
||||
```
|
||||
|
||||
Next, you'll create the `CMakeLists.txt` file and declare a dependency on
|
||||
GoogleTest. There are many ways to express dependencies in the CMake ecosystem;
|
||||
in this quickstart, you'll use the
|
||||
[`FetchContent` CMake module](https://cmake.org/cmake/help/latest/module/FetchContent.html).
|
||||
To do this, in your project directory (`my_project`), create a file named
|
||||
`CMakeLists.txt` with the following contents:
|
||||
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
project(my_project)
|
||||
|
||||
# GoogleTest requires at least C++14
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
|
||||
)
|
||||
# For Windows: Prevent overriding the parent project's compiler/linker settings
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
```
|
||||
|
||||
The above configuration declares a dependency on GoogleTest which is downloaded
|
||||
from GitHub. In the above example, `03597a01ee50ed33e9dfd640b249b4be3799d395` is
|
||||
the Git commit hash of the GoogleTest version to use; we recommend updating the
|
||||
hash often to point to the latest version.
|
||||
|
||||
For more information about how to create `CMakeLists.txt` files, see the
|
||||
[CMake Tutorial](https://cmake.org/cmake/help/latest/guide/tutorial/index.html).
|
||||
|
||||
## Create and run a binary
|
||||
|
||||
With GoogleTest declared as a dependency, you can use GoogleTest code within
|
||||
your own project.
|
||||
|
||||
As an example, create a file named `hello_test.cc` in your `my_project`
|
||||
directory with the following contents:
|
||||
|
||||
```cpp
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
// Demonstrate some basic assertions.
|
||||
TEST(HelloTest, BasicAssertions) {
|
||||
// Expect two strings not to be equal.
|
||||
EXPECT_STRNE("hello", "world");
|
||||
// Expect equality.
|
||||
EXPECT_EQ(7 * 6, 42);
|
||||
}
|
||||
```
|
||||
|
||||
GoogleTest provides [assertions](primer.md#assertions) that you use to test the
|
||||
behavior of your code. The above sample includes the main GoogleTest header file
|
||||
and demonstrates some basic assertions.
|
||||
|
||||
To build the code, add the following to the end of your `CMakeLists.txt` file:
|
||||
|
||||
```cmake
|
||||
enable_testing()
|
||||
|
||||
add_executable(
|
||||
hello_test
|
||||
hello_test.cc
|
||||
)
|
||||
target_link_libraries(
|
||||
hello_test
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(hello_test)
|
||||
```
|
||||
|
||||
The above configuration enables testing in CMake, declares the C++ test binary
|
||||
you want to build (`hello_test`), and links it to GoogleTest (`gtest_main`). The
|
||||
last two lines enable CMake's test runner to discover the tests included in the
|
||||
binary, using the
|
||||
[`GoogleTest` CMake module](https://cmake.org/cmake/help/git-stage/module/GoogleTest.html).
|
||||
|
||||
Now you can build and run your test:
|
||||
|
||||
<pre>
|
||||
<strong>my_project$ cmake -S . -B build</strong>
|
||||
-- The C compiler identification is GNU 10.2.1
|
||||
-- The CXX compiler identification is GNU 10.2.1
|
||||
...
|
||||
-- Build files have been written to: .../my_project/build
|
||||
|
||||
<strong>my_project$ cmake --build build</strong>
|
||||
Scanning dependencies of target gtest
|
||||
...
|
||||
[100%] Built target gmock_main
|
||||
|
||||
<strong>my_project$ cd build && ctest</strong>
|
||||
Test project .../my_project/build
|
||||
Start 1: HelloTest.BasicAssertions
|
||||
1/1 Test #1: HelloTest.BasicAssertions ........ Passed 0.00 sec
|
||||
|
||||
100% tests passed, 0 tests failed out of 1
|
||||
|
||||
Total Test time (real) = 0.01 sec
|
||||
</pre>
|
||||
|
||||
Congratulations! You've successfully built and run a test binary using
|
||||
GoogleTest.
|
||||
|
||||
## Next steps
|
||||
|
||||
* [Check out the Primer](primer.md) to start learning how to write simple
|
||||
tests.
|
||||
* [See the code samples](samples.md) for more examples showing how to use a
|
||||
variety of GoogleTest features.
|
@@ -1,115 +0,0 @@
|
||||
# Actions Reference
|
||||
|
||||
[**Actions**](../gmock_for_dummies.md#actions-what-should-it-do) specify what a
|
||||
mock function should do when invoked. This page lists the built-in actions
|
||||
provided by GoogleTest. All actions are defined in the `::testing` namespace.
|
||||
|
||||
## Returning a Value
|
||||
|
||||
| Action | Description |
|
||||
| :-------------------------------- | :-------------------------------------------- |
|
||||
| `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. |
|
||||
| `ReturnRoundRobin({a1, ..., ak})` | Each call will return the next `ai` in the list, starting at the beginning when the end of the list is reached. |
|
||||
|
||||
## Side Effects
|
||||
|
||||
| Action | Description |
|
||||
| :--------------------------------- | :-------------------------------------- |
|
||||
| `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. |
|
||||
|
||||
## Using a Function, Functor, or Lambda as an Action
|
||||
|
||||
In the following, by "callable" we mean a free function, `std::function`,
|
||||
functor, or lambda.
|
||||
|
||||
| Action | Description |
|
||||
| :---------------------------------- | :------------------------------------- |
|
||||
| `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. |
|
||||
|
||||
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 `std::ref()`. For example,
|
||||
|
||||
```cpp
|
||||
using ::testing::InvokeArgument;
|
||||
...
|
||||
InvokeArgument<2>(5, string("Hi"), std::ref(foo))
|
||||
```
|
||||
|
||||
calls the mock function's #2 argument, passing to it `5` and `string("Hi")` by
|
||||
value, and `foo` by reference.
|
||||
|
||||
## Default Action
|
||||
|
||||
| Action | Description |
|
||||
| :------------ | :----------------------------------------------------- |
|
||||
| `DoDefault()` | Do the default action (specified by `ON_CALL()` or the built-in one). |
|
||||
|
||||
{: .callout .note}
|
||||
**Note:** due to technical reasons, `DoDefault()` cannot be used inside a
|
||||
composite action - trying to do so will result in a run-time error.
|
||||
|
||||
## Composite Actions
|
||||
|
||||
| Action | Description |
|
||||
| :----------------------------- | :------------------------------------------ |
|
||||
| `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 and will receive a readonly view of the arguments. |
|
||||
| `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. |
|
||||
|
||||
## Defining Actions
|
||||
|
||||
| Macro | Description |
|
||||
| :--------------------------------- | :-------------------------------------- |
|
||||
| `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`. |
|
||||
|
||||
The `ACTION*` macros cannot be used inside a function or class.
|
@@ -1,633 +0,0 @@
|
||||
# Assertions Reference
|
||||
|
||||
This page lists the assertion macros provided by GoogleTest for verifying code
|
||||
behavior. To use them, include the header `gtest/gtest.h`.
|
||||
|
||||
The majority of the macros listed below come as a pair with an `EXPECT_` variant
|
||||
and an `ASSERT_` variant. Upon failure, `EXPECT_` macros generate nonfatal
|
||||
failures and allow the current function to continue running, while `ASSERT_`
|
||||
macros generate fatal failures and abort the current function.
|
||||
|
||||
All assertion macros support streaming a custom failure message into them with
|
||||
the `<<` operator, for example:
|
||||
|
||||
```cpp
|
||||
EXPECT_TRUE(my_condition) << "My condition is not true";
|
||||
```
|
||||
|
||||
Anything that can be streamed to an `ostream` can be streamed to an assertion
|
||||
macro—in particular, C strings and string objects. If a wide string (`wchar_t*`,
|
||||
`TCHAR*` in `UNICODE` mode on Windows, or `std::wstring`) is streamed to an
|
||||
assertion, it will be translated to UTF-8 when printed.
|
||||
|
||||
## Explicit Success and Failure {#success-failure}
|
||||
|
||||
The assertions in this section generate a success or failure directly instead of
|
||||
testing a value or expression. These are useful when control flow, rather than a
|
||||
Boolean expression, determines the test's success or failure, as shown by the
|
||||
following example:
|
||||
|
||||
```c++
|
||||
switch(expression) {
|
||||
case 1:
|
||||
... some checks ...
|
||||
case 2:
|
||||
... some other checks ...
|
||||
default:
|
||||
FAIL() << "We shouldn't get here.";
|
||||
}
|
||||
```
|
||||
|
||||
### SUCCEED {#SUCCEED}
|
||||
|
||||
`SUCCEED()`
|
||||
|
||||
Generates a success. This *does not* make the overall test succeed. A test is
|
||||
considered successful only if none of its assertions fail during its execution.
|
||||
|
||||
The `SUCCEED` assertion is purely documentary and currently doesn't generate any
|
||||
user-visible output. However, we may add `SUCCEED` messages to GoogleTest output
|
||||
in the future.
|
||||
|
||||
### FAIL {#FAIL}
|
||||
|
||||
`FAIL()`
|
||||
|
||||
Generates a fatal failure, which returns from the current function.
|
||||
|
||||
Can only be used in functions that return `void`. See
|
||||
[Assertion Placement](../advanced.md#assertion-placement) for more information.
|
||||
|
||||
### ADD_FAILURE {#ADD_FAILURE}
|
||||
|
||||
`ADD_FAILURE()`
|
||||
|
||||
Generates a nonfatal failure, which allows the current function to continue
|
||||
running.
|
||||
|
||||
### ADD_FAILURE_AT {#ADD_FAILURE_AT}
|
||||
|
||||
`ADD_FAILURE_AT(`*`file_path`*`,`*`line_number`*`)`
|
||||
|
||||
Generates a nonfatal failure at the file and line number specified.
|
||||
|
||||
## Generalized Assertion {#generalized}
|
||||
|
||||
The following assertion allows [matchers](matchers.md) to be used to verify
|
||||
values.
|
||||
|
||||
### EXPECT_THAT {#EXPECT_THAT}
|
||||
|
||||
`EXPECT_THAT(`*`value`*`,`*`matcher`*`)` \
|
||||
`ASSERT_THAT(`*`value`*`,`*`matcher`*`)`
|
||||
|
||||
Verifies that *`value`* matches the [matcher](matchers.md) *`matcher`*.
|
||||
|
||||
For example, the following code verifies that the string `value1` starts with
|
||||
`"Hello"`, `value2` matches a regular expression, and `value3` is between 5 and
|
||||
10:
|
||||
|
||||
```cpp
|
||||
#include "gmock/gmock.h"
|
||||
|
||||
using ::testing::AllOf;
|
||||
using ::testing::Gt;
|
||||
using ::testing::Lt;
|
||||
using ::testing::MatchesRegex;
|
||||
using ::testing::StartsWith;
|
||||
|
||||
...
|
||||
EXPECT_THAT(value1, StartsWith("Hello"));
|
||||
EXPECT_THAT(value2, MatchesRegex("Line \\d+"));
|
||||
ASSERT_THAT(value3, AllOf(Gt(5), Lt(10)));
|
||||
```
|
||||
|
||||
Matchers enable assertions of this form to read like English and generate
|
||||
informative failure messages. For example, if the above assertion on `value1`
|
||||
fails, the resulting message will be similar to the following:
|
||||
|
||||
```
|
||||
Value of: value1
|
||||
Actual: "Hi, world!"
|
||||
Expected: starts with "Hello"
|
||||
```
|
||||
|
||||
GoogleTest provides a built-in library of matchers—see the
|
||||
[Matchers Reference](matchers.md). It is also possible to write your own
|
||||
matchers—see [Writing New Matchers Quickly](../gmock_cook_book.md#NewMatchers).
|
||||
The use of matchers makes `EXPECT_THAT` a powerful, extensible assertion.
|
||||
|
||||
*The idea for this assertion was borrowed from Joe Walnes' Hamcrest project,
|
||||
which adds `assertThat()` to JUnit.*
|
||||
|
||||
## Boolean Conditions {#boolean}
|
||||
|
||||
The following assertions test Boolean conditions.
|
||||
|
||||
### EXPECT_TRUE {#EXPECT_TRUE}
|
||||
|
||||
`EXPECT_TRUE(`*`condition`*`)` \
|
||||
`ASSERT_TRUE(`*`condition`*`)`
|
||||
|
||||
Verifies that *`condition`* is true.
|
||||
|
||||
### EXPECT_FALSE {#EXPECT_FALSE}
|
||||
|
||||
`EXPECT_FALSE(`*`condition`*`)` \
|
||||
`ASSERT_FALSE(`*`condition`*`)`
|
||||
|
||||
Verifies that *`condition`* is false.
|
||||
|
||||
## Binary Comparison {#binary-comparison}
|
||||
|
||||
The following assertions compare two values. The value arguments must be
|
||||
comparable by the assertion's comparison operator, otherwise a compiler error
|
||||
will result.
|
||||
|
||||
If an argument supports the `<<` operator, it will be called to print the
|
||||
argument when the assertion fails. Otherwise, GoogleTest will attempt to print
|
||||
them in the best way it can—see
|
||||
[Teaching GoogleTest How to Print Your Values](../advanced.md#teaching-googletest-how-to-print-your-values).
|
||||
|
||||
Arguments are always evaluated exactly once, so it's OK for the arguments to
|
||||
have side effects. However, the argument evaluation order is undefined and
|
||||
programs should not depend on any particular argument evaluation order.
|
||||
|
||||
These assertions work with both narrow and wide string objects (`string` and
|
||||
`wstring`).
|
||||
|
||||
See also the [Floating-Point Comparison](#floating-point) assertions to compare
|
||||
floating-point numbers and avoid problems caused by rounding.
|
||||
|
||||
### EXPECT_EQ {#EXPECT_EQ}
|
||||
|
||||
`EXPECT_EQ(`*`val1`*`,`*`val2`*`)` \
|
||||
`ASSERT_EQ(`*`val1`*`,`*`val2`*`)`
|
||||
|
||||
Verifies that *`val1`*`==`*`val2`*.
|
||||
|
||||
Does pointer equality on pointers. If used on two C strings, it tests if they
|
||||
are in the same memory location, not if they have the same value. Use
|
||||
[`EXPECT_STREQ`](#EXPECT_STREQ) to compare C strings (e.g. `const char*`) by
|
||||
value.
|
||||
|
||||
When comparing a pointer to `NULL`, use `EXPECT_EQ(`*`ptr`*`, nullptr)` instead
|
||||
of `EXPECT_EQ(`*`ptr`*`, NULL)`.
|
||||
|
||||
### EXPECT_NE {#EXPECT_NE}
|
||||
|
||||
`EXPECT_NE(`*`val1`*`,`*`val2`*`)` \
|
||||
`ASSERT_NE(`*`val1`*`,`*`val2`*`)`
|
||||
|
||||
Verifies that *`val1`*`!=`*`val2`*.
|
||||
|
||||
Does pointer equality on pointers. If used on two C strings, it tests if they
|
||||
are in different memory locations, not if they have different values. Use
|
||||
[`EXPECT_STRNE`](#EXPECT_STRNE) to compare C strings (e.g. `const char*`) by
|
||||
value.
|
||||
|
||||
When comparing a pointer to `NULL`, use `EXPECT_NE(`*`ptr`*`, nullptr)` instead
|
||||
of `EXPECT_NE(`*`ptr`*`, NULL)`.
|
||||
|
||||
### EXPECT_LT {#EXPECT_LT}
|
||||
|
||||
`EXPECT_LT(`*`val1`*`,`*`val2`*`)` \
|
||||
`ASSERT_LT(`*`val1`*`,`*`val2`*`)`
|
||||
|
||||
Verifies that *`val1`*`<`*`val2`*.
|
||||
|
||||
### EXPECT_LE {#EXPECT_LE}
|
||||
|
||||
`EXPECT_LE(`*`val1`*`,`*`val2`*`)` \
|
||||
`ASSERT_LE(`*`val1`*`,`*`val2`*`)`
|
||||
|
||||
Verifies that *`val1`*`<=`*`val2`*.
|
||||
|
||||
### EXPECT_GT {#EXPECT_GT}
|
||||
|
||||
`EXPECT_GT(`*`val1`*`,`*`val2`*`)` \
|
||||
`ASSERT_GT(`*`val1`*`,`*`val2`*`)`
|
||||
|
||||
Verifies that *`val1`*`>`*`val2`*.
|
||||
|
||||
### EXPECT_GE {#EXPECT_GE}
|
||||
|
||||
`EXPECT_GE(`*`val1`*`,`*`val2`*`)` \
|
||||
`ASSERT_GE(`*`val1`*`,`*`val2`*`)`
|
||||
|
||||
Verifies that *`val1`*`>=`*`val2`*.
|
||||
|
||||
## String Comparison {#c-strings}
|
||||
|
||||
The following assertions compare two **C strings**. To compare two `string`
|
||||
objects, use [`EXPECT_EQ`](#EXPECT_EQ) or [`EXPECT_NE`](#EXPECT_NE) instead.
|
||||
|
||||
These assertions also accept wide C strings (`wchar_t*`). If a comparison of two
|
||||
wide strings fails, their values will be printed as UTF-8 narrow strings.
|
||||
|
||||
To compare a C string with `NULL`, use `EXPECT_EQ(`*`c_string`*`, nullptr)` or
|
||||
`EXPECT_NE(`*`c_string`*`, nullptr)`.
|
||||
|
||||
### EXPECT_STREQ {#EXPECT_STREQ}
|
||||
|
||||
`EXPECT_STREQ(`*`str1`*`,`*`str2`*`)` \
|
||||
`ASSERT_STREQ(`*`str1`*`,`*`str2`*`)`
|
||||
|
||||
Verifies that the two C strings *`str1`* and *`str2`* have the same contents.
|
||||
|
||||
### EXPECT_STRNE {#EXPECT_STRNE}
|
||||
|
||||
`EXPECT_STRNE(`*`str1`*`,`*`str2`*`)` \
|
||||
`ASSERT_STRNE(`*`str1`*`,`*`str2`*`)`
|
||||
|
||||
Verifies that the two C strings *`str1`* and *`str2`* have different contents.
|
||||
|
||||
### EXPECT_STRCASEEQ {#EXPECT_STRCASEEQ}
|
||||
|
||||
`EXPECT_STRCASEEQ(`*`str1`*`,`*`str2`*`)` \
|
||||
`ASSERT_STRCASEEQ(`*`str1`*`,`*`str2`*`)`
|
||||
|
||||
Verifies that the two C strings *`str1`* and *`str2`* have the same contents,
|
||||
ignoring case.
|
||||
|
||||
### EXPECT_STRCASENE {#EXPECT_STRCASENE}
|
||||
|
||||
`EXPECT_STRCASENE(`*`str1`*`,`*`str2`*`)` \
|
||||
`ASSERT_STRCASENE(`*`str1`*`,`*`str2`*`)`
|
||||
|
||||
Verifies that the two C strings *`str1`* and *`str2`* have different contents,
|
||||
ignoring case.
|
||||
|
||||
## Floating-Point Comparison {#floating-point}
|
||||
|
||||
The following assertions compare two floating-point values.
|
||||
|
||||
Due to rounding errors, it is very unlikely that two floating-point values will
|
||||
match exactly, so `EXPECT_EQ` is not suitable. In general, for floating-point
|
||||
comparison to make sense, the user needs to carefully choose the error bound.
|
||||
|
||||
GoogleTest also provides assertions that use a default error bound based on
|
||||
Units in the Last Place (ULPs). To learn more about ULPs, see the article
|
||||
[Comparing Floating Point Numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
|
||||
|
||||
### EXPECT_FLOAT_EQ {#EXPECT_FLOAT_EQ}
|
||||
|
||||
`EXPECT_FLOAT_EQ(`*`val1`*`,`*`val2`*`)` \
|
||||
`ASSERT_FLOAT_EQ(`*`val1`*`,`*`val2`*`)`
|
||||
|
||||
Verifies that the two `float` values *`val1`* and *`val2`* are approximately
|
||||
equal, to within 4 ULPs from each other.
|
||||
|
||||
### EXPECT_DOUBLE_EQ {#EXPECT_DOUBLE_EQ}
|
||||
|
||||
`EXPECT_DOUBLE_EQ(`*`val1`*`,`*`val2`*`)` \
|
||||
`ASSERT_DOUBLE_EQ(`*`val1`*`,`*`val2`*`)`
|
||||
|
||||
Verifies that the two `double` values *`val1`* and *`val2`* are approximately
|
||||
equal, to within 4 ULPs from each other.
|
||||
|
||||
### EXPECT_NEAR {#EXPECT_NEAR}
|
||||
|
||||
`EXPECT_NEAR(`*`val1`*`,`*`val2`*`,`*`abs_error`*`)` \
|
||||
`ASSERT_NEAR(`*`val1`*`,`*`val2`*`,`*`abs_error`*`)`
|
||||
|
||||
Verifies that the difference between *`val1`* and *`val2`* does not exceed the
|
||||
absolute error bound *`abs_error`*.
|
||||
|
||||
## Exception Assertions {#exceptions}
|
||||
|
||||
The following assertions verify that a piece of code throws, or does not throw,
|
||||
an exception. Usage requires exceptions to be enabled in the build environment.
|
||||
|
||||
Note that the piece of code under test can be a compound statement, for example:
|
||||
|
||||
```cpp
|
||||
EXPECT_NO_THROW({
|
||||
int n = 5;
|
||||
DoSomething(&n);
|
||||
});
|
||||
```
|
||||
|
||||
### EXPECT_THROW {#EXPECT_THROW}
|
||||
|
||||
`EXPECT_THROW(`*`statement`*`,`*`exception_type`*`)` \
|
||||
`ASSERT_THROW(`*`statement`*`,`*`exception_type`*`)`
|
||||
|
||||
Verifies that *`statement`* throws an exception of type *`exception_type`*.
|
||||
|
||||
### EXPECT_ANY_THROW {#EXPECT_ANY_THROW}
|
||||
|
||||
`EXPECT_ANY_THROW(`*`statement`*`)` \
|
||||
`ASSERT_ANY_THROW(`*`statement`*`)`
|
||||
|
||||
Verifies that *`statement`* throws an exception of any type.
|
||||
|
||||
### EXPECT_NO_THROW {#EXPECT_NO_THROW}
|
||||
|
||||
`EXPECT_NO_THROW(`*`statement`*`)` \
|
||||
`ASSERT_NO_THROW(`*`statement`*`)`
|
||||
|
||||
Verifies that *`statement`* does not throw any exception.
|
||||
|
||||
## Predicate Assertions {#predicates}
|
||||
|
||||
The following assertions enable more complex predicates to be verified while
|
||||
printing a more clear failure message than if `EXPECT_TRUE` were used alone.
|
||||
|
||||
### EXPECT_PRED* {#EXPECT_PRED}
|
||||
|
||||
`EXPECT_PRED1(`*`pred`*`,`*`val1`*`)` \
|
||||
`EXPECT_PRED2(`*`pred`*`,`*`val1`*`,`*`val2`*`)` \
|
||||
`EXPECT_PRED3(`*`pred`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`)` \
|
||||
`EXPECT_PRED4(`*`pred`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`,`*`val4`*`)` \
|
||||
`EXPECT_PRED5(`*`pred`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`,`*`val4`*`,`*`val5`*`)`
|
||||
|
||||
`ASSERT_PRED1(`*`pred`*`,`*`val1`*`)` \
|
||||
`ASSERT_PRED2(`*`pred`*`,`*`val1`*`,`*`val2`*`)` \
|
||||
`ASSERT_PRED3(`*`pred`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`)` \
|
||||
`ASSERT_PRED4(`*`pred`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`,`*`val4`*`)` \
|
||||
`ASSERT_PRED5(`*`pred`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`,`*`val4`*`,`*`val5`*`)`
|
||||
|
||||
Verifies that the predicate *`pred`* returns `true` when passed the given values
|
||||
as arguments.
|
||||
|
||||
The parameter *`pred`* is a function or functor that accepts as many arguments
|
||||
as the corresponding macro accepts values. If *`pred`* returns `true` for the
|
||||
given arguments, the assertion succeeds, otherwise the assertion fails.
|
||||
|
||||
When the assertion fails, it prints the value of each argument. Arguments are
|
||||
always evaluated exactly once.
|
||||
|
||||
As an example, see the following code:
|
||||
|
||||
```cpp
|
||||
// Returns true if m and n have no common divisors except 1.
|
||||
bool MutuallyPrime(int m, int n) { ... }
|
||||
...
|
||||
const int a = 3;
|
||||
const int b = 4;
|
||||
const int c = 10;
|
||||
...
|
||||
EXPECT_PRED2(MutuallyPrime, a, b); // Succeeds
|
||||
EXPECT_PRED2(MutuallyPrime, b, c); // Fails
|
||||
```
|
||||
|
||||
In the above example, the first assertion succeeds, and the second fails with
|
||||
the following message:
|
||||
|
||||
```
|
||||
MutuallyPrime(b, c) is false, where
|
||||
b is 4
|
||||
c is 10
|
||||
```
|
||||
|
||||
Note that if the given predicate is an overloaded function or a function
|
||||
template, the assertion macro might not be able to determine which version to
|
||||
use, and it might be necessary to explicitly specify the type of the function.
|
||||
For example, for a Boolean function `IsPositive()` overloaded to take either a
|
||||
single `int` or `double` argument, it would be necessary to write one of the
|
||||
following:
|
||||
|
||||
```cpp
|
||||
EXPECT_PRED1(static_cast<bool (*)(int)>(IsPositive), 5);
|
||||
EXPECT_PRED1(static_cast<bool (*)(double)>(IsPositive), 3.14);
|
||||
```
|
||||
|
||||
Writing simply `EXPECT_PRED1(IsPositive, 5);` would result in a compiler error.
|
||||
Similarly, to use a template function, specify the template arguments:
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
bool IsNegative(T x) {
|
||||
return x < 0;
|
||||
}
|
||||
...
|
||||
EXPECT_PRED1(IsNegative<int>, -5); // Must specify type for IsNegative
|
||||
```
|
||||
|
||||
If a template has multiple parameters, wrap the predicate in parentheses so the
|
||||
macro arguments are parsed correctly:
|
||||
|
||||
```cpp
|
||||
ASSERT_PRED2((MyPredicate<int, int>), 5, 0);
|
||||
```
|
||||
|
||||
### EXPECT_PRED_FORMAT* {#EXPECT_PRED_FORMAT}
|
||||
|
||||
`EXPECT_PRED_FORMAT1(`*`pred_formatter`*`,`*`val1`*`)` \
|
||||
`EXPECT_PRED_FORMAT2(`*`pred_formatter`*`,`*`val1`*`,`*`val2`*`)` \
|
||||
`EXPECT_PRED_FORMAT3(`*`pred_formatter`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`)` \
|
||||
`EXPECT_PRED_FORMAT4(`*`pred_formatter`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`,`*`val4`*`)`
|
||||
\
|
||||
`EXPECT_PRED_FORMAT5(`*`pred_formatter`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`,`*`val4`*`,`*`val5`*`)`
|
||||
|
||||
`ASSERT_PRED_FORMAT1(`*`pred_formatter`*`,`*`val1`*`)` \
|
||||
`ASSERT_PRED_FORMAT2(`*`pred_formatter`*`,`*`val1`*`,`*`val2`*`)` \
|
||||
`ASSERT_PRED_FORMAT3(`*`pred_formatter`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`)` \
|
||||
`ASSERT_PRED_FORMAT4(`*`pred_formatter`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`,`*`val4`*`)`
|
||||
\
|
||||
`ASSERT_PRED_FORMAT5(`*`pred_formatter`*`,`*`val1`*`,`*`val2`*`,`*`val3`*`,`*`val4`*`,`*`val5`*`)`
|
||||
|
||||
Verifies that the predicate *`pred_formatter`* succeeds when passed the given
|
||||
values as arguments.
|
||||
|
||||
The parameter *`pred_formatter`* is a *predicate-formatter*, which is a function
|
||||
or functor with the signature:
|
||||
|
||||
```cpp
|
||||
testing::AssertionResult PredicateFormatter(const char* expr1,
|
||||
const char* expr2,
|
||||
...
|
||||
const char* exprn,
|
||||
T1 val1,
|
||||
T2 val2,
|
||||
...
|
||||
Tn valn);
|
||||
```
|
||||
|
||||
where *`val1`*, *`val2`*, ..., *`valn`* are the values of the predicate
|
||||
arguments, and *`expr1`*, *`expr2`*, ..., *`exprn`* are the corresponding
|
||||
expressions as they appear in the source code. The types `T1`, `T2`, ..., `Tn`
|
||||
can be either value types or reference types; if an argument has type `T`, it
|
||||
can be declared as either `T` or `const T&`, whichever is appropriate. For more
|
||||
about the return type `testing::AssertionResult`, see
|
||||
[Using a Function That Returns an AssertionResult](../advanced.md#using-a-function-that-returns-an-assertionresult).
|
||||
|
||||
As an example, see the following code:
|
||||
|
||||
```cpp
|
||||
// Returns the smallest prime common divisor of m and n,
|
||||
// or 1 when m and n are mutually prime.
|
||||
int SmallestPrimeCommonDivisor(int m, int n) { ... }
|
||||
|
||||
// Returns true if m and n have no common divisors except 1.
|
||||
bool MutuallyPrime(int m, int n) { ... }
|
||||
|
||||
// A predicate-formatter for asserting that two integers are mutually prime.
|
||||
testing::AssertionResult AssertMutuallyPrime(const char* m_expr,
|
||||
const char* n_expr,
|
||||
int m,
|
||||
int n) {
|
||||
if (MutuallyPrime(m, n)) return testing::AssertionSuccess();
|
||||
|
||||
return testing::AssertionFailure() << m_expr << " and " << n_expr
|
||||
<< " (" << m << " and " << n << ") are not mutually prime, "
|
||||
<< "as they have a common divisor " << SmallestPrimeCommonDivisor(m, n);
|
||||
}
|
||||
|
||||
...
|
||||
const int a = 3;
|
||||
const int b = 4;
|
||||
const int c = 10;
|
||||
...
|
||||
EXPECT_PRED_FORMAT2(AssertMutuallyPrime, a, b); // Succeeds
|
||||
EXPECT_PRED_FORMAT2(AssertMutuallyPrime, b, c); // Fails
|
||||
```
|
||||
|
||||
In the above example, the final assertion fails and the predicate-formatter
|
||||
produces the following failure message:
|
||||
|
||||
```
|
||||
b and c (4 and 10) are not mutually prime, as they have a common divisor 2
|
||||
```
|
||||
|
||||
## Windows HRESULT Assertions {#HRESULT}
|
||||
|
||||
The following assertions test for `HRESULT` success or failure. For example:
|
||||
|
||||
```cpp
|
||||
CComPtr<IShellDispatch2> shell;
|
||||
ASSERT_HRESULT_SUCCEEDED(shell.CoCreateInstance(L"Shell.Application"));
|
||||
CComVariant empty;
|
||||
ASSERT_HRESULT_SUCCEEDED(shell->ShellExecute(CComBSTR(url), empty, empty, empty, empty));
|
||||
```
|
||||
|
||||
The generated output contains the human-readable error message associated with
|
||||
the returned `HRESULT` code.
|
||||
|
||||
### EXPECT_HRESULT_SUCCEEDED {#EXPECT_HRESULT_SUCCEEDED}
|
||||
|
||||
`EXPECT_HRESULT_SUCCEEDED(`*`expression`*`)` \
|
||||
`ASSERT_HRESULT_SUCCEEDED(`*`expression`*`)`
|
||||
|
||||
Verifies that *`expression`* is a success `HRESULT`.
|
||||
|
||||
### EXPECT_HRESULT_FAILED {#EXPECT_HRESULT_FAILED}
|
||||
|
||||
`EXPECT_HRESULT_FAILED(`*`expression`*`)` \
|
||||
`EXPECT_HRESULT_FAILED(`*`expression`*`)`
|
||||
|
||||
Verifies that *`expression`* is a failure `HRESULT`.
|
||||
|
||||
## Death Assertions {#death}
|
||||
|
||||
The following assertions verify that a piece of code causes the process to
|
||||
terminate. For context, see [Death Tests](../advanced.md#death-tests).
|
||||
|
||||
These assertions spawn a new process and execute the code under test in that
|
||||
process. How that happens depends on the platform and the variable
|
||||
`::testing::GTEST_FLAG(death_test_style)`, which is initialized from the
|
||||
command-line flag `--gtest_death_test_style`.
|
||||
|
||||
* On POSIX systems, `fork()` (or `clone()` on Linux) is used to spawn the
|
||||
child, after which:
|
||||
* If the variable's value is `"fast"`, the death test statement is
|
||||
immediately executed.
|
||||
* If the variable's value is `"threadsafe"`, the child process re-executes
|
||||
the unit test binary just as it was originally invoked, but with some
|
||||
extra flags to cause just the single death test under consideration to
|
||||
be run.
|
||||
* On Windows, the child is spawned using the `CreateProcess()` API, and
|
||||
re-executes the binary to cause just the single death test under
|
||||
consideration to be run - much like the `"threadsafe"` mode on POSIX.
|
||||
|
||||
Other values for the variable are illegal and will cause the death test to fail.
|
||||
Currently, the flag's default value is
|
||||
**`"fast"`**.
|
||||
|
||||
If the death test statement runs to completion without dying, the child process
|
||||
will nonetheless terminate, and the assertion fails.
|
||||
|
||||
Note that the piece of code under test can be a compound statement, for example:
|
||||
|
||||
```cpp
|
||||
EXPECT_DEATH({
|
||||
int n = 5;
|
||||
DoSomething(&n);
|
||||
}, "Error on line .* of DoSomething()");
|
||||
```
|
||||
|
||||
### EXPECT_DEATH {#EXPECT_DEATH}
|
||||
|
||||
`EXPECT_DEATH(`*`statement`*`,`*`matcher`*`)` \
|
||||
`ASSERT_DEATH(`*`statement`*`,`*`matcher`*`)`
|
||||
|
||||
Verifies that *`statement`* causes the process to terminate with a nonzero exit
|
||||
status and produces `stderr` output that matches *`matcher`*.
|
||||
|
||||
The parameter *`matcher`* is either a [matcher](matchers.md) for a `const
|
||||
std::string&`, or a regular expression (see
|
||||
[Regular Expression Syntax](../advanced.md#regular-expression-syntax))—a bare
|
||||
string *`s`* (with no matcher) is treated as
|
||||
[`ContainsRegex(s)`](matchers.md#string-matchers), **not**
|
||||
[`Eq(s)`](matchers.md#generic-comparison).
|
||||
|
||||
For example, the following code verifies that calling `DoSomething(42)` causes
|
||||
the process to die with an error message that contains the text `My error`:
|
||||
|
||||
```cpp
|
||||
EXPECT_DEATH(DoSomething(42), "My error");
|
||||
```
|
||||
|
||||
### EXPECT_DEATH_IF_SUPPORTED {#EXPECT_DEATH_IF_SUPPORTED}
|
||||
|
||||
`EXPECT_DEATH_IF_SUPPORTED(`*`statement`*`,`*`matcher`*`)` \
|
||||
`ASSERT_DEATH_IF_SUPPORTED(`*`statement`*`,`*`matcher`*`)`
|
||||
|
||||
If death tests are supported, behaves the same as
|
||||
[`EXPECT_DEATH`](#EXPECT_DEATH). Otherwise, verifies nothing.
|
||||
|
||||
### EXPECT_DEBUG_DEATH {#EXPECT_DEBUG_DEATH}
|
||||
|
||||
`EXPECT_DEBUG_DEATH(`*`statement`*`,`*`matcher`*`)` \
|
||||
`ASSERT_DEBUG_DEATH(`*`statement`*`,`*`matcher`*`)`
|
||||
|
||||
In debug mode, behaves the same as [`EXPECT_DEATH`](#EXPECT_DEATH). When not in
|
||||
debug mode (i.e. `NDEBUG` is defined), just executes *`statement`*.
|
||||
|
||||
### EXPECT_EXIT {#EXPECT_EXIT}
|
||||
|
||||
`EXPECT_EXIT(`*`statement`*`,`*`predicate`*`,`*`matcher`*`)` \
|
||||
`ASSERT_EXIT(`*`statement`*`,`*`predicate`*`,`*`matcher`*`)`
|
||||
|
||||
Verifies that *`statement`* causes the process to terminate with an exit status
|
||||
that satisfies *`predicate`*, and produces `stderr` output that matches
|
||||
*`matcher`*.
|
||||
|
||||
The parameter *`predicate`* is a function or functor that accepts an `int` exit
|
||||
status and returns a `bool`. GoogleTest provides two predicates to handle common
|
||||
cases:
|
||||
|
||||
```cpp
|
||||
// Returns true if the program exited normally with the given exit status code.
|
||||
::testing::ExitedWithCode(exit_code);
|
||||
|
||||
// Returns true if the program was killed by the given signal.
|
||||
// Not available on Windows.
|
||||
::testing::KilledBySignal(signal_number);
|
||||
```
|
||||
|
||||
The parameter *`matcher`* is either a [matcher](matchers.md) for a `const
|
||||
std::string&`, or a regular expression (see
|
||||
[Regular Expression Syntax](../advanced.md#regular-expression-syntax))—a bare
|
||||
string *`s`* (with no matcher) is treated as
|
||||
[`ContainsRegex(s)`](matchers.md#string-matchers), **not**
|
||||
[`Eq(s)`](matchers.md#generic-comparison).
|
||||
|
||||
For example, the following code verifies that calling `NormalExit()` causes the
|
||||
process to print a message containing the text `Success` to `stderr` and exit
|
||||
with exit status code 0:
|
||||
|
||||
```cpp
|
||||
EXPECT_EXIT(NormalExit(), testing::ExitedWithCode(0), "Success");
|
||||
```
|
@@ -1,290 +0,0 @@
|
||||
# Matchers Reference
|
||||
|
||||
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:
|
||||
|
||||
| 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. |
|
||||
|
||||
{: .callout .warning}
|
||||
**WARNING:** Equality matching via `EXPECT_THAT(actual_value, expected_value)`
|
||||
is supported, however note that implicit conversions can cause surprising
|
||||
results. For example, `EXPECT_THAT(some_bool, "some string")` will compile and
|
||||
may pass unintentionally.
|
||||
|
||||
**BEST PRACTICE:** Prefer to make the comparison explicit via
|
||||
`EXPECT_THAT(actual_value, Eq(expected_value))` or `EXPECT_EQ(actual_value,
|
||||
expected_value)`.
|
||||
|
||||
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. All matchers are defined in the `::testing`
|
||||
namespace unless otherwise noted.
|
||||
|
||||
## 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
|
||||
|
||||
| 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`. (For testing whether an `optional<>` is set, check for equality with `nullopt`. You may need to use `Eq(nullopt)` if the inner type doesn't have `==`.)|
|
||||
| `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. |
|
||||
|
||||
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 `std::ref()`, e.g.
|
||||
`Eq(std::ref(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.
|
||||
|
||||
`IsTrue` and `IsFalse` are useful when you need to use a matcher, or for types
|
||||
that can be explicitly converted to Boolean, but are not implicitly converted to
|
||||
Boolean. In other cases, you can use the basic
|
||||
[`EXPECT_TRUE` and `EXPECT_FALSE`](assertions.md#boolean) assertions.
|
||||
|
||||
## Floating-Point Matchers {#FpMatchers}
|
||||
|
||||
| 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. |
|
||||
| `IsNan()` | `argument` is any floating-point type with a NaN value. |
|
||||
|
||||
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.
|
||||
|
||||
| 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. |
|
||||
|
||||
## String Matchers
|
||||
|
||||
The `argument` can be either a C string or a C++ string object:
|
||||
|
||||
| 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. |
|
||||
| `IsEmpty()` | `argument` is an empty 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`. |
|
||||
| `WhenBase64Unescaped(m)` | `argument` is a base-64 escaped string whose unescaped string matches `m`. |
|
||||
|
||||
`ContainsRegex()` and `MatchesRegex()` take ownership of the `RE` object. They
|
||||
use the regular expression syntax defined
|
||||
[here](../advanced.md#regular-expression-syntax). All of these matchers, except
|
||||
`ContainsRegex()` and `MatchesRegex()` 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:
|
||||
|
||||
| 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. |
|
||||
| `Contains(e).Times(n)` | `argument` contains elements that match `e`, which can be either a value or a matcher, and the number of matches is `n`, which can be either a value or a matcher. Unlike the plain `Contains` and `Each` this allows to check for arbitrary occurrences including testing for absence with `Contains(e).Times(0)`. |
|
||||
| `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))`. |
|
||||
|
||||
**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, ...)` and `UnorderedPointwise(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
|
||||
MATCHER(FooEq, "") {
|
||||
return std::get<0>(arg).Equals(std::get<1>(arg));
|
||||
}
|
||||
...
|
||||
EXPECT_THAT(actual_foos, Pointwise(FooEq(), expected_foos));
|
||||
```
|
||||
|
||||
## Member Matchers
|
||||
|
||||
| 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_. |
|
||||
| `Field(field_name, &class::field, m)` | The same as the two-parameter version, but provides a better error message. |
|
||||
| `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`. |
|
||||
| `FieldsAre(m...)` | `argument` is a compatible object where each field matches piecewise with the matchers `m...`. A compatible object is any that supports the `std::tuple_size<Obj>`+`get<I>(obj)` protocol. In C++17 and up this also supports types compatible with structured bindings, like aggregates. |
|
||||
| `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_. The method `property()` must take no argument and be declared as `const`. |
|
||||
| `Property(property_name, &class::property, m)` | The same as the two-parameter version, but provides a better error message.
|
||||
|
||||
**Notes:**
|
||||
|
||||
* You can use `FieldsAre()` to match any type that supports structured
|
||||
bindings, such as `std::tuple`, `std::pair`, `std::array`, and aggregate
|
||||
types. For example:
|
||||
|
||||
```cpp
|
||||
std::tuple<int, std::string> my_tuple{7, "hello world"};
|
||||
EXPECT_THAT(my_tuple, FieldsAre(Ge(0), HasSubstr("hello")));
|
||||
|
||||
struct MyStruct {
|
||||
int value = 42;
|
||||
std::string greeting = "aloha";
|
||||
};
|
||||
MyStruct s;
|
||||
EXPECT_THAT(s, FieldsAre(42, "aloha"));
|
||||
```
|
||||
|
||||
* Don't use `Property()` against member functions that you do not own, because
|
||||
taking addresses of functions is fragile and generally not part of the
|
||||
contract of the function.
|
||||
|
||||
## Matching the Result of a Function, Functor, or Callback
|
||||
|
||||
| Matcher | Description |
|
||||
| :--------------- | :------------------------------------------------ |
|
||||
| `ResultOf(f, m)` | `f(argument)` matches matcher `m`, where `f` is a function or functor. |
|
||||
| `ResultOf(result_description, f, m)` | The same as the two-parameter version, but provides a better error message.
|
||||
|
||||
## Pointer Matchers
|
||||
|
||||
| Matcher | Description |
|
||||
| :------------------------ | :---------------------------------------------- |
|
||||
| `Address(m)` | the result of `std::addressof(argument)` matches `m`. |
|
||||
| `Pointee(m)` | `argument` (either a smart pointer or a raw pointer) points to a value that matches matcher `m`. |
|
||||
| `Pointer(m)` | `argument` (either a smart pointer or a raw pointer) contains a pointer that matches `m`. `m` will match against the raw pointer regardless of the type of `argument`. |
|
||||
| `WhenDynamicCastTo<T>(m)` | when `argument` is passed through `dynamic_cast<T>()`, it matches matcher `m`. |
|
||||
|
||||
## 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:
|
||||
|
||||
| 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())`. |
|
||||
|
||||
## Composite Matchers
|
||||
|
||||
You can make a matcher from one or more other matchers:
|
||||
|
||||
| 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`. |
|
||||
| `Conditional(cond, m1, m2)` | Matches matcher `m1` if `cond` evaluates to true, else matches `m2`.|
|
||||
|
||||
## Adapters for Matchers
|
||||
|
||||
| Matcher | Description |
|
||||
| :---------------------- | :------------------------------------ |
|
||||
| `MatcherCast<T>(m)` | casts matcher `m` to type `Matcher<T>`. |
|
||||
| `SafeMatcherCast<T>(m)` | [safely casts](../gmock_cook_book.md#SafeMatcherCast) 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. |
|
||||
|
||||
`AddressSatisfies(callback)` and `Truly(callback)` take ownership of `callback`,
|
||||
which must be a permanent callback.
|
||||
|
||||
## Using Matchers as Predicates {#MatchersAsPredicatesCheat}
|
||||
|
||||
| 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`. |
|
||||
|
||||
## Defining Matchers
|
||||
|
||||
| Macro | 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 matcher `IsDivisibleBy(n)` to match a number divisible by `n`. |
|
||||
| `MATCHER_P2(IsBetween, a, b, absl::StrCat(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`]. |
|
||||
|
||||
**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.
|
||||
4. You can use `ExplainMatchResult()` in a custom matcher to wrap another
|
||||
matcher, for example:
|
||||
|
||||
```cpp
|
||||
MATCHER_P(NestedPropertyMatches, matcher, "") {
|
||||
return ExplainMatchResult(matcher, arg.nested().property(), result_listener);
|
||||
}
|
||||
```
|
@@ -1,589 +0,0 @@
|
||||
# Mocking Reference
|
||||
|
||||
This page lists the facilities provided by GoogleTest for creating and working
|
||||
with mock objects. To use them, include the header
|
||||
`gmock/gmock.h`.
|
||||
|
||||
## Macros {#macros}
|
||||
|
||||
GoogleTest defines the following macros for working with mocks.
|
||||
|
||||
### MOCK_METHOD {#MOCK_METHOD}
|
||||
|
||||
`MOCK_METHOD(`*`return_type`*`,`*`method_name`*`, (`*`args...`*`));` \
|
||||
`MOCK_METHOD(`*`return_type`*`,`*`method_name`*`, (`*`args...`*`),
|
||||
(`*`specs...`*`));`
|
||||
|
||||
Defines a mock method *`method_name`* with arguments `(`*`args...`*`)` and
|
||||
return type *`return_type`* within a mock class.
|
||||
|
||||
The parameters of `MOCK_METHOD` mirror the method declaration. The optional
|
||||
fourth parameter *`specs...`* is a comma-separated list of qualifiers. The
|
||||
following qualifiers are accepted:
|
||||
|
||||
| Qualifier | Meaning |
|
||||
| -------------------------- | -------------------------------------------- |
|
||||
| `const` | Makes the mocked method a `const` method. Required if overriding a `const` method. |
|
||||
| `override` | Marks the method with `override`. Recommended if overriding a `virtual` method. |
|
||||
| `noexcept` | Marks the method with `noexcept`. Required if overriding a `noexcept` method. |
|
||||
| `Calltype(`*`calltype`*`)` | Sets the call type for the method, for example `Calltype(STDMETHODCALLTYPE)`. Useful on Windows. |
|
||||
| `ref(`*`qualifier`*`)` | Marks the method with the given reference qualifier, for example `ref(&)` or `ref(&&)`. Required if overriding a method that has a reference qualifier. |
|
||||
|
||||
Note that commas in arguments prevent `MOCK_METHOD` from parsing the arguments
|
||||
correctly if they are not appropriately surrounded by parentheses. See the
|
||||
following example:
|
||||
|
||||
```cpp
|
||||
class MyMock {
|
||||
public:
|
||||
// The following 2 lines will not compile due to commas in the arguments:
|
||||
MOCK_METHOD(std::pair<bool, int>, GetPair, ()); // Error!
|
||||
MOCK_METHOD(bool, CheckMap, (std::map<int, double>, bool)); // Error!
|
||||
|
||||
// One solution - wrap arguments that contain commas in parentheses:
|
||||
MOCK_METHOD((std::pair<bool, int>), GetPair, ());
|
||||
MOCK_METHOD(bool, CheckMap, ((std::map<int, double>), bool));
|
||||
|
||||
// Another solution - use type aliases:
|
||||
using BoolAndInt = std::pair<bool, int>;
|
||||
MOCK_METHOD(BoolAndInt, GetPair, ());
|
||||
using MapIntDouble = std::map<int, double>;
|
||||
MOCK_METHOD(bool, CheckMap, (MapIntDouble, bool));
|
||||
};
|
||||
```
|
||||
|
||||
`MOCK_METHOD` must be used in the `public:` section of a mock class definition,
|
||||
regardless of whether the method being mocked is `public`, `protected`, or
|
||||
`private` in the base class.
|
||||
|
||||
### EXPECT_CALL {#EXPECT_CALL}
|
||||
|
||||
`EXPECT_CALL(`*`mock_object`*`,`*`method_name`*`(`*`matchers...`*`))`
|
||||
|
||||
Creates an [expectation](../gmock_for_dummies.md#setting-expectations) that the
|
||||
method *`method_name`* of the object *`mock_object`* is called with arguments
|
||||
that match the given matchers *`matchers...`*. `EXPECT_CALL` must precede any
|
||||
code that exercises the mock object.
|
||||
|
||||
The parameter *`matchers...`* is a comma-separated list of
|
||||
[matchers](../gmock_for_dummies.md#matchers-what-arguments-do-we-expect) that
|
||||
correspond to each argument of the method *`method_name`*. The expectation will
|
||||
apply only to calls of *`method_name`* whose arguments match all of the
|
||||
matchers. If `(`*`matchers...`*`)` is omitted, the expectation behaves as if
|
||||
each argument's matcher were a [wildcard matcher (`_`)](matchers.md#wildcard).
|
||||
See the [Matchers Reference](matchers.md) for a list of all built-in matchers.
|
||||
|
||||
The following chainable clauses can be used to modify the expectation, and they
|
||||
must be used in the following order:
|
||||
|
||||
```cpp
|
||||
EXPECT_CALL(mock_object, method_name(matchers...))
|
||||
.With(multi_argument_matcher) // Can be used at most once
|
||||
.Times(cardinality) // Can be used at most once
|
||||
.InSequence(sequences...) // Can be used any number of times
|
||||
.After(expectations...) // Can be used any number of times
|
||||
.WillOnce(action) // Can be used any number of times
|
||||
.WillRepeatedly(action) // Can be used at most once
|
||||
.RetiresOnSaturation(); // Can be used at most once
|
||||
```
|
||||
|
||||
See details for each modifier clause below.
|
||||
|
||||
#### With {#EXPECT_CALL.With}
|
||||
|
||||
`.With(`*`multi_argument_matcher`*`)`
|
||||
|
||||
Restricts the expectation to apply only to mock function calls whose arguments
|
||||
as a whole match the multi-argument matcher *`multi_argument_matcher`*.
|
||||
|
||||
GoogleTest passes all of the arguments as one tuple into the matcher. The
|
||||
parameter *`multi_argument_matcher`* must thus be a matcher of type
|
||||
`Matcher<std::tuple<A1, ..., An>>`, where `A1, ..., An` are the types of the
|
||||
function arguments.
|
||||
|
||||
For example, the following code sets the expectation that
|
||||
`my_mock.SetPosition()` is called with any two arguments, the first argument
|
||||
being less than the second:
|
||||
|
||||
```cpp
|
||||
using ::testing::_;
|
||||
using ::testing::Lt;
|
||||
...
|
||||
EXPECT_CALL(my_mock, SetPosition(_, _))
|
||||
.With(Lt());
|
||||
```
|
||||
|
||||
GoogleTest provides some built-in matchers for 2-tuples, including the `Lt()`
|
||||
matcher above. See [Multi-argument Matchers](matchers.md#MultiArgMatchers).
|
||||
|
||||
The `With` clause can be used at most once on an expectation and must be the
|
||||
first clause.
|
||||
|
||||
#### Times {#EXPECT_CALL.Times}
|
||||
|
||||
`.Times(`*`cardinality`*`)`
|
||||
|
||||
Specifies how many times the mock function call is expected.
|
||||
|
||||
The parameter *`cardinality`* represents the number of expected calls and can be
|
||||
one of the following, all defined in the `::testing` namespace:
|
||||
|
||||
| Cardinality | Meaning |
|
||||
| ------------------- | --------------------------------------------------- |
|
||||
| `AnyNumber()` | The function can be called any number of times. |
|
||||
| `AtLeast(n)` | The function call is expected at least *n* times. |
|
||||
| `AtMost(n)` | The function call is expected at most *n* times. |
|
||||
| `Between(m, n)` | The function call is expected between *m* and *n* times, inclusive. |
|
||||
| `Exactly(n)` or `n` | The function call is expected exactly *n* times. If *n* is 0, the call should never happen. |
|
||||
|
||||
If the `Times` clause is omitted, GoogleTest infers the cardinality as follows:
|
||||
|
||||
* If neither [`WillOnce`](#EXPECT_CALL.WillOnce) nor
|
||||
[`WillRepeatedly`](#EXPECT_CALL.WillRepeatedly) are specified, the inferred
|
||||
cardinality is `Times(1)`.
|
||||
* If there are *n* `WillOnce` clauses and no `WillRepeatedly` clause, where
|
||||
*n* >= 1, the inferred cardinality is `Times(n)`.
|
||||
* If there are *n* `WillOnce` clauses and one `WillRepeatedly` clause, where
|
||||
*n* >= 0, the inferred cardinality is `Times(AtLeast(n))`.
|
||||
|
||||
The `Times` clause can be used at most once on an expectation.
|
||||
|
||||
#### InSequence {#EXPECT_CALL.InSequence}
|
||||
|
||||
`.InSequence(`*`sequences...`*`)`
|
||||
|
||||
Specifies that the mock function call is expected in a certain sequence.
|
||||
|
||||
The parameter *`sequences...`* is any number of [`Sequence`](#Sequence) objects.
|
||||
Expected calls assigned to the same sequence are expected to occur in the order
|
||||
the expectations are declared.
|
||||
|
||||
For example, the following code sets the expectation that the `Reset()` method
|
||||
of `my_mock` is called before both `GetSize()` and `Describe()`, and `GetSize()`
|
||||
and `Describe()` can occur in any order relative to each other:
|
||||
|
||||
```cpp
|
||||
using ::testing::Sequence;
|
||||
Sequence s1, s2;
|
||||
...
|
||||
EXPECT_CALL(my_mock, Reset())
|
||||
.InSequence(s1, s2);
|
||||
EXPECT_CALL(my_mock, GetSize())
|
||||
.InSequence(s1);
|
||||
EXPECT_CALL(my_mock, Describe())
|
||||
.InSequence(s2);
|
||||
```
|
||||
|
||||
The `InSequence` clause can be used any number of times on an expectation.
|
||||
|
||||
See also the [`InSequence` class](#InSequence).
|
||||
|
||||
#### After {#EXPECT_CALL.After}
|
||||
|
||||
`.After(`*`expectations...`*`)`
|
||||
|
||||
Specifies that the mock function call is expected to occur after one or more
|
||||
other calls.
|
||||
|
||||
The parameter *`expectations...`* can be up to five
|
||||
[`Expectation`](#Expectation) or [`ExpectationSet`](#ExpectationSet) objects.
|
||||
The mock function call is expected to occur after all of the given expectations.
|
||||
|
||||
For example, the following code sets the expectation that the `Describe()`
|
||||
method of `my_mock` is called only after both `InitX()` and `InitY()` have been
|
||||
called.
|
||||
|
||||
```cpp
|
||||
using ::testing::Expectation;
|
||||
...
|
||||
Expectation init_x = EXPECT_CALL(my_mock, InitX());
|
||||
Expectation init_y = EXPECT_CALL(my_mock, InitY());
|
||||
EXPECT_CALL(my_mock, Describe())
|
||||
.After(init_x, init_y);
|
||||
```
|
||||
|
||||
The `ExpectationSet` object is helpful when the number of prerequisites for an
|
||||
expectation is large or variable, for example:
|
||||
|
||||
```cpp
|
||||
using ::testing::ExpectationSet;
|
||||
...
|
||||
ExpectationSet all_inits;
|
||||
// Collect all expectations of InitElement() calls
|
||||
for (int i = 0; i < element_count; i++) {
|
||||
all_inits += EXPECT_CALL(my_mock, InitElement(i));
|
||||
}
|
||||
EXPECT_CALL(my_mock, Describe())
|
||||
.After(all_inits); // Expect Describe() call after all InitElement() calls
|
||||
```
|
||||
|
||||
The `After` clause can be used any number of times on an expectation.
|
||||
|
||||
#### WillOnce {#EXPECT_CALL.WillOnce}
|
||||
|
||||
`.WillOnce(`*`action`*`)`
|
||||
|
||||
Specifies the mock function's actual behavior when invoked, for a single
|
||||
matching function call.
|
||||
|
||||
The parameter *`action`* represents the
|
||||
[action](../gmock_for_dummies.md#actions-what-should-it-do) that the function
|
||||
call will perform. See the [Actions Reference](actions.md) for a list of
|
||||
built-in actions.
|
||||
|
||||
The use of `WillOnce` implicitly sets a cardinality on the expectation when
|
||||
`Times` is not specified. See [`Times`](#EXPECT_CALL.Times).
|
||||
|
||||
Each matching function call will perform the next action in the order declared.
|
||||
For example, the following code specifies that `my_mock.GetNumber()` is expected
|
||||
to be called exactly 3 times and will return `1`, `2`, and `3` respectively on
|
||||
the first, second, and third calls:
|
||||
|
||||
```cpp
|
||||
using ::testing::Return;
|
||||
...
|
||||
EXPECT_CALL(my_mock, GetNumber())
|
||||
.WillOnce(Return(1))
|
||||
.WillOnce(Return(2))
|
||||
.WillOnce(Return(3));
|
||||
```
|
||||
|
||||
The `WillOnce` clause can be used any number of times on an expectation. Unlike
|
||||
`WillRepeatedly`, the action fed to each `WillOnce` call will be called at most
|
||||
once, so may be a move-only type and/or have an `&&`-qualified call operator.
|
||||
|
||||
#### WillRepeatedly {#EXPECT_CALL.WillRepeatedly}
|
||||
|
||||
`.WillRepeatedly(`*`action`*`)`
|
||||
|
||||
Specifies the mock function's actual behavior when invoked, for all subsequent
|
||||
matching function calls. Takes effect after the actions specified in the
|
||||
[`WillOnce`](#EXPECT_CALL.WillOnce) clauses, if any, have been performed.
|
||||
|
||||
The parameter *`action`* represents the
|
||||
[action](../gmock_for_dummies.md#actions-what-should-it-do) that the function
|
||||
call will perform. See the [Actions Reference](actions.md) for a list of
|
||||
built-in actions.
|
||||
|
||||
The use of `WillRepeatedly` implicitly sets a cardinality on the expectation
|
||||
when `Times` is not specified. See [`Times`](#EXPECT_CALL.Times).
|
||||
|
||||
If any `WillOnce` clauses have been specified, matching function calls will
|
||||
perform those actions before the action specified by `WillRepeatedly`. See the
|
||||
following example:
|
||||
|
||||
```cpp
|
||||
using ::testing::Return;
|
||||
...
|
||||
EXPECT_CALL(my_mock, GetName())
|
||||
.WillRepeatedly(Return("John Doe")); // Return "John Doe" on all calls
|
||||
|
||||
EXPECT_CALL(my_mock, GetNumber())
|
||||
.WillOnce(Return(42)) // Return 42 on the first call
|
||||
.WillRepeatedly(Return(7)); // Return 7 on all subsequent calls
|
||||
```
|
||||
|
||||
The `WillRepeatedly` clause can be used at most once on an expectation.
|
||||
|
||||
#### RetiresOnSaturation {#EXPECT_CALL.RetiresOnSaturation}
|
||||
|
||||
`.RetiresOnSaturation()`
|
||||
|
||||
Indicates that the expectation will no longer be active after the expected
|
||||
number of matching function calls has been reached.
|
||||
|
||||
The `RetiresOnSaturation` clause is only meaningful for expectations with an
|
||||
upper-bounded cardinality. The expectation will *retire* (no longer match any
|
||||
function calls) after it has been *saturated* (the upper bound has been
|
||||
reached). See the following example:
|
||||
|
||||
```cpp
|
||||
using ::testing::_;
|
||||
using ::testing::AnyNumber;
|
||||
...
|
||||
EXPECT_CALL(my_mock, SetNumber(_)) // Expectation 1
|
||||
.Times(AnyNumber());
|
||||
EXPECT_CALL(my_mock, SetNumber(7)) // Expectation 2
|
||||
.Times(2)
|
||||
.RetiresOnSaturation();
|
||||
```
|
||||
|
||||
In the above example, the first two calls to `my_mock.SetNumber(7)` match
|
||||
expectation 2, which then becomes inactive and no longer matches any calls. A
|
||||
third call to `my_mock.SetNumber(7)` would then match expectation 1. Without
|
||||
`RetiresOnSaturation()` on expectation 2, a third call to `my_mock.SetNumber(7)`
|
||||
would match expectation 2 again, producing a failure since the limit of 2 calls
|
||||
was exceeded.
|
||||
|
||||
The `RetiresOnSaturation` clause can be used at most once on an expectation and
|
||||
must be the last clause.
|
||||
|
||||
### ON_CALL {#ON_CALL}
|
||||
|
||||
`ON_CALL(`*`mock_object`*`,`*`method_name`*`(`*`matchers...`*`))`
|
||||
|
||||
Defines what happens when the method *`method_name`* of the object
|
||||
*`mock_object`* is called with arguments that match the given matchers
|
||||
*`matchers...`*. Requires a modifier clause to specify the method's behavior.
|
||||
*Does not* set any expectations that the method will be called.
|
||||
|
||||
The parameter *`matchers...`* is a comma-separated list of
|
||||
[matchers](../gmock_for_dummies.md#matchers-what-arguments-do-we-expect) that
|
||||
correspond to each argument of the method *`method_name`*. The `ON_CALL`
|
||||
specification will apply only to calls of *`method_name`* whose arguments match
|
||||
all of the matchers. If `(`*`matchers...`*`)` is omitted, the behavior is as if
|
||||
each argument's matcher were a [wildcard matcher (`_`)](matchers.md#wildcard).
|
||||
See the [Matchers Reference](matchers.md) for a list of all built-in matchers.
|
||||
|
||||
The following chainable clauses can be used to set the method's behavior, and
|
||||
they must be used in the following order:
|
||||
|
||||
```cpp
|
||||
ON_CALL(mock_object, method_name(matchers...))
|
||||
.With(multi_argument_matcher) // Can be used at most once
|
||||
.WillByDefault(action); // Required
|
||||
```
|
||||
|
||||
See details for each modifier clause below.
|
||||
|
||||
#### With {#ON_CALL.With}
|
||||
|
||||
`.With(`*`multi_argument_matcher`*`)`
|
||||
|
||||
Restricts the specification to only mock function calls whose arguments as a
|
||||
whole match the multi-argument matcher *`multi_argument_matcher`*.
|
||||
|
||||
GoogleTest passes all of the arguments as one tuple into the matcher. The
|
||||
parameter *`multi_argument_matcher`* must thus be a matcher of type
|
||||
`Matcher<std::tuple<A1, ..., An>>`, where `A1, ..., An` are the types of the
|
||||
function arguments.
|
||||
|
||||
For example, the following code sets the default behavior when
|
||||
`my_mock.SetPosition()` is called with any two arguments, the first argument
|
||||
being less than the second:
|
||||
|
||||
```cpp
|
||||
using ::testing::_;
|
||||
using ::testing::Lt;
|
||||
using ::testing::Return;
|
||||
...
|
||||
ON_CALL(my_mock, SetPosition(_, _))
|
||||
.With(Lt())
|
||||
.WillByDefault(Return(true));
|
||||
```
|
||||
|
||||
GoogleTest provides some built-in matchers for 2-tuples, including the `Lt()`
|
||||
matcher above. See [Multi-argument Matchers](matchers.md#MultiArgMatchers).
|
||||
|
||||
The `With` clause can be used at most once with each `ON_CALL` statement.
|
||||
|
||||
#### WillByDefault {#ON_CALL.WillByDefault}
|
||||
|
||||
`.WillByDefault(`*`action`*`)`
|
||||
|
||||
Specifies the default behavior of a matching mock function call.
|
||||
|
||||
The parameter *`action`* represents the
|
||||
[action](../gmock_for_dummies.md#actions-what-should-it-do) that the function
|
||||
call will perform. See the [Actions Reference](actions.md) for a list of
|
||||
built-in actions.
|
||||
|
||||
For example, the following code specifies that by default, a call to
|
||||
`my_mock.Greet()` will return `"hello"`:
|
||||
|
||||
```cpp
|
||||
using ::testing::Return;
|
||||
...
|
||||
ON_CALL(my_mock, Greet())
|
||||
.WillByDefault(Return("hello"));
|
||||
```
|
||||
|
||||
The action specified by `WillByDefault` is superseded by the actions specified
|
||||
on a matching `EXPECT_CALL` statement, if any. See the
|
||||
[`WillOnce`](#EXPECT_CALL.WillOnce) and
|
||||
[`WillRepeatedly`](#EXPECT_CALL.WillRepeatedly) clauses of `EXPECT_CALL`.
|
||||
|
||||
The `WillByDefault` clause must be used exactly once with each `ON_CALL`
|
||||
statement.
|
||||
|
||||
## Classes {#classes}
|
||||
|
||||
GoogleTest defines the following classes for working with mocks.
|
||||
|
||||
### DefaultValue {#DefaultValue}
|
||||
|
||||
`::testing::DefaultValue<T>`
|
||||
|
||||
Allows a user to specify the default value for a type `T` that is both copyable
|
||||
and publicly destructible (i.e. anything that can be used as a function return
|
||||
type). For mock functions with a return type of `T`, this default value is
|
||||
returned from function calls that do not specify an action.
|
||||
|
||||
Provides the static methods `Set()`, `SetFactory()`, and `Clear()` to manage the
|
||||
default value:
|
||||
|
||||
```cpp
|
||||
// Sets the default value to be returned. T must be copy constructible.
|
||||
DefaultValue<T>::Set(value);
|
||||
|
||||
// Sets a factory. Will be invoked on demand. T must be move constructible.
|
||||
T MakeT();
|
||||
DefaultValue<T>::SetFactory(&MakeT);
|
||||
|
||||
// Unsets the default value.
|
||||
DefaultValue<T>::Clear();
|
||||
```
|
||||
|
||||
### NiceMock {#NiceMock}
|
||||
|
||||
`::testing::NiceMock<T>`
|
||||
|
||||
Represents a mock object that suppresses warnings on
|
||||
[uninteresting calls](../gmock_cook_book.md#uninteresting-vs-unexpected). The
|
||||
template parameter `T` is any mock class, except for another `NiceMock`,
|
||||
`NaggyMock`, or `StrictMock`.
|
||||
|
||||
Usage of `NiceMock<T>` is analogous to usage of `T`. `NiceMock<T>` is a subclass
|
||||
of `T`, so it can be used wherever an object of type `T` is accepted. In
|
||||
addition, `NiceMock<T>` can be constructed with any arguments that a constructor
|
||||
of `T` accepts.
|
||||
|
||||
For example, the following code suppresses warnings on the mock `my_mock` of
|
||||
type `MockClass` if a method other than `DoSomething()` is called:
|
||||
|
||||
```cpp
|
||||
using ::testing::NiceMock;
|
||||
...
|
||||
NiceMock<MockClass> my_mock("some", "args");
|
||||
EXPECT_CALL(my_mock, DoSomething());
|
||||
... code that uses my_mock ...
|
||||
```
|
||||
|
||||
`NiceMock<T>` only works for mock methods defined using the `MOCK_METHOD` macro
|
||||
directly in the definition of class `T`. If a mock method is defined in a base
|
||||
class of `T`, a warning might still be generated.
|
||||
|
||||
`NiceMock<T>` might not work correctly if the destructor of `T` is not virtual.
|
||||
|
||||
### NaggyMock {#NaggyMock}
|
||||
|
||||
`::testing::NaggyMock<T>`
|
||||
|
||||
Represents a mock object that generates warnings on
|
||||
[uninteresting calls](../gmock_cook_book.md#uninteresting-vs-unexpected). The
|
||||
template parameter `T` is any mock class, except for another `NiceMock`,
|
||||
`NaggyMock`, or `StrictMock`.
|
||||
|
||||
Usage of `NaggyMock<T>` is analogous to usage of `T`. `NaggyMock<T>` is a
|
||||
subclass of `T`, so it can be used wherever an object of type `T` is accepted.
|
||||
In addition, `NaggyMock<T>` can be constructed with any arguments that a
|
||||
constructor of `T` accepts.
|
||||
|
||||
For example, the following code generates warnings on the mock `my_mock` of type
|
||||
`MockClass` if a method other than `DoSomething()` is called:
|
||||
|
||||
```cpp
|
||||
using ::testing::NaggyMock;
|
||||
...
|
||||
NaggyMock<MockClass> my_mock("some", "args");
|
||||
EXPECT_CALL(my_mock, DoSomething());
|
||||
... code that uses my_mock ...
|
||||
```
|
||||
|
||||
Mock objects of type `T` by default behave the same way as `NaggyMock<T>`.
|
||||
|
||||
### StrictMock {#StrictMock}
|
||||
|
||||
`::testing::StrictMock<T>`
|
||||
|
||||
Represents a mock object that generates test failures on
|
||||
[uninteresting calls](../gmock_cook_book.md#uninteresting-vs-unexpected). The
|
||||
template parameter `T` is any mock class, except for another `NiceMock`,
|
||||
`NaggyMock`, or `StrictMock`.
|
||||
|
||||
Usage of `StrictMock<T>` is analogous to usage of `T`. `StrictMock<T>` is a
|
||||
subclass of `T`, so it can be used wherever an object of type `T` is accepted.
|
||||
In addition, `StrictMock<T>` can be constructed with any arguments that a
|
||||
constructor of `T` accepts.
|
||||
|
||||
For example, the following code generates a test failure on the mock `my_mock`
|
||||
of type `MockClass` if a method other than `DoSomething()` is called:
|
||||
|
||||
```cpp
|
||||
using ::testing::StrictMock;
|
||||
...
|
||||
StrictMock<MockClass> my_mock("some", "args");
|
||||
EXPECT_CALL(my_mock, DoSomething());
|
||||
... code that uses my_mock ...
|
||||
```
|
||||
|
||||
`StrictMock<T>` only works for mock methods defined using the `MOCK_METHOD`
|
||||
macro directly in the definition of class `T`. If a mock method is defined in a
|
||||
base class of `T`, a failure might not be generated.
|
||||
|
||||
`StrictMock<T>` might not work correctly if the destructor of `T` is not
|
||||
virtual.
|
||||
|
||||
### Sequence {#Sequence}
|
||||
|
||||
`::testing::Sequence`
|
||||
|
||||
Represents a chronological sequence of expectations. See the
|
||||
[`InSequence`](#EXPECT_CALL.InSequence) clause of `EXPECT_CALL` for usage.
|
||||
|
||||
### InSequence {#InSequence}
|
||||
|
||||
`::testing::InSequence`
|
||||
|
||||
An object of this type causes all expectations encountered in its scope to be
|
||||
put in an anonymous sequence.
|
||||
|
||||
This allows more convenient expression of multiple expectations in a single
|
||||
sequence:
|
||||
|
||||
```cpp
|
||||
using ::testing::InSequence;
|
||||
{
|
||||
InSequence seq;
|
||||
|
||||
// The following are expected to occur in the order declared.
|
||||
EXPECT_CALL(...);
|
||||
EXPECT_CALL(...);
|
||||
...
|
||||
EXPECT_CALL(...);
|
||||
}
|
||||
```
|
||||
|
||||
The name of the `InSequence` object does not matter.
|
||||
|
||||
### Expectation {#Expectation}
|
||||
|
||||
`::testing::Expectation`
|
||||
|
||||
Represents a mock function call expectation as created by
|
||||
[`EXPECT_CALL`](#EXPECT_CALL):
|
||||
|
||||
```cpp
|
||||
using ::testing::Expectation;
|
||||
Expectation my_expectation = EXPECT_CALL(...);
|
||||
```
|
||||
|
||||
Useful for specifying sequences of expectations; see the
|
||||
[`After`](#EXPECT_CALL.After) clause of `EXPECT_CALL`.
|
||||
|
||||
### ExpectationSet {#ExpectationSet}
|
||||
|
||||
`::testing::ExpectationSet`
|
||||
|
||||
Represents a set of mock function call expectations.
|
||||
|
||||
Use the `+=` operator to add [`Expectation`](#Expectation) objects to the set:
|
||||
|
||||
```cpp
|
||||
using ::testing::ExpectationSet;
|
||||
ExpectationSet my_expectations;
|
||||
my_expectations += EXPECT_CALL(...);
|
||||
```
|
||||
|
||||
Useful for specifying sequences of expectations; see the
|
||||
[`After`](#EXPECT_CALL.After) clause of `EXPECT_CALL`.
|
File diff suppressed because it is too large
Load Diff
@@ -1,40 +0,0 @@
|
||||
# Googletest Mocking (gMock) Framework
|
||||
|
||||
### Overview
|
||||
|
||||
Google's framework for writing and using C++ mock classes. It can help you
|
||||
derive better designs of your system and write better tests.
|
||||
|
||||
It is inspired by:
|
||||
|
||||
* [jMock](http://www.jmock.org/)
|
||||
* [EasyMock](http://www.easymock.org/)
|
||||
* [Hamcrest](http://code.google.com/p/hamcrest/)
|
||||
|
||||
It is 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.
|
||||
- Is easy to learn and use.
|
||||
|
||||
Details and examples can be found here:
|
||||
|
||||
* [gMock for Dummies](https://google.github.io/googletest/gmock_for_dummies.html)
|
||||
* [Legacy gMock FAQ](https://google.github.io/googletest/gmock_faq.html)
|
||||
* [gMock Cookbook](https://google.github.io/googletest/gmock_cook_book.html)
|
||||
* [gMock Cheat Sheet](https://google.github.io/googletest/gmock_cheat_sheet.html)
|
||||
|
||||
GoogleMock is a part of
|
||||
[GoogleTest C++ testing framework](http://github.com/google/googletest/) and a
|
||||
subject to the same requirements.
|
@@ -1,10 +0,0 @@
|
||||
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
|
||||
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
|
||||
|
||||
Name: gmock
|
||||
Description: GoogleMock (without main() function)
|
||||
Version: @PROJECT_VERSION@
|
||||
URL: https://github.com/google/googletest
|
||||
Requires: gtest = @PROJECT_VERSION@
|
||||
Libs: -L${libdir} -lgmock @CMAKE_THREAD_LIBS_INIT@
|
||||
Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@
|
@@ -1,10 +0,0 @@
|
||||
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
|
||||
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
|
||||
|
||||
Name: gmock_main
|
||||
Description: GoogleMock (with main() function)
|
||||
Version: @PROJECT_VERSION@
|
||||
URL: https://github.com/google/googletest
|
||||
Requires: gmock = @PROJECT_VERSION@
|
||||
Libs: -L${libdir} -lgmock_main @CMAKE_THREAD_LIBS_INIT@
|
||||
Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@
|
@@ -1,4 +0,0 @@
|
||||
# Content Moved
|
||||
|
||||
We are working on updates to the GoogleTest documentation, which has moved to
|
||||
the top-level [docs](../../docs) directory.
|
File diff suppressed because it is too large
Load Diff
@@ -1,517 +0,0 @@
|
||||
// Copyright 2007, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Google Mock - a framework for writing C++ mock classes.
|
||||
//
|
||||
// This file implements MOCK_METHOD.
|
||||
|
||||
// IWYU pragma: private, include "gmock/gmock.h"
|
||||
// IWYU pragma: friend gmock/.*
|
||||
|
||||
#ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_FUNCTION_MOCKER_H_
|
||||
#define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_FUNCTION_MOCKER_H_
|
||||
|
||||
#include <type_traits> // IWYU pragma: keep
|
||||
#include <utility> // IWYU pragma: keep
|
||||
|
||||
#include "gmock/gmock-spec-builders.h"
|
||||
#include "gmock/internal/gmock-internal-utils.h"
|
||||
#include "gmock/internal/gmock-pp.h"
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
template <typename T>
|
||||
using identity_t = T;
|
||||
|
||||
template <typename Pattern>
|
||||
struct ThisRefAdjuster {
|
||||
template <typename T>
|
||||
using AdjustT = typename std::conditional<
|
||||
std::is_const<typename std::remove_reference<Pattern>::type>::value,
|
||||
typename std::conditional<std::is_lvalue_reference<Pattern>::value,
|
||||
const T&, const T&&>::type,
|
||||
typename std::conditional<std::is_lvalue_reference<Pattern>::value, T&,
|
||||
T&&>::type>::type;
|
||||
|
||||
template <typename MockType>
|
||||
static AdjustT<MockType> Adjust(const MockType& mock) {
|
||||
return static_cast<AdjustT<MockType>>(const_cast<MockType&>(mock));
|
||||
}
|
||||
};
|
||||
|
||||
constexpr bool PrefixOf(const char* a, const char* b) {
|
||||
return *a == 0 || (*a == *b && internal::PrefixOf(a + 1, b + 1));
|
||||
}
|
||||
|
||||
template <int N, int M>
|
||||
constexpr bool StartsWith(const char (&prefix)[N], const char (&str)[M]) {
|
||||
return N <= M && internal::PrefixOf(prefix, str);
|
||||
}
|
||||
|
||||
template <int N, int M>
|
||||
constexpr bool EndsWith(const char (&suffix)[N], const char (&str)[M]) {
|
||||
return N <= M && internal::PrefixOf(suffix, str + M - N);
|
||||
}
|
||||
|
||||
template <int N, int M>
|
||||
constexpr bool Equals(const char (&a)[N], const char (&b)[M]) {
|
||||
return N == M && internal::PrefixOf(a, b);
|
||||
}
|
||||
|
||||
template <int N>
|
||||
constexpr bool ValidateSpec(const char (&spec)[N]) {
|
||||
return internal::Equals("const", spec) ||
|
||||
internal::Equals("override", spec) ||
|
||||
internal::Equals("final", spec) ||
|
||||
internal::Equals("noexcept", spec) ||
|
||||
(internal::StartsWith("noexcept(", spec) &&
|
||||
internal::EndsWith(")", spec)) ||
|
||||
internal::Equals("ref(&)", spec) ||
|
||||
internal::Equals("ref(&&)", spec) ||
|
||||
(internal::StartsWith("Calltype(", spec) &&
|
||||
internal::EndsWith(")", spec));
|
||||
}
|
||||
|
||||
} // 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;
|
||||
} // namespace testing
|
||||
|
||||
#define MOCK_METHOD(...) \
|
||||
GMOCK_INTERNAL_WARNING_PUSH() \
|
||||
GMOCK_INTERNAL_WARNING_CLANG(ignored, "-Wunused-member-function") \
|
||||
GMOCK_PP_VARIADIC_CALL(GMOCK_INTERNAL_MOCK_METHOD_ARG_, __VA_ARGS__) \
|
||||
GMOCK_INTERNAL_WARNING_POP()
|
||||
|
||||
#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_GET_NOEXCEPT_SPEC(_Spec), \
|
||||
GMOCK_INTERNAL_GET_CALLTYPE_SPEC(_Spec), \
|
||||
GMOCK_INTERNAL_GET_REF_SPEC(_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 unprotected 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, _NoexceptSpec, \
|
||||
_CallType, _RefSpec, _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, ) _RefSpec _NoexceptSpec \
|
||||
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, ) _RefSpec { \
|
||||
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 _RefSpec _NoexceptSpec { \
|
||||
return ::testing::internal::ThisRefAdjuster<GMOCK_PP_IF( \
|
||||
_Constness, const, ) int _RefSpec>::Adjust(*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__
|
||||
|
||||
// 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_GET_NOEXCEPT_SPEC(_Tuple) \
|
||||
GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_NOEXCEPT_SPEC_IF_NOEXCEPT, ~, _Tuple)
|
||||
|
||||
#define GMOCK_INTERNAL_NOEXCEPT_SPEC_IF_NOEXCEPT(_i, _, _elem) \
|
||||
GMOCK_PP_IF( \
|
||||
GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem)), \
|
||||
_elem, )
|
||||
|
||||
#define GMOCK_INTERNAL_GET_CALLTYPE_SPEC(_Tuple) \
|
||||
GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_CALLTYPE_SPEC_IF_CALLTYPE, ~, _Tuple)
|
||||
|
||||
#define GMOCK_INTERNAL_CALLTYPE_SPEC_IF_CALLTYPE(_i, _, _elem) \
|
||||
GMOCK_PP_IF( \
|
||||
GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_CALLTYPE(_i, _, _elem)), \
|
||||
GMOCK_PP_CAT(GMOCK_INTERNAL_UNPACK_, _elem), )
|
||||
|
||||
#define GMOCK_INTERNAL_GET_REF_SPEC(_Tuple) \
|
||||
GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_REF_SPEC_IF_REF, ~, _Tuple)
|
||||
|
||||
#define GMOCK_INTERNAL_REF_SPEC_IF_REF(_i, _, _elem) \
|
||||
GMOCK_PP_IF(GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_REF(_i, _, _elem)), \
|
||||
GMOCK_PP_CAT(GMOCK_INTERNAL_UNPACK_, _elem), )
|
||||
|
||||
#ifdef GMOCK_INTERNAL_STRICT_SPEC_ASSERT
|
||||
#define GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT(_i, _, _elem) \
|
||||
static_assert( \
|
||||
::testing::internal::ValidateSpec(GMOCK_PP_STRINGIZE(_elem)), \
|
||||
"Token \'" GMOCK_PP_STRINGIZE( \
|
||||
_elem) "\' cannot be recognized as a valid specification " \
|
||||
"modifier. Is a ',' missing?");
|
||||
#else
|
||||
#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_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_REF(_i, _, _elem)) + \
|
||||
GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_CALLTYPE(_i, _, _elem))) == 1, \
|
||||
GMOCK_PP_STRINGIZE( \
|
||||
_elem) " cannot be recognized as a valid specification modifier.");
|
||||
#endif // GMOCK_INTERNAL_STRICT_SPEC_ASSERT
|
||||
|
||||
// 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 ,
|
||||
|
||||
#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_DETECT_REF(_i, _, _elem) \
|
||||
GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_REF_I_, _elem)
|
||||
|
||||
#define GMOCK_INTERNAL_DETECT_REF_I_ref ,
|
||||
|
||||
#define GMOCK_INTERNAL_UNPACK_ref(x) x
|
||||
|
||||
#define GMOCK_INTERNAL_DETECT_CALLTYPE(_i, _, _elem) \
|
||||
GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_CALLTYPE_I_, _elem)
|
||||
|
||||
#define GMOCK_INTERNAL_DETECT_CALLTYPE_I_Calltype ,
|
||||
|
||||
#define GMOCK_INTERNAL_UNPACK_Calltype(...) __VA_ARGS__
|
||||
|
||||
// Note: The use of `identity_t` here allows _Ret to represent return types that
|
||||
// would normally need to be specified in a different way. For example, a method
|
||||
// returning a function pointer must be written as
|
||||
//
|
||||
// fn_ptr_return_t (*method(method_args_t...))(fn_ptr_args_t...)
|
||||
//
|
||||
// But we only support placing the return type at the beginning. To handle this,
|
||||
// we wrap all calls in identity_t, so that a declaration will be expanded to
|
||||
//
|
||||
// identity_t<fn_ptr_return_t (*)(fn_ptr_args_t...)> method(method_args_t...)
|
||||
//
|
||||
// This allows us to work around the syntactic oddities of function/method
|
||||
// types.
|
||||
#define GMOCK_INTERNAL_SIGNATURE(_Ret, _Args) \
|
||||
::testing::internal::identity_t<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(_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( \
|
||||
_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(_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(_i, GMOCK_PP_REMOVE_PARENS(_Signature))>()
|
||||
|
||||
#define GMOCK_INTERNAL_ARG_O(_i, ...) \
|
||||
typename ::testing::internal::Function<__VA_ARGS__>::template Arg<_i>::type
|
||||
|
||||
#define GMOCK_INTERNAL_MATCHER_O(_i, ...) \
|
||||
const ::testing::Matcher<typename ::testing::internal::Function< \
|
||||
__VA_ARGS__>::template Arg<_i>::type>&
|
||||
|
||||
#define MOCK_METHOD0(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 0, __VA_ARGS__)
|
||||
#define MOCK_METHOD1(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 1, __VA_ARGS__)
|
||||
#define MOCK_METHOD2(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 2, __VA_ARGS__)
|
||||
#define MOCK_METHOD3(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 3, __VA_ARGS__)
|
||||
#define MOCK_METHOD4(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 4, __VA_ARGS__)
|
||||
#define MOCK_METHOD5(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 5, __VA_ARGS__)
|
||||
#define MOCK_METHOD6(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 6, __VA_ARGS__)
|
||||
#define MOCK_METHOD7(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 7, __VA_ARGS__)
|
||||
#define MOCK_METHOD8(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 8, __VA_ARGS__)
|
||||
#define MOCK_METHOD9(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 9, __VA_ARGS__)
|
||||
#define MOCK_METHOD10(m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(, , m, 10, __VA_ARGS__)
|
||||
|
||||
#define MOCK_CONST_METHOD0(m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, , m, 0, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD1(m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, , m, 1, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD2(m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, , m, 2, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD3(m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, , m, 3, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD4(m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, , m, 4, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD5(m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, , m, 5, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD6(m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, , m, 6, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD7(m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, , m, 7, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD8(m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, , m, 8, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD9(m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, , m, 9, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD10(m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, , m, 10, __VA_ARGS__)
|
||||
|
||||
#define MOCK_METHOD0_T(m, ...) MOCK_METHOD0(m, __VA_ARGS__)
|
||||
#define MOCK_METHOD1_T(m, ...) MOCK_METHOD1(m, __VA_ARGS__)
|
||||
#define MOCK_METHOD2_T(m, ...) MOCK_METHOD2(m, __VA_ARGS__)
|
||||
#define MOCK_METHOD3_T(m, ...) MOCK_METHOD3(m, __VA_ARGS__)
|
||||
#define MOCK_METHOD4_T(m, ...) MOCK_METHOD4(m, __VA_ARGS__)
|
||||
#define MOCK_METHOD5_T(m, ...) MOCK_METHOD5(m, __VA_ARGS__)
|
||||
#define MOCK_METHOD6_T(m, ...) MOCK_METHOD6(m, __VA_ARGS__)
|
||||
#define MOCK_METHOD7_T(m, ...) MOCK_METHOD7(m, __VA_ARGS__)
|
||||
#define MOCK_METHOD8_T(m, ...) MOCK_METHOD8(m, __VA_ARGS__)
|
||||
#define MOCK_METHOD9_T(m, ...) MOCK_METHOD9(m, __VA_ARGS__)
|
||||
#define MOCK_METHOD10_T(m, ...) MOCK_METHOD10(m, __VA_ARGS__)
|
||||
|
||||
#define MOCK_CONST_METHOD0_T(m, ...) MOCK_CONST_METHOD0(m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD1_T(m, ...) MOCK_CONST_METHOD1(m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD2_T(m, ...) MOCK_CONST_METHOD2(m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD3_T(m, ...) MOCK_CONST_METHOD3(m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD4_T(m, ...) MOCK_CONST_METHOD4(m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD5_T(m, ...) MOCK_CONST_METHOD5(m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD6_T(m, ...) MOCK_CONST_METHOD6(m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD7_T(m, ...) MOCK_CONST_METHOD7(m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD8_T(m, ...) MOCK_CONST_METHOD8(m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD9_T(m, ...) MOCK_CONST_METHOD9(m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD10_T(m, ...) MOCK_CONST_METHOD10(m, __VA_ARGS__)
|
||||
|
||||
#define MOCK_METHOD0_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 0, __VA_ARGS__)
|
||||
#define MOCK_METHOD1_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 1, __VA_ARGS__)
|
||||
#define MOCK_METHOD2_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 2, __VA_ARGS__)
|
||||
#define MOCK_METHOD3_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 3, __VA_ARGS__)
|
||||
#define MOCK_METHOD4_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 4, __VA_ARGS__)
|
||||
#define MOCK_METHOD5_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 5, __VA_ARGS__)
|
||||
#define MOCK_METHOD6_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 6, __VA_ARGS__)
|
||||
#define MOCK_METHOD7_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 7, __VA_ARGS__)
|
||||
#define MOCK_METHOD8_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 8, __VA_ARGS__)
|
||||
#define MOCK_METHOD9_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 9, __VA_ARGS__)
|
||||
#define MOCK_METHOD10_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 10, __VA_ARGS__)
|
||||
|
||||
#define MOCK_CONST_METHOD0_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 0, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD1_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 1, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD2_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 2, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD3_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 3, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD4_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 4, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD5_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 5, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD6_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 6, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD7_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 7, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD8_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 8, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD9_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 9, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD10_WITH_CALLTYPE(ct, m, ...) \
|
||||
GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 10, __VA_ARGS__)
|
||||
|
||||
#define MOCK_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_METHOD0_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_METHOD1_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_METHOD2_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_METHOD3_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_METHOD4_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_METHOD5_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_METHOD6_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_METHOD7_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_METHOD8_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_METHOD9_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_METHOD10_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
|
||||
#define MOCK_CONST_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_CONST_METHOD0_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_CONST_METHOD1_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_CONST_METHOD2_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_CONST_METHOD3_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_CONST_METHOD4_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_CONST_METHOD5_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_CONST_METHOD6_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_CONST_METHOD7_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_CONST_METHOD8_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_CONST_METHOD9_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
#define MOCK_CONST_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \
|
||||
MOCK_CONST_METHOD10_WITH_CALLTYPE(ct, m, __VA_ARGS__)
|
||||
|
||||
#define GMOCK_INTERNAL_MOCK_METHODN(constness, ct, Method, args_num, ...) \
|
||||
GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE( \
|
||||
args_num, ::testing::internal::identity_t<__VA_ARGS__>); \
|
||||
GMOCK_INTERNAL_MOCK_METHOD_IMPL( \
|
||||
args_num, Method, GMOCK_PP_NARG0(constness), 0, 0, , ct, , \
|
||||
(::testing::internal::identity_t<__VA_ARGS__>))
|
||||
|
||||
#define GMOCK_MOCKER_(arity, constness, Method) \
|
||||
GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__)
|
||||
|
||||
#endif // GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_FUNCTION_MOCKER_H_
|
@@ -1,662 +0,0 @@
|
||||
// Copyright 2007, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Google Mock - a framework for writing C++ mock classes.
|
||||
//
|
||||
// This file implements some commonly used variadic actions.
|
||||
|
||||
// IWYU pragma: private, include "gmock/gmock.h"
|
||||
// IWYU pragma: friend gmock/.*
|
||||
|
||||
#ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
|
||||
#define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "gmock/gmock-actions.h"
|
||||
#include "gmock/internal/gmock-port.h"
|
||||
|
||||
// Include any custom callback actions added by the local installation.
|
||||
#include "gmock/internal/custom/gmock-generated-actions.h"
|
||||
|
||||
// Sometimes you want to give an action explicit template parameters
|
||||
// that cannot be inferred from its value parameters. ACTION() and
|
||||
// ACTION_P*() don't support that. ACTION_TEMPLATE() remedies that
|
||||
// and can be viewed as an extension to ACTION() and ACTION_P*().
|
||||
//
|
||||
// The syntax:
|
||||
//
|
||||
// ACTION_TEMPLATE(ActionName,
|
||||
// HAS_m_TEMPLATE_PARAMS(kind1, name1, ..., kind_m, name_m),
|
||||
// AND_n_VALUE_PARAMS(p1, ..., p_n)) { statements; }
|
||||
//
|
||||
// defines an action template that takes m explicit template
|
||||
// parameters and n value parameters. name_i is the name of the i-th
|
||||
// template parameter, and kind_i specifies whether it's a typename,
|
||||
// an integral constant, or a template. p_i is the name of the i-th
|
||||
// value parameter.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// // DuplicateArg<k, T>(output) converts the k-th argument of the mock
|
||||
// // function to type T and copies it to *output.
|
||||
// ACTION_TEMPLATE(DuplicateArg,
|
||||
// HAS_2_TEMPLATE_PARAMS(int, k, typename, T),
|
||||
// AND_1_VALUE_PARAMS(output)) {
|
||||
// *output = T(::std::get<k>(args));
|
||||
// }
|
||||
// ...
|
||||
// int n;
|
||||
// EXPECT_CALL(mock, Foo(_, _))
|
||||
// .WillOnce(DuplicateArg<1, unsigned char>(&n));
|
||||
//
|
||||
// To create an instance of an action template, write:
|
||||
//
|
||||
// ActionName<t1, ..., t_m>(v1, ..., v_n)
|
||||
//
|
||||
// where the ts are the template arguments and the vs are the value
|
||||
// arguments. The value argument types are inferred by the compiler.
|
||||
// If you want to explicitly specify the value argument types, you can
|
||||
// provide additional template arguments:
|
||||
//
|
||||
// ActionName<t1, ..., t_m, u1, ..., u_k>(v1, ..., v_n)
|
||||
//
|
||||
// where u_i is the desired type of v_i.
|
||||
//
|
||||
// ACTION_TEMPLATE and ACTION/ACTION_P* can be overloaded on the
|
||||
// number of value parameters, but not on the number of template
|
||||
// parameters. Without the restriction, the meaning of the following
|
||||
// is unclear:
|
||||
//
|
||||
// OverloadedAction<int, bool>(x);
|
||||
//
|
||||
// Are we using a single-template-parameter action where 'bool' refers
|
||||
// to the type of x, or are we using a two-template-parameter action
|
||||
// where the compiler is asked to infer the type of x?
|
||||
//
|
||||
// Implementation notes:
|
||||
//
|
||||
// GMOCK_INTERNAL_*_HAS_m_TEMPLATE_PARAMS and
|
||||
// GMOCK_INTERNAL_*_AND_n_VALUE_PARAMS are internal macros for
|
||||
// implementing ACTION_TEMPLATE. The main trick we use is to create
|
||||
// new macro invocations when expanding a macro. For example, we have
|
||||
//
|
||||
// #define ACTION_TEMPLATE(name, template_params, value_params)
|
||||
// ... GMOCK_INTERNAL_DECL_##template_params ...
|
||||
//
|
||||
// which causes ACTION_TEMPLATE(..., HAS_1_TEMPLATE_PARAMS(typename, T), ...)
|
||||
// to expand to
|
||||
//
|
||||
// ... GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS(typename, T) ...
|
||||
//
|
||||
// Since GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS is a macro, the
|
||||
// preprocessor will continue to expand it to
|
||||
//
|
||||
// ... typename T ...
|
||||
//
|
||||
// This technique conforms to the C++ standard and is portable. It
|
||||
// allows us to implement action templates using O(N) code, where N is
|
||||
// the maximum number of template/value parameters supported. Without
|
||||
// using it, we'd have to devote O(N^2) amount of code to implement all
|
||||
// combinations of m and n.
|
||||
|
||||
// Declares the template parameters.
|
||||
#define GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS(kind0, name0) kind0 name0
|
||||
#define GMOCK_INTERNAL_DECL_HAS_2_TEMPLATE_PARAMS(kind0, name0, kind1, name1) \
|
||||
kind0 name0, kind1 name1
|
||||
#define GMOCK_INTERNAL_DECL_HAS_3_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
|
||||
kind2, name2) \
|
||||
kind0 name0, kind1 name1, kind2 name2
|
||||
#define GMOCK_INTERNAL_DECL_HAS_4_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
|
||||
kind2, name2, kind3, name3) \
|
||||
kind0 name0, kind1 name1, kind2 name2, kind3 name3
|
||||
#define GMOCK_INTERNAL_DECL_HAS_5_TEMPLATE_PARAMS( \
|
||||
kind0, name0, kind1, name1, kind2, name2, kind3, name3, kind4, name4) \
|
||||
kind0 name0, kind1 name1, kind2 name2, kind3 name3, kind4 name4
|
||||
#define GMOCK_INTERNAL_DECL_HAS_6_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
|
||||
kind2, name2, kind3, name3, \
|
||||
kind4, name4, kind5, name5) \
|
||||
kind0 name0, kind1 name1, kind2 name2, kind3 name3, kind4 name4, kind5 name5
|
||||
#define GMOCK_INTERNAL_DECL_HAS_7_TEMPLATE_PARAMS( \
|
||||
kind0, name0, kind1, name1, kind2, name2, kind3, name3, kind4, name4, \
|
||||
kind5, name5, kind6, name6) \
|
||||
kind0 name0, kind1 name1, kind2 name2, kind3 name3, kind4 name4, \
|
||||
kind5 name5, kind6 name6
|
||||
#define GMOCK_INTERNAL_DECL_HAS_8_TEMPLATE_PARAMS( \
|
||||
kind0, name0, kind1, name1, kind2, name2, kind3, name3, kind4, name4, \
|
||||
kind5, name5, kind6, name6, kind7, name7) \
|
||||
kind0 name0, kind1 name1, kind2 name2, kind3 name3, kind4 name4, \
|
||||
kind5 name5, kind6 name6, kind7 name7
|
||||
#define GMOCK_INTERNAL_DECL_HAS_9_TEMPLATE_PARAMS( \
|
||||
kind0, name0, kind1, name1, kind2, name2, kind3, name3, kind4, name4, \
|
||||
kind5, name5, kind6, name6, kind7, name7, kind8, name8) \
|
||||
kind0 name0, kind1 name1, kind2 name2, kind3 name3, kind4 name4, \
|
||||
kind5 name5, kind6 name6, kind7 name7, kind8 name8
|
||||
#define GMOCK_INTERNAL_DECL_HAS_10_TEMPLATE_PARAMS( \
|
||||
kind0, name0, kind1, name1, kind2, name2, kind3, name3, kind4, name4, \
|
||||
kind5, name5, kind6, name6, kind7, name7, kind8, name8, kind9, name9) \
|
||||
kind0 name0, kind1 name1, kind2 name2, kind3 name3, kind4 name4, \
|
||||
kind5 name5, kind6 name6, kind7 name7, kind8 name8, kind9 name9
|
||||
|
||||
// Lists the template parameters.
|
||||
#define GMOCK_INTERNAL_LIST_HAS_1_TEMPLATE_PARAMS(kind0, name0) name0
|
||||
#define GMOCK_INTERNAL_LIST_HAS_2_TEMPLATE_PARAMS(kind0, name0, kind1, name1) \
|
||||
name0, name1
|
||||
#define GMOCK_INTERNAL_LIST_HAS_3_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
|
||||
kind2, name2) \
|
||||
name0, name1, name2
|
||||
#define GMOCK_INTERNAL_LIST_HAS_4_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
|
||||
kind2, name2, kind3, name3) \
|
||||
name0, name1, name2, name3
|
||||
#define GMOCK_INTERNAL_LIST_HAS_5_TEMPLATE_PARAMS( \
|
||||
kind0, name0, kind1, name1, kind2, name2, kind3, name3, kind4, name4) \
|
||||
name0, name1, name2, name3, name4
|
||||
#define GMOCK_INTERNAL_LIST_HAS_6_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
|
||||
kind2, name2, kind3, name3, \
|
||||
kind4, name4, kind5, name5) \
|
||||
name0, name1, name2, name3, name4, name5
|
||||
#define GMOCK_INTERNAL_LIST_HAS_7_TEMPLATE_PARAMS( \
|
||||
kind0, name0, kind1, name1, kind2, name2, kind3, name3, kind4, name4, \
|
||||
kind5, name5, kind6, name6) \
|
||||
name0, name1, name2, name3, name4, name5, name6
|
||||
#define GMOCK_INTERNAL_LIST_HAS_8_TEMPLATE_PARAMS( \
|
||||
kind0, name0, kind1, name1, kind2, name2, kind3, name3, kind4, name4, \
|
||||
kind5, name5, kind6, name6, kind7, name7) \
|
||||
name0, name1, name2, name3, name4, name5, name6, name7
|
||||
#define GMOCK_INTERNAL_LIST_HAS_9_TEMPLATE_PARAMS( \
|
||||
kind0, name0, kind1, name1, kind2, name2, kind3, name3, kind4, name4, \
|
||||
kind5, name5, kind6, name6, kind7, name7, kind8, name8) \
|
||||
name0, name1, name2, name3, name4, name5, name6, name7, name8
|
||||
#define GMOCK_INTERNAL_LIST_HAS_10_TEMPLATE_PARAMS( \
|
||||
kind0, name0, kind1, name1, kind2, name2, kind3, name3, kind4, name4, \
|
||||
kind5, name5, kind6, name6, kind7, name7, kind8, name8, kind9, name9) \
|
||||
name0, name1, name2, name3, name4, name5, name6, name7, name8, name9
|
||||
|
||||
// Declares the types of value parameters.
|
||||
#define GMOCK_INTERNAL_DECL_TYPE_AND_0_VALUE_PARAMS()
|
||||
#define GMOCK_INTERNAL_DECL_TYPE_AND_1_VALUE_PARAMS(p0) , typename p0##_type
|
||||
#define GMOCK_INTERNAL_DECL_TYPE_AND_2_VALUE_PARAMS(p0, p1) \
|
||||
, typename p0##_type, typename p1##_type
|
||||
#define GMOCK_INTERNAL_DECL_TYPE_AND_3_VALUE_PARAMS(p0, p1, p2) \
|
||||
, typename p0##_type, typename p1##_type, typename p2##_type
|
||||
#define GMOCK_INTERNAL_DECL_TYPE_AND_4_VALUE_PARAMS(p0, p1, p2, p3) \
|
||||
, typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type
|
||||
#define GMOCK_INTERNAL_DECL_TYPE_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) \
|
||||
, typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type, typename p4##_type
|
||||
#define GMOCK_INTERNAL_DECL_TYPE_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) \
|
||||
, typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type, typename p4##_type, typename p5##_type
|
||||
#define GMOCK_INTERNAL_DECL_TYPE_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
|
||||
p6) \
|
||||
, typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type, typename p4##_type, typename p5##_type, \
|
||||
typename p6##_type
|
||||
#define GMOCK_INTERNAL_DECL_TYPE_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
|
||||
p6, p7) \
|
||||
, typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type, typename p4##_type, typename p5##_type, \
|
||||
typename p6##_type, typename p7##_type
|
||||
#define GMOCK_INTERNAL_DECL_TYPE_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
|
||||
p6, p7, p8) \
|
||||
, typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type, typename p4##_type, typename p5##_type, \
|
||||
typename p6##_type, typename p7##_type, typename p8##_type
|
||||
#define GMOCK_INTERNAL_DECL_TYPE_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
|
||||
p6, p7, p8, p9) \
|
||||
, typename p0##_type, typename p1##_type, typename p2##_type, \
|
||||
typename p3##_type, typename p4##_type, typename p5##_type, \
|
||||
typename p6##_type, typename p7##_type, typename p8##_type, \
|
||||
typename p9##_type
|
||||
|
||||
// Initializes the value parameters.
|
||||
#define GMOCK_INTERNAL_INIT_AND_0_VALUE_PARAMS() ()
|
||||
#define GMOCK_INTERNAL_INIT_AND_1_VALUE_PARAMS(p0) \
|
||||
(p0##_type gmock_p0) : p0(::std::move(gmock_p0))
|
||||
#define GMOCK_INTERNAL_INIT_AND_2_VALUE_PARAMS(p0, p1) \
|
||||
(p0##_type gmock_p0, p1##_type gmock_p1) \
|
||||
: p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1))
|
||||
#define GMOCK_INTERNAL_INIT_AND_3_VALUE_PARAMS(p0, p1, p2) \
|
||||
(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2) \
|
||||
: p0(::std::move(gmock_p0)), \
|
||||
p1(::std::move(gmock_p1)), \
|
||||
p2(::std::move(gmock_p2))
|
||||
#define GMOCK_INTERNAL_INIT_AND_4_VALUE_PARAMS(p0, p1, p2, p3) \
|
||||
(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
|
||||
p3##_type gmock_p3) \
|
||||
: p0(::std::move(gmock_p0)), \
|
||||
p1(::std::move(gmock_p1)), \
|
||||
p2(::std::move(gmock_p2)), \
|
||||
p3(::std::move(gmock_p3))
|
||||
#define GMOCK_INTERNAL_INIT_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) \
|
||||
(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
|
||||
p3##_type gmock_p3, p4##_type gmock_p4) \
|
||||
: p0(::std::move(gmock_p0)), \
|
||||
p1(::std::move(gmock_p1)), \
|
||||
p2(::std::move(gmock_p2)), \
|
||||
p3(::std::move(gmock_p3)), \
|
||||
p4(::std::move(gmock_p4))
|
||||
#define GMOCK_INTERNAL_INIT_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) \
|
||||
(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
|
||||
p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5) \
|
||||
: p0(::std::move(gmock_p0)), \
|
||||
p1(::std::move(gmock_p1)), \
|
||||
p2(::std::move(gmock_p2)), \
|
||||
p3(::std::move(gmock_p3)), \
|
||||
p4(::std::move(gmock_p4)), \
|
||||
p5(::std::move(gmock_p5))
|
||||
#define GMOCK_INTERNAL_INIT_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6) \
|
||||
(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
|
||||
p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
|
||||
p6##_type gmock_p6) \
|
||||
: p0(::std::move(gmock_p0)), \
|
||||
p1(::std::move(gmock_p1)), \
|
||||
p2(::std::move(gmock_p2)), \
|
||||
p3(::std::move(gmock_p3)), \
|
||||
p4(::std::move(gmock_p4)), \
|
||||
p5(::std::move(gmock_p5)), \
|
||||
p6(::std::move(gmock_p6))
|
||||
#define GMOCK_INTERNAL_INIT_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7) \
|
||||
(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
|
||||
p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
|
||||
p6##_type gmock_p6, p7##_type gmock_p7) \
|
||||
: p0(::std::move(gmock_p0)), \
|
||||
p1(::std::move(gmock_p1)), \
|
||||
p2(::std::move(gmock_p2)), \
|
||||
p3(::std::move(gmock_p3)), \
|
||||
p4(::std::move(gmock_p4)), \
|
||||
p5(::std::move(gmock_p5)), \
|
||||
p6(::std::move(gmock_p6)), \
|
||||
p7(::std::move(gmock_p7))
|
||||
#define GMOCK_INTERNAL_INIT_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, \
|
||||
p8) \
|
||||
(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
|
||||
p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
|
||||
p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8) \
|
||||
: p0(::std::move(gmock_p0)), \
|
||||
p1(::std::move(gmock_p1)), \
|
||||
p2(::std::move(gmock_p2)), \
|
||||
p3(::std::move(gmock_p3)), \
|
||||
p4(::std::move(gmock_p4)), \
|
||||
p5(::std::move(gmock_p5)), \
|
||||
p6(::std::move(gmock_p6)), \
|
||||
p7(::std::move(gmock_p7)), \
|
||||
p8(::std::move(gmock_p8))
|
||||
#define GMOCK_INTERNAL_INIT_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
|
||||
p7, p8, p9) \
|
||||
(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
|
||||
p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
|
||||
p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8, \
|
||||
p9##_type gmock_p9) \
|
||||
: p0(::std::move(gmock_p0)), \
|
||||
p1(::std::move(gmock_p1)), \
|
||||
p2(::std::move(gmock_p2)), \
|
||||
p3(::std::move(gmock_p3)), \
|
||||
p4(::std::move(gmock_p4)), \
|
||||
p5(::std::move(gmock_p5)), \
|
||||
p6(::std::move(gmock_p6)), \
|
||||
p7(::std::move(gmock_p7)), \
|
||||
p8(::std::move(gmock_p8)), \
|
||||
p9(::std::move(gmock_p9))
|
||||
|
||||
// Defines the copy constructor
|
||||
#define GMOCK_INTERNAL_DEFN_COPY_AND_0_VALUE_PARAMS() \
|
||||
{} // Avoid https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82134
|
||||
#define GMOCK_INTERNAL_DEFN_COPY_AND_1_VALUE_PARAMS(...) = default;
|
||||
#define GMOCK_INTERNAL_DEFN_COPY_AND_2_VALUE_PARAMS(...) = default;
|
||||
#define GMOCK_INTERNAL_DEFN_COPY_AND_3_VALUE_PARAMS(...) = default;
|
||||
#define GMOCK_INTERNAL_DEFN_COPY_AND_4_VALUE_PARAMS(...) = default;
|
||||
#define GMOCK_INTERNAL_DEFN_COPY_AND_5_VALUE_PARAMS(...) = default;
|
||||
#define GMOCK_INTERNAL_DEFN_COPY_AND_6_VALUE_PARAMS(...) = default;
|
||||
#define GMOCK_INTERNAL_DEFN_COPY_AND_7_VALUE_PARAMS(...) = default;
|
||||
#define GMOCK_INTERNAL_DEFN_COPY_AND_8_VALUE_PARAMS(...) = default;
|
||||
#define GMOCK_INTERNAL_DEFN_COPY_AND_9_VALUE_PARAMS(...) = default;
|
||||
#define GMOCK_INTERNAL_DEFN_COPY_AND_10_VALUE_PARAMS(...) = default;
|
||||
|
||||
// Declares the fields for storing the value parameters.
|
||||
#define GMOCK_INTERNAL_DEFN_AND_0_VALUE_PARAMS()
|
||||
#define GMOCK_INTERNAL_DEFN_AND_1_VALUE_PARAMS(p0) p0##_type p0;
|
||||
#define GMOCK_INTERNAL_DEFN_AND_2_VALUE_PARAMS(p0, p1) \
|
||||
p0##_type p0; \
|
||||
p1##_type p1;
|
||||
#define GMOCK_INTERNAL_DEFN_AND_3_VALUE_PARAMS(p0, p1, p2) \
|
||||
p0##_type p0; \
|
||||
p1##_type p1; \
|
||||
p2##_type p2;
|
||||
#define GMOCK_INTERNAL_DEFN_AND_4_VALUE_PARAMS(p0, p1, p2, p3) \
|
||||
p0##_type p0; \
|
||||
p1##_type p1; \
|
||||
p2##_type p2; \
|
||||
p3##_type p3;
|
||||
#define GMOCK_INTERNAL_DEFN_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) \
|
||||
p0##_type p0; \
|
||||
p1##_type p1; \
|
||||
p2##_type p2; \
|
||||
p3##_type p3; \
|
||||
p4##_type p4;
|
||||
#define GMOCK_INTERNAL_DEFN_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) \
|
||||
p0##_type p0; \
|
||||
p1##_type p1; \
|
||||
p2##_type p2; \
|
||||
p3##_type p3; \
|
||||
p4##_type p4; \
|
||||
p5##_type p5;
|
||||
#define GMOCK_INTERNAL_DEFN_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6) \
|
||||
p0##_type p0; \
|
||||
p1##_type p1; \
|
||||
p2##_type p2; \
|
||||
p3##_type p3; \
|
||||
p4##_type p4; \
|
||||
p5##_type p5; \
|
||||
p6##_type p6;
|
||||
#define GMOCK_INTERNAL_DEFN_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7) \
|
||||
p0##_type p0; \
|
||||
p1##_type p1; \
|
||||
p2##_type p2; \
|
||||
p3##_type p3; \
|
||||
p4##_type p4; \
|
||||
p5##_type p5; \
|
||||
p6##_type p6; \
|
||||
p7##_type p7;
|
||||
#define GMOCK_INTERNAL_DEFN_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, \
|
||||
p8) \
|
||||
p0##_type p0; \
|
||||
p1##_type p1; \
|
||||
p2##_type p2; \
|
||||
p3##_type p3; \
|
||||
p4##_type p4; \
|
||||
p5##_type p5; \
|
||||
p6##_type p6; \
|
||||
p7##_type p7; \
|
||||
p8##_type p8;
|
||||
#define GMOCK_INTERNAL_DEFN_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
|
||||
p7, p8, p9) \
|
||||
p0##_type p0; \
|
||||
p1##_type p1; \
|
||||
p2##_type p2; \
|
||||
p3##_type p3; \
|
||||
p4##_type p4; \
|
||||
p5##_type p5; \
|
||||
p6##_type p6; \
|
||||
p7##_type p7; \
|
||||
p8##_type p8; \
|
||||
p9##_type p9;
|
||||
|
||||
// Lists the value parameters.
|
||||
#define GMOCK_INTERNAL_LIST_AND_0_VALUE_PARAMS()
|
||||
#define GMOCK_INTERNAL_LIST_AND_1_VALUE_PARAMS(p0) p0
|
||||
#define GMOCK_INTERNAL_LIST_AND_2_VALUE_PARAMS(p0, p1) p0, p1
|
||||
#define GMOCK_INTERNAL_LIST_AND_3_VALUE_PARAMS(p0, p1, p2) p0, p1, p2
|
||||
#define GMOCK_INTERNAL_LIST_AND_4_VALUE_PARAMS(p0, p1, p2, p3) p0, p1, p2, p3
|
||||
#define GMOCK_INTERNAL_LIST_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) \
|
||||
p0, p1, p2, p3, p4
|
||||
#define GMOCK_INTERNAL_LIST_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) \
|
||||
p0, p1, p2, p3, p4, p5
|
||||
#define GMOCK_INTERNAL_LIST_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6) \
|
||||
p0, p1, p2, p3, p4, p5, p6
|
||||
#define GMOCK_INTERNAL_LIST_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7) \
|
||||
p0, p1, p2, p3, p4, p5, p6, p7
|
||||
#define GMOCK_INTERNAL_LIST_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, \
|
||||
p8) \
|
||||
p0, p1, p2, p3, p4, p5, p6, p7, p8
|
||||
#define GMOCK_INTERNAL_LIST_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
|
||||
p7, p8, p9) \
|
||||
p0, p1, p2, p3, p4, p5, p6, p7, p8, p9
|
||||
|
||||
// Lists the value parameter types.
|
||||
#define GMOCK_INTERNAL_LIST_TYPE_AND_0_VALUE_PARAMS()
|
||||
#define GMOCK_INTERNAL_LIST_TYPE_AND_1_VALUE_PARAMS(p0) , p0##_type
|
||||
#define GMOCK_INTERNAL_LIST_TYPE_AND_2_VALUE_PARAMS(p0, p1) \
|
||||
, p0##_type, p1##_type
|
||||
#define GMOCK_INTERNAL_LIST_TYPE_AND_3_VALUE_PARAMS(p0, p1, p2) \
|
||||
, p0##_type, p1##_type, p2##_type
|
||||
#define GMOCK_INTERNAL_LIST_TYPE_AND_4_VALUE_PARAMS(p0, p1, p2, p3) \
|
||||
, p0##_type, p1##_type, p2##_type, p3##_type
|
||||
#define GMOCK_INTERNAL_LIST_TYPE_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) \
|
||||
, p0##_type, p1##_type, p2##_type, p3##_type, p4##_type
|
||||
#define GMOCK_INTERNAL_LIST_TYPE_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) \
|
||||
, p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, p5##_type
|
||||
#define GMOCK_INTERNAL_LIST_TYPE_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
|
||||
p6) \
|
||||
, p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, p5##_type, p6##_type
|
||||
#define GMOCK_INTERNAL_LIST_TYPE_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
|
||||
p6, p7) \
|
||||
, p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, p5##_type, \
|
||||
p6##_type, p7##_type
|
||||
#define GMOCK_INTERNAL_LIST_TYPE_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
|
||||
p6, p7, p8) \
|
||||
, p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, p5##_type, \
|
||||
p6##_type, p7##_type, p8##_type
|
||||
#define GMOCK_INTERNAL_LIST_TYPE_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
|
||||
p6, p7, p8, p9) \
|
||||
, p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, p5##_type, \
|
||||
p6##_type, p7##_type, p8##_type, p9##_type
|
||||
|
||||
// Declares the value parameters.
|
||||
#define GMOCK_INTERNAL_DECL_AND_0_VALUE_PARAMS()
|
||||
#define GMOCK_INTERNAL_DECL_AND_1_VALUE_PARAMS(p0) p0##_type p0
|
||||
#define GMOCK_INTERNAL_DECL_AND_2_VALUE_PARAMS(p0, p1) \
|
||||
p0##_type p0, p1##_type p1
|
||||
#define GMOCK_INTERNAL_DECL_AND_3_VALUE_PARAMS(p0, p1, p2) \
|
||||
p0##_type p0, p1##_type p1, p2##_type p2
|
||||
#define GMOCK_INTERNAL_DECL_AND_4_VALUE_PARAMS(p0, p1, p2, p3) \
|
||||
p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3
|
||||
#define GMOCK_INTERNAL_DECL_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) \
|
||||
p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4
|
||||
#define GMOCK_INTERNAL_DECL_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) \
|
||||
p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, \
|
||||
p5##_type p5
|
||||
#define GMOCK_INTERNAL_DECL_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6) \
|
||||
p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, \
|
||||
p5##_type p5, p6##_type p6
|
||||
#define GMOCK_INTERNAL_DECL_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7) \
|
||||
p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, \
|
||||
p5##_type p5, p6##_type p6, p7##_type p7
|
||||
#define GMOCK_INTERNAL_DECL_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, \
|
||||
p8) \
|
||||
p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, \
|
||||
p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8
|
||||
#define GMOCK_INTERNAL_DECL_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
|
||||
p7, p8, p9) \
|
||||
p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, \
|
||||
p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8, p9##_type p9
|
||||
|
||||
// The suffix of the class template implementing the action template.
|
||||
#define GMOCK_INTERNAL_COUNT_AND_0_VALUE_PARAMS()
|
||||
#define GMOCK_INTERNAL_COUNT_AND_1_VALUE_PARAMS(p0) P
|
||||
#define GMOCK_INTERNAL_COUNT_AND_2_VALUE_PARAMS(p0, p1) P2
|
||||
#define GMOCK_INTERNAL_COUNT_AND_3_VALUE_PARAMS(p0, p1, p2) P3
|
||||
#define GMOCK_INTERNAL_COUNT_AND_4_VALUE_PARAMS(p0, p1, p2, p3) P4
|
||||
#define GMOCK_INTERNAL_COUNT_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) P5
|
||||
#define GMOCK_INTERNAL_COUNT_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) P6
|
||||
#define GMOCK_INTERNAL_COUNT_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6) P7
|
||||
#define GMOCK_INTERNAL_COUNT_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
|
||||
p7) \
|
||||
P8
|
||||
#define GMOCK_INTERNAL_COUNT_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
|
||||
p7, p8) \
|
||||
P9
|
||||
#define GMOCK_INTERNAL_COUNT_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
|
||||
p7, p8, p9) \
|
||||
P10
|
||||
|
||||
// The name of the class template implementing the action template.
|
||||
#define GMOCK_ACTION_CLASS_(name, value_params) \
|
||||
GTEST_CONCAT_TOKEN_(name##Action, GMOCK_INTERNAL_COUNT_##value_params)
|
||||
|
||||
#define ACTION_TEMPLATE(name, template_params, value_params) \
|
||||
template <GMOCK_INTERNAL_DECL_##template_params \
|
||||
GMOCK_INTERNAL_DECL_TYPE_##value_params> \
|
||||
class GMOCK_ACTION_CLASS_(name, value_params) { \
|
||||
public: \
|
||||
explicit GMOCK_ACTION_CLASS_(name, value_params)( \
|
||||
GMOCK_INTERNAL_DECL_##value_params) \
|
||||
GMOCK_PP_IF(GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params), \
|
||||
= default; \
|
||||
, \
|
||||
: impl_(std::make_shared<gmock_Impl>( \
|
||||
GMOCK_INTERNAL_LIST_##value_params)){}) \
|
||||
GMOCK_ACTION_CLASS_(name, value_params)(const GMOCK_ACTION_CLASS_( \
|
||||
name, value_params) &) noexcept GMOCK_INTERNAL_DEFN_COPY_ \
|
||||
##value_params GMOCK_ACTION_CLASS_(name, value_params)( \
|
||||
GMOCK_ACTION_CLASS_(name, value_params) &&) noexcept \
|
||||
GMOCK_INTERNAL_DEFN_COPY_##value_params template <typename F> \
|
||||
operator ::testing::Action<F>() const { \
|
||||
return GMOCK_PP_IF( \
|
||||
GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params), \
|
||||
(::testing::internal::MakeAction<F, gmock_Impl>()), \
|
||||
(::testing::internal::MakeAction<F>(impl_))); \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
class gmock_Impl { \
|
||||
public: \
|
||||
explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {} \
|
||||
template <typename function_type, typename return_type, \
|
||||
typename args_type, GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \
|
||||
return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \
|
||||
GMOCK_INTERNAL_DEFN_##value_params \
|
||||
}; \
|
||||
GMOCK_PP_IF(GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params), , \
|
||||
std::shared_ptr<const gmock_Impl> impl_;) \
|
||||
}; \
|
||||
template <GMOCK_INTERNAL_DECL_##template_params \
|
||||
GMOCK_INTERNAL_DECL_TYPE_##value_params> \
|
||||
GMOCK_ACTION_CLASS_( \
|
||||
name, value_params)<GMOCK_INTERNAL_LIST_##template_params \
|
||||
GMOCK_INTERNAL_LIST_TYPE_##value_params> \
|
||||
name(GMOCK_INTERNAL_DECL_##value_params) GTEST_MUST_USE_RESULT_; \
|
||||
template <GMOCK_INTERNAL_DECL_##template_params \
|
||||
GMOCK_INTERNAL_DECL_TYPE_##value_params> \
|
||||
inline GMOCK_ACTION_CLASS_( \
|
||||
name, value_params)<GMOCK_INTERNAL_LIST_##template_params \
|
||||
GMOCK_INTERNAL_LIST_TYPE_##value_params> \
|
||||
name(GMOCK_INTERNAL_DECL_##value_params) { \
|
||||
return GMOCK_ACTION_CLASS_( \
|
||||
name, value_params)<GMOCK_INTERNAL_LIST_##template_params \
|
||||
GMOCK_INTERNAL_LIST_TYPE_##value_params>( \
|
||||
GMOCK_INTERNAL_LIST_##value_params); \
|
||||
} \
|
||||
template <GMOCK_INTERNAL_DECL_##template_params \
|
||||
GMOCK_INTERNAL_DECL_TYPE_##value_params> \
|
||||
template <typename function_type, typename return_type, typename args_type, \
|
||||
GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \
|
||||
return_type GMOCK_ACTION_CLASS_( \
|
||||
name, value_params)<GMOCK_INTERNAL_LIST_##template_params \
|
||||
GMOCK_INTERNAL_LIST_TYPE_##value_params>:: \
|
||||
gmock_Impl::gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) \
|
||||
const
|
||||
|
||||
namespace testing {
|
||||
|
||||
// The ACTION*() macros trigger warning C4100 (unreferenced formal
|
||||
// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in
|
||||
// the macro definition, as the warnings are generated when the macro
|
||||
// is expanded and macro expansion cannot contain #pragma. Therefore
|
||||
// we suppress them here.
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4100)
|
||||
#endif
|
||||
|
||||
namespace internal {
|
||||
|
||||
// internal::InvokeArgument - a helper for InvokeArgument action.
|
||||
// The basic overloads are provided here for generic functors.
|
||||
// Overloads for other custom-callables are provided in the
|
||||
// internal/custom/gmock-generated-actions.h header.
|
||||
template <typename F, typename... Args>
|
||||
auto InvokeArgument(F f, Args... args) -> decltype(f(args...)) {
|
||||
return f(args...);
|
||||
}
|
||||
|
||||
template <std::size_t index, typename... Params>
|
||||
struct InvokeArgumentAction {
|
||||
template <typename... Args,
|
||||
typename = typename std::enable_if<(index < sizeof...(Args))>::type>
|
||||
auto operator()(Args&&... args) const -> decltype(internal::InvokeArgument(
|
||||
std::get<index>(std::forward_as_tuple(std::forward<Args>(args)...)),
|
||||
std::declval<const Params&>()...)) {
|
||||
internal::FlatTuple<Args&&...> args_tuple(FlatTupleConstructTag{},
|
||||
std::forward<Args>(args)...);
|
||||
return params.Apply([&](const Params&... unpacked_params) {
|
||||
auto&& callable = args_tuple.template Get<index>();
|
||||
return internal::InvokeArgument(
|
||||
std::forward<decltype(callable)>(callable), unpacked_params...);
|
||||
});
|
||||
}
|
||||
|
||||
internal::FlatTuple<Params...> params;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// The InvokeArgument<N>(a1, a2, ..., a_k) action invokes the N-th
|
||||
// (0-based) argument, which must be a k-ary callable, of the mock
|
||||
// function, with arguments a1, a2, ..., a_k.
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// 1. The arguments are passed by value by default. If you need to
|
||||
// pass an argument by reference, wrap it inside std::ref(). For
|
||||
// example,
|
||||
//
|
||||
// InvokeArgument<1>(5, string("Hello"), std::ref(foo))
|
||||
//
|
||||
// passes 5 and string("Hello") by value, and passes foo by
|
||||
// reference.
|
||||
//
|
||||
// 2. If the callable takes an argument by reference but std::ref() is
|
||||
// not used, it will receive the reference to a copy of the value,
|
||||
// instead of the original value. For example, when the 0-th
|
||||
// argument of the mock function takes a const string&, the action
|
||||
//
|
||||
// InvokeArgument<0>(string("Hello"))
|
||||
//
|
||||
// makes a copy of the temporary string("Hello") object and passes a
|
||||
// reference of the copy, instead of the original temporary object,
|
||||
// to the callable. This makes it easy for a user to define an
|
||||
// InvokeArgument action from temporary values and have it performed
|
||||
// later.
|
||||
template <std::size_t index, typename... Params>
|
||||
internal::InvokeArgumentAction<index, typename std::decay<Params>::type...>
|
||||
InvokeArgument(Params&&... params) {
|
||||
return {internal::FlatTuple<typename std::decay<Params>::type...>(
|
||||
internal::FlatTupleConstructTag{}, std::forward<Params>(params)...)};
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace testing
|
||||
|
||||
#endif // GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
|
@@ -1,277 +0,0 @@
|
||||
// Copyright 2008, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Implements class templates NiceMock, NaggyMock, and StrictMock.
|
||||
//
|
||||
// Given a mock class MockFoo that is created using Google Mock,
|
||||
// NiceMock<MockFoo> is a subclass of MockFoo that allows
|
||||
// uninteresting calls (i.e. calls to mock methods that have no
|
||||
// EXPECT_CALL specs), NaggyMock<MockFoo> is a subclass of MockFoo
|
||||
// that prints a warning when an uninteresting call occurs, and
|
||||
// StrictMock<MockFoo> is a subclass of MockFoo that treats all
|
||||
// uninteresting calls as errors.
|
||||
//
|
||||
// Currently a mock is naggy by default, so MockFoo and
|
||||
// NaggyMock<MockFoo> behave like the same. However, we will soon
|
||||
// switch the default behavior of mocks to be nice, as that in general
|
||||
// leads to more maintainable tests. When that happens, MockFoo will
|
||||
// stop behaving like NaggyMock<MockFoo> and start behaving like
|
||||
// NiceMock<MockFoo>.
|
||||
//
|
||||
// NiceMock, NaggyMock, and StrictMock "inherit" the constructors of
|
||||
// their respective base class. Therefore you can write
|
||||
// NiceMock<MockFoo>(5, "a") to construct a nice mock where MockFoo
|
||||
// has a constructor that accepts (int, const char*), for example.
|
||||
//
|
||||
// A known limitation is that NiceMock<MockFoo>, NaggyMock<MockFoo>,
|
||||
// and StrictMock<MockFoo> only works for mock methods defined using
|
||||
// the MOCK_METHOD* family of macros DIRECTLY in the MockFoo class.
|
||||
// If a mock method is defined in a base class of MockFoo, the "nice"
|
||||
// or "strict" modifier may not affect it, depending on the compiler.
|
||||
// In particular, nesting NiceMock, NaggyMock, and StrictMock is NOT
|
||||
// supported.
|
||||
|
||||
// IWYU pragma: private, include "gmock/gmock.h"
|
||||
// IWYU pragma: friend gmock/.*
|
||||
|
||||
#ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_NICE_STRICT_H_
|
||||
#define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_NICE_STRICT_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
#include "gmock/gmock-spec-builders.h"
|
||||
#include "gmock/internal/gmock-port.h"
|
||||
|
||||
namespace testing {
|
||||
template <class MockClass>
|
||||
class NiceMock;
|
||||
template <class MockClass>
|
||||
class NaggyMock;
|
||||
template <class MockClass>
|
||||
class StrictMock;
|
||||
|
||||
namespace internal {
|
||||
template <typename T>
|
||||
std::true_type StrictnessModifierProbe(const NiceMock<T>&);
|
||||
template <typename T>
|
||||
std::true_type StrictnessModifierProbe(const NaggyMock<T>&);
|
||||
template <typename T>
|
||||
std::true_type StrictnessModifierProbe(const StrictMock<T>&);
|
||||
std::false_type StrictnessModifierProbe(...);
|
||||
|
||||
template <typename T>
|
||||
constexpr bool HasStrictnessModifier() {
|
||||
return decltype(StrictnessModifierProbe(std::declval<const T&>()))::value;
|
||||
}
|
||||
|
||||
// Base classes that register and deregister with testing::Mock to alter the
|
||||
// default behavior around uninteresting calls. Inheriting from one of these
|
||||
// classes first and then MockClass ensures the MockClass constructor is run
|
||||
// after registration, and that the MockClass destructor runs before
|
||||
// deregistration. This guarantees that MockClass's constructor and destructor
|
||||
// run with the same level of strictness as its instance methods.
|
||||
|
||||
#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW && \
|
||||
(defined(_MSC_VER) || defined(__clang__))
|
||||
// We need to mark these classes with this declspec to ensure that
|
||||
// the empty base class optimization is performed.
|
||||
#define GTEST_INTERNAL_EMPTY_BASE_CLASS __declspec(empty_bases)
|
||||
#else
|
||||
#define GTEST_INTERNAL_EMPTY_BASE_CLASS
|
||||
#endif
|
||||
|
||||
template <typename Base>
|
||||
class NiceMockImpl {
|
||||
public:
|
||||
NiceMockImpl() {
|
||||
::testing::Mock::AllowUninterestingCalls(reinterpret_cast<uintptr_t>(this));
|
||||
}
|
||||
|
||||
~NiceMockImpl() {
|
||||
::testing::Mock::UnregisterCallReaction(reinterpret_cast<uintptr_t>(this));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Base>
|
||||
class NaggyMockImpl {
|
||||
public:
|
||||
NaggyMockImpl() {
|
||||
::testing::Mock::WarnUninterestingCalls(reinterpret_cast<uintptr_t>(this));
|
||||
}
|
||||
|
||||
~NaggyMockImpl() {
|
||||
::testing::Mock::UnregisterCallReaction(reinterpret_cast<uintptr_t>(this));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Base>
|
||||
class StrictMockImpl {
|
||||
public:
|
||||
StrictMockImpl() {
|
||||
::testing::Mock::FailUninterestingCalls(reinterpret_cast<uintptr_t>(this));
|
||||
}
|
||||
|
||||
~StrictMockImpl() {
|
||||
::testing::Mock::UnregisterCallReaction(reinterpret_cast<uintptr_t>(this));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <class MockClass>
|
||||
class GTEST_INTERNAL_EMPTY_BASE_CLASS NiceMock
|
||||
: private internal::NiceMockImpl<MockClass>,
|
||||
public MockClass {
|
||||
public:
|
||||
static_assert(!internal::HasStrictnessModifier<MockClass>(),
|
||||
"Can't apply NiceMock to a class hierarchy that already has a "
|
||||
"strictness modifier. See "
|
||||
"https://google.github.io/googletest/"
|
||||
"gmock_cook_book.html#NiceStrictNaggy");
|
||||
NiceMock() : MockClass() {
|
||||
static_assert(sizeof(*this) == sizeof(MockClass),
|
||||
"The impl subclass shouldn't introduce any padding");
|
||||
}
|
||||
|
||||
// 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 NiceMock(A&& arg) : MockClass(std::forward<A>(arg)) {
|
||||
static_assert(sizeof(*this) == sizeof(MockClass),
|
||||
"The impl subclass shouldn't introduce any padding");
|
||||
}
|
||||
|
||||
template <typename TArg1, typename TArg2, typename... An>
|
||||
NiceMock(TArg1&& arg1, TArg2&& arg2, An&&... args)
|
||||
: MockClass(std::forward<TArg1>(arg1), std::forward<TArg2>(arg2),
|
||||
std::forward<An>(args)...) {
|
||||
static_assert(sizeof(*this) == sizeof(MockClass),
|
||||
"The impl subclass shouldn't introduce any padding");
|
||||
}
|
||||
|
||||
private:
|
||||
NiceMock(const NiceMock&) = delete;
|
||||
NiceMock& operator=(const NiceMock&) = delete;
|
||||
};
|
||||
|
||||
template <class MockClass>
|
||||
class GTEST_INTERNAL_EMPTY_BASE_CLASS NaggyMock
|
||||
: private internal::NaggyMockImpl<MockClass>,
|
||||
public MockClass {
|
||||
static_assert(!internal::HasStrictnessModifier<MockClass>(),
|
||||
"Can't apply NaggyMock to a class hierarchy that already has a "
|
||||
"strictness modifier. See "
|
||||
"https://google.github.io/googletest/"
|
||||
"gmock_cook_book.html#NiceStrictNaggy");
|
||||
|
||||
public:
|
||||
NaggyMock() : MockClass() {
|
||||
static_assert(sizeof(*this) == sizeof(MockClass),
|
||||
"The impl subclass shouldn't introduce any padding");
|
||||
}
|
||||
|
||||
// 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)) {
|
||||
static_assert(sizeof(*this) == sizeof(MockClass),
|
||||
"The impl subclass shouldn't introduce any padding");
|
||||
}
|
||||
|
||||
template <typename TArg1, typename TArg2, typename... An>
|
||||
NaggyMock(TArg1&& arg1, TArg2&& arg2, An&&... args)
|
||||
: MockClass(std::forward<TArg1>(arg1), std::forward<TArg2>(arg2),
|
||||
std::forward<An>(args)...) {
|
||||
static_assert(sizeof(*this) == sizeof(MockClass),
|
||||
"The impl subclass shouldn't introduce any padding");
|
||||
}
|
||||
|
||||
private:
|
||||
NaggyMock(const NaggyMock&) = delete;
|
||||
NaggyMock& operator=(const NaggyMock&) = delete;
|
||||
};
|
||||
|
||||
template <class MockClass>
|
||||
class GTEST_INTERNAL_EMPTY_BASE_CLASS StrictMock
|
||||
: private internal::StrictMockImpl<MockClass>,
|
||||
public MockClass {
|
||||
public:
|
||||
static_assert(
|
||||
!internal::HasStrictnessModifier<MockClass>(),
|
||||
"Can't apply StrictMock to a class hierarchy that already has a "
|
||||
"strictness modifier. See "
|
||||
"https://google.github.io/googletest/"
|
||||
"gmock_cook_book.html#NiceStrictNaggy");
|
||||
StrictMock() : MockClass() {
|
||||
static_assert(sizeof(*this) == sizeof(MockClass),
|
||||
"The impl subclass shouldn't introduce any padding");
|
||||
}
|
||||
|
||||
// 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)) {
|
||||
static_assert(sizeof(*this) == sizeof(MockClass),
|
||||
"The impl subclass shouldn't introduce any padding");
|
||||
}
|
||||
|
||||
template <typename TArg1, typename TArg2, typename... An>
|
||||
StrictMock(TArg1&& arg1, TArg2&& arg2, An&&... args)
|
||||
: MockClass(std::forward<TArg1>(arg1), std::forward<TArg2>(arg2),
|
||||
std::forward<An>(args)...) {
|
||||
static_assert(sizeof(*this) == sizeof(MockClass),
|
||||
"The impl subclass shouldn't introduce any padding");
|
||||
}
|
||||
|
||||
private:
|
||||
StrictMock(const StrictMock&) = delete;
|
||||
StrictMock& operator=(const StrictMock&) = delete;
|
||||
};
|
||||
|
||||
#undef GTEST_INTERNAL_EMPTY_BASE_CLASS
|
||||
|
||||
} // namespace testing
|
||||
|
||||
#endif // GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_NICE_STRICT_H_
|
@@ -1,7 +0,0 @@
|
||||
// IWYU pragma: private, include "gmock/gmock.h"
|
||||
// IWYU pragma: friend gmock/.*
|
||||
|
||||
#ifndef GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
|
||||
#define GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
|
||||
|
||||
#endif // GOOGLEMOCK_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