Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7260682388 | ||
|
|
0daf775f8c | ||
|
|
1a447fdce7 | ||
|
|
91c99b6ffe | ||
|
|
7358557f03 | ||
|
|
71edd0ef29 | ||
|
|
a2118f6587 | ||
|
|
49495eacfd | ||
|
|
aa1eefe02c | ||
|
|
002d14757f | ||
|
|
02e50550c6 | ||
|
|
963dd8ea18 | ||
|
|
d89aac5f0d | ||
|
|
4cb0ab12a1 | ||
|
|
c0afb7f69d | ||
|
|
4f472747b1 | ||
|
|
b607d9f590 | ||
|
|
c5a47cc5bd | ||
|
|
488c47cc68 | ||
|
|
5f9ad7d401 | ||
|
|
51725d1111 | ||
|
|
92f71eddb0 | ||
|
|
1b6f64d659 | ||
|
|
3940de9189 | ||
|
|
a0f06a70e3 | ||
|
|
3ff51c3e80 | ||
|
|
c6f04243ed | ||
|
|
af4c3cfcb3 | ||
|
|
ecb18f0b03 | ||
|
|
806b89cf63 | ||
|
|
b78aa5ee64 | ||
|
|
56cf341d9c | ||
|
|
136a6b8865 | ||
|
|
425811f10e | ||
|
|
679a61d3a8 | ||
|
|
80b3670e1a | ||
|
|
44f4904703 | ||
|
|
fef8e5e23b | ||
|
|
a798392000 | ||
|
|
c914e89e2a | ||
|
|
0dbcd8d006 | ||
|
|
1269db9643 | ||
|
|
a901203eff | ||
|
|
d4e2591485 | ||
|
|
7ec05f657d | ||
|
|
a503186d79 | ||
|
|
7f7595f67d | ||
|
|
e331081278 | ||
|
|
08da6214b8 | ||
|
|
1be4946590 | ||
|
|
30a3151b0c | ||
|
|
51109ebb47 | ||
|
|
fcd5e26089 | ||
|
|
fa005b296f | ||
|
|
4141c384aa | ||
|
|
a25f43576e | ||
|
|
b973ccb9ab | ||
|
|
f132c89311 | ||
|
|
961158b5e3 | ||
|
|
86ec940f63 | ||
|
|
bc410696f4 | ||
|
|
8240fa7d62 | ||
|
|
7d012aa162 | ||
|
|
cd975499e8 | ||
|
|
3064a609c7 | ||
|
|
3549aa63f2 | ||
|
|
985d542c73 | ||
|
|
18c6bc3dc4 | ||
|
|
22bda2ba15 | ||
|
|
df4fdc5cfd | ||
|
|
1c2082e8bd | ||
|
|
5b39f4c876 | ||
|
|
973323ed64 | ||
|
|
78f6d54f9f | ||
|
|
8b53336594 | ||
|
|
aa40ee603e | ||
|
|
d4a1a3599b | ||
|
|
1fc11dea10 | ||
|
|
0b1e895ba4 | ||
|
|
44f22083d7 | ||
|
|
b7ced159db | ||
|
|
7140cd416c | ||
|
|
a721f1b20c | ||
|
|
8736d2cd5c | ||
|
|
09f45f51fb | ||
|
|
add971c7cb | ||
|
|
4969916f0c | ||
|
|
dc3c9eda2f | ||
|
|
d72f9c8aea | ||
|
|
5fddfab2d2 | ||
|
|
2461743991 | ||
|
|
015950a936 | ||
|
|
f38004c441 | ||
|
|
94be250af7 | ||
|
|
a35bc7693c | ||
|
|
f426a71abf | ||
|
|
73a63ea05d | ||
|
|
a407966592 | ||
|
|
73e0fc18eb | ||
|
|
e9907112b4 | ||
|
|
850cb69efd | ||
|
|
77f6bd3e75 | ||
|
|
f68374efa7 | ||
|
|
ef6cf65af5 | ||
|
|
5a9c3f9e8d | ||
|
|
32c3dce34b | ||
|
|
872d386a87 | ||
|
|
2151d93c2f | ||
|
|
7c3b4d54e3 | ||
|
|
56efe39831 | ||
|
|
5fd443cdc3 | ||
|
|
85087857ad | ||
|
|
ff6133ab49 | ||
|
|
cb1bd88191 | ||
|
|
5554fcaab4 | ||
|
|
7d7e750850 | ||
|
|
76cd89bcf1 | ||
|
|
9156d4caac | ||
|
|
065127f1e4 | ||
|
|
0b65649543 | ||
|
|
1b96fa13f5 | ||
|
|
085af2cc08 | ||
|
|
37678c92fb | ||
|
|
dedab73a68 | ||
|
|
d54d30fecb | ||
|
|
ae2b601bea | ||
|
|
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 |
+31
-5
@@ -30,6 +30,8 @@
|
||||
#
|
||||
# Bazel Build for Google C++ Testing Framework(Google Test)
|
||||
|
||||
load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
@@ -56,6 +58,16 @@ config_setting(
|
||||
constraint_values = ["@platforms//os:openbsd"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "emscripten_without_threads",
|
||||
constraint_values = [
|
||||
"@platforms//os:emscripten",
|
||||
],
|
||||
values = {
|
||||
"features": "-use_pthreads",
|
||||
},
|
||||
)
|
||||
|
||||
# NOTE: Fuchsia is not an officially supported platform.
|
||||
config_setting(
|
||||
name = "fuchsia",
|
||||
@@ -83,6 +95,10 @@ cc_library(
|
||||
)
|
||||
|
||||
# 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(
|
||||
name = "gtest",
|
||||
srcs = glob(
|
||||
@@ -107,10 +123,12 @@ cc_library(
|
||||
copts = select({
|
||||
":qnx": [],
|
||||
":windows": [],
|
||||
":emscripten_without_threads": [],
|
||||
"//conditions:default": ["-pthread"],
|
||||
}),
|
||||
defines = select({
|
||||
":has_absl": ["GTEST_HAS_ABSL=1"],
|
||||
":emscripten_without_threads": ["GTEST_HAS_PTHREAD=0"],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
features = select({
|
||||
@@ -134,6 +152,7 @@ cc_library(
|
||||
"-lm",
|
||||
"-pthread",
|
||||
],
|
||||
":emscripten_without_threads": [],
|
||||
"//conditions:default": ["-pthread"],
|
||||
}),
|
||||
deps = select({
|
||||
@@ -147,10 +166,7 @@ cc_library(
|
||||
"@abseil-cpp//absl/flags:reflection",
|
||||
"@abseil-cpp//absl/flags:usage",
|
||||
"@abseil-cpp//absl/strings",
|
||||
"@abseil-cpp//absl/types:any",
|
||||
"@abseil-cpp//absl/types:optional",
|
||||
"@abseil-cpp//absl/types:variant",
|
||||
"@re2//:re2",
|
||||
"@re2",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}) + select({
|
||||
@@ -160,13 +176,22 @@ cc_library(
|
||||
# Otherwise, builds targeting Fuchsia would fail to compile.
|
||||
":fuchsia": [
|
||||
"@fuchsia_sdk//pkg/fdio",
|
||||
"@fuchsia_sdk//pkg/syslog",
|
||||
"@fuchsia_sdk//pkg/zx",
|
||||
],
|
||||
"//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(
|
||||
name = "gtest_main",
|
||||
srcs = ["googlemock/src/gmock_main.cc"],
|
||||
@@ -175,6 +200,7 @@ cc_library(
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
deps = [":gtest"],
|
||||
alwayslink = True,
|
||||
)
|
||||
|
||||
# The following rules build samples of how to use gTest.
|
||||
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
# Note: CMake support is community-based. The maintainers do not use CMake
|
||||
# internally.
|
||||
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(googletest-distribution)
|
||||
set(GOOGLETEST_VERSION 1.15.2)
|
||||
set(GOOGLETEST_VERSION 1.18.0)
|
||||
|
||||
if(NOT CYGWIN AND NOT MSYS AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL QNX)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
+9
-5
@@ -41,20 +41,24 @@ module(
|
||||
|
||||
bazel_dep(
|
||||
name = "abseil-cpp",
|
||||
version = "20250127.0",
|
||||
version = "20260526.0",
|
||||
)
|
||||
bazel_dep(
|
||||
name = "platforms",
|
||||
version = "0.0.10",
|
||||
version = "1.1.0",
|
||||
)
|
||||
bazel_dep(
|
||||
name = "re2",
|
||||
version = "2024-07-02",
|
||||
version = "2025-11-05.bcr.1",
|
||||
)
|
||||
bazel_dep(
|
||||
name = "rules_cc",
|
||||
version = "0.2.22",
|
||||
)
|
||||
|
||||
bazel_dep(
|
||||
name = "rules_python",
|
||||
version = "1.1.0",
|
||||
version = "2.2.0",
|
||||
dev_dependency = True,
|
||||
)
|
||||
|
||||
@@ -67,7 +71,7 @@ python = use_extension(
|
||||
python.toolchain(
|
||||
ignore_root_user_error = True,
|
||||
is_default = True,
|
||||
python_version = "3.12",
|
||||
python_version = "3.13",
|
||||
)
|
||||
|
||||
# See fake_fuchsia_sdk.bzl for instructions on how to override this with a real SDK, if needed.
|
||||
|
||||
@@ -2,27 +2,19 @@
|
||||
|
||||
### 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
|
||||
|
||||
Our documentation is now live on GitHub Pages at
|
||||
https://google.github.io/googletest/. We recommend browsing the documentation on
|
||||
GitHub Pages rather than directly in the repository.
|
||||
|
||||
#### Release 1.15.2
|
||||
#### Release 1.18.0
|
||||
|
||||
[Release 1.15.2](https://github.com/google/googletest/releases/tag/v1.15.2) is
|
||||
[Release 1.18.0](https://github.com/google/googletest/releases/tag/v1.18.0) is
|
||||
now available.
|
||||
|
||||
The 1.15.x branch requires at least C++14.
|
||||
The 1.18.x branch
|
||||
[requires at least C++17](https://opensource.google/documentation/policies/cplusplus-support#c_language_standard).
|
||||
|
||||
#### Continuous Integration
|
||||
|
||||
@@ -52,35 +44,35 @@ More information about building GoogleTest can be found at
|
||||
|
||||
* xUnit test framework: \
|
||||
Googletest is based on the [xUnit](https://en.wikipedia.org/wiki/XUnit)
|
||||
testing framework, a popular architecture for unit testing
|
||||
testing framework, a popular architecture for unit testing.
|
||||
* Test discovery: \
|
||||
Googletest automatically discovers and runs your tests, eliminating the need
|
||||
to manually register your tests
|
||||
to manually register your tests.
|
||||
* Rich set of assertions: \
|
||||
Googletest provides a variety of assertions, such as equality, inequality,
|
||||
exceptions, and more, making it easy to test your code
|
||||
exceptions, and more, making it easy to test your code.
|
||||
* User-defined assertions: \
|
||||
You can define your own assertions with Googletest, making it simple to
|
||||
write tests that are specific to your code
|
||||
write tests that are specific to your code.
|
||||
* Death tests: \
|
||||
Googletest supports death tests, which verify that your code exits in a
|
||||
certain way, making it useful for testing error-handling code
|
||||
certain way, making it useful for testing error-handling code.
|
||||
* Fatal and non-fatal failures: \
|
||||
You can specify whether a test failure should be treated as fatal or
|
||||
non-fatal with Googletest, allowing tests to continue running even if a
|
||||
failure occurs
|
||||
failure occurs.
|
||||
* Value-parameterized tests: \
|
||||
Googletest supports value-parameterized tests, which run multiple times with
|
||||
different input values, making it useful for testing functions that take
|
||||
different inputs
|
||||
different inputs.
|
||||
* Type-parameterized tests: \
|
||||
Googletest also supports type-parameterized tests, which run with different
|
||||
data types, making it useful for testing functions that work with different
|
||||
data types
|
||||
data types.
|
||||
* Various options for running tests: \
|
||||
Googletest provides many options for running tests including running
|
||||
individual tests, running tests in a specific order and running tests in
|
||||
parallel
|
||||
parallel.
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
|
||||
@@ -31,31 +31,36 @@
|
||||
workspace(name = "googletest")
|
||||
|
||||
load("//:googletest_deps.bzl", "googletest_deps")
|
||||
|
||||
googletest_deps()
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
http_archive(
|
||||
name = "rules_python",
|
||||
sha256 = "9c6e26911a79fbf510a8f06d8eedb40f412023cf7fa6d1461def27116bff022c",
|
||||
strip_prefix = "rules_python-1.1.0",
|
||||
url = "https://github.com/bazelbuild/rules_python/releases/download/1.1.0/rules_python-1.1.0.tar.gz",
|
||||
sha256 = "e11d2e1efce1589e5bdfa93986712c74fc7467a0f093143d489d2ef5ebb1ed2a",
|
||||
strip_prefix = "rules_python-2.2.0",
|
||||
url = "https://github.com/bazelbuild/rules_python/releases/download/2.2.0/rules_python-2.2.0.tar.gz",
|
||||
)
|
||||
|
||||
# https://github.com/bazelbuild/rules_python/releases/tag/1.1.0
|
||||
load("@rules_python//python:repositories.bzl", "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"],
|
||||
name = "platforms",
|
||||
sha256 = "dbad4a23abcca6171e47b79edc53bd6a41067a3b75f9e8b104656b459ff25046",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/1.1.0/platforms-1.1.0.tar.gz",
|
||||
"https://github.com/bazelbuild/platforms/releases/download/1.1.0/platforms-1.1.0.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "platforms",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.10/platforms-0.0.10.tar.gz",
|
||||
"https://github.com/bazelbuild/platforms/releases/download/0.0.10/platforms-0.0.10.tar.gz",
|
||||
],
|
||||
sha256 = "218efe8ee736d26a3572663b374a253c012b716d8af0c07e842e82f238a0a7ee",
|
||||
)
|
||||
load("@bazel_features//:deps.bzl", "bazel_features_deps")
|
||||
|
||||
bazel_features_deps()
|
||||
|
||||
load("@rules_cc//cc:extensions.bzl", "compatibility_proxy_repo")
|
||||
|
||||
compatibility_proxy_repo()
|
||||
|
||||
+105
-63
@@ -31,62 +31,94 @@
|
||||
|
||||
set -euox pipefail
|
||||
|
||||
readonly LINUX_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20241218"
|
||||
readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20250205"
|
||||
readonly LINUX_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest@sha256:baa99e65a3cc837bab8e5246f1870d25c76d0adf2b1d598ee5a3ec77fd2e19bd"
|
||||
|
||||
if [[ -z ${GTEST_ROOT:-} ]]; then
|
||||
GTEST_ROOT="$(realpath $(dirname ${0})/..)"
|
||||
fi
|
||||
|
||||
if [[ -z ${STD:-} ]]; then
|
||||
STD="c++14 c++17 c++20"
|
||||
# Use Bazel Vendor mode to reduce reliance on external dependencies.
|
||||
# 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
|
||||
|
||||
# Test the CMake build
|
||||
for cc in /usr/local/bin/gcc /opt/llvm/clang/bin/clang; do
|
||||
for cmake_off_on in OFF ON; do
|
||||
time docker run \
|
||||
--volume="${GTEST_ROOT}:/src:ro" \
|
||||
--tmpfs="/build:exec" \
|
||||
--workdir="/build" \
|
||||
--rm \
|
||||
--env="CC=${cc}" \
|
||||
--env=CXXFLAGS="-Werror -Wdeprecated" \
|
||||
${LINUX_LATEST_CONTAINER} \
|
||||
/bin/bash -c "
|
||||
cmake /src \
|
||||
-DCMAKE_CXX_STANDARD=14 \
|
||||
-Dgtest_build_samples=ON \
|
||||
-Dgtest_build_tests=ON \
|
||||
-Dgmock_build_tests=ON \
|
||||
-Dcxx_no_exception=${cmake_off_on} \
|
||||
-Dcxx_no_rtti=${cmake_off_on} && \
|
||||
make -j$(nproc) && \
|
||||
ctest -j$(nproc) --output-on-failure"
|
||||
done
|
||||
if [[ -z ${STD:-} ]]; then
|
||||
STD="c++17 c++20 c++23"
|
||||
fi
|
||||
|
||||
# Test CMake + GCC
|
||||
for cmake_off_on in OFF ON; do
|
||||
time docker run \
|
||||
--volume="${GTEST_ROOT}:/src:ro" \
|
||||
--tmpfs="/build:exec" \
|
||||
--workdir="/build" \
|
||||
--rm \
|
||||
--env="CC=/usr/local/bin/gcc" \
|
||||
--env=CXXFLAGS="-Werror -Wdeprecated" \
|
||||
${LINUX_LATEST_CONTAINER} \
|
||||
/bin/bash -c "
|
||||
cmake /src \
|
||||
-DCMAKE_CXX_STANDARD=17 \
|
||||
-Dgtest_build_samples=ON \
|
||||
-Dgtest_build_tests=ON \
|
||||
-Dgmock_build_tests=ON \
|
||||
-Dcxx_no_exception=${cmake_off_on} \
|
||||
-Dcxx_no_rtti=${cmake_off_on} && \
|
||||
make -j$(nproc) && \
|
||||
ctest -j$(nproc) --output-on-failure"
|
||||
done
|
||||
|
||||
# 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/bin/clang" \
|
||||
--env=CXXFLAGS="-Werror -Wdeprecated --gcc-toolchain=/usr/local" \
|
||||
${LINUX_LATEST_CONTAINER} \
|
||||
/bin/bash -c "
|
||||
cmake /src \
|
||||
-DCMAKE_CXX_STANDARD=17 \
|
||||
-Dgtest_build_samples=ON \
|
||||
-Dgtest_build_tests=ON \
|
||||
-Dgmock_build_tests=ON \
|
||||
-Dcxx_no_exception=${cmake_off_on} \
|
||||
-Dcxx_no_rtti=${cmake_off_on} && \
|
||||
make -j$(nproc) && \
|
||||
ctest -j$(nproc) --output-on-failure"
|
||||
done
|
||||
|
||||
# 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 \
|
||||
--volume="${GTEST_ROOT}:/src:ro" \
|
||||
--workdir="/src" \
|
||||
--rm \
|
||||
--env="CC=/usr/local/bin/gcc" \
|
||||
--env="BAZEL_CXXOPTS=-std=c++14" \
|
||||
${LINUX_GCC_FLOOR_CONTAINER} \
|
||||
--env="CC=/opt/gcc-10/bin/gcc" \
|
||||
--env="BAZEL_CXXOPTS=-std=c++17" \
|
||||
--env="BAZEL_LINKOPTS=-L/opt/gcc-10/lib64:-Wl,-rpath=/opt/gcc-10/lib64" \
|
||||
--env="USE_BAZEL_VERSION=8.5.1" \
|
||||
${DOCKER_EXTRA_ARGS:-} \
|
||||
${LINUX_LATEST_CONTAINER} \
|
||||
/bin/bash --login -c "
|
||||
/usr/local/bin/bazel test ... \
|
||||
--copt="-Wall" \
|
||||
--copt="-Werror" \
|
||||
--copt="-Wuninitialized" \
|
||||
--copt="-Wundef" \
|
||||
--copt="-Wno-error=pragmas" \
|
||||
--copt=\"-Wall\" \
|
||||
--copt=\"-Werror\" \
|
||||
--copt=\"-Wuninitialized\" \
|
||||
--copt=\"-Wundef\" \
|
||||
--copt=\"-Wno-error=pragmas\" \
|
||||
--enable_bzlmod=false \
|
||||
--enable_workspace=true \
|
||||
--features=external_include_paths \
|
||||
--keep_going \
|
||||
--per_file_copt=\"external/.*@-w\" \
|
||||
--show_timestamps \
|
||||
--test_output=errors
|
||||
--test_output=errors \
|
||||
${BAZEL_EXTRA_ARGS:-}"
|
||||
|
||||
# Test GCC
|
||||
for std in ${STD}; do
|
||||
@@ -97,18 +129,23 @@ for std in ${STD}; do
|
||||
--rm \
|
||||
--env="CC=/usr/local/bin/gcc" \
|
||||
--env="BAZEL_CXXOPTS=-std=${std}" \
|
||||
--env="USE_BAZEL_VERSION=9.1.0" \
|
||||
${DOCKER_EXTRA_ARGS:-} \
|
||||
${LINUX_LATEST_CONTAINER} \
|
||||
/usr/local/bin/bazel test ... \
|
||||
--copt="-Wall" \
|
||||
--copt="-Werror" \
|
||||
--copt="-Wuninitialized" \
|
||||
--copt="-Wundef" \
|
||||
--define="absl=${absl}" \
|
||||
--enable_bzlmod=true \
|
||||
--features=external_include_paths \
|
||||
--keep_going \
|
||||
--show_timestamps \
|
||||
--test_output=errors
|
||||
/bin/bash --login -c "
|
||||
/usr/local/bin/bazel test ... \
|
||||
--copt=\"-Wall\" \
|
||||
--copt=\"-Werror\" \
|
||||
--copt=\"-Wuninitialized\" \
|
||||
--copt=\"-Wundef\" \
|
||||
--define=\"absl=${absl}\" \
|
||||
--enable_bzlmod=true \
|
||||
--features=external_include_paths \
|
||||
--keep_going \
|
||||
--per_file_copt=\"external/.*@-w\" \
|
||||
--show_timestamps \
|
||||
--test_output=errors \
|
||||
${BAZEL_EXTRA_ARGS:-}"
|
||||
done
|
||||
done
|
||||
|
||||
@@ -119,21 +156,26 @@ for std in ${STD}; do
|
||||
--volume="${GTEST_ROOT}:/src:ro" \
|
||||
--workdir="/src" \
|
||||
--rm \
|
||||
--env="CC=/opt/llvm/clang/bin/clang" \
|
||||
--env="CC=/opt/llvm/bin/clang" \
|
||||
--env="BAZEL_CXXOPTS=-std=${std}" \
|
||||
--env="USE_BAZEL_VERSION=9.1.0" \
|
||||
${DOCKER_EXTRA_ARGS:-} \
|
||||
${LINUX_LATEST_CONTAINER} \
|
||||
/usr/local/bin/bazel test ... \
|
||||
--copt="--gcc-toolchain=/usr/local" \
|
||||
--copt="-Wall" \
|
||||
--copt="-Werror" \
|
||||
--copt="-Wuninitialized" \
|
||||
--copt="-Wundef" \
|
||||
--define="absl=${absl}" \
|
||||
--enable_bzlmod=true \
|
||||
--features=external_include_paths \
|
||||
--keep_going \
|
||||
--linkopt="--gcc-toolchain=/usr/local" \
|
||||
--show_timestamps \
|
||||
--test_output=errors
|
||||
/bin/bash --login -c "
|
||||
/usr/local/bin/bazel test ... \
|
||||
--copt=\"--gcc-toolchain=/usr/local\" \
|
||||
--copt=\"-Wall\" \
|
||||
--copt=\"-Werror\" \
|
||||
--copt=\"-Wuninitialized\" \
|
||||
--copt=\"-Wundef\" \
|
||||
--define=\"absl=${absl}\" \
|
||||
--enable_bzlmod=true \
|
||||
--features=external_include_paths \
|
||||
--keep_going \
|
||||
--linkopt=\"--gcc-toolchain=/usr/local\" \
|
||||
--per_file_copt=\"external/.*@-w\" \
|
||||
--show_timestamps \
|
||||
--test_output=errors \
|
||||
${BAZEL_EXTRA_ARGS:-}"
|
||||
done
|
||||
done
|
||||
|
||||
+21
-5
@@ -31,6 +31,14 @@
|
||||
|
||||
set -euox pipefail
|
||||
|
||||
# Use Xcode 26.2
|
||||
sudo xcode-select -s /Applications/Xcode_26.2.app/Contents/Developer
|
||||
|
||||
brew install cmake
|
||||
|
||||
export CMAKE_BUILD_PARALLEL_LEVEL=$(sysctl -n hw.ncpu)
|
||||
export CTEST_PARALLEL_LEVEL=$(sysctl -n hw.ncpu)
|
||||
|
||||
if [[ -z ${GTEST_ROOT:-} ]]; then
|
||||
GTEST_ROOT="$(realpath $(dirname ${0})/..)"
|
||||
fi
|
||||
@@ -40,20 +48,20 @@ for cmake_off_on in OFF ON; do
|
||||
BUILD_DIR=$(mktemp -d build_dir.XXXXXXXX)
|
||||
cd ${BUILD_DIR}
|
||||
time cmake ${GTEST_ROOT} \
|
||||
-DCMAKE_CXX_STANDARD=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}
|
||||
time make
|
||||
time make -j$(nproc)
|
||||
time ctest -j$(nproc) --output-on-failure
|
||||
done
|
||||
|
||||
# Test the Bazel build
|
||||
|
||||
# If we are running on Kokoro, check for a versioned Bazel binary.
|
||||
KOKORO_GFILE_BAZEL_BIN="bazel-7.0.0-darwin-x86_64"
|
||||
KOKORO_GFILE_BAZEL_BIN="bazel-9.1.0-darwin-x86_64"
|
||||
if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]]; then
|
||||
BAZEL_BIN="${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN}"
|
||||
chmod +x ${BAZEL_BIN}
|
||||
@@ -61,17 +69,25 @@ else
|
||||
BAZEL_BIN="bazel"
|
||||
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}
|
||||
for absl in 0 1; do
|
||||
${BAZEL_BIN} test ... \
|
||||
--copt="-Wall" \
|
||||
--copt="-Werror" \
|
||||
--copt="-Wundef" \
|
||||
--cxxopt="-std=c++14" \
|
||||
--cxxopt="-std=c++17" \
|
||||
--define="absl=${absl}" \
|
||||
--enable_bzlmod=true \
|
||||
--features=external_include_paths \
|
||||
--keep_going \
|
||||
--per_file_copt="external/.*@-w" \
|
||||
--show_timestamps \
|
||||
--test_output=errors
|
||||
--test_output=errors \
|
||||
${BAZEL_EXTRA_ARGS:-}
|
||||
done
|
||||
|
||||
+40
-14
@@ -1,6 +1,6 @@
|
||||
SETLOCAL ENABLEDELAYEDEXPANSION
|
||||
|
||||
SET BAZEL_EXE=%KOKORO_GFILE_DIR%\bazel-7.0.0-windows-x86_64.exe
|
||||
SET BAZEL_EXE=%KOKORO_GFILE_DIR%\bazel-9.1.0-windows-x86_64.exe
|
||||
|
||||
SET PATH=C:\Python34;%PATH%
|
||||
SET BAZEL_PYTHON=C:\python34\python.exe
|
||||
@@ -11,21 +11,19 @@ SET CTEST_OUTPUT_ON_FAILURE=1
|
||||
SET CMAKE_BUILD_PARALLEL_LEVEL=16
|
||||
SET CTEST_PARALLEL_LEVEL=16
|
||||
|
||||
IF EXIST git\googletest (
|
||||
CD git\googletest
|
||||
) ELSE IF EXIST github\googletest (
|
||||
CD github\googletest
|
||||
)
|
||||
|
||||
SET GTEST_ROOT=%~dp0\..
|
||||
IF %errorlevel% neq 0 EXIT /B 1
|
||||
|
||||
:: ----------------------------------------------------------------------------
|
||||
:: CMake
|
||||
MKDIR cmake_msvc2022
|
||||
CD cmake_msvc2022
|
||||
SET CMAKE_BUILD_PATH=cmake_msvc2022
|
||||
MKDIR %CMAKE_BUILD_PATH%
|
||||
CD %CMAKE_BUILD_PATH%
|
||||
SET CXXFLAGS="/WX"
|
||||
|
||||
%CMAKE_BIN% .. ^
|
||||
%CMAKE_BIN% %GTEST_ROOT% ^
|
||||
-G "Visual Studio 17 2022" ^
|
||||
-DCMAKE_CXX_STANDARD=17 ^
|
||||
-DPYTHON_EXECUTABLE:FILEPATH=c:\python37\python.exe ^
|
||||
-DPYTHON_INCLUDE_DIR:PATH=c:\python37\include ^
|
||||
-DPYTHON_LIBRARY:FILEPATH=c:\python37\lib\site-packages\pip ^
|
||||
@@ -40,8 +38,9 @@ IF %errorlevel% neq 0 EXIT /B 1
|
||||
%CTEST_BIN% -C Debug --timeout 600
|
||||
IF %errorlevel% neq 0 EXIT /B 1
|
||||
|
||||
CD ..
|
||||
RMDIR /S /Q cmake_msvc2022
|
||||
SET "CXXFLAGS="
|
||||
CD %GTEST_ROOT%
|
||||
RMDIR /S /Q %CMAKE_BUILD_PATH%
|
||||
|
||||
:: ----------------------------------------------------------------------------
|
||||
:: Bazel
|
||||
@@ -50,14 +49,41 @@ RMDIR /S /Q cmake_msvc2022
|
||||
:: because of Windows limitations on path length.
|
||||
:: --output_user_root=C:\tmp causes Bazel to use a shorter path.
|
||||
SET BAZEL_VS=C:\Program Files\Microsoft Visual Studio\2022\Community
|
||||
|
||||
:: 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% ^
|
||||
--output_user_root=C:\tmp ^
|
||||
test ... ^
|
||||
--compilation_mode=dbg ^
|
||||
--copt=/std:c++14 ^
|
||||
--copt=/std:c++17 ^
|
||||
--copt=/WX ^
|
||||
--enable_bzlmod=true ^
|
||||
--keep_going ^
|
||||
--per_file_copt=external/.*@/w ^
|
||||
--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 ^
|
||||
--per_file_copt=external/.*@/w ^
|
||||
--test_output=errors ^
|
||||
--test_tag_filters=-no_test_msvc2017 ^
|
||||
%VENDOR_FLAG%
|
||||
IF %errorlevel% neq 0 EXIT /B 1
|
||||
|
||||
@@ -7,15 +7,15 @@
|
||||
|
||||
{% seo %}
|
||||
<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>
|
||||
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
|
||||
ga('create', 'UA-197576187-1', { 'storage': 'none' });
|
||||
ga('set', 'referrer', document.referrer.split('?')[0]);
|
||||
ga('set', 'location', window.location.href.split('?')[0]);
|
||||
ga('set', 'anonymizeIp', true);
|
||||
ga('send', 'pageview');
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'G-9PTP6FW1M5');
|
||||
</script>
|
||||
<script async src='https://www.google-analytics.com/analytics.js'></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="sidebar">
|
||||
|
||||
+46
-16
@@ -349,7 +349,8 @@ void AbslStringify(Sink& sink, EnumWithStringify e) {
|
||||
{: .callout .note}
|
||||
Note: `AbslStringify()` utilizes a generic "sink" buffer to construct its
|
||||
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
|
||||
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
|
||||
libraries, see go/abslstringify.
|
||||
libraries, see
|
||||
[the documentation](https://abseil.io/docs/cpp/guides/abslstringify).
|
||||
|
||||
## Regular Expression Syntax
|
||||
|
||||
@@ -1448,17 +1450,19 @@ are two cases to consider:
|
||||
To test them, we use the following special techniques:
|
||||
|
||||
* Both static functions and definitions/declarations in an unnamed namespace
|
||||
are only visible within the same translation unit. To test them, you can
|
||||
`#include` the entire `.cc` file being tested in your `*_test.cc` file.
|
||||
(#including `.cc` files is not a good way to reuse code - you should not do
|
||||
this in production code!)
|
||||
are only visible within the same translation unit. To test them, move the
|
||||
private code into the `foo::internal` namespace, where `foo` is the
|
||||
namespace your project normally uses, and put the private declarations in a
|
||||
`*-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
|
||||
`foo::internal` namespace, where `foo` is the namespace your project
|
||||
normally uses, and put the private declarations in a `*-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.
|
||||
{: .callout .note}
|
||||
NOTE: It is also technically *possible* to `#include` the entire `.cc` file
|
||||
being tested in your `*_test.cc` file to test static functions and
|
||||
definitions/declarations in an unnamed namespace. However, this technique is
|
||||
**not recommended** by this documentation and it is only presented here for the
|
||||
sake of completeness.
|
||||
|
||||
* Private class members are only accessible from within the class or by
|
||||
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
|
||||
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
|
||||
called the
|
||||
[Pimpl](https://www.gamedev.net/articles/programming/general-and-gameplay-programming/the-c-pimpl-r1794/)
|
||||
(Private Implementation) idiom.
|
||||
clients aren't allowed to include this header but your tests can.
|
||||
|
||||
Or, you can declare an individual test as a friend of your class by adding
|
||||
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
|
||||
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
|
||||
|
||||
Once in a while you'll run into a test whose result is hit-or-miss. Perhaps it
|
||||
|
||||
-13
@@ -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
|
||||
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`?
|
||||
|
||||
GoogleTest does not interleave tests from different test suites. That is, it
|
||||
|
||||
@@ -130,7 +130,7 @@ TEST(BarTest, DoesThis) {
|
||||
## Setting Default Actions {#OnCall}
|
||||
|
||||
gMock has a **built-in default action** for any function that returns `void`,
|
||||
`bool`, a numeric value, or a pointer. In C++11, it will additionally returns
|
||||
`bool`, a numeric value, or a pointer. In C++11, it additionally returns
|
||||
the default-constructed value, if one exists for the given type.
|
||||
|
||||
To customize the default action for functions with return type `T`, use
|
||||
@@ -153,7 +153,7 @@ To customize the default action for functions with return type `T`, use
|
||||
EXPECT_NE(buzz1, buzz2);
|
||||
|
||||
// Resets the default action for return type std::unique_ptr<Buzz>,
|
||||
// to avoid interfere with other tests.
|
||||
// to avoid interfering with other tests.
|
||||
DefaultValue<std::unique_ptr<Buzz>>::Clear();
|
||||
```
|
||||
|
||||
|
||||
+107
-37
@@ -900,15 +900,16 @@ using ::testing::Not;
|
||||
|
||||
Matchers are function objects, and parametrized matchers can be composed just
|
||||
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
|
||||
generic lambdas to avoid specifying types. For example,
|
||||
provide meaningful information, it can be easier to express them with template
|
||||
parameters and `auto`. For example,
|
||||
|
||||
```cpp
|
||||
using ::testing::Contains;
|
||||
using ::testing::Property;
|
||||
|
||||
inline constexpr auto HasFoo = [](const auto& f) {
|
||||
return Property("foo", &MyClass::foo, Contains(f));
|
||||
template <typename SubMatcher>
|
||||
inline constexpr auto HasFoo(const SubMatcher& sub_matcher) {
|
||||
return Property("foo", &MyClass::foo, Contains(sub_matcher));
|
||||
};
|
||||
...
|
||||
EXPECT_THAT(x, HasFoo("blah"));
|
||||
@@ -3385,30 +3386,6 @@ With this definition, the above assertion will give a better message:
|
||||
Actual: 27 (the remainder is 6)
|
||||
```
|
||||
|
||||
#### Using EXPECT_ Statements in Matchers
|
||||
|
||||
You can also use `EXPECT_...` statements inside custom matcher definitions. In
|
||||
many cases, this allows you to write your matcher more concisely while still
|
||||
providing an informative error message. For example:
|
||||
|
||||
```cpp
|
||||
MATCHER(IsDivisibleBy7, "") {
|
||||
const auto remainder = arg % 7;
|
||||
EXPECT_EQ(remainder, 0);
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
If you write a test that includes the line `EXPECT_THAT(27, IsDivisibleBy7());`,
|
||||
you will get an error something like the following:
|
||||
|
||||
```shell
|
||||
Expected equality of these values:
|
||||
remainder
|
||||
Which is: 6
|
||||
0
|
||||
```
|
||||
|
||||
#### `MatchAndExplain`
|
||||
|
||||
You should let `MatchAndExplain()` print *any additional information* that can
|
||||
@@ -3428,6 +3405,66 @@ the value of `(arg % 7) == 0` can be implicitly converted to a `bool`. In the
|
||||
`arg_type` will be `int`; if it takes an `unsigned long`, `arg_type` will be
|
||||
`unsigned long`; and so on.
|
||||
|
||||
#### Anti-pattern: Using EXPECT_ Statements in Matchers
|
||||
|
||||
Using `EXPECT_...` statements inside custom matcher definitions is an
|
||||
**anti-pattern** and should be avoided.
|
||||
|
||||
While it might appear to write matchers more concisely and generate informative
|
||||
messages, this pattern has critical issues:
|
||||
|
||||
1. **Negation Breakage (`Not`):** If wrapped in `Not(IsDivisibleBy7())`,
|
||||
evaluating it still triggers the internal `EXPECT_EQ`, registering a test
|
||||
failure on the runner even when the overall assertion is expected to
|
||||
succeed.
|
||||
2. **Composition / Container Breakage (`AnyOf`, `AllOf`, `Contains`):** When
|
||||
composed or used inside container matchers, elements that are expected
|
||||
mismatches will trigger the internal `EXPECT_` and register spurious
|
||||
failures.
|
||||
3. **ASSERT_* compilation errors:** `ASSERT_*` macros use `return;` to abort
|
||||
from a void function. Since matchers return `bool`, using `ASSERT_` inside
|
||||
them triggers a compilation error.
|
||||
4. **Purity Violations:** Matchers must be functionally pure (side-effect
|
||||
free), whereas registering global failures is a major side effect.
|
||||
5. **Line Number Confusion:** Failure reports point to the matcher's definition
|
||||
line rather than the calling `EXPECT_THAT`
|
||||
line.
|
||||
|
||||
##### The Anti-Pattern
|
||||
|
||||
```cpp
|
||||
// Anti-pattern: Do not do this!
|
||||
MATCHER(IsDivisibleBy7, "") {
|
||||
const auto remainder = arg % 7;
|
||||
EXPECT_EQ(remainder, 0); // Spurious failures if negated/composed!
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
##### The Correct Solution
|
||||
|
||||
To write concise matchers that delegate to other matchers and safely propagate
|
||||
the mismatch explanation, use **`::testing::ExplainMatchResult`** instead,
|
||||
passing it the sub-matcher, the value to check, and the `result_listener`:
|
||||
|
||||
```cpp
|
||||
MATCHER(IsDivisibleBy7, "") {
|
||||
const auto remainder = arg % 7;
|
||||
return ::testing::ExplainMatchResult(::testing::Eq(0), remainder,
|
||||
result_listener);
|
||||
}
|
||||
```
|
||||
|
||||
If you write a test that includes the line:
|
||||
|
||||
```cpp
|
||||
EXPECT_THAT(28, Not(IsDivisibleBy7()));
|
||||
```
|
||||
|
||||
it will correctly report the mismatch, properly point to the `EXPECT_THAT` line
|
||||
number, and support negation (`Not`) and composition (`AllOf`, `AnyOf`, etc.)
|
||||
without registering spurious failures.
|
||||
|
||||
### Writing New Parameterized Matchers Quickly
|
||||
|
||||
Sometimes you'll want to define a matcher that has parameters. For that you can
|
||||
@@ -3565,12 +3602,17 @@ general leads to better compiler error messages that pay off in the long run.
|
||||
They also allow overloading matchers based on parameter types (as opposed to
|
||||
just based on the number of parameters).
|
||||
|
||||
### Writing New Monomorphic Matchers
|
||||
### Writing New Monomorphic Matchers {#MonomorphicMatchers}
|
||||
|
||||
A matcher of argument type `T` implements the matcher interface for `T` and does
|
||||
two things: it tests whether a value of type `T` matches the matcher, and can
|
||||
describe what kind of values it matches. The latter ability is used for
|
||||
generating readable error messages when expectations are violated.
|
||||
A matcher of type `testing::Matcher<T>` implements the matcher interface for `T`
|
||||
and does two things: it tests whether a value of type `T` matches the matcher,
|
||||
and can describe what kind of values it matches. The latter ability is used for
|
||||
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:
|
||||
|
||||
@@ -3585,7 +3627,7 @@ and supports the following operations:
|
||||
bool matched = matcher.MatchAndExplain(value, maybe_os);
|
||||
// where `value` is of type `T` and
|
||||
// `maybe_os` is of type `std::ostream*`, where it can be null if the caller
|
||||
// is not interested in there textual explanation.
|
||||
// is not interested in the textual explanation.
|
||||
|
||||
matcher.DescribeTo(os);
|
||||
matcher.DescribeNegationTo(os);
|
||||
@@ -3660,10 +3702,18 @@ Expected: is divisible by 7
|
||||
Tip: for convenience, `MatchAndExplain()` can take a `MatchResultListener*`
|
||||
instead of `std::ostream*`.
|
||||
|
||||
### Writing New Polymorphic Matchers
|
||||
### Writing New Polymorphic Matchers {#PolymorphicMatchers}
|
||||
|
||||
Expanding what we learned above to *polymorphic* matchers is now just as simple
|
||||
as adding templates in the right place.
|
||||
Unlike a monomorphic matcher, which can only be used to match a value of a
|
||||
particular type, a *polymorphic* matcher is one that can be used to match values
|
||||
of multiple types. For example, `Eq(5)` is a polymorphic 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
|
||||
|
||||
@@ -3789,6 +3839,26 @@ virtual.
|
||||
Like in a monomorphic matcher, you may explain the match result by streaming
|
||||
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
|
||||
|
||||
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:
|
||||
|
||||
* 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
|
||||
by the GoogleTest team.
|
||||
|
||||
@@ -48,7 +48,7 @@ with the following content:
|
||||
|
||||
# Choose the most recent version available at
|
||||
# https://registry.bazel.build/modules/googletest
|
||||
bazel_dep(name = "googletest", version = "1.15.2")
|
||||
bazel_dep(name = "googletest", version = "1.18.0")
|
||||
```
|
||||
|
||||
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).
|
||||
|
||||
{: .callout .note}
|
||||
NOTE: In the example below, we assume Clang or GCC and set `--cxxopt=-std=c++14`
|
||||
to ensure that GoogleTest is compiled as C++14 instead of the compiler's default
|
||||
setting (which could be C++11). For MSVC, the equivalent would be
|
||||
`--cxxopt=/std:c++14`. See [Supported Platforms](platforms.md) for more details
|
||||
on supported language versions.
|
||||
NOTE: In the example below, we assume Clang or GCC and set `--cxxopt=-std=c++17`
|
||||
to ensure that GoogleTest is compiled as C++17 instead of the compiler's default
|
||||
setting. For MSVC, the equivalent would be `--cxxopt=/std:c++17`. See
|
||||
[Supported Platforms](platforms.md) for more details on supported language
|
||||
versions.
|
||||
|
||||
Now you can build and run your test:
|
||||
|
||||
<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: Found 1 test target...
|
||||
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:
|
||||
|
||||
* 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
|
||||
project.
|
||||
* 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)
|
||||
project(my_project)
|
||||
|
||||
# GoogleTest requires at least C++14
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
# GoogleTest requires at least C++17
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
@@ -24,7 +24,8 @@ provided by GoogleTest. All actions are defined in the `::testing` namespace.
|
||||
| :--------------------------------- | :-------------------------------------- |
|
||||
| `Assign(&variable, value)` | Assign `value` to variable. |
|
||||
| `DeleteArg<N>()` | Delete the `N`-th (0-based) argument, which must be a pointer. |
|
||||
| `SaveArg<N>(pointer)` | Save the `N`-th (0-based) argument to `*pointer`. |
|
||||
| `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`. |
|
||||
| `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. |
|
||||
@@ -47,8 +48,8 @@ functor, or lambda.
|
||||
| `InvokeWithoutArgs(object_pointer, &class::method)` | Invoke the method on the object, which takes no arguments. |
|
||||
| `InvokeArgument<N>(arg1, arg2, ..., argk)` | Invoke the mock function's `N`-th (0-based) argument, which must be a function or a functor, with the `k` arguments. |
|
||||
|
||||
The return value of the invoked function is used as the return value of the
|
||||
action.
|
||||
The return value of the invoked function (except `InvokeArgument`) is used as
|
||||
the return value of the action.
|
||||
|
||||
When defining a callable to be used with `Invoke*()`, you can declare any unused
|
||||
parameters as `Unused`:
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# Matchers Reference
|
||||
|
||||
<!-- disableFinding(LINK_RELATIVE_G3DOC) -->
|
||||
|
||||
A **matcher** matches a *single* argument. You can use it inside `ON_CALL()` or
|
||||
`EXPECT_CALL()`, or use it to validate a value directly using two macros:
|
||||
|
||||
@@ -42,11 +44,14 @@ Matcher | Description
|
||||
| `Lt(value)` | `argument < value` |
|
||||
| `Ne(value)` | `argument != value` |
|
||||
| `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. |
|
||||
| `IsNull()` | `argument` is a `NULL` pointer (raw or smart). |
|
||||
| `NotNull()` | `argument` is a non-null pointer (raw or smart). |
|
||||
| `Optional(m)` | `argument` is `optional<>` that contains a value matching `m`. (For testing whether an `optional<>` is set, check for equality with `nullopt`. You may need to use `Eq(nullopt)` if the inner type doesn't have `==`.)|
|
||||
| `Optional(m)` | `argument` is `optional<>` that contains a value matching `m`. (For testing whether an `optional<>` is unset, 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`. |
|
||||
| `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`. |
|
||||
| `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 +114,33 @@ use the regular expression syntax defined
|
||||
[here](../advanced.md#regular-expression-syntax). All of these matchers, except
|
||||
`ContainsRegex()` and `MatchesRegex()` work for wide strings as well.
|
||||
|
||||
## 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
|
||||
|
||||
Most STL-style containers support `==`, so you can use `Eq(expected_container)`
|
||||
@@ -171,6 +203,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(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:**
|
||||
|
||||
* You can use `FieldsAre()` to match any type that supports structured
|
||||
@@ -189,10 +226,6 @@ messages, you can use:
|
||||
EXPECT_THAT(s, FieldsAre(42, "aloha"));
|
||||
```
|
||||
|
||||
* Don't use `Property()` against member functions that you do not own, because
|
||||
taking addresses of functions is fragile and generally not part of the
|
||||
contract of the function.
|
||||
|
||||
## Matching the Result of a Function, Functor, or Callback
|
||||
|
||||
| Matcher | Description |
|
||||
@@ -223,6 +256,14 @@ Matcher | Description
|
||||
`Le()` | `x <= y`
|
||||
`Lt()` | `x < y`
|
||||
`Ne()` | `x != y`
|
||||
`FloatEq()` | `x` approximately equals `y`
|
||||
`DoubleEq()` | `x` approximately equals `y`
|
||||
`NanSensitiveFloatEq()` | Same as `FloatEq()`, but treats two NaNs as equal
|
||||
`NanSensitiveDoubleEq()` | Same as `DoubleEq()`, but treats two NaNs as equal
|
||||
`FloatNear(max_abs_error)` | `x` is within `max_abs_error` of `y`
|
||||
`DoubleNear(max_abs_error)` | `x` is within `max_abs_error` of `y`
|
||||
`NanSensitiveFloatNear(max_abs_error)` | Same as `FloatNear(max_abs_error)`, but treats two NaNs as near
|
||||
`NanSensitiveDoubleNear(max_abs_error)` | Same as `DoubleNear(max_abs_error)`, but treats two NaNs as near
|
||||
|
||||
You can use the following selectors to pick a subset of the arguments (or
|
||||
reorder them) to participate in the matching:
|
||||
@@ -266,6 +307,13 @@ which must be a permanent callback.
|
||||
|
||||
## Defining Matchers
|
||||
|
||||
{: .callout .note}
|
||||
Note: full details about defining new matchers are in the
|
||||
[cookbook](../gmock_cook_book.md#NewMatchers). In particular, if `MATCHER`
|
||||
macros are not sufficient, you can directly implement
|
||||
[monomorphic](../gmock_cook_book.md#MonomorphicMatchers) or
|
||||
[polymorphic](../gmock_cook_book.md#PolymorphicMatchers) matchers.
|
||||
|
||||
| Macro | Description |
|
||||
| :----------------------------------- | :------------------------------------ |
|
||||
| `MATCHER(IsEven, "") { return (arg % 2) == 0; }` | Defines a matcher `IsEven()` to match an even number. |
|
||||
|
||||
@@ -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)`. |
|
||||
| `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`. |
|
||||
| `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
|
||||
generates custom test name suffixes based on the test parameters. The function
|
||||
@@ -137,6 +137,103 @@ For more information, see
|
||||
See also
|
||||
[`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(`*`TestFixtureName`*`,`*`Types`*`)`
|
||||
|
||||
@@ -105,10 +105,10 @@ endif()
|
||||
string(REPLACE ";" "$<SEMICOLON>" dirs "${gmock_build_include_dirs}")
|
||||
target_include_directories(gmock SYSTEM INTERFACE
|
||||
"$<BUILD_INTERFACE:${dirs}>"
|
||||
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
|
||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
|
||||
target_include_directories(gmock_main SYSTEM INTERFACE
|
||||
"$<BUILD_INTERFACE:${dirs}>"
|
||||
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
|
||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
|
||||
|
||||
########################################################################
|
||||
#
|
||||
|
||||
@@ -146,6 +146,7 @@
|
||||
#include "gmock/internal/gmock-internal-utils.h"
|
||||
#include "gmock/internal/gmock-port.h"
|
||||
#include "gmock/internal/gmock-pp.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4100)
|
||||
|
||||
@@ -196,7 +197,7 @@ struct BuiltInDefaultValueGetter<T, false> {
|
||||
// other type T, the built-in default T value is undefined, and the
|
||||
// function will abort the process.
|
||||
template <typename T>
|
||||
class BuiltInDefaultValue {
|
||||
class [[nodiscard]] BuiltInDefaultValue {
|
||||
public:
|
||||
// This function returns true if and only if type T has a built-in default
|
||||
// value.
|
||||
@@ -211,7 +212,7 @@ class BuiltInDefaultValue {
|
||||
// This partial specialization says that we use the same built-in
|
||||
// default value for T and const T.
|
||||
template <typename T>
|
||||
class BuiltInDefaultValue<const T> {
|
||||
class [[nodiscard]] BuiltInDefaultValue<const T> {
|
||||
public:
|
||||
static bool Exists() { return BuiltInDefaultValue<T>::Exists(); }
|
||||
static T Get() { return BuiltInDefaultValue<T>::Get(); }
|
||||
@@ -220,7 +221,7 @@ class BuiltInDefaultValue<const T> {
|
||||
// This partial specialization defines the default values for pointer
|
||||
// types.
|
||||
template <typename T>
|
||||
class BuiltInDefaultValue<T*> {
|
||||
class [[nodiscard]] BuiltInDefaultValue<T*> {
|
||||
public:
|
||||
static bool Exists() { return true; }
|
||||
static T* Get() { return nullptr; }
|
||||
@@ -249,7 +250,7 @@ GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(char, '\0');
|
||||
// There's also no need for a default action for unsigned wchar_t, as
|
||||
// that type is the same as unsigned int for gcc, and invalid for
|
||||
// MSVC.
|
||||
#if GMOCK_WCHAR_T_IS_NATIVE_
|
||||
#if GTEST_HAS_NATIVE_WCHAR
|
||||
GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(wchar_t, 0U); // NOLINT
|
||||
#endif
|
||||
|
||||
@@ -383,7 +384,7 @@ typename std::add_const<T>::type& as_const(T& t) {
|
||||
|
||||
// Specialized for function types below.
|
||||
template <typename F>
|
||||
class OnceAction;
|
||||
class [[nodiscard]] OnceAction;
|
||||
|
||||
// An action that can only be used once.
|
||||
//
|
||||
@@ -421,27 +422,26 @@ class OnceAction;
|
||||
// A less-contrived example would be an action that returns an arbitrary type,
|
||||
// whose &&-qualified call operator is capable of dealing with move-only types.
|
||||
template <typename Result, typename... Args>
|
||||
class OnceAction<Result(Args...)> final {
|
||||
class [[nodiscard]] OnceAction<Result(Args...)> final {
|
||||
private:
|
||||
// True iff we can use the given callable type (or lvalue reference) directly
|
||||
// via StdFunctionAdaptor.
|
||||
template <typename Callable>
|
||||
using IsDirectlyCompatible = internal::conjunction<
|
||||
// It must be possible to capture the callable in StdFunctionAdaptor.
|
||||
std::is_constructible<typename std::decay<Callable>::type, Callable>,
|
||||
// The callable must be compatible with our signature.
|
||||
internal::is_callable_r<Result, typename std::decay<Callable>::type,
|
||||
Args...>>;
|
||||
internal::is_callable_r<Result, std::decay_t<Callable>, Args...>,
|
||||
// It must be possible to capture the callable in StdFunctionAdaptor.
|
||||
std::is_constructible<std::decay_t<Callable>, Callable>>;
|
||||
|
||||
// True iff we can use the given callable type via StdFunctionAdaptor once we
|
||||
// ignore incoming arguments.
|
||||
template <typename Callable>
|
||||
using IsCompatibleAfterIgnoringArguments = internal::conjunction<
|
||||
// It must be possible to capture the callable in a lambda.
|
||||
std::is_constructible<typename std::decay<Callable>::type, Callable>,
|
||||
// The callable must be invocable with zero arguments, returning something
|
||||
// convertible to Result.
|
||||
internal::is_callable_r<Result, typename std::decay<Callable>::type>>;
|
||||
internal::is_callable_r<Result, std::decay_t<Callable>>,
|
||||
// It must be possible to capture the callable in a lambda.
|
||||
std::is_constructible<std::decay_t<Callable>, Callable>>;
|
||||
|
||||
public:
|
||||
// Construct from a callable that is directly compatible with our mocked
|
||||
@@ -574,7 +574,7 @@ class OnceAction<Result(Args...)> final {
|
||||
// // Sets the default value for type T to be foo.
|
||||
// DefaultValue<T>::Set(foo);
|
||||
template <typename T>
|
||||
class DefaultValue {
|
||||
class [[nodiscard]] DefaultValue {
|
||||
public:
|
||||
// Sets the default value for type T; requires T to be
|
||||
// copy-constructable and have a public destructor.
|
||||
@@ -651,7 +651,7 @@ class DefaultValue {
|
||||
// This partial specialization allows a user to set default values for
|
||||
// reference types.
|
||||
template <typename T>
|
||||
class DefaultValue<T&> {
|
||||
class [[nodiscard]] DefaultValue<T&> {
|
||||
public:
|
||||
// Sets the default value for type T&.
|
||||
static void Set(T& x) { // NOLINT
|
||||
@@ -685,7 +685,7 @@ class DefaultValue<T&> {
|
||||
// This specialization allows DefaultValue<void>::Get() to
|
||||
// compile.
|
||||
template <>
|
||||
class DefaultValue<void> {
|
||||
class [[nodiscard]] DefaultValue<void> {
|
||||
public:
|
||||
static bool Exists() { return true; }
|
||||
static void Get() {}
|
||||
@@ -701,7 +701,7 @@ T* DefaultValue<T&>::address_ = nullptr;
|
||||
|
||||
// Implement this interface to define an action for function type F.
|
||||
template <typename F>
|
||||
class ActionInterface {
|
||||
class [[nodiscard]] ActionInterface {
|
||||
public:
|
||||
typedef typename internal::Function<F>::Result Result;
|
||||
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
|
||||
@@ -721,7 +721,7 @@ class ActionInterface {
|
||||
};
|
||||
|
||||
template <typename F>
|
||||
class Action;
|
||||
class [[nodiscard]] Action;
|
||||
|
||||
// An Action<R(Args...)> is a copyable and IMMUTABLE (except by assignment)
|
||||
// object that represents an action to be taken when a mock function of type
|
||||
@@ -730,7 +730,7 @@ class Action;
|
||||
// can view an object implementing ActionInterface<F> as a concrete action
|
||||
// (including its current state), and an Action<F> object as a handle to it.
|
||||
template <typename R, typename... Args>
|
||||
class Action<R(Args...)> {
|
||||
class [[nodiscard]] Action<R(Args...)> {
|
||||
private:
|
||||
using F = R(Args...);
|
||||
|
||||
@@ -835,6 +835,10 @@ class Action<R(Args...)> {
|
||||
Result operator()(const InArgs&...) const {
|
||||
return function_impl();
|
||||
}
|
||||
template <typename... InArgs>
|
||||
Result operator()(const InArgs&...) {
|
||||
return function_impl();
|
||||
}
|
||||
|
||||
FunctionImpl function_impl;
|
||||
};
|
||||
@@ -865,7 +869,7 @@ class Action<R(Args...)> {
|
||||
// the definition of Return(void) and SetArgumentPointee<N>(value) for
|
||||
// complete examples.
|
||||
template <typename Impl>
|
||||
class PolymorphicAction {
|
||||
class [[nodiscard]] PolymorphicAction {
|
||||
public:
|
||||
explicit PolymorphicAction(const Impl& impl) : impl_(impl) {}
|
||||
|
||||
@@ -925,7 +929,7 @@ struct ByMoveWrapper {
|
||||
|
||||
// The general implementation of Return(R). Specializations follow below.
|
||||
template <typename R>
|
||||
class ReturnAction final {
|
||||
class [[nodiscard]] ReturnAction final {
|
||||
public:
|
||||
explicit ReturnAction(R value) : value_(std::move(value)) {}
|
||||
|
||||
@@ -937,7 +941,7 @@ class ReturnAction final {
|
||||
std::is_convertible<R, U>, //
|
||||
std::is_move_constructible<U>>::value>::type>
|
||||
operator OnceAction<U(Args...)>() && { // NOLINT
|
||||
return Impl<U>(std::move(value_));
|
||||
return OnceImpl<U>(std::move(value_));
|
||||
}
|
||||
|
||||
template <typename U, typename... Args,
|
||||
@@ -956,13 +960,6 @@ class ReturnAction final {
|
||||
template <typename U>
|
||||
class Impl final {
|
||||
public:
|
||||
// The constructor used when the return value is allowed to move from the
|
||||
// input value (i.e. we are converting to OnceAction).
|
||||
explicit Impl(R&& input_value)
|
||||
: state_(new State(std::move(input_value))) {}
|
||||
|
||||
// The constructor used when the return value is not allowed to move from
|
||||
// the input value (i.e. we are converting to Action).
|
||||
explicit Impl(const R& input_value) : state_(new State(input_value)) {}
|
||||
|
||||
U operator()() && { return std::move(state_->value); }
|
||||
@@ -993,18 +990,6 @@ class ReturnAction final {
|
||||
// explicit constructor from R.
|
||||
value(ImplicitCast_<U>(internal::as_const(input_value))) {}
|
||||
|
||||
// As above, but for the case where we're moving from the ReturnAction
|
||||
// object because it's being used as a OnceAction.
|
||||
explicit State(R&& input_value_in)
|
||||
: input_value(std::move(input_value_in)),
|
||||
// For the same reason as above we make an implicit conversion to U
|
||||
// before initializing the value.
|
||||
//
|
||||
// Unlike above we provide the input value as an rvalue to the
|
||||
// implicit conversion because this is a OnceAction: it's fine if it
|
||||
// wants to consume the input value.
|
||||
value(ImplicitCast_<U>(std::move(input_value))) {}
|
||||
|
||||
// A copy of the value originally provided by the user. We retain this in
|
||||
// addition to the value of the mock function's result type below in case
|
||||
// the latter is a reference-like type. See the std::string_view example
|
||||
@@ -1082,6 +1067,23 @@ class ReturnAction final {
|
||||
const std::shared_ptr<State> state_;
|
||||
};
|
||||
|
||||
// Implements the Return(x) action for a mock function that returns type U,
|
||||
// but is only executed at most once. This allows us to store the original
|
||||
// value and move construct the return value type on the first (and only)
|
||||
// call.
|
||||
template <typename U>
|
||||
class OnceImpl final {
|
||||
public:
|
||||
explicit OnceImpl(R&& input_value)
|
||||
: input_value_(new R(std::move(input_value))) {}
|
||||
|
||||
U operator()() && { return std::move(*input_value_); }
|
||||
|
||||
private:
|
||||
// Move the input value to the heap and make it copyable.
|
||||
const std::shared_ptr<R> input_value_;
|
||||
};
|
||||
|
||||
R value_;
|
||||
};
|
||||
|
||||
@@ -1091,7 +1093,7 @@ class ReturnAction final {
|
||||
// the const call operator, checking at runtime that it isn't called more than
|
||||
// once, since the user has declared their intent to do so by using ByMove.
|
||||
template <typename T>
|
||||
class ReturnAction<ByMoveWrapper<T>> final {
|
||||
class [[nodiscard]] ReturnAction<ByMoveWrapper<T>> final {
|
||||
public:
|
||||
explicit ReturnAction(ByMoveWrapper<T> wrapper)
|
||||
: state_(new State(std::move(wrapper.payload))) {}
|
||||
@@ -1118,7 +1120,7 @@ class ReturnAction<ByMoveWrapper<T>> final {
|
||||
};
|
||||
|
||||
// Implements the ReturnNull() action.
|
||||
class ReturnNullAction {
|
||||
class [[nodiscard]] ReturnNullAction {
|
||||
public:
|
||||
// Allows ReturnNull() to be used in any pointer-returning function. In C++11
|
||||
// this is enforced by returning nullptr, and in non-C++11 by asserting a
|
||||
@@ -1130,7 +1132,7 @@ class ReturnNullAction {
|
||||
};
|
||||
|
||||
// Implements the Return() action.
|
||||
class ReturnVoidAction {
|
||||
class [[nodiscard]] ReturnVoidAction {
|
||||
public:
|
||||
// Allows Return() to be used in any void-returning function.
|
||||
template <typename Result, typename ArgumentTuple>
|
||||
@@ -1143,7 +1145,7 @@ class ReturnVoidAction {
|
||||
// in any function that returns a reference to the type of x,
|
||||
// regardless of the argument types.
|
||||
template <typename T>
|
||||
class ReturnRefAction {
|
||||
class [[nodiscard]] ReturnRefAction {
|
||||
public:
|
||||
// Constructs a ReturnRefAction object from the reference to be returned.
|
||||
explicit ReturnRefAction(T& ref) : ref_(ref) {} // NOLINT
|
||||
@@ -1184,7 +1186,7 @@ class ReturnRefAction {
|
||||
// used in any function that returns a reference to the type of x,
|
||||
// regardless of the argument types.
|
||||
template <typename T>
|
||||
class ReturnRefOfCopyAction {
|
||||
class [[nodiscard]] ReturnRefOfCopyAction {
|
||||
public:
|
||||
// Constructs a ReturnRefOfCopyAction object from the reference to
|
||||
// be returned.
|
||||
@@ -1225,7 +1227,7 @@ class ReturnRefOfCopyAction {
|
||||
// Implements the polymorphic ReturnRoundRobin(v) action, which can be
|
||||
// used in any function that returns the element_type of v.
|
||||
template <typename T>
|
||||
class ReturnRoundRobinAction {
|
||||
class [[nodiscard]] ReturnRoundRobinAction {
|
||||
public:
|
||||
explicit ReturnRoundRobinAction(std::vector<T> values) {
|
||||
GTEST_CHECK_(!values.empty())
|
||||
@@ -1253,7 +1255,7 @@ class ReturnRoundRobinAction {
|
||||
};
|
||||
|
||||
// Implements the polymorphic DoDefault() action.
|
||||
class DoDefaultAction {
|
||||
class [[nodiscard]] DoDefaultAction {
|
||||
public:
|
||||
// This template type conversion operator allows DoDefault() to be
|
||||
// used in any function.
|
||||
@@ -1266,7 +1268,7 @@ class DoDefaultAction {
|
||||
// Implements the Assign action to set a given pointer referent to a
|
||||
// particular value.
|
||||
template <typename T1, typename T2>
|
||||
class AssignAction {
|
||||
class [[nodiscard]] AssignAction {
|
||||
public:
|
||||
AssignAction(T1* ptr, T2 value) : ptr_(ptr), value_(value) {}
|
||||
|
||||
@@ -1285,7 +1287,7 @@ class AssignAction {
|
||||
// Implements the SetErrnoAndReturn action to simulate return from
|
||||
// various system calls and libc functions.
|
||||
template <typename T>
|
||||
class SetErrnoAndReturnAction {
|
||||
class [[nodiscard]] SetErrnoAndReturnAction {
|
||||
public:
|
||||
SetErrnoAndReturnAction(int errno_value, T result)
|
||||
: errno_(errno_value), result_(result) {}
|
||||
@@ -1327,22 +1329,6 @@ struct InvokeMethodAction {
|
||||
}
|
||||
};
|
||||
|
||||
// Implements the InvokeWithoutArgs(f) action. The template argument
|
||||
// FunctionImpl is the implementation type of f, which can be either a
|
||||
// function pointer or a functor. InvokeWithoutArgs(f) can be used as an
|
||||
// Action<F> as long as f's type is compatible with F.
|
||||
template <typename FunctionImpl>
|
||||
struct InvokeWithoutArgsAction {
|
||||
FunctionImpl function_impl;
|
||||
|
||||
// Allows InvokeWithoutArgs(f) to be used as any action whose type is
|
||||
// compatible with f.
|
||||
template <typename... Args>
|
||||
auto operator()(const Args&...) -> decltype(function_impl()) {
|
||||
return function_impl();
|
||||
}
|
||||
};
|
||||
|
||||
// Implements the InvokeWithoutArgs(object_ptr, &Class::Method) action.
|
||||
template <class Class, typename MethodPtr>
|
||||
struct InvokeMethodWithoutArgsAction {
|
||||
@@ -1393,7 +1379,7 @@ class IgnoreResultAction {
|
||||
|
||||
void Perform(const ArgumentTuple& args) override {
|
||||
// Performs the action and ignores its result.
|
||||
action_.Perform(args);
|
||||
(void)action_.Perform(args);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -1451,6 +1437,30 @@ struct WithArgsAction {
|
||||
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 <
|
||||
typename R, typename... Args,
|
||||
typename std::enable_if<
|
||||
@@ -1475,11 +1485,11 @@ struct WithArgsAction {
|
||||
};
|
||||
|
||||
template <typename... Actions>
|
||||
class DoAllAction;
|
||||
class [[nodiscard]] DoAllAction;
|
||||
|
||||
// Base case: only a single action.
|
||||
template <typename FinalAction>
|
||||
class DoAllAction<FinalAction> {
|
||||
class [[nodiscard]] DoAllAction<FinalAction> {
|
||||
public:
|
||||
struct UserConstructorTag {};
|
||||
|
||||
@@ -1533,7 +1543,7 @@ class DoAllAction<FinalAction> {
|
||||
// Recursive case: support N actions by calling the initial action and then
|
||||
// calling through to the base class containing N-1 actions.
|
||||
template <typename InitialAction, typename... OtherActions>
|
||||
class DoAllAction<InitialAction, OtherActions...>
|
||||
class [[nodiscard]] DoAllAction<InitialAction, OtherActions...>
|
||||
: private DoAllAction<OtherActions...> {
|
||||
private:
|
||||
using Base = DoAllAction<OtherActions...>;
|
||||
@@ -1703,9 +1713,8 @@ template <size_t k>
|
||||
struct ReturnArgAction {
|
||||
template <typename... Args,
|
||||
typename = typename std::enable_if<(k < sizeof...(Args))>::type>
|
||||
auto operator()(Args&&... args) const
|
||||
-> decltype(std::get<k>(
|
||||
std::forward_as_tuple(std::forward<Args>(args)...))) {
|
||||
auto operator()(Args&&... args) const -> decltype(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 +1729,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>
|
||||
struct SaveArgPointeeAction {
|
||||
Ptr pointer;
|
||||
@@ -1759,11 +1778,24 @@ struct SetArrayArgumentAction {
|
||||
};
|
||||
|
||||
template <size_t k>
|
||||
struct DeleteArgAction {
|
||||
class [[nodiscard]] DeleteArgAction {
|
||||
public:
|
||||
template <typename... Args>
|
||||
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>
|
||||
@@ -1829,6 +1861,13 @@ struct RethrowAction {
|
||||
// EXPECT_CALL(mock, Bar(5, _, _)).WillOnce(Invoke(DistanceToOrigin));
|
||||
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
|
||||
// each invocation. All but the last action will have a readonly view of the
|
||||
// arguments.
|
||||
@@ -1994,10 +2033,11 @@ PolymorphicAction<internal::SetErrnoAndReturnAction<T>> SetErrnoAndReturn(
|
||||
// Various overloads for Invoke().
|
||||
|
||||
// Legacy function.
|
||||
// Actions can now be implicitly constructed from callables. No need to create
|
||||
// wrapper objects.
|
||||
// This function exists for backwards compatibility.
|
||||
template <typename FunctionImpl>
|
||||
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) {
|
||||
return std::forward<FunctionImpl>(function_impl);
|
||||
}
|
||||
@@ -2012,9 +2052,11 @@ internal::InvokeMethodAction<Class, MethodPtr> Invoke(Class* obj_ptr,
|
||||
|
||||
// Creates an action that invokes 'function_impl' with no argument.
|
||||
template <typename FunctionImpl>
|
||||
internal::InvokeWithoutArgsAction<typename std::decay<FunctionImpl>::type>
|
||||
InvokeWithoutArgs(FunctionImpl function_impl) {
|
||||
return {std::move(function_impl)};
|
||||
GTEST_INTERNAL_DEPRECATE_AND_INLINE(
|
||||
"Actions can now be implicitly constructed from zero-argument callables. "
|
||||
"No need to create wrapper objects using InvokeWithoutArgs().")
|
||||
std::decay_t<FunctionImpl> InvokeWithoutArgs(FunctionImpl&& function_impl) {
|
||||
return std::forward<FunctionImpl>(function_impl);
|
||||
}
|
||||
|
||||
// Creates an action that invokes the given method on the given object
|
||||
@@ -2070,6 +2112,13 @@ internal::SaveArgAction<k, Ptr> SaveArg(Ptr 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
|
||||
// by the k-th (0-based) argument of the mock function to *pointer.
|
||||
template <size_t k, typename Ptr>
|
||||
@@ -2213,9 +2262,9 @@ template <typename F, typename Impl>
|
||||
}
|
||||
|
||||
#define GMOCK_INTERNAL_ARG_UNUSED(i, data, el) \
|
||||
, GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED const arg##i##_type& arg##i
|
||||
#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_ \
|
||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED const args_type& args GMOCK_PP_REPEAT( \
|
||||
, [[maybe_unused]] const arg##i##_type& arg##i
|
||||
#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_ \
|
||||
[[maybe_unused]] const args_type& args GMOCK_PP_REPEAT( \
|
||||
GMOCK_INTERNAL_ARG_UNUSED, , 10)
|
||||
|
||||
#define GMOCK_INTERNAL_ARG(i, data, el) , const arg##i##_type& arg##i
|
||||
@@ -2280,8 +2329,8 @@ template <typename F, typename Impl>
|
||||
std::shared_ptr<const gmock_Impl> impl_; \
|
||||
}; \
|
||||
template <GMOCK_ACTION_TYPENAME_PARAMS_(params)> \
|
||||
inline full_name<GMOCK_ACTION_TYPE_PARAMS_(params)> name( \
|
||||
GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) GTEST_MUST_USE_RESULT_; \
|
||||
[[nodiscard]] inline full_name<GMOCK_ACTION_TYPE_PARAMS_(params)> name( \
|
||||
GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)); \
|
||||
template <GMOCK_ACTION_TYPENAME_PARAMS_(params)> \
|
||||
inline full_name<GMOCK_ACTION_TYPE_PARAMS_(params)> name( \
|
||||
GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) { \
|
||||
@@ -2316,7 +2365,7 @@ template <typename F, typename Impl>
|
||||
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(); } \
|
||||
template <typename function_type, typename return_type, typename args_type, \
|
||||
GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace testing {
|
||||
// management as Cardinality objects can now be copied like plain values.
|
||||
|
||||
// The implementation of a cardinality.
|
||||
class CardinalityInterface {
|
||||
class [[nodiscard]] CardinalityInterface {
|
||||
public:
|
||||
virtual ~CardinalityInterface() = default;
|
||||
|
||||
@@ -88,7 +88,7 @@ class CardinalityInterface {
|
||||
// object that specifies how many times a mock function is expected to
|
||||
// be called. The implementation of Cardinality is just a std::shared_ptr
|
||||
// to const CardinalityInterface. Don't inherit from Cardinality!
|
||||
class GTEST_API_ Cardinality {
|
||||
class GTEST_API_ [[nodiscard]] Cardinality {
|
||||
public:
|
||||
// Constructs a null cardinality. Needed for storing Cardinality
|
||||
// objects in STL containers.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -521,9 +521,8 @@
|
||||
GMOCK_INTERNAL_DECL_##value_params) \
|
||||
GMOCK_PP_IF(GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params), \
|
||||
= default; \
|
||||
, \
|
||||
: impl_(std::make_shared<gmock_Impl>( \
|
||||
GMOCK_INTERNAL_LIST_##value_params)){}) \
|
||||
, : impl_(std::make_shared<gmock_Impl>( \
|
||||
GMOCK_INTERNAL_LIST_##value_params)){}) \
|
||||
GMOCK_ACTION_CLASS_(name, value_params)(const GMOCK_ACTION_CLASS_( \
|
||||
name, value_params) &) noexcept GMOCK_INTERNAL_DEFN_COPY_ \
|
||||
##value_params \
|
||||
@@ -551,10 +550,10 @@
|
||||
}; \
|
||||
template <GMOCK_INTERNAL_DECL_##template_params \
|
||||
GMOCK_INTERNAL_DECL_TYPE_##value_params> \
|
||||
GMOCK_ACTION_CLASS_( \
|
||||
[[nodiscard]] GMOCK_ACTION_CLASS_( \
|
||||
name, value_params)<GMOCK_INTERNAL_LIST_##template_params \
|
||||
GMOCK_INTERNAL_LIST_TYPE_##value_params> \
|
||||
name(GMOCK_INTERNAL_DECL_##value_params) GTEST_MUST_USE_RESULT_; \
|
||||
name(GMOCK_INTERNAL_DECL_##value_params); \
|
||||
template <GMOCK_INTERNAL_DECL_##template_params \
|
||||
GMOCK_INTERNAL_DECL_TYPE_##value_params> \
|
||||
inline GMOCK_ACTION_CLASS_( \
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace internal {
|
||||
// Implements the polymorphic IsEmpty matcher, which
|
||||
// can be used as a Matcher<T> as long as T is either a container that defines
|
||||
// empty() and size() (e.g. std::vector or std::string), or a C-style string.
|
||||
class IsEmptyMatcher {
|
||||
class [[nodiscard]] IsEmptyMatcher {
|
||||
public:
|
||||
// Matches anything that defines empty() and size().
|
||||
template <typename MatcheeContainerType>
|
||||
@@ -76,9 +76,22 @@ class IsEmptyMatcher {
|
||||
|
||||
// Matches C-style strings.
|
||||
bool MatchAndExplain(const char* s, MatchResultListener* listener) const {
|
||||
if (s == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return MatchAndExplain(std::string(s), listener);
|
||||
}
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
// Matches C-style wide strings.
|
||||
bool MatchAndExplain(const wchar_t* s, MatchResultListener* listener) const {
|
||||
if (s == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return MatchAndExplain(std::wstring(s), listener);
|
||||
}
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
|
||||
// Describes what this matcher matches.
|
||||
void DescribeTo(std::ostream* os) const { *os << "is empty"; }
|
||||
|
||||
|
||||
@@ -71,11 +71,11 @@
|
||||
|
||||
namespace testing {
|
||||
template <class MockClass>
|
||||
class NiceMock;
|
||||
class [[nodiscard]] NiceMock;
|
||||
template <class MockClass>
|
||||
class NaggyMock;
|
||||
class [[nodiscard]] NaggyMock;
|
||||
template <class MockClass>
|
||||
class StrictMock;
|
||||
class [[nodiscard]] StrictMock;
|
||||
|
||||
namespace internal {
|
||||
template <typename T>
|
||||
@@ -108,7 +108,7 @@ constexpr bool HasStrictnessModifier() {
|
||||
#endif
|
||||
|
||||
template <typename Base>
|
||||
class NiceMockImpl {
|
||||
class [[nodiscard]] NiceMockImpl {
|
||||
public:
|
||||
NiceMockImpl() {
|
||||
::testing::Mock::AllowUninterestingCalls(reinterpret_cast<uintptr_t>(this));
|
||||
@@ -120,7 +120,7 @@ class NiceMockImpl {
|
||||
};
|
||||
|
||||
template <typename Base>
|
||||
class NaggyMockImpl {
|
||||
class [[nodiscard]] NaggyMockImpl {
|
||||
public:
|
||||
NaggyMockImpl() {
|
||||
::testing::Mock::WarnUninterestingCalls(reinterpret_cast<uintptr_t>(this));
|
||||
@@ -132,7 +132,7 @@ class NaggyMockImpl {
|
||||
};
|
||||
|
||||
template <typename Base>
|
||||
class StrictMockImpl {
|
||||
class [[nodiscard]] StrictMockImpl {
|
||||
public:
|
||||
StrictMockImpl() {
|
||||
::testing::Mock::FailUninterestingCalls(reinterpret_cast<uintptr_t>(this));
|
||||
@@ -146,7 +146,7 @@ class StrictMockImpl {
|
||||
} // namespace internal
|
||||
|
||||
template <class MockClass>
|
||||
class GTEST_INTERNAL_EMPTY_BASE_CLASS NiceMock
|
||||
class [[nodiscard]] GTEST_INTERNAL_EMPTY_BASE_CLASS NiceMock
|
||||
: private internal::NiceMockImpl<MockClass>,
|
||||
public MockClass {
|
||||
public:
|
||||
@@ -187,7 +187,7 @@ class GTEST_INTERNAL_EMPTY_BASE_CLASS NiceMock
|
||||
};
|
||||
|
||||
template <class MockClass>
|
||||
class GTEST_INTERNAL_EMPTY_BASE_CLASS NaggyMock
|
||||
class [[nodiscard]] GTEST_INTERNAL_EMPTY_BASE_CLASS NaggyMock
|
||||
: private internal::NaggyMockImpl<MockClass>,
|
||||
public MockClass {
|
||||
static_assert(!internal::HasStrictnessModifier<MockClass>(),
|
||||
@@ -229,7 +229,7 @@ class GTEST_INTERNAL_EMPTY_BASE_CLASS NaggyMock
|
||||
};
|
||||
|
||||
template <class MockClass>
|
||||
class GTEST_INTERNAL_EMPTY_BASE_CLASS StrictMock
|
||||
class [[nodiscard]] GTEST_INTERNAL_EMPTY_BASE_CLASS StrictMock
|
||||
: private internal::StrictMockImpl<MockClass>,
|
||||
public MockClass {
|
||||
public:
|
||||
|
||||
@@ -1292,10 +1292,10 @@ class MockSpec {
|
||||
: function_mocker_(function_mocker), matchers_(matchers) {}
|
||||
|
||||
// Adds a new default action spec to the function mocker and returns
|
||||
// the newly created spec.
|
||||
internal::OnCallSpec<F>& InternalDefaultActionSetAt(const char* file,
|
||||
int line, const char* obj,
|
||||
const char* call) {
|
||||
// the newly created spec. .WillByDefault() must be called on the returned
|
||||
// object.
|
||||
[[nodiscard]] internal::OnCallSpec<F>& InternalDefaultActionSetAt(
|
||||
const char* file, int line, const char* obj, const char* call) {
|
||||
LogWithLocation(internal::kInfo, file, line,
|
||||
std::string("ON_CALL(") + obj + ", " + call + ") invoked");
|
||||
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
|
||||
// non-fatal failures for the violations.
|
||||
~FunctionMocker() override GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||
MutexLock l(&g_gmock_mutex);
|
||||
MutexLock l(g_gmock_mutex);
|
||||
VerifyAndClearExpectationsLocked();
|
||||
Mock::UnregisterLocked(this);
|
||||
ClearDefaultActionsLocked();
|
||||
@@ -1530,7 +1530,7 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase {
|
||||
UntypedOnCallSpecs 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();
|
||||
it != specs_to_delete.end(); ++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
|
||||
// return.
|
||||
g_gmock_mutex.Lock();
|
||||
g_gmock_mutex.lock();
|
||||
}
|
||||
|
||||
// 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) {
|
||||
const ArgumentTuple& args =
|
||||
*static_cast<const ArgumentTuple*>(untyped_args);
|
||||
MutexLock l(&g_gmock_mutex);
|
||||
MutexLock l(g_gmock_mutex);
|
||||
TypedExpectation<F>* exp = this->FindMatchingExpectationLocked(args);
|
||||
if (exp == nullptr) { // A match wasn't found.
|
||||
this->FormatUnexpectedCallMessageLocked(args, what, why);
|
||||
@@ -1957,6 +1957,11 @@ struct SignatureOf<R(Args...)> {
|
||||
using type = R(Args...);
|
||||
};
|
||||
|
||||
template <typename R, typename... Args>
|
||||
struct SignatureOf<R(Args...) const> {
|
||||
using type = R(Args...);
|
||||
};
|
||||
|
||||
template <template <typename> class C, typename F>
|
||||
struct SignatureOf<C<F>,
|
||||
typename std::enable_if<std::is_function<F>::value>::type>
|
||||
@@ -2132,9 +2137,9 @@ GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||
// second argument is an internal type derived from the method signature. The
|
||||
// failure to disambiguate two overloads of this method in the ON_CALL statement
|
||||
// is how we block callers from setting expectations on overloaded methods.
|
||||
#define GMOCK_ON_CALL_IMPL_(mock_expr, Setter, call) \
|
||||
((mock_expr).gmock_##call)(::testing::internal::GetWithoutMatchers(), \
|
||||
nullptr) \
|
||||
#define GMOCK_ON_CALL_IMPL_(mock_expr, Setter, call) \
|
||||
((mock_expr).gmock_##call)(::testing::internal::WithoutMatchers::Get(), \
|
||||
nullptr) \
|
||||
.Setter(__FILE__, __LINE__, #mock_expr, #call)
|
||||
|
||||
#define ON_CALL(obj, call) \
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <iterator>
|
||||
#include <ostream> // NOLINT
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
@@ -110,16 +111,6 @@ inline Element* GetRawPointer(Element* p) {
|
||||
#define GMOCK_INTERNAL_WARNING_POP() _Pragma("clang diagnostic pop")
|
||||
#endif
|
||||
|
||||
// MSVC treats wchar_t as a native type usually, but treats it as the
|
||||
// same as unsigned short when the compiler option /Zc:wchar_t- is
|
||||
// specified. It defines _NATIVE_WCHAR_T_DEFINED symbol when wchar_t
|
||||
// is a native type.
|
||||
#if defined(_MSC_VER) && !defined(_NATIVE_WCHAR_T_DEFINED)
|
||||
// wchar_t is a typedef.
|
||||
#else
|
||||
#define GMOCK_WCHAR_T_IS_NATIVE_ 1
|
||||
#endif
|
||||
|
||||
// In what follows, we use the term "kind" to indicate whether a type
|
||||
// is bool, an integer type (excluding bool), a floating-point type,
|
||||
// or none of them. This categorization is useful for determining
|
||||
@@ -155,7 +146,7 @@ GMOCK_DECLARE_KIND_(unsigned long, kInteger); // NOLINT
|
||||
GMOCK_DECLARE_KIND_(long long, kInteger); // NOLINT
|
||||
GMOCK_DECLARE_KIND_(unsigned long long, kInteger); // NOLINT
|
||||
|
||||
#if GMOCK_WCHAR_T_IS_NATIVE_
|
||||
#if GTEST_HAS_NATIVE_WCHAR
|
||||
GMOCK_DECLARE_KIND_(wchar_t, kInteger);
|
||||
#endif
|
||||
|
||||
@@ -193,11 +184,11 @@ using LosslessArithmeticConvertibleImpl = std::integral_constant<
|
||||
// Converting between integers of different widths is allowed so long
|
||||
// as the conversion does not go from signed to unsigned.
|
||||
(((sizeof(From) < sizeof(To)) &&
|
||||
!(std::is_signed<From>::value && !std::is_signed<To>::value)) ||
|
||||
!(std::is_signed_v<From> && !std::is_signed_v<To>)) ||
|
||||
// Converting between integers of the same width only requires the
|
||||
// two types to have the same signedness.
|
||||
((sizeof(From) == sizeof(To)) &&
|
||||
(std::is_signed<From>::value == std::is_signed<To>::value)))
|
||||
(std::is_signed_v<From> == std::is_signed_v<To>)))
|
||||
) ? true
|
||||
// Floating point conversions are lossless if and only if `To` is at least
|
||||
// as wide as `From`.
|
||||
@@ -220,7 +211,7 @@ using LosslessArithmeticConvertible =
|
||||
|
||||
// This interface knows how to report a Google Mock failure (either
|
||||
// non-fatal or fatal).
|
||||
class FailureReporterInterface {
|
||||
class [[nodiscard]] FailureReporterInterface {
|
||||
public:
|
||||
// The type of a failure (either non-fatal or fatal).
|
||||
enum FailureType { kNonfatal, kFatal };
|
||||
@@ -296,14 +287,13 @@ GTEST_API_ void Log(LogSeverity severity, const std::string& message,
|
||||
//
|
||||
// ON_CALL(mock, Method({}, nullptr))...
|
||||
//
|
||||
class WithoutMatchers {
|
||||
class [[nodiscard]] WithoutMatchers {
|
||||
private:
|
||||
WithoutMatchers() {}
|
||||
friend GTEST_API_ WithoutMatchers GetWithoutMatchers();
|
||||
};
|
||||
WithoutMatchers() = default;
|
||||
|
||||
// Internal use only: access the singleton instance of WithoutMatchers.
|
||||
GTEST_API_ WithoutMatchers GetWithoutMatchers();
|
||||
public:
|
||||
GTEST_API_ static WithoutMatchers Get();
|
||||
};
|
||||
|
||||
// Invalid<T>() is usable as an expression of type T, but will terminate
|
||||
// the program with an assertion failure if actually run. This is useful
|
||||
@@ -323,6 +313,24 @@ inline T Invalid() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void GetValueType(const void*);
|
||||
|
||||
template <class T>
|
||||
typename std::iterator_traits<
|
||||
decltype(std::begin(std::declval<T&>()))>::value_type
|
||||
GetValueType(T*);
|
||||
|
||||
template <class T, class = void>
|
||||
struct RangeTraits {
|
||||
typedef decltype(internal::GetValueType(
|
||||
static_cast<std::remove_reference_t<T>*>(nullptr))) value_type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct RangeTraits<T, std::conditional_t<true, void, typename T::value_type>> {
|
||||
typedef typename T::value_type value_type;
|
||||
};
|
||||
|
||||
// Given a raw type (i.e. having no top-level reference or const
|
||||
// modifier) RawContainer that's either an STL-style container or a
|
||||
// native array, class StlContainerView<RawContainer> has the
|
||||
@@ -340,13 +348,13 @@ inline T Invalid() {
|
||||
// This generic version is used when RawContainer itself is already an
|
||||
// STL-style container.
|
||||
template <class RawContainer>
|
||||
class StlContainerView {
|
||||
class [[nodiscard]] StlContainerView {
|
||||
public:
|
||||
typedef RawContainer type;
|
||||
typedef const type& const_reference;
|
||||
|
||||
static const_reference ConstReference(const RawContainer& container) {
|
||||
static_assert(!std::is_const<RawContainer>::value,
|
||||
static_assert(!std::is_const_v<RawContainer>,
|
||||
"RawContainer type must not be const");
|
||||
return container;
|
||||
}
|
||||
@@ -355,7 +363,7 @@ class StlContainerView {
|
||||
|
||||
// This specialization is used when RawContainer is a native array type.
|
||||
template <typename Element, size_t N>
|
||||
class StlContainerView<Element[N]> {
|
||||
class [[nodiscard]] StlContainerView<Element[N]> {
|
||||
public:
|
||||
typedef typename std::remove_const<Element>::type RawElement;
|
||||
typedef internal::NativeArray<RawElement> type;
|
||||
@@ -367,7 +375,7 @@ class StlContainerView<Element[N]> {
|
||||
typedef const type const_reference;
|
||||
|
||||
static const_reference ConstReference(const Element (&array)[N]) {
|
||||
static_assert(std::is_same<Element, RawElement>::value,
|
||||
static_assert(std::is_same_v<Element, RawElement>,
|
||||
"Element type must not be const");
|
||||
return type(array, N, RelationToSourceReference());
|
||||
}
|
||||
@@ -379,7 +387,7 @@ class StlContainerView<Element[N]> {
|
||||
// This specialization is used when RawContainer is a native array
|
||||
// represented as a (pointer, size) tuple.
|
||||
template <typename ElementPointer, typename Size>
|
||||
class StlContainerView< ::std::tuple<ElementPointer, Size> > {
|
||||
class [[nodiscard]] StlContainerView< ::std::tuple<ElementPointer, Size> > {
|
||||
public:
|
||||
typedef typename std::remove_const<
|
||||
typename std::pointer_traits<ElementPointer>::element_type>::type
|
||||
@@ -429,14 +437,13 @@ auto ApplyImpl(F&& f, Tuple&& args, std::index_sequence<Idx...>)
|
||||
|
||||
// Apply the function to a tuple of arguments.
|
||||
template <typename F, typename Tuple>
|
||||
auto Apply(F&& f, Tuple&& args)
|
||||
-> decltype(ApplyImpl(
|
||||
std::forward<F>(f), std::forward<Tuple>(args),
|
||||
std::make_index_sequence<std::tuple_size<
|
||||
typename std::remove_reference<Tuple>::type>::value>())) {
|
||||
auto Apply(F&& f, Tuple&& args) -> decltype(ApplyImpl(
|
||||
std::forward<F>(f), std::forward<Tuple>(args),
|
||||
std::make_index_sequence<
|
||||
std::tuple_size_v<std::remove_reference_t<Tuple>>>())) {
|
||||
return ApplyImpl(std::forward<F>(f), std::forward<Tuple>(args),
|
||||
std::make_index_sequence<std::tuple_size<
|
||||
typename std::remove_reference<Tuple>::type>::value>());
|
||||
std::make_index_sequence<
|
||||
std::tuple_size_v<std::remove_reference_t<Tuple>>>());
|
||||
}
|
||||
|
||||
// Template struct Function<F>, where F must be a function type, contains
|
||||
@@ -467,17 +474,12 @@ struct Function<R(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'
|
||||
// when std::tuple_element is used.
|
||||
// See: https://github.com/google/googletest/issues/3931
|
||||
// Can be replaced with std::tuple_element_t in C++14.
|
||||
template <size_t I, typename T>
|
||||
using TupleElement = typename std::tuple_element<I, T>::type;
|
||||
using TupleElement = std::tuple_element_t<I, T>;
|
||||
|
||||
bool Base64Unescape(const std::string& encoded, std::string* decoded);
|
||||
|
||||
|
||||
@@ -86,11 +86,11 @@
|
||||
|
||||
// Macros for declaring flags.
|
||||
#define GMOCK_DECLARE_bool_(name) \
|
||||
ABSL_DECLARE_FLAG(bool, GMOCK_FLAG_NAME_(name))
|
||||
GTEST_API_ ABSL_DECLARE_FLAG(bool, GMOCK_FLAG_NAME_(name))
|
||||
#define GMOCK_DECLARE_int32_(name) \
|
||||
ABSL_DECLARE_FLAG(int32_t, GMOCK_FLAG_NAME_(name))
|
||||
GTEST_API_ ABSL_DECLARE_FLAG(int32_t, GMOCK_FLAG_NAME_(name))
|
||||
#define GMOCK_DECLARE_string_(name) \
|
||||
ABSL_DECLARE_FLAG(std::string, GMOCK_FLAG_NAME_(name))
|
||||
GTEST_API_ ABSL_DECLARE_FLAG(std::string, GMOCK_FLAG_NAME_(name))
|
||||
|
||||
#define GMOCK_FLAG_GET(name) ::absl::GetFlag(GMOCK_FLAG(name))
|
||||
#define GMOCK_FLAG_SET(name, value) \
|
||||
|
||||
@@ -25,16 +25,18 @@
|
||||
// GMOCK_PP_NARG(x, y) => 2
|
||||
// GMOCK_PP_NARG(PAIR) => 2
|
||||
//
|
||||
// Requires: the number of arguments after expansion is at most 15.
|
||||
#define GMOCK_PP_NARG(...) \
|
||||
GMOCK_PP_INTERNAL_16TH( \
|
||||
(__VA_ARGS__, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
|
||||
// Requires: the number of arguments after expansion is at most 31.
|
||||
#define GMOCK_PP_NARG(...) \
|
||||
GMOCK_PP_INTERNAL_32ND((__VA_ARGS__, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, \
|
||||
21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, \
|
||||
8, 7, 6, 5, 4, 3, 2, 1, 0))
|
||||
|
||||
// Returns 1 if the expansion of arguments has an unprotected comma. Otherwise
|
||||
// returns 0. Requires no more than 15 unprotected commas.
|
||||
#define GMOCK_PP_HAS_COMMA(...) \
|
||||
GMOCK_PP_INTERNAL_16TH( \
|
||||
(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0))
|
||||
// returns 0. Requires no more than 31 unprotected commas.
|
||||
#define GMOCK_PP_HAS_COMMA(...) \
|
||||
GMOCK_PP_INTERNAL_32ND((__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
0, 0))
|
||||
|
||||
// Returns the first argument.
|
||||
#define GMOCK_PP_HEAD(...) GMOCK_PP_INTERNAL_HEAD((__VA_ARGS__, unusedArg))
|
||||
@@ -51,7 +53,7 @@
|
||||
// If the arguments after expansion have no tokens, evaluates to `1`. Otherwise
|
||||
// evaluates to `0`.
|
||||
//
|
||||
// Requires: * the number of arguments after expansion is at most 15.
|
||||
// Requires: * the number of arguments after expansion is at most 31.
|
||||
// * If the argument is a macro, it must be able to be called with one
|
||||
// argument.
|
||||
//
|
||||
@@ -104,7 +106,7 @@
|
||||
// GMOCK_PP_NARG0(x, y) => 2
|
||||
// GMOCK_PP_NARG0(PAIR) => 2
|
||||
//
|
||||
// Requires: * the number of arguments after expansion is at most 15.
|
||||
// Requires: * the number of arguments after expansion is at most 31.
|
||||
// * If the argument is a macro, it must be able to be called with one
|
||||
// argument.
|
||||
#define GMOCK_PP_NARG0(...) \
|
||||
@@ -127,7 +129,7 @@
|
||||
// Expands to _Macro(0, _Data, e1) _Macro(1, _Data, e2) ... _Macro(K -1, _Data,
|
||||
// eK) as many of GMOCK_INTERNAL_NARG0 _Tuple.
|
||||
// Requires: * |_Macro| can be called with 3 arguments.
|
||||
// * |_Tuple| expansion has no more than 15 elements.
|
||||
// * |_Tuple| expansion has no more than 31 elements.
|
||||
#define GMOCK_PP_FOR_EACH(_Macro, _Data, _Tuple) \
|
||||
GMOCK_PP_CAT(GMOCK_PP_INTERNAL_FOR_EACH_IMPL_, GMOCK_PP_NARG0 _Tuple) \
|
||||
(0, _Macro, _Data, _Tuple)
|
||||
@@ -135,20 +137,21 @@
|
||||
// Expands to _Macro(0, _Data, ) _Macro(1, _Data, ) ... _Macro(K - 1, _Data, )
|
||||
// Empty if _K = 0.
|
||||
// Requires: * |_Macro| can be called with 3 arguments.
|
||||
// * |_K| literal between 0 and 15
|
||||
// * |_K| literal between 0 and 31
|
||||
#define GMOCK_PP_REPEAT(_Macro, _Data, _N) \
|
||||
GMOCK_PP_CAT(GMOCK_PP_INTERNAL_FOR_EACH_IMPL_, _N) \
|
||||
(0, _Macro, _Data, GMOCK_PP_INTENRAL_EMPTY_TUPLE)
|
||||
|
||||
// Increments the argument, requires the argument to be between 0 and 15.
|
||||
// Increments the argument, requires the argument to be between 0 and 31.
|
||||
#define GMOCK_PP_INC(_i) GMOCK_PP_CAT(GMOCK_PP_INTERNAL_INC_, _i)
|
||||
|
||||
// Returns comma if _i != 0. Requires _i to be between 0 and 15.
|
||||
// Returns comma if _i != 0. Requires _i to be between 0 and 31.
|
||||
#define GMOCK_PP_COMMA_IF(_i) GMOCK_PP_CAT(GMOCK_PP_INTERNAL_COMMA_IF_, _i)
|
||||
|
||||
// Internal details follow. Do not use any of these symbols outside of this
|
||||
// file or we will break your code.
|
||||
#define GMOCK_PP_INTENRAL_EMPTY_TUPLE (, , , , , , , , , , , , , , , )
|
||||
#define GMOCK_PP_INTENRAL_EMPTY_TUPLE \
|
||||
(, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , )
|
||||
#define GMOCK_PP_INTERNAL_CAT(_1, _2) _1##_2
|
||||
#define GMOCK_PP_INTERNAL_STRINGIZE(...) #__VA_ARGS__
|
||||
#define GMOCK_PP_INTERNAL_CAT_5(_1, _2, _3, _4, _5) _1##_2##_3##_4##_5
|
||||
@@ -164,12 +167,13 @@
|
||||
// tokens. We do that by using a "IDENTITY(MACRO PARENTHESIZED_ARGS)" macro. We
|
||||
// define one per possible macro that relies on this behavior. Note "_Args" must
|
||||
// be parenthesized.
|
||||
#define GMOCK_PP_INTERNAL_INTERNAL_16TH(_1, _2, _3, _4, _5, _6, _7, _8, _9, \
|
||||
_10, _11, _12, _13, _14, _15, _16, \
|
||||
...) \
|
||||
_16
|
||||
#define GMOCK_PP_INTERNAL_16TH(_Args) \
|
||||
GMOCK_PP_IDENTITY(GMOCK_PP_INTERNAL_INTERNAL_16TH _Args)
|
||||
#define GMOCK_PP_INTERNAL_INTERNAL_32ND( \
|
||||
_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, \
|
||||
_17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, \
|
||||
_32, ...) \
|
||||
_32
|
||||
#define GMOCK_PP_INTERNAL_32ND(_Args) \
|
||||
GMOCK_PP_IDENTITY(GMOCK_PP_INTERNAL_INTERNAL_32ND _Args)
|
||||
#define GMOCK_PP_INTERNAL_INTERNAL_HEAD(_1, ...) _1
|
||||
#define GMOCK_PP_INTERNAL_HEAD(_Args) \
|
||||
GMOCK_PP_IDENTITY(GMOCK_PP_INTERNAL_INTERNAL_HEAD _Args)
|
||||
@@ -198,6 +202,22 @@
|
||||
#define GMOCK_PP_INTERNAL_INC_13 14
|
||||
#define GMOCK_PP_INTERNAL_INC_14 15
|
||||
#define GMOCK_PP_INTERNAL_INC_15 16
|
||||
#define GMOCK_PP_INTERNAL_INC_16 17
|
||||
#define GMOCK_PP_INTERNAL_INC_17 18
|
||||
#define GMOCK_PP_INTERNAL_INC_18 19
|
||||
#define GMOCK_PP_INTERNAL_INC_19 20
|
||||
#define GMOCK_PP_INTERNAL_INC_20 21
|
||||
#define GMOCK_PP_INTERNAL_INC_21 22
|
||||
#define GMOCK_PP_INTERNAL_INC_22 23
|
||||
#define GMOCK_PP_INTERNAL_INC_23 24
|
||||
#define GMOCK_PP_INTERNAL_INC_24 25
|
||||
#define GMOCK_PP_INTERNAL_INC_25 26
|
||||
#define GMOCK_PP_INTERNAL_INC_26 27
|
||||
#define GMOCK_PP_INTERNAL_INC_27 28
|
||||
#define GMOCK_PP_INTERNAL_INC_28 29
|
||||
#define GMOCK_PP_INTERNAL_INC_29 30
|
||||
#define GMOCK_PP_INTERNAL_INC_30 31
|
||||
#define GMOCK_PP_INTERNAL_INC_31 32
|
||||
#define GMOCK_PP_INTERNAL_COMMA_IF_0
|
||||
#define GMOCK_PP_INTERNAL_COMMA_IF_1 ,
|
||||
#define GMOCK_PP_INTERNAL_COMMA_IF_2 ,
|
||||
@@ -214,6 +234,22 @@
|
||||
#define GMOCK_PP_INTERNAL_COMMA_IF_13 ,
|
||||
#define GMOCK_PP_INTERNAL_COMMA_IF_14 ,
|
||||
#define GMOCK_PP_INTERNAL_COMMA_IF_15 ,
|
||||
#define GMOCK_PP_INTERNAL_COMMA_IF_16 ,
|
||||
#define GMOCK_PP_INTERNAL_COMMA_IF_17 ,
|
||||
#define GMOCK_PP_INTERNAL_COMMA_IF_18 ,
|
||||
#define GMOCK_PP_INTERNAL_COMMA_IF_19 ,
|
||||
#define GMOCK_PP_INTERNAL_COMMA_IF_20 ,
|
||||
#define GMOCK_PP_INTERNAL_COMMA_IF_21 ,
|
||||
#define GMOCK_PP_INTERNAL_COMMA_IF_22 ,
|
||||
#define GMOCK_PP_INTERNAL_COMMA_IF_23 ,
|
||||
#define GMOCK_PP_INTERNAL_COMMA_IF_24 ,
|
||||
#define GMOCK_PP_INTERNAL_COMMA_IF_25 ,
|
||||
#define GMOCK_PP_INTERNAL_COMMA_IF_26 ,
|
||||
#define GMOCK_PP_INTERNAL_COMMA_IF_27 ,
|
||||
#define GMOCK_PP_INTERNAL_COMMA_IF_28 ,
|
||||
#define GMOCK_PP_INTERNAL_COMMA_IF_29 ,
|
||||
#define GMOCK_PP_INTERNAL_COMMA_IF_30 ,
|
||||
#define GMOCK_PP_INTERNAL_COMMA_IF_31 ,
|
||||
#define GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, _element) \
|
||||
_Macro(_i, _Data, _element)
|
||||
#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_0(_i, _Macro, _Data, _Tuple)
|
||||
@@ -275,5 +311,69 @@
|
||||
GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
|
||||
GMOCK_PP_INTERNAL_FOR_EACH_IMPL_14(GMOCK_PP_INC(_i), _Macro, _Data, \
|
||||
(GMOCK_PP_TAIL _Tuple))
|
||||
#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_16(_i, _Macro, _Data, _Tuple) \
|
||||
GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
|
||||
GMOCK_PP_INTERNAL_FOR_EACH_IMPL_15(GMOCK_PP_INC(_i), _Macro, _Data, \
|
||||
(GMOCK_PP_TAIL _Tuple))
|
||||
#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_17(_i, _Macro, _Data, _Tuple) \
|
||||
GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
|
||||
GMOCK_PP_INTERNAL_FOR_EACH_IMPL_16(GMOCK_PP_INC(_i), _Macro, _Data, \
|
||||
(GMOCK_PP_TAIL _Tuple))
|
||||
#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_18(_i, _Macro, _Data, _Tuple) \
|
||||
GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
|
||||
GMOCK_PP_INTERNAL_FOR_EACH_IMPL_17(GMOCK_PP_INC(_i), _Macro, _Data, \
|
||||
(GMOCK_PP_TAIL _Tuple))
|
||||
#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_19(_i, _Macro, _Data, _Tuple) \
|
||||
GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
|
||||
GMOCK_PP_INTERNAL_FOR_EACH_IMPL_18(GMOCK_PP_INC(_i), _Macro, _Data, \
|
||||
(GMOCK_PP_TAIL _Tuple))
|
||||
#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_20(_i, _Macro, _Data, _Tuple) \
|
||||
GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
|
||||
GMOCK_PP_INTERNAL_FOR_EACH_IMPL_19(GMOCK_PP_INC(_i), _Macro, _Data, \
|
||||
(GMOCK_PP_TAIL _Tuple))
|
||||
#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_21(_i, _Macro, _Data, _Tuple) \
|
||||
GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
|
||||
GMOCK_PP_INTERNAL_FOR_EACH_IMPL_20(GMOCK_PP_INC(_i), _Macro, _Data, \
|
||||
(GMOCK_PP_TAIL _Tuple))
|
||||
#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_22(_i, _Macro, _Data, _Tuple) \
|
||||
GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
|
||||
GMOCK_PP_INTERNAL_FOR_EACH_IMPL_21(GMOCK_PP_INC(_i), _Macro, _Data, \
|
||||
(GMOCK_PP_TAIL _Tuple))
|
||||
#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_23(_i, _Macro, _Data, _Tuple) \
|
||||
GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
|
||||
GMOCK_PP_INTERNAL_FOR_EACH_IMPL_22(GMOCK_PP_INC(_i), _Macro, _Data, \
|
||||
(GMOCK_PP_TAIL _Tuple))
|
||||
#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_24(_i, _Macro, _Data, _Tuple) \
|
||||
GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
|
||||
GMOCK_PP_INTERNAL_FOR_EACH_IMPL_23(GMOCK_PP_INC(_i), _Macro, _Data, \
|
||||
(GMOCK_PP_TAIL _Tuple))
|
||||
#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_25(_i, _Macro, _Data, _Tuple) \
|
||||
GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
|
||||
GMOCK_PP_INTERNAL_FOR_EACH_IMPL_24(GMOCK_PP_INC(_i), _Macro, _Data, \
|
||||
(GMOCK_PP_TAIL _Tuple))
|
||||
#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_26(_i, _Macro, _Data, _Tuple) \
|
||||
GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
|
||||
GMOCK_PP_INTERNAL_FOR_EACH_IMPL_25(GMOCK_PP_INC(_i), _Macro, _Data, \
|
||||
(GMOCK_PP_TAIL _Tuple))
|
||||
#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_27(_i, _Macro, _Data, _Tuple) \
|
||||
GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
|
||||
GMOCK_PP_INTERNAL_FOR_EACH_IMPL_26(GMOCK_PP_INC(_i), _Macro, _Data, \
|
||||
(GMOCK_PP_TAIL _Tuple))
|
||||
#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_28(_i, _Macro, _Data, _Tuple) \
|
||||
GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
|
||||
GMOCK_PP_INTERNAL_FOR_EACH_IMPL_27(GMOCK_PP_INC(_i), _Macro, _Data, \
|
||||
(GMOCK_PP_TAIL _Tuple))
|
||||
#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_29(_i, _Macro, _Data, _Tuple) \
|
||||
GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
|
||||
GMOCK_PP_INTERNAL_FOR_EACH_IMPL_28(GMOCK_PP_INC(_i), _Macro, _Data, \
|
||||
(GMOCK_PP_TAIL _Tuple))
|
||||
#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_30(_i, _Macro, _Data, _Tuple) \
|
||||
GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
|
||||
GMOCK_PP_INTERNAL_FOR_EACH_IMPL_29(GMOCK_PP_INC(_i), _Macro, _Data, \
|
||||
(GMOCK_PP_TAIL _Tuple))
|
||||
#define GMOCK_PP_INTERNAL_FOR_EACH_IMPL_31(_i, _Macro, _Data, _Tuple) \
|
||||
GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple) \
|
||||
GMOCK_PP_INTERNAL_FOR_EACH_IMPL_30(GMOCK_PP_INC(_i), _Macro, _Data, \
|
||||
(GMOCK_PP_TAIL _Tuple))
|
||||
|
||||
#endif // GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PP_H_
|
||||
|
||||
@@ -156,7 +156,7 @@ GTEST_API_ void Log(LogSeverity severity, const std::string& message,
|
||||
if (!LogIsVisible(severity)) return;
|
||||
|
||||
// Ensures that logs from different threads don't interleave.
|
||||
MutexLock l(&g_log_mutex);
|
||||
MutexLock l(g_log_mutex);
|
||||
|
||||
if (severity == kWarning) {
|
||||
// Prints a GMOCK WARNING marker to make the warnings easily searchable.
|
||||
@@ -188,7 +188,7 @@ GTEST_API_ void Log(LogSeverity severity, const std::string& message,
|
||||
std::cout << ::std::flush;
|
||||
}
|
||||
|
||||
GTEST_API_ WithoutMatchers GetWithoutMatchers() { return WithoutMatchers(); }
|
||||
GTEST_API_ WithoutMatchers WithoutMatchers::Get() { return WithoutMatchers(); }
|
||||
|
||||
GTEST_API_ void IllegalDoDefault(const char* file, int line) {
|
||||
internal::Assert(
|
||||
|
||||
@@ -212,7 +212,7 @@ void ExpectationBase::CheckActionCountIfNotDone() const
|
||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
bool should_check = false;
|
||||
{
|
||||
MutexLock l(&mutex_);
|
||||
MutexLock l(mutex_);
|
||||
if (!action_count_checked_) {
|
||||
action_count_checked_ = true;
|
||||
should_check = true;
|
||||
@@ -293,7 +293,7 @@ void ReportUninterestingCall(CallReaction reaction, const std::string& msg) {
|
||||
Log(kWarning,
|
||||
msg +
|
||||
"\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. "
|
||||
"See "
|
||||
"https://github.com/google/googletest/blob/main/docs/"
|
||||
@@ -318,7 +318,7 @@ UntypedFunctionMockerBase::~UntypedFunctionMockerBase() = default;
|
||||
void UntypedFunctionMockerBase::RegisterOwner(const void* mock_obj)
|
||||
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||
{
|
||||
MutexLock l(&g_gmock_mutex);
|
||||
MutexLock l(g_gmock_mutex);
|
||||
mock_obj_ = mock_obj;
|
||||
}
|
||||
Mock::Register(mock_obj, this);
|
||||
@@ -332,7 +332,7 @@ void UntypedFunctionMockerBase::SetOwnerAndName(const void* mock_obj,
|
||||
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
|
||||
// We protect name_ under g_gmock_mutex in case this mock function
|
||||
// is called from two threads concurrently.
|
||||
MutexLock l(&g_gmock_mutex);
|
||||
MutexLock l(g_gmock_mutex);
|
||||
mock_obj_ = mock_obj;
|
||||
name_ = name;
|
||||
}
|
||||
@@ -345,7 +345,7 @@ const void* UntypedFunctionMockerBase::MockObject() const
|
||||
{
|
||||
// We protect mock_obj_ under g_gmock_mutex in case this mock
|
||||
// function is called from two threads concurrently.
|
||||
MutexLock l(&g_gmock_mutex);
|
||||
MutexLock l(g_gmock_mutex);
|
||||
Assert(mock_obj_ != nullptr, __FILE__, __LINE__,
|
||||
"MockObject() must not be called before RegisterOwner() or "
|
||||
"SetOwnerAndName() has been called.");
|
||||
@@ -362,7 +362,7 @@ const char* UntypedFunctionMockerBase::Name() const
|
||||
{
|
||||
// We protect name_ under g_gmock_mutex in case this mock
|
||||
// function is called from two threads concurrently.
|
||||
MutexLock l(&g_gmock_mutex);
|
||||
MutexLock l(g_gmock_mutex);
|
||||
Assert(name_ != nullptr, __FILE__, __LINE__,
|
||||
"Name() must not be called before SetOwnerAndName() has "
|
||||
"been called.");
|
||||
@@ -436,9 +436,9 @@ bool UntypedFunctionMockerBase::VerifyAndClearExpectationsLocked()
|
||||
UntypedExpectations expectations_to_delete;
|
||||
untyped_expectations_.swap(expectations_to_delete);
|
||||
|
||||
g_gmock_mutex.Unlock();
|
||||
g_gmock_mutex.unlock();
|
||||
expectations_to_delete.clear();
|
||||
g_gmock_mutex.Lock();
|
||||
g_gmock_mutex.lock();
|
||||
|
||||
return expectations_met;
|
||||
}
|
||||
@@ -490,7 +490,7 @@ class MockObjectRegistry {
|
||||
// failure, unless the user explicitly asked us to ignore it.
|
||||
~MockObjectRegistry() {
|
||||
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;
|
||||
for (StateMap::const_iterator it = states_.begin(); it != states_.end();
|
||||
@@ -559,7 +559,7 @@ UninterestingCallReactionMap() {
|
||||
void SetReactionOnUninterestingCalls(uintptr_t mock_obj,
|
||||
internal::CallReaction reaction)
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -590,7 +590,7 @@ void Mock::FailUninterestingCalls(uintptr_t mock_obj)
|
||||
// entry in the call-reaction table should be removed.
|
||||
void Mock::UnregisterCallReaction(uintptr_t mock_obj)
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -598,7 +598,7 @@ void Mock::UnregisterCallReaction(uintptr_t mock_obj)
|
||||
// made on the given mock object.
|
||||
internal::CallReaction Mock::GetReactionOnUninterestingCalls(
|
||||
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(
|
||||
reinterpret_cast<uintptr_t>(mock_obj)) == 0)
|
||||
? internal::intToCallReaction(
|
||||
@@ -611,7 +611,7 @@ internal::CallReaction Mock::GetReactionOnUninterestingCalls(
|
||||
// objects.
|
||||
void Mock::AllowLeak(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);
|
||||
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.
|
||||
bool Mock::VerifyAndClearExpectations(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 VerifyAndClearExpectationsLocked(mock_obj);
|
||||
}
|
||||
|
||||
@@ -629,7 +629,7 @@ bool Mock::VerifyAndClearExpectations(void* mock_obj)
|
||||
// verification was successful.
|
||||
bool Mock::VerifyAndClear(void* mock_obj)
|
||||
GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex) {
|
||||
internal::MutexLock l(&internal::g_gmock_mutex);
|
||||
internal::MutexLock l(internal::g_gmock_mutex);
|
||||
ClearDefaultActionsLocked(mock_obj);
|
||||
return VerifyAndClearExpectationsLocked(mock_obj);
|
||||
}
|
||||
@@ -679,7 +679,7 @@ bool Mock::IsStrict(void* mock_obj)
|
||||
void Mock::Register(const void* mock_obj,
|
||||
internal::UntypedFunctionMockerBase* mocker)
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -689,7 +689,7 @@ void Mock::Register(const void* mock_obj,
|
||||
void Mock::RegisterUseByOnCallOrExpectCall(const void* mock_obj,
|
||||
const char* file, int line)
|
||||
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];
|
||||
if (state.first_used_file == nullptr) {
|
||||
state.first_used_file = file;
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#
|
||||
# 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")
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
@@ -66,30 +66,30 @@ using ::testing::internal::BuiltInDefaultValue;
|
||||
|
||||
TEST(TypeTraits, Negation) {
|
||||
// Direct use with std types.
|
||||
static_assert(std::is_base_of<std::false_type,
|
||||
internal::negation<std::true_type>>::value,
|
||||
"");
|
||||
static_assert(
|
||||
std::is_base_of_v<std::false_type, internal::negation<std::true_type>>,
|
||||
"");
|
||||
|
||||
static_assert(std::is_base_of<std::true_type,
|
||||
internal::negation<std::false_type>>::value,
|
||||
"");
|
||||
static_assert(
|
||||
std::is_base_of_v<std::true_type, internal::negation<std::false_type>>,
|
||||
"");
|
||||
|
||||
// With other types that fit the requirement of a value member that is
|
||||
// convertible to bool.
|
||||
static_assert(std::is_base_of<
|
||||
std::true_type,
|
||||
internal::negation<std::integral_constant<int, 0>>>::value,
|
||||
"");
|
||||
static_assert(
|
||||
std::is_base_of_v<std::true_type,
|
||||
internal::negation<std::integral_constant<int, 0>>>,
|
||||
"");
|
||||
|
||||
static_assert(std::is_base_of<
|
||||
std::false_type,
|
||||
internal::negation<std::integral_constant<int, 1>>>::value,
|
||||
"");
|
||||
static_assert(
|
||||
std::is_base_of_v<std::false_type,
|
||||
internal::negation<std::integral_constant<int, 1>>>,
|
||||
"");
|
||||
|
||||
static_assert(std::is_base_of<
|
||||
std::false_type,
|
||||
internal::negation<std::integral_constant<int, -1>>>::value,
|
||||
"");
|
||||
static_assert(
|
||||
std::is_base_of_v<std::false_type,
|
||||
internal::negation<std::integral_constant<int, -1>>>,
|
||||
"");
|
||||
}
|
||||
|
||||
// Weird false/true types that aren't actually bool constants (but should still
|
||||
@@ -108,79 +108,76 @@ struct MyTrue : std::integral_constant<int, -1> {};
|
||||
|
||||
TEST(TypeTraits, Conjunction) {
|
||||
// Base case: always true.
|
||||
static_assert(std::is_base_of<std::true_type, internal::conjunction<>>::value,
|
||||
"");
|
||||
static_assert(std::is_base_of_v<std::true_type, internal::conjunction<>>, "");
|
||||
|
||||
// One predicate: inherits from that predicate, regardless of value.
|
||||
static_assert(
|
||||
std::is_base_of<MyFalse<0>, internal::conjunction<MyFalse<0>>>::value,
|
||||
"");
|
||||
std::is_base_of_v<MyFalse<0>, internal::conjunction<MyFalse<0>>>, "");
|
||||
|
||||
static_assert(
|
||||
std::is_base_of<MyTrue<0>, internal::conjunction<MyTrue<0>>>::value, "");
|
||||
static_assert(std::is_base_of_v<MyTrue<0>, internal::conjunction<MyTrue<0>>>,
|
||||
"");
|
||||
|
||||
// Multiple predicates, with at least one false: inherits from that one.
|
||||
static_assert(
|
||||
std::is_base_of<MyFalse<1>, internal::conjunction<MyTrue<0>, MyFalse<1>,
|
||||
MyTrue<2>>>::value,
|
||||
std::is_base_of_v<
|
||||
MyFalse<1>, internal::conjunction<MyTrue<0>, MyFalse<1>, MyTrue<2>>>,
|
||||
"");
|
||||
|
||||
static_assert(
|
||||
std::is_base_of<MyFalse<1>, internal::conjunction<MyTrue<0>, MyFalse<1>,
|
||||
MyFalse<2>>>::value,
|
||||
std::is_base_of_v<
|
||||
MyFalse<1>, internal::conjunction<MyTrue<0>, MyFalse<1>, MyFalse<2>>>,
|
||||
"");
|
||||
|
||||
// Short circuiting: in the case above, additional predicates need not even
|
||||
// define a value member.
|
||||
struct Empty {};
|
||||
static_assert(
|
||||
std::is_base_of<MyFalse<1>, internal::conjunction<MyTrue<0>, MyFalse<1>,
|
||||
Empty>>::value,
|
||||
std::is_base_of_v<MyFalse<1>,
|
||||
internal::conjunction<MyTrue<0>, MyFalse<1>, Empty>>,
|
||||
"");
|
||||
|
||||
// All predicates true: inherits from the last.
|
||||
static_assert(
|
||||
std::is_base_of<MyTrue<2>, internal::conjunction<MyTrue<0>, MyTrue<1>,
|
||||
MyTrue<2>>>::value,
|
||||
std::is_base_of_v<MyTrue<2>,
|
||||
internal::conjunction<MyTrue<0>, MyTrue<1>, MyTrue<2>>>,
|
||||
"");
|
||||
}
|
||||
|
||||
TEST(TypeTraits, Disjunction) {
|
||||
// Base case: always false.
|
||||
static_assert(
|
||||
std::is_base_of<std::false_type, internal::disjunction<>>::value, "");
|
||||
static_assert(std::is_base_of_v<std::false_type, internal::disjunction<>>,
|
||||
"");
|
||||
|
||||
// One predicate: inherits from that predicate, regardless of value.
|
||||
static_assert(
|
||||
std::is_base_of<MyFalse<0>, internal::disjunction<MyFalse<0>>>::value,
|
||||
"");
|
||||
std::is_base_of_v<MyFalse<0>, internal::disjunction<MyFalse<0>>>, "");
|
||||
|
||||
static_assert(
|
||||
std::is_base_of<MyTrue<0>, internal::disjunction<MyTrue<0>>>::value, "");
|
||||
static_assert(std::is_base_of_v<MyTrue<0>, internal::disjunction<MyTrue<0>>>,
|
||||
"");
|
||||
|
||||
// Multiple predicates, with at least one true: inherits from that one.
|
||||
static_assert(
|
||||
std::is_base_of<MyTrue<1>, internal::disjunction<MyFalse<0>, MyTrue<1>,
|
||||
MyFalse<2>>>::value,
|
||||
std::is_base_of_v<
|
||||
MyTrue<1>, internal::disjunction<MyFalse<0>, MyTrue<1>, MyFalse<2>>>,
|
||||
"");
|
||||
|
||||
static_assert(
|
||||
std::is_base_of<MyTrue<1>, internal::disjunction<MyFalse<0>, MyTrue<1>,
|
||||
MyTrue<2>>>::value,
|
||||
std::is_base_of_v<
|
||||
MyTrue<1>, internal::disjunction<MyFalse<0>, MyTrue<1>, MyTrue<2>>>,
|
||||
"");
|
||||
|
||||
// Short circuiting: in the case above, additional predicates need not even
|
||||
// define a value member.
|
||||
struct Empty {};
|
||||
static_assert(
|
||||
std::is_base_of<MyTrue<1>, internal::disjunction<MyFalse<0>, MyTrue<1>,
|
||||
Empty>>::value,
|
||||
std::is_base_of_v<MyTrue<1>,
|
||||
internal::disjunction<MyFalse<0>, MyTrue<1>, Empty>>,
|
||||
"");
|
||||
|
||||
// All predicates false: inherits from the last.
|
||||
static_assert(
|
||||
std::is_base_of<MyFalse<2>, internal::disjunction<MyFalse<0>, MyFalse<1>,
|
||||
MyFalse<2>>>::value,
|
||||
std::is_base_of_v<MyFalse<2>, internal::disjunction<
|
||||
MyFalse<0>, MyFalse<1>, MyFalse<2>>>,
|
||||
"");
|
||||
}
|
||||
|
||||
@@ -188,7 +185,7 @@ TEST(TypeTraits, IsInvocableRV) {
|
||||
struct C {
|
||||
int operator()() const { return 0; }
|
||||
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.
|
||||
@@ -222,8 +219,8 @@ TEST(TypeTraits, IsInvocableRV) {
|
||||
// In C++17 and above, where it's guaranteed that functions can return
|
||||
// non-moveable objects, everything should work fine for non-moveable rsult
|
||||
// types too.
|
||||
#if defined(GTEST_INTERNAL_CPLUSPLUS_LANG) && \
|
||||
GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L
|
||||
// TODO(b/396121064) - Fix this test under MSVC
|
||||
#ifndef _MSC_VER
|
||||
{
|
||||
struct NonMoveable {
|
||||
NonMoveable() = default;
|
||||
@@ -244,7 +241,7 @@ TEST(TypeTraits, IsInvocableRV) {
|
||||
static_assert(!internal::is_callable_r<int, Callable>::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
|
||||
// callable objects, but they should not show up as callable.
|
||||
@@ -273,7 +270,7 @@ TEST(BuiltInDefaultValueTest, IsZeroForNumericTypes) {
|
||||
EXPECT_EQ(0U, BuiltInDefaultValue<unsigned char>::Get());
|
||||
EXPECT_EQ(0, BuiltInDefaultValue<signed char>::Get());
|
||||
EXPECT_EQ(0, BuiltInDefaultValue<char>::Get());
|
||||
#if GMOCK_WCHAR_T_IS_NATIVE_
|
||||
#if GTEST_HAS_NATIVE_WCHAR
|
||||
#if !defined(__WCHAR_UNSIGNED__)
|
||||
EXPECT_EQ(0, BuiltInDefaultValue<wchar_t>::Get());
|
||||
#else
|
||||
@@ -302,7 +299,7 @@ TEST(BuiltInDefaultValueTest, ExistsForNumericTypes) {
|
||||
EXPECT_TRUE(BuiltInDefaultValue<unsigned char>::Exists());
|
||||
EXPECT_TRUE(BuiltInDefaultValue<signed char>::Exists());
|
||||
EXPECT_TRUE(BuiltInDefaultValue<char>::Exists());
|
||||
#if GMOCK_WCHAR_T_IS_NATIVE_
|
||||
#if GTEST_HAS_NATIVE_WCHAR
|
||||
EXPECT_TRUE(BuiltInDefaultValue<wchar_t>::Exists());
|
||||
#endif
|
||||
EXPECT_TRUE(BuiltInDefaultValue<unsigned short>::Exists()); // NOLINT
|
||||
@@ -747,8 +744,8 @@ TEST(ReturnTest, ConversionRequiresConstLvalueReference) {
|
||||
using R = int;
|
||||
using U = std::reference_wrapper<const int>;
|
||||
|
||||
static_assert(std::is_convertible<const R&, U>::value, "");
|
||||
static_assert(!std::is_convertible<R, U>::value, "");
|
||||
static_assert(std::is_convertible_v<const R&, U>, "");
|
||||
static_assert(!std::is_convertible_v<R, U>, "");
|
||||
|
||||
MockFunction<U()> mock;
|
||||
EXPECT_CALL(mock, Call).WillOnce(Return(17)).WillRepeatedly(Return(19));
|
||||
@@ -771,11 +768,11 @@ TEST(ReturnTest, ConversionRequiresMutableLvalueReference) {
|
||||
S(std::string&) {} // NOLINT
|
||||
};
|
||||
|
||||
static_assert(std::is_convertible<std::string&, S>::value, "");
|
||||
static_assert(std::is_convertible_v<std::string&, S>, "");
|
||||
#ifndef _MSC_VER
|
||||
static_assert(!std::is_convertible<std::string&&, S>::value, "");
|
||||
static_assert(!std::is_convertible_v<std::string&&, S>, "");
|
||||
#endif
|
||||
static_assert(!std::is_convertible<const std::string&, S>::value, "");
|
||||
static_assert(!std::is_convertible_v<const std::string&, S>, "");
|
||||
|
||||
// It shouldn't be possible to use the result of Return(std::string) in a
|
||||
// context where an S is needed.
|
||||
@@ -784,9 +781,9 @@ TEST(ReturnTest, ConversionRequiresMutableLvalueReference) {
|
||||
// implementation of is_convertible causes our SFINAE to be wrong.
|
||||
using RA = decltype(Return(std::string()));
|
||||
|
||||
static_assert(!std::is_convertible<RA, Action<S()>>::value, "");
|
||||
static_assert(!std::is_convertible_v<RA, Action<S()>>, "");
|
||||
#ifndef _MSC_VER
|
||||
static_assert(!std::is_convertible<RA, OnceAction<S()>>::value, "");
|
||||
static_assert(!std::is_convertible_v<RA, OnceAction<S()>>, "");
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -803,8 +800,8 @@ TEST(ReturnTest, MoveOnlyResultType) {
|
||||
|
||||
// The result of Return should not be convertible to Action (so it can't be
|
||||
// used with WillRepeatedly).
|
||||
static_assert(!std::is_convertible<decltype(Return(std::unique_ptr<int>())),
|
||||
Action<std::unique_ptr<int>()>>::value,
|
||||
static_assert(!std::is_convertible_v<decltype(Return(std::unique_ptr<int>())),
|
||||
Action<std::unique_ptr<int>()>>,
|
||||
"");
|
||||
}
|
||||
|
||||
@@ -1030,8 +1027,7 @@ void VoidFunc(bool /* flag */) {}
|
||||
|
||||
TEST(DoDefaultDeathTest, DiesIfUsedInCompositeAction) {
|
||||
MockClass mock;
|
||||
EXPECT_CALL(mock, IntFunc(_))
|
||||
.WillRepeatedly(DoAll(Invoke(VoidFunc), DoDefault()));
|
||||
EXPECT_CALL(mock, IntFunc(_)).WillRepeatedly(DoAll(VoidFunc, DoDefault()));
|
||||
|
||||
// Ideally we should verify the error message as well. Sadly,
|
||||
// EXPECT_DEATH() can only capture stderr, while Google Mock's
|
||||
@@ -1105,6 +1101,7 @@ TEST(SetArgPointeeTest, AcceptsStringLiteral) {
|
||||
EXPECT_STREQ("world", ptr);
|
||||
}
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
TEST(SetArgPointeeTest, AcceptsWideStringLiteral) {
|
||||
typedef void MyFunction(const wchar_t**);
|
||||
Action<MyFunction> a = SetArgPointee<0>(L"world");
|
||||
@@ -1112,16 +1109,13 @@ TEST(SetArgPointeeTest, AcceptsWideStringLiteral) {
|
||||
a.Perform(std::make_tuple(&ptr));
|
||||
EXPECT_STREQ(L"world", ptr);
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
|
||||
typedef void MyStringFunction(std::wstring*);
|
||||
Action<MyStringFunction> a2 = SetArgPointee<0>(L"world");
|
||||
std::wstring str = L"";
|
||||
a2.Perform(std::make_tuple(&str));
|
||||
EXPECT_EQ(L"world", str);
|
||||
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
// Tests that SetArgPointee<N>() accepts a char pointer.
|
||||
TEST(SetArgPointeeTest, AcceptsCharPointer) {
|
||||
@@ -1226,37 +1220,41 @@ class Foo {
|
||||
|
||||
// Tests InvokeWithoutArgs(function).
|
||||
TEST(InvokeWithoutArgsTest, Function) {
|
||||
GTEST_DISABLE_DEPRECATED_PUSH_()
|
||||
// As an action that takes one argument.
|
||||
Action<int(int)> a = InvokeWithoutArgs(Nullary); // NOLINT
|
||||
Action<int(int)> a = Nullary; // NOLINT
|
||||
EXPECT_EQ(1, a.Perform(std::make_tuple(2)));
|
||||
|
||||
// As an action that takes two arguments.
|
||||
Action<int(int, double)> a2 = InvokeWithoutArgs(Nullary); // NOLINT
|
||||
Action<int(int, double)> a2 = Nullary; // NOLINT
|
||||
EXPECT_EQ(1, a2.Perform(std::make_tuple(2, 3.5)));
|
||||
|
||||
// As an action that returns void.
|
||||
Action<void(int)> a3 = InvokeWithoutArgs(VoidNullary); // NOLINT
|
||||
Action<void(int)> a3 = VoidNullary; // NOLINT
|
||||
g_done = false;
|
||||
a3.Perform(std::make_tuple(1));
|
||||
EXPECT_TRUE(g_done);
|
||||
GTEST_DISABLE_DEPRECATED_POP_()
|
||||
}
|
||||
|
||||
// Tests InvokeWithoutArgs(functor).
|
||||
TEST(InvokeWithoutArgsTest, Functor) {
|
||||
GTEST_DISABLE_DEPRECATED_PUSH_()
|
||||
// As an action that takes no argument.
|
||||
Action<int()> a = InvokeWithoutArgs(NullaryFunctor()); // NOLINT
|
||||
Action<int()> a = NullaryFunctor(); // NOLINT
|
||||
EXPECT_EQ(2, a.Perform(std::make_tuple()));
|
||||
|
||||
// As an action that takes three arguments.
|
||||
Action<int(int, double, char)> a2 = // NOLINT
|
||||
InvokeWithoutArgs(NullaryFunctor());
|
||||
NullaryFunctor();
|
||||
EXPECT_EQ(2, a2.Perform(std::make_tuple(3, 3.5, 'a')));
|
||||
|
||||
// As an action that returns void.
|
||||
Action<void()> a3 = InvokeWithoutArgs(VoidNullaryFunctor());
|
||||
Action<void()> a3 = VoidNullaryFunctor();
|
||||
g_done = false;
|
||||
a3.Perform(std::make_tuple());
|
||||
EXPECT_TRUE(g_done);
|
||||
GTEST_DISABLE_DEPRECATED_POP_()
|
||||
}
|
||||
|
||||
// Tests InvokeWithoutArgs(obj_ptr, method).
|
||||
@@ -1282,7 +1280,7 @@ int ReturnOne() {
|
||||
|
||||
TEST(IgnoreResultTest, MonomorphicAction) {
|
||||
g_done = false;
|
||||
Action<void()> a = IgnoreResult(Invoke(ReturnOne));
|
||||
Action<void()> a = IgnoreResult(&ReturnOne);
|
||||
a.Perform(std::make_tuple());
|
||||
EXPECT_TRUE(g_done);
|
||||
}
|
||||
@@ -1297,7 +1295,7 @@ MyNonDefaultConstructible ReturnMyNonDefaultConstructible(double /* x */) {
|
||||
TEST(IgnoreResultTest, ActionReturningClass) {
|
||||
g_done = false;
|
||||
Action<void(int)> a =
|
||||
IgnoreResult(Invoke(ReturnMyNonDefaultConstructible)); // NOLINT
|
||||
IgnoreResult(&ReturnMyNonDefaultConstructible); // NOLINT
|
||||
a.Perform(std::make_tuple(2));
|
||||
EXPECT_TRUE(g_done);
|
||||
}
|
||||
@@ -1311,7 +1309,7 @@ TEST(AssignTest, Int) {
|
||||
|
||||
TEST(AssignTest, String) {
|
||||
::std::string x;
|
||||
Action<void(void)> a = Assign(&x, "Hello, world");
|
||||
Action<void()> a = Assign(&x, "Hello, world");
|
||||
a.Perform(std::make_tuple());
|
||||
EXPECT_EQ("Hello, world", x);
|
||||
}
|
||||
@@ -1477,12 +1475,15 @@ TEST(DoAll, SupportsTypeErasedActions) {
|
||||
}
|
||||
}
|
||||
|
||||
// A DoAll action should be convertible to a OnceAction, even when its component
|
||||
// sub-actions are user-provided types that define only an Action conversion
|
||||
// operator. If they supposed being called more than once then they also support
|
||||
// being called at most once.
|
||||
// A multi-action DoAll action should be convertible to a OnceAction, even when
|
||||
// its component sub-actions are user-provided types that define only an Action
|
||||
// conversion operator. If they supposed being called more than once then they
|
||||
// also support being called at most once.
|
||||
//
|
||||
// Single-arg DoAll just returns its argument, so will prefer the Action<F>
|
||||
// overload for WillOnce.
|
||||
TEST(DoAll, ConvertibleToOnceActionWithUserProvidedActionConversion) {
|
||||
// Simplest case: only one sub-action.
|
||||
// Final action.
|
||||
struct CustomFinal final {
|
||||
operator Action<int()>() { // NOLINT
|
||||
return Return(17);
|
||||
@@ -1493,17 +1494,7 @@ TEST(DoAll, ConvertibleToOnceActionWithUserProvidedActionConversion) {
|
||||
}
|
||||
};
|
||||
|
||||
{
|
||||
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.
|
||||
// Sub-actions.
|
||||
struct CustomInitial final {
|
||||
operator Action<void()>() { // NOLINT
|
||||
return [] {};
|
||||
@@ -1527,7 +1518,7 @@ TEST(DoAll, ConvertibleToOnceActionWithUserProvidedActionConversion) {
|
||||
|
||||
// Tests using WithArgs and with an action that takes 1 argument.
|
||||
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_FALSE(a.Perform(std::make_tuple(1.5, 1)));
|
||||
}
|
||||
@@ -1535,7 +1526,7 @@ TEST(WithArgsTest, OneArg) {
|
||||
// Tests using WithArgs with an action that takes 2 arguments.
|
||||
TEST(WithArgsTest, TwoArgs) {
|
||||
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";
|
||||
EXPECT_EQ(s + 2, a.Perform(std::make_tuple(CharPtr(s), 0.5, Short(2))));
|
||||
}
|
||||
@@ -1551,7 +1542,7 @@ struct ConcatAll {
|
||||
// Tests using WithArgs with an action that takes 10 arguments.
|
||||
TEST(WithArgsTest, TenArgs) {
|
||||
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",
|
||||
a.Perform(std::make_tuple(CharPtr("0"), CharPtr("1"), CharPtr("2"),
|
||||
CharPtr("3"))));
|
||||
@@ -1576,21 +1567,21 @@ TEST(WithArgsTest, NonInvokeAction) {
|
||||
// Tests using WithArgs to pass all original arguments in the original order.
|
||||
TEST(WithArgsTest, Identity) {
|
||||
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))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with repeated arguments.
|
||||
TEST(WithArgsTest, RepeatedArguments) {
|
||||
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)));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with reversed argument order.
|
||||
TEST(WithArgsTest, ReversedArgumentOrder) {
|
||||
Action<const char*(short n, const char* input)> a = // NOLINT
|
||||
WithArgs<1, 0>(Invoke(Binary));
|
||||
WithArgs<1, 0>(Binary);
|
||||
const char s[] = "Hello";
|
||||
EXPECT_EQ(s + 2, a.Perform(std::make_tuple(Short(2), CharPtr(s))));
|
||||
}
|
||||
@@ -1598,14 +1589,14 @@ TEST(WithArgsTest, ReversedArgumentOrder) {
|
||||
// Tests using WithArgs with compatible, but not identical, argument types.
|
||||
TEST(WithArgsTest, ArgsOfCompatibleTypes) {
|
||||
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,
|
||||
a.Perform(std::make_tuple(Short(100), Char(20), 5.6, Char(3))));
|
||||
}
|
||||
|
||||
// Tests using WithArgs with an action that returns void.
|
||||
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;
|
||||
a.Perform(std::make_tuple(1.5, 'a', 3));
|
||||
EXPECT_TRUE(g_done);
|
||||
@@ -1645,6 +1636,22 @@ TEST(WithArgsTest, RefQualifiedInnerAction) {
|
||||
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
|
||||
|
||||
class SetErrnoAndReturnTest : public testing::Test {
|
||||
@@ -1654,14 +1661,14 @@ class SetErrnoAndReturnTest : public testing::Test {
|
||||
};
|
||||
|
||||
TEST_F(SetErrnoAndReturnTest, Int) {
|
||||
Action<int(void)> a = SetErrnoAndReturn(ENOTTY, -5);
|
||||
Action<int()> a = SetErrnoAndReturn(ENOTTY, -5);
|
||||
EXPECT_EQ(-5, a.Perform(std::make_tuple()));
|
||||
EXPECT_EQ(ENOTTY, errno);
|
||||
}
|
||||
|
||||
TEST_F(SetErrnoAndReturnTest, Ptr) {
|
||||
int x;
|
||||
Action<int*(void)> a = SetErrnoAndReturn(ENOTTY, &x);
|
||||
Action<int*()> a = SetErrnoAndReturn(ENOTTY, &x);
|
||||
EXPECT_EQ(&x, a.Perform(std::make_tuple()));
|
||||
EXPECT_EQ(ENOTTY, errno);
|
||||
}
|
||||
@@ -1814,7 +1821,7 @@ std::vector<std::unique_ptr<int>> VectorUniquePtrSource() {
|
||||
|
||||
TEST(MockMethodTest, CanReturnMoveOnlyValue_Return) {
|
||||
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, MakeVectorUnique())
|
||||
.WillOnce(Return(ByMove(VectorUniquePtrSource())));
|
||||
@@ -1837,7 +1844,7 @@ TEST(MockMethodTest, CanReturnMoveOnlyValue_Return) {
|
||||
TEST(MockMethodTest, CanReturnMoveOnlyValue_DoAllReturn) {
|
||||
testing::MockFunction<void()> mock_function;
|
||||
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, MakeUnique())
|
||||
.WillOnce(DoAll(InvokeWithoutArgs(&mock_function,
|
||||
@@ -1856,9 +1863,8 @@ TEST(MockMethodTest, CanReturnMoveOnlyValue_Invoke) {
|
||||
[] { return std::make_unique<int>(42); });
|
||||
EXPECT_EQ(42, *mock.MakeUnique());
|
||||
|
||||
EXPECT_CALL(mock, MakeUnique()).WillRepeatedly(Invoke(UniquePtrSource));
|
||||
EXPECT_CALL(mock, MakeVectorUnique())
|
||||
.WillRepeatedly(Invoke(VectorUniquePtrSource));
|
||||
EXPECT_CALL(mock, MakeUnique()).WillRepeatedly(UniquePtrSource);
|
||||
EXPECT_CALL(mock, MakeVectorUnique()).WillRepeatedly(VectorUniquePtrSource);
|
||||
std::unique_ptr<int> result1 = mock.MakeUnique();
|
||||
EXPECT_EQ(19, *result1);
|
||||
std::unique_ptr<int> result2 = mock.MakeUnique();
|
||||
@@ -1880,7 +1886,7 @@ TEST(MockMethodTest, CanTakeMoveOnlyValue) {
|
||||
});
|
||||
// DoAll() does not compile, since it would move from its arguments twice.
|
||||
// EXPECT_CALL(mock, TakeUnique(_, _))
|
||||
// .WillRepeatedly(DoAll(Invoke([](std::unique_ptr<int> j) {}),
|
||||
// .WillRepeatedly(DoAll([](std::unique_ptr<int> j) {})),
|
||||
// Return(1)));
|
||||
EXPECT_CALL(mock, TakeUnique(testing::Pointee(7)))
|
||||
.WillOnce(Return(-7))
|
||||
@@ -2163,7 +2169,7 @@ TEST(FunctorActionTest, TypeConversion) {
|
||||
EXPECT_EQ(7, d.Perform(std::make_tuple(1)));
|
||||
|
||||
// Ensure creation of an empty action succeeds.
|
||||
Action<void(int)>(nullptr);
|
||||
(void)Action<void(int)>(nullptr);
|
||||
}
|
||||
|
||||
TEST(FunctorActionTest, UnusedArguments) {
|
||||
@@ -2189,7 +2195,7 @@ TEST(MoveOnlyArgumentsTest, ReturningActions) {
|
||||
EXPECT_EQ(x, 3);
|
||||
}
|
||||
|
||||
ACTION(ReturnArity) { return std::tuple_size<args_type>::value; }
|
||||
ACTION(ReturnArity) { return std::tuple_size_v<args_type>; }
|
||||
|
||||
TEST(ActionMacro, LargeArity) {
|
||||
EXPECT_EQ(
|
||||
|
||||
@@ -133,7 +133,7 @@ TEST(AnyNumberTest, HasCorrectBounds) {
|
||||
TEST(AtLeastTest, OnNegativeNumber) {
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
{ // NOLINT
|
||||
AtLeast(-1);
|
||||
(void)AtLeast(-1);
|
||||
},
|
||||
"The invocation lower bound must be >= 0");
|
||||
}
|
||||
@@ -186,7 +186,7 @@ TEST(AtLeastTest, HasCorrectBounds) {
|
||||
TEST(AtMostTest, OnNegativeNumber) {
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
{ // NOLINT
|
||||
AtMost(-1);
|
||||
(void)AtMost(-1);
|
||||
},
|
||||
"The invocation upper bound must be >= 0");
|
||||
}
|
||||
@@ -239,7 +239,7 @@ TEST(AtMostTest, HasCorrectBounds) {
|
||||
TEST(BetweenTest, OnNegativeStart) {
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
{ // NOLINT
|
||||
Between(-1, 2);
|
||||
(void)Between(-1, 2);
|
||||
},
|
||||
"The invocation lower bound must be >= 0, but is actually -1");
|
||||
}
|
||||
@@ -247,7 +247,7 @@ TEST(BetweenTest, OnNegativeStart) {
|
||||
TEST(BetweenTest, OnNegativeEnd) {
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
{ // NOLINT
|
||||
Between(1, -2);
|
||||
(void)Between(1, -2);
|
||||
},
|
||||
"The invocation upper bound must be >= 0, but is actually -2");
|
||||
}
|
||||
@@ -255,7 +255,7 @@ TEST(BetweenTest, OnNegativeEnd) {
|
||||
TEST(BetweenTest, OnStartBiggerThanEnd) {
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
{ // NOLINT
|
||||
Between(2, 1);
|
||||
(void)Between(2, 1);
|
||||
},
|
||||
"The invocation upper bound (1) must be >= "
|
||||
"the invocation lower bound (2)");
|
||||
@@ -340,7 +340,7 @@ TEST(BetweenTest, HasCorrectBounds) {
|
||||
TEST(ExactlyTest, OnNegativeNumber) {
|
||||
EXPECT_NONFATAL_FAILURE(
|
||||
{ // NOLINT
|
||||
Exactly(-1);
|
||||
(void)Exactly(-1);
|
||||
},
|
||||
"The invocation lower bound must be >= 0");
|
||||
}
|
||||
|
||||
@@ -35,6 +35,13 @@
|
||||
// Silence C4503 (decorated name length exceeded) for MSVC.
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4503)
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
// This file intentionally tests many ways of writing Mock classes, including
|
||||
// with and without the override keyword.
|
||||
#pragma clang diagnostic ignored "-Winconsistent-missing-override"
|
||||
#endif
|
||||
|
||||
#ifdef GTEST_OS_WINDOWS
|
||||
// MSDN says the header file to be included for STDMETHOD is BaseTyps.h but
|
||||
// we are getting compiler errors if we use basetyps.h, hence including
|
||||
@@ -91,7 +98,7 @@ class FooInterface {
|
||||
|
||||
virtual bool TakesNonConstReference(int& n) = 0; // NOLINT
|
||||
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(int n) = 0;
|
||||
@@ -451,6 +458,87 @@ TYPED_TEST(FunctionMockerTest, MocksReturnTypeWithCommaAndCallType) {
|
||||
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
// Compilability test, to ensure macros expand to all the arguments they're
|
||||
// supposed to.
|
||||
class MockManyArgs {
|
||||
using T = int;
|
||||
|
||||
public:
|
||||
MockManyArgs() = default;
|
||||
|
||||
MOCK_METHOD(void, F, (), ());
|
||||
MOCK_METHOD(void, F, (T), ());
|
||||
MOCK_METHOD(void, F, (T, T), ());
|
||||
MOCK_METHOD(void, F, (T, T, T), ());
|
||||
MOCK_METHOD(void, F, (T, T, T, T), ());
|
||||
MOCK_METHOD(void, F, (T, T, T, T, T), ());
|
||||
MOCK_METHOD(void, F, (T, T, T, T, T, T), ());
|
||||
MOCK_METHOD(void, F, (T, T, T, T, T, T, T), ());
|
||||
MOCK_METHOD(void, F, (T, T, T, T, T, T, T, T), ());
|
||||
MOCK_METHOD(void, F, (T, T, T, T, T, T, T, T, T), ());
|
||||
MOCK_METHOD(void, F, (T, T, T, T, T, T, T, T, T, T), ());
|
||||
MOCK_METHOD(void, F, (T, T, T, T, T, T, T, T, T, T, T), ());
|
||||
MOCK_METHOD(void, F, (T, T, T, T, T, T, T, T, T, T, T, T), ());
|
||||
MOCK_METHOD(void, F, (T, T, T, T, T, T, T, T, T, T, T, T, T), ());
|
||||
MOCK_METHOD(void, F, (T, T, T, T, T, T, T, T, T, T, T, T, T, T), ());
|
||||
MOCK_METHOD(void, F, (T, T, T, T, T, T, T, T, T, T, T, T, T, T, T), ());
|
||||
MOCK_METHOD(void, F, (T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T), ());
|
||||
MOCK_METHOD(void, F, (T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T), ());
|
||||
MOCK_METHOD(void, F, (T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T),
|
||||
());
|
||||
MOCK_METHOD(void, F,
|
||||
(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T), ());
|
||||
MOCK_METHOD(void, F,
|
||||
(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T), ());
|
||||
MOCK_METHOD(void, F,
|
||||
(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T),
|
||||
());
|
||||
MOCK_METHOD(void, F,
|
||||
(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
|
||||
T),
|
||||
());
|
||||
MOCK_METHOD(void, F,
|
||||
(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
|
||||
T),
|
||||
());
|
||||
MOCK_METHOD(void, F,
|
||||
(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
|
||||
T, T),
|
||||
());
|
||||
MOCK_METHOD(void, F,
|
||||
(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
|
||||
T, T, T),
|
||||
());
|
||||
MOCK_METHOD(void, F,
|
||||
(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
|
||||
T, T, T, T),
|
||||
());
|
||||
MOCK_METHOD(void, F,
|
||||
(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
|
||||
T, T, T, T, T),
|
||||
());
|
||||
MOCK_METHOD(void, F,
|
||||
(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
|
||||
T, T, T, T, T, T),
|
||||
());
|
||||
MOCK_METHOD(void, F,
|
||||
(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
|
||||
T, T, T, T, T, T, T),
|
||||
());
|
||||
MOCK_METHOD(void, F,
|
||||
(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
|
||||
T, T, T, T, T, T, T, T),
|
||||
());
|
||||
MOCK_METHOD(void, F,
|
||||
(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,
|
||||
T, T, T, T, T, T, T, T, T),
|
||||
());
|
||||
|
||||
private:
|
||||
MockManyArgs(const MockManyArgs&) = delete;
|
||||
MockManyArgs& operator=(const MockManyArgs&) = delete;
|
||||
};
|
||||
|
||||
TEST(FunctionMockerTest, RefQualified) {
|
||||
MockFoo mock_foo;
|
||||
|
||||
@@ -849,11 +937,20 @@ namespace {
|
||||
template <typename Expected, typename F>
|
||||
static constexpr bool IsMockFunctionTemplateArgumentDeducedTo(
|
||||
const internal::MockFunction<F>&) {
|
||||
return std::is_same<F, Expected>::value;
|
||||
return std::is_same_v<F, Expected>;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Like std::add_const, but for function types.
|
||||
template <typename F>
|
||||
struct AddConstToFunction;
|
||||
|
||||
template <typename R, typename... Args>
|
||||
struct AddConstToFunction<R(Args...)> {
|
||||
using type = R(Args...) const;
|
||||
};
|
||||
|
||||
template <typename F>
|
||||
class MockMethodMockFunctionSignatureTest : public Test {};
|
||||
|
||||
@@ -865,25 +962,69 @@ TYPED_TEST_SUITE(MockMethodMockFunctionSignatureTest,
|
||||
|
||||
TYPED_TEST(MockMethodMockFunctionSignatureTest,
|
||||
IsMockFunctionTemplateArgumentDeducedForRawSignature) {
|
||||
using Argument = TypeParam;
|
||||
MockFunction<Argument> foo;
|
||||
EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<TypeParam>(foo));
|
||||
// Non-const
|
||||
{
|
||||
using Argument = TypeParam;
|
||||
MockFunction<Argument> foo;
|
||||
EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<TypeParam>(foo));
|
||||
}
|
||||
|
||||
// Const
|
||||
{
|
||||
using Argument = typename AddConstToFunction<TypeParam>::type;
|
||||
MockFunction<Argument> foo;
|
||||
EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<TypeParam>(foo));
|
||||
}
|
||||
}
|
||||
|
||||
TYPED_TEST(MockMethodMockFunctionSignatureTest,
|
||||
IsMockFunctionTemplateArgumentDeducedForStdFunction) {
|
||||
using Argument = std::function<TypeParam>;
|
||||
MockFunction<Argument> foo;
|
||||
EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<TypeParam>(foo));
|
||||
// Non-const
|
||||
{
|
||||
using Argument = std::function<TypeParam>;
|
||||
MockFunction<Argument> foo;
|
||||
EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<TypeParam>(foo));
|
||||
}
|
||||
|
||||
// As of 2026-05 MSVC doesn't know how to deal with this, providing pages of
|
||||
// inscrutable errors about std::_Get_function_impl. But this is fine, since
|
||||
// std::function<R(Args...) const> doesn't apply the const qualifier correctly
|
||||
// anyway.
|
||||
#if !defined(_MSC_VER)
|
||||
|
||||
// Const
|
||||
{
|
||||
using Argument =
|
||||
std::function<typename AddConstToFunction<TypeParam>::type>;
|
||||
|
||||
MockFunction<Argument> foo;
|
||||
EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<TypeParam>(foo));
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
TYPED_TEST(
|
||||
MockMethodMockFunctionSignatureTest,
|
||||
IsMockFunctionCallMethodSignatureTheSameForRawSignatureAndStdFunction) {
|
||||
using ForRawSignature = decltype(&MockFunction<TypeParam>::Call);
|
||||
using ForStdFunction =
|
||||
decltype(&MockFunction<std::function<TypeParam>>::Call);
|
||||
EXPECT_TRUE((std::is_same<ForRawSignature, ForStdFunction>::value));
|
||||
// Non-const
|
||||
{
|
||||
using ForRawSignature = decltype(&MockFunction<TypeParam>::Call);
|
||||
using ForStdFunction =
|
||||
decltype(&MockFunction<std::function<TypeParam>>::Call);
|
||||
EXPECT_TRUE((std::is_same<ForRawSignature, ForStdFunction>::value));
|
||||
}
|
||||
|
||||
// Const
|
||||
{
|
||||
using ConstTypeParam = typename AddConstToFunction<TypeParam>::type;
|
||||
using ForRawSignature = decltype(&MockFunction<ConstTypeParam>::Call);
|
||||
|
||||
using ForStdFunction =
|
||||
decltype(&MockFunction<std::function<ConstTypeParam>>::Call);
|
||||
|
||||
EXPECT_TRUE((std::is_same<ForRawSignature, ForStdFunction>::value));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
|
||||
@@ -545,7 +545,7 @@ TEST(ExpectCallTest, DoesNotLogWhenVerbosityIsError) {
|
||||
|
||||
void OnCallLogger() {
|
||||
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".
|
||||
@@ -568,7 +568,7 @@ TEST(OnCallTest, DoesNotLogWhenVerbosityIsError) {
|
||||
|
||||
void OnCallAnyArgumentLogger() {
|
||||
DummyMock mock;
|
||||
ON_CALL(mock, TestMethodArg(_));
|
||||
(void)ON_CALL(mock, TestMethodArg(_));
|
||||
}
|
||||
|
||||
// Verifies that ON_CALL prints provided _ argument.
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
@@ -398,6 +399,188 @@ TEST(NanSensitiveDoubleNearTest, CanDescribeSelfWithNaNs) {
|
||||
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.
|
||||
TEST(NotTest, NegatesMatcher) {
|
||||
Matcher<int> m;
|
||||
@@ -537,7 +720,6 @@ TEST(AllOfTest, CanDescribeNegation) {
|
||||
|
||||
m = AllOf(Ne(1), Ne(2), Ne(3), Ne(4), Ne(5), Ne(6), Ne(7), Ne(8), Ne(9),
|
||||
Ne(10), Ne(11));
|
||||
AllOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
|
||||
EXPECT_THAT(Describe(m), EndsWith("and (isn't equal to 11)"));
|
||||
AllOfMatches(11, m);
|
||||
}
|
||||
@@ -587,7 +769,8 @@ TEST_P(AllOfTestP, ExplainsResult) {
|
||||
// Failed match. The first matcher, which failed, needs to
|
||||
// explain.
|
||||
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
|
||||
// explain. Since it doesn't given an explanation, the matcher text is
|
||||
@@ -1442,7 +1625,7 @@ TEST_F(DoubleNearTest, NanSensitiveDoubleNearCanMatchNaN) {
|
||||
}
|
||||
|
||||
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, Not(Pointee(Eq(2))));
|
||||
}
|
||||
@@ -1498,13 +1681,13 @@ TEST(AnyOfTest, DoesNotCallAnyOfUnqualified) {
|
||||
} // namespace adl_test
|
||||
|
||||
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, Not(AllOf(Pointee(Eq(3)), Pointee(Gt(0)), Pointee(Lt(3)))));
|
||||
}
|
||||
|
||||
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, Not(AnyOf(Pointee(Eq(5)), Pointee(Lt(0)), Pointee(Gt(5)))));
|
||||
}
|
||||
|
||||
@@ -33,7 +33,9 @@
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
@@ -235,7 +237,6 @@ TEST(StringMatcherTest, CanBeImplicitlyConstructedFromString) {
|
||||
EXPECT_FALSE(m2.Matches("hello"));
|
||||
}
|
||||
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
// Tests that a C-string literal can be implicitly converted to a
|
||||
// Matcher<StringView> or Matcher<const StringView&>.
|
||||
TEST(StringViewMatcherTest, CanBeImplicitlyConstructedFromCStringLiteral) {
|
||||
@@ -271,7 +272,6 @@ TEST(StringViewMatcherTest, CanBeImplicitlyConstructedFromStringView) {
|
||||
EXPECT_TRUE(m2.Matches("cats"));
|
||||
EXPECT_FALSE(m2.Matches("dogs"));
|
||||
}
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
// Tests that a std::reference_wrapper<std::string> object can be implicitly
|
||||
// converted to a Matcher<std::string> or Matcher<const std::string&> via Eq().
|
||||
@@ -621,15 +621,42 @@ struct IntReferenceWrapper {
|
||||
const int* value;
|
||||
};
|
||||
|
||||
// Compared the contained values
|
||||
bool operator==(const IntReferenceWrapper& a, const IntReferenceWrapper& b) {
|
||||
return a.value == b.value;
|
||||
return *a.value == *b.value;
|
||||
}
|
||||
|
||||
TEST(MatcherCastTest, ValueIsNotCopied) {
|
||||
int n = 42;
|
||||
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));
|
||||
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;
|
||||
Matcher<IntReferenceWrapper> m = MatcherCast<IntReferenceWrapper>(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 {
|
||||
@@ -770,6 +797,7 @@ TEST(ExpectThat, TakesLiterals) {
|
||||
EXPECT_THAT(1, 1);
|
||||
EXPECT_THAT(1.0, 1.0);
|
||||
EXPECT_THAT(std::string(), "");
|
||||
EXPECT_THAT(std::shared_ptr<int>(), nullptr);
|
||||
}
|
||||
|
||||
TEST(ExpectThat, TakesFunctions) {
|
||||
@@ -1063,8 +1091,20 @@ TEST(IsEmptyTest, MatchesCString) {
|
||||
const char b[] = "x";
|
||||
EXPECT_TRUE(m.Matches(a));
|
||||
EXPECT_FALSE(m.Matches(b));
|
||||
EXPECT_FALSE(m.Matches(nullptr));
|
||||
}
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
TEST(IsEmptyTest, MatchesCWideString) {
|
||||
const Matcher<const wchar_t*> m = IsEmpty();
|
||||
const wchar_t a[] = L"";
|
||||
const wchar_t b[] = L"x";
|
||||
EXPECT_TRUE(m.Matches(a));
|
||||
EXPECT_FALSE(m.Matches(b));
|
||||
EXPECT_FALSE(m.Matches(nullptr));
|
||||
}
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
|
||||
// Tests that IsNull() matches any NULL pointer of any type.
|
||||
TEST(IsNullTest, MatchesNullPointer) {
|
||||
Matcher<int*> m1 = IsNull();
|
||||
@@ -1098,6 +1138,16 @@ TEST(IsNullTest, CanDescribeSelf) {
|
||||
EXPECT_EQ("isn't NULL", DescribeNegation(m));
|
||||
}
|
||||
|
||||
struct SmartPtrHelper {
|
||||
MOCK_METHOD(void, Call, (std::shared_ptr<int>));
|
||||
};
|
||||
|
||||
TEST(IsNullTest, WorksWithSmartPtr) {
|
||||
SmartPtrHelper helper;
|
||||
EXPECT_CALL(helper, Call(nullptr));
|
||||
helper.Call(nullptr);
|
||||
}
|
||||
|
||||
// Tests that NotNull() matches any non-NULL pointer of any type.
|
||||
TEST(NotNullTest, MatchesNonNullPointer) {
|
||||
Matcher<int*> m1 = NotNull();
|
||||
@@ -1203,22 +1253,26 @@ TEST(RefTest, ExplainsResult) {
|
||||
// Tests string comparison matchers.
|
||||
|
||||
template <typename T = std::string>
|
||||
std::string FromStringLike(internal::StringLike<T> str) {
|
||||
return std::string(str);
|
||||
internal::StringType<T> ToString(T str) {
|
||||
return internal::StringType<T>(str);
|
||||
}
|
||||
|
||||
TEST(StringLike, TestConversions) {
|
||||
EXPECT_EQ("foo", FromStringLike("foo"));
|
||||
EXPECT_EQ("foo", FromStringLike(std::string("foo")));
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
EXPECT_EQ("foo", FromStringLike(internal::StringView("foo")));
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
TEST(StringType, TestConversions) {
|
||||
EXPECT_EQ("foo", ToString("foo"));
|
||||
EXPECT_EQ("foo", ToString(std::string("foo")));
|
||||
EXPECT_EQ("foo", ToString(internal::StringView("foo")));
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
EXPECT_EQ(L"foo", ToString(L"foo"));
|
||||
EXPECT_EQ(L"foo", ToString(std::wstring(L"foo")));
|
||||
EXPECT_EQ(L"foo", ToString(std::wstring_view(L"foo")));
|
||||
#endif
|
||||
|
||||
// Non deducible types.
|
||||
EXPECT_EQ("", FromStringLike({}));
|
||||
EXPECT_EQ("foo", FromStringLike({'f', 'o', 'o'}));
|
||||
EXPECT_EQ("", ToString({}));
|
||||
EXPECT_EQ("foo", ToString({'f', 'o', 'o'}));
|
||||
const char buf[] = "foo";
|
||||
EXPECT_EQ("foo", FromStringLike({buf, buf + 3}));
|
||||
EXPECT_EQ("foo", ToString({buf, buf + 3}));
|
||||
}
|
||||
|
||||
TEST(StrEqTest, MatchesEqualString) {
|
||||
@@ -1231,7 +1285,6 @@ TEST(StrEqTest, MatchesEqualString) {
|
||||
EXPECT_TRUE(m2.Matches("Hello"));
|
||||
EXPECT_FALSE(m2.Matches("Hi"));
|
||||
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
Matcher<const internal::StringView&> m3 =
|
||||
StrEq(internal::StringView("Hello"));
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView("Hello")));
|
||||
@@ -1242,7 +1295,6 @@ TEST(StrEqTest, MatchesEqualString) {
|
||||
EXPECT_TRUE(m_empty.Matches(internal::StringView("")));
|
||||
EXPECT_TRUE(m_empty.Matches(internal::StringView()));
|
||||
EXPECT_FALSE(m_empty.Matches(internal::StringView("hello")));
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
}
|
||||
|
||||
TEST(StrEqTest, CanDescribeSelf) {
|
||||
@@ -1269,12 +1321,10 @@ TEST(StrNeTest, MatchesUnequalString) {
|
||||
EXPECT_TRUE(m2.Matches("hello"));
|
||||
EXPECT_FALSE(m2.Matches("Hello"));
|
||||
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
Matcher<const internal::StringView> m3 = StrNe(internal::StringView("Hello"));
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView("")));
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView()));
|
||||
EXPECT_FALSE(m3.Matches(internal::StringView("Hello")));
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
}
|
||||
|
||||
TEST(StrNeTest, CanDescribeSelf) {
|
||||
@@ -1293,14 +1343,12 @@ TEST(StrCaseEqTest, MatchesEqualStringIgnoringCase) {
|
||||
EXPECT_TRUE(m2.Matches("hello"));
|
||||
EXPECT_FALSE(m2.Matches("Hi"));
|
||||
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
Matcher<const internal::StringView&> m3 =
|
||||
StrCaseEq(internal::StringView("Hello"));
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView("Hello")));
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView("hello")));
|
||||
EXPECT_FALSE(m3.Matches(internal::StringView("Hi")));
|
||||
EXPECT_FALSE(m3.Matches(internal::StringView()));
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
}
|
||||
|
||||
TEST(StrCaseEqTest, MatchesEqualStringWith0IgnoringCase) {
|
||||
@@ -1344,14 +1392,12 @@ TEST(StrCaseNeTest, MatchesUnequalStringIgnoringCase) {
|
||||
EXPECT_TRUE(m2.Matches(""));
|
||||
EXPECT_FALSE(m2.Matches("Hello"));
|
||||
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
Matcher<const internal::StringView> m3 =
|
||||
StrCaseNe(internal::StringView("Hello"));
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView("Hi")));
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView()));
|
||||
EXPECT_FALSE(m3.Matches(internal::StringView("Hello")));
|
||||
EXPECT_FALSE(m3.Matches(internal::StringView("hello")));
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
}
|
||||
|
||||
TEST(StrCaseNeTest, CanDescribeSelf) {
|
||||
@@ -1392,7 +1438,6 @@ TEST(HasSubstrTest, WorksForCStrings) {
|
||||
EXPECT_FALSE(m_empty.Matches(nullptr));
|
||||
}
|
||||
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
// Tests that HasSubstr() works for matching StringView-typed values.
|
||||
TEST(HasSubstrTest, WorksForStringViewClasses) {
|
||||
const Matcher<internal::StringView> m1 =
|
||||
@@ -1411,7 +1456,6 @@ TEST(HasSubstrTest, WorksForStringViewClasses) {
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView("")));
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView()));
|
||||
}
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
// Tests that HasSubstr(s) describes itself properly.
|
||||
TEST(HasSubstrTest, CanDescribeSelf) {
|
||||
@@ -1810,13 +1854,11 @@ TEST(StartsWithTest, MatchesStringWithGivenPrefix) {
|
||||
EXPECT_FALSE(m2.Matches("H"));
|
||||
EXPECT_FALSE(m2.Matches(" Hi"));
|
||||
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
const Matcher<internal::StringView> m_empty =
|
||||
StartsWith(internal::StringView(""));
|
||||
EXPECT_TRUE(m_empty.Matches(internal::StringView()));
|
||||
EXPECT_TRUE(m_empty.Matches(internal::StringView("")));
|
||||
EXPECT_TRUE(m_empty.Matches(internal::StringView("not empty")));
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
}
|
||||
|
||||
TEST(StartsWithTest, CanDescribeSelf) {
|
||||
@@ -1825,12 +1867,8 @@ TEST(StartsWithTest, CanDescribeSelf) {
|
||||
}
|
||||
|
||||
TEST(StartsWithTest, WorksWithStringMatcherOnStringViewMatchee) {
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
EXPECT_THAT(internal::StringView("talk to me goose"),
|
||||
StartsWith(std::string("talk")));
|
||||
#else
|
||||
GTEST_SKIP() << "Not applicable without internal::StringView.";
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
}
|
||||
|
||||
// Tests EndsWith(s).
|
||||
@@ -1848,14 +1886,12 @@ TEST(EndsWithTest, MatchesStringWithGivenSuffix) {
|
||||
EXPECT_FALSE(m2.Matches("i"));
|
||||
EXPECT_FALSE(m2.Matches("Hi "));
|
||||
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
const Matcher<const internal::StringView&> m4 =
|
||||
EndsWith(internal::StringView(""));
|
||||
EXPECT_TRUE(m4.Matches("Hi"));
|
||||
EXPECT_TRUE(m4.Matches(""));
|
||||
EXPECT_TRUE(m4.Matches(internal::StringView()));
|
||||
EXPECT_TRUE(m4.Matches(internal::StringView("")));
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
}
|
||||
|
||||
TEST(EndsWithTest, CanDescribeSelf) {
|
||||
@@ -1878,14 +1914,12 @@ TEST(WhenBase64UnescapedTest, MatchesUnescapedBase64Strings) {
|
||||
EXPECT_TRUE(m2.Matches("aGVsbG8gd29ybGQh")); // hello world!
|
||||
EXPECT_TRUE(m2.Matches("+/-_IQ")); // \xfb\xff\xbf!
|
||||
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
const Matcher<const internal::StringView&> m3 =
|
||||
WhenBase64Unescaped(EndsWith("!"));
|
||||
EXPECT_FALSE(m3.Matches("invalid base64"));
|
||||
EXPECT_FALSE(m3.Matches("aGVsbG8gd29ybGQ=")); // hello world
|
||||
EXPECT_TRUE(m3.Matches("aGVsbG8gd29ybGQh")); // hello world!
|
||||
EXPECT_TRUE(m3.Matches("+/-_IQ")); // \xfb\xff\xbf!
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
}
|
||||
|
||||
TEST(WhenBase64UnescapedTest, CanDescribeSelf) {
|
||||
@@ -1906,7 +1940,6 @@ TEST(MatchesRegexTest, MatchesStringMatchingGivenRegex) {
|
||||
EXPECT_FALSE(m2.Matches("az1"));
|
||||
EXPECT_FALSE(m2.Matches("1az"));
|
||||
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
const Matcher<const internal::StringView&> m3 = MatchesRegex("a.*z");
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView("az")));
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView("abcz")));
|
||||
@@ -1916,7 +1949,6 @@ TEST(MatchesRegexTest, MatchesStringMatchingGivenRegex) {
|
||||
MatchesRegex(internal::StringView(""));
|
||||
EXPECT_TRUE(m4.Matches(internal::StringView("")));
|
||||
EXPECT_TRUE(m4.Matches(internal::StringView()));
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
}
|
||||
|
||||
TEST(MatchesRegexTest, CanDescribeSelf) {
|
||||
@@ -1926,10 +1958,8 @@ TEST(MatchesRegexTest, CanDescribeSelf) {
|
||||
Matcher<const char*> m2 = MatchesRegex(new RE("a.*"));
|
||||
EXPECT_EQ("matches regular expression \"a.*\"", Describe(m2));
|
||||
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
Matcher<const internal::StringView> m3 = MatchesRegex(new RE("0.*"));
|
||||
EXPECT_EQ("matches regular expression \"0.*\"", Describe(m3));
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
}
|
||||
|
||||
// Tests ContainsRegex().
|
||||
@@ -1945,7 +1975,6 @@ TEST(ContainsRegexTest, MatchesStringContainingGivenRegex) {
|
||||
EXPECT_TRUE(m2.Matches("az1"));
|
||||
EXPECT_FALSE(m2.Matches("1a"));
|
||||
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
const Matcher<const internal::StringView&> m3 = ContainsRegex(new RE("a.*z"));
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView("azbz")));
|
||||
EXPECT_TRUE(m3.Matches(internal::StringView("az1")));
|
||||
@@ -1955,7 +1984,6 @@ TEST(ContainsRegexTest, MatchesStringContainingGivenRegex) {
|
||||
ContainsRegex(internal::StringView(""));
|
||||
EXPECT_TRUE(m4.Matches(internal::StringView("")));
|
||||
EXPECT_TRUE(m4.Matches(internal::StringView()));
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
}
|
||||
|
||||
TEST(ContainsRegexTest, CanDescribeSelf) {
|
||||
@@ -1965,10 +1993,8 @@ TEST(ContainsRegexTest, CanDescribeSelf) {
|
||||
Matcher<const char*> m2 = ContainsRegex(new RE("a.*"));
|
||||
EXPECT_EQ("contains regular expression \"a.*\"", Describe(m2));
|
||||
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
Matcher<const internal::StringView> m3 = ContainsRegex(new RE("0.*"));
|
||||
EXPECT_EQ("contains regular expression \"0.*\"", Describe(m3));
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
}
|
||||
|
||||
// Tests for wide strings.
|
||||
@@ -2361,22 +2387,19 @@ PolymorphicMatcher<DivisibleByImpl> DivisibleBy(int n) {
|
||||
return MakePolymorphicMatcher(DivisibleByImpl(n));
|
||||
}
|
||||
|
||||
// Tests that when AllOf() fails, only the first failing matcher is
|
||||
// asked to explain why.
|
||||
// Tests that when AllOf() fails, all failing matchers are asked to explain why.
|
||||
TEST(ExplainMatchResultTest, AllOf_False_False) {
|
||||
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
|
||||
// asked to explain why.
|
||||
// Tests that when AllOf() fails, all failing matchers are asked to explain why.
|
||||
TEST(ExplainMatchResultTest, AllOf_False_True) {
|
||||
const Matcher<int> m = AllOf(DivisibleBy(4), DivisibleBy(3));
|
||||
EXPECT_EQ("which is 2 modulo 4", Explain(m, 6));
|
||||
}
|
||||
|
||||
// Tests that when AllOf() fails, only the first failing matcher is
|
||||
// asked to explain why.
|
||||
// Tests that when AllOf() fails, all failing matchers are asked to explain why.
|
||||
TEST(ExplainMatchResultTest, AllOf_True_False) {
|
||||
const Matcher<int> m = AllOf(Ge(1), DivisibleBy(3));
|
||||
EXPECT_EQ("which is 2 modulo 3", Explain(m, 5));
|
||||
@@ -2396,6 +2419,74 @@ TEST(ExplainMatchResultTest, AllOf_True_True_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);
|
||||
|
||||
TEST_P(ExplainmatcherResultTestP, MonomorphicMatcher) {
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <deque>
|
||||
#include <forward_list>
|
||||
#include <iterator>
|
||||
@@ -216,7 +217,7 @@ TEST(PointeeTest, ReferenceToNonConstRawPointer) {
|
||||
TEST(PointeeTest, SmartPointer) {
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -253,7 +254,7 @@ TEST(PointerTest, RawPointerToConst) {
|
||||
}
|
||||
|
||||
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();
|
||||
const Matcher<std::unique_ptr<int>> m = Pointer(Eq(raw_n));
|
||||
|
||||
@@ -1046,8 +1047,8 @@ TEST(ResultOfTest, WorksForCompatibleMatcherTypes) {
|
||||
// a NULL function pointer.
|
||||
TEST(ResultOfDeathTest, DiesOnNullFunctionPointers) {
|
||||
EXPECT_DEATH_IF_SUPPORTED(
|
||||
ResultOf(static_cast<std::string (*)(int dummy)>(nullptr),
|
||||
Eq(std::string("foo"))),
|
||||
(void)ResultOf(static_cast<std::string (*)(int dummy)>(nullptr),
|
||||
Eq(std::string("foo"))),
|
||||
"NULL function pointer is passed into ResultOf\\(\\)\\.");
|
||||
}
|
||||
|
||||
@@ -1271,10 +1272,11 @@ TEST(WhenSortedByTest, CanDescribeSelf) {
|
||||
|
||||
TEST(WhenSortedByTest, ExplainsMatchResult) {
|
||||
const int a[] = {2, 1};
|
||||
EXPECT_EQ("which is { 1, 2 } when sorted, whose element #0 doesn't match",
|
||||
Explain(WhenSortedBy(less<int>(), ElementsAre(2, 3)), a));
|
||||
EXPECT_EQ("which is { 1, 2 } when sorted",
|
||||
Explain(WhenSortedBy(less<int>(), ElementsAre(1, 2)), a));
|
||||
EXPECT_EQ(
|
||||
Explain(WhenSortedBy(less<int>(), ElementsAre(2, 3)), a),
|
||||
"which is { 1, 2 } when sorted, whose element #0 (1) isn't equal to 2");
|
||||
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
|
||||
@@ -1775,6 +1777,295 @@ TEST(IsSubsetOfTest, WorksWithMoveOnly) {
|
||||
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
|
||||
// "containers".
|
||||
|
||||
@@ -2155,7 +2446,7 @@ TEST_P(EachTestP, ExplainsMatchResultCorrectly) {
|
||||
Matcher<set<int>> m = Each(2);
|
||||
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};
|
||||
EXPECT_EQ("", Explain(n, b));
|
||||
@@ -2290,7 +2581,7 @@ TEST(PointwiseTest, MakesCopyOfRhs) {
|
||||
rhs.push_back(4);
|
||||
|
||||
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);
|
||||
|
||||
// Changing rhs now shouldn't affect m, which made a copy of rhs.
|
||||
@@ -2418,7 +2709,7 @@ TEST(UnorderedPointwiseTest, MakesCopyOfRhs) {
|
||||
rhs.push_back(4);
|
||||
|
||||
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);
|
||||
|
||||
// Changing rhs now shouldn't affect m, which made a copy of rhs.
|
||||
@@ -2505,7 +2796,7 @@ TEST(UnorderedPointwiseTest, WorksWithMoveOnly) {
|
||||
}
|
||||
|
||||
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, Not(Pointee(Eq(2))));
|
||||
}
|
||||
@@ -2669,11 +2960,11 @@ TEST_P(ElementsAreTestP, CanExplainMismatchRightSize) {
|
||||
vector<int> v;
|
||||
v.push_back(2);
|
||||
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;
|
||||
EXPECT_EQ("whose element #1 doesn't match, which is 4 less than 5",
|
||||
Explain(m, v));
|
||||
EXPECT_EQ(Explain(m, v),
|
||||
"whose element #1 (1) is <= 5, which is 4 less than 5");
|
||||
}
|
||||
|
||||
TEST(ElementsAreTest, MatchesOneElementVector) {
|
||||
@@ -3073,7 +3364,7 @@ TEST(ContainsTest, SetDoesNotMatchWhenElementIsNotInContainer) {
|
||||
|
||||
TEST_P(ContainsTestP, ExplainsMatchResultCorrectly) {
|
||||
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));
|
||||
|
||||
m = Contains(3);
|
||||
@@ -3148,6 +3439,78 @@ TEST(ContainsTest, WorksForTwoDimensionalNativeArray) {
|
||||
EXPECT_THAT(a, Contains(Not(Contains(5))));
|
||||
}
|
||||
|
||||
// Tests ContainsSubsequence().
|
||||
|
||||
TEST(ContainsSubsequenceTest, WorksForNativeArray) {
|
||||
const int a[] = {1, 2, 3, 4, 5};
|
||||
EXPECT_THAT(a, ContainsSubsequence(1, 3, 4));
|
||||
EXPECT_THAT(a, Not(ContainsSubsequence(1, 3, 2)));
|
||||
}
|
||||
|
||||
TEST(ContainsSubsequenceTest, AcceptsMatcher) {
|
||||
const int a[] = {1, 2, 3, 4, 5};
|
||||
EXPECT_THAT(a, ContainsSubsequence(Eq(1), Gt(3), Gt(4)));
|
||||
EXPECT_THAT(a, Not(ContainsSubsequence(1, Gt(3), Lt(3))));
|
||||
}
|
||||
|
||||
TEST(ContainsSubsequenceTest, WorksForTwoDimensionalNativeArray) {
|
||||
int a[][3] = {{1, 2, 3}, {7, 8, 9}, {4, 5, 6}};
|
||||
EXPECT_THAT(a, ContainsSubsequence(ElementsAre(1, 2, 3), Contains(4)));
|
||||
EXPECT_THAT(a,
|
||||
Not(ContainsSubsequence(Contains(1), Contains(8), Contains(9))));
|
||||
}
|
||||
|
||||
TEST(ContainsSubsequenceTest, WorksForVector) {
|
||||
const vector<int> a = {1, 2, 3, 4, 5};
|
||||
EXPECT_THAT(a, ContainsSubsequence(1, 3, 4));
|
||||
EXPECT_THAT(a, Not(ContainsSubsequence(1, 3, 2)));
|
||||
}
|
||||
|
||||
TEST(ContainsSubsequenceTest, WorksForEmptySmallSizedSubsequences) {
|
||||
const int a[] = {1, 2, 3, 4, 5};
|
||||
EXPECT_THAT(a, ContainsSubsequence());
|
||||
EXPECT_THAT(a, ContainsSubsequence(Gt(4)));
|
||||
EXPECT_THAT(a, Not(ContainsSubsequence(Gt(6))));
|
||||
EXPECT_THAT(a, ContainsSubsequence(Lt(2), Gt(3)));
|
||||
EXPECT_THAT(a, Not(ContainsSubsequence(Lt(2), Lt(2))));
|
||||
}
|
||||
|
||||
TEST(ContainsSubsequenceTest, DescribesItselfCorrectly) {
|
||||
Matcher<const int (&)[5]> m = ContainsSubsequence(1, 3, 4);
|
||||
EXPECT_EQ(
|
||||
"contains in order a subsequence of elements that matches: is equal to "
|
||||
"1, then is equal to 3, then is equal to 4",
|
||||
Describe(m));
|
||||
m = ContainsSubsequence(Eq(1), Gt(3), Gt(4));
|
||||
EXPECT_EQ(
|
||||
"contains in order a subsequence of elements that matches: is equal to "
|
||||
"1, then is > 3, then is > 4",
|
||||
Describe(m));
|
||||
|
||||
m = Not(ContainsSubsequence(1, 3, 4));
|
||||
EXPECT_EQ(
|
||||
"does not contain in order a subsequence of elements that matches is "
|
||||
"equal to 1, then is equal to 3, then is equal to 4",
|
||||
Describe(m));
|
||||
}
|
||||
|
||||
TEST(ContainsSubsequenceTest, ExplainsMismatchCorrectlyForSingleMatcher) {
|
||||
const int a[] = {1, 2, 3, 4, 5};
|
||||
Matcher<const int (&)[5]> m = ContainsSubsequence(Eq(6));
|
||||
EXPECT_EQ(Explain(m, a),
|
||||
"could not find a match for matcher #0 (is equal to 6)");
|
||||
}
|
||||
|
||||
TEST(ContainsSubsequenceTest, ExplainsMismatchCorrectlyForMultipleMatchers) {
|
||||
const int a[] = {1, 2, 3, 4, 5};
|
||||
Matcher<const int (&)[5]> m = ContainsSubsequence(Eq(2), Gt(4), Gt(4));
|
||||
EXPECT_EQ(
|
||||
Explain(m, a),
|
||||
"found match for matcher #0 with element at position #1, found match for "
|
||||
"matcher #1 with element at position #4, but could not find a match for "
|
||||
"matcher #2 (is > 4) after the last match at position #4");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace gmock_matchers_test
|
||||
} // namespace testing
|
||||
|
||||
@@ -79,7 +79,7 @@ TEST(AddressTest, Const) {
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
EXPECT_TRUE(m.Matches(n));
|
||||
@@ -202,7 +202,7 @@ TEST(IsTrueTest, IsTrueIsFalse) {
|
||||
EXPECT_THAT(nullptr, Not(IsTrue()));
|
||||
EXPECT_THAT(nullptr, IsFalse());
|
||||
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, IsFalse());
|
||||
EXPECT_THAT(nonnull_unique, IsTrue());
|
||||
@@ -789,7 +789,7 @@ class SampleVariantIntString {
|
||||
|
||||
template <typename T>
|
||||
friend bool holds_alternative(const SampleVariantIntString& value) {
|
||||
return value.has_int_ == std::is_same<T, int>::value;
|
||||
return value.has_int_ == std::is_same_v<T, int>;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -1665,7 +1665,7 @@ MATCHER(IsNotNull, "") { return arg != nullptr; }
|
||||
// Verifies that a matcher defined using MATCHER() can work on
|
||||
// move-only types.
|
||||
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(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
|
||||
// move-only types.
|
||||
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, Not(UniquePointee(2)));
|
||||
}
|
||||
|
||||
@@ -123,8 +123,7 @@ struct GtestGreaterThanMatcher {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
GtestGreaterThanMatcher<typename std::decay<T>::type> GtestGreaterThan(
|
||||
T&& rhs) {
|
||||
GtestGreaterThanMatcher<std::decay_t<T>> GtestGreaterThan(T&& rhs) {
|
||||
return {rhs};
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ using testing::Invoke;
|
||||
using testing::ReturnArg;
|
||||
using testing::ReturnPointee;
|
||||
using testing::SaveArg;
|
||||
using testing::SaveArgByMove;
|
||||
using testing::SaveArgPointee;
|
||||
using testing::SetArgReferee;
|
||||
using testing::Unused;
|
||||
@@ -201,45 +202,45 @@ class Foo {
|
||||
|
||||
// Tests using Invoke() with a nullary function.
|
||||
TEST(InvokeTest, Nullary) {
|
||||
Action<int()> a = Invoke(Nullary); // NOLINT
|
||||
Action<int()> a = &Nullary;
|
||||
EXPECT_EQ(1, a.Perform(std::make_tuple()));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a unary function.
|
||||
TEST(InvokeTest, Unary) {
|
||||
Action<bool(int)> a = Invoke(Unary); // NOLINT
|
||||
Action<bool(int)> a = &Unary;
|
||||
EXPECT_FALSE(a.Perform(std::make_tuple(1)));
|
||||
EXPECT_TRUE(a.Perform(std::make_tuple(-1)));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a binary function.
|
||||
TEST(InvokeTest, Binary) {
|
||||
Action<const char*(const char*, short)> a = Invoke(Binary); // NOLINT
|
||||
Action<const char*(const char*, short)> a = &Binary; // NOLINT
|
||||
const char* p = "Hello";
|
||||
EXPECT_EQ(p + 2, a.Perform(std::make_tuple(p, Short(2))));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a ternary function.
|
||||
TEST(InvokeTest, Ternary) {
|
||||
Action<int(int, char, short)> a = Invoke(Ternary); // NOLINT
|
||||
Action<int(int, char, short)> a = &Ternary; // NOLINT
|
||||
EXPECT_EQ(6, a.Perform(std::make_tuple(1, '\2', Short(3))));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a 4-argument function.
|
||||
TEST(InvokeTest, FunctionThatTakes4Arguments) {
|
||||
Action<int(int, int, int, int)> a = Invoke(SumOf4); // NOLINT
|
||||
Action<int(int, int, int, int)> a = &SumOf4;
|
||||
EXPECT_EQ(1234, a.Perform(std::make_tuple(1000, 200, 30, 4)));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a 5-argument function.
|
||||
TEST(InvokeTest, FunctionThatTakes5Arguments) {
|
||||
Action<int(int, int, int, int, int)> a = Invoke(SumOf5); // NOLINT
|
||||
Action<int(int, int, int, int, int)> a = &SumOf5;
|
||||
EXPECT_EQ(12345, a.Perform(std::make_tuple(10000, 2000, 300, 40, 5)));
|
||||
}
|
||||
|
||||
// Tests using Invoke() with a 6-argument function.
|
||||
TEST(InvokeTest, FunctionThatTakes6Arguments) {
|
||||
Action<int(int, int, int, int, int, int)> a = Invoke(SumOf6); // NOLINT
|
||||
Action<int(int, int, int, int, int, int)> a = &SumOf6;
|
||||
EXPECT_EQ(123456,
|
||||
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) {
|
||||
Action<std::string(const char*, const char*, const char*, const char*,
|
||||
const char*, const char*, const char*)>
|
||||
a = Invoke(Concat7);
|
||||
a = &Concat7;
|
||||
EXPECT_EQ("1234567",
|
||||
a.Perform(std::make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
||||
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
||||
@@ -263,7 +264,7 @@ TEST(InvokeTest, FunctionThatTakes7Arguments) {
|
||||
TEST(InvokeTest, FunctionThatTakes8Arguments) {
|
||||
Action<std::string(const char*, const char*, const char*, const char*,
|
||||
const char*, const char*, const char*, const char*)>
|
||||
a = Invoke(Concat8);
|
||||
a = &Concat8;
|
||||
EXPECT_EQ("12345678",
|
||||
a.Perform(std::make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
||||
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
||||
@@ -275,7 +276,7 @@ TEST(InvokeTest, FunctionThatTakes9Arguments) {
|
||||
Action<std::string(const char*, const char*, const char*, const char*,
|
||||
const char*, const char*, const char*, const char*,
|
||||
const char*)>
|
||||
a = Invoke(Concat9);
|
||||
a = &Concat9;
|
||||
EXPECT_EQ("123456789", a.Perform(std::make_tuple(
|
||||
CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
||||
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
||||
@@ -287,7 +288,7 @@ TEST(InvokeTest, FunctionThatTakes10Arguments) {
|
||||
Action<std::string(const char*, const char*, const char*, const char*,
|
||||
const char*, const char*, const char*, const char*,
|
||||
const char*, const char*)>
|
||||
a = Invoke(Concat10);
|
||||
a = &Concat10;
|
||||
EXPECT_EQ("1234567890",
|
||||
a.Perform(std::make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
|
||||
CharPtr("4"), CharPtr("5"), CharPtr("6"),
|
||||
@@ -297,12 +298,12 @@ TEST(InvokeTest, FunctionThatTakes10Arguments) {
|
||||
|
||||
// Tests using Invoke() with functions with parameters declared as Unused.
|
||||
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::make_tuple(10, 2, 5.6, std::string("hi"));
|
||||
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(
|
||||
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.
|
||||
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)));
|
||||
}
|
||||
|
||||
// Tests using Invoke(f) as an action of a compatible type.
|
||||
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)));
|
||||
}
|
||||
|
||||
@@ -446,13 +447,13 @@ TEST(InvokeMethodTest, MethodWithCompatibleType) {
|
||||
|
||||
// Tests using WithoutArgs with an action that takes no argument.
|
||||
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)));
|
||||
}
|
||||
|
||||
// Tests using WithArg with an action that takes 1 argument.
|
||||
TEST(WithArgTest, OneArg) {
|
||||
Action<bool(double x, int n)> b = WithArg<1>(Invoke(Unary)); // NOLINT
|
||||
Action<bool(double x, int n)> b = WithArg<1>(&Unary); // NOLINT
|
||||
EXPECT_TRUE(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);
|
||||
}
|
||||
|
||||
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) {
|
||||
int result = 0;
|
||||
const int value = 5;
|
||||
@@ -585,13 +614,13 @@ TEST(ThrowActionTest, ThrowsGivenExceptionInNullaryFunction) {
|
||||
|
||||
class Object {
|
||||
public:
|
||||
virtual ~Object() {}
|
||||
virtual ~Object() = default;
|
||||
virtual void Func() {}
|
||||
};
|
||||
|
||||
class MockObject : public Object {
|
||||
public:
|
||||
~MockObject() override {}
|
||||
~MockObject() override = default;
|
||||
MOCK_METHOD(void, Func, (), (override));
|
||||
};
|
||||
|
||||
@@ -756,34 +785,34 @@ TEST(InvokeArgumentTest, Functor6) {
|
||||
|
||||
// Tests using InvokeArgument with a 7-ary function.
|
||||
TEST(InvokeArgumentTest, Function7) {
|
||||
Action<std::string(std::string(*)(const char*, const char*, const char*,
|
||||
const char*, 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*))>
|
||||
a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7");
|
||||
EXPECT_EQ("1234567", a.Perform(std::make_tuple(&Concat7)));
|
||||
}
|
||||
|
||||
// Tests using InvokeArgument with a 8-ary function.
|
||||
TEST(InvokeArgumentTest, Function8) {
|
||||
Action<std::string(std::string(*)(const char*, const char*, const char*,
|
||||
const char*, const char*, 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*))>
|
||||
a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8");
|
||||
EXPECT_EQ("12345678", a.Perform(std::make_tuple(&Concat8)));
|
||||
}
|
||||
|
||||
// Tests using InvokeArgument with a 9-ary function.
|
||||
TEST(InvokeArgumentTest, Function9) {
|
||||
Action<std::string(std::string(*)(const char*, const char*, const char*,
|
||||
const char*, const char*, const char*,
|
||||
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*))>
|
||||
a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8", "9");
|
||||
EXPECT_EQ("123456789", a.Perform(std::make_tuple(&Concat9)));
|
||||
}
|
||||
|
||||
// Tests using InvokeArgument with a 10-ary function.
|
||||
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*))>
|
||||
a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8", "9", "0");
|
||||
@@ -997,9 +1026,8 @@ TEST(DoAllTest, NoArgs) {
|
||||
|
||||
TEST(DoAllTest, MoveOnlyArgs) {
|
||||
bool ran_first = false;
|
||||
Action<int(std::unique_ptr<int>)> a =
|
||||
DoAll(InvokeWithoutArgs([&] { ran_first = true; }),
|
||||
[](std::unique_ptr<int> p) { return *p; });
|
||||
Action<int(std::unique_ptr<int>)> a = DoAll(
|
||||
[&] { ran_first = true; }, [](std::unique_ptr<int> p) { return *p; });
|
||||
EXPECT_EQ(7, a.Perform(std::make_tuple(std::unique_ptr<int>(new int(7)))));
|
||||
EXPECT_TRUE(ran_first);
|
||||
}
|
||||
|
||||
@@ -11,8 +11,10 @@ namespace internal {
|
||||
namespace gmockpp {
|
||||
|
||||
static_assert(GMOCK_PP_CAT(1, 4) == 14, "");
|
||||
static_assert(GMOCK_PP_INTERNAL_INTERNAL_16TH(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
|
||||
12, 13, 14, 15, 16, 17, 18) == 16,
|
||||
static_assert(GMOCK_PP_INTERNAL_INTERNAL_32ND(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
|
||||
12, 13, 14, 15, 16, 17, 18, 19,
|
||||
20, 21, 22, 23, 24, 25, 26, 27,
|
||||
28, 29, 30, 31, 32, 33, 34) == 32,
|
||||
"");
|
||||
static_assert(GMOCK_PP_NARG() == 1, "");
|
||||
static_assert(GMOCK_PP_NARG(x) == 1, "");
|
||||
|
||||
@@ -160,7 +160,7 @@ class MockCC : public CC {
|
||||
// Tests that a method with expanded name compiles.
|
||||
TEST(OnCallSyntaxTest, CompilesWithMethodNameExpandedFromMacro) {
|
||||
MockCC cc;
|
||||
ON_CALL(cc, Method());
|
||||
(void)ON_CALL(cc, Method());
|
||||
}
|
||||
|
||||
// Tests that the method with expanded name not only compiles but runs
|
||||
@@ -193,7 +193,7 @@ TEST(OnCallSyntaxTest, EvaluatesFirstArgumentOnce) {
|
||||
MockA a;
|
||||
MockA* pa = &a;
|
||||
|
||||
ON_CALL(*pa++, DoA(_));
|
||||
(void)ON_CALL(*pa++, DoA(_));
|
||||
EXPECT_EQ(&a + 1, pa);
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ TEST(OnCallSyntaxTest, EvaluatesSecondArgumentOnce) {
|
||||
MockA a;
|
||||
int n = 0;
|
||||
|
||||
ON_CALL(a, DoA(n++));
|
||||
(void)ON_CALL(a, DoA(n++));
|
||||
EXPECT_EQ(1, n);
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ TEST(OnCallSyntaxTest, WillByDefaultIsMandatory) {
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED(
|
||||
{
|
||||
ON_CALL(a, DoA(5));
|
||||
(void)ON_CALL(a, DoA(5));
|
||||
a.DoA(5);
|
||||
},
|
||||
"");
|
||||
@@ -804,9 +804,8 @@ TEST(ExpectCallTest, InfersCardinality1WhenThereIsWillRepeatedly) {
|
||||
"to be called at least once");
|
||||
}
|
||||
|
||||
#if defined(GTEST_INTERNAL_CPLUSPLUS_LANG) && \
|
||||
GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L
|
||||
|
||||
// TODO(b/396121064) - Fix this test under MSVC
|
||||
#ifndef _MSC_VER
|
||||
// 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
|
||||
// from a prvalue returned from a function.
|
||||
@@ -847,7 +846,7 @@ TEST(ExpectCallTest, NonMoveableType) {
|
||||
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
|
||||
// invocation.
|
||||
@@ -2046,7 +2045,7 @@ class GMockVerboseFlagTest : public VerboseFlagPreservingFixture {
|
||||
NaggyMock<MockA> a;
|
||||
const std::string note =
|
||||
"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. "
|
||||
"See "
|
||||
"https://github.com/google/googletest/blob/main/docs/"
|
||||
|
||||
@@ -327,7 +327,7 @@ TEST(LinkTest, TestInvoke) {
|
||||
InvokeHelper test_invoke_helper;
|
||||
|
||||
EXPECT_CALL(mock, VoidFromString(_))
|
||||
.WillOnce(Invoke(&InvokeHelper::StaticVoidFromString))
|
||||
.WillOnce(&InvokeHelper::StaticVoidFromString)
|
||||
.WillOnce(Invoke(&test_invoke_helper, &InvokeHelper::VoidFromString));
|
||||
mock.VoidFromString(nullptr);
|
||||
mock.VoidFromString(nullptr);
|
||||
@@ -338,10 +338,12 @@ TEST(LinkTest, TestInvokeWithoutArgs) {
|
||||
Mock mock;
|
||||
InvokeHelper test_invoke_helper;
|
||||
|
||||
GTEST_DISABLE_DEPRECATED_PUSH_()
|
||||
EXPECT_CALL(mock, VoidFromString(_))
|
||||
.WillOnce(InvokeWithoutArgs(&InvokeHelper::StaticVoidFromVoid))
|
||||
.WillOnce(&InvokeHelper::StaticVoidFromVoid)
|
||||
.WillOnce(
|
||||
InvokeWithoutArgs(&test_invoke_helper, &InvokeHelper::VoidFromVoid));
|
||||
GTEST_DISABLE_DEPRECATED_POP_()
|
||||
mock.VoidFromString(nullptr);
|
||||
mock.VoidFromString(nullptr);
|
||||
}
|
||||
@@ -360,7 +362,7 @@ TEST(LinkTest, TestWithArg) {
|
||||
Mock mock;
|
||||
|
||||
EXPECT_CALL(mock, VoidFromString(_))
|
||||
.WillOnce(WithArg<0>(Invoke(&InvokeHelper::StaticVoidFromString)));
|
||||
.WillOnce(WithArg<0>(&InvokeHelper::StaticVoidFromString));
|
||||
mock.VoidFromString(nullptr);
|
||||
}
|
||||
|
||||
@@ -369,7 +371,7 @@ TEST(LinkTest, TestWithArgs) {
|
||||
Mock mock;
|
||||
|
||||
EXPECT_CALL(mock, VoidFromString(_))
|
||||
.WillOnce(WithArgs<0>(Invoke(&InvokeHelper::StaticVoidFromString)));
|
||||
.WillOnce(WithArgs<0>(&InvokeHelper::StaticVoidFromString));
|
||||
mock.VoidFromString(nullptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -79,14 +79,14 @@ GMOCK WARNING:
|
||||
Uninteresting mock function call - returning default value.
|
||||
Function call: Bar2(0, 1)
|
||||
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
|
||||
[ RUN ] GMockOutputTest.UninterestingCallToVoidFunction
|
||||
|
||||
GMOCK WARNING:
|
||||
Uninteresting mock function call - returning directly.
|
||||
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
|
||||
[ RUN ] GMockOutputTest.RetiredExpectation
|
||||
unknown file: Failure
|
||||
@@ -283,14 +283,14 @@ Uninteresting mock function call - taking default action specified at:
|
||||
FILE:#:
|
||||
Function call: Bar2(2, 2)
|
||||
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:
|
||||
Uninteresting mock function call - taking default action specified at:
|
||||
FILE:#:
|
||||
Function call: Bar2(1, 1)
|
||||
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
|
||||
[ RUN ] GMockOutputTest.ExplicitActionsRunOutWithDefaultAction
|
||||
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
// Tests that Google Mock constructs can be used in a large number of
|
||||
// threads concurrently.
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
@@ -188,7 +190,7 @@ TEST(StressTest, CanUseGMockWithThreads) {
|
||||
&TestPartiallyOrderedExpectationsWithThreads,
|
||||
};
|
||||
|
||||
const int kRoutines = sizeof(test_routines) / sizeof(test_routines[0]);
|
||||
const int kRoutines = std::size(test_routines);
|
||||
const int kCopiesOfEachRoutine = kMaxTestThreads / kRoutines;
|
||||
const int kTestThreads = kCopiesOfEachRoutine * kRoutines;
|
||||
ThreadWithParam<Dummy>* threads[kTestThreads] = {};
|
||||
|
||||
@@ -87,10 +87,10 @@ TEST(InitGoogleMockTest, ParsesSingleFlag) {
|
||||
|
||||
TEST(InitGoogleMockTest, ParsesMultipleFlags) {
|
||||
int old_default_behavior = GMOCK_FLAG_GET(default_mock_behavior);
|
||||
const wchar_t* argv[] = {L"foo.exe", L"--gmock_verbose=info",
|
||||
L"--gmock_default_mock_behavior=2", nullptr};
|
||||
const char* argv[] = {"foo.exe", "--gmock_verbose=info",
|
||||
"--gmock_default_mock_behavior=2", nullptr};
|
||||
|
||||
const wchar_t* new_argv[] = {L"foo.exe", nullptr};
|
||||
const char* new_argv[] = {"foo.exe", nullptr};
|
||||
|
||||
TestInitGoogleMock(argv, new_argv, "info");
|
||||
EXPECT_EQ(2, GMOCK_FLAG_GET(default_mock_behavior));
|
||||
@@ -115,6 +115,8 @@ TEST(InitGoogleMockTest, ParsesGoogleMockFlagAndUnrecognizedFlag) {
|
||||
TestInitGoogleMock(argv, new_argv, "error");
|
||||
}
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
|
||||
TEST(WideInitGoogleMockTest, ParsesInvalidCommandLine) {
|
||||
const wchar_t* argv[] = {nullptr};
|
||||
|
||||
@@ -168,6 +170,7 @@ TEST(WideInitGoogleMockTest, ParsesGoogleMockFlagAndUnrecognizedFlag) {
|
||||
|
||||
TestInitGoogleMock(argv, new_argv, "error");
|
||||
}
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
|
||||
#endif // !defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
|
||||
|
||||
|
||||
@@ -132,9 +132,6 @@ if(GTEST_HAS_ABSL)
|
||||
absl::flags_reflection
|
||||
absl::flags_usage
|
||||
absl::strings
|
||||
absl::any
|
||||
absl::optional
|
||||
absl::variant
|
||||
re2::re2
|
||||
)
|
||||
endif()
|
||||
@@ -143,10 +140,10 @@ set_target_properties(gtest_main PROPERTIES VERSION ${GOOGLETEST_VERSION})
|
||||
string(REPLACE ";" "$<SEMICOLON>" dirs "${gtest_build_include_dirs}")
|
||||
target_include_directories(gtest SYSTEM INTERFACE
|
||||
"$<BUILD_INTERFACE:${dirs}>"
|
||||
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
|
||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
|
||||
target_include_directories(gtest_main SYSTEM INTERFACE
|
||||
"$<BUILD_INTERFACE:${dirs}>"
|
||||
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
|
||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "QNX" AND CMAKE_SYSTEM_VERSION VERSION_GREATER_EQUAL 7.1)
|
||||
target_link_libraries(gtest PUBLIC regex)
|
||||
endif()
|
||||
|
||||
@@ -25,7 +25,7 @@ When building GoogleTest as a standalone project, the typical workflow starts
|
||||
with
|
||||
|
||||
```
|
||||
git clone https://github.com/google/googletest.git -b v1.15.2
|
||||
git clone https://github.com/google/googletest.git -b v1.18.0
|
||||
cd googletest # Main directory of the cloned repository.
|
||||
mkdir build # Create a directory to hold the build output.
|
||||
cd build
|
||||
@@ -124,9 +124,9 @@ match the project in which it is included.
|
||||
|
||||
#### 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
|
||||
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
|
||||
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.
|
||||
@@ -145,9 +145,9 @@ We list the most frequently used macros below. For a complete list, see file
|
||||
### Multi-threaded Tests
|
||||
|
||||
GoogleTest is thread-safe where the pthread library is available. After
|
||||
`#include <gtest/gtest.h>`, you can check the
|
||||
`GTEST_IS_THREADSAFE` macro to see whether this is the case (yes if the macro is
|
||||
`#defined` to 1, no if it's undefined.).
|
||||
`#include <gtest/gtest.h>`, you can check the `GTEST_IS_THREADSAFE` macro to see
|
||||
whether this is the case (yes if the macro is `#defined` to 1, no if it's
|
||||
undefined.).
|
||||
|
||||
If GoogleTest doesn't correctly detect whether pthread is available in your
|
||||
environment, you can force it with
|
||||
|
||||
@@ -28,28 +28,19 @@ macro(fix_default_compiler_settings_)
|
||||
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
|
||||
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
|
||||
if (NOT BUILD_SHARED_LIBS AND NOT gtest_force_shared_crt)
|
||||
# When Google Test is built as a shared library, it should also use
|
||||
# shared runtime libraries. Otherwise, it may end up with multiple
|
||||
# copies of runtime library data in different modules, resulting in
|
||||
# hard-to-find crashes. When it is built as a static library, it is
|
||||
# preferable to use CRT as static libraries, as we don't have to rely
|
||||
# on CRT DLLs being available. CMake always defaults to using shared
|
||||
# CRT libraries, so we override that default here.
|
||||
string(REPLACE "/MD" "-MT" ${flag_var} "${${flag_var}}")
|
||||
|
||||
# When using Ninja with Clang, static builds pass -D_DLL on Windows.
|
||||
# This is incorrect and should not happen, so we fix that here.
|
||||
string(REPLACE "-D_DLL" "" ${flag_var} "${${flag_var}}")
|
||||
string(REGEX REPLACE "([/-])D_DLL" "" ${flag_var} "${${flag_var}}")
|
||||
endif()
|
||||
|
||||
# We prefer more strict warning checking for building Google Test.
|
||||
# Replaces /W3 with /W4 in defaults.
|
||||
string(REPLACE "/W3" "/W4" ${flag_var} "${${flag_var}}")
|
||||
string(REGEX REPLACE "([/-])W3" "\\1W4" ${flag_var} "${${flag_var}}")
|
||||
|
||||
# Prevent D9025 warning for targets that have exception handling
|
||||
# turned off (/EHs-c- flag). Where required, exceptions are explicitly
|
||||
# re-enabled using the cxx_exception_flags variable.
|
||||
string(REPLACE "/EHsc" "" ${flag_var} "${${flag_var}}")
|
||||
string(REGEX REPLACE "([/-])EHsc" "" ${flag_var} "${${flag_var}}")
|
||||
endforeach()
|
||||
endif()
|
||||
endmacro()
|
||||
@@ -63,6 +54,7 @@ macro(config_compiler_and_linker)
|
||||
unset(GTEST_HAS_PTHREAD)
|
||||
if (NOT gtest_disable_pthreads AND NOT MINGW)
|
||||
# Defines CMAKE_USE_PTHREADS_INIT and CMAKE_THREAD_LIBS_INIT.
|
||||
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
|
||||
find_package(Threads)
|
||||
if (CMAKE_USE_PTHREADS_INIT)
|
||||
set(GTEST_HAS_PTHREAD ON)
|
||||
@@ -70,10 +62,23 @@ macro(config_compiler_and_linker)
|
||||
endif()
|
||||
|
||||
fix_default_compiler_settings_()
|
||||
set(cxx_strict_flags "")
|
||||
if (MSVC)
|
||||
# When Google Test is built as a shared library, it should also use shared
|
||||
# runtime libraries. Otherwise, it may end up with multiple copies of
|
||||
# runtime library data in different modules, resulting in hard-to-find
|
||||
# crashes. When it is built as a static library, it is preferable to use CRT
|
||||
# as static libraries, as we don't have to rely on CRT DLLs being available.
|
||||
# CMake always defaults to using shared CRT libraries, so we override that
|
||||
# default here.
|
||||
if (NOT BUILD_SHARED_LIBS AND NOT gtest_force_shared_crt AND NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY
|
||||
AND CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
endif()
|
||||
|
||||
# Newlines inside flags variables break CMake's NMake generator.
|
||||
# TODO(vladl@google.com): Add -RTCs and -RTCu to debug builds.
|
||||
set(cxx_base_flags "-GS -W4 -WX -wd4251 -wd4275 -nologo -J")
|
||||
set(cxx_base_flags "-GS -W4 -wd4251 -wd4275 -nologo -J")
|
||||
set(cxx_base_flags "${cxx_base_flags} -D_UNICODE -DUNICODE -DWIN32 -D_WIN32")
|
||||
set(cxx_base_flags "${cxx_base_flags} -DSTRICT -DWIN32_LEAN_AND_MEAN")
|
||||
set(cxx_exception_flags "-EHsc -D_HAS_EXCEPTIONS=1")
|
||||
@@ -100,7 +105,12 @@ macro(config_compiler_and_linker)
|
||||
set(cxx_strict_flags "${cxx_strict_flags} -Wchar-subscripts")
|
||||
endif()
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM")
|
||||
set(cxx_base_flags "${cxx_base_flags} -Wno-implicit-float-size-conversion -ffp-model=precise")
|
||||
set(cxx_base_flags "${cxx_base_flags} -ffp-model=precise")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 2025.2.0)
|
||||
set(cxx_base_flags "${cxx_base_flags} -Wno-implicit-float-size-conversion")
|
||||
else()
|
||||
set(cxx_base_flags "${cxx_base_flags} -Wno-sycl-implicit-float-size-conversion")
|
||||
endif()
|
||||
endif()
|
||||
elseif (CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(cxx_base_flags "-Wall -Wshadow -Wundef")
|
||||
@@ -185,17 +195,25 @@ function(cxx_library_with_type name type cxx_flags)
|
||||
COMPILE_PDB_NAME_DEBUG "${name}${pdb_debug_postfix}")
|
||||
|
||||
if (BUILD_SHARED_LIBS OR type STREQUAL "SHARED")
|
||||
set_target_properties(${name}
|
||||
PROPERTIES
|
||||
COMPILE_DEFINITIONS "GTEST_CREATE_SHARED_LIBRARY=1")
|
||||
target_compile_definitions(${name} PRIVATE
|
||||
"GTEST_CREATE_SHARED_LIBRARY=1")
|
||||
target_compile_definitions(${name} INTERFACE
|
||||
$<INSTALL_INTERFACE:GTEST_LINKED_AS_SHARED_LIBRARY=1>)
|
||||
$<BUILD_INTERFACE:GTEST_LINKED_AS_SHARED_LIBRARY=1>
|
||||
$<INSTALL_INTERFACE:GTEST_LINKED_AS_SHARED_LIBRARY=1>
|
||||
)
|
||||
if(APPLE)
|
||||
set_target_properties(${name} PROPERTIES
|
||||
INSTALL_RPATH "@loader_path")
|
||||
elseif(UNIX)
|
||||
set_target_properties(${name} PROPERTIES
|
||||
INSTALL_RPATH "$ORIGIN")
|
||||
endif()
|
||||
endif()
|
||||
if (DEFINED GTEST_HAS_PTHREAD)
|
||||
target_link_libraries(${name} PUBLIC Threads::Threads)
|
||||
endif()
|
||||
|
||||
target_compile_features(${name} PUBLIC cxx_std_14)
|
||||
target_compile_features(${name} PUBLIC cxx_std_17)
|
||||
endfunction()
|
||||
|
||||
########################################################################
|
||||
@@ -226,9 +244,8 @@ function(cxx_executable_with_flags name cxx_flags libs)
|
||||
COMPILE_FLAGS "${cxx_flags}")
|
||||
endif()
|
||||
if (BUILD_SHARED_LIBS)
|
||||
set_target_properties(${name}
|
||||
PROPERTIES
|
||||
COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1")
|
||||
target_compile_definitions(${name} PRIVATE
|
||||
"GTEST_LINKED_AS_SHARED_LIBRARY=1")
|
||||
endif()
|
||||
# To support mixing linking in static and dynamic libraries, link each
|
||||
# library in with an extra call to target_link_libraries.
|
||||
@@ -248,7 +265,12 @@ function(cxx_executable name dir libs)
|
||||
endfunction()
|
||||
|
||||
if(gtest_build_tests)
|
||||
find_package(Python3)
|
||||
# Only the interpreter is needed for Python tests. Specifying the component
|
||||
# explicitly avoids a crash in CMake <= 3.23's FindPython3 module when no
|
||||
# Python installation is present (the module calls list(GET) on an empty
|
||||
# list). QUIET lets the build continue without Python tests instead of
|
||||
# failing outright.
|
||||
find_package(Python3 COMPONENTS Interpreter QUIET)
|
||||
endif()
|
||||
|
||||
# cxx_test_with_flags(name cxx_flags libs srcs...)
|
||||
@@ -313,11 +335,15 @@ function(install_project)
|
||||
foreach(t ${ARGN})
|
||||
get_target_property(t_pdb_name ${t} COMPILE_PDB_NAME)
|
||||
get_target_property(t_pdb_name_debug ${t} COMPILE_PDB_NAME_DEBUG)
|
||||
get_target_property(t_pdb_output_directory ${t} PDB_OUTPUT_DIRECTORY)
|
||||
get_target_property(t_pdb_output_directory ${t} COMPILE_PDB_OUTPUT_DIRECTORY)
|
||||
get_target_property(t_shared_pdb_name ${t} PDB_NAME)
|
||||
get_target_property(t_shared_pdb_name_debug ${t} PDB_NAME_DEBUG)
|
||||
get_target_property(t_shared_pdb_output_directory ${t} PDB_OUTPUT_DIRECTORY)
|
||||
install(FILES
|
||||
"${t_pdb_output_directory}/\${CMAKE_INSTALL_CONFIG_NAME}/$<$<CONFIG:Debug>:${t_pdb_name_debug}>$<$<NOT:$<CONFIG:Debug>>:${t_pdb_name}>.pdb"
|
||||
"$<$<STREQUAL:$<TARGET_PROPERTY:${t},TYPE>,STATIC_LIBRARY>:${t_pdb_output_directory}/\${CMAKE_INSTALL_CONFIG_NAME}/$<IF:$<CONFIG:Debug>,${t_pdb_name_debug},${t_pdb_name}>.pdb>"
|
||||
"$<$<STREQUAL:$<TARGET_PROPERTY:${t},TYPE>,SHARED_LIBRARY>:${t_shared_pdb_output_directory}/\${CMAKE_INSTALL_CONFIG_NAME}/$<IF:$<CONFIG:Debug>,${t_shared_pdb_name_debug},${t_shared_pdb_name}>.pdb>"
|
||||
COMPONENT "${PROJECT_NAME}"
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
DESTINATION $<IF:$<STREQUAL:$<TARGET_PROPERTY:${t},TYPE>,STATIC_LIBRARY>,${CMAKE_INSTALL_LIBDIR},${CMAKE_INSTALL_BINDIR}>
|
||||
OPTIONAL)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
@@ -129,8 +129,15 @@ namespace testing {
|
||||
//
|
||||
// Expected: Foo() is even
|
||||
// Actual: it's 5
|
||||
//
|
||||
|
||||
class GTEST_API_ AssertionResult {
|
||||
// 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_ [[nodiscard]] AssertionResult {
|
||||
public:
|
||||
// Copy constructor.
|
||||
// Used in EXPECT_TRUE/FALSE(assertion_result).
|
||||
@@ -151,14 +158,18 @@ class GTEST_API_ AssertionResult {
|
||||
// The second parameter prevents this overload from being considered if
|
||||
// the argument is implicitly convertible to AssertionResult. In that case
|
||||
// we want AssertionResult's copy constructor to be used.
|
||||
template <typename T>
|
||||
explicit AssertionResult(
|
||||
const T& success,
|
||||
typename std::enable_if<
|
||||
!std::is_convertible<T, AssertionResult>::value>::type*
|
||||
/*enabler*/
|
||||
= nullptr)
|
||||
: success_(success) {}
|
||||
template <typename T,
|
||||
std::enable_if_t<!std::is_convertible_v<T, AssertionResult> &&
|
||||
!std::is_trivially_constructible_v<bool, T>,
|
||||
int> = 0>
|
||||
explicit AssertionResult(T&& success) : success_(std::forward<T>(success)) {}
|
||||
|
||||
// Similar to the mutable overload, but for cases where mutability is
|
||||
// unnecessary or problematic (e.g., bitfields).
|
||||
template <typename T,
|
||||
std::enable_if_t<!std::is_convertible_v<const T&, AssertionResult>,
|
||||
int> = 0>
|
||||
explicit AssertionResult(const T& success) : success_(success) {}
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1910 || _MSC_VER >= 1920)
|
||||
GTEST_DISABLE_MSC_WARNINGS_POP_()
|
||||
@@ -220,6 +231,24 @@ class GTEST_API_ AssertionResult {
|
||||
std::unique_ptr< ::std::string> message_;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
// A pair containing the result that an assertion is evaluating, and the
|
||||
// expected result (true, false).
|
||||
//
|
||||
// Contains a conversion operator that indicates whether the two match.
|
||||
struct AssertionResultExpectation {
|
||||
testing::AssertionResult assertion_result;
|
||||
bool expected_result;
|
||||
|
||||
explicit operator bool() const {
|
||||
bool converted(assertion_result);
|
||||
return converted == expected_result;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Makes a successful assertion result.
|
||||
GTEST_API_ AssertionResult AssertionSuccess();
|
||||
|
||||
|
||||
@@ -192,7 +192,7 @@ GTEST_API_ bool InDeathTestChild();
|
||||
// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
|
||||
|
||||
// Tests that an exit code describes a normal exit with a given exit code.
|
||||
class GTEST_API_ ExitedWithCode {
|
||||
class GTEST_API_ [[nodiscard]] ExitedWithCode {
|
||||
public:
|
||||
explicit ExitedWithCode(int exit_code);
|
||||
ExitedWithCode(const ExitedWithCode&) = default;
|
||||
@@ -206,7 +206,7 @@ class GTEST_API_ ExitedWithCode {
|
||||
#if !defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_FUCHSIA)
|
||||
// Tests that an exit code describes an exit due to termination by a
|
||||
// given signal.
|
||||
class GTEST_API_ KilledBySignal {
|
||||
class GTEST_API_ [[nodiscard]] KilledBySignal {
|
||||
public:
|
||||
explicit KilledBySignal(int signum);
|
||||
bool operator()(int exit_status) const;
|
||||
@@ -317,7 +317,7 @@ class GTEST_API_ KilledBySignal {
|
||||
GTEST_LOG_(WARNING) << "Death tests are not supported on this platform.\n" \
|
||||
<< "Statement '" #statement "' cannot be verified."; \
|
||||
} else if (::testing::internal::AlwaysFalse()) { \
|
||||
::testing::internal::MakeDeathTestMatcher(regex_or_matcher); \
|
||||
(void)::testing::internal::MakeDeathTestMatcher(regex_or_matcher); \
|
||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||
terminator; \
|
||||
} else \
|
||||
|
||||
@@ -40,10 +40,12 @@
|
||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
|
||||
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
|
||||
#include "gtest/gtest-printers.h"
|
||||
@@ -75,7 +77,7 @@ namespace testing {
|
||||
// 2. a factory function that creates a Matcher<T> object from a
|
||||
// FooMatcherMatcher.
|
||||
|
||||
class MatchResultListener {
|
||||
class [[nodiscard]] MatchResultListener {
|
||||
public:
|
||||
// Creates a listener object with the given underlying ostream. The
|
||||
// listener does not own the ostream, and does not dereference it
|
||||
@@ -111,7 +113,7 @@ inline MatchResultListener::~MatchResultListener() = default;
|
||||
|
||||
// An instance of a subclass of this knows how to describe itself as a
|
||||
// matcher.
|
||||
class GTEST_API_ MatcherDescriberInterface {
|
||||
class GTEST_API_ [[nodiscard]] MatcherDescriberInterface {
|
||||
public:
|
||||
virtual ~MatcherDescriberInterface() = default;
|
||||
|
||||
@@ -137,7 +139,7 @@ class GTEST_API_ MatcherDescriberInterface {
|
||||
|
||||
// The implementation of a matcher.
|
||||
template <typename T>
|
||||
class MatcherInterface : public MatcherDescriberInterface {
|
||||
class [[nodiscard]] MatcherInterface : public MatcherDescriberInterface {
|
||||
public:
|
||||
// Returns true if and only if the matcher matches x; also explains the
|
||||
// match result to 'listener' if necessary (see the next paragraph), in
|
||||
@@ -180,7 +182,7 @@ class MatcherInterface : public MatcherDescriberInterface {
|
||||
namespace internal {
|
||||
|
||||
// A match result listener that ignores the explanation.
|
||||
class DummyMatchResultListener : public MatchResultListener {
|
||||
class [[nodiscard]] DummyMatchResultListener : public MatchResultListener {
|
||||
public:
|
||||
DummyMatchResultListener() : MatchResultListener(nullptr) {}
|
||||
|
||||
@@ -192,7 +194,7 @@ class DummyMatchResultListener : public MatchResultListener {
|
||||
// A match result listener that forwards the explanation to a given
|
||||
// ostream. The difference between this and MatchResultListener is
|
||||
// that the former is concrete.
|
||||
class StreamMatchResultListener : public MatchResultListener {
|
||||
class [[nodiscard]] StreamMatchResultListener : public MatchResultListener {
|
||||
public:
|
||||
explicit StreamMatchResultListener(::std::ostream* os)
|
||||
: MatchResultListener(os) {}
|
||||
@@ -225,7 +227,7 @@ struct SharedPayload : SharedPayloadBase {
|
||||
// from it. We put functionalities common to all Matcher<T>
|
||||
// specializations here to avoid code duplication.
|
||||
template <typename T>
|
||||
class MatcherBase : private MatcherDescriberInterface {
|
||||
class [[nodiscard]] MatcherBase : private MatcherDescriberInterface {
|
||||
public:
|
||||
// Returns true if and only if the matcher matches x; also explains the
|
||||
// match result to 'listener'.
|
||||
@@ -276,8 +278,8 @@ class MatcherBase : private MatcherDescriberInterface {
|
||||
Init(impl);
|
||||
}
|
||||
|
||||
template <typename M, typename = typename std::remove_reference<
|
||||
M>::type::is_gtest_matcher>
|
||||
template <typename M,
|
||||
typename = typename std::remove_reference_t<M>::is_gtest_matcher>
|
||||
MatcherBase(M&& m) : vtable_(nullptr), buffer_() { // NOLINT
|
||||
Init(std::forward<M>(m));
|
||||
}
|
||||
@@ -296,12 +298,12 @@ class MatcherBase : private MatcherDescriberInterface {
|
||||
return *this;
|
||||
}
|
||||
|
||||
MatcherBase(MatcherBase&& other)
|
||||
MatcherBase(MatcherBase&& other) noexcept
|
||||
: vtable_(other.vtable_), buffer_(other.buffer_) {
|
||||
other.vtable_ = nullptr;
|
||||
}
|
||||
|
||||
MatcherBase& operator=(MatcherBase&& other) {
|
||||
MatcherBase& operator=(MatcherBase&& other) noexcept {
|
||||
if (this == &other) return *this;
|
||||
Destroy();
|
||||
vtable_ = other.vtable_;
|
||||
@@ -362,11 +364,10 @@ class MatcherBase : private MatcherDescriberInterface {
|
||||
// from the impl, but some users really want to get their impl back when
|
||||
// they call GetDescriber().
|
||||
// We use std::get on a tuple as a workaround of not having `if constexpr`.
|
||||
return std::get<(
|
||||
std::is_convertible<decltype(&P::Get(m)),
|
||||
const MatcherDescriberInterface*>::value
|
||||
? 1
|
||||
: 0)>(std::make_tuple(&m, &P::Get(m)));
|
||||
return std::get<(std::is_convertible_v<decltype(&P::Get(m)),
|
||||
const MatcherDescriberInterface*>
|
||||
? 1
|
||||
: 0)>(std::make_tuple(&m, &P::Get(m)));
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
@@ -395,8 +396,8 @@ class MatcherBase : private MatcherDescriberInterface {
|
||||
template <typename M>
|
||||
static constexpr bool IsInlined() {
|
||||
return sizeof(M) <= sizeof(Buffer) && alignof(M) <= alignof(Buffer) &&
|
||||
std::is_trivially_copy_constructible<M>::value &&
|
||||
std::is_trivially_destructible<M>::value;
|
||||
std::is_trivially_copy_constructible_v<M> &&
|
||||
std::is_trivially_destructible_v<M>;
|
||||
}
|
||||
|
||||
template <typename M, bool = MatcherBase::IsInlined<M>()>
|
||||
@@ -443,7 +444,7 @@ class MatcherBase : private MatcherDescriberInterface {
|
||||
|
||||
template <typename M>
|
||||
void Init(M&& m) {
|
||||
using MM = typename std::decay<M>::type;
|
||||
using MM = std::decay_t<M>;
|
||||
using Policy = ValuePolicy<MM>;
|
||||
vtable_ = GetVTable<Policy>();
|
||||
Policy::Init(*this, std::forward<M>(m));
|
||||
@@ -460,7 +461,7 @@ class MatcherBase : private MatcherDescriberInterface {
|
||||
// implementation of Matcher<T> is just a std::shared_ptr to const
|
||||
// MatcherInterface<T>. Don't inherit from Matcher!
|
||||
template <typename T>
|
||||
class Matcher : public internal::MatcherBase<T> {
|
||||
class [[nodiscard]] Matcher : public internal::MatcherBase<T> {
|
||||
public:
|
||||
// Constructs a null matcher. Needed for storing Matcher objects in STL
|
||||
// containers. A default-constructed matcher is not yet initialized. You
|
||||
@@ -472,35 +473,42 @@ class Matcher : public internal::MatcherBase<T> {
|
||||
: internal::MatcherBase<T>(impl) {}
|
||||
|
||||
template <typename U>
|
||||
explicit Matcher(
|
||||
const MatcherInterface<U>* impl,
|
||||
typename std::enable_if<!std::is_same<U, const U&>::value>::type* =
|
||||
nullptr)
|
||||
explicit Matcher(const MatcherInterface<U>* impl,
|
||||
std::enable_if_t<!std::is_same_v<U, const U&>>* = nullptr)
|
||||
: internal::MatcherBase<T>(impl) {}
|
||||
|
||||
template <typename M, typename = typename std::remove_reference<
|
||||
M>::type::is_gtest_matcher>
|
||||
template <typename M,
|
||||
typename = typename std::remove_reference_t<M>::is_gtest_matcher>
|
||||
Matcher(M&& m) : internal::MatcherBase<T>(std::forward<M>(m)) {} // NOLINT
|
||||
|
||||
// Implicit constructor here allows people to write
|
||||
// EXPECT_CALL(foo, Bar(5)) instead of EXPECT_CALL(foo, Bar(Eq(5))) sometimes
|
||||
Matcher(T value); // NOLINT
|
||||
|
||||
// Implicit constructor here allows people to write
|
||||
// EXPECT_THAT(foo, nullptr) instead of EXPECT_THAT(foo, IsNull()) for smart
|
||||
// pointer types.
|
||||
//
|
||||
// The second argument is needed to avoid capturing literal '0'.
|
||||
template <typename U>
|
||||
Matcher(U, // NOLINT
|
||||
std::enable_if_t<std::is_same_v<U, std::nullptr_t>>* = nullptr);
|
||||
};
|
||||
|
||||
// The following two specializations allow the user to write str
|
||||
// instead of Eq(str) and "foo" instead of Eq("foo") when a std::string
|
||||
// matcher is expected.
|
||||
template <>
|
||||
class GTEST_API_ Matcher<const std::string&>
|
||||
: public internal::MatcherBase<const std::string&> {
|
||||
class GTEST_API_ [[nodiscard]]
|
||||
Matcher<const std::string&> : public internal::MatcherBase<const std::string&> {
|
||||
public:
|
||||
Matcher() = default;
|
||||
|
||||
explicit Matcher(const MatcherInterface<const std::string&>* impl)
|
||||
: internal::MatcherBase<const std::string&>(impl) {}
|
||||
|
||||
template <typename M, typename = typename std::remove_reference<
|
||||
M>::type::is_gtest_matcher>
|
||||
template <typename M,
|
||||
typename = typename std::remove_reference_t<M>::is_gtest_matcher>
|
||||
Matcher(M&& m) // NOLINT
|
||||
: internal::MatcherBase<const std::string&>(std::forward<M>(m)) {}
|
||||
|
||||
@@ -513,8 +521,8 @@ class GTEST_API_ Matcher<const std::string&>
|
||||
};
|
||||
|
||||
template <>
|
||||
class GTEST_API_ Matcher<std::string>
|
||||
: public internal::MatcherBase<std::string> {
|
||||
class GTEST_API_ [[nodiscard]]
|
||||
Matcher<std::string> : public internal::MatcherBase<std::string> {
|
||||
public:
|
||||
Matcher() = default;
|
||||
|
||||
@@ -523,8 +531,8 @@ class GTEST_API_ Matcher<std::string>
|
||||
explicit Matcher(const MatcherInterface<std::string>* impl)
|
||||
: internal::MatcherBase<std::string>(impl) {}
|
||||
|
||||
template <typename M, typename = typename std::remove_reference<
|
||||
M>::type::is_gtest_matcher>
|
||||
template <typename M,
|
||||
typename = typename std::remove_reference_t<M>::is_gtest_matcher>
|
||||
Matcher(M&& m) // NOLINT
|
||||
: internal::MatcherBase<std::string>(std::forward<M>(m)) {}
|
||||
|
||||
@@ -536,12 +544,11 @@ class GTEST_API_ Matcher<std::string>
|
||||
Matcher(const char* s); // NOLINT
|
||||
};
|
||||
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
// The following two specializations allow the user to write str
|
||||
// instead of Eq(str) and "foo" instead of Eq("foo") when a absl::string_view
|
||||
// instead of Eq(str) and "foo" instead of Eq("foo") when a std::string_view
|
||||
// matcher is expected.
|
||||
template <>
|
||||
class GTEST_API_ Matcher<const internal::StringView&>
|
||||
class GTEST_API_ [[nodiscard]] Matcher<const internal::StringView&>
|
||||
: public internal::MatcherBase<const internal::StringView&> {
|
||||
public:
|
||||
Matcher() = default;
|
||||
@@ -549,8 +556,8 @@ class GTEST_API_ Matcher<const internal::StringView&>
|
||||
explicit Matcher(const MatcherInterface<const internal::StringView&>* impl)
|
||||
: internal::MatcherBase<const internal::StringView&>(impl) {}
|
||||
|
||||
template <typename M, typename = typename std::remove_reference<
|
||||
M>::type::is_gtest_matcher>
|
||||
template <typename M,
|
||||
typename = typename std::remove_reference_t<M>::is_gtest_matcher>
|
||||
Matcher(M&& m) // NOLINT
|
||||
: internal::MatcherBase<const internal::StringView&>(std::forward<M>(m)) {
|
||||
}
|
||||
@@ -562,12 +569,12 @@ class GTEST_API_ Matcher<const internal::StringView&>
|
||||
// Allows the user to write "foo" instead of Eq("foo") sometimes.
|
||||
Matcher(const char* s); // NOLINT
|
||||
|
||||
// Allows the user to pass absl::string_views or std::string_views directly.
|
||||
// Allows the user to pass std::string_views directly.
|
||||
Matcher(internal::StringView s); // NOLINT
|
||||
};
|
||||
|
||||
template <>
|
||||
class GTEST_API_ Matcher<internal::StringView>
|
||||
class GTEST_API_ [[nodiscard]] Matcher<internal::StringView>
|
||||
: public internal::MatcherBase<internal::StringView> {
|
||||
public:
|
||||
Matcher() = default;
|
||||
@@ -577,8 +584,8 @@ class GTEST_API_ Matcher<internal::StringView>
|
||||
explicit Matcher(const MatcherInterface<internal::StringView>* impl)
|
||||
: internal::MatcherBase<internal::StringView>(impl) {}
|
||||
|
||||
template <typename M, typename = typename std::remove_reference<
|
||||
M>::type::is_gtest_matcher>
|
||||
template <typename M,
|
||||
typename = typename std::remove_reference_t<M>::is_gtest_matcher>
|
||||
Matcher(M&& m) // NOLINT
|
||||
: internal::MatcherBase<internal::StringView>(std::forward<M>(m)) {}
|
||||
|
||||
@@ -589,10 +596,9 @@ class GTEST_API_ Matcher<internal::StringView>
|
||||
// Allows the user to write "foo" instead of Eq("foo") sometimes.
|
||||
Matcher(const char* s); // NOLINT
|
||||
|
||||
// Allows the user to pass absl::string_views or std::string_views directly.
|
||||
// Allows the user to pass std::string_views directly.
|
||||
Matcher(internal::StringView s); // NOLINT
|
||||
};
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
// Prints a matcher in a human-readable format.
|
||||
template <typename T>
|
||||
@@ -614,7 +620,7 @@ std::ostream& operator<<(std::ostream& os, const Matcher<T>& matcher) {
|
||||
//
|
||||
// See the definition of NotNull() for a complete example.
|
||||
template <class Impl>
|
||||
class PolymorphicMatcher {
|
||||
class [[nodiscard]] PolymorphicMatcher {
|
||||
public:
|
||||
explicit PolymorphicMatcher(const Impl& an_impl) : impl_(an_impl) {}
|
||||
|
||||
@@ -689,7 +695,7 @@ namespace internal {
|
||||
// The following template definition assumes that the Rhs parameter is
|
||||
// a "bare" type (i.e. neither 'const T' nor 'T&').
|
||||
template <typename D, typename Rhs, typename Op>
|
||||
class ComparisonBase {
|
||||
class [[nodiscard]] ComparisonBase {
|
||||
public:
|
||||
explicit ComparisonBase(const Rhs& rhs) : rhs_(rhs) {}
|
||||
|
||||
@@ -722,7 +728,8 @@ class ComparisonBase {
|
||||
};
|
||||
|
||||
template <typename Rhs>
|
||||
class EqMatcher : public ComparisonBase<EqMatcher<Rhs>, Rhs, std::equal_to<>> {
|
||||
class [[nodiscard]] EqMatcher
|
||||
: public ComparisonBase<EqMatcher<Rhs>, Rhs, std::equal_to<>> {
|
||||
public:
|
||||
explicit EqMatcher(const Rhs& rhs)
|
||||
: ComparisonBase<EqMatcher<Rhs>, Rhs, std::equal_to<>>(rhs) {}
|
||||
@@ -730,7 +737,7 @@ class EqMatcher : public ComparisonBase<EqMatcher<Rhs>, Rhs, std::equal_to<>> {
|
||||
static const char* NegatedDesc() { return "isn't equal to"; }
|
||||
};
|
||||
template <typename Rhs>
|
||||
class NeMatcher
|
||||
class [[nodiscard]] NeMatcher
|
||||
: public ComparisonBase<NeMatcher<Rhs>, Rhs, std::not_equal_to<>> {
|
||||
public:
|
||||
explicit NeMatcher(const Rhs& rhs)
|
||||
@@ -739,7 +746,8 @@ class NeMatcher
|
||||
static const char* NegatedDesc() { return "is equal to"; }
|
||||
};
|
||||
template <typename Rhs>
|
||||
class LtMatcher : public ComparisonBase<LtMatcher<Rhs>, Rhs, std::less<>> {
|
||||
class [[nodiscard]] LtMatcher
|
||||
: public ComparisonBase<LtMatcher<Rhs>, Rhs, std::less<>> {
|
||||
public:
|
||||
explicit LtMatcher(const Rhs& rhs)
|
||||
: ComparisonBase<LtMatcher<Rhs>, Rhs, std::less<>>(rhs) {}
|
||||
@@ -747,7 +755,8 @@ class LtMatcher : public ComparisonBase<LtMatcher<Rhs>, Rhs, std::less<>> {
|
||||
static const char* NegatedDesc() { return "isn't <"; }
|
||||
};
|
||||
template <typename Rhs>
|
||||
class GtMatcher : public ComparisonBase<GtMatcher<Rhs>, Rhs, std::greater<>> {
|
||||
class [[nodiscard]] GtMatcher
|
||||
: public ComparisonBase<GtMatcher<Rhs>, Rhs, std::greater<>> {
|
||||
public:
|
||||
explicit GtMatcher(const Rhs& rhs)
|
||||
: ComparisonBase<GtMatcher<Rhs>, Rhs, std::greater<>>(rhs) {}
|
||||
@@ -755,7 +764,7 @@ class GtMatcher : public ComparisonBase<GtMatcher<Rhs>, Rhs, std::greater<>> {
|
||||
static const char* NegatedDesc() { return "isn't >"; }
|
||||
};
|
||||
template <typename Rhs>
|
||||
class LeMatcher
|
||||
class [[nodiscard]] LeMatcher
|
||||
: public ComparisonBase<LeMatcher<Rhs>, Rhs, std::less_equal<>> {
|
||||
public:
|
||||
explicit LeMatcher(const Rhs& rhs)
|
||||
@@ -764,7 +773,7 @@ class LeMatcher
|
||||
static const char* NegatedDesc() { return "isn't <="; }
|
||||
};
|
||||
template <typename Rhs>
|
||||
class GeMatcher
|
||||
class [[nodiscard]] GeMatcher
|
||||
: public ComparisonBase<GeMatcher<Rhs>, Rhs, std::greater_equal<>> {
|
||||
public:
|
||||
explicit GeMatcher(const Rhs& rhs)
|
||||
@@ -773,24 +782,68 @@ class GeMatcher
|
||||
static const char* NegatedDesc() { return "isn't >="; }
|
||||
};
|
||||
|
||||
template <typename T, typename = typename std::enable_if<
|
||||
std::is_constructible<std::string, T>::value>::type>
|
||||
using StringLike = 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 [[nodiscard]] 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_;
|
||||
};
|
||||
|
||||
// Dummy function (never defined) whose return type evaluates to std::string if
|
||||
// the given type is a string-like type that can be converted to std::string,
|
||||
// either directly or through an intermediate std::string_view.
|
||||
template <class T>
|
||||
extern std::enable_if_t<std::is_constructible_v<std::string, T>, std::string>
|
||||
ResolveAsString(const void* /* preferred */);
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
// Same as above, but for std::wstring. In cases where both conversions are
|
||||
// possible, this overload takes lower priority.
|
||||
template <class T>
|
||||
extern std::enable_if_t<std::is_constructible_v<std::wstring, T>, std::wstring>
|
||||
ResolveAsString(... /* fallback */);
|
||||
#endif
|
||||
|
||||
// Evaluates to the std::basic_string type that the given string-like type can
|
||||
// be converted to. Prefers std::string over std::wstring if both are possible.
|
||||
// Fails in a SFINAE-friendly way if no conversion was viable.
|
||||
template <typename T>
|
||||
using StringType = decltype(ResolveAsString<T>(nullptr));
|
||||
|
||||
// Implements polymorphic matchers MatchesRegex(regex) and
|
||||
// ContainsRegex(regex), which can be used as a Matcher<T> as long as
|
||||
// T can be converted to a string.
|
||||
class MatchesRegexMatcher {
|
||||
class [[nodiscard]] MatchesRegexMatcher {
|
||||
public:
|
||||
MatchesRegexMatcher(const RE* regex, bool full_match)
|
||||
: regex_(regex), full_match_(full_match) {}
|
||||
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
bool MatchAndExplain(const internal::StringView& s,
|
||||
MatchResultListener* listener) const {
|
||||
return MatchAndExplain(std::string(s), listener);
|
||||
}
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
// Accepts pointer types, particularly:
|
||||
// const char*
|
||||
@@ -805,7 +858,7 @@ class MatchesRegexMatcher {
|
||||
// Matches anything that can convert to std::string.
|
||||
//
|
||||
// This is a template, not just a plain function with const std::string&,
|
||||
// because absl::string_view has some interfering non-explicit constructors.
|
||||
// because std::string_view has some interfering non-explicit constructors.
|
||||
template <class MatcheeStringType>
|
||||
bool MatchAndExplain(const MatcheeStringType& s,
|
||||
MatchResultListener* /* listener */) const {
|
||||
@@ -838,9 +891,10 @@ inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
|
||||
return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, true));
|
||||
}
|
||||
template <typename T = std::string>
|
||||
PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
|
||||
const internal::StringLike<T>& regex) {
|
||||
return MatchesRegex(new internal::RE(std::string(regex)));
|
||||
std::enable_if_t<std::is_constructible_v<internal::RE, internal::StringType<T>>,
|
||||
PolymorphicMatcher<internal::MatchesRegexMatcher>>
|
||||
MatchesRegex(const T& regex) {
|
||||
return MatchesRegex(new internal::RE(internal::StringType<T>(regex)));
|
||||
}
|
||||
|
||||
// Matches a string that contains regular expression 'regex'.
|
||||
@@ -850,9 +904,10 @@ inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
|
||||
return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false));
|
||||
}
|
||||
template <typename T = std::string>
|
||||
PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
|
||||
const internal::StringLike<T>& regex) {
|
||||
return ContainsRegex(new internal::RE(std::string(regex)));
|
||||
std::enable_if_t<std::is_constructible_v<internal::RE, internal::StringType<T>>,
|
||||
PolymorphicMatcher<internal::MatchesRegexMatcher>>
|
||||
ContainsRegex(const T& regex) {
|
||||
return ContainsRegex(new internal::RE(internal::StringType<T>(regex)));
|
||||
}
|
||||
|
||||
// Creates a polymorphic matcher that matches anything equal to x.
|
||||
@@ -863,13 +918,21 @@ inline internal::EqMatcher<T> Eq(T x) {
|
||||
return internal::EqMatcher<T>(x);
|
||||
}
|
||||
|
||||
// Constructs a Matcher<T> from a 'value' of type T. The constructed
|
||||
// Constructs a Matcher<T> from a 'value' of type T. The constructed
|
||||
// matcher matches any value that's equal to 'value'.
|
||||
template <typename T>
|
||||
Matcher<T>::Matcher(T value) {
|
||||
*this = Eq(value);
|
||||
}
|
||||
|
||||
// Constructs a Matcher<T> from nullptr. The constructed matcher matches any
|
||||
// value that is equal to nullptr.
|
||||
template <typename T>
|
||||
template <typename U>
|
||||
Matcher<T>::Matcher(U, std::enable_if_t<std::is_same_v<U, std::nullptr_t>>*) {
|
||||
*this = Eq(nullptr);
|
||||
}
|
||||
|
||||
// Creates a monomorphic matcher that matches anything with type Lhs
|
||||
// and equal to rhs. A user may need to use this instead of Eq(...)
|
||||
// in order to resolve an overloading ambiguity.
|
||||
|
||||
@@ -129,7 +129,7 @@ class GTEST_API_ Message {
|
||||
int>::type = 0
|
||||
#endif // GTEST_HAS_ABSL
|
||||
>
|
||||
inline Message& operator<<(const T& val) {
|
||||
Message& operator<<(const T& val) {
|
||||
// Some libraries overload << for STL containers. These
|
||||
// overloads are defined in the global namespace instead of ::std.
|
||||
//
|
||||
@@ -155,7 +155,7 @@ class GTEST_API_ Message {
|
||||
template <typename T,
|
||||
typename std::enable_if<absl::HasAbslStringify<T>::value, // NOLINT
|
||||
int>::type = 0>
|
||||
inline Message& operator<<(const T& val) {
|
||||
Message& operator<<(const T& val) {
|
||||
// ::operator<< is needed here for a similar reason as with the non-Abseil
|
||||
// version above
|
||||
using ::operator<<;
|
||||
|
||||
@@ -174,6 +174,7 @@ TEST_P(DerivedTest, DoesBlah) {
|
||||
|
||||
#endif // 0
|
||||
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
|
||||
@@ -413,7 +414,8 @@ internal::CartesianProductHolder<Generator...> Combine(const Generator&... g) {
|
||||
// Synopsis:
|
||||
// ConvertGenerator<T>(gen)
|
||||
// - 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
|
||||
// parameters in a custom type instead of std::tuple
|
||||
@@ -441,10 +443,65 @@ internal::CartesianProductHolder<Generator...> Combine(const Generator&... g) {
|
||||
// Combine(Values("cat", "dog"),
|
||||
// Values(BLACK, WHITE))));
|
||||
//
|
||||
template <typename T>
|
||||
internal::ParamConverterGenerator<T> ConvertGenerator(
|
||||
internal::ParamGenerator<T> gen) {
|
||||
return internal::ParamConverterGenerator<T>(gen);
|
||||
template <typename RequestedT>
|
||||
internal::ParamConverterGenerator<RequestedT> ConvertGenerator(
|
||||
internal::ParamGenerator<RequestedT> 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) \
|
||||
@@ -469,7 +526,7 @@ internal::ParamConverterGenerator<T> ConvertGenerator(
|
||||
::testing::internal::CodeLocation(__FILE__, __LINE__)); \
|
||||
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, \
|
||||
test_name)::gtest_registering_dummy_ = \
|
||||
@@ -493,39 +550,38 @@ internal::ParamConverterGenerator<T> ConvertGenerator(
|
||||
#define GTEST_GET_FIRST_(first, ...) first
|
||||
#define GTEST_GET_SECOND_(first, second, ...) second
|
||||
|
||||
#define INSTANTIATE_TEST_SUITE_P(prefix, test_suite_name, ...) \
|
||||
static ::testing::internal::ParamGenerator<test_suite_name::ParamType> \
|
||||
gtest_##prefix##test_suite_name##_EvalGenerator_() { \
|
||||
return GTEST_EXPAND_(GTEST_GET_FIRST_(__VA_ARGS__, DUMMY_PARAM_)); \
|
||||
} \
|
||||
static ::std::string gtest_##prefix##test_suite_name##_EvalGenerateName_( \
|
||||
const ::testing::TestParamInfo<test_suite_name::ParamType>& info) { \
|
||||
if (::testing::internal::AlwaysFalse()) { \
|
||||
::testing::internal::TestNotEmpty(GTEST_EXPAND_(GTEST_GET_SECOND_( \
|
||||
__VA_ARGS__, \
|
||||
::testing::internal::DefaultParamName<test_suite_name::ParamType>, \
|
||||
DUMMY_PARAM_))); \
|
||||
auto t = std::make_tuple(__VA_ARGS__); \
|
||||
static_assert(std::tuple_size<decltype(t)>::value <= 2, \
|
||||
"Too Many Args!"); \
|
||||
} \
|
||||
return ((GTEST_EXPAND_(GTEST_GET_SECOND_( \
|
||||
__VA_ARGS__, \
|
||||
::testing::internal::DefaultParamName<test_suite_name::ParamType>, \
|
||||
DUMMY_PARAM_))))(info); \
|
||||
} \
|
||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static int \
|
||||
gtest_##prefix##test_suite_name##_dummy_ = \
|
||||
::testing::UnitTest::GetInstance() \
|
||||
->parameterized_test_registry() \
|
||||
.GetTestSuitePatternHolder<test_suite_name>( \
|
||||
GTEST_STRINGIFY_(test_suite_name), \
|
||||
::testing::internal::CodeLocation(__FILE__, __LINE__)) \
|
||||
->AddTestSuiteInstantiation( \
|
||||
GTEST_STRINGIFY_(prefix), \
|
||||
>est_##prefix##test_suite_name##_EvalGenerator_, \
|
||||
>est_##prefix##test_suite_name##_EvalGenerateName_, \
|
||||
__FILE__, __LINE__)
|
||||
#define INSTANTIATE_TEST_SUITE_P(prefix, test_suite_name, ...) \
|
||||
static ::testing::internal::ParamGenerator<test_suite_name::ParamType> \
|
||||
gtest_##prefix##test_suite_name##_EvalGenerator_() { \
|
||||
return GTEST_EXPAND_(GTEST_GET_FIRST_(__VA_ARGS__, DUMMY_PARAM_)); \
|
||||
} \
|
||||
static ::std::string gtest_##prefix##test_suite_name##_EvalGenerateName_( \
|
||||
const ::testing::TestParamInfo<test_suite_name::ParamType>& info) { \
|
||||
if (::testing::internal::AlwaysFalse()) { \
|
||||
::testing::internal::TestNotEmpty(GTEST_EXPAND_(GTEST_GET_SECOND_( \
|
||||
__VA_ARGS__, \
|
||||
::testing::internal::DefaultParamName<test_suite_name::ParamType>, \
|
||||
DUMMY_PARAM_))); \
|
||||
const auto t = std::make_tuple(__VA_ARGS__); \
|
||||
static_assert(std::tuple_size<decltype(t)>::value <= 2, \
|
||||
"Too Many Args!"); \
|
||||
} \
|
||||
return ((GTEST_EXPAND_(GTEST_GET_SECOND_( \
|
||||
__VA_ARGS__, \
|
||||
::testing::internal::DefaultParamName<test_suite_name::ParamType>, \
|
||||
DUMMY_PARAM_))))(info); \
|
||||
} \
|
||||
[[maybe_unused]] static int gtest_##prefix##test_suite_name##_dummy_ = \
|
||||
::testing::UnitTest::GetInstance() \
|
||||
->parameterized_test_registry() \
|
||||
.GetTestSuitePatternHolder<test_suite_name>( \
|
||||
GTEST_STRINGIFY_(test_suite_name), \
|
||||
::testing::internal::CodeLocation(__FILE__, __LINE__)) \
|
||||
->AddTestSuiteInstantiation( \
|
||||
GTEST_STRINGIFY_(prefix), \
|
||||
>est_##prefix##test_suite_name##_EvalGenerator_, \
|
||||
>est_##prefix##test_suite_name##_EvalGenerateName_, __FILE__, \
|
||||
__LINE__)
|
||||
|
||||
// Allow Marking a Parameterized test class as not needing to be instantiated.
|
||||
#define GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(T) \
|
||||
|
||||
@@ -104,15 +104,19 @@
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
|
||||
|
||||
#include <any>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <ostream> // NOLINT
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
#ifdef GTEST_HAS_ABSL
|
||||
@@ -245,8 +249,8 @@ struct StreamPrinter {
|
||||
// ADL (possibly involving implicit conversions).
|
||||
// (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.)
|
||||
static auto PrintValue(const T& value,
|
||||
::std::ostream* os) -> decltype((void)(*os << value)) {
|
||||
static auto PrintValue(const T& value, ::std::ostream* os)
|
||||
-> decltype((void)(*os << value)) {
|
||||
// Call streaming operator found by ADL, possibly with implicit conversions
|
||||
// of the arguments.
|
||||
*os << value;
|
||||
@@ -287,11 +291,9 @@ struct ConvertibleToIntegerPrinter {
|
||||
};
|
||||
|
||||
struct ConvertibleToStringViewPrinter {
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
static void PrintValue(internal::StringView value, ::std::ostream* os) {
|
||||
internal::UniversalPrint(value, os);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef GTEST_HAS_ABSL
|
||||
@@ -378,7 +380,7 @@ void PrintWithFallback(const T& value, ::std::ostream* os) {
|
||||
|
||||
// The default case.
|
||||
template <typename ToPrint, typename OtherOperand>
|
||||
class FormatForComparison {
|
||||
class [[nodiscard]] FormatForComparison {
|
||||
public:
|
||||
static ::std::string Format(const ToPrint& value) {
|
||||
return ::testing::PrintToString(value);
|
||||
@@ -387,7 +389,7 @@ class FormatForComparison {
|
||||
|
||||
// Array.
|
||||
template <typename ToPrint, size_t N, typename OtherOperand>
|
||||
class FormatForComparison<ToPrint[N], OtherOperand> {
|
||||
class [[nodiscard]] FormatForComparison<ToPrint[N], OtherOperand> {
|
||||
public:
|
||||
static ::std::string Format(const ToPrint* value) {
|
||||
return FormatForComparison<const ToPrint*, OtherOperand>::Format(value);
|
||||
@@ -473,7 +475,7 @@ std::string FormatForComparisonFailureMessage(const T1& value,
|
||||
// function template), as we need to partially specialize it for
|
||||
// reference types, which cannot be done with function templates.
|
||||
template <typename T>
|
||||
class UniversalPrinter;
|
||||
class [[nodiscard]] UniversalPrinter;
|
||||
|
||||
// Prints the given value using the << operator if it has one;
|
||||
// otherwise prints the bytes in it. This is what
|
||||
@@ -520,13 +522,14 @@ inline void PrintTo(bool x, ::std::ostream* os) {
|
||||
GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os);
|
||||
|
||||
GTEST_API_ void PrintTo(char32_t c, ::std::ostream* os);
|
||||
inline void PrintTo(char16_t c, ::std::ostream* os) {
|
||||
PrintTo(ImplicitCast_<char32_t>(c), os);
|
||||
}
|
||||
|
||||
// Overloads for the UTF-8 and UTF-16 code unit types. A code unit that
|
||||
// encodes a code point all by itself is printed with the U+XXXX notation;
|
||||
// one that does not (any non-ASCII char8_t, and the UTF-16 surrogates) is
|
||||
// printed as a code unit instead, the way wchar_t is.
|
||||
GTEST_API_ void PrintTo(char16_t c, ::std::ostream* os);
|
||||
#ifdef __cpp_lib_char8_t
|
||||
inline void PrintTo(char8_t c, ::std::ostream* os) {
|
||||
PrintTo(ImplicitCast_<char32_t>(c), os);
|
||||
}
|
||||
GTEST_API_ void PrintTo(char8_t c, ::std::ostream* os);
|
||||
#endif
|
||||
|
||||
// gcc/clang __{u,}int128_t
|
||||
@@ -668,12 +671,12 @@ inline void PrintTo(char32_t* s, ::std::ostream* os) {
|
||||
PrintTo(ImplicitCast_<const char32_t*>(s), os);
|
||||
}
|
||||
|
||||
// MSVC can be configured to define wchar_t as a typedef of unsigned
|
||||
// short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native
|
||||
// type. When wchar_t is a typedef, defining an overload for const
|
||||
// wchar_t* would cause unsigned short* be printed as a wide string,
|
||||
// possibly causing invalid memory accesses.
|
||||
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
|
||||
// Only add an overload for printing wchar_t* if:
|
||||
// 1. Wide string support is enabled.
|
||||
// 2. wchar_t is a distinct native type. (If it's a typedef, the overload could
|
||||
// cause a pointer to the underlying type to be mistakenly treated as a
|
||||
// string.)
|
||||
#if GTEST_HAS_STD_WSTRING && GTEST_HAS_NATIVE_WCHAR
|
||||
// Overloads for wide C strings
|
||||
GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os);
|
||||
inline void PrintTo(wchar_t* s, ::std::ostream* os) {
|
||||
@@ -695,46 +698,63 @@ void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) {
|
||||
}
|
||||
}
|
||||
|
||||
// Overloads for ::std::string.
|
||||
GTEST_API_ void PrintStringTo(const ::std::string& s, ::std::ostream* os);
|
||||
// Overloads for ::std::string and std::string_view
|
||||
GTEST_API_ void PrintStringTo(std::string_view s, ::std::ostream* os);
|
||||
inline void PrintTo(const ::std::string& s, ::std::ostream* 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
|
||||
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) {
|
||||
PrintU8StringTo(s, os);
|
||||
}
|
||||
inline void PrintTo(::std::u8string_view s, ::std::ostream* os) {
|
||||
PrintU8StringTo(s, os);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Overloads for ::std::u16string
|
||||
GTEST_API_ void PrintU16StringTo(const ::std::u16string& s, ::std::ostream* os);
|
||||
// Overloads for ::std::u16string and ::std::u16string_view
|
||||
GTEST_API_ void PrintU16StringTo(::std::u16string_view s, ::std::ostream* os);
|
||||
inline void PrintTo(const ::std::u16string& s, ::std::ostream* os) {
|
||||
PrintU16StringTo(s, os);
|
||||
}
|
||||
inline void PrintTo(::std::u16string_view s, ::std::ostream* os) {
|
||||
PrintU16StringTo(s, os);
|
||||
}
|
||||
|
||||
// Overloads for ::std::u32string
|
||||
GTEST_API_ void PrintU32StringTo(const ::std::u32string& s, ::std::ostream* os);
|
||||
// Overloads for ::std::u32string and ::std::u32string_view
|
||||
GTEST_API_ void PrintU32StringTo(::std::u32string_view s, ::std::ostream* os);
|
||||
inline void PrintTo(const ::std::u32string& s, ::std::ostream* 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
|
||||
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) {
|
||||
PrintWideStringTo(s, os);
|
||||
}
|
||||
inline void PrintTo(::std::wstring_view s, ::std::ostream* os) {
|
||||
PrintWideStringTo(s, os);
|
||||
}
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
|
||||
#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) {
|
||||
PrintTo(::std::string(sp), os);
|
||||
PrintStringTo(sp, os);
|
||||
}
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
inline void PrintTo(std::nullptr_t, ::std::ostream* os) { *os << "(nullptr)"; }
|
||||
|
||||
@@ -836,8 +856,8 @@ void PrintTupleTo(const T& t, std::integral_constant<size_t, I>,
|
||||
GTEST_INTENTIONAL_CONST_COND_POP_()
|
||||
*os << ", ";
|
||||
}
|
||||
UniversalPrinter<typename std::tuple_element<I - 1, T>::type>::Print(
|
||||
std::get<I - 1>(t), os);
|
||||
UniversalPrinter<std::tuple_element_t<I - 1, T>>::Print(std::get<I - 1>(t),
|
||||
os);
|
||||
}
|
||||
|
||||
template <typename... Types>
|
||||
@@ -862,7 +882,7 @@ void PrintTo(const ::std::pair<T1, T2>& value, ::std::ostream* os) {
|
||||
// Implements printing a non-reference type T by letting the compiler
|
||||
// pick the right overload of PrintTo() for T.
|
||||
template <typename T>
|
||||
class UniversalPrinter {
|
||||
class [[nodiscard]] UniversalPrinter {
|
||||
public:
|
||||
// MSVC warns about adding const to a function type, so we want to
|
||||
// disable the warning.
|
||||
@@ -888,16 +908,13 @@ class UniversalPrinter {
|
||||
|
||||
// Remove any const-qualifiers before passing a type to UniversalPrinter.
|
||||
template <typename T>
|
||||
class UniversalPrinter<const T> : public UniversalPrinter<T> {};
|
||||
|
||||
#if GTEST_INTERNAL_HAS_ANY
|
||||
|
||||
// Printer for std::any / absl::any
|
||||
class [[nodiscard]] UniversalPrinter<const T> : public UniversalPrinter<T> {};
|
||||
|
||||
// Printer for std::any
|
||||
template <>
|
||||
class UniversalPrinter<Any> {
|
||||
class [[nodiscard]] UniversalPrinter<std::any> {
|
||||
public:
|
||||
static void Print(const Any& value, ::std::ostream* os) {
|
||||
static void Print(const std::any& value, ::std::ostream* os) {
|
||||
if (value.has_value()) {
|
||||
*os << "value of type " << GetTypeName(value);
|
||||
} else {
|
||||
@@ -906,7 +923,7 @@ class UniversalPrinter<Any> {
|
||||
}
|
||||
|
||||
private:
|
||||
static std::string GetTypeName(const Any& value) {
|
||||
static std::string GetTypeName(const std::any& value) {
|
||||
#if GTEST_HAS_RTTI
|
||||
return internal::GetTypeName(value.type());
|
||||
#else
|
||||
@@ -916,67 +933,60 @@ class UniversalPrinter<Any> {
|
||||
}
|
||||
};
|
||||
|
||||
#endif // GTEST_INTERNAL_HAS_ANY
|
||||
|
||||
#if GTEST_INTERNAL_HAS_OPTIONAL
|
||||
|
||||
// Printer for std::optional / absl::optional
|
||||
|
||||
// Printer for std::optional
|
||||
template <typename T>
|
||||
class UniversalPrinter<Optional<T>> {
|
||||
class [[nodiscard]] UniversalPrinter<std::optional<T>> {
|
||||
public:
|
||||
static void Print(const Optional<T>& value, ::std::ostream* os) {
|
||||
*os << '(';
|
||||
static void Print(const std::optional<T>& value, ::std::ostream* os) {
|
||||
if (!value) {
|
||||
*os << "nullopt";
|
||||
UniversalPrint(std::nullopt, os);
|
||||
} else {
|
||||
*os << '(';
|
||||
UniversalPrint(*value, os);
|
||||
*os << ')';
|
||||
}
|
||||
*os << ')';
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class UniversalPrinter<decltype(Nullopt())> {
|
||||
class [[nodiscard]] UniversalPrinter<std::nullopt_t> {
|
||||
public:
|
||||
static void Print(decltype(Nullopt()), ::std::ostream* os) {
|
||||
*os << "(nullopt)";
|
||||
}
|
||||
static void Print(std::nullopt_t, ::std::ostream* os) { *os << "(nullopt)"; }
|
||||
};
|
||||
|
||||
#endif // GTEST_INTERNAL_HAS_OPTIONAL
|
||||
|
||||
#if GTEST_INTERNAL_HAS_VARIANT
|
||||
|
||||
// Printer for std::variant / absl::variant
|
||||
struct UniversalPrinterVisitor {
|
||||
template <typename T>
|
||||
void operator()(const T& arg) const {
|
||||
*os << "'" << GetTypeName<T>() << "(index = " << index << ")' with value ";
|
||||
UniversalPrint(arg, os);
|
||||
}
|
||||
::std::ostream* os;
|
||||
std::size_t index;
|
||||
};
|
||||
|
||||
// Printer for std::variant
|
||||
template <typename... T>
|
||||
class UniversalPrinter<Variant<T...>> {
|
||||
class [[nodiscard]] UniversalPrinter<std::variant<T...>> {
|
||||
public:
|
||||
static void Print(const Variant<T...>& value, ::std::ostream* os) {
|
||||
*os << '(';
|
||||
#ifdef GTEST_HAS_ABSL
|
||||
absl::visit(Visitor{os, value.index()}, value);
|
||||
#else
|
||||
std::visit(Visitor{os, value.index()}, value);
|
||||
#endif // GTEST_HAS_ABSL
|
||||
*os << ')';
|
||||
}
|
||||
|
||||
private:
|
||||
struct Visitor {
|
||||
template <typename U>
|
||||
void operator()(const U& u) const {
|
||||
*os << "'" << GetTypeName<U>() << "(index = " << index
|
||||
<< ")' with value ";
|
||||
UniversalPrint(u, os);
|
||||
static void Print(const std::variant<T...>& value, ::std::ostream* os) {
|
||||
if (value.valueless_by_exception()) {
|
||||
*os << "(valueless)";
|
||||
} else {
|
||||
*os << '(';
|
||||
std::visit(UniversalPrinterVisitor{os, value.index()}, value);
|
||||
*os << ')';
|
||||
}
|
||||
::std::ostream* os;
|
||||
std::size_t index;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
#endif // GTEST_INTERNAL_HAS_VARIANT
|
||||
// Printer for std::monostate
|
||||
template <>
|
||||
class [[nodiscard]] UniversalPrinter<std::monostate> {
|
||||
public:
|
||||
static void Print(std::monostate, ::std::ostream* os) {
|
||||
*os << "(monostate)";
|
||||
}
|
||||
};
|
||||
|
||||
// UniversalPrintArray(begin, len, os) prints an array of 'len'
|
||||
// elements, starting at address 'begin'.
|
||||
@@ -1025,7 +1035,7 @@ GTEST_API_ void UniversalPrintArray(const wchar_t* begin, size_t len,
|
||||
|
||||
// Implements printing an array type T[N].
|
||||
template <typename T, size_t N>
|
||||
class UniversalPrinter<T[N]> {
|
||||
class [[nodiscard]] UniversalPrinter<T[N]> {
|
||||
public:
|
||||
// Prints the given array, omitting some elements when there are too
|
||||
// many.
|
||||
@@ -1036,7 +1046,7 @@ class UniversalPrinter<T[N]> {
|
||||
|
||||
// Implements printing a reference type T&.
|
||||
template <typename T>
|
||||
class UniversalPrinter<T&> {
|
||||
class [[nodiscard]] UniversalPrinter<T&> {
|
||||
public:
|
||||
// MSVC warns about adding const to a function type, so we want to
|
||||
// disable the warning.
|
||||
@@ -1059,35 +1069,35 @@ class UniversalPrinter<T&> {
|
||||
// NUL-terminated string (but not the pointer) is printed.
|
||||
|
||||
template <typename T>
|
||||
class UniversalTersePrinter {
|
||||
class [[nodiscard]] UniversalTersePrinter {
|
||||
public:
|
||||
static void Print(const T& value, ::std::ostream* os) {
|
||||
UniversalPrint(value, os);
|
||||
}
|
||||
};
|
||||
template <typename T>
|
||||
class UniversalTersePrinter<T&> {
|
||||
class [[nodiscard]] UniversalTersePrinter<T&> {
|
||||
public:
|
||||
static void Print(const T& value, ::std::ostream* os) {
|
||||
UniversalPrint(value, os);
|
||||
}
|
||||
};
|
||||
template <typename T>
|
||||
class UniversalTersePrinter<std::reference_wrapper<T>> {
|
||||
class [[nodiscard]] UniversalTersePrinter<std::reference_wrapper<T>> {
|
||||
public:
|
||||
static void Print(std::reference_wrapper<T> value, ::std::ostream* os) {
|
||||
UniversalTersePrinter<T>::Print(value.get(), os);
|
||||
}
|
||||
};
|
||||
template <typename T, size_t N>
|
||||
class UniversalTersePrinter<T[N]> {
|
||||
class [[nodiscard]] UniversalTersePrinter<T[N]> {
|
||||
public:
|
||||
static void Print(const T (&value)[N], ::std::ostream* os) {
|
||||
UniversalPrinter<T[N]>::Print(value, os);
|
||||
}
|
||||
};
|
||||
template <>
|
||||
class UniversalTersePrinter<const char*> {
|
||||
class [[nodiscard]] UniversalTersePrinter<const char*> {
|
||||
public:
|
||||
static void Print(const char* str, ::std::ostream* os) {
|
||||
if (str == nullptr) {
|
||||
@@ -1098,12 +1108,12 @@ class UniversalTersePrinter<const char*> {
|
||||
}
|
||||
};
|
||||
template <>
|
||||
class UniversalTersePrinter<char*> : public UniversalTersePrinter<const char*> {
|
||||
};
|
||||
class [[nodiscard]]
|
||||
UniversalTersePrinter<char*> : public UniversalTersePrinter<const char*> {};
|
||||
|
||||
#ifdef __cpp_lib_char8_t
|
||||
template <>
|
||||
class UniversalTersePrinter<const char8_t*> {
|
||||
class [[nodiscard]] UniversalTersePrinter<const char8_t*> {
|
||||
public:
|
||||
static void Print(const char8_t* str, ::std::ostream* os) {
|
||||
if (str == nullptr) {
|
||||
@@ -1114,12 +1124,12 @@ class UniversalTersePrinter<const char8_t*> {
|
||||
}
|
||||
};
|
||||
template <>
|
||||
class UniversalTersePrinter<char8_t*>
|
||||
class [[nodiscard]] UniversalTersePrinter<char8_t*>
|
||||
: public UniversalTersePrinter<const char8_t*> {};
|
||||
#endif
|
||||
|
||||
template <>
|
||||
class UniversalTersePrinter<const char16_t*> {
|
||||
class [[nodiscard]] UniversalTersePrinter<const char16_t*> {
|
||||
public:
|
||||
static void Print(const char16_t* str, ::std::ostream* os) {
|
||||
if (str == nullptr) {
|
||||
@@ -1130,11 +1140,11 @@ class UniversalTersePrinter<const char16_t*> {
|
||||
}
|
||||
};
|
||||
template <>
|
||||
class UniversalTersePrinter<char16_t*>
|
||||
class [[nodiscard]] UniversalTersePrinter<char16_t*>
|
||||
: public UniversalTersePrinter<const char16_t*> {};
|
||||
|
||||
template <>
|
||||
class UniversalTersePrinter<const char32_t*> {
|
||||
class [[nodiscard]] UniversalTersePrinter<const char32_t*> {
|
||||
public:
|
||||
static void Print(const char32_t* str, ::std::ostream* os) {
|
||||
if (str == nullptr) {
|
||||
@@ -1145,12 +1155,12 @@ class UniversalTersePrinter<const char32_t*> {
|
||||
}
|
||||
};
|
||||
template <>
|
||||
class UniversalTersePrinter<char32_t*>
|
||||
class [[nodiscard]] UniversalTersePrinter<char32_t*>
|
||||
: public UniversalTersePrinter<const char32_t*> {};
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
template <>
|
||||
class UniversalTersePrinter<const wchar_t*> {
|
||||
class [[nodiscard]] UniversalTersePrinter<const wchar_t*> {
|
||||
public:
|
||||
static void Print(const wchar_t* str, ::std::ostream* os) {
|
||||
if (str == nullptr) {
|
||||
@@ -1160,15 +1170,12 @@ class UniversalTersePrinter<const wchar_t*> {
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template <>
|
||||
class UniversalTersePrinter<wchar_t*> {
|
||||
public:
|
||||
static void Print(wchar_t* str, ::std::ostream* os) {
|
||||
UniversalTersePrinter<const wchar_t*>::Print(str, os);
|
||||
}
|
||||
};
|
||||
class [[nodiscard]] UniversalTersePrinter<wchar_t*>
|
||||
: public UniversalTersePrinter<const wchar_t*> {};
|
||||
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
|
||||
template <typename T>
|
||||
void UniversalTersePrint(const T& value, ::std::ostream* os) {
|
||||
@@ -1212,7 +1219,7 @@ template <typename Tuple>
|
||||
Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
|
||||
Strings result;
|
||||
TersePrintPrefixToStrings(
|
||||
value, std::integral_constant<size_t, std::tuple_size<Tuple>::value>(),
|
||||
value, std::integral_constant<size_t, std::tuple_size_v<Tuple>>(),
|
||||
&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace testing {
|
||||
// generated in the same thread that created this object or it can intercept
|
||||
// all generated failures. The scope of this mock object can be controlled with
|
||||
// the second argument to the two arguments constructor.
|
||||
class GTEST_API_ ScopedFakeTestPartResultReporter
|
||||
class GTEST_API_ [[nodiscard]] ScopedFakeTestPartResultReporter
|
||||
: public TestPartResultReporterInterface {
|
||||
public:
|
||||
// The two possible mocking modes of this object.
|
||||
@@ -100,7 +100,7 @@ namespace internal {
|
||||
// TestPartResultArray contains exactly one failure that has the given
|
||||
// type and contains the given substring. If that's not the case, a
|
||||
// non-fatal failure will be generated.
|
||||
class GTEST_API_ SingleFailureChecker {
|
||||
class GTEST_API_ [[nodiscard]] SingleFailureChecker {
|
||||
public:
|
||||
// The constructor remembers the arguments.
|
||||
SingleFailureChecker(const TestPartResultArray* results,
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <iosfwd>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/internal/gtest-internal.h"
|
||||
@@ -51,7 +52,7 @@ namespace testing {
|
||||
// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()).
|
||||
//
|
||||
// Don't inherit from TestPartResult as its destructor is not virtual.
|
||||
class GTEST_API_ TestPartResult {
|
||||
class GTEST_API_ [[nodiscard]] TestPartResult {
|
||||
public:
|
||||
// The possible outcomes of a test part (i.e. an assertion or an
|
||||
// explicit SUCCEED(), FAIL(), or ADD_FAILURE()).
|
||||
@@ -65,10 +66,10 @@ class GTEST_API_ TestPartResult {
|
||||
// C'tor. TestPartResult does NOT have a default constructor.
|
||||
// Always use this constructor (with parameters) to create a
|
||||
// TestPartResult object.
|
||||
TestPartResult(Type a_type, const char* a_file_name, int a_line_number,
|
||||
const char* a_message)
|
||||
TestPartResult(Type a_type, std::string_view a_file_name, int a_line_number,
|
||||
std::string_view a_message)
|
||||
: type_(a_type),
|
||||
file_name_(a_file_name == nullptr ? "" : a_file_name),
|
||||
file_name_(a_file_name),
|
||||
line_number_(a_line_number),
|
||||
summary_(ExtractSummary(a_message)),
|
||||
message_(a_message) {}
|
||||
@@ -112,7 +113,7 @@ class GTEST_API_ TestPartResult {
|
||||
|
||||
// Gets the summary of the failure message by omitting the stack
|
||||
// trace in it.
|
||||
static std::string ExtractSummary(const char* message);
|
||||
static std::string ExtractSummary(std::string_view message);
|
||||
|
||||
// The name of the source file where the test part took place, or
|
||||
// "" if the source file is unknown.
|
||||
@@ -131,7 +132,7 @@ std::ostream& operator<<(std::ostream& os, const TestPartResult& result);
|
||||
//
|
||||
// Don't inherit from TestPartResultArray as its destructor is not
|
||||
// virtual.
|
||||
class GTEST_API_ TestPartResultArray {
|
||||
class GTEST_API_ [[nodiscard]] TestPartResultArray {
|
||||
public:
|
||||
TestPartResultArray() = default;
|
||||
|
||||
@@ -152,7 +153,7 @@ class GTEST_API_ TestPartResultArray {
|
||||
};
|
||||
|
||||
// This interface knows how to report a test part result.
|
||||
class GTEST_API_ TestPartResultReporterInterface {
|
||||
class GTEST_API_ [[nodiscard]] TestPartResultReporterInterface {
|
||||
public:
|
||||
virtual ~TestPartResultReporterInterface() = default;
|
||||
|
||||
@@ -167,7 +168,7 @@ namespace internal {
|
||||
// reported, it only delegates the reporting to the former result reporter.
|
||||
// The original result reporter is restored in the destructor.
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||
class GTEST_API_ HasNewFatalFailureHelper
|
||||
class GTEST_API_ [[nodiscard]] HasNewFatalFailureHelper
|
||||
: public TestPartResultReporterInterface {
|
||||
public:
|
||||
HasNewFatalFailureHelper();
|
||||
|
||||
@@ -45,18 +45,18 @@
|
||||
// First, define a fixture class template. It should be parameterized
|
||||
// by a type. Remember to derive it from testing::Test.
|
||||
template <typename T>
|
||||
class FooTest : public testing::Test {
|
||||
class [[nodiscard]] FooTest : public testing::Test {
|
||||
public:
|
||||
...
|
||||
typedef std::list<T> List;
|
||||
using List = ::std::list<T>;
|
||||
static T shared_;
|
||||
T value_;
|
||||
};
|
||||
|
||||
// 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.
|
||||
typedef testing::Types<char, int, unsigned int> MyTypes;
|
||||
using MyTypes = ::testing::Types<char, int, unsigned int>;
|
||||
TYPED_TEST_SUITE(FooTest, MyTypes);
|
||||
|
||||
// If the type list contains only one type, you can write that type
|
||||
@@ -123,7 +123,7 @@ TYPED_TEST(FooTest, HasPropertyA) { ... }
|
||||
// First, define a fixture class template. It should be parameterized
|
||||
// by a type. Remember to derive it from testing::Test.
|
||||
template <typename T>
|
||||
class FooTest : public testing::Test {
|
||||
class [[nodiscard]] FooTest : public testing::Test {
|
||||
...
|
||||
};
|
||||
|
||||
@@ -157,7 +157,7 @@ REGISTER_TYPED_TEST_SUITE_P(FooTest,
|
||||
// argument to the INSTANTIATE_* macro is a prefix that will be added
|
||||
// to the actual test suite name. Remember to pick unique prefixes for
|
||||
// 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);
|
||||
|
||||
// If the type list contains only one type, you can write that type
|
||||
@@ -194,34 +194,33 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
|
||||
typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \
|
||||
GTEST_NAME_GENERATOR_(CaseName)
|
||||
|
||||
#define TYPED_TEST(CaseName, TestName) \
|
||||
static_assert(sizeof(GTEST_STRINGIFY_(TestName)) > 1, \
|
||||
"test-name must not be empty"); \
|
||||
template <typename gtest_TypeParam_> \
|
||||
class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
|
||||
: public CaseName<gtest_TypeParam_> { \
|
||||
private: \
|
||||
typedef CaseName<gtest_TypeParam_> TestFixture; \
|
||||
typedef gtest_TypeParam_ TypeParam; \
|
||||
void TestBody() override; \
|
||||
}; \
|
||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool \
|
||||
gtest_##CaseName##_##TestName##_registered_ = \
|
||||
::testing::internal::TypeParameterizedTest< \
|
||||
CaseName, \
|
||||
::testing::internal::TemplateSel<GTEST_TEST_CLASS_NAME_( \
|
||||
CaseName, TestName)>, \
|
||||
GTEST_TYPE_PARAMS_( \
|
||||
CaseName)>::Register("", \
|
||||
::testing::internal::CodeLocation( \
|
||||
__FILE__, __LINE__), \
|
||||
GTEST_STRINGIFY_(CaseName), \
|
||||
GTEST_STRINGIFY_(TestName), 0, \
|
||||
::testing::internal::GenerateNames< \
|
||||
GTEST_NAME_GENERATOR_(CaseName), \
|
||||
GTEST_TYPE_PARAMS_(CaseName)>()); \
|
||||
template <typename gtest_TypeParam_> \
|
||||
void GTEST_TEST_CLASS_NAME_(CaseName, \
|
||||
#define TYPED_TEST(CaseName, TestName) \
|
||||
static_assert(sizeof(GTEST_STRINGIFY_(TestName)) > 1, \
|
||||
"test-name must not be empty"); \
|
||||
template <typename gtest_TypeParam_> \
|
||||
class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
|
||||
: public CaseName<gtest_TypeParam_> { \
|
||||
private: \
|
||||
typedef CaseName<gtest_TypeParam_> TestFixture; \
|
||||
typedef gtest_TypeParam_ TypeParam; \
|
||||
void TestBody() override; \
|
||||
}; \
|
||||
[[maybe_unused]] static bool gtest_##CaseName##_##TestName##_registered_ = \
|
||||
::testing::internal::TypeParameterizedTest< \
|
||||
CaseName, \
|
||||
::testing::internal::TemplateSel<GTEST_TEST_CLASS_NAME_(CaseName, \
|
||||
TestName)>, \
|
||||
GTEST_TYPE_PARAMS_( \
|
||||
CaseName)>::Register("", \
|
||||
::testing::internal::CodeLocation( \
|
||||
__FILE__, __LINE__), \
|
||||
GTEST_STRINGIFY_(CaseName), \
|
||||
GTEST_STRINGIFY_(TestName), 0, \
|
||||
::testing::internal::GenerateNames< \
|
||||
GTEST_NAME_GENERATOR_(CaseName), \
|
||||
GTEST_TYPE_PARAMS_(CaseName)>()); \
|
||||
template <typename gtest_TypeParam_> \
|
||||
void GTEST_TEST_CLASS_NAME_(CaseName, \
|
||||
TestName)<gtest_TypeParam_>::TestBody()
|
||||
|
||||
// Legacy API is deprecated but still available
|
||||
@@ -268,23 +267,22 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
|
||||
TYPED_TEST_SUITE_P
|
||||
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
|
||||
#define TYPED_TEST_P(SuiteName, TestName) \
|
||||
namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \
|
||||
template <typename gtest_TypeParam_> \
|
||||
class TestName : public SuiteName<gtest_TypeParam_> { \
|
||||
private: \
|
||||
typedef SuiteName<gtest_TypeParam_> TestFixture; \
|
||||
typedef gtest_TypeParam_ TypeParam; \
|
||||
void TestBody() override; \
|
||||
}; \
|
||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool \
|
||||
gtest_##TestName##_defined_ = \
|
||||
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).AddTestName( \
|
||||
__FILE__, __LINE__, GTEST_STRINGIFY_(SuiteName), \
|
||||
GTEST_STRINGIFY_(TestName)); \
|
||||
} \
|
||||
template <typename gtest_TypeParam_> \
|
||||
void GTEST_SUITE_NAMESPACE_( \
|
||||
#define TYPED_TEST_P(SuiteName, TestName) \
|
||||
namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \
|
||||
template <typename gtest_TypeParam_> \
|
||||
class TestName : public SuiteName<gtest_TypeParam_> { \
|
||||
private: \
|
||||
typedef SuiteName<gtest_TypeParam_> TestFixture; \
|
||||
typedef gtest_TypeParam_ TypeParam; \
|
||||
void TestBody() override; \
|
||||
}; \
|
||||
[[maybe_unused]] static bool gtest_##TestName##_defined_ = \
|
||||
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).AddTestName( \
|
||||
__FILE__, __LINE__, GTEST_STRINGIFY_(SuiteName), \
|
||||
GTEST_STRINGIFY_(TestName)); \
|
||||
} \
|
||||
template <typename gtest_TypeParam_> \
|
||||
void GTEST_SUITE_NAMESPACE_( \
|
||||
SuiteName)::TestName<gtest_TypeParam_>::TestBody()
|
||||
|
||||
// Note: this won't work correctly if the trailing arguments are macros.
|
||||
@@ -292,8 +290,8 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
|
||||
namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \
|
||||
typedef ::testing::internal::Templates<__VA_ARGS__> gtest_AllTests_; \
|
||||
} \
|
||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static const char* const \
|
||||
GTEST_REGISTERED_TEST_NAMES_(SuiteName) = \
|
||||
[[maybe_unused]] static const char* const GTEST_REGISTERED_TEST_NAMES_( \
|
||||
SuiteName) = \
|
||||
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).VerifyRegisteredTestNames( \
|
||||
GTEST_STRINGIFY_(SuiteName), __FILE__, __LINE__, #__VA_ARGS__)
|
||||
|
||||
@@ -305,24 +303,22 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
|
||||
REGISTER_TYPED_TEST_SUITE_P
|
||||
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
|
||||
#define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...) \
|
||||
static_assert(sizeof(GTEST_STRINGIFY_(Prefix)) > 1, \
|
||||
"test-suit-prefix must not be empty"); \
|
||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool \
|
||||
gtest_##Prefix##_##SuiteName = \
|
||||
::testing::internal::TypeParameterizedTestSuite< \
|
||||
SuiteName, GTEST_SUITE_NAMESPACE_(SuiteName)::gtest_AllTests_, \
|
||||
::testing::internal::GenerateTypeList<Types>::type>:: \
|
||||
Register( \
|
||||
GTEST_STRINGIFY_(Prefix), \
|
||||
::testing::internal::CodeLocation(__FILE__, __LINE__), \
|
||||
>EST_TYPED_TEST_SUITE_P_STATE_(SuiteName), \
|
||||
GTEST_STRINGIFY_(SuiteName), \
|
||||
GTEST_REGISTERED_TEST_NAMES_(SuiteName), \
|
||||
::testing::internal::GenerateNames< \
|
||||
::testing::internal::NameGeneratorSelector< \
|
||||
__VA_ARGS__>::type, \
|
||||
::testing::internal::GenerateTypeList<Types>::type>())
|
||||
#define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...) \
|
||||
static_assert(sizeof(GTEST_STRINGIFY_(Prefix)) > 1, \
|
||||
"test-suit-prefix must not be empty"); \
|
||||
[[maybe_unused]] static bool gtest_##Prefix##_##SuiteName = \
|
||||
::testing::internal::TypeParameterizedTestSuite< \
|
||||
SuiteName, GTEST_SUITE_NAMESPACE_(SuiteName)::gtest_AllTests_, \
|
||||
::testing::internal::GenerateTypeList<Types>::type>:: \
|
||||
Register(GTEST_STRINGIFY_(Prefix), \
|
||||
::testing::internal::CodeLocation(__FILE__, __LINE__), \
|
||||
>EST_TYPED_TEST_SUITE_P_STATE_(SuiteName), \
|
||||
GTEST_STRINGIFY_(SuiteName), \
|
||||
GTEST_REGISTERED_TEST_NAMES_(SuiteName), \
|
||||
::testing::internal::GenerateNames< \
|
||||
::testing::internal::NameGeneratorSelector< \
|
||||
__VA_ARGS__>::type, \
|
||||
::testing::internal::GenerateTypeList<Types>::type>())
|
||||
|
||||
// Legacy API is deprecated but still available
|
||||
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
@@ -70,7 +71,7 @@
|
||||
#include "gtest/gtest-typed-test.h" // IWYU pragma: export
|
||||
#include "gtest/gtest_pred_impl.h" // IWYU pragma: export
|
||||
#include "gtest/gtest_prod.h" // IWYU pragma: export
|
||||
#include "gtest/internal/gtest-internal.h"
|
||||
#include "gtest/internal/gtest-internal.h" // IWYU pragma: export
|
||||
#include "gtest/internal/gtest-string.h"
|
||||
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
|
||||
@@ -136,6 +137,10 @@ GTEST_DECLARE_int32_(repeat);
|
||||
// only torn down once, for the last.
|
||||
GTEST_DECLARE_bool_(recreate_environments_when_repeating);
|
||||
|
||||
// Together these flags determine which tests are run if the test is sharded.
|
||||
GTEST_DECLARE_int32_(shard_index);
|
||||
GTEST_DECLARE_int32_(total_shards);
|
||||
|
||||
// This flag controls whether Google Test includes Google Test internal
|
||||
// stack frames in failure stack traces.
|
||||
GTEST_DECLARE_bool_(show_internal_stack_frames);
|
||||
@@ -193,7 +198,7 @@ std::set<std::string>* GetIgnoredParameterizedTestSuites();
|
||||
// A base class that prevents subclasses from being copyable.
|
||||
// We do this instead of using '= delete' so as to avoid triggering warnings
|
||||
// inside user code regarding any of our declarations.
|
||||
class GTestNonCopyable {
|
||||
class [[nodiscard]] GTestNonCopyable {
|
||||
public:
|
||||
GTestNonCopyable() = default;
|
||||
GTestNonCopyable(const GTestNonCopyable&) = delete;
|
||||
@@ -206,15 +211,15 @@ class GTestNonCopyable {
|
||||
// The friend relationship of some of these classes is cyclic.
|
||||
// If we don't forward declare them the compiler might confuse the classes
|
||||
// in friendship clauses with same named classes on the scope.
|
||||
class Test;
|
||||
class TestSuite;
|
||||
class [[nodiscard]] Test;
|
||||
class [[nodiscard]] TestSuite;
|
||||
|
||||
// Old API is still available but deprecated
|
||||
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
using TestCase = TestSuite;
|
||||
#endif
|
||||
class TestInfo;
|
||||
class UnitTest;
|
||||
class [[nodiscard]] TestInfo;
|
||||
class [[nodiscard]] UnitTest;
|
||||
|
||||
// The abstract class that all tests inherit from.
|
||||
//
|
||||
@@ -239,7 +244,7 @@ class UnitTest;
|
||||
// TEST_F(FooTest, Baz) { ... }
|
||||
//
|
||||
// Test is not copyable.
|
||||
class GTEST_API_ Test {
|
||||
class GTEST_API_ [[nodiscard]] Test {
|
||||
public:
|
||||
friend class TestInfo;
|
||||
|
||||
@@ -366,7 +371,7 @@ typedef internal::TimeInMillis TimeInMillis;
|
||||
// output as a key/value string pair.
|
||||
//
|
||||
// Don't inherit from TestProperty as its destructor is not virtual.
|
||||
class TestProperty {
|
||||
class [[nodiscard]] TestProperty {
|
||||
public:
|
||||
// C'tor. TestProperty does NOT have a default constructor.
|
||||
// Always use this constructor (with parameters) to create a
|
||||
@@ -396,7 +401,7 @@ class TestProperty {
|
||||
// the Test.
|
||||
//
|
||||
// TestResult is not copyable.
|
||||
class GTEST_API_ TestResult {
|
||||
class GTEST_API_ [[nodiscard]] TestResult {
|
||||
public:
|
||||
// Creates an empty TestResult.
|
||||
TestResult();
|
||||
@@ -530,7 +535,7 @@ class GTEST_API_ TestResult {
|
||||
// The constructor of TestInfo registers itself with the UnitTest
|
||||
// singleton such that the RUN_ALL_TESTS() macro knows which tests to
|
||||
// run.
|
||||
class GTEST_API_ TestInfo {
|
||||
class GTEST_API_ [[nodiscard]] TestInfo {
|
||||
public:
|
||||
// Destructs a TestInfo object. This function is not virtual, so
|
||||
// don't inherit from TestInfo.
|
||||
@@ -669,7 +674,7 @@ class GTEST_API_ TestInfo {
|
||||
// A test suite, which consists of a vector of TestInfos.
|
||||
//
|
||||
// TestSuite is not copyable.
|
||||
class GTEST_API_ TestSuite {
|
||||
class GTEST_API_ [[nodiscard]] TestSuite {
|
||||
public:
|
||||
// Creates a TestSuite with the given name.
|
||||
//
|
||||
@@ -890,7 +895,7 @@ class GTEST_API_ TestSuite {
|
||||
// available.
|
||||
// 2. You cannot use ASSERT_* directly in a constructor or
|
||||
// destructor.
|
||||
class Environment {
|
||||
class [[nodiscard]] Environment {
|
||||
public:
|
||||
// The d'tor is virtual as we need to subclass Environment.
|
||||
virtual ~Environment() = default;
|
||||
@@ -911,7 +916,7 @@ class Environment {
|
||||
#if GTEST_HAS_EXCEPTIONS
|
||||
|
||||
// Exception which can be thrown from TestEventListener::OnTestPartResult.
|
||||
class GTEST_API_ AssertionException
|
||||
class GTEST_API_ [[nodiscard]] AssertionException
|
||||
: public internal::GoogleTestFailureException {
|
||||
public:
|
||||
explicit AssertionException(const TestPartResult& result)
|
||||
@@ -922,7 +927,7 @@ class GTEST_API_ AssertionException
|
||||
|
||||
// The interface for tracing execution of tests. The methods are organized in
|
||||
// the order the corresponding events are fired.
|
||||
class TestEventListener {
|
||||
class [[nodiscard]] TestEventListener {
|
||||
public:
|
||||
virtual ~TestEventListener() = default;
|
||||
|
||||
@@ -989,7 +994,7 @@ class TestEventListener {
|
||||
// the methods they override will not be caught during the build. For
|
||||
// comments about each method please see the definition of TestEventListener
|
||||
// above.
|
||||
class EmptyTestEventListener : public TestEventListener {
|
||||
class [[nodiscard]] EmptyTestEventListener : public TestEventListener {
|
||||
public:
|
||||
void OnTestProgramStart(const UnitTest& /*unit_test*/) override {}
|
||||
void OnTestIterationStart(const UnitTest& /*unit_test*/,
|
||||
@@ -1019,7 +1024,7 @@ class EmptyTestEventListener : public TestEventListener {
|
||||
};
|
||||
|
||||
// TestEventListeners lets users add listeners to track events in Google Test.
|
||||
class GTEST_API_ TestEventListeners {
|
||||
class GTEST_API_ [[nodiscard]] TestEventListeners {
|
||||
public:
|
||||
TestEventListeners();
|
||||
~TestEventListeners();
|
||||
@@ -1110,7 +1115,7 @@ class GTEST_API_ TestEventListeners {
|
||||
//
|
||||
// This class is thread-safe as long as the methods are called
|
||||
// according to their specification.
|
||||
class GTEST_API_ UnitTest {
|
||||
class GTEST_API_ [[nodiscard]] UnitTest {
|
||||
public:
|
||||
// Gets the singleton UnitTest object. The first time this method
|
||||
// is called, a UnitTest object is constructed and returned.
|
||||
@@ -1123,7 +1128,7 @@ class GTEST_API_ UnitTest {
|
||||
// This method can only be called from the main thread.
|
||||
//
|
||||
// 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()
|
||||
// was executed. The UnitTest object owns the string.
|
||||
@@ -1246,7 +1251,7 @@ class GTEST_API_ UnitTest {
|
||||
// eventually call this to report their results. The user code
|
||||
// should use the assertion macros instead of calling this directly.
|
||||
void AddTestPartResult(TestPartResult::Type result_type,
|
||||
const char* file_name, int line_number,
|
||||
std::string_view file_name, int line_number,
|
||||
const std::string& message,
|
||||
const std::string& os_stack_trace)
|
||||
GTEST_LOCK_EXCLUDED_(mutex_);
|
||||
@@ -1398,7 +1403,7 @@ AssertionResult CmpHelperEQ(const char* lhs_expression,
|
||||
return CmpHelperEQFailure(lhs_expression, rhs_expression, lhs, rhs);
|
||||
}
|
||||
|
||||
class EqHelper {
|
||||
class [[nodiscard]] EqHelper {
|
||||
public:
|
||||
// This templatized version is for the general case.
|
||||
template <
|
||||
@@ -1509,6 +1514,8 @@ GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
|
||||
const char* s2_expression,
|
||||
const char* s1, const char* s2);
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
|
||||
// Helper function for *_STREQ on wide strings.
|
||||
//
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
|
||||
@@ -1523,6 +1530,8 @@ GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
|
||||
const char* s2_expression,
|
||||
const wchar_t* s1, const wchar_t* s2);
|
||||
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// IsSubstring() and IsNotSubstring() are intended to be used as the
|
||||
@@ -1537,18 +1546,10 @@ GTEST_API_ AssertionResult IsSubstring(const char* needle_expr,
|
||||
const char* haystack_expr,
|
||||
const char* needle,
|
||||
const char* haystack);
|
||||
GTEST_API_ AssertionResult IsSubstring(const char* needle_expr,
|
||||
const char* haystack_expr,
|
||||
const wchar_t* needle,
|
||||
const wchar_t* haystack);
|
||||
GTEST_API_ AssertionResult IsNotSubstring(const char* needle_expr,
|
||||
const char* haystack_expr,
|
||||
const char* needle,
|
||||
const char* haystack);
|
||||
GTEST_API_ AssertionResult IsNotSubstring(const char* needle_expr,
|
||||
const char* haystack_expr,
|
||||
const wchar_t* needle,
|
||||
const wchar_t* haystack);
|
||||
GTEST_API_ AssertionResult IsSubstring(const char* needle_expr,
|
||||
const char* haystack_expr,
|
||||
const ::std::string& needle,
|
||||
@@ -1559,6 +1560,14 @@ GTEST_API_ AssertionResult IsNotSubstring(const char* needle_expr,
|
||||
const ::std::string& haystack);
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
GTEST_API_ AssertionResult IsSubstring(const char* needle_expr,
|
||||
const char* haystack_expr,
|
||||
const wchar_t* needle,
|
||||
const wchar_t* haystack);
|
||||
GTEST_API_ AssertionResult IsNotSubstring(const char* needle_expr,
|
||||
const char* haystack_expr,
|
||||
const wchar_t* needle,
|
||||
const wchar_t* haystack);
|
||||
GTEST_API_ AssertionResult IsSubstring(const char* needle_expr,
|
||||
const char* haystack_expr,
|
||||
const ::std::wstring& needle,
|
||||
@@ -1610,18 +1619,23 @@ GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1,
|
||||
double val1, double val2,
|
||||
double abs_error);
|
||||
|
||||
using GoogleTest_NotSupported_OnFunctionReturningNonVoid = void;
|
||||
|
||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
|
||||
// A class that enables one to stream messages to assertion macros
|
||||
class GTEST_API_ AssertHelper {
|
||||
class GTEST_API_ [[nodiscard]] AssertHelper {
|
||||
public:
|
||||
// Constructor.
|
||||
AssertHelper(TestPartResult::Type type, const char* file, int line,
|
||||
const char* message);
|
||||
AssertHelper(TestPartResult::Type type, std::string_view file, int line,
|
||||
std::string_view message);
|
||||
~AssertHelper();
|
||||
|
||||
// Message assignment is a semantic trick to enable assertion
|
||||
// streaming; see the GTEST_MESSAGE_ macro below.
|
||||
void operator=(const Message& message) const;
|
||||
GoogleTest_NotSupported_OnFunctionReturningNonVoid operator=(
|
||||
const Message& message) const;
|
||||
|
||||
private:
|
||||
// We put our data in a struct so that the size of the AssertHelper class can
|
||||
@@ -1629,12 +1643,12 @@ class GTEST_API_ AssertHelper {
|
||||
// re-using stack space even for temporary variables, so every EXPECT_EQ
|
||||
// reserves stack space for another AssertHelper.
|
||||
struct AssertHelperData {
|
||||
AssertHelperData(TestPartResult::Type t, const char* srcfile, int line_num,
|
||||
const char* msg)
|
||||
AssertHelperData(TestPartResult::Type t, std::string_view srcfile,
|
||||
int line_num, std::string_view msg)
|
||||
: type(t), file(srcfile), line(line_num), message(msg) {}
|
||||
|
||||
TestPartResult::Type const type;
|
||||
const char* const file;
|
||||
const std::string_view file;
|
||||
int const line;
|
||||
std::string const message;
|
||||
|
||||
@@ -1686,14 +1700,14 @@ class GTEST_API_ AssertHelper {
|
||||
// INSTANTIATE_TEST_SUITE_P(OneToTenRange, FooTest, ::testing::Range(1, 10));
|
||||
|
||||
template <typename T>
|
||||
class WithParamInterface {
|
||||
class [[nodiscard]] WithParamInterface {
|
||||
public:
|
||||
typedef T ParamType;
|
||||
virtual ~WithParamInterface() = default;
|
||||
|
||||
// The current parameter value. Is also available in the test fixture's
|
||||
// constructor.
|
||||
static const ParamType& GetParam() {
|
||||
[[nodiscard]] static const ParamType& GetParam() {
|
||||
GTEST_CHECK_(parameter_ != nullptr)
|
||||
<< "GetParam() can only be called inside a value-parameterized test "
|
||||
<< "-- did you intend to write TEST_P instead of TEST_F?";
|
||||
@@ -1720,7 +1734,8 @@ const T* WithParamInterface<T>::parameter_ = nullptr;
|
||||
// WithParamInterface, and can just inherit from ::testing::TestWithParam.
|
||||
|
||||
template <typename T>
|
||||
class TestWithParam : public Test, public WithParamInterface<T> {};
|
||||
class [[nodiscard]] TestWithParam : public Test,
|
||||
public WithParamInterface<T> {};
|
||||
|
||||
// Macros for indicating success/failure in test code.
|
||||
|
||||
@@ -1807,14 +1822,13 @@ class TestWithParam : public Test, public WithParamInterface<T> {};
|
||||
#define GTEST_EXPECT_TRUE(condition) \
|
||||
GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
|
||||
GTEST_NONFATAL_FAILURE_)
|
||||
#define GTEST_EXPECT_FALSE(condition) \
|
||||
GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
|
||||
#define GTEST_EXPECT_FALSE(condition) \
|
||||
GTEST_TEST_BOOLEAN_(condition, #condition, true, false, \
|
||||
GTEST_NONFATAL_FAILURE_)
|
||||
#define GTEST_ASSERT_TRUE(condition) \
|
||||
GTEST_TEST_BOOLEAN_(condition, #condition, false, true, GTEST_FATAL_FAILURE_)
|
||||
#define GTEST_ASSERT_FALSE(condition) \
|
||||
GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
|
||||
GTEST_FATAL_FAILURE_)
|
||||
#define GTEST_ASSERT_FALSE(condition) \
|
||||
GTEST_TEST_BOOLEAN_(condition, #condition, true, false, GTEST_FATAL_FAILURE_)
|
||||
|
||||
// Define these macros to 1 to omit the definition of the corresponding
|
||||
// EXPECT or ASSERT, which clashes with some users' own code.
|
||||
@@ -2068,7 +2082,7 @@ GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
|
||||
// Example:
|
||||
// testing::ScopedTrace trace("file.cc", 123, "message");
|
||||
//
|
||||
class GTEST_API_ ScopedTrace {
|
||||
class GTEST_API_ [[nodiscard]] ScopedTrace {
|
||||
public:
|
||||
// The c'tor pushes the given source file location and message onto
|
||||
// a trace stack maintained by Google Test.
|
||||
@@ -2153,7 +2167,7 @@ class GTEST_API_ ScopedTrace {
|
||||
// to cause a compiler error.
|
||||
template <typename T1, typename T2>
|
||||
constexpr bool StaticAssertTypeEq() noexcept {
|
||||
static_assert(std::is_same<T1, T2>::value, "T1 and T2 are not the same type");
|
||||
static_assert(std::is_same_v<T1, T2>, "T1 and T2 are not the same type");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2299,7 +2313,7 @@ template <int&... ExplicitParameterBarrier, typename Factory>
|
||||
TestInfo* RegisterTest(const char* test_suite_name, const char* test_name,
|
||||
const char* type_param, const char* value_param,
|
||||
const char* file, int line, Factory factory) {
|
||||
using TestT = typename std::remove_pointer<decltype(factory())>::type;
|
||||
using TestT = std::remove_pointer_t<decltype(factory())>;
|
||||
|
||||
class FactoryImpl : public internal::TestFactoryBase {
|
||||
public:
|
||||
@@ -2329,7 +2343,7 @@ TestInfo* RegisterTest(const char* test_suite_name, const char* test_name,
|
||||
//
|
||||
// This function was formerly a macro; thus, it is in the global
|
||||
// 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(); }
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "gtest/gtest-matchers.h"
|
||||
#include "gtest/internal/gtest-internal.h"
|
||||
@@ -63,6 +64,10 @@ inline Matcher<const ::std::string&> MakeDeathTestMatcher(
|
||||
::testing::internal::RE regex) {
|
||||
return ContainsRegex(regex.pattern());
|
||||
}
|
||||
inline Matcher<const ::std::string&> MakeDeathTestMatcher(
|
||||
std::string_view regex) {
|
||||
return ContainsRegex(regex);
|
||||
}
|
||||
inline Matcher<const ::std::string&> MakeDeathTestMatcher(const char* regex) {
|
||||
return ContainsRegex(regex);
|
||||
}
|
||||
@@ -96,7 +101,7 @@ GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
|
||||
// by wait(2)
|
||||
// exit code: The integer code passed to exit(3), _Exit(2), or
|
||||
// returned from main()
|
||||
class GTEST_API_ DeathTest {
|
||||
class GTEST_API_ [[nodiscard]] DeathTest {
|
||||
public:
|
||||
// Create returns false if there was an error determining the
|
||||
// appropriate action to take for the current death test; for example,
|
||||
@@ -172,7 +177,7 @@ class GTEST_API_ DeathTest {
|
||||
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||
|
||||
// Factory interface for death tests. May be mocked out for testing.
|
||||
class DeathTestFactory {
|
||||
class [[nodiscard]] DeathTestFactory {
|
||||
public:
|
||||
virtual ~DeathTestFactory() = default;
|
||||
virtual bool Create(const char* statement,
|
||||
@@ -181,7 +186,7 @@ class DeathTestFactory {
|
||||
};
|
||||
|
||||
// A concrete DeathTestFactory implementation for normal use.
|
||||
class DefaultDeathTestFactory : public DeathTestFactory {
|
||||
class [[nodiscard]] DefaultDeathTestFactory : public DeathTestFactory {
|
||||
public:
|
||||
bool Create(const char* statement, Matcher<const std::string&> matcher,
|
||||
const char* file, int line, DeathTest** test) override;
|
||||
@@ -229,7 +234,8 @@ GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
|
||||
goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
|
||||
} \
|
||||
if (gtest_dt != nullptr) { \
|
||||
std::unique_ptr< ::testing::internal::DeathTest> gtest_dt_ptr(gtest_dt); \
|
||||
const std::unique_ptr< ::testing::internal::DeathTest> gtest_dt_ptr( \
|
||||
gtest_dt); \
|
||||
switch (gtest_dt->AssumeRole()) { \
|
||||
case ::testing::internal::DeathTest::OVERSEE_TEST: \
|
||||
if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \
|
||||
@@ -256,19 +262,19 @@ GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
|
||||
// must accept a streamed message even though the message is never printed.
|
||||
// The regex object is not evaluated, but it is used to prevent "unused"
|
||||
// warnings and to avoid an expression that doesn't compile in debug mode.
|
||||
#define GTEST_EXECUTE_STATEMENT_(statement, regex_or_matcher) \
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
if (::testing::internal::AlwaysTrue()) { \
|
||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||
} else if (!::testing::internal::AlwaysTrue()) { \
|
||||
::testing::internal::MakeDeathTestMatcher(regex_or_matcher); \
|
||||
} else \
|
||||
#define GTEST_EXECUTE_STATEMENT_(statement, regex_or_matcher) \
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
if (::testing::internal::AlwaysTrue()) { \
|
||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
|
||||
} else if (!::testing::internal::AlwaysTrue()) { \
|
||||
(void)::testing::internal::MakeDeathTestMatcher(regex_or_matcher); \
|
||||
} else \
|
||||
::testing::Message()
|
||||
|
||||
// A class representing the parsed contents of the
|
||||
// --gtest_internal_run_death_test flag, as it existed when
|
||||
// RUN_ALL_TESTS was called.
|
||||
class InternalRunDeathTestFlag {
|
||||
class [[nodiscard]] InternalRunDeathTestFlag {
|
||||
public:
|
||||
InternalRunDeathTestFlag(const std::string& a_file, int a_line, int an_index,
|
||||
int a_write_fd)
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace internal {
|
||||
// Names are NOT checked for syntax correctness -- no checking for illegal
|
||||
// characters, malformed paths, etc.
|
||||
|
||||
class GTEST_API_ FilePath {
|
||||
class GTEST_API_ [[nodiscard]] FilePath {
|
||||
public:
|
||||
FilePath() : pathname_("") {}
|
||||
FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) {}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
|
||||
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
|
||||
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
#include "gtest/internal/gtest-port.h" // IWYU pragma: export
|
||||
|
||||
#ifdef GTEST_OS_LINUX
|
||||
#include <stdlib.h>
|
||||
@@ -95,7 +95,13 @@
|
||||
#define GTEST_STRINGIFY_(...) GTEST_STRINGIFY_HELPER_(__VA_ARGS__, )
|
||||
|
||||
namespace proto2 {
|
||||
class MessageLite;
|
||||
class [[nodiscard]] MessageLite;
|
||||
|
||||
// Dummy forward declaration of `DynamicCastMessage`. Does not match any actual
|
||||
// overloads of `DynamicCastMessage`, but can be used to assist name resolution
|
||||
// in templates.
|
||||
template <typename T>
|
||||
T DynamicCastMessage() = delete;
|
||||
}
|
||||
|
||||
namespace testing {
|
||||
@@ -115,15 +121,15 @@ template <typename T>
|
||||
namespace internal {
|
||||
|
||||
struct TraceInfo; // Information about a trace point.
|
||||
class TestInfoImpl; // Opaque implementation of TestInfo
|
||||
class UnitTestImpl; // Opaque implementation of UnitTest
|
||||
class [[nodiscard]] TestInfoImpl; // Opaque implementation of TestInfo
|
||||
class [[nodiscard]] UnitTestImpl; // Opaque implementation of UnitTest
|
||||
|
||||
// The text used in failure messages to indicate the start of the
|
||||
// stack trace.
|
||||
GTEST_API_ extern const char kStackTraceMarker[];
|
||||
|
||||
// An IgnoredValue object can be implicitly constructed from ANY value.
|
||||
class IgnoredValue {
|
||||
class [[nodiscard]] IgnoredValue {
|
||||
struct Sink {};
|
||||
|
||||
public:
|
||||
@@ -155,7 +161,8 @@ GTEST_DISABLE_MSC_WARNINGS_PUSH_(
|
||||
// errors presumably detectable only at run time. Since
|
||||
// std::runtime_error inherits from std::exception, many testing
|
||||
// frameworks know how to extract and print the message inside it.
|
||||
class GTEST_API_ GoogleTestFailureException : public ::std::runtime_error {
|
||||
class GTEST_API_ [[nodiscard]] GoogleTestFailureException
|
||||
: public ::std::runtime_error {
|
||||
public:
|
||||
explicit GoogleTestFailureException(const TestPartResult& failure);
|
||||
};
|
||||
@@ -242,7 +249,7 @@ GTEST_API_ std::string GetBoolAssertionFailureMessage(
|
||||
//
|
||||
// RawType: the raw floating-point type (either float or double)
|
||||
template <typename RawType>
|
||||
class FloatingPoint {
|
||||
class [[nodiscard]] FloatingPoint {
|
||||
public:
|
||||
// Defines the unsigned integer type that has the same size as the
|
||||
// floating point number.
|
||||
@@ -290,17 +297,17 @@ class FloatingPoint {
|
||||
// around may change its bits, although the new value is guaranteed
|
||||
// to be also a NAN. Therefore, don't expect this constructor to
|
||||
// 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
|
||||
|
||||
// Reinterprets a bit pattern as a floating-point number.
|
||||
//
|
||||
// This function is needed to test the AlmostEquals() method.
|
||||
static RawType ReinterpretBits(const Bits bits) {
|
||||
FloatingPoint fp(0);
|
||||
fp.u_.bits_ = bits;
|
||||
return fp.u_.value_;
|
||||
static RawType ReinterpretBits(Bits bits) {
|
||||
RawType fp;
|
||||
memcpy(&fp, &bits, sizeof(fp));
|
||||
return fp;
|
||||
}
|
||||
|
||||
// Returns the floating-point number that represent positive infinity.
|
||||
@@ -309,16 +316,16 @@ class FloatingPoint {
|
||||
// Non-static methods
|
||||
|
||||
// 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.
|
||||
Bits exponent_bits() const { return kExponentBitMask & u_.bits_; }
|
||||
Bits exponent_bits() const { return kExponentBitMask & bits_; }
|
||||
|
||||
// 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.
|
||||
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).
|
||||
bool is_nan() const {
|
||||
@@ -332,23 +339,16 @@ class FloatingPoint {
|
||||
//
|
||||
// - returns false if either number is (or both are) NAN.
|
||||
// - 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 {
|
||||
// The IEEE standard says that any comparison operation involving
|
||||
// a NAN must return false.
|
||||
if (is_nan() || rhs.is_nan()) return false;
|
||||
|
||||
return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_) <=
|
||||
kMaxUlps;
|
||||
return DistanceBetweenSignAndMagnitudeNumbers(bits_, rhs.bits_) <= kMaxUlps;
|
||||
}
|
||||
|
||||
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
|
||||
// the biased representation. More precisely, let N be 2 to the
|
||||
// power of (kBitCount - 1), an integer x is represented by the
|
||||
@@ -364,7 +364,7 @@ class FloatingPoint {
|
||||
//
|
||||
// Read https://en.wikipedia.org/wiki/Signed_number_representations
|
||||
// for more details on signed number representations.
|
||||
static Bits SignAndMagnitudeToBiased(const Bits& sam) {
|
||||
static Bits SignAndMagnitudeToBiased(Bits sam) {
|
||||
if (kSignBitMask & sam) {
|
||||
// sam represents a negative number.
|
||||
return ~sam + 1;
|
||||
@@ -376,14 +376,13 @@ class FloatingPoint {
|
||||
|
||||
// Given two numbers in the sign-and-magnitude representation,
|
||||
// returns the distance between them as an unsigned number.
|
||||
static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits& sam1,
|
||||
const Bits& sam2) {
|
||||
static Bits DistanceBetweenSignAndMagnitudeNumbers(Bits sam1, Bits sam2) {
|
||||
const Bits biased1 = SignAndMagnitudeToBiased(sam1);
|
||||
const Bits biased2 = SignAndMagnitudeToBiased(sam2);
|
||||
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
|
||||
@@ -400,7 +399,7 @@ typedef FloatingPoint<double> Double;
|
||||
typedef const void* TypeId;
|
||||
|
||||
template <typename T>
|
||||
class TypeIdHelper {
|
||||
class [[nodiscard]] TypeIdHelper {
|
||||
public:
|
||||
// dummy_ must not have a const type. Otherwise an overly eager
|
||||
// compiler (e.g. MSVC 7.1 & 8.0) may try to merge
|
||||
@@ -432,7 +431,7 @@ GTEST_API_ TypeId GetTestTypeId();
|
||||
|
||||
// Defines the abstract factory interface that creates instances
|
||||
// of a Test object.
|
||||
class TestFactoryBase {
|
||||
class [[nodiscard]] TestFactoryBase {
|
||||
public:
|
||||
virtual ~TestFactoryBase() = default;
|
||||
|
||||
@@ -451,7 +450,7 @@ class TestFactoryBase {
|
||||
// This class provides implementation of TestFactoryBase interface.
|
||||
// It is used in TEST and TEST_F macros.
|
||||
template <class TestClass>
|
||||
class TestFactoryImpl : public TestFactoryBase {
|
||||
class [[nodiscard]] TestFactoryImpl : public TestFactoryBase {
|
||||
public:
|
||||
Test* CreateTest() override { return new TestClass; }
|
||||
};
|
||||
@@ -578,7 +577,7 @@ GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
|
||||
/* class A needs to have dll-interface to be used by clients of class B */)
|
||||
|
||||
// State of the definition of a type-parameterized test suite.
|
||||
class GTEST_API_ TypedTestSuitePState {
|
||||
class GTEST_API_ [[nodiscard]] TypedTestSuitePState {
|
||||
public:
|
||||
TypedTestSuitePState() : registered_(false) {}
|
||||
|
||||
@@ -693,7 +692,7 @@ std::vector<std::string> GenerateNames() {
|
||||
// Implementation note: The GTEST_TEMPLATE_ macro declares a template
|
||||
// template parameter. It's defined in gtest-type-util.h.
|
||||
template <GTEST_TEMPLATE_ Fixture, class TestSel, typename Types>
|
||||
class TypeParameterizedTest {
|
||||
class [[nodiscard]] TypeParameterizedTest {
|
||||
public:
|
||||
// 'index' is the index of the test in the type list 'Types'
|
||||
// specified in INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, TestSuite,
|
||||
@@ -731,7 +730,7 @@ class TypeParameterizedTest {
|
||||
|
||||
// The base case for the compile time recursion.
|
||||
template <GTEST_TEMPLATE_ Fixture, class TestSel>
|
||||
class TypeParameterizedTest<Fixture, TestSel, internal::None> {
|
||||
class [[nodiscard]] TypeParameterizedTest<Fixture, TestSel, internal::None> {
|
||||
public:
|
||||
static bool Register(const char* /*prefix*/, CodeLocation,
|
||||
const char* /*case_name*/, const char* /*test_names*/,
|
||||
@@ -752,7 +751,7 @@ GTEST_API_ void RegisterTypeParameterizedTestSuiteInstantiation(
|
||||
// Test. The return value is insignificant - we just need to return
|
||||
// something such that we can call this function in a namespace scope.
|
||||
template <GTEST_TEMPLATE_ Fixture, typename Tests, typename Types>
|
||||
class TypeParameterizedTestSuite {
|
||||
class [[nodiscard]] TypeParameterizedTestSuite {
|
||||
public:
|
||||
static bool Register(const char* prefix, CodeLocation code_location,
|
||||
const TypedTestSuitePState* state, const char* case_name,
|
||||
@@ -790,7 +789,7 @@ class TypeParameterizedTestSuite {
|
||||
|
||||
// The base case for the compile time recursion.
|
||||
template <GTEST_TEMPLATE_ Fixture, typename Types>
|
||||
class TypeParameterizedTestSuite<Fixture, internal::None, Types> {
|
||||
class [[nodiscard]] TypeParameterizedTestSuite<Fixture, internal::None, Types> {
|
||||
public:
|
||||
static bool Register(const char* /*prefix*/, const CodeLocation&,
|
||||
const TypedTestSuitePState* /*state*/,
|
||||
@@ -846,7 +845,7 @@ struct TrueWithString {
|
||||
// doesn't use global state (and therefore can't interfere with user
|
||||
// code). Unlike rand_r(), it's portable. An LCG isn't very random,
|
||||
// but it's good enough for our purposes.
|
||||
class GTEST_API_ Random {
|
||||
class GTEST_API_ [[nodiscard]] Random {
|
||||
public:
|
||||
static const uint32_t kMaxRange = 1u << 31;
|
||||
|
||||
@@ -872,7 +871,7 @@ class GTEST_API_ Random {
|
||||
// that's true if and only if T has methods DebugString() and ShortDebugString()
|
||||
// that return std::string.
|
||||
template <typename T>
|
||||
class HasDebugStringAndShortDebugString {
|
||||
class [[nodiscard]] HasDebugStringAndShortDebugString {
|
||||
private:
|
||||
template <typename C>
|
||||
static auto CheckDebugString(C*) -> typename std::is_same<
|
||||
@@ -894,11 +893,6 @@ class HasDebugStringAndShortDebugString {
|
||||
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
|
||||
// STL-style container class, the first overload of IsContainerTest
|
||||
// will be viable (since both C::iterator* and C::const_iterator* are
|
||||
@@ -1077,7 +1071,7 @@ struct RelationToSourceCopy {};
|
||||
// this requirement. Element can be an array type itself (hence
|
||||
// multi-dimensional arrays are supported).
|
||||
template <typename Element>
|
||||
class NativeArray {
|
||||
class [[nodiscard]] NativeArray {
|
||||
public:
|
||||
// STL-style container typedefs.
|
||||
typedef Element value_type;
|
||||
@@ -1163,7 +1157,7 @@ struct ElemFromList {
|
||||
struct FlatTupleConstructTag {};
|
||||
|
||||
template <typename... T>
|
||||
class FlatTuple;
|
||||
class [[nodiscard]] FlatTuple;
|
||||
|
||||
template <typename Derived, size_t I>
|
||||
struct FlatTupleElemBase;
|
||||
@@ -1222,7 +1216,7 @@ struct FlatTupleBase<FlatTuple<T...>, std::index_sequence<Idx...>>
|
||||
// std::make_index_sequence, on the other hand, it is recursive but with an
|
||||
// instantiation depth of O(ln(N)).
|
||||
template <typename... T>
|
||||
class FlatTuple
|
||||
class [[nodiscard]] FlatTuple
|
||||
: private FlatTupleBase<FlatTuple<T...>,
|
||||
std::make_index_sequence<sizeof...(T)>> {
|
||||
using Indices =
|
||||
@@ -1241,30 +1235,40 @@ class FlatTuple
|
||||
|
||||
// Utility functions to be called with static_assert to induce deprecation
|
||||
// warnings.
|
||||
GTEST_INTERNAL_DEPRECATED(
|
||||
[[deprecated(
|
||||
"INSTANTIATE_TEST_CASE_P is deprecated, please use "
|
||||
"INSTANTIATE_TEST_SUITE_P")
|
||||
constexpr bool InstantiateTestCase_P_IsDeprecated() { return true; }
|
||||
"INSTANTIATE_TEST_SUITE_P")]]
|
||||
constexpr bool InstantiateTestCase_P_IsDeprecated() {
|
||||
return true;
|
||||
}
|
||||
|
||||
GTEST_INTERNAL_DEPRECATED(
|
||||
[[deprecated(
|
||||
"TYPED_TEST_CASE_P is deprecated, please use "
|
||||
"TYPED_TEST_SUITE_P")
|
||||
constexpr bool TypedTestCase_P_IsDeprecated() { return true; }
|
||||
"TYPED_TEST_SUITE_P")]]
|
||||
constexpr bool TypedTestCase_P_IsDeprecated() {
|
||||
return true;
|
||||
}
|
||||
|
||||
GTEST_INTERNAL_DEPRECATED(
|
||||
[[deprecated(
|
||||
"TYPED_TEST_CASE is deprecated, please use "
|
||||
"TYPED_TEST_SUITE")
|
||||
constexpr bool TypedTestCaseIsDeprecated() { return true; }
|
||||
"TYPED_TEST_SUITE")]]
|
||||
constexpr bool TypedTestCaseIsDeprecated() {
|
||||
return true;
|
||||
}
|
||||
|
||||
GTEST_INTERNAL_DEPRECATED(
|
||||
[[deprecated(
|
||||
"REGISTER_TYPED_TEST_CASE_P is deprecated, please use "
|
||||
"REGISTER_TYPED_TEST_SUITE_P")
|
||||
constexpr bool RegisterTypedTestCase_P_IsDeprecated() { return true; }
|
||||
"REGISTER_TYPED_TEST_SUITE_P")]]
|
||||
constexpr bool RegisterTypedTestCase_P_IsDeprecated() {
|
||||
return true;
|
||||
}
|
||||
|
||||
GTEST_INTERNAL_DEPRECATED(
|
||||
[[deprecated(
|
||||
"INSTANTIATE_TYPED_TEST_CASE_P is deprecated, please use "
|
||||
"INSTANTIATE_TYPED_TEST_SUITE_P")
|
||||
constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; }
|
||||
"INSTANTIATE_TYPED_TEST_SUITE_P")]]
|
||||
constexpr bool InstantiateTypedTestCase_P_IsDeprecated() {
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
@@ -1320,7 +1324,7 @@ struct tuple_size<testing::internal::FlatTuple<Ts...>>
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
class NeverThrown {
|
||||
class [[nodiscard]] NeverThrown {
|
||||
public:
|
||||
const char* what() const noexcept {
|
||||
return "this exception should never be thrown";
|
||||
@@ -1447,15 +1451,14 @@ class NeverThrown {
|
||||
// Implements Boolean test assertions such as EXPECT_TRUE. expression can be
|
||||
// either a boolean expression or an AssertionResult. text is a textual
|
||||
// representation of expression as it was passed into the EXPECT_TRUE.
|
||||
#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
if (const ::testing::AssertionResult gtest_ar_ = \
|
||||
::testing::AssertionResult(expression)) \
|
||||
; \
|
||||
else \
|
||||
fail(::testing::internal::GetBoolAssertionFailureMessage( \
|
||||
gtest_ar_, text, #actual, #expected) \
|
||||
.c_str())
|
||||
#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
if (const ::testing::internal::AssertionResultExpectation gtest_are_ = { \
|
||||
::testing::AssertionResult(expression), expected}) \
|
||||
; \
|
||||
else /* NOLINT */ \
|
||||
fail(::testing::internal::GetBoolAssertionFailureMessage( \
|
||||
gtest_are_.assertion_result, text, #actual, #expected))
|
||||
|
||||
#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \
|
||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
||||
@@ -1501,8 +1504,7 @@ class NeverThrown {
|
||||
\
|
||||
private: \
|
||||
void TestBody() override; \
|
||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static ::testing::TestInfo* const \
|
||||
test_info_; \
|
||||
[[maybe_unused]] static ::testing::TestInfo* const test_info_; \
|
||||
}; \
|
||||
\
|
||||
::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name, \
|
||||
@@ -1514,8 +1516,9 @@ class NeverThrown {
|
||||
parent_class>::GetSetUpCaseOrSuite(__FILE__, __LINE__), \
|
||||
::testing::internal::SuiteApiResolver< \
|
||||
parent_class>::GetTearDownCaseOrSuite(__FILE__, __LINE__), \
|
||||
new ::testing::internal::TestFactoryImpl<GTEST_TEST_CLASS_NAME_( \
|
||||
test_suite_name, test_name)>); \
|
||||
::std::make_unique<::testing::internal::TestFactoryImpl< \
|
||||
GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)>>() \
|
||||
.release()); \
|
||||
void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody()
|
||||
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <ctype.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
@@ -89,14 +90,14 @@ GTEST_API_ void ReportInvalidTestSuiteType(const char* test_suite_name,
|
||||
const CodeLocation& code_location);
|
||||
|
||||
template <typename>
|
||||
class ParamGeneratorInterface;
|
||||
class [[nodiscard]] ParamGeneratorInterface;
|
||||
template <typename>
|
||||
class ParamGenerator;
|
||||
class [[nodiscard]] ParamGenerator;
|
||||
|
||||
// Interface for iterating over elements provided by an implementation
|
||||
// of ParamGeneratorInterface<T>.
|
||||
template <typename T>
|
||||
class ParamIteratorInterface {
|
||||
class [[nodiscard]] ParamIteratorInterface {
|
||||
public:
|
||||
virtual ~ParamIteratorInterface() = default;
|
||||
// A pointer to the base generator instance.
|
||||
@@ -126,7 +127,7 @@ class ParamIteratorInterface {
|
||||
// ParamGeneratorInterface<T>. It wraps ParamIteratorInterface<T>
|
||||
// and implements the const forward iterator concept.
|
||||
template <typename T>
|
||||
class ParamIterator {
|
||||
class [[nodiscard]] ParamIterator {
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef const T& reference;
|
||||
@@ -168,7 +169,7 @@ class ParamIterator {
|
||||
// ParamGeneratorInterface<T> is the binary interface to access generators
|
||||
// defined in other translation units.
|
||||
template <typename T>
|
||||
class ParamGeneratorInterface {
|
||||
class [[nodiscard]] ParamGeneratorInterface {
|
||||
public:
|
||||
typedef T ParamType;
|
||||
|
||||
@@ -185,7 +186,7 @@ class ParamGeneratorInterface {
|
||||
// ParamGeneratorInterface<T> instance is shared among all copies
|
||||
// of the original object. This is possible because that instance is immutable.
|
||||
template <typename T>
|
||||
class ParamGenerator {
|
||||
class [[nodiscard]] ParamGenerator {
|
||||
public:
|
||||
typedef ParamIterator<T> iterator;
|
||||
|
||||
@@ -209,7 +210,7 @@ class ParamGenerator {
|
||||
// operator<().
|
||||
// This class is used in the Range() function.
|
||||
template <typename T, typename IncrementT>
|
||||
class RangeGenerator : public ParamGeneratorInterface<T> {
|
||||
class [[nodiscard]] RangeGenerator : public ParamGeneratorInterface<T> {
|
||||
public:
|
||||
RangeGenerator(T begin, T end, IncrementT step)
|
||||
: begin_(begin),
|
||||
@@ -295,7 +296,8 @@ class RangeGenerator : public ParamGeneratorInterface<T> {
|
||||
// since the source can be located on the stack, and the generator
|
||||
// is likely to persist beyond that stack frame.
|
||||
template <typename T>
|
||||
class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
|
||||
class [[nodiscard]] ValuesInIteratorRangeGenerator
|
||||
: public ParamGeneratorInterface<T> {
|
||||
public:
|
||||
template <typename ForwardIterator>
|
||||
ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
|
||||
@@ -395,7 +397,7 @@ void TestNotEmpty(const T&) {}
|
||||
// Stores a parameter value and later creates tests parameterized with that
|
||||
// value.
|
||||
template <class TestClass>
|
||||
class ParameterizedTestFactory : public TestFactoryBase {
|
||||
class [[nodiscard]] ParameterizedTestFactory : public TestFactoryBase {
|
||||
public:
|
||||
typedef typename TestClass::ParamType ParamType;
|
||||
explicit ParameterizedTestFactory(ParamType parameter)
|
||||
@@ -417,7 +419,7 @@ class ParameterizedTestFactory : public TestFactoryBase {
|
||||
// TestMetaFactoryBase is a base class for meta-factories that create
|
||||
// test factories for passing into MakeAndRegisterTestInfo function.
|
||||
template <class ParamType>
|
||||
class TestMetaFactoryBase {
|
||||
class [[nodiscard]] TestMetaFactoryBase {
|
||||
public:
|
||||
virtual ~TestMetaFactoryBase() = default;
|
||||
|
||||
@@ -433,7 +435,7 @@ class TestMetaFactoryBase {
|
||||
// it for each Test/Parameter value combination. Thus it needs meta factory
|
||||
// creator class.
|
||||
template <class TestSuite>
|
||||
class TestMetaFactory
|
||||
class [[nodiscard]] TestMetaFactory
|
||||
: public TestMetaFactoryBase<typename TestSuite::ParamType> {
|
||||
public:
|
||||
using ParamType = typename TestSuite::ParamType;
|
||||
@@ -459,7 +461,7 @@ class TestMetaFactory
|
||||
// in RegisterTests method. The ParameterizeTestSuiteRegistry class holds
|
||||
// a collection of pointers to the ParameterizedTestSuiteInfo objects
|
||||
// and calls RegisterTests() on each of them when asked.
|
||||
class ParameterizedTestSuiteInfoBase {
|
||||
class [[nodiscard]] ParameterizedTestSuiteInfoBase {
|
||||
public:
|
||||
virtual ~ParameterizedTestSuiteInfoBase() = default;
|
||||
|
||||
@@ -502,7 +504,8 @@ GTEST_API_ void InsertSyntheticTestCase(const std::string& name,
|
||||
// test suite. It registers tests with all values generated by all
|
||||
// generators when asked.
|
||||
template <class TestSuite>
|
||||
class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
|
||||
class [[nodiscard]] ParameterizedTestSuiteInfo
|
||||
: public ParameterizedTestSuiteInfoBase {
|
||||
public:
|
||||
// ParamType and GeneratorCreationFunc are private types but are required
|
||||
// for declarations of public methods AddTestPattern() and
|
||||
@@ -529,8 +532,7 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
|
||||
// prefix). test_base_name is the name of an individual test without
|
||||
// parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
|
||||
// test suite base name and DoBar is test base name.
|
||||
void AddTestPattern(const char*,
|
||||
const char* test_base_name,
|
||||
void AddTestPattern(const char*, const char* test_base_name,
|
||||
TestMetaFactoryBase<ParamType>* meta_factory,
|
||||
CodeLocation code_location) {
|
||||
tests_.emplace_back(
|
||||
@@ -688,7 +690,7 @@ using ParameterizedTestCaseInfo = ParameterizedTestSuiteInfo<TestCase>;
|
||||
// ParameterizedTestSuiteInfoBase classes accessed by test suite names. TEST_P
|
||||
// and INSTANTIATE_TEST_SUITE_P macros use it to locate their corresponding
|
||||
// ParameterizedTestSuiteInfo descriptors.
|
||||
class ParameterizedTestSuiteRegistry {
|
||||
class [[nodiscard]] ParameterizedTestSuiteRegistry {
|
||||
public:
|
||||
ParameterizedTestSuiteRegistry() = default;
|
||||
~ParameterizedTestSuiteRegistry() {
|
||||
@@ -762,7 +764,7 @@ class ParameterizedTestSuiteRegistry {
|
||||
// Keep track of what type-parameterized test suite are defined and
|
||||
// where as well as which are intatiated. This allows susequently
|
||||
// identifying suits that are defined but never used.
|
||||
class TypeParameterizedTestSuiteRegistry {
|
||||
class [[nodiscard]] TypeParameterizedTestSuiteRegistry {
|
||||
public:
|
||||
// Add a suite definition
|
||||
void RegisterTestSuite(const char* test_suite_name,
|
||||
@@ -801,7 +803,7 @@ namespace internal {
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4100)
|
||||
|
||||
template <typename... Ts>
|
||||
class ValueArray {
|
||||
class [[nodiscard]] ValueArray {
|
||||
public:
|
||||
explicit ValueArray(Ts... v) : v_(FlatTupleConstructTag{}, std::move(v)...) {}
|
||||
|
||||
@@ -822,7 +824,7 @@ class ValueArray {
|
||||
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4100
|
||||
|
||||
template <typename... T>
|
||||
class CartesianProductGenerator
|
||||
class [[nodiscard]] CartesianProductGenerator
|
||||
: public ParamGeneratorInterface<::std::tuple<T...>> {
|
||||
public:
|
||||
typedef ::std::tuple<T...> ParamType;
|
||||
@@ -939,7 +941,7 @@ class CartesianProductGenerator
|
||||
};
|
||||
|
||||
template <class... Gen>
|
||||
class CartesianProductHolder {
|
||||
class [[nodiscard]] CartesianProductHolder {
|
||||
public:
|
||||
CartesianProductHolder(const Gen&... g) : generators_(g...) {}
|
||||
template <typename... T>
|
||||
@@ -952,11 +954,12 @@ class CartesianProductHolder {
|
||||
std::tuple<Gen...> generators_;
|
||||
};
|
||||
|
||||
template <typename From, typename To>
|
||||
class ParamGeneratorConverter : public ParamGeneratorInterface<To> {
|
||||
template <typename From, typename To, typename Func>
|
||||
class [[nodiscard]] ParamGeneratorConverter
|
||||
: public ParamGeneratorInterface<To> {
|
||||
public:
|
||||
ParamGeneratorConverter(ParamGenerator<From> gen) // NOLINT
|
||||
: generator_(std::move(gen)) {}
|
||||
ParamGeneratorConverter(ParamGenerator<From> gen, Func converter) // NOLINT
|
||||
: generator_(std::move(gen)), converter_(std::move(converter)) {}
|
||||
|
||||
ParamIteratorInterface<To>* Begin() const override {
|
||||
return new Iterator(this, generator_.begin(), generator_.end());
|
||||
@@ -965,13 +968,21 @@ class ParamGeneratorConverter : public ParamGeneratorInterface<To> {
|
||||
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:
|
||||
class Iterator : public ParamIteratorInterface<To> {
|
||||
public:
|
||||
Iterator(const ParamGeneratorInterface<To>* base, ParamIterator<From> it,
|
||||
Iterator(const ParamGeneratorConverter* base, ParamIterator<From> it,
|
||||
ParamIterator<From> 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;
|
||||
|
||||
@@ -980,7 +991,9 @@ class ParamGeneratorConverter : public ParamGeneratorInterface<To> {
|
||||
}
|
||||
void Advance() override {
|
||||
++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 {
|
||||
return new Iterator(*this);
|
||||
@@ -1000,30 +1013,54 @@ class ParamGeneratorConverter : public ParamGeneratorInterface<To> {
|
||||
private:
|
||||
Iterator(const Iterator& other) = default;
|
||||
|
||||
const ParamGeneratorInterface<To>* const base_;
|
||||
const ParamGeneratorConverter* const base_;
|
||||
ParamIterator<From> it_;
|
||||
ParamIterator<From> end_;
|
||||
std::shared_ptr<To> value_;
|
||||
}; // class ParamGeneratorConverter::Iterator
|
||||
|
||||
ParamGenerator<From> generator_;
|
||||
Func converter_;
|
||||
}; // class ParamGeneratorConverter
|
||||
|
||||
template <class Gen>
|
||||
class ParamConverterGenerator {
|
||||
template <class GeneratedT,
|
||||
typename StdFunction =
|
||||
std::function<const GeneratedT&(const GeneratedT&)>>
|
||||
class [[nodiscard]] ParamConverterGenerator {
|
||||
public:
|
||||
ParamConverterGenerator(ParamGenerator<Gen> g) // NOLINT
|
||||
: generator_(std::move(g)) {}
|
||||
ParamConverterGenerator(ParamGenerator<GeneratedT> g) // NOLINT
|
||||
: generator_(std::move(g)), converter_(Identity) {}
|
||||
|
||||
ParamConverterGenerator(ParamGenerator<GeneratedT> g, StdFunction converter)
|
||||
: generator_(std::move(g)), converter_(std::move(converter)) {}
|
||||
|
||||
template <typename T>
|
||||
operator ParamGenerator<T>() const { // NOLINT
|
||||
return ParamGenerator<T>(new ParamGeneratorConverter<Gen, T>(generator_));
|
||||
return ParamGenerator<T>(
|
||||
new ParamGeneratorConverter<GeneratedT, T, StdFunction>(generator_,
|
||||
converter_));
|
||||
}
|
||||
|
||||
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 testing
|
||||
|
||||
|
||||
@@ -119,6 +119,8 @@
|
||||
#define GTEST_OS_NXP_QN9090 1
|
||||
#elif defined(NRF52)
|
||||
#define GTEST_OS_NRF52 1
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
#define GTEST_OS_EMSCRIPTEN 1
|
||||
#endif // __CYGWIN__
|
||||
|
||||
#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
|
||||
|
||||
@@ -194,26 +194,12 @@
|
||||
//
|
||||
// Macros for basic C++ coding:
|
||||
// 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
|
||||
// suppressed (constant conditional).
|
||||
// GTEST_INTENTIONAL_CONST_COND_POP_ - finish code section where MSVC C4127
|
||||
// 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>
|
||||
// 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_HAS_CXXABI_H_ - 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.
|
||||
// Int32FromGTestEnv() - parses an int32_t 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
|
||||
// potentially be used as an #include guard.
|
||||
@@ -275,8 +256,8 @@
|
||||
#endif
|
||||
|
||||
#if !defined(GTEST_INTERNAL_CPLUSPLUS_LANG) || \
|
||||
GTEST_INTERNAL_CPLUSPLUS_LANG < 201402L
|
||||
#error C++ versions less than C++14 are not supported.
|
||||
GTEST_INTERNAL_CPLUSPLUS_LANG < 201703L
|
||||
#error C++ versions less than C++17 are not supported.
|
||||
#endif
|
||||
|
||||
// MSVC >= 19.11 (VS 2017 Update 3) supports __has_include.
|
||||
@@ -288,10 +269,14 @@
|
||||
|
||||
// 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.
|
||||
#if GTEST_INTERNAL_CPLUSPLUS_LANG >= 202002L && \
|
||||
(!defined(__has_include) || GTEST_INTERNAL_HAS_INCLUDE(<version>))
|
||||
#include <version> // C++20 and later
|
||||
#elif (!defined(__has_include) || GTEST_INTERNAL_HAS_INCLUDE(<ciso646>))
|
||||
//
|
||||
// GCC15 warns that <ciso646> is deprecated in C++17 and suggests using
|
||||
// <version> instead, even though <version> is not available in C++17 mode prior
|
||||
// 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
|
||||
#endif
|
||||
|
||||
@@ -308,9 +293,10 @@
|
||||
#include <limits>
|
||||
#include <locale>
|
||||
#include <memory>
|
||||
// #include <mutex> // Guarded by GTEST_IS_THREADSAFE below
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
// #include <mutex> // Guarded by GTEST_IS_THREADSAFE below
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
@@ -378,18 +364,24 @@
|
||||
#define GTEST_DISABLE_MSC_WARNINGS_POP_()
|
||||
#endif
|
||||
|
||||
// Clang on Windows does not understand MSVC's pragma warning.
|
||||
// We need clang-specific way to disable function deprecation warning.
|
||||
#ifdef __clang__
|
||||
#define GTEST_DISABLE_MSC_DEPRECATED_PUSH_() \
|
||||
// Pragmas to disable function deprecation warnings.
|
||||
#if defined(__clang__)
|
||||
#define GTEST_DISABLE_DEPRECATED_PUSH_() \
|
||||
_Pragma("clang diagnostic push") \
|
||||
_Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") \
|
||||
_Pragma("clang diagnostic ignored \"-Wdeprecated-implementations\"")
|
||||
#define GTEST_DISABLE_MSC_DEPRECATED_POP_() _Pragma("clang diagnostic pop")
|
||||
#define GTEST_DISABLE_DEPRECATED_POP_() _Pragma("clang diagnostic pop")
|
||||
#elif defined(__GNUC__)
|
||||
#define GTEST_DISABLE_DEPRECATED_PUSH_() \
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
|
||||
#define GTEST_DISABLE_DEPRECATED_POP_() _Pragma("GCC diagnostic pop")
|
||||
#elif defined(_MSC_VER)
|
||||
#define GTEST_DISABLE_DEPRECATED_PUSH_() GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996)
|
||||
#define GTEST_DISABLE_DEPRECATED_POP_() GTEST_DISABLE_MSC_WARNINGS_POP_()
|
||||
#else
|
||||
#define GTEST_DISABLE_MSC_DEPRECATED_PUSH_() \
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996)
|
||||
#define GTEST_DISABLE_MSC_DEPRECATED_POP_() GTEST_DISABLE_MSC_WARNINGS_POP_()
|
||||
#define GTEST_DISABLE_DEPRECATED_PUSH_()
|
||||
#define GTEST_DISABLE_DEPRECATED_POP_()
|
||||
#endif
|
||||
|
||||
// Brings in definitions for functions used in the testing::internal::posix
|
||||
@@ -508,22 +500,82 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
|
||||
#endif // defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
#endif // GTEST_HAS_EXCEPTIONS
|
||||
|
||||
#ifndef GTEST_HAS_STD_WSTRING
|
||||
// The user didn't tell us whether ::std::wstring is available, so we need
|
||||
// to figure it out.
|
||||
// Cygwin 1.7 and below doesn't support ::std::wstring.
|
||||
// Solaris' libc++ doesn't support it either. Android has
|
||||
// no support for it at least as recent as Froyo (2.2).
|
||||
#if (!(defined(GTEST_OS_LINUX_ANDROID) || defined(GTEST_OS_CYGWIN) || \
|
||||
defined(GTEST_OS_SOLARIS) || defined(GTEST_OS_HAIKU) || \
|
||||
defined(GTEST_OS_ESP32) || defined(GTEST_OS_ESP8266) || \
|
||||
defined(GTEST_OS_XTENSA) || defined(GTEST_OS_QURT) || \
|
||||
defined(GTEST_OS_NXP_QN9090) || defined(GTEST_OS_NRF52)))
|
||||
#define GTEST_HAS_STD_WSTRING 1
|
||||
// MSVC either defines wchar_t as a typedef of unsigned short, or as a native
|
||||
// type (in which case, it defines _NATIVE_WCHAR_T_DEFINED). When wchar_t is a
|
||||
// typedef, defining an overload for const wchar_t* would cause unsigned short*
|
||||
// be printed as a wide string, possibly causing invalid memory accesses, so we
|
||||
// omit wchar_t overloads in that case.
|
||||
#if defined(_MSC_VER) && !defined(_NATIVE_WCHAR_T_DEFINED)
|
||||
#define GTEST_HAS_NATIVE_WCHAR 0
|
||||
#else
|
||||
#define GTEST_HAS_STD_WSTRING 0
|
||||
#define GTEST_HAS_NATIVE_WCHAR 1
|
||||
#endif
|
||||
|
||||
// 1. Calculate default GTEST_HAS_STD_WSTRING values based on STL capabilities.
|
||||
#if defined(_MSVC_STL_VERSION)
|
||||
// Microsoft's STL implementation always supports ::std::wstring.
|
||||
#define GTEST_HAS_STD_WSTRING_DEFAULT 1
|
||||
|
||||
#elif defined(_LIBCPP_VERSION)
|
||||
// Modern libc++ always defines _LIBCPP_HAS_WIDE_CHARACTERS; its value
|
||||
// determines whether wide characters are supported.
|
||||
// Older libc++ omits a definition for _LIBCPP_HAS_NO_WIDE_CHARACTERS when wide
|
||||
// characters are supported.
|
||||
#if (defined(_LIBCPP_HAS_WIDE_CHARACTERS) && !_LIBCPP_HAS_WIDE_CHARACTERS) || \
|
||||
defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS)
|
||||
#define GTEST_HAS_STD_WSTRING_DEFAULT 0
|
||||
#else
|
||||
#define GTEST_HAS_STD_WSTRING_DEFAULT 1
|
||||
#endif
|
||||
|
||||
#elif defined(__GLIBCXX__)
|
||||
#if defined(_GLIBCXX_USE_WCHAR_T) && _GLIBCXX_USE_WCHAR_T
|
||||
#define GTEST_HAS_STD_WSTRING_DEFAULT 1
|
||||
#else
|
||||
#define GTEST_HAS_STD_WSTRING_DEFAULT 0
|
||||
#endif
|
||||
|
||||
#else
|
||||
// Unknown standard library implementation; fall back looking at the OS.
|
||||
//
|
||||
// Always let the user override the defaults in this case; they might have more
|
||||
// information about what's supported than we do.
|
||||
#if defined(GTEST_OS_LINUX_ANDROID)
|
||||
// Android started supporting std::wstring with API Level 21 (Lollipop).
|
||||
#define GTEST_HAS_STD_WSTRING_DEFAULT (__ANDROID_API__ >= 21)
|
||||
// The following platforms are known not to support ::std::wstring; assume it's
|
||||
// supported on all others.
|
||||
//
|
||||
// Cygwin 1.7 and below doesn't support ::std::wstring.
|
||||
// Solaris' libc++ doesn't support it either.
|
||||
#elif defined(GTEST_OS_CYGWIN) || defined(GTEST_OS_SOLARIS) || \
|
||||
defined(GTEST_OS_HAIKU) || defined(GTEST_OS_ESP32) || \
|
||||
defined(GTEST_OS_ESP8266) || defined(GTEST_OS_XTENSA) || \
|
||||
defined(GTEST_OS_QURT) || defined(GTEST_OS_NXP_QN9090) || \
|
||||
defined(GTEST_OS_NRF52)
|
||||
#define GTEST_HAS_STD_WSTRING_DEFAULT 0
|
||||
#else
|
||||
#define GTEST_HAS_STD_WSTRING_DEFAULT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// 2. Validate explicit user overrides (if user passed -DGTEST_HAS_*=1) against
|
||||
// what the standard library implementation tells us it supports.
|
||||
#if defined(GTEST_HAS_STD_WSTRING) && GTEST_HAS_STD_WSTRING
|
||||
#if defined(_LIBCPP_VERSION) && \
|
||||
((defined(_LIBCPP_HAS_WIDE_CHARACTERS) && !_LIBCPP_HAS_WIDE_CHARACTERS) || \
|
||||
defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS))
|
||||
#error Cannot explicitly enable GTEST_HAS_STD_WSTRING without libc++ wide character support.
|
||||
#elif defined(__GLIBCXX__) && \
|
||||
!(defined(_GLIBCXX_USE_WCHAR_T) && _GLIBCXX_USE_WCHAR_T)
|
||||
#error Cannot explicitly enable GTEST_HAS_STD_WSTRING without libstdc++ wide character support.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// 3. Set final values if not explicitly overridden by user
|
||||
#if !defined(GTEST_HAS_STD_WSTRING)
|
||||
#define GTEST_HAS_STD_WSTRING GTEST_HAS_STD_WSTRING_DEFAULT
|
||||
#endif
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
|
||||
#ifndef GTEST_HAS_FILE_SYSTEM
|
||||
// Most platforms support a file system.
|
||||
@@ -608,7 +660,8 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
|
||||
defined(GTEST_OS_DRAGONFLY) || defined(GTEST_OS_GNU_KFREEBSD) || \
|
||||
defined(GTEST_OS_OPENBSD) || defined(GTEST_OS_HAIKU) || \
|
||||
defined(GTEST_OS_GNU_HURD) || defined(GTEST_OS_SOLARIS) || \
|
||||
defined(GTEST_OS_AIX) || defined(GTEST_OS_ZOS))
|
||||
defined(GTEST_OS_AIX) || defined(GTEST_OS_ZOS) || \
|
||||
(defined(GTEST_OS_EMSCRIPTEN) && defined(__EMSCRIPTEN_PTHREADS__)))
|
||||
#define GTEST_HAS_PTHREAD 1
|
||||
#else
|
||||
#define GTEST_HAS_PTHREAD 0
|
||||
@@ -679,12 +732,22 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
|
||||
defined(GTEST_OS_NETBSD) || defined(GTEST_OS_FUCHSIA) || \
|
||||
defined(GTEST_OS_DRAGONFLY) || defined(GTEST_OS_GNU_KFREEBSD) || \
|
||||
defined(GTEST_OS_HAIKU) || defined(GTEST_OS_GNU_HURD))
|
||||
|
||||
// Death tests require a file system to work properly.
|
||||
#if GTEST_HAS_FILE_SYSTEM
|
||||
#define GTEST_HAS_DEATH_TEST 1
|
||||
#endif // GTEST_HAS_FILE_SYSTEM
|
||||
#endif
|
||||
|
||||
// Determines whether the Premature Exit file can be created.
|
||||
// Created by default when Death tests are supported, but other platforms can
|
||||
// use the Premature exit file without Death test support (e.g. for detecting
|
||||
// crashes).
|
||||
#if GTEST_HAS_DEATH_TEST || \
|
||||
(defined(GTEST_OS_EMSCRIPTEN) && GTEST_HAS_FILE_SYSTEM)
|
||||
#define GTEST_INTERNAL_HAS_PREMATURE_EXIT_FILE 1
|
||||
#endif
|
||||
|
||||
// Determines whether to support type-driven tests.
|
||||
|
||||
// Typed tests need <typeinfo> and variadic macros, which GCC, VC++ 8.0,
|
||||
@@ -772,25 +835,6 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
|
||||
#define GTEST_HAVE_FEATURE_(x) 0
|
||||
#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.
|
||||
#if GTEST_HAVE_ATTRIBUTE_(format) && defined(__MINGW_PRINTF_FORMAT)
|
||||
// MinGW has two different printf implementations. Ensure the format macro
|
||||
@@ -805,17 +849,6 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
|
||||
#define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check)
|
||||
#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
|
||||
// constant. In some contexts this warning is false positive and needs to be
|
||||
// suppressed. Use the following two macros in such cases:
|
||||
@@ -867,11 +900,13 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
|
||||
#ifndef GTEST_API_
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if defined(GTEST_LINKED_AS_SHARED_LIBRARY) && GTEST_LINKED_AS_SHARED_LIBRARY
|
||||
#define GTEST_API_ __declspec(dllimport)
|
||||
#elif defined(GTEST_CREATE_SHARED_LIBRARY) && GTEST_CREATE_SHARED_LIBRARY
|
||||
#if defined(GTEST_CREATE_SHARED_LIBRARY) && GTEST_CREATE_SHARED_LIBRARY
|
||||
#define GTEST_API_ __declspec(dllexport)
|
||||
#elif defined(GTEST_LINKED_AS_SHARED_LIBRARY) && GTEST_LINKED_AS_SHARED_LIBRARY
|
||||
#define GTEST_API_ __declspec(dllimport)
|
||||
#endif
|
||||
#elif GTEST_INTERNAL_HAVE_CPP_ATTRIBUTE(gnu::visibility)
|
||||
#define GTEST_API_ [[gnu::visibility("default")]]
|
||||
#elif GTEST_HAVE_ATTRIBUTE_(visibility)
|
||||
#define GTEST_API_ __attribute__((visibility("default")))
|
||||
#endif // _MSC_VER
|
||||
@@ -962,7 +997,7 @@ namespace internal {
|
||||
// A secret type that Google Test users don't know about. It has no
|
||||
// accessible constructors on purpose. Therefore it's impossible to create a
|
||||
// Secret object, which is what we want.
|
||||
class Secret {
|
||||
class [[nodiscard]] Secret {
|
||||
Secret(const Secret&) = delete;
|
||||
};
|
||||
|
||||
@@ -975,21 +1010,21 @@ GTEST_API_ bool IsTrue(bool condition);
|
||||
#ifdef GTEST_USES_RE2
|
||||
|
||||
// This is almost `using RE = ::RE2`, except it is copy-constructible, and it
|
||||
// needs to disambiguate the `std::string`, `absl::string_view`, and `const
|
||||
// needs to disambiguate the `std::string`, `std::string_view`, and `const
|
||||
// char*` constructors.
|
||||
class GTEST_API_ RE {
|
||||
class GTEST_API_ [[nodiscard]] RE {
|
||||
public:
|
||||
RE(absl::string_view regex) : regex_(regex) {} // NOLINT
|
||||
RE(const char* regex) : RE(absl::string_view(regex)) {} // NOLINT
|
||||
RE(const std::string& regex) : RE(absl::string_view(regex)) {} // NOLINT
|
||||
RE(std::string_view regex) : regex_(regex) {} // NOLINT
|
||||
RE(const char* regex) : RE(std::string_view(regex)) {} // NOLINT
|
||||
RE(const std::string& regex) : RE(std::string_view(regex)) {} // NOLINT
|
||||
RE(const RE& other) : RE(other.pattern()) {}
|
||||
|
||||
const std::string& pattern() const { return regex_.pattern(); }
|
||||
|
||||
static bool FullMatch(absl::string_view str, const RE& re) {
|
||||
static bool FullMatch(std::string_view str, const RE& re) {
|
||||
return RE2::FullMatch(str, re.regex_);
|
||||
}
|
||||
static bool PartialMatch(absl::string_view str, const RE& re) {
|
||||
static bool PartialMatch(std::string_view str, const RE& re) {
|
||||
return RE2::PartialMatch(str, re.regex_);
|
||||
}
|
||||
|
||||
@@ -1003,7 +1038,7 @@ GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
|
||||
|
||||
// A simple C++ wrapper for <regex.h>. It uses the POSIX Extended
|
||||
// Regular Expression syntax.
|
||||
class GTEST_API_ RE {
|
||||
class GTEST_API_ [[nodiscard]] RE {
|
||||
public:
|
||||
// A copy constructor is required by the Standard to initialize object
|
||||
// references from r-values.
|
||||
@@ -1072,7 +1107,7 @@ enum GTestLogSeverity { GTEST_INFO, GTEST_WARNING, GTEST_ERROR, GTEST_FATAL };
|
||||
// Formats log entry severity, provides a stream object for streaming the
|
||||
// log message, and terminates the message with a newline when going out of
|
||||
// scope.
|
||||
class GTEST_API_ GTestLog {
|
||||
class GTEST_API_ [[nodiscard]] GTestLog {
|
||||
public:
|
||||
GTestLog(GTestLogSeverity severity, const char* file, int line);
|
||||
|
||||
@@ -1235,7 +1270,7 @@ void ClearInjectableArgvs();
|
||||
#ifdef GTEST_OS_WINDOWS
|
||||
// Provides leak-safe Windows kernel handle ownership.
|
||||
// Used in death tests and in threading support.
|
||||
class GTEST_API_ AutoHandle {
|
||||
class GTEST_API_ [[nodiscard]] AutoHandle {
|
||||
public:
|
||||
// Assume that Win32 HANDLE type is equivalent to void*. Doing so allows us to
|
||||
// avoid including <windows.h> in this header file. Including <windows.h> is
|
||||
@@ -1269,9 +1304,6 @@ class GTEST_API_ AutoHandle {
|
||||
// Nothing to do here.
|
||||
|
||||
#else
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
|
||||
/* class A needs to have dll-interface to be used by clients of class B */)
|
||||
|
||||
// Allows a controller thread to pause execution of newly created
|
||||
// threads until notified. Instances of this class must be created
|
||||
// and destroyed in the controller thread.
|
||||
@@ -1279,7 +1311,40 @@ GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
|
||||
// This class is only for testing Google Test's own constructs. Do not
|
||||
// use it in user tests, either directly or indirectly.
|
||||
// TODO(b/203539622): Replace unconditionally with absl::Notification.
|
||||
class GTEST_API_ Notification {
|
||||
#ifdef GTEST_OS_WINDOWS_MINGW
|
||||
// GCC version < 13 with the win32 thread model does not provide std::mutex and
|
||||
// std::condition_variable in the <mutex> and <condition_variable> headers. So
|
||||
// we implement the Notification class using a Windows manual-reset event. See
|
||||
// https://gcc.gnu.org/gcc-13/changes.html#windows.
|
||||
class GTEST_API_ [[nodiscard]] Notification {
|
||||
public:
|
||||
Notification();
|
||||
Notification(const Notification&) = delete;
|
||||
Notification& operator=(const Notification&) = delete;
|
||||
~Notification();
|
||||
|
||||
// Notifies all threads created with this notification to start. Must
|
||||
// be called from the controller thread.
|
||||
void Notify();
|
||||
|
||||
// Blocks until the controller thread notifies. Must be called from a test
|
||||
// thread.
|
||||
void WaitForNotification();
|
||||
|
||||
private:
|
||||
// Assume that Win32 HANDLE type is equivalent to void*. Doing so allows us to
|
||||
// avoid including <windows.h> in this header file. Including <windows.h> is
|
||||
// undesirable because it defines a lot of symbols and macros that tend to
|
||||
// conflict with client code. This assumption is verified by
|
||||
// WindowsTypesTest.HANDLEIsVoidStar.
|
||||
typedef void* Handle;
|
||||
Handle event_;
|
||||
};
|
||||
#else
|
||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
|
||||
/* class A needs to have dll-interface to be used by clients of class B */)
|
||||
|
||||
class GTEST_API_ [[nodiscard]] Notification {
|
||||
public:
|
||||
Notification() : notified_(false) {}
|
||||
Notification(const Notification&) = delete;
|
||||
@@ -1306,6 +1371,7 @@ class GTEST_API_ Notification {
|
||||
bool notified_;
|
||||
};
|
||||
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||
#endif // GTEST_OS_WINDOWS_MINGW
|
||||
#endif // GTEST_HAS_NOTIFICATION_
|
||||
|
||||
// On MinGW, we can have both GTEST_OS_WINDOWS and GTEST_HAS_PTHREAD
|
||||
@@ -1318,7 +1384,7 @@ GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
|
||||
// in order to call its Run(). Introducing ThreadWithParamBase as a
|
||||
// non-templated base class for ThreadWithParam allows us to bypass this
|
||||
// problem.
|
||||
class ThreadWithParamBase {
|
||||
class [[nodiscard]] ThreadWithParamBase {
|
||||
public:
|
||||
virtual ~ThreadWithParamBase() = default;
|
||||
virtual void Run() = 0;
|
||||
@@ -1348,7 +1414,7 @@ extern "C" inline void* ThreadFuncWithCLinkage(void* thread) {
|
||||
// These classes are only for testing Google Test's own constructs. Do
|
||||
// not use them in user tests, either directly or indirectly.
|
||||
template <typename T>
|
||||
class ThreadWithParam : public ThreadWithParamBase {
|
||||
class [[nodiscard]] ThreadWithParam : public ThreadWithParamBase {
|
||||
public:
|
||||
typedef void UserThreadFunc(T);
|
||||
|
||||
@@ -1414,7 +1480,7 @@ class ThreadWithParam : public ThreadWithParamBase {
|
||||
// GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex);
|
||||
//
|
||||
// (A non-static Mutex is defined/declared in the usual way).
|
||||
class GTEST_API_ Mutex {
|
||||
class GTEST_API_ [[nodiscard]] Mutex {
|
||||
public:
|
||||
enum MutexType { kStatic = 0, kDynamic = 1 };
|
||||
// We rely on kStaticMutex being 0 as it is to what the linker initializes
|
||||
@@ -1430,9 +1496,9 @@ class GTEST_API_ Mutex {
|
||||
Mutex();
|
||||
~Mutex();
|
||||
|
||||
void Lock();
|
||||
void lock();
|
||||
|
||||
void Unlock();
|
||||
void unlock();
|
||||
|
||||
// Does nothing if the current thread holds the mutex. Otherwise, crashes
|
||||
// with high probability.
|
||||
@@ -1467,14 +1533,13 @@ class GTEST_API_ Mutex {
|
||||
// platforms. That macro is used as a defensive measure to prevent against
|
||||
// inadvertent misuses of MutexLock like "MutexLock(&mu)" rather than
|
||||
// "MutexLock l(&mu)". Hence the typedef trick below.
|
||||
class GTestMutexLock {
|
||||
class [[nodiscard]] GTestMutexLock {
|
||||
public:
|
||||
explicit GTestMutexLock(Mutex* mutex) : mutex_(mutex) { mutex_->Lock(); }
|
||||
|
||||
~GTestMutexLock() { mutex_->Unlock(); }
|
||||
explicit GTestMutexLock(Mutex& mutex) : mutex_(mutex) { mutex_.lock(); }
|
||||
~GTestMutexLock() { mutex_.unlock(); }
|
||||
|
||||
private:
|
||||
Mutex* const mutex_;
|
||||
Mutex& mutex_;
|
||||
|
||||
GTestMutexLock(const GTestMutexLock&) = delete;
|
||||
GTestMutexLock& operator=(const GTestMutexLock&) = delete;
|
||||
@@ -1484,14 +1549,14 @@ typedef GTestMutexLock MutexLock;
|
||||
|
||||
// Base class for ValueHolder<T>. Allows a caller to hold and delete a value
|
||||
// without knowing its type.
|
||||
class ThreadLocalValueHolderBase {
|
||||
class [[nodiscard]] ThreadLocalValueHolderBase {
|
||||
public:
|
||||
virtual ~ThreadLocalValueHolderBase() {}
|
||||
virtual ~ThreadLocalValueHolderBase() = default;
|
||||
};
|
||||
|
||||
// Provides a way for a thread to send notifications to a ThreadLocal
|
||||
// regardless of its parameter type.
|
||||
class ThreadLocalBase {
|
||||
class [[nodiscard]] ThreadLocalBase {
|
||||
public:
|
||||
// Creates a new ValueHolder<T> object holding a default value passed to
|
||||
// this ThreadLocal<T>'s constructor and returns it. It is the caller's
|
||||
@@ -1500,8 +1565,8 @@ class ThreadLocalBase {
|
||||
virtual ThreadLocalValueHolderBase* NewValueForCurrentThread() const = 0;
|
||||
|
||||
protected:
|
||||
ThreadLocalBase() {}
|
||||
virtual ~ThreadLocalBase() {}
|
||||
ThreadLocalBase() = default;
|
||||
virtual ~ThreadLocalBase() = default;
|
||||
|
||||
private:
|
||||
ThreadLocalBase(const ThreadLocalBase&) = delete;
|
||||
@@ -1511,7 +1576,7 @@ class ThreadLocalBase {
|
||||
// Maps a thread to a set of ThreadLocals that have values instantiated on that
|
||||
// thread and notifies them when the thread exits. A ThreadLocal instance is
|
||||
// expected to persist until all threads it has values on have terminated.
|
||||
class GTEST_API_ ThreadLocalRegistry {
|
||||
class GTEST_API_ [[nodiscard]] ThreadLocalRegistry {
|
||||
public:
|
||||
// Registers thread_local_instance as having value on the current thread.
|
||||
// Returns a value that can be used to identify the thread from other threads.
|
||||
@@ -1523,14 +1588,14 @@ class GTEST_API_ ThreadLocalRegistry {
|
||||
const ThreadLocalBase* thread_local_instance);
|
||||
};
|
||||
|
||||
class GTEST_API_ ThreadWithParamBase {
|
||||
class GTEST_API_ [[nodiscard]] ThreadWithParamBase {
|
||||
public:
|
||||
void Join();
|
||||
|
||||
protected:
|
||||
class Runnable {
|
||||
public:
|
||||
virtual ~Runnable() {}
|
||||
virtual ~Runnable() = default;
|
||||
virtual void Run() = 0;
|
||||
};
|
||||
|
||||
@@ -1543,20 +1608,20 @@ class GTEST_API_ ThreadWithParamBase {
|
||||
|
||||
// Helper class for testing Google Test's multi-threading constructs.
|
||||
template <typename T>
|
||||
class ThreadWithParam : public ThreadWithParamBase {
|
||||
class [[nodiscard]] ThreadWithParam : public ThreadWithParamBase {
|
||||
public:
|
||||
typedef void UserThreadFunc(T);
|
||||
|
||||
ThreadWithParam(UserThreadFunc* func, T param, Notification* thread_can_start)
|
||||
: ThreadWithParamBase(new RunnableImpl(func, param), thread_can_start) {}
|
||||
virtual ~ThreadWithParam() {}
|
||||
~ThreadWithParam() override = default;
|
||||
|
||||
private:
|
||||
class RunnableImpl : public Runnable {
|
||||
public:
|
||||
RunnableImpl(UserThreadFunc* func, T param) : func_(func), param_(param) {}
|
||||
virtual ~RunnableImpl() {}
|
||||
virtual void Run() { func_(param_); }
|
||||
~RunnableImpl() override = default;
|
||||
void Run() override { func_(param_); }
|
||||
|
||||
private:
|
||||
UserThreadFunc* const func_;
|
||||
@@ -1598,7 +1663,7 @@ class ThreadWithParam : public ThreadWithParamBase {
|
||||
// object managed by Google Test will be leaked as long as all threads
|
||||
// using Google Test have exited when main() returns.
|
||||
template <typename T>
|
||||
class ThreadLocal : public ThreadLocalBase {
|
||||
class [[nodiscard]] ThreadLocal : public ThreadLocalBase {
|
||||
public:
|
||||
ThreadLocal() : default_factory_(new DefaultValueHolderFactory()) {}
|
||||
explicit ThreadLocal(const T& value)
|
||||
@@ -1639,8 +1704,8 @@ class ThreadLocal : public ThreadLocalBase {
|
||||
|
||||
class ValueHolderFactory {
|
||||
public:
|
||||
ValueHolderFactory() {}
|
||||
virtual ~ValueHolderFactory() {}
|
||||
ValueHolderFactory() = default;
|
||||
virtual ~ValueHolderFactory() = default;
|
||||
virtual ValueHolder* MakeNewHolder() const = 0;
|
||||
|
||||
private:
|
||||
@@ -1650,7 +1715,7 @@ class ThreadLocal : public ThreadLocalBase {
|
||||
|
||||
class DefaultValueHolderFactory : public ValueHolderFactory {
|
||||
public:
|
||||
DefaultValueHolderFactory() {}
|
||||
DefaultValueHolderFactory() = default;
|
||||
ValueHolder* MakeNewHolder() const override { return new ValueHolder(); }
|
||||
|
||||
private:
|
||||
@@ -1683,17 +1748,17 @@ class ThreadLocal : public ThreadLocalBase {
|
||||
#elif GTEST_HAS_PTHREAD
|
||||
|
||||
// MutexBase and Mutex implement mutex on pthreads-based platforms.
|
||||
class MutexBase {
|
||||
class [[nodiscard]] MutexBase {
|
||||
public:
|
||||
// Acquires this mutex.
|
||||
void Lock() {
|
||||
void lock() {
|
||||
GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_));
|
||||
owner_ = pthread_self();
|
||||
has_owner_ = true;
|
||||
}
|
||||
|
||||
// Releases this mutex.
|
||||
void Unlock() {
|
||||
void unlock() {
|
||||
// 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
|
||||
// the caller's responsibility to ensure that the current thread holds the
|
||||
@@ -1741,7 +1806,7 @@ class MutexBase {
|
||||
|
||||
// The Mutex class can only be used for mutexes created at runtime. It
|
||||
// shares its API with MutexBase otherwise.
|
||||
class Mutex : public MutexBase {
|
||||
class [[nodiscard]] Mutex : public MutexBase {
|
||||
public:
|
||||
Mutex() {
|
||||
GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, nullptr));
|
||||
@@ -1759,14 +1824,13 @@ class Mutex : public MutexBase {
|
||||
// platforms. That macro is used as a defensive measure to prevent against
|
||||
// inadvertent misuses of MutexLock like "MutexLock(&mu)" rather than
|
||||
// "MutexLock l(&mu)". Hence the typedef trick below.
|
||||
class GTestMutexLock {
|
||||
class [[nodiscard]] GTestMutexLock {
|
||||
public:
|
||||
explicit GTestMutexLock(MutexBase* mutex) : mutex_(mutex) { mutex_->Lock(); }
|
||||
|
||||
~GTestMutexLock() { mutex_->Unlock(); }
|
||||
explicit GTestMutexLock(MutexBase& mutex) : mutex_(mutex) { mutex_.lock(); }
|
||||
~GTestMutexLock() { mutex_.unlock(); }
|
||||
|
||||
private:
|
||||
MutexBase* const mutex_;
|
||||
MutexBase& mutex_;
|
||||
|
||||
GTestMutexLock(const GTestMutexLock&) = delete;
|
||||
GTestMutexLock& operator=(const GTestMutexLock&) = delete;
|
||||
@@ -1780,7 +1844,7 @@ typedef GTestMutexLock MutexLock;
|
||||
// C-linkage. Therefore it cannot be templatized to access
|
||||
// ThreadLocal<T>. Hence the need for class
|
||||
// ThreadLocalValueHolderBase.
|
||||
class GTEST_API_ ThreadLocalValueHolderBase {
|
||||
class GTEST_API_ [[nodiscard]] ThreadLocalValueHolderBase {
|
||||
public:
|
||||
virtual ~ThreadLocalValueHolderBase() = default;
|
||||
};
|
||||
@@ -1793,7 +1857,7 @@ extern "C" inline void DeleteThreadLocalValue(void* value_holder) {
|
||||
|
||||
// Implements thread-local storage on pthreads-based systems.
|
||||
template <typename T>
|
||||
class GTEST_API_ ThreadLocal {
|
||||
class GTEST_API_ [[nodiscard]] ThreadLocal {
|
||||
public:
|
||||
ThreadLocal()
|
||||
: key_(CreateKey()), default_factory_(new DefaultValueHolderFactory()) {}
|
||||
@@ -1906,11 +1970,11 @@ class GTEST_API_ ThreadLocal {
|
||||
// mutex is not supported - using Google Test in multiple threads is not
|
||||
// supported on such platforms.
|
||||
|
||||
class Mutex {
|
||||
class [[nodiscard]] Mutex {
|
||||
public:
|
||||
Mutex() {}
|
||||
void Lock() {}
|
||||
void Unlock() {}
|
||||
void lock() {}
|
||||
void unlock() {}
|
||||
void AssertHeld() const {}
|
||||
};
|
||||
|
||||
@@ -1924,15 +1988,15 @@ class Mutex {
|
||||
// platforms. That macro is used as a defensive measure to prevent against
|
||||
// inadvertent misuses of MutexLock like "MutexLock(&mu)" rather than
|
||||
// "MutexLock l(&mu)". Hence the typedef trick below.
|
||||
class GTestMutexLock {
|
||||
class [[nodiscard]] GTestMutexLock {
|
||||
public:
|
||||
explicit GTestMutexLock(Mutex*) {} // NOLINT
|
||||
explicit GTestMutexLock(Mutex&) {} // NOLINT
|
||||
};
|
||||
|
||||
typedef GTestMutexLock MutexLock;
|
||||
|
||||
template <typename T>
|
||||
class GTEST_API_ ThreadLocal {
|
||||
class GTEST_API_ [[nodiscard]] ThreadLocal {
|
||||
public:
|
||||
ThreadLocal() : value_() {}
|
||||
explicit ThreadLocal(const T& value) : value_(value) {}
|
||||
@@ -2122,7 +2186,7 @@ inline int IsATTY(int fd) {
|
||||
|
||||
// Functions deprecated by MSVC 8.0.
|
||||
|
||||
GTEST_DISABLE_MSC_DEPRECATED_PUSH_()
|
||||
GTEST_DISABLE_DEPRECATED_PUSH_()
|
||||
|
||||
// ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and
|
||||
// StrError() aren't needed on Windows CE at this time and thus not
|
||||
@@ -2184,7 +2248,7 @@ inline const char* GetEnv(const char* name) {
|
||||
#endif
|
||||
}
|
||||
|
||||
GTEST_DISABLE_MSC_DEPRECATED_POP_()
|
||||
GTEST_DISABLE_DEPRECATED_POP_()
|
||||
|
||||
#ifdef GTEST_OS_WINDOWS_MOBILE
|
||||
// Windows CE has no C library. The abort() function is used in
|
||||
@@ -2240,7 +2304,7 @@ constexpr BiggestInt kMaxBiggestInt = (std::numeric_limits<BiggestInt>::max)();
|
||||
// needs. Other types can be easily added in the future if need
|
||||
// arises.
|
||||
template <size_t size>
|
||||
class TypeWithSize {
|
||||
class [[nodiscard]] TypeWithSize {
|
||||
public:
|
||||
// This prevents the user from using TypeWithSize<N> with incorrect
|
||||
// values of N.
|
||||
@@ -2249,7 +2313,7 @@ class TypeWithSize {
|
||||
|
||||
// The specialization for size 4.
|
||||
template <>
|
||||
class TypeWithSize<4> {
|
||||
class [[nodiscard]] TypeWithSize<4> {
|
||||
public:
|
||||
using Int = std::int32_t;
|
||||
using UInt = std::uint32_t;
|
||||
@@ -2257,7 +2321,7 @@ class TypeWithSize<4> {
|
||||
|
||||
// The specialization for size 8.
|
||||
template <>
|
||||
class TypeWithSize<8> {
|
||||
class [[nodiscard]] TypeWithSize<8> {
|
||||
public:
|
||||
using Int = std::int64_t;
|
||||
using UInt = std::uint64_t;
|
||||
@@ -2287,11 +2351,11 @@ using TimeInMillis = int64_t; // Represents time in milliseconds.
|
||||
|
||||
// Macros for declaring flags.
|
||||
#define GTEST_DECLARE_bool_(name) \
|
||||
ABSL_DECLARE_FLAG(bool, GTEST_FLAG_NAME_(name))
|
||||
GTEST_API_ ABSL_DECLARE_FLAG(bool, GTEST_FLAG_NAME_(name))
|
||||
#define GTEST_DECLARE_int32_(name) \
|
||||
ABSL_DECLARE_FLAG(int32_t, GTEST_FLAG_NAME_(name))
|
||||
GTEST_API_ ABSL_DECLARE_FLAG(int32_t, GTEST_FLAG_NAME_(name))
|
||||
#define GTEST_DECLARE_string_(name) \
|
||||
ABSL_DECLARE_FLAG(std::string, GTEST_FLAG_NAME_(name))
|
||||
GTEST_API_ ABSL_DECLARE_FLAG(std::string, GTEST_FLAG_NAME_(name))
|
||||
|
||||
#define GTEST_FLAG_SAVER_ ::absl::FlagSaver
|
||||
|
||||
@@ -2305,22 +2369,29 @@ using TimeInMillis = int64_t; // Represents time in milliseconds.
|
||||
|
||||
// Macros for defining flags.
|
||||
#define GTEST_DEFINE_bool_(name, default_val, doc) \
|
||||
GTEST_DECLARE_bool_(name); \
|
||||
namespace testing { \
|
||||
GTEST_API_ bool GTEST_FLAG(name) = (default_val); \
|
||||
} \
|
||||
static_assert(true, "no-op to require trailing semicolon")
|
||||
#define GTEST_DEFINE_int32_(name, default_val, doc) \
|
||||
GTEST_DECLARE_int32_(name); \
|
||||
namespace testing { \
|
||||
GTEST_API_ std::int32_t GTEST_FLAG(name) = (default_val); \
|
||||
} \
|
||||
static_assert(true, "no-op to require trailing semicolon")
|
||||
#define GTEST_DEFINE_string_(name, default_val, doc) \
|
||||
GTEST_DECLARE_string_(name); \
|
||||
namespace testing { \
|
||||
GTEST_API_ ::std::string GTEST_FLAG(name) = (default_val); \
|
||||
} \
|
||||
static_assert(true, "no-op to require trailing semicolon")
|
||||
|
||||
// Macros for declaring flags.
|
||||
//
|
||||
// We also need to declare the flag in the public namespace to avoid triggering
|
||||
// -Wmissing-variable-declarations warnings, as reported here:
|
||||
// https://github.com/google/googletest/issues/4897
|
||||
#define GTEST_DECLARE_bool_(name) \
|
||||
namespace testing { \
|
||||
GTEST_API_ extern bool GTEST_FLAG(name); \
|
||||
@@ -2367,91 +2438,11 @@ const char* StringFromGTestEnv(const char* flag, const char* default_val);
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
|
||||
#if !defined(GTEST_INTERNAL_DEPRECATED)
|
||||
|
||||
// Internal Macro to mark an API deprecated, for googletest usage only
|
||||
// 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)))
|
||||
#if GTEST_INTERNAL_HAVE_CPP_ATTRIBUTE(clang::annotate)
|
||||
#define GTEST_INTERNAL_DEPRECATE_AND_INLINE(msg) \
|
||||
[[deprecated(msg), clang::annotate("inline-me")]]
|
||||
#else
|
||||
#define GTEST_INTERNAL_DEPRECATED(message)
|
||||
#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
|
||||
#define GTEST_INTERNAL_DEPRECATE_AND_INLINE(msg) [[deprecated(msg)]]
|
||||
#endif
|
||||
|
||||
#if defined(__cpp_lib_span) || (GTEST_INTERNAL_HAS_INCLUDE(<span>) && \
|
||||
@@ -2466,7 +2457,6 @@ inline ::std::nullopt_t Nullopt() { return ::std::nullopt; }
|
||||
#ifdef GTEST_HAS_ABSL
|
||||
// Always use absl::string_view for Matcher<> specializations if googletest
|
||||
// is built with absl support.
|
||||
#define GTEST_INTERNAL_HAS_STRING_VIEW 1
|
||||
#include "absl/strings/string_view.h"
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
@@ -2474,68 +2464,17 @@ using StringView = ::absl::string_view;
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
#else
|
||||
#if defined(__cpp_lib_string_view) || \
|
||||
(GTEST_INTERNAL_HAS_INCLUDE(<string_view>) && \
|
||||
GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L)
|
||||
// Otherwise for C++17 and higher use std::string_view for Matcher<>
|
||||
// specializations.
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
using StringView = std::string_view;
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
#endif // GTEST_HAS_ABSL
|
||||
#define GTEST_INTERNAL_HAS_STRING_VIEW 1
|
||||
#include <string_view>
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
using StringView = ::std::string_view;
|
||||
} // namespace internal
|
||||
} // namespace testing
|
||||
// The case where absl is configured NOT to alias std::string_view is not
|
||||
// supported.
|
||||
#endif // __cpp_lib_string_view
|
||||
#endif // GTEST_HAS_ABSL
|
||||
|
||||
#ifndef GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
#define GTEST_INTERNAL_HAS_STRING_VIEW 0
|
||||
#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) || \
|
||||
(GTEST_INTERNAL_HAS_INCLUDE(<compare>) && \
|
||||
GTEST_INTERNAL_CPLUSPLUS_LANG >= 201907L))
|
||||
#if defined(__cpp_lib_three_way_comparison)
|
||||
#define GTEST_INTERNAL_HAS_COMPARE_LIB 1
|
||||
#else
|
||||
#define GTEST_INTERNAL_HAS_COMPARE_LIB 0
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace testing {
|
||||
namespace internal {
|
||||
|
||||
// String - an abstract class holding static string utilities.
|
||||
class GTEST_API_ String {
|
||||
class GTEST_API_ [[nodiscard]] String {
|
||||
public:
|
||||
// Static utility methods
|
||||
|
||||
@@ -166,7 +166,7 @@ class GTEST_API_ String {
|
||||
|
||||
private:
|
||||
String(); // Not meant to be instantiated.
|
||||
}; // class String
|
||||
}; // class String
|
||||
|
||||
// Gets the content of the stringstream's buffer as an std::string. Each '\0'
|
||||
// character in the buffer is replaced with "\\0".
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
|
||||
#include "sample2.h"
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
namespace {
|
||||
// In this example, we test the MyString class (a simple string).
|
||||
@@ -78,7 +80,7 @@ const char kHelloString[] = "Hello, world!";
|
||||
TEST(MyString, ConstructorFromCString) {
|
||||
const MyString s(kHelloString);
|
||||
EXPECT_EQ(0, strcmp(s.c_string(), kHelloString));
|
||||
EXPECT_EQ(sizeof(kHelloString) / sizeof(kHelloString[0]) - 1, s.Length());
|
||||
EXPECT_EQ(std::size(kHelloString) - 1, s.Length());
|
||||
}
|
||||
|
||||
// Tests the copy c'tor.
|
||||
|
||||
@@ -246,15 +246,12 @@ GTEST_API_ std::string WideStringToUtf8(const wchar_t* str, int num_chars);
|
||||
// be created, prints an error and exits.
|
||||
void WriteToShardStatusFileIfNeeded();
|
||||
|
||||
// Checks whether sharding is enabled by examining the relevant
|
||||
// environment variable values. If the variables are present,
|
||||
// but inconsistent (e.g., shard_index >= total_shards), prints
|
||||
// an error and exits. If in_subprocess_for_death_test, sharding is
|
||||
// Checks whether sharding is enabled by examining the relevant flag values.
|
||||
// If the flags are set, but inconsistent (e.g., shard_index >= total_shards),
|
||||
// prints an error and exits. If in_subprocess_for_death_test, sharding is
|
||||
// disabled because it must only be applied to the original test
|
||||
// process. Otherwise, we could filter out death tests we intended to execute.
|
||||
GTEST_API_ bool ShouldShard(const char* total_shards_str,
|
||||
const char* shard_index_str,
|
||||
bool in_subprocess_for_death_test);
|
||||
GTEST_API_ bool ShouldShard(bool in_subprocess_for_death_test);
|
||||
|
||||
// Parses the environment variable var as a 32-bit integer. If it is unset,
|
||||
// returns default_val. If it is not a 32-bit integer, prints an error and
|
||||
@@ -590,7 +587,7 @@ class GTEST_API_ UnitTestImpl {
|
||||
// total_test_suite_count() - 1. If i is not in that range, returns NULL.
|
||||
const TestSuite* GetTestSuite(int i) const {
|
||||
const int index = GetElementOr(test_suite_indices_, i, -1);
|
||||
return index < 0 ? nullptr : test_suites_[static_cast<size_t>(i)];
|
||||
return index < 0 ? nullptr : test_suites_[static_cast<size_t>(index)];
|
||||
}
|
||||
|
||||
// Legacy API is deprecated but still available
|
||||
@@ -826,6 +823,10 @@ class GTEST_API_ UnitTestImpl {
|
||||
bool catch_exceptions() const { return catch_exceptions_; }
|
||||
|
||||
private:
|
||||
// Returns true if a warning should be issued if no tests match the test
|
||||
// filter flag.
|
||||
bool ShouldWarnIfNoTestsMatchFilter() const;
|
||||
|
||||
struct CompareTestSuitesByPointer {
|
||||
bool operator()(const TestSuite* lhs, const TestSuite* rhs) const {
|
||||
return lhs->name_ < rhs->name_;
|
||||
@@ -1105,7 +1106,7 @@ class StreamingListener : public EmptyTestEventListener {
|
||||
GTEST_CHECK_(sockfd_ != -1)
|
||||
<< "Send() can be called only when there is a connection.";
|
||||
|
||||
const auto len = static_cast<size_t>(message.length());
|
||||
const size_t len = message.length();
|
||||
if (write(sockfd_, message.c_str(), len) != static_cast<ssize_t>(len)) {
|
||||
GTEST_LOG_(WARNING) << "stream_result_to: failed to stream to "
|
||||
<< host_name_ << ":" << port_num_;
|
||||
|
||||
@@ -59,7 +59,6 @@ Matcher<std::string>::Matcher(const std::string& s) { *this = Eq(s); }
|
||||
// s.
|
||||
Matcher<std::string>::Matcher(const char* s) { *this = Eq(std::string(s)); }
|
||||
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
// Constructs a matcher that matches a const StringView& whose value is
|
||||
// equal to s.
|
||||
Matcher<const internal::StringView&>::Matcher(const std::string& s) {
|
||||
@@ -93,6 +92,5 @@ Matcher<internal::StringView>::Matcher(const char* s) {
|
||||
Matcher<internal::StringView>::Matcher(internal::StringView s) {
|
||||
*this = Eq(std::string(s));
|
||||
}
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
} // namespace testing
|
||||
|
||||
@@ -89,6 +89,7 @@
|
||||
|
||||
#include "gtest/gtest-message.h"
|
||||
#include "gtest/gtest-spi.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "gtest/internal/gtest-internal.h"
|
||||
#include "gtest/internal/gtest-string.h"
|
||||
#include "src/gtest-internal-inl.h"
|
||||
@@ -302,6 +303,22 @@ bool AutoHandle::IsCloseable() const {
|
||||
return handle_ != nullptr && handle_ != INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
#if !GTEST_HAS_NOTIFICATION_ && defined(GTEST_OS_WINDOWS_MINGW)
|
||||
Notification::Notification() {
|
||||
// Create a manual-reset event object.
|
||||
event_ = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
|
||||
GTEST_CHECK_(event_ != nullptr);
|
||||
}
|
||||
|
||||
Notification::~Notification() { ::CloseHandle(event_); }
|
||||
|
||||
void Notification::Notify() { GTEST_CHECK_(::SetEvent(event_)); }
|
||||
|
||||
void Notification::WaitForNotification() {
|
||||
GTEST_CHECK_(::WaitForSingleObject(event_, INFINITE) == WAIT_OBJECT_0);
|
||||
}
|
||||
#endif // !GTEST_HAS_NOTIFICATION_ && defined(GTEST_OS_WINDOWS_MINGW)
|
||||
|
||||
Mutex::Mutex()
|
||||
: owner_thread_id_(0),
|
||||
type_(kDynamic),
|
||||
@@ -320,13 +337,13 @@ Mutex::~Mutex() {
|
||||
}
|
||||
}
|
||||
|
||||
void Mutex::Lock() {
|
||||
void Mutex::lock() {
|
||||
ThreadSafeLazyInit();
|
||||
::EnterCriticalSection(critical_section_);
|
||||
owner_thread_id_ = ::GetCurrentThreadId();
|
||||
}
|
||||
|
||||
void Mutex::Unlock() {
|
||||
void Mutex::unlock() {
|
||||
ThreadSafeLazyInit();
|
||||
// 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
|
||||
@@ -499,7 +516,7 @@ class ThreadLocalRegistryImpl {
|
||||
MemoryIsNotDeallocated memory_is_not_deallocated;
|
||||
#endif // _MSC_VER
|
||||
DWORD current_thread = ::GetCurrentThreadId();
|
||||
MutexLock lock(&mutex_);
|
||||
MutexLock lock(mutex_);
|
||||
ThreadIdToThreadLocals* const thread_to_thread_locals =
|
||||
GetThreadLocalsMapLocked();
|
||||
ThreadIdToThreadLocals::iterator thread_local_pos =
|
||||
@@ -532,7 +549,7 @@ class ThreadLocalRegistryImpl {
|
||||
// Clean up the ThreadLocalValues data structure while holding the lock, but
|
||||
// defer the destruction of the ThreadLocalValueHolderBases.
|
||||
{
|
||||
MutexLock lock(&mutex_);
|
||||
MutexLock lock(mutex_);
|
||||
ThreadIdToThreadLocals* const thread_to_thread_locals =
|
||||
GetThreadLocalsMapLocked();
|
||||
for (ThreadIdToThreadLocals::iterator it =
|
||||
@@ -559,7 +576,7 @@ class ThreadLocalRegistryImpl {
|
||||
// Clean up the ThreadIdToThreadLocals data structure while holding the
|
||||
// lock, but defer the destruction of the ThreadLocalValueHolderBases.
|
||||
{
|
||||
MutexLock lock(&mutex_);
|
||||
MutexLock lock(mutex_);
|
||||
ThreadIdToThreadLocals* const thread_to_thread_locals =
|
||||
GetThreadLocalsMapLocked();
|
||||
ThreadIdToThreadLocals::iterator thread_local_pos =
|
||||
@@ -729,7 +746,7 @@ void RE::Init(const char* regex) {
|
||||
char* const full_pattern = new char[full_regex_len];
|
||||
|
||||
snprintf(full_pattern, full_regex_len, "^(%s)$", regex);
|
||||
is_valid_ = regcomp(&full_regex_, full_pattern, reg_flags) == 0;
|
||||
int error = regcomp(&full_regex_, full_pattern, reg_flags);
|
||||
// We want to call regcomp(&partial_regex_, ...) even if the
|
||||
// previous expression returns false. Otherwise partial_regex_ may
|
||||
// not be properly initialized can may cause trouble when it's
|
||||
@@ -738,13 +755,13 @@ void RE::Init(const char* regex) {
|
||||
// Some implementation of POSIX regex (e.g. on at least some
|
||||
// versions of Cygwin) doesn't accept the empty string as a valid
|
||||
// regex. We change it to an equivalent form "()" to be safe.
|
||||
if (is_valid_) {
|
||||
if (!error) {
|
||||
const char* const partial_regex = (*regex == '\0') ? "()" : regex;
|
||||
is_valid_ = regcomp(&partial_regex_, partial_regex, reg_flags) == 0;
|
||||
error = regcomp(&partial_regex_, partial_regex, reg_flags);
|
||||
}
|
||||
EXPECT_TRUE(is_valid_)
|
||||
<< "Regular expression \"" << regex
|
||||
<< "\" is not a valid POSIX Extended regular expression.";
|
||||
is_valid_ = error == 0;
|
||||
EXPECT_EQ(error, 0) << "Regular expression \"" << regex
|
||||
<< "\" is not a valid POSIX Extended regular expression.";
|
||||
|
||||
delete[] full_pattern;
|
||||
}
|
||||
@@ -1052,7 +1069,7 @@ GTestLog::~GTestLog() {
|
||||
|
||||
// Disable Microsoft deprecation warnings for POSIX functions called from
|
||||
// this class (creat, dup, dup2, and close)
|
||||
GTEST_DISABLE_MSC_DEPRECATED_PUSH_()
|
||||
GTEST_DISABLE_DEPRECATED_PUSH_()
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -1078,10 +1095,12 @@ class CapturedStream {
|
||||
0, // Generate unique file name.
|
||||
temp_file_path);
|
||||
GTEST_CHECK_(success != 0)
|
||||
<< "Unable to create a temporary file in " << temp_dir_path;
|
||||
<< "Failed to create temporary file in " << temp_dir_path
|
||||
<< " with error " << ::GetLastError();
|
||||
const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE);
|
||||
GTEST_CHECK_(captured_fd != -1)
|
||||
<< "Unable to open temporary file " << temp_file_path;
|
||||
<< "Failed to open temporary file " << temp_file_path << " with error "
|
||||
<< ::GetLastError();
|
||||
filename_ = temp_file_path;
|
||||
#else
|
||||
// There's no guarantee that a test has write access to the current
|
||||
@@ -1183,7 +1202,7 @@ class CapturedStream {
|
||||
CapturedStream& operator=(const CapturedStream&) = delete;
|
||||
};
|
||||
|
||||
GTEST_DISABLE_MSC_DEPRECATED_POP_()
|
||||
GTEST_DISABLE_DEPRECATED_POP_()
|
||||
|
||||
static CapturedStream* g_captured_stderr = nullptr;
|
||||
static CapturedStream* g_captured_stdout = nullptr;
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
#include <ios>
|
||||
#include <ostream> // NOLINT
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
@@ -114,8 +115,7 @@ void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
|
||||
// char32_t.
|
||||
template <typename CharType>
|
||||
char32_t ToChar32(CharType in) {
|
||||
return static_cast<char32_t>(
|
||||
static_cast<typename std::make_unsigned<CharType>::type>(in));
|
||||
return static_cast<char32_t>(static_cast<std::make_unsigned_t<CharType>>(in));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -286,6 +286,28 @@ void PrintTo(char32_t c, ::std::ostream* os) {
|
||||
<< static_cast<uint32_t>(c);
|
||||
}
|
||||
|
||||
// char8_t and char16_t hold code units, not code points, so the U+XXXX
|
||||
// notation only applies to the values that encode a code point on their own.
|
||||
// The rest -- non-ASCII char8_t, which are always part of a multi-unit UTF-8
|
||||
// sequence, and the UTF-16 surrogates -- are printed as code units.
|
||||
void PrintTo(char16_t c, ::std::ostream* os) {
|
||||
if (c >= 0xD800 && c <= 0xDFFF) {
|
||||
PrintCharAndCodeTo(c, os);
|
||||
} else {
|
||||
PrintTo(static_cast<char32_t>(c), os);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cpp_lib_char8_t
|
||||
void PrintTo(char8_t c, ::std::ostream* os) {
|
||||
if (c >= 0x80) {
|
||||
PrintCharAndCodeTo(c, os);
|
||||
} else {
|
||||
PrintTo(static_cast<char32_t>(c), os);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// gcc/clang __{u,}int128_t
|
||||
#if defined(__SIZEOF_INT128__)
|
||||
void PrintTo(__uint128_t v, ::std::ostream* os) {
|
||||
@@ -333,14 +355,14 @@ void PrintTo(__int128_t v, ::std::ostream* os) {
|
||||
|
||||
// Prints the given array of characters to the ostream. CharType must be either
|
||||
// char, char8_t, char16_t, char32_t, or wchar_t.
|
||||
// The array starts at begin, the length is len, it may include '\0' characters
|
||||
// and may not be NUL-terminated.
|
||||
// The array starts at begin (which may be nullptr) and contains len characters.
|
||||
// The array may include '\0' characters and may not be NUL-terminated.
|
||||
template <typename CharType>
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
|
||||
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ static CharFormat
|
||||
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 << "\"";
|
||||
bool is_previous_hex = false;
|
||||
CharFormat print_format = kAsIs;
|
||||
@@ -423,6 +445,28 @@ void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) {
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename Char>
|
||||
size_t GetLength(const Char* s) {
|
||||
return std::char_traits<Char>::length(s);
|
||||
}
|
||||
|
||||
#if !GTEST_HAS_STD_WSTRING
|
||||
|
||||
// If GTEST_HAS_STD_WSTRING is unset because the standard library has disabled
|
||||
// wide character support, std::char_traits<wchar_t> won't be defined, which
|
||||
// will cause a compile error, even if user code never actually could print a
|
||||
// wide cstring. In that case, instead use `wcslen` directly.
|
||||
//
|
||||
// If `libc` _also_ lacks wide character support, this (and a bunch of other
|
||||
// calls to wc functions) will fail to link, but only if user code actually
|
||||
// uses them.
|
||||
template <>
|
||||
size_t GetLength<wchar_t>(const wchar_t* s) {
|
||||
return wcslen(s);
|
||||
}
|
||||
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
|
||||
// Prints a null-terminated C-style string to the ostream.
|
||||
template <typename Char>
|
||||
void PrintCStringTo(const Char* s, ostream* os) {
|
||||
@@ -430,7 +474,7 @@ void PrintCStringTo(const Char* s, ostream* os) {
|
||||
*os << "NULL";
|
||||
} else {
|
||||
*os << ImplicitCast_<const void*>(s) << " pointing to ";
|
||||
PrintCharsAsStringTo(s, std::char_traits<Char>::length(s), os);
|
||||
PrintCharsAsStringTo(s, GetLength(s), os);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,16 +490,9 @@ void PrintTo(const char16_t* s, ostream* os) { PrintCStringTo(s, os); }
|
||||
|
||||
void PrintTo(const char32_t* s, ostream* os) { PrintCStringTo(s, os); }
|
||||
|
||||
// MSVC compiler can be configured to define whar_t as a typedef
|
||||
// of unsigned short. Defining an overload for const wchar_t* in that case
|
||||
// would cause pointers to unsigned shorts be printed as wide strings,
|
||||
// possibly accessing more memory than intended and causing invalid
|
||||
// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
|
||||
// wchar_t is implemented as a native type.
|
||||
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
|
||||
// Prints the given wide C string to the ostream.
|
||||
#if GTEST_HAS_STD_WSTRING && GTEST_HAS_NATIVE_WCHAR
|
||||
void PrintTo(const wchar_t* s, ostream* os) { PrintCStringTo(s, os); }
|
||||
#endif // wchar_t is native
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -516,13 +553,13 @@ bool IsValidUTF8(const char* str, size_t length) {
|
||||
void ConditionalPrintAsText(const char* str, size_t length, ostream* os) {
|
||||
if (!ContainsUnprintableControlCodes(str, length) &&
|
||||
IsValidUTF8(str, length)) {
|
||||
*os << "\n As Text: \"" << str << "\"";
|
||||
*os << "\n As Text: \"" << std::string_view(str, length) << "\"";
|
||||
}
|
||||
}
|
||||
|
||||
} // 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 (GTEST_FLAG_GET(print_utf8)) {
|
||||
ConditionalPrintAsText(s.data(), s.size(), os);
|
||||
@@ -531,21 +568,21 @@ void PrintStringTo(const ::std::string& s, ostream* os) {
|
||||
}
|
||||
|
||||
#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);
|
||||
}
|
||||
#endif
|
||||
|
||||
void PrintU16StringTo(const ::std::u16string& s, ostream* os) {
|
||||
void PrintU16StringTo(::std::u16string_view s, ostream* 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);
|
||||
}
|
||||
|
||||
#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);
|
||||
}
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
|
||||
@@ -34,7 +34,9 @@
|
||||
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "gtest/internal/gtest-internal.h"
|
||||
#include "gtest/internal/gtest-port.h"
|
||||
#include "src/gtest-internal-inl.h"
|
||||
|
||||
@@ -42,9 +44,9 @@ namespace testing {
|
||||
|
||||
// Gets the summary of the failure message by omitting the stack trace
|
||||
// in it.
|
||||
std::string TestPartResult::ExtractSummary(const char* message) {
|
||||
const char* const stack_trace = strstr(message, internal::kStackTraceMarker);
|
||||
return stack_trace == nullptr ? message : std::string(message, stack_trace);
|
||||
std::string TestPartResult::ExtractSummary(const std::string_view message) {
|
||||
auto stack_trace = message.find(internal::kStackTraceMarker);
|
||||
return std::string(message.substr(0, stack_trace));
|
||||
}
|
||||
|
||||
// Prints a TestPartResult object.
|
||||
|
||||
+241
-85
@@ -58,6 +58,7 @@
|
||||
#include <ostream> // NOLINT
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <string_view>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@@ -192,12 +193,17 @@ static const char kDefaultOutputFormat[] = "xml";
|
||||
// The default output file.
|
||||
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.
|
||||
static const char kTestShardIndex[] = "GTEST_SHARD_INDEX";
|
||||
// The environment variable name for the total number of test shards.
|
||||
static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS";
|
||||
// The environment variable name for the test 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 {
|
||||
|
||||
@@ -258,6 +264,19 @@ GTEST_DEFINE_bool_(
|
||||
testing::GetDefaultFailFast()),
|
||||
"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_(
|
||||
also_run_disabled_tests,
|
||||
testing::internal::BoolFromGTestEnv("also_run_disabled_tests", false),
|
||||
@@ -388,6 +407,18 @@ GTEST_DEFINE_bool_(
|
||||
"if exceptions are enabled or exit the program with a non-zero code "
|
||||
"otherwise. For use with an external test framework.");
|
||||
|
||||
GTEST_DEFINE_int32_(
|
||||
shard_index,
|
||||
testing::internal::Int32FromEnvOrDie(testing::kTestShardIndex, -1),
|
||||
"The zero-based index of the shard to run. A value of -1 "
|
||||
"(the default) indicates that sharding is disabled.");
|
||||
|
||||
GTEST_DEFINE_int32_(
|
||||
total_shards,
|
||||
testing::internal::Int32FromEnvOrDie(testing::kTestTotalShards, -1),
|
||||
"The total number of shards to use when running tests in parallel. "
|
||||
"A value of -1 (the default) indicates that sharding is disabled.");
|
||||
|
||||
#if GTEST_USE_OWN_FLAGFILE_FLAG_
|
||||
GTEST_DEFINE_string_(
|
||||
flagfile, testing::internal::StringFromGTestEnv("flagfile", ""),
|
||||
@@ -467,6 +498,15 @@ bool ShouldEmitStackTraceForResultType(TestPartResult::Type type) {
|
||||
// AssertHelper constructor.
|
||||
AssertHelper::AssertHelper(TestPartResult::Type type, const char* file,
|
||||
int line, const char* message)
|
||||
: AssertHelper(
|
||||
type, file == nullptr ? std::string_view() : std::string_view(file),
|
||||
line,
|
||||
message == nullptr ? std::string_view() : std::string_view(message)) {
|
||||
}
|
||||
|
||||
AssertHelper::AssertHelper(TestPartResult::Type type,
|
||||
const std::string_view file, int line,
|
||||
const std::string_view message)
|
||||
: data_(new AssertHelperData(type, file, line, message)) {}
|
||||
|
||||
AssertHelper::~AssertHelper() { delete data_; }
|
||||
@@ -695,7 +735,7 @@ std::string UnitTestOptions::GetAbsolutePathToOutputFile() {
|
||||
const char* const gtest_output_flag = s.c_str();
|
||||
|
||||
std::string format = GetOutputFormat();
|
||||
if (format.empty()) format = std::string(kDefaultOutputFormat);
|
||||
if (format.empty()) format = kDefaultOutputFormat;
|
||||
|
||||
const char* const colon = strchr(gtest_output_flag, ':');
|
||||
if (colon == nullptr)
|
||||
@@ -857,7 +897,11 @@ class PositiveAndNegativeUnitTestFilter {
|
||||
// and does not match the negative filter.
|
||||
bool MatchesTest(const std::string& test_suite_name,
|
||||
const std::string& test_name) const {
|
||||
#ifdef GTEST_HAS_ABSL
|
||||
return MatchesName(absl::StrCat(test_suite_name, ".", test_name));
|
||||
#else
|
||||
return MatchesName(test_suite_name + "." + test_name);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns true if and only if name matches the positive filter and does not
|
||||
@@ -1068,14 +1112,14 @@ void DefaultPerThreadTestPartResultReporter::ReportTestPartResult(
|
||||
// Returns the global test part result reporter.
|
||||
TestPartResultReporterInterface*
|
||||
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_;
|
||||
}
|
||||
|
||||
// Sets the global test part result reporter.
|
||||
void UnitTestImpl::SetGlobalTestPartResultReporter(
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1165,7 +1209,7 @@ int UnitTestImpl::test_to_run_count() const {
|
||||
// trace but Bar() and CurrentOsStackTraceExceptTop() won't.
|
||||
std::string UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) {
|
||||
return os_stack_trace_getter()->CurrentStackTrace(
|
||||
static_cast<int>(GTEST_FLAG_GET(stack_trace_depth)), skip_count + 1
|
||||
GTEST_FLAG_GET(stack_trace_depth), skip_count + 1
|
||||
// Skips the user-specified number of frames plus this function
|
||||
// itself.
|
||||
); // NOLINT
|
||||
@@ -1477,17 +1521,17 @@ class Hunk {
|
||||
// Print a unified diff header for one hunk.
|
||||
// The format is
|
||||
// "@@ -<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 {
|
||||
*ss << "@@ ";
|
||||
if (removes_) {
|
||||
*ss << "-" << left_start_ << "," << (removes_ + common_);
|
||||
size_t left_length = removes_ + common_;
|
||||
size_t right_length = adds_ + common_;
|
||||
*ss << "@@ " << "-" << left_start_;
|
||||
if (left_length != 1) {
|
||||
*ss << "," << left_length;
|
||||
}
|
||||
if (removes_ && adds_) {
|
||||
*ss << " ";
|
||||
}
|
||||
if (adds_) {
|
||||
*ss << "+" << right_start_ << "," << (adds_ + common_);
|
||||
*ss << " " << "+" << right_start_;
|
||||
if (right_length != 1) {
|
||||
*ss << "," << right_length;
|
||||
}
|
||||
*ss << " @@\n";
|
||||
}
|
||||
@@ -1832,11 +1876,13 @@ bool IsSubstringPred(const char* needle, const char* haystack) {
|
||||
return strstr(haystack, needle) != nullptr;
|
||||
}
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
bool IsSubstringPred(const wchar_t* needle, const wchar_t* haystack) {
|
||||
if (needle == nullptr || haystack == nullptr) return needle == haystack;
|
||||
|
||||
return wcsstr(haystack, needle) != nullptr;
|
||||
}
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
|
||||
// StringType here can be either ::std::string or ::std::wstring.
|
||||
template <typename StringType>
|
||||
@@ -1878,23 +1924,12 @@ AssertionResult IsSubstring(const char* needle_expr, const char* haystack_expr,
|
||||
return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
|
||||
}
|
||||
|
||||
AssertionResult IsSubstring(const char* needle_expr, const char* haystack_expr,
|
||||
const wchar_t* needle, const wchar_t* haystack) {
|
||||
return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
|
||||
}
|
||||
|
||||
AssertionResult IsNotSubstring(const char* needle_expr,
|
||||
const char* haystack_expr, const char* needle,
|
||||
const char* haystack) {
|
||||
return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
|
||||
}
|
||||
|
||||
AssertionResult IsNotSubstring(const char* needle_expr,
|
||||
const char* haystack_expr, const wchar_t* needle,
|
||||
const wchar_t* haystack) {
|
||||
return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
|
||||
}
|
||||
|
||||
AssertionResult IsSubstring(const char* needle_expr, const char* haystack_expr,
|
||||
const ::std::string& needle,
|
||||
const ::std::string& haystack) {
|
||||
@@ -1909,6 +1944,17 @@ AssertionResult IsNotSubstring(const char* needle_expr,
|
||||
}
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
AssertionResult IsSubstring(const char* needle_expr, const char* haystack_expr,
|
||||
const wchar_t* needle, const wchar_t* haystack) {
|
||||
return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
|
||||
}
|
||||
|
||||
AssertionResult IsNotSubstring(const char* needle_expr,
|
||||
const char* haystack_expr, const wchar_t* needle,
|
||||
const wchar_t* haystack) {
|
||||
return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
|
||||
}
|
||||
|
||||
AssertionResult IsSubstring(const char* needle_expr, const char* haystack_expr,
|
||||
const ::std::wstring& needle,
|
||||
const ::std::wstring& haystack) {
|
||||
@@ -2138,6 +2184,7 @@ bool String::WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs) {
|
||||
return wcscmp(lhs, rhs) == 0;
|
||||
}
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
// Helper function for *_STREQ on wide strings.
|
||||
AssertionResult CmpHelperSTREQ(const char* lhs_expression,
|
||||
const char* rhs_expression, const wchar_t* lhs,
|
||||
@@ -2162,6 +2209,7 @@ AssertionResult CmpHelperSTRNE(const char* s1_expression,
|
||||
<< "Expected: (" << s1_expression << ") != (" << s2_expression
|
||||
<< "), actual: " << PrintToString(s1) << " vs " << PrintToString(s2);
|
||||
}
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
|
||||
// Compares two C strings, ignoring case. Returns true if and only if they have
|
||||
// the same content.
|
||||
@@ -2329,7 +2377,7 @@ void TestResult::RecordProperty(const std::string& xml_element,
|
||||
if (!ValidateTestProperty(xml_element, test_property)) {
|
||||
return;
|
||||
}
|
||||
internal::MutexLock lock(&test_properties_mutex_);
|
||||
internal::MutexLock lock(test_properties_mutex_);
|
||||
const std::vector<TestProperty>::iterator property_with_matching_key =
|
||||
std::find_if(test_properties_.begin(), test_properties_.end(),
|
||||
internal::TestPropertyKeyIs(test_property.key()));
|
||||
@@ -2529,8 +2577,9 @@ void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
|
||||
// AddTestPartResult.
|
||||
UnitTest::GetInstance()->AddTestPartResult(
|
||||
result_type,
|
||||
nullptr, // No info about the source file where the exception occurred.
|
||||
-1, // We have no info on which line caused the exception.
|
||||
std::string_view(), // No info about the source file where the exception
|
||||
// occurred.
|
||||
-1, // We have no info on which line caused the exception.
|
||||
message,
|
||||
""); // No stack trace, either.
|
||||
}
|
||||
@@ -2655,7 +2704,7 @@ Result HandleSehExceptionsInMethodIfSupported(T* object, Result (T::*method)(),
|
||||
}
|
||||
|
||||
// Runs the given method and catches and reports C++ and/or SEH-style
|
||||
// exceptions, if they are supported; returns the 0-value for type
|
||||
// exceptions, if they are supported; returns the default-value for type
|
||||
// Result in case of an SEH exception.
|
||||
template <class T, typename Result>
|
||||
Result HandleExceptionsInMethodIfSupported(T* object, Result (T::*method)(),
|
||||
@@ -2703,7 +2752,7 @@ Result HandleExceptionsInMethodIfSupported(T* object, Result (T::*method)(),
|
||||
TestPartResult::kFatalFailure,
|
||||
FormatCxxExceptionMessage(nullptr, location));
|
||||
}
|
||||
return static_cast<Result>(0);
|
||||
return Result();
|
||||
#else
|
||||
return HandleSehExceptionsInMethodIfSupported(object, method, location);
|
||||
#endif // GTEST_HAS_EXCEPTIONS
|
||||
@@ -3287,6 +3336,7 @@ bool ShouldUseColor(bool stdout_is_tty) {
|
||||
const bool term_supports_color =
|
||||
term != nullptr && (String::CStringEquals(term, "xterm") ||
|
||||
String::CStringEquals(term, "xterm-color") ||
|
||||
String::CStringEquals(term, "xterm-ghostty") ||
|
||||
String::CStringEquals(term, "xterm-kitty") ||
|
||||
String::CStringEquals(term, "alacritty") ||
|
||||
String::CStringEquals(term, "screen") ||
|
||||
@@ -3441,11 +3491,11 @@ void PrettyUnitTestResultPrinter::OnTestIterationStart(
|
||||
filter);
|
||||
}
|
||||
|
||||
if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) {
|
||||
const int32_t shard_index = Int32FromEnvOrDie(kTestShardIndex, -1);
|
||||
ColoredPrintf(GTestColor::kYellow, "Note: This is test shard %d of %s.\n",
|
||||
if (internal::ShouldShard(false)) {
|
||||
const int32_t shard_index = GTEST_FLAG_GET(shard_index);
|
||||
ColoredPrintf(GTestColor::kYellow, "Note: This is test shard %d of %d.\n",
|
||||
static_cast<int>(shard_index) + 1,
|
||||
internal::posix::GetEnv(kTestTotalShards));
|
||||
GTEST_FLAG_GET(total_shards));
|
||||
}
|
||||
|
||||
if (GTEST_FLAG_GET(shuffle)) {
|
||||
@@ -4193,8 +4243,7 @@ void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream,
|
||||
for (;;) {
|
||||
const char* const next_segment = strstr(segment, "]]>");
|
||||
if (next_segment != nullptr) {
|
||||
stream->write(segment,
|
||||
static_cast<std::streamsize>(next_segment - segment));
|
||||
stream->write(segment, next_segment - segment);
|
||||
*stream << "]]>]]><![CDATA[";
|
||||
segment = next_segment + strlen("]]>");
|
||||
} else {
|
||||
@@ -4336,8 +4385,8 @@ void XmlUnitTestResultPrinter::OutputXmlTestResult(::std::ostream* stream,
|
||||
internal::FormatCompilerIndependentFileLocation(part.file_name(),
|
||||
part.line_number());
|
||||
const std::string summary = location + "\n" + part.summary();
|
||||
*stream << " <skipped message=\""
|
||||
<< EscapeXmlAttribute(summary.c_str()) << "\">";
|
||||
*stream << " <skipped message=\"" << EscapeXmlAttribute(summary)
|
||||
<< "\">";
|
||||
const std::string detail = location + "\n" + part.message();
|
||||
OutputXmlCDataSection(stream, RemoveInvalidXmlCharacters(detail).c_str());
|
||||
*stream << "</skipped>\n";
|
||||
@@ -5069,7 +5118,7 @@ std::string OsStackTraceGetter::CurrentStackTrace(int max_depth, int skip_count)
|
||||
|
||||
void* caller_frame = nullptr;
|
||||
{
|
||||
MutexLock lock(&mutex_);
|
||||
MutexLock lock(mutex_);
|
||||
caller_frame = caller_frame_;
|
||||
}
|
||||
|
||||
@@ -5108,12 +5157,12 @@ void OsStackTraceGetter::UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
caller_frame = nullptr;
|
||||
}
|
||||
|
||||
MutexLock lock(&mutex_);
|
||||
MutexLock lock(mutex_);
|
||||
caller_frame_ = caller_frame;
|
||||
#endif // GTEST_HAS_ABSL
|
||||
}
|
||||
|
||||
#ifdef GTEST_HAS_DEATH_TEST
|
||||
#ifdef GTEST_INTERNAL_HAS_PREMATURE_EXIT_FILE
|
||||
// A helper class that creates the premature-exit file in its
|
||||
// constructor and deletes the file in its destructor.
|
||||
class ScopedPrematureExitFile {
|
||||
@@ -5126,9 +5175,12 @@ class ScopedPrematureExitFile {
|
||||
// create the file with a single "0" character in it. I/O
|
||||
// errors are ignored as there's nothing better we can do and we
|
||||
// don't want to fail the test because of this.
|
||||
FILE* pfile = posix::FOpen(premature_exit_filepath_.c_str(), "w");
|
||||
fwrite("0", 1, 1, pfile);
|
||||
fclose(pfile);
|
||||
if (FILE* pfile = posix::FOpen(premature_exit_filepath_.c_str(), "w")) {
|
||||
fwrite("0", 1, 1, pfile);
|
||||
fclose(pfile);
|
||||
} else {
|
||||
premature_exit_filepath_.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5146,12 +5198,12 @@ class ScopedPrematureExitFile {
|
||||
}
|
||||
|
||||
private:
|
||||
const std::string premature_exit_filepath_;
|
||||
std::string premature_exit_filepath_;
|
||||
|
||||
ScopedPrematureExitFile(const ScopedPrematureExitFile&) = delete;
|
||||
ScopedPrematureExitFile& operator=(const ScopedPrematureExitFile&) = delete;
|
||||
};
|
||||
#endif // GTEST_HAS_DEATH_TEST
|
||||
#endif // GTEST_INTERNAL_HAS_PREMATURE_EXIT_FILE
|
||||
|
||||
} // namespace internal
|
||||
|
||||
@@ -5371,13 +5423,13 @@ void UnitTest::UponLeavingGTest() {
|
||||
|
||||
// Sets the TestSuite object for the test that's currently running.
|
||||
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);
|
||||
}
|
||||
|
||||
// Sets the TestInfo object for the test that's currently running.
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -5409,14 +5461,14 @@ Environment* UnitTest::AddEnvironment(Environment* env) {
|
||||
// this to report their results. The user code should use the
|
||||
// assertion macros instead of calling this directly.
|
||||
void UnitTest::AddTestPartResult(TestPartResult::Type result_type,
|
||||
const char* file_name, int line_number,
|
||||
const std::string& message,
|
||||
const std::string_view file_name,
|
||||
int line_number, const std::string& message,
|
||||
const std::string& os_stack_trace)
|
||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
Message msg;
|
||||
msg << message;
|
||||
|
||||
internal::MutexLock lock(&mutex_);
|
||||
internal::MutexLock lock(mutex_);
|
||||
if (!impl_->gtest_trace_stack().empty()) {
|
||||
msg << "\n" << GTEST_NAME_ << " trace:";
|
||||
|
||||
@@ -5496,7 +5548,7 @@ void UnitTest::RecordProperty(const std::string& key,
|
||||
// We don't protect this under mutex_, as we only support calling it
|
||||
// from the main thread.
|
||||
int UnitTest::Run() {
|
||||
#ifdef GTEST_HAS_DEATH_TEST
|
||||
#ifdef GTEST_INTERNAL_HAS_PREMATURE_EXIT_FILE
|
||||
const bool in_death_test_child_process =
|
||||
!GTEST_FLAG_GET(internal_run_death_test).empty();
|
||||
|
||||
@@ -5527,7 +5579,7 @@ int UnitTest::Run() {
|
||||
: internal::posix::GetEnv("TEST_PREMATURE_EXIT_FILE"));
|
||||
#else
|
||||
const bool in_death_test_child_process = false;
|
||||
#endif // GTEST_HAS_DEATH_TEST
|
||||
#endif // GTEST_INTERNAL_HAS_PREMATURE_EXIT_FILE
|
||||
|
||||
// Captures the value of GTEST_FLAG(catch_exceptions). This value will be
|
||||
// used for the duration of the program.
|
||||
@@ -5599,7 +5651,7 @@ const char* UnitTest::original_working_dir() const {
|
||||
// or NULL if no test is running.
|
||||
const TestSuite* UnitTest::current_test_suite() const
|
||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
internal::MutexLock lock(&mutex_);
|
||||
internal::MutexLock lock(mutex_);
|
||||
return impl_->current_test_suite();
|
||||
}
|
||||
|
||||
@@ -5607,7 +5659,7 @@ const TestSuite* UnitTest::current_test_suite() const
|
||||
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
const TestCase* UnitTest::current_test_case() const
|
||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
internal::MutexLock lock(&mutex_);
|
||||
internal::MutexLock lock(mutex_);
|
||||
return impl_->current_test_suite();
|
||||
}
|
||||
#endif
|
||||
@@ -5616,7 +5668,7 @@ const TestCase* UnitTest::current_test_case() const
|
||||
// or NULL if no test is running.
|
||||
const TestInfo* UnitTest::current_test_info() const
|
||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
internal::MutexLock lock(&mutex_);
|
||||
internal::MutexLock lock(mutex_);
|
||||
return impl_->current_test_info();
|
||||
}
|
||||
|
||||
@@ -5640,13 +5692,13 @@ UnitTest::~UnitTest() { delete impl_; }
|
||||
// Google Test trace stack.
|
||||
void UnitTest::PushGTestTrace(const internal::TraceInfo& trace)
|
||||
GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
internal::MutexLock lock(&mutex_);
|
||||
internal::MutexLock lock(mutex_);
|
||||
impl_->gtest_trace_stack().push_back(trace);
|
||||
}
|
||||
|
||||
// Pops a trace from the per-thread Google Test trace stack.
|
||||
void UnitTest::PopGTestTrace() GTEST_LOCK_EXCLUDED_(mutex_) {
|
||||
internal::MutexLock lock(&mutex_);
|
||||
internal::MutexLock lock(mutex_);
|
||||
impl_->gtest_trace_stack().pop_back();
|
||||
}
|
||||
|
||||
@@ -5869,6 +5921,23 @@ TestSuite* UnitTestImpl::GetTestSuite(
|
||||
static void SetUpEnvironment(Environment* env) { env->SetUp(); }
|
||||
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
|
||||
// returns true if all tests are successful. If any exception is
|
||||
// thrown during a test, the test is considered to be failed, but the
|
||||
@@ -5890,6 +5959,28 @@ bool UnitTestImpl::RunAllTests() {
|
||||
// user didn't call InitGoogleTest.
|
||||
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
|
||||
// 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
|
||||
@@ -5910,8 +6001,7 @@ bool UnitTestImpl::RunAllTests() {
|
||||
#endif // defined(GTEST_EXTRA_DEATH_TEST_CHILD_SETUP_)
|
||||
#endif // GTEST_HAS_DEATH_TEST
|
||||
|
||||
const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex,
|
||||
in_subprocess_for_death_test);
|
||||
const bool should_shard = ShouldShard(in_subprocess_for_death_test);
|
||||
|
||||
// Compares the full test names with the filter to decide which
|
||||
// tests to run.
|
||||
@@ -6029,6 +6119,20 @@ bool UnitTestImpl::RunAllTests() {
|
||||
TearDownEnvironment);
|
||||
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();
|
||||
@@ -6063,6 +6167,17 @@ bool UnitTestImpl::RunAllTests() {
|
||||
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) {
|
||||
ColoredPrintf(
|
||||
GTestColor::kRed,
|
||||
@@ -6098,45 +6213,44 @@ void WriteToShardStatusFileIfNeeded() {
|
||||
}
|
||||
#endif // GTEST_HAS_FILE_SYSTEM
|
||||
|
||||
// Checks whether sharding is enabled by examining the relevant
|
||||
// environment variable values. If the variables are present,
|
||||
// but inconsistent (i.e., shard_index >= total_shards), prints
|
||||
// an error and exits. If in_subprocess_for_death_test, sharding is
|
||||
// disabled because it must only be applied to the original test
|
||||
// process. Otherwise, we could filter out death tests we intended to execute.
|
||||
bool ShouldShard(const char* total_shards_env, const char* shard_index_env,
|
||||
bool in_subprocess_for_death_test) {
|
||||
// Checks whether sharding is enabled by examining the relevant command line
|
||||
// arguments. If the arguments are present, but inconsistent
|
||||
// (i.e., shard_index >= total_shards), prints an error and exits.
|
||||
// If in_subprocess_for_death_test, sharding is disabled because it must only
|
||||
// be applied to the original test process. Otherwise, we could filter out death
|
||||
// tests we intended to execute.
|
||||
bool ShouldShard(bool in_subprocess_for_death_test) {
|
||||
if (in_subprocess_for_death_test) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int32_t total_shards = Int32FromEnvOrDie(total_shards_env, -1);
|
||||
const int32_t shard_index = Int32FromEnvOrDie(shard_index_env, -1);
|
||||
const int32_t total_shards = GTEST_FLAG_GET(total_shards);
|
||||
const int32_t shard_index = GTEST_FLAG_GET(shard_index);
|
||||
|
||||
if (total_shards == -1 && shard_index == -1) {
|
||||
return false;
|
||||
} else if (total_shards == -1 && shard_index != -1) {
|
||||
const Message msg = Message() << "Invalid environment variables: you have "
|
||||
<< kTestShardIndex << " = " << shard_index
|
||||
<< ", but have left " << kTestTotalShards
|
||||
<< " unset.\n";
|
||||
const Message msg = Message()
|
||||
<< "Invalid sharding: you have " << kTestShardIndex
|
||||
<< " = " << shard_index << ", but have left "
|
||||
<< kTestTotalShards << " unset.\n";
|
||||
ColoredPrintf(GTestColor::kRed, "%s", msg.GetString().c_str());
|
||||
fflush(stdout);
|
||||
exit(EXIT_FAILURE);
|
||||
} else if (total_shards != -1 && shard_index == -1) {
|
||||
const Message msg = Message()
|
||||
<< "Invalid environment variables: you have "
|
||||
<< kTestTotalShards << " = " << total_shards
|
||||
<< ", but have left " << kTestShardIndex << " unset.\n";
|
||||
<< "Invalid sharding: you have " << kTestTotalShards
|
||||
<< " = " << total_shards << ", but have left "
|
||||
<< kTestShardIndex << " unset.\n";
|
||||
ColoredPrintf(GTestColor::kRed, "%s", msg.GetString().c_str());
|
||||
fflush(stdout);
|
||||
exit(EXIT_FAILURE);
|
||||
} else if (shard_index < 0 || shard_index >= total_shards) {
|
||||
const Message msg =
|
||||
Message() << "Invalid environment variables: we require 0 <= "
|
||||
<< kTestShardIndex << " < " << kTestTotalShards
|
||||
<< ", but you have " << kTestShardIndex << "=" << shard_index
|
||||
<< ", " << kTestTotalShards << "=" << total_shards << ".\n";
|
||||
Message() << "Invalid sharding: we require 0 <= " << kTestShardIndex
|
||||
<< " < " << kTestTotalShards << ", but you have "
|
||||
<< kTestShardIndex << "=" << shard_index << ", "
|
||||
<< kTestTotalShards << "=" << total_shards << ".\n";
|
||||
ColoredPrintf(GTestColor::kRed, "%s", msg.GetString().c_str());
|
||||
fflush(stdout);
|
||||
exit(EXIT_FAILURE);
|
||||
@@ -6179,11 +6293,10 @@ bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) {
|
||||
// . Returns the number of tests that should run.
|
||||
int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
|
||||
const int32_t total_shards = shard_tests == HONOR_SHARDING_PROTOCOL
|
||||
? Int32FromEnvOrDie(kTestTotalShards, -1)
|
||||
? GTEST_FLAG_GET(total_shards)
|
||||
: -1;
|
||||
const int32_t shard_index = shard_tests == HONOR_SHARDING_PROTOCOL
|
||||
? Int32FromEnvOrDie(kTestShardIndex, -1)
|
||||
: -1;
|
||||
const int32_t shard_index =
|
||||
shard_tests == HONOR_SHARDING_PROTOCOL ? GTEST_FLAG_GET(shard_index) : -1;
|
||||
|
||||
const PositiveAndNegativeUnitTestFilter gtest_flag_filter(
|
||||
GTEST_FLAG_GET(filter));
|
||||
@@ -6231,6 +6344,30 @@ int UnitTestImpl::FilterTests(ReactionToSharding shard_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'
|
||||
// characters with string "\\n". If the output takes more than
|
||||
// max_length characters, only prints the first max_length characters
|
||||
@@ -6601,6 +6738,12 @@ static const char kColorEncodedHelpMessage[] =
|
||||
"recreate_environments_when_repeating@D\n"
|
||||
" Sets up and tears down the global test environment on each repeat\n"
|
||||
" of the test.\n"
|
||||
" @G--" GTEST_FLAG_PREFIX_
|
||||
"fail_fast@D\n"
|
||||
" Stop running tests after the first failure.\n"
|
||||
" @G--" GTEST_FLAG_PREFIX_
|
||||
"fail_if_no_test_linked@D\n"
|
||||
" Fail if no test is linked into the test program.\n"
|
||||
"\n"
|
||||
"Test Output:\n"
|
||||
" @G--" GTEST_FLAG_PREFIX_
|
||||
@@ -6613,6 +6756,9 @@ static const char kColorEncodedHelpMessage[] =
|
||||
"print_time=0@D\n"
|
||||
" Don't print the elapsed time of each test.\n"
|
||||
" @G--" GTEST_FLAG_PREFIX_
|
||||
"print_utf8=0@D\n"
|
||||
" Don't print UTF-8 characters as text.\n"
|
||||
" @G--" GTEST_FLAG_PREFIX_
|
||||
"output=@Y(@Gjson@Y|@Gxml@Y)[@G:@YDIRECTORY_PATH@G" GTEST_PATH_SEP_
|
||||
"@Y|@G:@YFILE_PATH]@D\n"
|
||||
" Generate a JSON or XML report in the given directory or with the "
|
||||
@@ -6629,6 +6775,9 @@ static const char kColorEncodedHelpMessage[] =
|
||||
" @G--" GTEST_FLAG_PREFIX_
|
||||
"death_test_style=@Y(@Gfast@Y|@Gthreadsafe@Y)@D\n"
|
||||
" Set the default death test style.\n"
|
||||
" @G--" GTEST_FLAG_PREFIX_
|
||||
"death_test_use_fork@D\n"
|
||||
" Use fork() instead of clone() to spawn death test child processes.\n"
|
||||
#endif // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
|
||||
" @G--" GTEST_FLAG_PREFIX_
|
||||
"break_on_failure@D\n"
|
||||
@@ -6641,6 +6790,9 @@ static const char kColorEncodedHelpMessage[] =
|
||||
"catch_exceptions=0@D\n"
|
||||
" Do not report exceptions as test failures. Instead, allow them\n"
|
||||
" to crash the program or throw a pop-up (on Windows).\n"
|
||||
" @G--" GTEST_FLAG_PREFIX_
|
||||
"stack_trace_depth=@Y[NUMBER]@D\n"
|
||||
" Maximum number of stack frames to print when an assertion fails.\n"
|
||||
"\n"
|
||||
"Except for @G--" GTEST_FLAG_PREFIX_
|
||||
"list_tests@D, you can alternatively set "
|
||||
@@ -6677,6 +6829,8 @@ static bool ParseGoogleTestFlag(const char* const arg) {
|
||||
GTEST_INTERNAL_PARSE_FLAG(death_test_style);
|
||||
GTEST_INTERNAL_PARSE_FLAG(death_test_use_fork);
|
||||
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(internal_run_death_test);
|
||||
GTEST_INTERNAL_PARSE_FLAG(list_tests);
|
||||
@@ -6686,6 +6840,8 @@ static bool ParseGoogleTestFlag(const char* const arg) {
|
||||
GTEST_INTERNAL_PARSE_FLAG(print_utf8);
|
||||
GTEST_INTERNAL_PARSE_FLAG(random_seed);
|
||||
GTEST_INTERNAL_PARSE_FLAG(repeat);
|
||||
GTEST_INTERNAL_PARSE_FLAG(shard_index);
|
||||
GTEST_INTERNAL_PARSE_FLAG(total_shards);
|
||||
GTEST_INTERNAL_PARSE_FLAG(recreate_environments_when_repeating);
|
||||
GTEST_INTERNAL_PARSE_FLAG(shuffle);
|
||||
GTEST_INTERNAL_PARSE_FLAG(stack_trace_depth);
|
||||
@@ -6778,7 +6934,7 @@ void ParseGoogleTestFlagsOnly(int* argc, char** argv) {
|
||||
std::vector<char*> positional_args;
|
||||
std::vector<absl::UnrecognizedFlag> unrecognized_flags;
|
||||
absl::ParseAbseilFlagsOnly(*argc, argv, positional_args, unrecognized_flags);
|
||||
absl::flat_hash_set<absl::string_view> unrecognized;
|
||||
absl::flat_hash_set<std::string_view> unrecognized;
|
||||
for (const auto& flag : unrecognized_flags) {
|
||||
unrecognized.insert(flag.flag_name);
|
||||
}
|
||||
|
||||
+56
-20
@@ -30,6 +30,7 @@
|
||||
#
|
||||
# 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")
|
||||
|
||||
licenses(["notice"])
|
||||
@@ -47,33 +48,36 @@ cc_test(
|
||||
"*.h",
|
||||
],
|
||||
exclude = [
|
||||
"gtest-unittest-api_test.cc",
|
||||
"googletest/src/gtest-all.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",
|
||||
# go/keep-sorted start
|
||||
"googletest-break-on-failure-unittest_.cc",
|
||||
"googletest-catch-exceptions-test_.cc",
|
||||
"googletest-color-test_.cc",
|
||||
"googletest-death-test_ex_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-filter-unittest_.cc",
|
||||
"googletest-global-environment-unittest_.cc",
|
||||
"googletest-break-on-failure-unittest_.cc",
|
||||
"googletest-list-tests-unittest_.cc",
|
||||
"googletest-listener-test.cc",
|
||||
"googletest-message-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-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({
|
||||
"//:windows": [],
|
||||
@@ -121,7 +125,7 @@ cc_test(
|
||||
name = "googletest-listener-test",
|
||||
size = "small",
|
||||
srcs = ["googletest-listener-test.cc"],
|
||||
deps = ["//:gtest_main"],
|
||||
deps = ["//:gtest"],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
@@ -323,6 +327,26 @@ cc_binary(
|
||||
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(
|
||||
name = "gtest_skip_test",
|
||||
size = "small",
|
||||
@@ -334,7 +358,7 @@ cc_test(
|
||||
name = "gtest_skip_in_environment_setup_test",
|
||||
size = "small",
|
||||
srcs = ["gtest_skip_in_environment_setup_test.cc"],
|
||||
deps = ["//:gtest_main"],
|
||||
deps = ["//:gtest"],
|
||||
)
|
||||
|
||||
py_test(
|
||||
@@ -363,6 +387,18 @@ py_test(
|
||||
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(
|
||||
name = "googletest-shuffle-test_",
|
||||
srcs = ["googletest-shuffle-test_.cc"],
|
||||
@@ -381,7 +417,7 @@ cc_binary(
|
||||
name = "googletest-catch-exceptions-no-ex-test_",
|
||||
testonly = 1,
|
||||
srcs = ["googletest-catch-exceptions-test_.cc"],
|
||||
deps = ["//:gtest_main"],
|
||||
deps = ["//:gtest"],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
@@ -389,7 +425,7 @@ cc_binary(
|
||||
testonly = 1,
|
||||
srcs = ["googletest-catch-exceptions-test_.cc"],
|
||||
copts = ["-fexceptions"],
|
||||
deps = ["//:gtest_main"],
|
||||
deps = ["//:gtest"],
|
||||
)
|
||||
|
||||
py_test(
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
edition = "2024";
|
||||
|
||||
package testing.internal.dynamic_cast_message_test;
|
||||
|
||||
message FooMessage {
|
||||
int32 int_field = 1;
|
||||
}
|
||||
|
||||
message BarMessage {}
|
||||
@@ -79,6 +79,7 @@ class GTestColorTest(gtest_test_utils.TestCase):
|
||||
self.assertTrue(UsesColor('cygwin', None, None))
|
||||
self.assertTrue(UsesColor('xterm', 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('alacritty', None, None))
|
||||
self.assertTrue(UsesColor('xterm-256color', None, None))
|
||||
|
||||
@@ -208,6 +208,7 @@ int DieInDebugElse12(int* sideeffect) {
|
||||
#ifdef GTEST_OS_WINDOWS
|
||||
|
||||
// Death in dbg due to Windows CRT assertion failure, not opt.
|
||||
#ifdef _DEBUG
|
||||
int DieInCRTDebugElse12(int* sideeffect) {
|
||||
if (sideeffect) *sideeffect = 12;
|
||||
|
||||
@@ -222,6 +223,7 @@ int DieInCRTDebugElse12(int* sideeffect) {
|
||||
|
||||
return 12;
|
||||
}
|
||||
#endif // _DEBUG
|
||||
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
@@ -291,7 +293,7 @@ TEST(ExitStatusPredicateTest, KilledBySignal) {
|
||||
const int status_kill = KilledExitStatus(SIGKILL);
|
||||
const testing::KilledBySignal pred_segv(SIGSEGV);
|
||||
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);
|
||||
#endif
|
||||
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
@@ -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()
|
||||
@@ -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_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.
|
||||
FILTER_FLAG = 'gtest_filter'
|
||||
|
||||
@@ -419,6 +422,22 @@ class GTestFilterUnitTest(gtest_test_utils.TestCase):
|
||||
self.RunAndVerify('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):
|
||||
"""Tests filtering by full name."""
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
// This file verifies Google Test event listeners receive events at the
|
||||
// right times.
|
||||
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -498,8 +499,7 @@ int main(int argc, char** argv) {
|
||||
"1st.OnTestProgramEnd"};
|
||||
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
|
||||
|
||||
VerifyResults(events, expected_events,
|
||||
sizeof(expected_events) / sizeof(expected_events[0]));
|
||||
VerifyResults(events, expected_events, std::size(expected_events));
|
||||
|
||||
// We need to check manually for ad hoc test failures that happen after
|
||||
// RUN_ALL_TESTS finishes.
|
||||
|
||||
@@ -62,7 +62,7 @@ Expected equality of these values:
|
||||
Which is: "\"Line\0 1\"\nLine 2"
|
||||
"Line 2"
|
||||
With diff:
|
||||
@@ -1,2 @@
|
||||
@@ -1,2 +1 @@
|
||||
-\"Line\0 1\"
|
||||
Line 2
|
||||
|
||||
|
||||
@@ -349,14 +349,16 @@ class GTestOutputTest(gtest_test_utils.TestCase):
|
||||
gtest_test_utils.GetSourceDir(),
|
||||
'_googletest-output-test_normalized_actual.txt',
|
||||
),
|
||||
'wb',
|
||||
'w',
|
||||
encoding='utf-8',
|
||||
).write(normalized_actual)
|
||||
open(
|
||||
os.path.join(
|
||||
gtest_test_utils.GetSourceDir(),
|
||||
'_googletest-output-test_normalized_golden.txt',
|
||||
),
|
||||
'wb',
|
||||
'w',
|
||||
encoding='utf-8',
|
||||
).write(normalized_golden)
|
||||
|
||||
self.assertEqual(normalized_golden, normalized_actual)
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
|
||||
#include "gtest/gtest-spi.h"
|
||||
@@ -149,7 +150,7 @@ TEST(LoggingTest, InterleavingLoggingAndAssertions) {
|
||||
static const int a[4] = {3, 9, 2, 6};
|
||||
|
||||
printf("(expecting 2 failures on (3) >= (a[i]))\n");
|
||||
for (int i = 0; i < static_cast<int>(sizeof(a) / sizeof(*a)); i++) {
|
||||
for (int i = 0; i < static_cast<int>(std::size(a)); i++) {
|
||||
printf("i == %d\n", i);
|
||||
EXPECT_GE(3, a[i]);
|
||||
}
|
||||
|
||||
@@ -35,12 +35,18 @@
|
||||
#include "test/googletest-param-test-test.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
@@ -583,6 +589,71 @@ TEST(ConvertTest, NonDefaultConstructAssign) {
|
||||
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
|
||||
// assigned from another generator.
|
||||
TEST(ParamGeneratorTest, AssignmentWorks) {
|
||||
@@ -626,7 +697,7 @@ class TestGenerationEnvironment : public ::testing::Environment {
|
||||
msg << "TestsExpandedAndRun/" << i;
|
||||
if (UnitTestOptions::FilterMatchesTest(
|
||||
"TestExpansionModule/MultipleTestGenerationTest",
|
||||
msg.GetString().c_str())) {
|
||||
msg.GetString())) {
|
||||
perform_check = true;
|
||||
}
|
||||
}
|
||||
@@ -667,10 +738,7 @@ const int test_generation_params[] = {36, 42, 72};
|
||||
|
||||
class TestGenerationTest : public TestWithParam<int> {
|
||||
public:
|
||||
enum {
|
||||
PARAMETER_COUNT =
|
||||
sizeof(test_generation_params) / sizeof(test_generation_params[0])
|
||||
};
|
||||
enum { PARAMETER_COUNT = std::size(test_generation_params) };
|
||||
|
||||
typedef TestGenerationEnvironment<PARAMETER_COUNT> Environment;
|
||||
|
||||
@@ -1104,7 +1172,7 @@ TEST_P(ParameterizedDerivedTest, SeesSequence) {
|
||||
class ParameterizedDeathTest : public ::testing::TestWithParam<int> {};
|
||||
|
||||
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,
|
||||
|
||||
@@ -288,8 +288,8 @@ TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownFileAndLine) {
|
||||
defined(GTEST_OS_OPENBSD) || defined(GTEST_OS_GNU_HURD)
|
||||
void* ThreadFunc(void* data) {
|
||||
internal::Mutex* mutex = static_cast<internal::Mutex*>(data);
|
||||
mutex->Lock();
|
||||
mutex->Unlock();
|
||||
mutex->lock();
|
||||
mutex->unlock();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -308,7 +308,7 @@ TEST(GetThreadCountTest, ReturnsCorrectValue) {
|
||||
|
||||
internal::Mutex mutex;
|
||||
{
|
||||
internal::MutexLock lock(&mutex);
|
||||
internal::MutexLock lock(mutex);
|
||||
pthread_attr_t attr;
|
||||
ASSERT_EQ(0, pthread_attr_init(&attr));
|
||||
ASSERT_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE));
|
||||
@@ -1028,7 +1028,9 @@ TEST(MutexDeathTest, AssertHeldShouldAssertWhenNotLocked) {
|
||||
EXPECT_DEATH_IF_SUPPORTED(
|
||||
{
|
||||
Mutex m;
|
||||
{ MutexLock lock(&m); }
|
||||
{
|
||||
MutexLock lock(m);
|
||||
}
|
||||
m.AssertHeld();
|
||||
},
|
||||
"thread .*hold");
|
||||
@@ -1036,13 +1038,13 @@ TEST(MutexDeathTest, AssertHeldShouldAssertWhenNotLocked) {
|
||||
|
||||
TEST(MutexTest, AssertHeldShouldNotAssertWhenLocked) {
|
||||
Mutex m;
|
||||
MutexLock lock(&m);
|
||||
MutexLock lock(m);
|
||||
m.AssertHeld();
|
||||
}
|
||||
|
||||
class AtomicCounterWithMutex {
|
||||
public:
|
||||
explicit AtomicCounterWithMutex(Mutex* mutex)
|
||||
explicit AtomicCounterWithMutex(Mutex& mutex)
|
||||
: value_(0), mutex_(mutex), random_(42) {}
|
||||
|
||||
void Increment() {
|
||||
@@ -1083,7 +1085,7 @@ class AtomicCounterWithMutex {
|
||||
|
||||
private:
|
||||
volatile int value_;
|
||||
Mutex* const mutex_; // Protects value_.
|
||||
Mutex& mutex_; // Protects value_.
|
||||
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.
|
||||
TEST(MutexTest, OnlyOneThreadCanLockAtATime) {
|
||||
Mutex mutex;
|
||||
AtomicCounterWithMutex locked_counter(&mutex);
|
||||
AtomicCounterWithMutex locked_counter(mutex);
|
||||
|
||||
typedef ThreadWithParam<pair<AtomicCounterWithMutex*, int> > ThreadType;
|
||||
const int kCycleCount = 20;
|
||||
|
||||
@@ -32,24 +32,29 @@
|
||||
// This file tests the universal value printer.
|
||||
|
||||
#include <algorithm>
|
||||
#include <any>
|
||||
#include <cctype>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <deque>
|
||||
#include <forward_list>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/gtest-printers.h"
|
||||
@@ -62,7 +67,7 @@
|
||||
|
||||
#if GTEST_INTERNAL_HAS_STD_SPAN
|
||||
#include <span> // NOLINT
|
||||
#endif // GTEST_INTERNAL_HAS_STD_SPAN
|
||||
#endif // GTEST_INTERNAL_HAS_STD_SPAN
|
||||
|
||||
#if GTEST_INTERNAL_HAS_COMPARE_LIB
|
||||
#include <compare> // NOLINT
|
||||
@@ -121,6 +126,9 @@ class UnprintableTemplateInGlobal {
|
||||
// A user-defined streamable type in the global namespace.
|
||||
class StreamableInGlobal {
|
||||
public:
|
||||
StreamableInGlobal() = default;
|
||||
StreamableInGlobal(const StreamableInGlobal&) = default;
|
||||
StreamableInGlobal& operator=(const StreamableInGlobal&) = default;
|
||||
virtual ~StreamableInGlobal() = default;
|
||||
};
|
||||
|
||||
@@ -388,12 +396,24 @@ TEST(PrintCharTest, UnsignedChar) {
|
||||
EXPECT_EQ("'b' (98, 0x62)", Print(static_cast<unsigned char>('b')));
|
||||
}
|
||||
|
||||
TEST(PrintCharTest, Char16) { EXPECT_EQ("U+0041", Print(u'A')); }
|
||||
TEST(PrintCharTest, Char16) {
|
||||
EXPECT_EQ("U+0041", Print(u'A'));
|
||||
EXPECT_EQ("U+754C", Print(u'界'));
|
||||
// Surrogates are not code points, so they are printed as code units.
|
||||
EXPECT_EQ("u'\\xD800' (55296)", Print(static_cast<char16_t>(0xD800)));
|
||||
EXPECT_EQ("u'\\xDFFF' (57343)", Print(static_cast<char16_t>(0xDFFF)));
|
||||
}
|
||||
|
||||
TEST(PrintCharTest, Char32) { EXPECT_EQ("U+0041", Print(U'A')); }
|
||||
|
||||
#ifdef __cpp_lib_char8_t
|
||||
TEST(PrintCharTest, Char8) { EXPECT_EQ("U+0041", Print(u8'A')); }
|
||||
TEST(PrintCharTest, Char8) {
|
||||
EXPECT_EQ("U+0041", Print(u8'A'));
|
||||
// Only ASCII code units encode a code point on their own; the rest are
|
||||
// printed as code units.
|
||||
EXPECT_EQ("u8'\\x80' (128)", Print(static_cast<char8_t>(0x80)));
|
||||
EXPECT_EQ("u8'\\xFF' (255)", Print(static_cast<char8_t>(0xFF)));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Tests printing other simple, built-in types.
|
||||
@@ -448,7 +468,7 @@ TEST(PrintBuiltInTypeTest, Integer) {
|
||||
#ifdef __cpp_lib_char8_t
|
||||
EXPECT_EQ("U+0000",
|
||||
Print(std::numeric_limits<char8_t>::min())); // char8_t
|
||||
EXPECT_EQ("U+00FF",
|
||||
EXPECT_EQ("u8'\\xFF' (255)",
|
||||
Print(std::numeric_limits<char8_t>::max())); // char8_t
|
||||
#endif
|
||||
EXPECT_EQ("U+0000",
|
||||
@@ -572,6 +592,8 @@ TEST(PrintU8StringTest, Null) {
|
||||
}
|
||||
|
||||
// Tests that u8 strings are escaped properly.
|
||||
// TODO(b/396121064) - Fix this test under MSVC
|
||||
#ifndef _MSC_VER
|
||||
TEST(PrintU8StringTest, EscapesProperly) {
|
||||
const char8_t* p = u8"'\"?\\\a\b\f\n\r\t\v\x7F\xFF hello 世界";
|
||||
EXPECT_EQ(PrintPointer(p) +
|
||||
@@ -579,7 +601,8 @@ TEST(PrintU8StringTest, EscapesProperly) {
|
||||
"hello \\xE4\\xB8\\x96\\xE7\\x95\\x8C\"",
|
||||
Print(p));
|
||||
}
|
||||
#endif
|
||||
#endif // _MSC_VER
|
||||
#endif // __cpp_lib_char8_t
|
||||
|
||||
// const char16_t*.
|
||||
TEST(PrintU16StringTest, Const) {
|
||||
@@ -637,13 +660,8 @@ TEST(PrintU32StringTest, EscapesProperly) {
|
||||
Print(p));
|
||||
}
|
||||
|
||||
// MSVC compiler can be configured to define whar_t as a typedef
|
||||
// of unsigned short. Defining an overload for const wchar_t* in that case
|
||||
// would cause pointers to unsigned shorts be printed as wide strings,
|
||||
// possibly accessing more memory than intended and causing invalid
|
||||
// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
|
||||
// wchar_t is implemented as a native type.
|
||||
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
|
||||
#if GTEST_HAS_NATIVE_WCHAR
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
|
||||
// const wchar_t*.
|
||||
TEST(PrintWideCStringTest, Const) {
|
||||
@@ -674,7 +692,8 @@ TEST(PrintWideCStringTest, EscapesProperly) {
|
||||
"\\n\\r\\t\\v\\xD3\\x576\\x8D3\\xC74D a\"",
|
||||
Print(static_cast<const wchar_t*>(s)));
|
||||
}
|
||||
#endif // native wchar_t
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
#endif // GTEST_HAS_NATIVE_WCHAR
|
||||
|
||||
// Tests printing pointers to other char types.
|
||||
|
||||
@@ -790,7 +809,7 @@ struct Foo {
|
||||
TEST(PrintPointerTest, MemberVariablePointer) {
|
||||
EXPECT_TRUE(HasPrefix(Print(&Foo::value),
|
||||
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 "));
|
||||
}
|
||||
|
||||
@@ -917,7 +936,7 @@ TEST(PrintArrayTest, BigArray) {
|
||||
PrintArrayHelper(a));
|
||||
}
|
||||
|
||||
// Tests printing ::string and ::std::string.
|
||||
// Tests printing ::std::string and ::string_view.
|
||||
|
||||
// ::std::string.
|
||||
TEST(PrintStringTest, StringInStdNamespace) {
|
||||
@@ -927,6 +946,13 @@ TEST(PrintStringTest, StringInStdNamespace) {
|
||||
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) {
|
||||
// "\x6BANANA" is ambiguous, it can be interpreted as starting with either of:
|
||||
// '\x6', '\x6B', or '\x6BA'.
|
||||
@@ -944,7 +970,7 @@ TEST(PrintStringTest, StringAmbiguousHex) {
|
||||
EXPECT_EQ("\"!\\x5-!\"", Print(::std::string("!\x5-!")));
|
||||
}
|
||||
|
||||
// Tests printing ::std::wstring.
|
||||
// Tests printing ::std::wstring and ::std::wstring_view.
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
// ::std::wstring.
|
||||
TEST(PrintWideStringTest, StringInStdNamespace) {
|
||||
@@ -956,6 +982,15 @@ TEST(PrintWideStringTest, StringInStdNamespace) {
|
||||
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) {
|
||||
// same for wide strings.
|
||||
EXPECT_EQ("L\"0\\x12\" L\"3\"", Print(::std::wstring(L"0\x12"
|
||||
@@ -974,6 +1009,12 @@ TEST(PrintStringTest, U8String) {
|
||||
EXPECT_EQ(str, str); // Verify EXPECT_EQ compiles with this type.
|
||||
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
|
||||
|
||||
TEST(PrintStringTest, U16String) {
|
||||
@@ -982,12 +1023,24 @@ TEST(PrintStringTest, U16String) {
|
||||
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) {
|
||||
std::u32string str = U"Hello, 🗺️";
|
||||
EXPECT_EQ(str, str); // Verify EXPECT_EQ compiles with this type
|
||||
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
|
||||
// to std::basic_ostream<Char, CharTraits> for any valid Char and
|
||||
// CharTraits types).
|
||||
@@ -1046,8 +1099,6 @@ TEST(PrintTypeWithGenericStreamingTest, TypeImplicitlyConvertible) {
|
||||
EXPECT_EQ("AllowsGenericStreamingAndImplicitConversionTemplate", Print(a));
|
||||
}
|
||||
|
||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
// Tests printing internal::StringView.
|
||||
|
||||
TEST(PrintStringViewTest, SimpleStringView) {
|
||||
@@ -1061,8 +1112,6 @@ TEST(PrintStringViewTest, UnprintableCharacters) {
|
||||
EXPECT_EQ("\"NUL (\\0) and \\r\\t\"", Print(sp));
|
||||
}
|
||||
|
||||
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
|
||||
|
||||
// Tests printing STL containers.
|
||||
|
||||
TEST(PrintStlContainerTest, EmptyDeque) {
|
||||
@@ -1447,7 +1496,7 @@ TEST(PrintReferenceTest, HandlesMemberFunctionPointer) {
|
||||
// Tests that the universal printer prints a member variable pointer
|
||||
// passed by reference.
|
||||
TEST(PrintReferenceTest, HandlesMemberVariablePointer) {
|
||||
int Foo::*p = &Foo::value; // NOLINT
|
||||
int Foo::* p = &Foo::value; // NOLINT
|
||||
EXPECT_TRUE(HasPrefix(PrintByRef(p), "@" + PrintPointer(&p) + " " +
|
||||
Print(sizeof(p)) + "-byte object "));
|
||||
}
|
||||
@@ -1655,7 +1704,7 @@ TEST(PrintToStringTest, ContainsNonLatin) {
|
||||
EXPECT_PRINT_TO_STRING_(non_ascii_str,
|
||||
"\"\\xEC\\x98\\xA4\\xEC\\xA0\\x84 4:30\"\n"
|
||||
" As Text: \"오전 4:30\"");
|
||||
non_ascii_str = ::std::string("From ä — ẑ");
|
||||
non_ascii_str = "From ä — ẑ";
|
||||
EXPECT_PRINT_TO_STRING_(non_ascii_str,
|
||||
"\"From \\xC3\\xA4 \\xE2\\x80\\x94 \\xE1\\xBA\\x91\""
|
||||
"\n As Text: \"From ä — ẑ\"");
|
||||
@@ -1740,7 +1789,7 @@ TEST(IsValidUTF8Test, IllFormedUTF8) {
|
||||
// too.
|
||||
{"\xEE\x80\x80", "\"\\xEE\\x80\\x80\"\n As Text: \"\""}};
|
||||
|
||||
for (int i = 0; i < int(sizeof(kTestdata) / sizeof(kTestdata[0])); ++i) {
|
||||
for (int i = 0; i < int(std::size(kTestdata)); ++i) {
|
||||
EXPECT_PRINT_TO_STRING_(kTestdata[i][0], kTestdata[i][1]);
|
||||
}
|
||||
}
|
||||
@@ -1885,6 +1934,22 @@ TEST(UniversalPrintTest, SmartPointers) {
|
||||
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) {
|
||||
Strings result = UniversalTersePrintTupleFieldsToStrings(::std::make_tuple());
|
||||
EXPECT_EQ(0u, result.size());
|
||||
@@ -1914,7 +1979,6 @@ TEST(UniversalTersePrintTupleFieldsToStringsTestWithStd, PrintsTersely) {
|
||||
EXPECT_EQ("\"a\"", result[1]);
|
||||
}
|
||||
|
||||
#if GTEST_INTERNAL_HAS_ANY
|
||||
class PrintAnyTest : public ::testing::Test {
|
||||
protected:
|
||||
template <typename T>
|
||||
@@ -1928,12 +1992,12 @@ class PrintAnyTest : public ::testing::Test {
|
||||
};
|
||||
|
||||
TEST_F(PrintAnyTest, Empty) {
|
||||
internal::Any any;
|
||||
std::any any;
|
||||
EXPECT_EQ("no value", PrintToString(any));
|
||||
}
|
||||
|
||||
TEST_F(PrintAnyTest, NonEmpty) {
|
||||
internal::Any any;
|
||||
std::any any;
|
||||
constexpr int val1 = 10;
|
||||
const std::string val2 = "content";
|
||||
|
||||
@@ -1944,27 +2008,23 @@ TEST_F(PrintAnyTest, NonEmpty) {
|
||||
EXPECT_EQ("value of type " + ExpectedTypeName<std::string>(),
|
||||
PrintToString(any));
|
||||
}
|
||||
#endif // GTEST_INTERNAL_HAS_ANY
|
||||
|
||||
#if GTEST_INTERNAL_HAS_OPTIONAL
|
||||
TEST(PrintOptionalTest, Basic) {
|
||||
EXPECT_EQ("(nullopt)", PrintToString(internal::Nullopt()));
|
||||
internal::Optional<int> value;
|
||||
EXPECT_EQ("(nullopt)", PrintToString(std::nullopt));
|
||||
std::optional<int> value;
|
||||
EXPECT_EQ("(nullopt)", PrintToString(value));
|
||||
value = {7};
|
||||
EXPECT_EQ("(7)", PrintToString(value));
|
||||
EXPECT_EQ("(1.1)", PrintToString(internal::Optional<double>{1.1}));
|
||||
EXPECT_EQ("(\"A\")", PrintToString(internal::Optional<std::string>{"A"}));
|
||||
EXPECT_EQ("(1.1)", PrintToString(std::optional<double>{1.1}));
|
||||
EXPECT_EQ("(\"A\")", PrintToString(std::optional<std::string>{"A"}));
|
||||
}
|
||||
#endif // GTEST_INTERNAL_HAS_OPTIONAL
|
||||
|
||||
#if GTEST_INTERNAL_HAS_VARIANT
|
||||
struct NonPrintable {
|
||||
unsigned char contents = 17;
|
||||
};
|
||||
|
||||
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("('StreamableInGlobal(index = 1)' with value StreamableInGlobal)",
|
||||
PrintToString(Type(StreamableInGlobal{})));
|
||||
@@ -1973,7 +2033,27 @@ TEST(PrintOneofTest, Basic) {
|
||||
"1-byte object <11>)",
|
||||
PrintToString(Type(NonPrintable{})));
|
||||
}
|
||||
#endif // GTEST_INTERNAL_HAS_VARIANT
|
||||
|
||||
TEST(PrintVariantTest, Monostate) {
|
||||
EXPECT_EQ("(monostate)", PrintToString(std::monostate()));
|
||||
|
||||
#if GTEST_HAS_EXCEPTIONS
|
||||
struct ThrowOnMove {
|
||||
ThrowOnMove() = default;
|
||||
ThrowOnMove(ThrowOnMove&& other) { *this = std::move(other); }
|
||||
ThrowOnMove& operator=(ThrowOnMove&&) {
|
||||
(void)std::vector<bool>().at(0);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
std::variant<std::monostate, ThrowOnMove> v = std::monostate();
|
||||
std::string res = PrintToString(v);
|
||||
EXPECT_NE(res.find("::monostate(index = 0)' with value (monostate))"),
|
||||
res.npos);
|
||||
EXPECT_THROW(v = ThrowOnMove(), std::out_of_range);
|
||||
EXPECT_EQ("(valueless)", PrintToString(v));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if GTEST_INTERNAL_HAS_COMPARE_LIB
|
||||
TEST(PrintOrderingTest, Basic) {
|
||||
|
||||
@@ -31,14 +31,14 @@
|
||||
|
||||
class SetupFailTest : public ::testing::Test {
|
||||
protected:
|
||||
static void SetUpTestSuite() { ASSERT_EQ("", "SET_UP_FAIL"); }
|
||||
static void SetUpTestSuite() { ASSERT_STREQ("", "SET_UP_FAIL"); }
|
||||
};
|
||||
|
||||
TEST_F(SetupFailTest, NoopPassingTest) {}
|
||||
|
||||
class TearDownFailTest : public ::testing::Test {
|
||||
protected:
|
||||
static void TearDownTestSuite() { ASSERT_EQ("", "TEAR_DOWN_FAIL"); }
|
||||
static void TearDownTestSuite() { ASSERT_STREQ("", "TEAR_DOWN_FAIL"); }
|
||||
};
|
||||
|
||||
TEST_F(TearDownFailTest, NoopPassingTest) {}
|
||||
|
||||
@@ -45,7 +45,7 @@ class TestPartResultTest : public Test {
|
||||
TestPartResultTest()
|
||||
: r1_(TestPartResult::kSuccess, "foo/bar.cc", 10, "Success!"),
|
||||
r2_(TestPartResult::kNonFatalFailure, "foo/bar.cc", -1, "Failure!"),
|
||||
r3_(TestPartResult::kFatalFailure, nullptr, -1, "Failure!"),
|
||||
r3_(TestPartResult::kFatalFailure, "", -1, "Failure!"),
|
||||
r4_(TestPartResult::kSkip, "foo/bar.cc", 2, "Skipped!") {}
|
||||
|
||||
TestPartResult r1_, r2_, r3_, r4_;
|
||||
|
||||
@@ -64,6 +64,7 @@ IS_WINDOWS = os.name == 'nt'
|
||||
PROGRAM_PATH = gtest_test_utils.GetTestExecutablePath('gtest_help_test_')
|
||||
FLAG_PREFIX = '--gtest_'
|
||||
DEATH_TEST_STYLE_FLAG = FLAG_PREFIX + 'death_test_style'
|
||||
DEATH_TEST_USE_FORK_FLAG = FLAG_PREFIX + 'death_test_use_fork'
|
||||
STREAM_RESULT_TO_FLAG = FLAG_PREFIX + 'stream_result_to'
|
||||
LIST_TESTS_FLAG = FLAG_PREFIX + 'list_tests'
|
||||
INTERNAL_FLAG_FOR_TESTING = FLAG_PREFIX + 'internal_flag_for_testing'
|
||||
@@ -90,19 +91,27 @@ HELP_REGEX = re.compile(
|
||||
+ FLAG_PREFIX
|
||||
+ r'random_seed=.*'
|
||||
+ FLAG_PREFIX
|
||||
+ r'fail_fast.*'
|
||||
+ FLAG_PREFIX
|
||||
+ r'fail_if_no_test_linked.*'
|
||||
+ FLAG_PREFIX
|
||||
+ r'color=.*'
|
||||
+ FLAG_PREFIX
|
||||
+ r'brief.*'
|
||||
+ FLAG_PREFIX
|
||||
+ r'print_time.*'
|
||||
+ FLAG_PREFIX
|
||||
+ r'print_utf8.*'
|
||||
+ FLAG_PREFIX
|
||||
+ r'output=.*'
|
||||
+ FLAG_PREFIX
|
||||
+ r'break_on_failure.*'
|
||||
+ FLAG_PREFIX
|
||||
+ r'throw_on_failure.*'
|
||||
+ FLAG_PREFIX
|
||||
+ r'catch_exceptions=0.*',
|
||||
+ r'catch_exceptions=0.*'
|
||||
+ FLAG_PREFIX
|
||||
+ r'stack_trace_depth=.*',
|
||||
re.DOTALL,
|
||||
)
|
||||
|
||||
@@ -151,8 +160,10 @@ class GTestHelpTest(gtest_test_utils.TestCase):
|
||||
|
||||
if SUPPORTS_DEATH_TESTS and not IS_WINDOWS:
|
||||
self.assertIn(DEATH_TEST_STYLE_FLAG, output)
|
||||
self.assertIn(DEATH_TEST_USE_FORK_FLAG, output)
|
||||
else:
|
||||
self.assertNotIn(DEATH_TEST_STYLE_FLAG, output)
|
||||
self.assertNotIn(DEATH_TEST_USE_FORK_FLAG, output)
|
||||
|
||||
def test_runs_tests_without_help_flag(self):
|
||||
"""Verifies correct behavior when no help flag is specified.
|
||||
|
||||
@@ -95,9 +95,9 @@ void ManyAsserts(int id) {
|
||||
|
||||
// RecordProperty() should interact safely with other threads as well.
|
||||
// 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("shared_key", IdToString(id).c_str());
|
||||
Test::RecordProperty("shared_key", IdToString(id));
|
||||
|
||||
// This assertion should fail kThreadCount times per thread. It
|
||||
// is for testing whether Google Test can handle failed assertions in a
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <iterator>
|
||||
|
||||
// Verifies that the command line flag variables can be accessed in
|
||||
// code once "gtest.h" has been #included.
|
||||
// Do not move it after other gtest #includes.
|
||||
@@ -88,6 +90,20 @@ static_assert(sizeof(decltype(std::declval<ConvertibleGlobalType&>()
|
||||
<< 1)(*)()) > 0,
|
||||
"error in operator<< overload resolution");
|
||||
|
||||
namespace {
|
||||
|
||||
template <bool MutableResult, bool ConstResult>
|
||||
struct ConvertibleToBool {
|
||||
explicit operator bool() { return MutableResult; }
|
||||
explicit operator bool() const { return ConstResult; }
|
||||
};
|
||||
|
||||
struct Bitfield {
|
||||
bool bit : 1;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace testing {
|
||||
namespace internal {
|
||||
|
||||
@@ -195,7 +211,7 @@ class TestEventListenersAccessor {
|
||||
|
||||
class UnitTestRecordPropertyTestHelper : public Test {
|
||||
protected:
|
||||
UnitTestRecordPropertyTestHelper() {}
|
||||
UnitTestRecordPropertyTestHelper() = default;
|
||||
|
||||
// Forwards to UnitTest::RecordProperty() to bypass access controls.
|
||||
void UnitTestRecordProperty(const char* key, const std::string& value) {
|
||||
@@ -375,7 +391,7 @@ TEST(CanonicalizeForStdLibVersioning, LeavesUnversionedNamesUnchanged) {
|
||||
EXPECT_EQ("std::bind", CanonicalizeForStdLibVersioning("std::bind"));
|
||||
EXPECT_EQ("std::_", CanonicalizeForStdLibVersioning("std::_"));
|
||||
EXPECT_EQ("std::__foo", CanonicalizeForStdLibVersioning("std::__foo"));
|
||||
EXPECT_EQ("gtl::__1::x", CanonicalizeForStdLibVersioning("gtl::__1::x"));
|
||||
EXPECT_EQ("absl::__1::x", CanonicalizeForStdLibVersioning("absl::__1::x"));
|
||||
EXPECT_EQ("__1::x", CanonicalizeForStdLibVersioning("__1::x"));
|
||||
EXPECT_EQ("::__1::x", CanonicalizeForStdLibVersioning("::__1::x"));
|
||||
}
|
||||
@@ -442,11 +458,11 @@ class FormatEpochTimeInMillisAsIso8601Test : public Test {
|
||||
void SetUp() override {
|
||||
saved_tz_.reset();
|
||||
|
||||
GTEST_DISABLE_MSC_DEPRECATED_PUSH_(/* getenv: deprecated */)
|
||||
GTEST_DISABLE_DEPRECATED_PUSH_(/* getenv: deprecated */)
|
||||
if (const char* tz = getenv("TZ")) {
|
||||
saved_tz_ = std::make_unique<std::string>(tz);
|
||||
}
|
||||
GTEST_DISABLE_MSC_DEPRECATED_POP_()
|
||||
GTEST_DISABLE_DEPRECATED_POP_()
|
||||
|
||||
// Set the local time zone for FormatEpochTimeInMillisAsIso8601 to be
|
||||
// a fixed time zone for reproducibility purposes.
|
||||
@@ -1873,36 +1889,31 @@ TEST(ShouldRunTestOnShardTest, IsPartitionWhenThereIsOneShard) {
|
||||
|
||||
class ShouldShardTest : public testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
index_var_ = GTEST_FLAG_PREFIX_UPPER_ "INDEX";
|
||||
total_var_ = GTEST_FLAG_PREFIX_UPPER_ "TOTAL";
|
||||
}
|
||||
void SetUp() override {}
|
||||
|
||||
void TearDown() override {
|
||||
SetEnv(index_var_, "");
|
||||
SetEnv(total_var_, "");
|
||||
GTEST_FLAG_SET(shard_index, -1);
|
||||
GTEST_FLAG_SET(total_shards, -1);
|
||||
}
|
||||
|
||||
const char* index_var_;
|
||||
const char* total_var_;
|
||||
};
|
||||
|
||||
// Tests that sharding is disabled if neither of the environment variables
|
||||
// are set.
|
||||
TEST_F(ShouldShardTest, ReturnsFalseWhenNeitherEnvVarIsSet) {
|
||||
SetEnv(index_var_, "");
|
||||
SetEnv(total_var_, "");
|
||||
GTEST_FLAG_SET(shard_index, -1);
|
||||
GTEST_FLAG_SET(total_shards, -1);
|
||||
|
||||
EXPECT_FALSE(ShouldShard(total_var_, index_var_, false));
|
||||
EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
|
||||
EXPECT_FALSE(ShouldShard(false));
|
||||
EXPECT_FALSE(ShouldShard(true));
|
||||
}
|
||||
|
||||
// Tests that sharding is not enabled if total_shards == 1.
|
||||
TEST_F(ShouldShardTest, ReturnsFalseWhenTotalShardIsOne) {
|
||||
SetEnv(index_var_, "0");
|
||||
SetEnv(total_var_, "1");
|
||||
EXPECT_FALSE(ShouldShard(total_var_, index_var_, false));
|
||||
EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
|
||||
GTEST_FLAG_SET(shard_index, 0);
|
||||
GTEST_FLAG_SET(total_shards, 1);
|
||||
|
||||
EXPECT_FALSE(ShouldShard(false));
|
||||
EXPECT_FALSE(ShouldShard(true));
|
||||
}
|
||||
|
||||
// Tests that sharding is enabled if total_shards > 1 and
|
||||
@@ -1910,20 +1921,20 @@ TEST_F(ShouldShardTest, ReturnsFalseWhenTotalShardIsOne) {
|
||||
// Environment variables are not supported on Windows CE.
|
||||
#ifndef GTEST_OS_WINDOWS_MOBILE
|
||||
TEST_F(ShouldShardTest, WorksWhenShardEnvVarsAreValid) {
|
||||
SetEnv(index_var_, "4");
|
||||
SetEnv(total_var_, "22");
|
||||
EXPECT_TRUE(ShouldShard(total_var_, index_var_, false));
|
||||
EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
|
||||
GTEST_FLAG_SET(shard_index, 4);
|
||||
GTEST_FLAG_SET(total_shards, 22);
|
||||
EXPECT_TRUE(ShouldShard(false));
|
||||
EXPECT_FALSE(ShouldShard(true));
|
||||
|
||||
SetEnv(index_var_, "8");
|
||||
SetEnv(total_var_, "9");
|
||||
EXPECT_TRUE(ShouldShard(total_var_, index_var_, false));
|
||||
EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
|
||||
GTEST_FLAG_SET(shard_index, 8);
|
||||
GTEST_FLAG_SET(total_shards, 9);
|
||||
EXPECT_TRUE(ShouldShard(false));
|
||||
EXPECT_FALSE(ShouldShard(true));
|
||||
|
||||
SetEnv(index_var_, "0");
|
||||
SetEnv(total_var_, "9");
|
||||
EXPECT_TRUE(ShouldShard(total_var_, index_var_, false));
|
||||
EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
|
||||
GTEST_FLAG_SET(shard_index, 0);
|
||||
GTEST_FLAG_SET(total_shards, 9);
|
||||
EXPECT_TRUE(ShouldShard(false));
|
||||
EXPECT_FALSE(ShouldShard(true));
|
||||
}
|
||||
#endif // !GTEST_OS_WINDOWS_MOBILE
|
||||
|
||||
@@ -1932,21 +1943,21 @@ TEST_F(ShouldShardTest, WorksWhenShardEnvVarsAreValid) {
|
||||
typedef ShouldShardTest ShouldShardDeathTest;
|
||||
|
||||
TEST_F(ShouldShardDeathTest, AbortsWhenShardingEnvVarsAreInvalid) {
|
||||
SetEnv(index_var_, "4");
|
||||
SetEnv(total_var_, "4");
|
||||
EXPECT_DEATH_IF_SUPPORTED(ShouldShard(total_var_, index_var_, false), ".*");
|
||||
GTEST_FLAG_SET(shard_index, 4);
|
||||
GTEST_FLAG_SET(total_shards, 4);
|
||||
EXPECT_DEATH_IF_SUPPORTED(ShouldShard(false), ".*");
|
||||
|
||||
SetEnv(index_var_, "4");
|
||||
SetEnv(total_var_, "-2");
|
||||
EXPECT_DEATH_IF_SUPPORTED(ShouldShard(total_var_, index_var_, false), ".*");
|
||||
GTEST_FLAG_SET(shard_index, 4);
|
||||
GTEST_FLAG_SET(total_shards, -2);
|
||||
EXPECT_DEATH_IF_SUPPORTED(ShouldShard(false), ".*");
|
||||
|
||||
SetEnv(index_var_, "5");
|
||||
SetEnv(total_var_, "");
|
||||
EXPECT_DEATH_IF_SUPPORTED(ShouldShard(total_var_, index_var_, false), ".*");
|
||||
GTEST_FLAG_SET(shard_index, 5);
|
||||
GTEST_FLAG_SET(total_shards, 5);
|
||||
EXPECT_DEATH_IF_SUPPORTED(ShouldShard(false), ".*");
|
||||
|
||||
SetEnv(index_var_, "");
|
||||
SetEnv(total_var_, "5");
|
||||
EXPECT_DEATH_IF_SUPPORTED(ShouldShard(total_var_, index_var_, false), ".*");
|
||||
GTEST_FLAG_SET(shard_index, -1);
|
||||
GTEST_FLAG_SET(total_shards, 5);
|
||||
EXPECT_DEATH_IF_SUPPORTED(ShouldShard(false), ".*");
|
||||
}
|
||||
|
||||
// Tests that ShouldRunTestOnShard is a partition when 5
|
||||
@@ -2163,7 +2174,7 @@ class UnitTestRecordPropertyTestEnvironment : public Environment {
|
||||
};
|
||||
|
||||
// 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);
|
||||
|
||||
// This group of tests is for predicate assertions (ASSERT_PRED*, etc)
|
||||
@@ -2553,6 +2564,7 @@ TEST(StringAssertionTest, ASSERT_STRCASENE) {
|
||||
EXPECT_FATAL_FAILURE(ASSERT_STRCASENE("Hi", "hi"), "(ignoring case)");
|
||||
}
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
// Tests *_STREQ on wide strings.
|
||||
TEST(StringAssertionTest, STREQ_Wide) {
|
||||
// NULL strings.
|
||||
@@ -2608,6 +2620,7 @@ TEST(StringAssertionTest, STRNE_Wide) {
|
||||
// The streaming variation.
|
||||
ASSERT_STRNE(L"abc\x8119", L"abc\x8120") << "This shouldn't happen";
|
||||
}
|
||||
#endif // GTEST_HAS_STD_WSTRING
|
||||
|
||||
// Tests for ::testing::IsSubstring().
|
||||
|
||||
@@ -2622,18 +2635,6 @@ TEST(IsSubstringTest, ReturnsCorrectResultForCString) {
|
||||
EXPECT_TRUE(IsSubstring("", "", "needle", "two needles"));
|
||||
}
|
||||
|
||||
// Tests that IsSubstring() returns the correct result when the input
|
||||
// argument type is const wchar_t*.
|
||||
TEST(IsSubstringTest, ReturnsCorrectResultForWideCString) {
|
||||
EXPECT_FALSE(IsSubstring("", "", kNull, L"a"));
|
||||
EXPECT_FALSE(IsSubstring("", "", L"b", kNull));
|
||||
EXPECT_FALSE(IsSubstring("", "", L"needle", L"haystack"));
|
||||
|
||||
EXPECT_TRUE(
|
||||
IsSubstring("", "", static_cast<const wchar_t*>(nullptr), nullptr));
|
||||
EXPECT_TRUE(IsSubstring("", "", L"needle", L"two needles"));
|
||||
}
|
||||
|
||||
// Tests that IsSubstring() generates the correct message when the input
|
||||
// argument type is const char*.
|
||||
TEST(IsSubstringTest, GeneratesCorrectMessageForCString) {
|
||||
@@ -2649,11 +2650,23 @@ TEST(IsSubstringTest, GeneratesCorrectMessageForCString) {
|
||||
// Tests that IsSubstring returns the correct result when the input
|
||||
// argument type is ::std::string.
|
||||
TEST(IsSubstringTest, ReturnsCorrectResultsForStdString) {
|
||||
EXPECT_TRUE(IsSubstring("", "", std::string("hello"), "ahellob"));
|
||||
EXPECT_FALSE(IsSubstring("", "", "hello", std::string("world")));
|
||||
EXPECT_TRUE(IsSubstring("", "", "hello", "ahellob"));
|
||||
EXPECT_FALSE(IsSubstring("", "", "hello", "world"));
|
||||
}
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
// Tests that IsSubstring() returns the correct result when the input
|
||||
// argument type is const wchar_t*.
|
||||
TEST(IsSubstringTest, ReturnsCorrectResultForWideCString) {
|
||||
EXPECT_FALSE(IsSubstring("", "", kNull, L"a"));
|
||||
EXPECT_FALSE(IsSubstring("", "", L"b", kNull));
|
||||
EXPECT_FALSE(IsSubstring("", "", L"needle", L"haystack"));
|
||||
|
||||
EXPECT_TRUE(
|
||||
IsSubstring("", "", static_cast<const wchar_t*>(nullptr), nullptr));
|
||||
EXPECT_TRUE(IsSubstring("", "", L"needle", L"two needles"));
|
||||
}
|
||||
|
||||
// Tests that IsSubstring returns the correct result when the input
|
||||
// argument type is ::std::wstring.
|
||||
TEST(IsSubstringTest, ReturnsCorrectResultForStdWstring) {
|
||||
@@ -2685,6 +2698,27 @@ TEST(IsNotSubstringTest, ReturnsCorrectResultForCString) {
|
||||
EXPECT_FALSE(IsNotSubstring("", "", "needle", "two needles"));
|
||||
}
|
||||
|
||||
// Tests that IsNotSubstring returns the correct result when the input
|
||||
// argument type is ::std::string.
|
||||
TEST(IsNotSubstringTest, ReturnsCorrectResultsForStdString) {
|
||||
EXPECT_FALSE(IsNotSubstring("", "", "hello", "ahellob"));
|
||||
EXPECT_TRUE(IsNotSubstring("", "", "hello", "world"));
|
||||
}
|
||||
|
||||
// Tests that IsNotSubstring() generates the correct message when the input
|
||||
// argument type is ::std::string.
|
||||
TEST(IsNotSubstringTest, GeneratesCorrectMessageForStdString) {
|
||||
EXPECT_STREQ(
|
||||
"Value of: needle_expr\n"
|
||||
" Actual: \"needle\"\n"
|
||||
"Expected: not a substring of haystack_expr\n"
|
||||
"Which is: \"two needles\"",
|
||||
IsNotSubstring("needle_expr", "haystack_expr", "needle", "two needles")
|
||||
.failure_message());
|
||||
}
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
|
||||
// Tests that IsNotSubstring() returns the correct result when the input
|
||||
// argument type is const wchar_t*.
|
||||
TEST(IsNotSubstringTest, ReturnsCorrectResultForWideCString) {
|
||||
@@ -2704,28 +2738,6 @@ TEST(IsNotSubstringTest, GeneratesCorrectMessageForWideCString) {
|
||||
.failure_message());
|
||||
}
|
||||
|
||||
// Tests that IsNotSubstring returns the correct result when the input
|
||||
// argument type is ::std::string.
|
||||
TEST(IsNotSubstringTest, ReturnsCorrectResultsForStdString) {
|
||||
EXPECT_FALSE(IsNotSubstring("", "", std::string("hello"), "ahellob"));
|
||||
EXPECT_TRUE(IsNotSubstring("", "", "hello", std::string("world")));
|
||||
}
|
||||
|
||||
// Tests that IsNotSubstring() generates the correct message when the input
|
||||
// argument type is ::std::string.
|
||||
TEST(IsNotSubstringTest, GeneratesCorrectMessageForStdString) {
|
||||
EXPECT_STREQ(
|
||||
"Value of: needle_expr\n"
|
||||
" Actual: \"needle\"\n"
|
||||
"Expected: not a substring of haystack_expr\n"
|
||||
"Which is: \"two needles\"",
|
||||
IsNotSubstring("needle_expr", "haystack_expr", ::std::string("needle"),
|
||||
"two needles")
|
||||
.failure_message());
|
||||
}
|
||||
|
||||
#if GTEST_HAS_STD_WSTRING
|
||||
|
||||
// Tests that IsNotSubstring returns the correct result when the input
|
||||
// argument type is ::std::wstring.
|
||||
TEST(IsNotSubstringTest, ReturnsCorrectResultForStdWstring) {
|
||||
@@ -3579,13 +3591,13 @@ TEST(EditDistance, TestSuites) {
|
||||
{__LINE__, "A", "A", " ", ""},
|
||||
{__LINE__, "ABCDE", "ABCDE", " ", ""},
|
||||
// Simple adds.
|
||||
{__LINE__, "X", "XA", " +", "@@ +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", "XA", " +", "@@ -1 +1,2 @@\n X\n+A\n"},
|
||||
{__LINE__, "X", "XABCD", " ++++", "@@ -1 +1,5 @@\n X\n+A\n+B\n+C\n+D\n"},
|
||||
// Simple removes.
|
||||
{__LINE__, "XA", "X", " -", "@@ -1,2 @@\n X\n-A\n"},
|
||||
{__LINE__, "XABCD", "X", " ----", "@@ -1,5 @@\n X\n-A\n-B\n-C\n-D\n"},
|
||||
{__LINE__, "XA", "X", " -", "@@ -1,2 +1 @@\n X\n-A\n"},
|
||||
{__LINE__, "XABCD", "X", " ----", "@@ -1,5 +1 @@\n X\n-A\n-B\n-C\n-D\n"},
|
||||
// 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", "////",
|
||||
"@@ -1,4 +1,4 @@\n-A\n-B\n-C\n-D\n+a\n+b\n+c\n+d\n"},
|
||||
// Path finding.
|
||||
@@ -3655,8 +3667,7 @@ TEST(AssertionTest, EqFailure) {
|
||||
msg4.c_str());
|
||||
|
||||
const std::string msg5(
|
||||
EqFailure("foo", "bar", std::string("\"x\""), std::string("\"y\""), true)
|
||||
.failure_message());
|
||||
EqFailure("foo", "bar", "\"x\"", "\"y\"", true).failure_message());
|
||||
EXPECT_STREQ(
|
||||
"Expected equality of these values:\n"
|
||||
" foo\n"
|
||||
@@ -3706,6 +3717,15 @@ TEST(AssertionTest, AppendUserMessage) {
|
||||
TEST(AssertionTest, ASSERT_TRUE) {
|
||||
ASSERT_TRUE(2 > 1); // NOLINT
|
||||
EXPECT_FATAL_FAILURE(ASSERT_TRUE(2 < 1), "2 < 1");
|
||||
|
||||
ASSERT_TRUE((ConvertibleToBool<true, false>()));
|
||||
ASSERT_TRUE((std::add_const_t<ConvertibleToBool<false, true>>()));
|
||||
|
||||
Bitfield bf = {true};
|
||||
ASSERT_TRUE(bf.bit); // &
|
||||
ASSERT_TRUE(Bitfield{true}.bit); // &&
|
||||
ASSERT_TRUE(static_cast<const Bitfield&>(Bitfield{true}).bit); // const&
|
||||
ASSERT_TRUE(static_cast<const Bitfield&&>(Bitfield{true}).bit); // const&&
|
||||
}
|
||||
|
||||
// Tests ASSERT_TRUE(predicate) for predicates returning AssertionResult.
|
||||
@@ -3732,6 +3752,15 @@ TEST(AssertionTest, ASSERT_FALSE) {
|
||||
"Value of: 2 > 1\n"
|
||||
" Actual: true\n"
|
||||
"Expected: false");
|
||||
|
||||
ASSERT_FALSE((ConvertibleToBool<false, true>()));
|
||||
ASSERT_FALSE((std::add_const_t<ConvertibleToBool<true, false>>()));
|
||||
|
||||
Bitfield bf = {false};
|
||||
ASSERT_FALSE(bf.bit); // &
|
||||
ASSERT_FALSE(Bitfield{false}.bit); // &&
|
||||
ASSERT_FALSE(static_cast<const Bitfield&>(Bitfield{false}).bit); // const&
|
||||
ASSERT_FALSE(static_cast<const Bitfield&&>(Bitfield{false}).bit); // const&&
|
||||
}
|
||||
|
||||
// Tests ASSERT_FALSE(predicate) for predicates returning AssertionResult.
|
||||
@@ -4433,6 +4462,15 @@ TEST(ExpectTest, EXPECT_TRUE) {
|
||||
" Actual: false\n"
|
||||
"Expected: true");
|
||||
EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(2 > 3), "2 > 3");
|
||||
|
||||
EXPECT_TRUE((ConvertibleToBool<true, false>()));
|
||||
EXPECT_TRUE((std::add_const_t<ConvertibleToBool<false, true>>()));
|
||||
|
||||
Bitfield bf = {true};
|
||||
EXPECT_TRUE(bf.bit); // &
|
||||
EXPECT_TRUE(Bitfield{true}.bit); // &&
|
||||
EXPECT_TRUE(static_cast<const Bitfield&>(Bitfield{true}).bit); // const&
|
||||
EXPECT_TRUE(static_cast<const Bitfield&&>(Bitfield{true}).bit); // const&&
|
||||
}
|
||||
|
||||
// Tests EXPECT_TRUE(predicate) for predicates returning AssertionResult.
|
||||
@@ -4462,6 +4500,15 @@ TEST(ExpectTest, EXPECT_FALSE) {
|
||||
" Actual: true\n"
|
||||
"Expected: false");
|
||||
EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(2 < 3), "2 < 3");
|
||||
|
||||
EXPECT_FALSE((ConvertibleToBool<false, true>()));
|
||||
EXPECT_FALSE((std::add_const_t<ConvertibleToBool<true, false>>()));
|
||||
|
||||
Bitfield bf = {false};
|
||||
EXPECT_FALSE(bf.bit); // &
|
||||
EXPECT_FALSE(Bitfield{false}.bit); // &&
|
||||
EXPECT_FALSE(static_cast<const Bitfield&>(Bitfield{false}).bit); // const&
|
||||
EXPECT_FALSE(static_cast<const Bitfield&&>(Bitfield{false}).bit); // const&&
|
||||
}
|
||||
|
||||
// Tests EXPECT_FALSE(predicate) for predicates returning AssertionResult.
|
||||
@@ -5810,9 +5857,8 @@ class ParseFlagsTest : public Test {
|
||||
// to specify the array sizes.
|
||||
|
||||
#define GTEST_TEST_PARSING_FLAGS_(argv1, argv2, expected, should_print_help) \
|
||||
TestParsingFlags(sizeof(argv1) / sizeof(*argv1) - 1, argv1, \
|
||||
sizeof(argv2) / sizeof(*argv2) - 1, argv2, expected, \
|
||||
should_print_help)
|
||||
TestParsingFlags(std::size(argv1) - 1, argv1, std::size(argv2) - 1, argv2, \
|
||||
expected, should_print_help)
|
||||
};
|
||||
|
||||
// Tests parsing an empty command line.
|
||||
@@ -6717,6 +6763,9 @@ TEST(ColoredOutputTest, UsesColorsWhenTermSupportsColors) {
|
||||
SetEnv("TERM", "xterm-color"); // TERM supports colors.
|
||||
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.
|
||||
EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
|
||||
|
||||
@@ -6754,9 +6803,8 @@ TEST(ColoredOutputTest, UsesColorsWhenTermSupportsColors) {
|
||||
|
||||
// Verifies that StaticAssertTypeEq works in a namespace scope.
|
||||
|
||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool dummy1 =
|
||||
StaticAssertTypeEq<bool, bool>();
|
||||
GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool dummy2 =
|
||||
[[maybe_unused]] static bool dummy1 = StaticAssertTypeEq<bool, bool>();
|
||||
[[maybe_unused]] static bool dummy2 =
|
||||
StaticAssertTypeEq<const int, const int>();
|
||||
|
||||
// Verifies that StaticAssertTypeEq works in a class.
|
||||
|
||||
+22
-6
@@ -9,17 +9,33 @@ def googletest_deps():
|
||||
if not native.existing_rule("re2"):
|
||||
http_archive(
|
||||
name = "re2",
|
||||
sha256 = "eb2df807c781601c14a260a507a5bb4509be1ee626024cb45acbd57cb9d4032b",
|
||||
strip_prefix = "re2-2024-07-02",
|
||||
urls = ["https://github.com/google/re2/releases/download/2024-07-02/re2-2024-07-02.tar.gz"],
|
||||
sha256 = "87f6029d2f6de8aa023654240a03ada90e876ce9a4676e258dd01ea4c26ffd67",
|
||||
strip_prefix = "re2-2025-11-05",
|
||||
urls = ["https://github.com/google/re2/releases/download/2025-11-05/re2-2025-11-05.tar.gz"],
|
||||
)
|
||||
|
||||
if not native.existing_rule("abseil-cpp"):
|
||||
http_archive(
|
||||
name = "abseil-cpp",
|
||||
sha256 = "16242f394245627e508ec6bb296b433c90f8d914f73b9c026fddb905e27276e8",
|
||||
strip_prefix = "abseil-cpp-20250127.0",
|
||||
urls = ["https://github.com/abseil/abseil-cpp/releases/download/20250127.0/abseil-cpp-20250127.0.tar.gz"],
|
||||
sha256 = "4c124408da902be896a2f368042729655709db5e3004ec99f57e3e14439bc1b2",
|
||||
strip_prefix = "abseil-cpp-20260107.0",
|
||||
urls = ["https://github.com/abseil/abseil-cpp/releases/download/20260107.0/abseil-cpp-20260107.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"):
|
||||
|
||||
Reference in New Issue
Block a user