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