Compare commits

..

2 Commits

Author SHA1 Message Date
Derek Mauro
075196ca06
Remove auto-detection of Python toolchain from MODULE.bazel (#4582)
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.

Backport of 3e3b44c300
2024-07-30 20:25:53 -04:00
Derek Mauro
e397860881
Prepare for v1.15.0 (#4574) 2024-07-15 13:46:49 -04:00
46 changed files with 470 additions and 1206 deletions

View File

@ -138,19 +138,19 @@ cc_library(
}), }),
deps = select({ deps = select({
":has_absl": [ ":has_absl": [
"@abseil-cpp//absl/container:flat_hash_set", "@com_google_absl//absl/container:flat_hash_set",
"@abseil-cpp//absl/debugging:failure_signal_handler", "@com_google_absl//absl/debugging:failure_signal_handler",
"@abseil-cpp//absl/debugging:stacktrace", "@com_google_absl//absl/debugging:stacktrace",
"@abseil-cpp//absl/debugging:symbolize", "@com_google_absl//absl/debugging:symbolize",
"@abseil-cpp//absl/flags:flag", "@com_google_absl//absl/flags:flag",
"@abseil-cpp//absl/flags:parse", "@com_google_absl//absl/flags:parse",
"@abseil-cpp//absl/flags:reflection", "@com_google_absl//absl/flags:reflection",
"@abseil-cpp//absl/flags:usage", "@com_google_absl//absl/flags:usage",
"@abseil-cpp//absl/strings", "@com_google_absl//absl/strings",
"@abseil-cpp//absl/types:any", "@com_google_absl//absl/types:any",
"@abseil-cpp//absl/types:optional", "@com_google_absl//absl/types:optional",
"@abseil-cpp//absl/types:variant", "@com_google_absl//absl/types:variant",
"@re2//:re2", "@com_googlesource_code_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.16) cmake_minimum_required(VERSION 3.13)
project(googletest-distribution) project(googletest-distribution)
set(GOOGLETEST_VERSION 1.16.0) set(GOOGLETEST_VERSION 1.15.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,45 +32,38 @@
module( module(
name = "googletest", name = "googletest",
version = "head", version = "1.15.1",
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( bazel_dep(name = "abseil-cpp",
name = "abseil-cpp", version = "20240116.2",
version = "20250127.0", repo_name = "com_google_absl")
)
bazel_dep(
name = "platforms",
version = "0.0.10",
)
bazel_dep(
name = "re2",
version = "2024-07-02",
)
bazel_dep( bazel_dep(name = "platforms",
name = "rules_python", version = "0.0.10")
version = "1.1.0",
dev_dependency = True, bazel_dep(name = "re2",
) 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",
) )
# See fake_fuchsia_sdk.bzl for instructions on how to override this with a real SDK, if needed. python.toolchain(python_version = "3.12",
fuchsia_sdk = use_extension("//:fake_fuchsia_sdk.bzl", "fuchsia_sdk") is_default = True,
fuchsia_sdk.create_fake() ignore_root_user_error = True)
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.16.0`). `v${major}.${minor}.${patch}` (e.g. `v1.15.0`).
#### Documentation Updates #### Documentation Updates
@ -17,15 +17,12 @@ 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.16.0 #### Release 1.15.0
[Release 1.16.0](https://github.com/google/googletest/releases/tag/v1.16.0) is [Release 1.15.0](https://github.com/google/googletest/releases/tag/v1.15.0) is
now available. now available.
The 1.16.x branch requires at least C++14. The 1.15.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,34 +1,4 @@
# Copyright 2024 Google Inc. workspace(name = "com_google_googletest")
# 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()
@ -36,12 +6,13 @@ 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 = "9c6e26911a79fbf510a8f06d8eedb40f412023cf7fa6d1461def27116bff022c", sha256 = "d71d2c67e0bce986e1c5a7731b4693226867c45bfe0b7c5e0067228a536fc580",
strip_prefix = "rules_python-1.1.0", strip_prefix = "rules_python-0.29.0",
url = "https://github.com/bazelbuild/rules_python/releases/download/1.1.0/rules_python-1.1.0.tar.gz", urls = ["https://github.com/bazelbuild/rules_python/releases/download/0.29.0/rules_python-0.29.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,68 +31,51 @@
set -euox pipefail set -euox pipefail
readonly LINUX_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20241218" readonly LINUX_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20240523"
readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20250205" readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20230120"
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++17 c++20" STD="c++14 c++17 c++20"
fi fi
# Test CMake + GCC # Test the CMake build
for cmake_off_on in OFF ON; do for cc in /usr/local/bin/gcc /opt/llvm/clang/bin/clang; do
time docker run \ for cmake_off_on in OFF ON; do
--volume="${GTEST_ROOT}:/src:ro" \ time docker run \
--tmpfs="/build:exec" \ --volume="${GTEST_ROOT}:/src:ro" \
--workdir="/build" \ --tmpfs="/build:exec" \
--rm \ --workdir="/build" \
--env="CC=/usr/local/bin/gcc" \ --rm \
--env=CXXFLAGS="-Werror -Wdeprecated" \ --env="CC=${cc}" \
${LINUX_LATEST_CONTAINER} \ --env=CXXFLAGS="-Werror -Wdeprecated" \
/bin/bash -c " ${LINUX_LATEST_CONTAINER} \
cmake /src \ /bin/bash -c "
-DCMAKE_CXX_STANDARD=17 \ cmake /src \
-Dgtest_build_samples=ON \ -DCMAKE_CXX_STANDARD=14 \
-Dgtest_build_tests=ON \ -Dgtest_build_samples=ON \
-Dgmock_build_tests=ON \ -Dgtest_build_tests=ON \
-Dcxx_no_exception=${cmake_off_on} \ -Dgmock_build_tests=ON \
-Dcxx_no_rtti=${cmake_off_on} && \ -Dcxx_no_exception=${cmake_off_on} \
make -j$(nproc) && \ -Dcxx_no_rtti=${cmake_off_on} && \
ctest -j$(nproc) --output-on-failure" make -j$(nproc) && \
done ctest -j$(nproc) --output-on-failure"
done
# Test CMake + Clang
for cmake_off_on in OFF ON; do
time docker run \
--volume="${GTEST_ROOT}:/src:ro" \
--tmpfs="/build:exec" \
--workdir="/build" \
--rm \
--env="CC=/opt/llvm/clang/bin/clang" \
--env=CXXFLAGS="-Werror -Wdeprecated --gcc-toolchain=/usr/local" \
${LINUX_LATEST_CONTAINER} \
/bin/bash -c "
cmake /src \
-DCMAKE_CXX_STANDARD=17 \
-Dgtest_build_samples=ON \
-Dgtest_build_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++17" \ --env="BAZEL_CXXOPTS=-std=c++14" \
${LINUX_GCC_FLOOR_CONTAINER} \ ${LINUX_GCC_FLOOR_CONTAINER} \
/usr/local/bin/bazel test ... \ /usr/local/bin/bazel test ... \
--copt="-Wall" \ --copt="-Wall" \
@ -100,7 +83,6 @@ 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,9 +31,6 @@
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
@ -43,20 +40,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=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}
time make -j$(nproc) time make
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-8.0.0-darwin-x86_64" KOKORO_GFILE_BAZEL_BIN="bazel-7.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}
@ -70,7 +67,7 @@ for absl in 0 1; do
--copt="-Wall" \ --copt="-Wall" \
--copt="-Werror" \ --copt="-Werror" \
--copt="-Wundef" \ --copt="-Wundef" \
--cxxopt="-std=c++17" \ --cxxopt="-std=c++14" \
--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-8.0.0-windows-x86_64.exe SET BAZEL_EXE=%KOKORO_GFILE_DIR%\bazel-7.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,18 +11,21 @@ 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
SET GTEST_ROOT=%~dp0\.. IF EXIST git\googletest (
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
SET CMAKE_BUILD_PATH=cmake_msvc2022 MKDIR cmake_msvc2022
MKDIR %CMAKE_BUILD_PATH% CD cmake_msvc2022
CD %CMAKE_BUILD_PATH%
%CMAKE_BIN% %GTEST_ROOT% ^ %CMAKE_BIN% .. ^
-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 ^
@ -37,8 +40,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 %GTEST_ROOT% CD ..
RMDIR /S /Q %CMAKE_BUILD_PATH% RMDIR /S /Q cmake_msvc2022
:: ---------------------------------------------------------------------------- :: ----------------------------------------------------------------------------
:: Bazel :: Bazel
@ -47,26 +50,11 @@ RMDIR /S /Q %CMAKE_BUILD_PATH%
:: 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++17 ^ --copt=/std:c++14 ^
--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";
FAIL(); // Won't fail; it won't be executed EXPECT_EQ(0, 1); // 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) {
FAIL(); // Won't fail; it won't be executed EXPECT_EQ(5, 7); // Won't fail
} }
``` ```
@ -405,51 +405,6 @@ 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
@ -461,7 +416,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"
@ -507,12 +462,6 @@ 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.
@ -554,6 +503,51 @@ 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
@ -733,7 +727,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++
@ -2388,7 +2382,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, (), (const, override)); MOCK_METHOD(int, GetSize, (), (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 non-const reference, `T` must also be a reference (as the 3. When `U` is a reference, `T` must also be a reference (as the underlying
underlying matcher may be interested in the address of the `U` value). 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_...` statements inside custom matcher definitions. In You can also use `EXPECT_...` (and `ASSERT_...`) statements inside custom
many cases, this allows you to write your matcher more concisely while still matcher definitions. In many cases, this allows you to write your matcher more
providing an informative error message. For example: concisely while still 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 context in The type of the value being matched (`arg_type`) is determined by the
which you use the matcher and is supplied to you by the compiler, so you don't context in which you use the matcher and is supplied to you by the compiler, so
need to worry about declaring it (nor can you). This allows the matcher to be you don't need to worry about declaring it (nor can you). This allows the
polymorphic. For example, `IsDivisibleBy7()` can be used to match any type where matcher to be polymorphic. For example, `IsDivisibleBy7()` can be used to match
the value of `(arg % 7) == 0` can be implicitly converted to a `bool`. In the any type where the value of `(arg % 7) == 0` can be implicitly converted to a
`Bar(IsDivisibleBy7())` example above, if method `Bar()` takes an `int`, `bool`. In the `Bar(IsDivisibleBy7())` example above, if method `Bar()` takes an
`arg_type` will be `int`; if it takes an `unsigned long`, `arg_type` will be `int`, `arg_type` will be `int`; if it takes an `unsigned long`, `arg_type` will
`unsigned long`; and so on. be `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 [istqb test case]: https://glossary.istqb.org/en_US/term/test-case-2
[istqb test suite]: https://glossary.istqb.org/en_US/term/test-suite [istqb test suite]: https://glossary.istqb.org/en_US/term/test-suite-1-3
## 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/) 7.0 or higher, the preferred build system used * [Bazel](https://bazel.build/), the preferred build system used by the
by the GoogleTest team. 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
`MODULE.bazel` which may be empty, or may contain references to external `WORKSPACE` 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,20 +37,30 @@ First, create a directory for your workspace:
$ mkdir my_workspace && cd my_workspace $ mkdir my_workspace && cd my_workspace
``` ```
Next, youll create the `MODULE.bazel` file to specify dependencies. As of Bazel Next, youll create the `WORKSPACE` file to specify dependencies. A common and
7.0, the recommended way to consume GoogleTest is through the recommended way to depend on GoogleTest is to use a
[Bazel Central Registry](https://registry.bazel.build/modules/googletest). To do [Bazel external dependency](https://docs.bazel.build/versions/main/external.html)
this, create a `MODULE.bazel` file in the root directory of your Bazel workspace via the
with the following content: [`http_archive` rule](https://docs.bazel.build/versions/main/repo/http.html#http_archive).
To do this, in the root directory of your workspace (`my_workspace/`), create a
file named `WORKSPACE` with the following contents:
``` ```
# MODULE.bazel load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
# Choose the most recent version available at http_archive(
# https://registry.bazel.build/modules/googletest name = "com_google_googletest",
bazel_dep(name = "googletest", version = "1.15.2") urls = ["https://github.com/google/googletest/archive/5ab508a01f9eb089207ee87fd547d290da39d015.zip"],
strip_prefix = "googletest-5ab508a01f9eb089207ee87fd547d290da39d015",
)
``` ```
The above configuration declares a dependency on GoogleTest which is downloaded
as a ZIP archive from GitHub. In the above example,
`5ab508a01f9eb089207ee87fd547d290da39d015` is the Git commit hash of the
GoogleTest version to use; we recommend updating the hash often to point to the
latest version. Use a recent hash on the `main` branch.
Now you're ready to build C++ code that uses GoogleTest. Now you're ready to build C++ code that uses GoogleTest.
## Create and run a binary ## Create and run a binary
@ -82,20 +92,17 @@ 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 = [ deps = ["@com_google_googletest//:gtest_main"],
"@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
the GoogleTest library (`@googletest//:gtest"`) and the GoogleTest `main()` GoogleTest (`//:gtest_main`) using the prefix you specified in the `WORKSPACE`
function (`@googletest//:gtest_main`). For more information about Bazel `BUILD` file (`@com_google_googletest`). For more information about Bazel `BUILD` files,
files, see the 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}
@ -108,7 +115,7 @@ on supported language versions.
Now you can build and run your test: Now you can build and run your test:
<pre> <pre>
<strong>$ bazel test --cxxopt=-std=c++14 --test_output=all //:hello_test</strong> <strong>my_workspace$ 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,8 +24,7 @@ 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` by copy-assignment. | | `SaveArg<N>(pointer)` | Save the `N`-th (0-based) argument to `*pointer`. |
| `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,8 +276,7 @@ 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. Infinity and the largest finite float equal, to within 4 ULPs from each other.
value are considered to be one ULP apart.
### EXPECT_DOUBLE_EQ {#EXPECT_DOUBLE_EQ} ### EXPECT_DOUBLE_EQ {#EXPECT_DOUBLE_EQ}
@ -285,8 +284,7 @@ value are considered to be one ULP apart.
`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. Infinity and the largest finite double equal, to within 4 ULPs from each other.
value are considered to be one ULP apart.
### EXPECT_NEAR {#EXPECT_NEAR} ### EXPECT_NEAR {#EXPECT_NEAR}
@ -296,11 +294,6 @@ value are considered to be one ULP apart.
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,11 +171,6 @@ 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
@ -194,6 +189,10 @@ contract of the function.
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,20 +1,10 @@
"""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.
GoogleTest can be used with the [Fuchsia](https://fuchsia.dev/) SDK. However, This is needed since bazel queries on targets that depend on //:gtest (eg:
because the Fuchsia SDK does not yet support bzlmod, GoogleTest's `MODULE.bazel` `bazel query "deps(set(//googletest/test:gtest_all_test))"`) will fail if @fuchsia_sdk is not
file by default provides a "fake" Fuchsia SDK. defined when bazel is evaluating the transitive closure of the query target.
To override this and use the real Fuchsia SDK, you can add the following to your See https://github.com/google/googletest/issues/4472.
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):
@ -41,21 +31,3 @@ 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,7 +1493,6 @@ 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,
@ -1502,21 +1501,6 @@ 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<
@ -1596,16 +1580,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)) {}
// We support conversion to OnceAction whenever both the initial action and template <typename R, typename... Args,
// the rest support conversion to OnceAction. typename std::enable_if<
template < conjunction<
typename R, typename... Args, // Both the initial action and the rest must support
typename std::enable_if< // conversion to OnceAction.
conjunction<std::is_convertible< 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
@ -1628,34 +1612,12 @@ 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,
@ -1703,9 +1665,8 @@ template <size_t k>
struct ReturnArgAction { struct ReturnArgAction {
template <typename... Args, template <typename... Args,
typename = typename std::enable_if<(k < sizeof...(Args))>::type> typename = typename std::enable_if<(k < sizeof...(Args))>::type>
auto operator()(Args&&... args) const auto operator()(Args&&... args) const -> decltype(std::get<k>(
-> decltype(std::get<k>( std::forward_as_tuple(std::forward<Args>(args)...))) {
std::forward_as_tuple(std::forward<Args>(args)...))) {
return std::get<k>(std::forward_as_tuple(std::forward<Args>(args)...)); return std::get<k>(std::forward_as_tuple(std::forward<Args>(args)...));
} }
}; };
@ -1720,16 +1681,6 @@ 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;
@ -2080,13 +2031,6 @@ 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,22 +408,13 @@ class MatcherCastImpl<T, Matcher<U>> {
} }
private: private:
// If it's possible to implicitly convert a `const T&` to U, then `Impl` can class Impl : public MatcherInterface<T> {
// 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(ImplArgT x, bool MatchAndExplain(T x, MatchResultListener* listener) const override {
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<
@ -440,8 +431,9 @@ 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 = typename std::conditional< using CastType =
std::is_convertible<ImplArgT&, const U&>::value, ImplArgT&, U>::type; typename std::conditional<std::is_convertible<T&, const U&>::value,
T&, U>::type;
return source_matcher_.MatchAndExplain(static_cast<CastType>(x), return source_matcher_.MatchAndExplain(static_cast<CastType>(x),
listener); listener);
@ -536,16 +528,18 @@ 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 non-const reference and T is not, as the // The only exception is when U is a 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
// cannot be preserved in the conversion from T to U (since a copy of the input // is not preserved in the conversion from T to U.
// 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 (and T must be a " "T must be implicitly convertible to U");
"non-const reference if U is a non-const reference)"); // Enforce that we are not converting a non-reference type T to a 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;
@ -567,11 +561,6 @@ 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) {
@ -1311,48 +1300,34 @@ class AllOfMatcherImpl : 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. // If either matcher1_ or matcher2_ doesn't match x, we only need
// However, if matcher doesn't provide one, this method uses matcher's // to explain why one of them fails.
// 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;
// Return explanation for first failed matcher. if (matchers_[i].MatchAndExplain(x, &slistener)) {
if (!matcher.MatchAndExplain(x, &slistener)) { if (all_match_result.empty()) {
const std::string explanation = slistener.str(); all_match_result = slistener.str();
if (!explanation.empty()) {
*listener << explanation;
} else { } else {
*listener << "which doesn't match (" << Describe(matcher) << ")"; std::string result = slistener.str();
if (!result.empty()) {
all_match_result += ", and ";
all_match_result += result;
}
} }
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 { } else {
if (!explanation.empty()) { *listener << slistener.str();
all_match_result += ", and "; return false;
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_;
}; };
@ -1430,55 +1405,34 @@ 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;
// Return explanation for first match. if (matchers_[i].MatchAndExplain(x, &slistener)) {
if (matcher.MatchAndExplain(x, &slistener)) { *listener << slistener.str();
const std::string explanation = slistener.str();
if (!explanation.empty()) {
*listener << explanation;
} else {
*listener << "which matches (" << Describe(matcher) << ")";
}
return true; return true;
}
// 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 { } else {
if (!explanation.empty()) { if (no_match_result.empty()) {
no_match_result += ", and "; no_match_result = slistener.str();
no_match_result += explanation; } else {
std::string result = slistener.str();
if (!result.empty()) {
no_match_result += ", and ";
no_match_result += result;
}
} }
} }
} }
// 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_;
}; };
@ -1529,7 +1483,7 @@ class SomeOfArrayMatcher {
} }
private: private:
const std::vector<std::remove_const_t<T>> matchers_; const ::std::vector<T> matchers_;
}; };
template <typename T> template <typename T>
@ -2281,9 +2235,6 @@ 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>
@ -2291,7 +2242,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<InnerType>(matcher)) {} matcher_(MatcherCast<ResultType>(matcher)) {}
void DescribeTo(::std::ostream* os) const override { void DescribeTo(::std::ostream* os) const override {
if (result_description_.empty()) { if (result_description_.empty()) {
@ -2321,7 +2272,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&>).
InnerType result = ResultType 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);
} }
@ -2334,7 +2285,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<InnerType> matcher_; const Matcher<ResultType> matcher_;
}; // class Impl }; // class Impl
const std::string result_description_; const std::string result_description_;
@ -2969,6 +2920,10 @@ 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>
@ -3300,11 +3255,6 @@ 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>
@ -3819,7 +3769,7 @@ class UnorderedElementsAreArrayMatcher {
private: private:
UnorderedMatcherRequire::Flags match_flags_; UnorderedMatcherRequire::Flags match_flags_;
std::vector<std::remove_const_t<T>> matchers_; ::std::vector<T> matchers_;
}; };
// Implements ElementsAreArray(). // Implements ElementsAreArray().
@ -3840,7 +3790,7 @@ class ElementsAreArrayMatcher {
} }
private: private:
const std::vector<std::remove_const_t<T>> matchers_; const ::std::vector<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
@ -3927,21 +3877,6 @@ 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 {
@ -3974,7 +3909,7 @@ class OptionalMatcher {
bool MatchAndExplain(Optional optional, bool MatchAndExplain(Optional optional,
MatchResultListener* listener) const override { MatchResultListener* listener) const override {
if (!IsOptionalEngaged(optional, HighestRank())) { if (!optional) {
*listener << "which is not engaged"; *listener << "which is not engaged";
return false; return false;
} }
@ -4453,10 +4388,6 @@ 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>>
@ -4811,10 +4742,9 @@ 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, inline internal::PointwiseMatcher<TupleMatcher, std::vector<T>> Pointwise(
std::vector<std::remove_const_t<T>>> const TupleMatcher& tuple_matcher, std::initializer_list<T> rhs) {
Pointwise(const TupleMatcher& tuple_matcher, std::initializer_list<T> rhs) { return Pointwise(tuple_matcher, std::vector<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
@ -4976,7 +4906,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 match IsSubsetOf({Gt(0), Lt(0)}), even though 1 and 2 both // - {1, 2} doesn't matches 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.
// //
@ -5301,10 +5231,9 @@ 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' (or 'arg.has_value()' if '!arg` // The matcher implementation only uses '!arg' and requires that the optional<>
// isn't a valid expression) and requires that the optional<> type has a // type has a 'value_type' member type and that '*arg' is of type 'value_type'
// 'value_type' member type and that '*arg' is of type 'value_type' and is // and is printable using 'PrintToString'. It is compatible with
// 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,10 +601,9 @@ 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 auto operator()(Args &&...args) const -> decltype(internal::InvokeArgument(
-> decltype(internal::InvokeArgument( std::get<index>(std::forward_as_tuple(std::forward<Args>(args)...)),
std::get<index>(std::forward_as_tuple(std::forward<Args>(args)...)), std::declval<const Params &>()...)) {
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,8 +1838,9 @@ 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 = {reaction, const UninterestingCallCleanupHandler report_uninteresting_call = {
ss}; reaction, ss
};
return PerformActionAndPrintResult(nullptr, std::move(args), ss.str(), ss); return PerformActionAndPrintResult(nullptr, std::move(args), ss.str(), ss);
} }
@ -1889,7 +1890,8 @@ 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,7 +42,6 @@
#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, " << "but is actually " ss << "The invocation lower bound must be >= 0, "
<< min << "."; << "but is actually " << 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, " << "but is actually " ss << "The invocation upper bound must be >= 0, "
<< max << "."; << "but is actually " << 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.
// TODO(b/396121064) - Fix this test under MSVC #if defined(GTEST_INTERNAL_CPLUSPLUS_LANG) && \
#ifndef _MSC_VER GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L
{ {
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 // _MSC_VER #endif // C++17 and above
// 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( EXPECT_DEATH_IF_SUPPORTED({ DefaultValue<MyNonDefaultConstructible>::Get(); },
{ 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( EXPECT_DEATH_IF_SUPPORTED({ DefaultValue<MyNonDefaultConstructible>::Get(); },
{ DefaultValue<MyNonDefaultConstructible>::Get(); }, ""); "");
} }
// Tests that ActionInterface can be implemented by defining the // Tests that ActionInterface can be implemented by defining the
@ -1477,54 +1477,6 @@ 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_, Decimal(true, 'a', 0, 0, 1L, A<float>(), Lt(100), EXPECT_CALL(this->mock_foo_,
5U, nullptr, "hi")) Decimal(true, 'a', 0, 0, 1L, A<float>(), Lt(100), 5U, NULL, "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,9 +36,7 @@
#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
@ -561,9 +559,10 @@ 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 the matcher description is used. // matcher doesn't give an explanation, so only the first matcher's
// explanation is printed.
m = AllOf(GreaterThan(10), Lt(30)); m = AllOf(GreaterThan(10), Lt(30));
EXPECT_EQ("which is 15 more than 10, and is < 30", Explain(m, 25)); EXPECT_EQ("which is 15 more than 10", 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));
@ -573,9 +572,8 @@ 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( EXPECT_EQ("which is 15 more than 10, and which is 5 more than 20",
"which is 15 more than 10, and is < 30, and which is 5 more than 20", Explain(m, 25));
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));
@ -590,10 +588,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, the matcher text is // explain. Since it doesn't given an explanation, nothing is
// printed. // printed.
m = AllOf(GreaterThan(10), Lt(30)); m = AllOf(GreaterThan(10), Lt(30));
EXPECT_EQ("which doesn't match (is < 30)", Explain(m, 40)); EXPECT_EQ("", Explain(m, 40));
// Failed match. The second matcher, which failed, needs to // Failed match. The second matcher, which failed, needs to
// explain. // explain.
@ -776,43 +774,45 @@ TEST(AnyOfTest, AnyOfMatcherSafelyCastsMonomorphicMatchers) {
TEST_P(AnyOfTestP, ExplainsResult) { TEST_P(AnyOfTestP, ExplainsResult) {
Matcher<int> m; Matcher<int> m;
// Failed match. The second matcher have no explanation (description is used). // Failed match. Both matchers need to explain. The second
// 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, and isn't < 0", Explain(m, 5)); EXPECT_EQ("which is 5 less than 10", Explain(m, 5));
// Failed match. Both matchers have explanations. // Failed match. Both matchers need to explain.
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. The middle matcher have no explanation. // Failed match. All matchers need to explain. The second
// matcher doesn't given an explanation.
m = AnyOf(GreaterThan(10), Gt(20), GreaterThan(30)); m = AnyOf(GreaterThan(10), Gt(20), GreaterThan(30));
EXPECT_EQ( EXPECT_EQ("which is 5 less than 10, and which is 25 less than 30",
"which is 5 less than 10, and isn't > 20, and which is 25 less than 30", Explain(m, 5));
Explain(m, 5));
// Failed match. All three matchers have explanations. // Failed match. All matchers need to explain.
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 macher succeeded and has explanation. // Successful match. The first matcher, which succeeded, needs to
// 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 succeeded and has explanation. // Successful match. The second matcher, which succeeded, needs to
// 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,14 +37,13 @@
#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 {
@ -411,27 +410,9 @@ 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) {
@ -447,34 +428,14 @@ 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) {
int n = 0; Matcher<const int&> m1 = Eq(0);
Matcher<const int&> m1 = Ref(n);
Matcher<int> m2 = MatcherCast<int>(m1); Matcher<int> m2 = MatcherCast<int>(m1);
int n1 = 0; EXPECT_TRUE(m2.Matches(0));
EXPECT_TRUE(m2.Matches(n)); EXPECT_FALSE(m2.Matches(1));
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&>.
@ -483,12 +444,6 @@ 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>.
@ -693,16 +648,6 @@ 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;
@ -2389,11 +2334,9 @@ 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("is >= 2, and is <= 3", Explain(m, 2)); EXPECT_EQ("", 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,16 +1204,13 @@ 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, which matches (is equal to 0)", EXPECT_EQ("whose size 0 matches", Explain(m3, container));
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( EXPECT_EQ("whose size 2 doesn't match", Explain(m3, container));
"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));
} }
@ -1478,10 +1475,8 @@ 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( EXPECT_EQ("whose distance between begin() and end() 0 matches",
"whose distance between begin() and end() 0 matches, which matches (is " Explain(m3, container));
"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",
@ -1492,10 +1487,8 @@ 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( EXPECT_EQ("whose distance between begin() and end() 2 doesn't match",
"whose distance between begin() and end() 2 doesn't match, isn't equal " Explain(m3, container));
"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,7 +32,6 @@
// 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>
@ -40,14 +39,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 {
@ -675,8 +674,6 @@ 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>
@ -694,94 +691,38 @@ class SampleOptional {
bool has_value_; bool has_value_;
}; };
// Sample optional type implementation with alternative minimal requirements for TEST(OptionalTest, DescribesSelf) {
// use with Optional matcher. In particular, while it doesn't have a bool const Matcher<SampleOptional<int>> m = Optional(Eq(1));
// 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));
} }
TYPED_TEST(OptionalTest, ExplainsSelf) { TEST(OptionalTest, ExplainsSelf) {
const Matcher<TypeParam> m = Optional(Eq(1)); const Matcher<SampleOptional<int>> m = Optional(Eq(1));
EXPECT_EQ("whose value 1 matches", Explain(m, TypeParam(1))); EXPECT_EQ("whose value 1 matches", Explain(m, SampleOptional<int>(1)));
EXPECT_EQ("whose value 2 doesn't match", Explain(m, TypeParam(2))); EXPECT_EQ("whose value 2 doesn't match", Explain(m, SampleOptional<int>(2)));
} }
TYPED_TEST(OptionalTest, MatchesNonEmptyOptional) { TEST(OptionalTest, MatchesNonEmptyOptional) {
const Matcher<TypeParam> m1 = Optional(1); const Matcher<SampleOptional<int>> m1 = Optional(1);
const Matcher<TypeParam> m2 = Optional(Eq(2)); const Matcher<SampleOptional<int>> m2 = Optional(Eq(2));
const Matcher<TypeParam> m3 = Optional(Lt(3)); const Matcher<SampleOptional<int>> m3 = Optional(Lt(3));
TypeParam opt(1); SampleOptional<int> 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));
} }
TYPED_TEST(OptionalTest, DoesNotMatchNullopt) { TEST(OptionalTest, DoesNotMatchNullopt) {
const Matcher<TypeParam> m = Optional(1); const Matcher<SampleOptional<int>> m = Optional(1);
TypeParam empty; SampleOptional<int> empty;
EXPECT_FALSE(m.Matches(empty)); EXPECT_FALSE(m.Matches(empty));
} }
TYPED_TEST(OptionalTest, ComposesWithMonomorphicMatchersTakingReferences) { TEST(OptionalTest, WorksWithMoveOnly) {
const Matcher<const int&> eq1 = Eq(1); Matcher<SampleOptional<std::unique_ptr<int>>> m = Optional(Eq(nullptr));
const Matcher<const int&> eq2 = Eq(2); EXPECT_TRUE(m.Matches(SampleOptional<std::unique_ptr<int>>(nullptr)));
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) {}
@ -1635,10 +1576,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("which matches (is equal to 1)", Explain(m1, 1)); EXPECT_EQ("", Explain(m1, 1));
EXPECT_EQ("isn't equal to 1", Explain(m1, 2)); EXPECT_EQ("", Explain(m1, 2));
EXPECT_EQ("which matches (is equal to 3)", Explain(m2, 3)); EXPECT_EQ("", Explain(m2, 3));
EXPECT_EQ("isn't equal to 2, and isn't equal to 3", Explain(m2, 4)); EXPECT_EQ("", 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,7 +59,6 @@ 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;
@ -493,34 +492,6 @@ 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;
@ -785,34 +756,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=windows. // TODO(iserna): The following asserts fail in --config=lexan.
#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,8 +804,9 @@ TEST(ExpectCallTest, InfersCardinality1WhenThereIsWillRepeatedly) {
"to be called at least once"); "to be called at least once");
} }
// TODO(b/396121064) - Fix this test under MSVC #if defined(GTEST_INTERNAL_CPLUSPLUS_LANG) && \
#ifndef _MSC_VER GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L
// 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.
@ -846,7 +847,7 @@ TEST(ExpectCallTest, NonMoveableType) {
EXPECT_EQ(17, mock.AsStdFunction()().x); EXPECT_EQ(17, mock.AsStdFunction()().x);
} }
#endif // _MSC_VER #endif // C++17 and above
// 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::Rethrow;
using testing::Throw; using testing::Throw;
using testing::Rethrow;
#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.16.0 git clone https://github.com/google/googletest.git -b v1.15.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_17) target_compile_features(${name} PUBLIC cxx_std_14)
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*) const; // bool MatchAndExplain(const T&, std::ostream*);
// (MatchResultListener* can also be used instead of std::ostream*) // (MatchResultListener* can also be used instead of std::ostream*)
// void DescribeTo(std::ostream*) const; // void DescribeTo(std::ostream*);
// void DescribeNegationTo(std::ostream*) const; // void DescribeNegationTo(std::ostream*);
// //
// 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,10 +126,6 @@
#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.
@ -786,41 +782,6 @@ 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 < 201703L GTEST_INTERNAL_CPLUSPLUS_LANG < 201402L
#error C++ versions less than C++17 are not supported. #error C++ versions less than C++14 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,12 +2533,4 @@ 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,25 +1660,10 @@ std::string GetBoolAssertionFailureMessage(
return msg.GetString(); return msg.GetString();
} }
// Helper function for implementing ASSERT_NEAR. Treats infinity as a specific // Helper function for implementing ASSERT_NEAR.
// 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();
@ -3989,12 +3974,6 @@ 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);
@ -4012,11 +3991,16 @@ 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_;
@ -4237,15 +4221,6 @@ 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", "");
@ -4260,6 +4235,9 @@ void XmlUnitTestResultPrinter::OutputXmlTestCaseForTestResult(
// 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.
@ -4350,7 +4328,7 @@ void XmlUnitTestResultPrinter::OutputXmlTestResult(::std::ostream* stream,
if (failures == 0 && skips == 0) { if (failures == 0 && skips == 0) {
*stream << ">\n"; *stream << ">\n";
} }
OutputXmlTestProperties(stream, result, /*indent=*/" "); OutputXmlTestProperties(stream, result);
*stream << " </testcase>\n"; *stream << " </testcase>\n";
} }
} }
@ -4379,18 +4357,13 @@ 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";
} }
@ -4420,12 +4393,11 @@ 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));
@ -4462,8 +4434,21 @@ 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, const std::string& indent) { std::ostream* stream, const TestResult& result) {
const std::string kProperties = "properties"; const std::string kProperties = "properties";
const std::string kProperty = "property"; const std::string kProperty = "property";
@ -4471,15 +4456,15 @@ void XmlUnitTestResultPrinter::OutputXmlTestProperties(
return; return;
} }
*stream << indent << "<" << kProperties << ">\n"; *stream << " <" << 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 << indent << " <" << kProperty; *stream << " <" << 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 << indent << "</" << kProperties << ">\n"; *stream << " </" << kProperties << ">\n";
} }
// End XmlUnitTestResultPrinter // End XmlUnitTestResultPrinter
@ -4518,12 +4503,6 @@ 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);
@ -4694,15 +4673,6 @@ 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));
@ -4719,6 +4689,9 @@ void JsonUnitTestResultPrinter::OutputJsonTestCaseForTestResult(
// 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.
@ -4863,16 +4836,6 @@ 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,6 +45,7 @@ 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': 28, 'tests': 26,
'failures': 5, 'failures': 5,
'disabled': 2, 'disabled': 2,
'errors': 0, 'errors': 0,
@ -323,14 +323,12 @@ 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': 125, 'line': 121,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -341,7 +339,7 @@ EXPECTED_NON_EMPTY = {
{ {
'name': 'IntValuedProperty', 'name': 'IntValuedProperty',
'file': 'gtest_xml_output_unittest_.cc', 'file': 'gtest_xml_output_unittest_.cc',
'line': 129, 'line': 125,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -352,7 +350,7 @@ EXPECTED_NON_EMPTY = {
{ {
'name': 'ThreeProperties', 'name': 'ThreeProperties',
'file': 'gtest_xml_output_unittest_.cc', 'file': 'gtest_xml_output_unittest_.cc',
'line': 133, 'line': 129,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -365,7 +363,7 @@ EXPECTED_NON_EMPTY = {
{ {
'name': 'TwoValuesForOneKeyUsesLastValue', 'name': 'TwoValuesForOneKeyUsesLastValue',
'file': 'gtest_xml_output_unittest_.cc', 'file': 'gtest_xml_output_unittest_.cc',
'line': 139, 'line': 135,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -387,7 +385,7 @@ EXPECTED_NON_EMPTY = {
{ {
'name': 'RecordProperty', 'name': 'RecordProperty',
'file': 'gtest_xml_output_unittest_.cc', 'file': 'gtest_xml_output_unittest_.cc',
'line': 144, 'line': 140,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -398,7 +396,7 @@ EXPECTED_NON_EMPTY = {
{ {
'name': 'ExternalUtilityThatCallsRecordIntValuedProperty', 'name': 'ExternalUtilityThatCallsRecordIntValuedProperty',
'file': 'gtest_xml_output_unittest_.cc', 'file': 'gtest_xml_output_unittest_.cc',
'line': 157, 'line': 153,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -411,7 +409,7 @@ EXPECTED_NON_EMPTY = {
'ExternalUtilityThatCallsRecordStringValuedProperty' 'ExternalUtilityThatCallsRecordStringValuedProperty'
), ),
'file': 'gtest_xml_output_unittest_.cc', 'file': 'gtest_xml_output_unittest_.cc',
'line': 161, 'line': 157,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -421,83 +419,6 @@ 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,
@ -510,7 +431,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': 193, 'line': 173,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -530,7 +451,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': 193, 'line': 173,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -550,7 +471,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': 200, 'line': 180,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -570,7 +491,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': 200, 'line': 180,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -591,7 +512,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': 184, 'line': 164,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -602,7 +523,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': 184, 'line': 164,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -613,7 +534,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': 185, 'line': 165,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',
@ -624,7 +545,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': 185, 'line': 165,
'status': 'RUN', 'status': 'RUN',
'result': 'COMPLETED', 'result': 'COMPLETED',
'time': '*', 'time': '*',

View File

@ -64,10 +64,6 @@
#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.
@ -121,9 +117,6 @@ 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;
}; };
@ -575,8 +568,6 @@ 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) +
@ -584,8 +575,7 @@ TEST(PrintU8StringTest, EscapesProperly) {
"hello \\xE4\\xB8\\x96\\xE7\\x95\\x8C\"", "hello \\xE4\\xB8\\x96\\xE7\\x95\\x8C\"",
Print(p)); Print(p));
} }
#endif // _MSC_VER #endif
#endif // __cpp_lib_char8_t
// const char16_t*. // const char16_t*.
TEST(PrintU16StringTest, Const) { TEST(PrintU16StringTest, Const) {
@ -1980,26 +1970,6 @@ 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_STREQ("", "SET_UP_FAIL"); } static void SetUpTestSuite() { ASSERT_EQ("", "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_STREQ("", "TEAR_DOWN_FAIL"); } static void TearDownTestSuite() { ASSERT_EQ("", "TEAR_DOWN_FAIL"); }
}; };
TEST_F(TearDownFailTest, NoopPassingTest) {} TEST_F(TearDownFailTest, NoopPassingTest) {}

View File

@ -2870,8 +2870,6 @@ 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),
@ -2896,11 +2894,6 @@ 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");
} }
@ -2924,28 +2917,11 @@ 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.
@ -3052,8 +3028,6 @@ 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),
@ -3073,12 +3047,6 @@ 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");
} }
@ -3101,28 +3069,11 @@ 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 from xml.dom import minidom, Node
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,10 +67,7 @@ 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="28" failures="5" disabled="2" errors="0" time="*" timestamp="*" name="AllTests"> <testsuites tests="26" failures="5" disabled="2" errors="0" time="*" 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" 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>
@ -135,91 +132,64 @@ 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="*"> <testsuite name="PropertyRecordingTest" tests="4" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*" SetUpTestSuite="yes" TearDownTestSuite="aye">
<properties> <testcase name="OneProperty" file="gtest_xml_output_unittest_.cc" line="121" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
<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="129" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest"> <testcase name="IntValuedProperty" file="gtest_xml_output_unittest_.cc" line="125" 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="133" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest"> <testcase name="ThreeProperties" file="gtest_xml_output_unittest_.cc" line="129" 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="139" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest"> <testcase name="TwoValuesForOneKeyUsesLastValue" file="gtest_xml_output_unittest_.cc" line="135" 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="144" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest"> <testcase name="RecordProperty" file="gtest_xml_output_unittest_.cc" line="140" 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="157" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest"> <testcase name="ExternalUtilityThatCallsRecordIntValuedProperty" file="gtest_xml_output_unittest_.cc" line="153" 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="161" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest"> <testcase name="ExternalUtilityThatCallsRecordStringValuedProperty" file="gtest_xml_output_unittest_.cc" line="157" 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="184" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" /> <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/1" file="gtest_xml_output_unittest_.cc" line="184" value_param="42" 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="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/0" file="gtest_xml_output_unittest_.cc" line="165" value_param="33" 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" /> <testcase name="AnotherTestThatHasValueParamAttribute/1" file="gtest_xml_output_unittest_.cc" line="165" 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="193" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="TypedTest/0" /> <testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="173" 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="193" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="TypedTest/1" /> <testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="173" 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="200" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/0" /> <testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="180" 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="200" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/1" /> <testcase name="HasTypeParamAttribute" file="gtest_xml_output_unittest_.cc" line="180" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/1" />
</testsuite> </testsuite>
</testsuites>""" % { </testsuites>""" % {
'stack': STACK_TRACE_TEMPLATE, 'stack': STACK_TRACE_TEMPLATE,
@ -227,10 +197,8 @@ Expected equality of these values:
} }
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="*" timestamp="*" name="AllTests"> <testsuites tests="1" failures="0" disabled="0" errors="0" time="*"
<properties> timestamp="*" name="AllTests" ad_hoc_property="42">
<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"/>
@ -238,28 +206,19 @@ 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"> <testsuites tests="3" failures="0" disabled="0" errors="0" time="*" 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" 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="*"> <testsuite name="PropertyRecordingTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*" SetUpTestSuite="yes" TearDownTestSuite="aye">
<properties> <testcase name="IntValuedProperty" file="gtest_xml_output_unittest_.cc" line="125" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
<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/TypeParameterizedTestSuite/0" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*"> <testsuite name="Single/ValueParamTest" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
<testcase name="HasTypeParamAttribute" type_param="*" file="gtest_xml_output_unittest_.cc" line="200" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/0" /> <testcase name="HasValueParamAttribute/0" file="gtest_xml_output_unittest_.cc" line="164" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
</testsuite> </testsuite>
</testsuites>""" </testsuites>"""

View File

@ -112,12 +112,8 @@ TEST(InvalidCharactersTest, InvalidCharactersInMessage) {
class PropertyRecordingTest : public Test { class PropertyRecordingTest : public Test {
public: public:
static void SetUpTestSuite() { static void SetUpTestSuite() { RecordProperty("SetUpTestSuite", "yes"); }
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");
} }
}; };
@ -162,22 +158,6 @@ 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("re2"): if not native.existing_rule("com_googlesource_code_re2"):
http_archive( http_archive(
name = "re2", name = "com_googlesource_code_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("abseil-cpp"): if not native.existing_rule("com_google_absl"):
http_archive( http_archive(
name = "abseil-cpp", name = "com_google_absl",
sha256 = "16242f394245627e508ec6bb296b433c90f8d914f73b9c026fddb905e27276e8", sha256 = "733726b8c3a6d39a4120d7e45ea8b41a434cdacde401cba500f14236c49b39dc",
strip_prefix = "abseil-cpp-20250127.0", strip_prefix = "abseil-cpp-20240116.2",
urls = ["https://github.com/abseil/abseil-cpp/releases/download/20250127.0/abseil-cpp-20250127.0.tar.gz"], urls = ["https://github.com/abseil/abseil-cpp/releases/download/20240116.2/abseil-cpp-20240116.2.tar.gz"],
) )
if not native.existing_rule("fuchsia_sdk"): if not native.existing_rule("fuchsia_sdk"):