Compare commits
40 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a6ce08abf7 | ||
![]() |
c00fd25b71 | ||
![]() |
4a00a24fff | ||
![]() |
a866428a78 | ||
![]() |
445e9bd8d0 | ||
![]() |
e5443e5c65 | ||
![]() |
e235eb34c6 | ||
![]() |
66d7401378 | ||
![]() |
b4aae50ce1 | ||
![]() |
2b6b042a77 | ||
![]() |
e4ece4881d | ||
![]() |
504ea69cf7 | ||
![]() |
4bbf80823c | ||
![]() |
7d76a231b0 | ||
![]() |
e54519b094 | ||
![]() |
f3c355f9dd | ||
![]() |
79219e26e0 | ||
![]() |
d122c0d435 | ||
![]() |
35d0c36560 | ||
![]() |
7927f8e93d | ||
![]() |
d144031940 | ||
![]() |
1204d63444 | ||
![]() |
5ed2186395 | ||
![]() |
df1544bcee | ||
![]() |
62df7bdbc1 | ||
![]() |
71815bbf7d | ||
![]() |
a1e255a582 | ||
![]() |
6dae7eb4a5 | ||
![]() |
0953a17a42 | ||
![]() |
ff233bdd4c | ||
![]() |
3e3b44c300 | ||
![]() |
ffa31aec1c | ||
![]() |
5bcb2d78a1 | ||
![]() |
352788321f | ||
![]() |
57e107a10e | ||
![]() |
cee1ba1f24 | ||
![]() |
9ff2450a56 | ||
![]() |
b62593aceb | ||
![]() |
d49a665484 | ||
![]() |
417158b8bc |
26
BUILD.bazel
26
BUILD.bazel
@ -138,19 +138,19 @@ cc_library(
|
|||||||
}),
|
}),
|
||||||
deps = select({
|
deps = select({
|
||||||
":has_absl": [
|
":has_absl": [
|
||||||
"@com_google_absl//absl/container:flat_hash_set",
|
"@abseil-cpp//absl/container:flat_hash_set",
|
||||||
"@com_google_absl//absl/debugging:failure_signal_handler",
|
"@abseil-cpp//absl/debugging:failure_signal_handler",
|
||||||
"@com_google_absl//absl/debugging:stacktrace",
|
"@abseil-cpp//absl/debugging:stacktrace",
|
||||||
"@com_google_absl//absl/debugging:symbolize",
|
"@abseil-cpp//absl/debugging:symbolize",
|
||||||
"@com_google_absl//absl/flags:flag",
|
"@abseil-cpp//absl/flags:flag",
|
||||||
"@com_google_absl//absl/flags:parse",
|
"@abseil-cpp//absl/flags:parse",
|
||||||
"@com_google_absl//absl/flags:reflection",
|
"@abseil-cpp//absl/flags:reflection",
|
||||||
"@com_google_absl//absl/flags:usage",
|
"@abseil-cpp//absl/flags:usage",
|
||||||
"@com_google_absl//absl/strings",
|
"@abseil-cpp//absl/strings",
|
||||||
"@com_google_absl//absl/types:any",
|
"@abseil-cpp//absl/types:any",
|
||||||
"@com_google_absl//absl/types:optional",
|
"@abseil-cpp//absl/types:optional",
|
||||||
"@com_google_absl//absl/types:variant",
|
"@abseil-cpp//absl/types:variant",
|
||||||
"@com_googlesource_code_re2//:re2",
|
"@re2//:re2",
|
||||||
],
|
],
|
||||||
"//conditions:default": [],
|
"//conditions:default": [],
|
||||||
}) + select({
|
}) + select({
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
# Note: CMake support is community-based. The maintainers do not use CMake
|
# Note: CMake support is community-based. The maintainers do not use CMake
|
||||||
# internally.
|
# internally.
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
project(googletest-distribution)
|
project(googletest-distribution)
|
||||||
set(GOOGLETEST_VERSION 1.14.0)
|
set(GOOGLETEST_VERSION 1.16.0)
|
||||||
|
|
||||||
if(NOT CYGWIN AND NOT MSYS AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL QNX)
|
if(NOT CYGWIN AND NOT MSYS AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL QNX)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
49
MODULE.bazel
49
MODULE.bazel
@ -39,23 +39,38 @@ module(
|
|||||||
# Only direct dependencies need to be listed below.
|
# Only direct dependencies need to be listed below.
|
||||||
# Please keep the versions in sync with the versions in the WORKSPACE file.
|
# Please keep the versions in sync with the versions in the WORKSPACE file.
|
||||||
|
|
||||||
bazel_dep(name = "abseil-cpp",
|
bazel_dep(
|
||||||
version = "20240116.2",
|
name = "abseil-cpp",
|
||||||
repo_name = "com_google_absl")
|
version = "20250127.0",
|
||||||
|
)
|
||||||
|
bazel_dep(
|
||||||
|
name = "platforms",
|
||||||
|
version = "0.0.10",
|
||||||
|
)
|
||||||
|
bazel_dep(
|
||||||
|
name = "re2",
|
||||||
|
version = "2024-07-02",
|
||||||
|
)
|
||||||
|
|
||||||
bazel_dep(name = "platforms",
|
bazel_dep(
|
||||||
version = "0.0.10")
|
name = "rules_python",
|
||||||
|
version = "1.1.0",
|
||||||
|
dev_dependency = True,
|
||||||
|
)
|
||||||
|
|
||||||
bazel_dep(name = "re2",
|
# https://rules-python.readthedocs.io/en/stable/toolchains.html#library-modules-with-dev-only-python-usage
|
||||||
repo_name = "com_googlesource_code_re2",
|
python = use_extension(
|
||||||
version = "2024-07-02")
|
"@rules_python//python/extensions:python.bzl",
|
||||||
|
"python",
|
||||||
|
dev_dependency = True,
|
||||||
|
)
|
||||||
|
python.toolchain(
|
||||||
|
ignore_root_user_error = True,
|
||||||
|
is_default = True,
|
||||||
|
python_version = "3.12",
|
||||||
|
)
|
||||||
|
|
||||||
bazel_dep(name = "rules_python",
|
# See fake_fuchsia_sdk.bzl for instructions on how to override this with a real SDK, if needed.
|
||||||
version = "0.29.0")
|
fuchsia_sdk = use_extension("//:fake_fuchsia_sdk.bzl", "fuchsia_sdk")
|
||||||
|
fuchsia_sdk.create_fake()
|
||||||
|
use_repo(fuchsia_sdk, "fuchsia_sdk")
|
||||||
fake_fuchsia_sdk = use_repo_rule("//:fake_fuchsia_sdk.bzl", "fake_fuchsia_sdk")
|
|
||||||
fake_fuchsia_sdk(name = "fuchsia_sdk")
|
|
||||||
|
|
||||||
# https://github.com/bazelbuild/rules_python/blob/main/BZLMOD_SUPPORT.md#default-toolchain-is-not-the-local-system-python
|
|
||||||
register_toolchains("@bazel_tools//tools/python:autodetecting_toolchain")
|
|
||||||
|
11
README.md
11
README.md
@ -9,7 +9,7 @@ GoogleTest now follows the
|
|||||||
We recommend
|
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).
|
[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).
|
||||||
We do publish occasional semantic versions, tagged with
|
We do publish occasional semantic versions, tagged with
|
||||||
`v${major}.${minor}.${patch}` (e.g. `v1.14.0`).
|
`v${major}.${minor}.${patch}` (e.g. `v1.16.0`).
|
||||||
|
|
||||||
#### Documentation Updates
|
#### Documentation Updates
|
||||||
|
|
||||||
@ -17,12 +17,15 @@ Our documentation is now live on GitHub Pages at
|
|||||||
https://google.github.io/googletest/. We recommend browsing the documentation on
|
https://google.github.io/googletest/. We recommend browsing the documentation on
|
||||||
GitHub Pages rather than directly in the repository.
|
GitHub Pages rather than directly in the repository.
|
||||||
|
|
||||||
#### Release 1.14.0
|
#### Release 1.16.0
|
||||||
|
|
||||||
[Release 1.14.0](https://github.com/google/googletest/releases/tag/v1.14.0) is
|
[Release 1.16.0](https://github.com/google/googletest/releases/tag/v1.16.0) is
|
||||||
now available.
|
now available.
|
||||||
|
|
||||||
The 1.14.x branch requires at least C++14.
|
The 1.16.x branch requires at least C++14.
|
||||||
|
|
||||||
|
The 1.16.x branch will be the last to support C++14. Future development will
|
||||||
|
[require at least C++17](https://opensource.google/documentation/policies/cplusplus-support#c_language_standard).
|
||||||
|
|
||||||
#### Continuous Integration
|
#### Continuous Integration
|
||||||
|
|
||||||
|
43
WORKSPACE
43
WORKSPACE
@ -1,4 +1,34 @@
|
|||||||
workspace(name = "com_google_googletest")
|
# Copyright 2024 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.
|
||||||
|
|
||||||
|
workspace(name = "googletest")
|
||||||
|
|
||||||
load("//:googletest_deps.bzl", "googletest_deps")
|
load("//:googletest_deps.bzl", "googletest_deps")
|
||||||
googletest_deps()
|
googletest_deps()
|
||||||
@ -6,13 +36,12 @@ googletest_deps()
|
|||||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||||
|
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "rules_python",
|
name = "rules_python",
|
||||||
sha256 = "d71d2c67e0bce986e1c5a7731b4693226867c45bfe0b7c5e0067228a536fc580",
|
sha256 = "9c6e26911a79fbf510a8f06d8eedb40f412023cf7fa6d1461def27116bff022c",
|
||||||
strip_prefix = "rules_python-0.29.0",
|
strip_prefix = "rules_python-1.1.0",
|
||||||
urls = ["https://github.com/bazelbuild/rules_python/releases/download/0.29.0/rules_python-0.29.0.tar.gz"],
|
url = "https://github.com/bazelbuild/rules_python/releases/download/1.1.0/rules_python-1.1.0.tar.gz",
|
||||||
)
|
)
|
||||||
|
# https://github.com/bazelbuild/rules_python/releases/tag/1.1.0
|
||||||
# https://github.com/bazelbuild/rules_python/releases/tag/0.29.0
|
|
||||||
load("@rules_python//python:repositories.bzl", "py_repositories")
|
load("@rules_python//python:repositories.bzl", "py_repositories")
|
||||||
py_repositories()
|
py_repositories()
|
||||||
|
|
||||||
|
@ -31,51 +31,68 @@
|
|||||||
|
|
||||||
set -euox pipefail
|
set -euox pipefail
|
||||||
|
|
||||||
readonly LINUX_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20240523"
|
readonly LINUX_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20241218"
|
||||||
readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20230120"
|
readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20250205"
|
||||||
|
|
||||||
if [[ -z ${GTEST_ROOT:-} ]]; then
|
if [[ -z ${GTEST_ROOT:-} ]]; then
|
||||||
GTEST_ROOT="$(realpath $(dirname ${0})/..)"
|
GTEST_ROOT="$(realpath $(dirname ${0})/..)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z ${STD:-} ]]; then
|
if [[ -z ${STD:-} ]]; then
|
||||||
STD="c++14 c++17 c++20"
|
STD="c++17 c++20"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Test the CMake build
|
# Test CMake + GCC
|
||||||
for cc in /usr/local/bin/gcc /opt/llvm/clang/bin/clang; do
|
for cmake_off_on in OFF ON; do
|
||||||
for cmake_off_on in OFF ON; do
|
time docker run \
|
||||||
time docker run \
|
--volume="${GTEST_ROOT}:/src:ro" \
|
||||||
--volume="${GTEST_ROOT}:/src:ro" \
|
--tmpfs="/build:exec" \
|
||||||
--tmpfs="/build:exec" \
|
--workdir="/build" \
|
||||||
--workdir="/build" \
|
--rm \
|
||||||
--rm \
|
--env="CC=/usr/local/bin/gcc" \
|
||||||
--env="CC=${cc}" \
|
--env=CXXFLAGS="-Werror -Wdeprecated" \
|
||||||
--env=CXXFLAGS="-Werror -Wdeprecated" \
|
${LINUX_LATEST_CONTAINER} \
|
||||||
${LINUX_LATEST_CONTAINER} \
|
/bin/bash -c "
|
||||||
/bin/bash -c "
|
cmake /src \
|
||||||
cmake /src \
|
-DCMAKE_CXX_STANDARD=17 \
|
||||||
-DCMAKE_CXX_STANDARD=14 \
|
-Dgtest_build_samples=ON \
|
||||||
-Dgtest_build_samples=ON \
|
-Dgtest_build_tests=ON \
|
||||||
-Dgtest_build_tests=ON \
|
-Dgmock_build_tests=ON \
|
||||||
-Dgmock_build_tests=ON \
|
-Dcxx_no_exception=${cmake_off_on} \
|
||||||
-Dcxx_no_exception=${cmake_off_on} \
|
-Dcxx_no_rtti=${cmake_off_on} && \
|
||||||
-Dcxx_no_rtti=${cmake_off_on} && \
|
make -j$(nproc) && \
|
||||||
make -j$(nproc) && \
|
ctest -j$(nproc) --output-on-failure"
|
||||||
ctest -j$(nproc) --output-on-failure"
|
done
|
||||||
done
|
|
||||||
|
# Test CMake + Clang
|
||||||
|
for cmake_off_on in OFF ON; do
|
||||||
|
time docker run \
|
||||||
|
--volume="${GTEST_ROOT}:/src:ro" \
|
||||||
|
--tmpfs="/build:exec" \
|
||||||
|
--workdir="/build" \
|
||||||
|
--rm \
|
||||||
|
--env="CC=/opt/llvm/clang/bin/clang" \
|
||||||
|
--env=CXXFLAGS="-Werror -Wdeprecated --gcc-toolchain=/usr/local" \
|
||||||
|
${LINUX_LATEST_CONTAINER} \
|
||||||
|
/bin/bash -c "
|
||||||
|
cmake /src \
|
||||||
|
-DCMAKE_CXX_STANDARD=17 \
|
||||||
|
-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
|
# Do one test with an older version of GCC
|
||||||
# TODO(googletest-team): This currently uses Bazel 5. When upgrading to a
|
|
||||||
# version of Bazel that supports Bzlmod, add --enable_bzlmod=false to keep test
|
|
||||||
# coverage for the old WORKSPACE dependency management.
|
|
||||||
time docker run \
|
time docker run \
|
||||||
--volume="${GTEST_ROOT}:/src:ro" \
|
--volume="${GTEST_ROOT}:/src:ro" \
|
||||||
--workdir="/src" \
|
--workdir="/src" \
|
||||||
--rm \
|
--rm \
|
||||||
--env="CC=/usr/local/bin/gcc" \
|
--env="CC=/usr/local/bin/gcc" \
|
||||||
--env="BAZEL_CXXOPTS=-std=c++14" \
|
--env="BAZEL_CXXOPTS=-std=c++17" \
|
||||||
${LINUX_GCC_FLOOR_CONTAINER} \
|
${LINUX_GCC_FLOOR_CONTAINER} \
|
||||||
/usr/local/bin/bazel test ... \
|
/usr/local/bin/bazel test ... \
|
||||||
--copt="-Wall" \
|
--copt="-Wall" \
|
||||||
@ -83,6 +100,7 @@ time docker run \
|
|||||||
--copt="-Wuninitialized" \
|
--copt="-Wuninitialized" \
|
||||||
--copt="-Wundef" \
|
--copt="-Wundef" \
|
||||||
--copt="-Wno-error=pragmas" \
|
--copt="-Wno-error=pragmas" \
|
||||||
|
--enable_bzlmod=false \
|
||||||
--features=external_include_paths \
|
--features=external_include_paths \
|
||||||
--keep_going \
|
--keep_going \
|
||||||
--show_timestamps \
|
--show_timestamps \
|
||||||
|
@ -31,6 +31,9 @@
|
|||||||
|
|
||||||
set -euox pipefail
|
set -euox pipefail
|
||||||
|
|
||||||
|
# Use Xcode 16.0
|
||||||
|
sudo xcode-select -s /Applications/Xcode_16.0.app/Contents/Developer
|
||||||
|
|
||||||
if [[ -z ${GTEST_ROOT:-} ]]; then
|
if [[ -z ${GTEST_ROOT:-} ]]; then
|
||||||
GTEST_ROOT="$(realpath $(dirname ${0})/..)"
|
GTEST_ROOT="$(realpath $(dirname ${0})/..)"
|
||||||
fi
|
fi
|
||||||
@ -40,20 +43,20 @@ for cmake_off_on in OFF ON; do
|
|||||||
BUILD_DIR=$(mktemp -d build_dir.XXXXXXXX)
|
BUILD_DIR=$(mktemp -d build_dir.XXXXXXXX)
|
||||||
cd ${BUILD_DIR}
|
cd ${BUILD_DIR}
|
||||||
time cmake ${GTEST_ROOT} \
|
time cmake ${GTEST_ROOT} \
|
||||||
-DCMAKE_CXX_STANDARD=14 \
|
-DCMAKE_CXX_STANDARD=17 \
|
||||||
-Dgtest_build_samples=ON \
|
-Dgtest_build_samples=ON \
|
||||||
-Dgtest_build_tests=ON \
|
-Dgtest_build_tests=ON \
|
||||||
-Dgmock_build_tests=ON \
|
-Dgmock_build_tests=ON \
|
||||||
-Dcxx_no_exception=${cmake_off_on} \
|
-Dcxx_no_exception=${cmake_off_on} \
|
||||||
-Dcxx_no_rtti=${cmake_off_on}
|
-Dcxx_no_rtti=${cmake_off_on}
|
||||||
time make
|
time make -j$(nproc)
|
||||||
time ctest -j$(nproc) --output-on-failure
|
time ctest -j$(nproc) --output-on-failure
|
||||||
done
|
done
|
||||||
|
|
||||||
# Test the Bazel build
|
# Test the Bazel build
|
||||||
|
|
||||||
# If we are running on Kokoro, check for a versioned Bazel binary.
|
# If we are running on Kokoro, check for a versioned Bazel binary.
|
||||||
KOKORO_GFILE_BAZEL_BIN="bazel-7.0.0-darwin-x86_64"
|
KOKORO_GFILE_BAZEL_BIN="bazel-8.0.0-darwin-x86_64"
|
||||||
if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]]; then
|
if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]]; then
|
||||||
BAZEL_BIN="${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN}"
|
BAZEL_BIN="${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN}"
|
||||||
chmod +x ${BAZEL_BIN}
|
chmod +x ${BAZEL_BIN}
|
||||||
@ -67,7 +70,7 @@ for absl in 0 1; do
|
|||||||
--copt="-Wall" \
|
--copt="-Wall" \
|
||||||
--copt="-Werror" \
|
--copt="-Werror" \
|
||||||
--copt="-Wundef" \
|
--copt="-Wundef" \
|
||||||
--cxxopt="-std=c++14" \
|
--cxxopt="-std=c++17" \
|
||||||
--define="absl=${absl}" \
|
--define="absl=${absl}" \
|
||||||
--enable_bzlmod=true \
|
--enable_bzlmod=true \
|
||||||
--features=external_include_paths \
|
--features=external_include_paths \
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
SETLOCAL ENABLEDELAYEDEXPANSION
|
SETLOCAL ENABLEDELAYEDEXPANSION
|
||||||
|
|
||||||
SET BAZEL_EXE=%KOKORO_GFILE_DIR%\bazel-7.0.0-windows-x86_64.exe
|
SET BAZEL_EXE=%KOKORO_GFILE_DIR%\bazel-8.0.0-windows-x86_64.exe
|
||||||
|
|
||||||
SET PATH=C:\Python34;%PATH%
|
SET PATH=C:\Python34;%PATH%
|
||||||
SET BAZEL_PYTHON=C:\python34\python.exe
|
SET BAZEL_PYTHON=C:\python34\python.exe
|
||||||
@ -11,21 +11,18 @@ SET CTEST_OUTPUT_ON_FAILURE=1
|
|||||||
SET CMAKE_BUILD_PARALLEL_LEVEL=16
|
SET CMAKE_BUILD_PARALLEL_LEVEL=16
|
||||||
SET CTEST_PARALLEL_LEVEL=16
|
SET CTEST_PARALLEL_LEVEL=16
|
||||||
|
|
||||||
IF EXIST git\googletest (
|
SET GTEST_ROOT=%~dp0\..
|
||||||
CD git\googletest
|
|
||||||
) ELSE IF EXIST github\googletest (
|
|
||||||
CD github\googletest
|
|
||||||
)
|
|
||||||
|
|
||||||
IF %errorlevel% neq 0 EXIT /B 1
|
IF %errorlevel% neq 0 EXIT /B 1
|
||||||
|
|
||||||
:: ----------------------------------------------------------------------------
|
:: ----------------------------------------------------------------------------
|
||||||
:: CMake
|
:: CMake
|
||||||
MKDIR cmake_msvc2022
|
SET CMAKE_BUILD_PATH=cmake_msvc2022
|
||||||
CD cmake_msvc2022
|
MKDIR %CMAKE_BUILD_PATH%
|
||||||
|
CD %CMAKE_BUILD_PATH%
|
||||||
|
|
||||||
%CMAKE_BIN% .. ^
|
%CMAKE_BIN% %GTEST_ROOT% ^
|
||||||
-G "Visual Studio 17 2022" ^
|
-G "Visual Studio 17 2022" ^
|
||||||
|
-DCMAKE_CXX_STANDARD=17 ^
|
||||||
-DPYTHON_EXECUTABLE:FILEPATH=c:\python37\python.exe ^
|
-DPYTHON_EXECUTABLE:FILEPATH=c:\python37\python.exe ^
|
||||||
-DPYTHON_INCLUDE_DIR:PATH=c:\python37\include ^
|
-DPYTHON_INCLUDE_DIR:PATH=c:\python37\include ^
|
||||||
-DPYTHON_LIBRARY:FILEPATH=c:\python37\lib\site-packages\pip ^
|
-DPYTHON_LIBRARY:FILEPATH=c:\python37\lib\site-packages\pip ^
|
||||||
@ -40,16 +37,36 @@ IF %errorlevel% neq 0 EXIT /B 1
|
|||||||
%CTEST_BIN% -C Debug --timeout 600
|
%CTEST_BIN% -C Debug --timeout 600
|
||||||
IF %errorlevel% neq 0 EXIT /B 1
|
IF %errorlevel% neq 0 EXIT /B 1
|
||||||
|
|
||||||
CD ..
|
CD %GTEST_ROOT%
|
||||||
RMDIR /S /Q cmake_msvc2022
|
RMDIR /S /Q %CMAKE_BUILD_PATH%
|
||||||
|
|
||||||
:: ----------------------------------------------------------------------------
|
:: ----------------------------------------------------------------------------
|
||||||
:: Bazel
|
:: Bazel
|
||||||
|
|
||||||
|
:: The default home directory on Kokoro is a long path which causes errors
|
||||||
|
:: because of Windows limitations on path length.
|
||||||
|
:: --output_user_root=C:\tmp causes Bazel to use a shorter path.
|
||||||
SET BAZEL_VS=C:\Program Files\Microsoft Visual Studio\2022\Community
|
SET BAZEL_VS=C:\Program Files\Microsoft Visual Studio\2022\Community
|
||||||
%BAZEL_EXE% test ... ^
|
|
||||||
|
:: C++17
|
||||||
|
%BAZEL_EXE% ^
|
||||||
|
--output_user_root=C:\tmp ^
|
||||||
|
test ... ^
|
||||||
--compilation_mode=dbg ^
|
--compilation_mode=dbg ^
|
||||||
--copt=/std:c++14 ^
|
--copt=/std:c++17 ^
|
||||||
|
--copt=/WX ^
|
||||||
|
--enable_bzlmod=true ^
|
||||||
|
--keep_going ^
|
||||||
|
--test_output=errors ^
|
||||||
|
--test_tag_filters=-no_test_msvc2017
|
||||||
|
IF %errorlevel% neq 0 EXIT /B 1
|
||||||
|
|
||||||
|
:: C++20
|
||||||
|
%BAZEL_EXE% ^
|
||||||
|
--output_user_root=C:\tmp ^
|
||||||
|
test ... ^
|
||||||
|
--compilation_mode=dbg ^
|
||||||
|
--copt=/std:c++20 ^
|
||||||
--copt=/WX ^
|
--copt=/WX ^
|
||||||
--enable_bzlmod=true ^
|
--enable_bzlmod=true ^
|
||||||
--keep_going ^
|
--keep_going ^
|
||||||
|
106
docs/advanced.md
106
docs/advanced.md
@ -286,7 +286,7 @@ For example:
|
|||||||
```c++
|
```c++
|
||||||
TEST(SkipTest, DoesSkip) {
|
TEST(SkipTest, DoesSkip) {
|
||||||
GTEST_SKIP() << "Skipping single test";
|
GTEST_SKIP() << "Skipping single test";
|
||||||
EXPECT_EQ(0, 1); // Won't fail; it won't be executed
|
FAIL(); // Won't fail; it won't be executed
|
||||||
}
|
}
|
||||||
|
|
||||||
class SkipFixture : public ::testing::Test {
|
class SkipFixture : public ::testing::Test {
|
||||||
@ -298,7 +298,7 @@ class SkipFixture : public ::testing::Test {
|
|||||||
|
|
||||||
// Tests for SkipFixture won't be executed.
|
// Tests for SkipFixture won't be executed.
|
||||||
TEST_F(SkipFixture, SkipsOneTest) {
|
TEST_F(SkipFixture, SkipsOneTest) {
|
||||||
EXPECT_EQ(5, 7); // Won't fail
|
FAIL(); // Won't fail; it won't be executed
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -405,6 +405,51 @@ EXPECT_TRUE(IsCorrectPointIntVector(point_ints))
|
|||||||
For more details regarding `AbslStringify()` and its integration with other
|
For more details regarding `AbslStringify()` and its integration with other
|
||||||
libraries, see go/abslstringify.
|
libraries, see go/abslstringify.
|
||||||
|
|
||||||
|
## Regular Expression Syntax
|
||||||
|
|
||||||
|
When built with Bazel and using Abseil, GoogleTest uses the
|
||||||
|
[RE2](https://github.com/google/re2/wiki/Syntax) syntax. Otherwise, for POSIX
|
||||||
|
systems (Linux, Cygwin, Mac), GoogleTest uses the
|
||||||
|
[POSIX extended regular expression](https://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap09.html#tag_09_04)
|
||||||
|
syntax. To learn about POSIX syntax, you may want to read this
|
||||||
|
[Wikipedia entry](https://en.wikipedia.org/wiki/Regular_expression#POSIX_extended).
|
||||||
|
|
||||||
|
On Windows, GoogleTest uses its own simple regular expression implementation. It
|
||||||
|
lacks many features. For example, we don't support union (`"x|y"`), grouping
|
||||||
|
(`"(xy)"`), brackets (`"[xy]"`), and repetition count (`"x{5,7}"`), among
|
||||||
|
others. Below is what we do support (`A` denotes a literal character, period
|
||||||
|
(`.`), or a single `\\ ` escape sequence; `x` and `y` denote regular
|
||||||
|
expressions.):
|
||||||
|
|
||||||
|
Expression | Meaning
|
||||||
|
---------- | --------------------------------------------------------------
|
||||||
|
`c` | matches any literal character `c`
|
||||||
|
`\\d` | matches any decimal digit
|
||||||
|
`\\D` | matches any character that's not a decimal digit
|
||||||
|
`\\f` | matches `\f`
|
||||||
|
`\\n` | matches `\n`
|
||||||
|
`\\r` | matches `\r`
|
||||||
|
`\\s` | matches any ASCII whitespace, including `\n`
|
||||||
|
`\\S` | matches any character that's not a whitespace
|
||||||
|
`\\t` | matches `\t`
|
||||||
|
`\\v` | matches `\v`
|
||||||
|
`\\w` | matches any letter, `_`, or decimal digit
|
||||||
|
`\\W` | matches any character that `\\w` doesn't match
|
||||||
|
`\\c` | matches any literal character `c`, which must be a punctuation
|
||||||
|
`.` | matches any single character except `\n`
|
||||||
|
`A?` | matches 0 or 1 occurrences of `A`
|
||||||
|
`A*` | matches 0 or many occurrences of `A`
|
||||||
|
`A+` | matches 1 or many occurrences of `A`
|
||||||
|
`^` | matches the beginning of a string (not that of each line)
|
||||||
|
`$` | matches the end of a string (not that of each line)
|
||||||
|
`xy` | matches `x` followed by `y`
|
||||||
|
|
||||||
|
To help you determine which capability is available on your system, GoogleTest
|
||||||
|
defines macros to govern which regular expression it is using. The macros are:
|
||||||
|
`GTEST_USES_SIMPLE_RE=1` or `GTEST_USES_POSIX_RE=1`. If you want your death
|
||||||
|
tests to work in all cases, you can either `#if` on these macros or use the more
|
||||||
|
limited syntax only.
|
||||||
|
|
||||||
## Death Tests
|
## Death Tests
|
||||||
|
|
||||||
In many applications, there are assertions that can cause application failure if
|
In many applications, there are assertions that can cause application failure if
|
||||||
@ -416,7 +461,7 @@ corruption, security holes, or worse. Hence it is vitally important to test that
|
|||||||
such assertion statements work as expected.
|
such assertion statements work as expected.
|
||||||
|
|
||||||
Since these precondition checks cause the processes to die, we call such tests
|
Since these precondition checks cause the processes to die, we call such tests
|
||||||
_death tests_. More generally, any test that checks that a program terminates
|
*death tests*. More generally, any test that checks that a program terminates
|
||||||
(except by throwing an exception) in an expected fashion is also a death test.
|
(except by throwing an exception) in an expected fashion is also a death test.
|
||||||
|
|
||||||
Note that if a piece of code throws an exception, we don't consider it "death"
|
Note that if a piece of code throws an exception, we don't consider it "death"
|
||||||
@ -462,6 +507,12 @@ verifies that:
|
|||||||
exit with exit code 0, and
|
exit with exit code 0, and
|
||||||
* calling `KillProcess()` kills the process with signal `SIGKILL`.
|
* calling `KillProcess()` kills the process with signal `SIGKILL`.
|
||||||
|
|
||||||
|
{: .callout .warning}
|
||||||
|
Warning: If your death test contains mocks and is expecting a specific exit
|
||||||
|
code, then you must allow the mock objects to be leaked via `Mock::AllowLeak`.
|
||||||
|
This is because the mock leak detector will exit with its own error code if it
|
||||||
|
detects a leak.
|
||||||
|
|
||||||
The test function body may contain other assertions and statements as well, if
|
The test function body may contain other assertions and statements as well, if
|
||||||
necessary.
|
necessary.
|
||||||
|
|
||||||
@ -503,51 +554,6 @@ TEST_F(FooDeathTest, DoesThat) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Regular Expression Syntax
|
|
||||||
|
|
||||||
When built with Bazel and using Abseil, GoogleTest uses the
|
|
||||||
[RE2](https://github.com/google/re2/wiki/Syntax) syntax. Otherwise, for POSIX
|
|
||||||
systems (Linux, Cygwin, Mac), GoogleTest uses the
|
|
||||||
[POSIX extended regular expression](https://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap09.html#tag_09_04)
|
|
||||||
syntax. To learn about POSIX syntax, you may want to read this
|
|
||||||
[Wikipedia entry](https://en.wikipedia.org/wiki/Regular_expression#POSIX_extended).
|
|
||||||
|
|
||||||
On Windows, GoogleTest uses its own simple regular expression implementation. It
|
|
||||||
lacks many features. For example, we don't support union (`"x|y"`), grouping
|
|
||||||
(`"(xy)"`), brackets (`"[xy]"`), and repetition count (`"x{5,7}"`), among
|
|
||||||
others. Below is what we do support (`A` denotes a literal character, period
|
|
||||||
(`.`), or a single `\\ ` escape sequence; `x` and `y` denote regular
|
|
||||||
expressions.):
|
|
||||||
|
|
||||||
Expression | Meaning
|
|
||||||
---------- | --------------------------------------------------------------
|
|
||||||
`c` | matches any literal character `c`
|
|
||||||
`\\d` | matches any decimal digit
|
|
||||||
`\\D` | matches any character that's not a decimal digit
|
|
||||||
`\\f` | matches `\f`
|
|
||||||
`\\n` | matches `\n`
|
|
||||||
`\\r` | matches `\r`
|
|
||||||
`\\s` | matches any ASCII whitespace, including `\n`
|
|
||||||
`\\S` | matches any character that's not a whitespace
|
|
||||||
`\\t` | matches `\t`
|
|
||||||
`\\v` | matches `\v`
|
|
||||||
`\\w` | matches any letter, `_`, or decimal digit
|
|
||||||
`\\W` | matches any character that `\\w` doesn't match
|
|
||||||
`\\c` | matches any literal character `c`, which must be a punctuation
|
|
||||||
`.` | matches any single character except `\n`
|
|
||||||
`A?` | matches 0 or 1 occurrences of `A`
|
|
||||||
`A*` | matches 0 or many occurrences of `A`
|
|
||||||
`A+` | matches 1 or many occurrences of `A`
|
|
||||||
`^` | matches the beginning of a string (not that of each line)
|
|
||||||
`$` | matches the end of a string (not that of each line)
|
|
||||||
`xy` | matches `x` followed by `y`
|
|
||||||
|
|
||||||
To help you determine which capability is available on your system, GoogleTest
|
|
||||||
defines macros to govern which regular expression it is using. The macros are:
|
|
||||||
`GTEST_USES_SIMPLE_RE=1` or `GTEST_USES_POSIX_RE=1`. If you want your death
|
|
||||||
tests to work in all cases, you can either `#if` on these macros or use the more
|
|
||||||
limited syntax only.
|
|
||||||
|
|
||||||
### How It Works
|
### How It Works
|
||||||
|
|
||||||
See [Death Assertions](reference/assertions.md#death) in the Assertions
|
See [Death Assertions](reference/assertions.md#death) in the Assertions
|
||||||
@ -727,7 +733,7 @@ Some tips on using `SCOPED_TRACE`:
|
|||||||
### Propagating Fatal Failures
|
### Propagating Fatal Failures
|
||||||
|
|
||||||
A common pitfall when using `ASSERT_*` and `FAIL*` is not understanding that
|
A common pitfall when using `ASSERT_*` and `FAIL*` is not understanding that
|
||||||
when they fail they only abort the _current function_, not the entire test. For
|
when they fail they only abort the *current function*, not the entire test. For
|
||||||
example, the following test will segfault:
|
example, the following test will segfault:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
@ -2382,7 +2388,7 @@ IMPORTANT: The exact format of the JSON document is subject to change.
|
|||||||
|
|
||||||
#### Detecting Test Premature Exit
|
#### Detecting Test Premature Exit
|
||||||
|
|
||||||
Google Test implements the _premature-exit-file_ protocol for test runners to
|
Google Test implements the *premature-exit-file* protocol for test runners to
|
||||||
catch any kind of unexpected exits of test programs. Upon start, Google Test
|
catch any kind of unexpected exits of test programs. Upon start, Google Test
|
||||||
creates the file which will be automatically deleted after all work has been
|
creates the file which will be automatically deleted after all work has been
|
||||||
finished. Then, the test runner can check if this file exists. In case the file
|
finished. Then, the test runner can check if this file exists. In case the file
|
||||||
|
@ -177,7 +177,7 @@ class StackInterface {
|
|||||||
template <typename Elem>
|
template <typename Elem>
|
||||||
class MockStack : public StackInterface<Elem> {
|
class MockStack : public StackInterface<Elem> {
|
||||||
...
|
...
|
||||||
MOCK_METHOD(int, GetSize, (), (override));
|
MOCK_METHOD(int, GetSize, (), (const, override));
|
||||||
MOCK_METHOD(void, Push, (const Elem& x), (override));
|
MOCK_METHOD(void, Push, (const Elem& x), (override));
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
@ -936,8 +936,8 @@ casts a matcher `m` to type `Matcher<T>`. To ensure safety, gMock checks that
|
|||||||
floating-point numbers), the conversion from `T` to `U` is not lossy (in
|
floating-point numbers), the conversion from `T` to `U` is not lossy (in
|
||||||
other words, any value representable by `T` can also be represented by `U`);
|
other words, any value representable by `T` can also be represented by `U`);
|
||||||
and
|
and
|
||||||
3. When `U` is a reference, `T` must also be a reference (as the underlying
|
3. When `U` is a non-const reference, `T` must also be a reference (as the
|
||||||
matcher may be interested in the address of the `U` value).
|
underlying matcher may be interested in the address of the `U` value).
|
||||||
|
|
||||||
The code won't compile if any of these conditions isn't met.
|
The code won't compile if any of these conditions isn't met.
|
||||||
|
|
||||||
@ -3387,9 +3387,9 @@ With this definition, the above assertion will give a better message:
|
|||||||
|
|
||||||
#### Using EXPECT_ Statements in Matchers
|
#### Using EXPECT_ Statements in Matchers
|
||||||
|
|
||||||
You can also use `EXPECT_...` (and `ASSERT_...`) statements inside custom
|
You can also use `EXPECT_...` statements inside custom matcher definitions. In
|
||||||
matcher definitions. In many cases, this allows you to write your matcher more
|
many cases, this allows you to write your matcher more concisely while still
|
||||||
concisely while still providing an informative error message. For example:
|
providing an informative error message. For example:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
MATCHER(IsDivisibleBy7, "") {
|
MATCHER(IsDivisibleBy7, "") {
|
||||||
@ -3419,14 +3419,14 @@ itself, as gMock already prints it for you.
|
|||||||
|
|
||||||
#### Argument Types
|
#### Argument Types
|
||||||
|
|
||||||
The type of the value being matched (`arg_type`) is determined by the
|
The type of the value being matched (`arg_type`) is determined by the context in
|
||||||
context in which you use the matcher and is supplied to you by the compiler, so
|
which you use the matcher and is supplied to you by the compiler, so you don't
|
||||||
you don't need to worry about declaring it (nor can you). This allows the
|
need to worry about declaring it (nor can you). This allows the matcher to be
|
||||||
matcher to be polymorphic. For example, `IsDivisibleBy7()` can be used to match
|
polymorphic. For example, `IsDivisibleBy7()` can be used to match any type where
|
||||||
any type where the value of `(arg % 7) == 0` can be implicitly converted to a
|
the value of `(arg % 7) == 0` can be implicitly converted to a `bool`. In the
|
||||||
`bool`. In the `Bar(IsDivisibleBy7())` example above, if method `Bar()` takes an
|
`Bar(IsDivisibleBy7())` example above, if method `Bar()` takes an `int`,
|
||||||
`int`, `arg_type` will be `int`; if it takes an `unsigned long`, `arg_type` will
|
`arg_type` will be `int`; if it takes an `unsigned long`, `arg_type` will be
|
||||||
be `unsigned long`; and so on.
|
`unsigned long`; and so on.
|
||||||
|
|
||||||
### Writing New Parameterized Matchers Quickly
|
### Writing New Parameterized Matchers Quickly
|
||||||
|
|
||||||
|
@ -73,8 +73,8 @@ Meaning
|
|||||||
Exercise a particular program path with specific input values and verify the results | [TEST()](#simple-tests) | [Test Case][istqb test case]
|
Exercise a particular program path with specific input values and verify the results | [TEST()](#simple-tests) | [Test Case][istqb test case]
|
||||||
|
|
||||||
|
|
||||||
[istqb test case]: https://glossary.istqb.org/en_US/term/test-case-2
|
[istqb test case]: https://glossary.istqb.org/en_US/term/test-case
|
||||||
[istqb test suite]: https://glossary.istqb.org/en_US/term/test-suite-1-3
|
[istqb test suite]: https://glossary.istqb.org/en_US/term/test-suite
|
||||||
|
|
||||||
## Basic Concepts
|
## Basic Concepts
|
||||||
|
|
||||||
|
@ -10,8 +10,8 @@ To complete this tutorial, you'll need:
|
|||||||
|
|
||||||
* A compatible operating system (e.g. Linux, macOS, Windows).
|
* A compatible operating system (e.g. Linux, macOS, Windows).
|
||||||
* A compatible C++ compiler that supports at least C++14.
|
* A compatible C++ compiler that supports at least C++14.
|
||||||
* [Bazel](https://bazel.build/), the preferred build system used by the
|
* [Bazel](https://bazel.build/) 7.0 or higher, the preferred build system used
|
||||||
GoogleTest team.
|
by the GoogleTest team.
|
||||||
|
|
||||||
See [Supported Platforms](platforms.md) for more information about platforms
|
See [Supported Platforms](platforms.md) for more information about platforms
|
||||||
compatible with GoogleTest.
|
compatible with GoogleTest.
|
||||||
@ -28,7 +28,7 @@ A
|
|||||||
[Bazel workspace](https://docs.bazel.build/versions/main/build-ref.html#workspace)
|
[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
|
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
|
software you want to build. Each workspace directory has a text file named
|
||||||
`WORKSPACE` which may be empty, or may contain references to external
|
`MODULE.bazel` which may be empty, or may contain references to external
|
||||||
dependencies required to build the outputs.
|
dependencies required to build the outputs.
|
||||||
|
|
||||||
First, create a directory for your workspace:
|
First, create a directory for your workspace:
|
||||||
@ -37,30 +37,20 @@ First, create a directory for your workspace:
|
|||||||
$ mkdir my_workspace && cd my_workspace
|
$ mkdir my_workspace && cd my_workspace
|
||||||
```
|
```
|
||||||
|
|
||||||
Next, you’ll create the `WORKSPACE` file to specify dependencies. A common and
|
Next, you’ll create the `MODULE.bazel` file to specify dependencies. As of Bazel
|
||||||
recommended way to depend on GoogleTest is to use a
|
7.0, the recommended way to consume GoogleTest is through the
|
||||||
[Bazel external dependency](https://docs.bazel.build/versions/main/external.html)
|
[Bazel Central Registry](https://registry.bazel.build/modules/googletest). To do
|
||||||
via the
|
this, create a `MODULE.bazel` file in the root directory of your Bazel workspace
|
||||||
[`http_archive` rule](https://docs.bazel.build/versions/main/repo/http.html#http_archive).
|
with the following content:
|
||||||
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")
|
# MODULE.bazel
|
||||||
|
|
||||||
http_archive(
|
# Choose the most recent version available at
|
||||||
name = "com_google_googletest",
|
# https://registry.bazel.build/modules/googletest
|
||||||
urls = ["https://github.com/google/googletest/archive/5ab508a01f9eb089207ee87fd547d290da39d015.zip"],
|
bazel_dep(name = "googletest", version = "1.15.2")
|
||||||
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.
|
Now you're ready to build C++ code that uses GoogleTest.
|
||||||
|
|
||||||
## Create and run a binary
|
## Create and run a binary
|
||||||
@ -92,17 +82,20 @@ following contents:
|
|||||||
|
|
||||||
```
|
```
|
||||||
cc_test(
|
cc_test(
|
||||||
name = "hello_test",
|
name = "hello_test",
|
||||||
size = "small",
|
size = "small",
|
||||||
srcs = ["hello_test.cc"],
|
srcs = ["hello_test.cc"],
|
||||||
deps = ["@com_google_googletest//:gtest_main"],
|
deps = [
|
||||||
|
"@googletest//:gtest",
|
||||||
|
"@googletest//:gtest_main",
|
||||||
|
],
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
This `cc_test` rule declares the C++ test binary you want to build, and links to
|
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`
|
the GoogleTest library (`@googletest//:gtest"`) and the GoogleTest `main()`
|
||||||
file (`@com_google_googletest`). For more information about Bazel `BUILD` files,
|
function (`@googletest//:gtest_main`). For more information about Bazel `BUILD`
|
||||||
see the
|
files, see the
|
||||||
[Bazel C++ Tutorial](https://docs.bazel.build/versions/main/tutorial/cpp.html).
|
[Bazel C++ Tutorial](https://docs.bazel.build/versions/main/tutorial/cpp.html).
|
||||||
|
|
||||||
{: .callout .note}
|
{: .callout .note}
|
||||||
@ -115,7 +108,7 @@ on supported language versions.
|
|||||||
Now you can build and run your test:
|
Now you can build and run your test:
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
<strong>my_workspace$ bazel test --cxxopt=-std=c++14 --test_output=all //:hello_test</strong>
|
<strong>$ bazel test --cxxopt=-std=c++14 --test_output=all //:hello_test</strong>
|
||||||
INFO: Analyzed target //:hello_test (26 packages loaded, 362 targets configured).
|
INFO: Analyzed target //:hello_test (26 packages loaded, 362 targets configured).
|
||||||
INFO: Found 1 test target...
|
INFO: Found 1 test target...
|
||||||
INFO: From Testing //:hello_test:
|
INFO: From Testing //:hello_test:
|
||||||
|
@ -24,7 +24,8 @@ provided by GoogleTest. All actions are defined in the `::testing` namespace.
|
|||||||
| :--------------------------------- | :-------------------------------------- |
|
| :--------------------------------- | :-------------------------------------- |
|
||||||
| `Assign(&variable, value)` | Assign `value` to variable. |
|
| `Assign(&variable, value)` | Assign `value` to variable. |
|
||||||
| `DeleteArg<N>()` | Delete the `N`-th (0-based) argument, which must be a pointer. |
|
| `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`. |
|
| `SaveArg<N>(pointer)` | Save the `N`-th (0-based) argument to `*pointer` by copy-assignment. |
|
||||||
|
| `SaveArgByMove<N>(pointer)` | Save the `N`-th (0-based) argument to `*pointer` by move-assignment. |
|
||||||
| `SaveArgPointee<N>(pointer)` | Save the value pointed to by 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. |
|
| `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. |
|
| `SetArgPointee<N>(value)` | Assign `value` to the variable pointed by the `N`-th (0-based) argument. |
|
||||||
|
@ -276,7 +276,8 @@ Units in the Last Place (ULPs). To learn more about ULPs, see the article
|
|||||||
`ASSERT_FLOAT_EQ(`*`val1`*`,`*`val2`*`)`
|
`ASSERT_FLOAT_EQ(`*`val1`*`,`*`val2`*`)`
|
||||||
|
|
||||||
Verifies that the two `float` values *`val1`* and *`val2`* are approximately
|
Verifies that the two `float` values *`val1`* and *`val2`* are approximately
|
||||||
equal, to within 4 ULPs from each other.
|
equal, to within 4 ULPs from each other. Infinity and the largest finite float
|
||||||
|
value are considered to be one ULP apart.
|
||||||
|
|
||||||
### EXPECT_DOUBLE_EQ {#EXPECT_DOUBLE_EQ}
|
### EXPECT_DOUBLE_EQ {#EXPECT_DOUBLE_EQ}
|
||||||
|
|
||||||
@ -284,7 +285,8 @@ equal, to within 4 ULPs from each other.
|
|||||||
`ASSERT_DOUBLE_EQ(`*`val1`*`,`*`val2`*`)`
|
`ASSERT_DOUBLE_EQ(`*`val1`*`,`*`val2`*`)`
|
||||||
|
|
||||||
Verifies that the two `double` values *`val1`* and *`val2`* are approximately
|
Verifies that the two `double` values *`val1`* and *`val2`* are approximately
|
||||||
equal, to within 4 ULPs from each other.
|
equal, to within 4 ULPs from each other. Infinity and the largest finite double
|
||||||
|
value are considered to be one ULP apart.
|
||||||
|
|
||||||
### EXPECT_NEAR {#EXPECT_NEAR}
|
### EXPECT_NEAR {#EXPECT_NEAR}
|
||||||
|
|
||||||
@ -294,6 +296,11 @@ equal, to within 4 ULPs from each other.
|
|||||||
Verifies that the difference between *`val1`* and *`val2`* does not exceed the
|
Verifies that the difference between *`val1`* and *`val2`* does not exceed the
|
||||||
absolute error bound *`abs_error`*.
|
absolute error bound *`abs_error`*.
|
||||||
|
|
||||||
|
If *`val`* and *`val2`* are both infinity of the same sign, the difference is
|
||||||
|
considered to be 0. Otherwise, if either value is infinity, the difference is
|
||||||
|
considered to be infinity. All non-NaN values (including infinity) are
|
||||||
|
considered to not exceed an *`abs_error`* of infinity.
|
||||||
|
|
||||||
## Exception Assertions {#exceptions}
|
## Exception Assertions {#exceptions}
|
||||||
|
|
||||||
The following assertions verify that a piece of code throws, or does not throw,
|
The following assertions verify that a piece of code throws, or does not throw,
|
||||||
|
@ -171,6 +171,11 @@ messages, you can use:
|
|||||||
| `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(&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.
|
| `Property(property_name, &class::property, m)` | The same as the two-parameter version, but provides a better error message.
|
||||||
|
|
||||||
|
{: .callout .warning}
|
||||||
|
Warning: 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.
|
||||||
|
|
||||||
**Notes:**
|
**Notes:**
|
||||||
|
|
||||||
* You can use `FieldsAre()` to match any type that supports structured
|
* You can use `FieldsAre()` to match any type that supports structured
|
||||||
@ -189,10 +194,6 @@ messages, you can use:
|
|||||||
EXPECT_THAT(s, FieldsAre(42, "aloha"));
|
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
|
## Matching the Result of a Function, Functor, or Callback
|
||||||
|
|
||||||
| Matcher | Description |
|
| Matcher | Description |
|
||||||
|
@ -1,10 +1,20 @@
|
|||||||
"""Provides a fake @fuchsia_sdk implementation that's used when the real one isn't available.
|
"""Provides a fake @fuchsia_sdk implementation that's used when the real one isn't available.
|
||||||
|
|
||||||
This is needed since bazel queries on targets that depend on //:gtest (eg:
|
GoogleTest can be used with the [Fuchsia](https://fuchsia.dev/) SDK. However,
|
||||||
`bazel query "deps(set(//googletest/test:gtest_all_test))"`) will fail if @fuchsia_sdk is not
|
because the Fuchsia SDK does not yet support bzlmod, GoogleTest's `MODULE.bazel`
|
||||||
defined when bazel is evaluating the transitive closure of the query target.
|
file by default provides a "fake" Fuchsia SDK.
|
||||||
|
|
||||||
See https://github.com/google/googletest/issues/4472.
|
To override this and use the real Fuchsia SDK, you can add the following to your
|
||||||
|
project's `MODULE.bazel` file:
|
||||||
|
|
||||||
|
fake_fuchsia_sdk_extension =
|
||||||
|
use_extension("@com_google_googletest//:fake_fuchsia_sdk.bzl", "fuchsia_sdk")
|
||||||
|
override_repo(fake_fuchsia_sdk_extension, "fuchsia_sdk")
|
||||||
|
|
||||||
|
NOTE: The `override_repo` built-in is only available in Bazel 8.0 and higher.
|
||||||
|
|
||||||
|
See https://github.com/google/googletest/issues/4472 for more details of why the
|
||||||
|
fake Fuchsia SDK is needed.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _fake_fuchsia_sdk_impl(repo_ctx):
|
def _fake_fuchsia_sdk_impl(repo_ctx):
|
||||||
@ -31,3 +41,21 @@ fake_fuchsia_sdk = repository_rule(
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
_create_fake = tag_class()
|
||||||
|
|
||||||
|
def _fuchsia_sdk_impl(module_ctx):
|
||||||
|
create_fake_sdk = False
|
||||||
|
for mod in module_ctx.modules:
|
||||||
|
for _ in mod.tags.create_fake:
|
||||||
|
create_fake_sdk = True
|
||||||
|
|
||||||
|
if create_fake_sdk:
|
||||||
|
fake_fuchsia_sdk(name = "fuchsia_sdk")
|
||||||
|
|
||||||
|
return module_ctx.extension_metadata(reproducible = True)
|
||||||
|
|
||||||
|
fuchsia_sdk = module_extension(
|
||||||
|
implementation = _fuchsia_sdk_impl,
|
||||||
|
tag_classes = {"create_fake": _create_fake},
|
||||||
|
)
|
||||||
|
@ -1493,6 +1493,7 @@ class DoAllAction<FinalAction> {
|
|||||||
// providing a call operator because even with a particular set of arguments
|
// providing a call operator because even with a particular set of arguments
|
||||||
// they don't have a fixed return type.
|
// they don't have a fixed return type.
|
||||||
|
|
||||||
|
// We support conversion to OnceAction whenever the sub-action does.
|
||||||
template <typename R, typename... Args,
|
template <typename R, typename... Args,
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
std::is_convertible<FinalAction, OnceAction<R(Args...)>>::value,
|
std::is_convertible<FinalAction, OnceAction<R(Args...)>>::value,
|
||||||
@ -1501,6 +1502,21 @@ class DoAllAction<FinalAction> {
|
|||||||
return std::move(final_action_);
|
return std::move(final_action_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We also support conversion to OnceAction whenever the sub-action supports
|
||||||
|
// conversion to Action (since any Action can also be a OnceAction).
|
||||||
|
template <
|
||||||
|
typename R, typename... Args,
|
||||||
|
typename std::enable_if<
|
||||||
|
conjunction<
|
||||||
|
negation<
|
||||||
|
std::is_convertible<FinalAction, OnceAction<R(Args...)>>>,
|
||||||
|
std::is_convertible<FinalAction, Action<R(Args...)>>>::value,
|
||||||
|
int>::type = 0>
|
||||||
|
operator OnceAction<R(Args...)>() && { // NOLINT
|
||||||
|
return Action<R(Args...)>(std::move(final_action_));
|
||||||
|
}
|
||||||
|
|
||||||
|
// We support conversion to Action whenever the sub-action does.
|
||||||
template <
|
template <
|
||||||
typename R, typename... Args,
|
typename R, typename... Args,
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
@ -1580,16 +1596,16 @@ class DoAllAction<InitialAction, OtherActions...>
|
|||||||
: Base({}, std::forward<U>(other_actions)...),
|
: Base({}, std::forward<U>(other_actions)...),
|
||||||
initial_action_(std::forward<T>(initial_action)) {}
|
initial_action_(std::forward<T>(initial_action)) {}
|
||||||
|
|
||||||
template <typename R, typename... Args,
|
// We support conversion to OnceAction whenever both the initial action and
|
||||||
typename std::enable_if<
|
// the rest support conversion to OnceAction.
|
||||||
conjunction<
|
template <
|
||||||
// Both the initial action and the rest must support
|
typename R, typename... Args,
|
||||||
// conversion to OnceAction.
|
typename std::enable_if<
|
||||||
std::is_convertible<
|
conjunction<std::is_convertible<
|
||||||
InitialAction,
|
InitialAction,
|
||||||
OnceAction<void(InitialActionArgType<Args>...)>>,
|
OnceAction<void(InitialActionArgType<Args>...)>>,
|
||||||
std::is_convertible<Base, OnceAction<R(Args...)>>>::value,
|
std::is_convertible<Base, OnceAction<R(Args...)>>>::value,
|
||||||
int>::type = 0>
|
int>::type = 0>
|
||||||
operator OnceAction<R(Args...)>() && { // NOLINT
|
operator OnceAction<R(Args...)>() && { // NOLINT
|
||||||
// Return an action that first calls the initial action with arguments
|
// Return an action that first calls the initial action with arguments
|
||||||
// filtered through InitialActionArgType, then forwards arguments directly
|
// filtered through InitialActionArgType, then forwards arguments directly
|
||||||
@ -1612,12 +1628,34 @@ class DoAllAction<InitialAction, OtherActions...>
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We also support conversion to OnceAction whenever the initial action
|
||||||
|
// supports conversion to Action (since any Action can also be a OnceAction).
|
||||||
|
//
|
||||||
|
// The remaining sub-actions must also be compatible, but we don't need to
|
||||||
|
// special case them because the base class deals with them.
|
||||||
|
template <
|
||||||
|
typename R, typename... Args,
|
||||||
|
typename std::enable_if<
|
||||||
|
conjunction<
|
||||||
|
negation<std::is_convertible<
|
||||||
|
InitialAction,
|
||||||
|
OnceAction<void(InitialActionArgType<Args>...)>>>,
|
||||||
|
std::is_convertible<InitialAction,
|
||||||
|
Action<void(InitialActionArgType<Args>...)>>,
|
||||||
|
std::is_convertible<Base, OnceAction<R(Args...)>>>::value,
|
||||||
|
int>::type = 0>
|
||||||
|
operator OnceAction<R(Args...)>() && { // NOLINT
|
||||||
|
return DoAll(
|
||||||
|
Action<void(InitialActionArgType<Args>...)>(std::move(initial_action_)),
|
||||||
|
std::move(static_cast<Base&>(*this)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// We support conversion to Action whenever both the initial action and the
|
||||||
|
// rest support conversion to Action.
|
||||||
template <
|
template <
|
||||||
typename R, typename... Args,
|
typename R, typename... Args,
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
conjunction<
|
conjunction<
|
||||||
// Both the initial action and the rest must support conversion to
|
|
||||||
// Action.
|
|
||||||
std::is_convertible<const InitialAction&,
|
std::is_convertible<const InitialAction&,
|
||||||
Action<void(InitialActionArgType<Args>...)>>,
|
Action<void(InitialActionArgType<Args>...)>>,
|
||||||
std::is_convertible<const Base&, Action<R(Args...)>>>::value,
|
std::is_convertible<const Base&, Action<R(Args...)>>>::value,
|
||||||
@ -1665,8 +1703,9 @@ template <size_t k>
|
|||||||
struct ReturnArgAction {
|
struct ReturnArgAction {
|
||||||
template <typename... Args,
|
template <typename... Args,
|
||||||
typename = typename std::enable_if<(k < sizeof...(Args))>::type>
|
typename = typename std::enable_if<(k < sizeof...(Args))>::type>
|
||||||
auto operator()(Args&&... args) const -> decltype(std::get<k>(
|
auto operator()(Args&&... args) const
|
||||||
std::forward_as_tuple(std::forward<Args>(args)...))) {
|
-> decltype(std::get<k>(
|
||||||
|
std::forward_as_tuple(std::forward<Args>(args)...))) {
|
||||||
return std::get<k>(std::forward_as_tuple(std::forward<Args>(args)...));
|
return std::get<k>(std::forward_as_tuple(std::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1681,6 +1720,16 @@ struct SaveArgAction {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <size_t k, typename Ptr>
|
||||||
|
struct SaveArgByMoveAction {
|
||||||
|
Ptr pointer;
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
void operator()(Args&&... args) const {
|
||||||
|
*pointer = std::move(std::get<k>(std::tie(args...)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <size_t k, typename Ptr>
|
template <size_t k, typename Ptr>
|
||||||
struct SaveArgPointeeAction {
|
struct SaveArgPointeeAction {
|
||||||
Ptr pointer;
|
Ptr pointer;
|
||||||
@ -2031,6 +2080,13 @@ internal::SaveArgAction<k, Ptr> SaveArg(Ptr pointer) {
|
|||||||
return {pointer};
|
return {pointer};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Action SaveArgByMove<k>(pointer) moves the k-th (0-based) argument of the
|
||||||
|
// mock function into *pointer.
|
||||||
|
template <size_t k, typename Ptr>
|
||||||
|
internal::SaveArgByMoveAction<k, Ptr> SaveArgByMove(Ptr pointer) {
|
||||||
|
return {pointer};
|
||||||
|
}
|
||||||
|
|
||||||
// Action SaveArgPointee<k>(pointer) saves the value pointed to
|
// Action SaveArgPointee<k>(pointer) saves the value pointed to
|
||||||
// by the k-th (0-based) argument of the mock function to *pointer.
|
// by the k-th (0-based) argument of the mock function to *pointer.
|
||||||
template <size_t k, typename Ptr>
|
template <size_t k, typename Ptr>
|
||||||
|
@ -408,13 +408,22 @@ class MatcherCastImpl<T, Matcher<U>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Impl : public MatcherInterface<T> {
|
// If it's possible to implicitly convert a `const T&` to U, then `Impl` can
|
||||||
|
// take that as input to avoid a copy. Otherwise, such as when `T` is a
|
||||||
|
// non-const reference type or a type explicitly constructible only from a
|
||||||
|
// non-const reference, then `Impl` must use `T` as-is (potentially copying).
|
||||||
|
using ImplArgT =
|
||||||
|
typename std::conditional<std::is_convertible<const T&, const U&>::value,
|
||||||
|
const T&, T>::type;
|
||||||
|
|
||||||
|
class Impl : public MatcherInterface<ImplArgT> {
|
||||||
public:
|
public:
|
||||||
explicit Impl(const Matcher<U>& source_matcher)
|
explicit Impl(const Matcher<U>& source_matcher)
|
||||||
: source_matcher_(source_matcher) {}
|
: source_matcher_(source_matcher) {}
|
||||||
|
|
||||||
// We delegate the matching logic to the source matcher.
|
// We delegate the matching logic to the source matcher.
|
||||||
bool MatchAndExplain(T x, MatchResultListener* listener) const override {
|
bool MatchAndExplain(ImplArgT x,
|
||||||
|
MatchResultListener* listener) const override {
|
||||||
using FromType = typename std::remove_cv<typename std::remove_pointer<
|
using FromType = typename std::remove_cv<typename std::remove_pointer<
|
||||||
typename std::remove_reference<T>::type>::type>::type;
|
typename std::remove_reference<T>::type>::type>::type;
|
||||||
using ToType = typename std::remove_cv<typename std::remove_pointer<
|
using ToType = typename std::remove_cv<typename std::remove_pointer<
|
||||||
@ -431,9 +440,8 @@ class MatcherCastImpl<T, Matcher<U>> {
|
|||||||
|
|
||||||
// Do the cast to `U` explicitly if necessary.
|
// Do the cast to `U` explicitly if necessary.
|
||||||
// Otherwise, let implicit conversions do the trick.
|
// Otherwise, let implicit conversions do the trick.
|
||||||
using CastType =
|
using CastType = typename std::conditional<
|
||||||
typename std::conditional<std::is_convertible<T&, const U&>::value,
|
std::is_convertible<ImplArgT&, const U&>::value, ImplArgT&, U>::type;
|
||||||
T&, U>::type;
|
|
||||||
|
|
||||||
return source_matcher_.MatchAndExplain(static_cast<CastType>(x),
|
return source_matcher_.MatchAndExplain(static_cast<CastType>(x),
|
||||||
listener);
|
listener);
|
||||||
@ -528,18 +536,16 @@ inline Matcher<T> SafeMatcherCast(const M& polymorphic_matcher_or_value) {
|
|||||||
// safely convert a Matcher<U> to a Matcher<T> (i.e. Matcher is
|
// safely convert a Matcher<U> to a Matcher<T> (i.e. Matcher is
|
||||||
// contravariant): just keep a copy of the original Matcher<U>, convert the
|
// contravariant): just keep a copy of the original Matcher<U>, convert the
|
||||||
// argument from type T to U, and then pass it to the underlying Matcher<U>.
|
// argument from type T to U, and then pass it to the underlying Matcher<U>.
|
||||||
// The only exception is when U is a reference and T is not, as the
|
// The only exception is when U is a non-const reference and T is not, as the
|
||||||
// underlying Matcher<U> may be interested in the argument's address, which
|
// underlying Matcher<U> may be interested in the argument's address, which
|
||||||
// is not preserved in the conversion from T to U.
|
// cannot be preserved in the conversion from T to U (since a copy of the input
|
||||||
|
// T argument would be required to provide a non-const reference U).
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
inline Matcher<T> SafeMatcherCast(const Matcher<U>& matcher) {
|
inline Matcher<T> SafeMatcherCast(const Matcher<U>& matcher) {
|
||||||
// Enforce that T can be implicitly converted to U.
|
// Enforce that T can be implicitly converted to U.
|
||||||
static_assert(std::is_convertible<const T&, const U&>::value,
|
static_assert(std::is_convertible<const T&, const U&>::value,
|
||||||
"T must be implicitly convertible to U");
|
"T must be implicitly convertible to U (and T must be a "
|
||||||
// Enforce that we are not converting a non-reference type T to a reference
|
"non-const reference if U is a non-const reference)");
|
||||||
// type U.
|
|
||||||
static_assert(std::is_reference<T>::value || !std::is_reference<U>::value,
|
|
||||||
"cannot convert non reference arg to reference");
|
|
||||||
// In case both T and U are arithmetic types, enforce that the
|
// In case both T and U are arithmetic types, enforce that the
|
||||||
// conversion is not lossy.
|
// conversion is not lossy.
|
||||||
typedef GTEST_REMOVE_REFERENCE_AND_CONST_(T) RawT;
|
typedef GTEST_REMOVE_REFERENCE_AND_CONST_(T) RawT;
|
||||||
@ -561,6 +567,11 @@ Matcher<T> A();
|
|||||||
// and MUST NOT BE USED IN USER CODE!!!
|
// and MUST NOT BE USED IN USER CODE!!!
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
// Used per go/ranked-overloads for dispatching.
|
||||||
|
struct Rank0 {};
|
||||||
|
struct Rank1 : Rank0 {};
|
||||||
|
using HighestRank = Rank1;
|
||||||
|
|
||||||
// If the explanation is not empty, prints it to the ostream.
|
// If the explanation is not empty, prints it to the ostream.
|
||||||
inline void PrintIfNotEmpty(const std::string& explanation,
|
inline void PrintIfNotEmpty(const std::string& explanation,
|
||||||
::std::ostream* os) {
|
::std::ostream* os) {
|
||||||
@ -1300,34 +1311,48 @@ class AllOfMatcherImpl : public MatcherInterface<const T&> {
|
|||||||
|
|
||||||
bool MatchAndExplain(const T& x,
|
bool MatchAndExplain(const T& x,
|
||||||
MatchResultListener* listener) const override {
|
MatchResultListener* listener) const override {
|
||||||
// If either matcher1_ or matcher2_ doesn't match x, we only need
|
// This method uses matcher's explanation when explaining the result.
|
||||||
// to explain why one of them fails.
|
// However, if matcher doesn't provide one, this method uses matcher's
|
||||||
|
// description.
|
||||||
std::string all_match_result;
|
std::string all_match_result;
|
||||||
|
for (const Matcher<T>& matcher : matchers_) {
|
||||||
for (size_t i = 0; i < matchers_.size(); ++i) {
|
|
||||||
StringMatchResultListener slistener;
|
StringMatchResultListener slistener;
|
||||||
if (matchers_[i].MatchAndExplain(x, &slistener)) {
|
// Return explanation for first failed matcher.
|
||||||
if (all_match_result.empty()) {
|
if (!matcher.MatchAndExplain(x, &slistener)) {
|
||||||
all_match_result = slistener.str();
|
const std::string explanation = slistener.str();
|
||||||
|
if (!explanation.empty()) {
|
||||||
|
*listener << explanation;
|
||||||
} else {
|
} else {
|
||||||
std::string result = slistener.str();
|
*listener << "which doesn't match (" << Describe(matcher) << ")";
|
||||||
if (!result.empty()) {
|
|
||||||
all_match_result += ", and ";
|
|
||||||
all_match_result += result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
*listener << slistener.str();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// Keep track of explanations in case all matchers succeed.
|
||||||
|
std::string explanation = slistener.str();
|
||||||
|
if (explanation.empty()) {
|
||||||
|
explanation = Describe(matcher);
|
||||||
|
}
|
||||||
|
if (all_match_result.empty()) {
|
||||||
|
all_match_result = explanation;
|
||||||
|
} else {
|
||||||
|
if (!explanation.empty()) {
|
||||||
|
all_match_result += ", and ";
|
||||||
|
all_match_result += explanation;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise we need to explain why *both* of them match.
|
|
||||||
*listener << all_match_result;
|
*listener << all_match_result;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Returns matcher description as a string.
|
||||||
|
std::string Describe(const Matcher<T>& matcher) const {
|
||||||
|
StringMatchResultListener listener;
|
||||||
|
matcher.DescribeTo(listener.stream());
|
||||||
|
return listener.str();
|
||||||
|
}
|
||||||
const std::vector<Matcher<T>> matchers_;
|
const std::vector<Matcher<T>> matchers_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1405,34 +1430,55 @@ class AnyOfMatcherImpl : public MatcherInterface<const T&> {
|
|||||||
|
|
||||||
bool MatchAndExplain(const T& x,
|
bool MatchAndExplain(const T& x,
|
||||||
MatchResultListener* listener) const override {
|
MatchResultListener* listener) const override {
|
||||||
|
// This method uses matcher's explanation when explaining the result.
|
||||||
|
// However, if matcher doesn't provide one, this method uses matcher's
|
||||||
|
// description.
|
||||||
std::string no_match_result;
|
std::string no_match_result;
|
||||||
|
for (const Matcher<T>& matcher : matchers_) {
|
||||||
// If either matcher1_ or matcher2_ matches x, we just need to
|
|
||||||
// explain why *one* of them matches.
|
|
||||||
for (size_t i = 0; i < matchers_.size(); ++i) {
|
|
||||||
StringMatchResultListener slistener;
|
StringMatchResultListener slistener;
|
||||||
if (matchers_[i].MatchAndExplain(x, &slistener)) {
|
// Return explanation for first match.
|
||||||
*listener << slistener.str();
|
if (matcher.MatchAndExplain(x, &slistener)) {
|
||||||
return true;
|
const std::string explanation = slistener.str();
|
||||||
} else {
|
if (!explanation.empty()) {
|
||||||
if (no_match_result.empty()) {
|
*listener << explanation;
|
||||||
no_match_result = slistener.str();
|
|
||||||
} else {
|
} else {
|
||||||
std::string result = slistener.str();
|
*listener << "which matches (" << Describe(matcher) << ")";
|
||||||
if (!result.empty()) {
|
}
|
||||||
no_match_result += ", and ";
|
return true;
|
||||||
no_match_result += result;
|
}
|
||||||
}
|
// Keep track of explanations in case there is no match.
|
||||||
|
std::string explanation = slistener.str();
|
||||||
|
if (explanation.empty()) {
|
||||||
|
explanation = DescribeNegation(matcher);
|
||||||
|
}
|
||||||
|
if (no_match_result.empty()) {
|
||||||
|
no_match_result = explanation;
|
||||||
|
} else {
|
||||||
|
if (!explanation.empty()) {
|
||||||
|
no_match_result += ", and ";
|
||||||
|
no_match_result += explanation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise we need to explain why *both* of them fail.
|
|
||||||
*listener << no_match_result;
|
*listener << no_match_result;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Returns matcher description as a string.
|
||||||
|
std::string Describe(const Matcher<T>& matcher) const {
|
||||||
|
StringMatchResultListener listener;
|
||||||
|
matcher.DescribeTo(listener.stream());
|
||||||
|
return listener.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DescribeNegation(const Matcher<T>& matcher) const {
|
||||||
|
StringMatchResultListener listener;
|
||||||
|
matcher.DescribeNegationTo(listener.stream());
|
||||||
|
return listener.str();
|
||||||
|
}
|
||||||
|
|
||||||
const std::vector<Matcher<T>> matchers_;
|
const std::vector<Matcher<T>> matchers_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1483,7 +1529,7 @@ class SomeOfArrayMatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const ::std::vector<T> matchers_;
|
const std::vector<std::remove_const_t<T>> matchers_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -2235,6 +2281,9 @@ class ResultOfMatcher {
|
|||||||
class Impl : public MatcherInterface<T> {
|
class Impl : public MatcherInterface<T> {
|
||||||
using ResultType = decltype(CallableTraits<Callable>::template Invoke<T>(
|
using ResultType = decltype(CallableTraits<Callable>::template Invoke<T>(
|
||||||
std::declval<CallableStorageType>(), std::declval<T>()));
|
std::declval<CallableStorageType>(), std::declval<T>()));
|
||||||
|
using InnerType = std::conditional_t<
|
||||||
|
std::is_lvalue_reference<ResultType>::value,
|
||||||
|
const typename std::remove_reference<ResultType>::type&, ResultType>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename M>
|
template <typename M>
|
||||||
@ -2242,7 +2291,7 @@ class ResultOfMatcher {
|
|||||||
const CallableStorageType& callable, const M& matcher)
|
const CallableStorageType& callable, const M& matcher)
|
||||||
: result_description_(result_description),
|
: result_description_(result_description),
|
||||||
callable_(callable),
|
callable_(callable),
|
||||||
matcher_(MatcherCast<ResultType>(matcher)) {}
|
matcher_(MatcherCast<InnerType>(matcher)) {}
|
||||||
|
|
||||||
void DescribeTo(::std::ostream* os) const override {
|
void DescribeTo(::std::ostream* os) const override {
|
||||||
if (result_description_.empty()) {
|
if (result_description_.empty()) {
|
||||||
@ -2272,7 +2321,7 @@ class ResultOfMatcher {
|
|||||||
// takes a non-const reference as argument.
|
// takes a non-const reference as argument.
|
||||||
// Also, specifying template argument explicitly is needed because T could
|
// Also, specifying template argument explicitly is needed because T could
|
||||||
// be a non-const reference (e.g. Matcher<Uncopyable&>).
|
// be a non-const reference (e.g. Matcher<Uncopyable&>).
|
||||||
ResultType result =
|
InnerType result =
|
||||||
CallableTraits<Callable>::template Invoke<T>(callable_, obj);
|
CallableTraits<Callable>::template Invoke<T>(callable_, obj);
|
||||||
return MatchPrintAndExplain(result, matcher_, listener);
|
return MatchPrintAndExplain(result, matcher_, listener);
|
||||||
}
|
}
|
||||||
@ -2285,7 +2334,7 @@ class ResultOfMatcher {
|
|||||||
// use stateful callables with ResultOf(), which doesn't guarantee
|
// use stateful callables with ResultOf(), which doesn't guarantee
|
||||||
// how many times the callable will be invoked.
|
// how many times the callable will be invoked.
|
||||||
mutable CallableStorageType callable_;
|
mutable CallableStorageType callable_;
|
||||||
const Matcher<ResultType> matcher_;
|
const Matcher<InnerType> matcher_;
|
||||||
}; // class Impl
|
}; // class Impl
|
||||||
|
|
||||||
const std::string result_description_;
|
const std::string result_description_;
|
||||||
@ -2920,10 +2969,6 @@ class EachMatcher {
|
|||||||
const M inner_matcher_;
|
const M inner_matcher_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Use go/ranked-overloads for dispatching.
|
|
||||||
struct Rank0 {};
|
|
||||||
struct Rank1 : Rank0 {};
|
|
||||||
|
|
||||||
namespace pair_getters {
|
namespace pair_getters {
|
||||||
using std::get;
|
using std::get;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -3255,6 +3300,11 @@ auto UnpackStructImpl(const T& t, std::make_index_sequence<19>, char) {
|
|||||||
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s] = t;
|
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s] = t;
|
||||||
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s);
|
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s);
|
||||||
}
|
}
|
||||||
|
template <typename T>
|
||||||
|
auto UnpackStructImpl(const T& u, std::make_index_sequence<20>, char) {
|
||||||
|
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t] = u;
|
||||||
|
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t);
|
||||||
|
}
|
||||||
#endif // defined(__cpp_structured_bindings)
|
#endif // defined(__cpp_structured_bindings)
|
||||||
|
|
||||||
template <size_t I, typename T>
|
template <size_t I, typename T>
|
||||||
@ -3769,7 +3819,7 @@ class UnorderedElementsAreArrayMatcher {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
UnorderedMatcherRequire::Flags match_flags_;
|
UnorderedMatcherRequire::Flags match_flags_;
|
||||||
::std::vector<T> matchers_;
|
std::vector<std::remove_const_t<T>> matchers_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Implements ElementsAreArray().
|
// Implements ElementsAreArray().
|
||||||
@ -3790,7 +3840,7 @@ class ElementsAreArrayMatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const ::std::vector<T> matchers_;
|
const std::vector<std::remove_const_t<T>> matchers_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Given a 2-tuple matcher tm of type Tuple2Matcher and a value second
|
// Given a 2-tuple matcher tm of type Tuple2Matcher and a value second
|
||||||
@ -3877,6 +3927,21 @@ GTEST_API_ std::string FormatMatcherDescription(
|
|||||||
bool negation, const char* matcher_name,
|
bool negation, const char* matcher_name,
|
||||||
const std::vector<const char*>& param_names, const Strings& param_values);
|
const std::vector<const char*>& param_names, const Strings& param_values);
|
||||||
|
|
||||||
|
// Overloads to support `OptionalMatcher` being used with a type that either
|
||||||
|
// supports implicit conversion to bool or a `has_value()` method.
|
||||||
|
template <typename Optional>
|
||||||
|
auto IsOptionalEngaged(const Optional& optional,
|
||||||
|
Rank1) -> decltype(!!optional) {
|
||||||
|
// The use of double-negation here is to preserve historical behavior where
|
||||||
|
// the matcher used `operator!` rather than directly using `operator bool`.
|
||||||
|
return !static_cast<bool>(!optional);
|
||||||
|
}
|
||||||
|
template <typename Optional>
|
||||||
|
auto IsOptionalEngaged(const Optional& optional,
|
||||||
|
Rank0) -> decltype(!optional.has_value()) {
|
||||||
|
return optional.has_value();
|
||||||
|
}
|
||||||
|
|
||||||
// Implements a matcher that checks the value of a optional<> type variable.
|
// Implements a matcher that checks the value of a optional<> type variable.
|
||||||
template <typename ValueMatcher>
|
template <typename ValueMatcher>
|
||||||
class OptionalMatcher {
|
class OptionalMatcher {
|
||||||
@ -3909,7 +3974,7 @@ class OptionalMatcher {
|
|||||||
|
|
||||||
bool MatchAndExplain(Optional optional,
|
bool MatchAndExplain(Optional optional,
|
||||||
MatchResultListener* listener) const override {
|
MatchResultListener* listener) const override {
|
||||||
if (!optional) {
|
if (!IsOptionalEngaged(optional, HighestRank())) {
|
||||||
*listener << "which is not engaged";
|
*listener << "which is not engaged";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -4388,6 +4453,10 @@ inline PolymorphicMatcher<internal::FieldMatcher<Class, FieldType>> Field(
|
|||||||
// matches 'matcher'. For example,
|
// matches 'matcher'. For example,
|
||||||
// Property(&Foo::str, StartsWith("hi"))
|
// Property(&Foo::str, StartsWith("hi"))
|
||||||
// matches a Foo object x if and only if x.str() starts with "hi".
|
// matches a Foo object x if and only if x.str() starts with "hi".
|
||||||
|
//
|
||||||
|
// Warning: 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.
|
||||||
template <typename Class, typename PropertyType, typename PropertyMatcher>
|
template <typename Class, typename PropertyType, typename PropertyMatcher>
|
||||||
inline PolymorphicMatcher<internal::PropertyMatcher<
|
inline PolymorphicMatcher<internal::PropertyMatcher<
|
||||||
Class, PropertyType, PropertyType (Class::*)() const>>
|
Class, PropertyType, PropertyType (Class::*)() const>>
|
||||||
@ -4742,9 +4811,10 @@ Pointwise(const TupleMatcher& tuple_matcher, const Container& rhs) {
|
|||||||
|
|
||||||
// Supports the Pointwise(m, {a, b, c}) syntax.
|
// Supports the Pointwise(m, {a, b, c}) syntax.
|
||||||
template <typename TupleMatcher, typename T>
|
template <typename TupleMatcher, typename T>
|
||||||
inline internal::PointwiseMatcher<TupleMatcher, std::vector<T>> Pointwise(
|
inline internal::PointwiseMatcher<TupleMatcher,
|
||||||
const TupleMatcher& tuple_matcher, std::initializer_list<T> rhs) {
|
std::vector<std::remove_const_t<T>>>
|
||||||
return Pointwise(tuple_matcher, std::vector<T>(rhs));
|
Pointwise(const TupleMatcher& tuple_matcher, std::initializer_list<T> rhs) {
|
||||||
|
return Pointwise(tuple_matcher, std::vector<std::remove_const_t<T>>(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnorderedPointwise(pair_matcher, rhs) matches an STL-style
|
// UnorderedPointwise(pair_matcher, rhs) matches an STL-style
|
||||||
@ -4906,7 +4976,7 @@ inline internal::UnorderedElementsAreArrayMatcher<T> IsSupersetOf(
|
|||||||
// - {1} matches IsSubsetOf({Gt(0), Lt(0)}), as 1 matches Gt(0).
|
// - {1} matches IsSubsetOf({Gt(0), Lt(0)}), as 1 matches Gt(0).
|
||||||
// - {1, -1} matches IsSubsetOf({Lt(0), Gt(0)}), as 1 matches Gt(0) and -1
|
// - {1, -1} matches IsSubsetOf({Lt(0), Gt(0)}), as 1 matches Gt(0) and -1
|
||||||
// matches Lt(0).
|
// matches Lt(0).
|
||||||
// - {1, 2} doesn't matches IsSubsetOf({Gt(0), Lt(0)}), even though 1 and 2 both
|
// - {1, 2} doesn't match IsSubsetOf({Gt(0), Lt(0)}), even though 1 and 2 both
|
||||||
// match Gt(0). The reason is that different matchers must be used for
|
// match Gt(0). The reason is that different matchers must be used for
|
||||||
// elements in different slots of the container.
|
// elements in different slots of the container.
|
||||||
//
|
//
|
||||||
@ -5231,9 +5301,10 @@ inline InnerMatcher AllArgs(const InnerMatcher& matcher) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns a matcher that matches the value of an optional<> type variable.
|
// Returns a matcher that matches the value of an optional<> type variable.
|
||||||
// The matcher implementation only uses '!arg' and requires that the optional<>
|
// The matcher implementation only uses '!arg' (or 'arg.has_value()' if '!arg`
|
||||||
// type has a 'value_type' member type and that '*arg' is of type 'value_type'
|
// isn't a valid expression) and requires that the optional<> type has a
|
||||||
// and is printable using 'PrintToString'. It is compatible with
|
// 'value_type' member type and that '*arg' is of type 'value_type' and is
|
||||||
|
// printable using 'PrintToString'. It is compatible with
|
||||||
// std::optional/std::experimental::optional.
|
// std::optional/std::experimental::optional.
|
||||||
// Note that to compare an optional type variable against nullopt you should
|
// Note that to compare an optional type variable against nullopt you should
|
||||||
// use Eq(nullopt) and not Eq(Optional(nullopt)). The latter implies that the
|
// use Eq(nullopt) and not Eq(Optional(nullopt)). The latter implies that the
|
||||||
|
@ -601,9 +601,10 @@ template <std::size_t index, typename... Params>
|
|||||||
struct InvokeArgumentAction {
|
struct InvokeArgumentAction {
|
||||||
template <typename... Args,
|
template <typename... Args,
|
||||||
typename = typename std::enable_if<(index < sizeof...(Args))>::type>
|
typename = typename std::enable_if<(index < sizeof...(Args))>::type>
|
||||||
auto operator()(Args &&...args) const -> decltype(internal::InvokeArgument(
|
auto operator()(Args &&...args) const
|
||||||
std::get<index>(std::forward_as_tuple(std::forward<Args>(args)...)),
|
-> decltype(internal::InvokeArgument(
|
||||||
std::declval<const Params &>()...)) {
|
std::get<index>(std::forward_as_tuple(std::forward<Args>(args)...)),
|
||||||
|
std::declval<const Params &>()...)) {
|
||||||
internal::FlatTuple<Args &&...> args_tuple(FlatTupleConstructTag{},
|
internal::FlatTuple<Args &&...> args_tuple(FlatTupleConstructTag{},
|
||||||
std::forward<Args>(args)...);
|
std::forward<Args>(args)...);
|
||||||
return params.Apply([&](const Params &...unpacked_params) {
|
return params.Apply([&](const Params &...unpacked_params) {
|
||||||
|
@ -868,7 +868,7 @@ class GTEST_API_ ExpectationBase {
|
|||||||
Clause last_clause_;
|
Clause last_clause_;
|
||||||
mutable bool action_count_checked_; // Under mutex_.
|
mutable bool action_count_checked_; // Under mutex_.
|
||||||
mutable Mutex mutex_; // Protects action_count_checked_.
|
mutable Mutex mutex_; // Protects action_count_checked_.
|
||||||
}; // class ExpectationBase
|
}; // class ExpectationBase
|
||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
class TypedExpectation;
|
class TypedExpectation;
|
||||||
@ -1838,9 +1838,8 @@ R FunctionMocker<R(Args...)>::InvokeWith(ArgumentTuple&& args)
|
|||||||
// Doing so slows down compilation dramatically because the *constructor* of
|
// Doing so slows down compilation dramatically because the *constructor* of
|
||||||
// std::function<T> is re-instantiated with different template
|
// std::function<T> is re-instantiated with different template
|
||||||
// parameters each time.
|
// parameters each time.
|
||||||
const UninterestingCallCleanupHandler report_uninteresting_call = {
|
const UninterestingCallCleanupHandler report_uninteresting_call = {reaction,
|
||||||
reaction, ss
|
ss};
|
||||||
};
|
|
||||||
|
|
||||||
return PerformActionAndPrintResult(nullptr, std::move(args), ss.str(), ss);
|
return PerformActionAndPrintResult(nullptr, std::move(args), ss.str(), ss);
|
||||||
}
|
}
|
||||||
@ -1890,8 +1889,7 @@ R FunctionMocker<R(Args...)>::InvokeWith(ArgumentTuple&& args)
|
|||||||
// std::function<T> is re-instantiated with different template
|
// std::function<T> is re-instantiated with different template
|
||||||
// parameters each time.
|
// parameters each time.
|
||||||
const FailureCleanupHandler handle_failures = {
|
const FailureCleanupHandler handle_failures = {
|
||||||
ss, why, loc, untyped_expectation, found, is_excessive
|
ss, why, loc, untyped_expectation, found, is_excessive};
|
||||||
};
|
|
||||||
|
|
||||||
return PerformActionAndPrintResult(untyped_action, std::move(args), ss.str(),
|
return PerformActionAndPrintResult(untyped_action, std::move(args), ss.str(),
|
||||||
ss);
|
ss);
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
@ -53,12 +53,12 @@ class BetweenCardinalityImpl : public CardinalityInterface {
|
|||||||
: min_(min >= 0 ? min : 0), max_(max >= min_ ? max : min_) {
|
: min_(min >= 0 ? min : 0), max_(max >= min_ ? max : min_) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
if (min < 0) {
|
if (min < 0) {
|
||||||
ss << "The invocation lower bound must be >= 0, "
|
ss << "The invocation lower bound must be >= 0, " << "but is actually "
|
||||||
<< "but is actually " << min << ".";
|
<< min << ".";
|
||||||
internal::Expect(false, __FILE__, __LINE__, ss.str());
|
internal::Expect(false, __FILE__, __LINE__, ss.str());
|
||||||
} else if (max < 0) {
|
} else if (max < 0) {
|
||||||
ss << "The invocation upper bound must be >= 0, "
|
ss << "The invocation upper bound must be >= 0, " << "but is actually "
|
||||||
<< "but is actually " << max << ".";
|
<< max << ".";
|
||||||
internal::Expect(false, __FILE__, __LINE__, ss.str());
|
internal::Expect(false, __FILE__, __LINE__, ss.str());
|
||||||
} else if (min > max) {
|
} else if (min > max) {
|
||||||
ss << "The invocation upper bound (" << max
|
ss << "The invocation upper bound (" << max
|
||||||
|
@ -222,8 +222,8 @@ TEST(TypeTraits, IsInvocableRV) {
|
|||||||
// In C++17 and above, where it's guaranteed that functions can return
|
// In C++17 and above, where it's guaranteed that functions can return
|
||||||
// non-moveable objects, everything should work fine for non-moveable rsult
|
// non-moveable objects, everything should work fine for non-moveable rsult
|
||||||
// types too.
|
// types too.
|
||||||
#if defined(GTEST_INTERNAL_CPLUSPLUS_LANG) && \
|
// TODO(b/396121064) - Fix this test under MSVC
|
||||||
GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L
|
#ifndef _MSC_VER
|
||||||
{
|
{
|
||||||
struct NonMoveable {
|
struct NonMoveable {
|
||||||
NonMoveable() = default;
|
NonMoveable() = default;
|
||||||
@ -244,7 +244,7 @@ TEST(TypeTraits, IsInvocableRV) {
|
|||||||
static_assert(!internal::is_callable_r<int, Callable>::value);
|
static_assert(!internal::is_callable_r<int, Callable>::value);
|
||||||
static_assert(!internal::is_callable_r<NonMoveable, Callable, int>::value);
|
static_assert(!internal::is_callable_r<NonMoveable, Callable, int>::value);
|
||||||
}
|
}
|
||||||
#endif // C++17 and above
|
#endif // _MSC_VER
|
||||||
|
|
||||||
// Nothing should choke when we try to call other arguments besides directly
|
// Nothing should choke when we try to call other arguments besides directly
|
||||||
// callable objects, but they should not show up as callable.
|
// callable objects, but they should not show up as callable.
|
||||||
@ -441,8 +441,8 @@ TEST(DefaultValueDeathTest, GetReturnsBuiltInDefaultValueWhenUnset) {
|
|||||||
|
|
||||||
EXPECT_EQ(0, DefaultValue<int>::Get());
|
EXPECT_EQ(0, DefaultValue<int>::Get());
|
||||||
|
|
||||||
EXPECT_DEATH_IF_SUPPORTED({ DefaultValue<MyNonDefaultConstructible>::Get(); },
|
EXPECT_DEATH_IF_SUPPORTED(
|
||||||
"");
|
{ DefaultValue<MyNonDefaultConstructible>::Get(); }, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(DefaultValueTest, GetWorksForMoveOnlyIfSet) {
|
TEST(DefaultValueTest, GetWorksForMoveOnlyIfSet) {
|
||||||
@ -505,8 +505,8 @@ TEST(DefaultValueOfReferenceDeathTest, GetReturnsBuiltInDefaultValueWhenUnset) {
|
|||||||
EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible&>::IsSet());
|
EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible&>::IsSet());
|
||||||
|
|
||||||
EXPECT_DEATH_IF_SUPPORTED({ DefaultValue<int&>::Get(); }, "");
|
EXPECT_DEATH_IF_SUPPORTED({ DefaultValue<int&>::Get(); }, "");
|
||||||
EXPECT_DEATH_IF_SUPPORTED({ DefaultValue<MyNonDefaultConstructible>::Get(); },
|
EXPECT_DEATH_IF_SUPPORTED(
|
||||||
"");
|
{ DefaultValue<MyNonDefaultConstructible>::Get(); }, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that ActionInterface can be implemented by defining the
|
// Tests that ActionInterface can be implemented by defining the
|
||||||
@ -1477,6 +1477,54 @@ TEST(DoAll, SupportsTypeErasedActions) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A DoAll action should be convertible to a OnceAction, even when its component
|
||||||
|
// sub-actions are user-provided types that define only an Action conversion
|
||||||
|
// operator. If they supposed being called more than once then they also support
|
||||||
|
// being called at most once.
|
||||||
|
TEST(DoAll, ConvertibleToOnceActionWithUserProvidedActionConversion) {
|
||||||
|
// Simplest case: only one sub-action.
|
||||||
|
struct CustomFinal final {
|
||||||
|
operator Action<int()>() { // NOLINT
|
||||||
|
return Return(17);
|
||||||
|
}
|
||||||
|
|
||||||
|
operator Action<int(int, char)>() { // NOLINT
|
||||||
|
return Return(19);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
OnceAction<int()> action = DoAll(CustomFinal{});
|
||||||
|
EXPECT_EQ(17, std::move(action).Call());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
OnceAction<int(int, char)> action = DoAll(CustomFinal{});
|
||||||
|
EXPECT_EQ(19, std::move(action).Call(0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// It should also work with multiple sub-actions.
|
||||||
|
struct CustomInitial final {
|
||||||
|
operator Action<void()>() { // NOLINT
|
||||||
|
return [] {};
|
||||||
|
}
|
||||||
|
|
||||||
|
operator Action<void(int, char)>() { // NOLINT
|
||||||
|
return [] {};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
OnceAction<int()> action = DoAll(CustomInitial{}, CustomFinal{});
|
||||||
|
EXPECT_EQ(17, std::move(action).Call());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
OnceAction<int(int, char)> action = DoAll(CustomInitial{}, CustomFinal{});
|
||||||
|
EXPECT_EQ(19, std::move(action).Call(0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Tests using WithArgs and with an action that takes 1 argument.
|
// Tests using WithArgs and with an action that takes 1 argument.
|
||||||
TEST(WithArgsTest, OneArg) {
|
TEST(WithArgsTest, OneArg) {
|
||||||
Action<bool(double x, int n)> a = WithArgs<1>(Invoke(Unary)); // NOLINT
|
Action<bool(double x, int n)> a = WithArgs<1>(Invoke(Unary)); // NOLINT
|
||||||
|
@ -325,8 +325,8 @@ TYPED_TEST(FunctionMockerTest, MocksBinaryFunction) {
|
|||||||
|
|
||||||
// Tests mocking a decimal function.
|
// Tests mocking a decimal function.
|
||||||
TYPED_TEST(FunctionMockerTest, MocksDecimalFunction) {
|
TYPED_TEST(FunctionMockerTest, MocksDecimalFunction) {
|
||||||
EXPECT_CALL(this->mock_foo_,
|
EXPECT_CALL(this->mock_foo_, Decimal(true, 'a', 0, 0, 1L, A<float>(), Lt(100),
|
||||||
Decimal(true, 'a', 0, 0, 1L, A<float>(), Lt(100), 5U, NULL, "hi"))
|
5U, nullptr, "hi"))
|
||||||
.WillOnce(Return(5));
|
.WillOnce(Return(5));
|
||||||
|
|
||||||
EXPECT_EQ(5, this->foo_->Decimal(true, 'a', 0, 0, 1, 0, 0, 5, nullptr, "hi"));
|
EXPECT_EQ(5, this->foo_->Decimal(true, 'a', 0, 0, 1, 0, 0, 5, nullptr, "hi"));
|
||||||
|
@ -36,7 +36,9 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
#include "test/gmock-matchers_test.h"
|
#include "test/gmock-matchers_test.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
// Silence warning C4244: 'initializing': conversion from 'int' to 'short',
|
// Silence warning C4244: 'initializing': conversion from 'int' to 'short',
|
||||||
// possible loss of data and C4100, unreferenced local parameter
|
// possible loss of data and C4100, unreferenced local parameter
|
||||||
@ -559,10 +561,9 @@ TEST_P(AllOfTestP, ExplainsResult) {
|
|||||||
Matcher<int> m;
|
Matcher<int> m;
|
||||||
|
|
||||||
// Successful match. Both matchers need to explain. The second
|
// Successful match. Both matchers need to explain. The second
|
||||||
// matcher doesn't give an explanation, so only the first matcher's
|
// matcher doesn't give an explanation, so the matcher description is used.
|
||||||
// explanation is printed.
|
|
||||||
m = AllOf(GreaterThan(10), Lt(30));
|
m = AllOf(GreaterThan(10), Lt(30));
|
||||||
EXPECT_EQ("which is 15 more than 10", Explain(m, 25));
|
EXPECT_EQ("which is 15 more than 10, and is < 30", Explain(m, 25));
|
||||||
|
|
||||||
// Successful match. Both matchers need to explain.
|
// Successful match. Both matchers need to explain.
|
||||||
m = AllOf(GreaterThan(10), GreaterThan(20));
|
m = AllOf(GreaterThan(10), GreaterThan(20));
|
||||||
@ -572,8 +573,9 @@ TEST_P(AllOfTestP, ExplainsResult) {
|
|||||||
// Successful match. All matchers need to explain. The second
|
// Successful match. All matchers need to explain. The second
|
||||||
// matcher doesn't given an explanation.
|
// matcher doesn't given an explanation.
|
||||||
m = AllOf(GreaterThan(10), Lt(30), GreaterThan(20));
|
m = AllOf(GreaterThan(10), Lt(30), GreaterThan(20));
|
||||||
EXPECT_EQ("which is 15 more than 10, and which is 5 more than 20",
|
EXPECT_EQ(
|
||||||
Explain(m, 25));
|
"which is 15 more than 10, and is < 30, and which is 5 more than 20",
|
||||||
|
Explain(m, 25));
|
||||||
|
|
||||||
// Successful match. All matchers need to explain.
|
// Successful match. All matchers need to explain.
|
||||||
m = AllOf(GreaterThan(10), GreaterThan(20), GreaterThan(30));
|
m = AllOf(GreaterThan(10), GreaterThan(20), GreaterThan(30));
|
||||||
@ -588,10 +590,10 @@ TEST_P(AllOfTestP, ExplainsResult) {
|
|||||||
EXPECT_EQ("which is 5 less than 10", Explain(m, 5));
|
EXPECT_EQ("which is 5 less than 10", Explain(m, 5));
|
||||||
|
|
||||||
// Failed match. The second matcher, which failed, needs to
|
// Failed match. The second matcher, which failed, needs to
|
||||||
// explain. Since it doesn't given an explanation, nothing is
|
// explain. Since it doesn't given an explanation, the matcher text is
|
||||||
// printed.
|
// printed.
|
||||||
m = AllOf(GreaterThan(10), Lt(30));
|
m = AllOf(GreaterThan(10), Lt(30));
|
||||||
EXPECT_EQ("", Explain(m, 40));
|
EXPECT_EQ("which doesn't match (is < 30)", Explain(m, 40));
|
||||||
|
|
||||||
// Failed match. The second matcher, which failed, needs to
|
// Failed match. The second matcher, which failed, needs to
|
||||||
// explain.
|
// explain.
|
||||||
@ -774,45 +776,43 @@ TEST(AnyOfTest, AnyOfMatcherSafelyCastsMonomorphicMatchers) {
|
|||||||
TEST_P(AnyOfTestP, ExplainsResult) {
|
TEST_P(AnyOfTestP, ExplainsResult) {
|
||||||
Matcher<int> m;
|
Matcher<int> m;
|
||||||
|
|
||||||
// Failed match. Both matchers need to explain. The second
|
// Failed match. The second matcher have no explanation (description is used).
|
||||||
// matcher doesn't give an explanation, so only the first matcher's
|
|
||||||
// explanation is printed.
|
|
||||||
m = AnyOf(GreaterThan(10), Lt(0));
|
m = AnyOf(GreaterThan(10), Lt(0));
|
||||||
EXPECT_EQ("which is 5 less than 10", Explain(m, 5));
|
EXPECT_EQ("which is 5 less than 10, and isn't < 0", Explain(m, 5));
|
||||||
|
|
||||||
// Failed match. Both matchers need to explain.
|
// Failed match. Both matchers have explanations.
|
||||||
m = AnyOf(GreaterThan(10), GreaterThan(20));
|
m = AnyOf(GreaterThan(10), GreaterThan(20));
|
||||||
EXPECT_EQ("which is 5 less than 10, and which is 15 less than 20",
|
EXPECT_EQ("which is 5 less than 10, and which is 15 less than 20",
|
||||||
Explain(m, 5));
|
Explain(m, 5));
|
||||||
|
|
||||||
// Failed match. All matchers need to explain. The second
|
// Failed match. The middle matcher have no explanation.
|
||||||
// matcher doesn't given an explanation.
|
|
||||||
m = AnyOf(GreaterThan(10), Gt(20), GreaterThan(30));
|
m = AnyOf(GreaterThan(10), Gt(20), GreaterThan(30));
|
||||||
EXPECT_EQ("which is 5 less than 10, and which is 25 less than 30",
|
EXPECT_EQ(
|
||||||
Explain(m, 5));
|
"which is 5 less than 10, and isn't > 20, and which is 25 less than 30",
|
||||||
|
Explain(m, 5));
|
||||||
|
|
||||||
// Failed match. All matchers need to explain.
|
// Failed match. All three matchers have explanations.
|
||||||
m = AnyOf(GreaterThan(10), GreaterThan(20), GreaterThan(30));
|
m = AnyOf(GreaterThan(10), GreaterThan(20), GreaterThan(30));
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
"which is 5 less than 10, and which is 15 less than 20, "
|
"which is 5 less than 10, and which is 15 less than 20, "
|
||||||
"and which is 25 less than 30",
|
"and which is 25 less than 30",
|
||||||
Explain(m, 5));
|
Explain(m, 5));
|
||||||
|
|
||||||
// Successful match. The first matcher, which succeeded, needs to
|
// Successful match. The first macher succeeded and has explanation.
|
||||||
// explain.
|
|
||||||
m = AnyOf(GreaterThan(10), GreaterThan(20));
|
m = AnyOf(GreaterThan(10), GreaterThan(20));
|
||||||
EXPECT_EQ("which is 5 more than 10", Explain(m, 15));
|
EXPECT_EQ("which is 5 more than 10", Explain(m, 15));
|
||||||
|
|
||||||
// Successful match. The second matcher, which succeeded, needs to
|
// Successful match. The second matcher succeeded and has explanation.
|
||||||
// explain. Since it doesn't given an explanation, nothing is
|
|
||||||
// printed.
|
|
||||||
m = AnyOf(GreaterThan(10), Lt(30));
|
|
||||||
EXPECT_EQ("", Explain(m, 0));
|
|
||||||
|
|
||||||
// Successful match. The second matcher, which succeeded, needs to
|
|
||||||
// explain.
|
|
||||||
m = AnyOf(GreaterThan(30), GreaterThan(20));
|
m = AnyOf(GreaterThan(30), GreaterThan(20));
|
||||||
EXPECT_EQ("which is 5 more than 20", Explain(m, 25));
|
EXPECT_EQ("which is 5 more than 20", Explain(m, 25));
|
||||||
|
|
||||||
|
// Successful match. The first matcher succeeded and has no explanation.
|
||||||
|
m = AnyOf(Gt(10), Lt(20));
|
||||||
|
EXPECT_EQ("which matches (is > 10)", Explain(m, 15));
|
||||||
|
|
||||||
|
// Successful match. The second matcher succeeded and has no explanation.
|
||||||
|
m = AnyOf(Gt(30), Gt(20));
|
||||||
|
EXPECT_EQ("which matches (is > 20)", Explain(m, 25));
|
||||||
}
|
}
|
||||||
|
|
||||||
// The following predicate function and predicate functor are for
|
// The following predicate function and predicate functor are for
|
||||||
|
@ -37,13 +37,14 @@
|
|||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
#include "test/gmock-matchers_test.h"
|
#include "test/gmock-matchers_test.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
// Silence warning C4244: 'initializing': conversion from 'int' to 'short',
|
// Silence warning C4244: 'initializing': conversion from 'int' to 'short',
|
||||||
// possible loss of data and C4100, unreferenced local parameter
|
// possible loss of data and C4100, unreferenced local parameter
|
||||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244 4100)
|
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244 4100)
|
||||||
|
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
namespace gmock_matchers_test {
|
namespace gmock_matchers_test {
|
||||||
namespace {
|
namespace {
|
||||||
@ -410,9 +411,27 @@ class IntValue {
|
|||||||
int value_;
|
int value_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// For testing casting matchers between compatible types. This is similar to
|
||||||
|
// IntValue, but takes a non-const reference to the value, showing MatcherCast
|
||||||
|
// works with such types (and doesn't, for example, use a const ref internally).
|
||||||
|
class MutableIntView {
|
||||||
|
public:
|
||||||
|
// An int& can be statically (although not implicitly) cast to a
|
||||||
|
// MutableIntView.
|
||||||
|
explicit MutableIntView(int& a_value) : value_(a_value) {}
|
||||||
|
|
||||||
|
int& value() const { return value_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int& value_;
|
||||||
|
};
|
||||||
|
|
||||||
// For testing casting matchers between compatible types.
|
// For testing casting matchers between compatible types.
|
||||||
bool IsPositiveIntValue(const IntValue& foo) { return foo.value() > 0; }
|
bool IsPositiveIntValue(const IntValue& foo) { return foo.value() > 0; }
|
||||||
|
|
||||||
|
// For testing casting matchers between compatible types.
|
||||||
|
bool IsPositiveMutableIntView(MutableIntView foo) { return foo.value() > 0; }
|
||||||
|
|
||||||
// Tests that MatcherCast<T>(m) works when m is a Matcher<U> where T
|
// Tests that MatcherCast<T>(m) works when m is a Matcher<U> where T
|
||||||
// can be statically converted to U.
|
// can be statically converted to U.
|
||||||
TEST(MatcherCastTest, FromCompatibleType) {
|
TEST(MatcherCastTest, FromCompatibleType) {
|
||||||
@ -428,14 +447,34 @@ TEST(MatcherCastTest, FromCompatibleType) {
|
|||||||
// predicate.
|
// predicate.
|
||||||
EXPECT_TRUE(m4.Matches(1));
|
EXPECT_TRUE(m4.Matches(1));
|
||||||
EXPECT_FALSE(m4.Matches(0));
|
EXPECT_FALSE(m4.Matches(0));
|
||||||
|
|
||||||
|
Matcher<MutableIntView> m5 = Truly(IsPositiveMutableIntView);
|
||||||
|
Matcher<int> m6 = MatcherCast<int>(m5);
|
||||||
|
// In the following, the arguments 1 and 0 are statically converted to
|
||||||
|
// MutableIntView objects, and then tested by the IsPositiveMutableIntView()
|
||||||
|
// predicate.
|
||||||
|
EXPECT_TRUE(m6.Matches(1));
|
||||||
|
EXPECT_FALSE(m6.Matches(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that MatcherCast<T>(m) works when m is a Matcher<const T&>.
|
// Tests that MatcherCast<T>(m) works when m is a Matcher<const T&>.
|
||||||
TEST(MatcherCastTest, FromConstReferenceToNonReference) {
|
TEST(MatcherCastTest, FromConstReferenceToNonReference) {
|
||||||
Matcher<const int&> m1 = Eq(0);
|
int n = 0;
|
||||||
|
Matcher<const int&> m1 = Ref(n);
|
||||||
Matcher<int> m2 = MatcherCast<int>(m1);
|
Matcher<int> m2 = MatcherCast<int>(m1);
|
||||||
EXPECT_TRUE(m2.Matches(0));
|
int n1 = 0;
|
||||||
EXPECT_FALSE(m2.Matches(1));
|
EXPECT_TRUE(m2.Matches(n));
|
||||||
|
EXPECT_FALSE(m2.Matches(n1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that MatcherCast<T&>(m) works when m is a Matcher<const T&>.
|
||||||
|
TEST(MatcherCastTest, FromConstReferenceToReference) {
|
||||||
|
int n = 0;
|
||||||
|
Matcher<const int&> m1 = Ref(n);
|
||||||
|
Matcher<int&> m2 = MatcherCast<int&>(m1);
|
||||||
|
int n1 = 0;
|
||||||
|
EXPECT_TRUE(m2.Matches(n));
|
||||||
|
EXPECT_FALSE(m2.Matches(n1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that MatcherCast<T>(m) works when m is a Matcher<T&>.
|
// Tests that MatcherCast<T>(m) works when m is a Matcher<T&>.
|
||||||
@ -444,6 +483,12 @@ TEST(MatcherCastTest, FromReferenceToNonReference) {
|
|||||||
Matcher<int> m2 = MatcherCast<int>(m1);
|
Matcher<int> m2 = MatcherCast<int>(m1);
|
||||||
EXPECT_TRUE(m2.Matches(0));
|
EXPECT_TRUE(m2.Matches(0));
|
||||||
EXPECT_FALSE(m2.Matches(1));
|
EXPECT_FALSE(m2.Matches(1));
|
||||||
|
|
||||||
|
// Of course, reference identity isn't preserved since a copy is required.
|
||||||
|
int n = 0;
|
||||||
|
Matcher<int&> m3 = Ref(n);
|
||||||
|
Matcher<int> m4 = MatcherCast<int>(m3);
|
||||||
|
EXPECT_FALSE(m4.Matches(n));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that MatcherCast<const T&>(m) works when m is a Matcher<T>.
|
// Tests that MatcherCast<const T&>(m) works when m is a Matcher<T>.
|
||||||
@ -648,6 +693,16 @@ TEST(SafeMatcherCastTest, FromBaseClass) {
|
|||||||
EXPECT_FALSE(m4.Matches(d2));
|
EXPECT_FALSE(m4.Matches(d2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests that SafeMatcherCast<T>(m) works when m is a Matcher<const T&>.
|
||||||
|
TEST(SafeMatcherCastTest, FromConstReferenceToNonReference) {
|
||||||
|
int n = 0;
|
||||||
|
Matcher<const int&> m1 = Ref(n);
|
||||||
|
Matcher<int> m2 = SafeMatcherCast<int>(m1);
|
||||||
|
int n1 = 0;
|
||||||
|
EXPECT_TRUE(m2.Matches(n));
|
||||||
|
EXPECT_FALSE(m2.Matches(n1));
|
||||||
|
}
|
||||||
|
|
||||||
// Tests that SafeMatcherCast<T&>(m) works when m is a Matcher<const T&>.
|
// Tests that SafeMatcherCast<T&>(m) works when m is a Matcher<const T&>.
|
||||||
TEST(SafeMatcherCastTest, FromConstReferenceToReference) {
|
TEST(SafeMatcherCastTest, FromConstReferenceToReference) {
|
||||||
int n = 0;
|
int n = 0;
|
||||||
@ -2334,9 +2389,11 @@ TEST(ExplainMatchResultTest, AllOf_True_True) {
|
|||||||
EXPECT_EQ("which is 0 modulo 2, and which is 0 modulo 3", Explain(m, 6));
|
EXPECT_EQ("which is 0 modulo 2, and which is 0 modulo 3", Explain(m, 6));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests that when AllOf() succeeds, but matchers have no explanation,
|
||||||
|
// the matcher description is used.
|
||||||
TEST(ExplainMatchResultTest, AllOf_True_True_2) {
|
TEST(ExplainMatchResultTest, AllOf_True_True_2) {
|
||||||
const Matcher<int> m = AllOf(Ge(2), Le(3));
|
const Matcher<int> m = AllOf(Ge(2), Le(3));
|
||||||
EXPECT_EQ("", Explain(m, 2));
|
EXPECT_EQ("is >= 2, and is <= 3", Explain(m, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
INSTANTIATE_GTEST_MATCHER_TEST_P(ExplainmatcherResultTest);
|
INSTANTIATE_GTEST_MATCHER_TEST_P(ExplainmatcherResultTest);
|
||||||
|
@ -43,14 +43,14 @@
|
|||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
#include "test/gmock-matchers_test.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
// Silence warning C4244: 'initializing': conversion from 'int' to 'short',
|
// Silence warning C4244: 'initializing': conversion from 'int' to 'short',
|
||||||
// possible loss of data and C4100, unreferenced local parameter
|
// possible loss of data and C4100, unreferenced local parameter
|
||||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244 4100)
|
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244 4100)
|
||||||
|
|
||||||
#include "test/gmock-matchers_test.h"
|
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
namespace gmock_matchers_test {
|
namespace gmock_matchers_test {
|
||||||
namespace {
|
namespace {
|
||||||
@ -1204,13 +1204,16 @@ TEST(SizeIsTest, ExplainsResult) {
|
|||||||
vector<int> container;
|
vector<int> container;
|
||||||
EXPECT_EQ("whose size 0 doesn't match", Explain(m1, container));
|
EXPECT_EQ("whose size 0 doesn't match", Explain(m1, container));
|
||||||
EXPECT_EQ("whose size 0 matches", Explain(m2, container));
|
EXPECT_EQ("whose size 0 matches", Explain(m2, container));
|
||||||
EXPECT_EQ("whose size 0 matches", Explain(m3, container));
|
EXPECT_EQ("whose size 0 matches, which matches (is equal to 0)",
|
||||||
|
Explain(m3, container));
|
||||||
EXPECT_EQ("whose size 0 doesn't match", Explain(m4, container));
|
EXPECT_EQ("whose size 0 doesn't match", Explain(m4, container));
|
||||||
container.push_back(0);
|
container.push_back(0);
|
||||||
container.push_back(0);
|
container.push_back(0);
|
||||||
EXPECT_EQ("whose size 2 matches", Explain(m1, container));
|
EXPECT_EQ("whose size 2 matches", Explain(m1, container));
|
||||||
EXPECT_EQ("whose size 2 doesn't match", Explain(m2, container));
|
EXPECT_EQ("whose size 2 doesn't match", Explain(m2, container));
|
||||||
EXPECT_EQ("whose size 2 doesn't match", Explain(m3, container));
|
EXPECT_EQ(
|
||||||
|
"whose size 2 doesn't match, isn't equal to 0, and isn't equal to 3",
|
||||||
|
Explain(m3, container));
|
||||||
EXPECT_EQ("whose size 2 matches", Explain(m4, container));
|
EXPECT_EQ("whose size 2 matches", Explain(m4, container));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1475,8 +1478,10 @@ TEST_P(BeginEndDistanceIsTestP, ExplainsResult) {
|
|||||||
Explain(m1, container));
|
Explain(m1, container));
|
||||||
EXPECT_EQ("whose distance between begin() and end() 0 matches",
|
EXPECT_EQ("whose distance between begin() and end() 0 matches",
|
||||||
Explain(m2, container));
|
Explain(m2, container));
|
||||||
EXPECT_EQ("whose distance between begin() and end() 0 matches",
|
EXPECT_EQ(
|
||||||
Explain(m3, container));
|
"whose distance between begin() and end() 0 matches, which matches (is "
|
||||||
|
"equal to 0)",
|
||||||
|
Explain(m3, container));
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
"whose distance between begin() and end() 0 doesn't match, which is 1 "
|
"whose distance between begin() and end() 0 doesn't match, which is 1 "
|
||||||
"less than 1",
|
"less than 1",
|
||||||
@ -1487,8 +1492,10 @@ TEST_P(BeginEndDistanceIsTestP, ExplainsResult) {
|
|||||||
Explain(m1, container));
|
Explain(m1, container));
|
||||||
EXPECT_EQ("whose distance between begin() and end() 2 doesn't match",
|
EXPECT_EQ("whose distance between begin() and end() 2 doesn't match",
|
||||||
Explain(m2, container));
|
Explain(m2, container));
|
||||||
EXPECT_EQ("whose distance between begin() and end() 2 doesn't match",
|
EXPECT_EQ(
|
||||||
Explain(m3, container));
|
"whose distance between begin() and end() 2 doesn't match, isn't equal "
|
||||||
|
"to 0, and isn't equal to 3",
|
||||||
|
Explain(m3, container));
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
"whose distance between begin() and end() 2 matches, which is 1 more "
|
"whose distance between begin() and end() 2 matches, which is 1 more "
|
||||||
"than 1",
|
"than 1",
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
// This file tests some commonly used argument matchers.
|
// This file tests some commonly used argument matchers.
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <cstdint>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -39,14 +40,14 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
|
#include "test/gmock-matchers_test.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
// Silence warning C4244: 'initializing': conversion from 'int' to 'short',
|
// Silence warning C4244: 'initializing': conversion from 'int' to 'short',
|
||||||
// possible loss of data and C4100, unreferenced local parameter
|
// possible loss of data and C4100, unreferenced local parameter
|
||||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244 4100)
|
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244 4100)
|
||||||
|
|
||||||
#include "test/gmock-matchers_test.h"
|
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
namespace gmock_matchers_test {
|
namespace gmock_matchers_test {
|
||||||
namespace {
|
namespace {
|
||||||
@ -674,6 +675,8 @@ TEST_P(MatcherTupleTestP, ExplainsMatchFailure) {
|
|||||||
// explanation.
|
// explanation.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if GTEST_HAS_TYPED_TEST
|
||||||
|
|
||||||
// Sample optional type implementation with minimal requirements for use with
|
// Sample optional type implementation with minimal requirements for use with
|
||||||
// Optional matcher.
|
// Optional matcher.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -691,38 +694,94 @@ class SampleOptional {
|
|||||||
bool has_value_;
|
bool has_value_;
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST(OptionalTest, DescribesSelf) {
|
// Sample optional type implementation with alternative minimal requirements for
|
||||||
const Matcher<SampleOptional<int>> m = Optional(Eq(1));
|
// use with Optional matcher. In particular, while it doesn't have a bool
|
||||||
|
// conversion operator, it does have a has_value() method.
|
||||||
|
template <typename T>
|
||||||
|
class SampleOptionalWithoutBoolConversion {
|
||||||
|
public:
|
||||||
|
using value_type = T;
|
||||||
|
explicit SampleOptionalWithoutBoolConversion(T value)
|
||||||
|
: value_(std::move(value)), has_value_(true) {}
|
||||||
|
SampleOptionalWithoutBoolConversion() : value_(), has_value_(false) {}
|
||||||
|
bool has_value() const { return has_value_; }
|
||||||
|
const T& operator*() const { return value_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
T value_;
|
||||||
|
bool has_value_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class OptionalTest : public testing::Test {};
|
||||||
|
|
||||||
|
using OptionalTestTypes =
|
||||||
|
testing::Types<SampleOptional<int>,
|
||||||
|
SampleOptionalWithoutBoolConversion<int>>;
|
||||||
|
|
||||||
|
TYPED_TEST_SUITE(OptionalTest, OptionalTestTypes);
|
||||||
|
|
||||||
|
TYPED_TEST(OptionalTest, DescribesSelf) {
|
||||||
|
const Matcher<TypeParam> m = Optional(Eq(1));
|
||||||
EXPECT_EQ("value is equal to 1", Describe(m));
|
EXPECT_EQ("value is equal to 1", Describe(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(OptionalTest, ExplainsSelf) {
|
TYPED_TEST(OptionalTest, ExplainsSelf) {
|
||||||
const Matcher<SampleOptional<int>> m = Optional(Eq(1));
|
const Matcher<TypeParam> m = Optional(Eq(1));
|
||||||
EXPECT_EQ("whose value 1 matches", Explain(m, SampleOptional<int>(1)));
|
EXPECT_EQ("whose value 1 matches", Explain(m, TypeParam(1)));
|
||||||
EXPECT_EQ("whose value 2 doesn't match", Explain(m, SampleOptional<int>(2)));
|
EXPECT_EQ("whose value 2 doesn't match", Explain(m, TypeParam(2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(OptionalTest, MatchesNonEmptyOptional) {
|
TYPED_TEST(OptionalTest, MatchesNonEmptyOptional) {
|
||||||
const Matcher<SampleOptional<int>> m1 = Optional(1);
|
const Matcher<TypeParam> m1 = Optional(1);
|
||||||
const Matcher<SampleOptional<int>> m2 = Optional(Eq(2));
|
const Matcher<TypeParam> m2 = Optional(Eq(2));
|
||||||
const Matcher<SampleOptional<int>> m3 = Optional(Lt(3));
|
const Matcher<TypeParam> m3 = Optional(Lt(3));
|
||||||
SampleOptional<int> opt(1);
|
TypeParam opt(1);
|
||||||
EXPECT_TRUE(m1.Matches(opt));
|
EXPECT_TRUE(m1.Matches(opt));
|
||||||
EXPECT_FALSE(m2.Matches(opt));
|
EXPECT_FALSE(m2.Matches(opt));
|
||||||
EXPECT_TRUE(m3.Matches(opt));
|
EXPECT_TRUE(m3.Matches(opt));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(OptionalTest, DoesNotMatchNullopt) {
|
TYPED_TEST(OptionalTest, DoesNotMatchNullopt) {
|
||||||
const Matcher<SampleOptional<int>> m = Optional(1);
|
const Matcher<TypeParam> m = Optional(1);
|
||||||
SampleOptional<int> empty;
|
TypeParam empty;
|
||||||
EXPECT_FALSE(m.Matches(empty));
|
EXPECT_FALSE(m.Matches(empty));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(OptionalTest, WorksWithMoveOnly) {
|
TYPED_TEST(OptionalTest, ComposesWithMonomorphicMatchersTakingReferences) {
|
||||||
Matcher<SampleOptional<std::unique_ptr<int>>> m = Optional(Eq(nullptr));
|
const Matcher<const int&> eq1 = Eq(1);
|
||||||
EXPECT_TRUE(m.Matches(SampleOptional<std::unique_ptr<int>>(nullptr)));
|
const Matcher<const int&> eq2 = Eq(2);
|
||||||
|
TypeParam opt(1);
|
||||||
|
EXPECT_THAT(opt, Optional(eq1));
|
||||||
|
EXPECT_THAT(opt, Optional(Not(eq2)));
|
||||||
|
EXPECT_THAT(opt, Optional(AllOf(eq1, Not(eq2))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TYPED_TEST(OptionalTest, ComposesWithMonomorphicMatchersRequiringConversion) {
|
||||||
|
const Matcher<int64_t> eq1 = Eq(1);
|
||||||
|
const Matcher<int64_t> eq2 = Eq(2);
|
||||||
|
TypeParam opt(1);
|
||||||
|
EXPECT_THAT(opt, Optional(eq1));
|
||||||
|
EXPECT_THAT(opt, Optional(Not(eq2)));
|
||||||
|
EXPECT_THAT(opt, Optional(AllOf(eq1, Not(eq2))));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class MoveOnlyOptionalTest : public testing::Test {};
|
||||||
|
|
||||||
|
using MoveOnlyOptionalTestTypes =
|
||||||
|
testing::Types<SampleOptional<std::unique_ptr<int>>,
|
||||||
|
SampleOptionalWithoutBoolConversion<std::unique_ptr<int>>>;
|
||||||
|
|
||||||
|
TYPED_TEST_SUITE(MoveOnlyOptionalTest, MoveOnlyOptionalTestTypes);
|
||||||
|
|
||||||
|
TYPED_TEST(MoveOnlyOptionalTest, WorksWithMoveOnly) {
|
||||||
|
Matcher<TypeParam> m = Optional(Eq(nullptr));
|
||||||
|
EXPECT_TRUE(m.Matches(TypeParam(nullptr)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // GTEST_HAS_TYPED_TEST
|
||||||
|
|
||||||
class SampleVariantIntString {
|
class SampleVariantIntString {
|
||||||
public:
|
public:
|
||||||
SampleVariantIntString(int i) : i_(i), has_int_(true) {}
|
SampleVariantIntString(int i) : i_(i), has_int_(true) {}
|
||||||
@ -1576,10 +1635,10 @@ TEST_P(AnyOfArrayTestP, ExplainsMatchResultCorrectly) {
|
|||||||
const Matcher<int> m1 = AnyOfArray(v1);
|
const Matcher<int> m1 = AnyOfArray(v1);
|
||||||
const Matcher<int> m2 = AnyOfArray(v2);
|
const Matcher<int> m2 = AnyOfArray(v2);
|
||||||
EXPECT_EQ("", Explain(m0, 0));
|
EXPECT_EQ("", Explain(m0, 0));
|
||||||
EXPECT_EQ("", Explain(m1, 1));
|
EXPECT_EQ("which matches (is equal to 1)", Explain(m1, 1));
|
||||||
EXPECT_EQ("", Explain(m1, 2));
|
EXPECT_EQ("isn't equal to 1", Explain(m1, 2));
|
||||||
EXPECT_EQ("", Explain(m2, 3));
|
EXPECT_EQ("which matches (is equal to 3)", Explain(m2, 3));
|
||||||
EXPECT_EQ("", Explain(m2, 4));
|
EXPECT_EQ("isn't equal to 2, and isn't equal to 3", Explain(m2, 4));
|
||||||
EXPECT_EQ("()", Describe(m0));
|
EXPECT_EQ("()", Describe(m0));
|
||||||
EXPECT_EQ("(is equal to 1)", Describe(m1));
|
EXPECT_EQ("(is equal to 1)", Describe(m1));
|
||||||
EXPECT_EQ("(is equal to 2) or (is equal to 3)", Describe(m2));
|
EXPECT_EQ("(is equal to 2) or (is equal to 3)", Describe(m2));
|
||||||
|
@ -59,6 +59,7 @@ using testing::Invoke;
|
|||||||
using testing::ReturnArg;
|
using testing::ReturnArg;
|
||||||
using testing::ReturnPointee;
|
using testing::ReturnPointee;
|
||||||
using testing::SaveArg;
|
using testing::SaveArg;
|
||||||
|
using testing::SaveArgByMove;
|
||||||
using testing::SaveArgPointee;
|
using testing::SaveArgPointee;
|
||||||
using testing::SetArgReferee;
|
using testing::SetArgReferee;
|
||||||
using testing::Unused;
|
using testing::Unused;
|
||||||
@ -492,6 +493,34 @@ TEST(SaveArgActionTest, WorksForCompatibleType) {
|
|||||||
EXPECT_EQ('a', result);
|
EXPECT_EQ('a', result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct MoveOnly {
|
||||||
|
explicit MoveOnly(int v) : i(v) {}
|
||||||
|
MoveOnly(MoveOnly&& o) {
|
||||||
|
i = o.i;
|
||||||
|
o.i = -1;
|
||||||
|
}
|
||||||
|
MoveOnly& operator=(MoveOnly&& o) {
|
||||||
|
i = o.i;
|
||||||
|
o.i = -1;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
int i;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(SaveArgByMoveActionTest, WorksForSameType) {
|
||||||
|
MoveOnly result{0};
|
||||||
|
const Action<void(MoveOnly v)> a1 = SaveArgByMove<0>(&result);
|
||||||
|
a1.Perform(std::make_tuple(MoveOnly{5}));
|
||||||
|
EXPECT_EQ(5, result.i);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SaveArgByMoveActionTest, WorksForCompatibleType) {
|
||||||
|
MoveOnly result{0};
|
||||||
|
const Action<void(bool, MoveOnly)> a1 = SaveArgByMove<1>(&result);
|
||||||
|
a1.Perform(std::make_tuple(true, MoveOnly{7}));
|
||||||
|
EXPECT_EQ(7, result.i);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(SaveArgPointeeActionTest, WorksForSameType) {
|
TEST(SaveArgPointeeActionTest, WorksForSameType) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
const int value = 5;
|
const int value = 5;
|
||||||
@ -756,34 +785,34 @@ TEST(InvokeArgumentTest, Functor6) {
|
|||||||
|
|
||||||
// Tests using InvokeArgument with a 7-ary function.
|
// Tests using InvokeArgument with a 7-ary function.
|
||||||
TEST(InvokeArgumentTest, Function7) {
|
TEST(InvokeArgumentTest, Function7) {
|
||||||
Action<std::string(std::string(*)(const char*, const char*, const char*,
|
Action<std::string(std::string (*)(const char*, const char*, const char*,
|
||||||
const char*, const char*, const char*,
|
const char*, const char*, const char*,
|
||||||
const char*))>
|
const char*))>
|
||||||
a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7");
|
a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7");
|
||||||
EXPECT_EQ("1234567", a.Perform(std::make_tuple(&Concat7)));
|
EXPECT_EQ("1234567", a.Perform(std::make_tuple(&Concat7)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests using InvokeArgument with a 8-ary function.
|
// Tests using InvokeArgument with a 8-ary function.
|
||||||
TEST(InvokeArgumentTest, Function8) {
|
TEST(InvokeArgumentTest, Function8) {
|
||||||
Action<std::string(std::string(*)(const char*, const char*, const char*,
|
Action<std::string(std::string (*)(const char*, const char*, const char*,
|
||||||
const char*, const char*, const char*,
|
const char*, const char*, const char*,
|
||||||
const char*, const char*))>
|
const char*, const char*))>
|
||||||
a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8");
|
a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8");
|
||||||
EXPECT_EQ("12345678", a.Perform(std::make_tuple(&Concat8)));
|
EXPECT_EQ("12345678", a.Perform(std::make_tuple(&Concat8)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests using InvokeArgument with a 9-ary function.
|
// Tests using InvokeArgument with a 9-ary function.
|
||||||
TEST(InvokeArgumentTest, Function9) {
|
TEST(InvokeArgumentTest, Function9) {
|
||||||
Action<std::string(std::string(*)(const char*, const char*, const char*,
|
Action<std::string(std::string (*)(const char*, const char*, const char*,
|
||||||
const char*, const char*, const char*,
|
const char*, const char*, const char*,
|
||||||
const char*, const char*, const char*))>
|
const char*, const char*, const char*))>
|
||||||
a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8", "9");
|
a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8", "9");
|
||||||
EXPECT_EQ("123456789", a.Perform(std::make_tuple(&Concat9)));
|
EXPECT_EQ("123456789", a.Perform(std::make_tuple(&Concat9)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests using InvokeArgument with a 10-ary function.
|
// Tests using InvokeArgument with a 10-ary function.
|
||||||
TEST(InvokeArgumentTest, Function10) {
|
TEST(InvokeArgumentTest, Function10) {
|
||||||
Action<std::string(std::string(*)(
|
Action<std::string(std::string (*)(
|
||||||
const char*, const char*, const char*, const char*, const char*,
|
const char*, const char*, const char*, const char*, const char*,
|
||||||
const char*, const char*, const char*, const char*, const char*))>
|
const char*, const char*, const char*, const char*, const char*))>
|
||||||
a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8", "9", "0");
|
a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8", "9", "0");
|
||||||
|
@ -70,7 +70,7 @@ static_assert(GMOCK_PP_INTERNAL_VAR_TEST(x, y) == 2, "");
|
|||||||
static_assert(GMOCK_PP_INTERNAL_VAR_TEST(silly) == 1, "");
|
static_assert(GMOCK_PP_INTERNAL_VAR_TEST(silly) == 1, "");
|
||||||
static_assert(GMOCK_PP_INTERNAL_VAR_TEST(x, y, z) == 3, "");
|
static_assert(GMOCK_PP_INTERNAL_VAR_TEST(x, y, z) == 3, "");
|
||||||
|
|
||||||
// TODO(iserna): The following asserts fail in --config=lexan.
|
// TODO(iserna): The following asserts fail in --config=windows.
|
||||||
#define GMOCK_PP_INTERNAL_IS_EMPTY_TEST_1
|
#define GMOCK_PP_INTERNAL_IS_EMPTY_TEST_1
|
||||||
static_assert(GMOCK_PP_IS_EMPTY(GMOCK_PP_INTERNAL_IS_EMPTY_TEST_1), "");
|
static_assert(GMOCK_PP_IS_EMPTY(GMOCK_PP_INTERNAL_IS_EMPTY_TEST_1), "");
|
||||||
static_assert(GMOCK_PP_IS_EMPTY(), "");
|
static_assert(GMOCK_PP_IS_EMPTY(), "");
|
||||||
|
@ -804,9 +804,8 @@ TEST(ExpectCallTest, InfersCardinality1WhenThereIsWillRepeatedly) {
|
|||||||
"to be called at least once");
|
"to be called at least once");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(GTEST_INTERNAL_CPLUSPLUS_LANG) && \
|
// TODO(b/396121064) - Fix this test under MSVC
|
||||||
GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L
|
#ifndef _MSC_VER
|
||||||
|
|
||||||
// It should be possible to return a non-moveable type from a mock action in
|
// It should be possible to return a non-moveable type from a mock action in
|
||||||
// C++17 and above, where it's guaranteed that such a type can be initialized
|
// C++17 and above, where it's guaranteed that such a type can be initialized
|
||||||
// from a prvalue returned from a function.
|
// from a prvalue returned from a function.
|
||||||
@ -847,7 +846,7 @@ TEST(ExpectCallTest, NonMoveableType) {
|
|||||||
EXPECT_EQ(17, mock.AsStdFunction()().x);
|
EXPECT_EQ(17, mock.AsStdFunction()().x);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // C++17 and above
|
#endif // _MSC_VER
|
||||||
|
|
||||||
// Tests that the n-th action is taken for the n-th matching
|
// Tests that the n-th action is taken for the n-th matching
|
||||||
// invocation.
|
// invocation.
|
||||||
|
@ -186,8 +186,8 @@ using testing::SetErrnoAndReturn;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if GTEST_HAS_EXCEPTIONS
|
#if GTEST_HAS_EXCEPTIONS
|
||||||
using testing::Throw;
|
|
||||||
using testing::Rethrow;
|
using testing::Rethrow;
|
||||||
|
using testing::Throw;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using testing::ContainsRegex;
|
using testing::ContainsRegex;
|
||||||
|
@ -25,7 +25,7 @@ When building GoogleTest as a standalone project, the typical workflow starts
|
|||||||
with
|
with
|
||||||
|
|
||||||
```
|
```
|
||||||
git clone https://github.com/google/googletest.git -b v1.14.0
|
git clone https://github.com/google/googletest.git -b v1.16.0
|
||||||
cd googletest # Main directory of the cloned repository.
|
cd googletest # Main directory of the cloned repository.
|
||||||
mkdir build # Create a directory to hold the build output.
|
mkdir build # Create a directory to hold the build output.
|
||||||
cd build
|
cd build
|
||||||
|
@ -195,7 +195,7 @@ function(cxx_library_with_type name type cxx_flags)
|
|||||||
target_link_libraries(${name} PUBLIC Threads::Threads)
|
target_link_libraries(${name} PUBLIC Threads::Threads)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_compile_features(${name} PUBLIC cxx_std_14)
|
target_compile_features(${name} PUBLIC cxx_std_17)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
|
@ -67,10 +67,10 @@ namespace testing {
|
|||||||
// To implement a matcher Foo for type T, define:
|
// To implement a matcher Foo for type T, define:
|
||||||
// 1. a class FooMatcherMatcher that implements the matcher interface:
|
// 1. a class FooMatcherMatcher that implements the matcher interface:
|
||||||
// using is_gtest_matcher = void;
|
// using is_gtest_matcher = void;
|
||||||
// bool MatchAndExplain(const T&, std::ostream*);
|
// bool MatchAndExplain(const T&, std::ostream*) const;
|
||||||
// (MatchResultListener* can also be used instead of std::ostream*)
|
// (MatchResultListener* can also be used instead of std::ostream*)
|
||||||
// void DescribeTo(std::ostream*);
|
// void DescribeTo(std::ostream*) const;
|
||||||
// void DescribeNegationTo(std::ostream*);
|
// void DescribeNegationTo(std::ostream*) const;
|
||||||
//
|
//
|
||||||
// 2. a factory function that creates a Matcher<T> object from a
|
// 2. a factory function that creates a Matcher<T> object from a
|
||||||
// FooMatcherMatcher.
|
// FooMatcherMatcher.
|
||||||
|
@ -126,6 +126,10 @@
|
|||||||
#include <span> // NOLINT
|
#include <span> // NOLINT
|
||||||
#endif // GTEST_INTERNAL_HAS_STD_SPAN
|
#endif // GTEST_INTERNAL_HAS_STD_SPAN
|
||||||
|
|
||||||
|
#if GTEST_INTERNAL_HAS_COMPARE_LIB
|
||||||
|
#include <compare> // NOLINT
|
||||||
|
#endif // GTEST_INTERNAL_HAS_COMPARE_LIB
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
// Definitions in the internal* namespaces are subject to change without notice.
|
// Definitions in the internal* namespaces are subject to change without notice.
|
||||||
@ -782,6 +786,41 @@ void PrintTo(const std::shared_ptr<T>& ptr, std::ostream* os) {
|
|||||||
(PrintSmartPointer<T>)(ptr, os, 0);
|
(PrintSmartPointer<T>)(ptr, os, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if GTEST_INTERNAL_HAS_COMPARE_LIB
|
||||||
|
template <typename T>
|
||||||
|
void PrintOrderingHelper(T ordering, std::ostream* os) {
|
||||||
|
if (ordering == T::less) {
|
||||||
|
*os << "(less)";
|
||||||
|
} else if (ordering == T::greater) {
|
||||||
|
*os << "(greater)";
|
||||||
|
} else if (ordering == T::equivalent) {
|
||||||
|
*os << "(equivalent)";
|
||||||
|
} else {
|
||||||
|
*os << "(unknown ordering)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PrintTo(std::strong_ordering ordering, std::ostream* os) {
|
||||||
|
if (ordering == std::strong_ordering::equal) {
|
||||||
|
*os << "(equal)";
|
||||||
|
} else {
|
||||||
|
PrintOrderingHelper(ordering, os);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PrintTo(std::partial_ordering ordering, std::ostream* os) {
|
||||||
|
if (ordering == std::partial_ordering::unordered) {
|
||||||
|
*os << "(unordered)";
|
||||||
|
} else {
|
||||||
|
PrintOrderingHelper(ordering, os);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PrintTo(std::weak_ordering ordering, std::ostream* os) {
|
||||||
|
PrintOrderingHelper(ordering, os);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Helper function for printing a tuple. T must be instantiated with
|
// Helper function for printing a tuple. T must be instantiated with
|
||||||
// a tuple type.
|
// a tuple type.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -275,8 +275,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(GTEST_INTERNAL_CPLUSPLUS_LANG) || \
|
#if !defined(GTEST_INTERNAL_CPLUSPLUS_LANG) || \
|
||||||
GTEST_INTERNAL_CPLUSPLUS_LANG < 201402L
|
GTEST_INTERNAL_CPLUSPLUS_LANG < 201703L
|
||||||
#error C++ versions less than C++14 are not supported.
|
#error C++ versions less than C++17 are not supported.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// MSVC >= 19.11 (VS 2017 Update 3) supports __has_include.
|
// MSVC >= 19.11 (VS 2017 Update 3) supports __has_include.
|
||||||
@ -2533,4 +2533,12 @@ using Variant = ::std::variant<T...>;
|
|||||||
#define GTEST_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL 1
|
#define GTEST_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (defined(__cpp_lib_three_way_comparison) || \
|
||||||
|
(GTEST_INTERNAL_HAS_INCLUDE(<compare>) && \
|
||||||
|
GTEST_INTERNAL_CPLUSPLUS_LANG >= 201907L))
|
||||||
|
#define GTEST_INTERNAL_HAS_COMPARE_LIB 1
|
||||||
|
#else
|
||||||
|
#define GTEST_INTERNAL_HAS_COMPARE_LIB 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
|
#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
|
||||||
|
@ -1660,10 +1660,25 @@ std::string GetBoolAssertionFailureMessage(
|
|||||||
return msg.GetString();
|
return msg.GetString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function for implementing ASSERT_NEAR.
|
// Helper function for implementing ASSERT_NEAR. Treats infinity as a specific
|
||||||
|
// value, such that comparing infinity to infinity is equal, the distance
|
||||||
|
// between -infinity and +infinity is infinity, and infinity <= infinity is
|
||||||
|
// true.
|
||||||
AssertionResult DoubleNearPredFormat(const char* expr1, const char* expr2,
|
AssertionResult DoubleNearPredFormat(const char* expr1, const char* expr2,
|
||||||
const char* abs_error_expr, double val1,
|
const char* abs_error_expr, double val1,
|
||||||
double val2, double abs_error) {
|
double val2, double abs_error) {
|
||||||
|
// We want to return success when the two values are infinity and at least
|
||||||
|
// one of the following is true:
|
||||||
|
// * The values are the same-signed infinity.
|
||||||
|
// * The error limit itself is infinity.
|
||||||
|
// This is done here so that we don't end up with a NaN when calculating the
|
||||||
|
// difference in values.
|
||||||
|
if (std::isinf(val1) && std::isinf(val2) &&
|
||||||
|
(std::signbit(val1) == std::signbit(val2) ||
|
||||||
|
(abs_error > 0.0 && std::isinf(abs_error)))) {
|
||||||
|
return AssertionSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
const double diff = fabs(val1 - val2);
|
const double diff = fabs(val1 - val2);
|
||||||
if (diff <= abs_error) return AssertionSuccess();
|
if (diff <= abs_error) return AssertionSuccess();
|
||||||
|
|
||||||
@ -3974,6 +3989,12 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
|
|||||||
static void OutputXmlTestSuiteForTestResult(::std::ostream* stream,
|
static void OutputXmlTestSuiteForTestResult(::std::ostream* stream,
|
||||||
const TestResult& result);
|
const TestResult& result);
|
||||||
|
|
||||||
|
// Streams a test case XML stanza containing the given test result.
|
||||||
|
//
|
||||||
|
// Requires: result.Failed()
|
||||||
|
static void OutputXmlTestCaseForTestResult(::std::ostream* stream,
|
||||||
|
const TestResult& result);
|
||||||
|
|
||||||
// Streams an XML representation of a TestResult object.
|
// Streams an XML representation of a TestResult object.
|
||||||
static void OutputXmlTestResult(::std::ostream* stream,
|
static void OutputXmlTestResult(::std::ostream* stream,
|
||||||
const TestResult& result);
|
const TestResult& result);
|
||||||
@ -3991,16 +4012,11 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
|
|||||||
static void PrintXmlUnitTest(::std::ostream* stream,
|
static void PrintXmlUnitTest(::std::ostream* stream,
|
||||||
const UnitTest& unit_test);
|
const UnitTest& unit_test);
|
||||||
|
|
||||||
// Produces a string representing the test properties in a result as space
|
|
||||||
// delimited XML attributes based on the property key="value" pairs.
|
|
||||||
// When the std::string is not empty, it includes a space at the beginning,
|
|
||||||
// to delimit this attribute from prior attributes.
|
|
||||||
static std::string TestPropertiesAsXmlAttributes(const TestResult& result);
|
|
||||||
|
|
||||||
// Streams an XML representation of the test properties of a TestResult
|
// Streams an XML representation of the test properties of a TestResult
|
||||||
// object.
|
// object.
|
||||||
static void OutputXmlTestProperties(std::ostream* stream,
|
static void OutputXmlTestProperties(std::ostream* stream,
|
||||||
const TestResult& result);
|
const TestResult& result,
|
||||||
|
const std::string& indent);
|
||||||
|
|
||||||
// The output file.
|
// The output file.
|
||||||
const std::string output_file_;
|
const std::string output_file_;
|
||||||
@ -4221,6 +4237,15 @@ void XmlUnitTestResultPrinter::OutputXmlTestSuiteForTestResult(
|
|||||||
FormatEpochTimeInMillisAsIso8601(result.start_timestamp()));
|
FormatEpochTimeInMillisAsIso8601(result.start_timestamp()));
|
||||||
*stream << ">";
|
*stream << ">";
|
||||||
|
|
||||||
|
OutputXmlTestCaseForTestResult(stream, result);
|
||||||
|
|
||||||
|
// Complete the test suite.
|
||||||
|
*stream << " </testsuite>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Streams a test case XML stanza containing the given test result.
|
||||||
|
void XmlUnitTestResultPrinter::OutputXmlTestCaseForTestResult(
|
||||||
|
::std::ostream* stream, const TestResult& result) {
|
||||||
// Output the boilerplate for a minimal test case with a single test.
|
// Output the boilerplate for a minimal test case with a single test.
|
||||||
*stream << " <testcase";
|
*stream << " <testcase";
|
||||||
OutputXmlAttribute(stream, "testcase", "name", "");
|
OutputXmlAttribute(stream, "testcase", "name", "");
|
||||||
@ -4235,9 +4260,6 @@ void XmlUnitTestResultPrinter::OutputXmlTestSuiteForTestResult(
|
|||||||
|
|
||||||
// Output the actual test result.
|
// Output the actual test result.
|
||||||
OutputXmlTestResult(stream, result);
|
OutputXmlTestResult(stream, result);
|
||||||
|
|
||||||
// Complete the test suite.
|
|
||||||
*stream << " </testsuite>\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prints an XML representation of a TestInfo object.
|
// Prints an XML representation of a TestInfo object.
|
||||||
@ -4328,7 +4350,7 @@ void XmlUnitTestResultPrinter::OutputXmlTestResult(::std::ostream* stream,
|
|||||||
if (failures == 0 && skips == 0) {
|
if (failures == 0 && skips == 0) {
|
||||||
*stream << ">\n";
|
*stream << ">\n";
|
||||||
}
|
}
|
||||||
OutputXmlTestProperties(stream, result);
|
OutputXmlTestProperties(stream, result, /*indent=*/" ");
|
||||||
*stream << " </testcase>\n";
|
*stream << " </testcase>\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4357,13 +4379,18 @@ void XmlUnitTestResultPrinter::PrintXmlTestSuite(std::ostream* stream,
|
|||||||
OutputXmlAttribute(
|
OutputXmlAttribute(
|
||||||
stream, kTestsuite, "timestamp",
|
stream, kTestsuite, "timestamp",
|
||||||
FormatEpochTimeInMillisAsIso8601(test_suite.start_timestamp()));
|
FormatEpochTimeInMillisAsIso8601(test_suite.start_timestamp()));
|
||||||
*stream << TestPropertiesAsXmlAttributes(test_suite.ad_hoc_test_result());
|
|
||||||
}
|
}
|
||||||
*stream << ">\n";
|
*stream << ">\n";
|
||||||
|
OutputXmlTestProperties(stream, test_suite.ad_hoc_test_result(),
|
||||||
|
/*indent=*/" ");
|
||||||
for (int i = 0; i < test_suite.total_test_count(); ++i) {
|
for (int i = 0; i < test_suite.total_test_count(); ++i) {
|
||||||
if (test_suite.GetTestInfo(i)->is_reportable())
|
if (test_suite.GetTestInfo(i)->is_reportable())
|
||||||
OutputXmlTestInfo(stream, test_suite.name(), *test_suite.GetTestInfo(i));
|
OutputXmlTestInfo(stream, test_suite.name(), *test_suite.GetTestInfo(i));
|
||||||
}
|
}
|
||||||
|
if (test_suite.ad_hoc_test_result().Failed()) {
|
||||||
|
OutputXmlTestCaseForTestResult(stream, test_suite.ad_hoc_test_result());
|
||||||
|
}
|
||||||
|
|
||||||
*stream << " </" << kTestsuite << ">\n";
|
*stream << " </" << kTestsuite << ">\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4393,11 +4420,12 @@ void XmlUnitTestResultPrinter::PrintXmlUnitTest(std::ostream* stream,
|
|||||||
OutputXmlAttribute(stream, kTestsuites, "random_seed",
|
OutputXmlAttribute(stream, kTestsuites, "random_seed",
|
||||||
StreamableToString(unit_test.random_seed()));
|
StreamableToString(unit_test.random_seed()));
|
||||||
}
|
}
|
||||||
*stream << TestPropertiesAsXmlAttributes(unit_test.ad_hoc_test_result());
|
|
||||||
|
|
||||||
OutputXmlAttribute(stream, kTestsuites, "name", "AllTests");
|
OutputXmlAttribute(stream, kTestsuites, "name", "AllTests");
|
||||||
*stream << ">\n";
|
*stream << ">\n";
|
||||||
|
|
||||||
|
OutputXmlTestProperties(stream, unit_test.ad_hoc_test_result(),
|
||||||
|
/*indent=*/" ");
|
||||||
for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
|
for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
|
||||||
if (unit_test.GetTestSuite(i)->reportable_test_count() > 0)
|
if (unit_test.GetTestSuite(i)->reportable_test_count() > 0)
|
||||||
PrintXmlTestSuite(stream, *unit_test.GetTestSuite(i));
|
PrintXmlTestSuite(stream, *unit_test.GetTestSuite(i));
|
||||||
@ -4434,21 +4462,8 @@ void XmlUnitTestResultPrinter::PrintXmlTestsList(
|
|||||||
*stream << "</" << kTestsuites << ">\n";
|
*stream << "</" << kTestsuites << ">\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Produces a string representing the test properties in a result as space
|
|
||||||
// delimited XML attributes based on the property key="value" pairs.
|
|
||||||
std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
|
|
||||||
const TestResult& result) {
|
|
||||||
Message attributes;
|
|
||||||
for (int i = 0; i < result.test_property_count(); ++i) {
|
|
||||||
const TestProperty& property = result.GetTestProperty(i);
|
|
||||||
attributes << " " << property.key() << "=" << "\""
|
|
||||||
<< EscapeXmlAttribute(property.value()) << "\"";
|
|
||||||
}
|
|
||||||
return attributes.GetString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void XmlUnitTestResultPrinter::OutputXmlTestProperties(
|
void XmlUnitTestResultPrinter::OutputXmlTestProperties(
|
||||||
std::ostream* stream, const TestResult& result) {
|
std::ostream* stream, const TestResult& result, const std::string& indent) {
|
||||||
const std::string kProperties = "properties";
|
const std::string kProperties = "properties";
|
||||||
const std::string kProperty = "property";
|
const std::string kProperty = "property";
|
||||||
|
|
||||||
@ -4456,15 +4471,15 @@ void XmlUnitTestResultPrinter::OutputXmlTestProperties(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
*stream << " <" << kProperties << ">\n";
|
*stream << indent << "<" << kProperties << ">\n";
|
||||||
for (int i = 0; i < result.test_property_count(); ++i) {
|
for (int i = 0; i < result.test_property_count(); ++i) {
|
||||||
const TestProperty& property = result.GetTestProperty(i);
|
const TestProperty& property = result.GetTestProperty(i);
|
||||||
*stream << " <" << kProperty;
|
*stream << indent << " <" << kProperty;
|
||||||
*stream << " name=\"" << EscapeXmlAttribute(property.key()) << "\"";
|
*stream << " name=\"" << EscapeXmlAttribute(property.key()) << "\"";
|
||||||
*stream << " value=\"" << EscapeXmlAttribute(property.value()) << "\"";
|
*stream << " value=\"" << EscapeXmlAttribute(property.value()) << "\"";
|
||||||
*stream << "/>\n";
|
*stream << "/>\n";
|
||||||
}
|
}
|
||||||
*stream << " </" << kProperties << ">\n";
|
*stream << indent << "</" << kProperties << ">\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// End XmlUnitTestResultPrinter
|
// End XmlUnitTestResultPrinter
|
||||||
@ -4503,6 +4518,12 @@ class JsonUnitTestResultPrinter : public EmptyTestEventListener {
|
|||||||
static void OutputJsonTestSuiteForTestResult(::std::ostream* stream,
|
static void OutputJsonTestSuiteForTestResult(::std::ostream* stream,
|
||||||
const TestResult& result);
|
const TestResult& result);
|
||||||
|
|
||||||
|
// Streams a test case JSON stanza containing the given test result.
|
||||||
|
//
|
||||||
|
// Requires: result.Failed()
|
||||||
|
static void OutputJsonTestCaseForTestResult(::std::ostream* stream,
|
||||||
|
const TestResult& result);
|
||||||
|
|
||||||
// Streams a JSON representation of a TestResult object.
|
// Streams a JSON representation of a TestResult object.
|
||||||
static void OutputJsonTestResult(::std::ostream* stream,
|
static void OutputJsonTestResult(::std::ostream* stream,
|
||||||
const TestResult& result);
|
const TestResult& result);
|
||||||
@ -4673,6 +4694,15 @@ void JsonUnitTestResultPrinter::OutputJsonTestSuiteForTestResult(
|
|||||||
}
|
}
|
||||||
*stream << Indent(6) << "\"testsuite\": [\n";
|
*stream << Indent(6) << "\"testsuite\": [\n";
|
||||||
|
|
||||||
|
OutputJsonTestCaseForTestResult(stream, result);
|
||||||
|
|
||||||
|
// Finish the test suite.
|
||||||
|
*stream << "\n" << Indent(6) << "]\n" << Indent(4) << "}";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Streams a test case JSON stanza containing the given test result.
|
||||||
|
void JsonUnitTestResultPrinter::OutputJsonTestCaseForTestResult(
|
||||||
|
::std::ostream* stream, const TestResult& result) {
|
||||||
// Output the boilerplate for a new test case.
|
// Output the boilerplate for a new test case.
|
||||||
*stream << Indent(8) << "{\n";
|
*stream << Indent(8) << "{\n";
|
||||||
OutputJsonKey(stream, "testcase", "name", "", Indent(10));
|
OutputJsonKey(stream, "testcase", "name", "", Indent(10));
|
||||||
@ -4689,9 +4719,6 @@ void JsonUnitTestResultPrinter::OutputJsonTestSuiteForTestResult(
|
|||||||
|
|
||||||
// Output the actual test result.
|
// Output the actual test result.
|
||||||
OutputJsonTestResult(stream, result);
|
OutputJsonTestResult(stream, result);
|
||||||
|
|
||||||
// Finish the test suite.
|
|
||||||
*stream << "\n" << Indent(6) << "]\n" << Indent(4) << "}";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prints a JSON representation of a TestInfo object.
|
// Prints a JSON representation of a TestInfo object.
|
||||||
@ -4836,6 +4863,16 @@ void JsonUnitTestResultPrinter::PrintJsonTestSuite(
|
|||||||
OutputJsonTestInfo(stream, test_suite.name(), *test_suite.GetTestInfo(i));
|
OutputJsonTestInfo(stream, test_suite.name(), *test_suite.GetTestInfo(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there was a failure in the test suite setup or teardown include that in
|
||||||
|
// the output.
|
||||||
|
if (test_suite.ad_hoc_test_result().Failed()) {
|
||||||
|
if (comma) {
|
||||||
|
*stream << ",\n";
|
||||||
|
}
|
||||||
|
OutputJsonTestCaseForTestResult(stream, test_suite.ad_hoc_test_result());
|
||||||
|
}
|
||||||
|
|
||||||
*stream << "\n" << kIndent << "]\n" << Indent(4) << "}";
|
*stream << "\n" << kIndent << "]\n" << Indent(4) << "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,6 @@ cc_test(
|
|||||||
"gtest-*.cc",
|
"gtest-*.cc",
|
||||||
"googletest-*.cc",
|
"googletest-*.cc",
|
||||||
"*.h",
|
"*.h",
|
||||||
"googletest/include/gtest/**/*.h",
|
|
||||||
],
|
],
|
||||||
exclude = [
|
exclude = [
|
||||||
"gtest-unittest-api_test.cc",
|
"gtest-unittest-api_test.cc",
|
||||||
|
@ -57,7 +57,7 @@ else:
|
|||||||
STACK_TRACE_TEMPLATE = '\n'
|
STACK_TRACE_TEMPLATE = '\n'
|
||||||
|
|
||||||
EXPECTED_NON_EMPTY = {
|
EXPECTED_NON_EMPTY = {
|
||||||
'tests': 26,
|
'tests': 28,
|
||||||
'failures': 5,
|
'failures': 5,
|
||||||
'disabled': 2,
|
'disabled': 2,
|
||||||
'errors': 0,
|
'errors': 0,
|
||||||
@ -323,12 +323,14 @@ EXPECTED_NON_EMPTY = {
|
|||||||
'time': '*',
|
'time': '*',
|
||||||
'timestamp': '*',
|
'timestamp': '*',
|
||||||
'SetUpTestSuite': 'yes',
|
'SetUpTestSuite': 'yes',
|
||||||
|
'SetUpTestSuite (with whitespace)': 'yes and yes',
|
||||||
'TearDownTestSuite': 'aye',
|
'TearDownTestSuite': 'aye',
|
||||||
|
'TearDownTestSuite (with whitespace)': 'aye and aye',
|
||||||
'testsuite': [
|
'testsuite': [
|
||||||
{
|
{
|
||||||
'name': 'OneProperty',
|
'name': 'OneProperty',
|
||||||
'file': 'gtest_xml_output_unittest_.cc',
|
'file': 'gtest_xml_output_unittest_.cc',
|
||||||
'line': 121,
|
'line': 125,
|
||||||
'status': 'RUN',
|
'status': 'RUN',
|
||||||
'result': 'COMPLETED',
|
'result': 'COMPLETED',
|
||||||
'time': '*',
|
'time': '*',
|
||||||
@ -339,7 +341,7 @@ EXPECTED_NON_EMPTY = {
|
|||||||
{
|
{
|
||||||
'name': 'IntValuedProperty',
|
'name': 'IntValuedProperty',
|
||||||
'file': 'gtest_xml_output_unittest_.cc',
|
'file': 'gtest_xml_output_unittest_.cc',
|
||||||
'line': 125,
|
'line': 129,
|
||||||
'status': 'RUN',
|
'status': 'RUN',
|
||||||
'result': 'COMPLETED',
|
'result': 'COMPLETED',
|
||||||
'time': '*',
|
'time': '*',
|
||||||
@ -350,7 +352,7 @@ EXPECTED_NON_EMPTY = {
|
|||||||
{
|
{
|
||||||
'name': 'ThreeProperties',
|
'name': 'ThreeProperties',
|
||||||
'file': 'gtest_xml_output_unittest_.cc',
|
'file': 'gtest_xml_output_unittest_.cc',
|
||||||
'line': 129,
|
'line': 133,
|
||||||
'status': 'RUN',
|
'status': 'RUN',
|
||||||
'result': 'COMPLETED',
|
'result': 'COMPLETED',
|
||||||
'time': '*',
|
'time': '*',
|
||||||
@ -363,7 +365,7 @@ EXPECTED_NON_EMPTY = {
|
|||||||
{
|
{
|
||||||
'name': 'TwoValuesForOneKeyUsesLastValue',
|
'name': 'TwoValuesForOneKeyUsesLastValue',
|
||||||
'file': 'gtest_xml_output_unittest_.cc',
|
'file': 'gtest_xml_output_unittest_.cc',
|
||||||
'line': 135,
|
'line': 139,
|
||||||
'status': 'RUN',
|
'status': 'RUN',
|
||||||
'result': 'COMPLETED',
|
'result': 'COMPLETED',
|
||||||
'time': '*',
|
'time': '*',
|
||||||
@ -385,7 +387,7 @@ EXPECTED_NON_EMPTY = {
|
|||||||
{
|
{
|
||||||
'name': 'RecordProperty',
|
'name': 'RecordProperty',
|
||||||
'file': 'gtest_xml_output_unittest_.cc',
|
'file': 'gtest_xml_output_unittest_.cc',
|
||||||
'line': 140,
|
'line': 144,
|
||||||
'status': 'RUN',
|
'status': 'RUN',
|
||||||
'result': 'COMPLETED',
|
'result': 'COMPLETED',
|
||||||
'time': '*',
|
'time': '*',
|
||||||
@ -396,7 +398,7 @@ EXPECTED_NON_EMPTY = {
|
|||||||
{
|
{
|
||||||
'name': 'ExternalUtilityThatCallsRecordIntValuedProperty',
|
'name': 'ExternalUtilityThatCallsRecordIntValuedProperty',
|
||||||
'file': 'gtest_xml_output_unittest_.cc',
|
'file': 'gtest_xml_output_unittest_.cc',
|
||||||
'line': 153,
|
'line': 157,
|
||||||
'status': 'RUN',
|
'status': 'RUN',
|
||||||
'result': 'COMPLETED',
|
'result': 'COMPLETED',
|
||||||
'time': '*',
|
'time': '*',
|
||||||
@ -409,7 +411,7 @@ EXPECTED_NON_EMPTY = {
|
|||||||
'ExternalUtilityThatCallsRecordStringValuedProperty'
|
'ExternalUtilityThatCallsRecordStringValuedProperty'
|
||||||
),
|
),
|
||||||
'file': 'gtest_xml_output_unittest_.cc',
|
'file': 'gtest_xml_output_unittest_.cc',
|
||||||
'line': 157,
|
'line': 161,
|
||||||
'status': 'RUN',
|
'status': 'RUN',
|
||||||
'result': 'COMPLETED',
|
'result': 'COMPLETED',
|
||||||
'time': '*',
|
'time': '*',
|
||||||
@ -419,6 +421,83 @@ EXPECTED_NON_EMPTY = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'name': 'SetupFailTest',
|
||||||
|
'tests': 1,
|
||||||
|
'failures': 0,
|
||||||
|
'disabled': 0,
|
||||||
|
'errors': 0,
|
||||||
|
'time': '*',
|
||||||
|
'timestamp': '*',
|
||||||
|
'testsuite': [
|
||||||
|
{
|
||||||
|
'name': 'NoopPassingTest',
|
||||||
|
'file': 'gtest_xml_output_unittest_.cc',
|
||||||
|
'line': 172,
|
||||||
|
'status': 'RUN',
|
||||||
|
'result': 'SKIPPED',
|
||||||
|
'timestamp': '*',
|
||||||
|
'time': '*',
|
||||||
|
'classname': 'SetupFailTest',
|
||||||
|
'skipped': [
|
||||||
|
{'message': 'gtest_xml_output_unittest_.cc:*\n'}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': '',
|
||||||
|
'status': 'RUN',
|
||||||
|
'result': 'COMPLETED',
|
||||||
|
'timestamp': '*',
|
||||||
|
'time': '*',
|
||||||
|
'classname': '',
|
||||||
|
'failures': [{
|
||||||
|
'failure': (
|
||||||
|
'gtest_xml_output_unittest_.cc:*\nExpected equality'
|
||||||
|
' of these values:\n 1\n 2'
|
||||||
|
+ STACK_TRACE_TEMPLATE
|
||||||
|
),
|
||||||
|
'type': '',
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'TearDownFailTest',
|
||||||
|
'tests': 1,
|
||||||
|
'failures': 0,
|
||||||
|
'disabled': 0,
|
||||||
|
'errors': 0,
|
||||||
|
'timestamp': '*',
|
||||||
|
'time': '*',
|
||||||
|
'testsuite': [
|
||||||
|
{
|
||||||
|
'name': 'NoopPassingTest',
|
||||||
|
'file': 'gtest_xml_output_unittest_.cc',
|
||||||
|
'line': 179,
|
||||||
|
'status': 'RUN',
|
||||||
|
'result': 'COMPLETED',
|
||||||
|
'timestamp': '*',
|
||||||
|
'time': '*',
|
||||||
|
'classname': 'TearDownFailTest',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': '',
|
||||||
|
'status': 'RUN',
|
||||||
|
'result': 'COMPLETED',
|
||||||
|
'timestamp': '*',
|
||||||
|
'time': '*',
|
||||||
|
'classname': '',
|
||||||
|
'failures': [{
|
||||||
|
'failure': (
|
||||||
|
'gtest_xml_output_unittest_.cc:*\nExpected equality'
|
||||||
|
' of these values:\n 1\n 2'
|
||||||
|
+ STACK_TRACE_TEMPLATE
|
||||||
|
),
|
||||||
|
'type': '',
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
'name': 'TypedTest/0',
|
'name': 'TypedTest/0',
|
||||||
'tests': 1,
|
'tests': 1,
|
||||||
@ -431,7 +510,7 @@ EXPECTED_NON_EMPTY = {
|
|||||||
'name': 'HasTypeParamAttribute',
|
'name': 'HasTypeParamAttribute',
|
||||||
'type_param': 'int',
|
'type_param': 'int',
|
||||||
'file': 'gtest_xml_output_unittest_.cc',
|
'file': 'gtest_xml_output_unittest_.cc',
|
||||||
'line': 173,
|
'line': 193,
|
||||||
'status': 'RUN',
|
'status': 'RUN',
|
||||||
'result': 'COMPLETED',
|
'result': 'COMPLETED',
|
||||||
'time': '*',
|
'time': '*',
|
||||||
@ -451,7 +530,7 @@ EXPECTED_NON_EMPTY = {
|
|||||||
'name': 'HasTypeParamAttribute',
|
'name': 'HasTypeParamAttribute',
|
||||||
'type_param': 'long',
|
'type_param': 'long',
|
||||||
'file': 'gtest_xml_output_unittest_.cc',
|
'file': 'gtest_xml_output_unittest_.cc',
|
||||||
'line': 173,
|
'line': 193,
|
||||||
'status': 'RUN',
|
'status': 'RUN',
|
||||||
'result': 'COMPLETED',
|
'result': 'COMPLETED',
|
||||||
'time': '*',
|
'time': '*',
|
||||||
@ -471,7 +550,7 @@ EXPECTED_NON_EMPTY = {
|
|||||||
'name': 'HasTypeParamAttribute',
|
'name': 'HasTypeParamAttribute',
|
||||||
'type_param': 'int',
|
'type_param': 'int',
|
||||||
'file': 'gtest_xml_output_unittest_.cc',
|
'file': 'gtest_xml_output_unittest_.cc',
|
||||||
'line': 180,
|
'line': 200,
|
||||||
'status': 'RUN',
|
'status': 'RUN',
|
||||||
'result': 'COMPLETED',
|
'result': 'COMPLETED',
|
||||||
'time': '*',
|
'time': '*',
|
||||||
@ -491,7 +570,7 @@ EXPECTED_NON_EMPTY = {
|
|||||||
'name': 'HasTypeParamAttribute',
|
'name': 'HasTypeParamAttribute',
|
||||||
'type_param': 'long',
|
'type_param': 'long',
|
||||||
'file': 'gtest_xml_output_unittest_.cc',
|
'file': 'gtest_xml_output_unittest_.cc',
|
||||||
'line': 180,
|
'line': 200,
|
||||||
'status': 'RUN',
|
'status': 'RUN',
|
||||||
'result': 'COMPLETED',
|
'result': 'COMPLETED',
|
||||||
'time': '*',
|
'time': '*',
|
||||||
@ -512,7 +591,7 @@ EXPECTED_NON_EMPTY = {
|
|||||||
'name': 'HasValueParamAttribute/0',
|
'name': 'HasValueParamAttribute/0',
|
||||||
'value_param': '33',
|
'value_param': '33',
|
||||||
'file': 'gtest_xml_output_unittest_.cc',
|
'file': 'gtest_xml_output_unittest_.cc',
|
||||||
'line': 164,
|
'line': 184,
|
||||||
'status': 'RUN',
|
'status': 'RUN',
|
||||||
'result': 'COMPLETED',
|
'result': 'COMPLETED',
|
||||||
'time': '*',
|
'time': '*',
|
||||||
@ -523,7 +602,7 @@ EXPECTED_NON_EMPTY = {
|
|||||||
'name': 'HasValueParamAttribute/1',
|
'name': 'HasValueParamAttribute/1',
|
||||||
'value_param': '42',
|
'value_param': '42',
|
||||||
'file': 'gtest_xml_output_unittest_.cc',
|
'file': 'gtest_xml_output_unittest_.cc',
|
||||||
'line': 164,
|
'line': 184,
|
||||||
'status': 'RUN',
|
'status': 'RUN',
|
||||||
'result': 'COMPLETED',
|
'result': 'COMPLETED',
|
||||||
'time': '*',
|
'time': '*',
|
||||||
@ -534,7 +613,7 @@ EXPECTED_NON_EMPTY = {
|
|||||||
'name': 'AnotherTestThatHasValueParamAttribute/0',
|
'name': 'AnotherTestThatHasValueParamAttribute/0',
|
||||||
'value_param': '33',
|
'value_param': '33',
|
||||||
'file': 'gtest_xml_output_unittest_.cc',
|
'file': 'gtest_xml_output_unittest_.cc',
|
||||||
'line': 165,
|
'line': 185,
|
||||||
'status': 'RUN',
|
'status': 'RUN',
|
||||||
'result': 'COMPLETED',
|
'result': 'COMPLETED',
|
||||||
'time': '*',
|
'time': '*',
|
||||||
@ -545,7 +624,7 @@ EXPECTED_NON_EMPTY = {
|
|||||||
'name': 'AnotherTestThatHasValueParamAttribute/1',
|
'name': 'AnotherTestThatHasValueParamAttribute/1',
|
||||||
'value_param': '42',
|
'value_param': '42',
|
||||||
'file': 'gtest_xml_output_unittest_.cc',
|
'file': 'gtest_xml_output_unittest_.cc',
|
||||||
'line': 165,
|
'line': 185,
|
||||||
'status': 'RUN',
|
'status': 'RUN',
|
||||||
'result': 'COMPLETED',
|
'result': 'COMPLETED',
|
||||||
'time': '*',
|
'time': '*',
|
||||||
|
@ -64,6 +64,10 @@
|
|||||||
#include <span> // NOLINT
|
#include <span> // NOLINT
|
||||||
#endif // GTEST_INTERNAL_HAS_STD_SPAN
|
#endif // GTEST_INTERNAL_HAS_STD_SPAN
|
||||||
|
|
||||||
|
#if GTEST_INTERNAL_HAS_COMPARE_LIB
|
||||||
|
#include <compare> // NOLINT
|
||||||
|
#endif // GTEST_INTERNAL_HAS_COMPARE_LIB
|
||||||
|
|
||||||
// Some user-defined types for testing the universal value printer.
|
// Some user-defined types for testing the universal value printer.
|
||||||
|
|
||||||
// An anonymous enum type.
|
// An anonymous enum type.
|
||||||
@ -117,6 +121,9 @@ class UnprintableTemplateInGlobal {
|
|||||||
// A user-defined streamable type in the global namespace.
|
// A user-defined streamable type in the global namespace.
|
||||||
class StreamableInGlobal {
|
class StreamableInGlobal {
|
||||||
public:
|
public:
|
||||||
|
StreamableInGlobal() = default;
|
||||||
|
StreamableInGlobal(const StreamableInGlobal&) = default;
|
||||||
|
StreamableInGlobal& operator=(const StreamableInGlobal&) = default;
|
||||||
virtual ~StreamableInGlobal() = default;
|
virtual ~StreamableInGlobal() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -568,6 +575,8 @@ TEST(PrintU8StringTest, Null) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Tests that u8 strings are escaped properly.
|
// Tests that u8 strings are escaped properly.
|
||||||
|
// TODO(b/396121064) - Fix this test under MSVC
|
||||||
|
#ifndef _MSC_VER
|
||||||
TEST(PrintU8StringTest, EscapesProperly) {
|
TEST(PrintU8StringTest, EscapesProperly) {
|
||||||
const char8_t* p = u8"'\"?\\\a\b\f\n\r\t\v\x7F\xFF hello 世界";
|
const char8_t* p = u8"'\"?\\\a\b\f\n\r\t\v\x7F\xFF hello 世界";
|
||||||
EXPECT_EQ(PrintPointer(p) +
|
EXPECT_EQ(PrintPointer(p) +
|
||||||
@ -575,7 +584,8 @@ TEST(PrintU8StringTest, EscapesProperly) {
|
|||||||
"hello \\xE4\\xB8\\x96\\xE7\\x95\\x8C\"",
|
"hello \\xE4\\xB8\\x96\\xE7\\x95\\x8C\"",
|
||||||
Print(p));
|
Print(p));
|
||||||
}
|
}
|
||||||
#endif
|
#endif // _MSC_VER
|
||||||
|
#endif // __cpp_lib_char8_t
|
||||||
|
|
||||||
// const char16_t*.
|
// const char16_t*.
|
||||||
TEST(PrintU16StringTest, Const) {
|
TEST(PrintU16StringTest, Const) {
|
||||||
@ -1970,6 +1980,26 @@ TEST(PrintOneofTest, Basic) {
|
|||||||
PrintToString(Type(NonPrintable{})));
|
PrintToString(Type(NonPrintable{})));
|
||||||
}
|
}
|
||||||
#endif // GTEST_INTERNAL_HAS_VARIANT
|
#endif // GTEST_INTERNAL_HAS_VARIANT
|
||||||
|
|
||||||
|
#if GTEST_INTERNAL_HAS_COMPARE_LIB
|
||||||
|
TEST(PrintOrderingTest, Basic) {
|
||||||
|
EXPECT_EQ("(less)", PrintToString(std::strong_ordering::less));
|
||||||
|
EXPECT_EQ("(greater)", PrintToString(std::strong_ordering::greater));
|
||||||
|
// equal == equivalent for strong_ordering.
|
||||||
|
EXPECT_EQ("(equal)", PrintToString(std::strong_ordering::equivalent));
|
||||||
|
EXPECT_EQ("(equal)", PrintToString(std::strong_ordering::equal));
|
||||||
|
|
||||||
|
EXPECT_EQ("(less)", PrintToString(std::weak_ordering::less));
|
||||||
|
EXPECT_EQ("(greater)", PrintToString(std::weak_ordering::greater));
|
||||||
|
EXPECT_EQ("(equivalent)", PrintToString(std::weak_ordering::equivalent));
|
||||||
|
|
||||||
|
EXPECT_EQ("(less)", PrintToString(std::partial_ordering::less));
|
||||||
|
EXPECT_EQ("(greater)", PrintToString(std::partial_ordering::greater));
|
||||||
|
EXPECT_EQ("(equivalent)", PrintToString(std::partial_ordering::equivalent));
|
||||||
|
EXPECT_EQ("(unordered)", PrintToString(std::partial_ordering::unordered));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class string_ref;
|
class string_ref;
|
||||||
|
|
||||||
|
@ -31,14 +31,14 @@
|
|||||||
|
|
||||||
class SetupFailTest : public ::testing::Test {
|
class SetupFailTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
static void SetUpTestSuite() { ASSERT_EQ("", "SET_UP_FAIL"); }
|
static void SetUpTestSuite() { ASSERT_STREQ("", "SET_UP_FAIL"); }
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(SetupFailTest, NoopPassingTest) {}
|
TEST_F(SetupFailTest, NoopPassingTest) {}
|
||||||
|
|
||||||
class TearDownFailTest : public ::testing::Test {
|
class TearDownFailTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
static void TearDownTestSuite() { ASSERT_EQ("", "TEAR_DOWN_FAIL"); }
|
static void TearDownTestSuite() { ASSERT_STREQ("", "TEAR_DOWN_FAIL"); }
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(TearDownFailTest, NoopPassingTest) {}
|
TEST_F(TearDownFailTest, NoopPassingTest) {}
|
||||||
|
@ -2870,6 +2870,8 @@ TEST_F(FloatTest, LargeDiff) {
|
|||||||
// This ensures that no overflow occurs when comparing numbers whose
|
// This ensures that no overflow occurs when comparing numbers whose
|
||||||
// absolute value is very large.
|
// absolute value is very large.
|
||||||
TEST_F(FloatTest, Infinity) {
|
TEST_F(FloatTest, Infinity) {
|
||||||
|
EXPECT_FLOAT_EQ(values_.infinity, values_.infinity);
|
||||||
|
EXPECT_FLOAT_EQ(-values_.infinity, -values_.infinity);
|
||||||
EXPECT_FLOAT_EQ(values_.infinity, values_.close_to_infinity);
|
EXPECT_FLOAT_EQ(values_.infinity, values_.close_to_infinity);
|
||||||
EXPECT_FLOAT_EQ(-values_.infinity, -values_.close_to_infinity);
|
EXPECT_FLOAT_EQ(-values_.infinity, -values_.close_to_infinity);
|
||||||
EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(values_.infinity, -values_.infinity),
|
EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(values_.infinity, -values_.infinity),
|
||||||
@ -2894,6 +2896,11 @@ TEST_F(FloatTest, NaN) {
|
|||||||
EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(v.nan1, v.nan1), "v.nan1");
|
EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(v.nan1, v.nan1), "v.nan1");
|
||||||
EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(v.nan1, v.nan2), "v.nan2");
|
EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(v.nan1, v.nan2), "v.nan2");
|
||||||
EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(1.0, v.nan1), "v.nan1");
|
EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(1.0, v.nan1), "v.nan1");
|
||||||
|
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0f, v.nan1, 1.0f), "v.nan1");
|
||||||
|
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0f, v.nan1, v.infinity), "v.nan1");
|
||||||
|
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(v.infinity, v.nan1, 1.0f), "v.nan1");
|
||||||
|
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(v.infinity, v.nan1, v.infinity),
|
||||||
|
"v.nan1");
|
||||||
|
|
||||||
EXPECT_FATAL_FAILURE(ASSERT_FLOAT_EQ(v.nan1, v.infinity), "v.infinity");
|
EXPECT_FATAL_FAILURE(ASSERT_FLOAT_EQ(v.nan1, v.infinity), "v.infinity");
|
||||||
}
|
}
|
||||||
@ -2917,11 +2924,28 @@ TEST_F(FloatTest, Commutative) {
|
|||||||
|
|
||||||
// Tests EXPECT_NEAR.
|
// Tests EXPECT_NEAR.
|
||||||
TEST_F(FloatTest, EXPECT_NEAR) {
|
TEST_F(FloatTest, EXPECT_NEAR) {
|
||||||
|
static const FloatTest::TestValues& v = this->values_;
|
||||||
|
|
||||||
EXPECT_NEAR(-1.0f, -1.1f, 0.2f);
|
EXPECT_NEAR(-1.0f, -1.1f, 0.2f);
|
||||||
EXPECT_NEAR(2.0f, 3.0f, 1.0f);
|
EXPECT_NEAR(2.0f, 3.0f, 1.0f);
|
||||||
|
EXPECT_NEAR(v.infinity, v.infinity, 0.0f);
|
||||||
|
EXPECT_NEAR(-v.infinity, -v.infinity, 0.0f);
|
||||||
|
EXPECT_NEAR(0.0f, 1.0f, v.infinity);
|
||||||
|
EXPECT_NEAR(v.infinity, -v.infinity, v.infinity);
|
||||||
|
EXPECT_NEAR(-v.infinity, v.infinity, v.infinity);
|
||||||
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0f, 1.5f, 0.25f), // NOLINT
|
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0f, 1.5f, 0.25f), // NOLINT
|
||||||
"The difference between 1.0f and 1.5f is 0.5, "
|
"The difference between 1.0f and 1.5f is 0.5, "
|
||||||
"which exceeds 0.25f");
|
"which exceeds 0.25f");
|
||||||
|
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(v.infinity, -v.infinity, 0.0f), // NOLINT
|
||||||
|
"The difference between v.infinity and -v.infinity "
|
||||||
|
"is inf, which exceeds 0.0f");
|
||||||
|
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(-v.infinity, v.infinity, 0.0f), // NOLINT
|
||||||
|
"The difference between -v.infinity and v.infinity "
|
||||||
|
"is inf, which exceeds 0.0f");
|
||||||
|
EXPECT_NONFATAL_FAILURE(
|
||||||
|
EXPECT_NEAR(v.infinity, v.close_to_infinity, v.further_from_infinity),
|
||||||
|
"The difference between v.infinity and v.close_to_infinity is inf, which "
|
||||||
|
"exceeds v.further_from_infinity");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests ASSERT_NEAR.
|
// Tests ASSERT_NEAR.
|
||||||
@ -3028,6 +3052,8 @@ TEST_F(DoubleTest, LargeDiff) {
|
|||||||
// This ensures that no overflow occurs when comparing numbers whose
|
// This ensures that no overflow occurs when comparing numbers whose
|
||||||
// absolute value is very large.
|
// absolute value is very large.
|
||||||
TEST_F(DoubleTest, Infinity) {
|
TEST_F(DoubleTest, Infinity) {
|
||||||
|
EXPECT_DOUBLE_EQ(values_.infinity, values_.infinity);
|
||||||
|
EXPECT_DOUBLE_EQ(-values_.infinity, -values_.infinity);
|
||||||
EXPECT_DOUBLE_EQ(values_.infinity, values_.close_to_infinity);
|
EXPECT_DOUBLE_EQ(values_.infinity, values_.close_to_infinity);
|
||||||
EXPECT_DOUBLE_EQ(-values_.infinity, -values_.close_to_infinity);
|
EXPECT_DOUBLE_EQ(-values_.infinity, -values_.close_to_infinity);
|
||||||
EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(values_.infinity, -values_.infinity),
|
EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(values_.infinity, -values_.infinity),
|
||||||
@ -3047,6 +3073,12 @@ TEST_F(DoubleTest, NaN) {
|
|||||||
EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(v.nan1, v.nan1), "v.nan1");
|
EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(v.nan1, v.nan1), "v.nan1");
|
||||||
EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(v.nan1, v.nan2), "v.nan2");
|
EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(v.nan1, v.nan2), "v.nan2");
|
||||||
EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(1.0, v.nan1), "v.nan1");
|
EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(1.0, v.nan1), "v.nan1");
|
||||||
|
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0, v.nan1, 1.0), "v.nan1");
|
||||||
|
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0, v.nan1, v.infinity), "v.nan1");
|
||||||
|
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(v.infinity, v.nan1, 1.0), "v.nan1");
|
||||||
|
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(v.infinity, v.nan1, v.infinity),
|
||||||
|
"v.nan1");
|
||||||
|
|
||||||
EXPECT_FATAL_FAILURE(ASSERT_DOUBLE_EQ(v.nan1, v.infinity), "v.infinity");
|
EXPECT_FATAL_FAILURE(ASSERT_DOUBLE_EQ(v.nan1, v.infinity), "v.infinity");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3069,11 +3101,28 @@ TEST_F(DoubleTest, Commutative) {
|
|||||||
|
|
||||||
// Tests EXPECT_NEAR.
|
// Tests EXPECT_NEAR.
|
||||||
TEST_F(DoubleTest, EXPECT_NEAR) {
|
TEST_F(DoubleTest, EXPECT_NEAR) {
|
||||||
|
static const DoubleTest::TestValues& v = this->values_;
|
||||||
|
|
||||||
EXPECT_NEAR(-1.0, -1.1, 0.2);
|
EXPECT_NEAR(-1.0, -1.1, 0.2);
|
||||||
EXPECT_NEAR(2.0, 3.0, 1.0);
|
EXPECT_NEAR(2.0, 3.0, 1.0);
|
||||||
|
EXPECT_NEAR(v.infinity, v.infinity, 0.0);
|
||||||
|
EXPECT_NEAR(-v.infinity, -v.infinity, 0.0);
|
||||||
|
EXPECT_NEAR(0.0, 1.0, v.infinity);
|
||||||
|
EXPECT_NEAR(v.infinity, -v.infinity, v.infinity);
|
||||||
|
EXPECT_NEAR(-v.infinity, v.infinity, v.infinity);
|
||||||
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0, 1.5, 0.25), // NOLINT
|
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0, 1.5, 0.25), // NOLINT
|
||||||
"The difference between 1.0 and 1.5 is 0.5, "
|
"The difference between 1.0 and 1.5 is 0.5, "
|
||||||
"which exceeds 0.25");
|
"which exceeds 0.25");
|
||||||
|
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(v.infinity, -v.infinity, 0.0),
|
||||||
|
"The difference between v.infinity and -v.infinity "
|
||||||
|
"is inf, which exceeds 0.0");
|
||||||
|
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(-v.infinity, v.infinity, 0.0),
|
||||||
|
"The difference between -v.infinity and v.infinity "
|
||||||
|
"is inf, which exceeds 0.0");
|
||||||
|
EXPECT_NONFATAL_FAILURE(
|
||||||
|
EXPECT_NEAR(v.infinity, v.close_to_infinity, v.further_from_infinity),
|
||||||
|
"The difference between v.infinity and v.close_to_infinity is inf, which "
|
||||||
|
"exceeds v.further_from_infinity");
|
||||||
// At this magnitude adjacent doubles are 512.0 apart, so this triggers a
|
// At this magnitude adjacent doubles are 512.0 apart, so this triggers a
|
||||||
// slightly different failure reporting path.
|
// slightly different failure reporting path.
|
||||||
EXPECT_NONFATAL_FAILURE(
|
EXPECT_NONFATAL_FAILURE(
|
||||||
|
@ -29,14 +29,14 @@
|
|||||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
"""Unit test for the gtest_xml_output module"""
|
"""Unit test for the gtest_xml_output module."""
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import errno
|
import errno
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from xml.dom import minidom, Node
|
from xml.dom import minidom
|
||||||
|
|
||||||
from googletest.test import gtest_test_utils
|
from googletest.test import gtest_test_utils
|
||||||
from googletest.test import gtest_xml_test_utils
|
from googletest.test import gtest_xml_test_utils
|
||||||
@ -67,7 +67,10 @@ else:
|
|||||||
sys.argv.remove(NO_STACKTRACE_SUPPORT_FLAG)
|
sys.argv.remove(NO_STACKTRACE_SUPPORT_FLAG)
|
||||||
|
|
||||||
EXPECTED_NON_EMPTY_XML = """<?xml version="1.0" encoding="UTF-8"?>
|
EXPECTED_NON_EMPTY_XML = """<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<testsuites tests="26" failures="5" disabled="2" errors="0" time="*" timestamp="*" name="AllTests" ad_hoc_property="42">
|
<testsuites tests="28" failures="5" disabled="2" errors="0" time="*" timestamp="*" name="AllTests">
|
||||||
|
<properties>
|
||||||
|
<property name="ad_hoc_property" value="42"/>
|
||||||
|
</properties>
|
||||||
<testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
|
<testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
|
||||||
<testcase name="Succeeds" file="gtest_xml_output_unittest_.cc" line="53" status="run" result="completed" time="*" timestamp="*" classname="SuccessfulTest"/>
|
<testcase name="Succeeds" file="gtest_xml_output_unittest_.cc" line="53" status="run" result="completed" time="*" timestamp="*" classname="SuccessfulTest"/>
|
||||||
</testsuite>
|
</testsuite>
|
||||||
@ -132,64 +135,91 @@ It is good practice to tell why you skip a test.
|
|||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
</testsuite>
|
</testsuite>
|
||||||
<testsuite name="PropertyRecordingTest" tests="4" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*" SetUpTestSuite="yes" TearDownTestSuite="aye">
|
<testsuite name="PropertyRecordingTest" tests="4" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
|
||||||
<testcase name="OneProperty" file="gtest_xml_output_unittest_.cc" line="121" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
|
<properties>
|
||||||
|
<property name="SetUpTestSuite" value="yes"/>
|
||||||
|
<property name="SetUpTestSuite (with whitespace)" value="yes and yes"/>
|
||||||
|
<property name="TearDownTestSuite" value="aye"/>
|
||||||
|
<property name="TearDownTestSuite (with whitespace)" value="aye and aye"/>
|
||||||
|
</properties>
|
||||||
|
<testcase name="OneProperty" file="gtest_xml_output_unittest_.cc" line="125" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="key_1" value="1"/>
|
<property name="key_1" value="1"/>
|
||||||
</properties>
|
</properties>
|
||||||
</testcase>
|
</testcase>
|
||||||
<testcase name="IntValuedProperty" file="gtest_xml_output_unittest_.cc" line="125" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
|
<testcase name="IntValuedProperty" file="gtest_xml_output_unittest_.cc" line="129" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="key_int" value="1"/>
|
<property name="key_int" value="1"/>
|
||||||
</properties>
|
</properties>
|
||||||
</testcase>
|
</testcase>
|
||||||
<testcase name="ThreeProperties" file="gtest_xml_output_unittest_.cc" line="129" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
|
<testcase name="ThreeProperties" file="gtest_xml_output_unittest_.cc" line="133" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="key_1" value="1"/>
|
<property name="key_1" value="1"/>
|
||||||
<property name="key_2" value="2"/>
|
<property name="key_2" value="2"/>
|
||||||
<property name="key_3" value="3"/>
|
<property name="key_3" value="3"/>
|
||||||
</properties>
|
</properties>
|
||||||
</testcase>
|
</testcase>
|
||||||
<testcase name="TwoValuesForOneKeyUsesLastValue" file="gtest_xml_output_unittest_.cc" line="135" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
|
<testcase name="TwoValuesForOneKeyUsesLastValue" file="gtest_xml_output_unittest_.cc" line="139" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="key_1" value="2"/>
|
<property name="key_1" value="2"/>
|
||||||
</properties>
|
</properties>
|
||||||
</testcase>
|
</testcase>
|
||||||
</testsuite>
|
</testsuite>
|
||||||
<testsuite name="NoFixtureTest" tests="3" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
|
<testsuite name="NoFixtureTest" tests="3" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
|
||||||
<testcase name="RecordProperty" file="gtest_xml_output_unittest_.cc" line="140" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest">
|
<testcase name="RecordProperty" file="gtest_xml_output_unittest_.cc" line="144" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="key" value="1"/>
|
<property name="key" value="1"/>
|
||||||
</properties>
|
</properties>
|
||||||
</testcase>
|
</testcase>
|
||||||
<testcase name="ExternalUtilityThatCallsRecordIntValuedProperty" file="gtest_xml_output_unittest_.cc" line="153" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest">
|
<testcase name="ExternalUtilityThatCallsRecordIntValuedProperty" file="gtest_xml_output_unittest_.cc" line="157" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="key_for_utility_int" value="1"/>
|
<property name="key_for_utility_int" value="1"/>
|
||||||
</properties>
|
</properties>
|
||||||
</testcase>
|
</testcase>
|
||||||
<testcase name="ExternalUtilityThatCallsRecordStringValuedProperty" file="gtest_xml_output_unittest_.cc" line="157" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest">
|
<testcase name="ExternalUtilityThatCallsRecordStringValuedProperty" file="gtest_xml_output_unittest_.cc" line="161" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="key_for_utility_string" value="1"/>
|
<property name="key_for_utility_string" value="1"/>
|
||||||
</properties>
|
</properties>
|
||||||
</testcase>
|
</testcase>
|
||||||
</testsuite>
|
</testsuite>
|
||||||
|
<testsuite name="SetupFailTest" tests="1" failures="0" disabled="0" skipped="1" errors="0" time="*" timestamp="*">
|
||||||
|
<testcase name="NoopPassingTest" file="gtest_xml_output_unittest_.cc" line="172" status="run" result="skipped" time="*" timestamp="*" classname="SetupFailTest">
|
||||||
|
<skipped message="gtest_xml_output_unittest_.cc:*
"><![CDATA[gtest_xml_output_unittest_.cc:*
|
||||||
|
]]></skipped>
|
||||||
|
</testcase>
|
||||||
|
<testcase name="" status="run" result="completed" classname="" time="*" timestamp="*">
|
||||||
|
<failure message="gtest_xml_output_unittest_.cc:*
Expected equality of these values:
 1
 2%(stack_entity)s" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
|
||||||
|
Expected equality of these values:
|
||||||
|
1
|
||||||
|
2%(stack)s]]></failure>
|
||||||
|
</testcase>
|
||||||
|
</testsuite>
|
||||||
|
<testsuite name="TearDownFailTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
|
||||||
|
<testcase name="NoopPassingTest" file="gtest_xml_output_unittest_.cc" line="179" status="run" result="completed" time="*" timestamp="*" classname="TearDownFailTest"/>
|
||||||
|
<testcase name="" status="run" result="completed" classname="" time="*" timestamp="*">
|
||||||
|
<failure message="gtest_xml_output_unittest_.cc:*
Expected equality of these values:
 1
 2%(stack_entity)s" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
|
||||||
|
Expected equality of these values:
|
||||||
|
1
|
||||||
|
2%(stack)s]]></failure>
|
||||||
|
</testcase>
|
||||||
|
</testsuite>
|
||||||
<testsuite name="Single/ValueParamTest" tests="4" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
|
<testsuite name="Single/ValueParamTest" tests="4" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
|
||||||
<testcase name="HasValueParamAttribute/0" file="gtest_xml_output_unittest_.cc" line="164" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
|
<testcase name="HasValueParamAttribute/0" file="gtest_xml_output_unittest_.cc" line="184" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
|
||||||
<testcase name="HasValueParamAttribute/1" file="gtest_xml_output_unittest_.cc" line="164" value_param="42" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
|
<testcase name="HasValueParamAttribute/1" file="gtest_xml_output_unittest_.cc" line="184" value_param="42" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
|
||||||
<testcase name="AnotherTestThatHasValueParamAttribute/0" file="gtest_xml_output_unittest_.cc" line="165" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
|
<testcase name="AnotherTestThatHasValueParamAttribute/0" file="gtest_xml_output_unittest_.cc" line="185" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
|
||||||
<testcase name="AnotherTestThatHasValueParamAttribute/1" file="gtest_xml_output_unittest_.cc" line="165" value_param="42" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
|
<testcase name="AnotherTestThatHasValueParamAttribute/1" file="gtest_xml_output_unittest_.cc" line="185" value_param="42" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
|
||||||
</testsuite>
|
</testsuite>
|
||||||
<testsuite name="TypedTest/0" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
|
<testsuite name="TypedTest/0" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
|
||||||
<testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="173" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="TypedTest/0" />
|
<testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="193" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="TypedTest/0" />
|
||||||
</testsuite>
|
</testsuite>
|
||||||
<testsuite name="TypedTest/1" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
|
<testsuite name="TypedTest/1" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
|
||||||
<testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="173" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="TypedTest/1" />
|
<testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="193" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="TypedTest/1" />
|
||||||
</testsuite>
|
</testsuite>
|
||||||
<testsuite name="Single/TypeParameterizedTestSuite/0" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
|
<testsuite name="Single/TypeParameterizedTestSuite/0" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
|
||||||
<testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="180" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/0" />
|
<testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="200" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/0" />
|
||||||
</testsuite>
|
</testsuite>
|
||||||
<testsuite name="Single/TypeParameterizedTestSuite/1" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
|
<testsuite name="Single/TypeParameterizedTestSuite/1" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
|
||||||
<testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="180" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/1" />
|
<testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="200" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/1" />
|
||||||
</testsuite>
|
</testsuite>
|
||||||
</testsuites>""" % {
|
</testsuites>""" % {
|
||||||
'stack': STACK_TRACE_TEMPLATE,
|
'stack': STACK_TRACE_TEMPLATE,
|
||||||
@ -197,8 +227,10 @@ It is good practice to tell why you skip a test.
|
|||||||
}
|
}
|
||||||
|
|
||||||
EXPECTED_FILTERED_TEST_XML = """<?xml version="1.0" encoding="UTF-8"?>
|
EXPECTED_FILTERED_TEST_XML = """<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<testsuites tests="1" failures="0" disabled="0" errors="0" time="*"
|
<testsuites tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests">
|
||||||
timestamp="*" name="AllTests" ad_hoc_property="42">
|
<properties>
|
||||||
|
<property name="ad_hoc_property" value="42"/>
|
||||||
|
</properties>
|
||||||
<testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" skipped="0"
|
<testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" skipped="0"
|
||||||
errors="0" time="*" timestamp="*">
|
errors="0" time="*" timestamp="*">
|
||||||
<testcase name="Succeeds" file="gtest_xml_output_unittest_.cc" line="53" status="run" result="completed" time="*" timestamp="*" classname="SuccessfulTest"/>
|
<testcase name="Succeeds" file="gtest_xml_output_unittest_.cc" line="53" status="run" result="completed" time="*" timestamp="*" classname="SuccessfulTest"/>
|
||||||
@ -206,19 +238,28 @@ EXPECTED_FILTERED_TEST_XML = """<?xml version="1.0" encoding="UTF-8"?>
|
|||||||
</testsuites>"""
|
</testsuites>"""
|
||||||
|
|
||||||
EXPECTED_SHARDED_TEST_XML = """<?xml version="1.0" encoding="UTF-8"?>
|
EXPECTED_SHARDED_TEST_XML = """<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<testsuites tests="3" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests" ad_hoc_property="42">
|
<testsuites tests="3" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests">
|
||||||
|
<properties>
|
||||||
|
<property name="ad_hoc_property" value="42"/>
|
||||||
|
</properties>
|
||||||
<testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
|
<testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
|
||||||
<testcase name="Succeeds" file="gtest_xml_output_unittest_.cc" line="53" status="run" result="completed" time="*" timestamp="*" classname="SuccessfulTest"/>
|
<testcase name="Succeeds" file="gtest_xml_output_unittest_.cc" line="53" status="run" result="completed" time="*" timestamp="*" classname="SuccessfulTest"/>
|
||||||
</testsuite>
|
</testsuite>
|
||||||
<testsuite name="PropertyRecordingTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*" SetUpTestSuite="yes" TearDownTestSuite="aye">
|
<testsuite name="PropertyRecordingTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
|
||||||
<testcase name="IntValuedProperty" file="gtest_xml_output_unittest_.cc" line="125" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
|
<properties>
|
||||||
|
<property name="SetUpTestSuite" value="yes"/>
|
||||||
|
<property name="SetUpTestSuite (with whitespace)" value="yes and yes"/>
|
||||||
|
<property name="TearDownTestSuite" value="aye"/>
|
||||||
|
<property name="TearDownTestSuite (with whitespace)" value="aye and aye"/>
|
||||||
|
</properties>
|
||||||
|
<testcase name="IntValuedProperty" file="gtest_xml_output_unittest_.cc" line="129" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="key_int" value="1"/>
|
<property name="key_int" value="1"/>
|
||||||
</properties>
|
</properties>
|
||||||
</testcase>
|
</testcase>
|
||||||
</testsuite>
|
</testsuite>
|
||||||
<testsuite name="Single/ValueParamTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
|
<testsuite name="Single/TypeParameterizedTestSuite/0" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
|
||||||
<testcase name="HasValueParamAttribute/0" file="gtest_xml_output_unittest_.cc" line="164" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
|
<testcase name="HasTypeParamAttribute" type_param="*" file="gtest_xml_output_unittest_.cc" line="200" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/0" />
|
||||||
</testsuite>
|
</testsuite>
|
||||||
</testsuites>"""
|
</testsuites>"""
|
||||||
|
|
||||||
|
@ -112,8 +112,12 @@ TEST(InvalidCharactersTest, InvalidCharactersInMessage) {
|
|||||||
|
|
||||||
class PropertyRecordingTest : public Test {
|
class PropertyRecordingTest : public Test {
|
||||||
public:
|
public:
|
||||||
static void SetUpTestSuite() { RecordProperty("SetUpTestSuite", "yes"); }
|
static void SetUpTestSuite() {
|
||||||
|
RecordProperty("SetUpTestSuite (with whitespace)", "yes and yes");
|
||||||
|
RecordProperty("SetUpTestSuite", "yes");
|
||||||
|
}
|
||||||
static void TearDownTestSuite() {
|
static void TearDownTestSuite() {
|
||||||
|
RecordProperty("TearDownTestSuite (with whitespace)", "aye and aye");
|
||||||
RecordProperty("TearDownTestSuite", "aye");
|
RecordProperty("TearDownTestSuite", "aye");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -158,6 +162,22 @@ TEST(NoFixtureTest, ExternalUtilityThatCallsRecordStringValuedProperty) {
|
|||||||
ExternalUtilityThatCallsRecordProperty("key_for_utility_string", "1");
|
ExternalUtilityThatCallsRecordProperty("key_for_utility_string", "1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensures that SetUpTestSuite and TearDownTestSuite failures are reported in
|
||||||
|
// the XML output.
|
||||||
|
class SetupFailTest : public ::testing::Test {
|
||||||
|
protected:
|
||||||
|
static void SetUpTestSuite() { ASSERT_EQ(1, 2); }
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(SetupFailTest, NoopPassingTest) {}
|
||||||
|
|
||||||
|
class TearDownFailTest : public ::testing::Test {
|
||||||
|
protected:
|
||||||
|
static void TearDownTestSuite() { ASSERT_EQ(1, 2); }
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(TearDownFailTest, NoopPassingTest) {}
|
||||||
|
|
||||||
// Verifies that the test parameter value is output in the 'value_param'
|
// Verifies that the test parameter value is output in the 'value_param'
|
||||||
// XML attribute for value-parameterized tests.
|
// XML attribute for value-parameterized tests.
|
||||||
class ValueParamTest : public TestWithParam<int> {};
|
class ValueParamTest : public TestWithParam<int> {};
|
||||||
|
@ -6,20 +6,20 @@ load("//:fake_fuchsia_sdk.bzl", "fake_fuchsia_sdk")
|
|||||||
def googletest_deps():
|
def googletest_deps():
|
||||||
"""Loads common dependencies needed to use the googletest library."""
|
"""Loads common dependencies needed to use the googletest library."""
|
||||||
|
|
||||||
if not native.existing_rule("com_googlesource_code_re2"):
|
if not native.existing_rule("re2"):
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "com_googlesource_code_re2",
|
name = "re2",
|
||||||
sha256 = "eb2df807c781601c14a260a507a5bb4509be1ee626024cb45acbd57cb9d4032b",
|
sha256 = "eb2df807c781601c14a260a507a5bb4509be1ee626024cb45acbd57cb9d4032b",
|
||||||
strip_prefix = "re2-2024-07-02",
|
strip_prefix = "re2-2024-07-02",
|
||||||
urls = ["https://github.com/google/re2/releases/download/2024-07-02/re2-2024-07-02.tar.gz"],
|
urls = ["https://github.com/google/re2/releases/download/2024-07-02/re2-2024-07-02.tar.gz"],
|
||||||
)
|
)
|
||||||
|
|
||||||
if not native.existing_rule("com_google_absl"):
|
if not native.existing_rule("abseil-cpp"):
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "com_google_absl",
|
name = "abseil-cpp",
|
||||||
sha256 = "733726b8c3a6d39a4120d7e45ea8b41a434cdacde401cba500f14236c49b39dc",
|
sha256 = "16242f394245627e508ec6bb296b433c90f8d914f73b9c026fddb905e27276e8",
|
||||||
strip_prefix = "abseil-cpp-20240116.2",
|
strip_prefix = "abseil-cpp-20250127.0",
|
||||||
urls = ["https://github.com/abseil/abseil-cpp/releases/download/20240116.2/abseil-cpp-20240116.2.tar.gz"],
|
urls = ["https://github.com/abseil/abseil-cpp/releases/download/20250127.0/abseil-cpp-20250127.0.tar.gz"],
|
||||||
)
|
)
|
||||||
|
|
||||||
if not native.existing_rule("fuchsia_sdk"):
|
if not native.existing_rule("fuchsia_sdk"):
|
||||||
|
Loading…
Reference in New Issue
Block a user