mirror of
https://github.com/google/googletest.git
synced 2025-12-06 16:57:00 +08:00
Compare commits
80 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b96fa13f5 | ||
|
|
085af2cc08 | ||
|
|
37678c92fb | ||
|
|
dedab73a68 | ||
|
|
6ec14dfd8c | ||
|
|
17d335d7c7 | ||
|
|
4fe3307fb2 | ||
|
|
b2b9072ecb | ||
|
|
e17e37a115 | ||
|
|
8dbd60f7d5 | ||
|
|
2ce9d8f2e8 | ||
|
|
279f847946 | ||
|
|
de1c609262 | ||
|
|
9706f75b8f | ||
|
|
50b8600c63 | ||
|
|
0934b7e112 | ||
|
|
4969d0ad54 | ||
|
|
9df216cc9d | ||
|
|
7917641ff9 | ||
|
|
eb2d85edd0 | ||
|
|
6986c2b575 | ||
|
|
a05c091507 | ||
|
|
244cec869d | ||
|
|
373af2e3df | ||
|
|
32f9f4c82a | ||
|
|
7e17b15f15 | ||
|
|
309dab8d4b | ||
|
|
3983f67e32 | ||
|
|
c67de11737 | ||
|
|
a45468c0fc | ||
|
|
f8ed0e687c | ||
|
|
35b75a2cba | ||
|
|
175c1b55cf | ||
|
|
1aeec48a1d | ||
|
|
0fe21ac6ef | ||
|
|
fd15f51d57 | ||
|
|
6230d316e1 | ||
|
|
28e9d1f267 | ||
|
|
7e2c425db2 | ||
|
|
e9092b12dc | ||
|
|
7427a6b5e3 | ||
|
|
7da55820cc | ||
|
|
3abc68be30 | ||
|
|
09ffd00153 | ||
|
|
6aa03e6774 | ||
|
|
16d4f8eff6 | ||
|
|
bac6a8fd8a | ||
|
|
fa8438ae6b | ||
|
|
571930618f | ||
|
|
9f79a9597a | ||
|
|
8b8ef3ff0d | ||
|
|
90a4152114 | ||
|
|
04ee1b4f2a | ||
|
|
54915d462b | ||
|
|
59c924bc47 | ||
|
|
00b2154e8e | ||
|
|
cd430b47a5 | ||
|
|
155b337c93 | ||
|
|
e90fe24856 | ||
|
|
50a9511f50 | ||
|
|
52204f78f9 | ||
|
|
2ae29b52fd | ||
|
|
c2ceb2b09b | ||
|
|
e7b26b7246 | ||
|
|
3af834740f | ||
|
|
4902ea2d7c | ||
|
|
4ee4b17bf5 | ||
|
|
0bdccf4aa2 | ||
|
|
e88cb95b92 | ||
|
|
24a9e940d4 | ||
|
|
72189081ca | ||
|
|
144d335538 | ||
|
|
e5669fdffc | ||
|
|
54501746a6 | ||
|
|
3fbe4db9a3 | ||
|
|
a6ce08abf7 | ||
|
|
c00fd25b71 | ||
|
|
4a00a24fff | ||
|
|
a866428a78 | ||
|
|
005254dae2 |
22
BUILD.bazel
22
BUILD.bazel
@ -30,6 +30,8 @@
|
|||||||
#
|
#
|
||||||
# Bazel Build for Google C++ Testing Framework(Google Test)
|
# Bazel Build for Google C++ Testing Framework(Google Test)
|
||||||
|
|
||||||
|
load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
|
||||||
|
|
||||||
package(default_visibility = ["//visibility:public"])
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
licenses(["notice"])
|
licenses(["notice"])
|
||||||
@ -83,6 +85,10 @@ cc_library(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Google Test including Google Mock
|
# Google Test including Google Mock
|
||||||
|
|
||||||
|
# For an actual test, use `gtest` and also `gtest_main` if you depend on gtest's
|
||||||
|
# main(). For a library, use `gtest_for_library` instead if the library can be
|
||||||
|
# testonly.
|
||||||
cc_library(
|
cc_library(
|
||||||
name = "gtest",
|
name = "gtest",
|
||||||
srcs = glob(
|
srcs = glob(
|
||||||
@ -147,10 +153,7 @@ cc_library(
|
|||||||
"@abseil-cpp//absl/flags:reflection",
|
"@abseil-cpp//absl/flags:reflection",
|
||||||
"@abseil-cpp//absl/flags:usage",
|
"@abseil-cpp//absl/flags:usage",
|
||||||
"@abseil-cpp//absl/strings",
|
"@abseil-cpp//absl/strings",
|
||||||
"@abseil-cpp//absl/types:any",
|
"@re2",
|
||||||
"@abseil-cpp//absl/types:optional",
|
|
||||||
"@abseil-cpp//absl/types:variant",
|
|
||||||
"@re2//:re2",
|
|
||||||
],
|
],
|
||||||
"//conditions:default": [],
|
"//conditions:default": [],
|
||||||
}) + select({
|
}) + select({
|
||||||
@ -160,13 +163,22 @@ cc_library(
|
|||||||
# Otherwise, builds targeting Fuchsia would fail to compile.
|
# Otherwise, builds targeting Fuchsia would fail to compile.
|
||||||
":fuchsia": [
|
":fuchsia": [
|
||||||
"@fuchsia_sdk//pkg/fdio",
|
"@fuchsia_sdk//pkg/fdio",
|
||||||
"@fuchsia_sdk//pkg/syslog",
|
|
||||||
"@fuchsia_sdk//pkg/zx",
|
"@fuchsia_sdk//pkg/zx",
|
||||||
],
|
],
|
||||||
"//conditions:default": [],
|
"//conditions:default": [],
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# `gtest`, but testonly. See guidance on `gtest` for when to use this.
|
||||||
|
alias(
|
||||||
|
name = "gtest_for_library",
|
||||||
|
testonly = True,
|
||||||
|
actual = ":gtest",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Implements main() for tests using gtest. Prefer to depend on `gtest` as well
|
||||||
|
# to ensure compliance with the layering_check Bazel feature where only the
|
||||||
|
# direct hdrs values are available.
|
||||||
cc_library(
|
cc_library(
|
||||||
name = "gtest_main",
|
name = "gtest_main",
|
||||||
srcs = ["googlemock/src/gmock_main.cc"],
|
srcs = ["googlemock/src/gmock_main.cc"],
|
||||||
|
|||||||
@ -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.15.2)
|
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)
|
||||||
|
|||||||
13
MODULE.bazel
13
MODULE.bazel
@ -41,20 +41,25 @@ module(
|
|||||||
|
|
||||||
bazel_dep(
|
bazel_dep(
|
||||||
name = "abseil-cpp",
|
name = "abseil-cpp",
|
||||||
version = "20250127.0",
|
version = "20250814.0",
|
||||||
)
|
)
|
||||||
bazel_dep(
|
bazel_dep(
|
||||||
name = "platforms",
|
name = "platforms",
|
||||||
version = "0.0.10",
|
version = "0.0.11",
|
||||||
)
|
)
|
||||||
bazel_dep(
|
bazel_dep(
|
||||||
name = "re2",
|
name = "re2",
|
||||||
version = "2024-07-02",
|
version = "2024-07-02.bcr.1",
|
||||||
|
)
|
||||||
|
|
||||||
|
bazel_dep(
|
||||||
|
name = "rules_cc",
|
||||||
|
version = "0.2.8"
|
||||||
)
|
)
|
||||||
|
|
||||||
bazel_dep(
|
bazel_dep(
|
||||||
name = "rules_python",
|
name = "rules_python",
|
||||||
version = "1.1.0",
|
version = "1.3.0",
|
||||||
dev_dependency = True,
|
dev_dependency = True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
16
README.md
16
README.md
@ -2,27 +2,19 @@
|
|||||||
|
|
||||||
### Announcements
|
### Announcements
|
||||||
|
|
||||||
#### Live at Head
|
|
||||||
|
|
||||||
GoogleTest now follows the
|
|
||||||
[Abseil Live at Head philosophy](https://abseil.io/about/philosophy#upgrade-support).
|
|
||||||
We recommend
|
|
||||||
[updating to the latest commit in the `main` branch as often as possible](https://github.com/abseil/abseil-cpp/blob/master/FAQ.md#what-is-live-at-head-and-how-do-i-do-it).
|
|
||||||
We do publish occasional semantic versions, tagged with
|
|
||||||
`v${major}.${minor}.${patch}` (e.g. `v1.15.2`).
|
|
||||||
|
|
||||||
#### Documentation Updates
|
#### Documentation Updates
|
||||||
|
|
||||||
Our documentation is now live on GitHub Pages at
|
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.15.2
|
#### Release 1.17.0
|
||||||
|
|
||||||
[Release 1.15.2](https://github.com/google/googletest/releases/tag/v1.15.2) is
|
[Release 1.17.0](https://github.com/google/googletest/releases/tag/v1.17.0) is
|
||||||
now available.
|
now available.
|
||||||
|
|
||||||
The 1.15.x branch requires at least C++14.
|
The 1.17.x branch
|
||||||
|
[requires at least C++17](https://opensource.google/documentation/policies/cplusplus-support#c_language_standard).
|
||||||
|
|
||||||
#### Continuous Integration
|
#### Continuous Integration
|
||||||
|
|
||||||
|
|||||||
24
WORKSPACE
24
WORKSPACE
@ -37,25 +37,25 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
|||||||
|
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "rules_python",
|
name = "rules_python",
|
||||||
sha256 = "9c6e26911a79fbf510a8f06d8eedb40f412023cf7fa6d1461def27116bff022c",
|
sha256 = "2cc26bbd53854ceb76dd42a834b1002cd4ba7f8df35440cf03482e045affc244",
|
||||||
strip_prefix = "rules_python-1.1.0",
|
strip_prefix = "rules_python-1.3.0",
|
||||||
url = "https://github.com/bazelbuild/rules_python/releases/download/1.1.0/rules_python-1.1.0.tar.gz",
|
url = "https://github.com/bazelbuild/rules_python/releases/download/1.3.0/rules_python-1.3.0.tar.gz",
|
||||||
)
|
)
|
||||||
# https://github.com/bazelbuild/rules_python/releases/tag/1.1.0
|
# https://github.com/bazelbuild/rules_python/releases/tag/1.1.0
|
||||||
load("@rules_python//python:repositories.bzl", "py_repositories")
|
load("@rules_python//python:repositories.bzl", "py_repositories")
|
||||||
py_repositories()
|
py_repositories()
|
||||||
|
|
||||||
http_archive(
|
|
||||||
name = "bazel_skylib",
|
|
||||||
sha256 = "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94",
|
|
||||||
urls = ["https://github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz"],
|
|
||||||
)
|
|
||||||
|
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "platforms",
|
name = "platforms",
|
||||||
urls = [
|
urls = [
|
||||||
"https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.10/platforms-0.0.10.tar.gz",
|
"https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.11/platforms-0.0.11.tar.gz",
|
||||||
"https://github.com/bazelbuild/platforms/releases/download/0.0.10/platforms-0.0.10.tar.gz",
|
"https://github.com/bazelbuild/platforms/releases/download/0.0.11/platforms-0.0.11.tar.gz",
|
||||||
],
|
],
|
||||||
sha256 = "218efe8ee736d26a3572663b374a253c012b716d8af0c07e842e82f238a0a7ee",
|
sha256 = "29742e87275809b5e598dc2f04d86960cc7a55b3067d97221c9abbc9926bff0f",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
load("@bazel_features//:deps.bzl", "bazel_features_deps")
|
||||||
|
bazel_features_deps()
|
||||||
|
|
||||||
|
load("@rules_cc//cc:extensions.bzl", "compatibility_proxy_repo")
|
||||||
|
compatibility_proxy_repo()
|
||||||
|
|||||||
@ -31,31 +31,60 @@
|
|||||||
|
|
||||||
set -euox pipefail
|
set -euox pipefail
|
||||||
|
|
||||||
readonly LINUX_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20241218"
|
readonly LINUX_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20250430"
|
||||||
readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20250205"
|
readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20250430"
|
||||||
|
|
||||||
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
|
# Use Bazel Vendor mode to reduce reliance on external dependencies.
|
||||||
STD="c++14 c++17 c++20"
|
# See https://bazel.build/external/vendor and the Dockerfile for
|
||||||
|
# an explaination of how this works.
|
||||||
|
if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f "${KOKORO_GFILE_DIR}/distdir/googletest_vendor.tar.gz" ]]; then
|
||||||
|
DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly --env=BAZEL_VENDOR_ARCHIVE=/distdir/googletest_vendor.tar.gz ${DOCKER_EXTRA_ARGS:-}"
|
||||||
|
BAZEL_EXTRA_ARGS="--vendor_dir=/googletest_vendor ${BAZEL_EXTRA_ARGS:-}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Test the CMake build
|
if [[ -z ${STD:-} ]]; then
|
||||||
for cc in /usr/local/bin/gcc /opt/llvm/clang/bin/clang; do
|
STD="c++17 c++20 c++23"
|
||||||
for cmake_off_on in OFF ON; do
|
fi
|
||||||
|
|
||||||
|
# Test CMake + GCC
|
||||||
|
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=${cc}" \
|
--env="CC=/usr/local/bin/gcc" \
|
||||||
--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=14 \
|
-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
|
||||||
|
|
||||||
|
# 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_samples=ON \
|
||||||
-Dgtest_build_tests=ON \
|
-Dgtest_build_tests=ON \
|
||||||
-Dgmock_build_tests=ON \
|
-Dgmock_build_tests=ON \
|
||||||
@ -63,30 +92,30 @@ for cc in /usr/local/bin/gcc /opt/llvm/clang/bin/clang; do
|
|||||||
-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
|
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" \
|
||||||
|
${DOCKER_EXTRA_ARGS:-} \
|
||||||
${LINUX_GCC_FLOOR_CONTAINER} \
|
${LINUX_GCC_FLOOR_CONTAINER} \
|
||||||
|
/bin/bash --login -c "
|
||||||
/usr/local/bin/bazel test ... \
|
/usr/local/bin/bazel test ... \
|
||||||
--copt="-Wall" \
|
--copt=\"-Wall\" \
|
||||||
--copt="-Werror" \
|
--copt=\"-Werror\" \
|
||||||
--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 \
|
||||||
--test_output=errors
|
--test_output=errors \
|
||||||
|
${BAZEL_EXTRA_ARGS:-}"
|
||||||
|
|
||||||
# Test GCC
|
# Test GCC
|
||||||
for std in ${STD}; do
|
for std in ${STD}; do
|
||||||
@ -97,18 +126,21 @@ for std in ${STD}; do
|
|||||||
--rm \
|
--rm \
|
||||||
--env="CC=/usr/local/bin/gcc" \
|
--env="CC=/usr/local/bin/gcc" \
|
||||||
--env="BAZEL_CXXOPTS=-std=${std}" \
|
--env="BAZEL_CXXOPTS=-std=${std}" \
|
||||||
|
${DOCKER_EXTRA_ARGS:-} \
|
||||||
${LINUX_LATEST_CONTAINER} \
|
${LINUX_LATEST_CONTAINER} \
|
||||||
|
/bin/bash --login -c "
|
||||||
/usr/local/bin/bazel test ... \
|
/usr/local/bin/bazel test ... \
|
||||||
--copt="-Wall" \
|
--copt=\"-Wall\" \
|
||||||
--copt="-Werror" \
|
--copt=\"-Werror\" \
|
||||||
--copt="-Wuninitialized" \
|
--copt=\"-Wuninitialized\" \
|
||||||
--copt="-Wundef" \
|
--copt=\"-Wundef\" \
|
||||||
--define="absl=${absl}" \
|
--define=\"absl=${absl}\" \
|
||||||
--enable_bzlmod=true \
|
--enable_bzlmod=true \
|
||||||
--features=external_include_paths \
|
--features=external_include_paths \
|
||||||
--keep_going \
|
--keep_going \
|
||||||
--show_timestamps \
|
--show_timestamps \
|
||||||
--test_output=errors
|
--test_output=errors \
|
||||||
|
${BAZEL_EXTRA_ARGS:-}"
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
@ -121,19 +153,22 @@ for std in ${STD}; do
|
|||||||
--rm \
|
--rm \
|
||||||
--env="CC=/opt/llvm/clang/bin/clang" \
|
--env="CC=/opt/llvm/clang/bin/clang" \
|
||||||
--env="BAZEL_CXXOPTS=-std=${std}" \
|
--env="BAZEL_CXXOPTS=-std=${std}" \
|
||||||
|
${DOCKER_EXTRA_ARGS:-} \
|
||||||
${LINUX_LATEST_CONTAINER} \
|
${LINUX_LATEST_CONTAINER} \
|
||||||
|
/bin/bash --login -c "
|
||||||
/usr/local/bin/bazel test ... \
|
/usr/local/bin/bazel test ... \
|
||||||
--copt="--gcc-toolchain=/usr/local" \
|
--copt=\"--gcc-toolchain=/usr/local\" \
|
||||||
--copt="-Wall" \
|
--copt=\"-Wall\" \
|
||||||
--copt="-Werror" \
|
--copt=\"-Werror\" \
|
||||||
--copt="-Wuninitialized" \
|
--copt=\"-Wuninitialized\" \
|
||||||
--copt="-Wundef" \
|
--copt=\"-Wundef\" \
|
||||||
--define="absl=${absl}" \
|
--define=\"absl=${absl}\" \
|
||||||
--enable_bzlmod=true \
|
--enable_bzlmod=true \
|
||||||
--features=external_include_paths \
|
--features=external_include_paths \
|
||||||
--keep_going \
|
--keep_going \
|
||||||
--linkopt="--gcc-toolchain=/usr/local" \
|
--linkopt=\"--gcc-toolchain=/usr/local\" \
|
||||||
--show_timestamps \
|
--show_timestamps \
|
||||||
--test_output=errors
|
--test_output=errors \
|
||||||
|
${BAZEL_EXTRA_ARGS:-}"
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|||||||
@ -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.2.1-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}
|
||||||
@ -61,17 +64,24 @@ else
|
|||||||
BAZEL_BIN="bazel"
|
BAZEL_BIN="bazel"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Use Bazel Vendor mode to reduce reliance on external dependencies.
|
||||||
|
if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f "${KOKORO_GFILE_DIR}/distdir/googletest_vendor.tar.gz" ]]; then
|
||||||
|
tar -xf "${KOKORO_GFILE_DIR}/distdir/googletest_vendor.tar.gz" -C "${HOME}/"
|
||||||
|
BAZEL_EXTRA_ARGS="--vendor_dir=${HOME}/googletest_vendor ${BAZEL_EXTRA_ARGS:-}"
|
||||||
|
fi
|
||||||
|
|
||||||
cd ${GTEST_ROOT}
|
cd ${GTEST_ROOT}
|
||||||
for absl in 0 1; do
|
for absl in 0 1; do
|
||||||
${BAZEL_BIN} test ... \
|
${BAZEL_BIN} test ... \
|
||||||
--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 \
|
||||||
--keep_going \
|
--keep_going \
|
||||||
--show_timestamps \
|
--show_timestamps \
|
||||||
--test_output=errors
|
--test_output=errors \
|
||||||
|
${BAZEL_EXTRA_ARGS:-}
|
||||||
done
|
done
|
||||||
|
|||||||
@ -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.2.1-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,8 +37,8 @@ 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
|
||||||
@ -50,14 +47,39 @@ RMDIR /S /Q cmake_msvc2022
|
|||||||
:: because of Windows limitations on path length.
|
:: because of Windows limitations on path length.
|
||||||
:: --output_user_root=C:\tmp causes Bazel to use a shorter path.
|
:: --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
|
||||||
|
|
||||||
|
:: Use Bazel Vendor mode to reduce reliance on external dependencies.
|
||||||
|
IF EXIST "%KOKORO_GFILE_DIR%\distdir\googletest_vendor.tar.gz" (
|
||||||
|
tar --force-local -xf "%KOKORO_GFILE_DIR%\distdir\googletest_vendor.tar.gz" -C c:
|
||||||
|
SET VENDOR_FLAG=--vendor_dir=c:\googletest_vendor
|
||||||
|
) ELSE (
|
||||||
|
SET VENDOR_FLAG=
|
||||||
|
)
|
||||||
|
|
||||||
|
:: C++17
|
||||||
%BAZEL_EXE% ^
|
%BAZEL_EXE% ^
|
||||||
--output_user_root=C:\tmp ^
|
--output_user_root=C:\tmp ^
|
||||||
test ... ^
|
test ... ^
|
||||||
--compilation_mode=dbg ^
|
--compilation_mode=dbg ^
|
||||||
--copt=/std:c++14 ^
|
--copt=/std:c++17 ^
|
||||||
--copt=/WX ^
|
--copt=/WX ^
|
||||||
--enable_bzlmod=true ^
|
--enable_bzlmod=true ^
|
||||||
--keep_going ^
|
--keep_going ^
|
||||||
--test_output=errors ^
|
--test_output=errors ^
|
||||||
--test_tag_filters=-no_test_msvc2017
|
--test_tag_filters=-no_test_msvc2017 ^
|
||||||
|
%VENDOR_FLAG%
|
||||||
|
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 ^
|
||||||
|
--enable_bzlmod=true ^
|
||||||
|
--keep_going ^
|
||||||
|
--test_output=errors ^
|
||||||
|
--test_tag_filters=-no_test_msvc2017 ^
|
||||||
|
%VENDOR_FLAG%
|
||||||
IF %errorlevel% neq 0 EXIT /B 1
|
IF %errorlevel% neq 0 EXIT /B 1
|
||||||
|
|||||||
@ -7,15 +7,15 @@
|
|||||||
|
|
||||||
{% seo %}
|
{% seo %}
|
||||||
<link rel="stylesheet" href="{{ "/assets/css/style.css?v=" | append: site.github.build_revision | relative_url }}">
|
<link rel="stylesheet" href="{{ "/assets/css/style.css?v=" | append: site.github.build_revision | relative_url }}">
|
||||||
|
<!-- Google tag (gtag.js) -->
|
||||||
|
<script async src="https://www.googletagmanager.com/gtag/js?id=G-9PTP6FW1M5"></script>
|
||||||
<script>
|
<script>
|
||||||
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
|
window.dataLayer = window.dataLayer || [];
|
||||||
ga('create', 'UA-197576187-1', { 'storage': 'none' });
|
function gtag(){dataLayer.push(arguments);}
|
||||||
ga('set', 'referrer', document.referrer.split('?')[0]);
|
gtag('js', new Date());
|
||||||
ga('set', 'location', window.location.href.split('?')[0]);
|
|
||||||
ga('set', 'anonymizeIp', true);
|
gtag('config', 'G-9PTP6FW1M5');
|
||||||
ga('send', 'pageview');
|
|
||||||
</script>
|
</script>
|
||||||
<script async src='https://www.google-analytics.com/analytics.js'></script>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
|
|||||||
@ -349,7 +349,8 @@ void AbslStringify(Sink& sink, EnumWithStringify e) {
|
|||||||
{: .callout .note}
|
{: .callout .note}
|
||||||
Note: `AbslStringify()` utilizes a generic "sink" buffer to construct its
|
Note: `AbslStringify()` utilizes a generic "sink" buffer to construct its
|
||||||
string. For more information about supported operations on `AbslStringify()`'s
|
string. For more information about supported operations on `AbslStringify()`'s
|
||||||
sink, see go/abslstringify.
|
sink, see
|
||||||
|
[the `AbslStringify()` documentation](https://abseil.io/docs/cpp/guides/abslstringify).
|
||||||
|
|
||||||
`AbslStringify()` can also use `absl::StrFormat`'s catch-all `%v` type specifier
|
`AbslStringify()` can also use `absl::StrFormat`'s catch-all `%v` type specifier
|
||||||
within its own format strings to perform type deduction. `Point` above could be
|
within its own format strings to perform type deduction. `Point` above could be
|
||||||
@ -403,7 +404,8 @@ 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
|
||||||
|
[the documentation](https://abseil.io/docs/cpp/guides/abslstringify).
|
||||||
|
|
||||||
## Regular Expression Syntax
|
## Regular Expression Syntax
|
||||||
|
|
||||||
@ -1448,17 +1450,19 @@ are two cases to consider:
|
|||||||
To test them, we use the following special techniques:
|
To test them, we use the following special techniques:
|
||||||
|
|
||||||
* Both static functions and definitions/declarations in an unnamed namespace
|
* Both static functions and definitions/declarations in an unnamed namespace
|
||||||
are only visible within the same translation unit. To test them, you can
|
are only visible within the same translation unit. To test them, move the
|
||||||
`#include` the entire `.cc` file being tested in your `*_test.cc` file.
|
private code into the `foo::internal` namespace, where `foo` is the
|
||||||
(#including `.cc` files is not a good way to reuse code - you should not do
|
namespace your project normally uses, and put the private declarations in a
|
||||||
this in production code!)
|
`*-internal.h` file. Your production `.cc` files and your tests are allowed
|
||||||
|
to include this internal header, but your clients are not. This way, you can
|
||||||
|
fully test your internal implementation without leaking it to your clients.
|
||||||
|
|
||||||
However, a better approach is to move the private code into the
|
{: .callout .note}
|
||||||
`foo::internal` namespace, where `foo` is the namespace your project
|
NOTE: It is also technically *possible* to `#include` the entire `.cc` file
|
||||||
normally uses, and put the private declarations in a `*-internal.h` file.
|
being tested in your `*_test.cc` file to test static functions and
|
||||||
Your production `.cc` files and your tests are allowed to include this
|
definitions/declarations in an unnamed namespace. However, this technique is
|
||||||
internal header, but your clients are not. This way, you can fully test your
|
**not recommended** by this documentation and it is only presented here for the
|
||||||
internal implementation without leaking it to your clients.
|
sake of completeness.
|
||||||
|
|
||||||
* Private class members are only accessible from within the class or by
|
* Private class members are only accessible from within the class or by
|
||||||
friends. To access a class' private members, you can declare your test
|
friends. To access a class' private members, you can declare your test
|
||||||
@ -1471,10 +1475,7 @@ To test them, we use the following special techniques:
|
|||||||
|
|
||||||
Another way to test private members is to refactor them into an
|
Another way to test private members is to refactor them into an
|
||||||
implementation class, which is then declared in a `*-internal.h` file. Your
|
implementation class, which is then declared in a `*-internal.h` file. Your
|
||||||
clients aren't allowed to include this header but your tests can. Such is
|
clients aren't allowed to include this header but your tests can.
|
||||||
called the
|
|
||||||
[Pimpl](https://www.gamedev.net/articles/programming/general-and-gameplay-programming/the-c-pimpl-r1794/)
|
|
||||||
(Private Implementation) idiom.
|
|
||||||
|
|
||||||
Or, you can declare an individual test as a friend of your class by adding
|
Or, you can declare an individual test as a friend of your class by adding
|
||||||
this line in the class body:
|
this line in the class body:
|
||||||
@ -1929,6 +1930,35 @@ the `--gtest_also_run_disabled_tests` flag or set the
|
|||||||
You can combine this with the `--gtest_filter` flag to further select which
|
You can combine this with the `--gtest_filter` flag to further select which
|
||||||
disabled tests to run.
|
disabled tests to run.
|
||||||
|
|
||||||
|
### Enforcing Having At Least One Test Case
|
||||||
|
|
||||||
|
A not uncommon programmer mistake is to write a test program that has no test
|
||||||
|
case linked in. This can happen, for example, when you put test case definitions
|
||||||
|
in a library and the library is not marked as "always link".
|
||||||
|
|
||||||
|
To catch such mistakes, run the test program with the
|
||||||
|
`--gtest_fail_if_no_test_linked` flag or set the `GTEST_FAIL_IF_NO_TEST_LINKED`
|
||||||
|
environment variable to a value other than `0`. Now the program will fail if no
|
||||||
|
test case is linked in.
|
||||||
|
|
||||||
|
Note that *any* test case linked in makes the program valid for the purpose of
|
||||||
|
this check. In particular, even a disabled test case suffices.
|
||||||
|
|
||||||
|
### Enforcing Running At Least One Test Case
|
||||||
|
|
||||||
|
In addition to enforcing that tests are defined in the binary with
|
||||||
|
`--gtest_fail_if_no_test_linked`, it is also possible to enforce that a test
|
||||||
|
case was actually executed to ensure that resources are not consumed by tests
|
||||||
|
that do nothing.
|
||||||
|
|
||||||
|
To catch such optimization opportunities, run the test program with the
|
||||||
|
`--gtest_fail_if_no_test_selected` flag or set the
|
||||||
|
`GTEST_FAIL_IF_NO_TEST_SELECTED` environment variable to a value other than `0`.
|
||||||
|
|
||||||
|
A test is considered selected if it begins to run, even if it is later skipped
|
||||||
|
via `GTEST_SKIP`. Thus, `DISABLED` tests do not count as selected and neither do
|
||||||
|
tests that are not matched by `--gtest_filter`.
|
||||||
|
|
||||||
### Repeating the Tests
|
### Repeating the Tests
|
||||||
|
|
||||||
Once in a while you'll run into a test whose result is hit-or-miss. Perhaps it
|
Once in a while you'll run into a test whose result is hit-or-miss. Perhaps it
|
||||||
|
|||||||
13
docs/faq.md
13
docs/faq.md
@ -511,19 +511,6 @@ However, there are cases where you have to define your own:
|
|||||||
list of the constructor. (Early versions of `gcc` doesn't force you to
|
list of the constructor. (Early versions of `gcc` doesn't force you to
|
||||||
initialize the const member. It's a bug that has been fixed in `gcc 4`.)
|
initialize the const member. It's a bug that has been fixed in `gcc 4`.)
|
||||||
|
|
||||||
## Why does ASSERT_DEATH complain about previous threads that were already joined?
|
|
||||||
|
|
||||||
With the Linux pthread library, there is no turning back once you cross the line
|
|
||||||
from a single thread to multiple threads. The first time you create a thread, a
|
|
||||||
manager thread is created in addition, so you get 3, not 2, threads. Later when
|
|
||||||
the thread you create joins the main thread, the thread count decrements by 1,
|
|
||||||
but the manager thread will never be killed, so you still have 2 threads, which
|
|
||||||
means you cannot safely run a death test.
|
|
||||||
|
|
||||||
The new NPTL thread library doesn't suffer from this problem, as it doesn't
|
|
||||||
create a manager thread. However, if you don't control which machine your test
|
|
||||||
runs on, you shouldn't depend on this.
|
|
||||||
|
|
||||||
## Why does GoogleTest require the entire test suite, instead of individual tests, to be named `*DeathTest` when it uses `ASSERT_DEATH`?
|
## Why does GoogleTest require the entire test suite, instead of individual tests, to be named `*DeathTest` when it uses `ASSERT_DEATH`?
|
||||||
|
|
||||||
GoogleTest does not interleave tests from different test suites. That is, it
|
GoogleTest does not interleave tests from different test suites. That is, it
|
||||||
|
|||||||
@ -130,7 +130,7 @@ TEST(BarTest, DoesThis) {
|
|||||||
## Setting Default Actions {#OnCall}
|
## Setting Default Actions {#OnCall}
|
||||||
|
|
||||||
gMock has a **built-in default action** for any function that returns `void`,
|
gMock has a **built-in default action** for any function that returns `void`,
|
||||||
`bool`, a numeric value, or a pointer. In C++11, it will additionally returns
|
`bool`, a numeric value, or a pointer. In C++11, it additionally returns
|
||||||
the default-constructed value, if one exists for the given type.
|
the default-constructed value, if one exists for the given type.
|
||||||
|
|
||||||
To customize the default action for functions with return type `T`, use
|
To customize the default action for functions with return type `T`, use
|
||||||
|
|||||||
@ -900,15 +900,16 @@ using ::testing::Not;
|
|||||||
|
|
||||||
Matchers are function objects, and parametrized matchers can be composed just
|
Matchers are function objects, and parametrized matchers can be composed just
|
||||||
like any other function. However because their types can be long and rarely
|
like any other function. However because their types can be long and rarely
|
||||||
provide meaningful information, it can be easier to express them with C++14
|
provide meaningful information, it can be easier to express them with template
|
||||||
generic lambdas to avoid specifying types. For example,
|
parameters and `auto`. For example,
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
using ::testing::Contains;
|
using ::testing::Contains;
|
||||||
using ::testing::Property;
|
using ::testing::Property;
|
||||||
|
|
||||||
inline constexpr auto HasFoo = [](const auto& f) {
|
template <typename SubMatcher>
|
||||||
return Property("foo", &MyClass::foo, Contains(f));
|
inline constexpr auto HasFoo(const SubMatcher& sub_matcher) {
|
||||||
|
return Property("foo", &MyClass::foo, Contains(sub_matcher));
|
||||||
};
|
};
|
||||||
...
|
...
|
||||||
EXPECT_THAT(x, HasFoo("blah"));
|
EXPECT_THAT(x, HasFoo("blah"));
|
||||||
@ -3567,10 +3568,15 @@ just based on the number of parameters).
|
|||||||
|
|
||||||
### Writing New Monomorphic Matchers
|
### Writing New Monomorphic Matchers
|
||||||
|
|
||||||
A matcher of argument type `T` implements the matcher interface for `T` and does
|
A matcher of type `testing::Matcher<T>` implements the matcher interface for `T`
|
||||||
two things: it tests whether a value of type `T` matches the matcher, and can
|
and does two things: it tests whether a value of type `T` matches the matcher,
|
||||||
describe what kind of values it matches. The latter ability is used for
|
and can describe what kind of values it matches. The latter ability is used for
|
||||||
generating readable error messages when expectations are violated.
|
generating readable error messages when expectations are violated. Some matchers
|
||||||
|
can even explain why it matches or doesn't match a certain value, which can be
|
||||||
|
helpful when the reason isn't obvious.
|
||||||
|
|
||||||
|
Because a matcher of type `testing::Matcher<T>` for a particular type `T` can
|
||||||
|
only be used to match a value of type `T`, we call it "monomorphic."
|
||||||
|
|
||||||
A matcher of `T` must declare a typedef like:
|
A matcher of `T` must declare a typedef like:
|
||||||
|
|
||||||
@ -3662,8 +3668,16 @@ instead of `std::ostream*`.
|
|||||||
|
|
||||||
### Writing New Polymorphic Matchers
|
### Writing New Polymorphic Matchers
|
||||||
|
|
||||||
Expanding what we learned above to *polymorphic* matchers is now just as simple
|
Unlike a monomorphic matcher, which can only be used to match a value of a
|
||||||
as adding templates in the right place.
|
particular type, a *polymorphic* matcher is one that can be used to match values
|
||||||
|
of multiple types. For example, `Eq(5)` is a polymorhpic matcher as it can be
|
||||||
|
used to match an `int`, a `double`, a `float`, and so on. You should think of a
|
||||||
|
polymorphic matcher as a *matcher factory* as opposed to a
|
||||||
|
`testing::Matcher<SomeType>` - itself is not an actual matcher, but can be
|
||||||
|
implicitly converted to a `testing::Matcher<SomeType>` depending on the context.
|
||||||
|
|
||||||
|
Expanding what we learned above to polymorphic matchers is now as simple as
|
||||||
|
adding templates in the right place.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
|
|
||||||
@ -3789,6 +3803,26 @@ virtual.
|
|||||||
Like in a monomorphic matcher, you may explain the match result by streaming
|
Like in a monomorphic matcher, you may explain the match result by streaming
|
||||||
additional information to the `listener` argument in `MatchAndExplain()`.
|
additional information to the `listener` argument in `MatchAndExplain()`.
|
||||||
|
|
||||||
|
### Implementing Composite Matchers {#CompositeMatchers}
|
||||||
|
|
||||||
|
Sometimes we want to define a matcher that takes other matchers as parameters.
|
||||||
|
For example, `DistanceFrom(target, m)` is a polymorphic matcher that takes a
|
||||||
|
matcher `m` as a parameter. It tests that the distance from `target` to the
|
||||||
|
value being matched satisfies sub-matcher `m`.
|
||||||
|
|
||||||
|
If you are implementing such a composite matcher, you'll need to generate the
|
||||||
|
description of the matcher based on the description(s) of its sub-matcher(s).
|
||||||
|
You can see the implementation of `DistanceFrom()` in
|
||||||
|
`googlemock/include/gmock/gmock-matchers.h` for an example. In particular, pay
|
||||||
|
attention to `DistanceFromMatcherImpl`. Notice that it stores the sub-matcher as
|
||||||
|
a `const Matcher<const Distance&> distance_matcher_` instead of a polymorphic
|
||||||
|
matcher - this allows it to call `distance_matcher_.DescribeTo(os)` to describe
|
||||||
|
the sub-matcher. If the sub-matcher is stored as a polymorphic matcher instead,
|
||||||
|
it would not be possible to get its description as in general polymorphic
|
||||||
|
matchers don't know how to describe themselves - they are matcher factories
|
||||||
|
instead of actual matchers; only after being converted to `Matcher<SomeType>`
|
||||||
|
can they be described.
|
||||||
|
|
||||||
### Writing New Cardinalities
|
### Writing New Cardinalities
|
||||||
|
|
||||||
A cardinality is used in `Times()` to tell gMock how many times you expect a
|
A cardinality is used in `Times()` to tell gMock how many times you expect a
|
||||||
|
|||||||
@ -9,7 +9,7 @@ we recommend this tutorial as a starting point.
|
|||||||
To complete this tutorial, you'll need:
|
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++17.
|
||||||
* [Bazel](https://bazel.build/) 7.0 or higher, the preferred build system used
|
* [Bazel](https://bazel.build/) 7.0 or higher, the preferred build system used
|
||||||
by the GoogleTest team.
|
by the GoogleTest team.
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ with the following content:
|
|||||||
|
|
||||||
# Choose the most recent version available at
|
# Choose the most recent version available at
|
||||||
# https://registry.bazel.build/modules/googletest
|
# https://registry.bazel.build/modules/googletest
|
||||||
bazel_dep(name = "googletest", version = "1.15.2")
|
bazel_dep(name = "googletest", version = "1.17.0")
|
||||||
```
|
```
|
||||||
|
|
||||||
Now you're ready to build C++ code that uses GoogleTest.
|
Now you're ready to build C++ code that uses GoogleTest.
|
||||||
@ -99,16 +99,16 @@ 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}
|
||||||
NOTE: In the example below, we assume Clang or GCC and set `--cxxopt=-std=c++14`
|
NOTE: In the example below, we assume Clang or GCC and set `--cxxopt=-std=c++17`
|
||||||
to ensure that GoogleTest is compiled as C++14 instead of the compiler's default
|
to ensure that GoogleTest is compiled as C++17 instead of the compiler's default
|
||||||
setting (which could be C++11). For MSVC, the equivalent would be
|
setting. For MSVC, the equivalent would be `--cxxopt=/std:c++17`. See
|
||||||
`--cxxopt=/std:c++14`. See [Supported Platforms](platforms.md) for more details
|
[Supported Platforms](platforms.md) for more details on supported language
|
||||||
on supported language versions.
|
versions.
|
||||||
|
|
||||||
Now you can build and run your test:
|
Now you can build and run your test:
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
<strong>$ bazel test --cxxopt=-std=c++14 --test_output=all //:hello_test</strong>
|
<strong>$ bazel test --cxxopt=-std=c++17 --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:
|
||||||
|
|||||||
@ -10,7 +10,7 @@ this tutorial as a starting point. If your project uses Bazel, see the
|
|||||||
To complete this tutorial, you'll need:
|
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++17.
|
||||||
* [CMake](https://cmake.org/) and a compatible build tool for building the
|
* [CMake](https://cmake.org/) and a compatible build tool for building the
|
||||||
project.
|
project.
|
||||||
* Compatible build tools include
|
* Compatible build tools include
|
||||||
@ -52,8 +52,8 @@ To do this, in your project directory (`my_project`), create a file named
|
|||||||
cmake_minimum_required(VERSION 3.14)
|
cmake_minimum_required(VERSION 3.14)
|
||||||
project(my_project)
|
project(my_project)
|
||||||
|
|
||||||
# GoogleTest requires at least C++14
|
# GoogleTest requires at least C++17
|
||||||
set(CMAKE_CXX_STANDARD 14)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|||||||
@ -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. |
|
||||||
@ -47,8 +48,8 @@ functor, or lambda.
|
|||||||
| `InvokeWithoutArgs(object_pointer, &class::method)` | Invoke the method on the object, which takes no arguments. |
|
| `InvokeWithoutArgs(object_pointer, &class::method)` | Invoke the method on the object, which takes no arguments. |
|
||||||
| `InvokeArgument<N>(arg1, arg2, ..., argk)` | Invoke the mock function's `N`-th (0-based) argument, which must be a function or a functor, with the `k` arguments. |
|
| `InvokeArgument<N>(arg1, arg2, ..., argk)` | Invoke the mock function's `N`-th (0-based) argument, which must be a function or a functor, with the `k` arguments. |
|
||||||
|
|
||||||
The return value of the invoked function is used as the return value of the
|
The return value of the invoked function (except `InvokeArgument`) is used as
|
||||||
action.
|
the return value of the action.
|
||||||
|
|
||||||
When defining a callable to be used with `Invoke*()`, you can declare any unused
|
When defining a callable to be used with `Invoke*()`, you can declare any unused
|
||||||
parameters as `Unused`:
|
parameters as `Unused`:
|
||||||
|
|||||||
@ -42,11 +42,14 @@ Matcher | Description
|
|||||||
| `Lt(value)` | `argument < value` |
|
| `Lt(value)` | `argument < value` |
|
||||||
| `Ne(value)` | `argument != value` |
|
| `Ne(value)` | `argument != value` |
|
||||||
| `IsFalse()` | `argument` evaluates to `false` in a Boolean context. |
|
| `IsFalse()` | `argument` evaluates to `false` in a Boolean context. |
|
||||||
|
| `DistanceFrom(target, m)` | The distance between `argument` and `target` (computed by `abs(argument - target)`) matches `m`. |
|
||||||
|
| `DistanceFrom(target, get_distance, m)` | The distance between `argument` and `target` (computed by `get_distance(argument, target)`) matches `m`. |
|
||||||
| `IsTrue()` | `argument` evaluates to `true` in a Boolean context. |
|
| `IsTrue()` | `argument` evaluates to `true` in a Boolean context. |
|
||||||
| `IsNull()` | `argument` is a `NULL` pointer (raw or smart). |
|
| `IsNull()` | `argument` is a `NULL` pointer (raw or smart). |
|
||||||
| `NotNull()` | `argument` is a non-null pointer (raw or smart). |
|
| `NotNull()` | `argument` is a non-null pointer (raw or smart). |
|
||||||
| `Optional(m)` | `argument` is `optional<>` that contains a value matching `m`. (For testing whether an `optional<>` is set, check for equality with `nullopt`. You may need to use `Eq(nullopt)` if the inner type doesn't have `==`.)|
|
| `Optional(m)` | `argument` is `optional<>` that contains a value matching `m`. (For testing whether an `optional<>` is set, check for equality with `nullopt`. You may need to use `Eq(nullopt)` if the inner type doesn't have `==`.)|
|
||||||
| `VariantWith<T>(m)` | `argument` is `variant<>` that holds the alternative of type T with a value matching `m`. |
|
| `VariantWith<T>(m)` | `argument` is `variant<>` that holds the alternative of type T with a value matching `m`. |
|
||||||
|
| `AnyWith<T>(m)` | `argument` is `any<>` that holds a value of type T with a value matching `m`. |
|
||||||
| `Ref(variable)` | `argument` is a reference to `variable`. |
|
| `Ref(variable)` | `argument` is a reference to `variable`. |
|
||||||
| `TypedEq<type>(value)` | `argument` has type `type` and is equal to `value`. You may need to use this instead of `Eq(value)` when the mock function is overloaded. |
|
| `TypedEq<type>(value)` | `argument` has type `type` and is equal to `value`. You may need to use this instead of `Eq(value)` when the mock function is overloaded. |
|
||||||
|
|
||||||
@ -109,6 +112,33 @@ use the regular expression syntax defined
|
|||||||
[here](../advanced.md#regular-expression-syntax). All of these matchers, except
|
[here](../advanced.md#regular-expression-syntax). All of these matchers, except
|
||||||
`ContainsRegex()` and `MatchesRegex()` work for wide strings as well.
|
`ContainsRegex()` and `MatchesRegex()` work for wide strings as well.
|
||||||
|
|
||||||
|
## Exception Matchers
|
||||||
|
|
||||||
|
| Matcher | Description |
|
||||||
|
| :---------------------------------------- | :------------------------------- |
|
||||||
|
| `Throws<E>()` | The `argument` is a callable object that, when called, throws an exception of the expected type `E`. |
|
||||||
|
| `Throws<E>(m)` | The `argument` is a callable object that, when called, throws an exception of type `E` that satisfies the matcher `m`. |
|
||||||
|
| `ThrowsMessage<E>(m)` | The `argument` is a callable object that, when called, throws an exception of type `E` with a message that satisfies the matcher `m`. |
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto argument = [] { throw std::runtime_error("error msg"); };
|
||||||
|
|
||||||
|
// Checks if the lambda throws a `std::runtime_error`.
|
||||||
|
EXPECT_THAT(argument, Throws<std::runtime_error>());
|
||||||
|
|
||||||
|
// Checks if the lambda throws a `std::runtime_error` with a specific message
|
||||||
|
// that matches "error msg".
|
||||||
|
EXPECT_THAT(argument,
|
||||||
|
Throws<std::runtime_error>(Property(&std::runtime_error::what,
|
||||||
|
Eq("error msg"))));
|
||||||
|
|
||||||
|
// Checks if the lambda throws a `std::runtime_error` with a message that
|
||||||
|
// contains "msg".
|
||||||
|
EXPECT_THAT(argument, ThrowsMessage<std::runtime_error>(HasSubstr("msg")));
|
||||||
|
```
|
||||||
|
|
||||||
## Container Matchers
|
## Container Matchers
|
||||||
|
|
||||||
Most STL-style containers support `==`, so you can use `Eq(expected_container)`
|
Most STL-style containers support `==`, so you can use `Eq(expected_container)`
|
||||||
@ -171,6 +201,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 +224,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 |
|
||||||
|
|||||||
@ -110,7 +110,7 @@ namespace:
|
|||||||
| `ValuesIn(container)` or `ValuesIn(begin,end)` | Yields values from a C-style array, an STL-style container, or an iterator range `[begin, end)`. |
|
| `ValuesIn(container)` or `ValuesIn(begin,end)` | Yields values from a C-style array, an STL-style container, or an iterator range `[begin, end)`. |
|
||||||
| `Bool()` | Yields sequence `{false, true}`. |
|
| `Bool()` | Yields sequence `{false, true}`. |
|
||||||
| `Combine(g1, g2, ..., gN)` | Yields as `std::tuple` *n*-tuples all combinations (Cartesian product) of the values generated by the given *n* generators `g1`, `g2`, ..., `gN`. |
|
| `Combine(g1, g2, ..., gN)` | Yields as `std::tuple` *n*-tuples all combinations (Cartesian product) of the values generated by the given *n* generators `g1`, `g2`, ..., `gN`. |
|
||||||
| `ConvertGenerator<T>(g)` | Yields values generated by generator `g`, `static_cast` to `T`. |
|
| `ConvertGenerator<T>(g)` or `ConvertGenerator(g, func)` | Yields values generated by generator `g`, `static_cast` from `T`. (Note: `T` might not be what you expect. See [*Using ConvertGenerator*](#using-convertgenerator) below.) The second overload uses `func` to perform the conversion. |
|
||||||
|
|
||||||
The optional last argument *`name_generator`* is a function or functor that
|
The optional last argument *`name_generator`* is a function or functor that
|
||||||
generates custom test name suffixes based on the test parameters. The function
|
generates custom test name suffixes based on the test parameters. The function
|
||||||
@ -137,6 +137,103 @@ For more information, see
|
|||||||
See also
|
See also
|
||||||
[`GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST`](#GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST).
|
[`GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST`](#GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST).
|
||||||
|
|
||||||
|
###### Using `ConvertGenerator`
|
||||||
|
|
||||||
|
The functions listed in the table above appear to return generators that create
|
||||||
|
values of the desired types, but this is not generally the case. Rather, they
|
||||||
|
typically return factory objects that convert to the the desired generators.
|
||||||
|
This affords some flexibility in allowing you to specify values of types that
|
||||||
|
are different from, yet implicitly convertible to, the actual parameter type
|
||||||
|
required by your fixture class.
|
||||||
|
|
||||||
|
For example, you can do the following with a fixture that requires an `int`
|
||||||
|
parameter:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
INSTANTIATE_TEST_SUITE_P(MyInstantiation, MyTestSuite,
|
||||||
|
testing::Values(1, 1.2)); // Yes, Values() supports heterogeneous argument types.
|
||||||
|
```
|
||||||
|
|
||||||
|
It might seem obvious that `1.2` — a `double` — will be converted to
|
||||||
|
an `int` but in actuality it requires some template gymnastics involving the
|
||||||
|
indirection described in the previous paragraph.
|
||||||
|
|
||||||
|
What if your parameter type is not implicitly convertible from the generated
|
||||||
|
type but is *explicitly* convertible? There will be no automatic conversion, but
|
||||||
|
you can force it by applying `ConvertGenerator<T>`. The compiler can
|
||||||
|
automatically deduce the target type (your fixture's parameter type), but
|
||||||
|
because of the aforementioned indirection it cannot decide what the generated
|
||||||
|
type should be. You need to tell it, by providing the type `T` explicitly. Thus
|
||||||
|
`T` should not be your fixture's parameter type, but rather an intermediate type
|
||||||
|
that is supported by the factory object, and which can be `static_cast` to the
|
||||||
|
fixture's parameter type:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// The fixture's parameter type.
|
||||||
|
class MyParam {
|
||||||
|
public:
|
||||||
|
// Explicit converting ctor.
|
||||||
|
explicit MyParam(const std::tuple<int, bool>& t);
|
||||||
|
...
|
||||||
|
};
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(MyInstantiation, MyTestSuite,
|
||||||
|
ConvertGenerator<std::tuple<int, bool>>(Combine(Values(0.1, 1.2), Bool())));
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example `Combine` supports the generation of `std::tuple<int, bool>>`
|
||||||
|
objects (even though the provided values for the first tuple element are
|
||||||
|
`double`s) and those `tuple`s get converted into `MyParam` objects by virtue of
|
||||||
|
the call to `ConvertGenerator`.
|
||||||
|
|
||||||
|
For parameter types that are not convertible from the generated types you can
|
||||||
|
provide a callable that does the conversion. The callable accepts an object of
|
||||||
|
the generated type and returns an object of the fixture's parameter type. The
|
||||||
|
generated type can often be deduced by the compiler from the callable's call
|
||||||
|
signature so you do not usually need specify it explicitly (but see a caveat
|
||||||
|
below).
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// The fixture's parameter type.
|
||||||
|
class MyParam {
|
||||||
|
public:
|
||||||
|
MyParam(int, bool);
|
||||||
|
...
|
||||||
|
};
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(MyInstantiation, MyTestSuite,
|
||||||
|
ConvertGenerator(Combine(Values(1, 1.2), Bool()),
|
||||||
|
[](const std::tuple<int, bool>& t){
|
||||||
|
const auto [i, b] = t;
|
||||||
|
return MyParam(i, b);
|
||||||
|
}));
|
||||||
|
```
|
||||||
|
|
||||||
|
The callable may be anything that can be used to initialize a `std::function`
|
||||||
|
with the appropriate call signature. Note the callable's return object gets
|
||||||
|
`static_cast` to the fixture's parameter type, so it does not have to be of that
|
||||||
|
exact type, only convertible to it.
|
||||||
|
|
||||||
|
**Caveat:** Consider the following example.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
INSTANTIATE_TEST_SUITE_P(MyInstantiation, MyTestSuite,
|
||||||
|
ConvertGenerator(Values(std::string("s")), [](std::string_view s) { ... }));
|
||||||
|
```
|
||||||
|
|
||||||
|
The `string` argument gets copied into the factory object returned by `Values`.
|
||||||
|
Then, because the generated type deduced from the lambda is `string_view`, the
|
||||||
|
factory object spawns a generator that holds a `string_view` referencing that
|
||||||
|
`string`. Unfortunately, by the time this generator gets invoked, the factory
|
||||||
|
object is gone and the `string_view` is dangling.
|
||||||
|
|
||||||
|
To overcome this problem you can specify the generated type explicitly:
|
||||||
|
`ConvertGenerator<std::string>(Values(std::string("s")), [](std::string_view s)
|
||||||
|
{ ... })`. Alternatively, you can change the lambda's signature to take a
|
||||||
|
`std::string` or a `const std::string&` (the latter will not leave you with a
|
||||||
|
dangling reference because the type deduction strips off the reference and the
|
||||||
|
`const`).
|
||||||
|
|
||||||
### TYPED_TEST_SUITE {#TYPED_TEST_SUITE}
|
### TYPED_TEST_SUITE {#TYPED_TEST_SUITE}
|
||||||
|
|
||||||
`TYPED_TEST_SUITE(`*`TestFixtureName`*`,`*`Types`*`)`
|
`TYPED_TEST_SUITE(`*`TestFixtureName`*`,`*`Types`*`)`
|
||||||
|
|||||||
@ -835,6 +835,10 @@ class Action<R(Args...)> {
|
|||||||
Result operator()(const InArgs&...) const {
|
Result operator()(const InArgs&...) const {
|
||||||
return function_impl();
|
return function_impl();
|
||||||
}
|
}
|
||||||
|
template <typename... InArgs>
|
||||||
|
Result operator()(const InArgs&...) {
|
||||||
|
return function_impl();
|
||||||
|
}
|
||||||
|
|
||||||
FunctionImpl function_impl;
|
FunctionImpl function_impl;
|
||||||
};
|
};
|
||||||
@ -1451,6 +1455,30 @@ struct WithArgsAction {
|
|||||||
return OA{std::move(inner_action)};
|
return OA{std::move(inner_action)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// As above, but in the case where we want to create a OnceAction from a const
|
||||||
|
// WithArgsAction. This is fine as long as the inner action doesn't need to
|
||||||
|
// move any of its state to create a OnceAction.
|
||||||
|
template <
|
||||||
|
typename R, typename... Args,
|
||||||
|
typename std::enable_if<
|
||||||
|
std::is_convertible<const InnerAction&,
|
||||||
|
OnceAction<R(internal::TupleElement<
|
||||||
|
I, std::tuple<Args...>>...)>>::value,
|
||||||
|
int>::type = 0>
|
||||||
|
operator OnceAction<R(Args...)>() const& { // NOLINT
|
||||||
|
struct OA {
|
||||||
|
OnceAction<InnerSignature<R, Args...>> inner_action;
|
||||||
|
|
||||||
|
R operator()(Args&&... args) && {
|
||||||
|
return std::move(inner_action)
|
||||||
|
.Call(std::get<I>(
|
||||||
|
std::forward_as_tuple(std::forward<Args>(args)...))...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return OA{inner_action};
|
||||||
|
}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
typename R, typename... Args,
|
typename R, typename... Args,
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
@ -1703,8 +1731,7 @@ 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
|
auto operator()(Args&&... args) const -> decltype(std::get<k>(
|
||||||
-> decltype(std::get<k>(
|
|
||||||
std::forward_as_tuple(std::forward<Args>(args)...))) {
|
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)...));
|
||||||
}
|
}
|
||||||
@ -1720,6 +1747,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;
|
||||||
@ -1759,11 +1796,24 @@ struct SetArrayArgumentAction {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <size_t k>
|
template <size_t k>
|
||||||
struct DeleteArgAction {
|
class DeleteArgAction {
|
||||||
|
public:
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
void operator()(const Args&... args) const {
|
void operator()(const Args&... args) const {
|
||||||
delete std::get<k>(std::tie(args...));
|
DoDelete(std::get<k>(std::tie(args...)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename T>
|
||||||
|
static void DoDelete(T* ptr) {
|
||||||
|
delete ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
[[deprecated(
|
||||||
|
"DeleteArg<N> used for a non-pointer argument, it was likely migrated "
|
||||||
|
"to a smart pointer type. This action should be removed.")]]
|
||||||
|
static void DoDelete(T&) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Ptr>
|
template <typename Ptr>
|
||||||
@ -1829,6 +1879,13 @@ struct RethrowAction {
|
|||||||
// EXPECT_CALL(mock, Bar(5, _, _)).WillOnce(Invoke(DistanceToOrigin));
|
// EXPECT_CALL(mock, Bar(5, _, _)).WillOnce(Invoke(DistanceToOrigin));
|
||||||
typedef internal::IgnoredValue Unused;
|
typedef internal::IgnoredValue Unused;
|
||||||
|
|
||||||
|
// Deprecated single-argument DoAll.
|
||||||
|
template <typename Action>
|
||||||
|
GTEST_INTERNAL_DEPRECATE_AND_INLINE("Avoid using DoAll() for single actions")
|
||||||
|
typename std::decay<Action>::type DoAll(Action&& action) {
|
||||||
|
return std::forward<Action>(action);
|
||||||
|
}
|
||||||
|
|
||||||
// Creates an action that does actions a1, a2, ..., sequentially in
|
// Creates an action that does actions a1, a2, ..., sequentially in
|
||||||
// each invocation. All but the last action will have a readonly view of the
|
// each invocation. All but the last action will have a readonly view of the
|
||||||
// arguments.
|
// arguments.
|
||||||
@ -1994,10 +2051,11 @@ PolymorphicAction<internal::SetErrnoAndReturnAction<T>> SetErrnoAndReturn(
|
|||||||
// Various overloads for Invoke().
|
// Various overloads for Invoke().
|
||||||
|
|
||||||
// Legacy function.
|
// Legacy function.
|
||||||
// Actions can now be implicitly constructed from callables. No need to create
|
|
||||||
// wrapper objects.
|
|
||||||
// This function exists for backwards compatibility.
|
// This function exists for backwards compatibility.
|
||||||
template <typename FunctionImpl>
|
template <typename FunctionImpl>
|
||||||
|
GTEST_INTERNAL_DEPRECATE_AND_INLINE(
|
||||||
|
"Actions can now be implicitly constructed from callables. No need to "
|
||||||
|
"create wrapper objects using Invoke().")
|
||||||
typename std::decay<FunctionImpl>::type Invoke(FunctionImpl&& function_impl) {
|
typename std::decay<FunctionImpl>::type Invoke(FunctionImpl&& function_impl) {
|
||||||
return std::forward<FunctionImpl>(function_impl);
|
return std::forward<FunctionImpl>(function_impl);
|
||||||
}
|
}
|
||||||
@ -2070,6 +2128,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>
|
||||||
@ -2213,9 +2278,9 @@ template <typename F, typename Impl>
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define GMOCK_INTERNAL_ARG_UNUSED(i, data, el) \
|
#define GMOCK_INTERNAL_ARG_UNUSED(i, data, el) \
|
||||||
, GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED const arg##i##_type& arg##i
|
, [[maybe_unused]] const arg##i##_type& arg##i
|
||||||
#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_ \
|
#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_ \
|
||||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED const args_type& args GMOCK_PP_REPEAT( \
|
[[maybe_unused]] const args_type& args GMOCK_PP_REPEAT( \
|
||||||
GMOCK_INTERNAL_ARG_UNUSED, , 10)
|
GMOCK_INTERNAL_ARG_UNUSED, , 10)
|
||||||
|
|
||||||
#define GMOCK_INTERNAL_ARG(i, data, el) , const arg##i##_type& arg##i
|
#define GMOCK_INTERNAL_ARG(i, data, el) , const arg##i##_type& arg##i
|
||||||
@ -2280,8 +2345,8 @@ template <typename F, typename Impl>
|
|||||||
std::shared_ptr<const gmock_Impl> impl_; \
|
std::shared_ptr<const gmock_Impl> impl_; \
|
||||||
}; \
|
}; \
|
||||||
template <GMOCK_ACTION_TYPENAME_PARAMS_(params)> \
|
template <GMOCK_ACTION_TYPENAME_PARAMS_(params)> \
|
||||||
inline full_name<GMOCK_ACTION_TYPE_PARAMS_(params)> name( \
|
[[nodiscard]] inline full_name<GMOCK_ACTION_TYPE_PARAMS_(params)> name( \
|
||||||
GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) GTEST_MUST_USE_RESULT_; \
|
GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)); \
|
||||||
template <GMOCK_ACTION_TYPENAME_PARAMS_(params)> \
|
template <GMOCK_ACTION_TYPENAME_PARAMS_(params)> \
|
||||||
inline full_name<GMOCK_ACTION_TYPE_PARAMS_(params)> name( \
|
inline full_name<GMOCK_ACTION_TYPE_PARAMS_(params)> name( \
|
||||||
GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) { \
|
GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) { \
|
||||||
@ -2316,7 +2381,7 @@ template <typename F, typename Impl>
|
|||||||
return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \
|
return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \
|
||||||
}; \
|
}; \
|
||||||
}; \
|
}; \
|
||||||
inline name##Action name() GTEST_MUST_USE_RESULT_; \
|
[[nodiscard]] inline name##Action name(); \
|
||||||
inline name##Action name() { return name##Action(); } \
|
inline name##Action name() { return name##Action(); } \
|
||||||
template <typename function_type, typename return_type, typename args_type, \
|
template <typename function_type, typename return_type, typename args_type, \
|
||||||
GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \
|
GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \
|
||||||
|
|||||||
@ -257,7 +257,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <exception>
|
#include <cstddef>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
#include <ios>
|
#include <ios>
|
||||||
@ -267,12 +267,12 @@
|
|||||||
#include <ostream> // NOLINT
|
#include <ostream> // NOLINT
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "gmock/internal/gmock-internal-utils.h"
|
#include "gmock/internal/gmock-internal-utils.h"
|
||||||
#include "gmock/internal/gmock-port.h"
|
|
||||||
#include "gmock/internal/gmock-pp.h"
|
#include "gmock/internal/gmock-pp.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
@ -375,11 +375,16 @@ class MatcherCastImpl {
|
|||||||
|
|
||||||
// M can't be implicitly converted to Matcher<T>, so M isn't a polymorphic
|
// M can't be implicitly converted to Matcher<T>, so M isn't a polymorphic
|
||||||
// matcher. It's a value of a type implicitly convertible to T. Use direct
|
// matcher. It's a value of a type implicitly convertible to T. Use direct
|
||||||
// initialization to create a matcher.
|
// initialization or `ImplicitCastEqMatcher` to create a matcher.
|
||||||
static Matcher<T> CastImpl(const M& value,
|
static Matcher<T> CastImpl(const M& value,
|
||||||
std::false_type /* convertible_to_matcher */,
|
std::false_type /* convertible_to_matcher */,
|
||||||
std::true_type /* convertible_to_T */) {
|
std::true_type /* convertible_to_T */) {
|
||||||
return Matcher<T>(ImplicitCast_<T>(value));
|
using NoRefT = std::remove_cv_t<std::remove_reference_t<T>>;
|
||||||
|
if constexpr (std::is_same_v<M, NoRefT>) {
|
||||||
|
return Matcher<T>(value);
|
||||||
|
} else {
|
||||||
|
return ImplicitCastEqMatcher<NoRefT, std::decay_t<const M&>>(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// M can't be implicitly converted to either Matcher<T> or T. Attempt to use
|
// M can't be implicitly converted to either Matcher<T> or T. Attempt to use
|
||||||
@ -390,11 +395,11 @@ class MatcherCastImpl {
|
|||||||
// latter calls bool operator==(const Lhs& lhs, const Rhs& rhs) in the end
|
// latter calls bool operator==(const Lhs& lhs, const Rhs& rhs) in the end
|
||||||
// which might be undefined even when Rhs is implicitly convertible to Lhs
|
// which might be undefined even when Rhs is implicitly convertible to Lhs
|
||||||
// (e.g. std::pair<const int, int> vs. std::pair<int, int>).
|
// (e.g. std::pair<const int, int> vs. std::pair<int, int>).
|
||||||
//
|
|
||||||
// We don't define this method inline as we need the declaration of Eq().
|
|
||||||
static Matcher<T> CastImpl(const M& value,
|
static Matcher<T> CastImpl(const M& value,
|
||||||
std::false_type /* convertible_to_matcher */,
|
std::false_type /* convertible_to_matcher */,
|
||||||
std::false_type /* convertible_to_T */);
|
std::false_type /* convertible_to_T */) {
|
||||||
|
return Eq(value);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// This more specialized version is used when MatcherCast()'s argument
|
// This more specialized version is used when MatcherCast()'s argument
|
||||||
@ -1311,21 +1316,36 @@ 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 (!listener->IsInterested()) {
|
||||||
|
// Fast path to avoid unnecessary formatting.
|
||||||
|
for (const Matcher<T>& matcher : matchers_) {
|
||||||
|
if (!matcher.Matches(x)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// This method uses matcher's explanation when explaining the result.
|
// This method uses matcher's explanation when explaining the result.
|
||||||
// However, if matcher doesn't provide one, this method uses matcher's
|
// However, if matcher doesn't provide one, this method uses matcher's
|
||||||
// description.
|
// description.
|
||||||
std::string all_match_result;
|
std::string all_match_result;
|
||||||
|
bool success = true;
|
||||||
for (const Matcher<T>& matcher : matchers_) {
|
for (const Matcher<T>& matcher : matchers_) {
|
||||||
StringMatchResultListener slistener;
|
StringMatchResultListener slistener;
|
||||||
// Return explanation for first failed matcher.
|
// Return explanation for first failed matcher.
|
||||||
if (!matcher.MatchAndExplain(x, &slistener)) {
|
if (!matcher.MatchAndExplain(x, &slistener)) {
|
||||||
const std::string explanation = slistener.str();
|
const std::string explanation = slistener.str();
|
||||||
|
if (!success) {
|
||||||
|
// Already had a failure.
|
||||||
|
*listener << ", and ";
|
||||||
|
}
|
||||||
if (!explanation.empty()) {
|
if (!explanation.empty()) {
|
||||||
*listener << explanation;
|
*listener << explanation;
|
||||||
} else {
|
} else {
|
||||||
*listener << "which doesn't match (" << Describe(matcher) << ")";
|
*listener << "which doesn't match (" << Describe(matcher) << ")";
|
||||||
}
|
}
|
||||||
return false;
|
success = false;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
// Keep track of explanations in case all matchers succeed.
|
// Keep track of explanations in case all matchers succeed.
|
||||||
std::string explanation = slistener.str();
|
std::string explanation = slistener.str();
|
||||||
@ -1342,8 +1362,10 @@ class AllOfMatcherImpl : public MatcherInterface<const T&> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (success) {
|
||||||
*listener << all_match_result;
|
*listener << all_match_result;
|
||||||
return true;
|
}
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -1430,6 +1452,15 @@ class AnyOfMatcherImpl : public MatcherInterface<const T&> {
|
|||||||
|
|
||||||
bool MatchAndExplain(const T& x,
|
bool MatchAndExplain(const T& x,
|
||||||
MatchResultListener* listener) const override {
|
MatchResultListener* listener) const override {
|
||||||
|
if (!listener->IsInterested()) {
|
||||||
|
// Fast path to avoid unnecessary formatting of match explanations.
|
||||||
|
for (const Matcher<T>& matcher : matchers_) {
|
||||||
|
if (matcher.Matches(x)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// This method uses matcher's explanation when explaining the result.
|
// This method uses matcher's explanation when explaining the result.
|
||||||
// However, if matcher doesn't provide one, this method uses matcher's
|
// However, if matcher doesn't provide one, this method uses matcher's
|
||||||
// description.
|
// description.
|
||||||
@ -2097,11 +2128,11 @@ class WhenDynamicCastToMatcher<To&> : public WhenDynamicCastToMatcherBase<To&> {
|
|||||||
template <typename Class, typename FieldType>
|
template <typename Class, typename FieldType>
|
||||||
class FieldMatcher {
|
class FieldMatcher {
|
||||||
public:
|
public:
|
||||||
FieldMatcher(FieldType Class::*field,
|
FieldMatcher(FieldType Class::* field,
|
||||||
const Matcher<const FieldType&>& matcher)
|
const Matcher<const FieldType&>& matcher)
|
||||||
: field_(field), matcher_(matcher), whose_field_("whose given field ") {}
|
: field_(field), matcher_(matcher), whose_field_("whose given field ") {}
|
||||||
|
|
||||||
FieldMatcher(const std::string& field_name, FieldType Class::*field,
|
FieldMatcher(const std::string& field_name, FieldType Class::* field,
|
||||||
const Matcher<const FieldType&>& matcher)
|
const Matcher<const FieldType&>& matcher)
|
||||||
: field_(field),
|
: field_(field),
|
||||||
matcher_(matcher),
|
matcher_(matcher),
|
||||||
@ -2145,7 +2176,7 @@ class FieldMatcher {
|
|||||||
return MatchAndExplainImpl(std::false_type(), *p, listener);
|
return MatchAndExplainImpl(std::false_type(), *p, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
const FieldType Class::*field_;
|
const FieldType Class::* field_;
|
||||||
const Matcher<const FieldType&> matcher_;
|
const Matcher<const FieldType&> matcher_;
|
||||||
|
|
||||||
// Contains either "whose given field " if the name of the field is unknown
|
// Contains either "whose given field " if the name of the field is unknown
|
||||||
@ -2855,6 +2886,54 @@ class ContainsMatcherImpl : public QuantifierMatcherImpl<Container> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Implements DistanceFrom(target, get_distance, distance_matcher) for the given
|
||||||
|
// argument types:
|
||||||
|
// * V is the type of the value to be matched.
|
||||||
|
// * T is the type of the target value.
|
||||||
|
// * Distance is the type of the distance between V and T.
|
||||||
|
// * GetDistance is the type of the functor for computing the distance between
|
||||||
|
// V and T.
|
||||||
|
template <typename V, typename T, typename Distance, typename GetDistance>
|
||||||
|
class DistanceFromMatcherImpl : public MatcherInterface<V> {
|
||||||
|
public:
|
||||||
|
// Arguments:
|
||||||
|
// * target: the target value.
|
||||||
|
// * get_distance: the functor for computing the distance between the value
|
||||||
|
// being matched and target.
|
||||||
|
// * distance_matcher: the matcher for checking the distance.
|
||||||
|
DistanceFromMatcherImpl(T target, GetDistance get_distance,
|
||||||
|
Matcher<const Distance&> distance_matcher)
|
||||||
|
: target_(std::move(target)),
|
||||||
|
get_distance_(std::move(get_distance)),
|
||||||
|
distance_matcher_(std::move(distance_matcher)) {}
|
||||||
|
|
||||||
|
// Describes what this matcher does.
|
||||||
|
void DescribeTo(::std::ostream* os) const override {
|
||||||
|
distance_matcher_.DescribeTo(os);
|
||||||
|
*os << " away from " << PrintToString(target_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescribeNegationTo(::std::ostream* os) const override {
|
||||||
|
distance_matcher_.DescribeNegationTo(os);
|
||||||
|
*os << " away from " << PrintToString(target_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MatchAndExplain(V value, MatchResultListener* listener) const override {
|
||||||
|
const auto distance = get_distance_(value, target_);
|
||||||
|
const bool match = distance_matcher_.Matches(distance);
|
||||||
|
if (!match && listener->IsInterested()) {
|
||||||
|
*listener << "which is " << PrintToString(distance) << " away from "
|
||||||
|
<< PrintToString(target_);
|
||||||
|
}
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const T target_;
|
||||||
|
const GetDistance get_distance_;
|
||||||
|
const Matcher<const Distance&> distance_matcher_;
|
||||||
|
};
|
||||||
|
|
||||||
// Implements Each(element_matcher) for the given argument type Container.
|
// Implements Each(element_matcher) for the given argument type Container.
|
||||||
// Symmetric to ContainsMatcherImpl.
|
// Symmetric to ContainsMatcherImpl.
|
||||||
template <typename Container>
|
template <typename Container>
|
||||||
@ -2990,6 +3069,52 @@ auto Second(T& x, Rank1) -> decltype((x.second)) { // NOLINT
|
|||||||
}
|
}
|
||||||
} // namespace pair_getters
|
} // namespace pair_getters
|
||||||
|
|
||||||
|
// Default functor for computing the distance between two values.
|
||||||
|
struct DefaultGetDistance {
|
||||||
|
template <typename T, typename U>
|
||||||
|
auto operator()(const T& lhs, const U& rhs) const {
|
||||||
|
using std::abs;
|
||||||
|
// Allow finding abs() in the type's namespace via ADL.
|
||||||
|
return abs(lhs - rhs);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Implements polymorphic DistanceFrom(target, get_distance, distance_matcher)
|
||||||
|
// matcher. Template arguments:
|
||||||
|
// * T is the type of the target value.
|
||||||
|
// * GetDistance is the type of the functor for computing the distance between
|
||||||
|
// the value being matched and the target.
|
||||||
|
// * DistanceMatcher is the type of the matcher for checking the distance.
|
||||||
|
template <typename T, typename GetDistance, typename DistanceMatcher>
|
||||||
|
class DistanceFromMatcher {
|
||||||
|
public:
|
||||||
|
// Arguments:
|
||||||
|
// * target: the target value.
|
||||||
|
// * get_distance: the functor for computing the distance between the value
|
||||||
|
// being matched and target.
|
||||||
|
// * distance_matcher: the matcher for checking the distance.
|
||||||
|
DistanceFromMatcher(T target, GetDistance get_distance,
|
||||||
|
DistanceMatcher distance_matcher)
|
||||||
|
: target_(std::move(target)),
|
||||||
|
get_distance_(std::move(get_distance)),
|
||||||
|
distance_matcher_(std::move(distance_matcher)) {}
|
||||||
|
|
||||||
|
DistanceFromMatcher(const DistanceFromMatcher& other) = default;
|
||||||
|
|
||||||
|
// Implicitly converts to a monomorphic matcher of the given type.
|
||||||
|
template <typename V>
|
||||||
|
operator Matcher<V>() const { // NOLINT
|
||||||
|
using Distance = decltype(get_distance_(std::declval<V>(), target_));
|
||||||
|
return Matcher<V>(new DistanceFromMatcherImpl<V, T, Distance, GetDistance>(
|
||||||
|
target_, get_distance_, distance_matcher_));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const T target_;
|
||||||
|
const GetDistance get_distance_;
|
||||||
|
const DistanceMatcher distance_matcher_;
|
||||||
|
};
|
||||||
|
|
||||||
// Implements Key(inner_matcher) for the given argument pair type.
|
// Implements Key(inner_matcher) for the given argument pair type.
|
||||||
// Key(inner_matcher) matches an std::pair whose 'first' field matches
|
// Key(inner_matcher) matches an std::pair whose 'first' field matches
|
||||||
// inner_matcher. For example, Contains(Key(Ge(5))) can be used to match an
|
// inner_matcher. For example, Contains(Key(Ge(5))) can be used to match an
|
||||||
@ -3197,8 +3322,8 @@ class PairMatcher {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, size_t... I>
|
template <typename T, size_t... I>
|
||||||
auto UnpackStructImpl(const T& t, std::index_sequence<I...>,
|
auto UnpackStructImpl(const T& t, std::index_sequence<I...>, int)
|
||||||
int) -> decltype(std::tie(get<I>(t)...)) {
|
-> decltype(std::tie(get<I>(t)...)) {
|
||||||
static_assert(std::tuple_size<T>::value == sizeof...(I),
|
static_assert(std::tuple_size<T>::value == sizeof...(I),
|
||||||
"Number of arguments doesn't match the number of fields.");
|
"Number of arguments doesn't match the number of fields.");
|
||||||
return std::tie(get<I>(t)...);
|
return std::tie(get<I>(t)...);
|
||||||
@ -3305,6 +3430,50 @@ 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;
|
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);
|
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t);
|
||||||
}
|
}
|
||||||
|
template <typename T>
|
||||||
|
auto UnpackStructImpl(const T& in, std::make_index_sequence<21>, char) {
|
||||||
|
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u] =
|
||||||
|
in;
|
||||||
|
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t,
|
||||||
|
u);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto UnpackStructImpl(const T& in, std::make_index_sequence<22>, char) {
|
||||||
|
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u,
|
||||||
|
v] = in;
|
||||||
|
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u,
|
||||||
|
v);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto UnpackStructImpl(const T& in, std::make_index_sequence<23>, char) {
|
||||||
|
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v,
|
||||||
|
w] = in;
|
||||||
|
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u,
|
||||||
|
v, w);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
auto UnpackStructImpl(const T& in, std::make_index_sequence<24>, char) {
|
||||||
|
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v,
|
||||||
|
w, x] = in;
|
||||||
|
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u,
|
||||||
|
v, w, x);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
auto UnpackStructImpl(const T& in, std::make_index_sequence<25>, char) {
|
||||||
|
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v,
|
||||||
|
w, x, y] = in;
|
||||||
|
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u,
|
||||||
|
v, w, x, y);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
auto UnpackStructImpl(const T& in, std::make_index_sequence<26>, char) {
|
||||||
|
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v,
|
||||||
|
w, x, y, z] = in;
|
||||||
|
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u,
|
||||||
|
v, w, x, y, z);
|
||||||
|
}
|
||||||
#endif // defined(__cpp_structured_bindings)
|
#endif // defined(__cpp_structured_bindings)
|
||||||
|
|
||||||
template <size_t I, typename T>
|
template <size_t I, typename T>
|
||||||
@ -3480,7 +3649,7 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
|
|||||||
StlContainerReference stl_container = View::ConstReference(container);
|
StlContainerReference stl_container = View::ConstReference(container);
|
||||||
auto it = stl_container.begin();
|
auto it = stl_container.begin();
|
||||||
size_t exam_pos = 0;
|
size_t exam_pos = 0;
|
||||||
bool mismatch_found = false; // Have we found a mismatched element yet?
|
bool unmatched_found = false;
|
||||||
|
|
||||||
// Go through the elements and matchers in pairs, until we reach
|
// Go through the elements and matchers in pairs, until we reach
|
||||||
// the end of either the elements or the matchers, or until we find a
|
// the end of either the elements or the matchers, or until we find a
|
||||||
@ -3496,11 +3665,23 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!match) {
|
if (!match) {
|
||||||
mismatch_found = true;
|
unmatched_found = true;
|
||||||
|
// We cannot store the iterator for the unmatched element to be used
|
||||||
|
// later, as some users use ElementsAre() with a "container" whose
|
||||||
|
// iterator is not copy-constructible or copy-assignable.
|
||||||
|
//
|
||||||
|
// We cannot store a pointer to the element either, as some container's
|
||||||
|
// iterators return a temporary.
|
||||||
|
//
|
||||||
|
// We cannot store the element itself either, as the element may not be
|
||||||
|
// copyable.
|
||||||
|
//
|
||||||
|
// Therefore, we just remember the index of the unmatched element,
|
||||||
|
// and use it later to print the unmatched element.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If mismatch_found is true, 'exam_pos' is the index of the mismatch.
|
// If unmatched_found is true, exam_pos is the index of the mismatch.
|
||||||
|
|
||||||
// Find how many elements the actual container has. We avoid
|
// Find how many elements the actual container has. We avoid
|
||||||
// calling size() s.t. this code works for stream-like "containers"
|
// calling size() s.t. this code works for stream-like "containers"
|
||||||
@ -3521,10 +3702,27 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mismatch_found) {
|
if (unmatched_found) {
|
||||||
// The element count matches, but the exam_pos-th element doesn't match.
|
// The element count matches, but the exam_pos-th element doesn't match.
|
||||||
if (listener_interested) {
|
if (listener_interested) {
|
||||||
*listener << "whose element #" << exam_pos << " doesn't match";
|
// Find the unmatched element.
|
||||||
|
auto unmatched_it = stl_container.begin();
|
||||||
|
// We cannot call std::advance() on the iterator, as some users use
|
||||||
|
// ElementsAre() with a "container" whose iterator is incompatible with
|
||||||
|
// std::advance() (e.g. it may not have the difference_type member
|
||||||
|
// type).
|
||||||
|
for (size_t i = 0; i != exam_pos; ++i) {
|
||||||
|
++unmatched_it;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the array is long or the elements' print-out is large, it may be
|
||||||
|
// hard for the user to find the mismatched element and its
|
||||||
|
// corresponding matcher description. Therefore we print the index, the
|
||||||
|
// value of the mismatched element, and the corresponding matcher
|
||||||
|
// description to ease debugging.
|
||||||
|
*listener << "whose element #" << exam_pos << " ("
|
||||||
|
<< PrintToString(*unmatched_it) << ") ";
|
||||||
|
matchers_[exam_pos].DescribeNegationTo(listener->stream());
|
||||||
PrintIfNotEmpty(explanations[exam_pos], listener->stream());
|
PrintIfNotEmpty(explanations[exam_pos], listener->stream());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -3930,15 +4128,15 @@ GTEST_API_ std::string FormatMatcherDescription(
|
|||||||
// Overloads to support `OptionalMatcher` being used with a type that either
|
// Overloads to support `OptionalMatcher` being used with a type that either
|
||||||
// supports implicit conversion to bool or a `has_value()` method.
|
// supports implicit conversion to bool or a `has_value()` method.
|
||||||
template <typename Optional>
|
template <typename Optional>
|
||||||
auto IsOptionalEngaged(const Optional& optional,
|
auto IsOptionalEngaged(const Optional& optional, Rank1)
|
||||||
Rank1) -> decltype(!!optional) {
|
-> decltype(!!optional) {
|
||||||
// The use of double-negation here is to preserve historical behavior where
|
// The use of double-negation here is to preserve historical behavior where
|
||||||
// the matcher used `operator!` rather than directly using `operator bool`.
|
// the matcher used `operator!` rather than directly using `operator bool`.
|
||||||
return !static_cast<bool>(!optional);
|
return !static_cast<bool>(!optional);
|
||||||
}
|
}
|
||||||
template <typename Optional>
|
template <typename Optional>
|
||||||
auto IsOptionalEngaged(const Optional& optional,
|
auto IsOptionalEngaged(const Optional& optional, Rank0)
|
||||||
Rank0) -> decltype(!optional.has_value()) {
|
-> decltype(!optional.has_value()) {
|
||||||
return optional.has_value();
|
return optional.has_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3979,6 +4177,10 @@ class OptionalMatcher {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const ValueType& value = *optional;
|
const ValueType& value = *optional;
|
||||||
|
if (!listener->IsInterested()) {
|
||||||
|
// Fast path to avoid unnecessary generation of match explanation.
|
||||||
|
return value_matcher_.Matches(value);
|
||||||
|
}
|
||||||
StringMatchResultListener value_listener;
|
StringMatchResultListener value_listener;
|
||||||
const bool match = value_matcher_.MatchAndExplain(value, &value_listener);
|
const bool match = value_matcher_.MatchAndExplain(value, &value_listener);
|
||||||
*listener << "whose value " << PrintToString(value)
|
*listener << "whose value " << PrintToString(value)
|
||||||
@ -4314,13 +4516,6 @@ inline Matcher<T> An() {
|
|||||||
return _;
|
return _;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename M>
|
|
||||||
Matcher<T> internal::MatcherCastImpl<T, M>::CastImpl(
|
|
||||||
const M& value, std::false_type /* convertible_to_matcher */,
|
|
||||||
std::false_type /* convertible_to_T */) {
|
|
||||||
return Eq(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates a polymorphic matcher that matches any NULL pointer.
|
// Creates a polymorphic matcher that matches any NULL pointer.
|
||||||
inline PolymorphicMatcher<internal::IsNullMatcher> IsNull() {
|
inline PolymorphicMatcher<internal::IsNullMatcher> IsNull() {
|
||||||
return MakePolymorphicMatcher(internal::IsNullMatcher());
|
return MakePolymorphicMatcher(internal::IsNullMatcher());
|
||||||
@ -4365,6 +4560,42 @@ inline internal::FloatingEqMatcher<double> DoubleNear(double rhs,
|
|||||||
return internal::FloatingEqMatcher<double>(rhs, false, max_abs_error);
|
return internal::FloatingEqMatcher<double>(rhs, false, max_abs_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The DistanceFrom(target, get_distance, m) and DistanceFrom(target, m)
|
||||||
|
// matchers work on arbitrary types that have the "distance" concept. What they
|
||||||
|
// do:
|
||||||
|
//
|
||||||
|
// 1. compute the distance between the value and the target using
|
||||||
|
// get_distance(value, target) if get_distance is provided; otherwise compute
|
||||||
|
// the distance as abs(value - target).
|
||||||
|
// 2. match the distance against the user-provided matcher m; if the match
|
||||||
|
// succeeds, the DistanceFrom() match succeeds.
|
||||||
|
//
|
||||||
|
// Examples:
|
||||||
|
//
|
||||||
|
// // 0.5's distance from 0.6 should be <= 0.2.
|
||||||
|
// EXPECT_THAT(0.5, DistanceFrom(0.6, Le(0.2)));
|
||||||
|
//
|
||||||
|
// Vector2D v1(3.0, 4.0), v2(3.2, 6.0);
|
||||||
|
// // v1's distance from v2, as computed by EuclideanDistance(v1, v2),
|
||||||
|
// // should be >= 1.0.
|
||||||
|
// EXPECT_THAT(v1, DistanceFrom(v2, EuclideanDistance, Ge(1.0)));
|
||||||
|
|
||||||
|
template <typename T, typename GetDistance, typename DistanceMatcher>
|
||||||
|
inline internal::DistanceFromMatcher<T, GetDistance, DistanceMatcher>
|
||||||
|
DistanceFrom(T target, GetDistance get_distance,
|
||||||
|
DistanceMatcher distance_matcher) {
|
||||||
|
return internal::DistanceFromMatcher<T, GetDistance, DistanceMatcher>(
|
||||||
|
std::move(target), std::move(get_distance), std::move(distance_matcher));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename DistanceMatcher>
|
||||||
|
inline internal::DistanceFromMatcher<T, internal::DefaultGetDistance,
|
||||||
|
DistanceMatcher>
|
||||||
|
DistanceFrom(T target, DistanceMatcher distance_matcher) {
|
||||||
|
return DistanceFrom(std::move(target), internal::DefaultGetDistance(),
|
||||||
|
std::move(distance_matcher));
|
||||||
|
}
|
||||||
|
|
||||||
// Creates a matcher that matches any double argument approximately equal to
|
// Creates a matcher that matches any double argument approximately equal to
|
||||||
// rhs, up to the specified max absolute error bound, including NaN values when
|
// rhs, up to the specified max absolute error bound, including NaN values when
|
||||||
// rhs is NaN. The max absolute error bound must be non-negative.
|
// rhs is NaN. The max absolute error bound must be non-negative.
|
||||||
@ -4430,7 +4661,7 @@ WhenDynamicCastTo(const Matcher<To>& inner_matcher) {
|
|||||||
// matches a Foo object x if and only if x.number >= 5.
|
// matches a Foo object x if and only if x.number >= 5.
|
||||||
template <typename Class, typename FieldType, typename FieldMatcher>
|
template <typename Class, typename FieldType, typename FieldMatcher>
|
||||||
inline PolymorphicMatcher<internal::FieldMatcher<Class, FieldType>> Field(
|
inline PolymorphicMatcher<internal::FieldMatcher<Class, FieldType>> Field(
|
||||||
FieldType Class::*field, const FieldMatcher& matcher) {
|
FieldType Class::* field, const FieldMatcher& matcher) {
|
||||||
return MakePolymorphicMatcher(internal::FieldMatcher<Class, FieldType>(
|
return MakePolymorphicMatcher(internal::FieldMatcher<Class, FieldType>(
|
||||||
field, MatcherCast<const FieldType&>(matcher)));
|
field, MatcherCast<const FieldType&>(matcher)));
|
||||||
// The call to MatcherCast() is required for supporting inner
|
// The call to MatcherCast() is required for supporting inner
|
||||||
@ -4443,7 +4674,7 @@ inline PolymorphicMatcher<internal::FieldMatcher<Class, FieldType>> Field(
|
|||||||
// messages.
|
// messages.
|
||||||
template <typename Class, typename FieldType, typename FieldMatcher>
|
template <typename Class, typename FieldType, typename FieldMatcher>
|
||||||
inline PolymorphicMatcher<internal::FieldMatcher<Class, FieldType>> Field(
|
inline PolymorphicMatcher<internal::FieldMatcher<Class, FieldType>> Field(
|
||||||
const std::string& field_name, FieldType Class::*field,
|
const std::string& field_name, FieldType Class::* field,
|
||||||
const FieldMatcher& matcher) {
|
const FieldMatcher& matcher) {
|
||||||
return MakePolymorphicMatcher(internal::FieldMatcher<Class, FieldType>(
|
return MakePolymorphicMatcher(internal::FieldMatcher<Class, FieldType>(
|
||||||
field_name, field, MatcherCast<const FieldType&>(matcher)));
|
field_name, field, MatcherCast<const FieldType&>(matcher)));
|
||||||
@ -4453,6 +4684,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>>
|
||||||
@ -5551,8 +5786,7 @@ PolymorphicMatcher<internal::ExceptionMatcherImpl<Err>> ThrowsMessage(
|
|||||||
template <typename arg_type> \
|
template <typename arg_type> \
|
||||||
bool name##Matcher::gmock_Impl<arg_type>::MatchAndExplain( \
|
bool name##Matcher::gmock_Impl<arg_type>::MatchAndExplain( \
|
||||||
const arg_type& arg, \
|
const arg_type& arg, \
|
||||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED ::testing::MatchResultListener* \
|
[[maybe_unused]] ::testing::MatchResultListener* result_listener) const
|
||||||
result_listener) const
|
|
||||||
|
|
||||||
#define MATCHER_P(name, p0, description) \
|
#define MATCHER_P(name, p0, description) \
|
||||||
GMOCK_INTERNAL_MATCHER(name, name##MatcherP, description, (#p0), (p0))
|
GMOCK_INTERNAL_MATCHER(name, name##MatcherP, description, (#p0), (p0))
|
||||||
@ -5637,8 +5871,8 @@ PolymorphicMatcher<internal::ExceptionMatcherImpl<Err>> ThrowsMessage(
|
|||||||
bool full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>:: \
|
bool full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>:: \
|
||||||
gmock_Impl<arg_type>::MatchAndExplain( \
|
gmock_Impl<arg_type>::MatchAndExplain( \
|
||||||
const arg_type& arg, \
|
const arg_type& arg, \
|
||||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED ::testing:: \
|
[[maybe_unused]] ::testing::MatchResultListener* result_listener) \
|
||||||
MatchResultListener* result_listener) const
|
const
|
||||||
|
|
||||||
#define GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args) \
|
#define GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args) \
|
||||||
GMOCK_PP_TAIL( \
|
GMOCK_PP_TAIL( \
|
||||||
|
|||||||
@ -521,8 +521,7 @@
|
|||||||
GMOCK_INTERNAL_DECL_##value_params) \
|
GMOCK_INTERNAL_DECL_##value_params) \
|
||||||
GMOCK_PP_IF(GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params), \
|
GMOCK_PP_IF(GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params), \
|
||||||
= default; \
|
= default; \
|
||||||
, \
|
, : impl_(std::make_shared<gmock_Impl>( \
|
||||||
: impl_(std::make_shared<gmock_Impl>( \
|
|
||||||
GMOCK_INTERNAL_LIST_##value_params)){}) \
|
GMOCK_INTERNAL_LIST_##value_params)){}) \
|
||||||
GMOCK_ACTION_CLASS_(name, value_params)(const GMOCK_ACTION_CLASS_( \
|
GMOCK_ACTION_CLASS_(name, value_params)(const GMOCK_ACTION_CLASS_( \
|
||||||
name, value_params) &) noexcept GMOCK_INTERNAL_DEFN_COPY_ \
|
name, value_params) &) noexcept GMOCK_INTERNAL_DEFN_COPY_ \
|
||||||
@ -551,10 +550,10 @@
|
|||||||
}; \
|
}; \
|
||||||
template <GMOCK_INTERNAL_DECL_##template_params \
|
template <GMOCK_INTERNAL_DECL_##template_params \
|
||||||
GMOCK_INTERNAL_DECL_TYPE_##value_params> \
|
GMOCK_INTERNAL_DECL_TYPE_##value_params> \
|
||||||
GMOCK_ACTION_CLASS_( \
|
[[nodiscard]] GMOCK_ACTION_CLASS_( \
|
||||||
name, value_params)<GMOCK_INTERNAL_LIST_##template_params \
|
name, value_params)<GMOCK_INTERNAL_LIST_##template_params \
|
||||||
GMOCK_INTERNAL_LIST_TYPE_##value_params> \
|
GMOCK_INTERNAL_LIST_TYPE_##value_params> \
|
||||||
name(GMOCK_INTERNAL_DECL_##value_params) GTEST_MUST_USE_RESULT_; \
|
name(GMOCK_INTERNAL_DECL_##value_params); \
|
||||||
template <GMOCK_INTERNAL_DECL_##template_params \
|
template <GMOCK_INTERNAL_DECL_##template_params \
|
||||||
GMOCK_INTERNAL_DECL_TYPE_##value_params> \
|
GMOCK_INTERNAL_DECL_TYPE_##value_params> \
|
||||||
inline GMOCK_ACTION_CLASS_( \
|
inline GMOCK_ACTION_CLASS_( \
|
||||||
|
|||||||
@ -1292,10 +1292,10 @@ class MockSpec {
|
|||||||
: function_mocker_(function_mocker), matchers_(matchers) {}
|
: function_mocker_(function_mocker), matchers_(matchers) {}
|
||||||
|
|
||||||
// Adds a new default action spec to the function mocker and returns
|
// Adds a new default action spec to the function mocker and returns
|
||||||
// the newly created spec.
|
// the newly created spec. .WillByDefault() must be called on the returned
|
||||||
internal::OnCallSpec<F>& InternalDefaultActionSetAt(const char* file,
|
// object.
|
||||||
int line, const char* obj,
|
[[nodiscard]] internal::OnCallSpec<F>& InternalDefaultActionSetAt(
|
||||||
const char* call) {
|
const char* file, int line, const char* obj, const char* call) {
|
||||||
LogWithLocation(internal::kInfo, file, line,
|
LogWithLocation(internal::kInfo, file, line,
|
||||||
std::string("ON_CALL(") + obj + ", " + call + ") invoked");
|
std::string("ON_CALL(") + obj + ", " + call + ") invoked");
|
||||||
return function_mocker_->AddNewOnCallSpec(file, line, matchers_);
|
return function_mocker_->AddNewOnCallSpec(file, line, matchers_);
|
||||||
@ -1467,7 +1467,7 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase {
|
|||||||
// function have been satisfied. If not, it will report Google Test
|
// function have been satisfied. If not, it will report Google Test
|
||||||
// non-fatal failures for the violations.
|
// non-fatal failures for the violations.
|
||||||
~FunctionMocker() override GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
~FunctionMocker() override GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||||
MutexLock l(&g_gmock_mutex);
|
MutexLock l(g_gmock_mutex);
|
||||||
VerifyAndClearExpectationsLocked();
|
VerifyAndClearExpectationsLocked();
|
||||||
Mock::UnregisterLocked(this);
|
Mock::UnregisterLocked(this);
|
||||||
ClearDefaultActionsLocked();
|
ClearDefaultActionsLocked();
|
||||||
@ -1530,7 +1530,7 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase {
|
|||||||
UntypedOnCallSpecs specs_to_delete;
|
UntypedOnCallSpecs specs_to_delete;
|
||||||
untyped_on_call_specs_.swap(specs_to_delete);
|
untyped_on_call_specs_.swap(specs_to_delete);
|
||||||
|
|
||||||
g_gmock_mutex.Unlock();
|
g_gmock_mutex.unlock();
|
||||||
for (UntypedOnCallSpecs::const_iterator it = specs_to_delete.begin();
|
for (UntypedOnCallSpecs::const_iterator it = specs_to_delete.begin();
|
||||||
it != specs_to_delete.end(); ++it) {
|
it != specs_to_delete.end(); ++it) {
|
||||||
delete static_cast<const OnCallSpec<F>*>(*it);
|
delete static_cast<const OnCallSpec<F>*>(*it);
|
||||||
@ -1538,7 +1538,7 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase {
|
|||||||
|
|
||||||
// Lock the mutex again, since the caller expects it to be locked when we
|
// Lock the mutex again, since the caller expects it to be locked when we
|
||||||
// return.
|
// return.
|
||||||
g_gmock_mutex.Lock();
|
g_gmock_mutex.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the result of invoking this mock function with the given
|
// Returns the result of invoking this mock function with the given
|
||||||
@ -1646,7 +1646,7 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase {
|
|||||||
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||||
const ArgumentTuple& args =
|
const ArgumentTuple& args =
|
||||||
*static_cast<const ArgumentTuple*>(untyped_args);
|
*static_cast<const ArgumentTuple*>(untyped_args);
|
||||||
MutexLock l(&g_gmock_mutex);
|
MutexLock l(g_gmock_mutex);
|
||||||
TypedExpectation<F>* exp = this->FindMatchingExpectationLocked(args);
|
TypedExpectation<F>* exp = this->FindMatchingExpectationLocked(args);
|
||||||
if (exp == nullptr) { // A match wasn't found.
|
if (exp == nullptr) { // A match wasn't found.
|
||||||
this->FormatUnexpectedCallMessageLocked(args, what, why);
|
this->FormatUnexpectedCallMessageLocked(args, what, why);
|
||||||
|
|||||||
@ -298,7 +298,7 @@ GTEST_API_ void Log(LogSeverity severity, const std::string& message,
|
|||||||
//
|
//
|
||||||
class WithoutMatchers {
|
class WithoutMatchers {
|
||||||
private:
|
private:
|
||||||
WithoutMatchers() {}
|
WithoutMatchers() = default;
|
||||||
friend GTEST_API_ WithoutMatchers GetWithoutMatchers();
|
friend GTEST_API_ WithoutMatchers GetWithoutMatchers();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -467,11 +467,6 @@ struct Function<R(Args...)> {
|
|||||||
using MakeResultIgnoredValue = IgnoredValue(Args...);
|
using MakeResultIgnoredValue = IgnoredValue(Args...);
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef GTEST_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
|
|
||||||
template <typename R, typename... Args>
|
|
||||||
constexpr size_t Function<R(Args...)>::ArgumentCount;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Workaround for MSVC error C2039: 'type': is not a member of 'std'
|
// Workaround for MSVC error C2039: 'type': is not a member of 'std'
|
||||||
// when std::tuple_element is used.
|
// when std::tuple_element is used.
|
||||||
// See: https://github.com/google/googletest/issues/3931
|
// See: https://github.com/google/googletest/issues/3931
|
||||||
|
|||||||
@ -156,7 +156,7 @@ GTEST_API_ void Log(LogSeverity severity, const std::string& message,
|
|||||||
if (!LogIsVisible(severity)) return;
|
if (!LogIsVisible(severity)) return;
|
||||||
|
|
||||||
// Ensures that logs from different threads don't interleave.
|
// Ensures that logs from different threads don't interleave.
|
||||||
MutexLock l(&g_log_mutex);
|
MutexLock l(g_log_mutex);
|
||||||
|
|
||||||
if (severity == kWarning) {
|
if (severity == kWarning) {
|
||||||
// Prints a GMOCK WARNING marker to make the warnings easily searchable.
|
// Prints a GMOCK WARNING marker to make the warnings easily searchable.
|
||||||
|
|||||||
@ -212,7 +212,7 @@ void ExpectationBase::CheckActionCountIfNotDone() const
|
|||||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||||
bool should_check = false;
|
bool should_check = false;
|
||||||
{
|
{
|
||||||
MutexLock l(&mutex_);
|
MutexLock l(mutex_);
|
||||||
if (!action_count_checked_) {
|
if (!action_count_checked_) {
|
||||||
action_count_checked_ = true;
|
action_count_checked_ = true;
|
||||||
should_check = true;
|
should_check = true;
|
||||||
@ -293,7 +293,7 @@ void ReportUninterestingCall(CallReaction reaction, const std::string& msg) {
|
|||||||
Log(kWarning,
|
Log(kWarning,
|
||||||
msg +
|
msg +
|
||||||
"\nNOTE: You can safely ignore the above warning unless this "
|
"\nNOTE: You can safely ignore the above warning unless this "
|
||||||
"call should not happen. Do not suppress it by blindly adding "
|
"call should not happen. Do not suppress it by adding "
|
||||||
"an EXPECT_CALL() if you don't mean to enforce the call. "
|
"an EXPECT_CALL() if you don't mean to enforce the call. "
|
||||||
"See "
|
"See "
|
||||||
"https://github.com/google/googletest/blob/main/docs/"
|
"https://github.com/google/googletest/blob/main/docs/"
|
||||||
@ -318,7 +318,7 @@ UntypedFunctionMockerBase::~UntypedFunctionMockerBase() = default;
|
|||||||
void UntypedFunctionMockerBase::RegisterOwner(const void* mock_obj)
|
void UntypedFunctionMockerBase::RegisterOwner(const void* mock_obj)
|
||||||
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||||
{
|
{
|
||||||
MutexLock l(&g_gmock_mutex);
|
MutexLock l(g_gmock_mutex);
|
||||||
mock_obj_ = mock_obj;
|
mock_obj_ = mock_obj;
|
||||||
}
|
}
|
||||||
Mock::Register(mock_obj, this);
|
Mock::Register(mock_obj, this);
|
||||||
@ -332,7 +332,7 @@ void UntypedFunctionMockerBase::SetOwnerAndName(const void* mock_obj,
|
|||||||
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||||
// We protect name_ under g_gmock_mutex in case this mock function
|
// We protect name_ under g_gmock_mutex in case this mock function
|
||||||
// is called from two threads concurrently.
|
// is called from two threads concurrently.
|
||||||
MutexLock l(&g_gmock_mutex);
|
MutexLock l(g_gmock_mutex);
|
||||||
mock_obj_ = mock_obj;
|
mock_obj_ = mock_obj;
|
||||||
name_ = name;
|
name_ = name;
|
||||||
}
|
}
|
||||||
@ -345,7 +345,7 @@ const void* UntypedFunctionMockerBase::MockObject() const
|
|||||||
{
|
{
|
||||||
// We protect mock_obj_ under g_gmock_mutex in case this mock
|
// We protect mock_obj_ under g_gmock_mutex in case this mock
|
||||||
// function is called from two threads concurrently.
|
// function is called from two threads concurrently.
|
||||||
MutexLock l(&g_gmock_mutex);
|
MutexLock l(g_gmock_mutex);
|
||||||
Assert(mock_obj_ != nullptr, __FILE__, __LINE__,
|
Assert(mock_obj_ != nullptr, __FILE__, __LINE__,
|
||||||
"MockObject() must not be called before RegisterOwner() or "
|
"MockObject() must not be called before RegisterOwner() or "
|
||||||
"SetOwnerAndName() has been called.");
|
"SetOwnerAndName() has been called.");
|
||||||
@ -362,7 +362,7 @@ const char* UntypedFunctionMockerBase::Name() const
|
|||||||
{
|
{
|
||||||
// We protect name_ under g_gmock_mutex in case this mock
|
// We protect name_ under g_gmock_mutex in case this mock
|
||||||
// function is called from two threads concurrently.
|
// function is called from two threads concurrently.
|
||||||
MutexLock l(&g_gmock_mutex);
|
MutexLock l(g_gmock_mutex);
|
||||||
Assert(name_ != nullptr, __FILE__, __LINE__,
|
Assert(name_ != nullptr, __FILE__, __LINE__,
|
||||||
"Name() must not be called before SetOwnerAndName() has "
|
"Name() must not be called before SetOwnerAndName() has "
|
||||||
"been called.");
|
"been called.");
|
||||||
@ -436,9 +436,9 @@ bool UntypedFunctionMockerBase::VerifyAndClearExpectationsLocked()
|
|||||||
UntypedExpectations expectations_to_delete;
|
UntypedExpectations expectations_to_delete;
|
||||||
untyped_expectations_.swap(expectations_to_delete);
|
untyped_expectations_.swap(expectations_to_delete);
|
||||||
|
|
||||||
g_gmock_mutex.Unlock();
|
g_gmock_mutex.unlock();
|
||||||
expectations_to_delete.clear();
|
expectations_to_delete.clear();
|
||||||
g_gmock_mutex.Lock();
|
g_gmock_mutex.lock();
|
||||||
|
|
||||||
return expectations_met;
|
return expectations_met;
|
||||||
}
|
}
|
||||||
@ -490,7 +490,7 @@ class MockObjectRegistry {
|
|||||||
// failure, unless the user explicitly asked us to ignore it.
|
// failure, unless the user explicitly asked us to ignore it.
|
||||||
~MockObjectRegistry() {
|
~MockObjectRegistry() {
|
||||||
if (!GMOCK_FLAG_GET(catch_leaked_mocks)) return;
|
if (!GMOCK_FLAG_GET(catch_leaked_mocks)) return;
|
||||||
internal::MutexLock l(&internal::g_gmock_mutex);
|
internal::MutexLock l(internal::g_gmock_mutex);
|
||||||
|
|
||||||
int leaked_count = 0;
|
int leaked_count = 0;
|
||||||
for (StateMap::const_iterator it = states_.begin(); it != states_.end();
|
for (StateMap::const_iterator it = states_.begin(); it != states_.end();
|
||||||
@ -559,7 +559,7 @@ UninterestingCallReactionMap() {
|
|||||||
void SetReactionOnUninterestingCalls(uintptr_t mock_obj,
|
void SetReactionOnUninterestingCalls(uintptr_t mock_obj,
|
||||||
internal::CallReaction reaction)
|
internal::CallReaction reaction)
|
||||||
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||||
internal::MutexLock l(&internal::g_gmock_mutex);
|
internal::MutexLock l(internal::g_gmock_mutex);
|
||||||
UninterestingCallReactionMap()[mock_obj] = reaction;
|
UninterestingCallReactionMap()[mock_obj] = reaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -590,7 +590,7 @@ void Mock::FailUninterestingCalls(uintptr_t mock_obj)
|
|||||||
// entry in the call-reaction table should be removed.
|
// entry in the call-reaction table should be removed.
|
||||||
void Mock::UnregisterCallReaction(uintptr_t mock_obj)
|
void Mock::UnregisterCallReaction(uintptr_t mock_obj)
|
||||||
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||||
internal::MutexLock l(&internal::g_gmock_mutex);
|
internal::MutexLock l(internal::g_gmock_mutex);
|
||||||
UninterestingCallReactionMap().erase(static_cast<uintptr_t>(mock_obj));
|
UninterestingCallReactionMap().erase(static_cast<uintptr_t>(mock_obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -598,7 +598,7 @@ void Mock::UnregisterCallReaction(uintptr_t mock_obj)
|
|||||||
// made on the given mock object.
|
// made on the given mock object.
|
||||||
internal::CallReaction Mock::GetReactionOnUninterestingCalls(
|
internal::CallReaction Mock::GetReactionOnUninterestingCalls(
|
||||||
const void* mock_obj) GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
const void* mock_obj) GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||||
internal::MutexLock l(&internal::g_gmock_mutex);
|
internal::MutexLock l(internal::g_gmock_mutex);
|
||||||
return (UninterestingCallReactionMap().count(
|
return (UninterestingCallReactionMap().count(
|
||||||
reinterpret_cast<uintptr_t>(mock_obj)) == 0)
|
reinterpret_cast<uintptr_t>(mock_obj)) == 0)
|
||||||
? internal::intToCallReaction(
|
? internal::intToCallReaction(
|
||||||
@ -611,7 +611,7 @@ internal::CallReaction Mock::GetReactionOnUninterestingCalls(
|
|||||||
// objects.
|
// objects.
|
||||||
void Mock::AllowLeak(const void* mock_obj)
|
void Mock::AllowLeak(const void* mock_obj)
|
||||||
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||||
internal::MutexLock l(&internal::g_gmock_mutex);
|
internal::MutexLock l(internal::g_gmock_mutex);
|
||||||
g_mock_object_registry.states()[mock_obj].leakable = true;
|
g_mock_object_registry.states()[mock_obj].leakable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -620,7 +620,7 @@ void Mock::AllowLeak(const void* mock_obj)
|
|||||||
// Test non-fatal failures and returns false.
|
// Test non-fatal failures and returns false.
|
||||||
bool Mock::VerifyAndClearExpectations(void* mock_obj)
|
bool Mock::VerifyAndClearExpectations(void* mock_obj)
|
||||||
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||||
internal::MutexLock l(&internal::g_gmock_mutex);
|
internal::MutexLock l(internal::g_gmock_mutex);
|
||||||
return VerifyAndClearExpectationsLocked(mock_obj);
|
return VerifyAndClearExpectationsLocked(mock_obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -629,7 +629,7 @@ bool Mock::VerifyAndClearExpectations(void* mock_obj)
|
|||||||
// verification was successful.
|
// verification was successful.
|
||||||
bool Mock::VerifyAndClear(void* mock_obj)
|
bool Mock::VerifyAndClear(void* mock_obj)
|
||||||
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||||
internal::MutexLock l(&internal::g_gmock_mutex);
|
internal::MutexLock l(internal::g_gmock_mutex);
|
||||||
ClearDefaultActionsLocked(mock_obj);
|
ClearDefaultActionsLocked(mock_obj);
|
||||||
return VerifyAndClearExpectationsLocked(mock_obj);
|
return VerifyAndClearExpectationsLocked(mock_obj);
|
||||||
}
|
}
|
||||||
@ -679,7 +679,7 @@ bool Mock::IsStrict(void* mock_obj)
|
|||||||
void Mock::Register(const void* mock_obj,
|
void Mock::Register(const void* mock_obj,
|
||||||
internal::UntypedFunctionMockerBase* mocker)
|
internal::UntypedFunctionMockerBase* mocker)
|
||||||
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||||
internal::MutexLock l(&internal::g_gmock_mutex);
|
internal::MutexLock l(internal::g_gmock_mutex);
|
||||||
g_mock_object_registry.states()[mock_obj].function_mockers.insert(mocker);
|
g_mock_object_registry.states()[mock_obj].function_mockers.insert(mocker);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -689,7 +689,7 @@ void Mock::Register(const void* mock_obj,
|
|||||||
void Mock::RegisterUseByOnCallOrExpectCall(const void* mock_obj,
|
void Mock::RegisterUseByOnCallOrExpectCall(const void* mock_obj,
|
||||||
const char* file, int line)
|
const char* file, int line)
|
||||||
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||||
internal::MutexLock l(&internal::g_gmock_mutex);
|
internal::MutexLock l(internal::g_gmock_mutex);
|
||||||
MockObjectState& state = g_mock_object_registry.states()[mock_obj];
|
MockObjectState& state = g_mock_object_registry.states()[mock_obj];
|
||||||
if (state.first_used_file == nullptr) {
|
if (state.first_used_file == nullptr) {
|
||||||
state.first_used_file = file;
|
state.first_used_file = file;
|
||||||
|
|||||||
@ -30,6 +30,7 @@
|
|||||||
#
|
#
|
||||||
# Bazel Build for Google C++ Testing Framework(Google Test)-googlemock
|
# Bazel Build for Google C++ Testing Framework(Google Test)-googlemock
|
||||||
|
|
||||||
|
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_test")
|
||||||
load("@rules_python//python:defs.bzl", "py_library", "py_test")
|
load("@rules_python//python:defs.bzl", "py_library", "py_test")
|
||||||
|
|
||||||
licenses(["notice"])
|
licenses(["notice"])
|
||||||
|
|||||||
@ -188,7 +188,7 @@ TEST(TypeTraits, IsInvocableRV) {
|
|||||||
struct C {
|
struct C {
|
||||||
int operator()() const { return 0; }
|
int operator()() const { return 0; }
|
||||||
void operator()(int) & {}
|
void operator()(int) & {}
|
||||||
std::string operator()(int) && { return ""; };
|
std::string operator()(int) && { return ""; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// The first overload is callable for const and non-const rvalues and lvalues.
|
// The first overload is callable for const and non-const rvalues and lvalues.
|
||||||
@ -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.
|
||||||
@ -1030,8 +1030,7 @@ void VoidFunc(bool /* flag */) {}
|
|||||||
|
|
||||||
TEST(DoDefaultDeathTest, DiesIfUsedInCompositeAction) {
|
TEST(DoDefaultDeathTest, DiesIfUsedInCompositeAction) {
|
||||||
MockClass mock;
|
MockClass mock;
|
||||||
EXPECT_CALL(mock, IntFunc(_))
|
EXPECT_CALL(mock, IntFunc(_)).WillRepeatedly(DoAll(VoidFunc, DoDefault()));
|
||||||
.WillRepeatedly(DoAll(Invoke(VoidFunc), DoDefault()));
|
|
||||||
|
|
||||||
// Ideally we should verify the error message as well. Sadly,
|
// Ideally we should verify the error message as well. Sadly,
|
||||||
// EXPECT_DEATH() can only capture stderr, while Google Mock's
|
// EXPECT_DEATH() can only capture stderr, while Google Mock's
|
||||||
@ -1282,7 +1281,7 @@ int ReturnOne() {
|
|||||||
|
|
||||||
TEST(IgnoreResultTest, MonomorphicAction) {
|
TEST(IgnoreResultTest, MonomorphicAction) {
|
||||||
g_done = false;
|
g_done = false;
|
||||||
Action<void()> a = IgnoreResult(Invoke(ReturnOne));
|
Action<void()> a = IgnoreResult(&ReturnOne);
|
||||||
a.Perform(std::make_tuple());
|
a.Perform(std::make_tuple());
|
||||||
EXPECT_TRUE(g_done);
|
EXPECT_TRUE(g_done);
|
||||||
}
|
}
|
||||||
@ -1297,7 +1296,7 @@ MyNonDefaultConstructible ReturnMyNonDefaultConstructible(double /* x */) {
|
|||||||
TEST(IgnoreResultTest, ActionReturningClass) {
|
TEST(IgnoreResultTest, ActionReturningClass) {
|
||||||
g_done = false;
|
g_done = false;
|
||||||
Action<void(int)> a =
|
Action<void(int)> a =
|
||||||
IgnoreResult(Invoke(ReturnMyNonDefaultConstructible)); // NOLINT
|
IgnoreResult(&ReturnMyNonDefaultConstructible); // NOLINT
|
||||||
a.Perform(std::make_tuple(2));
|
a.Perform(std::make_tuple(2));
|
||||||
EXPECT_TRUE(g_done);
|
EXPECT_TRUE(g_done);
|
||||||
}
|
}
|
||||||
@ -1477,12 +1476,15 @@ TEST(DoAll, SupportsTypeErasedActions) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A DoAll action should be convertible to a OnceAction, even when its component
|
// A multi-action DoAll action should be convertible to a OnceAction, even when
|
||||||
// sub-actions are user-provided types that define only an Action conversion
|
// its component sub-actions are user-provided types that define only an Action
|
||||||
// operator. If they supposed being called more than once then they also support
|
// conversion operator. If they supposed being called more than once then they
|
||||||
// being called at most once.
|
// also support being called at most once.
|
||||||
|
//
|
||||||
|
// Single-arg DoAll just returns its argument, so will prefer the Action<F>
|
||||||
|
// overload for WillOnce.
|
||||||
TEST(DoAll, ConvertibleToOnceActionWithUserProvidedActionConversion) {
|
TEST(DoAll, ConvertibleToOnceActionWithUserProvidedActionConversion) {
|
||||||
// Simplest case: only one sub-action.
|
// Final action.
|
||||||
struct CustomFinal final {
|
struct CustomFinal final {
|
||||||
operator Action<int()>() { // NOLINT
|
operator Action<int()>() { // NOLINT
|
||||||
return Return(17);
|
return Return(17);
|
||||||
@ -1493,17 +1495,7 @@ TEST(DoAll, ConvertibleToOnceActionWithUserProvidedActionConversion) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
// Sub-actions.
|
||||||
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 {
|
struct CustomInitial final {
|
||||||
operator Action<void()>() { // NOLINT
|
operator Action<void()>() { // NOLINT
|
||||||
return [] {};
|
return [] {};
|
||||||
@ -1527,7 +1519,7 @@ TEST(DoAll, ConvertibleToOnceActionWithUserProvidedActionConversion) {
|
|||||||
|
|
||||||
// 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>(Unary);
|
||||||
EXPECT_TRUE(a.Perform(std::make_tuple(1.5, -1)));
|
EXPECT_TRUE(a.Perform(std::make_tuple(1.5, -1)));
|
||||||
EXPECT_FALSE(a.Perform(std::make_tuple(1.5, 1)));
|
EXPECT_FALSE(a.Perform(std::make_tuple(1.5, 1)));
|
||||||
}
|
}
|
||||||
@ -1535,7 +1527,7 @@ TEST(WithArgsTest, OneArg) {
|
|||||||
// Tests using WithArgs with an action that takes 2 arguments.
|
// Tests using WithArgs with an action that takes 2 arguments.
|
||||||
TEST(WithArgsTest, TwoArgs) {
|
TEST(WithArgsTest, TwoArgs) {
|
||||||
Action<const char*(const char* s, double x, short n)> a = // NOLINT
|
Action<const char*(const char* s, double x, short n)> a = // NOLINT
|
||||||
WithArgs<0, 2>(Invoke(Binary));
|
WithArgs<0, 2>(Binary);
|
||||||
const char s[] = "Hello";
|
const char s[] = "Hello";
|
||||||
EXPECT_EQ(s + 2, a.Perform(std::make_tuple(CharPtr(s), 0.5, Short(2))));
|
EXPECT_EQ(s + 2, a.Perform(std::make_tuple(CharPtr(s), 0.5, Short(2))));
|
||||||
}
|
}
|
||||||
@ -1551,7 +1543,7 @@ struct ConcatAll {
|
|||||||
// Tests using WithArgs with an action that takes 10 arguments.
|
// Tests using WithArgs with an action that takes 10 arguments.
|
||||||
TEST(WithArgsTest, TenArgs) {
|
TEST(WithArgsTest, TenArgs) {
|
||||||
Action<std::string(const char*, const char*, const char*, const char*)> a =
|
Action<std::string(const char*, const char*, const char*, const char*)> a =
|
||||||
WithArgs<0, 1, 2, 3, 2, 1, 0, 1, 2, 3>(Invoke(ConcatAll{}));
|
WithArgs<0, 1, 2, 3, 2, 1, 0, 1, 2, 3>(ConcatAll{});
|
||||||
EXPECT_EQ("0123210123",
|
EXPECT_EQ("0123210123",
|
||||||
a.Perform(std::make_tuple(CharPtr("0"), CharPtr("1"), CharPtr("2"),
|
a.Perform(std::make_tuple(CharPtr("0"), CharPtr("1"), CharPtr("2"),
|
||||||
CharPtr("3"))));
|
CharPtr("3"))));
|
||||||
@ -1576,21 +1568,21 @@ TEST(WithArgsTest, NonInvokeAction) {
|
|||||||
// Tests using WithArgs to pass all original arguments in the original order.
|
// Tests using WithArgs to pass all original arguments in the original order.
|
||||||
TEST(WithArgsTest, Identity) {
|
TEST(WithArgsTest, Identity) {
|
||||||
Action<int(int x, char y, short z)> a = // NOLINT
|
Action<int(int x, char y, short z)> a = // NOLINT
|
||||||
WithArgs<0, 1, 2>(Invoke(Ternary));
|
WithArgs<0, 1, 2>(Ternary);
|
||||||
EXPECT_EQ(123, a.Perform(std::make_tuple(100, Char(20), Short(3))));
|
EXPECT_EQ(123, a.Perform(std::make_tuple(100, Char(20), Short(3))));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests using WithArgs with repeated arguments.
|
// Tests using WithArgs with repeated arguments.
|
||||||
TEST(WithArgsTest, RepeatedArguments) {
|
TEST(WithArgsTest, RepeatedArguments) {
|
||||||
Action<int(bool, int m, int n)> a = // NOLINT
|
Action<int(bool, int m, int n)> a = // NOLINT
|
||||||
WithArgs<1, 1, 1, 1>(Invoke(SumOf4));
|
WithArgs<1, 1, 1, 1>(SumOf4);
|
||||||
EXPECT_EQ(4, a.Perform(std::make_tuple(false, 1, 10)));
|
EXPECT_EQ(4, a.Perform(std::make_tuple(false, 1, 10)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests using WithArgs with reversed argument order.
|
// Tests using WithArgs with reversed argument order.
|
||||||
TEST(WithArgsTest, ReversedArgumentOrder) {
|
TEST(WithArgsTest, ReversedArgumentOrder) {
|
||||||
Action<const char*(short n, const char* input)> a = // NOLINT
|
Action<const char*(short n, const char* input)> a = // NOLINT
|
||||||
WithArgs<1, 0>(Invoke(Binary));
|
WithArgs<1, 0>(Binary);
|
||||||
const char s[] = "Hello";
|
const char s[] = "Hello";
|
||||||
EXPECT_EQ(s + 2, a.Perform(std::make_tuple(Short(2), CharPtr(s))));
|
EXPECT_EQ(s + 2, a.Perform(std::make_tuple(Short(2), CharPtr(s))));
|
||||||
}
|
}
|
||||||
@ -1598,14 +1590,14 @@ TEST(WithArgsTest, ReversedArgumentOrder) {
|
|||||||
// Tests using WithArgs with compatible, but not identical, argument types.
|
// Tests using WithArgs with compatible, but not identical, argument types.
|
||||||
TEST(WithArgsTest, ArgsOfCompatibleTypes) {
|
TEST(WithArgsTest, ArgsOfCompatibleTypes) {
|
||||||
Action<long(short x, char y, double z, char c)> a = // NOLINT
|
Action<long(short x, char y, double z, char c)> a = // NOLINT
|
||||||
WithArgs<0, 1, 3>(Invoke(Ternary));
|
WithArgs<0, 1, 3>(Ternary);
|
||||||
EXPECT_EQ(123,
|
EXPECT_EQ(123,
|
||||||
a.Perform(std::make_tuple(Short(100), Char(20), 5.6, Char(3))));
|
a.Perform(std::make_tuple(Short(100), Char(20), 5.6, Char(3))));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests using WithArgs with an action that returns void.
|
// Tests using WithArgs with an action that returns void.
|
||||||
TEST(WithArgsTest, VoidAction) {
|
TEST(WithArgsTest, VoidAction) {
|
||||||
Action<void(double x, char c, int n)> a = WithArgs<2, 1>(Invoke(VoidBinary));
|
Action<void(double x, char c, int n)> a = WithArgs<2, 1>(VoidBinary);
|
||||||
g_done = false;
|
g_done = false;
|
||||||
a.Perform(std::make_tuple(1.5, 'a', 3));
|
a.Perform(std::make_tuple(1.5, 'a', 3));
|
||||||
EXPECT_TRUE(g_done);
|
EXPECT_TRUE(g_done);
|
||||||
@ -1645,6 +1637,22 @@ TEST(WithArgsTest, RefQualifiedInnerAction) {
|
|||||||
EXPECT_EQ(19, mock.AsStdFunction()(0, 17));
|
EXPECT_EQ(19, mock.AsStdFunction()(0, 17));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// It should be fine to provide an lvalue WithArgsAction to WillOnce, even when
|
||||||
|
// the inner action only wants to convert to OnceAction.
|
||||||
|
TEST(WithArgsTest, ProvideAsLvalueToWillOnce) {
|
||||||
|
struct SomeAction {
|
||||||
|
operator OnceAction<int(int)>() const { // NOLINT
|
||||||
|
return [](const int arg) { return arg + 2; };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto wa = WithArg<1>(SomeAction{});
|
||||||
|
|
||||||
|
MockFunction<int(int, int)> mock;
|
||||||
|
EXPECT_CALL(mock, Call).WillOnce(wa);
|
||||||
|
EXPECT_EQ(19, mock.AsStdFunction()(0, 17));
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef GTEST_OS_WINDOWS_MOBILE
|
#ifndef GTEST_OS_WINDOWS_MOBILE
|
||||||
|
|
||||||
class SetErrnoAndReturnTest : public testing::Test {
|
class SetErrnoAndReturnTest : public testing::Test {
|
||||||
@ -1814,7 +1822,7 @@ std::vector<std::unique_ptr<int>> VectorUniquePtrSource() {
|
|||||||
|
|
||||||
TEST(MockMethodTest, CanReturnMoveOnlyValue_Return) {
|
TEST(MockMethodTest, CanReturnMoveOnlyValue_Return) {
|
||||||
MockClass mock;
|
MockClass mock;
|
||||||
std::unique_ptr<int> i(new int(19));
|
std::unique_ptr<int> i = std::make_unique<int>(19);
|
||||||
EXPECT_CALL(mock, MakeUnique()).WillOnce(Return(ByMove(std::move(i))));
|
EXPECT_CALL(mock, MakeUnique()).WillOnce(Return(ByMove(std::move(i))));
|
||||||
EXPECT_CALL(mock, MakeVectorUnique())
|
EXPECT_CALL(mock, MakeVectorUnique())
|
||||||
.WillOnce(Return(ByMove(VectorUniquePtrSource())));
|
.WillOnce(Return(ByMove(VectorUniquePtrSource())));
|
||||||
@ -1837,7 +1845,7 @@ TEST(MockMethodTest, CanReturnMoveOnlyValue_Return) {
|
|||||||
TEST(MockMethodTest, CanReturnMoveOnlyValue_DoAllReturn) {
|
TEST(MockMethodTest, CanReturnMoveOnlyValue_DoAllReturn) {
|
||||||
testing::MockFunction<void()> mock_function;
|
testing::MockFunction<void()> mock_function;
|
||||||
MockClass mock;
|
MockClass mock;
|
||||||
std::unique_ptr<int> i(new int(19));
|
std::unique_ptr<int> i = std::make_unique<int>(19);
|
||||||
EXPECT_CALL(mock_function, Call());
|
EXPECT_CALL(mock_function, Call());
|
||||||
EXPECT_CALL(mock, MakeUnique())
|
EXPECT_CALL(mock, MakeUnique())
|
||||||
.WillOnce(DoAll(InvokeWithoutArgs(&mock_function,
|
.WillOnce(DoAll(InvokeWithoutArgs(&mock_function,
|
||||||
@ -1856,9 +1864,8 @@ TEST(MockMethodTest, CanReturnMoveOnlyValue_Invoke) {
|
|||||||
[] { return std::make_unique<int>(42); });
|
[] { return std::make_unique<int>(42); });
|
||||||
EXPECT_EQ(42, *mock.MakeUnique());
|
EXPECT_EQ(42, *mock.MakeUnique());
|
||||||
|
|
||||||
EXPECT_CALL(mock, MakeUnique()).WillRepeatedly(Invoke(UniquePtrSource));
|
EXPECT_CALL(mock, MakeUnique()).WillRepeatedly(UniquePtrSource);
|
||||||
EXPECT_CALL(mock, MakeVectorUnique())
|
EXPECT_CALL(mock, MakeVectorUnique()).WillRepeatedly(VectorUniquePtrSource);
|
||||||
.WillRepeatedly(Invoke(VectorUniquePtrSource));
|
|
||||||
std::unique_ptr<int> result1 = mock.MakeUnique();
|
std::unique_ptr<int> result1 = mock.MakeUnique();
|
||||||
EXPECT_EQ(19, *result1);
|
EXPECT_EQ(19, *result1);
|
||||||
std::unique_ptr<int> result2 = mock.MakeUnique();
|
std::unique_ptr<int> result2 = mock.MakeUnique();
|
||||||
@ -1880,7 +1887,7 @@ TEST(MockMethodTest, CanTakeMoveOnlyValue) {
|
|||||||
});
|
});
|
||||||
// DoAll() does not compile, since it would move from its arguments twice.
|
// DoAll() does not compile, since it would move from its arguments twice.
|
||||||
// EXPECT_CALL(mock, TakeUnique(_, _))
|
// EXPECT_CALL(mock, TakeUnique(_, _))
|
||||||
// .WillRepeatedly(DoAll(Invoke([](std::unique_ptr<int> j) {}),
|
// .WillRepeatedly(DoAll([](std::unique_ptr<int> j) {})),
|
||||||
// Return(1)));
|
// Return(1)));
|
||||||
EXPECT_CALL(mock, TakeUnique(testing::Pointee(7)))
|
EXPECT_CALL(mock, TakeUnique(testing::Pointee(7)))
|
||||||
.WillOnce(Return(-7))
|
.WillOnce(Return(-7))
|
||||||
|
|||||||
@ -91,7 +91,7 @@ class FooInterface {
|
|||||||
|
|
||||||
virtual bool TakesNonConstReference(int& n) = 0; // NOLINT
|
virtual bool TakesNonConstReference(int& n) = 0; // NOLINT
|
||||||
virtual std::string TakesConstReference(const int& n) = 0;
|
virtual std::string TakesConstReference(const int& n) = 0;
|
||||||
virtual bool TakesConst(const int x) = 0;
|
virtual bool TakesConst(int x) = 0;
|
||||||
|
|
||||||
virtual int OverloadedOnArgumentNumber() = 0;
|
virtual int OverloadedOnArgumentNumber() = 0;
|
||||||
virtual int OverloadedOnArgumentNumber(int n) = 0;
|
virtual int OverloadedOnArgumentNumber(int n) = 0;
|
||||||
|
|||||||
@ -545,7 +545,7 @@ TEST(ExpectCallTest, DoesNotLogWhenVerbosityIsError) {
|
|||||||
|
|
||||||
void OnCallLogger() {
|
void OnCallLogger() {
|
||||||
DummyMock mock;
|
DummyMock mock;
|
||||||
ON_CALL(mock, TestMethod());
|
(void)ON_CALL(mock, TestMethod());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verifies that ON_CALL logs if the --gmock_verbose flag is set to "info".
|
// Verifies that ON_CALL logs if the --gmock_verbose flag is set to "info".
|
||||||
@ -568,7 +568,7 @@ TEST(OnCallTest, DoesNotLogWhenVerbosityIsError) {
|
|||||||
|
|
||||||
void OnCallAnyArgumentLogger() {
|
void OnCallAnyArgumentLogger() {
|
||||||
DummyMock mock;
|
DummyMock mock;
|
||||||
ON_CALL(mock, TestMethodArg(_));
|
(void)ON_CALL(mock, TestMethodArg(_));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verifies that ON_CALL prints provided _ argument.
|
// Verifies that ON_CALL prints provided _ argument.
|
||||||
|
|||||||
@ -34,6 +34,7 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <ostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
@ -398,6 +399,188 @@ TEST(NanSensitiveDoubleNearTest, CanDescribeSelfWithNaNs) {
|
|||||||
EXPECT_EQ("are an almost-equal pair", Describe(m));
|
EXPECT_EQ("are an almost-equal pair", Describe(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests that DistanceFrom() can describe itself properly.
|
||||||
|
TEST(DistanceFrom, CanDescribeSelf) {
|
||||||
|
Matcher<double> m = DistanceFrom(1.5, Lt(0.1));
|
||||||
|
EXPECT_EQ(Describe(m), "is < 0.1 away from 1.5");
|
||||||
|
|
||||||
|
m = DistanceFrom(2.5, Gt(0.2));
|
||||||
|
EXPECT_EQ(Describe(m), "is > 0.2 away from 2.5");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that DistanceFrom() can explain match failure.
|
||||||
|
TEST(DistanceFrom, CanExplainMatchFailure) {
|
||||||
|
Matcher<double> m = DistanceFrom(1.5, Lt(0.1));
|
||||||
|
EXPECT_EQ(Explain(m, 2.0), "which is 0.5 away from 1.5");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that DistanceFrom() matches a double that is within the given range of
|
||||||
|
// the given value.
|
||||||
|
TEST(DistanceFrom, MatchesDoubleWithinRange) {
|
||||||
|
const Matcher<double> m = DistanceFrom(0.5, Le(0.1));
|
||||||
|
EXPECT_TRUE(m.Matches(0.45));
|
||||||
|
EXPECT_TRUE(m.Matches(0.5));
|
||||||
|
EXPECT_TRUE(m.Matches(0.55));
|
||||||
|
EXPECT_FALSE(m.Matches(0.39));
|
||||||
|
EXPECT_FALSE(m.Matches(0.61));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that DistanceFrom() matches a double reference that is within the given
|
||||||
|
// range of the given value.
|
||||||
|
TEST(DistanceFrom, MatchesDoubleRefWithinRange) {
|
||||||
|
const Matcher<const double&> m = DistanceFrom(0.5, Le(0.1));
|
||||||
|
EXPECT_TRUE(m.Matches(0.45));
|
||||||
|
EXPECT_TRUE(m.Matches(0.5));
|
||||||
|
EXPECT_TRUE(m.Matches(0.55));
|
||||||
|
EXPECT_FALSE(m.Matches(0.39));
|
||||||
|
EXPECT_FALSE(m.Matches(0.61));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that DistanceFrom() can be implicitly converted to a matcher depending
|
||||||
|
// on the type of the argument.
|
||||||
|
TEST(DistanceFrom, CanBeImplicitlyConvertedToMatcher) {
|
||||||
|
EXPECT_THAT(0.58, DistanceFrom(0.5, Le(0.1)));
|
||||||
|
EXPECT_THAT(0.2, Not(DistanceFrom(0.5, Le(0.1))));
|
||||||
|
|
||||||
|
EXPECT_THAT(0.58f, DistanceFrom(0.5f, Le(0.1f)));
|
||||||
|
EXPECT_THAT(0.7f, Not(DistanceFrom(0.5f, Le(0.1f))));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that DistanceFrom() can be used on compatible types (i.e. not
|
||||||
|
// everything has to be of the same type).
|
||||||
|
TEST(DistanceFrom, CanBeUsedOnCompatibleTypes) {
|
||||||
|
EXPECT_THAT(0.58, DistanceFrom(0.5, Le(0.1f)));
|
||||||
|
EXPECT_THAT(0.2, Not(DistanceFrom(0.5, Le(0.1f))));
|
||||||
|
|
||||||
|
EXPECT_THAT(0.58, DistanceFrom(0.5f, Le(0.1)));
|
||||||
|
EXPECT_THAT(0.2, Not(DistanceFrom(0.5f, Le(0.1))));
|
||||||
|
|
||||||
|
EXPECT_THAT(0.58, DistanceFrom(0.5f, Le(0.1f)));
|
||||||
|
EXPECT_THAT(0.2, Not(DistanceFrom(0.5f, Le(0.1f))));
|
||||||
|
|
||||||
|
EXPECT_THAT(0.58f, DistanceFrom(0.5, Le(0.1)));
|
||||||
|
EXPECT_THAT(0.2f, Not(DistanceFrom(0.5, Le(0.1))));
|
||||||
|
|
||||||
|
EXPECT_THAT(0.58f, DistanceFrom(0.5, Le(0.1f)));
|
||||||
|
EXPECT_THAT(0.2f, Not(DistanceFrom(0.5, Le(0.1f))));
|
||||||
|
|
||||||
|
EXPECT_THAT(0.58f, DistanceFrom(0.5f, Le(0.1)));
|
||||||
|
EXPECT_THAT(0.2f, Not(DistanceFrom(0.5f, Le(0.1))));
|
||||||
|
}
|
||||||
|
|
||||||
|
// A 2-dimensional point. For testing using DistanceFrom() with a custom type
|
||||||
|
// that doesn't have a built-in distance function.
|
||||||
|
class Point {
|
||||||
|
public:
|
||||||
|
Point(double x, double y) : x_(x), y_(y) {}
|
||||||
|
double x() const { return x_; }
|
||||||
|
double y() const { return y_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
double x_;
|
||||||
|
double y_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the distance between two points.
|
||||||
|
double PointDistance(const Point& lhs, const Point& rhs) {
|
||||||
|
return std::sqrt(std::pow(lhs.x() - rhs.x(), 2) +
|
||||||
|
std::pow(lhs.y() - rhs.y(), 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that DistanceFrom() can be used on a type with a custom distance
|
||||||
|
// function.
|
||||||
|
TEST(DistanceFrom, CanBeUsedOnTypeWithCustomDistanceFunction) {
|
||||||
|
const Matcher<Point> m =
|
||||||
|
DistanceFrom(Point(0.5, 0.5), PointDistance, Le(0.1));
|
||||||
|
EXPECT_THAT(Point(0.45, 0.45), m);
|
||||||
|
EXPECT_THAT(Point(0.2, 0.45), Not(m));
|
||||||
|
}
|
||||||
|
|
||||||
|
// A wrapper around a double value. For testing using DistanceFrom() with a
|
||||||
|
// custom type that has neither a built-in distance function nor a built-in
|
||||||
|
// distance comparator.
|
||||||
|
class Double {
|
||||||
|
public:
|
||||||
|
explicit Double(double value) : value_(value) {}
|
||||||
|
Double(const Double& other) = default;
|
||||||
|
double value() const { return value_; }
|
||||||
|
|
||||||
|
// Defines how to print a Double value. We don't use the AbslStringify API
|
||||||
|
// because googletest doesn't require absl yet.
|
||||||
|
friend void PrintTo(const Double& value, std::ostream* os) {
|
||||||
|
*os << "Double(" << value.value() << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
double value_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the distance between two Double values.
|
||||||
|
Double DoubleDistance(Double lhs, Double rhs) {
|
||||||
|
return Double(std::abs(lhs.value() - rhs.value()));
|
||||||
|
}
|
||||||
|
|
||||||
|
MATCHER_P(DoubleLe, rhs, (negation ? "is > " : "is <= ") + PrintToString(rhs)) {
|
||||||
|
return arg.value() <= rhs.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that DistanceFrom() can describe itself properly for a type with a
|
||||||
|
// custom printer.
|
||||||
|
TEST(DistanceFrom, CanDescribeWithCustomPrinter) {
|
||||||
|
const Matcher<Double> m =
|
||||||
|
DistanceFrom(Double(0.5), DoubleDistance, DoubleLe(Double(0.1)));
|
||||||
|
EXPECT_EQ(Describe(m), "is <= Double(0.1) away from Double(0.5)");
|
||||||
|
EXPECT_EQ(DescribeNegation(m), "is > Double(0.1) away from Double(0.5)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that DistanceFrom() can be used with a custom distance function and
|
||||||
|
// comparator.
|
||||||
|
TEST(DistanceFrom, CanCustomizeDistanceAndComparator) {
|
||||||
|
const Matcher<Double> m =
|
||||||
|
DistanceFrom(Double(0.5), DoubleDistance, DoubleLe(Double(0.1)));
|
||||||
|
EXPECT_TRUE(m.Matches(Double(0.45)));
|
||||||
|
EXPECT_TRUE(m.Matches(Double(0.5)));
|
||||||
|
EXPECT_FALSE(m.Matches(Double(0.39)));
|
||||||
|
EXPECT_FALSE(m.Matches(Double(0.61)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// For testing using DistanceFrom() with a type that supports both - and abs.
|
||||||
|
class Float {
|
||||||
|
public:
|
||||||
|
explicit Float(float value) : value_(value) {}
|
||||||
|
Float(const Float& other) = default;
|
||||||
|
float value() const { return value_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
float value_ = 0.0f;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the difference between two Float values. This must be defined in the
|
||||||
|
// same namespace as Float.
|
||||||
|
Float operator-(const Float& lhs, const Float& rhs) {
|
||||||
|
return Float(lhs.value() - rhs.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the absolute value of a Float value. This must be defined in the
|
||||||
|
// same namespace as Float.
|
||||||
|
Float abs(Float value) { return Float(std::abs(value.value())); }
|
||||||
|
|
||||||
|
// Returns true if and only if the first Float value is less than the second
|
||||||
|
// Float value. This must be defined in the same namespace as Float.
|
||||||
|
bool operator<(const Float& lhs, const Float& rhs) {
|
||||||
|
return lhs.value() < rhs.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that DistanceFrom() can be used with a type that supports both - and
|
||||||
|
// abs.
|
||||||
|
TEST(DistanceFrom, CanBeUsedWithTypeThatSupportsBothMinusAndAbs) {
|
||||||
|
const Matcher<Float> m = DistanceFrom(Float(0.5f), Lt(Float(0.1f)));
|
||||||
|
EXPECT_TRUE(m.Matches(Float(0.45f)));
|
||||||
|
EXPECT_TRUE(m.Matches(Float(0.55f)));
|
||||||
|
EXPECT_FALSE(m.Matches(Float(0.39f)));
|
||||||
|
EXPECT_FALSE(m.Matches(Float(0.61f)));
|
||||||
|
}
|
||||||
|
|
||||||
// Tests that Not(m) matches any value that doesn't match m.
|
// Tests that Not(m) matches any value that doesn't match m.
|
||||||
TEST(NotTest, NegatesMatcher) {
|
TEST(NotTest, NegatesMatcher) {
|
||||||
Matcher<int> m;
|
Matcher<int> m;
|
||||||
@ -587,7 +770,8 @@ TEST_P(AllOfTestP, ExplainsResult) {
|
|||||||
// Failed match. The first matcher, which failed, needs to
|
// Failed match. The first matcher, which failed, needs to
|
||||||
// explain.
|
// explain.
|
||||||
m = AllOf(GreaterThan(10), GreaterThan(20));
|
m = AllOf(GreaterThan(10), GreaterThan(20));
|
||||||
EXPECT_EQ("which is 5 less than 10", Explain(m, 5));
|
EXPECT_EQ("which is 5 less than 10, and which is 15 less than 20",
|
||||||
|
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, the matcher text is
|
// explain. Since it doesn't given an explanation, the matcher text is
|
||||||
@ -1442,7 +1626,7 @@ TEST_F(DoubleNearTest, NanSensitiveDoubleNearCanMatchNaN) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(NotTest, WorksOnMoveOnlyType) {
|
TEST(NotTest, WorksOnMoveOnlyType) {
|
||||||
std::unique_ptr<int> p(new int(3));
|
std::unique_ptr<int> p = std::make_unique<int>(3);
|
||||||
EXPECT_THAT(p, Pointee(Eq(3)));
|
EXPECT_THAT(p, Pointee(Eq(3)));
|
||||||
EXPECT_THAT(p, Not(Pointee(Eq(2))));
|
EXPECT_THAT(p, Not(Pointee(Eq(2))));
|
||||||
}
|
}
|
||||||
@ -1498,13 +1682,13 @@ TEST(AnyOfTest, DoesNotCallAnyOfUnqualified) {
|
|||||||
} // namespace adl_test
|
} // namespace adl_test
|
||||||
|
|
||||||
TEST(AllOfTest, WorksOnMoveOnlyType) {
|
TEST(AllOfTest, WorksOnMoveOnlyType) {
|
||||||
std::unique_ptr<int> p(new int(3));
|
std::unique_ptr<int> p = std::make_unique<int>(3);
|
||||||
EXPECT_THAT(p, AllOf(Pointee(Eq(3)), Pointee(Gt(0)), Pointee(Lt(5))));
|
EXPECT_THAT(p, AllOf(Pointee(Eq(3)), Pointee(Gt(0)), Pointee(Lt(5))));
|
||||||
EXPECT_THAT(p, Not(AllOf(Pointee(Eq(3)), Pointee(Gt(0)), Pointee(Lt(3)))));
|
EXPECT_THAT(p, Not(AllOf(Pointee(Eq(3)), Pointee(Gt(0)), Pointee(Lt(3)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AnyOfTest, WorksOnMoveOnlyType) {
|
TEST(AnyOfTest, WorksOnMoveOnlyType) {
|
||||||
std::unique_ptr<int> p(new int(3));
|
std::unique_ptr<int> p = std::make_unique<int>(3);
|
||||||
EXPECT_THAT(p, AnyOf(Pointee(Eq(5)), Pointee(Lt(0)), Pointee(Lt(5))));
|
EXPECT_THAT(p, AnyOf(Pointee(Eq(5)), Pointee(Lt(0)), Pointee(Lt(5))));
|
||||||
EXPECT_THAT(p, Not(AnyOf(Pointee(Eq(5)), Pointee(Lt(0)), Pointee(Gt(5)))));
|
EXPECT_THAT(p, Not(AnyOf(Pointee(Eq(5)), Pointee(Lt(0)), Pointee(Gt(5)))));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -621,15 +622,42 @@ struct IntReferenceWrapper {
|
|||||||
const int* value;
|
const int* value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Compared the contained values
|
||||||
bool operator==(const IntReferenceWrapper& a, const IntReferenceWrapper& b) {
|
bool operator==(const IntReferenceWrapper& a, const IntReferenceWrapper& b) {
|
||||||
return a.value == b.value;
|
return *a.value == *b.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(MatcherCastTest, ValueIsNotCopied) {
|
TEST(MatcherCastTest, ValueIsCopied) {
|
||||||
|
{
|
||||||
|
// When an IntReferenceWrapper is passed.
|
||||||
|
int n = 42;
|
||||||
|
Matcher<IntReferenceWrapper> m =
|
||||||
|
MatcherCast<IntReferenceWrapper>(IntReferenceWrapper(n));
|
||||||
|
{
|
||||||
|
int value = 42;
|
||||||
|
EXPECT_TRUE(m.Matches(value));
|
||||||
|
value = 10;
|
||||||
|
EXPECT_FALSE(m.Matches(value));
|
||||||
|
// This changes the stored reference.
|
||||||
|
n = 10;
|
||||||
|
EXPECT_TRUE(m.Matches(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// When an int is passed.
|
||||||
int n = 42;
|
int n = 42;
|
||||||
Matcher<IntReferenceWrapper> m = MatcherCast<IntReferenceWrapper>(n);
|
Matcher<IntReferenceWrapper> m = MatcherCast<IntReferenceWrapper>(n);
|
||||||
// Verify that the matcher holds a reference to n, not to its temporary copy.
|
{
|
||||||
EXPECT_TRUE(m.Matches(n));
|
int value = 42;
|
||||||
|
EXPECT_TRUE(m.Matches(value));
|
||||||
|
value = 10;
|
||||||
|
EXPECT_FALSE(m.Matches(value));
|
||||||
|
// This does not change the stored int.
|
||||||
|
n = 10;
|
||||||
|
EXPECT_FALSE(m.Matches(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Base {
|
class Base {
|
||||||
@ -2361,22 +2389,19 @@ PolymorphicMatcher<DivisibleByImpl> DivisibleBy(int n) {
|
|||||||
return MakePolymorphicMatcher(DivisibleByImpl(n));
|
return MakePolymorphicMatcher(DivisibleByImpl(n));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that when AllOf() fails, only the first failing matcher is
|
// Tests that when AllOf() fails, all failing matchers are asked to explain why.
|
||||||
// asked to explain why.
|
|
||||||
TEST(ExplainMatchResultTest, AllOf_False_False) {
|
TEST(ExplainMatchResultTest, AllOf_False_False) {
|
||||||
const Matcher<int> m = AllOf(DivisibleBy(4), DivisibleBy(3));
|
const Matcher<int> m = AllOf(DivisibleBy(4), DivisibleBy(3));
|
||||||
EXPECT_EQ("which is 1 modulo 4", Explain(m, 5));
|
EXPECT_EQ("which is 1 modulo 4, and which is 2 modulo 3", Explain(m, 5));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that when AllOf() fails, only the first failing matcher is
|
// Tests that when AllOf() fails, all failing matchers are asked to explain why.
|
||||||
// asked to explain why.
|
|
||||||
TEST(ExplainMatchResultTest, AllOf_False_True) {
|
TEST(ExplainMatchResultTest, AllOf_False_True) {
|
||||||
const Matcher<int> m = AllOf(DivisibleBy(4), DivisibleBy(3));
|
const Matcher<int> m = AllOf(DivisibleBy(4), DivisibleBy(3));
|
||||||
EXPECT_EQ("which is 2 modulo 4", Explain(m, 6));
|
EXPECT_EQ("which is 2 modulo 4", Explain(m, 6));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that when AllOf() fails, only the first failing matcher is
|
// Tests that when AllOf() fails, all failing matchers are asked to explain why.
|
||||||
// asked to explain why.
|
|
||||||
TEST(ExplainMatchResultTest, AllOf_True_False) {
|
TEST(ExplainMatchResultTest, AllOf_True_False) {
|
||||||
const Matcher<int> m = AllOf(Ge(1), DivisibleBy(3));
|
const Matcher<int> m = AllOf(Ge(1), DivisibleBy(3));
|
||||||
EXPECT_EQ("which is 2 modulo 3", Explain(m, 5));
|
EXPECT_EQ("which is 2 modulo 3", Explain(m, 5));
|
||||||
@ -2396,6 +2421,74 @@ TEST(ExplainMatchResultTest, AllOf_True_True_2) {
|
|||||||
EXPECT_EQ("is >= 2, and is <= 3", Explain(m, 2));
|
EXPECT_EQ("is >= 2, and is <= 3", Explain(m, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A matcher that records whether the listener was interested.
|
||||||
|
template <typename T>
|
||||||
|
class CountingMatcher : public MatcherInterface<T> {
|
||||||
|
public:
|
||||||
|
explicit CountingMatcher(const Matcher<T>& base_matcher,
|
||||||
|
std::vector<bool>* listener_interested)
|
||||||
|
: base_matcher_(base_matcher),
|
||||||
|
listener_interested_(listener_interested) {}
|
||||||
|
|
||||||
|
bool MatchAndExplain(T x, MatchResultListener* listener) const override {
|
||||||
|
listener_interested_->push_back(listener->IsInterested());
|
||||||
|
return base_matcher_.MatchAndExplain(x, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescribeTo(ostream* os) const override { base_matcher_.DescribeTo(os); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Matcher<T> base_matcher_;
|
||||||
|
std::vector<bool>* listener_interested_;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(AllOfTest, DoesNotFormatChildMatchersWhenNotInterested) {
|
||||||
|
std::vector<bool> listener_interested;
|
||||||
|
Matcher<int> matcher =
|
||||||
|
MakeMatcher(new CountingMatcher<int>(Eq(1), &listener_interested));
|
||||||
|
EXPECT_TRUE(matcher.Matches(1));
|
||||||
|
EXPECT_THAT(listener_interested, ElementsAre(false));
|
||||||
|
listener_interested.clear();
|
||||||
|
Matcher<int> all_of_matcher = AllOf(matcher, matcher);
|
||||||
|
EXPECT_TRUE(all_of_matcher.Matches(1));
|
||||||
|
EXPECT_THAT(listener_interested, ElementsAre(false, false));
|
||||||
|
listener_interested.clear();
|
||||||
|
EXPECT_FALSE(all_of_matcher.Matches(0));
|
||||||
|
EXPECT_THAT(listener_interested, ElementsAre(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AnyOfTest, DoesNotFormatChildMatchersWhenNotInterested) {
|
||||||
|
std::vector<bool> listener_interested;
|
||||||
|
Matcher<int> matcher =
|
||||||
|
MakeMatcher(new CountingMatcher<int>(Eq(1), &listener_interested));
|
||||||
|
EXPECT_TRUE(matcher.Matches(1));
|
||||||
|
EXPECT_THAT(listener_interested, ElementsAre(false));
|
||||||
|
listener_interested.clear();
|
||||||
|
Matcher<int> any_of_matcher = AnyOf(matcher, matcher);
|
||||||
|
EXPECT_TRUE(any_of_matcher.Matches(1));
|
||||||
|
EXPECT_THAT(listener_interested, ElementsAre(false));
|
||||||
|
listener_interested.clear();
|
||||||
|
EXPECT_FALSE(any_of_matcher.Matches(0));
|
||||||
|
EXPECT_THAT(listener_interested, ElementsAre(false, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(OptionalTest, DoesNotFormatChildMatcherWhenNotInterested) {
|
||||||
|
std::vector<bool> listener_interested;
|
||||||
|
Matcher<int> matcher =
|
||||||
|
MakeMatcher(new CountingMatcher<int>(Eq(1), &listener_interested));
|
||||||
|
EXPECT_TRUE(matcher.Matches(1));
|
||||||
|
EXPECT_THAT(listener_interested, ElementsAre(false));
|
||||||
|
listener_interested.clear();
|
||||||
|
Matcher<std::optional<int>> optional_matcher = Optional(matcher);
|
||||||
|
EXPECT_FALSE(optional_matcher.Matches(std::nullopt));
|
||||||
|
EXPECT_THAT(listener_interested, ElementsAre());
|
||||||
|
EXPECT_TRUE(optional_matcher.Matches(1));
|
||||||
|
EXPECT_THAT(listener_interested, ElementsAre(false));
|
||||||
|
listener_interested.clear();
|
||||||
|
EXPECT_FALSE(matcher.Matches(0));
|
||||||
|
EXPECT_THAT(listener_interested, ElementsAre(false));
|
||||||
|
}
|
||||||
|
|
||||||
INSTANTIATE_GTEST_MATCHER_TEST_P(ExplainmatcherResultTest);
|
INSTANTIATE_GTEST_MATCHER_TEST_P(ExplainmatcherResultTest);
|
||||||
|
|
||||||
TEST_P(ExplainmatcherResultTestP, MonomorphicMatcher) {
|
TEST_P(ExplainmatcherResultTestP, MonomorphicMatcher) {
|
||||||
|
|||||||
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <cstddef>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <forward_list>
|
#include <forward_list>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
@ -216,7 +217,7 @@ TEST(PointeeTest, ReferenceToNonConstRawPointer) {
|
|||||||
TEST(PointeeTest, SmartPointer) {
|
TEST(PointeeTest, SmartPointer) {
|
||||||
const Matcher<std::unique_ptr<int>> m = Pointee(Ge(0));
|
const Matcher<std::unique_ptr<int>> m = Pointee(Ge(0));
|
||||||
|
|
||||||
std::unique_ptr<int> n(new int(1));
|
std::unique_ptr<int> n = std::make_unique<int>(1);
|
||||||
EXPECT_TRUE(m.Matches(n));
|
EXPECT_TRUE(m.Matches(n));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,7 +254,7 @@ TEST(PointerTest, RawPointerToConst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(PointerTest, SmartPointer) {
|
TEST(PointerTest, SmartPointer) {
|
||||||
std::unique_ptr<int> n(new int(10));
|
std::unique_ptr<int> n = std::make_unique<int>(10);
|
||||||
int* raw_n = n.get();
|
int* raw_n = n.get();
|
||||||
const Matcher<std::unique_ptr<int>> m = Pointer(Eq(raw_n));
|
const Matcher<std::unique_ptr<int>> m = Pointer(Eq(raw_n));
|
||||||
|
|
||||||
@ -1271,10 +1272,11 @@ TEST(WhenSortedByTest, CanDescribeSelf) {
|
|||||||
|
|
||||||
TEST(WhenSortedByTest, ExplainsMatchResult) {
|
TEST(WhenSortedByTest, ExplainsMatchResult) {
|
||||||
const int a[] = {2, 1};
|
const int a[] = {2, 1};
|
||||||
EXPECT_EQ("which is { 1, 2 } when sorted, whose element #0 doesn't match",
|
EXPECT_EQ(
|
||||||
Explain(WhenSortedBy(less<int>(), ElementsAre(2, 3)), a));
|
Explain(WhenSortedBy(less<int>(), ElementsAre(2, 3)), a),
|
||||||
EXPECT_EQ("which is { 1, 2 } when sorted",
|
"which is { 1, 2 } when sorted, whose element #0 (1) isn't equal to 2");
|
||||||
Explain(WhenSortedBy(less<int>(), ElementsAre(1, 2)), a));
|
EXPECT_EQ(Explain(WhenSortedBy(less<int>(), ElementsAre(1, 2)), a),
|
||||||
|
"which is { 1, 2 } when sorted");
|
||||||
}
|
}
|
||||||
|
|
||||||
// WhenSorted() is a simple wrapper on WhenSortedBy(). Hence we don't
|
// WhenSorted() is a simple wrapper on WhenSortedBy(). Hence we don't
|
||||||
@ -1775,6 +1777,295 @@ TEST(IsSubsetOfTest, WorksWithMoveOnly) {
|
|||||||
helper.Call(MakeUniquePtrs({2}));
|
helper.Call(MakeUniquePtrs({2}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A container whose iterator returns a temporary. This can iterate over the
|
||||||
|
// characters in a string.
|
||||||
|
class CharString {
|
||||||
|
public:
|
||||||
|
using value_type = char;
|
||||||
|
|
||||||
|
class const_iterator {
|
||||||
|
public:
|
||||||
|
using iterator_category = std::input_iterator_tag;
|
||||||
|
using value_type = char;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using pointer = const char*;
|
||||||
|
using reference = const char&;
|
||||||
|
|
||||||
|
// Create an iterator that points to the given character.
|
||||||
|
explicit const_iterator(const char* ptr) : ptr_(ptr) {}
|
||||||
|
|
||||||
|
// Returns the current character. IMPORTANT: this must return a temporary,
|
||||||
|
// not a reference, to test that ElementsAre() works with containers whose
|
||||||
|
// iterators return temporaries.
|
||||||
|
char operator*() const { return *ptr_; }
|
||||||
|
|
||||||
|
// Advances to the next character.
|
||||||
|
const_iterator& operator++() {
|
||||||
|
++ptr_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compares two iterators.
|
||||||
|
bool operator==(const const_iterator& other) const {
|
||||||
|
return ptr_ == other.ptr_;
|
||||||
|
}
|
||||||
|
bool operator!=(const const_iterator& other) const {
|
||||||
|
return ptr_ != other.ptr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char* ptr_ = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Creates a CharString that contains the given string.
|
||||||
|
explicit CharString(const std::string& s) : s_(s) {}
|
||||||
|
|
||||||
|
// Returns an iterator pointing to the first character in the string.
|
||||||
|
const_iterator begin() const { return const_iterator(s_.c_str()); }
|
||||||
|
|
||||||
|
// Returns an iterator pointing past the last character in the string.
|
||||||
|
const_iterator end() const { return const_iterator(s_.c_str() + s_.size()); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string s_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tests using ElementsAre() with a container whose iterator returns a
|
||||||
|
// temporary.
|
||||||
|
TEST(ElementsAreTest, WorksWithContainerThatReturnsTempInIterator) {
|
||||||
|
CharString s("abc");
|
||||||
|
EXPECT_THAT(s, ElementsAre('a', 'b', 'c'));
|
||||||
|
EXPECT_THAT(s, Not(ElementsAre('a', 'b', 'd')));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests using ElementsAreArray() with a container whose iterator returns a
|
||||||
|
// temporary.
|
||||||
|
TEST(ElementsAreArrayTest, WorksWithContainerThatReturnsTempInIterator) {
|
||||||
|
CharString s("abc");
|
||||||
|
EXPECT_THAT(s, ElementsAreArray({'a', 'b', 'c'}));
|
||||||
|
EXPECT_THAT(s, Not(ElementsAreArray({'a', 'b', 'd'})));
|
||||||
|
}
|
||||||
|
|
||||||
|
// A container whose iterator returns a temporary and is not copy-assignable.
|
||||||
|
// This simulates the behavior of the proxy object returned by absl::StrSplit().
|
||||||
|
class CharString2 {
|
||||||
|
public:
|
||||||
|
using value_type = char;
|
||||||
|
|
||||||
|
class const_iterator {
|
||||||
|
public:
|
||||||
|
using iterator_category = std::input_iterator_tag;
|
||||||
|
using value_type = char;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using pointer = const char*;
|
||||||
|
using reference = const char&;
|
||||||
|
|
||||||
|
// Make const_iterator copy-constructible but not copy-assignable,
|
||||||
|
// simulating the behavior of the proxy object returned by absl::StrSplit().
|
||||||
|
const_iterator(const const_iterator&) = default;
|
||||||
|
const_iterator& operator=(const const_iterator&) = delete;
|
||||||
|
|
||||||
|
// Create an iterator that points to the given character.
|
||||||
|
explicit const_iterator(const char* ptr) : ptr_(ptr) {}
|
||||||
|
|
||||||
|
// Returns the current character. IMPORTANT: this must return a temporary,
|
||||||
|
// not a reference, to test that ElementsAre() works with containers whose
|
||||||
|
// iterators return temporaries.
|
||||||
|
char operator*() const { return *ptr_; }
|
||||||
|
|
||||||
|
// Advances to the next character.
|
||||||
|
const_iterator& operator++() {
|
||||||
|
++ptr_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compares two iterators.
|
||||||
|
bool operator==(const const_iterator& other) const {
|
||||||
|
return ptr_ == other.ptr_;
|
||||||
|
}
|
||||||
|
bool operator!=(const const_iterator& other) const {
|
||||||
|
return ptr_ != other.ptr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char* ptr_ = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Creates a CharString that contains the given string.
|
||||||
|
explicit CharString2(const std::string& s) : s_(s) {}
|
||||||
|
|
||||||
|
// Returns an iterator pointing to the first character in the string.
|
||||||
|
const_iterator begin() const { return const_iterator(s_.c_str()); }
|
||||||
|
|
||||||
|
// Returns an iterator pointing past the last character in the string.
|
||||||
|
const_iterator end() const { return const_iterator(s_.c_str() + s_.size()); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string s_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tests using ElementsAre() with a container whose iterator returns a
|
||||||
|
// temporary and is not copy-assignable.
|
||||||
|
TEST(ElementsAreTest, WorksWithContainerThatReturnsTempInUnassignableIterator) {
|
||||||
|
CharString2 s("abc");
|
||||||
|
EXPECT_THAT(s, ElementsAre('a', 'b', 'c'));
|
||||||
|
EXPECT_THAT(s, Not(ElementsAre('a', 'b', 'd')));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests using ElementsAreArray() with a container whose iterator returns a
|
||||||
|
// temporary and is not copy-assignable.
|
||||||
|
TEST(ElementsAreArrayTest,
|
||||||
|
WorksWithContainerThatReturnsTempInUnassignableIterator) {
|
||||||
|
CharString2 s("abc");
|
||||||
|
EXPECT_THAT(s, ElementsAreArray({'a', 'b', 'c'}));
|
||||||
|
EXPECT_THAT(s, Not(ElementsAreArray({'a', 'b', 'd'})));
|
||||||
|
}
|
||||||
|
|
||||||
|
// A container whose iterator returns a temporary and is neither
|
||||||
|
// copy-constructible nor copy-assignable.
|
||||||
|
class CharString3 {
|
||||||
|
public:
|
||||||
|
using value_type = char;
|
||||||
|
|
||||||
|
class const_iterator {
|
||||||
|
public:
|
||||||
|
using iterator_category = std::input_iterator_tag;
|
||||||
|
using value_type = char;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using pointer = const char*;
|
||||||
|
using reference = const char&;
|
||||||
|
|
||||||
|
// Make const_iterator neither copy-constructible nor copy-assignable.
|
||||||
|
const_iterator(const const_iterator&) = delete;
|
||||||
|
const_iterator& operator=(const const_iterator&) = delete;
|
||||||
|
|
||||||
|
// Create an iterator that points to the given character.
|
||||||
|
explicit const_iterator(const char* ptr) : ptr_(ptr) {}
|
||||||
|
|
||||||
|
// Returns the current character. IMPORTANT: this must return a temporary,
|
||||||
|
// not a reference, to test that ElementsAre() works with containers whose
|
||||||
|
// iterators return temporaries.
|
||||||
|
char operator*() const { return *ptr_; }
|
||||||
|
|
||||||
|
// Advances to the next character.
|
||||||
|
const_iterator& operator++() {
|
||||||
|
++ptr_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compares two iterators.
|
||||||
|
bool operator==(const const_iterator& other) const {
|
||||||
|
return ptr_ == other.ptr_;
|
||||||
|
}
|
||||||
|
bool operator!=(const const_iterator& other) const {
|
||||||
|
return ptr_ != other.ptr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char* ptr_ = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Creates a CharString that contains the given string.
|
||||||
|
explicit CharString3(const std::string& s) : s_(s) {}
|
||||||
|
|
||||||
|
// Returns an iterator pointing to the first character in the string.
|
||||||
|
const_iterator begin() const { return const_iterator(s_.c_str()); }
|
||||||
|
|
||||||
|
// Returns an iterator pointing past the last character in the string.
|
||||||
|
const_iterator end() const { return const_iterator(s_.c_str() + s_.size()); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string s_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tests using ElementsAre() with a container whose iterator returns a
|
||||||
|
// temporary and is neither copy-constructible nor copy-assignable.
|
||||||
|
TEST(ElementsAreTest, WorksWithContainerThatReturnsTempInUncopyableIterator) {
|
||||||
|
CharString3 s("abc");
|
||||||
|
EXPECT_THAT(s, ElementsAre('a', 'b', 'c'));
|
||||||
|
EXPECT_THAT(s, Not(ElementsAre('a', 'b', 'd')));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests using ElementsAreArray() with a container whose iterator returns a
|
||||||
|
// temporary and is neither copy-constructible nor copy-assignable.
|
||||||
|
TEST(ElementsAreArrayTest,
|
||||||
|
WorksWithContainerThatReturnsTempInUncopyableIterator) {
|
||||||
|
CharString3 s("abc");
|
||||||
|
EXPECT_THAT(s, ElementsAreArray({'a', 'b', 'c'}));
|
||||||
|
EXPECT_THAT(s, Not(ElementsAreArray({'a', 'b', 'd'})));
|
||||||
|
}
|
||||||
|
|
||||||
|
// A container whose iterator returns a temporary, is neither
|
||||||
|
// copy-constructible nor copy-assignable, and has no member types.
|
||||||
|
class CharString4 {
|
||||||
|
public:
|
||||||
|
using value_type = char;
|
||||||
|
|
||||||
|
class const_iterator {
|
||||||
|
public:
|
||||||
|
// Do not define difference_type, etc.
|
||||||
|
|
||||||
|
// Make const_iterator neither copy-constructible nor copy-assignable.
|
||||||
|
const_iterator(const const_iterator&) = delete;
|
||||||
|
const_iterator& operator=(const const_iterator&) = delete;
|
||||||
|
|
||||||
|
// Create an iterator that points to the given character.
|
||||||
|
explicit const_iterator(const char* ptr) : ptr_(ptr) {}
|
||||||
|
|
||||||
|
// Returns the current character. IMPORTANT: this must return a temporary,
|
||||||
|
// not a reference, to test that ElementsAre() works with containers whose
|
||||||
|
// iterators return temporaries.
|
||||||
|
char operator*() const { return *ptr_; }
|
||||||
|
|
||||||
|
// Advances to the next character.
|
||||||
|
const_iterator& operator++() {
|
||||||
|
++ptr_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compares two iterators.
|
||||||
|
bool operator==(const const_iterator& other) const {
|
||||||
|
return ptr_ == other.ptr_;
|
||||||
|
}
|
||||||
|
bool operator!=(const const_iterator& other) const {
|
||||||
|
return ptr_ != other.ptr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char* ptr_ = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Creates a CharString that contains the given string.
|
||||||
|
explicit CharString4(const std::string& s) : s_(s) {}
|
||||||
|
|
||||||
|
// Returns an iterator pointing to the first character in the string.
|
||||||
|
const_iterator begin() const { return const_iterator(s_.c_str()); }
|
||||||
|
|
||||||
|
// Returns an iterator pointing past the last character in the string.
|
||||||
|
const_iterator end() const { return const_iterator(s_.c_str() + s_.size()); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string s_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tests using ElementsAre() with a container whose iterator returns a
|
||||||
|
// temporary, is neither copy-constructible nor copy-assignable, and has no
|
||||||
|
// member types.
|
||||||
|
TEST(ElementsAreTest, WorksWithContainerWithIteratorWithNoMemberTypes) {
|
||||||
|
CharString4 s("abc");
|
||||||
|
EXPECT_THAT(s, ElementsAre('a', 'b', 'c'));
|
||||||
|
EXPECT_THAT(s, Not(ElementsAre('a', 'b', 'd')));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests using ElementsAreArray() with a container whose iterator returns a
|
||||||
|
// temporary, is neither copy-constructible nor copy-assignable, and has no
|
||||||
|
// member types.
|
||||||
|
TEST(ElementsAreArrayTest, WorksWithContainerWithIteratorWithNoMemberTypes) {
|
||||||
|
CharString4 s("abc");
|
||||||
|
EXPECT_THAT(s, ElementsAreArray({'a', 'b', 'c'}));
|
||||||
|
EXPECT_THAT(s, Not(ElementsAreArray({'a', 'b', 'd'})));
|
||||||
|
}
|
||||||
|
|
||||||
// Tests using ElementsAre() and ElementsAreArray() with stream-like
|
// Tests using ElementsAre() and ElementsAreArray() with stream-like
|
||||||
// "containers".
|
// "containers".
|
||||||
|
|
||||||
@ -2155,7 +2446,7 @@ TEST_P(EachTestP, ExplainsMatchResultCorrectly) {
|
|||||||
Matcher<set<int>> m = Each(2);
|
Matcher<set<int>> m = Each(2);
|
||||||
EXPECT_EQ("", Explain(m, a));
|
EXPECT_EQ("", Explain(m, a));
|
||||||
|
|
||||||
Matcher<const int(&)[1]> n = Each(1); // NOLINT
|
Matcher<const int (&)[1]> n = Each(1); // NOLINT
|
||||||
|
|
||||||
const int b[1] = {1};
|
const int b[1] = {1};
|
||||||
EXPECT_EQ("", Explain(n, b));
|
EXPECT_EQ("", Explain(n, b));
|
||||||
@ -2290,7 +2581,7 @@ TEST(PointwiseTest, MakesCopyOfRhs) {
|
|||||||
rhs.push_back(4);
|
rhs.push_back(4);
|
||||||
|
|
||||||
int lhs[] = {1, 2};
|
int lhs[] = {1, 2};
|
||||||
const Matcher<const int(&)[2]> m = Pointwise(IsHalfOf(), rhs);
|
const Matcher<const int (&)[2]> m = Pointwise(IsHalfOf(), rhs);
|
||||||
EXPECT_THAT(lhs, m);
|
EXPECT_THAT(lhs, m);
|
||||||
|
|
||||||
// Changing rhs now shouldn't affect m, which made a copy of rhs.
|
// Changing rhs now shouldn't affect m, which made a copy of rhs.
|
||||||
@ -2418,7 +2709,7 @@ TEST(UnorderedPointwiseTest, MakesCopyOfRhs) {
|
|||||||
rhs.push_back(4);
|
rhs.push_back(4);
|
||||||
|
|
||||||
int lhs[] = {2, 1};
|
int lhs[] = {2, 1};
|
||||||
const Matcher<const int(&)[2]> m = UnorderedPointwise(IsHalfOf(), rhs);
|
const Matcher<const int (&)[2]> m = UnorderedPointwise(IsHalfOf(), rhs);
|
||||||
EXPECT_THAT(lhs, m);
|
EXPECT_THAT(lhs, m);
|
||||||
|
|
||||||
// Changing rhs now shouldn't affect m, which made a copy of rhs.
|
// Changing rhs now shouldn't affect m, which made a copy of rhs.
|
||||||
@ -2505,7 +2796,7 @@ TEST(UnorderedPointwiseTest, WorksWithMoveOnly) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(PointeeTest, WorksOnMoveOnlyType) {
|
TEST(PointeeTest, WorksOnMoveOnlyType) {
|
||||||
std::unique_ptr<int> p(new int(3));
|
std::unique_ptr<int> p = std::make_unique<int>(3);
|
||||||
EXPECT_THAT(p, Pointee(Eq(3)));
|
EXPECT_THAT(p, Pointee(Eq(3)));
|
||||||
EXPECT_THAT(p, Not(Pointee(Eq(2))));
|
EXPECT_THAT(p, Not(Pointee(Eq(2))));
|
||||||
}
|
}
|
||||||
@ -2669,11 +2960,11 @@ TEST_P(ElementsAreTestP, CanExplainMismatchRightSize) {
|
|||||||
vector<int> v;
|
vector<int> v;
|
||||||
v.push_back(2);
|
v.push_back(2);
|
||||||
v.push_back(1);
|
v.push_back(1);
|
||||||
EXPECT_EQ("whose element #0 doesn't match", Explain(m, v));
|
EXPECT_EQ(Explain(m, v), "whose element #0 (2) isn't equal to 1");
|
||||||
|
|
||||||
v[0] = 1;
|
v[0] = 1;
|
||||||
EXPECT_EQ("whose element #1 doesn't match, which is 4 less than 5",
|
EXPECT_EQ(Explain(m, v),
|
||||||
Explain(m, v));
|
"whose element #1 (1) is <= 5, which is 4 less than 5");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ElementsAreTest, MatchesOneElementVector) {
|
TEST(ElementsAreTest, MatchesOneElementVector) {
|
||||||
@ -3073,7 +3364,7 @@ TEST(ContainsTest, SetDoesNotMatchWhenElementIsNotInContainer) {
|
|||||||
|
|
||||||
TEST_P(ContainsTestP, ExplainsMatchResultCorrectly) {
|
TEST_P(ContainsTestP, ExplainsMatchResultCorrectly) {
|
||||||
const int a[2] = {1, 2};
|
const int a[2] = {1, 2};
|
||||||
Matcher<const int(&)[2]> m = Contains(2);
|
Matcher<const int (&)[2]> m = Contains(2);
|
||||||
EXPECT_EQ("whose element #1 matches", Explain(m, a));
|
EXPECT_EQ("whose element #1 matches", Explain(m, a));
|
||||||
|
|
||||||
m = Contains(3);
|
m = Contains(3);
|
||||||
|
|||||||
@ -79,7 +79,7 @@ TEST(AddressTest, Const) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(AddressTest, MatcherDoesntCopy) {
|
TEST(AddressTest, MatcherDoesntCopy) {
|
||||||
std::unique_ptr<int> n(new int(1));
|
std::unique_ptr<int> n = std::make_unique<int>(1);
|
||||||
const Matcher<std::unique_ptr<int>> m = Address(Eq(&n));
|
const Matcher<std::unique_ptr<int>> m = Address(Eq(&n));
|
||||||
|
|
||||||
EXPECT_TRUE(m.Matches(n));
|
EXPECT_TRUE(m.Matches(n));
|
||||||
@ -202,7 +202,7 @@ TEST(IsTrueTest, IsTrueIsFalse) {
|
|||||||
EXPECT_THAT(nullptr, Not(IsTrue()));
|
EXPECT_THAT(nullptr, Not(IsTrue()));
|
||||||
EXPECT_THAT(nullptr, IsFalse());
|
EXPECT_THAT(nullptr, IsFalse());
|
||||||
std::unique_ptr<int> null_unique;
|
std::unique_ptr<int> null_unique;
|
||||||
std::unique_ptr<int> nonnull_unique(new int(0));
|
std::unique_ptr<int> nonnull_unique = std::make_unique<int>(0);
|
||||||
EXPECT_THAT(null_unique, Not(IsTrue()));
|
EXPECT_THAT(null_unique, Not(IsTrue()));
|
||||||
EXPECT_THAT(null_unique, IsFalse());
|
EXPECT_THAT(null_unique, IsFalse());
|
||||||
EXPECT_THAT(nonnull_unique, IsTrue());
|
EXPECT_THAT(nonnull_unique, IsTrue());
|
||||||
@ -1665,7 +1665,7 @@ MATCHER(IsNotNull, "") { return arg != nullptr; }
|
|||||||
// Verifies that a matcher defined using MATCHER() can work on
|
// Verifies that a matcher defined using MATCHER() can work on
|
||||||
// move-only types.
|
// move-only types.
|
||||||
TEST(MatcherMacroTest, WorksOnMoveOnlyType) {
|
TEST(MatcherMacroTest, WorksOnMoveOnlyType) {
|
||||||
std::unique_ptr<int> p(new int(3));
|
std::unique_ptr<int> p = std::make_unique<int>(3);
|
||||||
EXPECT_THAT(p, IsNotNull());
|
EXPECT_THAT(p, IsNotNull());
|
||||||
EXPECT_THAT(std::unique_ptr<int>(), Not(IsNotNull()));
|
EXPECT_THAT(std::unique_ptr<int>(), Not(IsNotNull()));
|
||||||
}
|
}
|
||||||
@ -1675,7 +1675,7 @@ MATCHER_P(UniquePointee, pointee, "") { return *arg == pointee; }
|
|||||||
// Verifies that a matcher defined using MATCHER_P*() can work on
|
// Verifies that a matcher defined using MATCHER_P*() can work on
|
||||||
// move-only types.
|
// move-only types.
|
||||||
TEST(MatcherPMacroTest, WorksOnMoveOnlyType) {
|
TEST(MatcherPMacroTest, WorksOnMoveOnlyType) {
|
||||||
std::unique_ptr<int> p(new int(3));
|
std::unique_ptr<int> p = std::make_unique<int>(3);
|
||||||
EXPECT_THAT(p, UniquePointee(3));
|
EXPECT_THAT(p, UniquePointee(3));
|
||||||
EXPECT_THAT(p, Not(UniquePointee(2)));
|
EXPECT_THAT(p, Not(UniquePointee(2)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
@ -201,45 +202,45 @@ class Foo {
|
|||||||
|
|
||||||
// Tests using Invoke() with a nullary function.
|
// Tests using Invoke() with a nullary function.
|
||||||
TEST(InvokeTest, Nullary) {
|
TEST(InvokeTest, Nullary) {
|
||||||
Action<int()> a = Invoke(Nullary); // NOLINT
|
Action<int()> a = &Nullary;
|
||||||
EXPECT_EQ(1, a.Perform(std::make_tuple()));
|
EXPECT_EQ(1, a.Perform(std::make_tuple()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests using Invoke() with a unary function.
|
// Tests using Invoke() with a unary function.
|
||||||
TEST(InvokeTest, Unary) {
|
TEST(InvokeTest, Unary) {
|
||||||
Action<bool(int)> a = Invoke(Unary); // NOLINT
|
Action<bool(int)> a = &Unary;
|
||||||
EXPECT_FALSE(a.Perform(std::make_tuple(1)));
|
EXPECT_FALSE(a.Perform(std::make_tuple(1)));
|
||||||
EXPECT_TRUE(a.Perform(std::make_tuple(-1)));
|
EXPECT_TRUE(a.Perform(std::make_tuple(-1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests using Invoke() with a binary function.
|
// Tests using Invoke() with a binary function.
|
||||||
TEST(InvokeTest, Binary) {
|
TEST(InvokeTest, Binary) {
|
||||||
Action<const char*(const char*, short)> a = Invoke(Binary); // NOLINT
|
Action<const char*(const char*, short)> a = &Binary; // NOLINT
|
||||||
const char* p = "Hello";
|
const char* p = "Hello";
|
||||||
EXPECT_EQ(p + 2, a.Perform(std::make_tuple(p, Short(2))));
|
EXPECT_EQ(p + 2, a.Perform(std::make_tuple(p, Short(2))));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests using Invoke() with a ternary function.
|
// Tests using Invoke() with a ternary function.
|
||||||
TEST(InvokeTest, Ternary) {
|
TEST(InvokeTest, Ternary) {
|
||||||
Action<int(int, char, short)> a = Invoke(Ternary); // NOLINT
|
Action<int(int, char, short)> a = &Ternary; // NOLINT
|
||||||
EXPECT_EQ(6, a.Perform(std::make_tuple(1, '\2', Short(3))));
|
EXPECT_EQ(6, a.Perform(std::make_tuple(1, '\2', Short(3))));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests using Invoke() with a 4-argument function.
|
// Tests using Invoke() with a 4-argument function.
|
||||||
TEST(InvokeTest, FunctionThatTakes4Arguments) {
|
TEST(InvokeTest, FunctionThatTakes4Arguments) {
|
||||||
Action<int(int, int, int, int)> a = Invoke(SumOf4); // NOLINT
|
Action<int(int, int, int, int)> a = &SumOf4;
|
||||||
EXPECT_EQ(1234, a.Perform(std::make_tuple(1000, 200, 30, 4)));
|
EXPECT_EQ(1234, a.Perform(std::make_tuple(1000, 200, 30, 4)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests using Invoke() with a 5-argument function.
|
// Tests using Invoke() with a 5-argument function.
|
||||||
TEST(InvokeTest, FunctionThatTakes5Arguments) {
|
TEST(InvokeTest, FunctionThatTakes5Arguments) {
|
||||||
Action<int(int, int, int, int, int)> a = Invoke(SumOf5); // NOLINT
|
Action<int(int, int, int, int, int)> a = &SumOf5;
|
||||||
EXPECT_EQ(12345, a.Perform(std::make_tuple(10000, 2000, 300, 40, 5)));
|
EXPECT_EQ(12345, a.Perform(std::make_tuple(10000, 2000, 300, 40, 5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests using Invoke() with a 6-argument function.
|
// Tests using Invoke() with a 6-argument function.
|
||||||
TEST(InvokeTest, FunctionThatTakes6Arguments) {
|
TEST(InvokeTest, FunctionThatTakes6Arguments) {
|
||||||
Action<int(int, int, int, int, int, int)> a = Invoke(SumOf6); // NOLINT
|
Action<int(int, int, int, int, int, int)> a = &SumOf6;
|
||||||
EXPECT_EQ(123456,
|
EXPECT_EQ(123456,
|
||||||
a.Perform(std::make_tuple(100000, 20000, 3000, 400, 50, 6)));
|
a.Perform(std::make_tuple(100000, 20000, 3000, 400, 50, 6)));
|
||||||
}
|
}
|
||||||
@ -252,7 +253,7 @@ inline const char* CharPtr(const char* s) { return s; }
|
|||||||
TEST(InvokeTest, FunctionThatTakes7Arguments) {
|
TEST(InvokeTest, FunctionThatTakes7Arguments) {
|
||||||
Action<std::string(const char*, const char*, const char*, const char*,
|
Action<std::string(const char*, const char*, const char*, const char*,
|
||||||
const char*, const char*, const char*)>
|
const char*, const char*, const char*)>
|
||||||
a = Invoke(Concat7);
|
a = &Concat7;
|
||||||
EXPECT_EQ("1234567",
|
EXPECT_EQ("1234567",
|
||||||
a.Perform(std::make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
a.Perform(std::make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
||||||
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
||||||
@ -263,7 +264,7 @@ TEST(InvokeTest, FunctionThatTakes7Arguments) {
|
|||||||
TEST(InvokeTest, FunctionThatTakes8Arguments) {
|
TEST(InvokeTest, FunctionThatTakes8Arguments) {
|
||||||
Action<std::string(const char*, const char*, const char*, const char*,
|
Action<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*)>
|
||||||
a = Invoke(Concat8);
|
a = &Concat8;
|
||||||
EXPECT_EQ("12345678",
|
EXPECT_EQ("12345678",
|
||||||
a.Perform(std::make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
a.Perform(std::make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
||||||
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
||||||
@ -275,7 +276,7 @@ TEST(InvokeTest, FunctionThatTakes9Arguments) {
|
|||||||
Action<std::string(const char*, const char*, const char*, const char*,
|
Action<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*)>
|
||||||
a = Invoke(Concat9);
|
a = &Concat9;
|
||||||
EXPECT_EQ("123456789", a.Perform(std::make_tuple(
|
EXPECT_EQ("123456789", a.Perform(std::make_tuple(
|
||||||
CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
||||||
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
||||||
@ -287,7 +288,7 @@ TEST(InvokeTest, FunctionThatTakes10Arguments) {
|
|||||||
Action<std::string(const char*, const char*, const char*, const char*,
|
Action<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*)>
|
||||||
a = Invoke(Concat10);
|
a = &Concat10;
|
||||||
EXPECT_EQ("1234567890",
|
EXPECT_EQ("1234567890",
|
||||||
a.Perform(std::make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
a.Perform(std::make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
||||||
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
||||||
@ -297,12 +298,12 @@ TEST(InvokeTest, FunctionThatTakes10Arguments) {
|
|||||||
|
|
||||||
// Tests using Invoke() with functions with parameters declared as Unused.
|
// Tests using Invoke() with functions with parameters declared as Unused.
|
||||||
TEST(InvokeTest, FunctionWithUnusedParameters) {
|
TEST(InvokeTest, FunctionWithUnusedParameters) {
|
||||||
Action<int(int, int, double, const std::string&)> a1 = Invoke(SumOfFirst2);
|
Action<int(int, int, double, const std::string&)> a1 = &SumOfFirst2;
|
||||||
std::tuple<int, int, double, std::string> dummy =
|
std::tuple<int, int, double, std::string> dummy =
|
||||||
std::make_tuple(10, 2, 5.6, std::string("hi"));
|
std::make_tuple(10, 2, 5.6, std::string("hi"));
|
||||||
EXPECT_EQ(12, a1.Perform(dummy));
|
EXPECT_EQ(12, a1.Perform(dummy));
|
||||||
|
|
||||||
Action<int(int, int, bool, int*)> a2 = Invoke(SumOfFirst2);
|
Action<int(int, int, bool, int*)> a2 = &SumOfFirst2;
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
23, a2.Perform(std::make_tuple(20, 3, true, static_cast<int*>(nullptr))));
|
23, a2.Perform(std::make_tuple(20, 3, true, static_cast<int*>(nullptr))));
|
||||||
}
|
}
|
||||||
@ -319,13 +320,13 @@ TEST(InvokeTest, MethodWithUnusedParameters) {
|
|||||||
|
|
||||||
// Tests using Invoke() with a functor.
|
// Tests using Invoke() with a functor.
|
||||||
TEST(InvokeTest, Functor) {
|
TEST(InvokeTest, Functor) {
|
||||||
Action<long(long, int)> a = Invoke(plus<long>()); // NOLINT
|
Action<long(long, int)> a = plus<long>(); // NOLINT
|
||||||
EXPECT_EQ(3L, a.Perform(std::make_tuple(1, 2)));
|
EXPECT_EQ(3L, a.Perform(std::make_tuple(1, 2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests using Invoke(f) as an action of a compatible type.
|
// Tests using Invoke(f) as an action of a compatible type.
|
||||||
TEST(InvokeTest, FunctionWithCompatibleType) {
|
TEST(InvokeTest, FunctionWithCompatibleType) {
|
||||||
Action<long(int, short, char, bool)> a = Invoke(SumOf4); // NOLINT
|
Action<long(int, short, char, bool)> a = &SumOf4; // NOLINT
|
||||||
EXPECT_EQ(4321, a.Perform(std::make_tuple(4000, Short(300), Char(20), true)));
|
EXPECT_EQ(4321, a.Perform(std::make_tuple(4000, Short(300), Char(20), true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,13 +447,13 @@ TEST(InvokeMethodTest, MethodWithCompatibleType) {
|
|||||||
|
|
||||||
// Tests using WithoutArgs with an action that takes no argument.
|
// Tests using WithoutArgs with an action that takes no argument.
|
||||||
TEST(WithoutArgsTest, NoArg) {
|
TEST(WithoutArgsTest, NoArg) {
|
||||||
Action<int(int n)> a = WithoutArgs(Invoke(Nullary)); // NOLINT
|
Action<int(int n)> a = WithoutArgs(&Nullary); // NOLINT
|
||||||
EXPECT_EQ(1, a.Perform(std::make_tuple(2)));
|
EXPECT_EQ(1, a.Perform(std::make_tuple(2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests using WithArg with an action that takes 1 argument.
|
// Tests using WithArg with an action that takes 1 argument.
|
||||||
TEST(WithArgTest, OneArg) {
|
TEST(WithArgTest, OneArg) {
|
||||||
Action<bool(double x, int n)> b = WithArg<1>(Invoke(Unary)); // NOLINT
|
Action<bool(double x, int n)> b = WithArg<1>(&Unary); // NOLINT
|
||||||
EXPECT_TRUE(b.Perform(std::make_tuple(1.5, -1)));
|
EXPECT_TRUE(b.Perform(std::make_tuple(1.5, -1)));
|
||||||
EXPECT_FALSE(b.Perform(std::make_tuple(1.5, 1)));
|
EXPECT_FALSE(b.Perform(std::make_tuple(1.5, 1)));
|
||||||
}
|
}
|
||||||
@ -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,7 +785,7 @@ 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");
|
||||||
@ -765,7 +794,7 @@ TEST(InvokeArgumentTest, Function7) {
|
|||||||
|
|
||||||
// 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");
|
||||||
@ -774,7 +803,7 @@ TEST(InvokeArgumentTest, Function8) {
|
|||||||
|
|
||||||
// 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");
|
||||||
@ -783,7 +812,7 @@ TEST(InvokeArgumentTest, Function9) {
|
|||||||
|
|
||||||
// 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");
|
||||||
|
|||||||
@ -160,7 +160,7 @@ class MockCC : public CC {
|
|||||||
// Tests that a method with expanded name compiles.
|
// Tests that a method with expanded name compiles.
|
||||||
TEST(OnCallSyntaxTest, CompilesWithMethodNameExpandedFromMacro) {
|
TEST(OnCallSyntaxTest, CompilesWithMethodNameExpandedFromMacro) {
|
||||||
MockCC cc;
|
MockCC cc;
|
||||||
ON_CALL(cc, Method());
|
(void)ON_CALL(cc, Method());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that the method with expanded name not only compiles but runs
|
// Tests that the method with expanded name not only compiles but runs
|
||||||
@ -193,7 +193,7 @@ TEST(OnCallSyntaxTest, EvaluatesFirstArgumentOnce) {
|
|||||||
MockA a;
|
MockA a;
|
||||||
MockA* pa = &a;
|
MockA* pa = &a;
|
||||||
|
|
||||||
ON_CALL(*pa++, DoA(_));
|
(void)ON_CALL(*pa++, DoA(_));
|
||||||
EXPECT_EQ(&a + 1, pa);
|
EXPECT_EQ(&a + 1, pa);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,7 +201,7 @@ TEST(OnCallSyntaxTest, EvaluatesSecondArgumentOnce) {
|
|||||||
MockA a;
|
MockA a;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
ON_CALL(a, DoA(n++));
|
(void)ON_CALL(a, DoA(n++));
|
||||||
EXPECT_EQ(1, n);
|
EXPECT_EQ(1, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +232,7 @@ TEST(OnCallSyntaxTest, WillByDefaultIsMandatory) {
|
|||||||
|
|
||||||
EXPECT_DEATH_IF_SUPPORTED(
|
EXPECT_DEATH_IF_SUPPORTED(
|
||||||
{
|
{
|
||||||
ON_CALL(a, DoA(5));
|
(void)ON_CALL(a, DoA(5));
|
||||||
a.DoA(5);
|
a.DoA(5);
|
||||||
},
|
},
|
||||||
"");
|
"");
|
||||||
@ -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.
|
||||||
@ -2046,7 +2045,7 @@ class GMockVerboseFlagTest : public VerboseFlagPreservingFixture {
|
|||||||
NaggyMock<MockA> a;
|
NaggyMock<MockA> a;
|
||||||
const std::string note =
|
const std::string note =
|
||||||
"NOTE: You can safely ignore the above warning unless this "
|
"NOTE: You can safely ignore the above warning unless this "
|
||||||
"call should not happen. Do not suppress it by blindly adding "
|
"call should not happen. Do not suppress it by adding "
|
||||||
"an EXPECT_CALL() if you don't mean to enforce the call. "
|
"an EXPECT_CALL() if you don't mean to enforce the call. "
|
||||||
"See "
|
"See "
|
||||||
"https://github.com/google/googletest/blob/main/docs/"
|
"https://github.com/google/googletest/blob/main/docs/"
|
||||||
|
|||||||
@ -79,14 +79,14 @@ GMOCK WARNING:
|
|||||||
Uninteresting mock function call - returning default value.
|
Uninteresting mock function call - returning default value.
|
||||||
Function call: Bar2(0, 1)
|
Function call: Bar2(0, 1)
|
||||||
Returns: false
|
Returns: false
|
||||||
NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call. See https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md#knowing-when-to-expect-useoncall for details.
|
NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by adding an EXPECT_CALL() if you don't mean to enforce the call. See https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md#knowing-when-to-expect-useoncall for details.
|
||||||
[ OK ] GMockOutputTest.UninterestingCall
|
[ OK ] GMockOutputTest.UninterestingCall
|
||||||
[ RUN ] GMockOutputTest.UninterestingCallToVoidFunction
|
[ RUN ] GMockOutputTest.UninterestingCallToVoidFunction
|
||||||
|
|
||||||
GMOCK WARNING:
|
GMOCK WARNING:
|
||||||
Uninteresting mock function call - returning directly.
|
Uninteresting mock function call - returning directly.
|
||||||
Function call: Bar3(0, 1)
|
Function call: Bar3(0, 1)
|
||||||
NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call. See https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md#knowing-when-to-expect-useoncall for details.
|
NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by adding an EXPECT_CALL() if you don't mean to enforce the call. See https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md#knowing-when-to-expect-useoncall for details.
|
||||||
[ OK ] GMockOutputTest.UninterestingCallToVoidFunction
|
[ OK ] GMockOutputTest.UninterestingCallToVoidFunction
|
||||||
[ RUN ] GMockOutputTest.RetiredExpectation
|
[ RUN ] GMockOutputTest.RetiredExpectation
|
||||||
unknown file: Failure
|
unknown file: Failure
|
||||||
@ -283,14 +283,14 @@ Uninteresting mock function call - taking default action specified at:
|
|||||||
FILE:#:
|
FILE:#:
|
||||||
Function call: Bar2(2, 2)
|
Function call: Bar2(2, 2)
|
||||||
Returns: true
|
Returns: true
|
||||||
NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call. See https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md#knowing-when-to-expect-useoncall for details.
|
NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by adding an EXPECT_CALL() if you don't mean to enforce the call. See https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md#knowing-when-to-expect-useoncall for details.
|
||||||
|
|
||||||
GMOCK WARNING:
|
GMOCK WARNING:
|
||||||
Uninteresting mock function call - taking default action specified at:
|
Uninteresting mock function call - taking default action specified at:
|
||||||
FILE:#:
|
FILE:#:
|
||||||
Function call: Bar2(1, 1)
|
Function call: Bar2(1, 1)
|
||||||
Returns: false
|
Returns: false
|
||||||
NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call. See https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md#knowing-when-to-expect-useoncall for details.
|
NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by adding an EXPECT_CALL() if you don't mean to enforce the call. See https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md#knowing-when-to-expect-useoncall for details.
|
||||||
[ OK ] GMockOutputTest.UninterestingCallWithDefaultAction
|
[ OK ] GMockOutputTest.UninterestingCallWithDefaultAction
|
||||||
[ RUN ] GMockOutputTest.ExplicitActionsRunOutWithDefaultAction
|
[ RUN ] GMockOutputTest.ExplicitActionsRunOutWithDefaultAction
|
||||||
|
|
||||||
|
|||||||
@ -132,9 +132,6 @@ if(GTEST_HAS_ABSL)
|
|||||||
absl::flags_reflection
|
absl::flags_reflection
|
||||||
absl::flags_usage
|
absl::flags_usage
|
||||||
absl::strings
|
absl::strings
|
||||||
absl::any
|
|
||||||
absl::optional
|
|
||||||
absl::variant
|
|
||||||
re2::re2
|
re2::re2
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@ -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.15.2
|
git clone https://github.com/google/googletest.git -b v1.17.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
|
||||||
@ -124,9 +124,9 @@ match the project in which it is included.
|
|||||||
|
|
||||||
#### C++ Standard Version
|
#### C++ Standard Version
|
||||||
|
|
||||||
An environment that supports C++14 is required in order to successfully build
|
An environment that supports C++17 is required in order to successfully build
|
||||||
GoogleTest. One way to ensure this is to specify the standard in the top-level
|
GoogleTest. One way to ensure this is to specify the standard in the top-level
|
||||||
project, for example by using the `set(CMAKE_CXX_STANDARD 14)` command along
|
project, for example by using the `set(CMAKE_CXX_STANDARD 17)` command along
|
||||||
with `set(CMAKE_CXX_STANDARD_REQUIRED ON)`. If this is not feasible, for example
|
with `set(CMAKE_CXX_STANDARD_REQUIRED ON)`. If this is not feasible, for example
|
||||||
in a C project using GoogleTest for validation, then it can be specified by
|
in a C project using GoogleTest for validation, then it can be specified by
|
||||||
adding it to the options for cmake via the`-DCMAKE_CXX_FLAGS` option.
|
adding it to the options for cmake via the`-DCMAKE_CXX_FLAGS` option.
|
||||||
@ -145,9 +145,9 @@ We list the most frequently used macros below. For a complete list, see file
|
|||||||
### Multi-threaded Tests
|
### Multi-threaded Tests
|
||||||
|
|
||||||
GoogleTest is thread-safe where the pthread library is available. After
|
GoogleTest is thread-safe where the pthread library is available. After
|
||||||
`#include <gtest/gtest.h>`, you can check the
|
`#include <gtest/gtest.h>`, you can check the `GTEST_IS_THREADSAFE` macro to see
|
||||||
`GTEST_IS_THREADSAFE` macro to see whether this is the case (yes if the macro is
|
whether this is the case (yes if the macro is `#defined` to 1, no if it's
|
||||||
`#defined` to 1, no if it's undefined.).
|
undefined.).
|
||||||
|
|
||||||
If GoogleTest doesn't correctly detect whether pthread is available in your
|
If GoogleTest doesn't correctly detect whether pthread is available in your
|
||||||
environment, you can force it with
|
environment, you can force it with
|
||||||
|
|||||||
@ -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()
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|||||||
@ -129,6 +129,13 @@ namespace testing {
|
|||||||
//
|
//
|
||||||
// Expected: Foo() is even
|
// Expected: Foo() is even
|
||||||
// Actual: it's 5
|
// Actual: it's 5
|
||||||
|
//
|
||||||
|
|
||||||
|
// Returned AssertionResult objects may not be ignored.
|
||||||
|
// Note: Disabled for SWIG as it doesn't parse attributes correctly.
|
||||||
|
#if !defined(SWIG)
|
||||||
|
class [[nodiscard]] AssertionResult;
|
||||||
|
#endif // !SWIG
|
||||||
|
|
||||||
class GTEST_API_ AssertionResult {
|
class GTEST_API_ AssertionResult {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@ -296,12 +296,12 @@ class MatcherBase : private MatcherDescriberInterface {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
MatcherBase(MatcherBase&& other)
|
MatcherBase(MatcherBase&& other) noexcept
|
||||||
: vtable_(other.vtable_), buffer_(other.buffer_) {
|
: vtable_(other.vtable_), buffer_(other.buffer_) {
|
||||||
other.vtable_ = nullptr;
|
other.vtable_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
MatcherBase& operator=(MatcherBase&& other) {
|
MatcherBase& operator=(MatcherBase&& other) noexcept {
|
||||||
if (this == &other) return *this;
|
if (this == &other) return *this;
|
||||||
Destroy();
|
Destroy();
|
||||||
vtable_ = other.vtable_;
|
vtable_ = other.vtable_;
|
||||||
@ -773,6 +773,35 @@ class GeMatcher
|
|||||||
static const char* NegatedDesc() { return "isn't >="; }
|
static const char* NegatedDesc() { return "isn't >="; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Same as `EqMatcher<Rhs>`, except that the `rhs` is stored as `StoredRhs` and
|
||||||
|
// must be implicitly convertible to `Rhs`.
|
||||||
|
template <typename Rhs, typename StoredRhs>
|
||||||
|
class ImplicitCastEqMatcher {
|
||||||
|
public:
|
||||||
|
explicit ImplicitCastEqMatcher(const StoredRhs& rhs) : stored_rhs_(rhs) {}
|
||||||
|
|
||||||
|
using is_gtest_matcher = void;
|
||||||
|
|
||||||
|
template <typename Lhs>
|
||||||
|
bool MatchAndExplain(const Lhs& lhs, std::ostream*) const {
|
||||||
|
return lhs == rhs();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescribeTo(std::ostream* os) const {
|
||||||
|
*os << "is equal to ";
|
||||||
|
UniversalPrint(rhs(), os);
|
||||||
|
}
|
||||||
|
void DescribeNegationTo(std::ostream* os) const {
|
||||||
|
*os << "isn't equal to ";
|
||||||
|
UniversalPrint(rhs(), os);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Rhs rhs() const { return ImplicitCast_<Rhs>(stored_rhs_); }
|
||||||
|
|
||||||
|
StoredRhs stored_rhs_;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T, typename = typename std::enable_if<
|
template <typename T, typename = typename std::enable_if<
|
||||||
std::is_constructible<std::string, T>::value>::type>
|
std::is_constructible<std::string, T>::value>::type>
|
||||||
using StringLike = T;
|
using StringLike = T;
|
||||||
|
|||||||
@ -174,6 +174,7 @@ TEST_P(DerivedTest, DoesBlah) {
|
|||||||
|
|
||||||
#endif // 0
|
#endif // 0
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@ -413,7 +414,8 @@ internal::CartesianProductHolder<Generator...> Combine(const Generator&... g) {
|
|||||||
// Synopsis:
|
// Synopsis:
|
||||||
// ConvertGenerator<T>(gen)
|
// ConvertGenerator<T>(gen)
|
||||||
// - returns a generator producing the same elements as generated by gen, but
|
// - returns a generator producing the same elements as generated by gen, but
|
||||||
// each element is static_cast to type T before being returned
|
// each T-typed element is static_cast to a type deduced from the interface
|
||||||
|
// that accepts this generator, and then returned
|
||||||
//
|
//
|
||||||
// It is useful when using the Combine() function to get the generated
|
// It is useful when using the Combine() function to get the generated
|
||||||
// parameters in a custom type instead of std::tuple
|
// parameters in a custom type instead of std::tuple
|
||||||
@ -441,10 +443,65 @@ internal::CartesianProductHolder<Generator...> Combine(const Generator&... g) {
|
|||||||
// Combine(Values("cat", "dog"),
|
// Combine(Values("cat", "dog"),
|
||||||
// Values(BLACK, WHITE))));
|
// Values(BLACK, WHITE))));
|
||||||
//
|
//
|
||||||
template <typename T>
|
template <typename RequestedT>
|
||||||
internal::ParamConverterGenerator<T> ConvertGenerator(
|
internal::ParamConverterGenerator<RequestedT> ConvertGenerator(
|
||||||
internal::ParamGenerator<T> gen) {
|
internal::ParamGenerator<RequestedT> gen) {
|
||||||
return internal::ParamConverterGenerator<T>(gen);
|
return internal::ParamConverterGenerator<RequestedT>(std::move(gen));
|
||||||
|
}
|
||||||
|
|
||||||
|
// As above, but takes a callable as a second argument. The callable converts
|
||||||
|
// the generated parameter to the test fixture's parameter type. This allows you
|
||||||
|
// to use a parameter type that does not have a converting constructor from the
|
||||||
|
// generated type.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// This will instantiate tests in test suite AnimalTest each one with
|
||||||
|
// the parameter values tuple("cat", BLACK), tuple("cat", WHITE),
|
||||||
|
// tuple("dog", BLACK), and tuple("dog", WHITE):
|
||||||
|
//
|
||||||
|
// enum Color { BLACK, GRAY, WHITE };
|
||||||
|
// struct ParamType {
|
||||||
|
// std::string animal;
|
||||||
|
// Color color;
|
||||||
|
// };
|
||||||
|
// class AnimalTest
|
||||||
|
// : public testing::TestWithParam<ParamType> {...};
|
||||||
|
//
|
||||||
|
// TEST_P(AnimalTest, AnimalLooksNice) {...}
|
||||||
|
//
|
||||||
|
// INSTANTIATE_TEST_SUITE_P(
|
||||||
|
// AnimalVariations, AnimalTest,
|
||||||
|
// ConvertGenerator(Combine(Values("cat", "dog"), Values(BLACK, WHITE)),
|
||||||
|
// [](std::tuple<std::string, Color> t) {
|
||||||
|
// return ParamType{.animal = std::get<0>(t),
|
||||||
|
// .color = std::get<1>(t)};
|
||||||
|
// }));
|
||||||
|
//
|
||||||
|
template <typename T, int&... ExplicitArgumentBarrier, typename Gen,
|
||||||
|
typename Func,
|
||||||
|
typename StdFunction = decltype(std::function(std::declval<Func>()))>
|
||||||
|
internal::ParamConverterGenerator<T, StdFunction> ConvertGenerator(Gen&& gen,
|
||||||
|
Func&& f) {
|
||||||
|
return internal::ParamConverterGenerator<T, StdFunction>(
|
||||||
|
std::forward<Gen>(gen), std::forward<Func>(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
// As above, but infers the T from the supplied std::function instead of
|
||||||
|
// having the caller specify it.
|
||||||
|
template <int&... ExplicitArgumentBarrier, typename Gen, typename Func,
|
||||||
|
typename StdFunction = decltype(std::function(std::declval<Func>()))>
|
||||||
|
auto ConvertGenerator(Gen&& gen, Func&& f) {
|
||||||
|
constexpr bool is_single_arg_std_function =
|
||||||
|
internal::IsSingleArgStdFunction<StdFunction>::value;
|
||||||
|
if constexpr (is_single_arg_std_function) {
|
||||||
|
return ConvertGenerator<
|
||||||
|
typename internal::FuncSingleParamType<StdFunction>::type>(
|
||||||
|
std::forward<Gen>(gen), std::forward<Func>(f));
|
||||||
|
} else {
|
||||||
|
static_assert(is_single_arg_std_function,
|
||||||
|
"The call signature must contain a single argument.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TEST_P(test_suite_name, test_name) \
|
#define TEST_P(test_suite_name, test_name) \
|
||||||
@ -469,7 +526,7 @@ internal::ParamConverterGenerator<T> ConvertGenerator(
|
|||||||
::testing::internal::CodeLocation(__FILE__, __LINE__)); \
|
::testing::internal::CodeLocation(__FILE__, __LINE__)); \
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static int gtest_registering_dummy_; \
|
[[maybe_unused]] static int gtest_registering_dummy_; \
|
||||||
}; \
|
}; \
|
||||||
int GTEST_TEST_CLASS_NAME_(test_suite_name, \
|
int GTEST_TEST_CLASS_NAME_(test_suite_name, \
|
||||||
test_name)::gtest_registering_dummy_ = \
|
test_name)::gtest_registering_dummy_ = \
|
||||||
@ -514,8 +571,7 @@ internal::ParamConverterGenerator<T> ConvertGenerator(
|
|||||||
::testing::internal::DefaultParamName<test_suite_name::ParamType>, \
|
::testing::internal::DefaultParamName<test_suite_name::ParamType>, \
|
||||||
DUMMY_PARAM_))))(info); \
|
DUMMY_PARAM_))))(info); \
|
||||||
} \
|
} \
|
||||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static int \
|
[[maybe_unused]] static int gtest_##prefix##test_suite_name##_dummy_ = \
|
||||||
gtest_##prefix##test_suite_name##_dummy_ = \
|
|
||||||
::testing::UnitTest::GetInstance() \
|
::testing::UnitTest::GetInstance() \
|
||||||
->parameterized_test_registry() \
|
->parameterized_test_registry() \
|
||||||
.GetTestSuitePatternHolder<test_suite_name>( \
|
.GetTestSuitePatternHolder<test_suite_name>( \
|
||||||
@ -524,8 +580,8 @@ internal::ParamConverterGenerator<T> ConvertGenerator(
|
|||||||
->AddTestSuiteInstantiation( \
|
->AddTestSuiteInstantiation( \
|
||||||
GTEST_STRINGIFY_(prefix), \
|
GTEST_STRINGIFY_(prefix), \
|
||||||
>est_##prefix##test_suite_name##_EvalGenerator_, \
|
>est_##prefix##test_suite_name##_EvalGenerator_, \
|
||||||
>est_##prefix##test_suite_name##_EvalGenerateName_, \
|
>est_##prefix##test_suite_name##_EvalGenerateName_, __FILE__, \
|
||||||
__FILE__, __LINE__)
|
__LINE__)
|
||||||
|
|
||||||
// Allow Marking a Parameterized test class as not needing to be instantiated.
|
// Allow Marking a Parameterized test class as not needing to be instantiated.
|
||||||
#define GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(T) \
|
#define GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(T) \
|
||||||
|
|||||||
@ -104,15 +104,19 @@
|
|||||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
|
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
|
||||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
|
#define GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
|
||||||
|
|
||||||
|
#include <any>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <ostream> // NOLINT
|
#include <ostream> // NOLINT
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#ifdef GTEST_HAS_ABSL
|
#ifdef GTEST_HAS_ABSL
|
||||||
@ -245,8 +249,8 @@ struct StreamPrinter {
|
|||||||
// ADL (possibly involving implicit conversions).
|
// ADL (possibly involving implicit conversions).
|
||||||
// (Use SFINAE via return type, because it seems GCC < 12 doesn't handle name
|
// (Use SFINAE via return type, because it seems GCC < 12 doesn't handle name
|
||||||
// lookup properly when we do it in the template parameter list.)
|
// lookup properly when we do it in the template parameter list.)
|
||||||
static auto PrintValue(const T& value,
|
static auto PrintValue(const T& value, ::std::ostream* os)
|
||||||
::std::ostream* os) -> decltype((void)(*os << value)) {
|
-> decltype((void)(*os << value)) {
|
||||||
// Call streaming operator found by ADL, possibly with implicit conversions
|
// Call streaming operator found by ADL, possibly with implicit conversions
|
||||||
// of the arguments.
|
// of the arguments.
|
||||||
*os << value;
|
*os << value;
|
||||||
@ -521,11 +525,15 @@ GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os);
|
|||||||
|
|
||||||
GTEST_API_ void PrintTo(char32_t c, ::std::ostream* os);
|
GTEST_API_ void PrintTo(char32_t c, ::std::ostream* os);
|
||||||
inline void PrintTo(char16_t c, ::std::ostream* os) {
|
inline void PrintTo(char16_t c, ::std::ostream* os) {
|
||||||
PrintTo(ImplicitCast_<char32_t>(c), os);
|
// TODO(b/418738869): Incorrect for values not representing valid codepoints.
|
||||||
|
// Also see https://github.com/google/googletest/issues/4762.
|
||||||
|
PrintTo(static_cast<char32_t>(c), os);
|
||||||
}
|
}
|
||||||
#ifdef __cpp_lib_char8_t
|
#ifdef __cpp_lib_char8_t
|
||||||
inline void PrintTo(char8_t c, ::std::ostream* os) {
|
inline void PrintTo(char8_t c, ::std::ostream* os) {
|
||||||
PrintTo(ImplicitCast_<char32_t>(c), os);
|
// TODO(b/418738869): Incorrect for values not representing valid codepoints.
|
||||||
|
// Also see https://github.com/google/googletest/issues/4762.
|
||||||
|
PrintTo(static_cast<char32_t>(c), os);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -695,44 +703,63 @@ void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overloads for ::std::string.
|
// Overloads for ::std::string and ::std::string_view
|
||||||
GTEST_API_ void PrintStringTo(const ::std::string& s, ::std::ostream* os);
|
GTEST_API_ void PrintStringTo(::std::string_view s, ::std::ostream* os);
|
||||||
inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
|
inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
|
||||||
PrintStringTo(s, os);
|
PrintStringTo(s, os);
|
||||||
}
|
}
|
||||||
|
inline void PrintTo(::std::string_view s, ::std::ostream* os) {
|
||||||
|
PrintStringTo(s, os);
|
||||||
|
}
|
||||||
|
|
||||||
// Overloads for ::std::u8string
|
// Overloads for ::std::u8string and ::std::u8string_view
|
||||||
#ifdef __cpp_lib_char8_t
|
#ifdef __cpp_lib_char8_t
|
||||||
GTEST_API_ void PrintU8StringTo(const ::std::u8string& s, ::std::ostream* os);
|
GTEST_API_ void PrintU8StringTo(::std::u8string_view s, ::std::ostream* os);
|
||||||
inline void PrintTo(const ::std::u8string& s, ::std::ostream* os) {
|
inline void PrintTo(const ::std::u8string& s, ::std::ostream* os) {
|
||||||
PrintU8StringTo(s, os);
|
PrintU8StringTo(s, os);
|
||||||
}
|
}
|
||||||
|
inline void PrintTo(::std::u8string_view s, ::std::ostream* os) {
|
||||||
|
PrintU8StringTo(s, os);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Overloads for ::std::u16string
|
// Overloads for ::std::u16string and ::std::u16string_view
|
||||||
GTEST_API_ void PrintU16StringTo(const ::std::u16string& s, ::std::ostream* os);
|
GTEST_API_ void PrintU16StringTo(::std::u16string_view s, ::std::ostream* os);
|
||||||
inline void PrintTo(const ::std::u16string& s, ::std::ostream* os) {
|
inline void PrintTo(const ::std::u16string& s, ::std::ostream* os) {
|
||||||
PrintU16StringTo(s, os);
|
PrintU16StringTo(s, os);
|
||||||
}
|
}
|
||||||
|
inline void PrintTo(::std::u16string_view s, ::std::ostream* os) {
|
||||||
|
PrintU16StringTo(s, os);
|
||||||
|
}
|
||||||
|
|
||||||
// Overloads for ::std::u32string
|
// Overloads for ::std::u32string and ::std::u32string_view
|
||||||
GTEST_API_ void PrintU32StringTo(const ::std::u32string& s, ::std::ostream* os);
|
GTEST_API_ void PrintU32StringTo(::std::u32string_view s, ::std::ostream* os);
|
||||||
inline void PrintTo(const ::std::u32string& s, ::std::ostream* os) {
|
inline void PrintTo(const ::std::u32string& s, ::std::ostream* os) {
|
||||||
PrintU32StringTo(s, os);
|
PrintU32StringTo(s, os);
|
||||||
}
|
}
|
||||||
|
inline void PrintTo(::std::u32string_view s, ::std::ostream* os) {
|
||||||
|
PrintU32StringTo(s, os);
|
||||||
|
}
|
||||||
|
|
||||||
// Overloads for ::std::wstring.
|
// Overloads for ::std::wstring and ::std::wstring_view
|
||||||
#if GTEST_HAS_STD_WSTRING
|
#if GTEST_HAS_STD_WSTRING
|
||||||
GTEST_API_ void PrintWideStringTo(const ::std::wstring& s, ::std::ostream* os);
|
GTEST_API_ void PrintWideStringTo(::std::wstring_view s, ::std::ostream* os);
|
||||||
inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
|
inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
|
||||||
PrintWideStringTo(s, os);
|
PrintWideStringTo(s, os);
|
||||||
}
|
}
|
||||||
|
inline void PrintTo(::std::wstring_view s, ::std::ostream* os) {
|
||||||
|
PrintWideStringTo(s, os);
|
||||||
|
}
|
||||||
#endif // GTEST_HAS_STD_WSTRING
|
#endif // GTEST_HAS_STD_WSTRING
|
||||||
|
|
||||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||||
// Overload for internal::StringView.
|
// Overload for internal::StringView. Needed for build configurations where
|
||||||
|
// internal::StringView is an alias for absl::string_view, but absl::string_view
|
||||||
|
// is a distinct type from std::string_view.
|
||||||
|
template <int&... ExplicitArgumentBarrier, typename T = internal::StringView,
|
||||||
|
std::enable_if_t<!std::is_same_v<T, ::std::string_view>, int> = 0>
|
||||||
inline void PrintTo(internal::StringView sp, ::std::ostream* os) {
|
inline void PrintTo(internal::StringView sp, ::std::ostream* os) {
|
||||||
PrintTo(::std::string(sp), os);
|
PrintStringTo(sp, os);
|
||||||
}
|
}
|
||||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||||
|
|
||||||
@ -890,14 +917,11 @@ class UniversalPrinter {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
class UniversalPrinter<const T> : public UniversalPrinter<T> {};
|
class UniversalPrinter<const T> : public UniversalPrinter<T> {};
|
||||||
|
|
||||||
#if GTEST_INTERNAL_HAS_ANY
|
// Printer for std::any
|
||||||
|
|
||||||
// Printer for std::any / absl::any
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
class UniversalPrinter<Any> {
|
class UniversalPrinter<std::any> {
|
||||||
public:
|
public:
|
||||||
static void Print(const Any& value, ::std::ostream* os) {
|
static void Print(const std::any& value, ::std::ostream* os) {
|
||||||
if (value.has_value()) {
|
if (value.has_value()) {
|
||||||
*os << "value of type " << GetTypeName(value);
|
*os << "value of type " << GetTypeName(value);
|
||||||
} else {
|
} else {
|
||||||
@ -906,7 +930,7 @@ class UniversalPrinter<Any> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::string GetTypeName(const Any& value) {
|
static std::string GetTypeName(const std::any& value) {
|
||||||
#if GTEST_HAS_RTTI
|
#if GTEST_HAS_RTTI
|
||||||
return internal::GetTypeName(value.type());
|
return internal::GetTypeName(value.type());
|
||||||
#else
|
#else
|
||||||
@ -916,16 +940,11 @@ class UniversalPrinter<Any> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GTEST_INTERNAL_HAS_ANY
|
// Printer for std::optional
|
||||||
|
|
||||||
#if GTEST_INTERNAL_HAS_OPTIONAL
|
|
||||||
|
|
||||||
// Printer for std::optional / absl::optional
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class UniversalPrinter<Optional<T>> {
|
class UniversalPrinter<std::optional<T>> {
|
||||||
public:
|
public:
|
||||||
static void Print(const Optional<T>& value, ::std::ostream* os) {
|
static void Print(const std::optional<T>& value, ::std::ostream* os) {
|
||||||
*os << '(';
|
*os << '(';
|
||||||
if (!value) {
|
if (!value) {
|
||||||
*os << "nullopt";
|
*os << "nullopt";
|
||||||
@ -937,29 +956,18 @@ class UniversalPrinter<Optional<T>> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
class UniversalPrinter<decltype(Nullopt())> {
|
class UniversalPrinter<std::nullopt_t> {
|
||||||
public:
|
public:
|
||||||
static void Print(decltype(Nullopt()), ::std::ostream* os) {
|
static void Print(std::nullopt_t, ::std::ostream* os) { *os << "(nullopt)"; }
|
||||||
*os << "(nullopt)";
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GTEST_INTERNAL_HAS_OPTIONAL
|
// Printer for std::variant
|
||||||
|
|
||||||
#if GTEST_INTERNAL_HAS_VARIANT
|
|
||||||
|
|
||||||
// Printer for std::variant / absl::variant
|
|
||||||
|
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
class UniversalPrinter<Variant<T...>> {
|
class UniversalPrinter<std::variant<T...>> {
|
||||||
public:
|
public:
|
||||||
static void Print(const Variant<T...>& value, ::std::ostream* os) {
|
static void Print(const std::variant<T...>& value, ::std::ostream* os) {
|
||||||
*os << '(';
|
*os << '(';
|
||||||
#ifdef GTEST_HAS_ABSL
|
|
||||||
absl::visit(Visitor{os, value.index()}, value);
|
|
||||||
#else
|
|
||||||
std::visit(Visitor{os, value.index()}, value);
|
std::visit(Visitor{os, value.index()}, value);
|
||||||
#endif // GTEST_HAS_ABSL
|
|
||||||
*os << ')';
|
*os << ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -976,8 +984,6 @@ class UniversalPrinter<Variant<T...>> {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GTEST_INTERNAL_HAS_VARIANT
|
|
||||||
|
|
||||||
// UniversalPrintArray(begin, len, os) prints an array of 'len'
|
// UniversalPrintArray(begin, len, os) prints an array of 'len'
|
||||||
// elements, starting at address 'begin'.
|
// elements, starting at address 'begin'.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|||||||
@ -48,15 +48,15 @@ template <typename T>
|
|||||||
class FooTest : public testing::Test {
|
class FooTest : public testing::Test {
|
||||||
public:
|
public:
|
||||||
...
|
...
|
||||||
typedef std::list<T> List;
|
using List = ::std::list<T>;
|
||||||
static T shared_;
|
static T shared_;
|
||||||
T value_;
|
T value_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Next, associate a list of types with the test suite, which will be
|
// Next, associate a list of types with the test suite, which will be
|
||||||
// repeated for each type in the list. The typedef is necessary for
|
// repeated for each type in the list. The using-declaration is necessary for
|
||||||
// the macro to parse correctly.
|
// the macro to parse correctly.
|
||||||
typedef testing::Types<char, int, unsigned int> MyTypes;
|
using MyTypes = ::testing::Types<char, int, unsigned int>;
|
||||||
TYPED_TEST_SUITE(FooTest, MyTypes);
|
TYPED_TEST_SUITE(FooTest, MyTypes);
|
||||||
|
|
||||||
// If the type list contains only one type, you can write that type
|
// If the type list contains only one type, you can write that type
|
||||||
@ -157,7 +157,7 @@ REGISTER_TYPED_TEST_SUITE_P(FooTest,
|
|||||||
// argument to the INSTANTIATE_* macro is a prefix that will be added
|
// argument to the INSTANTIATE_* macro is a prefix that will be added
|
||||||
// to the actual test suite name. Remember to pick unique prefixes for
|
// to the actual test suite name. Remember to pick unique prefixes for
|
||||||
// different instances.
|
// different instances.
|
||||||
typedef testing::Types<char, int, unsigned int> MyTypes;
|
using MyTypes = ::testing::Types<char, int, unsigned int>;
|
||||||
INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
|
INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
|
||||||
|
|
||||||
// If the type list contains only one type, you can write that type
|
// If the type list contains only one type, you can write that type
|
||||||
@ -205,12 +205,11 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
|
|||||||
typedef gtest_TypeParam_ TypeParam; \
|
typedef gtest_TypeParam_ TypeParam; \
|
||||||
void TestBody() override; \
|
void TestBody() override; \
|
||||||
}; \
|
}; \
|
||||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool \
|
[[maybe_unused]] static bool gtest_##CaseName##_##TestName##_registered_ = \
|
||||||
gtest_##CaseName##_##TestName##_registered_ = \
|
|
||||||
::testing::internal::TypeParameterizedTest< \
|
::testing::internal::TypeParameterizedTest< \
|
||||||
CaseName, \
|
CaseName, \
|
||||||
::testing::internal::TemplateSel<GTEST_TEST_CLASS_NAME_( \
|
::testing::internal::TemplateSel<GTEST_TEST_CLASS_NAME_(CaseName, \
|
||||||
CaseName, TestName)>, \
|
TestName)>, \
|
||||||
GTEST_TYPE_PARAMS_( \
|
GTEST_TYPE_PARAMS_( \
|
||||||
CaseName)>::Register("", \
|
CaseName)>::Register("", \
|
||||||
::testing::internal::CodeLocation( \
|
::testing::internal::CodeLocation( \
|
||||||
@ -277,8 +276,7 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
|
|||||||
typedef gtest_TypeParam_ TypeParam; \
|
typedef gtest_TypeParam_ TypeParam; \
|
||||||
void TestBody() override; \
|
void TestBody() override; \
|
||||||
}; \
|
}; \
|
||||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool \
|
[[maybe_unused]] static bool gtest_##TestName##_defined_ = \
|
||||||
gtest_##TestName##_defined_ = \
|
|
||||||
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).AddTestName( \
|
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).AddTestName( \
|
||||||
__FILE__, __LINE__, GTEST_STRINGIFY_(SuiteName), \
|
__FILE__, __LINE__, GTEST_STRINGIFY_(SuiteName), \
|
||||||
GTEST_STRINGIFY_(TestName)); \
|
GTEST_STRINGIFY_(TestName)); \
|
||||||
@ -292,8 +290,8 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
|
|||||||
namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \
|
namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \
|
||||||
typedef ::testing::internal::Templates<__VA_ARGS__> gtest_AllTests_; \
|
typedef ::testing::internal::Templates<__VA_ARGS__> gtest_AllTests_; \
|
||||||
} \
|
} \
|
||||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static const char* const \
|
[[maybe_unused]] static const char* const GTEST_REGISTERED_TEST_NAMES_( \
|
||||||
GTEST_REGISTERED_TEST_NAMES_(SuiteName) = \
|
SuiteName) = \
|
||||||
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).VerifyRegisteredTestNames( \
|
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).VerifyRegisteredTestNames( \
|
||||||
GTEST_STRINGIFY_(SuiteName), __FILE__, __LINE__, #__VA_ARGS__)
|
GTEST_STRINGIFY_(SuiteName), __FILE__, __LINE__, #__VA_ARGS__)
|
||||||
|
|
||||||
@ -308,13 +306,11 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
|
|||||||
#define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...) \
|
#define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...) \
|
||||||
static_assert(sizeof(GTEST_STRINGIFY_(Prefix)) > 1, \
|
static_assert(sizeof(GTEST_STRINGIFY_(Prefix)) > 1, \
|
||||||
"test-suit-prefix must not be empty"); \
|
"test-suit-prefix must not be empty"); \
|
||||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool \
|
[[maybe_unused]] static bool gtest_##Prefix##_##SuiteName = \
|
||||||
gtest_##Prefix##_##SuiteName = \
|
|
||||||
::testing::internal::TypeParameterizedTestSuite< \
|
::testing::internal::TypeParameterizedTestSuite< \
|
||||||
SuiteName, GTEST_SUITE_NAMESPACE_(SuiteName)::gtest_AllTests_, \
|
SuiteName, GTEST_SUITE_NAMESPACE_(SuiteName)::gtest_AllTests_, \
|
||||||
::testing::internal::GenerateTypeList<Types>::type>:: \
|
::testing::internal::GenerateTypeList<Types>::type>:: \
|
||||||
Register( \
|
Register(GTEST_STRINGIFY_(Prefix), \
|
||||||
GTEST_STRINGIFY_(Prefix), \
|
|
||||||
::testing::internal::CodeLocation(__FILE__, __LINE__), \
|
::testing::internal::CodeLocation(__FILE__, __LINE__), \
|
||||||
>EST_TYPED_TEST_SUITE_P_STATE_(SuiteName), \
|
>EST_TYPED_TEST_SUITE_P_STATE_(SuiteName), \
|
||||||
GTEST_STRINGIFY_(SuiteName), \
|
GTEST_STRINGIFY_(SuiteName), \
|
||||||
|
|||||||
@ -1123,7 +1123,7 @@ class GTEST_API_ UnitTest {
|
|||||||
// This method can only be called from the main thread.
|
// This method can only be called from the main thread.
|
||||||
//
|
//
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||||
int Run() GTEST_MUST_USE_RESULT_;
|
[[nodiscard]] int Run();
|
||||||
|
|
||||||
// Returns the working directory when the first TEST() or TEST_F()
|
// Returns the working directory when the first TEST() or TEST_F()
|
||||||
// was executed. The UnitTest object owns the string.
|
// was executed. The UnitTest object owns the string.
|
||||||
@ -1610,6 +1610,8 @@ GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1,
|
|||||||
double val1, double val2,
|
double val1, double val2,
|
||||||
double abs_error);
|
double abs_error);
|
||||||
|
|
||||||
|
using GoogleTest_NotSupported_OnFunctionReturningNonVoid = void;
|
||||||
|
|
||||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||||
// A class that enables one to stream messages to assertion macros
|
// A class that enables one to stream messages to assertion macros
|
||||||
class GTEST_API_ AssertHelper {
|
class GTEST_API_ AssertHelper {
|
||||||
@ -1621,7 +1623,8 @@ class GTEST_API_ AssertHelper {
|
|||||||
|
|
||||||
// Message assignment is a semantic trick to enable assertion
|
// Message assignment is a semantic trick to enable assertion
|
||||||
// streaming; see the GTEST_MESSAGE_ macro below.
|
// streaming; see the GTEST_MESSAGE_ macro below.
|
||||||
void operator=(const Message& message) const;
|
GoogleTest_NotSupported_OnFunctionReturningNonVoid operator=(
|
||||||
|
const Message& message) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// We put our data in a struct so that the size of the AssertHelper class can
|
// We put our data in a struct so that the size of the AssertHelper class can
|
||||||
@ -1693,7 +1696,7 @@ class WithParamInterface {
|
|||||||
|
|
||||||
// The current parameter value. Is also available in the test fixture's
|
// The current parameter value. Is also available in the test fixture's
|
||||||
// constructor.
|
// constructor.
|
||||||
static const ParamType& GetParam() {
|
[[nodiscard]] static const ParamType& GetParam() {
|
||||||
GTEST_CHECK_(parameter_ != nullptr)
|
GTEST_CHECK_(parameter_ != nullptr)
|
||||||
<< "GetParam() can only be called inside a value-parameterized test "
|
<< "GetParam() can only be called inside a value-parameterized test "
|
||||||
<< "-- did you intend to write TEST_P instead of TEST_F?";
|
<< "-- did you intend to write TEST_P instead of TEST_F?";
|
||||||
@ -2329,7 +2332,7 @@ TestInfo* RegisterTest(const char* test_suite_name, const char* test_name,
|
|||||||
//
|
//
|
||||||
// This function was formerly a macro; thus, it is in the global
|
// This function was formerly a macro; thus, it is in the global
|
||||||
// namespace and has an all-caps name.
|
// namespace and has an all-caps name.
|
||||||
int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_;
|
[[nodiscard]] int RUN_ALL_TESTS();
|
||||||
|
|
||||||
inline int RUN_ALL_TESTS() { return ::testing::UnitTest::GetInstance()->Run(); }
|
inline int RUN_ALL_TESTS() { return ::testing::UnitTest::GetInstance()->Run(); }
|
||||||
|
|
||||||
|
|||||||
@ -290,17 +290,17 @@ class FloatingPoint {
|
|||||||
// around may change its bits, although the new value is guaranteed
|
// around may change its bits, although the new value is guaranteed
|
||||||
// to be also a NAN. Therefore, don't expect this constructor to
|
// to be also a NAN. Therefore, don't expect this constructor to
|
||||||
// preserve the bits in x when x is a NAN.
|
// preserve the bits in x when x is a NAN.
|
||||||
explicit FloatingPoint(const RawType& x) { u_.value_ = x; }
|
explicit FloatingPoint(RawType x) { memcpy(&bits_, &x, sizeof(x)); }
|
||||||
|
|
||||||
// Static methods
|
// Static methods
|
||||||
|
|
||||||
// Reinterprets a bit pattern as a floating-point number.
|
// Reinterprets a bit pattern as a floating-point number.
|
||||||
//
|
//
|
||||||
// This function is needed to test the AlmostEquals() method.
|
// This function is needed to test the AlmostEquals() method.
|
||||||
static RawType ReinterpretBits(const Bits bits) {
|
static RawType ReinterpretBits(Bits bits) {
|
||||||
FloatingPoint fp(0);
|
RawType fp;
|
||||||
fp.u_.bits_ = bits;
|
memcpy(&fp, &bits, sizeof(fp));
|
||||||
return fp.u_.value_;
|
return fp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the floating-point number that represent positive infinity.
|
// Returns the floating-point number that represent positive infinity.
|
||||||
@ -309,16 +309,16 @@ class FloatingPoint {
|
|||||||
// Non-static methods
|
// Non-static methods
|
||||||
|
|
||||||
// Returns the bits that represents this number.
|
// Returns the bits that represents this number.
|
||||||
const Bits& bits() const { return u_.bits_; }
|
const Bits& bits() const { return bits_; }
|
||||||
|
|
||||||
// Returns the exponent bits of this number.
|
// Returns the exponent bits of this number.
|
||||||
Bits exponent_bits() const { return kExponentBitMask & u_.bits_; }
|
Bits exponent_bits() const { return kExponentBitMask & bits_; }
|
||||||
|
|
||||||
// Returns the fraction bits of this number.
|
// Returns the fraction bits of this number.
|
||||||
Bits fraction_bits() const { return kFractionBitMask & u_.bits_; }
|
Bits fraction_bits() const { return kFractionBitMask & bits_; }
|
||||||
|
|
||||||
// Returns the sign bit of this number.
|
// Returns the sign bit of this number.
|
||||||
Bits sign_bit() const { return kSignBitMask & u_.bits_; }
|
Bits sign_bit() const { return kSignBitMask & bits_; }
|
||||||
|
|
||||||
// Returns true if and only if this is NAN (not a number).
|
// Returns true if and only if this is NAN (not a number).
|
||||||
bool is_nan() const {
|
bool is_nan() const {
|
||||||
@ -332,23 +332,16 @@ class FloatingPoint {
|
|||||||
//
|
//
|
||||||
// - returns false if either number is (or both are) NAN.
|
// - returns false if either number is (or both are) NAN.
|
||||||
// - treats really large numbers as almost equal to infinity.
|
// - treats really large numbers as almost equal to infinity.
|
||||||
// - thinks +0.0 and -0.0 are 0 DLP's apart.
|
// - thinks +0.0 and -0.0 are 0 ULP's apart.
|
||||||
bool AlmostEquals(const FloatingPoint& rhs) const {
|
bool AlmostEquals(const FloatingPoint& rhs) const {
|
||||||
// The IEEE standard says that any comparison operation involving
|
// The IEEE standard says that any comparison operation involving
|
||||||
// a NAN must return false.
|
// a NAN must return false.
|
||||||
if (is_nan() || rhs.is_nan()) return false;
|
if (is_nan() || rhs.is_nan()) return false;
|
||||||
|
|
||||||
return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_) <=
|
return DistanceBetweenSignAndMagnitudeNumbers(bits_, rhs.bits_) <= kMaxUlps;
|
||||||
kMaxUlps;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The data type used to store the actual floating-point number.
|
|
||||||
union FloatingPointUnion {
|
|
||||||
RawType value_; // The raw floating-point number.
|
|
||||||
Bits bits_; // The bits that represent the number.
|
|
||||||
};
|
|
||||||
|
|
||||||
// Converts an integer from the sign-and-magnitude representation to
|
// Converts an integer from the sign-and-magnitude representation to
|
||||||
// the biased representation. More precisely, let N be 2 to the
|
// the biased representation. More precisely, let N be 2 to the
|
||||||
// power of (kBitCount - 1), an integer x is represented by the
|
// power of (kBitCount - 1), an integer x is represented by the
|
||||||
@ -364,7 +357,7 @@ class FloatingPoint {
|
|||||||
//
|
//
|
||||||
// Read https://en.wikipedia.org/wiki/Signed_number_representations
|
// Read https://en.wikipedia.org/wiki/Signed_number_representations
|
||||||
// for more details on signed number representations.
|
// for more details on signed number representations.
|
||||||
static Bits SignAndMagnitudeToBiased(const Bits& sam) {
|
static Bits SignAndMagnitudeToBiased(Bits sam) {
|
||||||
if (kSignBitMask & sam) {
|
if (kSignBitMask & sam) {
|
||||||
// sam represents a negative number.
|
// sam represents a negative number.
|
||||||
return ~sam + 1;
|
return ~sam + 1;
|
||||||
@ -376,14 +369,13 @@ class FloatingPoint {
|
|||||||
|
|
||||||
// Given two numbers in the sign-and-magnitude representation,
|
// Given two numbers in the sign-and-magnitude representation,
|
||||||
// returns the distance between them as an unsigned number.
|
// returns the distance between them as an unsigned number.
|
||||||
static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits& sam1,
|
static Bits DistanceBetweenSignAndMagnitudeNumbers(Bits sam1, Bits sam2) {
|
||||||
const Bits& sam2) {
|
|
||||||
const Bits biased1 = SignAndMagnitudeToBiased(sam1);
|
const Bits biased1 = SignAndMagnitudeToBiased(sam1);
|
||||||
const Bits biased2 = SignAndMagnitudeToBiased(sam2);
|
const Bits biased2 = SignAndMagnitudeToBiased(sam2);
|
||||||
return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
|
return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatingPointUnion u_;
|
Bits bits_; // The bits that represent the number.
|
||||||
};
|
};
|
||||||
|
|
||||||
// Typedefs the instances of the FloatingPoint template class that we
|
// Typedefs the instances of the FloatingPoint template class that we
|
||||||
@ -894,11 +886,6 @@ class HasDebugStringAndShortDebugString {
|
|||||||
HasDebugStringType::value && HasShortDebugStringType::value;
|
HasDebugStringType::value && HasShortDebugStringType::value;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef GTEST_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
|
|
||||||
template <typename T>
|
|
||||||
constexpr bool HasDebugStringAndShortDebugString<T>::value;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// When the compiler sees expression IsContainerTest<C>(0), if C is an
|
// When the compiler sees expression IsContainerTest<C>(0), if C is an
|
||||||
// STL-style container class, the first overload of IsContainerTest
|
// STL-style container class, the first overload of IsContainerTest
|
||||||
// will be viable (since both C::iterator* and C::const_iterator* are
|
// will be viable (since both C::iterator* and C::const_iterator* are
|
||||||
@ -1241,30 +1228,40 @@ class FlatTuple
|
|||||||
|
|
||||||
// Utility functions to be called with static_assert to induce deprecation
|
// Utility functions to be called with static_assert to induce deprecation
|
||||||
// warnings.
|
// warnings.
|
||||||
GTEST_INTERNAL_DEPRECATED(
|
[[deprecated(
|
||||||
"INSTANTIATE_TEST_CASE_P is deprecated, please use "
|
"INSTANTIATE_TEST_CASE_P is deprecated, please use "
|
||||||
"INSTANTIATE_TEST_SUITE_P")
|
"INSTANTIATE_TEST_SUITE_P")]]
|
||||||
constexpr bool InstantiateTestCase_P_IsDeprecated() { return true; }
|
constexpr bool InstantiateTestCase_P_IsDeprecated() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
GTEST_INTERNAL_DEPRECATED(
|
[[deprecated(
|
||||||
"TYPED_TEST_CASE_P is deprecated, please use "
|
"TYPED_TEST_CASE_P is deprecated, please use "
|
||||||
"TYPED_TEST_SUITE_P")
|
"TYPED_TEST_SUITE_P")]]
|
||||||
constexpr bool TypedTestCase_P_IsDeprecated() { return true; }
|
constexpr bool TypedTestCase_P_IsDeprecated() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
GTEST_INTERNAL_DEPRECATED(
|
[[deprecated(
|
||||||
"TYPED_TEST_CASE is deprecated, please use "
|
"TYPED_TEST_CASE is deprecated, please use "
|
||||||
"TYPED_TEST_SUITE")
|
"TYPED_TEST_SUITE")]]
|
||||||
constexpr bool TypedTestCaseIsDeprecated() { return true; }
|
constexpr bool TypedTestCaseIsDeprecated() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
GTEST_INTERNAL_DEPRECATED(
|
[[deprecated(
|
||||||
"REGISTER_TYPED_TEST_CASE_P is deprecated, please use "
|
"REGISTER_TYPED_TEST_CASE_P is deprecated, please use "
|
||||||
"REGISTER_TYPED_TEST_SUITE_P")
|
"REGISTER_TYPED_TEST_SUITE_P")]]
|
||||||
constexpr bool RegisterTypedTestCase_P_IsDeprecated() { return true; }
|
constexpr bool RegisterTypedTestCase_P_IsDeprecated() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
GTEST_INTERNAL_DEPRECATED(
|
[[deprecated(
|
||||||
"INSTANTIATE_TYPED_TEST_CASE_P is deprecated, please use "
|
"INSTANTIATE_TYPED_TEST_CASE_P is deprecated, please use "
|
||||||
"INSTANTIATE_TYPED_TEST_SUITE_P")
|
"INSTANTIATE_TYPED_TEST_SUITE_P")]]
|
||||||
constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; }
|
constexpr bool InstantiateTypedTestCase_P_IsDeprecated() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
@ -1501,8 +1498,7 @@ class NeverThrown {
|
|||||||
\
|
\
|
||||||
private: \
|
private: \
|
||||||
void TestBody() override; \
|
void TestBody() override; \
|
||||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static ::testing::TestInfo* const \
|
[[maybe_unused]] static ::testing::TestInfo* const test_info_; \
|
||||||
test_info_; \
|
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name, \
|
::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name, \
|
||||||
|
|||||||
@ -39,6 +39,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <functional>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -529,8 +530,7 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
|
|||||||
// prefix). test_base_name is the name of an individual test without
|
// prefix). test_base_name is the name of an individual test without
|
||||||
// parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
|
// parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
|
||||||
// test suite base name and DoBar is test base name.
|
// test suite base name and DoBar is test base name.
|
||||||
void AddTestPattern(const char*,
|
void AddTestPattern(const char*, const char* test_base_name,
|
||||||
const char* test_base_name,
|
|
||||||
TestMetaFactoryBase<ParamType>* meta_factory,
|
TestMetaFactoryBase<ParamType>* meta_factory,
|
||||||
CodeLocation code_location) {
|
CodeLocation code_location) {
|
||||||
tests_.emplace_back(
|
tests_.emplace_back(
|
||||||
@ -952,11 +952,11 @@ class CartesianProductHolder {
|
|||||||
std::tuple<Gen...> generators_;
|
std::tuple<Gen...> generators_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename From, typename To>
|
template <typename From, typename To, typename Func>
|
||||||
class ParamGeneratorConverter : public ParamGeneratorInterface<To> {
|
class ParamGeneratorConverter : public ParamGeneratorInterface<To> {
|
||||||
public:
|
public:
|
||||||
ParamGeneratorConverter(ParamGenerator<From> gen) // NOLINT
|
ParamGeneratorConverter(ParamGenerator<From> gen, Func converter) // NOLINT
|
||||||
: generator_(std::move(gen)) {}
|
: generator_(std::move(gen)), converter_(std::move(converter)) {}
|
||||||
|
|
||||||
ParamIteratorInterface<To>* Begin() const override {
|
ParamIteratorInterface<To>* Begin() const override {
|
||||||
return new Iterator(this, generator_.begin(), generator_.end());
|
return new Iterator(this, generator_.begin(), generator_.end());
|
||||||
@ -965,13 +965,21 @@ class ParamGeneratorConverter : public ParamGeneratorInterface<To> {
|
|||||||
return new Iterator(this, generator_.end(), generator_.end());
|
return new Iterator(this, generator_.end(), generator_.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the std::function wrapping the user-supplied converter callable. It
|
||||||
|
// is used by the iterator (see class Iterator below) to convert the object
|
||||||
|
// (of type FROM) returned by the ParamGenerator to an object of a type that
|
||||||
|
// can be static_cast to type TO.
|
||||||
|
const Func& TypeConverter() const { return converter_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Iterator : public ParamIteratorInterface<To> {
|
class Iterator : public ParamIteratorInterface<To> {
|
||||||
public:
|
public:
|
||||||
Iterator(const ParamGeneratorInterface<To>* base, ParamIterator<From> it,
|
Iterator(const ParamGeneratorConverter* base, ParamIterator<From> it,
|
||||||
ParamIterator<From> end)
|
ParamIterator<From> end)
|
||||||
: base_(base), it_(it), end_(end) {
|
: base_(base), it_(it), end_(end) {
|
||||||
if (it_ != end_) value_ = std::make_shared<To>(static_cast<To>(*it_));
|
if (it_ != end_)
|
||||||
|
value_ =
|
||||||
|
std::make_shared<To>(static_cast<To>(base->TypeConverter()(*it_)));
|
||||||
}
|
}
|
||||||
~Iterator() override = default;
|
~Iterator() override = default;
|
||||||
|
|
||||||
@ -980,7 +988,9 @@ class ParamGeneratorConverter : public ParamGeneratorInterface<To> {
|
|||||||
}
|
}
|
||||||
void Advance() override {
|
void Advance() override {
|
||||||
++it_;
|
++it_;
|
||||||
if (it_ != end_) value_ = std::make_shared<To>(static_cast<To>(*it_));
|
if (it_ != end_)
|
||||||
|
value_ =
|
||||||
|
std::make_shared<To>(static_cast<To>(base_->TypeConverter()(*it_)));
|
||||||
}
|
}
|
||||||
ParamIteratorInterface<To>* Clone() const override {
|
ParamIteratorInterface<To>* Clone() const override {
|
||||||
return new Iterator(*this);
|
return new Iterator(*this);
|
||||||
@ -1000,30 +1010,54 @@ class ParamGeneratorConverter : public ParamGeneratorInterface<To> {
|
|||||||
private:
|
private:
|
||||||
Iterator(const Iterator& other) = default;
|
Iterator(const Iterator& other) = default;
|
||||||
|
|
||||||
const ParamGeneratorInterface<To>* const base_;
|
const ParamGeneratorConverter* const base_;
|
||||||
ParamIterator<From> it_;
|
ParamIterator<From> it_;
|
||||||
ParamIterator<From> end_;
|
ParamIterator<From> end_;
|
||||||
std::shared_ptr<To> value_;
|
std::shared_ptr<To> value_;
|
||||||
}; // class ParamGeneratorConverter::Iterator
|
}; // class ParamGeneratorConverter::Iterator
|
||||||
|
|
||||||
ParamGenerator<From> generator_;
|
ParamGenerator<From> generator_;
|
||||||
|
Func converter_;
|
||||||
}; // class ParamGeneratorConverter
|
}; // class ParamGeneratorConverter
|
||||||
|
|
||||||
template <class Gen>
|
template <class GeneratedT,
|
||||||
|
typename StdFunction =
|
||||||
|
std::function<const GeneratedT&(const GeneratedT&)>>
|
||||||
class ParamConverterGenerator {
|
class ParamConverterGenerator {
|
||||||
public:
|
public:
|
||||||
ParamConverterGenerator(ParamGenerator<Gen> g) // NOLINT
|
ParamConverterGenerator(ParamGenerator<GeneratedT> g) // NOLINT
|
||||||
: generator_(std::move(g)) {}
|
: generator_(std::move(g)), converter_(Identity) {}
|
||||||
|
|
||||||
|
ParamConverterGenerator(ParamGenerator<GeneratedT> g, StdFunction converter)
|
||||||
|
: generator_(std::move(g)), converter_(std::move(converter)) {}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
operator ParamGenerator<T>() const { // NOLINT
|
operator ParamGenerator<T>() const { // NOLINT
|
||||||
return ParamGenerator<T>(new ParamGeneratorConverter<Gen, T>(generator_));
|
return ParamGenerator<T>(
|
||||||
|
new ParamGeneratorConverter<GeneratedT, T, StdFunction>(generator_,
|
||||||
|
converter_));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ParamGenerator<Gen> generator_;
|
static const GeneratedT& Identity(const GeneratedT& v) { return v; }
|
||||||
|
|
||||||
|
ParamGenerator<GeneratedT> generator_;
|
||||||
|
StdFunction converter_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Template to determine the param type of a single-param std::function.
|
||||||
|
template <typename T>
|
||||||
|
struct FuncSingleParamType;
|
||||||
|
template <typename R, typename P>
|
||||||
|
struct FuncSingleParamType<std::function<R(P)>> {
|
||||||
|
using type = std::remove_cv_t<std::remove_reference_t<P>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct IsSingleArgStdFunction : public std::false_type {};
|
||||||
|
template <typename R, typename P>
|
||||||
|
struct IsSingleArgStdFunction<std::function<R(P)>> : public std::true_type {};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
|
|||||||
@ -194,26 +194,12 @@
|
|||||||
//
|
//
|
||||||
// Macros for basic C++ coding:
|
// Macros for basic C++ coding:
|
||||||
// GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning.
|
// GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning.
|
||||||
// GTEST_MUST_USE_RESULT_ - declares that a function's result must be used.
|
|
||||||
// GTEST_INTENTIONAL_CONST_COND_PUSH_ - start code section where MSVC C4127 is
|
// GTEST_INTENTIONAL_CONST_COND_PUSH_ - start code section where MSVC C4127 is
|
||||||
// suppressed (constant conditional).
|
// suppressed (constant conditional).
|
||||||
// GTEST_INTENTIONAL_CONST_COND_POP_ - finish code section where MSVC C4127
|
// GTEST_INTENTIONAL_CONST_COND_POP_ - finish code section where MSVC C4127
|
||||||
// is suppressed.
|
// is suppressed.
|
||||||
// GTEST_INTERNAL_HAS_ANY - for enabling UniversalPrinter<std::any> or
|
|
||||||
// UniversalPrinter<absl::any> specializations.
|
|
||||||
// Always defined to 0 or 1.
|
|
||||||
// GTEST_INTERNAL_HAS_OPTIONAL - for enabling UniversalPrinter<std::optional>
|
|
||||||
// or
|
|
||||||
// UniversalPrinter<absl::optional>
|
|
||||||
// specializations. Always defined to 0 or 1.
|
|
||||||
// GTEST_INTERNAL_HAS_STD_SPAN - for enabling UniversalPrinter<std::span>
|
// GTEST_INTERNAL_HAS_STD_SPAN - for enabling UniversalPrinter<std::span>
|
||||||
// specializations. Always defined to 0 or 1
|
// specializations. Always defined to 0 or 1
|
||||||
// GTEST_INTERNAL_HAS_STRING_VIEW - for enabling Matcher<std::string_view> or
|
|
||||||
// Matcher<absl::string_view>
|
|
||||||
// specializations. Always defined to 0 or 1.
|
|
||||||
// GTEST_INTERNAL_HAS_VARIANT - for enabling UniversalPrinter<std::variant> or
|
|
||||||
// UniversalPrinter<absl::variant>
|
|
||||||
// specializations. Always defined to 0 or 1.
|
|
||||||
// GTEST_USE_OWN_FLAGFILE_FLAG_ - Always defined to 0 or 1.
|
// GTEST_USE_OWN_FLAGFILE_FLAG_ - Always defined to 0 or 1.
|
||||||
// GTEST_HAS_CXXABI_H_ - Always defined to 0 or 1.
|
// GTEST_HAS_CXXABI_H_ - Always defined to 0 or 1.
|
||||||
// GTEST_CAN_STREAM_RESULTS_ - Always defined to 0 or 1.
|
// GTEST_CAN_STREAM_RESULTS_ - Always defined to 0 or 1.
|
||||||
@ -260,11 +246,6 @@
|
|||||||
// BoolFromGTestEnv() - parses a bool environment variable.
|
// BoolFromGTestEnv() - parses a bool environment variable.
|
||||||
// Int32FromGTestEnv() - parses an int32_t environment variable.
|
// Int32FromGTestEnv() - parses an int32_t environment variable.
|
||||||
// StringFromGTestEnv() - parses a string environment variable.
|
// StringFromGTestEnv() - parses a string environment variable.
|
||||||
//
|
|
||||||
// Deprecation warnings:
|
|
||||||
// GTEST_INTERNAL_DEPRECATED(message) - attribute marking a function as
|
|
||||||
// deprecated; calling a marked function
|
|
||||||
// should generate a compiler warning
|
|
||||||
|
|
||||||
// The definition of GTEST_INTERNAL_CPLUSPLUS_LANG comes first because it can
|
// The definition of GTEST_INTERNAL_CPLUSPLUS_LANG comes first because it can
|
||||||
// potentially be used as an #include guard.
|
// potentially be used as an #include guard.
|
||||||
@ -275,8 +256,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.
|
||||||
@ -288,10 +269,14 @@
|
|||||||
|
|
||||||
// Detect C++ feature test macros as gracefully as possible.
|
// Detect C++ feature test macros as gracefully as possible.
|
||||||
// MSVC >= 19.15, Clang >= 3.4.1, and GCC >= 4.1.2 support feature test macros.
|
// MSVC >= 19.15, Clang >= 3.4.1, and GCC >= 4.1.2 support feature test macros.
|
||||||
#if GTEST_INTERNAL_CPLUSPLUS_LANG >= 202002L && \
|
//
|
||||||
(!defined(__has_include) || GTEST_INTERNAL_HAS_INCLUDE(<version>))
|
// GCC15 warns that <ciso646> is deprecated in C++17 and suggests using
|
||||||
#include <version> // C++20 and later
|
// <version> instead, even though <version> is not available in C++17 mode prior
|
||||||
#elif (!defined(__has_include) || GTEST_INTERNAL_HAS_INCLUDE(<ciso646>))
|
// to GCC9.
|
||||||
|
#if GTEST_INTERNAL_CPLUSPLUS_LANG >= 202002L || \
|
||||||
|
GTEST_INTERNAL_HAS_INCLUDE(<version>)
|
||||||
|
#include <version> // C++20 or <version> support.
|
||||||
|
#else
|
||||||
#include <ciso646> // Pre-C++20
|
#include <ciso646> // Pre-C++20
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -772,25 +757,6 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
|
|||||||
#define GTEST_HAVE_FEATURE_(x) 0
|
#define GTEST_HAVE_FEATURE_(x) 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Use this annotation after a variable or parameter declaration to tell the
|
|
||||||
// compiler the variable/parameter may be used.
|
|
||||||
// Example:
|
|
||||||
//
|
|
||||||
// GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED int foo = bar();
|
|
||||||
//
|
|
||||||
// This can be removed once we only support only C++17 or newer and
|
|
||||||
// [[maybe_unused]] is available on all supported platforms.
|
|
||||||
#if GTEST_INTERNAL_HAVE_CPP_ATTRIBUTE(maybe_unused)
|
|
||||||
#define GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED [[maybe_unused]]
|
|
||||||
#elif GTEST_HAVE_ATTRIBUTE_(unused)
|
|
||||||
// This is inferior to [[maybe_unused]] as it can produce a
|
|
||||||
// -Wused-but-marked-unused warning on optionally used symbols, but it is all we
|
|
||||||
// have.
|
|
||||||
#define GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED __attribute__((__unused__))
|
|
||||||
#else
|
|
||||||
#define GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Use this annotation before a function that takes a printf format string.
|
// Use this annotation before a function that takes a printf format string.
|
||||||
#if GTEST_HAVE_ATTRIBUTE_(format) && defined(__MINGW_PRINTF_FORMAT)
|
#if GTEST_HAVE_ATTRIBUTE_(format) && defined(__MINGW_PRINTF_FORMAT)
|
||||||
// MinGW has two different printf implementations. Ensure the format macro
|
// MinGW has two different printf implementations. Ensure the format macro
|
||||||
@ -805,17 +771,6 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
|
|||||||
#define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check)
|
#define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Tell the compiler to warn about unused return values for functions declared
|
|
||||||
// with this macro. The macro should be used on function declarations
|
|
||||||
// following the argument list:
|
|
||||||
//
|
|
||||||
// Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_;
|
|
||||||
#if GTEST_HAVE_ATTRIBUTE_(warn_unused_result)
|
|
||||||
#define GTEST_MUST_USE_RESULT_ __attribute__((warn_unused_result))
|
|
||||||
#else
|
|
||||||
#define GTEST_MUST_USE_RESULT_
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// MS C++ compiler emits warning when a conditional expression is compile time
|
// MS C++ compiler emits warning when a conditional expression is compile time
|
||||||
// constant. In some contexts this warning is false positive and needs to be
|
// constant. In some contexts this warning is false positive and needs to be
|
||||||
// suppressed. Use the following two macros in such cases:
|
// suppressed. Use the following two macros in such cases:
|
||||||
@ -1430,9 +1385,9 @@ class GTEST_API_ Mutex {
|
|||||||
Mutex();
|
Mutex();
|
||||||
~Mutex();
|
~Mutex();
|
||||||
|
|
||||||
void Lock();
|
void lock();
|
||||||
|
|
||||||
void Unlock();
|
void unlock();
|
||||||
|
|
||||||
// Does nothing if the current thread holds the mutex. Otherwise, crashes
|
// Does nothing if the current thread holds the mutex. Otherwise, crashes
|
||||||
// with high probability.
|
// with high probability.
|
||||||
@ -1469,12 +1424,11 @@ class GTEST_API_ Mutex {
|
|||||||
// "MutexLock l(&mu)". Hence the typedef trick below.
|
// "MutexLock l(&mu)". Hence the typedef trick below.
|
||||||
class GTestMutexLock {
|
class GTestMutexLock {
|
||||||
public:
|
public:
|
||||||
explicit GTestMutexLock(Mutex* mutex) : mutex_(mutex) { mutex_->Lock(); }
|
explicit GTestMutexLock(Mutex& mutex) : mutex_(mutex) { mutex_.lock(); }
|
||||||
|
~GTestMutexLock() { mutex_.unlock(); }
|
||||||
~GTestMutexLock() { mutex_->Unlock(); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Mutex* const mutex_;
|
Mutex& mutex_;
|
||||||
|
|
||||||
GTestMutexLock(const GTestMutexLock&) = delete;
|
GTestMutexLock(const GTestMutexLock&) = delete;
|
||||||
GTestMutexLock& operator=(const GTestMutexLock&) = delete;
|
GTestMutexLock& operator=(const GTestMutexLock&) = delete;
|
||||||
@ -1686,14 +1640,14 @@ class ThreadLocal : public ThreadLocalBase {
|
|||||||
class MutexBase {
|
class MutexBase {
|
||||||
public:
|
public:
|
||||||
// Acquires this mutex.
|
// Acquires this mutex.
|
||||||
void Lock() {
|
void lock() {
|
||||||
GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_));
|
GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_));
|
||||||
owner_ = pthread_self();
|
owner_ = pthread_self();
|
||||||
has_owner_ = true;
|
has_owner_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Releases this mutex.
|
// Releases this mutex.
|
||||||
void Unlock() {
|
void unlock() {
|
||||||
// Since the lock is being released the owner_ field should no longer be
|
// Since the lock is being released the owner_ field should no longer be
|
||||||
// considered valid. We don't protect writing to has_owner_ here, as it's
|
// considered valid. We don't protect writing to has_owner_ here, as it's
|
||||||
// the caller's responsibility to ensure that the current thread holds the
|
// the caller's responsibility to ensure that the current thread holds the
|
||||||
@ -1761,12 +1715,11 @@ class Mutex : public MutexBase {
|
|||||||
// "MutexLock l(&mu)". Hence the typedef trick below.
|
// "MutexLock l(&mu)". Hence the typedef trick below.
|
||||||
class GTestMutexLock {
|
class GTestMutexLock {
|
||||||
public:
|
public:
|
||||||
explicit GTestMutexLock(MutexBase* mutex) : mutex_(mutex) { mutex_->Lock(); }
|
explicit GTestMutexLock(MutexBase& mutex) : mutex_(mutex) { mutex_.lock(); }
|
||||||
|
~GTestMutexLock() { mutex_.unlock(); }
|
||||||
~GTestMutexLock() { mutex_->Unlock(); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MutexBase* const mutex_;
|
MutexBase& mutex_;
|
||||||
|
|
||||||
GTestMutexLock(const GTestMutexLock&) = delete;
|
GTestMutexLock(const GTestMutexLock&) = delete;
|
||||||
GTestMutexLock& operator=(const GTestMutexLock&) = delete;
|
GTestMutexLock& operator=(const GTestMutexLock&) = delete;
|
||||||
@ -1909,8 +1862,8 @@ class GTEST_API_ ThreadLocal {
|
|||||||
class Mutex {
|
class Mutex {
|
||||||
public:
|
public:
|
||||||
Mutex() {}
|
Mutex() {}
|
||||||
void Lock() {}
|
void lock() {}
|
||||||
void Unlock() {}
|
void unlock() {}
|
||||||
void AssertHeld() const {}
|
void AssertHeld() const {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1926,7 +1879,7 @@ class Mutex {
|
|||||||
// "MutexLock l(&mu)". Hence the typedef trick below.
|
// "MutexLock l(&mu)". Hence the typedef trick below.
|
||||||
class GTestMutexLock {
|
class GTestMutexLock {
|
||||||
public:
|
public:
|
||||||
explicit GTestMutexLock(Mutex*) {} // NOLINT
|
explicit GTestMutexLock(Mutex&) {} // NOLINT
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef GTestMutexLock MutexLock;
|
typedef GTestMutexLock MutexLock;
|
||||||
@ -2367,91 +2320,11 @@ const char* StringFromGTestEnv(const char* flag, const char* default_val);
|
|||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
#if !defined(GTEST_INTERNAL_DEPRECATED)
|
#if GTEST_INTERNAL_HAVE_CPP_ATTRIBUTE(clang::annotate)
|
||||||
|
#define GTEST_INTERNAL_DEPRECATE_AND_INLINE(msg) \
|
||||||
// Internal Macro to mark an API deprecated, for googletest usage only
|
[[deprecated(msg), clang::annotate("inline-me")]]
|
||||||
// Usage: class GTEST_INTERNAL_DEPRECATED(message) MyClass or
|
|
||||||
// GTEST_INTERNAL_DEPRECATED(message) <return_type> myFunction(); Every usage of
|
|
||||||
// a deprecated entity will trigger a warning when compiled with
|
|
||||||
// `-Wdeprecated-declarations` option (clang, gcc, any __GNUC__ compiler).
|
|
||||||
// For msvc /W3 option will need to be used
|
|
||||||
// Note that for 'other' compilers this macro evaluates to nothing to prevent
|
|
||||||
// compilations errors.
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#define GTEST_INTERNAL_DEPRECATED(message) __declspec(deprecated(message))
|
|
||||||
#elif defined(__GNUC__)
|
|
||||||
#define GTEST_INTERNAL_DEPRECATED(message) __attribute__((deprecated(message)))
|
|
||||||
#else
|
#else
|
||||||
#define GTEST_INTERNAL_DEPRECATED(message)
|
#define GTEST_INTERNAL_DEPRECATE_AND_INLINE(msg) [[deprecated(msg)]]
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // !defined(GTEST_INTERNAL_DEPRECATED)
|
|
||||||
|
|
||||||
#ifdef GTEST_HAS_ABSL
|
|
||||||
// Always use absl::any for UniversalPrinter<> specializations if googletest
|
|
||||||
// is built with absl support.
|
|
||||||
#define GTEST_INTERNAL_HAS_ANY 1
|
|
||||||
#include "absl/types/any.h"
|
|
||||||
namespace testing {
|
|
||||||
namespace internal {
|
|
||||||
using Any = ::absl::any;
|
|
||||||
} // namespace internal
|
|
||||||
} // namespace testing
|
|
||||||
#else
|
|
||||||
#if defined(__cpp_lib_any) || (GTEST_INTERNAL_HAS_INCLUDE(<any>) && \
|
|
||||||
GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L && \
|
|
||||||
(!defined(_MSC_VER) || GTEST_HAS_RTTI))
|
|
||||||
// Otherwise for C++17 and higher use std::any for UniversalPrinter<>
|
|
||||||
// specializations.
|
|
||||||
#define GTEST_INTERNAL_HAS_ANY 1
|
|
||||||
#include <any>
|
|
||||||
namespace testing {
|
|
||||||
namespace internal {
|
|
||||||
using Any = ::std::any;
|
|
||||||
} // namespace internal
|
|
||||||
} // namespace testing
|
|
||||||
// The case where absl is configured NOT to alias std::any is not
|
|
||||||
// supported.
|
|
||||||
#endif // __cpp_lib_any
|
|
||||||
#endif // GTEST_HAS_ABSL
|
|
||||||
|
|
||||||
#ifndef GTEST_INTERNAL_HAS_ANY
|
|
||||||
#define GTEST_INTERNAL_HAS_ANY 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef GTEST_HAS_ABSL
|
|
||||||
// Always use absl::optional for UniversalPrinter<> specializations if
|
|
||||||
// googletest is built with absl support.
|
|
||||||
#define GTEST_INTERNAL_HAS_OPTIONAL 1
|
|
||||||
#include "absl/types/optional.h"
|
|
||||||
namespace testing {
|
|
||||||
namespace internal {
|
|
||||||
template <typename T>
|
|
||||||
using Optional = ::absl::optional<T>;
|
|
||||||
inline ::absl::nullopt_t Nullopt() { return ::absl::nullopt; }
|
|
||||||
} // namespace internal
|
|
||||||
} // namespace testing
|
|
||||||
#else
|
|
||||||
#if defined(__cpp_lib_optional) || (GTEST_INTERNAL_HAS_INCLUDE(<optional>) && \
|
|
||||||
GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L)
|
|
||||||
// Otherwise for C++17 and higher use std::optional for UniversalPrinter<>
|
|
||||||
// specializations.
|
|
||||||
#define GTEST_INTERNAL_HAS_OPTIONAL 1
|
|
||||||
#include <optional>
|
|
||||||
namespace testing {
|
|
||||||
namespace internal {
|
|
||||||
template <typename T>
|
|
||||||
using Optional = ::std::optional<T>;
|
|
||||||
inline ::std::nullopt_t Nullopt() { return ::std::nullopt; }
|
|
||||||
} // namespace internal
|
|
||||||
} // namespace testing
|
|
||||||
// The case where absl is configured NOT to alias std::optional is not
|
|
||||||
// supported.
|
|
||||||
#endif // __cpp_lib_optional
|
|
||||||
#endif // GTEST_HAS_ABSL
|
|
||||||
|
|
||||||
#ifndef GTEST_INTERNAL_HAS_OPTIONAL
|
|
||||||
#define GTEST_INTERNAL_HAS_OPTIONAL 0
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__cpp_lib_span) || (GTEST_INTERNAL_HAS_INCLUDE(<span>) && \
|
#if defined(__cpp_lib_span) || (GTEST_INTERNAL_HAS_INCLUDE(<span>) && \
|
||||||
@ -2495,44 +2368,6 @@ using StringView = ::std::string_view;
|
|||||||
#define GTEST_INTERNAL_HAS_STRING_VIEW 0
|
#define GTEST_INTERNAL_HAS_STRING_VIEW 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef GTEST_HAS_ABSL
|
|
||||||
// Always use absl::variant for UniversalPrinter<> specializations if googletest
|
|
||||||
// is built with absl support.
|
|
||||||
#define GTEST_INTERNAL_HAS_VARIANT 1
|
|
||||||
#include "absl/types/variant.h"
|
|
||||||
namespace testing {
|
|
||||||
namespace internal {
|
|
||||||
template <typename... T>
|
|
||||||
using Variant = ::absl::variant<T...>;
|
|
||||||
} // namespace internal
|
|
||||||
} // namespace testing
|
|
||||||
#else
|
|
||||||
#if defined(__cpp_lib_variant) || (GTEST_INTERNAL_HAS_INCLUDE(<variant>) && \
|
|
||||||
GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L)
|
|
||||||
// Otherwise for C++17 and higher use std::variant for UniversalPrinter<>
|
|
||||||
// specializations.
|
|
||||||
#define GTEST_INTERNAL_HAS_VARIANT 1
|
|
||||||
#include <variant>
|
|
||||||
namespace testing {
|
|
||||||
namespace internal {
|
|
||||||
template <typename... T>
|
|
||||||
using Variant = ::std::variant<T...>;
|
|
||||||
} // namespace internal
|
|
||||||
} // namespace testing
|
|
||||||
// The case where absl is configured NOT to alias std::variant is not supported.
|
|
||||||
#endif // __cpp_lib_variant
|
|
||||||
#endif // GTEST_HAS_ABSL
|
|
||||||
|
|
||||||
#ifndef GTEST_INTERNAL_HAS_VARIANT
|
|
||||||
#define GTEST_INTERNAL_HAS_VARIANT 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (defined(__cpp_constexpr) && !defined(__cpp_inline_variables)) || \
|
|
||||||
(defined(GTEST_INTERNAL_CPLUSPLUS_LANG) && \
|
|
||||||
GTEST_INTERNAL_CPLUSPLUS_LANG < 201703L)
|
|
||||||
#define GTEST_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (defined(__cpp_lib_three_way_comparison) || \
|
#if (defined(__cpp_lib_three_way_comparison) || \
|
||||||
(GTEST_INTERNAL_HAS_INCLUDE(<compare>) && \
|
(GTEST_INTERNAL_HAS_INCLUDE(<compare>) && \
|
||||||
GTEST_INTERNAL_CPLUSPLUS_LANG >= 201907L))
|
GTEST_INTERNAL_CPLUSPLUS_LANG >= 201907L))
|
||||||
|
|||||||
@ -826,6 +826,10 @@ class GTEST_API_ UnitTestImpl {
|
|||||||
bool catch_exceptions() const { return catch_exceptions_; }
|
bool catch_exceptions() const { return catch_exceptions_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Returns true if a warning should be issued if no tests match the test
|
||||||
|
// filter flag.
|
||||||
|
bool ShouldWarnIfNoTestsMatchFilter() const;
|
||||||
|
|
||||||
struct CompareTestSuitesByPointer {
|
struct CompareTestSuitesByPointer {
|
||||||
bool operator()(const TestSuite* lhs, const TestSuite* rhs) const {
|
bool operator()(const TestSuite* lhs, const TestSuite* rhs) const {
|
||||||
return lhs->name_ < rhs->name_;
|
return lhs->name_ < rhs->name_;
|
||||||
|
|||||||
@ -320,13 +320,13 @@ Mutex::~Mutex() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mutex::Lock() {
|
void Mutex::lock() {
|
||||||
ThreadSafeLazyInit();
|
ThreadSafeLazyInit();
|
||||||
::EnterCriticalSection(critical_section_);
|
::EnterCriticalSection(critical_section_);
|
||||||
owner_thread_id_ = ::GetCurrentThreadId();
|
owner_thread_id_ = ::GetCurrentThreadId();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mutex::Unlock() {
|
void Mutex::unlock() {
|
||||||
ThreadSafeLazyInit();
|
ThreadSafeLazyInit();
|
||||||
// We don't protect writing to owner_thread_id_ here, as it's the
|
// We don't protect writing to owner_thread_id_ here, as it's the
|
||||||
// caller's responsibility to ensure that the current thread holds the
|
// caller's responsibility to ensure that the current thread holds the
|
||||||
@ -499,7 +499,7 @@ class ThreadLocalRegistryImpl {
|
|||||||
MemoryIsNotDeallocated memory_is_not_deallocated;
|
MemoryIsNotDeallocated memory_is_not_deallocated;
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
DWORD current_thread = ::GetCurrentThreadId();
|
DWORD current_thread = ::GetCurrentThreadId();
|
||||||
MutexLock lock(&mutex_);
|
MutexLock lock(mutex_);
|
||||||
ThreadIdToThreadLocals* const thread_to_thread_locals =
|
ThreadIdToThreadLocals* const thread_to_thread_locals =
|
||||||
GetThreadLocalsMapLocked();
|
GetThreadLocalsMapLocked();
|
||||||
ThreadIdToThreadLocals::iterator thread_local_pos =
|
ThreadIdToThreadLocals::iterator thread_local_pos =
|
||||||
@ -532,7 +532,7 @@ class ThreadLocalRegistryImpl {
|
|||||||
// Clean up the ThreadLocalValues data structure while holding the lock, but
|
// Clean up the ThreadLocalValues data structure while holding the lock, but
|
||||||
// defer the destruction of the ThreadLocalValueHolderBases.
|
// defer the destruction of the ThreadLocalValueHolderBases.
|
||||||
{
|
{
|
||||||
MutexLock lock(&mutex_);
|
MutexLock lock(mutex_);
|
||||||
ThreadIdToThreadLocals* const thread_to_thread_locals =
|
ThreadIdToThreadLocals* const thread_to_thread_locals =
|
||||||
GetThreadLocalsMapLocked();
|
GetThreadLocalsMapLocked();
|
||||||
for (ThreadIdToThreadLocals::iterator it =
|
for (ThreadIdToThreadLocals::iterator it =
|
||||||
@ -559,7 +559,7 @@ class ThreadLocalRegistryImpl {
|
|||||||
// Clean up the ThreadIdToThreadLocals data structure while holding the
|
// Clean up the ThreadIdToThreadLocals data structure while holding the
|
||||||
// lock, but defer the destruction of the ThreadLocalValueHolderBases.
|
// lock, but defer the destruction of the ThreadLocalValueHolderBases.
|
||||||
{
|
{
|
||||||
MutexLock lock(&mutex_);
|
MutexLock lock(mutex_);
|
||||||
ThreadIdToThreadLocals* const thread_to_thread_locals =
|
ThreadIdToThreadLocals* const thread_to_thread_locals =
|
||||||
GetThreadLocalsMapLocked();
|
GetThreadLocalsMapLocked();
|
||||||
ThreadIdToThreadLocals::iterator thread_local_pos =
|
ThreadIdToThreadLocals::iterator thread_local_pos =
|
||||||
|
|||||||
@ -50,7 +50,7 @@
|
|||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <ios>
|
#include <ios>
|
||||||
#include <ostream> // NOLINT
|
#include <ostream> // NOLINT
|
||||||
#include <string>
|
#include <string_view>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
#include "gtest/internal/gtest-port.h"
|
#include "gtest/internal/gtest-port.h"
|
||||||
@ -333,14 +333,14 @@ void PrintTo(__int128_t v, ::std::ostream* os) {
|
|||||||
|
|
||||||
// Prints the given array of characters to the ostream. CharType must be either
|
// Prints the given array of characters to the ostream. CharType must be either
|
||||||
// char, char8_t, char16_t, char32_t, or wchar_t.
|
// char, char8_t, char16_t, char32_t, or wchar_t.
|
||||||
// The array starts at begin, the length is len, it may include '\0' characters
|
// The array starts at begin (which may be nullptr) and contains len characters.
|
||||||
// and may not be NUL-terminated.
|
// The array may include '\0' characters and may not be NUL-terminated.
|
||||||
template <typename CharType>
|
template <typename CharType>
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ static CharFormat
|
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ static CharFormat
|
||||||
PrintCharsAsStringTo(const CharType* begin, size_t len, ostream* os) {
|
PrintCharsAsStringTo(const CharType* begin, size_t len, ostream* os) {
|
||||||
const char* const quote_prefix = GetCharWidthPrefix(*begin);
|
const char* const quote_prefix = GetCharWidthPrefix(CharType());
|
||||||
*os << quote_prefix << "\"";
|
*os << quote_prefix << "\"";
|
||||||
bool is_previous_hex = false;
|
bool is_previous_hex = false;
|
||||||
CharFormat print_format = kAsIs;
|
CharFormat print_format = kAsIs;
|
||||||
@ -516,13 +516,13 @@ bool IsValidUTF8(const char* str, size_t length) {
|
|||||||
void ConditionalPrintAsText(const char* str, size_t length, ostream* os) {
|
void ConditionalPrintAsText(const char* str, size_t length, ostream* os) {
|
||||||
if (!ContainsUnprintableControlCodes(str, length) &&
|
if (!ContainsUnprintableControlCodes(str, length) &&
|
||||||
IsValidUTF8(str, length)) {
|
IsValidUTF8(str, length)) {
|
||||||
*os << "\n As Text: \"" << str << "\"";
|
*os << "\n As Text: \"" << ::std::string_view(str, length) << "\"";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
void PrintStringTo(const ::std::string& s, ostream* os) {
|
void PrintStringTo(::std::string_view s, ostream* os) {
|
||||||
if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) {
|
if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) {
|
||||||
if (GTEST_FLAG_GET(print_utf8)) {
|
if (GTEST_FLAG_GET(print_utf8)) {
|
||||||
ConditionalPrintAsText(s.data(), s.size(), os);
|
ConditionalPrintAsText(s.data(), s.size(), os);
|
||||||
@ -531,21 +531,21 @@ void PrintStringTo(const ::std::string& s, ostream* os) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cpp_lib_char8_t
|
#ifdef __cpp_lib_char8_t
|
||||||
void PrintU8StringTo(const ::std::u8string& s, ostream* os) {
|
void PrintU8StringTo(::std::u8string_view s, ostream* os) {
|
||||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void PrintU16StringTo(const ::std::u16string& s, ostream* os) {
|
void PrintU16StringTo(::std::u16string_view s, ostream* os) {
|
||||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintU32StringTo(const ::std::u32string& s, ostream* os) {
|
void PrintU32StringTo(::std::u32string_view s, ostream* os) {
|
||||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if GTEST_HAS_STD_WSTRING
|
#if GTEST_HAS_STD_WSTRING
|
||||||
void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
|
void PrintWideStringTo(::std::wstring_view s, ostream* os) {
|
||||||
PrintCharsAsStringTo(s.data(), s.size(), os);
|
PrintCharsAsStringTo(s.data(), s.size(), os);
|
||||||
}
|
}
|
||||||
#endif // GTEST_HAS_STD_WSTRING
|
#endif // GTEST_HAS_STD_WSTRING
|
||||||
|
|||||||
@ -192,12 +192,17 @@ static const char kDefaultOutputFormat[] = "xml";
|
|||||||
// The default output file.
|
// The default output file.
|
||||||
static const char kDefaultOutputFile[] = "test_detail";
|
static const char kDefaultOutputFile[] = "test_detail";
|
||||||
|
|
||||||
|
// These environment variables are set by Bazel.
|
||||||
|
// https://bazel.build/reference/test-encyclopedia#initial-conditions
|
||||||
|
//
|
||||||
// The environment variable name for the test shard index.
|
// The environment variable name for the test shard index.
|
||||||
static const char kTestShardIndex[] = "GTEST_SHARD_INDEX";
|
static const char kTestShardIndex[] = "GTEST_SHARD_INDEX";
|
||||||
// The environment variable name for the total number of test shards.
|
// The environment variable name for the total number of test shards.
|
||||||
static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS";
|
static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS";
|
||||||
// The environment variable name for the test shard status file.
|
// The environment variable name for the test shard status file.
|
||||||
static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE";
|
static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE";
|
||||||
|
// The environment variable name for the test output warnings file.
|
||||||
|
static const char kTestWarningsOutputFile[] = "TEST_WARNINGS_OUTPUT_FILE";
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
@ -258,6 +263,19 @@ GTEST_DEFINE_bool_(
|
|||||||
testing::GetDefaultFailFast()),
|
testing::GetDefaultFailFast()),
|
||||||
"True if and only if a test failure should stop further test execution.");
|
"True if and only if a test failure should stop further test execution.");
|
||||||
|
|
||||||
|
GTEST_DEFINE_bool_(
|
||||||
|
fail_if_no_test_linked,
|
||||||
|
testing::internal::BoolFromGTestEnv("fail_if_no_test_linked", false),
|
||||||
|
"True if and only if the test should fail if no test case (including "
|
||||||
|
"disabled test cases) is linked.");
|
||||||
|
|
||||||
|
GTEST_DEFINE_bool_(
|
||||||
|
fail_if_no_test_selected,
|
||||||
|
testing::internal::BoolFromGTestEnv("fail_if_no_test_selected", false),
|
||||||
|
"True if and only if the test should fail if no test case is selected to "
|
||||||
|
"run. A test case is selected to run if it is not disabled and is matched "
|
||||||
|
"by the filter flag so that it starts executing.");
|
||||||
|
|
||||||
GTEST_DEFINE_bool_(
|
GTEST_DEFINE_bool_(
|
||||||
also_run_disabled_tests,
|
also_run_disabled_tests,
|
||||||
testing::internal::BoolFromGTestEnv("also_run_disabled_tests", false),
|
testing::internal::BoolFromGTestEnv("also_run_disabled_tests", false),
|
||||||
@ -695,7 +713,7 @@ std::string UnitTestOptions::GetAbsolutePathToOutputFile() {
|
|||||||
const char* const gtest_output_flag = s.c_str();
|
const char* const gtest_output_flag = s.c_str();
|
||||||
|
|
||||||
std::string format = GetOutputFormat();
|
std::string format = GetOutputFormat();
|
||||||
if (format.empty()) format = std::string(kDefaultOutputFormat);
|
if (format.empty()) format = kDefaultOutputFormat;
|
||||||
|
|
||||||
const char* const colon = strchr(gtest_output_flag, ':');
|
const char* const colon = strchr(gtest_output_flag, ':');
|
||||||
if (colon == nullptr)
|
if (colon == nullptr)
|
||||||
@ -1068,14 +1086,14 @@ void DefaultPerThreadTestPartResultReporter::ReportTestPartResult(
|
|||||||
// Returns the global test part result reporter.
|
// Returns the global test part result reporter.
|
||||||
TestPartResultReporterInterface*
|
TestPartResultReporterInterface*
|
||||||
UnitTestImpl::GetGlobalTestPartResultReporter() {
|
UnitTestImpl::GetGlobalTestPartResultReporter() {
|
||||||
internal::MutexLock lock(&global_test_part_result_reporter_mutex_);
|
internal::MutexLock lock(global_test_part_result_reporter_mutex_);
|
||||||
return global_test_part_result_reporter_;
|
return global_test_part_result_reporter_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the global test part result reporter.
|
// Sets the global test part result reporter.
|
||||||
void UnitTestImpl::SetGlobalTestPartResultReporter(
|
void UnitTestImpl::SetGlobalTestPartResultReporter(
|
||||||
TestPartResultReporterInterface* reporter) {
|
TestPartResultReporterInterface* reporter) {
|
||||||
internal::MutexLock lock(&global_test_part_result_reporter_mutex_);
|
internal::MutexLock lock(global_test_part_result_reporter_mutex_);
|
||||||
global_test_part_result_reporter_ = reporter;
|
global_test_part_result_reporter_ = reporter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1477,17 +1495,17 @@ class Hunk {
|
|||||||
// Print a unified diff header for one hunk.
|
// Print a unified diff header for one hunk.
|
||||||
// The format is
|
// The format is
|
||||||
// "@@ -<left_start>,<left_length> +<right_start>,<right_length> @@"
|
// "@@ -<left_start>,<left_length> +<right_start>,<right_length> @@"
|
||||||
// where the left/right parts are omitted if unnecessary.
|
// where the left/right lengths are omitted if unnecessary.
|
||||||
void PrintHeader(std::ostream* ss) const {
|
void PrintHeader(std::ostream* ss) const {
|
||||||
*ss << "@@ ";
|
size_t left_length = removes_ + common_;
|
||||||
if (removes_) {
|
size_t right_length = adds_ + common_;
|
||||||
*ss << "-" << left_start_ << "," << (removes_ + common_);
|
*ss << "@@ " << "-" << left_start_;
|
||||||
|
if (left_length != 1) {
|
||||||
|
*ss << "," << left_length;
|
||||||
}
|
}
|
||||||
if (removes_ && adds_) {
|
*ss << " " << "+" << right_start_;
|
||||||
*ss << " ";
|
if (right_length != 1) {
|
||||||
}
|
*ss << "," << right_length;
|
||||||
if (adds_) {
|
|
||||||
*ss << "+" << right_start_ << "," << (adds_ + common_);
|
|
||||||
}
|
}
|
||||||
*ss << " @@\n";
|
*ss << " @@\n";
|
||||||
}
|
}
|
||||||
@ -2329,7 +2347,7 @@ void TestResult::RecordProperty(const std::string& xml_element,
|
|||||||
if (!ValidateTestProperty(xml_element, test_property)) {
|
if (!ValidateTestProperty(xml_element, test_property)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
internal::MutexLock lock(&test_properties_mutex_);
|
internal::MutexLock lock(test_properties_mutex_);
|
||||||
const std::vector<TestProperty>::iterator property_with_matching_key =
|
const std::vector<TestProperty>::iterator property_with_matching_key =
|
||||||
std::find_if(test_properties_.begin(), test_properties_.end(),
|
std::find_if(test_properties_.begin(), test_properties_.end(),
|
||||||
internal::TestPropertyKeyIs(test_property.key()));
|
internal::TestPropertyKeyIs(test_property.key()));
|
||||||
@ -3287,6 +3305,7 @@ bool ShouldUseColor(bool stdout_is_tty) {
|
|||||||
const bool term_supports_color =
|
const bool term_supports_color =
|
||||||
term != nullptr && (String::CStringEquals(term, "xterm") ||
|
term != nullptr && (String::CStringEquals(term, "xterm") ||
|
||||||
String::CStringEquals(term, "xterm-color") ||
|
String::CStringEquals(term, "xterm-color") ||
|
||||||
|
String::CStringEquals(term, "xterm-ghostty") ||
|
||||||
String::CStringEquals(term, "xterm-kitty") ||
|
String::CStringEquals(term, "xterm-kitty") ||
|
||||||
String::CStringEquals(term, "alacritty") ||
|
String::CStringEquals(term, "alacritty") ||
|
||||||
String::CStringEquals(term, "screen") ||
|
String::CStringEquals(term, "screen") ||
|
||||||
@ -4336,8 +4355,8 @@ void XmlUnitTestResultPrinter::OutputXmlTestResult(::std::ostream* stream,
|
|||||||
internal::FormatCompilerIndependentFileLocation(part.file_name(),
|
internal::FormatCompilerIndependentFileLocation(part.file_name(),
|
||||||
part.line_number());
|
part.line_number());
|
||||||
const std::string summary = location + "\n" + part.summary();
|
const std::string summary = location + "\n" + part.summary();
|
||||||
*stream << " <skipped message=\""
|
*stream << " <skipped message=\"" << EscapeXmlAttribute(summary)
|
||||||
<< EscapeXmlAttribute(summary.c_str()) << "\">";
|
<< "\">";
|
||||||
const std::string detail = location + "\n" + part.message();
|
const std::string detail = location + "\n" + part.message();
|
||||||
OutputXmlCDataSection(stream, RemoveInvalidXmlCharacters(detail).c_str());
|
OutputXmlCDataSection(stream, RemoveInvalidXmlCharacters(detail).c_str());
|
||||||
*stream << "</skipped>\n";
|
*stream << "</skipped>\n";
|
||||||
@ -5069,7 +5088,7 @@ std::string OsStackTraceGetter::CurrentStackTrace(int max_depth, int skip_count)
|
|||||||
|
|
||||||
void* caller_frame = nullptr;
|
void* caller_frame = nullptr;
|
||||||
{
|
{
|
||||||
MutexLock lock(&mutex_);
|
MutexLock lock(mutex_);
|
||||||
caller_frame = caller_frame_;
|
caller_frame = caller_frame_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5108,7 +5127,7 @@ void OsStackTraceGetter::UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_) {
|
|||||||
caller_frame = nullptr;
|
caller_frame = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
MutexLock lock(&mutex_);
|
MutexLock lock(mutex_);
|
||||||
caller_frame_ = caller_frame;
|
caller_frame_ = caller_frame;
|
||||||
#endif // GTEST_HAS_ABSL
|
#endif // GTEST_HAS_ABSL
|
||||||
}
|
}
|
||||||
@ -5371,13 +5390,13 @@ void UnitTest::UponLeavingGTest() {
|
|||||||
|
|
||||||
// Sets the TestSuite object for the test that's currently running.
|
// Sets the TestSuite object for the test that's currently running.
|
||||||
void UnitTest::set_current_test_suite(TestSuite* a_current_test_suite) {
|
void UnitTest::set_current_test_suite(TestSuite* a_current_test_suite) {
|
||||||
internal::MutexLock lock(&mutex_);
|
internal::MutexLock lock(mutex_);
|
||||||
impl_->set_current_test_suite(a_current_test_suite);
|
impl_->set_current_test_suite(a_current_test_suite);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the TestInfo object for the test that's currently running.
|
// Sets the TestInfo object for the test that's currently running.
|
||||||
void UnitTest::set_current_test_info(TestInfo* a_current_test_info) {
|
void UnitTest::set_current_test_info(TestInfo* a_current_test_info) {
|
||||||
internal::MutexLock lock(&mutex_);
|
internal::MutexLock lock(mutex_);
|
||||||
impl_->set_current_test_info(a_current_test_info);
|
impl_->set_current_test_info(a_current_test_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5416,7 +5435,7 @@ void UnitTest::AddTestPartResult(TestPartResult::Type result_type,
|
|||||||
Message msg;
|
Message msg;
|
||||||
msg << message;
|
msg << message;
|
||||||
|
|
||||||
internal::MutexLock lock(&mutex_);
|
internal::MutexLock lock(mutex_);
|
||||||
if (!impl_->gtest_trace_stack().empty()) {
|
if (!impl_->gtest_trace_stack().empty()) {
|
||||||
msg << "\n" << GTEST_NAME_ << " trace:";
|
msg << "\n" << GTEST_NAME_ << " trace:";
|
||||||
|
|
||||||
@ -5599,7 +5618,7 @@ const char* UnitTest::original_working_dir() const {
|
|||||||
// or NULL if no test is running.
|
// or NULL if no test is running.
|
||||||
const TestSuite* UnitTest::current_test_suite() const
|
const TestSuite* UnitTest::current_test_suite() const
|
||||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||||
internal::MutexLock lock(&mutex_);
|
internal::MutexLock lock(mutex_);
|
||||||
return impl_->current_test_suite();
|
return impl_->current_test_suite();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5607,7 +5626,7 @@ const TestSuite* UnitTest::current_test_suite() const
|
|||||||
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||||
const TestCase* UnitTest::current_test_case() const
|
const TestCase* UnitTest::current_test_case() const
|
||||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||||
internal::MutexLock lock(&mutex_);
|
internal::MutexLock lock(mutex_);
|
||||||
return impl_->current_test_suite();
|
return impl_->current_test_suite();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -5616,7 +5635,7 @@ const TestCase* UnitTest::current_test_case() const
|
|||||||
// or NULL if no test is running.
|
// or NULL if no test is running.
|
||||||
const TestInfo* UnitTest::current_test_info() const
|
const TestInfo* UnitTest::current_test_info() const
|
||||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||||
internal::MutexLock lock(&mutex_);
|
internal::MutexLock lock(mutex_);
|
||||||
return impl_->current_test_info();
|
return impl_->current_test_info();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5640,13 +5659,13 @@ UnitTest::~UnitTest() { delete impl_; }
|
|||||||
// Google Test trace stack.
|
// Google Test trace stack.
|
||||||
void UnitTest::PushGTestTrace(const internal::TraceInfo& trace)
|
void UnitTest::PushGTestTrace(const internal::TraceInfo& trace)
|
||||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||||
internal::MutexLock lock(&mutex_);
|
internal::MutexLock lock(mutex_);
|
||||||
impl_->gtest_trace_stack().push_back(trace);
|
impl_->gtest_trace_stack().push_back(trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pops a trace from the per-thread Google Test trace stack.
|
// Pops a trace from the per-thread Google Test trace stack.
|
||||||
void UnitTest::PopGTestTrace() GTEST_LOCK_EXCLUDED_(mutex_) {
|
void UnitTest::PopGTestTrace() GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||||
internal::MutexLock lock(&mutex_);
|
internal::MutexLock lock(mutex_);
|
||||||
impl_->gtest_trace_stack().pop_back();
|
impl_->gtest_trace_stack().pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5869,6 +5888,23 @@ TestSuite* UnitTestImpl::GetTestSuite(
|
|||||||
static void SetUpEnvironment(Environment* env) { env->SetUp(); }
|
static void SetUpEnvironment(Environment* env) { env->SetUp(); }
|
||||||
static void TearDownEnvironment(Environment* env) { env->TearDown(); }
|
static void TearDownEnvironment(Environment* env) { env->TearDown(); }
|
||||||
|
|
||||||
|
// If the environment variable TEST_WARNINGS_OUTPUT_FILE was provided, appends
|
||||||
|
// `str` to the file, creating the file if necessary.
|
||||||
|
#if GTEST_HAS_FILE_SYSTEM
|
||||||
|
static void AppendToTestWarningsOutputFile(const std::string& str) {
|
||||||
|
const char* const filename = posix::GetEnv(kTestWarningsOutputFile);
|
||||||
|
if (filename == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto* const file = posix::FOpen(filename, "a");
|
||||||
|
if (file == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GTEST_CHECK_(fwrite(str.data(), 1, str.size(), file) == str.size());
|
||||||
|
GTEST_CHECK_(posix::FClose(file) == 0);
|
||||||
|
}
|
||||||
|
#endif // GTEST_HAS_FILE_SYSTEM
|
||||||
|
|
||||||
// Runs all tests in this UnitTest object, prints the result, and
|
// Runs all tests in this UnitTest object, prints the result, and
|
||||||
// returns true if all tests are successful. If any exception is
|
// returns true if all tests are successful. If any exception is
|
||||||
// thrown during a test, the test is considered to be failed, but the
|
// thrown during a test, the test is considered to be failed, but the
|
||||||
@ -5890,6 +5926,28 @@ bool UnitTestImpl::RunAllTests() {
|
|||||||
// user didn't call InitGoogleTest.
|
// user didn't call InitGoogleTest.
|
||||||
PostFlagParsingInit();
|
PostFlagParsingInit();
|
||||||
|
|
||||||
|
// Handle the case where the program has no tests linked.
|
||||||
|
// Sometimes this is a programmer mistake, but sometimes it is intended.
|
||||||
|
if (total_test_count() == 0) {
|
||||||
|
constexpr char kNoTestLinkedMessage[] =
|
||||||
|
"This test program does NOT link in any test case.";
|
||||||
|
constexpr char kNoTestLinkedFatal[] =
|
||||||
|
"This is INVALID. Please make sure to link in at least one test case.";
|
||||||
|
constexpr char kNoTestLinkedWarning[] =
|
||||||
|
"Please make sure this is intended.";
|
||||||
|
const bool fail_if_no_test_linked = GTEST_FLAG_GET(fail_if_no_test_linked);
|
||||||
|
ColoredPrintf(
|
||||||
|
GTestColor::kRed, "%s %s\n", kNoTestLinkedMessage,
|
||||||
|
fail_if_no_test_linked ? kNoTestLinkedFatal : kNoTestLinkedWarning);
|
||||||
|
if (fail_if_no_test_linked) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#if GTEST_HAS_FILE_SYSTEM
|
||||||
|
AppendToTestWarningsOutputFile(std::string(kNoTestLinkedMessage) + ' ' +
|
||||||
|
kNoTestLinkedWarning + '\n');
|
||||||
|
#endif // GTEST_HAS_FILE_SYSTEM
|
||||||
|
}
|
||||||
|
|
||||||
#if GTEST_HAS_FILE_SYSTEM
|
#if GTEST_HAS_FILE_SYSTEM
|
||||||
// Even if sharding is not on, test runners may want to use the
|
// Even if sharding is not on, test runners may want to use the
|
||||||
// GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding
|
// GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding
|
||||||
@ -6029,6 +6087,20 @@ bool UnitTestImpl::RunAllTests() {
|
|||||||
TearDownEnvironment);
|
TearDownEnvironment);
|
||||||
repeater->OnEnvironmentsTearDownEnd(*parent_);
|
repeater->OnEnvironmentsTearDownEnd(*parent_);
|
||||||
}
|
}
|
||||||
|
} else if (GTEST_FLAG_GET(fail_if_no_test_selected)) {
|
||||||
|
// If there were no tests to run, bail if we were requested to be
|
||||||
|
// strict.
|
||||||
|
constexpr char kNoTestsSelectedMessage[] =
|
||||||
|
"No tests ran. Check that tests exist and are not disabled or "
|
||||||
|
"filtered out.\n\n"
|
||||||
|
"For sharded runs, this error indicates an empty shard. This can "
|
||||||
|
"happen if you have more shards than tests, or if --gtest_filter "
|
||||||
|
"leaves a shard with no tests.\n\n"
|
||||||
|
"To permit empty shards (e.g., when debugging with a filter), "
|
||||||
|
"specify \n"
|
||||||
|
"--gtest_fail_if_no_test_selected=false.";
|
||||||
|
ColoredPrintf(GTestColor::kRed, "%s\n", kNoTestsSelectedMessage);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
elapsed_time_ = timer.Elapsed();
|
elapsed_time_ = timer.Elapsed();
|
||||||
@ -6063,6 +6135,17 @@ bool UnitTestImpl::RunAllTests() {
|
|||||||
environments_.clear();
|
environments_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try to warn the user if no tests matched the test filter.
|
||||||
|
if (ShouldWarnIfNoTestsMatchFilter()) {
|
||||||
|
const std::string filter_warning =
|
||||||
|
std::string("filter \"") + GTEST_FLAG_GET(filter) +
|
||||||
|
"\" did not match any test; no tests were run\n";
|
||||||
|
ColoredPrintf(GTestColor::kRed, "WARNING: %s", filter_warning.c_str());
|
||||||
|
#if GTEST_HAS_FILE_SYSTEM
|
||||||
|
AppendToTestWarningsOutputFile(filter_warning);
|
||||||
|
#endif // GTEST_HAS_FILE_SYSTEM
|
||||||
|
}
|
||||||
|
|
||||||
if (!gtest_is_initialized_before_run_all_tests) {
|
if (!gtest_is_initialized_before_run_all_tests) {
|
||||||
ColoredPrintf(
|
ColoredPrintf(
|
||||||
GTestColor::kRed,
|
GTestColor::kRed,
|
||||||
@ -6231,6 +6314,30 @@ int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
|
|||||||
return num_selected_tests;
|
return num_selected_tests;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns true if a warning should be issued if no tests match the test filter
|
||||||
|
// flag. We can't simply count the number of tests that ran because, for
|
||||||
|
// instance, test sharding and death tests might mean no tests are expected to
|
||||||
|
// run in this process, but will run in another process.
|
||||||
|
bool UnitTestImpl::ShouldWarnIfNoTestsMatchFilter() const {
|
||||||
|
if (total_test_count() == 0) {
|
||||||
|
// No tests were linked in to program.
|
||||||
|
// This case is handled by a different warning.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const PositiveAndNegativeUnitTestFilter gtest_flag_filter(
|
||||||
|
GTEST_FLAG_GET(filter));
|
||||||
|
for (auto* test_suite : test_suites_) {
|
||||||
|
const std::string& test_suite_name = test_suite->name_;
|
||||||
|
for (TestInfo* test_info : test_suite->test_info_list()) {
|
||||||
|
const std::string& test_name = test_info->name_;
|
||||||
|
if (gtest_flag_filter.MatchesTest(test_suite_name, test_name)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Prints the given C-string on a single line by replacing all '\n'
|
// Prints the given C-string on a single line by replacing all '\n'
|
||||||
// characters with string "\\n". If the output takes more than
|
// characters with string "\\n". If the output takes more than
|
||||||
// max_length characters, only prints the first max_length characters
|
// max_length characters, only prints the first max_length characters
|
||||||
@ -6677,6 +6784,8 @@ static bool ParseGoogleTestFlag(const char* const arg) {
|
|||||||
GTEST_INTERNAL_PARSE_FLAG(death_test_style);
|
GTEST_INTERNAL_PARSE_FLAG(death_test_style);
|
||||||
GTEST_INTERNAL_PARSE_FLAG(death_test_use_fork);
|
GTEST_INTERNAL_PARSE_FLAG(death_test_use_fork);
|
||||||
GTEST_INTERNAL_PARSE_FLAG(fail_fast);
|
GTEST_INTERNAL_PARSE_FLAG(fail_fast);
|
||||||
|
GTEST_INTERNAL_PARSE_FLAG(fail_if_no_test_linked);
|
||||||
|
GTEST_INTERNAL_PARSE_FLAG(fail_if_no_test_selected);
|
||||||
GTEST_INTERNAL_PARSE_FLAG(filter);
|
GTEST_INTERNAL_PARSE_FLAG(filter);
|
||||||
GTEST_INTERNAL_PARSE_FLAG(internal_run_death_test);
|
GTEST_INTERNAL_PARSE_FLAG(internal_run_death_test);
|
||||||
GTEST_INTERNAL_PARSE_FLAG(list_tests);
|
GTEST_INTERNAL_PARSE_FLAG(list_tests);
|
||||||
|
|||||||
@ -30,6 +30,7 @@
|
|||||||
#
|
#
|
||||||
# Bazel BUILD for The Google C++ Testing Framework (Google Test)
|
# Bazel BUILD for The Google C++ Testing Framework (Google Test)
|
||||||
|
|
||||||
|
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_test")
|
||||||
load("@rules_python//python:defs.bzl", "py_library", "py_test")
|
load("@rules_python//python:defs.bzl", "py_library", "py_test")
|
||||||
|
|
||||||
licenses(["notice"])
|
licenses(["notice"])
|
||||||
@ -47,33 +48,36 @@ cc_test(
|
|||||||
"*.h",
|
"*.h",
|
||||||
],
|
],
|
||||||
exclude = [
|
exclude = [
|
||||||
"gtest-unittest-api_test.cc",
|
# go/keep-sorted start
|
||||||
"googletest/src/gtest-all.cc",
|
"googletest-break-on-failure-unittest_.cc",
|
||||||
"gtest_all_test.cc",
|
|
||||||
"gtest-death-test_ex_test.cc",
|
|
||||||
"gtest-listener_test.cc",
|
|
||||||
"gtest-unittest-api_test.cc",
|
|
||||||
"googletest-param-test-test.cc",
|
|
||||||
"googletest-param-test2-test.cc",
|
|
||||||
"googletest-catch-exceptions-test_.cc",
|
"googletest-catch-exceptions-test_.cc",
|
||||||
"googletest-color-test_.cc",
|
"googletest-color-test_.cc",
|
||||||
|
"googletest-death-test_ex_test.cc",
|
||||||
"googletest-env-var-test_.cc",
|
"googletest-env-var-test_.cc",
|
||||||
|
"googletest-fail-if-no-test-linked-test-with-disabled-test_.cc",
|
||||||
|
"googletest-fail-if-no-test-linked-test-with-enabled-test_.cc",
|
||||||
"googletest-failfast-unittest_.cc",
|
"googletest-failfast-unittest_.cc",
|
||||||
"googletest-filter-unittest_.cc",
|
"googletest-filter-unittest_.cc",
|
||||||
"googletest-global-environment-unittest_.cc",
|
"googletest-global-environment-unittest_.cc",
|
||||||
"googletest-break-on-failure-unittest_.cc",
|
"googletest-list-tests-unittest_.cc",
|
||||||
"googletest-listener-test.cc",
|
"googletest-listener-test.cc",
|
||||||
"googletest-message-test.cc",
|
"googletest-message-test.cc",
|
||||||
"googletest-output-test_.cc",
|
"googletest-output-test_.cc",
|
||||||
"googletest-list-tests-unittest_.cc",
|
|
||||||
"googletest-shuffle-test_.cc",
|
|
||||||
"googletest-setuptestsuite-test_.cc",
|
|
||||||
"googletest-uninitialized-test_.cc",
|
|
||||||
"googletest-death-test_ex_test.cc",
|
|
||||||
"googletest-param-test-test",
|
|
||||||
"googletest-throw-on-failure-test_.cc",
|
|
||||||
"googletest-param-test-invalid-name1-test_.cc",
|
"googletest-param-test-invalid-name1-test_.cc",
|
||||||
"googletest-param-test-invalid-name2-test_.cc",
|
"googletest-param-test-invalid-name2-test_.cc",
|
||||||
|
"googletest-param-test-test",
|
||||||
|
"googletest-param-test-test.cc",
|
||||||
|
"googletest-param-test2-test.cc",
|
||||||
|
"googletest-setuptestsuite-test_.cc",
|
||||||
|
"googletest-shuffle-test_.cc",
|
||||||
|
"googletest-throw-on-failure-test_.cc",
|
||||||
|
"googletest-uninitialized-test_.cc",
|
||||||
|
"googletest/src/gtest-all.cc",
|
||||||
|
"gtest-death-test_ex_test.cc",
|
||||||
|
"gtest-listener_test.cc",
|
||||||
|
"gtest-unittest-api_test.cc",
|
||||||
|
"gtest_all_test.cc",
|
||||||
|
# go/keep-sorted end
|
||||||
],
|
],
|
||||||
) + select({
|
) + select({
|
||||||
"//:windows": [],
|
"//:windows": [],
|
||||||
@ -323,6 +327,26 @@ cc_binary(
|
|||||||
deps = ["//:gtest"],
|
deps = ["//:gtest"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cc_binary(
|
||||||
|
name = "googletest-fail-if-no-test-linked-test-without-test_",
|
||||||
|
testonly = 1,
|
||||||
|
deps = ["//:gtest_main"],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_binary(
|
||||||
|
name = "googletest-fail-if-no-test-linked-test-with-disabled-test_",
|
||||||
|
testonly = 1,
|
||||||
|
srcs = ["googletest-fail-if-no-test-linked-test-with-disabled-test_.cc"],
|
||||||
|
deps = ["//:gtest_main"],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_binary(
|
||||||
|
name = "googletest-fail-if-no-test-linked-test-with-enabled-test_",
|
||||||
|
testonly = 1,
|
||||||
|
srcs = ["googletest-fail-if-no-test-linked-test-with-enabled-test_.cc"],
|
||||||
|
deps = ["//:gtest_main"],
|
||||||
|
)
|
||||||
|
|
||||||
cc_test(
|
cc_test(
|
||||||
name = "gtest_skip_test",
|
name = "gtest_skip_test",
|
||||||
size = "small",
|
size = "small",
|
||||||
@ -363,6 +387,18 @@ py_test(
|
|||||||
deps = [":gtest_test_utils"],
|
deps = [":gtest_test_utils"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
py_test(
|
||||||
|
name = "googletest-fail-if-no-test-linked-test",
|
||||||
|
size = "small",
|
||||||
|
srcs = ["googletest-fail-if-no-test-linked-test.py"],
|
||||||
|
data = [
|
||||||
|
":googletest-fail-if-no-test-linked-test-with-disabled-test_",
|
||||||
|
":googletest-fail-if-no-test-linked-test-with-enabled-test_",
|
||||||
|
":googletest-fail-if-no-test-linked-test-without-test_",
|
||||||
|
],
|
||||||
|
deps = [":gtest_test_utils"],
|
||||||
|
)
|
||||||
|
|
||||||
cc_binary(
|
cc_binary(
|
||||||
name = "googletest-shuffle-test_",
|
name = "googletest-shuffle-test_",
|
||||||
srcs = ["googletest-shuffle-test_.cc"],
|
srcs = ["googletest-shuffle-test_.cc"],
|
||||||
|
|||||||
@ -79,6 +79,7 @@ class GTestColorTest(gtest_test_utils.TestCase):
|
|||||||
self.assertTrue(UsesColor('cygwin', None, None))
|
self.assertTrue(UsesColor('cygwin', None, None))
|
||||||
self.assertTrue(UsesColor('xterm', None, None))
|
self.assertTrue(UsesColor('xterm', None, None))
|
||||||
self.assertTrue(UsesColor('xterm-color', None, None))
|
self.assertTrue(UsesColor('xterm-color', None, None))
|
||||||
|
self.assertTrue(UsesColor('xterm-ghostty', None, None))
|
||||||
self.assertTrue(UsesColor('xterm-kitty', None, None))
|
self.assertTrue(UsesColor('xterm-kitty', None, None))
|
||||||
self.assertTrue(UsesColor('alacritty', None, None))
|
self.assertTrue(UsesColor('alacritty', None, None))
|
||||||
self.assertTrue(UsesColor('xterm-256color', None, None))
|
self.assertTrue(UsesColor('xterm-256color', None, None))
|
||||||
|
|||||||
@ -291,7 +291,7 @@ TEST(ExitStatusPredicateTest, KilledBySignal) {
|
|||||||
const int status_kill = KilledExitStatus(SIGKILL);
|
const int status_kill = KilledExitStatus(SIGKILL);
|
||||||
const testing::KilledBySignal pred_segv(SIGSEGV);
|
const testing::KilledBySignal pred_segv(SIGSEGV);
|
||||||
const testing::KilledBySignal pred_kill(SIGKILL);
|
const testing::KilledBySignal pred_kill(SIGKILL);
|
||||||
#if !(defined(GTEST_OS_LINUX_ANDROID) && __ANDROID_API__ <= 21)
|
#if !(defined(GTEST_OS_LINUX_ANDROID) && __ANDROID_API__ <= 23)
|
||||||
EXPECT_PRED1(pred_segv, status_segv);
|
EXPECT_PRED1(pred_segv, status_segv);
|
||||||
#endif
|
#endif
|
||||||
EXPECT_PRED1(pred_kill, status_kill);
|
EXPECT_PRED1(pred_kill, status_kill);
|
||||||
|
|||||||
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright 2025, 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.
|
||||||
|
|
||||||
|
// Unit test for Google Test's --gtest_fail_if_no_test_linked flag.
|
||||||
|
//
|
||||||
|
// This program will be invoked from a Python test.
|
||||||
|
// Don't run it directly.
|
||||||
|
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
// A dummy test that is disabled.
|
||||||
|
TEST(SomeTest, DISABLED_Test1) {}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright 2025, 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.
|
||||||
|
|
||||||
|
// Unit test for Google Test's --gtest_fail_if_no_test_linked flag.
|
||||||
|
//
|
||||||
|
// This program will be invoked from a Python test.
|
||||||
|
// Don't run it directly.
|
||||||
|
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
// A dummy test that is enabled.
|
||||||
|
TEST(SomeTest, Test1) {}
|
||||||
165
googletest/test/googletest-fail-if-no-test-linked-test.py
Executable file
165
googletest/test/googletest-fail-if-no-test-linked-test.py
Executable file
@ -0,0 +1,165 @@
|
|||||||
|
#!/usr/bin/env python3 # pylint: disable=g-interpreter-mismatch
|
||||||
|
#
|
||||||
|
# Copyright 2025, Google Inc.
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are
|
||||||
|
# met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# * Redistributions in binary form must reproduce the above
|
||||||
|
# copyright notice, this list of conditions and the following disclaimer
|
||||||
|
# in the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
# * Neither the name of Google Inc. nor the names of its
|
||||||
|
# contributors may be used to endorse or promote products derived from
|
||||||
|
# this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
"""Tests for Google Test's --gtest_fail_if_no_test_linked flag."""
|
||||||
|
|
||||||
|
import os
|
||||||
|
from googletest.test import gtest_test_utils
|
||||||
|
|
||||||
|
# The command line flag for enabling the fail-if-no-test-linked behavior.
|
||||||
|
FAIL_IF_NO_TEST_LINKED_FLAG = "gtest_fail_if_no_test_linked"
|
||||||
|
|
||||||
|
# The environment variable for the test output warnings file.
|
||||||
|
TEST_WARNINGS_OUTPUT_FILE = "TEST_WARNINGS_OUTPUT_FILE"
|
||||||
|
|
||||||
|
|
||||||
|
class GTestFailIfNoTestLinkedTest(gtest_test_utils.TestCase):
|
||||||
|
"""Tests the --gtest_fail_if_no_test_linked flag."""
|
||||||
|
|
||||||
|
def Run(self, program_name, flag=None, env=None):
|
||||||
|
"""Run the given program with the given flag.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
program_name: Name of the program to run.
|
||||||
|
flag: The command line flag to pass to the program, or None.
|
||||||
|
env: Dictionary with environment to pass to the subprocess.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if the program exits with code 0, false otherwise.
|
||||||
|
"""
|
||||||
|
|
||||||
|
exe_path = gtest_test_utils.GetTestExecutablePath(program_name)
|
||||||
|
args = [exe_path]
|
||||||
|
if flag is not None:
|
||||||
|
args += [flag]
|
||||||
|
process = gtest_test_utils.Subprocess(args, capture_stderr=False, env=env)
|
||||||
|
return process.exited and process.exit_code == 0
|
||||||
|
|
||||||
|
def testSucceedsIfNoTestLinkedAndFlagNotSpecified(self):
|
||||||
|
"""Tests the behavior of no test linked and flag not specified."""
|
||||||
|
self.assertTrue(
|
||||||
|
self.Run("googletest-fail-if-no-test-linked-test-without-test_")
|
||||||
|
)
|
||||||
|
|
||||||
|
def testSucceedsIfNoTestLinkedAndFlagNotSpecifiedWithWarningFile(self):
|
||||||
|
"""Tests that no test linked results in warning file output."""
|
||||||
|
|
||||||
|
warning_file = os.path.join(gtest_test_utils.GetTempDir(), "NO_TEST_LINKED")
|
||||||
|
self.assertTrue(
|
||||||
|
self.Run(
|
||||||
|
"googletest-fail-if-no-test-linked-test-without-test_",
|
||||||
|
env={TEST_WARNINGS_OUTPUT_FILE: warning_file},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
warning_file_contents = open(warning_file, "r").read()
|
||||||
|
self.assertIn("does NOT link", warning_file_contents)
|
||||||
|
|
||||||
|
def testFailsIfNoTestLinkedAndFlagSpecified(self):
|
||||||
|
"""Tests the behavior of no test linked and flag specified."""
|
||||||
|
|
||||||
|
warning_file = os.path.join(
|
||||||
|
gtest_test_utils.GetTempDir(), "SHOULD_NOT_EXIST"
|
||||||
|
)
|
||||||
|
self.assertFalse(
|
||||||
|
self.Run(
|
||||||
|
"googletest-fail-if-no-test-linked-test-without-test_",
|
||||||
|
f"--{FAIL_IF_NO_TEST_LINKED_FLAG}",
|
||||||
|
env={TEST_WARNINGS_OUTPUT_FILE: warning_file},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
with self.assertRaises(FileNotFoundError):
|
||||||
|
open(warning_file, "r")
|
||||||
|
|
||||||
|
def testSucceedsIfEnabledTestLinkedAndFlagNotSpecified(self):
|
||||||
|
"""Tests the behavior of enabled test linked and flag not specified."""
|
||||||
|
|
||||||
|
warning_file = os.path.join(
|
||||||
|
gtest_test_utils.GetTempDir(), "SHOULD_NOT_EXIST"
|
||||||
|
)
|
||||||
|
self.assertTrue(
|
||||||
|
self.Run(
|
||||||
|
"googletest-fail-if-no-test-linked-test-with-enabled-test_",
|
||||||
|
env={TEST_WARNINGS_OUTPUT_FILE: warning_file},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
with self.assertRaises(FileNotFoundError):
|
||||||
|
open(warning_file, "r")
|
||||||
|
|
||||||
|
def testSucceedsIfEnabledTestLinkedAndFlagSpecified(self):
|
||||||
|
"""Tests the behavior of enabled test linked and flag specified."""
|
||||||
|
|
||||||
|
warning_file = os.path.join(
|
||||||
|
gtest_test_utils.GetTempDir(), "SHOULD_NOT_EXIST"
|
||||||
|
)
|
||||||
|
self.assertTrue(
|
||||||
|
self.Run(
|
||||||
|
"googletest-fail-if-no-test-linked-test-with-enabled-test_",
|
||||||
|
f"--{FAIL_IF_NO_TEST_LINKED_FLAG}",
|
||||||
|
env={TEST_WARNINGS_OUTPUT_FILE: warning_file},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
with self.assertRaises(FileNotFoundError):
|
||||||
|
open(warning_file, "r")
|
||||||
|
|
||||||
|
def testSucceedsIfDisabledTestLinkedAndFlagNotSpecified(self):
|
||||||
|
"""Tests the behavior of disabled test linked and flag not specified."""
|
||||||
|
|
||||||
|
warning_file = os.path.join(
|
||||||
|
gtest_test_utils.GetTempDir(), "SHOULD_NOT_EXIST"
|
||||||
|
)
|
||||||
|
self.assertTrue(
|
||||||
|
self.Run(
|
||||||
|
"googletest-fail-if-no-test-linked-test-with-disabled-test_",
|
||||||
|
env={TEST_WARNINGS_OUTPUT_FILE: warning_file},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
with self.assertRaises(FileNotFoundError):
|
||||||
|
open(warning_file, "r")
|
||||||
|
|
||||||
|
def testSucceedsIfDisabledTestLinkedAndFlagSpecified(self):
|
||||||
|
"""Tests the behavior of disabled test linked and flag specified."""
|
||||||
|
|
||||||
|
warning_file = os.path.join(
|
||||||
|
gtest_test_utils.GetTempDir(), "SHOULD_NOT_EXIST"
|
||||||
|
)
|
||||||
|
self.assertTrue(
|
||||||
|
self.Run(
|
||||||
|
"googletest-fail-if-no-test-linked-test-with-disabled-test_",
|
||||||
|
f"--{FAIL_IF_NO_TEST_LINKED_FLAG}",
|
||||||
|
env={TEST_WARNINGS_OUTPUT_FILE: warning_file},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
with self.assertRaises(FileNotFoundError):
|
||||||
|
open(warning_file, "r")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
gtest_test_utils.Main()
|
||||||
91
googletest/test/googletest-fail-if-no-test-selected-test.py
Normal file
91
googletest/test/googletest-fail-if-no-test-selected-test.py
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#!/usr/bin/env python3 # pylint: disable=g-interpreter-mismatch
|
||||||
|
#
|
||||||
|
# Copyright 2025, Google Inc.
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are
|
||||||
|
# met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# * Redistributions in binary form must reproduce the above
|
||||||
|
# copyright notice, this list of conditions and the following disclaimer
|
||||||
|
# in the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
# * Neither the name of Google Inc. nor the names of its
|
||||||
|
# contributors may be used to endorse or promote products derived from
|
||||||
|
# this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
"""Tests for Google Test's --gtest_fail_if_no_test_selected flag."""
|
||||||
|
|
||||||
|
from googletest.test import gtest_test_utils
|
||||||
|
|
||||||
|
|
||||||
|
# The command line flag for enabling the fail-if-no-test-selected behavior.
|
||||||
|
FAIL_IF_NO_TEST_SELECTED_FLAG = "gtest_fail_if_no_test_selected"
|
||||||
|
|
||||||
|
# The environment variable for the test output warnings file.
|
||||||
|
TEST_WARNINGS_OUTPUT_FILE = "TEST_WARNINGS_OUTPUT_FILE"
|
||||||
|
|
||||||
|
|
||||||
|
class GTestFailIfNoTestSelectedTest(gtest_test_utils.TestCase):
|
||||||
|
"""Tests the --gtest_fail_if_no_test_selected flag."""
|
||||||
|
|
||||||
|
def Run(self, program_name, flags=None, env=None):
|
||||||
|
"""Run the given program with the given flag.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
program_name: Name of the program to run.
|
||||||
|
flags: The command line flags to pass to the program, or None.
|
||||||
|
env: Dictionary with environment to pass to the subprocess.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if the program exits with code 0, false otherwise.
|
||||||
|
"""
|
||||||
|
|
||||||
|
exe_path = gtest_test_utils.GetTestExecutablePath(program_name)
|
||||||
|
args = [exe_path]
|
||||||
|
if flags is not None:
|
||||||
|
args.extend(flags)
|
||||||
|
process = gtest_test_utils.Subprocess(args, capture_stderr=False, env=env)
|
||||||
|
return process.exited and process.exit_code == 0
|
||||||
|
|
||||||
|
def testSucceedsWhenFlagIsNotSetAndOnlyDisabledTestsPresent(self):
|
||||||
|
"""Tests that no test selected results in success without the flag set."""
|
||||||
|
self.assertTrue(
|
||||||
|
self.Run("googletest-fail-if-no-test-linked-test-with-disabled-test_"),
|
||||||
|
)
|
||||||
|
|
||||||
|
def testFailsWhenFlagIsSetAndOnlyDisabledTestsPresent(self):
|
||||||
|
"""Tests that no test selected results in failure with the flag set."""
|
||||||
|
self.assertFalse(
|
||||||
|
self.Run(
|
||||||
|
"googletest-fail-if-no-test-linked-test-with-disabled-test_",
|
||||||
|
flags=[f"--{FAIL_IF_NO_TEST_SELECTED_FLAG}"],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
def testSucceedsWhenFlagIsSetAndEnabledTestsPresent(self):
|
||||||
|
"""Tests that a test running still succeeds when the flag is set."""
|
||||||
|
self.assertTrue(
|
||||||
|
self.Run(
|
||||||
|
"googletest-fail-if-no-test-linked-test-with-enabled-test_",
|
||||||
|
flags=[f"--{FAIL_IF_NO_TEST_SELECTED_FLAG}"],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
gtest_test_utils.Main()
|
||||||
@ -97,6 +97,9 @@ TOTAL_SHARDS_ENV_VAR = 'GTEST_TOTAL_SHARDS'
|
|||||||
SHARD_INDEX_ENV_VAR = 'GTEST_SHARD_INDEX'
|
SHARD_INDEX_ENV_VAR = 'GTEST_SHARD_INDEX'
|
||||||
SHARD_STATUS_FILE_ENV_VAR = 'GTEST_SHARD_STATUS_FILE'
|
SHARD_STATUS_FILE_ENV_VAR = 'GTEST_SHARD_STATUS_FILE'
|
||||||
|
|
||||||
|
# The environment variable for the test warnings output file.
|
||||||
|
TEST_WARNINGS_OUTPUT_FILE = 'TEST_WARNINGS_OUTPUT_FILE'
|
||||||
|
|
||||||
# The command line flag for specifying the test filters.
|
# The command line flag for specifying the test filters.
|
||||||
FILTER_FLAG = 'gtest_filter'
|
FILTER_FLAG = 'gtest_filter'
|
||||||
|
|
||||||
@ -419,6 +422,22 @@ class GTestFilterUnitTest(gtest_test_utils.TestCase):
|
|||||||
self.RunAndVerify('BadFilter', [])
|
self.RunAndVerify('BadFilter', [])
|
||||||
self.RunAndVerifyAllowingDisabled('BadFilter', [])
|
self.RunAndVerifyAllowingDisabled('BadFilter', [])
|
||||||
|
|
||||||
|
def testBadFilterWithWarningFile(self):
|
||||||
|
"""Tests the warning file when a filter that matches nothing."""
|
||||||
|
|
||||||
|
warning_file = os.path.join(
|
||||||
|
gtest_test_utils.GetTempDir(), 'testBadFilterWithWarningFile'
|
||||||
|
)
|
||||||
|
extra_env = {TEST_WARNINGS_OUTPUT_FILE: warning_file}
|
||||||
|
args = ['--%s=%s' % (FILTER_FLAG, 'BadFilter')]
|
||||||
|
InvokeWithModifiedEnv(extra_env, RunAndReturnOutput, args)
|
||||||
|
with open(warning_file, 'r') as f:
|
||||||
|
warning_file_contents = f.read()
|
||||||
|
self.assertEqual(
|
||||||
|
warning_file_contents,
|
||||||
|
'filter "BadFilter" did not match any test; no tests were run\n',
|
||||||
|
)
|
||||||
|
|
||||||
def testFullName(self):
|
def testFullName(self):
|
||||||
"""Tests filtering by full name."""
|
"""Tests filtering by full name."""
|
||||||
|
|
||||||
|
|||||||
@ -62,7 +62,7 @@ Expected equality of these values:
|
|||||||
Which is: "\"Line\0 1\"\nLine 2"
|
Which is: "\"Line\0 1\"\nLine 2"
|
||||||
"Line 2"
|
"Line 2"
|
||||||
With diff:
|
With diff:
|
||||||
@@ -1,2 @@
|
@@ -1,2 +1 @@
|
||||||
-\"Line\0 1\"
|
-\"Line\0 1\"
|
||||||
Line 2
|
Line 2
|
||||||
|
|
||||||
|
|||||||
@ -35,12 +35,17 @@
|
|||||||
#include "test/googletest-param-test-test.h"
|
#include "test/googletest-param-test-test.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
@ -583,6 +588,71 @@ TEST(ConvertTest, NonDefaultConstructAssign) {
|
|||||||
EXPECT_TRUE(it == gen.end());
|
EXPECT_TRUE(it == gen.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ConvertTest, WithConverterLambdaAndDeducedType) {
|
||||||
|
const ParamGenerator<ConstructFromT<int8_t>> gen =
|
||||||
|
ConvertGenerator(Values("0", std::string("1")), [](const std::string& s) {
|
||||||
|
size_t pos;
|
||||||
|
int64_t value = std::stoll(s, &pos);
|
||||||
|
EXPECT_EQ(pos, s.size());
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
|
||||||
|
ConstructFromT<int8_t> expected_values[] = {ConstructFromT<int8_t>(0),
|
||||||
|
ConstructFromT<int8_t>(1)};
|
||||||
|
VerifyGenerator(gen, expected_values);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ConvertTest, WithConverterLambdaAndExplicitType) {
|
||||||
|
auto convert_generator = ConvertGenerator<std::string>(
|
||||||
|
Values("0", std::string("1")), [](std::string_view s) {
|
||||||
|
size_t pos;
|
||||||
|
int64_t value = std::stoll(std::string(s), &pos);
|
||||||
|
EXPECT_EQ(pos, s.size());
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
constexpr bool is_correct_type = std::is_same_v<
|
||||||
|
decltype(convert_generator),
|
||||||
|
testing::internal::ParamConverterGenerator<
|
||||||
|
std::string, std::function<int64_t(std::string_view)>>>;
|
||||||
|
EXPECT_TRUE(is_correct_type);
|
||||||
|
const ParamGenerator<ConstructFromT<int8_t>> gen = convert_generator;
|
||||||
|
|
||||||
|
ConstructFromT<int8_t> expected_values[] = {ConstructFromT<int8_t>(0),
|
||||||
|
ConstructFromT<int8_t>(1)};
|
||||||
|
VerifyGenerator(gen, expected_values);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ConvertTest, WithConverterFunctionPointer) {
|
||||||
|
int64_t (*func_ptr)(const std::string&) = [](const std::string& s) {
|
||||||
|
size_t pos;
|
||||||
|
int64_t value = std::stoll(s, &pos);
|
||||||
|
EXPECT_EQ(pos, s.size());
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
const ParamGenerator<ConstructFromT<int8_t>> gen =
|
||||||
|
ConvertGenerator(Values("0", std::string("1")), func_ptr);
|
||||||
|
|
||||||
|
ConstructFromT<int8_t> expected_values[] = {ConstructFromT<int8_t>(0),
|
||||||
|
ConstructFromT<int8_t>(1)};
|
||||||
|
VerifyGenerator(gen, expected_values);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ConvertTest, WithConverterFunctionReference) {
|
||||||
|
int64_t (*func_ptr)(const std::string&) = [](const std::string& s) {
|
||||||
|
size_t pos;
|
||||||
|
int64_t value = std::stoll(s, &pos);
|
||||||
|
EXPECT_EQ(pos, s.size());
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
int64_t (&func_ref)(const std::string&) = *func_ptr;
|
||||||
|
const ParamGenerator<ConstructFromT<int8_t>> gen =
|
||||||
|
ConvertGenerator(Values("0", std::string("1")), func_ref);
|
||||||
|
|
||||||
|
ConstructFromT<int8_t> expected_values[] = {ConstructFromT<int8_t>(0),
|
||||||
|
ConstructFromT<int8_t>(1)};
|
||||||
|
VerifyGenerator(gen, expected_values);
|
||||||
|
}
|
||||||
|
|
||||||
// Tests that an generator produces correct sequence after being
|
// Tests that an generator produces correct sequence after being
|
||||||
// assigned from another generator.
|
// assigned from another generator.
|
||||||
TEST(ParamGeneratorTest, AssignmentWorks) {
|
TEST(ParamGeneratorTest, AssignmentWorks) {
|
||||||
@ -626,7 +696,7 @@ class TestGenerationEnvironment : public ::testing::Environment {
|
|||||||
msg << "TestsExpandedAndRun/" << i;
|
msg << "TestsExpandedAndRun/" << i;
|
||||||
if (UnitTestOptions::FilterMatchesTest(
|
if (UnitTestOptions::FilterMatchesTest(
|
||||||
"TestExpansionModule/MultipleTestGenerationTest",
|
"TestExpansionModule/MultipleTestGenerationTest",
|
||||||
msg.GetString().c_str())) {
|
msg.GetString())) {
|
||||||
perform_check = true;
|
perform_check = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1104,7 +1174,7 @@ TEST_P(ParameterizedDerivedTest, SeesSequence) {
|
|||||||
class ParameterizedDeathTest : public ::testing::TestWithParam<int> {};
|
class ParameterizedDeathTest : public ::testing::TestWithParam<int> {};
|
||||||
|
|
||||||
TEST_F(ParameterizedDeathTest, GetParamDiesFromTestF) {
|
TEST_F(ParameterizedDeathTest, GetParamDiesFromTestF) {
|
||||||
EXPECT_DEATH_IF_SUPPORTED(GetParam(), ".* value-parameterized test .*");
|
EXPECT_DEATH_IF_SUPPORTED((void)GetParam(), ".* value-parameterized test .*");
|
||||||
}
|
}
|
||||||
|
|
||||||
INSTANTIATE_TEST_SUITE_P(RangeZeroToFive, ParameterizedDerivedTest,
|
INSTANTIATE_TEST_SUITE_P(RangeZeroToFive, ParameterizedDerivedTest,
|
||||||
|
|||||||
@ -288,8 +288,8 @@ TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownFileAndLine) {
|
|||||||
defined(GTEST_OS_OPENBSD) || defined(GTEST_OS_GNU_HURD)
|
defined(GTEST_OS_OPENBSD) || defined(GTEST_OS_GNU_HURD)
|
||||||
void* ThreadFunc(void* data) {
|
void* ThreadFunc(void* data) {
|
||||||
internal::Mutex* mutex = static_cast<internal::Mutex*>(data);
|
internal::Mutex* mutex = static_cast<internal::Mutex*>(data);
|
||||||
mutex->Lock();
|
mutex->lock();
|
||||||
mutex->Unlock();
|
mutex->unlock();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,7 +308,7 @@ TEST(GetThreadCountTest, ReturnsCorrectValue) {
|
|||||||
|
|
||||||
internal::Mutex mutex;
|
internal::Mutex mutex;
|
||||||
{
|
{
|
||||||
internal::MutexLock lock(&mutex);
|
internal::MutexLock lock(mutex);
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
ASSERT_EQ(0, pthread_attr_init(&attr));
|
ASSERT_EQ(0, pthread_attr_init(&attr));
|
||||||
ASSERT_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE));
|
ASSERT_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE));
|
||||||
@ -1028,7 +1028,9 @@ TEST(MutexDeathTest, AssertHeldShouldAssertWhenNotLocked) {
|
|||||||
EXPECT_DEATH_IF_SUPPORTED(
|
EXPECT_DEATH_IF_SUPPORTED(
|
||||||
{
|
{
|
||||||
Mutex m;
|
Mutex m;
|
||||||
{ MutexLock lock(&m); }
|
{
|
||||||
|
MutexLock lock(m);
|
||||||
|
}
|
||||||
m.AssertHeld();
|
m.AssertHeld();
|
||||||
},
|
},
|
||||||
"thread .*hold");
|
"thread .*hold");
|
||||||
@ -1036,13 +1038,13 @@ TEST(MutexDeathTest, AssertHeldShouldAssertWhenNotLocked) {
|
|||||||
|
|
||||||
TEST(MutexTest, AssertHeldShouldNotAssertWhenLocked) {
|
TEST(MutexTest, AssertHeldShouldNotAssertWhenLocked) {
|
||||||
Mutex m;
|
Mutex m;
|
||||||
MutexLock lock(&m);
|
MutexLock lock(m);
|
||||||
m.AssertHeld();
|
m.AssertHeld();
|
||||||
}
|
}
|
||||||
|
|
||||||
class AtomicCounterWithMutex {
|
class AtomicCounterWithMutex {
|
||||||
public:
|
public:
|
||||||
explicit AtomicCounterWithMutex(Mutex* mutex)
|
explicit AtomicCounterWithMutex(Mutex& mutex)
|
||||||
: value_(0), mutex_(mutex), random_(42) {}
|
: value_(0), mutex_(mutex), random_(42) {}
|
||||||
|
|
||||||
void Increment() {
|
void Increment() {
|
||||||
@ -1083,7 +1085,7 @@ class AtomicCounterWithMutex {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
volatile int value_;
|
volatile int value_;
|
||||||
Mutex* const mutex_; // Protects value_.
|
Mutex& mutex_; // Protects value_.
|
||||||
Random random_;
|
Random random_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1094,7 +1096,7 @@ void CountingThreadFunc(pair<AtomicCounterWithMutex*, int> param) {
|
|||||||
// Tests that the mutex only lets one thread at a time to lock it.
|
// Tests that the mutex only lets one thread at a time to lock it.
|
||||||
TEST(MutexTest, OnlyOneThreadCanLockAtATime) {
|
TEST(MutexTest, OnlyOneThreadCanLockAtATime) {
|
||||||
Mutex mutex;
|
Mutex mutex;
|
||||||
AtomicCounterWithMutex locked_counter(&mutex);
|
AtomicCounterWithMutex locked_counter(mutex);
|
||||||
|
|
||||||
typedef ThreadWithParam<pair<AtomicCounterWithMutex*, int> > ThreadType;
|
typedef ThreadWithParam<pair<AtomicCounterWithMutex*, int> > ThreadType;
|
||||||
const int kCycleCount = 20;
|
const int kCycleCount = 20;
|
||||||
|
|||||||
@ -32,6 +32,7 @@
|
|||||||
// This file tests the universal value printer.
|
// This file tests the universal value printer.
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <any>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -42,14 +43,17 @@
|
|||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "gtest/gtest-printers.h"
|
#include "gtest/gtest-printers.h"
|
||||||
@ -121,6 +125,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;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -572,6 +579,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) +
|
||||||
@ -579,7 +588,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) {
|
||||||
@ -790,7 +800,7 @@ struct Foo {
|
|||||||
TEST(PrintPointerTest, MemberVariablePointer) {
|
TEST(PrintPointerTest, MemberVariablePointer) {
|
||||||
EXPECT_TRUE(HasPrefix(Print(&Foo::value),
|
EXPECT_TRUE(HasPrefix(Print(&Foo::value),
|
||||||
Print(sizeof(&Foo::value)) + "-byte object "));
|
Print(sizeof(&Foo::value)) + "-byte object "));
|
||||||
int Foo::*p = NULL; // NOLINT
|
int Foo::* p = NULL; // NOLINT
|
||||||
EXPECT_TRUE(HasPrefix(Print(p), Print(sizeof(p)) + "-byte object "));
|
EXPECT_TRUE(HasPrefix(Print(p), Print(sizeof(p)) + "-byte object "));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -917,7 +927,7 @@ TEST(PrintArrayTest, BigArray) {
|
|||||||
PrintArrayHelper(a));
|
PrintArrayHelper(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests printing ::string and ::std::string.
|
// Tests printing ::std::string and ::string_view.
|
||||||
|
|
||||||
// ::std::string.
|
// ::std::string.
|
||||||
TEST(PrintStringTest, StringInStdNamespace) {
|
TEST(PrintStringTest, StringInStdNamespace) {
|
||||||
@ -927,6 +937,13 @@ TEST(PrintStringTest, StringInStdNamespace) {
|
|||||||
Print(str));
|
Print(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(PrintStringTest, StringViewInStdNamespace) {
|
||||||
|
const char s[] = "'\"?\\\a\b\f\n\0\r\t\v\x7F\xFF a";
|
||||||
|
const ::std::string_view str(s, sizeof(s));
|
||||||
|
EXPECT_EQ("\"'\\\"?\\\\\\a\\b\\f\\n\\0\\r\\t\\v\\x7F\\xFF a\\0\"",
|
||||||
|
Print(str));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(PrintStringTest, StringAmbiguousHex) {
|
TEST(PrintStringTest, StringAmbiguousHex) {
|
||||||
// "\x6BANANA" is ambiguous, it can be interpreted as starting with either of:
|
// "\x6BANANA" is ambiguous, it can be interpreted as starting with either of:
|
||||||
// '\x6', '\x6B', or '\x6BA'.
|
// '\x6', '\x6B', or '\x6BA'.
|
||||||
@ -944,7 +961,7 @@ TEST(PrintStringTest, StringAmbiguousHex) {
|
|||||||
EXPECT_EQ("\"!\\x5-!\"", Print(::std::string("!\x5-!")));
|
EXPECT_EQ("\"!\\x5-!\"", Print(::std::string("!\x5-!")));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests printing ::std::wstring.
|
// Tests printing ::std::wstring and ::std::wstring_view.
|
||||||
#if GTEST_HAS_STD_WSTRING
|
#if GTEST_HAS_STD_WSTRING
|
||||||
// ::std::wstring.
|
// ::std::wstring.
|
||||||
TEST(PrintWideStringTest, StringInStdNamespace) {
|
TEST(PrintWideStringTest, StringInStdNamespace) {
|
||||||
@ -956,6 +973,15 @@ TEST(PrintWideStringTest, StringInStdNamespace) {
|
|||||||
Print(str));
|
Print(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(PrintWideStringTest, StringViewInStdNamespace) {
|
||||||
|
const wchar_t s[] = L"'\"?\\\a\b\f\n\0\r\t\v\xD3\x576\x8D3\xC74D a";
|
||||||
|
const ::std::wstring_view str(s, sizeof(s) / sizeof(wchar_t));
|
||||||
|
EXPECT_EQ(
|
||||||
|
"L\"'\\\"?\\\\\\a\\b\\f\\n\\0\\r\\t\\v"
|
||||||
|
"\\xD3\\x576\\x8D3\\xC74D a\\0\"",
|
||||||
|
Print(str));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(PrintWideStringTest, StringAmbiguousHex) {
|
TEST(PrintWideStringTest, StringAmbiguousHex) {
|
||||||
// same for wide strings.
|
// same for wide strings.
|
||||||
EXPECT_EQ("L\"0\\x12\" L\"3\"", Print(::std::wstring(L"0\x12"
|
EXPECT_EQ("L\"0\\x12\" L\"3\"", Print(::std::wstring(L"0\x12"
|
||||||
@ -974,6 +1000,12 @@ TEST(PrintStringTest, U8String) {
|
|||||||
EXPECT_EQ(str, str); // Verify EXPECT_EQ compiles with this type.
|
EXPECT_EQ(str, str); // Verify EXPECT_EQ compiles with this type.
|
||||||
EXPECT_EQ("u8\"Hello, \\xE4\\xB8\\x96\\xE7\\x95\\x8C\"", Print(str));
|
EXPECT_EQ("u8\"Hello, \\xE4\\xB8\\x96\\xE7\\x95\\x8C\"", Print(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(PrintStringTest, U8StringView) {
|
||||||
|
std::u8string_view str = u8"Hello, 世界";
|
||||||
|
EXPECT_EQ(str, str); // Verify EXPECT_EQ compiles with this type.
|
||||||
|
EXPECT_EQ("u8\"Hello, \\xE4\\xB8\\x96\\xE7\\x95\\x8C\"", Print(str));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TEST(PrintStringTest, U16String) {
|
TEST(PrintStringTest, U16String) {
|
||||||
@ -982,12 +1014,24 @@ TEST(PrintStringTest, U16String) {
|
|||||||
EXPECT_EQ("u\"Hello, \\x4E16\\x754C\"", Print(str));
|
EXPECT_EQ("u\"Hello, \\x4E16\\x754C\"", Print(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(PrintStringTest, U16StringView) {
|
||||||
|
std::u16string_view str = u"Hello, 世界";
|
||||||
|
EXPECT_EQ(str, str); // Verify EXPECT_EQ compiles with this type.
|
||||||
|
EXPECT_EQ("u\"Hello, \\x4E16\\x754C\"", Print(str));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(PrintStringTest, U32String) {
|
TEST(PrintStringTest, U32String) {
|
||||||
std::u32string str = U"Hello, 🗺️";
|
std::u32string str = U"Hello, 🗺️";
|
||||||
EXPECT_EQ(str, str); // Verify EXPECT_EQ compiles with this type
|
EXPECT_EQ(str, str); // Verify EXPECT_EQ compiles with this type
|
||||||
EXPECT_EQ("U\"Hello, \\x1F5FA\\xFE0F\"", Print(str));
|
EXPECT_EQ("U\"Hello, \\x1F5FA\\xFE0F\"", Print(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(PrintStringTest, U32StringView) {
|
||||||
|
std::u32string_view str = U"Hello, 🗺️";
|
||||||
|
EXPECT_EQ(str, str); // Verify EXPECT_EQ compiles with this type
|
||||||
|
EXPECT_EQ("U\"Hello, \\x1F5FA\\xFE0F\"", Print(str));
|
||||||
|
}
|
||||||
|
|
||||||
// Tests printing types that support generic streaming (i.e. streaming
|
// Tests printing types that support generic streaming (i.e. streaming
|
||||||
// to std::basic_ostream<Char, CharTraits> for any valid Char and
|
// to std::basic_ostream<Char, CharTraits> for any valid Char and
|
||||||
// CharTraits types).
|
// CharTraits types).
|
||||||
@ -1447,7 +1491,7 @@ TEST(PrintReferenceTest, HandlesMemberFunctionPointer) {
|
|||||||
// Tests that the universal printer prints a member variable pointer
|
// Tests that the universal printer prints a member variable pointer
|
||||||
// passed by reference.
|
// passed by reference.
|
||||||
TEST(PrintReferenceTest, HandlesMemberVariablePointer) {
|
TEST(PrintReferenceTest, HandlesMemberVariablePointer) {
|
||||||
int Foo::*p = &Foo::value; // NOLINT
|
int Foo::* p = &Foo::value; // NOLINT
|
||||||
EXPECT_TRUE(HasPrefix(PrintByRef(p), "@" + PrintPointer(&p) + " " +
|
EXPECT_TRUE(HasPrefix(PrintByRef(p), "@" + PrintPointer(&p) + " " +
|
||||||
Print(sizeof(p)) + "-byte object "));
|
Print(sizeof(p)) + "-byte object "));
|
||||||
}
|
}
|
||||||
@ -1655,7 +1699,7 @@ TEST(PrintToStringTest, ContainsNonLatin) {
|
|||||||
EXPECT_PRINT_TO_STRING_(non_ascii_str,
|
EXPECT_PRINT_TO_STRING_(non_ascii_str,
|
||||||
"\"\\xEC\\x98\\xA4\\xEC\\xA0\\x84 4:30\"\n"
|
"\"\\xEC\\x98\\xA4\\xEC\\xA0\\x84 4:30\"\n"
|
||||||
" As Text: \"오전 4:30\"");
|
" As Text: \"오전 4:30\"");
|
||||||
non_ascii_str = ::std::string("From ä — ẑ");
|
non_ascii_str = "From ä — ẑ";
|
||||||
EXPECT_PRINT_TO_STRING_(non_ascii_str,
|
EXPECT_PRINT_TO_STRING_(non_ascii_str,
|
||||||
"\"From \\xC3\\xA4 \\xE2\\x80\\x94 \\xE1\\xBA\\x91\""
|
"\"From \\xC3\\xA4 \\xE2\\x80\\x94 \\xE1\\xBA\\x91\""
|
||||||
"\n As Text: \"From ä — ẑ\"");
|
"\n As Text: \"From ä — ẑ\"");
|
||||||
@ -1885,6 +1929,22 @@ TEST(UniversalPrintTest, SmartPointers) {
|
|||||||
PrintToString(std::shared_ptr<void>(p.get(), [](void*) {})));
|
PrintToString(std::shared_ptr<void>(p.get(), [](void*) {})));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(UniversalPrintTest, StringViewNonZeroTerminated) {
|
||||||
|
// Craft a non-ASCII UTF-8 input (to trigger a special path in
|
||||||
|
// `ConditionalPrintAsText`). Use array notation instead of the string
|
||||||
|
// literal syntax, to avoid placing a terminating 0 at the end of the input.
|
||||||
|
const char s[] = {'\357', '\243', '\242', 'X'};
|
||||||
|
// Only include the first 3 bytes in the `string_view` and leave the last one
|
||||||
|
// ('X') outside. This way, if the code tries to use `str.data()` with
|
||||||
|
// `strlen` instead of `str.size()`, it will include 'X' and cause a visible
|
||||||
|
// difference (in addition to ASAN tests detecting a buffer overflow due to
|
||||||
|
// the missing 0 at the end).
|
||||||
|
const ::std::string_view str(s, 3);
|
||||||
|
::std::stringstream ss;
|
||||||
|
UniversalPrint(str, &ss);
|
||||||
|
EXPECT_EQ("\"\\xEF\\xA3\\xA2\"\n As Text: \"\xEF\xA3\xA2\"", ss.str());
|
||||||
|
}
|
||||||
|
|
||||||
TEST(UniversalTersePrintTupleFieldsToStringsTestWithStd, PrintsEmptyTuple) {
|
TEST(UniversalTersePrintTupleFieldsToStringsTestWithStd, PrintsEmptyTuple) {
|
||||||
Strings result = UniversalTersePrintTupleFieldsToStrings(::std::make_tuple());
|
Strings result = UniversalTersePrintTupleFieldsToStrings(::std::make_tuple());
|
||||||
EXPECT_EQ(0u, result.size());
|
EXPECT_EQ(0u, result.size());
|
||||||
@ -1914,7 +1974,6 @@ TEST(UniversalTersePrintTupleFieldsToStringsTestWithStd, PrintsTersely) {
|
|||||||
EXPECT_EQ("\"a\"", result[1]);
|
EXPECT_EQ("\"a\"", result[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if GTEST_INTERNAL_HAS_ANY
|
|
||||||
class PrintAnyTest : public ::testing::Test {
|
class PrintAnyTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -1928,12 +1987,12 @@ class PrintAnyTest : public ::testing::Test {
|
|||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(PrintAnyTest, Empty) {
|
TEST_F(PrintAnyTest, Empty) {
|
||||||
internal::Any any;
|
std::any any;
|
||||||
EXPECT_EQ("no value", PrintToString(any));
|
EXPECT_EQ("no value", PrintToString(any));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(PrintAnyTest, NonEmpty) {
|
TEST_F(PrintAnyTest, NonEmpty) {
|
||||||
internal::Any any;
|
std::any any;
|
||||||
constexpr int val1 = 10;
|
constexpr int val1 = 10;
|
||||||
const std::string val2 = "content";
|
const std::string val2 = "content";
|
||||||
|
|
||||||
@ -1944,27 +2003,23 @@ TEST_F(PrintAnyTest, NonEmpty) {
|
|||||||
EXPECT_EQ("value of type " + ExpectedTypeName<std::string>(),
|
EXPECT_EQ("value of type " + ExpectedTypeName<std::string>(),
|
||||||
PrintToString(any));
|
PrintToString(any));
|
||||||
}
|
}
|
||||||
#endif // GTEST_INTERNAL_HAS_ANY
|
|
||||||
|
|
||||||
#if GTEST_INTERNAL_HAS_OPTIONAL
|
|
||||||
TEST(PrintOptionalTest, Basic) {
|
TEST(PrintOptionalTest, Basic) {
|
||||||
EXPECT_EQ("(nullopt)", PrintToString(internal::Nullopt()));
|
EXPECT_EQ("(nullopt)", PrintToString(std::nullopt));
|
||||||
internal::Optional<int> value;
|
std::optional<int> value;
|
||||||
EXPECT_EQ("(nullopt)", PrintToString(value));
|
EXPECT_EQ("(nullopt)", PrintToString(value));
|
||||||
value = {7};
|
value = {7};
|
||||||
EXPECT_EQ("(7)", PrintToString(value));
|
EXPECT_EQ("(7)", PrintToString(value));
|
||||||
EXPECT_EQ("(1.1)", PrintToString(internal::Optional<double>{1.1}));
|
EXPECT_EQ("(1.1)", PrintToString(std::optional<double>{1.1}));
|
||||||
EXPECT_EQ("(\"A\")", PrintToString(internal::Optional<std::string>{"A"}));
|
EXPECT_EQ("(\"A\")", PrintToString(std::optional<std::string>{"A"}));
|
||||||
}
|
}
|
||||||
#endif // GTEST_INTERNAL_HAS_OPTIONAL
|
|
||||||
|
|
||||||
#if GTEST_INTERNAL_HAS_VARIANT
|
|
||||||
struct NonPrintable {
|
struct NonPrintable {
|
||||||
unsigned char contents = 17;
|
unsigned char contents = 17;
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST(PrintOneofTest, Basic) {
|
TEST(PrintOneofTest, Basic) {
|
||||||
using Type = internal::Variant<int, StreamableInGlobal, NonPrintable>;
|
using Type = std::variant<int, StreamableInGlobal, NonPrintable>;
|
||||||
EXPECT_EQ("('int(index = 0)' with value 7)", PrintToString(Type(7)));
|
EXPECT_EQ("('int(index = 0)' with value 7)", PrintToString(Type(7)));
|
||||||
EXPECT_EQ("('StreamableInGlobal(index = 1)' with value StreamableInGlobal)",
|
EXPECT_EQ("('StreamableInGlobal(index = 1)' with value StreamableInGlobal)",
|
||||||
PrintToString(Type(StreamableInGlobal{})));
|
PrintToString(Type(StreamableInGlobal{})));
|
||||||
@ -1973,7 +2028,6 @@ TEST(PrintOneofTest, Basic) {
|
|||||||
"1-byte object <11>)",
|
"1-byte object <11>)",
|
||||||
PrintToString(Type(NonPrintable{})));
|
PrintToString(Type(NonPrintable{})));
|
||||||
}
|
}
|
||||||
#endif // GTEST_INTERNAL_HAS_VARIANT
|
|
||||||
|
|
||||||
#if GTEST_INTERNAL_HAS_COMPARE_LIB
|
#if GTEST_INTERNAL_HAS_COMPARE_LIB
|
||||||
TEST(PrintOrderingTest, Basic) {
|
TEST(PrintOrderingTest, Basic) {
|
||||||
|
|||||||
@ -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) {}
|
||||||
|
|||||||
@ -95,9 +95,9 @@ void ManyAsserts(int id) {
|
|||||||
|
|
||||||
// RecordProperty() should interact safely with other threads as well.
|
// RecordProperty() should interact safely with other threads as well.
|
||||||
// The shared_key forces property updates.
|
// The shared_key forces property updates.
|
||||||
Test::RecordProperty(IdToKey(id, "string").c_str(), IdToString(id).c_str());
|
Test::RecordProperty(IdToKey(id, "string"), IdToString(id));
|
||||||
Test::RecordProperty(IdToKey(id, "int").c_str(), id);
|
Test::RecordProperty(IdToKey(id, "int").c_str(), id);
|
||||||
Test::RecordProperty("shared_key", IdToString(id).c_str());
|
Test::RecordProperty("shared_key", IdToString(id));
|
||||||
|
|
||||||
// This assertion should fail kThreadCount times per thread. It
|
// This assertion should fail kThreadCount times per thread. It
|
||||||
// is for testing whether Google Test can handle failed assertions in a
|
// is for testing whether Google Test can handle failed assertions in a
|
||||||
|
|||||||
@ -2163,7 +2163,7 @@ class UnitTestRecordPropertyTestEnvironment : public Environment {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// This will test property recording outside of any test or test case.
|
// This will test property recording outside of any test or test case.
|
||||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static Environment* record_property_env =
|
[[maybe_unused]] static Environment* record_property_env =
|
||||||
AddGlobalTestEnvironment(new UnitTestRecordPropertyTestEnvironment);
|
AddGlobalTestEnvironment(new UnitTestRecordPropertyTestEnvironment);
|
||||||
|
|
||||||
// This group of tests is for predicate assertions (ASSERT_PRED*, etc)
|
// This group of tests is for predicate assertions (ASSERT_PRED*, etc)
|
||||||
@ -2649,8 +2649,8 @@ TEST(IsSubstringTest, GeneratesCorrectMessageForCString) {
|
|||||||
// Tests that IsSubstring returns the correct result when the input
|
// Tests that IsSubstring returns the correct result when the input
|
||||||
// argument type is ::std::string.
|
// argument type is ::std::string.
|
||||||
TEST(IsSubstringTest, ReturnsCorrectResultsForStdString) {
|
TEST(IsSubstringTest, ReturnsCorrectResultsForStdString) {
|
||||||
EXPECT_TRUE(IsSubstring("", "", std::string("hello"), "ahellob"));
|
EXPECT_TRUE(IsSubstring("", "", "hello", "ahellob"));
|
||||||
EXPECT_FALSE(IsSubstring("", "", "hello", std::string("world")));
|
EXPECT_FALSE(IsSubstring("", "", "hello", "world"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if GTEST_HAS_STD_WSTRING
|
#if GTEST_HAS_STD_WSTRING
|
||||||
@ -2707,8 +2707,8 @@ TEST(IsNotSubstringTest, GeneratesCorrectMessageForWideCString) {
|
|||||||
// Tests that IsNotSubstring returns the correct result when the input
|
// Tests that IsNotSubstring returns the correct result when the input
|
||||||
// argument type is ::std::string.
|
// argument type is ::std::string.
|
||||||
TEST(IsNotSubstringTest, ReturnsCorrectResultsForStdString) {
|
TEST(IsNotSubstringTest, ReturnsCorrectResultsForStdString) {
|
||||||
EXPECT_FALSE(IsNotSubstring("", "", std::string("hello"), "ahellob"));
|
EXPECT_FALSE(IsNotSubstring("", "", "hello", "ahellob"));
|
||||||
EXPECT_TRUE(IsNotSubstring("", "", "hello", std::string("world")));
|
EXPECT_TRUE(IsNotSubstring("", "", "hello", "world"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that IsNotSubstring() generates the correct message when the input
|
// Tests that IsNotSubstring() generates the correct message when the input
|
||||||
@ -2719,8 +2719,7 @@ TEST(IsNotSubstringTest, GeneratesCorrectMessageForStdString) {
|
|||||||
" Actual: \"needle\"\n"
|
" Actual: \"needle\"\n"
|
||||||
"Expected: not a substring of haystack_expr\n"
|
"Expected: not a substring of haystack_expr\n"
|
||||||
"Which is: \"two needles\"",
|
"Which is: \"two needles\"",
|
||||||
IsNotSubstring("needle_expr", "haystack_expr", ::std::string("needle"),
|
IsNotSubstring("needle_expr", "haystack_expr", "needle", "two needles")
|
||||||
"two needles")
|
|
||||||
.failure_message());
|
.failure_message());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3579,13 +3578,13 @@ TEST(EditDistance, TestSuites) {
|
|||||||
{__LINE__, "A", "A", " ", ""},
|
{__LINE__, "A", "A", " ", ""},
|
||||||
{__LINE__, "ABCDE", "ABCDE", " ", ""},
|
{__LINE__, "ABCDE", "ABCDE", " ", ""},
|
||||||
// Simple adds.
|
// Simple adds.
|
||||||
{__LINE__, "X", "XA", " +", "@@ +1,2 @@\n X\n+A\n"},
|
{__LINE__, "X", "XA", " +", "@@ -1 +1,2 @@\n X\n+A\n"},
|
||||||
{__LINE__, "X", "XABCD", " ++++", "@@ +1,5 @@\n X\n+A\n+B\n+C\n+D\n"},
|
{__LINE__, "X", "XABCD", " ++++", "@@ -1 +1,5 @@\n X\n+A\n+B\n+C\n+D\n"},
|
||||||
// Simple removes.
|
// Simple removes.
|
||||||
{__LINE__, "XA", "X", " -", "@@ -1,2 @@\n X\n-A\n"},
|
{__LINE__, "XA", "X", " -", "@@ -1,2 +1 @@\n X\n-A\n"},
|
||||||
{__LINE__, "XABCD", "X", " ----", "@@ -1,5 @@\n X\n-A\n-B\n-C\n-D\n"},
|
{__LINE__, "XABCD", "X", " ----", "@@ -1,5 +1 @@\n X\n-A\n-B\n-C\n-D\n"},
|
||||||
// Simple replaces.
|
// Simple replaces.
|
||||||
{__LINE__, "A", "a", "/", "@@ -1,1 +1,1 @@\n-A\n+a\n"},
|
{__LINE__, "A", "a", "/", "@@ -1 +1 @@\n-A\n+a\n"},
|
||||||
{__LINE__, "ABCD", "abcd", "////",
|
{__LINE__, "ABCD", "abcd", "////",
|
||||||
"@@ -1,4 +1,4 @@\n-A\n-B\n-C\n-D\n+a\n+b\n+c\n+d\n"},
|
"@@ -1,4 +1,4 @@\n-A\n-B\n-C\n-D\n+a\n+b\n+c\n+d\n"},
|
||||||
// Path finding.
|
// Path finding.
|
||||||
@ -3655,8 +3654,7 @@ TEST(AssertionTest, EqFailure) {
|
|||||||
msg4.c_str());
|
msg4.c_str());
|
||||||
|
|
||||||
const std::string msg5(
|
const std::string msg5(
|
||||||
EqFailure("foo", "bar", std::string("\"x\""), std::string("\"y\""), true)
|
EqFailure("foo", "bar", "\"x\"", "\"y\"", true).failure_message());
|
||||||
.failure_message());
|
|
||||||
EXPECT_STREQ(
|
EXPECT_STREQ(
|
||||||
"Expected equality of these values:\n"
|
"Expected equality of these values:\n"
|
||||||
" foo\n"
|
" foo\n"
|
||||||
@ -6717,6 +6715,9 @@ TEST(ColoredOutputTest, UsesColorsWhenTermSupportsColors) {
|
|||||||
SetEnv("TERM", "xterm-color"); // TERM supports colors.
|
SetEnv("TERM", "xterm-color"); // TERM supports colors.
|
||||||
EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
|
EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
|
||||||
|
|
||||||
|
SetEnv("TERM", "xterm-ghostty"); // TERM supports colors.
|
||||||
|
EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
|
||||||
|
|
||||||
SetEnv("TERM", "xterm-kitty"); // TERM supports colors.
|
SetEnv("TERM", "xterm-kitty"); // TERM supports colors.
|
||||||
EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
|
EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
|
||||||
|
|
||||||
@ -6754,9 +6755,8 @@ TEST(ColoredOutputTest, UsesColorsWhenTermSupportsColors) {
|
|||||||
|
|
||||||
// Verifies that StaticAssertTypeEq works in a namespace scope.
|
// Verifies that StaticAssertTypeEq works in a namespace scope.
|
||||||
|
|
||||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool dummy1 =
|
[[maybe_unused]] static bool dummy1 = StaticAssertTypeEq<bool, bool>();
|
||||||
StaticAssertTypeEq<bool, bool>();
|
[[maybe_unused]] static bool dummy2 =
|
||||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool dummy2 =
|
|
||||||
StaticAssertTypeEq<const int, const int>();
|
StaticAssertTypeEq<const int, const int>();
|
||||||
|
|
||||||
// Verifies that StaticAssertTypeEq works in a class.
|
// Verifies that StaticAssertTypeEq works in a class.
|
||||||
|
|||||||
@ -17,9 +17,25 @@ def googletest_deps():
|
|||||||
if not native.existing_rule("abseil-cpp"):
|
if not native.existing_rule("abseil-cpp"):
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "abseil-cpp",
|
name = "abseil-cpp",
|
||||||
sha256 = "16242f394245627e508ec6bb296b433c90f8d914f73b9c026fddb905e27276e8",
|
sha256 = "9b2b72d4e8367c0b843fa2bcfa2b08debbe3cee34f7aaa27de55a6cbb3e843db",
|
||||||
strip_prefix = "abseil-cpp-20250127.0",
|
strip_prefix = "abseil-cpp-20250814.0",
|
||||||
urls = ["https://github.com/abseil/abseil-cpp/releases/download/20250127.0/abseil-cpp-20250127.0.tar.gz"],
|
urls = ["https://github.com/abseil/abseil-cpp/releases/download/20250814.0/abseil-cpp-20250814.0.tar.gz"],
|
||||||
|
)
|
||||||
|
|
||||||
|
if not native.existing_rule("bazel_features"):
|
||||||
|
http_archive(
|
||||||
|
name = "bazel_features",
|
||||||
|
sha256 = "9390b391a68d3b24aef7966bce8556d28003fe3f022a5008efc7807e8acaaf1a",
|
||||||
|
strip_prefix = "bazel_features-1.36.0",
|
||||||
|
url = "https://github.com/bazel-contrib/bazel_features/releases/download/v1.36.0/bazel_features-v1.36.0.tar.gz",
|
||||||
|
)
|
||||||
|
|
||||||
|
if not native.existing_rule("rules_cc"):
|
||||||
|
http_archive(
|
||||||
|
name = "rules_cc",
|
||||||
|
sha256 = "207ea073dd20a705f9e8bc5ac02f5203e9621fc672774bb1a0935aefab7aebfa",
|
||||||
|
strip_prefix = "rules_cc-0.2.8",
|
||||||
|
url = "https://github.com/bazelbuild/rules_cc/releases/download/0.2.8/rules_cc-0.2.8.tar.gz",
|
||||||
)
|
)
|
||||||
|
|
||||||
if not native.existing_rule("fuchsia_sdk"):
|
if not native.existing_rule("fuchsia_sdk"):
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user