Compare commits

..

40 Commits

Author SHA1 Message Date
Jesse Rosenstock
a6ce08abf7 Property: Promote note to warning
Property() should not be used against member functions that you do not own.  Make
this warning more prominent in matchers.md and add it to gmock-matchers.h.

PiperOrigin-RevId: 727753777
Change-Id: Idf9155103b04b98efc957ff0d0cf3a8d8662eb72
2025-02-17 01:00:00 -08:00
Derek Mauro
c00fd25b71 Require C++17
Policy information:
https://opensource.google/documentation/policies/cplusplus-support#c_language_standard
https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md

Some small fixes are included for C++17 compatibility.

We had no tests for MSVC C++17 or C++20, so those tests that failed
and had no obvious fix are disabled and a tracking bug has been filed.

PiperOrigin-RevId: 726090558
Change-Id: I4d37d47e87c11f85bfd572deb10f67ca3eb2a9b5
2025-02-12 09:44:07 -08:00
Abseil Team
4a00a24fff Add SaveArgByMove
Allows capture of move-only argument types (e.g. AnyInvocable)

PiperOrigin-RevId: 725262899
Change-Id: Idcd46e333a42d99ff05d58a1bc57d8791f6d45a6
2025-02-10 10:22:27 -08:00
Derek Mauro
a866428a78 Update docs for v1.16.x branch
Also update the minimum required CMake version
https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md

PiperOrigin-RevId: 724375734
Change-Id: Iefa6c7e2061457bc6149a280d2408085b1fb9d11
2025-02-07 09:41:05 -08:00
Derek Mauro
445e9bd8d0 Update GoogleTest deps in preparation for release
PiperOrigin-RevId: 724135630
Change-Id: I24622387e508d27337769e83f7de8fecae9ad425
2025-02-06 17:40:25 -08:00
Derek Mauro
e5443e5c65 Remove empty glob pattern, which is now an error.
It look like this may be a copy-paste bug from the root BUILD file.

PiperOrigin-RevId: 724062332
Change-Id: I8eda2275d996dd14693aee569254db28d9bc4f9d
2025-02-06 13:52:23 -08:00
Abseil Team
e235eb34c6 Pull Regexp syntax out of Death test section in advanced.md
Regexps seem to have nothing in common with death tests, yet their description is planted right in the middle of the death test section.

This CL pulls the regexp section one level up and just before death tests.

PiperOrigin-RevId: 721817710
Change-Id: Idc52f450fb10960a590ceb1a70339f86d4478fe4
2025-01-31 10:23:04 -08:00
Abseil Team
66d7401378 Fix extended regular expressions reference URL in advanced.md
The original URL started with https://www.opengroup.org and fails to redirect to the reference page. According to Chrome's dev tools (Network tab), the response to that request is a HTTP 302 Found, with the new location being "balancer://pubs/onlinepubs/009695399/basedefs/xbd_chap09.html". Chrome does not know what to do with that and displays a blank page.

Changing the `www` subdomain to `pubs` results in HTTP 200.

PiperOrigin-RevId: 721804738
Change-Id: I816d08d5baf957c63ac97506d04c7cc49c3a5ce7
2025-01-31 09:45:17 -08:00
Abseil Team
b4aae50ce1 Export testsuite properties as XML elements, not attributes.
With this change, arbitrary property names in the testsuite no longer
cause the produced XML output to be ill-formed.

PiperOrigin-RevId: 721549090
Change-Id: Iedffa89bf914478f563c8f3b82cd50557762a665
2025-01-30 16:01:31 -08:00
Abseil Team
2b6b042a77 Cast mutable lvalue references to const from testing::ResultOf
PiperOrigin-RevId: 716343482
Change-Id: I125bc4725886958d026c88f3902a8289e476598b
2025-01-16 12:51:11 -08:00
Abseil Team
e4ece4881d Enable safe matcher casts from Matcher<const T&> to Matcher<T>.
PiperOrigin-RevId: 715826130
Change-Id: Id962fd456f6da21ea2a909f331f92d814f1dad46
2025-01-15 09:16:57 -08:00
Abseil Team
504ea69cf7 Document unexpected interaction with death test error code and gmock.
If you have a death test that uses mock objects, it's very likely that those mock objects are not properly cleaned up before death. The gMock atexit leak detector will call `_exit(1)`, overriding your expected exit code.

PiperOrigin-RevId: 713722657
Change-Id: I92a326f3923efc9f0e235d825616f3094eca995c
2025-01-09 10:43:08 -08:00
Abseil Team
4bbf80823c Add UnpackStructImpl for structs with 20 fields.
PiperOrigin-RevId: 713272335
Change-Id: I2b289ece4ce3f91834a8c9ba11a4bd18e6e40fca
2025-01-08 06:38:13 -08:00
Abseil Team
7d76a231b0 gtest: Output a canned test case for test suite setup / teardown failures in XML/JSON
This surfaces useful information about the environment failure in a structured form.

As we can see from the updated test, previously unsurfaced information is now present.

PiperOrigin-RevId: 709892315
Change-Id: I2656294d50c33f995bef5c96195a66cff3c4b907
2024-12-26 15:30:52 -08:00
Abseil Team
e54519b094 Put the fake Fuchsia SDK in a module extension
This allows users to override the fake SDK with a real one using https://bazel.build/rules/lib/globals/module#override_repo.

Without this change, it is impossible for a project that depends on googletest as a `bazel_dep` to build tests using the "real" Fuchsia SDK, because any references to `@fuchsia_sdk` within googletest `BUILD.bazel` files unconditionally resolve to the "fake" Fuchsia SDK. With this change, if you have the real Fuchsia SDK declared in your `MODULE.bazel`, you can add the following lines to coerce googletest to use the real Fuchsia SDK as well:

    fake_fuchsia_sdk_extension =
    use_extension("@com_google_googletest//:fake_fuchsia_sdk.bzl", "fuchsia_sdk")
    override_repo(fake_fuchsia_sdk_extension, "fuchsia_sdk")

PiperOrigin-RevId: 709139784
Change-Id: I4d10d441c76b7a2481f15723a24f11525dba3878
2024-12-23 13:33:10 -08:00
Abseil Team
f3c355f9dd the public version already has the const qualifier
PiperOrigin-RevId: 706721910
Change-Id: I8a76a66d62028176a70678954f095ac70996cc9e
2024-12-16 08:40:16 -08:00
Abseil Team
79219e26e0 Update the links to ISTQB glossary.
PiperOrigin-RevId: 705108072
Change-Id: I209e7fb24bd093412dda1cd5eba10e9ccc2306f4
2024-12-11 08:00:11 -08:00
Abseil Team
d122c0d435 Add support for printing C++20 std::*_ordering types to gtest.
Adds feature test macro for C++20 <compare> header, a pretty-printer, and tests.
Inexplicably, these types aren't enums, so can't be handled with a switch.

PiperOrigin-RevId: 704783038
Change-Id: I29688989d18f43520fe610c12a447a20d2f98c95
2024-12-10 11:23:04 -08:00
Copybara-Service
35d0c36560 Merge pull request #4662 from asoffer:patch-1
PiperOrigin-RevId: 698420375
Change-Id: I786e5b50d171c697c21579659a67716442f224df
2024-11-20 09:37:33 -08:00
Andy Soffer
7927f8e93d
Fix documentation bug.
Matchers require the signature of these three functions to be `const`.
2024-11-15 10:19:57 -05:00
Abseil Team
d144031940 Fixing a typo in the documentation of IsSubsetOf().
PiperOrigin-RevId: 692957797
Change-Id: Ifd3efe64cd2a3a5623167fa13de61d6e3358662d
2024-11-04 07:26:27 -08:00
Abseil Team
1204d63444 Remove mention of using ASSERT_... statements inside custom matcher definitions.
PiperOrigin-RevId: 691994071
Change-Id: I63913152217c99b8c08ae6af8924bc28b02aa9d0
2024-10-31 18:04:00 -07:00
Peter Boström
5ed2186395 Use FAIL() in GTEST_SKIP() documentation
This replaces EXPECT_EQ(0, 1) which would fail if hit.

PiperOrigin-RevId: 690491467
Change-Id: Ieff4e616348254f29200e0ba1d9a6900a2eea130
2024-10-27 23:57:15 -07:00
Abseil Team
df1544bcee Avoid creating std::vector<const T> in UnorderedElementsAreArrayMatcher and others.
std::vector<const T> for trivially relocatable types is not allowed by C++ and is rejected by libc++ starting from 4e112e5c1c
PiperOrigin-RevId: 686487841
Change-Id: I3c90c7c0a6e8e23ffa5ebd1702a3f30ebc4a702f
2024-10-16 06:39:54 -07:00
Abseil Team
62df7bdbc1 This change adjusts how ASSERT_NEAR and EXPECT_NEAR treats infinity, such that ASSERT_NEAR(inf, inf, 0) passes. This makes the behavior more consistent with ASSERT_EQ(inf, inf) which succeeds.
Some examples of asserts that now pass:
```
ASSERT_NEAR(inf, inf, 0)
ASSERT_NEAR(-inf, inf, inf)
ASSERT_NEAR(inf, x, inf)  // x is any finite floating point value
```

PiperOrigin-RevId: 685748133
Change-Id: I7b3af377773e8e0031e4c6b86830cbbf76bf20c6
2024-10-14 10:13:58 -07:00
Abseil Team
71815bbf7d Automated Code Change
PiperOrigin-RevId: 682549952
Change-Id: Ica81f0020c3001c01543a5851dae7d0b42730c66
2024-10-04 20:54:14 -07:00
Abseil Team
a1e255a582 Optional(): Add support for std::optional<>-like types lacking bool conversion.
PiperOrigin-RevId: 681053268
Change-Id: If80ba667fd4c91340e1405a9691f5ca0350fa9eb
2024-10-01 09:35:17 -07:00
Abseil Team
6dae7eb4a5 Use matcher's description in AnyOf when matcher has no explanation.
PiperOrigin-RevId: 675298308
Change-Id: I32d32cafebc7a63fd03e6d957c3a47043d71e5d9
2024-09-16 14:49:27 -07:00
Abseil Team
0953a17a42 Automated Code Change
PiperOrigin-RevId: 668944316
Change-Id: I65aa0a4f3b8a980242849963a3e921ec7fd92b28
2024-08-29 08:17:22 -07:00
Derek Mauro
ff233bdd4c Update main to point to 1.15.2 patch release
PiperOrigin-RevId: 658382055
Change-Id: Ia5eed4bec26da8c8cbe29fbd3a41b44048c25e07
2024-08-01 06:34:56 -07:00
Derek Mauro
3e3b44c300 Remove auto-detection of Python toolchain from MODULE.bazel
since it affects downstream users

The correct solution appears to be
https://rules-python.readthedocs.io/en/stable/toolchains.html#library-modules-with-dev-only-python-usage

This change also includes a workaround for the new mechanism creating
paths that are too long for Windows to handle.

Fixes #4581

PiperOrigin-RevId: 657706984
Change-Id: I8ae6b9e5efeb7629d79d14e7d4d3889876282d17
2024-07-30 13:17:40 -07:00
Abseil Team
ffa31aec1c Directly include gmock.h and gtest.h in gmock-matchers tests.
These headers have been included through `gmock-matchers_test.h`

PiperOrigin-RevId: 657612455
Change-Id: I65675f1cfe7789f1821ccacbe60acf90efd5c221
2024-07-30 09:03:18 -07:00
Abseil Team
5bcb2d78a1 Use matcher's description in AllOf if matcher has no explanation.
PiperOrigin-RevId: 655569834
Change-Id: Ia760d74d1cdde766e9719864c5e19c0159da3128
2024-07-24 08:07:57 -07:00
Aaron Jacobs
352788321f gmock-actions: make DoAll convert to OnceAction via custom conversions.
Currently it will refuse to become a `OnceAction` if its component sub-actions
have an `Action` conversion operator but don't know about `OnceAction` in
particular because although `Action` is convertible to `OnceAction`, the
compiler won't follow the chain of conversions.

Instead, teach it explicitly that it can always be a `OnceAction` when it can be
an `Action`.

PiperOrigin-RevId: 655393035
Change-Id: Ib205b518ceef5f256627f4b02cd93ec9bd98343b
2024-07-23 19:43:42 -07:00
Aaron Jacobs
57e107a10e Run clang-format.
PiperOrigin-RevId: 655106304
Change-Id: Ie69b407fce74b31cf71d6dcc1361910d30e86bb5
2024-07-23 03:57:23 -07:00
Derek Mauro
cee1ba1f24 Change the Bazel build to use the canonical repo names used by Bzlmod
and the Bazel Central Registry

GoogleTest and its dependencies now use the following names:
GoogleTest: com_google_googletest -> googletest
Abseil: com_google_absl -> abseil-cpp
RE2: com_googlesource_code_re2 -> re2

Bazel users using the WORKSPACE file to specify dependencies may
need to use https://bazel.build/rules/lib/repo/http#http_archive-repo_mapping
to remap repositories to their former names if their dependencies do not
agree on on which name is used.

It is recommended that users migrate to bzlmod to manage Bazel dependencies.

PiperOrigin-RevId: 654430227
Change-Id: Iae8797994d7d87bd4f013dcdc889e7494a6ad2fb
2024-07-20 23:09:44 -07:00
Derek Mauro
9ff2450a56 Update GoogleTest Bazel quickstart for Bzlmod
PiperOrigin-RevId: 652824490
Change-Id: I5e6f57004708e7fa62abb454db9bae81fa265c83
2024-07-16 06:58:45 -07:00
Derek Mauro
b62593aceb Update main branch to reflect the release of 1.15.0
PiperOrigin-RevId: 652824317
Change-Id: I39085d9451405c3decb462a0b4682added365d17
2024-07-16 06:57:43 -07:00
Abseil Team
d49a665484 Use matcher's description in AllOf if matcher has no explanation.
PiperOrigin-RevId: 652798234
Change-Id: I8e92248a2d9faf2a5719fe220145ea563acc14ff
2024-07-16 05:22:42 -07:00
Abseil Team
417158b8bc Use matcher's description in AllOf if matcher has no explanation.
PiperOrigin-RevId: 652634229
Change-Id: I5fd7eaef4db3dea3d4142e1fb5fc97e46f654358
2024-07-15 16:40:10 -07:00
46 changed files with 1207 additions and 471 deletions

View File

@ -138,19 +138,19 @@ cc_library(
}), }),
deps = select({ deps = select({
":has_absl": [ ":has_absl": [
"@com_google_absl//absl/container:flat_hash_set", "@abseil-cpp//absl/container:flat_hash_set",
"@com_google_absl//absl/debugging:failure_signal_handler", "@abseil-cpp//absl/debugging:failure_signal_handler",
"@com_google_absl//absl/debugging:stacktrace", "@abseil-cpp//absl/debugging:stacktrace",
"@com_google_absl//absl/debugging:symbolize", "@abseil-cpp//absl/debugging:symbolize",
"@com_google_absl//absl/flags:flag", "@abseil-cpp//absl/flags:flag",
"@com_google_absl//absl/flags:parse", "@abseil-cpp//absl/flags:parse",
"@com_google_absl//absl/flags:reflection", "@abseil-cpp//absl/flags:reflection",
"@com_google_absl//absl/flags:usage", "@abseil-cpp//absl/flags:usage",
"@com_google_absl//absl/strings", "@abseil-cpp//absl/strings",
"@com_google_absl//absl/types:any", "@abseil-cpp//absl/types:any",
"@com_google_absl//absl/types:optional", "@abseil-cpp//absl/types:optional",
"@com_google_absl//absl/types:variant", "@abseil-cpp//absl/types:variant",
"@com_googlesource_code_re2//:re2", "@re2//:re2",
], ],
"//conditions:default": [], "//conditions:default": [],
}) + select({ }) + select({

View File

@ -1,10 +1,10 @@
# Note: CMake support is community-based. The maintainers do not use CMake # Note: CMake support is community-based. The maintainers do not use CMake
# internally. # internally.
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.16)
project(googletest-distribution) project(googletest-distribution)
set(GOOGLETEST_VERSION 1.15.0) set(GOOGLETEST_VERSION 1.16.0)
if(NOT CYGWIN AND NOT MSYS AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL QNX) if(NOT CYGWIN AND NOT MSYS AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL QNX)
set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF)

View File

@ -32,38 +32,45 @@
module( module(
name = "googletest", name = "googletest",
version = "1.15.1", version = "head",
compatibility_level = 1, compatibility_level = 1,
) )
# Only direct dependencies need to be listed below. # Only direct dependencies need to be listed below.
# Please keep the versions in sync with the versions in the WORKSPACE file. # Please keep the versions in sync with the versions in the WORKSPACE file.
bazel_dep(name = "abseil-cpp", bazel_dep(
version = "20240116.2", name = "abseil-cpp",
repo_name = "com_google_absl") version = "20250127.0",
)
bazel_dep(
name = "platforms",
version = "0.0.10",
)
bazel_dep(
name = "re2",
version = "2024-07-02",
)
bazel_dep(name = "platforms", bazel_dep(
version = "0.0.10") name = "rules_python",
version = "1.1.0",
bazel_dep(name = "re2", dev_dependency = True,
repo_name = "com_googlesource_code_re2", )
version = "2024-07-02")
bazel_dep(name = "rules_python",
version = "0.34.0",
dev_dependency = True)
# https://rules-python.readthedocs.io/en/stable/toolchains.html#library-modules-with-dev-only-python-usage # https://rules-python.readthedocs.io/en/stable/toolchains.html#library-modules-with-dev-only-python-usage
python = use_extension( python = use_extension(
"@rules_python//python/extensions:python.bzl", "@rules_python//python/extensions:python.bzl",
"python", "python",
dev_dependency = True dev_dependency = True,
)
python.toolchain(
ignore_root_user_error = True,
is_default = True,
python_version = "3.12",
) )
python.toolchain(python_version = "3.12", # See fake_fuchsia_sdk.bzl for instructions on how to override this with a real SDK, if needed.
is_default = True, fuchsia_sdk = use_extension("//:fake_fuchsia_sdk.bzl", "fuchsia_sdk")
ignore_root_user_error = True) fuchsia_sdk.create_fake()
use_repo(fuchsia_sdk, "fuchsia_sdk")
fake_fuchsia_sdk = use_repo_rule("//:fake_fuchsia_sdk.bzl", "fake_fuchsia_sdk")
fake_fuchsia_sdk(name = "fuchsia_sdk")

View File

@ -9,7 +9,7 @@ GoogleTest now follows the
We recommend We recommend
[updating to the latest commit in the `main` branch as often as possible](https://github.com/abseil/abseil-cpp/blob/master/FAQ.md#what-is-live-at-head-and-how-do-i-do-it). [updating to the latest commit in the `main` branch as often as possible](https://github.com/abseil/abseil-cpp/blob/master/FAQ.md#what-is-live-at-head-and-how-do-i-do-it).
We do publish occasional semantic versions, tagged with We do publish occasional semantic versions, tagged with
`v${major}.${minor}.${patch}` (e.g. `v1.15.0`). `v${major}.${minor}.${patch}` (e.g. `v1.16.0`).
#### Documentation Updates #### Documentation Updates
@ -17,12 +17,15 @@ Our documentation is now live on GitHub Pages at
https://google.github.io/googletest/. We recommend browsing the documentation on https://google.github.io/googletest/. We recommend browsing the documentation on
GitHub Pages rather than directly in the repository. GitHub Pages rather than directly in the repository.
#### Release 1.15.0 #### Release 1.16.0
[Release 1.15.0](https://github.com/google/googletest/releases/tag/v1.15.0) is [Release 1.16.0](https://github.com/google/googletest/releases/tag/v1.16.0) is
now available. now available.
The 1.15.x branch requires at least C++14. The 1.16.x branch requires at least C++14.
The 1.16.x branch will be the last to support C++14. Future development will
[require at least C++17](https://opensource.google/documentation/policies/cplusplus-support#c_language_standard).
#### Continuous Integration #### Continuous Integration

View File

@ -1,4 +1,34 @@
workspace(name = "com_google_googletest") # Copyright 2024 Google Inc.
# All Rights Reserved.
#
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
workspace(name = "googletest")
load("//:googletest_deps.bzl", "googletest_deps") load("//:googletest_deps.bzl", "googletest_deps")
googletest_deps() googletest_deps()
@ -6,13 +36,12 @@ googletest_deps()
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive( http_archive(
name = "rules_python", name = "rules_python",
sha256 = "d71d2c67e0bce986e1c5a7731b4693226867c45bfe0b7c5e0067228a536fc580", sha256 = "9c6e26911a79fbf510a8f06d8eedb40f412023cf7fa6d1461def27116bff022c",
strip_prefix = "rules_python-0.29.0", strip_prefix = "rules_python-1.1.0",
urls = ["https://github.com/bazelbuild/rules_python/releases/download/0.29.0/rules_python-0.29.0.tar.gz"], url = "https://github.com/bazelbuild/rules_python/releases/download/1.1.0/rules_python-1.1.0.tar.gz",
) )
# https://github.com/bazelbuild/rules_python/releases/tag/1.1.0
# https://github.com/bazelbuild/rules_python/releases/tag/0.29.0
load("@rules_python//python:repositories.bzl", "py_repositories") load("@rules_python//python:repositories.bzl", "py_repositories")
py_repositories() py_repositories()

View File

@ -31,51 +31,68 @@
set -euox pipefail set -euox pipefail
readonly LINUX_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20240523" readonly LINUX_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20241218"
readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20230120" readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20250205"
if [[ -z ${GTEST_ROOT:-} ]]; then if [[ -z ${GTEST_ROOT:-} ]]; then
GTEST_ROOT="$(realpath $(dirname ${0})/..)" GTEST_ROOT="$(realpath $(dirname ${0})/..)"
fi fi
if [[ -z ${STD:-} ]]; then if [[ -z ${STD:-} ]]; then
STD="c++14 c++17 c++20" STD="c++17 c++20"
fi fi
# Test the CMake build # Test CMake + GCC
for cc in /usr/local/bin/gcc /opt/llvm/clang/bin/clang; do for cmake_off_on in OFF ON; do
for cmake_off_on in OFF ON; do time docker run \
time docker run \ --volume="${GTEST_ROOT}:/src:ro" \
--volume="${GTEST_ROOT}:/src:ro" \ --tmpfs="/build:exec" \
--tmpfs="/build:exec" \ --workdir="/build" \
--workdir="/build" \ --rm \
--rm \ --env="CC=/usr/local/bin/gcc" \
--env="CC=${cc}" \ --env=CXXFLAGS="-Werror -Wdeprecated" \
--env=CXXFLAGS="-Werror -Wdeprecated" \ ${LINUX_LATEST_CONTAINER} \
${LINUX_LATEST_CONTAINER} \ /bin/bash -c "
/bin/bash -c " cmake /src \
cmake /src \ -DCMAKE_CXX_STANDARD=17 \
-DCMAKE_CXX_STANDARD=14 \ -Dgtest_build_samples=ON \
-Dgtest_build_samples=ON \ -Dgtest_build_tests=ON \
-Dgtest_build_tests=ON \ -Dgmock_build_tests=ON \
-Dgmock_build_tests=ON \ -Dcxx_no_exception=${cmake_off_on} \
-Dcxx_no_exception=${cmake_off_on} \ -Dcxx_no_rtti=${cmake_off_on} && \
-Dcxx_no_rtti=${cmake_off_on} && \ make -j$(nproc) && \
make -j$(nproc) && \ ctest -j$(nproc) --output-on-failure"
ctest -j$(nproc) --output-on-failure" done
done
# Test CMake + Clang
for cmake_off_on in OFF ON; do
time docker run \
--volume="${GTEST_ROOT}:/src:ro" \
--tmpfs="/build:exec" \
--workdir="/build" \
--rm \
--env="CC=/opt/llvm/clang/bin/clang" \
--env=CXXFLAGS="-Werror -Wdeprecated --gcc-toolchain=/usr/local" \
${LINUX_LATEST_CONTAINER} \
/bin/bash -c "
cmake /src \
-DCMAKE_CXX_STANDARD=17 \
-Dgtest_build_samples=ON \
-Dgtest_build_tests=ON \
-Dgmock_build_tests=ON \
-Dcxx_no_exception=${cmake_off_on} \
-Dcxx_no_rtti=${cmake_off_on} && \
make -j$(nproc) && \
ctest -j$(nproc) --output-on-failure"
done done
# Do one test with an older version of GCC # Do one test with an older version of GCC
# TODO(googletest-team): This currently uses Bazel 5. When upgrading to a
# version of Bazel that supports Bzlmod, add --enable_bzlmod=false to keep test
# coverage for the old WORKSPACE dependency management.
time docker run \ time docker run \
--volume="${GTEST_ROOT}:/src:ro" \ --volume="${GTEST_ROOT}:/src:ro" \
--workdir="/src" \ --workdir="/src" \
--rm \ --rm \
--env="CC=/usr/local/bin/gcc" \ --env="CC=/usr/local/bin/gcc" \
--env="BAZEL_CXXOPTS=-std=c++14" \ --env="BAZEL_CXXOPTS=-std=c++17" \
${LINUX_GCC_FLOOR_CONTAINER} \ ${LINUX_GCC_FLOOR_CONTAINER} \
/usr/local/bin/bazel test ... \ /usr/local/bin/bazel test ... \
--copt="-Wall" \ --copt="-Wall" \
@ -83,6 +100,7 @@ time docker run \
--copt="-Wuninitialized" \ --copt="-Wuninitialized" \
--copt="-Wundef" \ --copt="-Wundef" \
--copt="-Wno-error=pragmas" \ --copt="-Wno-error=pragmas" \
--enable_bzlmod=false \
--features=external_include_paths \ --features=external_include_paths \
--keep_going \ --keep_going \
--show_timestamps \ --show_timestamps \

View File

@ -31,6 +31,9 @@
set -euox pipefail set -euox pipefail
# Use Xcode 16.0
sudo xcode-select -s /Applications/Xcode_16.0.app/Contents/Developer
if [[ -z ${GTEST_ROOT:-} ]]; then if [[ -z ${GTEST_ROOT:-} ]]; then
GTEST_ROOT="$(realpath $(dirname ${0})/..)" GTEST_ROOT="$(realpath $(dirname ${0})/..)"
fi fi
@ -40,20 +43,20 @@ for cmake_off_on in OFF ON; do
BUILD_DIR=$(mktemp -d build_dir.XXXXXXXX) BUILD_DIR=$(mktemp -d build_dir.XXXXXXXX)
cd ${BUILD_DIR} cd ${BUILD_DIR}
time cmake ${GTEST_ROOT} \ time cmake ${GTEST_ROOT} \
-DCMAKE_CXX_STANDARD=14 \ -DCMAKE_CXX_STANDARD=17 \
-Dgtest_build_samples=ON \ -Dgtest_build_samples=ON \
-Dgtest_build_tests=ON \ -Dgtest_build_tests=ON \
-Dgmock_build_tests=ON \ -Dgmock_build_tests=ON \
-Dcxx_no_exception=${cmake_off_on} \ -Dcxx_no_exception=${cmake_off_on} \
-Dcxx_no_rtti=${cmake_off_on} -Dcxx_no_rtti=${cmake_off_on}
time make time make -j$(nproc)
time ctest -j$(nproc) --output-on-failure time ctest -j$(nproc) --output-on-failure
done done
# Test the Bazel build # Test the Bazel build
# If we are running on Kokoro, check for a versioned Bazel binary. # If we are running on Kokoro, check for a versioned Bazel binary.
KOKORO_GFILE_BAZEL_BIN="bazel-7.0.0-darwin-x86_64" KOKORO_GFILE_BAZEL_BIN="bazel-8.0.0-darwin-x86_64"
if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]]; then if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]]; then
BAZEL_BIN="${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN}" BAZEL_BIN="${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN}"
chmod +x ${BAZEL_BIN} chmod +x ${BAZEL_BIN}
@ -67,7 +70,7 @@ for absl in 0 1; do
--copt="-Wall" \ --copt="-Wall" \
--copt="-Werror" \ --copt="-Werror" \
--copt="-Wundef" \ --copt="-Wundef" \
--cxxopt="-std=c++14" \ --cxxopt="-std=c++17" \
--define="absl=${absl}" \ --define="absl=${absl}" \
--enable_bzlmod=true \ --enable_bzlmod=true \
--features=external_include_paths \ --features=external_include_paths \

View File

@ -1,6 +1,6 @@
SETLOCAL ENABLEDELAYEDEXPANSION SETLOCAL ENABLEDELAYEDEXPANSION
SET BAZEL_EXE=%KOKORO_GFILE_DIR%\bazel-7.0.0-windows-x86_64.exe SET BAZEL_EXE=%KOKORO_GFILE_DIR%\bazel-8.0.0-windows-x86_64.exe
SET PATH=C:\Python34;%PATH% SET PATH=C:\Python34;%PATH%
SET BAZEL_PYTHON=C:\python34\python.exe SET BAZEL_PYTHON=C:\python34\python.exe
@ -11,21 +11,18 @@ SET CTEST_OUTPUT_ON_FAILURE=1
SET CMAKE_BUILD_PARALLEL_LEVEL=16 SET CMAKE_BUILD_PARALLEL_LEVEL=16
SET CTEST_PARALLEL_LEVEL=16 SET CTEST_PARALLEL_LEVEL=16
IF EXIST git\googletest ( SET GTEST_ROOT=%~dp0\..
CD git\googletest
) ELSE IF EXIST github\googletest (
CD github\googletest
)
IF %errorlevel% neq 0 EXIT /B 1 IF %errorlevel% neq 0 EXIT /B 1
:: ---------------------------------------------------------------------------- :: ----------------------------------------------------------------------------
:: CMake :: CMake
MKDIR cmake_msvc2022 SET CMAKE_BUILD_PATH=cmake_msvc2022
CD cmake_msvc2022 MKDIR %CMAKE_BUILD_PATH%
CD %CMAKE_BUILD_PATH%
%CMAKE_BIN% .. ^ %CMAKE_BIN% %GTEST_ROOT% ^
-G "Visual Studio 17 2022" ^ -G "Visual Studio 17 2022" ^
-DCMAKE_CXX_STANDARD=17 ^
-DPYTHON_EXECUTABLE:FILEPATH=c:\python37\python.exe ^ -DPYTHON_EXECUTABLE:FILEPATH=c:\python37\python.exe ^
-DPYTHON_INCLUDE_DIR:PATH=c:\python37\include ^ -DPYTHON_INCLUDE_DIR:PATH=c:\python37\include ^
-DPYTHON_LIBRARY:FILEPATH=c:\python37\lib\site-packages\pip ^ -DPYTHON_LIBRARY:FILEPATH=c:\python37\lib\site-packages\pip ^
@ -40,8 +37,8 @@ IF %errorlevel% neq 0 EXIT /B 1
%CTEST_BIN% -C Debug --timeout 600 %CTEST_BIN% -C Debug --timeout 600
IF %errorlevel% neq 0 EXIT /B 1 IF %errorlevel% neq 0 EXIT /B 1
CD .. CD %GTEST_ROOT%
RMDIR /S /Q cmake_msvc2022 RMDIR /S /Q %CMAKE_BUILD_PATH%
:: ---------------------------------------------------------------------------- :: ----------------------------------------------------------------------------
:: Bazel :: Bazel
@ -50,11 +47,26 @@ RMDIR /S /Q cmake_msvc2022
:: because of Windows limitations on path length. :: because of Windows limitations on path length.
:: --output_user_root=C:\tmp causes Bazel to use a shorter path. :: --output_user_root=C:\tmp causes Bazel to use a shorter path.
SET BAZEL_VS=C:\Program Files\Microsoft Visual Studio\2022\Community SET BAZEL_VS=C:\Program Files\Microsoft Visual Studio\2022\Community
:: C++17
%BAZEL_EXE% ^ %BAZEL_EXE% ^
--output_user_root=C:\tmp ^ --output_user_root=C:\tmp ^
test ... ^ test ... ^
--compilation_mode=dbg ^ --compilation_mode=dbg ^
--copt=/std:c++14 ^ --copt=/std:c++17 ^
--copt=/WX ^
--enable_bzlmod=true ^
--keep_going ^
--test_output=errors ^
--test_tag_filters=-no_test_msvc2017
IF %errorlevel% neq 0 EXIT /B 1
:: C++20
%BAZEL_EXE% ^
--output_user_root=C:\tmp ^
test ... ^
--compilation_mode=dbg ^
--copt=/std:c++20 ^
--copt=/WX ^ --copt=/WX ^
--enable_bzlmod=true ^ --enable_bzlmod=true ^
--keep_going ^ --keep_going ^

View File

@ -286,7 +286,7 @@ For example:
```c++ ```c++
TEST(SkipTest, DoesSkip) { TEST(SkipTest, DoesSkip) {
GTEST_SKIP() << "Skipping single test"; GTEST_SKIP() << "Skipping single test";
EXPECT_EQ(0, 1); // Won't fail; it won't be executed FAIL(); // Won't fail; it won't be executed
} }
class SkipFixture : public ::testing::Test { class SkipFixture : public ::testing::Test {
@ -298,7 +298,7 @@ class SkipFixture : public ::testing::Test {
// Tests for SkipFixture won't be executed. // Tests for SkipFixture won't be executed.
TEST_F(SkipFixture, SkipsOneTest) { TEST_F(SkipFixture, SkipsOneTest) {
EXPECT_EQ(5, 7); // Won't fail FAIL(); // Won't fail; it won't be executed
} }
``` ```
@ -405,6 +405,51 @@ EXPECT_TRUE(IsCorrectPointIntVector(point_ints))
For more details regarding `AbslStringify()` and its integration with other For more details regarding `AbslStringify()` and its integration with other
libraries, see go/abslstringify. libraries, see go/abslstringify.
## Regular Expression Syntax
When built with Bazel and using Abseil, GoogleTest uses the
[RE2](https://github.com/google/re2/wiki/Syntax) syntax. Otherwise, for POSIX
systems (Linux, Cygwin, Mac), GoogleTest uses the
[POSIX extended regular expression](https://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap09.html#tag_09_04)
syntax. To learn about POSIX syntax, you may want to read this
[Wikipedia entry](https://en.wikipedia.org/wiki/Regular_expression#POSIX_extended).
On Windows, GoogleTest uses its own simple regular expression implementation. It
lacks many features. For example, we don't support union (`"x|y"`), grouping
(`"(xy)"`), brackets (`"[xy]"`), and repetition count (`"x{5,7}"`), among
others. Below is what we do support (`A` denotes a literal character, period
(`.`), or a single `\\ ` escape sequence; `x` and `y` denote regular
expressions.):
Expression | Meaning
---------- | --------------------------------------------------------------
`c` | matches any literal character `c`
`\\d` | matches any decimal digit
`\\D` | matches any character that's not a decimal digit
`\\f` | matches `\f`
`\\n` | matches `\n`
`\\r` | matches `\r`
`\\s` | matches any ASCII whitespace, including `\n`
`\\S` | matches any character that's not a whitespace
`\\t` | matches `\t`
`\\v` | matches `\v`
`\\w` | matches any letter, `_`, or decimal digit
`\\W` | matches any character that `\\w` doesn't match
`\\c` | matches any literal character `c`, which must be a punctuation
`.` | matches any single character except `\n`
`A?` | matches 0 or 1 occurrences of `A`
`A*` | matches 0 or many occurrences of `A`
`A+` | matches 1 or many occurrences of `A`
`^` | matches the beginning of a string (not that of each line)
`$` | matches the end of a string (not that of each line)
`xy` | matches `x` followed by `y`
To help you determine which capability is available on your system, GoogleTest
defines macros to govern which regular expression it is using. The macros are:
`GTEST_USES_SIMPLE_RE=1` or `GTEST_USES_POSIX_RE=1`. If you want your death
tests to work in all cases, you can either `#if` on these macros or use the more
limited syntax only.
## Death Tests ## Death Tests
In many applications, there are assertions that can cause application failure if In many applications, there are assertions that can cause application failure if
@ -416,7 +461,7 @@ corruption, security holes, or worse. Hence it is vitally important to test that
such assertion statements work as expected. such assertion statements work as expected.
Since these precondition checks cause the processes to die, we call such tests Since these precondition checks cause the processes to die, we call such tests
_death tests_. More generally, any test that checks that a program terminates *death tests*. More generally, any test that checks that a program terminates
(except by throwing an exception) in an expected fashion is also a death test. (except by throwing an exception) in an expected fashion is also a death test.
Note that if a piece of code throws an exception, we don't consider it "death" Note that if a piece of code throws an exception, we don't consider it "death"
@ -462,6 +507,12 @@ verifies that:
exit with exit code 0, and exit with exit code 0, and
* calling `KillProcess()` kills the process with signal `SIGKILL`. * calling `KillProcess()` kills the process with signal `SIGKILL`.
{: .callout .warning}
Warning: If your death test contains mocks and is expecting a specific exit
code, then you must allow the mock objects to be leaked via `Mock::AllowLeak`.
This is because the mock leak detector will exit with its own error code if it
detects a leak.
The test function body may contain other assertions and statements as well, if The test function body may contain other assertions and statements as well, if
necessary. necessary.
@ -503,51 +554,6 @@ TEST_F(FooDeathTest, DoesThat) {
} }
``` ```
### Regular Expression Syntax
When built with Bazel and using Abseil, GoogleTest uses the
[RE2](https://github.com/google/re2/wiki/Syntax) syntax. Otherwise, for POSIX
systems (Linux, Cygwin, Mac), GoogleTest uses the
[POSIX extended regular expression](https://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap09.html#tag_09_04)
syntax. To learn about POSIX syntax, you may want to read this
[Wikipedia entry](https://en.wikipedia.org/wiki/Regular_expression#POSIX_extended).
On Windows, GoogleTest uses its own simple regular expression implementation. It
lacks many features. For example, we don't support union (`"x|y"`), grouping
(`"(xy)"`), brackets (`"[xy]"`), and repetition count (`"x{5,7}"`), among
others. Below is what we do support (`A` denotes a literal character, period
(`.`), or a single `\\ ` escape sequence; `x` and `y` denote regular
expressions.):
Expression | Meaning
---------- | --------------------------------------------------------------
`c` | matches any literal character `c`
`\\d` | matches any decimal digit
`\\D` | matches any character that's not a decimal digit
`\\f` | matches `\f`
`\\n` | matches `\n`
`\\r` | matches `\r`
`\\s` | matches any ASCII whitespace, including `\n`
`\\S` | matches any character that's not a whitespace
`\\t` | matches `\t`
`\\v` | matches `\v`
`\\w` | matches any letter, `_`, or decimal digit
`\\W` | matches any character that `\\w` doesn't match
`\\c` | matches any literal character `c`, which must be a punctuation
`.` | matches any single character except `\n`
`A?` | matches 0 or 1 occurrences of `A`
`A*` | matches 0 or many occurrences of `A`
`A+` | matches 1 or many occurrences of `A`
`^` | matches the beginning of a string (not that of each line)
`$` | matches the end of a string (not that of each line)
`xy` | matches `x` followed by `y`
To help you determine which capability is available on your system, GoogleTest
defines macros to govern which regular expression it is using. The macros are:
`GTEST_USES_SIMPLE_RE=1` or `GTEST_USES_POSIX_RE=1`. If you want your death
tests to work in all cases, you can either `#if` on these macros or use the more
limited syntax only.
### How It Works ### How It Works
See [Death Assertions](reference/assertions.md#death) in the Assertions See [Death Assertions](reference/assertions.md#death) in the Assertions
@ -727,7 +733,7 @@ Some tips on using `SCOPED_TRACE`:
### Propagating Fatal Failures ### Propagating Fatal Failures
A common pitfall when using `ASSERT_*` and `FAIL*` is not understanding that A common pitfall when using `ASSERT_*` and `FAIL*` is not understanding that
when they fail they only abort the _current function_, not the entire test. For when they fail they only abort the *current function*, not the entire test. For
example, the following test will segfault: example, the following test will segfault:
```c++ ```c++
@ -2382,7 +2388,7 @@ IMPORTANT: The exact format of the JSON document is subject to change.
#### Detecting Test Premature Exit #### Detecting Test Premature Exit
Google Test implements the _premature-exit-file_ protocol for test runners to Google Test implements the *premature-exit-file* protocol for test runners to
catch any kind of unexpected exits of test programs. Upon start, Google Test catch any kind of unexpected exits of test programs. Upon start, Google Test
creates the file which will be automatically deleted after all work has been creates the file which will be automatically deleted after all work has been
finished. Then, the test runner can check if this file exists. In case the file finished. Then, the test runner can check if this file exists. In case the file

View File

@ -177,7 +177,7 @@ class StackInterface {
template <typename Elem> template <typename Elem>
class MockStack : public StackInterface<Elem> { class MockStack : public StackInterface<Elem> {
... ...
MOCK_METHOD(int, GetSize, (), (override)); MOCK_METHOD(int, GetSize, (), (const, override));
MOCK_METHOD(void, Push, (const Elem& x), (override)); MOCK_METHOD(void, Push, (const Elem& x), (override));
}; };
``` ```
@ -936,8 +936,8 @@ casts a matcher `m` to type `Matcher<T>`. To ensure safety, gMock checks that
floating-point numbers), the conversion from `T` to `U` is not lossy (in floating-point numbers), the conversion from `T` to `U` is not lossy (in
other words, any value representable by `T` can also be represented by `U`); other words, any value representable by `T` can also be represented by `U`);
and and
3. When `U` is a reference, `T` must also be a reference (as the underlying 3. When `U` is a non-const reference, `T` must also be a reference (as the
matcher may be interested in the address of the `U` value). underlying matcher may be interested in the address of the `U` value).
The code won't compile if any of these conditions isn't met. The code won't compile if any of these conditions isn't met.
@ -3387,9 +3387,9 @@ With this definition, the above assertion will give a better message:
#### Using EXPECT_ Statements in Matchers #### Using EXPECT_ Statements in Matchers
You can also use `EXPECT_...` (and `ASSERT_...`) statements inside custom You can also use `EXPECT_...` statements inside custom matcher definitions. In
matcher definitions. In many cases, this allows you to write your matcher more many cases, this allows you to write your matcher more concisely while still
concisely while still providing an informative error message. For example: providing an informative error message. For example:
```cpp ```cpp
MATCHER(IsDivisibleBy7, "") { MATCHER(IsDivisibleBy7, "") {
@ -3419,14 +3419,14 @@ itself, as gMock already prints it for you.
#### Argument Types #### Argument Types
The type of the value being matched (`arg_type`) is determined by the The type of the value being matched (`arg_type`) is determined by the context in
context in which you use the matcher and is supplied to you by the compiler, so which you use the matcher and is supplied to you by the compiler, so you don't
you don't need to worry about declaring it (nor can you). This allows the need to worry about declaring it (nor can you). This allows the matcher to be
matcher to be polymorphic. For example, `IsDivisibleBy7()` can be used to match polymorphic. For example, `IsDivisibleBy7()` can be used to match any type where
any type where the value of `(arg % 7) == 0` can be implicitly converted to a the value of `(arg % 7) == 0` can be implicitly converted to a `bool`. In the
`bool`. In the `Bar(IsDivisibleBy7())` example above, if method `Bar()` takes an `Bar(IsDivisibleBy7())` example above, if method `Bar()` takes an `int`,
`int`, `arg_type` will be `int`; if it takes an `unsigned long`, `arg_type` will `arg_type` will be `int`; if it takes an `unsigned long`, `arg_type` will be
be `unsigned long`; and so on. `unsigned long`; and so on.
### Writing New Parameterized Matchers Quickly ### Writing New Parameterized Matchers Quickly

View File

@ -73,8 +73,8 @@ Meaning
Exercise a particular program path with specific input values and verify the results | [TEST()](#simple-tests) | [Test Case][istqb test case] Exercise a particular program path with specific input values and verify the results | [TEST()](#simple-tests) | [Test Case][istqb test case]
[istqb test case]: https://glossary.istqb.org/en_US/term/test-case-2 [istqb test case]: https://glossary.istqb.org/en_US/term/test-case
[istqb test suite]: https://glossary.istqb.org/en_US/term/test-suite-1-3 [istqb test suite]: https://glossary.istqb.org/en_US/term/test-suite
## Basic Concepts ## Basic Concepts

View File

@ -10,8 +10,8 @@ To complete this tutorial, you'll need:
* A compatible operating system (e.g. Linux, macOS, Windows). * A compatible operating system (e.g. Linux, macOS, Windows).
* A compatible C++ compiler that supports at least C++14. * A compatible C++ compiler that supports at least C++14.
* [Bazel](https://bazel.build/), the preferred build system used by the * [Bazel](https://bazel.build/) 7.0 or higher, the preferred build system used
GoogleTest team. by the GoogleTest team.
See [Supported Platforms](platforms.md) for more information about platforms See [Supported Platforms](platforms.md) for more information about platforms
compatible with GoogleTest. compatible with GoogleTest.
@ -28,7 +28,7 @@ A
[Bazel workspace](https://docs.bazel.build/versions/main/build-ref.html#workspace) [Bazel workspace](https://docs.bazel.build/versions/main/build-ref.html#workspace)
is a directory on your filesystem that you use to manage source files for the is a directory on your filesystem that you use to manage source files for the
software you want to build. Each workspace directory has a text file named software you want to build. Each workspace directory has a text file named
`WORKSPACE` which may be empty, or may contain references to external `MODULE.bazel` which may be empty, or may contain references to external
dependencies required to build the outputs. dependencies required to build the outputs.
First, create a directory for your workspace: First, create a directory for your workspace:
@ -37,30 +37,20 @@ First, create a directory for your workspace:
$ mkdir my_workspace && cd my_workspace $ mkdir my_workspace && cd my_workspace
``` ```
Next, youll create the `WORKSPACE` file to specify dependencies. A common and Next, youll create the `MODULE.bazel` file to specify dependencies. As of Bazel
recommended way to depend on GoogleTest is to use a 7.0, the recommended way to consume GoogleTest is through the
[Bazel external dependency](https://docs.bazel.build/versions/main/external.html) [Bazel Central Registry](https://registry.bazel.build/modules/googletest). To do
via the this, create a `MODULE.bazel` file in the root directory of your Bazel workspace
[`http_archive` rule](https://docs.bazel.build/versions/main/repo/http.html#http_archive). with the following content:
To do this, in the root directory of your workspace (`my_workspace/`), create a
file named `WORKSPACE` with the following contents:
``` ```
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") # MODULE.bazel
http_archive( # Choose the most recent version available at
name = "com_google_googletest", # https://registry.bazel.build/modules/googletest
urls = ["https://github.com/google/googletest/archive/5ab508a01f9eb089207ee87fd547d290da39d015.zip"], bazel_dep(name = "googletest", version = "1.15.2")
strip_prefix = "googletest-5ab508a01f9eb089207ee87fd547d290da39d015",
)
``` ```
The above configuration declares a dependency on GoogleTest which is downloaded
as a ZIP archive from GitHub. In the above example,
`5ab508a01f9eb089207ee87fd547d290da39d015` is the Git commit hash of the
GoogleTest version to use; we recommend updating the hash often to point to the
latest version. Use a recent hash on the `main` branch.
Now you're ready to build C++ code that uses GoogleTest. Now you're ready to build C++ code that uses GoogleTest.
## Create and run a binary ## Create and run a binary
@ -92,17 +82,20 @@ following contents:
``` ```
cc_test( cc_test(
name = "hello_test", name = "hello_test",
size = "small", size = "small",
srcs = ["hello_test.cc"], srcs = ["hello_test.cc"],
deps = ["@com_google_googletest//:gtest_main"], deps = [
"@googletest//:gtest",
"@googletest//:gtest_main",
],
) )
``` ```
This `cc_test` rule declares the C++ test binary you want to build, and links to This `cc_test` rule declares the C++ test binary you want to build, and links to
GoogleTest (`//:gtest_main`) using the prefix you specified in the `WORKSPACE` the GoogleTest library (`@googletest//:gtest"`) and the GoogleTest `main()`
file (`@com_google_googletest`). For more information about Bazel `BUILD` files, function (`@googletest//:gtest_main`). For more information about Bazel `BUILD`
see the files, see the
[Bazel C++ Tutorial](https://docs.bazel.build/versions/main/tutorial/cpp.html). [Bazel C++ Tutorial](https://docs.bazel.build/versions/main/tutorial/cpp.html).
{: .callout .note} {: .callout .note}
@ -115,7 +108,7 @@ on supported language versions.
Now you can build and run your test: Now you can build and run your test:
<pre> <pre>
<strong>my_workspace$ bazel test --cxxopt=-std=c++14 --test_output=all //:hello_test</strong> <strong>$ bazel test --cxxopt=-std=c++14 --test_output=all //:hello_test</strong>
INFO: Analyzed target //:hello_test (26 packages loaded, 362 targets configured). INFO: Analyzed target //:hello_test (26 packages loaded, 362 targets configured).
INFO: Found 1 test target... INFO: Found 1 test target...
INFO: From Testing //:hello_test: INFO: From Testing //:hello_test:

View File

@ -24,7 +24,8 @@ provided by GoogleTest. All actions are defined in the `::testing` namespace.
| :--------------------------------- | :-------------------------------------- | | :--------------------------------- | :-------------------------------------- |
| `Assign(&variable, value)` | Assign `value` to variable. | | `Assign(&variable, value)` | Assign `value` to variable. |
| `DeleteArg<N>()` | Delete the `N`-th (0-based) argument, which must be a pointer. | | `DeleteArg<N>()` | Delete the `N`-th (0-based) argument, which must be a pointer. |
| `SaveArg<N>(pointer)` | Save the `N`-th (0-based) argument to `*pointer`. | | `SaveArg<N>(pointer)` | Save the `N`-th (0-based) argument to `*pointer` by copy-assignment. |
| `SaveArgByMove<N>(pointer)` | Save the `N`-th (0-based) argument to `*pointer` by move-assignment. |
| `SaveArgPointee<N>(pointer)` | Save the value pointed to by the `N`-th (0-based) argument to `*pointer`. | | `SaveArgPointee<N>(pointer)` | Save the value pointed to by the `N`-th (0-based) argument to `*pointer`. |
| `SetArgReferee<N>(value)` | Assign `value` to the variable referenced by the `N`-th (0-based) argument. | | `SetArgReferee<N>(value)` | Assign `value` to the variable referenced by the `N`-th (0-based) argument. |
| `SetArgPointee<N>(value)` | Assign `value` to the variable pointed by the `N`-th (0-based) argument. | | `SetArgPointee<N>(value)` | Assign `value` to the variable pointed by the `N`-th (0-based) argument. |

View File

@ -276,7 +276,8 @@ Units in the Last Place (ULPs). To learn more about ULPs, see the article
`ASSERT_FLOAT_EQ(`*`val1`*`,`*`val2`*`)` `ASSERT_FLOAT_EQ(`*`val1`*`,`*`val2`*`)`
Verifies that the two `float` values *`val1`* and *`val2`* are approximately Verifies that the two `float` values *`val1`* and *`val2`* are approximately
equal, to within 4 ULPs from each other. equal, to within 4 ULPs from each other. Infinity and the largest finite float
value are considered to be one ULP apart.
### EXPECT_DOUBLE_EQ {#EXPECT_DOUBLE_EQ} ### EXPECT_DOUBLE_EQ {#EXPECT_DOUBLE_EQ}
@ -284,7 +285,8 @@ equal, to within 4 ULPs from each other.
`ASSERT_DOUBLE_EQ(`*`val1`*`,`*`val2`*`)` `ASSERT_DOUBLE_EQ(`*`val1`*`,`*`val2`*`)`
Verifies that the two `double` values *`val1`* and *`val2`* are approximately Verifies that the two `double` values *`val1`* and *`val2`* are approximately
equal, to within 4 ULPs from each other. equal, to within 4 ULPs from each other. Infinity and the largest finite double
value are considered to be one ULP apart.
### EXPECT_NEAR {#EXPECT_NEAR} ### EXPECT_NEAR {#EXPECT_NEAR}
@ -294,6 +296,11 @@ equal, to within 4 ULPs from each other.
Verifies that the difference between *`val1`* and *`val2`* does not exceed the Verifies that the difference between *`val1`* and *`val2`* does not exceed the
absolute error bound *`abs_error`*. absolute error bound *`abs_error`*.
If *`val`* and *`val2`* are both infinity of the same sign, the difference is
considered to be 0. Otherwise, if either value is infinity, the difference is
considered to be infinity. All non-NaN values (including infinity) are
considered to not exceed an *`abs_error`* of infinity.
## Exception Assertions {#exceptions} ## Exception Assertions {#exceptions}
The following assertions verify that a piece of code throws, or does not throw, The following assertions verify that a piece of code throws, or does not throw,

View File

@ -171,6 +171,11 @@ messages, you can use:
| `Property(&class::property, m)` | `argument.property()` (or `argument->property()` when `argument` is a plain pointer) matches matcher `m`, where `argument` is an object of type _class_. The method `property()` must take no argument and be declared as `const`. | | `Property(&class::property, m)` | `argument.property()` (or `argument->property()` when `argument` is a plain pointer) matches matcher `m`, where `argument` is an object of type _class_. The method `property()` must take no argument and be declared as `const`. |
| `Property(property_name, &class::property, m)` | The same as the two-parameter version, but provides a better error message. | `Property(property_name, &class::property, m)` | The same as the two-parameter version, but provides a better error message.
{: .callout .warning}
Warning: Don't use `Property()` against member functions that you do not own,
because taking addresses of functions is fragile and generally not part of the
contract of the function.
**Notes:** **Notes:**
* You can use `FieldsAre()` to match any type that supports structured * You can use `FieldsAre()` to match any type that supports structured
@ -189,10 +194,6 @@ messages, you can use:
EXPECT_THAT(s, FieldsAre(42, "aloha")); EXPECT_THAT(s, FieldsAre(42, "aloha"));
``` ```
* Don't use `Property()` against member functions that you do not own, because
taking addresses of functions is fragile and generally not part of the
contract of the function.
## Matching the Result of a Function, Functor, or Callback ## Matching the Result of a Function, Functor, or Callback
| Matcher | Description | | Matcher | Description |

View File

@ -1,10 +1,20 @@
"""Provides a fake @fuchsia_sdk implementation that's used when the real one isn't available. """Provides a fake @fuchsia_sdk implementation that's used when the real one isn't available.
This is needed since bazel queries on targets that depend on //:gtest (eg: GoogleTest can be used with the [Fuchsia](https://fuchsia.dev/) SDK. However,
`bazel query "deps(set(//googletest/test:gtest_all_test))"`) will fail if @fuchsia_sdk is not because the Fuchsia SDK does not yet support bzlmod, GoogleTest's `MODULE.bazel`
defined when bazel is evaluating the transitive closure of the query target. file by default provides a "fake" Fuchsia SDK.
See https://github.com/google/googletest/issues/4472. To override this and use the real Fuchsia SDK, you can add the following to your
project's `MODULE.bazel` file:
fake_fuchsia_sdk_extension =
use_extension("@com_google_googletest//:fake_fuchsia_sdk.bzl", "fuchsia_sdk")
override_repo(fake_fuchsia_sdk_extension, "fuchsia_sdk")
NOTE: The `override_repo` built-in is only available in Bazel 8.0 and higher.
See https://github.com/google/googletest/issues/4472 for more details of why the
fake Fuchsia SDK is needed.
""" """
def _fake_fuchsia_sdk_impl(repo_ctx): def _fake_fuchsia_sdk_impl(repo_ctx):
@ -31,3 +41,21 @@ fake_fuchsia_sdk = repository_rule(
), ),
}, },
) )
_create_fake = tag_class()
def _fuchsia_sdk_impl(module_ctx):
create_fake_sdk = False
for mod in module_ctx.modules:
for _ in mod.tags.create_fake:
create_fake_sdk = True
if create_fake_sdk:
fake_fuchsia_sdk(name = "fuchsia_sdk")
return module_ctx.extension_metadata(reproducible = True)
fuchsia_sdk = module_extension(
implementation = _fuchsia_sdk_impl,
tag_classes = {"create_fake": _create_fake},
)

View File

@ -1493,6 +1493,7 @@ class DoAllAction<FinalAction> {
// providing a call operator because even with a particular set of arguments // providing a call operator because even with a particular set of arguments
// they don't have a fixed return type. // they don't have a fixed return type.
// We support conversion to OnceAction whenever the sub-action does.
template <typename R, typename... Args, template <typename R, typename... Args,
typename std::enable_if< typename std::enable_if<
std::is_convertible<FinalAction, OnceAction<R(Args...)>>::value, std::is_convertible<FinalAction, OnceAction<R(Args...)>>::value,
@ -1501,6 +1502,21 @@ class DoAllAction<FinalAction> {
return std::move(final_action_); return std::move(final_action_);
} }
// We also support conversion to OnceAction whenever the sub-action supports
// conversion to Action (since any Action can also be a OnceAction).
template <
typename R, typename... Args,
typename std::enable_if<
conjunction<
negation<
std::is_convertible<FinalAction, OnceAction<R(Args...)>>>,
std::is_convertible<FinalAction, Action<R(Args...)>>>::value,
int>::type = 0>
operator OnceAction<R(Args...)>() && { // NOLINT
return Action<R(Args...)>(std::move(final_action_));
}
// We support conversion to Action whenever the sub-action does.
template < template <
typename R, typename... Args, typename R, typename... Args,
typename std::enable_if< typename std::enable_if<
@ -1580,16 +1596,16 @@ class DoAllAction<InitialAction, OtherActions...>
: Base({}, std::forward<U>(other_actions)...), : Base({}, std::forward<U>(other_actions)...),
initial_action_(std::forward<T>(initial_action)) {} initial_action_(std::forward<T>(initial_action)) {}
template <typename R, typename... Args, // We support conversion to OnceAction whenever both the initial action and
typename std::enable_if< // the rest support conversion to OnceAction.
conjunction< template <
// Both the initial action and the rest must support typename R, typename... Args,
// conversion to OnceAction. typename std::enable_if<
std::is_convertible< conjunction<std::is_convertible<
InitialAction, InitialAction,
OnceAction<void(InitialActionArgType<Args>...)>>, OnceAction<void(InitialActionArgType<Args>...)>>,
std::is_convertible<Base, OnceAction<R(Args...)>>>::value, std::is_convertible<Base, OnceAction<R(Args...)>>>::value,
int>::type = 0> int>::type = 0>
operator OnceAction<R(Args...)>() && { // NOLINT operator OnceAction<R(Args...)>() && { // NOLINT
// Return an action that first calls the initial action with arguments // Return an action that first calls the initial action with arguments
// filtered through InitialActionArgType, then forwards arguments directly // filtered through InitialActionArgType, then forwards arguments directly
@ -1612,12 +1628,34 @@ class DoAllAction<InitialAction, OtherActions...>
}; };
} }
// We also support conversion to OnceAction whenever the initial action
// supports conversion to Action (since any Action can also be a OnceAction).
//
// The remaining sub-actions must also be compatible, but we don't need to
// special case them because the base class deals with them.
template <
typename R, typename... Args,
typename std::enable_if<
conjunction<
negation<std::is_convertible<
InitialAction,
OnceAction<void(InitialActionArgType<Args>...)>>>,
std::is_convertible<InitialAction,
Action<void(InitialActionArgType<Args>...)>>,
std::is_convertible<Base, OnceAction<R(Args...)>>>::value,
int>::type = 0>
operator OnceAction<R(Args...)>() && { // NOLINT
return DoAll(
Action<void(InitialActionArgType<Args>...)>(std::move(initial_action_)),
std::move(static_cast<Base&>(*this)));
}
// We support conversion to Action whenever both the initial action and the
// rest support conversion to Action.
template < template <
typename R, typename... Args, typename R, typename... Args,
typename std::enable_if< typename std::enable_if<
conjunction< conjunction<
// Both the initial action and the rest must support conversion to
// Action.
std::is_convertible<const InitialAction&, std::is_convertible<const InitialAction&,
Action<void(InitialActionArgType<Args>...)>>, Action<void(InitialActionArgType<Args>...)>>,
std::is_convertible<const Base&, Action<R(Args...)>>>::value, std::is_convertible<const Base&, Action<R(Args...)>>>::value,
@ -1665,8 +1703,9 @@ template <size_t k>
struct ReturnArgAction { struct ReturnArgAction {
template <typename... Args, template <typename... Args,
typename = typename std::enable_if<(k < sizeof...(Args))>::type> typename = typename std::enable_if<(k < sizeof...(Args))>::type>
auto operator()(Args&&... args) const -> decltype(std::get<k>( auto operator()(Args&&... args) const
std::forward_as_tuple(std::forward<Args>(args)...))) { -> decltype(std::get<k>(
std::forward_as_tuple(std::forward<Args>(args)...))) {
return std::get<k>(std::forward_as_tuple(std::forward<Args>(args)...)); return std::get<k>(std::forward_as_tuple(std::forward<Args>(args)...));
} }
}; };
@ -1681,6 +1720,16 @@ struct SaveArgAction {
} }
}; };
template <size_t k, typename Ptr>
struct SaveArgByMoveAction {
Ptr pointer;
template <typename... Args>
void operator()(Args&&... args) const {
*pointer = std::move(std::get<k>(std::tie(args...)));
}
};
template <size_t k, typename Ptr> template <size_t k, typename Ptr>
struct SaveArgPointeeAction { struct SaveArgPointeeAction {
Ptr pointer; Ptr pointer;
@ -2031,6 +2080,13 @@ internal::SaveArgAction<k, Ptr> SaveArg(Ptr pointer) {
return {pointer}; return {pointer};
} }
// Action SaveArgByMove<k>(pointer) moves the k-th (0-based) argument of the
// mock function into *pointer.
template <size_t k, typename Ptr>
internal::SaveArgByMoveAction<k, Ptr> SaveArgByMove(Ptr pointer) {
return {pointer};
}
// Action SaveArgPointee<k>(pointer) saves the value pointed to // Action SaveArgPointee<k>(pointer) saves the value pointed to
// by the k-th (0-based) argument of the mock function to *pointer. // by the k-th (0-based) argument of the mock function to *pointer.
template <size_t k, typename Ptr> template <size_t k, typename Ptr>

View File

@ -408,13 +408,22 @@ class MatcherCastImpl<T, Matcher<U>> {
} }
private: private:
class Impl : public MatcherInterface<T> { // If it's possible to implicitly convert a `const T&` to U, then `Impl` can
// take that as input to avoid a copy. Otherwise, such as when `T` is a
// non-const reference type or a type explicitly constructible only from a
// non-const reference, then `Impl` must use `T` as-is (potentially copying).
using ImplArgT =
typename std::conditional<std::is_convertible<const T&, const U&>::value,
const T&, T>::type;
class Impl : public MatcherInterface<ImplArgT> {
public: public:
explicit Impl(const Matcher<U>& source_matcher) explicit Impl(const Matcher<U>& source_matcher)
: source_matcher_(source_matcher) {} : source_matcher_(source_matcher) {}
// We delegate the matching logic to the source matcher. // We delegate the matching logic to the source matcher.
bool MatchAndExplain(T x, MatchResultListener* listener) const override { bool MatchAndExplain(ImplArgT x,
MatchResultListener* listener) const override {
using FromType = typename std::remove_cv<typename std::remove_pointer< using FromType = typename std::remove_cv<typename std::remove_pointer<
typename std::remove_reference<T>::type>::type>::type; typename std::remove_reference<T>::type>::type>::type;
using ToType = typename std::remove_cv<typename std::remove_pointer< using ToType = typename std::remove_cv<typename std::remove_pointer<
@ -431,9 +440,8 @@ class MatcherCastImpl<T, Matcher<U>> {
// Do the cast to `U` explicitly if necessary. // Do the cast to `U` explicitly if necessary.
// Otherwise, let implicit conversions do the trick. // Otherwise, let implicit conversions do the trick.
using CastType = using CastType = typename std::conditional<
typename std::conditional<std::is_convertible<T&, const U&>::value, std::is_convertible<ImplArgT&, const U&>::value, ImplArgT&, U>::type;
T&, U>::type;
return source_matcher_.MatchAndExplain(static_cast<CastType>(x), return source_matcher_.MatchAndExplain(static_cast<CastType>(x),
listener); listener);
@ -528,18 +536,16 @@ inline Matcher<T> SafeMatcherCast(const M& polymorphic_matcher_or_value) {
// safely convert a Matcher<U> to a Matcher<T> (i.e. Matcher is // safely convert a Matcher<U> to a Matcher<T> (i.e. Matcher is
// contravariant): just keep a copy of the original Matcher<U>, convert the // contravariant): just keep a copy of the original Matcher<U>, convert the
// argument from type T to U, and then pass it to the underlying Matcher<U>. // argument from type T to U, and then pass it to the underlying Matcher<U>.
// The only exception is when U is a reference and T is not, as the // The only exception is when U is a non-const reference and T is not, as the
// underlying Matcher<U> may be interested in the argument's address, which // underlying Matcher<U> may be interested in the argument's address, which
// is not preserved in the conversion from T to U. // cannot be preserved in the conversion from T to U (since a copy of the input
// T argument would be required to provide a non-const reference U).
template <typename T, typename U> template <typename T, typename U>
inline Matcher<T> SafeMatcherCast(const Matcher<U>& matcher) { inline Matcher<T> SafeMatcherCast(const Matcher<U>& matcher) {
// Enforce that T can be implicitly converted to U. // Enforce that T can be implicitly converted to U.
static_assert(std::is_convertible<const T&, const U&>::value, static_assert(std::is_convertible<const T&, const U&>::value,
"T must be implicitly convertible to U"); "T must be implicitly convertible to U (and T must be a "
// Enforce that we are not converting a non-reference type T to a reference "non-const reference if U is a non-const reference)");
// type U.
static_assert(std::is_reference<T>::value || !std::is_reference<U>::value,
"cannot convert non reference arg to reference");
// In case both T and U are arithmetic types, enforce that the // In case both T and U are arithmetic types, enforce that the
// conversion is not lossy. // conversion is not lossy.
typedef GTEST_REMOVE_REFERENCE_AND_CONST_(T) RawT; typedef GTEST_REMOVE_REFERENCE_AND_CONST_(T) RawT;
@ -561,6 +567,11 @@ Matcher<T> A();
// and MUST NOT BE USED IN USER CODE!!! // and MUST NOT BE USED IN USER CODE!!!
namespace internal { namespace internal {
// Used per go/ranked-overloads for dispatching.
struct Rank0 {};
struct Rank1 : Rank0 {};
using HighestRank = Rank1;
// If the explanation is not empty, prints it to the ostream. // If the explanation is not empty, prints it to the ostream.
inline void PrintIfNotEmpty(const std::string& explanation, inline void PrintIfNotEmpty(const std::string& explanation,
::std::ostream* os) { ::std::ostream* os) {
@ -1300,34 +1311,48 @@ class AllOfMatcherImpl : public MatcherInterface<const T&> {
bool MatchAndExplain(const T& x, bool MatchAndExplain(const T& x,
MatchResultListener* listener) const override { MatchResultListener* listener) const override {
// If either matcher1_ or matcher2_ doesn't match x, we only need // This method uses matcher's explanation when explaining the result.
// to explain why one of them fails. // However, if matcher doesn't provide one, this method uses matcher's
// description.
std::string all_match_result; std::string all_match_result;
for (const Matcher<T>& matcher : matchers_) {
for (size_t i = 0; i < matchers_.size(); ++i) {
StringMatchResultListener slistener; StringMatchResultListener slistener;
if (matchers_[i].MatchAndExplain(x, &slistener)) { // Return explanation for first failed matcher.
if (all_match_result.empty()) { if (!matcher.MatchAndExplain(x, &slistener)) {
all_match_result = slistener.str(); const std::string explanation = slistener.str();
if (!explanation.empty()) {
*listener << explanation;
} else { } else {
std::string result = slistener.str(); *listener << "which doesn't match (" << Describe(matcher) << ")";
if (!result.empty()) {
all_match_result += ", and ";
all_match_result += result;
}
} }
} else {
*listener << slistener.str();
return false; return false;
} }
// Keep track of explanations in case all matchers succeed.
std::string explanation = slistener.str();
if (explanation.empty()) {
explanation = Describe(matcher);
}
if (all_match_result.empty()) {
all_match_result = explanation;
} else {
if (!explanation.empty()) {
all_match_result += ", and ";
all_match_result += explanation;
}
}
} }
// Otherwise we need to explain why *both* of them match.
*listener << all_match_result; *listener << all_match_result;
return true; return true;
} }
private: private:
// Returns matcher description as a string.
std::string Describe(const Matcher<T>& matcher) const {
StringMatchResultListener listener;
matcher.DescribeTo(listener.stream());
return listener.str();
}
const std::vector<Matcher<T>> matchers_; const std::vector<Matcher<T>> matchers_;
}; };
@ -1405,34 +1430,55 @@ class AnyOfMatcherImpl : public MatcherInterface<const T&> {
bool MatchAndExplain(const T& x, bool MatchAndExplain(const T& x,
MatchResultListener* listener) const override { MatchResultListener* listener) const override {
// This method uses matcher's explanation when explaining the result.
// However, if matcher doesn't provide one, this method uses matcher's
// description.
std::string no_match_result; std::string no_match_result;
for (const Matcher<T>& matcher : matchers_) {
// If either matcher1_ or matcher2_ matches x, we just need to
// explain why *one* of them matches.
for (size_t i = 0; i < matchers_.size(); ++i) {
StringMatchResultListener slistener; StringMatchResultListener slistener;
if (matchers_[i].MatchAndExplain(x, &slistener)) { // Return explanation for first match.
*listener << slistener.str(); if (matcher.MatchAndExplain(x, &slistener)) {
return true; const std::string explanation = slistener.str();
} else { if (!explanation.empty()) {
if (no_match_result.empty()) { *listener << explanation;
no_match_result = slistener.str();
} else { } else {
std::string result = slistener.str(); *listener << "which matches (" << Describe(matcher) << ")";
if (!result.empty()) { }
no_match_result += ", and "; return true;
no_match_result += result; }
} // Keep track of explanations in case there is no match.
std::string explanation = slistener.str();
if (explanation.empty()) {
explanation = DescribeNegation(matcher);
}
if (no_match_result.empty()) {
no_match_result = explanation;
} else {
if (!explanation.empty()) {
no_match_result += ", and ";
no_match_result += explanation;
} }
} }
} }
// Otherwise we need to explain why *both* of them fail.
*listener << no_match_result; *listener << no_match_result;
return false; return false;
} }
private: private:
// Returns matcher description as a string.
std::string Describe(const Matcher<T>& matcher) const {
StringMatchResultListener listener;
matcher.DescribeTo(listener.stream());
return listener.str();
}
std::string DescribeNegation(const Matcher<T>& matcher) const {
StringMatchResultListener listener;
matcher.DescribeNegationTo(listener.stream());
return listener.str();
}
const std::vector<Matcher<T>> matchers_; const std::vector<Matcher<T>> matchers_;
}; };
@ -1483,7 +1529,7 @@ class SomeOfArrayMatcher {
} }
private: private:
const ::std::vector<T> matchers_; const std::vector<std::remove_const_t<T>> matchers_;
}; };
template <typename T> template <typename T>
@ -2235,6 +2281,9 @@ class ResultOfMatcher {
class Impl : public MatcherInterface<T> { class Impl : public MatcherInterface<T> {
using ResultType = decltype(CallableTraits<Callable>::template Invoke<T>( using ResultType = decltype(CallableTraits<Callable>::template Invoke<T>(
std::declval<CallableStorageType>(), std::declval<T>())); std::declval<CallableStorageType>(), std::declval<T>()));
using InnerType = std::conditional_t<
std::is_lvalue_reference<ResultType>::value,
const typename std::remove_reference<ResultType>::type&, ResultType>;
public: public:
template <typename M> template <typename M>
@ -2242,7 +2291,7 @@ class ResultOfMatcher {
const CallableStorageType& callable, const M& matcher) const CallableStorageType& callable, const M& matcher)
: result_description_(result_description), : result_description_(result_description),
callable_(callable), callable_(callable),
matcher_(MatcherCast<ResultType>(matcher)) {} matcher_(MatcherCast<InnerType>(matcher)) {}
void DescribeTo(::std::ostream* os) const override { void DescribeTo(::std::ostream* os) const override {
if (result_description_.empty()) { if (result_description_.empty()) {
@ -2272,7 +2321,7 @@ class ResultOfMatcher {
// takes a non-const reference as argument. // takes a non-const reference as argument.
// Also, specifying template argument explicitly is needed because T could // Also, specifying template argument explicitly is needed because T could
// be a non-const reference (e.g. Matcher<Uncopyable&>). // be a non-const reference (e.g. Matcher<Uncopyable&>).
ResultType result = InnerType result =
CallableTraits<Callable>::template Invoke<T>(callable_, obj); CallableTraits<Callable>::template Invoke<T>(callable_, obj);
return MatchPrintAndExplain(result, matcher_, listener); return MatchPrintAndExplain(result, matcher_, listener);
} }
@ -2285,7 +2334,7 @@ class ResultOfMatcher {
// use stateful callables with ResultOf(), which doesn't guarantee // use stateful callables with ResultOf(), which doesn't guarantee
// how many times the callable will be invoked. // how many times the callable will be invoked.
mutable CallableStorageType callable_; mutable CallableStorageType callable_;
const Matcher<ResultType> matcher_; const Matcher<InnerType> matcher_;
}; // class Impl }; // class Impl
const std::string result_description_; const std::string result_description_;
@ -2920,10 +2969,6 @@ class EachMatcher {
const M inner_matcher_; const M inner_matcher_;
}; };
// Use go/ranked-overloads for dispatching.
struct Rank0 {};
struct Rank1 : Rank0 {};
namespace pair_getters { namespace pair_getters {
using std::get; using std::get;
template <typename T> template <typename T>
@ -3255,6 +3300,11 @@ auto UnpackStructImpl(const T& t, std::make_index_sequence<19>, char) {
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s] = t; const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s] = t;
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s); return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s);
} }
template <typename T>
auto UnpackStructImpl(const T& u, std::make_index_sequence<20>, char) {
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t] = u;
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t);
}
#endif // defined(__cpp_structured_bindings) #endif // defined(__cpp_structured_bindings)
template <size_t I, typename T> template <size_t I, typename T>
@ -3769,7 +3819,7 @@ class UnorderedElementsAreArrayMatcher {
private: private:
UnorderedMatcherRequire::Flags match_flags_; UnorderedMatcherRequire::Flags match_flags_;
::std::vector<T> matchers_; std::vector<std::remove_const_t<T>> matchers_;
}; };
// Implements ElementsAreArray(). // Implements ElementsAreArray().
@ -3790,7 +3840,7 @@ class ElementsAreArrayMatcher {
} }
private: private:
const ::std::vector<T> matchers_; const std::vector<std::remove_const_t<T>> matchers_;
}; };
// Given a 2-tuple matcher tm of type Tuple2Matcher and a value second // Given a 2-tuple matcher tm of type Tuple2Matcher and a value second
@ -3877,6 +3927,21 @@ GTEST_API_ std::string FormatMatcherDescription(
bool negation, const char* matcher_name, bool negation, const char* matcher_name,
const std::vector<const char*>& param_names, const Strings& param_values); const std::vector<const char*>& param_names, const Strings& param_values);
// Overloads to support `OptionalMatcher` being used with a type that either
// supports implicit conversion to bool or a `has_value()` method.
template <typename Optional>
auto IsOptionalEngaged(const Optional& optional,
Rank1) -> decltype(!!optional) {
// The use of double-negation here is to preserve historical behavior where
// the matcher used `operator!` rather than directly using `operator bool`.
return !static_cast<bool>(!optional);
}
template <typename Optional>
auto IsOptionalEngaged(const Optional& optional,
Rank0) -> decltype(!optional.has_value()) {
return optional.has_value();
}
// Implements a matcher that checks the value of a optional<> type variable. // Implements a matcher that checks the value of a optional<> type variable.
template <typename ValueMatcher> template <typename ValueMatcher>
class OptionalMatcher { class OptionalMatcher {
@ -3909,7 +3974,7 @@ class OptionalMatcher {
bool MatchAndExplain(Optional optional, bool MatchAndExplain(Optional optional,
MatchResultListener* listener) const override { MatchResultListener* listener) const override {
if (!optional) { if (!IsOptionalEngaged(optional, HighestRank())) {
*listener << "which is not engaged"; *listener << "which is not engaged";
return false; return false;
} }
@ -4388,6 +4453,10 @@ inline PolymorphicMatcher<internal::FieldMatcher<Class, FieldType>> Field(
// matches 'matcher'. For example, // matches 'matcher'. For example,
// Property(&Foo::str, StartsWith("hi")) // Property(&Foo::str, StartsWith("hi"))
// matches a Foo object x if and only if x.str() starts with "hi". // matches a Foo object x if and only if x.str() starts with "hi".
//
// Warning: Don't use `Property()` against member functions that you do not
// own, because taking addresses of functions is fragile and generally not part
// of the contract of the function.
template <typename Class, typename PropertyType, typename PropertyMatcher> template <typename Class, typename PropertyType, typename PropertyMatcher>
inline PolymorphicMatcher<internal::PropertyMatcher< inline PolymorphicMatcher<internal::PropertyMatcher<
Class, PropertyType, PropertyType (Class::*)() const>> Class, PropertyType, PropertyType (Class::*)() const>>
@ -4742,9 +4811,10 @@ Pointwise(const TupleMatcher& tuple_matcher, const Container& rhs) {
// Supports the Pointwise(m, {a, b, c}) syntax. // Supports the Pointwise(m, {a, b, c}) syntax.
template <typename TupleMatcher, typename T> template <typename TupleMatcher, typename T>
inline internal::PointwiseMatcher<TupleMatcher, std::vector<T>> Pointwise( inline internal::PointwiseMatcher<TupleMatcher,
const TupleMatcher& tuple_matcher, std::initializer_list<T> rhs) { std::vector<std::remove_const_t<T>>>
return Pointwise(tuple_matcher, std::vector<T>(rhs)); Pointwise(const TupleMatcher& tuple_matcher, std::initializer_list<T> rhs) {
return Pointwise(tuple_matcher, std::vector<std::remove_const_t<T>>(rhs));
} }
// UnorderedPointwise(pair_matcher, rhs) matches an STL-style // UnorderedPointwise(pair_matcher, rhs) matches an STL-style
@ -4906,7 +4976,7 @@ inline internal::UnorderedElementsAreArrayMatcher<T> IsSupersetOf(
// - {1} matches IsSubsetOf({Gt(0), Lt(0)}), as 1 matches Gt(0). // - {1} matches IsSubsetOf({Gt(0), Lt(0)}), as 1 matches Gt(0).
// - {1, -1} matches IsSubsetOf({Lt(0), Gt(0)}), as 1 matches Gt(0) and -1 // - {1, -1} matches IsSubsetOf({Lt(0), Gt(0)}), as 1 matches Gt(0) and -1
// matches Lt(0). // matches Lt(0).
// - {1, 2} doesn't matches IsSubsetOf({Gt(0), Lt(0)}), even though 1 and 2 both // - {1, 2} doesn't match IsSubsetOf({Gt(0), Lt(0)}), even though 1 and 2 both
// match Gt(0). The reason is that different matchers must be used for // match Gt(0). The reason is that different matchers must be used for
// elements in different slots of the container. // elements in different slots of the container.
// //
@ -5231,9 +5301,10 @@ inline InnerMatcher AllArgs(const InnerMatcher& matcher) {
} }
// Returns a matcher that matches the value of an optional<> type variable. // Returns a matcher that matches the value of an optional<> type variable.
// The matcher implementation only uses '!arg' and requires that the optional<> // The matcher implementation only uses '!arg' (or 'arg.has_value()' if '!arg`
// type has a 'value_type' member type and that '*arg' is of type 'value_type' // isn't a valid expression) and requires that the optional<> type has a
// and is printable using 'PrintToString'. It is compatible with // 'value_type' member type and that '*arg' is of type 'value_type' and is
// printable using 'PrintToString'. It is compatible with
// std::optional/std::experimental::optional. // std::optional/std::experimental::optional.
// Note that to compare an optional type variable against nullopt you should // Note that to compare an optional type variable against nullopt you should
// use Eq(nullopt) and not Eq(Optional(nullopt)). The latter implies that the // use Eq(nullopt) and not Eq(Optional(nullopt)). The latter implies that the

View File

@ -601,9 +601,10 @@ template <std::size_t index, typename... Params>
struct InvokeArgumentAction { struct InvokeArgumentAction {
template <typename... Args, template <typename... Args,
typename = typename std::enable_if<(index < sizeof...(Args))>::type> typename = typename std::enable_if<(index < sizeof...(Args))>::type>
auto operator()(Args &&...args) const -> decltype(internal::InvokeArgument( auto operator()(Args &&...args) const
std::get<index>(std::forward_as_tuple(std::forward<Args>(args)...)), -> decltype(internal::InvokeArgument(
std::declval<const Params &>()...)) { std::get<index>(std::forward_as_tuple(std::forward<Args>(args)...)),
std::declval<const Params &>()...)) {
internal::FlatTuple<Args &&...> args_tuple(FlatTupleConstructTag{}, internal::FlatTuple<Args &&...> args_tuple(FlatTupleConstructTag{},
std::forward<Args>(args)...); std::forward<Args>(args)...);
return params.Apply([&](const Params &...unpacked_params) { return params.Apply([&](const Params &...unpacked_params) {

View File

@ -868,7 +868,7 @@ class GTEST_API_ ExpectationBase {
Clause last_clause_; Clause last_clause_;
mutable bool action_count_checked_; // Under mutex_. mutable bool action_count_checked_; // Under mutex_.
mutable Mutex mutex_; // Protects action_count_checked_. mutable Mutex mutex_; // Protects action_count_checked_.
}; // class ExpectationBase }; // class ExpectationBase
template <typename F> template <typename F>
class TypedExpectation; class TypedExpectation;
@ -1838,9 +1838,8 @@ R FunctionMocker<R(Args...)>::InvokeWith(ArgumentTuple&& args)
// Doing so slows down compilation dramatically because the *constructor* of // Doing so slows down compilation dramatically because the *constructor* of
// std::function<T> is re-instantiated with different template // std::function<T> is re-instantiated with different template
// parameters each time. // parameters each time.
const UninterestingCallCleanupHandler report_uninteresting_call = { const UninterestingCallCleanupHandler report_uninteresting_call = {reaction,
reaction, ss ss};
};
return PerformActionAndPrintResult(nullptr, std::move(args), ss.str(), ss); return PerformActionAndPrintResult(nullptr, std::move(args), ss.str(), ss);
} }
@ -1890,8 +1889,7 @@ R FunctionMocker<R(Args...)>::InvokeWith(ArgumentTuple&& args)
// std::function<T> is re-instantiated with different template // std::function<T> is re-instantiated with different template
// parameters each time. // parameters each time.
const FailureCleanupHandler handle_failures = { const FailureCleanupHandler handle_failures = {
ss, why, loc, untyped_expectation, found, is_excessive ss, why, loc, untyped_expectation, found, is_excessive};
};
return PerformActionAndPrintResult(untyped_action, std::move(args), ss.str(), return PerformActionAndPrintResult(untyped_action, std::move(args), ss.str(),
ss); ss);

View File

@ -42,6 +42,7 @@
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <cstdint> #include <cstdint>
#include <iostream> #include <iostream>

View File

@ -53,12 +53,12 @@ class BetweenCardinalityImpl : public CardinalityInterface {
: min_(min >= 0 ? min : 0), max_(max >= min_ ? max : min_) { : min_(min >= 0 ? min : 0), max_(max >= min_ ? max : min_) {
std::stringstream ss; std::stringstream ss;
if (min < 0) { if (min < 0) {
ss << "The invocation lower bound must be >= 0, " ss << "The invocation lower bound must be >= 0, " << "but is actually "
<< "but is actually " << min << "."; << min << ".";
internal::Expect(false, __FILE__, __LINE__, ss.str()); internal::Expect(false, __FILE__, __LINE__, ss.str());
} else if (max < 0) { } else if (max < 0) {
ss << "The invocation upper bound must be >= 0, " ss << "The invocation upper bound must be >= 0, " << "but is actually "
<< "but is actually " << max << "."; << max << ".";
internal::Expect(false, __FILE__, __LINE__, ss.str()); internal::Expect(false, __FILE__, __LINE__, ss.str());
} else if (min > max) { } else if (min > max) {
ss << "The invocation upper bound (" << max ss << "The invocation upper bound (" << max

View File

@ -222,8 +222,8 @@ TEST(TypeTraits, IsInvocableRV) {
// In C++17 and above, where it's guaranteed that functions can return // In C++17 and above, where it's guaranteed that functions can return
// non-moveable objects, everything should work fine for non-moveable rsult // non-moveable objects, everything should work fine for non-moveable rsult
// types too. // types too.
#if defined(GTEST_INTERNAL_CPLUSPLUS_LANG) && \ // TODO(b/396121064) - Fix this test under MSVC
GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L #ifndef _MSC_VER
{ {
struct NonMoveable { struct NonMoveable {
NonMoveable() = default; NonMoveable() = default;
@ -244,7 +244,7 @@ TEST(TypeTraits, IsInvocableRV) {
static_assert(!internal::is_callable_r<int, Callable>::value); static_assert(!internal::is_callable_r<int, Callable>::value);
static_assert(!internal::is_callable_r<NonMoveable, Callable, int>::value); static_assert(!internal::is_callable_r<NonMoveable, Callable, int>::value);
} }
#endif // C++17 and above #endif // _MSC_VER
// Nothing should choke when we try to call other arguments besides directly // Nothing should choke when we try to call other arguments besides directly
// callable objects, but they should not show up as callable. // callable objects, but they should not show up as callable.
@ -441,8 +441,8 @@ TEST(DefaultValueDeathTest, GetReturnsBuiltInDefaultValueWhenUnset) {
EXPECT_EQ(0, DefaultValue<int>::Get()); EXPECT_EQ(0, DefaultValue<int>::Get());
EXPECT_DEATH_IF_SUPPORTED({ DefaultValue<MyNonDefaultConstructible>::Get(); }, EXPECT_DEATH_IF_SUPPORTED(
""); { DefaultValue<MyNonDefaultConstructible>::Get(); }, "");
} }
TEST(DefaultValueTest, GetWorksForMoveOnlyIfSet) { TEST(DefaultValueTest, GetWorksForMoveOnlyIfSet) {
@ -505,8 +505,8 @@ TEST(DefaultValueOfReferenceDeathTest, GetReturnsBuiltInDefaultValueWhenUnset) {
EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible&>::IsSet()); EXPECT_FALSE(DefaultValue<MyNonDefaultConstructible&>::IsSet());
EXPECT_DEATH_IF_SUPPORTED({ DefaultValue<int&>::Get(); }, ""); EXPECT_DEATH_IF_SUPPORTED({ DefaultValue<int&>::Get(); }, "");
EXPECT_DEATH_IF_SUPPORTED({ DefaultValue<MyNonDefaultConstructible>::Get(); }, EXPECT_DEATH_IF_SUPPORTED(
""); { DefaultValue<MyNonDefaultConstructible>::Get(); }, "");
} }
// Tests that ActionInterface can be implemented by defining the // Tests that ActionInterface can be implemented by defining the
@ -1477,6 +1477,54 @@ TEST(DoAll, SupportsTypeErasedActions) {
} }
} }
// A DoAll action should be convertible to a OnceAction, even when its component
// sub-actions are user-provided types that define only an Action conversion
// operator. If they supposed being called more than once then they also support
// being called at most once.
TEST(DoAll, ConvertibleToOnceActionWithUserProvidedActionConversion) {
// Simplest case: only one sub-action.
struct CustomFinal final {
operator Action<int()>() { // NOLINT
return Return(17);
}
operator Action<int(int, char)>() { // NOLINT
return Return(19);
}
};
{
OnceAction<int()> action = DoAll(CustomFinal{});
EXPECT_EQ(17, std::move(action).Call());
}
{
OnceAction<int(int, char)> action = DoAll(CustomFinal{});
EXPECT_EQ(19, std::move(action).Call(0, 0));
}
// It should also work with multiple sub-actions.
struct CustomInitial final {
operator Action<void()>() { // NOLINT
return [] {};
}
operator Action<void(int, char)>() { // NOLINT
return [] {};
}
};
{
OnceAction<int()> action = DoAll(CustomInitial{}, CustomFinal{});
EXPECT_EQ(17, std::move(action).Call());
}
{
OnceAction<int(int, char)> action = DoAll(CustomInitial{}, CustomFinal{});
EXPECT_EQ(19, std::move(action).Call(0, 0));
}
}
// Tests using WithArgs and with an action that takes 1 argument. // Tests using WithArgs and with an action that takes 1 argument.
TEST(WithArgsTest, OneArg) { TEST(WithArgsTest, OneArg) {
Action<bool(double x, int n)> a = WithArgs<1>(Invoke(Unary)); // NOLINT Action<bool(double x, int n)> a = WithArgs<1>(Invoke(Unary)); // NOLINT

View File

@ -325,8 +325,8 @@ TYPED_TEST(FunctionMockerTest, MocksBinaryFunction) {
// Tests mocking a decimal function. // Tests mocking a decimal function.
TYPED_TEST(FunctionMockerTest, MocksDecimalFunction) { TYPED_TEST(FunctionMockerTest, MocksDecimalFunction) {
EXPECT_CALL(this->mock_foo_, EXPECT_CALL(this->mock_foo_, Decimal(true, 'a', 0, 0, 1L, A<float>(), Lt(100),
Decimal(true, 'a', 0, 0, 1L, A<float>(), Lt(100), 5U, NULL, "hi")) 5U, nullptr, "hi"))
.WillOnce(Return(5)); .WillOnce(Return(5));
EXPECT_EQ(5, this->foo_->Decimal(true, 'a', 0, 0, 1, 0, 0, 5, nullptr, "hi")); EXPECT_EQ(5, this->foo_->Decimal(true, 'a', 0, 0, 1, 0, 0, 5, nullptr, "hi"));

View File

@ -36,7 +36,9 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include "gmock/gmock.h"
#include "test/gmock-matchers_test.h" #include "test/gmock-matchers_test.h"
#include "gtest/gtest.h"
// Silence warning C4244: 'initializing': conversion from 'int' to 'short', // Silence warning C4244: 'initializing': conversion from 'int' to 'short',
// possible loss of data and C4100, unreferenced local parameter // possible loss of data and C4100, unreferenced local parameter
@ -559,10 +561,9 @@ TEST_P(AllOfTestP, ExplainsResult) {
Matcher<int> m; Matcher<int> m;
// Successful match. Both matchers need to explain. The second // Successful match. Both matchers need to explain. The second
// matcher doesn't give an explanation, so only the first matcher's // matcher doesn't give an explanation, so the matcher description is used.
// explanation is printed.
m = AllOf(GreaterThan(10), Lt(30)); m = AllOf(GreaterThan(10), Lt(30));
EXPECT_EQ("which is 15 more than 10", Explain(m, 25)); EXPECT_EQ("which is 15 more than 10, and is < 30", Explain(m, 25));
// Successful match. Both matchers need to explain. // Successful match. Both matchers need to explain.
m = AllOf(GreaterThan(10), GreaterThan(20)); m = AllOf(GreaterThan(10), GreaterThan(20));
@ -572,8 +573,9 @@ TEST_P(AllOfTestP, ExplainsResult) {
// Successful match. All matchers need to explain. The second // Successful match. All matchers need to explain. The second
// matcher doesn't given an explanation. // matcher doesn't given an explanation.
m = AllOf(GreaterThan(10), Lt(30), GreaterThan(20)); m = AllOf(GreaterThan(10), Lt(30), GreaterThan(20));
EXPECT_EQ("which is 15 more than 10, and which is 5 more than 20", EXPECT_EQ(
Explain(m, 25)); "which is 15 more than 10, and is < 30, and which is 5 more than 20",
Explain(m, 25));
// Successful match. All matchers need to explain. // Successful match. All matchers need to explain.
m = AllOf(GreaterThan(10), GreaterThan(20), GreaterThan(30)); m = AllOf(GreaterThan(10), GreaterThan(20), GreaterThan(30));
@ -588,10 +590,10 @@ TEST_P(AllOfTestP, ExplainsResult) {
EXPECT_EQ("which is 5 less than 10", Explain(m, 5)); EXPECT_EQ("which is 5 less than 10", Explain(m, 5));
// Failed match. The second matcher, which failed, needs to // Failed match. The second matcher, which failed, needs to
// explain. Since it doesn't given an explanation, nothing is // explain. Since it doesn't given an explanation, the matcher text is
// printed. // printed.
m = AllOf(GreaterThan(10), Lt(30)); m = AllOf(GreaterThan(10), Lt(30));
EXPECT_EQ("", Explain(m, 40)); EXPECT_EQ("which doesn't match (is < 30)", Explain(m, 40));
// Failed match. The second matcher, which failed, needs to // Failed match. The second matcher, which failed, needs to
// explain. // explain.
@ -774,45 +776,43 @@ TEST(AnyOfTest, AnyOfMatcherSafelyCastsMonomorphicMatchers) {
TEST_P(AnyOfTestP, ExplainsResult) { TEST_P(AnyOfTestP, ExplainsResult) {
Matcher<int> m; Matcher<int> m;
// Failed match. Both matchers need to explain. The second // Failed match. The second matcher have no explanation (description is used).
// matcher doesn't give an explanation, so only the first matcher's
// explanation is printed.
m = AnyOf(GreaterThan(10), Lt(0)); m = AnyOf(GreaterThan(10), Lt(0));
EXPECT_EQ("which is 5 less than 10", Explain(m, 5)); EXPECT_EQ("which is 5 less than 10, and isn't < 0", Explain(m, 5));
// Failed match. Both matchers need to explain. // Failed match. Both matchers have explanations.
m = AnyOf(GreaterThan(10), GreaterThan(20)); m = AnyOf(GreaterThan(10), GreaterThan(20));
EXPECT_EQ("which is 5 less than 10, and which is 15 less than 20", EXPECT_EQ("which is 5 less than 10, and which is 15 less than 20",
Explain(m, 5)); Explain(m, 5));
// Failed match. All matchers need to explain. The second // Failed match. The middle matcher have no explanation.
// matcher doesn't given an explanation.
m = AnyOf(GreaterThan(10), Gt(20), GreaterThan(30)); m = AnyOf(GreaterThan(10), Gt(20), GreaterThan(30));
EXPECT_EQ("which is 5 less than 10, and which is 25 less than 30", EXPECT_EQ(
Explain(m, 5)); "which is 5 less than 10, and isn't > 20, and which is 25 less than 30",
Explain(m, 5));
// Failed match. All matchers need to explain. // Failed match. All three matchers have explanations.
m = AnyOf(GreaterThan(10), GreaterThan(20), GreaterThan(30)); m = AnyOf(GreaterThan(10), GreaterThan(20), GreaterThan(30));
EXPECT_EQ( EXPECT_EQ(
"which is 5 less than 10, and which is 15 less than 20, " "which is 5 less than 10, and which is 15 less than 20, "
"and which is 25 less than 30", "and which is 25 less than 30",
Explain(m, 5)); Explain(m, 5));
// Successful match. The first matcher, which succeeded, needs to // Successful match. The first macher succeeded and has explanation.
// explain.
m = AnyOf(GreaterThan(10), GreaterThan(20)); m = AnyOf(GreaterThan(10), GreaterThan(20));
EXPECT_EQ("which is 5 more than 10", Explain(m, 15)); EXPECT_EQ("which is 5 more than 10", Explain(m, 15));
// Successful match. The second matcher, which succeeded, needs to // Successful match. The second matcher succeeded and has explanation.
// explain. Since it doesn't given an explanation, nothing is
// printed.
m = AnyOf(GreaterThan(10), Lt(30));
EXPECT_EQ("", Explain(m, 0));
// Successful match. The second matcher, which succeeded, needs to
// explain.
m = AnyOf(GreaterThan(30), GreaterThan(20)); m = AnyOf(GreaterThan(30), GreaterThan(20));
EXPECT_EQ("which is 5 more than 20", Explain(m, 25)); EXPECT_EQ("which is 5 more than 20", Explain(m, 25));
// Successful match. The first matcher succeeded and has no explanation.
m = AnyOf(Gt(10), Lt(20));
EXPECT_EQ("which matches (is > 10)", Explain(m, 15));
// Successful match. The second matcher succeeded and has no explanation.
m = AnyOf(Gt(30), Gt(20));
EXPECT_EQ("which matches (is > 20)", Explain(m, 25));
} }
// The following predicate function and predicate functor are for // The following predicate function and predicate functor are for

View File

@ -37,13 +37,14 @@
#include <tuple> #include <tuple>
#include <vector> #include <vector>
#include "gmock/gmock.h"
#include "test/gmock-matchers_test.h" #include "test/gmock-matchers_test.h"
#include "gtest/gtest.h"
// Silence warning C4244: 'initializing': conversion from 'int' to 'short', // Silence warning C4244: 'initializing': conversion from 'int' to 'short',
// possible loss of data and C4100, unreferenced local parameter // possible loss of data and C4100, unreferenced local parameter
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244 4100) GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244 4100)
namespace testing { namespace testing {
namespace gmock_matchers_test { namespace gmock_matchers_test {
namespace { namespace {
@ -410,9 +411,27 @@ class IntValue {
int value_; int value_;
}; };
// For testing casting matchers between compatible types. This is similar to
// IntValue, but takes a non-const reference to the value, showing MatcherCast
// works with such types (and doesn't, for example, use a const ref internally).
class MutableIntView {
public:
// An int& can be statically (although not implicitly) cast to a
// MutableIntView.
explicit MutableIntView(int& a_value) : value_(a_value) {}
int& value() const { return value_; }
private:
int& value_;
};
// For testing casting matchers between compatible types. // For testing casting matchers between compatible types.
bool IsPositiveIntValue(const IntValue& foo) { return foo.value() > 0; } bool IsPositiveIntValue(const IntValue& foo) { return foo.value() > 0; }
// For testing casting matchers between compatible types.
bool IsPositiveMutableIntView(MutableIntView foo) { return foo.value() > 0; }
// Tests that MatcherCast<T>(m) works when m is a Matcher<U> where T // Tests that MatcherCast<T>(m) works when m is a Matcher<U> where T
// can be statically converted to U. // can be statically converted to U.
TEST(MatcherCastTest, FromCompatibleType) { TEST(MatcherCastTest, FromCompatibleType) {
@ -428,14 +447,34 @@ TEST(MatcherCastTest, FromCompatibleType) {
// predicate. // predicate.
EXPECT_TRUE(m4.Matches(1)); EXPECT_TRUE(m4.Matches(1));
EXPECT_FALSE(m4.Matches(0)); EXPECT_FALSE(m4.Matches(0));
Matcher<MutableIntView> m5 = Truly(IsPositiveMutableIntView);
Matcher<int> m6 = MatcherCast<int>(m5);
// In the following, the arguments 1 and 0 are statically converted to
// MutableIntView objects, and then tested by the IsPositiveMutableIntView()
// predicate.
EXPECT_TRUE(m6.Matches(1));
EXPECT_FALSE(m6.Matches(0));
} }
// Tests that MatcherCast<T>(m) works when m is a Matcher<const T&>. // Tests that MatcherCast<T>(m) works when m is a Matcher<const T&>.
TEST(MatcherCastTest, FromConstReferenceToNonReference) { TEST(MatcherCastTest, FromConstReferenceToNonReference) {
Matcher<const int&> m1 = Eq(0); int n = 0;
Matcher<const int&> m1 = Ref(n);
Matcher<int> m2 = MatcherCast<int>(m1); Matcher<int> m2 = MatcherCast<int>(m1);
EXPECT_TRUE(m2.Matches(0)); int n1 = 0;
EXPECT_FALSE(m2.Matches(1)); EXPECT_TRUE(m2.Matches(n));
EXPECT_FALSE(m2.Matches(n1));
}
// Tests that MatcherCast<T&>(m) works when m is a Matcher<const T&>.
TEST(MatcherCastTest, FromConstReferenceToReference) {
int n = 0;
Matcher<const int&> m1 = Ref(n);
Matcher<int&> m2 = MatcherCast<int&>(m1);
int n1 = 0;
EXPECT_TRUE(m2.Matches(n));
EXPECT_FALSE(m2.Matches(n1));
} }
// Tests that MatcherCast<T>(m) works when m is a Matcher<T&>. // Tests that MatcherCast<T>(m) works when m is a Matcher<T&>.
@ -444,6 +483,12 @@ TEST(MatcherCastTest, FromReferenceToNonReference) {
Matcher<int> m2 = MatcherCast<int>(m1); Matcher<int> m2 = MatcherCast<int>(m1);
EXPECT_TRUE(m2.Matches(0)); EXPECT_TRUE(m2.Matches(0));
EXPECT_FALSE(m2.Matches(1)); EXPECT_FALSE(m2.Matches(1));
// Of course, reference identity isn't preserved since a copy is required.
int n = 0;
Matcher<int&> m3 = Ref(n);
Matcher<int> m4 = MatcherCast<int>(m3);
EXPECT_FALSE(m4.Matches(n));
} }
// Tests that MatcherCast<const T&>(m) works when m is a Matcher<T>. // Tests that MatcherCast<const T&>(m) works when m is a Matcher<T>.
@ -648,6 +693,16 @@ TEST(SafeMatcherCastTest, FromBaseClass) {
EXPECT_FALSE(m4.Matches(d2)); EXPECT_FALSE(m4.Matches(d2));
} }
// Tests that SafeMatcherCast<T>(m) works when m is a Matcher<const T&>.
TEST(SafeMatcherCastTest, FromConstReferenceToNonReference) {
int n = 0;
Matcher<const int&> m1 = Ref(n);
Matcher<int> m2 = SafeMatcherCast<int>(m1);
int n1 = 0;
EXPECT_TRUE(m2.Matches(n));
EXPECT_FALSE(m2.Matches(n1));
}
// Tests that SafeMatcherCast<T&>(m) works when m is a Matcher<const T&>. // Tests that SafeMatcherCast<T&>(m) works when m is a Matcher<const T&>.
TEST(SafeMatcherCastTest, FromConstReferenceToReference) { TEST(SafeMatcherCastTest, FromConstReferenceToReference) {
int n = 0; int n = 0;
@ -2334,9 +2389,11 @@ TEST(ExplainMatchResultTest, AllOf_True_True) {
EXPECT_EQ("which is 0 modulo 2, and which is 0 modulo 3", Explain(m, 6)); EXPECT_EQ("which is 0 modulo 2, and which is 0 modulo 3", Explain(m, 6));
} }
// Tests that when AllOf() succeeds, but matchers have no explanation,
// the matcher description is used.
TEST(ExplainMatchResultTest, AllOf_True_True_2) { TEST(ExplainMatchResultTest, AllOf_True_True_2) {
const Matcher<int> m = AllOf(Ge(2), Le(3)); const Matcher<int> m = AllOf(Ge(2), Le(3));
EXPECT_EQ("", Explain(m, 2)); EXPECT_EQ("is >= 2, and is <= 3", Explain(m, 2));
} }
INSTANTIATE_GTEST_MATCHER_TEST_P(ExplainmatcherResultTest); INSTANTIATE_GTEST_MATCHER_TEST_P(ExplainmatcherResultTest);

View File

@ -43,14 +43,14 @@
#include <tuple> #include <tuple>
#include <vector> #include <vector>
#include "gmock/gmock.h"
#include "test/gmock-matchers_test.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
// Silence warning C4244: 'initializing': conversion from 'int' to 'short', // Silence warning C4244: 'initializing': conversion from 'int' to 'short',
// possible loss of data and C4100, unreferenced local parameter // possible loss of data and C4100, unreferenced local parameter
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244 4100) GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244 4100)
#include "test/gmock-matchers_test.h"
namespace testing { namespace testing {
namespace gmock_matchers_test { namespace gmock_matchers_test {
namespace { namespace {
@ -1204,13 +1204,16 @@ TEST(SizeIsTest, ExplainsResult) {
vector<int> container; vector<int> container;
EXPECT_EQ("whose size 0 doesn't match", Explain(m1, container)); EXPECT_EQ("whose size 0 doesn't match", Explain(m1, container));
EXPECT_EQ("whose size 0 matches", Explain(m2, container)); EXPECT_EQ("whose size 0 matches", Explain(m2, container));
EXPECT_EQ("whose size 0 matches", Explain(m3, container)); EXPECT_EQ("whose size 0 matches, which matches (is equal to 0)",
Explain(m3, container));
EXPECT_EQ("whose size 0 doesn't match", Explain(m4, container)); EXPECT_EQ("whose size 0 doesn't match", Explain(m4, container));
container.push_back(0); container.push_back(0);
container.push_back(0); container.push_back(0);
EXPECT_EQ("whose size 2 matches", Explain(m1, container)); EXPECT_EQ("whose size 2 matches", Explain(m1, container));
EXPECT_EQ("whose size 2 doesn't match", Explain(m2, container)); EXPECT_EQ("whose size 2 doesn't match", Explain(m2, container));
EXPECT_EQ("whose size 2 doesn't match", Explain(m3, container)); EXPECT_EQ(
"whose size 2 doesn't match, isn't equal to 0, and isn't equal to 3",
Explain(m3, container));
EXPECT_EQ("whose size 2 matches", Explain(m4, container)); EXPECT_EQ("whose size 2 matches", Explain(m4, container));
} }
@ -1475,8 +1478,10 @@ TEST_P(BeginEndDistanceIsTestP, ExplainsResult) {
Explain(m1, container)); Explain(m1, container));
EXPECT_EQ("whose distance between begin() and end() 0 matches", EXPECT_EQ("whose distance between begin() and end() 0 matches",
Explain(m2, container)); Explain(m2, container));
EXPECT_EQ("whose distance between begin() and end() 0 matches", EXPECT_EQ(
Explain(m3, container)); "whose distance between begin() and end() 0 matches, which matches (is "
"equal to 0)",
Explain(m3, container));
EXPECT_EQ( EXPECT_EQ(
"whose distance between begin() and end() 0 doesn't match, which is 1 " "whose distance between begin() and end() 0 doesn't match, which is 1 "
"less than 1", "less than 1",
@ -1487,8 +1492,10 @@ TEST_P(BeginEndDistanceIsTestP, ExplainsResult) {
Explain(m1, container)); Explain(m1, container));
EXPECT_EQ("whose distance between begin() and end() 2 doesn't match", EXPECT_EQ("whose distance between begin() and end() 2 doesn't match",
Explain(m2, container)); Explain(m2, container));
EXPECT_EQ("whose distance between begin() and end() 2 doesn't match", EXPECT_EQ(
Explain(m3, container)); "whose distance between begin() and end() 2 doesn't match, isn't equal "
"to 0, and isn't equal to 3",
Explain(m3, container));
EXPECT_EQ( EXPECT_EQ(
"whose distance between begin() and end() 2 matches, which is 1 more " "whose distance between begin() and end() 2 matches, which is 1 more "
"than 1", "than 1",

View File

@ -32,6 +32,7 @@
// This file tests some commonly used argument matchers. // This file tests some commonly used argument matchers.
#include <array> #include <array>
#include <cstdint>
#include <memory> #include <memory>
#include <ostream> #include <ostream>
#include <string> #include <string>
@ -39,14 +40,14 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "gmock/gmock.h"
#include "test/gmock-matchers_test.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
// Silence warning C4244: 'initializing': conversion from 'int' to 'short', // Silence warning C4244: 'initializing': conversion from 'int' to 'short',
// possible loss of data and C4100, unreferenced local parameter // possible loss of data and C4100, unreferenced local parameter
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244 4100) GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244 4100)
#include "test/gmock-matchers_test.h"
namespace testing { namespace testing {
namespace gmock_matchers_test { namespace gmock_matchers_test {
namespace { namespace {
@ -674,6 +675,8 @@ TEST_P(MatcherTupleTestP, ExplainsMatchFailure) {
// explanation. // explanation.
} }
#if GTEST_HAS_TYPED_TEST
// Sample optional type implementation with minimal requirements for use with // Sample optional type implementation with minimal requirements for use with
// Optional matcher. // Optional matcher.
template <typename T> template <typename T>
@ -691,38 +694,94 @@ class SampleOptional {
bool has_value_; bool has_value_;
}; };
TEST(OptionalTest, DescribesSelf) { // Sample optional type implementation with alternative minimal requirements for
const Matcher<SampleOptional<int>> m = Optional(Eq(1)); // use with Optional matcher. In particular, while it doesn't have a bool
// conversion operator, it does have a has_value() method.
template <typename T>
class SampleOptionalWithoutBoolConversion {
public:
using value_type = T;
explicit SampleOptionalWithoutBoolConversion(T value)
: value_(std::move(value)), has_value_(true) {}
SampleOptionalWithoutBoolConversion() : value_(), has_value_(false) {}
bool has_value() const { return has_value_; }
const T& operator*() const { return value_; }
private:
T value_;
bool has_value_;
};
template <typename T>
class OptionalTest : public testing::Test {};
using OptionalTestTypes =
testing::Types<SampleOptional<int>,
SampleOptionalWithoutBoolConversion<int>>;
TYPED_TEST_SUITE(OptionalTest, OptionalTestTypes);
TYPED_TEST(OptionalTest, DescribesSelf) {
const Matcher<TypeParam> m = Optional(Eq(1));
EXPECT_EQ("value is equal to 1", Describe(m)); EXPECT_EQ("value is equal to 1", Describe(m));
} }
TEST(OptionalTest, ExplainsSelf) { TYPED_TEST(OptionalTest, ExplainsSelf) {
const Matcher<SampleOptional<int>> m = Optional(Eq(1)); const Matcher<TypeParam> m = Optional(Eq(1));
EXPECT_EQ("whose value 1 matches", Explain(m, SampleOptional<int>(1))); EXPECT_EQ("whose value 1 matches", Explain(m, TypeParam(1)));
EXPECT_EQ("whose value 2 doesn't match", Explain(m, SampleOptional<int>(2))); EXPECT_EQ("whose value 2 doesn't match", Explain(m, TypeParam(2)));
} }
TEST(OptionalTest, MatchesNonEmptyOptional) { TYPED_TEST(OptionalTest, MatchesNonEmptyOptional) {
const Matcher<SampleOptional<int>> m1 = Optional(1); const Matcher<TypeParam> m1 = Optional(1);
const Matcher<SampleOptional<int>> m2 = Optional(Eq(2)); const Matcher<TypeParam> m2 = Optional(Eq(2));
const Matcher<SampleOptional<int>> m3 = Optional(Lt(3)); const Matcher<TypeParam> m3 = Optional(Lt(3));
SampleOptional<int> opt(1); TypeParam opt(1);
EXPECT_TRUE(m1.Matches(opt)); EXPECT_TRUE(m1.Matches(opt));
EXPECT_FALSE(m2.Matches(opt)); EXPECT_FALSE(m2.Matches(opt));
EXPECT_TRUE(m3.Matches(opt)); EXPECT_TRUE(m3.Matches(opt));
} }
TEST(OptionalTest, DoesNotMatchNullopt) { TYPED_TEST(OptionalTest, DoesNotMatchNullopt) {
const Matcher<SampleOptional<int>> m = Optional(1); const Matcher<TypeParam> m = Optional(1);
SampleOptional<int> empty; TypeParam empty;
EXPECT_FALSE(m.Matches(empty)); EXPECT_FALSE(m.Matches(empty));
} }
TEST(OptionalTest, WorksWithMoveOnly) { TYPED_TEST(OptionalTest, ComposesWithMonomorphicMatchersTakingReferences) {
Matcher<SampleOptional<std::unique_ptr<int>>> m = Optional(Eq(nullptr)); const Matcher<const int&> eq1 = Eq(1);
EXPECT_TRUE(m.Matches(SampleOptional<std::unique_ptr<int>>(nullptr))); const Matcher<const int&> eq2 = Eq(2);
TypeParam opt(1);
EXPECT_THAT(opt, Optional(eq1));
EXPECT_THAT(opt, Optional(Not(eq2)));
EXPECT_THAT(opt, Optional(AllOf(eq1, Not(eq2))));
} }
TYPED_TEST(OptionalTest, ComposesWithMonomorphicMatchersRequiringConversion) {
const Matcher<int64_t> eq1 = Eq(1);
const Matcher<int64_t> eq2 = Eq(2);
TypeParam opt(1);
EXPECT_THAT(opt, Optional(eq1));
EXPECT_THAT(opt, Optional(Not(eq2)));
EXPECT_THAT(opt, Optional(AllOf(eq1, Not(eq2))));
}
template <typename T>
class MoveOnlyOptionalTest : public testing::Test {};
using MoveOnlyOptionalTestTypes =
testing::Types<SampleOptional<std::unique_ptr<int>>,
SampleOptionalWithoutBoolConversion<std::unique_ptr<int>>>;
TYPED_TEST_SUITE(MoveOnlyOptionalTest, MoveOnlyOptionalTestTypes);
TYPED_TEST(MoveOnlyOptionalTest, WorksWithMoveOnly) {
Matcher<TypeParam> m = Optional(Eq(nullptr));
EXPECT_TRUE(m.Matches(TypeParam(nullptr)));
}
#endif // GTEST_HAS_TYPED_TEST
class SampleVariantIntString { class SampleVariantIntString {
public: public:
SampleVariantIntString(int i) : i_(i), has_int_(true) {} SampleVariantIntString(int i) : i_(i), has_int_(true) {}
@ -1576,10 +1635,10 @@ TEST_P(AnyOfArrayTestP, ExplainsMatchResultCorrectly) {
const Matcher<int> m1 = AnyOfArray(v1); const Matcher<int> m1 = AnyOfArray(v1);
const Matcher<int> m2 = AnyOfArray(v2); const Matcher<int> m2 = AnyOfArray(v2);
EXPECT_EQ("", Explain(m0, 0)); EXPECT_EQ("", Explain(m0, 0));
EXPECT_EQ("", Explain(m1, 1)); EXPECT_EQ("which matches (is equal to 1)", Explain(m1, 1));
EXPECT_EQ("", Explain(m1, 2)); EXPECT_EQ("isn't equal to 1", Explain(m1, 2));
EXPECT_EQ("", Explain(m2, 3)); EXPECT_EQ("which matches (is equal to 3)", Explain(m2, 3));
EXPECT_EQ("", Explain(m2, 4)); EXPECT_EQ("isn't equal to 2, and isn't equal to 3", Explain(m2, 4));
EXPECT_EQ("()", Describe(m0)); EXPECT_EQ("()", Describe(m0));
EXPECT_EQ("(is equal to 1)", Describe(m1)); EXPECT_EQ("(is equal to 1)", Describe(m1));
EXPECT_EQ("(is equal to 2) or (is equal to 3)", Describe(m2)); EXPECT_EQ("(is equal to 2) or (is equal to 3)", Describe(m2));

View File

@ -59,6 +59,7 @@ using testing::Invoke;
using testing::ReturnArg; using testing::ReturnArg;
using testing::ReturnPointee; using testing::ReturnPointee;
using testing::SaveArg; using testing::SaveArg;
using testing::SaveArgByMove;
using testing::SaveArgPointee; using testing::SaveArgPointee;
using testing::SetArgReferee; using testing::SetArgReferee;
using testing::Unused; using testing::Unused;
@ -492,6 +493,34 @@ TEST(SaveArgActionTest, WorksForCompatibleType) {
EXPECT_EQ('a', result); EXPECT_EQ('a', result);
} }
struct MoveOnly {
explicit MoveOnly(int v) : i(v) {}
MoveOnly(MoveOnly&& o) {
i = o.i;
o.i = -1;
}
MoveOnly& operator=(MoveOnly&& o) {
i = o.i;
o.i = -1;
return *this;
}
int i;
};
TEST(SaveArgByMoveActionTest, WorksForSameType) {
MoveOnly result{0};
const Action<void(MoveOnly v)> a1 = SaveArgByMove<0>(&result);
a1.Perform(std::make_tuple(MoveOnly{5}));
EXPECT_EQ(5, result.i);
}
TEST(SaveArgByMoveActionTest, WorksForCompatibleType) {
MoveOnly result{0};
const Action<void(bool, MoveOnly)> a1 = SaveArgByMove<1>(&result);
a1.Perform(std::make_tuple(true, MoveOnly{7}));
EXPECT_EQ(7, result.i);
}
TEST(SaveArgPointeeActionTest, WorksForSameType) { TEST(SaveArgPointeeActionTest, WorksForSameType) {
int result = 0; int result = 0;
const int value = 5; const int value = 5;
@ -756,34 +785,34 @@ TEST(InvokeArgumentTest, Functor6) {
// Tests using InvokeArgument with a 7-ary function. // Tests using InvokeArgument with a 7-ary function.
TEST(InvokeArgumentTest, Function7) { TEST(InvokeArgumentTest, Function7) {
Action<std::string(std::string(*)(const char*, const char*, const char*, Action<std::string(std::string (*)(const char*, const char*, const char*,
const char*, const char*, const char*, const char*, const char*, const char*,
const char*))> const char*))>
a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7"); a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7");
EXPECT_EQ("1234567", a.Perform(std::make_tuple(&Concat7))); EXPECT_EQ("1234567", a.Perform(std::make_tuple(&Concat7)));
} }
// Tests using InvokeArgument with a 8-ary function. // Tests using InvokeArgument with a 8-ary function.
TEST(InvokeArgumentTest, Function8) { TEST(InvokeArgumentTest, Function8) {
Action<std::string(std::string(*)(const char*, const char*, const char*, Action<std::string(std::string (*)(const char*, const char*, const char*,
const char*, const char*, const char*, const char*, const char*, const char*,
const char*, const char*))> const char*, const char*))>
a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8"); a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8");
EXPECT_EQ("12345678", a.Perform(std::make_tuple(&Concat8))); EXPECT_EQ("12345678", a.Perform(std::make_tuple(&Concat8)));
} }
// Tests using InvokeArgument with a 9-ary function. // Tests using InvokeArgument with a 9-ary function.
TEST(InvokeArgumentTest, Function9) { TEST(InvokeArgumentTest, Function9) {
Action<std::string(std::string(*)(const char*, const char*, const char*, Action<std::string(std::string (*)(const char*, const char*, const char*,
const char*, const char*, const char*, const char*, const char*, const char*,
const char*, const char*, const char*))> const char*, const char*, const char*))>
a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8", "9"); a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8", "9");
EXPECT_EQ("123456789", a.Perform(std::make_tuple(&Concat9))); EXPECT_EQ("123456789", a.Perform(std::make_tuple(&Concat9)));
} }
// Tests using InvokeArgument with a 10-ary function. // Tests using InvokeArgument with a 10-ary function.
TEST(InvokeArgumentTest, Function10) { TEST(InvokeArgumentTest, Function10) {
Action<std::string(std::string(*)( Action<std::string(std::string (*)(
const char*, const char*, const char*, const char*, const char*, const char*, const char*, const char*, const char*, const char*,
const char*, const char*, const char*, const char*, const char*))> const char*, const char*, const char*, const char*, const char*))>
a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8", "9", "0"); a = InvokeArgument<0>("1", "2", "3", "4", "5", "6", "7", "8", "9", "0");

View File

@ -70,7 +70,7 @@ static_assert(GMOCK_PP_INTERNAL_VAR_TEST(x, y) == 2, "");
static_assert(GMOCK_PP_INTERNAL_VAR_TEST(silly) == 1, ""); static_assert(GMOCK_PP_INTERNAL_VAR_TEST(silly) == 1, "");
static_assert(GMOCK_PP_INTERNAL_VAR_TEST(x, y, z) == 3, ""); static_assert(GMOCK_PP_INTERNAL_VAR_TEST(x, y, z) == 3, "");
// TODO(iserna): The following asserts fail in --config=lexan. // TODO(iserna): The following asserts fail in --config=windows.
#define GMOCK_PP_INTERNAL_IS_EMPTY_TEST_1 #define GMOCK_PP_INTERNAL_IS_EMPTY_TEST_1
static_assert(GMOCK_PP_IS_EMPTY(GMOCK_PP_INTERNAL_IS_EMPTY_TEST_1), ""); static_assert(GMOCK_PP_IS_EMPTY(GMOCK_PP_INTERNAL_IS_EMPTY_TEST_1), "");
static_assert(GMOCK_PP_IS_EMPTY(), ""); static_assert(GMOCK_PP_IS_EMPTY(), "");

View File

@ -804,9 +804,8 @@ TEST(ExpectCallTest, InfersCardinality1WhenThereIsWillRepeatedly) {
"to be called at least once"); "to be called at least once");
} }
#if defined(GTEST_INTERNAL_CPLUSPLUS_LANG) && \ // TODO(b/396121064) - Fix this test under MSVC
GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L #ifndef _MSC_VER
// It should be possible to return a non-moveable type from a mock action in // It should be possible to return a non-moveable type from a mock action in
// C++17 and above, where it's guaranteed that such a type can be initialized // C++17 and above, where it's guaranteed that such a type can be initialized
// from a prvalue returned from a function. // from a prvalue returned from a function.
@ -847,7 +846,7 @@ TEST(ExpectCallTest, NonMoveableType) {
EXPECT_EQ(17, mock.AsStdFunction()().x); EXPECT_EQ(17, mock.AsStdFunction()().x);
} }
#endif // C++17 and above #endif // _MSC_VER
// Tests that the n-th action is taken for the n-th matching // Tests that the n-th action is taken for the n-th matching
// invocation. // invocation.

View File

@ -186,8 +186,8 @@ using testing::SetErrnoAndReturn;
#endif #endif
#if GTEST_HAS_EXCEPTIONS #if GTEST_HAS_EXCEPTIONS
using testing::Throw;
using testing::Rethrow; using testing::Rethrow;
using testing::Throw;
#endif #endif
using testing::ContainsRegex; using testing::ContainsRegex;

View File

@ -25,7 +25,7 @@ When building GoogleTest as a standalone project, the typical workflow starts
with with
``` ```
git clone https://github.com/google/googletest.git -b v1.15.0 git clone https://github.com/google/googletest.git -b v1.16.0
cd googletest # Main directory of the cloned repository. cd googletest # Main directory of the cloned repository.
mkdir build # Create a directory to hold the build output. mkdir build # Create a directory to hold the build output.
cd build cd build

View File

@ -195,7 +195,7 @@ function(cxx_library_with_type name type cxx_flags)
target_link_libraries(${name} PUBLIC Threads::Threads) target_link_libraries(${name} PUBLIC Threads::Threads)
endif() endif()
target_compile_features(${name} PUBLIC cxx_std_14) target_compile_features(${name} PUBLIC cxx_std_17)
endfunction() endfunction()
######################################################################## ########################################################################

View File

@ -67,10 +67,10 @@ namespace testing {
// To implement a matcher Foo for type T, define: // To implement a matcher Foo for type T, define:
// 1. a class FooMatcherMatcher that implements the matcher interface: // 1. a class FooMatcherMatcher that implements the matcher interface:
// using is_gtest_matcher = void; // using is_gtest_matcher = void;
// bool MatchAndExplain(const T&, std::ostream*); // bool MatchAndExplain(const T&, std::ostream*) const;
// (MatchResultListener* can also be used instead of std::ostream*) // (MatchResultListener* can also be used instead of std::ostream*)
// void DescribeTo(std::ostream*); // void DescribeTo(std::ostream*) const;
// void DescribeNegationTo(std::ostream*); // void DescribeNegationTo(std::ostream*) const;
// //
// 2. a factory function that creates a Matcher<T> object from a // 2. a factory function that creates a Matcher<T> object from a
// FooMatcherMatcher. // FooMatcherMatcher.

View File

@ -126,6 +126,10 @@
#include <span> // NOLINT #include <span> // NOLINT
#endif // GTEST_INTERNAL_HAS_STD_SPAN #endif // GTEST_INTERNAL_HAS_STD_SPAN
#if GTEST_INTERNAL_HAS_COMPARE_LIB
#include <compare> // NOLINT
#endif // GTEST_INTERNAL_HAS_COMPARE_LIB
namespace testing { namespace testing {
// Definitions in the internal* namespaces are subject to change without notice. // Definitions in the internal* namespaces are subject to change without notice.
@ -782,6 +786,41 @@ void PrintTo(const std::shared_ptr<T>& ptr, std::ostream* os) {
(PrintSmartPointer<T>)(ptr, os, 0); (PrintSmartPointer<T>)(ptr, os, 0);
} }
#if GTEST_INTERNAL_HAS_COMPARE_LIB
template <typename T>
void PrintOrderingHelper(T ordering, std::ostream* os) {
if (ordering == T::less) {
*os << "(less)";
} else if (ordering == T::greater) {
*os << "(greater)";
} else if (ordering == T::equivalent) {
*os << "(equivalent)";
} else {
*os << "(unknown ordering)";
}
}
inline void PrintTo(std::strong_ordering ordering, std::ostream* os) {
if (ordering == std::strong_ordering::equal) {
*os << "(equal)";
} else {
PrintOrderingHelper(ordering, os);
}
}
inline void PrintTo(std::partial_ordering ordering, std::ostream* os) {
if (ordering == std::partial_ordering::unordered) {
*os << "(unordered)";
} else {
PrintOrderingHelper(ordering, os);
}
}
inline void PrintTo(std::weak_ordering ordering, std::ostream* os) {
PrintOrderingHelper(ordering, os);
}
#endif
// Helper function for printing a tuple. T must be instantiated with // Helper function for printing a tuple. T must be instantiated with
// a tuple type. // a tuple type.
template <typename T> template <typename T>

View File

@ -275,8 +275,8 @@
#endif #endif
#if !defined(GTEST_INTERNAL_CPLUSPLUS_LANG) || \ #if !defined(GTEST_INTERNAL_CPLUSPLUS_LANG) || \
GTEST_INTERNAL_CPLUSPLUS_LANG < 201402L GTEST_INTERNAL_CPLUSPLUS_LANG < 201703L
#error C++ versions less than C++14 are not supported. #error C++ versions less than C++17 are not supported.
#endif #endif
// MSVC >= 19.11 (VS 2017 Update 3) supports __has_include. // MSVC >= 19.11 (VS 2017 Update 3) supports __has_include.
@ -2533,4 +2533,12 @@ using Variant = ::std::variant<T...>;
#define GTEST_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL 1 #define GTEST_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL 1
#endif #endif
#if (defined(__cpp_lib_three_way_comparison) || \
(GTEST_INTERNAL_HAS_INCLUDE(<compare>) && \
GTEST_INTERNAL_CPLUSPLUS_LANG >= 201907L))
#define GTEST_INTERNAL_HAS_COMPARE_LIB 1
#else
#define GTEST_INTERNAL_HAS_COMPARE_LIB 0
#endif
#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ #endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_

View File

@ -1660,10 +1660,25 @@ std::string GetBoolAssertionFailureMessage(
return msg.GetString(); return msg.GetString();
} }
// Helper function for implementing ASSERT_NEAR. // Helper function for implementing ASSERT_NEAR. Treats infinity as a specific
// value, such that comparing infinity to infinity is equal, the distance
// between -infinity and +infinity is infinity, and infinity <= infinity is
// true.
AssertionResult DoubleNearPredFormat(const char* expr1, const char* expr2, AssertionResult DoubleNearPredFormat(const char* expr1, const char* expr2,
const char* abs_error_expr, double val1, const char* abs_error_expr, double val1,
double val2, double abs_error) { double val2, double abs_error) {
// We want to return success when the two values are infinity and at least
// one of the following is true:
// * The values are the same-signed infinity.
// * The error limit itself is infinity.
// This is done here so that we don't end up with a NaN when calculating the
// difference in values.
if (std::isinf(val1) && std::isinf(val2) &&
(std::signbit(val1) == std::signbit(val2) ||
(abs_error > 0.0 && std::isinf(abs_error)))) {
return AssertionSuccess();
}
const double diff = fabs(val1 - val2); const double diff = fabs(val1 - val2);
if (diff <= abs_error) return AssertionSuccess(); if (diff <= abs_error) return AssertionSuccess();
@ -3974,6 +3989,12 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
static void OutputXmlTestSuiteForTestResult(::std::ostream* stream, static void OutputXmlTestSuiteForTestResult(::std::ostream* stream,
const TestResult& result); const TestResult& result);
// Streams a test case XML stanza containing the given test result.
//
// Requires: result.Failed()
static void OutputXmlTestCaseForTestResult(::std::ostream* stream,
const TestResult& result);
// Streams an XML representation of a TestResult object. // Streams an XML representation of a TestResult object.
static void OutputXmlTestResult(::std::ostream* stream, static void OutputXmlTestResult(::std::ostream* stream,
const TestResult& result); const TestResult& result);
@ -3991,16 +4012,11 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
static void PrintXmlUnitTest(::std::ostream* stream, static void PrintXmlUnitTest(::std::ostream* stream,
const UnitTest& unit_test); const UnitTest& unit_test);
// Produces a string representing the test properties in a result as space
// delimited XML attributes based on the property key="value" pairs.
// When the std::string is not empty, it includes a space at the beginning,
// to delimit this attribute from prior attributes.
static std::string TestPropertiesAsXmlAttributes(const TestResult& result);
// Streams an XML representation of the test properties of a TestResult // Streams an XML representation of the test properties of a TestResult
// object. // object.
static void OutputXmlTestProperties(std::ostream* stream, static void OutputXmlTestProperties(std::ostream* stream,
const TestResult& result); const TestResult& result,
const std::string& indent);
// The output file. // The output file.
const std::string output_file_; const std::string output_file_;
@ -4221,6 +4237,15 @@ void XmlUnitTestResultPrinter::OutputXmlTestSuiteForTestResult(
FormatEpochTimeInMillisAsIso8601(result.start_timestamp())); FormatEpochTimeInMillisAsIso8601(result.start_timestamp()));
*stream << ">"; *stream << ">";
OutputXmlTestCaseForTestResult(stream, result);
// Complete the test suite.
*stream << " </testsuite>\n";
}
// Streams a test case XML stanza containing the given test result.
void XmlUnitTestResultPrinter::OutputXmlTestCaseForTestResult(
::std::ostream* stream, const TestResult& result) {
// Output the boilerplate for a minimal test case with a single test. // Output the boilerplate for a minimal test case with a single test.
*stream << " <testcase"; *stream << " <testcase";
OutputXmlAttribute(stream, "testcase", "name", ""); OutputXmlAttribute(stream, "testcase", "name", "");
@ -4235,9 +4260,6 @@ void XmlUnitTestResultPrinter::OutputXmlTestSuiteForTestResult(
// Output the actual test result. // Output the actual test result.
OutputXmlTestResult(stream, result); OutputXmlTestResult(stream, result);
// Complete the test suite.
*stream << " </testsuite>\n";
} }
// Prints an XML representation of a TestInfo object. // Prints an XML representation of a TestInfo object.
@ -4328,7 +4350,7 @@ void XmlUnitTestResultPrinter::OutputXmlTestResult(::std::ostream* stream,
if (failures == 0 && skips == 0) { if (failures == 0 && skips == 0) {
*stream << ">\n"; *stream << ">\n";
} }
OutputXmlTestProperties(stream, result); OutputXmlTestProperties(stream, result, /*indent=*/" ");
*stream << " </testcase>\n"; *stream << " </testcase>\n";
} }
} }
@ -4357,13 +4379,18 @@ void XmlUnitTestResultPrinter::PrintXmlTestSuite(std::ostream* stream,
OutputXmlAttribute( OutputXmlAttribute(
stream, kTestsuite, "timestamp", stream, kTestsuite, "timestamp",
FormatEpochTimeInMillisAsIso8601(test_suite.start_timestamp())); FormatEpochTimeInMillisAsIso8601(test_suite.start_timestamp()));
*stream << TestPropertiesAsXmlAttributes(test_suite.ad_hoc_test_result());
} }
*stream << ">\n"; *stream << ">\n";
OutputXmlTestProperties(stream, test_suite.ad_hoc_test_result(),
/*indent=*/" ");
for (int i = 0; i < test_suite.total_test_count(); ++i) { for (int i = 0; i < test_suite.total_test_count(); ++i) {
if (test_suite.GetTestInfo(i)->is_reportable()) if (test_suite.GetTestInfo(i)->is_reportable())
OutputXmlTestInfo(stream, test_suite.name(), *test_suite.GetTestInfo(i)); OutputXmlTestInfo(stream, test_suite.name(), *test_suite.GetTestInfo(i));
} }
if (test_suite.ad_hoc_test_result().Failed()) {
OutputXmlTestCaseForTestResult(stream, test_suite.ad_hoc_test_result());
}
*stream << " </" << kTestsuite << ">\n"; *stream << " </" << kTestsuite << ">\n";
} }
@ -4393,11 +4420,12 @@ void XmlUnitTestResultPrinter::PrintXmlUnitTest(std::ostream* stream,
OutputXmlAttribute(stream, kTestsuites, "random_seed", OutputXmlAttribute(stream, kTestsuites, "random_seed",
StreamableToString(unit_test.random_seed())); StreamableToString(unit_test.random_seed()));
} }
*stream << TestPropertiesAsXmlAttributes(unit_test.ad_hoc_test_result());
OutputXmlAttribute(stream, kTestsuites, "name", "AllTests"); OutputXmlAttribute(stream, kTestsuites, "name", "AllTests");
*stream << ">\n"; *stream << ">\n";
OutputXmlTestProperties(stream, unit_test.ad_hoc_test_result(),
/*indent=*/" ");
for (int i = 0; i < unit_test.total_test_suite_count(); ++i) { for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
if (unit_test.GetTestSuite(i)->reportable_test_count() > 0) if (unit_test.GetTestSuite(i)->reportable_test_count() > 0)
PrintXmlTestSuite(stream, *unit_test.GetTestSuite(i)); PrintXmlTestSuite(stream, *unit_test.GetTestSuite(i));
@ -4434,21 +4462,8 @@ void XmlUnitTestResultPrinter::PrintXmlTestsList(
*stream << "</" << kTestsuites << ">\n"; *stream << "</" << kTestsuites << ">\n";
} }
// Produces a string representing the test properties in a result as space
// delimited XML attributes based on the property key="value" pairs.
std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
const TestResult& result) {
Message attributes;
for (int i = 0; i < result.test_property_count(); ++i) {
const TestProperty& property = result.GetTestProperty(i);
attributes << " " << property.key() << "=" << "\""
<< EscapeXmlAttribute(property.value()) << "\"";
}
return attributes.GetString();
}
void XmlUnitTestResultPrinter::OutputXmlTestProperties( void XmlUnitTestResultPrinter::OutputXmlTestProperties(
std::ostream* stream, const TestResult& result) { std::ostream* stream, const TestResult& result, const std::string& indent) {
const std::string kProperties = "properties"; const std::string kProperties = "properties";
const std::string kProperty = "property"; const std::string kProperty = "property";
@ -4456,15 +4471,15 @@ void XmlUnitTestResultPrinter::OutputXmlTestProperties(
return; return;
} }
*stream << " <" << kProperties << ">\n"; *stream << indent << "<" << kProperties << ">\n";
for (int i = 0; i < result.test_property_count(); ++i) { for (int i = 0; i < result.test_property_count(); ++i) {
const TestProperty& property = result.GetTestProperty(i); const TestProperty& property = result.GetTestProperty(i);
*stream << " <" << kProperty; *stream << indent << " <" << kProperty;
*stream << " name=\"" << EscapeXmlAttribute(property.key()) << "\""; *stream << " name=\"" << EscapeXmlAttribute(property.key()) << "\"";
*stream << " value=\"" << EscapeXmlAttribute(property.value()) << "\""; *stream << " value=\"" << EscapeXmlAttribute(property.value()) << "\"";
*stream << "/>\n"; *stream << "/>\n";
} }
*stream << " </" << kProperties << ">\n"; *stream << indent << "</" << kProperties << ">\n";
} }
// End XmlUnitTestResultPrinter // End XmlUnitTestResultPrinter
@ -4503,6 +4518,12 @@ class JsonUnitTestResultPrinter : public EmptyTestEventListener {
static void OutputJsonTestSuiteForTestResult(::std::ostream* stream, static void OutputJsonTestSuiteForTestResult(::std::ostream* stream,
const TestResult& result); const TestResult& result);
// Streams a test case JSON stanza containing the given test result.
//
// Requires: result.Failed()
static void OutputJsonTestCaseForTestResult(::std::ostream* stream,
const TestResult& result);
// Streams a JSON representation of a TestResult object. // Streams a JSON representation of a TestResult object.
static void OutputJsonTestResult(::std::ostream* stream, static void OutputJsonTestResult(::std::ostream* stream,
const TestResult& result); const TestResult& result);
@ -4673,6 +4694,15 @@ void JsonUnitTestResultPrinter::OutputJsonTestSuiteForTestResult(
} }
*stream << Indent(6) << "\"testsuite\": [\n"; *stream << Indent(6) << "\"testsuite\": [\n";
OutputJsonTestCaseForTestResult(stream, result);
// Finish the test suite.
*stream << "\n" << Indent(6) << "]\n" << Indent(4) << "}";
}
// Streams a test case JSON stanza containing the given test result.
void JsonUnitTestResultPrinter::OutputJsonTestCaseForTestResult(
::std::ostream* stream, const TestResult& result) {
// Output the boilerplate for a new test case. // Output the boilerplate for a new test case.
*stream << Indent(8) << "{\n"; *stream << Indent(8) << "{\n";
OutputJsonKey(stream, "testcase", "name", "", Indent(10)); OutputJsonKey(stream, "testcase", "name", "", Indent(10));
@ -4689,9 +4719,6 @@ void JsonUnitTestResultPrinter::OutputJsonTestSuiteForTestResult(
// Output the actual test result. // Output the actual test result.
OutputJsonTestResult(stream, result); OutputJsonTestResult(stream, result);
// Finish the test suite.
*stream << "\n" << Indent(6) << "]\n" << Indent(4) << "}";
} }
// Prints a JSON representation of a TestInfo object. // Prints a JSON representation of a TestInfo object.
@ -4836,6 +4863,16 @@ void JsonUnitTestResultPrinter::PrintJsonTestSuite(
OutputJsonTestInfo(stream, test_suite.name(), *test_suite.GetTestInfo(i)); OutputJsonTestInfo(stream, test_suite.name(), *test_suite.GetTestInfo(i));
} }
} }
// If there was a failure in the test suite setup or teardown include that in
// the output.
if (test_suite.ad_hoc_test_result().Failed()) {
if (comma) {
*stream << ",\n";
}
OutputJsonTestCaseForTestResult(stream, test_suite.ad_hoc_test_result());
}
*stream << "\n" << kIndent << "]\n" << Indent(4) << "}"; *stream << "\n" << kIndent << "]\n" << Indent(4) << "}";
} }

View File

@ -45,7 +45,6 @@ cc_test(
"gtest-*.cc", "gtest-*.cc",
"googletest-*.cc", "googletest-*.cc",
"*.h", "*.h",
"googletest/include/gtest/**/*.h",
], ],
exclude = [ exclude = [
"gtest-unittest-api_test.cc", "gtest-unittest-api_test.cc",

View File

@ -57,7 +57,7 @@ else:
STACK_TRACE_TEMPLATE = '\n' STACK_TRACE_TEMPLATE = '\n'
EXPECTED_NON_EMPTY = { EXPECTED_NON_EMPTY = {
'tests': 26, 'tests': 28,
'failures': 5, 'failures': 5,
'disabled': 2, 'disabled': 2,
'errors': 0, 'errors': 0,
@ -323,12 +323,14 @@ EXPECTED_NON_EMPTY = {
'time': '*', 'time': '*',
'timestamp': '*', 'timestamp': '*',
'SetUpTestSuite': 'yes', 'SetUpTestSuite': 'yes',
'SetUpTestSuite (with whitespace)': 'yes and yes',
'TearDownTestSuite': 'aye', 'TearDownTestSuite': 'aye',
'TearDownTestSuite (with whitespace)': 'aye and aye',
'testsuite': [ 'testsuite': [
{ {
'name': 'OneProperty', 'name': 'OneProperty',
'file': 'gtest_xml_output_unittest_.cc', 'file': 'gtest_xml_output_unittest_.cc',
'line': 121, 'line': 125,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -339,7 +341,7 @@ EXPECTED_NON_EMPTY = {
{ {
'name': 'IntValuedProperty', 'name': 'IntValuedProperty',
'file': 'gtest_xml_output_unittest_.cc', 'file': 'gtest_xml_output_unittest_.cc',
'line': 125, 'line': 129,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -350,7 +352,7 @@ EXPECTED_NON_EMPTY = {
{ {
'name': 'ThreeProperties', 'name': 'ThreeProperties',
'file': 'gtest_xml_output_unittest_.cc', 'file': 'gtest_xml_output_unittest_.cc',
'line': 129, 'line': 133,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -363,7 +365,7 @@ EXPECTED_NON_EMPTY = {
{ {
'name': 'TwoValuesForOneKeyUsesLastValue', 'name': 'TwoValuesForOneKeyUsesLastValue',
'file': 'gtest_xml_output_unittest_.cc', 'file': 'gtest_xml_output_unittest_.cc',
'line': 135, 'line': 139,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -385,7 +387,7 @@ EXPECTED_NON_EMPTY = {
{ {
'name': 'RecordProperty', 'name': 'RecordProperty',
'file': 'gtest_xml_output_unittest_.cc', 'file': 'gtest_xml_output_unittest_.cc',
'line': 140, 'line': 144,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -396,7 +398,7 @@ EXPECTED_NON_EMPTY = {
{ {
'name': 'ExternalUtilityThatCallsRecordIntValuedProperty', 'name': 'ExternalUtilityThatCallsRecordIntValuedProperty',
'file': 'gtest_xml_output_unittest_.cc', 'file': 'gtest_xml_output_unittest_.cc',
'line': 153, 'line': 157,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -409,7 +411,7 @@ EXPECTED_NON_EMPTY = {
'ExternalUtilityThatCallsRecordStringValuedProperty' 'ExternalUtilityThatCallsRecordStringValuedProperty'
), ),
'file': 'gtest_xml_output_unittest_.cc', 'file': 'gtest_xml_output_unittest_.cc',
'line': 157, 'line': 161,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -419,6 +421,83 @@ EXPECTED_NON_EMPTY = {
}, },
], ],
}, },
{
'name': 'SetupFailTest',
'tests': 1,
'failures': 0,
'disabled': 0,
'errors': 0,
'time': '*',
'timestamp': '*',
'testsuite': [
{
'name': 'NoopPassingTest',
'file': 'gtest_xml_output_unittest_.cc',
'line': 172,
'status': 'RUN',
'result': 'SKIPPED',
'timestamp': '*',
'time': '*',
'classname': 'SetupFailTest',
'skipped': [
{'message': 'gtest_xml_output_unittest_.cc:*\n'}
],
},
{
'name': '',
'status': 'RUN',
'result': 'COMPLETED',
'timestamp': '*',
'time': '*',
'classname': '',
'failures': [{
'failure': (
'gtest_xml_output_unittest_.cc:*\nExpected equality'
' of these values:\n 1\n 2'
+ STACK_TRACE_TEMPLATE
),
'type': '',
}],
},
],
},
{
'name': 'TearDownFailTest',
'tests': 1,
'failures': 0,
'disabled': 0,
'errors': 0,
'timestamp': '*',
'time': '*',
'testsuite': [
{
'name': 'NoopPassingTest',
'file': 'gtest_xml_output_unittest_.cc',
'line': 179,
'status': 'RUN',
'result': 'COMPLETED',
'timestamp': '*',
'time': '*',
'classname': 'TearDownFailTest',
},
{
'name': '',
'status': 'RUN',
'result': 'COMPLETED',
'timestamp': '*',
'time': '*',
'classname': '',
'failures': [{
'failure': (
'gtest_xml_output_unittest_.cc:*\nExpected equality'
' of these values:\n 1\n 2'
+ STACK_TRACE_TEMPLATE
),
'type': '',
}],
},
],
},
{ {
'name': 'TypedTest/0', 'name': 'TypedTest/0',
'tests': 1, 'tests': 1,
@ -431,7 +510,7 @@ EXPECTED_NON_EMPTY = {
'name': 'HasTypeParamAttribute', 'name': 'HasTypeParamAttribute',
'type_param': 'int', 'type_param': 'int',
'file': 'gtest_xml_output_unittest_.cc', 'file': 'gtest_xml_output_unittest_.cc',
'line': 173, 'line': 193,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -451,7 +530,7 @@ EXPECTED_NON_EMPTY = {
'name': 'HasTypeParamAttribute', 'name': 'HasTypeParamAttribute',
'type_param': 'long', 'type_param': 'long',
'file': 'gtest_xml_output_unittest_.cc', 'file': 'gtest_xml_output_unittest_.cc',
'line': 173, 'line': 193,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -471,7 +550,7 @@ EXPECTED_NON_EMPTY = {
'name': 'HasTypeParamAttribute', 'name': 'HasTypeParamAttribute',
'type_param': 'int', 'type_param': 'int',
'file': 'gtest_xml_output_unittest_.cc', 'file': 'gtest_xml_output_unittest_.cc',
'line': 180, 'line': 200,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -491,7 +570,7 @@ EXPECTED_NON_EMPTY = {
'name': 'HasTypeParamAttribute', 'name': 'HasTypeParamAttribute',
'type_param': 'long', 'type_param': 'long',
'file': 'gtest_xml_output_unittest_.cc', 'file': 'gtest_xml_output_unittest_.cc',
'line': 180, 'line': 200,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -512,7 +591,7 @@ EXPECTED_NON_EMPTY = {
'name': 'HasValueParamAttribute/0', 'name': 'HasValueParamAttribute/0',
'value_param': '33', 'value_param': '33',
'file': 'gtest_xml_output_unittest_.cc', 'file': 'gtest_xml_output_unittest_.cc',
'line': 164, 'line': 184,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -523,7 +602,7 @@ EXPECTED_NON_EMPTY = {
'name': 'HasValueParamAttribute/1', 'name': 'HasValueParamAttribute/1',
'value_param': '42', 'value_param': '42',
'file': 'gtest_xml_output_unittest_.cc', 'file': 'gtest_xml_output_unittest_.cc',
'line': 164, 'line': 184,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -534,7 +613,7 @@ EXPECTED_NON_EMPTY = {
'name': 'AnotherTestThatHasValueParamAttribute/0', 'name': 'AnotherTestThatHasValueParamAttribute/0',
'value_param': '33', 'value_param': '33',
'file': 'gtest_xml_output_unittest_.cc', 'file': 'gtest_xml_output_unittest_.cc',
'line': 165, 'line': 185,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -545,7 +624,7 @@ EXPECTED_NON_EMPTY = {
'name': 'AnotherTestThatHasValueParamAttribute/1', 'name': 'AnotherTestThatHasValueParamAttribute/1',
'value_param': '42', 'value_param': '42',
'file': 'gtest_xml_output_unittest_.cc', 'file': 'gtest_xml_output_unittest_.cc',
'line': 165, 'line': 185,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',

View File

@ -64,6 +64,10 @@
#include <span> // NOLINT #include <span> // NOLINT
#endif // GTEST_INTERNAL_HAS_STD_SPAN #endif // GTEST_INTERNAL_HAS_STD_SPAN
#if GTEST_INTERNAL_HAS_COMPARE_LIB
#include <compare> // NOLINT
#endif // GTEST_INTERNAL_HAS_COMPARE_LIB
// Some user-defined types for testing the universal value printer. // Some user-defined types for testing the universal value printer.
// An anonymous enum type. // An anonymous enum type.
@ -117,6 +121,9 @@ class UnprintableTemplateInGlobal {
// A user-defined streamable type in the global namespace. // A user-defined streamable type in the global namespace.
class StreamableInGlobal { class StreamableInGlobal {
public: public:
StreamableInGlobal() = default;
StreamableInGlobal(const StreamableInGlobal&) = default;
StreamableInGlobal& operator=(const StreamableInGlobal&) = default;
virtual ~StreamableInGlobal() = default; virtual ~StreamableInGlobal() = default;
}; };
@ -568,6 +575,8 @@ TEST(PrintU8StringTest, Null) {
} }
// Tests that u8 strings are escaped properly. // Tests that u8 strings are escaped properly.
// TODO(b/396121064) - Fix this test under MSVC
#ifndef _MSC_VER
TEST(PrintU8StringTest, EscapesProperly) { TEST(PrintU8StringTest, EscapesProperly) {
const char8_t* p = u8"'\"?\\\a\b\f\n\r\t\v\x7F\xFF hello 世界"; const char8_t* p = u8"'\"?\\\a\b\f\n\r\t\v\x7F\xFF hello 世界";
EXPECT_EQ(PrintPointer(p) + EXPECT_EQ(PrintPointer(p) +
@ -575,7 +584,8 @@ TEST(PrintU8StringTest, EscapesProperly) {
"hello \\xE4\\xB8\\x96\\xE7\\x95\\x8C\"", "hello \\xE4\\xB8\\x96\\xE7\\x95\\x8C\"",
Print(p)); Print(p));
} }
#endif #endif // _MSC_VER
#endif // __cpp_lib_char8_t
// const char16_t*. // const char16_t*.
TEST(PrintU16StringTest, Const) { TEST(PrintU16StringTest, Const) {
@ -1970,6 +1980,26 @@ TEST(PrintOneofTest, Basic) {
PrintToString(Type(NonPrintable{}))); PrintToString(Type(NonPrintable{})));
} }
#endif // GTEST_INTERNAL_HAS_VARIANT #endif // GTEST_INTERNAL_HAS_VARIANT
#if GTEST_INTERNAL_HAS_COMPARE_LIB
TEST(PrintOrderingTest, Basic) {
EXPECT_EQ("(less)", PrintToString(std::strong_ordering::less));
EXPECT_EQ("(greater)", PrintToString(std::strong_ordering::greater));
// equal == equivalent for strong_ordering.
EXPECT_EQ("(equal)", PrintToString(std::strong_ordering::equivalent));
EXPECT_EQ("(equal)", PrintToString(std::strong_ordering::equal));
EXPECT_EQ("(less)", PrintToString(std::weak_ordering::less));
EXPECT_EQ("(greater)", PrintToString(std::weak_ordering::greater));
EXPECT_EQ("(equivalent)", PrintToString(std::weak_ordering::equivalent));
EXPECT_EQ("(less)", PrintToString(std::partial_ordering::less));
EXPECT_EQ("(greater)", PrintToString(std::partial_ordering::greater));
EXPECT_EQ("(equivalent)", PrintToString(std::partial_ordering::equivalent));
EXPECT_EQ("(unordered)", PrintToString(std::partial_ordering::unordered));
}
#endif
namespace { namespace {
class string_ref; class string_ref;

View File

@ -31,14 +31,14 @@
class SetupFailTest : public ::testing::Test { class SetupFailTest : public ::testing::Test {
protected: protected:
static void SetUpTestSuite() { ASSERT_EQ("", "SET_UP_FAIL"); } static void SetUpTestSuite() { ASSERT_STREQ("", "SET_UP_FAIL"); }
}; };
TEST_F(SetupFailTest, NoopPassingTest) {} TEST_F(SetupFailTest, NoopPassingTest) {}
class TearDownFailTest : public ::testing::Test { class TearDownFailTest : public ::testing::Test {
protected: protected:
static void TearDownTestSuite() { ASSERT_EQ("", "TEAR_DOWN_FAIL"); } static void TearDownTestSuite() { ASSERT_STREQ("", "TEAR_DOWN_FAIL"); }
}; };
TEST_F(TearDownFailTest, NoopPassingTest) {} TEST_F(TearDownFailTest, NoopPassingTest) {}

View File

@ -2870,6 +2870,8 @@ TEST_F(FloatTest, LargeDiff) {
// This ensures that no overflow occurs when comparing numbers whose // This ensures that no overflow occurs when comparing numbers whose
// absolute value is very large. // absolute value is very large.
TEST_F(FloatTest, Infinity) { TEST_F(FloatTest, Infinity) {
EXPECT_FLOAT_EQ(values_.infinity, values_.infinity);
EXPECT_FLOAT_EQ(-values_.infinity, -values_.infinity);
EXPECT_FLOAT_EQ(values_.infinity, values_.close_to_infinity); EXPECT_FLOAT_EQ(values_.infinity, values_.close_to_infinity);
EXPECT_FLOAT_EQ(-values_.infinity, -values_.close_to_infinity); EXPECT_FLOAT_EQ(-values_.infinity, -values_.close_to_infinity);
EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(values_.infinity, -values_.infinity), EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(values_.infinity, -values_.infinity),
@ -2894,6 +2896,11 @@ TEST_F(FloatTest, NaN) {
EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(v.nan1, v.nan1), "v.nan1"); EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(v.nan1, v.nan1), "v.nan1");
EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(v.nan1, v.nan2), "v.nan2"); EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(v.nan1, v.nan2), "v.nan2");
EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(1.0, v.nan1), "v.nan1"); EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(1.0, v.nan1), "v.nan1");
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0f, v.nan1, 1.0f), "v.nan1");
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0f, v.nan1, v.infinity), "v.nan1");
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(v.infinity, v.nan1, 1.0f), "v.nan1");
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(v.infinity, v.nan1, v.infinity),
"v.nan1");
EXPECT_FATAL_FAILURE(ASSERT_FLOAT_EQ(v.nan1, v.infinity), "v.infinity"); EXPECT_FATAL_FAILURE(ASSERT_FLOAT_EQ(v.nan1, v.infinity), "v.infinity");
} }
@ -2917,11 +2924,28 @@ TEST_F(FloatTest, Commutative) {
// Tests EXPECT_NEAR. // Tests EXPECT_NEAR.
TEST_F(FloatTest, EXPECT_NEAR) { TEST_F(FloatTest, EXPECT_NEAR) {
static const FloatTest::TestValues& v = this->values_;
EXPECT_NEAR(-1.0f, -1.1f, 0.2f); EXPECT_NEAR(-1.0f, -1.1f, 0.2f);
EXPECT_NEAR(2.0f, 3.0f, 1.0f); EXPECT_NEAR(2.0f, 3.0f, 1.0f);
EXPECT_NEAR(v.infinity, v.infinity, 0.0f);
EXPECT_NEAR(-v.infinity, -v.infinity, 0.0f);
EXPECT_NEAR(0.0f, 1.0f, v.infinity);
EXPECT_NEAR(v.infinity, -v.infinity, v.infinity);
EXPECT_NEAR(-v.infinity, v.infinity, v.infinity);
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0f, 1.5f, 0.25f), // NOLINT EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0f, 1.5f, 0.25f), // NOLINT
"The difference between 1.0f and 1.5f is 0.5, " "The difference between 1.0f and 1.5f is 0.5, "
"which exceeds 0.25f"); "which exceeds 0.25f");
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(v.infinity, -v.infinity, 0.0f), // NOLINT
"The difference between v.infinity and -v.infinity "
"is inf, which exceeds 0.0f");
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(-v.infinity, v.infinity, 0.0f), // NOLINT
"The difference between -v.infinity and v.infinity "
"is inf, which exceeds 0.0f");
EXPECT_NONFATAL_FAILURE(
EXPECT_NEAR(v.infinity, v.close_to_infinity, v.further_from_infinity),
"The difference between v.infinity and v.close_to_infinity is inf, which "
"exceeds v.further_from_infinity");
} }
// Tests ASSERT_NEAR. // Tests ASSERT_NEAR.
@ -3028,6 +3052,8 @@ TEST_F(DoubleTest, LargeDiff) {
// This ensures that no overflow occurs when comparing numbers whose // This ensures that no overflow occurs when comparing numbers whose
// absolute value is very large. // absolute value is very large.
TEST_F(DoubleTest, Infinity) { TEST_F(DoubleTest, Infinity) {
EXPECT_DOUBLE_EQ(values_.infinity, values_.infinity);
EXPECT_DOUBLE_EQ(-values_.infinity, -values_.infinity);
EXPECT_DOUBLE_EQ(values_.infinity, values_.close_to_infinity); EXPECT_DOUBLE_EQ(values_.infinity, values_.close_to_infinity);
EXPECT_DOUBLE_EQ(-values_.infinity, -values_.close_to_infinity); EXPECT_DOUBLE_EQ(-values_.infinity, -values_.close_to_infinity);
EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(values_.infinity, -values_.infinity), EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(values_.infinity, -values_.infinity),
@ -3047,6 +3073,12 @@ TEST_F(DoubleTest, NaN) {
EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(v.nan1, v.nan1), "v.nan1"); EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(v.nan1, v.nan1), "v.nan1");
EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(v.nan1, v.nan2), "v.nan2"); EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(v.nan1, v.nan2), "v.nan2");
EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(1.0, v.nan1), "v.nan1"); EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(1.0, v.nan1), "v.nan1");
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0, v.nan1, 1.0), "v.nan1");
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0, v.nan1, v.infinity), "v.nan1");
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(v.infinity, v.nan1, 1.0), "v.nan1");
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(v.infinity, v.nan1, v.infinity),
"v.nan1");
EXPECT_FATAL_FAILURE(ASSERT_DOUBLE_EQ(v.nan1, v.infinity), "v.infinity"); EXPECT_FATAL_FAILURE(ASSERT_DOUBLE_EQ(v.nan1, v.infinity), "v.infinity");
} }
@ -3069,11 +3101,28 @@ TEST_F(DoubleTest, Commutative) {
// Tests EXPECT_NEAR. // Tests EXPECT_NEAR.
TEST_F(DoubleTest, EXPECT_NEAR) { TEST_F(DoubleTest, EXPECT_NEAR) {
static const DoubleTest::TestValues& v = this->values_;
EXPECT_NEAR(-1.0, -1.1, 0.2); EXPECT_NEAR(-1.0, -1.1, 0.2);
EXPECT_NEAR(2.0, 3.0, 1.0); EXPECT_NEAR(2.0, 3.0, 1.0);
EXPECT_NEAR(v.infinity, v.infinity, 0.0);
EXPECT_NEAR(-v.infinity, -v.infinity, 0.0);
EXPECT_NEAR(0.0, 1.0, v.infinity);
EXPECT_NEAR(v.infinity, -v.infinity, v.infinity);
EXPECT_NEAR(-v.infinity, v.infinity, v.infinity);
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0, 1.5, 0.25), // NOLINT EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0, 1.5, 0.25), // NOLINT
"The difference between 1.0 and 1.5 is 0.5, " "The difference between 1.0 and 1.5 is 0.5, "
"which exceeds 0.25"); "which exceeds 0.25");
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(v.infinity, -v.infinity, 0.0),
"The difference between v.infinity and -v.infinity "
"is inf, which exceeds 0.0");
EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(-v.infinity, v.infinity, 0.0),
"The difference between -v.infinity and v.infinity "
"is inf, which exceeds 0.0");
EXPECT_NONFATAL_FAILURE(
EXPECT_NEAR(v.infinity, v.close_to_infinity, v.further_from_infinity),
"The difference between v.infinity and v.close_to_infinity is inf, which "
"exceeds v.further_from_infinity");
// At this magnitude adjacent doubles are 512.0 apart, so this triggers a // At this magnitude adjacent doubles are 512.0 apart, so this triggers a
// slightly different failure reporting path. // slightly different failure reporting path.
EXPECT_NONFATAL_FAILURE( EXPECT_NONFATAL_FAILURE(

View File

@ -29,14 +29,14 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Unit test for the gtest_xml_output module""" """Unit test for the gtest_xml_output module."""
import datetime import datetime
import errno import errno
import os import os
import re import re
import sys import sys
from xml.dom import minidom, Node from xml.dom import minidom
from googletest.test import gtest_test_utils from googletest.test import gtest_test_utils
from googletest.test import gtest_xml_test_utils from googletest.test import gtest_xml_test_utils
@ -67,7 +67,10 @@ else:
sys.argv.remove(NO_STACKTRACE_SUPPORT_FLAG) sys.argv.remove(NO_STACKTRACE_SUPPORT_FLAG)
EXPECTED_NON_EMPTY_XML = """<?xml version="1.0" encoding="UTF-8"?> EXPECTED_NON_EMPTY_XML = """<?xml version="1.0" encoding="UTF-8"?>
<testsuites tests="26" failures="5" disabled="2" errors="0" time="*" timestamp="*" name="AllTests" ad_hoc_property="42"> <testsuites tests="28" failures="5" disabled="2" errors="0" time="*" timestamp="*" name="AllTests">
<properties>
<property name="ad_hoc_property" value="42"/>
</properties>
<testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*"> <testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
<testcase name="Succeeds" file="gtest_xml_output_unittest_.cc" line="53" status="run" result="completed" time="*" timestamp="*" classname="SuccessfulTest"/> <testcase name="Succeeds" file="gtest_xml_output_unittest_.cc" line="53" status="run" result="completed" time="*" timestamp="*" classname="SuccessfulTest"/>
</testsuite> </testsuite>
@ -132,64 +135,91 @@ It is good practice to tell why you skip a test.
</testcase> </testcase>
</testsuite> </testsuite>
<testsuite name="PropertyRecordingTest" tests="4" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*" SetUpTestSuite="yes" TearDownTestSuite="aye"> <testsuite name="PropertyRecordingTest" tests="4" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
<testcase name="OneProperty" file="gtest_xml_output_unittest_.cc" line="121" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest"> <properties>
<property name="SetUpTestSuite" value="yes"/>
<property name="SetUpTestSuite (with whitespace)" value="yes and yes"/>
<property name="TearDownTestSuite" value="aye"/>
<property name="TearDownTestSuite (with whitespace)" value="aye and aye"/>
</properties>
<testcase name="OneProperty" file="gtest_xml_output_unittest_.cc" line="125" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
<properties> <properties>
<property name="key_1" value="1"/> <property name="key_1" value="1"/>
</properties> </properties>
</testcase> </testcase>
<testcase name="IntValuedProperty" file="gtest_xml_output_unittest_.cc" line="125" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest"> <testcase name="IntValuedProperty" file="gtest_xml_output_unittest_.cc" line="129" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
<properties> <properties>
<property name="key_int" value="1"/> <property name="key_int" value="1"/>
</properties> </properties>
</testcase> </testcase>
<testcase name="ThreeProperties" file="gtest_xml_output_unittest_.cc" line="129" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest"> <testcase name="ThreeProperties" file="gtest_xml_output_unittest_.cc" line="133" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
<properties> <properties>
<property name="key_1" value="1"/> <property name="key_1" value="1"/>
<property name="key_2" value="2"/> <property name="key_2" value="2"/>
<property name="key_3" value="3"/> <property name="key_3" value="3"/>
</properties> </properties>
</testcase> </testcase>
<testcase name="TwoValuesForOneKeyUsesLastValue" file="gtest_xml_output_unittest_.cc" line="135" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest"> <testcase name="TwoValuesForOneKeyUsesLastValue" file="gtest_xml_output_unittest_.cc" line="139" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
<properties> <properties>
<property name="key_1" value="2"/> <property name="key_1" value="2"/>
</properties> </properties>
</testcase> </testcase>
</testsuite> </testsuite>
<testsuite name="NoFixtureTest" tests="3" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*"> <testsuite name="NoFixtureTest" tests="3" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
<testcase name="RecordProperty" file="gtest_xml_output_unittest_.cc" line="140" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest"> <testcase name="RecordProperty" file="gtest_xml_output_unittest_.cc" line="144" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest">
<properties> <properties>
<property name="key" value="1"/> <property name="key" value="1"/>
</properties> </properties>
</testcase> </testcase>
<testcase name="ExternalUtilityThatCallsRecordIntValuedProperty" file="gtest_xml_output_unittest_.cc" line="153" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest"> <testcase name="ExternalUtilityThatCallsRecordIntValuedProperty" file="gtest_xml_output_unittest_.cc" line="157" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest">
<properties> <properties>
<property name="key_for_utility_int" value="1"/> <property name="key_for_utility_int" value="1"/>
</properties> </properties>
</testcase> </testcase>
<testcase name="ExternalUtilityThatCallsRecordStringValuedProperty" file="gtest_xml_output_unittest_.cc" line="157" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest"> <testcase name="ExternalUtilityThatCallsRecordStringValuedProperty" file="gtest_xml_output_unittest_.cc" line="161" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest">
<properties> <properties>
<property name="key_for_utility_string" value="1"/> <property name="key_for_utility_string" value="1"/>
</properties> </properties>
</testcase> </testcase>
</testsuite> </testsuite>
<testsuite name="SetupFailTest" tests="1" failures="0" disabled="0" skipped="1" errors="0" time="*" timestamp="*">
<testcase name="NoopPassingTest" file="gtest_xml_output_unittest_.cc" line="172" status="run" result="skipped" time="*" timestamp="*" classname="SetupFailTest">
<skipped message="gtest_xml_output_unittest_.cc:*&#x0A;"><![CDATA[gtest_xml_output_unittest_.cc:*
]]></skipped>
</testcase>
<testcase name="" status="run" result="completed" classname="" time="*" timestamp="*">
<failure message="gtest_xml_output_unittest_.cc:*&#x0A;Expected equality of these values:&#x0A; 1&#x0A; 2%(stack_entity)s" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
Expected equality of these values:
1
2%(stack)s]]></failure>
</testcase>
</testsuite>
<testsuite name="TearDownFailTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
<testcase name="NoopPassingTest" file="gtest_xml_output_unittest_.cc" line="179" status="run" result="completed" time="*" timestamp="*" classname="TearDownFailTest"/>
<testcase name="" status="run" result="completed" classname="" time="*" timestamp="*">
<failure message="gtest_xml_output_unittest_.cc:*&#x0A;Expected equality of these values:&#x0A; 1&#x0A; 2%(stack_entity)s" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
Expected equality of these values:
1
2%(stack)s]]></failure>
</testcase>
</testsuite>
<testsuite name="Single/ValueParamTest" tests="4" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*"> <testsuite name="Single/ValueParamTest" tests="4" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
<testcase name="HasValueParamAttribute/0" file="gtest_xml_output_unittest_.cc" line="164" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" /> <testcase name="HasValueParamAttribute/0" file="gtest_xml_output_unittest_.cc" line="184" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
<testcase name="HasValueParamAttribute/1" file="gtest_xml_output_unittest_.cc" line="164" value_param="42" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" /> <testcase name="HasValueParamAttribute/1" file="gtest_xml_output_unittest_.cc" line="184" value_param="42" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
<testcase name="AnotherTestThatHasValueParamAttribute/0" file="gtest_xml_output_unittest_.cc" line="165" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" /> <testcase name="AnotherTestThatHasValueParamAttribute/0" file="gtest_xml_output_unittest_.cc" line="185" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
<testcase name="AnotherTestThatHasValueParamAttribute/1" file="gtest_xml_output_unittest_.cc" line="165" value_param="42" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" /> <testcase name="AnotherTestThatHasValueParamAttribute/1" file="gtest_xml_output_unittest_.cc" line="185" value_param="42" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
</testsuite> </testsuite>
<testsuite name="TypedTest/0" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*"> <testsuite name="TypedTest/0" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
<testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="173" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="TypedTest/0" /> <testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="193" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="TypedTest/0" />
</testsuite> </testsuite>
<testsuite name="TypedTest/1" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*"> <testsuite name="TypedTest/1" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
<testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="173" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="TypedTest/1" /> <testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="193" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="TypedTest/1" />
</testsuite> </testsuite>
<testsuite name="Single/TypeParameterizedTestSuite/0" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*"> <testsuite name="Single/TypeParameterizedTestSuite/0" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
<testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="180" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/0" /> <testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="200" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/0" />
</testsuite> </testsuite>
<testsuite name="Single/TypeParameterizedTestSuite/1" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*"> <testsuite name="Single/TypeParameterizedTestSuite/1" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
<testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="180" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/1" /> <testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="200" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/1" />
</testsuite> </testsuite>
</testsuites>""" % { </testsuites>""" % {
'stack': STACK_TRACE_TEMPLATE, 'stack': STACK_TRACE_TEMPLATE,
@ -197,8 +227,10 @@ It is good practice to tell why you skip a test.
} }
EXPECTED_FILTERED_TEST_XML = """<?xml version="1.0" encoding="UTF-8"?> EXPECTED_FILTERED_TEST_XML = """<?xml version="1.0" encoding="UTF-8"?>
<testsuites tests="1" failures="0" disabled="0" errors="0" time="*" <testsuites tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests">
timestamp="*" name="AllTests" ad_hoc_property="42"> <properties>
<property name="ad_hoc_property" value="42"/>
</properties>
<testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" skipped="0" <testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" skipped="0"
errors="0" time="*" timestamp="*"> errors="0" time="*" timestamp="*">
<testcase name="Succeeds" file="gtest_xml_output_unittest_.cc" line="53" status="run" result="completed" time="*" timestamp="*" classname="SuccessfulTest"/> <testcase name="Succeeds" file="gtest_xml_output_unittest_.cc" line="53" status="run" result="completed" time="*" timestamp="*" classname="SuccessfulTest"/>
@ -206,19 +238,28 @@ EXPECTED_FILTERED_TEST_XML = """<?xml version="1.0" encoding="UTF-8"?>
</testsuites>""" </testsuites>"""
EXPECTED_SHARDED_TEST_XML = """<?xml version="1.0" encoding="UTF-8"?> EXPECTED_SHARDED_TEST_XML = """<?xml version="1.0" encoding="UTF-8"?>
<testsuites tests="3" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests" ad_hoc_property="42"> <testsuites tests="3" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests">
<properties>
<property name="ad_hoc_property" value="42"/>
</properties>
<testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*"> <testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
<testcase name="Succeeds" file="gtest_xml_output_unittest_.cc" line="53" status="run" result="completed" time="*" timestamp="*" classname="SuccessfulTest"/> <testcase name="Succeeds" file="gtest_xml_output_unittest_.cc" line="53" status="run" result="completed" time="*" timestamp="*" classname="SuccessfulTest"/>
</testsuite> </testsuite>
<testsuite name="PropertyRecordingTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*" SetUpTestSuite="yes" TearDownTestSuite="aye"> <testsuite name="PropertyRecordingTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
<testcase name="IntValuedProperty" file="gtest_xml_output_unittest_.cc" line="125" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest"> <properties>
<property name="SetUpTestSuite" value="yes"/>
<property name="SetUpTestSuite (with whitespace)" value="yes and yes"/>
<property name="TearDownTestSuite" value="aye"/>
<property name="TearDownTestSuite (with whitespace)" value="aye and aye"/>
</properties>
<testcase name="IntValuedProperty" file="gtest_xml_output_unittest_.cc" line="129" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
<properties> <properties>
<property name="key_int" value="1"/> <property name="key_int" value="1"/>
</properties> </properties>
</testcase> </testcase>
</testsuite> </testsuite>
<testsuite name="Single/ValueParamTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*"> <testsuite name="Single/TypeParameterizedTestSuite/0" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
<testcase name="HasValueParamAttribute/0" file="gtest_xml_output_unittest_.cc" line="164" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" /> <testcase name="HasTypeParamAttribute" type_param="*" file="gtest_xml_output_unittest_.cc" line="200" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/0" />
</testsuite> </testsuite>
</testsuites>""" </testsuites>"""

View File

@ -112,8 +112,12 @@ TEST(InvalidCharactersTest, InvalidCharactersInMessage) {
class PropertyRecordingTest : public Test { class PropertyRecordingTest : public Test {
public: public:
static void SetUpTestSuite() { RecordProperty("SetUpTestSuite", "yes"); } static void SetUpTestSuite() {
RecordProperty("SetUpTestSuite (with whitespace)", "yes and yes");
RecordProperty("SetUpTestSuite", "yes");
}
static void TearDownTestSuite() { static void TearDownTestSuite() {
RecordProperty("TearDownTestSuite (with whitespace)", "aye and aye");
RecordProperty("TearDownTestSuite", "aye"); RecordProperty("TearDownTestSuite", "aye");
} }
}; };
@ -158,6 +162,22 @@ TEST(NoFixtureTest, ExternalUtilityThatCallsRecordStringValuedProperty) {
ExternalUtilityThatCallsRecordProperty("key_for_utility_string", "1"); ExternalUtilityThatCallsRecordProperty("key_for_utility_string", "1");
} }
// Ensures that SetUpTestSuite and TearDownTestSuite failures are reported in
// the XML output.
class SetupFailTest : public ::testing::Test {
protected:
static void SetUpTestSuite() { ASSERT_EQ(1, 2); }
};
TEST_F(SetupFailTest, NoopPassingTest) {}
class TearDownFailTest : public ::testing::Test {
protected:
static void TearDownTestSuite() { ASSERT_EQ(1, 2); }
};
TEST_F(TearDownFailTest, NoopPassingTest) {}
// Verifies that the test parameter value is output in the 'value_param' // Verifies that the test parameter value is output in the 'value_param'
// XML attribute for value-parameterized tests. // XML attribute for value-parameterized tests.
class ValueParamTest : public TestWithParam<int> {}; class ValueParamTest : public TestWithParam<int> {};

View File

@ -6,20 +6,20 @@ load("//:fake_fuchsia_sdk.bzl", "fake_fuchsia_sdk")
def googletest_deps(): def googletest_deps():
"""Loads common dependencies needed to use the googletest library.""" """Loads common dependencies needed to use the googletest library."""
if not native.existing_rule("com_googlesource_code_re2"): if not native.existing_rule("re2"):
http_archive( http_archive(
name = "com_googlesource_code_re2", name = "re2",
sha256 = "eb2df807c781601c14a260a507a5bb4509be1ee626024cb45acbd57cb9d4032b", sha256 = "eb2df807c781601c14a260a507a5bb4509be1ee626024cb45acbd57cb9d4032b",
strip_prefix = "re2-2024-07-02", strip_prefix = "re2-2024-07-02",
urls = ["https://github.com/google/re2/releases/download/2024-07-02/re2-2024-07-02.tar.gz"], urls = ["https://github.com/google/re2/releases/download/2024-07-02/re2-2024-07-02.tar.gz"],
) )
if not native.existing_rule("com_google_absl"): if not native.existing_rule("abseil-cpp"):
http_archive( http_archive(
name = "com_google_absl", name = "abseil-cpp",
sha256 = "733726b8c3a6d39a4120d7e45ea8b41a434cdacde401cba500f14236c49b39dc", sha256 = "16242f394245627e508ec6bb296b433c90f8d914f73b9c026fddb905e27276e8",
strip_prefix = "abseil-cpp-20240116.2", strip_prefix = "abseil-cpp-20250127.0",
urls = ["https://github.com/abseil/abseil-cpp/releases/download/20240116.2/abseil-cpp-20240116.2.tar.gz"], urls = ["https://github.com/abseil/abseil-cpp/releases/download/20250127.0/abseil-cpp-20250127.0.tar.gz"],
) )
if not native.existing_rule("fuchsia_sdk"): if not native.existing_rule("fuchsia_sdk"):