summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--BUILD.bazel20
-rw-r--r--CMakeLists.txt4
-rw-r--r--MODULE.bazel8
-rw-r--r--README.md16
-rw-r--r--WORKSPACE17
-rw-r--r--ci/linux-presubmit.sh153
-rw-r--r--ci/macos-presubmit.sh20
-rw-r--r--ci/windows-presubmit.bat50
-rw-r--r--docs/_layouts/default.html14
-rw-r--r--docs/advanced.md166
-rw-r--r--docs/faq.md13
-rw-r--r--docs/gmock_cook_book.md49
-rw-r--r--docs/quickstart-bazel.md16
-rw-r--r--docs/quickstart-cmake.md6
-rw-r--r--docs/reference/actions.md7
-rw-r--r--docs/reference/matchers.md38
-rw-r--r--docs/reference/testing.md99
-rw-r--r--googlemock/include/gmock/gmock-actions.h70
-rw-r--r--googlemock/include/gmock/gmock-matchers.h333
-rw-r--r--googlemock/include/gmock/gmock-more-actions.h9
-rw-r--r--googlemock/include/gmock/gmock-spec-builders.h4
-rw-r--r--googlemock/include/gmock/internal/gmock-internal-utils.h7
-rw-r--r--googlemock/include/gmock/internal/gmock-port.h13
-rw-r--r--googlemock/src/gmock-spec-builders.cc6
-rw-r--r--googlemock/test/gmock-actions_test.cc79
-rw-r--r--googlemock/test/gmock-function-mocker_test.cc2
-rw-r--r--googlemock/test/gmock-matchers-arithmetic_test.cc183
-rw-r--r--googlemock/test/gmock-matchers-comparisons_test.cc168
-rw-r--r--googlemock/test/gmock-matchers-containers_test.cc313
-rw-r--r--googlemock/test/gmock-matchers-misc_test.cc19
-rw-r--r--googlemock/test/gmock-more-actions_test.cc83
-rw-r--r--googlemock/test/gmock-spec-builders_test.cc9
-rw-r--r--googlemock/test/gmock_output_test_golden.txt8
-rw-r--r--googletest/CMakeLists.txt3
-rw-r--r--googletest/README.md12
-rw-r--r--googletest/cmake/internal_utils.cmake2
-rw-r--r--googletest/include/gtest/gtest-assertion-result.h7
-rw-r--r--googletest/include/gtest/gtest-matchers.h29
-rw-r--r--googletest/include/gtest/gtest-param-test.h134
-rw-r--r--googletest/include/gtest/gtest-printers.h104
-rw-r--r--googletest/include/gtest/gtest-typed-test.h134
-rw-r--r--googletest/include/gtest/gtest.h11
-rw-r--r--googletest/include/gtest/internal/gtest-internal.h84
-rw-r--r--googletest/include/gtest/internal/gtest-param-util.h62
-rw-r--r--googletest/include/gtest/internal/gtest-port.h210
-rw-r--r--googletest/src/gtest-internal-inl.h4
-rw-r--r--googletest/src/gtest-port.cc4
-rw-r--r--googletest/src/gtest-printers.cc20
-rw-r--r--googletest/src/gtest.cc169
-rw-r--r--googletest/test/BUILD.bazel68
-rwxr-xr-xgoogletest/test/googletest-color-test.py1
-rw-r--r--googletest/test/googletest-death-test-test.cc2
-rw-r--r--googletest/test/googletest-fail-if-no-test-linked-test-with-disabled-test_.cc38
-rw-r--r--googletest/test/googletest-fail-if-no-test-linked-test-with-enabled-test_.cc38
-rwxr-xr-xgoogletest/test/googletest-fail-if-no-test-linked-test.py165
-rw-r--r--googletest/test/googletest-fail-if-no-test-selected-test.py91
-rwxr-xr-xgoogletest/test/googletest-filter-unittest.py19
-rw-r--r--googletest/test/googletest-json-output-unittest.py36
-rw-r--r--googletest/test/googletest-output-test-golden-lin.txt2
-rw-r--r--googletest/test/googletest-param-test-test.cc72
-rw-r--r--googletest/test/googletest-port-test.cc4
-rw-r--r--googletest/test/googletest-printers-test.cc92
-rw-r--r--googletest/test/googletest-setuptestsuite-test_.cc4
-rw-r--r--googletest/test/gtest_unittest.cc20
-rwxr-xr-xgoogletest/test/gtest_xml_output_unittest.py88
-rw-r--r--googletest/test/gtest_xml_output_unittest_.cc6
-rw-r--r--googletest_deps.bzl6
67 files changed, 2766 insertions, 977 deletions
diff --git a/BUILD.bazel b/BUILD.bazel
index 0306468..3ca5735 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -83,6 +83,10 @@ cc_library(
)
# Google Test including Google Mock
+
+# For an actual test, use `gtest` and also `gtest_main` if you depend on gtest's
+# main(). For a library, use `gtest_for_library` instead if the library can be
+# testonly.
cc_library(
name = "gtest",
srcs = glob(
@@ -147,10 +151,7 @@ cc_library(
"@abseil-cpp//absl/flags:reflection",
"@abseil-cpp//absl/flags:usage",
"@abseil-cpp//absl/strings",
- "@abseil-cpp//absl/types:any",
- "@abseil-cpp//absl/types:optional",
- "@abseil-cpp//absl/types:variant",
- "@re2//:re2",
+ "@re2",
],
"//conditions:default": [],
}) + select({
@@ -160,13 +161,22 @@ cc_library(
# Otherwise, builds targeting Fuchsia would fail to compile.
":fuchsia": [
"@fuchsia_sdk//pkg/fdio",
- "@fuchsia_sdk//pkg/syslog",
"@fuchsia_sdk//pkg/zx",
],
"//conditions:default": [],
}),
)
+# `gtest`, but testonly. See guidance on `gtest` for when to use this.
+alias(
+ name = "gtest_for_library",
+ testonly = True,
+ actual = ":gtest",
+)
+
+# Implements main() for tests using gtest. Prefer to depend on `gtest` as well
+# to ensure compliance with the layering_check Bazel feature where only the
+# direct hdrs values are available.
cc_library(
name = "gtest_main",
srcs = ["googlemock/src/gmock_main.cc"],
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 512e5c3..c784f3c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,10 +1,10 @@
# Note: CMake support is community-based. The maintainers do not use CMake
# internally.
-cmake_minimum_required(VERSION 3.13)
+cmake_minimum_required(VERSION 3.16)
project(googletest-distribution)
-set(GOOGLETEST_VERSION 1.15.2)
+set(GOOGLETEST_VERSION 1.16.0)
if(NOT CYGWIN AND NOT MSYS AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL QNX)
set(CMAKE_CXX_EXTENSIONS OFF)
diff --git a/MODULE.bazel b/MODULE.bazel
index e213d43..5d80b46 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -41,20 +41,20 @@ module(
bazel_dep(
name = "abseil-cpp",
- version = "20240116.2",
+ version = "20250814.0",
)
bazel_dep(
name = "platforms",
- version = "0.0.10",
+ version = "0.0.11",
)
bazel_dep(
name = "re2",
- version = "2024-07-02",
+ version = "2024-07-02.bcr.1",
)
bazel_dep(
name = "rules_python",
- version = "0.34.0",
+ version = "1.3.0",
dev_dependency = True,
)
diff --git a/README.md b/README.md
index 03c70a1..1584c79 100644
--- a/README.md
+++ b/README.md
@@ -2,27 +2,19 @@
### Announcements
-#### Live at Head
-
-GoogleTest now follows the
-[Abseil Live at Head philosophy](https://abseil.io/about/philosophy#upgrade-support).
-We recommend
-[updating to the latest commit in the `main` branch as often as possible](https://github.com/abseil/abseil-cpp/blob/master/FAQ.md#what-is-live-at-head-and-how-do-i-do-it).
-We do publish occasional semantic versions, tagged with
-`v${major}.${minor}.${patch}` (e.g. `v1.15.2`).
-
#### Documentation Updates
Our documentation is now live on GitHub Pages at
https://google.github.io/googletest/. We recommend browsing the documentation on
GitHub Pages rather than directly in the repository.
-#### Release 1.15.2
+#### Release 1.17.0
-[Release 1.15.2](https://github.com/google/googletest/releases/tag/v1.15.2) is
+[Release 1.17.0](https://github.com/google/googletest/releases/tag/v1.17.0) is
now available.
-The 1.15.x branch requires at least C++14.
+The 1.17.x branch
+[requires at least C++17](https://opensource.google/documentation/policies/cplusplus-support#c_language_standard).
#### Continuous Integration
diff --git a/WORKSPACE b/WORKSPACE
index 63f7681..0ae5dee 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -36,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 = "2cc26bbd53854ceb76dd42a834b1002cd4ba7f8df35440cf03482e045affc244",
+ strip_prefix = "rules_python-1.3.0",
+ url = "https://github.com/bazelbuild/rules_python/releases/download/1.3.0/rules_python-1.3.0.tar.gz",
)
-
-# https://github.com/bazelbuild/rules_python/releases/tag/0.29.0
+# https://github.com/bazelbuild/rules_python/releases/tag/1.1.0
load("@rules_python//python:repositories.bzl", "py_repositories")
py_repositories()
@@ -55,8 +54,8 @@ http_archive(
http_archive(
name = "platforms",
urls = [
- "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.10/platforms-0.0.10.tar.gz",
- "https://github.com/bazelbuild/platforms/releases/download/0.0.10/platforms-0.0.10.tar.gz",
+ "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.11/platforms-0.0.11.tar.gz",
+ "https://github.com/bazelbuild/platforms/releases/download/0.0.11/platforms-0.0.11.tar.gz",
],
- sha256 = "218efe8ee736d26a3572663b374a253c012b716d8af0c07e842e82f238a0a7ee",
+ sha256 = "29742e87275809b5e598dc2f04d86960cc7a55b3067d97221c9abbc9926bff0f",
)
diff --git a/ci/linux-presubmit.sh b/ci/linux-presubmit.sh
index 6d2b3fb..c4ad579 100644
--- a/ci/linux-presubmit.sh
+++ b/ci/linux-presubmit.sh
@@ -31,62 +31,91 @@
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:20250430"
+readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20250430"
if [[ -z ${GTEST_ROOT:-} ]]; then
GTEST_ROOT="$(realpath $(dirname ${0})/..)"
fi
+# Use Bazel Vendor mode to reduce reliance on external dependencies.
+# See https://bazel.build/external/vendor and the Dockerfile for
+# an explaination of how this works.
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f "${KOKORO_GFILE_DIR}/distdir/googletest_vendor.tar.gz" ]]; then
+ DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly --env=BAZEL_VENDOR_ARCHIVE=/distdir/googletest_vendor.tar.gz ${DOCKER_EXTRA_ARGS:-}"
+ BAZEL_EXTRA_ARGS="--vendor_dir=/googletest_vendor ${BAZEL_EXTRA_ARGS:-}"
+fi
+
if [[ -z ${STD:-} ]]; then
- STD="c++14 c++17 c++20"
+ STD="c++17 c++20 c++23"
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" \
+ ${DOCKER_EXTRA_ARGS:-} \
${LINUX_GCC_FLOOR_CONTAINER} \
+ /bin/bash --login -c "
/usr/local/bin/bazel test ... \
- --copt="-Wall" \
- --copt="-Werror" \
- --copt="-Wuninitialized" \
- --copt="-Wundef" \
- --copt="-Wno-error=pragmas" \
+ --copt=\"-Wall\" \
+ --copt=\"-Werror\" \
+ --copt=\"-Wuninitialized\" \
+ --copt=\"-Wundef\" \
+ --copt=\"-Wno-error=pragmas\" \
+ --enable_bzlmod=false \
--features=external_include_paths \
--keep_going \
--show_timestamps \
- --test_output=errors
+ --test_output=errors \
+ ${BAZEL_EXTRA_ARGS:-}"
# Test GCC
for std in ${STD}; do
@@ -97,18 +126,21 @@ for std in ${STD}; do
--rm \
--env="CC=/usr/local/bin/gcc" \
--env="BAZEL_CXXOPTS=-std=${std}" \
+ ${DOCKER_EXTRA_ARGS:-} \
${LINUX_LATEST_CONTAINER} \
- /usr/local/bin/bazel test ... \
- --copt="-Wall" \
- --copt="-Werror" \
- --copt="-Wuninitialized" \
- --copt="-Wundef" \
- --define="absl=${absl}" \
- --enable_bzlmod=true \
- --features=external_include_paths \
- --keep_going \
- --show_timestamps \
- --test_output=errors
+ /bin/bash --login -c "
+ /usr/local/bin/bazel test ... \
+ --copt=\"-Wall\" \
+ --copt=\"-Werror\" \
+ --copt=\"-Wuninitialized\" \
+ --copt=\"-Wundef\" \
+ --define=\"absl=${absl}\" \
+ --enable_bzlmod=true \
+ --features=external_include_paths \
+ --keep_going \
+ --show_timestamps \
+ --test_output=errors \
+ ${BAZEL_EXTRA_ARGS:-}"
done
done
@@ -121,19 +153,22 @@ for std in ${STD}; do
--rm \
--env="CC=/opt/llvm/clang/bin/clang" \
--env="BAZEL_CXXOPTS=-std=${std}" \
+ ${DOCKER_EXTRA_ARGS:-} \
${LINUX_LATEST_CONTAINER} \
- /usr/local/bin/bazel test ... \
- --copt="--gcc-toolchain=/usr/local" \
- --copt="-Wall" \
- --copt="-Werror" \
- --copt="-Wuninitialized" \
- --copt="-Wundef" \
- --define="absl=${absl}" \
- --enable_bzlmod=true \
- --features=external_include_paths \
- --keep_going \
- --linkopt="--gcc-toolchain=/usr/local" \
- --show_timestamps \
- --test_output=errors
+ /bin/bash --login -c "
+ /usr/local/bin/bazel test ... \
+ --copt=\"--gcc-toolchain=/usr/local\" \
+ --copt=\"-Wall\" \
+ --copt=\"-Werror\" \
+ --copt=\"-Wuninitialized\" \
+ --copt=\"-Wundef\" \
+ --define=\"absl=${absl}\" \
+ --enable_bzlmod=true \
+ --features=external_include_paths \
+ --keep_going \
+ --linkopt=\"--gcc-toolchain=/usr/local\" \
+ --show_timestamps \
+ --test_output=errors \
+ ${BAZEL_EXTRA_ARGS:-}"
done
done
diff --git a/ci/macos-presubmit.sh b/ci/macos-presubmit.sh
index 70eaa74..63cf814 100644
--- a/ci/macos-presubmit.sh
+++ b/ci/macos-presubmit.sh
@@ -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.2.1-darwin-x86_64"
if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]]; then
BAZEL_BIN="${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN}"
chmod +x ${BAZEL_BIN}
@@ -61,17 +64,24 @@ else
BAZEL_BIN="bazel"
fi
+# Use Bazel Vendor mode to reduce reliance on external dependencies.
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f "${KOKORO_GFILE_DIR}/distdir/googletest_vendor.tar.gz" ]]; then
+ tar -xf "${KOKORO_GFILE_DIR}/distdir/googletest_vendor.tar.gz" -C "${TMP}/"
+ BAZEL_EXTRA_ARGS="--vendor_dir=\"${TMP}/googletest_vendor\" ${BAZEL_EXTRA_ARGS:-}"
+fi
+
cd ${GTEST_ROOT}
for absl in 0 1; do
${BAZEL_BIN} test ... \
--copt="-Wall" \
--copt="-Werror" \
--copt="-Wundef" \
- --cxxopt="-std=c++14" \
+ --cxxopt="-std=c++17" \
--define="absl=${absl}" \
--enable_bzlmod=true \
--features=external_include_paths \
--keep_going \
--show_timestamps \
- --test_output=errors
+ --test_output=errors \
+ ${BAZEL_EXTRA_ARGS:-}
done
diff --git a/ci/windows-presubmit.bat b/ci/windows-presubmit.bat
index 1adc1a1..267e2e9 100644
--- a/ci/windows-presubmit.bat
+++ b/ci/windows-presubmit.bat
@@ -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.2.1-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,8 +37,8 @@ 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
@@ -50,14 +47,39 @@ RMDIR /S /Q cmake_msvc2022
:: because of Windows limitations on path length.
:: --output_user_root=C:\tmp causes Bazel to use a shorter path.
SET BAZEL_VS=C:\Program Files\Microsoft Visual Studio\2022\Community
+
+:: Use Bazel Vendor mode to reduce reliance on external dependencies.
+IF EXIST "%KOKORO_GFILE_DIR%\distdir\googletest_vendor.tar.gz" (
+ tar --force-local -xf "%KOKORO_GFILE_DIR%\distdir\googletest_vendor.tar.gz" -C c:
+ SET VENDOR_FLAG=--vendor_dir=c:\googletest_vendor
+) ELSE (
+ SET VENDOR_FLAG=
+)
+
+:: C++17
+%BAZEL_EXE% ^
+ --output_user_root=C:\tmp ^
+ test ... ^
+ --compilation_mode=dbg ^
+ --copt=/std:c++17 ^
+ --copt=/WX ^
+ --enable_bzlmod=true ^
+ --keep_going ^
+ --test_output=errors ^
+ --test_tag_filters=-no_test_msvc2017 ^
+ %VENDOR_FLAG%
+IF %errorlevel% neq 0 EXIT /B 1
+
+:: C++20
%BAZEL_EXE% ^
--output_user_root=C:\tmp ^
test ... ^
--compilation_mode=dbg ^
- --copt=/std:c++14 ^
+ --copt=/std:c++20 ^
--copt=/WX ^
--enable_bzlmod=true ^
--keep_going ^
--test_output=errors ^
- --test_tag_filters=-no_test_msvc2017
+ --test_tag_filters=-no_test_msvc2017 ^
+ %VENDOR_FLAG%
IF %errorlevel% neq 0 EXIT /B 1
diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html
index c7f331b..f0ae474 100644
--- a/docs/_layouts/default.html
+++ b/docs/_layouts/default.html
@@ -7,15 +7,15 @@
{% seo %}
<link rel="stylesheet" href="{{ "/assets/css/style.css?v=" | append: site.github.build_revision | relative_url }}">
+ <!-- Google tag (gtag.js) -->
+ <script async src="https://www.googletagmanager.com/gtag/js?id=G-9PTP6FW1M5"></script>
<script>
- window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
- ga('create', 'UA-197576187-1', { 'storage': 'none' });
- ga('set', 'referrer', document.referrer.split('?')[0]);
- ga('set', 'location', window.location.href.split('?')[0]);
- ga('set', 'anonymizeIp', true);
- ga('send', 'pageview');
+ window.dataLayer = window.dataLayer || [];
+ function gtag(){dataLayer.push(arguments);}
+ gtag('js', new Date());
+
+ gtag('config', 'G-9PTP6FW1M5');
</script>
- <script async src='https://www.google-analytics.com/analytics.js'></script>
</head>
<body>
<div class="sidebar">
diff --git a/docs/advanced.md b/docs/advanced.md
index 7e998cc..d703a7b 100644
--- a/docs/advanced.md
+++ b/docs/advanced.md
@@ -349,7 +349,8 @@ void AbslStringify(Sink& sink, EnumWithStringify e) {
{: .callout .note}
Note: `AbslStringify()` utilizes a generic "sink" buffer to construct its
string. For more information about supported operations on `AbslStringify()`'s
-sink, see go/abslstringify.
+sink, see
+[the `AbslStringify()` documentation](https://abseil.io/docs/cpp/guides/abslstringify).
`AbslStringify()` can also use `absl::StrFormat`'s catch-all `%v` type specifier
within its own format strings to perform type deduction. `Point` above could be
@@ -403,7 +404,53 @@ EXPECT_TRUE(IsCorrectPointIntVector(point_ints))
```
For more details regarding `AbslStringify()` and its integration with other
-libraries, see go/abslstringify.
+libraries, see
+[the documentation](https://abseil.io/docs/cpp/guides/abslstringify).
+
+## Regular Expression Syntax
+
+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
@@ -416,7 +463,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 +509,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 +556,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 +735,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++
@@ -1442,17 +1450,19 @@ are two cases to consider:
To test them, we use the following special techniques:
* Both static functions and definitions/declarations in an unnamed namespace
- are only visible within the same translation unit. To test them, you can
- `#include` the entire `.cc` file being tested in your `*_test.cc` file.
- (#including `.cc` files is not a good way to reuse code - you should not do
- this in production code!)
-
- However, a better approach is to move the private code into the
- `foo::internal` namespace, where `foo` is the namespace your project
- normally uses, and put the private declarations in a `*-internal.h` file.
- Your production `.cc` files and your tests are allowed to include this
- internal header, but your clients are not. This way, you can fully test your
- internal implementation without leaking it to your clients.
+ are only visible within the same translation unit. To test them, move the
+ private code into the `foo::internal` namespace, where `foo` is the
+ namespace your project normally uses, and put the private declarations in a
+ `*-internal.h` file. Your production `.cc` files and your tests are allowed
+ to include this internal header, but your clients are not. This way, you can
+ fully test your internal implementation without leaking it to your clients.
+
+{: .callout .note}
+NOTE: It is also technically *possible* to `#include` the entire `.cc` file
+being tested in your `*_test.cc` file to test static functions and
+definitions/declarations in an unnamed namespace. However, this technique is
+**not recommended** by this documentation and it is only presented here for the
+sake of completeness.
* Private class members are only accessible from within the class or by
friends. To access a class' private members, you can declare your test
@@ -1465,10 +1475,7 @@ To test them, we use the following special techniques:
Another way to test private members is to refactor them into an
implementation class, which is then declared in a `*-internal.h` file. Your
- clients aren't allowed to include this header but your tests can. Such is
- called the
- [Pimpl](https://www.gamedev.net/articles/programming/general-and-gameplay-programming/the-c-pimpl-r1794/)
- (Private Implementation) idiom.
+ clients aren't allowed to include this header but your tests can.
Or, you can declare an individual test as a friend of your class by adding
this line in the class body:
@@ -1923,6 +1930,35 @@ the `--gtest_also_run_disabled_tests` flag or set the
You can combine this with the `--gtest_filter` flag to further select which
disabled tests to run.
+### Enforcing Having At Least One Test Case
+
+A not uncommon programmer mistake is to write a test program that has no test
+case linked in. This can happen, for example, when you put test case definitions
+in a library and the library is not marked as "always link".
+
+To catch such mistakes, run the test program with the
+`--gtest_fail_if_no_test_linked` flag or set the `GTEST_FAIL_IF_NO_TEST_LINKED`
+environment variable to a value other than `0`. Now the program will fail if no
+test case is linked in.
+
+Note that *any* test case linked in makes the program valid for the purpose of
+this check. In particular, even a disabled test case suffices.
+
+### Enforcing Running At Least One Test Case
+
+In addition to enforcing that tests are defined in the binary with
+`--gtest_fail_if_no_test_linked`, it is also possible to enforce that a test
+case was actually executed to ensure that resources are not consumed by tests
+that do nothing.
+
+To catch such optimization opportunities, run the test program with the
+`--gtest_fail_if_no_test_selected` flag or set the
+`GTEST_FAIL_IF_NO_TEST_SELECTED` environment variable to a value other than `0`.
+
+A test is considered selected if it begins to run, even if it is later skipped
+via `GTEST_SKIP`. Thus, `DISABLED` tests do not count as selected and neither do
+tests that are not matched by `--gtest_filter`.
+
### Repeating the Tests
Once in a while you'll run into a test whose result is hit-or-miss. Perhaps it
@@ -2382,7 +2418,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
diff --git a/docs/faq.md b/docs/faq.md
index c7d10b5..4e95838 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -511,19 +511,6 @@ However, there are cases where you have to define your own:
list of the constructor. (Early versions of `gcc` doesn't force you to
initialize the const member. It's a bug that has been fixed in `gcc 4`.)
-## Why does ASSERT_DEATH complain about previous threads that were already joined?
-
-With the Linux pthread library, there is no turning back once you cross the line
-from a single thread to multiple threads. The first time you create a thread, a
-manager thread is created in addition, so you get 3, not 2, threads. Later when
-the thread you create joins the main thread, the thread count decrements by 1,
-but the manager thread will never be killed, so you still have 2 threads, which
-means you cannot safely run a death test.
-
-The new NPTL thread library doesn't suffer from this problem, as it doesn't
-create a manager thread. However, if you don't control which machine your test
-runs on, you shouldn't depend on this.
-
## Why does GoogleTest require the entire test suite, instead of individual tests, to be named `*DeathTest` when it uses `ASSERT_DEATH`?
GoogleTest does not interleave tests from different test suites. That is, it
diff --git a/docs/gmock_cook_book.md b/docs/gmock_cook_book.md
index 948abe9..9e59b4c 100644
--- a/docs/gmock_cook_book.md
+++ b/docs/gmock_cook_book.md
@@ -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.
@@ -3567,10 +3567,15 @@ just based on the number of parameters).
### Writing New Monomorphic Matchers
-A matcher of argument type `T` implements the matcher interface for `T` and does
-two things: it tests whether a value of type `T` matches the matcher, and can
-describe what kind of values it matches. The latter ability is used for
-generating readable error messages when expectations are violated.
+A matcher of type `testing::Matcher<T>` implements the matcher interface for `T`
+and does two things: it tests whether a value of type `T` matches the matcher,
+and can describe what kind of values it matches. The latter ability is used for
+generating readable error messages when expectations are violated. Some matchers
+can even explain why it matches or doesn't match a certain value, which can be
+helpful when the reason isn't obvious.
+
+Because a matcher of type `testing::Matcher<T>` for a particular type `T` can
+only be used to match a value of type `T`, we call it "monomorphic."
A matcher of `T` must declare a typedef like:
@@ -3662,8 +3667,16 @@ instead of `std::ostream*`.
### Writing New Polymorphic Matchers
-Expanding what we learned above to *polymorphic* matchers is now just as simple
-as adding templates in the right place.
+Unlike a monomorphic matcher, which can only be used to match a value of a
+particular type, a *polymorphic* matcher is one that can be used to match values
+of multiple types. For example, `Eq(5)` is a polymorhpic matcher as it can be
+used to match an `int`, a `double`, a `float`, and so on. You should think of a
+polymorphic matcher as a *matcher factory* as opposed to a
+`testing::Matcher<SomeType>` - itself is not an actual matcher, but can be
+implicitly converted to a `testing::Matcher<SomeType>` depending on the context.
+
+Expanding what we learned above to polymorphic matchers is now as simple as
+adding templates in the right place.
```cpp
@@ -3789,6 +3802,26 @@ virtual.
Like in a monomorphic matcher, you may explain the match result by streaming
additional information to the `listener` argument in `MatchAndExplain()`.
+### Implementing Composite Matchers {#CompositeMatchers}
+
+Sometimes we want to define a matcher that takes other matchers as parameters.
+For example, `DistanceFrom(target, m)` is a polymorphic matcher that takes a
+matcher `m` as a parameter. It tests that the distance from `target` to the
+value being matched satisfies sub-matcher `m`.
+
+If you are implementing such a composite matcher, you'll need to generate the
+description of the matcher based on the description(s) of its sub-matcher(s).
+You can see the implementation of `DistanceFrom()` in
+`googlemock/include/gmock/gmock-matchers.h` for an example. In particular, pay
+attention to `DistanceFromMatcherImpl`. Notice that it stores the sub-matcher as
+a `const Matcher<const Distance&> distance_matcher_` instead of a polymorphic
+matcher - this allows it to call `distance_matcher_.DescribeTo(os)` to describe
+the sub-matcher. If the sub-matcher is stored as a polymorphic matcher instead,
+it would not be possible to get its description as in general polymorphic
+matchers don't know how to describe themselves - they are matcher factories
+instead of actual matchers; only after being converted to `Matcher<SomeType>`
+can they be described.
+
### Writing New Cardinalities
A cardinality is used in `Times()` to tell gMock how many times you expect a
diff --git a/docs/quickstart-bazel.md b/docs/quickstart-bazel.md
index 5750f02..04fa829 100644
--- a/docs/quickstart-bazel.md
+++ b/docs/quickstart-bazel.md
@@ -9,7 +9,7 @@ we recommend this tutorial as a starting point.
To complete this tutorial, you'll need:
* A compatible operating system (e.g. Linux, macOS, Windows).
-* A compatible C++ compiler that supports at least C++14.
+* A compatible C++ compiler that supports at least C++17.
* [Bazel](https://bazel.build/) 7.0 or higher, the preferred build system used
by the GoogleTest team.
@@ -48,7 +48,7 @@ with the following content:
# Choose the most recent version available at
# https://registry.bazel.build/modules/googletest
-bazel_dep(name = "googletest", version = "1.15.2")
+bazel_dep(name = "googletest", version = "1.17.0")
```
Now you're ready to build C++ code that uses GoogleTest.
@@ -99,16 +99,16 @@ files, see the
[Bazel C++ Tutorial](https://docs.bazel.build/versions/main/tutorial/cpp.html).
{: .callout .note}
-NOTE: In the example below, we assume Clang or GCC and set `--cxxopt=-std=c++14`
-to ensure that GoogleTest is compiled as C++14 instead of the compiler's default
-setting (which could be C++11). For MSVC, the equivalent would be
-`--cxxopt=/std:c++14`. See [Supported Platforms](platforms.md) for more details
-on supported language versions.
+NOTE: In the example below, we assume Clang or GCC and set `--cxxopt=-std=c++17`
+to ensure that GoogleTest is compiled as C++17 instead of the compiler's default
+setting. For MSVC, the equivalent would be `--cxxopt=/std:c++17`. See
+[Supported Platforms](platforms.md) for more details on supported language
+versions.
Now you can build and run your test:
<pre>
-<strong>$ bazel test --cxxopt=-std=c++14 --test_output=all //:hello_test</strong>
+<strong>$ bazel test --cxxopt=-std=c++17 --test_output=all //:hello_test</strong>
INFO: Analyzed target //:hello_test (26 packages loaded, 362 targets configured).
INFO: Found 1 test target...
INFO: From Testing //:hello_test:
diff --git a/docs/quickstart-cmake.md b/docs/quickstart-cmake.md
index 4e422b7..bcdb1b5 100644
--- a/docs/quickstart-cmake.md
+++ b/docs/quickstart-cmake.md
@@ -10,7 +10,7 @@ this tutorial as a starting point. If your project uses Bazel, see the
To complete this tutorial, you'll need:
* A compatible operating system (e.g. Linux, macOS, Windows).
-* A compatible C++ compiler that supports at least C++14.
+* A compatible C++ compiler that supports at least C++17.
* [CMake](https://cmake.org/) and a compatible build tool for building the
project.
* Compatible build tools include
@@ -52,8 +52,8 @@ To do this, in your project directory (`my_project`), create a file named
cmake_minimum_required(VERSION 3.14)
project(my_project)
-# GoogleTest requires at least C++14
-set(CMAKE_CXX_STANDARD 14)
+# GoogleTest requires at least C++17
+set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
include(FetchContent)
diff --git a/docs/reference/actions.md b/docs/reference/actions.md
index ab81a12..2ca3a9f 100644
--- a/docs/reference/actions.md
+++ b/docs/reference/actions.md
@@ -24,7 +24,8 @@ provided by GoogleTest. All actions are defined in the `::testing` namespace.
| :--------------------------------- | :-------------------------------------- |
| `Assign(&variable, value)` | Assign `value` to variable. |
| `DeleteArg<N>()` | Delete the `N`-th (0-based) argument, which must be a pointer. |
-| `SaveArg<N>(pointer)` | Save the `N`-th (0-based) argument to `*pointer`. |
+| `SaveArg<N>(pointer)` | Save the `N`-th (0-based) argument to `*pointer` by copy-assignment. |
+| `SaveArgByMove<N>(pointer)` | Save the `N`-th (0-based) argument to `*pointer` by move-assignment. |
| `SaveArgPointee<N>(pointer)` | Save the value pointed to by the `N`-th (0-based) argument to `*pointer`. |
| `SetArgReferee<N>(value)` | Assign `value` to the variable referenced by the `N`-th (0-based) argument. |
| `SetArgPointee<N>(value)` | Assign `value` to the variable pointed by the `N`-th (0-based) argument. |
@@ -47,8 +48,8 @@ functor, or lambda.
| `InvokeWithoutArgs(object_pointer, &class::method)` | Invoke the method on the object, which takes no arguments. |
| `InvokeArgument<N>(arg1, arg2, ..., argk)` | Invoke the mock function's `N`-th (0-based) argument, which must be a function or a functor, with the `k` arguments. |
-The return value of the invoked function is used as the return value of the
-action.
+The return value of the invoked function (except `InvokeArgument`) is used as
+the return value of the action.
When defining a callable to be used with `Invoke*()`, you can declare any unused
parameters as `Unused`:
diff --git a/docs/reference/matchers.md b/docs/reference/matchers.md
index 243e3f9..8b3d140 100644
--- a/docs/reference/matchers.md
+++ b/docs/reference/matchers.md
@@ -42,6 +42,8 @@ Matcher | Description
| `Lt(value)` | `argument < value` |
| `Ne(value)` | `argument != value` |
| `IsFalse()` | `argument` evaluates to `false` in a Boolean context. |
+| `DistanceFrom(target, m)` | The distance between `argument` and `target` (computed by `abs(argument - target)`) matches `m`. |
+| `DistanceFrom(target, get_distance, m)` | The distance between `argument` and `target` (computed by `get_distance(argument, target)`) matches `m`. |
| `IsTrue()` | `argument` evaluates to `true` in a Boolean context. |
| `IsNull()` | `argument` is a `NULL` pointer (raw or smart). |
| `NotNull()` | `argument` is a non-null pointer (raw or smart). |
@@ -109,6 +111,33 @@ use the regular expression syntax defined
[here](../advanced.md#regular-expression-syntax). All of these matchers, except
`ContainsRegex()` and `MatchesRegex()` work for wide strings as well.
+## Exception Matchers
+
+| Matcher | Description |
+| :---------------------------------------- | :------------------------------- |
+| `Throws<E>()` | The `argument` is a callable object that, when called, throws an exception of the expected type `E`. |
+| `Throws<E>(m)` | The `argument` is a callable object that, when called, throws an exception of type `E` that satisfies the matcher `m`. |
+| `ThrowsMessage<E>(m)` | The `argument` is a callable object that, when called, throws an exception of type `E` with a message that satisfies the matcher `m`. |
+
+Examples:
+
+```cpp
+auto argument = [] { throw std::runtime_error("error msg"); };
+
+// Checks if the lambda throws a `std::runtime_error`.
+EXPECT_THAT(argument, Throws<std::runtime_error>());
+
+// Checks if the lambda throws a `std::runtime_error` with a specific message
+// that matches "error msg".
+EXPECT_THAT(argument,
+ Throws<std::runtime_error>(Property(&std::runtime_error::what,
+ Eq("error msg"))));
+
+// Checks if the lambda throws a `std::runtime_error` with a message that
+// contains "msg".
+EXPECT_THAT(argument, ThrowsMessage<std::runtime_error>(HasSubstr("msg")));
+```
+
## Container Matchers
Most STL-style containers support `==`, so you can use `Eq(expected_container)`
@@ -171,6 +200,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 +223,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 |
diff --git a/docs/reference/testing.md b/docs/reference/testing.md
index 3ed5211..ea43721 100644
--- a/docs/reference/testing.md
+++ b/docs/reference/testing.md
@@ -110,7 +110,7 @@ namespace:
| `ValuesIn(container)` or `ValuesIn(begin,end)` | Yields values from a C-style array, an STL-style container, or an iterator range `[begin, end)`. |
| `Bool()` | Yields sequence `{false, true}`. |
| `Combine(g1, g2, ..., gN)` | Yields as `std::tuple` *n*-tuples all combinations (Cartesian product) of the values generated by the given *n* generators `g1`, `g2`, ..., `gN`. |
-| `ConvertGenerator<T>(g)` | Yields values generated by generator `g`, `static_cast` to `T`. |
+| `ConvertGenerator<T>(g)` or `ConvertGenerator(g, func)` | Yields values generated by generator `g`, `static_cast` from `T`. (Note: `T` might not be what you expect. See [*Using ConvertGenerator*](#using-convertgenerator) below.) The second overload uses `func` to perform the conversion. |
The optional last argument *`name_generator`* is a function or functor that
generates custom test name suffixes based on the test parameters. The function
@@ -137,6 +137,103 @@ For more information, see
See also
[`GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST`](#GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST).
+###### Using `ConvertGenerator`
+
+The functions listed in the table above appear to return generators that create
+values of the desired types, but this is not generally the case. Rather, they
+typically return factory objects that convert to the the desired generators.
+This affords some flexibility in allowing you to specify values of types that
+are different from, yet implicitly convertible to, the actual parameter type
+required by your fixture class.
+
+For example, you can do the following with a fixture that requires an `int`
+parameter:
+
+```cpp
+INSTANTIATE_TEST_SUITE_P(MyInstantiation, MyTestSuite,
+ testing::Values(1, 1.2)); // Yes, Values() supports heterogeneous argument types.
+```
+
+It might seem obvious that `1.2` &mdash; a `double` &mdash; will be converted to
+an `int` but in actuality it requires some template gymnastics involving the
+indirection described in the previous paragraph.
+
+What if your parameter type is not implicitly convertible from the generated
+type but is *explicitly* convertible? There will be no automatic conversion, but
+you can force it by applying `ConvertGenerator<T>`. The compiler can
+automatically deduce the target type (your fixture's parameter type), but
+because of the aforementioned indirection it cannot decide what the generated
+type should be. You need to tell it, by providing the type `T` explicitly. Thus
+`T` should not be your fixture's parameter type, but rather an intermediate type
+that is supported by the factory object, and which can be `static_cast` to the
+fixture's parameter type:
+
+```cpp
+// The fixture's parameter type.
+class MyParam {
+ public:
+ // Explicit converting ctor.
+ explicit MyParam(const std::tuple<int, bool>& t);
+ ...
+};
+
+INSTANTIATE_TEST_SUITE_P(MyInstantiation, MyTestSuite,
+ ConvertGenerator<std::tuple<int, bool>>(Combine(Values(0.1, 1.2), Bool())));
+```
+
+In this example `Combine` supports the generation of `std::tuple<int, bool>>`
+objects (even though the provided values for the first tuple element are
+`double`s) and those `tuple`s get converted into `MyParam` objects by virtue of
+the call to `ConvertGenerator`.
+
+For parameter types that are not convertible from the generated types you can
+provide a callable that does the conversion. The callable accepts an object of
+the generated type and returns an object of the fixture's parameter type. The
+generated type can often be deduced by the compiler from the callable's call
+signature so you do not usually need specify it explicitly (but see a caveat
+below).
+
+```cpp
+// The fixture's parameter type.
+class MyParam {
+ public:
+ MyParam(int, bool);
+ ...
+};
+
+INSTANTIATE_TEST_SUITE_P(MyInstantiation, MyTestSuite,
+ ConvertGenerator(Combine(Values(1, 1.2), Bool()),
+ [](const std::tuple<int, bool>& t){
+ const auto [i, b] = t;
+ return MyParam(i, b);
+ }));
+```
+
+The callable may be anything that can be used to initialize a `std::function`
+with the appropriate call signature. Note the callable's return object gets
+`static_cast` to the fixture's parameter type, so it does not have to be of that
+exact type, only convertible to it.
+
+**Caveat:** Consider the following example.
+
+```cpp
+INSTANTIATE_TEST_SUITE_P(MyInstantiation, MyTestSuite,
+ ConvertGenerator(Values(std::string("s")), [](std::string_view s) { ... }));
+```
+
+The `string` argument gets copied into the factory object returned by `Values`.
+Then, because the generated type deduced from the lambda is `string_view`, the
+factory object spawns a generator that holds a `string_view` referencing that
+`string`. Unfortunately, by the time this generator gets invoked, the factory
+object is gone and the `string_view` is dangling.
+
+To overcome this problem you can specify the generated type explicitly:
+`ConvertGenerator<std::string>(Values(std::string("s")), [](std::string_view s)
+{ ... })`. Alternatively, you can change the lambda's signature to take a
+`std::string` or a `const std::string&` (the latter will not leave you with a
+dangling reference because the type deduction strips off the reference and the
+`const`).
+
### TYPED_TEST_SUITE {#TYPED_TEST_SUITE}
`TYPED_TEST_SUITE(`*`TestFixtureName`*`,`*`Types`*`)`
diff --git a/googlemock/include/gmock/gmock-actions.h b/googlemock/include/gmock/gmock-actions.h
index aa47079..2746edd 100644
--- a/googlemock/include/gmock/gmock-actions.h
+++ b/googlemock/include/gmock/gmock-actions.h
@@ -835,6 +835,10 @@ class Action<R(Args...)> {
Result operator()(const InArgs&...) const {
return function_impl();
}
+ template <typename... InArgs>
+ Result operator()(const InArgs&...) {
+ return function_impl();
+ }
FunctionImpl function_impl;
};
@@ -1451,6 +1455,30 @@ struct WithArgsAction {
return OA{std::move(inner_action)};
}
+ // As above, but in the case where we want to create a OnceAction from a const
+ // WithArgsAction. This is fine as long as the inner action doesn't need to
+ // move any of its state to create a OnceAction.
+ template <
+ typename R, typename... Args,
+ typename std::enable_if<
+ std::is_convertible<const InnerAction&,
+ OnceAction<R(internal::TupleElement<
+ I, std::tuple<Args...>>...)>>::value,
+ int>::type = 0>
+ operator OnceAction<R(Args...)>() const& { // NOLINT
+ struct OA {
+ OnceAction<InnerSignature<R, Args...>> inner_action;
+
+ R operator()(Args&&... args) && {
+ return std::move(inner_action)
+ .Call(std::get<I>(
+ std::forward_as_tuple(std::forward<Args>(args)...))...);
+ }
+ };
+
+ return OA{inner_action};
+ }
+
template <
typename R, typename... Args,
typename std::enable_if<
@@ -1703,9 +1731,8 @@ template <size_t k>
struct ReturnArgAction {
template <typename... Args,
typename = typename std::enable_if<(k < sizeof...(Args))>::type>
- auto operator()(Args&&... args) const
- -> decltype(std::get<k>(
- std::forward_as_tuple(std::forward<Args>(args)...))) {
+ auto operator()(Args&&... args) const -> decltype(std::get<k>(
+ std::forward_as_tuple(std::forward<Args>(args)...))) {
return std::get<k>(std::forward_as_tuple(std::forward<Args>(args)...));
}
};
@@ -1721,6 +1748,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;
@@ -1829,6 +1866,13 @@ struct RethrowAction {
// EXPECT_CALL(mock, Bar(5, _, _)).WillOnce(Invoke(DistanceToOrigin));
typedef internal::IgnoredValue Unused;
+// Deprecated single-argument DoAll.
+template <typename Action>
+GMOCK_DEPRECATE_AND_INLINE()
+typename std::decay<Action>::type DoAll(Action&& action) {
+ return std::forward<Action>(action);
+}
+
// Creates an action that does actions a1, a2, ..., sequentially in
// each invocation. All but the last action will have a readonly view of the
// arguments.
@@ -1998,6 +2042,7 @@ PolymorphicAction<internal::SetErrnoAndReturnAction<T>> SetErrnoAndReturn(
// wrapper objects.
// This function exists for backwards compatibility.
template <typename FunctionImpl>
+GMOCK_DEPRECATE_AND_INLINE()
typename std::decay<FunctionImpl>::type Invoke(FunctionImpl&& function_impl) {
return std::forward<FunctionImpl>(function_impl);
}
@@ -2070,6 +2115,13 @@ internal::SaveArgAction<k, Ptr> SaveArg(Ptr pointer) {
return {pointer};
}
+// Action SaveArgByMove<k>(pointer) moves the k-th (0-based) argument of the
+// mock function into *pointer.
+template <size_t k, typename Ptr>
+internal::SaveArgByMoveAction<k, Ptr> SaveArgByMove(Ptr pointer) {
+ return {pointer};
+}
+
// Action SaveArgPointee<k>(pointer) saves the value pointed to
// by the k-th (0-based) argument of the mock function to *pointer.
template <size_t k, typename Ptr>
@@ -2213,9 +2265,9 @@ template <typename F, typename Impl>
}
#define GMOCK_INTERNAL_ARG_UNUSED(i, data, el) \
- , GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED const arg##i##_type& arg##i
-#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_ \
- GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED const args_type& args GMOCK_PP_REPEAT( \
+ , [[maybe_unused]] const arg##i##_type& arg##i
+#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_ \
+ [[maybe_unused]] const args_type& args GMOCK_PP_REPEAT( \
GMOCK_INTERNAL_ARG_UNUSED, , 10)
#define GMOCK_INTERNAL_ARG(i, data, el) , const arg##i##_type& arg##i
@@ -2280,8 +2332,8 @@ template <typename F, typename Impl>
std::shared_ptr<const gmock_Impl> impl_; \
}; \
template <GMOCK_ACTION_TYPENAME_PARAMS_(params)> \
- inline full_name<GMOCK_ACTION_TYPE_PARAMS_(params)> name( \
- GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) GTEST_MUST_USE_RESULT_; \
+ [[nodiscard]] inline full_name<GMOCK_ACTION_TYPE_PARAMS_(params)> name( \
+ GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)); \
template <GMOCK_ACTION_TYPENAME_PARAMS_(params)> \
inline full_name<GMOCK_ACTION_TYPE_PARAMS_(params)> name( \
GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) { \
@@ -2316,7 +2368,7 @@ template <typename F, typename Impl>
return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \
}; \
}; \
- inline name##Action name() GTEST_MUST_USE_RESULT_; \
+ [[nodiscard]] inline name##Action name(); \
inline name##Action name() { return name##Action(); } \
template <typename function_type, typename return_type, typename args_type, \
GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \
diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h
index 8f82b27..236d3e5 100644
--- a/googlemock/include/gmock/gmock-matchers.h
+++ b/googlemock/include/gmock/gmock-matchers.h
@@ -257,7 +257,7 @@
#include <algorithm>
#include <cmath>
-#include <exception>
+#include <cstddef>
#include <functional>
#include <initializer_list>
#include <ios>
@@ -267,12 +267,12 @@
#include <ostream> // NOLINT
#include <sstream>
#include <string>
+#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>
#include "gmock/internal/gmock-internal-utils.h"
-#include "gmock/internal/gmock-port.h"
#include "gmock/internal/gmock-pp.h"
#include "gtest/gtest.h"
@@ -375,11 +375,16 @@ class MatcherCastImpl {
// M can't be implicitly converted to Matcher<T>, so M isn't a polymorphic
// matcher. It's a value of a type implicitly convertible to T. Use direct
- // initialization to create a matcher.
+ // initialization or `ImplicitCastEqMatcher` to create a matcher.
static Matcher<T> CastImpl(const M& value,
std::false_type /* convertible_to_matcher */,
std::true_type /* convertible_to_T */) {
- return Matcher<T>(ImplicitCast_<T>(value));
+ using NoRefT = std::remove_cv_t<std::remove_reference_t<T>>;
+ if constexpr (std::is_same_v<M, NoRefT>) {
+ return Matcher<T>(value);
+ } else {
+ return ImplicitCastEqMatcher<NoRefT, std::decay_t<const M&>>(value);
+ }
}
// M can't be implicitly converted to either Matcher<T> or T. Attempt to use
@@ -390,11 +395,11 @@ class MatcherCastImpl {
// latter calls bool operator==(const Lhs& lhs, const Rhs& rhs) in the end
// which might be undefined even when Rhs is implicitly convertible to Lhs
// (e.g. std::pair<const int, int> vs. std::pair<int, int>).
- //
- // We don't define this method inline as we need the declaration of Eq().
static Matcher<T> CastImpl(const M& value,
std::false_type /* convertible_to_matcher */,
- std::false_type /* convertible_to_T */);
+ std::false_type /* convertible_to_T */) {
+ return Eq(value);
+ }
};
// This more specialized version is used when MatcherCast()'s argument
@@ -408,13 +413,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 +445,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 +541,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;
@@ -1305,6 +1316,15 @@ class AllOfMatcherImpl : public MatcherInterface<const T&> {
bool MatchAndExplain(const T& x,
MatchResultListener* listener) const override {
+ if (!listener->IsInterested()) {
+ // Fast path to avoid unnecessary formatting.
+ for (const Matcher<T>& matcher : matchers_) {
+ if (!matcher.Matches(x)) {
+ return false;
+ }
+ }
+ return true;
+ }
// This method uses matcher's explanation when explaining the result.
// However, if matcher doesn't provide one, this method uses matcher's
// description.
@@ -1424,6 +1444,15 @@ class AnyOfMatcherImpl : public MatcherInterface<const T&> {
bool MatchAndExplain(const T& x,
MatchResultListener* listener) const override {
+ if (!listener->IsInterested()) {
+ // Fast path to avoid unnecessary formatting of match explanations.
+ for (const Matcher<T>& matcher : matchers_) {
+ if (matcher.Matches(x)) {
+ return true;
+ }
+ }
+ return false;
+ }
// This method uses matcher's explanation when explaining the result.
// However, if matcher doesn't provide one, this method uses matcher's
// description.
@@ -2091,11 +2120,11 @@ class WhenDynamicCastToMatcher<To&> : public WhenDynamicCastToMatcherBase<To&> {
template <typename Class, typename FieldType>
class FieldMatcher {
public:
- FieldMatcher(FieldType Class::*field,
+ FieldMatcher(FieldType Class::* field,
const Matcher<const FieldType&>& matcher)
: field_(field), matcher_(matcher), whose_field_("whose given field ") {}
- FieldMatcher(const std::string& field_name, FieldType Class::*field,
+ FieldMatcher(const std::string& field_name, FieldType Class::* field,
const Matcher<const FieldType&>& matcher)
: field_(field),
matcher_(matcher),
@@ -2139,7 +2168,7 @@ class FieldMatcher {
return MatchAndExplainImpl(std::false_type(), *p, listener);
}
- const FieldType Class::*field_;
+ const FieldType Class::* field_;
const Matcher<const FieldType&> matcher_;
// Contains either "whose given field " if the name of the field is unknown
@@ -2275,6 +2304,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>
@@ -2282,7 +2314,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()) {
@@ -2312,7 +2344,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);
}
@@ -2325,7 +2357,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_;
@@ -2846,6 +2878,54 @@ class ContainsMatcherImpl : public QuantifierMatcherImpl<Container> {
}
};
+// Implements DistanceFrom(target, get_distance, distance_matcher) for the given
+// argument types:
+// * V is the type of the value to be matched.
+// * T is the type of the target value.
+// * Distance is the type of the distance between V and T.
+// * GetDistance is the type of the functor for computing the distance between
+// V and T.
+template <typename V, typename T, typename Distance, typename GetDistance>
+class DistanceFromMatcherImpl : public MatcherInterface<V> {
+ public:
+ // Arguments:
+ // * target: the target value.
+ // * get_distance: the functor for computing the distance between the value
+ // being matched and target.
+ // * distance_matcher: the matcher for checking the distance.
+ DistanceFromMatcherImpl(T target, GetDistance get_distance,
+ Matcher<const Distance&> distance_matcher)
+ : target_(std::move(target)),
+ get_distance_(std::move(get_distance)),
+ distance_matcher_(std::move(distance_matcher)) {}
+
+ // Describes what this matcher does.
+ void DescribeTo(::std::ostream* os) const override {
+ distance_matcher_.DescribeTo(os);
+ *os << " away from " << PrintToString(target_);
+ }
+
+ void DescribeNegationTo(::std::ostream* os) const override {
+ distance_matcher_.DescribeNegationTo(os);
+ *os << " away from " << PrintToString(target_);
+ }
+
+ bool MatchAndExplain(V value, MatchResultListener* listener) const override {
+ const auto distance = get_distance_(value, target_);
+ const bool match = distance_matcher_.Matches(distance);
+ if (!match && listener->IsInterested()) {
+ *listener << "which is " << PrintToString(distance) << " away from "
+ << PrintToString(target_);
+ }
+ return match;
+ }
+
+ private:
+ const T target_;
+ const GetDistance get_distance_;
+ const Matcher<const Distance&> distance_matcher_;
+};
+
// Implements Each(element_matcher) for the given argument type Container.
// Symmetric to ContainsMatcherImpl.
template <typename Container>
@@ -2981,6 +3061,52 @@ auto Second(T& x, Rank1) -> decltype((x.second)) { // NOLINT
}
} // namespace pair_getters
+// Default functor for computing the distance between two values.
+struct DefaultGetDistance {
+ template <typename T, typename U>
+ auto operator()(const T& lhs, const U& rhs) const {
+ using std::abs;
+ // Allow finding abs() in the type's namespace via ADL.
+ return abs(lhs - rhs);
+ }
+};
+
+// Implements polymorphic DistanceFrom(target, get_distance, distance_matcher)
+// matcher. Template arguments:
+// * T is the type of the target value.
+// * GetDistance is the type of the functor for computing the distance between
+// the value being matched and the target.
+// * DistanceMatcher is the type of the matcher for checking the distance.
+template <typename T, typename GetDistance, typename DistanceMatcher>
+class DistanceFromMatcher {
+ public:
+ // Arguments:
+ // * target: the target value.
+ // * get_distance: the functor for computing the distance between the value
+ // being matched and target.
+ // * distance_matcher: the matcher for checking the distance.
+ DistanceFromMatcher(T target, GetDistance get_distance,
+ DistanceMatcher distance_matcher)
+ : target_(std::move(target)),
+ get_distance_(std::move(get_distance)),
+ distance_matcher_(std::move(distance_matcher)) {}
+
+ DistanceFromMatcher(const DistanceFromMatcher& other) = default;
+
+ // Implicitly converts to a monomorphic matcher of the given type.
+ template <typename V>
+ operator Matcher<V>() const { // NOLINT
+ using Distance = decltype(get_distance_(std::declval<V>(), target_));
+ return Matcher<V>(new DistanceFromMatcherImpl<V, T, Distance, GetDistance>(
+ target_, get_distance_, distance_matcher_));
+ }
+
+ private:
+ const T target_;
+ const GetDistance get_distance_;
+ const DistanceMatcher distance_matcher_;
+};
+
// Implements Key(inner_matcher) for the given argument pair type.
// Key(inner_matcher) matches an std::pair whose 'first' field matches
// inner_matcher. For example, Contains(Key(Ge(5))) can be used to match an
@@ -3188,8 +3314,8 @@ class PairMatcher {
};
template <typename T, size_t... I>
-auto UnpackStructImpl(const T& t, std::index_sequence<I...>,
- int) -> decltype(std::tie(get<I>(t)...)) {
+auto UnpackStructImpl(const T& t, std::index_sequence<I...>, int)
+ -> decltype(std::tie(get<I>(t)...)) {
static_assert(std::tuple_size<T>::value == sizeof...(I),
"Number of arguments doesn't match the number of fields.");
return std::tie(get<I>(t)...);
@@ -3296,6 +3422,50 @@ auto UnpackStructImpl(const T& u, std::make_index_sequence<20>, char) {
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t] = u;
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t);
}
+template <typename T>
+auto UnpackStructImpl(const T& in, std::make_index_sequence<21>, char) {
+ const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u] =
+ in;
+ return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t,
+ u);
+}
+
+template <typename T>
+auto UnpackStructImpl(const T& in, std::make_index_sequence<22>, char) {
+ const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u,
+ v] = in;
+ return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u,
+ v);
+}
+
+template <typename T>
+auto UnpackStructImpl(const T& in, std::make_index_sequence<23>, char) {
+ const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v,
+ w] = in;
+ return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u,
+ v, w);
+}
+template <typename T>
+auto UnpackStructImpl(const T& in, std::make_index_sequence<24>, char) {
+ const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v,
+ w, x] = in;
+ return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u,
+ v, w, x);
+}
+template <typename T>
+auto UnpackStructImpl(const T& in, std::make_index_sequence<25>, char) {
+ const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v,
+ w, x, y] = in;
+ return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u,
+ v, w, x, y);
+}
+template <typename T>
+auto UnpackStructImpl(const T& in, std::make_index_sequence<26>, char) {
+ const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v,
+ w, x, y, z] = in;
+ return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u,
+ v, w, x, y, z);
+}
#endif // defined(__cpp_structured_bindings)
template <size_t I, typename T>
@@ -3471,7 +3641,7 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
StlContainerReference stl_container = View::ConstReference(container);
auto it = stl_container.begin();
size_t exam_pos = 0;
- bool mismatch_found = false; // Have we found a mismatched element yet?
+ bool unmatched_found = false;
// Go through the elements and matchers in pairs, until we reach
// the end of either the elements or the matchers, or until we find a
@@ -3487,11 +3657,23 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
}
if (!match) {
- mismatch_found = true;
+ unmatched_found = true;
+ // We cannot store the iterator for the unmatched element to be used
+ // later, as some users use ElementsAre() with a "container" whose
+ // iterator is not copy-constructible or copy-assignable.
+ //
+ // We cannot store a pointer to the element either, as some container's
+ // iterators return a temporary.
+ //
+ // We cannot store the element itself either, as the element may not be
+ // copyable.
+ //
+ // Therefore, we just remember the index of the unmatched element,
+ // and use it later to print the unmatched element.
break;
}
}
- // If mismatch_found is true, 'exam_pos' is the index of the mismatch.
+ // If unmatched_found is true, exam_pos is the index of the mismatch.
// Find how many elements the actual container has. We avoid
// calling size() s.t. this code works for stream-like "containers"
@@ -3512,10 +3694,27 @@ class ElementsAreMatcherImpl : public MatcherInterface<Container> {
return false;
}
- if (mismatch_found) {
+ if (unmatched_found) {
// The element count matches, but the exam_pos-th element doesn't match.
if (listener_interested) {
- *listener << "whose element #" << exam_pos << " doesn't match";
+ // Find the unmatched element.
+ auto unmatched_it = stl_container.begin();
+ // We cannot call std::advance() on the iterator, as some users use
+ // ElementsAre() with a "container" whose iterator is incompatible with
+ // std::advance() (e.g. it may not have the difference_type member
+ // type).
+ for (size_t i = 0; i != exam_pos; ++i) {
+ ++unmatched_it;
+ }
+
+ // If the array is long or the elements' print-out is large, it may be
+ // hard for the user to find the mismatched element and its
+ // corresponding matcher description. Therefore we print the index, the
+ // value of the mismatched element, and the corresponding matcher
+ // description to ease debugging.
+ *listener << "whose element #" << exam_pos << " ("
+ << PrintToString(*unmatched_it) << ") ";
+ matchers_[exam_pos].DescribeNegationTo(listener->stream());
PrintIfNotEmpty(explanations[exam_pos], listener->stream());
}
return false;
@@ -3921,15 +4120,15 @@ GTEST_API_ std::string FormatMatcherDescription(
// 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) {
+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()) {
+auto IsOptionalEngaged(const Optional& optional, Rank0)
+ -> decltype(!optional.has_value()) {
return optional.has_value();
}
@@ -3970,6 +4169,10 @@ class OptionalMatcher {
return false;
}
const ValueType& value = *optional;
+ if (!listener->IsInterested()) {
+ // Fast path to avoid unnecessary generation of match explanation.
+ return value_matcher_.Matches(value);
+ }
StringMatchResultListener value_listener;
const bool match = value_matcher_.MatchAndExplain(value, &value_listener);
*listener << "whose value " << PrintToString(value)
@@ -4305,13 +4508,6 @@ inline Matcher<T> An() {
return _;
}
-template <typename T, typename M>
-Matcher<T> internal::MatcherCastImpl<T, M>::CastImpl(
- const M& value, std::false_type /* convertible_to_matcher */,
- std::false_type /* convertible_to_T */) {
- return Eq(value);
-}
-
// Creates a polymorphic matcher that matches any NULL pointer.
inline PolymorphicMatcher<internal::IsNullMatcher> IsNull() {
return MakePolymorphicMatcher(internal::IsNullMatcher());
@@ -4356,6 +4552,42 @@ inline internal::FloatingEqMatcher<double> DoubleNear(double rhs,
return internal::FloatingEqMatcher<double>(rhs, false, max_abs_error);
}
+// The DistanceFrom(target, get_distance, m) and DistanceFrom(target, m)
+// matchers work on arbitrary types that have the "distance" concept. What they
+// do:
+//
+// 1. compute the distance between the value and the target using
+// get_distance(value, target) if get_distance is provided; otherwise compute
+// the distance as abs(value - target).
+// 2. match the distance against the user-provided matcher m; if the match
+// succeeds, the DistanceFrom() match succeeds.
+//
+// Examples:
+//
+// // 0.5's distance from 0.6 should be <= 0.2.
+// EXPECT_THAT(0.5, DistanceFrom(0.6, Le(0.2)));
+//
+// Vector2D v1(3.0, 4.0), v2(3.2, 6.0);
+// // v1's distance from v2, as computed by EuclideanDistance(v1, v2),
+// // should be >= 1.0.
+// EXPECT_THAT(v1, DistanceFrom(v2, EuclideanDistance, Ge(1.0)));
+
+template <typename T, typename GetDistance, typename DistanceMatcher>
+inline internal::DistanceFromMatcher<T, GetDistance, DistanceMatcher>
+DistanceFrom(T target, GetDistance get_distance,
+ DistanceMatcher distance_matcher) {
+ return internal::DistanceFromMatcher<T, GetDistance, DistanceMatcher>(
+ std::move(target), std::move(get_distance), std::move(distance_matcher));
+}
+
+template <typename T, typename DistanceMatcher>
+inline internal::DistanceFromMatcher<T, internal::DefaultGetDistance,
+ DistanceMatcher>
+DistanceFrom(T target, DistanceMatcher distance_matcher) {
+ return DistanceFrom(std::move(target), internal::DefaultGetDistance(),
+ std::move(distance_matcher));
+}
+
// Creates a matcher that matches any double argument approximately equal to
// rhs, up to the specified max absolute error bound, including NaN values when
// rhs is NaN. The max absolute error bound must be non-negative.
@@ -4421,7 +4653,7 @@ WhenDynamicCastTo(const Matcher<To>& inner_matcher) {
// matches a Foo object x if and only if x.number >= 5.
template <typename Class, typename FieldType, typename FieldMatcher>
inline PolymorphicMatcher<internal::FieldMatcher<Class, FieldType>> Field(
- FieldType Class::*field, const FieldMatcher& matcher) {
+ FieldType Class::* field, const FieldMatcher& matcher) {
return MakePolymorphicMatcher(internal::FieldMatcher<Class, FieldType>(
field, MatcherCast<const FieldType&>(matcher)));
// The call to MatcherCast() is required for supporting inner
@@ -4434,7 +4666,7 @@ inline PolymorphicMatcher<internal::FieldMatcher<Class, FieldType>> Field(
// messages.
template <typename Class, typename FieldType, typename FieldMatcher>
inline PolymorphicMatcher<internal::FieldMatcher<Class, FieldType>> Field(
- const std::string& field_name, FieldType Class::*field,
+ const std::string& field_name, FieldType Class::* field,
const FieldMatcher& matcher) {
return MakePolymorphicMatcher(internal::FieldMatcher<Class, FieldType>(
field_name, field, MatcherCast<const FieldType&>(matcher)));
@@ -4444,6 +4676,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>>
@@ -5542,8 +5778,7 @@ PolymorphicMatcher<internal::ExceptionMatcherImpl<Err>> ThrowsMessage(
template <typename arg_type> \
bool name##Matcher::gmock_Impl<arg_type>::MatchAndExplain( \
const arg_type& arg, \
- GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED ::testing::MatchResultListener* \
- result_listener) const
+ [[maybe_unused]] ::testing::MatchResultListener* result_listener) const
#define MATCHER_P(name, p0, description) \
GMOCK_INTERNAL_MATCHER(name, name##MatcherP, description, (#p0), (p0))
@@ -5628,8 +5863,8 @@ PolymorphicMatcher<internal::ExceptionMatcherImpl<Err>> ThrowsMessage(
bool full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>:: \
gmock_Impl<arg_type>::MatchAndExplain( \
const arg_type& arg, \
- GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED ::testing:: \
- MatchResultListener* result_listener) const
+ [[maybe_unused]] ::testing::MatchResultListener* result_listener) \
+ const
#define GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args) \
GMOCK_PP_TAIL( \
diff --git a/googlemock/include/gmock/gmock-more-actions.h b/googlemock/include/gmock/gmock-more-actions.h
index 55294db..eacfdcd 100644
--- a/googlemock/include/gmock/gmock-more-actions.h
+++ b/googlemock/include/gmock/gmock-more-actions.h
@@ -521,9 +521,8 @@
GMOCK_INTERNAL_DECL_##value_params) \
GMOCK_PP_IF(GMOCK_PP_IS_EMPTY(GMOCK_INTERNAL_COUNT_##value_params), \
= default; \
- , \
- : impl_(std::make_shared<gmock_Impl>( \
- GMOCK_INTERNAL_LIST_##value_params)){}) \
+ , : impl_(std::make_shared<gmock_Impl>( \
+ GMOCK_INTERNAL_LIST_##value_params)){}) \
GMOCK_ACTION_CLASS_(name, value_params)(const GMOCK_ACTION_CLASS_( \
name, value_params) &) noexcept GMOCK_INTERNAL_DEFN_COPY_ \
##value_params \
@@ -551,10 +550,10 @@
}; \
template <GMOCK_INTERNAL_DECL_##template_params \
GMOCK_INTERNAL_DECL_TYPE_##value_params> \
- GMOCK_ACTION_CLASS_( \
+ [[nodiscard]] GMOCK_ACTION_CLASS_( \
name, value_params)<GMOCK_INTERNAL_LIST_##template_params \
GMOCK_INTERNAL_LIST_TYPE_##value_params> \
- name(GMOCK_INTERNAL_DECL_##value_params) GTEST_MUST_USE_RESULT_; \
+ name(GMOCK_INTERNAL_DECL_##value_params); \
template <GMOCK_INTERNAL_DECL_##template_params \
GMOCK_INTERNAL_DECL_TYPE_##value_params> \
inline GMOCK_ACTION_CLASS_( \
diff --git a/googlemock/include/gmock/gmock-spec-builders.h b/googlemock/include/gmock/gmock-spec-builders.h
index c4c42b7..445a3ed 100644
--- a/googlemock/include/gmock/gmock-spec-builders.h
+++ b/googlemock/include/gmock/gmock-spec-builders.h
@@ -1530,7 +1530,7 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase {
UntypedOnCallSpecs specs_to_delete;
untyped_on_call_specs_.swap(specs_to_delete);
- g_gmock_mutex.Unlock();
+ g_gmock_mutex.unlock();
for (UntypedOnCallSpecs::const_iterator it = specs_to_delete.begin();
it != specs_to_delete.end(); ++it) {
delete static_cast<const OnCallSpec<F>*>(*it);
@@ -1538,7 +1538,7 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase {
// Lock the mutex again, since the caller expects it to be locked when we
// return.
- g_gmock_mutex.Lock();
+ g_gmock_mutex.lock();
}
// Returns the result of invoking this mock function with the given
diff --git a/googlemock/include/gmock/internal/gmock-internal-utils.h b/googlemock/include/gmock/internal/gmock-internal-utils.h
index b7685f5..487d685 100644
--- a/googlemock/include/gmock/internal/gmock-internal-utils.h
+++ b/googlemock/include/gmock/internal/gmock-internal-utils.h
@@ -298,7 +298,7 @@ GTEST_API_ void Log(LogSeverity severity, const std::string& message,
//
class WithoutMatchers {
private:
- WithoutMatchers() {}
+ WithoutMatchers() = default;
friend GTEST_API_ WithoutMatchers GetWithoutMatchers();
};
@@ -467,11 +467,6 @@ struct Function<R(Args...)> {
using MakeResultIgnoredValue = IgnoredValue(Args...);
};
-#ifdef GTEST_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-template <typename R, typename... Args>
-constexpr size_t Function<R(Args...)>::ArgumentCount;
-#endif
-
// Workaround for MSVC error C2039: 'type': is not a member of 'std'
// when std::tuple_element is used.
// See: https://github.com/google/googletest/issues/3931
diff --git a/googlemock/include/gmock/internal/gmock-port.h b/googlemock/include/gmock/internal/gmock-port.h
index 42d36d2..c23b69d 100644
--- a/googlemock/include/gmock/internal/gmock-port.h
+++ b/googlemock/include/gmock/internal/gmock-port.h
@@ -57,10 +57,19 @@
#include "gmock/internal/custom/gmock-port.h"
#include "gtest/internal/gtest-port.h"
-#if defined(GTEST_HAS_ABSL) && !defined(GTEST_NO_ABSL_FLAGS)
+#if defined(GTEST_HAS_ABSL)
+#include "absl/base/macros.h"
+
+#define GMOCK_DEPRECATE_AND_INLINE() ABSL_DEPRECATE_AND_INLINE()
+
+#if !defined(GTEST_NO_ABSL_FLAGS)
#include "absl/flags/declare.h"
#include "absl/flags/flag.h"
-#endif
+#endif // !defined(GTEST_NO_ABSL_FLAGS)
+
+#else // defined(GTEST_HAS_ABSL)
+#define GMOCK_DEPRECATE_AND_INLINE()
+#endif // defined(GTEST_HAS_ABSL)
// For MS Visual C++, check the compiler version. At least VS 2015 is
// required to compile Google Mock.
diff --git a/googlemock/src/gmock-spec-builders.cc b/googlemock/src/gmock-spec-builders.cc
index ffdf03d..603ad7a 100644
--- a/googlemock/src/gmock-spec-builders.cc
+++ b/googlemock/src/gmock-spec-builders.cc
@@ -293,7 +293,7 @@ void ReportUninterestingCall(CallReaction reaction, const std::string& msg) {
Log(kWarning,
msg +
"\nNOTE: You can safely ignore the above warning unless this "
- "call should not happen. Do not suppress it by blindly adding "
+ "call should not happen. Do not suppress it by adding "
"an EXPECT_CALL() if you don't mean to enforce the call. "
"See "
"https://github.com/google/googletest/blob/main/docs/"
@@ -436,9 +436,9 @@ bool UntypedFunctionMockerBase::VerifyAndClearExpectationsLocked()
UntypedExpectations expectations_to_delete;
untyped_expectations_.swap(expectations_to_delete);
- g_gmock_mutex.Unlock();
+ g_gmock_mutex.unlock();
expectations_to_delete.clear();
- g_gmock_mutex.Lock();
+ g_gmock_mutex.lock();
return expectations_met;
}
diff --git a/googlemock/test/gmock-actions_test.cc b/googlemock/test/gmock-actions_test.cc
index 82c22c3..9751705 100644
--- a/googlemock/test/gmock-actions_test.cc
+++ b/googlemock/test/gmock-actions_test.cc
@@ -188,7 +188,7 @@ TEST(TypeTraits, IsInvocableRV) {
struct C {
int operator()() const { return 0; }
void operator()(int) & {}
- std::string operator()(int) && { return ""; };
+ std::string operator()(int) && { return ""; }
};
// The first overload is callable for const and non-const rvalues and lvalues.
@@ -222,8 +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.
@@ -1030,8 +1030,7 @@ void VoidFunc(bool /* flag */) {}
TEST(DoDefaultDeathTest, DiesIfUsedInCompositeAction) {
MockClass mock;
- EXPECT_CALL(mock, IntFunc(_))
- .WillRepeatedly(DoAll(Invoke(VoidFunc), DoDefault()));
+ EXPECT_CALL(mock, IntFunc(_)).WillRepeatedly(DoAll(VoidFunc, DoDefault()));
// Ideally we should verify the error message as well. Sadly,
// EXPECT_DEATH() can only capture stderr, while Google Mock's
@@ -1282,7 +1281,7 @@ int ReturnOne() {
TEST(IgnoreResultTest, MonomorphicAction) {
g_done = false;
- Action<void()> a = IgnoreResult(Invoke(ReturnOne));
+ Action<void()> a = IgnoreResult(&ReturnOne);
a.Perform(std::make_tuple());
EXPECT_TRUE(g_done);
}
@@ -1297,7 +1296,7 @@ MyNonDefaultConstructible ReturnMyNonDefaultConstructible(double /* x */) {
TEST(IgnoreResultTest, ActionReturningClass) {
g_done = false;
Action<void(int)> a =
- IgnoreResult(Invoke(ReturnMyNonDefaultConstructible)); // NOLINT
+ IgnoreResult(&ReturnMyNonDefaultConstructible); // NOLINT
a.Perform(std::make_tuple(2));
EXPECT_TRUE(g_done);
}
@@ -1477,12 +1476,15 @@ TEST(DoAll, SupportsTypeErasedActions) {
}
}
-// A DoAll action should be convertible to a OnceAction, even when its component
-// sub-actions are user-provided types that define only an Action conversion
-// operator. If they supposed being called more than once then they also support
-// being called at most once.
+// A multi-action DoAll action should be convertible to a OnceAction, even when
+// its component sub-actions are user-provided types that define only an Action
+// conversion operator. If they supposed being called more than once then they
+// also support being called at most once.
+//
+// Single-arg DoAll just returns its argument, so will prefer the Action<F>
+// overload for WillOnce.
TEST(DoAll, ConvertibleToOnceActionWithUserProvidedActionConversion) {
- // Simplest case: only one sub-action.
+ // Final action.
struct CustomFinal final {
operator Action<int()>() { // NOLINT
return Return(17);
@@ -1493,17 +1495,7 @@ TEST(DoAll, ConvertibleToOnceActionWithUserProvidedActionConversion) {
}
};
- {
- OnceAction<int()> action = DoAll(CustomFinal{});
- EXPECT_EQ(17, std::move(action).Call());
- }
-
- {
- OnceAction<int(int, char)> action = DoAll(CustomFinal{});
- EXPECT_EQ(19, std::move(action).Call(0, 0));
- }
-
- // It should also work with multiple sub-actions.
+ // Sub-actions.
struct CustomInitial final {
operator Action<void()>() { // NOLINT
return [] {};
@@ -1527,7 +1519,7 @@ TEST(DoAll, ConvertibleToOnceActionWithUserProvidedActionConversion) {
// Tests using WithArgs and with an action that takes 1 argument.
TEST(WithArgsTest, OneArg) {
- Action<bool(double x, int n)> a = WithArgs<1>(Invoke(Unary)); // NOLINT
+ Action<bool(double x, int n)> a = WithArgs<1>(Unary);
EXPECT_TRUE(a.Perform(std::make_tuple(1.5, -1)));
EXPECT_FALSE(a.Perform(std::make_tuple(1.5, 1)));
}
@@ -1535,7 +1527,7 @@ TEST(WithArgsTest, OneArg) {
// Tests using WithArgs with an action that takes 2 arguments.
TEST(WithArgsTest, TwoArgs) {
Action<const char*(const char* s, double x, short n)> a = // NOLINT
- WithArgs<0, 2>(Invoke(Binary));
+ WithArgs<0, 2>(Binary);
const char s[] = "Hello";
EXPECT_EQ(s + 2, a.Perform(std::make_tuple(CharPtr(s), 0.5, Short(2))));
}
@@ -1551,7 +1543,7 @@ struct ConcatAll {
// Tests using WithArgs with an action that takes 10 arguments.
TEST(WithArgsTest, TenArgs) {
Action<std::string(const char*, const char*, const char*, const char*)> a =
- WithArgs<0, 1, 2, 3, 2, 1, 0, 1, 2, 3>(Invoke(ConcatAll{}));
+ WithArgs<0, 1, 2, 3, 2, 1, 0, 1, 2, 3>(ConcatAll{});
EXPECT_EQ("0123210123",
a.Perform(std::make_tuple(CharPtr("0"), CharPtr("1"), CharPtr("2"),
CharPtr("3"))));
@@ -1576,21 +1568,21 @@ TEST(WithArgsTest, NonInvokeAction) {
// Tests using WithArgs to pass all original arguments in the original order.
TEST(WithArgsTest, Identity) {
Action<int(int x, char y, short z)> a = // NOLINT
- WithArgs<0, 1, 2>(Invoke(Ternary));
+ WithArgs<0, 1, 2>(Ternary);
EXPECT_EQ(123, a.Perform(std::make_tuple(100, Char(20), Short(3))));
}
// Tests using WithArgs with repeated arguments.
TEST(WithArgsTest, RepeatedArguments) {
Action<int(bool, int m, int n)> a = // NOLINT
- WithArgs<1, 1, 1, 1>(Invoke(SumOf4));
+ WithArgs<1, 1, 1, 1>(SumOf4);
EXPECT_EQ(4, a.Perform(std::make_tuple(false, 1, 10)));
}
// Tests using WithArgs with reversed argument order.
TEST(WithArgsTest, ReversedArgumentOrder) {
Action<const char*(short n, const char* input)> a = // NOLINT
- WithArgs<1, 0>(Invoke(Binary));
+ WithArgs<1, 0>(Binary);
const char s[] = "Hello";
EXPECT_EQ(s + 2, a.Perform(std::make_tuple(Short(2), CharPtr(s))));
}
@@ -1598,14 +1590,14 @@ TEST(WithArgsTest, ReversedArgumentOrder) {
// Tests using WithArgs with compatible, but not identical, argument types.
TEST(WithArgsTest, ArgsOfCompatibleTypes) {
Action<long(short x, char y, double z, char c)> a = // NOLINT
- WithArgs<0, 1, 3>(Invoke(Ternary));
+ WithArgs<0, 1, 3>(Ternary);
EXPECT_EQ(123,
a.Perform(std::make_tuple(Short(100), Char(20), 5.6, Char(3))));
}
// Tests using WithArgs with an action that returns void.
TEST(WithArgsTest, VoidAction) {
- Action<void(double x, char c, int n)> a = WithArgs<2, 1>(Invoke(VoidBinary));
+ Action<void(double x, char c, int n)> a = WithArgs<2, 1>(VoidBinary);
g_done = false;
a.Perform(std::make_tuple(1.5, 'a', 3));
EXPECT_TRUE(g_done);
@@ -1645,6 +1637,22 @@ TEST(WithArgsTest, RefQualifiedInnerAction) {
EXPECT_EQ(19, mock.AsStdFunction()(0, 17));
}
+// It should be fine to provide an lvalue WithArgsAction to WillOnce, even when
+// the inner action only wants to convert to OnceAction.
+TEST(WithArgsTest, ProvideAsLvalueToWillOnce) {
+ struct SomeAction {
+ operator OnceAction<int(int)>() const { // NOLINT
+ return [](const int arg) { return arg + 2; };
+ }
+ };
+
+ const auto wa = WithArg<1>(SomeAction{});
+
+ MockFunction<int(int, int)> mock;
+ EXPECT_CALL(mock, Call).WillOnce(wa);
+ EXPECT_EQ(19, mock.AsStdFunction()(0, 17));
+}
+
#ifndef GTEST_OS_WINDOWS_MOBILE
class SetErrnoAndReturnTest : public testing::Test {
@@ -1856,9 +1864,8 @@ TEST(MockMethodTest, CanReturnMoveOnlyValue_Invoke) {
[] { return std::make_unique<int>(42); });
EXPECT_EQ(42, *mock.MakeUnique());
- EXPECT_CALL(mock, MakeUnique()).WillRepeatedly(Invoke(UniquePtrSource));
- EXPECT_CALL(mock, MakeVectorUnique())
- .WillRepeatedly(Invoke(VectorUniquePtrSource));
+ EXPECT_CALL(mock, MakeUnique()).WillRepeatedly(UniquePtrSource);
+ EXPECT_CALL(mock, MakeVectorUnique()).WillRepeatedly(VectorUniquePtrSource);
std::unique_ptr<int> result1 = mock.MakeUnique();
EXPECT_EQ(19, *result1);
std::unique_ptr<int> result2 = mock.MakeUnique();
@@ -1880,7 +1887,7 @@ TEST(MockMethodTest, CanTakeMoveOnlyValue) {
});
// DoAll() does not compile, since it would move from its arguments twice.
// EXPECT_CALL(mock, TakeUnique(_, _))
- // .WillRepeatedly(DoAll(Invoke([](std::unique_ptr<int> j) {}),
+ // .WillRepeatedly(DoAll([](std::unique_ptr<int> j) {})),
// Return(1)));
EXPECT_CALL(mock, TakeUnique(testing::Pointee(7)))
.WillOnce(Return(-7))
diff --git a/googlemock/test/gmock-function-mocker_test.cc b/googlemock/test/gmock-function-mocker_test.cc
index cdac79b..c3719f9 100644
--- a/googlemock/test/gmock-function-mocker_test.cc
+++ b/googlemock/test/gmock-function-mocker_test.cc
@@ -91,7 +91,7 @@ class FooInterface {
virtual bool TakesNonConstReference(int& n) = 0; // NOLINT
virtual std::string TakesConstReference(const int& n) = 0;
- virtual bool TakesConst(const int x) = 0;
+ virtual bool TakesConst(int x) = 0;
virtual int OverloadedOnArgumentNumber() = 0;
virtual int OverloadedOnArgumentNumber(int n) = 0;
diff --git a/googlemock/test/gmock-matchers-arithmetic_test.cc b/googlemock/test/gmock-matchers-arithmetic_test.cc
index 06b0b47..b6c3511 100644
--- a/googlemock/test/gmock-matchers-arithmetic_test.cc
+++ b/googlemock/test/gmock-matchers-arithmetic_test.cc
@@ -34,6 +34,7 @@
#include <cmath>
#include <limits>
#include <memory>
+#include <ostream>
#include <string>
#include "gmock/gmock.h"
@@ -398,6 +399,188 @@ TEST(NanSensitiveDoubleNearTest, CanDescribeSelfWithNaNs) {
EXPECT_EQ("are an almost-equal pair", Describe(m));
}
+// Tests that DistanceFrom() can describe itself properly.
+TEST(DistanceFrom, CanDescribeSelf) {
+ Matcher<double> m = DistanceFrom(1.5, Lt(0.1));
+ EXPECT_EQ(Describe(m), "is < 0.1 away from 1.5");
+
+ m = DistanceFrom(2.5, Gt(0.2));
+ EXPECT_EQ(Describe(m), "is > 0.2 away from 2.5");
+}
+
+// Tests that DistanceFrom() can explain match failure.
+TEST(DistanceFrom, CanExplainMatchFailure) {
+ Matcher<double> m = DistanceFrom(1.5, Lt(0.1));
+ EXPECT_EQ(Explain(m, 2.0), "which is 0.5 away from 1.5");
+}
+
+// Tests that DistanceFrom() matches a double that is within the given range of
+// the given value.
+TEST(DistanceFrom, MatchesDoubleWithinRange) {
+ const Matcher<double> m = DistanceFrom(0.5, Le(0.1));
+ EXPECT_TRUE(m.Matches(0.45));
+ EXPECT_TRUE(m.Matches(0.5));
+ EXPECT_TRUE(m.Matches(0.55));
+ EXPECT_FALSE(m.Matches(0.39));
+ EXPECT_FALSE(m.Matches(0.61));
+}
+
+// Tests that DistanceFrom() matches a double reference that is within the given
+// range of the given value.
+TEST(DistanceFrom, MatchesDoubleRefWithinRange) {
+ const Matcher<const double&> m = DistanceFrom(0.5, Le(0.1));
+ EXPECT_TRUE(m.Matches(0.45));
+ EXPECT_TRUE(m.Matches(0.5));
+ EXPECT_TRUE(m.Matches(0.55));
+ EXPECT_FALSE(m.Matches(0.39));
+ EXPECT_FALSE(m.Matches(0.61));
+}
+
+// Tests that DistanceFrom() can be implicitly converted to a matcher depending
+// on the type of the argument.
+TEST(DistanceFrom, CanBeImplicitlyConvertedToMatcher) {
+ EXPECT_THAT(0.58, DistanceFrom(0.5, Le(0.1)));
+ EXPECT_THAT(0.2, Not(DistanceFrom(0.5, Le(0.1))));
+
+ EXPECT_THAT(0.58f, DistanceFrom(0.5f, Le(0.1f)));
+ EXPECT_THAT(0.7f, Not(DistanceFrom(0.5f, Le(0.1f))));
+}
+
+// Tests that DistanceFrom() can be used on compatible types (i.e. not
+// everything has to be of the same type).
+TEST(DistanceFrom, CanBeUsedOnCompatibleTypes) {
+ EXPECT_THAT(0.58, DistanceFrom(0.5, Le(0.1f)));
+ EXPECT_THAT(0.2, Not(DistanceFrom(0.5, Le(0.1f))));
+
+ EXPECT_THAT(0.58, DistanceFrom(0.5f, Le(0.1)));
+ EXPECT_THAT(0.2, Not(DistanceFrom(0.5f, Le(0.1))));
+
+ EXPECT_THAT(0.58, DistanceFrom(0.5f, Le(0.1f)));
+ EXPECT_THAT(0.2, Not(DistanceFrom(0.5f, Le(0.1f))));
+
+ EXPECT_THAT(0.58f, DistanceFrom(0.5, Le(0.1)));
+ EXPECT_THAT(0.2f, Not(DistanceFrom(0.5, Le(0.1))));
+
+ EXPECT_THAT(0.58f, DistanceFrom(0.5, Le(0.1f)));
+ EXPECT_THAT(0.2f, Not(DistanceFrom(0.5, Le(0.1f))));
+
+ EXPECT_THAT(0.58f, DistanceFrom(0.5f, Le(0.1)));
+ EXPECT_THAT(0.2f, Not(DistanceFrom(0.5f, Le(0.1))));
+}
+
+// A 2-dimensional point. For testing using DistanceFrom() with a custom type
+// that doesn't have a built-in distance function.
+class Point {
+ public:
+ Point(double x, double y) : x_(x), y_(y) {}
+ double x() const { return x_; }
+ double y() const { return y_; }
+
+ private:
+ double x_;
+ double y_;
+};
+
+// Returns the distance between two points.
+double PointDistance(const Point& lhs, const Point& rhs) {
+ return std::sqrt(std::pow(lhs.x() - rhs.x(), 2) +
+ std::pow(lhs.y() - rhs.y(), 2));
+}
+
+// Tests that DistanceFrom() can be used on a type with a custom distance
+// function.
+TEST(DistanceFrom, CanBeUsedOnTypeWithCustomDistanceFunction) {
+ const Matcher<Point> m =
+ DistanceFrom(Point(0.5, 0.5), PointDistance, Le(0.1));
+ EXPECT_THAT(Point(0.45, 0.45), m);
+ EXPECT_THAT(Point(0.2, 0.45), Not(m));
+}
+
+// A wrapper around a double value. For testing using DistanceFrom() with a
+// custom type that has neither a built-in distance function nor a built-in
+// distance comparator.
+class Double {
+ public:
+ explicit Double(double value) : value_(value) {}
+ Double(const Double& other) = default;
+ double value() const { return value_; }
+
+ // Defines how to print a Double value. We don't use the AbslStringify API
+ // because googletest doesn't require absl yet.
+ friend void PrintTo(const Double& value, std::ostream* os) {
+ *os << "Double(" << value.value() << ")";
+ }
+
+ private:
+ double value_;
+};
+
+// Returns the distance between two Double values.
+Double DoubleDistance(Double lhs, Double rhs) {
+ return Double(std::abs(lhs.value() - rhs.value()));
+}
+
+MATCHER_P(DoubleLe, rhs, (negation ? "is > " : "is <= ") + PrintToString(rhs)) {
+ return arg.value() <= rhs.value();
+}
+
+// Tests that DistanceFrom() can describe itself properly for a type with a
+// custom printer.
+TEST(DistanceFrom, CanDescribeWithCustomPrinter) {
+ const Matcher<Double> m =
+ DistanceFrom(Double(0.5), DoubleDistance, DoubleLe(Double(0.1)));
+ EXPECT_EQ(Describe(m), "is <= Double(0.1) away from Double(0.5)");
+ EXPECT_EQ(DescribeNegation(m), "is > Double(0.1) away from Double(0.5)");
+}
+
+// Tests that DistanceFrom() can be used with a custom distance function and
+// comparator.
+TEST(DistanceFrom, CanCustomizeDistanceAndComparator) {
+ const Matcher<Double> m =
+ DistanceFrom(Double(0.5), DoubleDistance, DoubleLe(Double(0.1)));
+ EXPECT_TRUE(m.Matches(Double(0.45)));
+ EXPECT_TRUE(m.Matches(Double(0.5)));
+ EXPECT_FALSE(m.Matches(Double(0.39)));
+ EXPECT_FALSE(m.Matches(Double(0.61)));
+}
+
+// For testing using DistanceFrom() with a type that supports both - and abs.
+class Float {
+ public:
+ explicit Float(float value) : value_(value) {}
+ Float(const Float& other) = default;
+ float value() const { return value_; }
+
+ private:
+ float value_ = 0.0f;
+};
+
+// Returns the difference between two Float values. This must be defined in the
+// same namespace as Float.
+Float operator-(const Float& lhs, const Float& rhs) {
+ return Float(lhs.value() - rhs.value());
+}
+
+// Returns the absolute value of a Float value. This must be defined in the
+// same namespace as Float.
+Float abs(Float value) { return Float(std::abs(value.value())); }
+
+// Returns true if and only if the first Float value is less than the second
+// Float value. This must be defined in the same namespace as Float.
+bool operator<(const Float& lhs, const Float& rhs) {
+ return lhs.value() < rhs.value();
+}
+
+// Tests that DistanceFrom() can be used with a type that supports both - and
+// abs.
+TEST(DistanceFrom, CanBeUsedWithTypeThatSupportsBothMinusAndAbs) {
+ const Matcher<Float> m = DistanceFrom(Float(0.5f), Lt(Float(0.1f)));
+ EXPECT_TRUE(m.Matches(Float(0.45f)));
+ EXPECT_TRUE(m.Matches(Float(0.55f)));
+ EXPECT_FALSE(m.Matches(Float(0.39f)));
+ EXPECT_FALSE(m.Matches(Float(0.61f)));
+}
+
// Tests that Not(m) matches any value that doesn't match m.
TEST(NotTest, NegatesMatcher) {
Matcher<int> m;
diff --git a/googlemock/test/gmock-matchers-comparisons_test.cc b/googlemock/test/gmock-matchers-comparisons_test.cc
index a324c4c..413c2bb 100644
--- a/googlemock/test/gmock-matchers-comparisons_test.cc
+++ b/googlemock/test/gmock-matchers-comparisons_test.cc
@@ -33,6 +33,7 @@
#include <functional>
#include <memory>
+#include <optional>
#include <string>
#include <tuple>
#include <vector>
@@ -411,9 +412,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) {
@@ -429,14 +448,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&>.
@@ -445,6 +484,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>.
@@ -577,15 +622,42 @@ struct IntReferenceWrapper {
const int* value;
};
+// Compared the contained values
bool operator==(const IntReferenceWrapper& a, const IntReferenceWrapper& b) {
- return a.value == b.value;
+ return *a.value == *b.value;
}
-TEST(MatcherCastTest, ValueIsNotCopied) {
- int n = 42;
- Matcher<IntReferenceWrapper> m = MatcherCast<IntReferenceWrapper>(n);
- // Verify that the matcher holds a reference to n, not to its temporary copy.
- EXPECT_TRUE(m.Matches(n));
+TEST(MatcherCastTest, ValueIsCopied) {
+ {
+ // When an IntReferenceWrapper is passed.
+ int n = 42;
+ Matcher<IntReferenceWrapper> m =
+ MatcherCast<IntReferenceWrapper>(IntReferenceWrapper(n));
+ {
+ int value = 42;
+ EXPECT_TRUE(m.Matches(value));
+ value = 10;
+ EXPECT_FALSE(m.Matches(value));
+ // This changes the stored reference.
+ n = 10;
+ EXPECT_TRUE(m.Matches(value));
+ }
+ }
+
+ {
+ // When an int is passed.
+ int n = 42;
+ Matcher<IntReferenceWrapper> m = MatcherCast<IntReferenceWrapper>(n);
+ {
+ int value = 42;
+ EXPECT_TRUE(m.Matches(value));
+ value = 10;
+ EXPECT_FALSE(m.Matches(value));
+ // This does not change the stored int.
+ n = 10;
+ EXPECT_FALSE(m.Matches(value));
+ }
+ }
}
class Base {
@@ -649,6 +721,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;
@@ -2342,6 +2424,74 @@ TEST(ExplainMatchResultTest, AllOf_True_True_2) {
EXPECT_EQ("is >= 2, and is <= 3", Explain(m, 2));
}
+// A matcher that records whether the listener was interested.
+template <typename T>
+class CountingMatcher : public MatcherInterface<T> {
+ public:
+ explicit CountingMatcher(const Matcher<T>& base_matcher,
+ std::vector<bool>* listener_interested)
+ : base_matcher_(base_matcher),
+ listener_interested_(listener_interested) {}
+
+ bool MatchAndExplain(T x, MatchResultListener* listener) const override {
+ listener_interested_->push_back(listener->IsInterested());
+ return base_matcher_.MatchAndExplain(x, listener);
+ }
+
+ void DescribeTo(ostream* os) const override { base_matcher_.DescribeTo(os); }
+
+ private:
+ Matcher<T> base_matcher_;
+ std::vector<bool>* listener_interested_;
+};
+
+TEST(AllOfTest, DoesNotFormatChildMatchersWhenNotInterested) {
+ std::vector<bool> listener_interested;
+ Matcher<int> matcher =
+ MakeMatcher(new CountingMatcher<int>(Eq(1), &listener_interested));
+ EXPECT_TRUE(matcher.Matches(1));
+ EXPECT_THAT(listener_interested, ElementsAre(false));
+ listener_interested.clear();
+ Matcher<int> all_of_matcher = AllOf(matcher, matcher);
+ EXPECT_TRUE(all_of_matcher.Matches(1));
+ EXPECT_THAT(listener_interested, ElementsAre(false, false));
+ listener_interested.clear();
+ EXPECT_FALSE(all_of_matcher.Matches(0));
+ EXPECT_THAT(listener_interested, ElementsAre(false));
+}
+
+TEST(AnyOfTest, DoesNotFormatChildMatchersWhenNotInterested) {
+ std::vector<bool> listener_interested;
+ Matcher<int> matcher =
+ MakeMatcher(new CountingMatcher<int>(Eq(1), &listener_interested));
+ EXPECT_TRUE(matcher.Matches(1));
+ EXPECT_THAT(listener_interested, ElementsAre(false));
+ listener_interested.clear();
+ Matcher<int> any_of_matcher = AnyOf(matcher, matcher);
+ EXPECT_TRUE(any_of_matcher.Matches(1));
+ EXPECT_THAT(listener_interested, ElementsAre(false));
+ listener_interested.clear();
+ EXPECT_FALSE(any_of_matcher.Matches(0));
+ EXPECT_THAT(listener_interested, ElementsAre(false, false));
+}
+
+TEST(OptionalTest, DoesNotFormatChildMatcherWhenNotInterested) {
+ std::vector<bool> listener_interested;
+ Matcher<int> matcher =
+ MakeMatcher(new CountingMatcher<int>(Eq(1), &listener_interested));
+ EXPECT_TRUE(matcher.Matches(1));
+ EXPECT_THAT(listener_interested, ElementsAre(false));
+ listener_interested.clear();
+ Matcher<std::optional<int>> optional_matcher = Optional(matcher);
+ EXPECT_FALSE(optional_matcher.Matches(std::nullopt));
+ EXPECT_THAT(listener_interested, ElementsAre());
+ EXPECT_TRUE(optional_matcher.Matches(1));
+ EXPECT_THAT(listener_interested, ElementsAre(false));
+ listener_interested.clear();
+ EXPECT_FALSE(matcher.Matches(0));
+ EXPECT_THAT(listener_interested, ElementsAre(false));
+}
+
INSTANTIATE_GTEST_MATCHER_TEST_P(ExplainmatcherResultTest);
TEST_P(ExplainmatcherResultTestP, MonomorphicMatcher) {
diff --git a/googlemock/test/gmock-matchers-containers_test.cc b/googlemock/test/gmock-matchers-containers_test.cc
index 751fb60..e9f1a02 100644
--- a/googlemock/test/gmock-matchers-containers_test.cc
+++ b/googlemock/test/gmock-matchers-containers_test.cc
@@ -33,6 +33,7 @@
#include <algorithm>
#include <array>
+#include <cstddef>
#include <deque>
#include <forward_list>
#include <iterator>
@@ -1271,10 +1272,11 @@ TEST(WhenSortedByTest, CanDescribeSelf) {
TEST(WhenSortedByTest, ExplainsMatchResult) {
const int a[] = {2, 1};
- EXPECT_EQ("which is { 1, 2 } when sorted, whose element #0 doesn't match",
- Explain(WhenSortedBy(less<int>(), ElementsAre(2, 3)), a));
- EXPECT_EQ("which is { 1, 2 } when sorted",
- Explain(WhenSortedBy(less<int>(), ElementsAre(1, 2)), a));
+ EXPECT_EQ(
+ Explain(WhenSortedBy(less<int>(), ElementsAre(2, 3)), a),
+ "which is { 1, 2 } when sorted, whose element #0 (1) isn't equal to 2");
+ EXPECT_EQ(Explain(WhenSortedBy(less<int>(), ElementsAre(1, 2)), a),
+ "which is { 1, 2 } when sorted");
}
// WhenSorted() is a simple wrapper on WhenSortedBy(). Hence we don't
@@ -1775,6 +1777,295 @@ TEST(IsSubsetOfTest, WorksWithMoveOnly) {
helper.Call(MakeUniquePtrs({2}));
}
+// A container whose iterator returns a temporary. This can iterate over the
+// characters in a string.
+class CharString {
+ public:
+ using value_type = char;
+
+ class const_iterator {
+ public:
+ using iterator_category = std::input_iterator_tag;
+ using value_type = char;
+ using difference_type = std::ptrdiff_t;
+ using pointer = const char*;
+ using reference = const char&;
+
+ // Create an iterator that points to the given character.
+ explicit const_iterator(const char* ptr) : ptr_(ptr) {}
+
+ // Returns the current character. IMPORTANT: this must return a temporary,
+ // not a reference, to test that ElementsAre() works with containers whose
+ // iterators return temporaries.
+ char operator*() const { return *ptr_; }
+
+ // Advances to the next character.
+ const_iterator& operator++() {
+ ++ptr_;
+ return *this;
+ }
+
+ // Compares two iterators.
+ bool operator==(const const_iterator& other) const {
+ return ptr_ == other.ptr_;
+ }
+ bool operator!=(const const_iterator& other) const {
+ return ptr_ != other.ptr_;
+ }
+
+ private:
+ const char* ptr_ = nullptr;
+ };
+
+ // Creates a CharString that contains the given string.
+ explicit CharString(const std::string& s) : s_(s) {}
+
+ // Returns an iterator pointing to the first character in the string.
+ const_iterator begin() const { return const_iterator(s_.c_str()); }
+
+ // Returns an iterator pointing past the last character in the string.
+ const_iterator end() const { return const_iterator(s_.c_str() + s_.size()); }
+
+ private:
+ std::string s_;
+};
+
+// Tests using ElementsAre() with a container whose iterator returns a
+// temporary.
+TEST(ElementsAreTest, WorksWithContainerThatReturnsTempInIterator) {
+ CharString s("abc");
+ EXPECT_THAT(s, ElementsAre('a', 'b', 'c'));
+ EXPECT_THAT(s, Not(ElementsAre('a', 'b', 'd')));
+}
+
+// Tests using ElementsAreArray() with a container whose iterator returns a
+// temporary.
+TEST(ElementsAreArrayTest, WorksWithContainerThatReturnsTempInIterator) {
+ CharString s("abc");
+ EXPECT_THAT(s, ElementsAreArray({'a', 'b', 'c'}));
+ EXPECT_THAT(s, Not(ElementsAreArray({'a', 'b', 'd'})));
+}
+
+// A container whose iterator returns a temporary and is not copy-assignable.
+// This simulates the behavior of the proxy object returned by absl::StrSplit().
+class CharString2 {
+ public:
+ using value_type = char;
+
+ class const_iterator {
+ public:
+ using iterator_category = std::input_iterator_tag;
+ using value_type = char;
+ using difference_type = std::ptrdiff_t;
+ using pointer = const char*;
+ using reference = const char&;
+
+ // Make const_iterator copy-constructible but not copy-assignable,
+ // simulating the behavior of the proxy object returned by absl::StrSplit().
+ const_iterator(const const_iterator&) = default;
+ const_iterator& operator=(const const_iterator&) = delete;
+
+ // Create an iterator that points to the given character.
+ explicit const_iterator(const char* ptr) : ptr_(ptr) {}
+
+ // Returns the current character. IMPORTANT: this must return a temporary,
+ // not a reference, to test that ElementsAre() works with containers whose
+ // iterators return temporaries.
+ char operator*() const { return *ptr_; }
+
+ // Advances to the next character.
+ const_iterator& operator++() {
+ ++ptr_;
+ return *this;
+ }
+
+ // Compares two iterators.
+ bool operator==(const const_iterator& other) const {
+ return ptr_ == other.ptr_;
+ }
+ bool operator!=(const const_iterator& other) const {
+ return ptr_ != other.ptr_;
+ }
+
+ private:
+ const char* ptr_ = nullptr;
+ };
+
+ // Creates a CharString that contains the given string.
+ explicit CharString2(const std::string& s) : s_(s) {}
+
+ // Returns an iterator pointing to the first character in the string.
+ const_iterator begin() const { return const_iterator(s_.c_str()); }
+
+ // Returns an iterator pointing past the last character in the string.
+ const_iterator end() const { return const_iterator(s_.c_str() + s_.size()); }
+
+ private:
+ std::string s_;
+};
+
+// Tests using ElementsAre() with a container whose iterator returns a
+// temporary and is not copy-assignable.
+TEST(ElementsAreTest, WorksWithContainerThatReturnsTempInUnassignableIterator) {
+ CharString2 s("abc");
+ EXPECT_THAT(s, ElementsAre('a', 'b', 'c'));
+ EXPECT_THAT(s, Not(ElementsAre('a', 'b', 'd')));
+}
+
+// Tests using ElementsAreArray() with a container whose iterator returns a
+// temporary and is not copy-assignable.
+TEST(ElementsAreArrayTest,
+ WorksWithContainerThatReturnsTempInUnassignableIterator) {
+ CharString2 s("abc");
+ EXPECT_THAT(s, ElementsAreArray({'a', 'b', 'c'}));
+ EXPECT_THAT(s, Not(ElementsAreArray({'a', 'b', 'd'})));
+}
+
+// A container whose iterator returns a temporary and is neither
+// copy-constructible nor copy-assignable.
+class CharString3 {
+ public:
+ using value_type = char;
+
+ class const_iterator {
+ public:
+ using iterator_category = std::input_iterator_tag;
+ using value_type = char;
+ using difference_type = std::ptrdiff_t;
+ using pointer = const char*;
+ using reference = const char&;
+
+ // Make const_iterator neither copy-constructible nor copy-assignable.
+ const_iterator(const const_iterator&) = delete;
+ const_iterator& operator=(const const_iterator&) = delete;
+
+ // Create an iterator that points to the given character.
+ explicit const_iterator(const char* ptr) : ptr_(ptr) {}
+
+ // Returns the current character. IMPORTANT: this must return a temporary,
+ // not a reference, to test that ElementsAre() works with containers whose
+ // iterators return temporaries.
+ char operator*() const { return *ptr_; }
+
+ // Advances to the next character.
+ const_iterator& operator++() {
+ ++ptr_;
+ return *this;
+ }
+
+ // Compares two iterators.
+ bool operator==(const const_iterator& other) const {
+ return ptr_ == other.ptr_;
+ }
+ bool operator!=(const const_iterator& other) const {
+ return ptr_ != other.ptr_;
+ }
+
+ private:
+ const char* ptr_ = nullptr;
+ };
+
+ // Creates a CharString that contains the given string.
+ explicit CharString3(const std::string& s) : s_(s) {}
+
+ // Returns an iterator pointing to the first character in the string.
+ const_iterator begin() const { return const_iterator(s_.c_str()); }
+
+ // Returns an iterator pointing past the last character in the string.
+ const_iterator end() const { return const_iterator(s_.c_str() + s_.size()); }
+
+ private:
+ std::string s_;
+};
+
+// Tests using ElementsAre() with a container whose iterator returns a
+// temporary and is neither copy-constructible nor copy-assignable.
+TEST(ElementsAreTest, WorksWithContainerThatReturnsTempInUncopyableIterator) {
+ CharString3 s("abc");
+ EXPECT_THAT(s, ElementsAre('a', 'b', 'c'));
+ EXPECT_THAT(s, Not(ElementsAre('a', 'b', 'd')));
+}
+
+// Tests using ElementsAreArray() with a container whose iterator returns a
+// temporary and is neither copy-constructible nor copy-assignable.
+TEST(ElementsAreArrayTest,
+ WorksWithContainerThatReturnsTempInUncopyableIterator) {
+ CharString3 s("abc");
+ EXPECT_THAT(s, ElementsAreArray({'a', 'b', 'c'}));
+ EXPECT_THAT(s, Not(ElementsAreArray({'a', 'b', 'd'})));
+}
+
+// A container whose iterator returns a temporary, is neither
+// copy-constructible nor copy-assignable, and has no member types.
+class CharString4 {
+ public:
+ using value_type = char;
+
+ class const_iterator {
+ public:
+ // Do not define difference_type, etc.
+
+ // Make const_iterator neither copy-constructible nor copy-assignable.
+ const_iterator(const const_iterator&) = delete;
+ const_iterator& operator=(const const_iterator&) = delete;
+
+ // Create an iterator that points to the given character.
+ explicit const_iterator(const char* ptr) : ptr_(ptr) {}
+
+ // Returns the current character. IMPORTANT: this must return a temporary,
+ // not a reference, to test that ElementsAre() works with containers whose
+ // iterators return temporaries.
+ char operator*() const { return *ptr_; }
+
+ // Advances to the next character.
+ const_iterator& operator++() {
+ ++ptr_;
+ return *this;
+ }
+
+ // Compares two iterators.
+ bool operator==(const const_iterator& other) const {
+ return ptr_ == other.ptr_;
+ }
+ bool operator!=(const const_iterator& other) const {
+ return ptr_ != other.ptr_;
+ }
+
+ private:
+ const char* ptr_ = nullptr;
+ };
+
+ // Creates a CharString that contains the given string.
+ explicit CharString4(const std::string& s) : s_(s) {}
+
+ // Returns an iterator pointing to the first character in the string.
+ const_iterator begin() const { return const_iterator(s_.c_str()); }
+
+ // Returns an iterator pointing past the last character in the string.
+ const_iterator end() const { return const_iterator(s_.c_str() + s_.size()); }
+
+ private:
+ std::string s_;
+};
+
+// Tests using ElementsAre() with a container whose iterator returns a
+// temporary, is neither copy-constructible nor copy-assignable, and has no
+// member types.
+TEST(ElementsAreTest, WorksWithContainerWithIteratorWithNoMemberTypes) {
+ CharString4 s("abc");
+ EXPECT_THAT(s, ElementsAre('a', 'b', 'c'));
+ EXPECT_THAT(s, Not(ElementsAre('a', 'b', 'd')));
+}
+
+// Tests using ElementsAreArray() with a container whose iterator returns a
+// temporary, is neither copy-constructible nor copy-assignable, and has no
+// member types.
+TEST(ElementsAreArrayTest, WorksWithContainerWithIteratorWithNoMemberTypes) {
+ CharString4 s("abc");
+ EXPECT_THAT(s, ElementsAreArray({'a', 'b', 'c'}));
+ EXPECT_THAT(s, Not(ElementsAreArray({'a', 'b', 'd'})));
+}
+
// Tests using ElementsAre() and ElementsAreArray() with stream-like
// "containers".
@@ -2155,7 +2446,7 @@ TEST_P(EachTestP, ExplainsMatchResultCorrectly) {
Matcher<set<int>> m = Each(2);
EXPECT_EQ("", Explain(m, a));
- Matcher<const int(&)[1]> n = Each(1); // NOLINT
+ Matcher<const int (&)[1]> n = Each(1); // NOLINT
const int b[1] = {1};
EXPECT_EQ("", Explain(n, b));
@@ -2290,7 +2581,7 @@ TEST(PointwiseTest, MakesCopyOfRhs) {
rhs.push_back(4);
int lhs[] = {1, 2};
- const Matcher<const int(&)[2]> m = Pointwise(IsHalfOf(), rhs);
+ const Matcher<const int (&)[2]> m = Pointwise(IsHalfOf(), rhs);
EXPECT_THAT(lhs, m);
// Changing rhs now shouldn't affect m, which made a copy of rhs.
@@ -2418,7 +2709,7 @@ TEST(UnorderedPointwiseTest, MakesCopyOfRhs) {
rhs.push_back(4);
int lhs[] = {2, 1};
- const Matcher<const int(&)[2]> m = UnorderedPointwise(IsHalfOf(), rhs);
+ const Matcher<const int (&)[2]> m = UnorderedPointwise(IsHalfOf(), rhs);
EXPECT_THAT(lhs, m);
// Changing rhs now shouldn't affect m, which made a copy of rhs.
@@ -2669,11 +2960,11 @@ TEST_P(ElementsAreTestP, CanExplainMismatchRightSize) {
vector<int> v;
v.push_back(2);
v.push_back(1);
- EXPECT_EQ("whose element #0 doesn't match", Explain(m, v));
+ EXPECT_EQ(Explain(m, v), "whose element #0 (2) isn't equal to 1");
v[0] = 1;
- EXPECT_EQ("whose element #1 doesn't match, which is 4 less than 5",
- Explain(m, v));
+ EXPECT_EQ(Explain(m, v),
+ "whose element #1 (1) is <= 5, which is 4 less than 5");
}
TEST(ElementsAreTest, MatchesOneElementVector) {
@@ -3073,7 +3364,7 @@ TEST(ContainsTest, SetDoesNotMatchWhenElementIsNotInContainer) {
TEST_P(ContainsTestP, ExplainsMatchResultCorrectly) {
const int a[2] = {1, 2};
- Matcher<const int(&)[2]> m = Contains(2);
+ Matcher<const int (&)[2]> m = Contains(2);
EXPECT_EQ("whose element #1 matches", Explain(m, a));
m = Contains(3);
diff --git a/googlemock/test/gmock-matchers-misc_test.cc b/googlemock/test/gmock-matchers-misc_test.cc
index ac976dd..de8b76c 100644
--- a/googlemock/test/gmock-matchers-misc_test.cc
+++ b/googlemock/test/gmock-matchers-misc_test.cc
@@ -32,6 +32,7 @@
// This file tests some commonly used argument matchers.
#include <array>
+#include <cstdint>
#include <memory>
#include <ostream>
#include <string>
@@ -747,6 +748,24 @@ TYPED_TEST(OptionalTest, DoesNotMatchNullopt) {
EXPECT_FALSE(m.Matches(empty));
}
+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 {};
diff --git a/googlemock/test/gmock-more-actions_test.cc b/googlemock/test/gmock-more-actions_test.cc
index 354a79b..7c44eb0 100644
--- a/googlemock/test/gmock-more-actions_test.cc
+++ b/googlemock/test/gmock-more-actions_test.cc
@@ -59,6 +59,7 @@ using testing::Invoke;
using testing::ReturnArg;
using testing::ReturnPointee;
using testing::SaveArg;
+using testing::SaveArgByMove;
using testing::SaveArgPointee;
using testing::SetArgReferee;
using testing::Unused;
@@ -201,45 +202,45 @@ class Foo {
// Tests using Invoke() with a nullary function.
TEST(InvokeTest, Nullary) {
- Action<int()> a = Invoke(Nullary); // NOLINT
+ Action<int()> a = &Nullary;
EXPECT_EQ(1, a.Perform(std::make_tuple()));
}
// Tests using Invoke() with a unary function.
TEST(InvokeTest, Unary) {
- Action<bool(int)> a = Invoke(Unary); // NOLINT
+ Action<bool(int)> a = &Unary;
EXPECT_FALSE(a.Perform(std::make_tuple(1)));
EXPECT_TRUE(a.Perform(std::make_tuple(-1)));
}
// Tests using Invoke() with a binary function.
TEST(InvokeTest, Binary) {
- Action<const char*(const char*, short)> a = Invoke(Binary); // NOLINT
+ Action<const char*(const char*, short)> a = &Binary; // NOLINT
const char* p = "Hello";
EXPECT_EQ(p + 2, a.Perform(std::make_tuple(p, Short(2))));
}
// Tests using Invoke() with a ternary function.
TEST(InvokeTest, Ternary) {
- Action<int(int, char, short)> a = Invoke(Ternary); // NOLINT
+ Action<int(int, char, short)> a = &Ternary; // NOLINT
EXPECT_EQ(6, a.Perform(std::make_tuple(1, '\2', Short(3))));
}
// Tests using Invoke() with a 4-argument function.
TEST(InvokeTest, FunctionThatTakes4Arguments) {
- Action<int(int, int, int, int)> a = Invoke(SumOf4); // NOLINT
+ Action<int(int, int, int, int)> a = &SumOf4;
EXPECT_EQ(1234, a.Perform(std::make_tuple(1000, 200, 30, 4)));
}
// Tests using Invoke() with a 5-argument function.
TEST(InvokeTest, FunctionThatTakes5Arguments) {
- Action<int(int, int, int, int, int)> a = Invoke(SumOf5); // NOLINT
+ Action<int(int, int, int, int, int)> a = &SumOf5;
EXPECT_EQ(12345, a.Perform(std::make_tuple(10000, 2000, 300, 40, 5)));
}
// Tests using Invoke() with a 6-argument function.
TEST(InvokeTest, FunctionThatTakes6Arguments) {
- Action<int(int, int, int, int, int, int)> a = Invoke(SumOf6); // NOLINT
+ Action<int(int, int, int, int, int, int)> a = &SumOf6;
EXPECT_EQ(123456,
a.Perform(std::make_tuple(100000, 20000, 3000, 400, 50, 6)));
}
@@ -252,7 +253,7 @@ inline const char* CharPtr(const char* s) { return s; }
TEST(InvokeTest, FunctionThatTakes7Arguments) {
Action<std::string(const char*, const char*, const char*, const char*,
const char*, const char*, const char*)>
- a = Invoke(Concat7);
+ a = &Concat7;
EXPECT_EQ("1234567",
a.Perform(std::make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
CharPtr("4"), CharPtr("5"), CharPtr("6"),
@@ -263,7 +264,7 @@ TEST(InvokeTest, FunctionThatTakes7Arguments) {
TEST(InvokeTest, FunctionThatTakes8Arguments) {
Action<std::string(const char*, const char*, const char*, const char*,
const char*, const char*, const char*, const char*)>
- a = Invoke(Concat8);
+ a = &Concat8;
EXPECT_EQ("12345678",
a.Perform(std::make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
CharPtr("4"), CharPtr("5"), CharPtr("6"),
@@ -275,7 +276,7 @@ TEST(InvokeTest, FunctionThatTakes9Arguments) {
Action<std::string(const char*, const char*, const char*, const char*,
const char*, const char*, const char*, const char*,
const char*)>
- a = Invoke(Concat9);
+ a = &Concat9;
EXPECT_EQ("123456789", a.Perform(std::make_tuple(
CharPtr("1"), CharPtr("2"), CharPtr("3"),
CharPtr("4"), CharPtr("5"), CharPtr("6"),
@@ -287,7 +288,7 @@ TEST(InvokeTest, FunctionThatTakes10Arguments) {
Action<std::string(const char*, const char*, const char*, const char*,
const char*, const char*, const char*, const char*,
const char*, const char*)>
- a = Invoke(Concat10);
+ a = &Concat10;
EXPECT_EQ("1234567890",
a.Perform(std::make_tuple(CharPtr("1"), CharPtr("2"), CharPtr("3"),
CharPtr("4"), CharPtr("5"), CharPtr("6"),
@@ -297,12 +298,12 @@ TEST(InvokeTest, FunctionThatTakes10Arguments) {
// Tests using Invoke() with functions with parameters declared as Unused.
TEST(InvokeTest, FunctionWithUnusedParameters) {
- Action<int(int, int, double, const std::string&)> a1 = Invoke(SumOfFirst2);
+ Action<int(int, int, double, const std::string&)> a1 = &SumOfFirst2;
std::tuple<int, int, double, std::string> dummy =
std::make_tuple(10, 2, 5.6, std::string("hi"));
EXPECT_EQ(12, a1.Perform(dummy));
- Action<int(int, int, bool, int*)> a2 = Invoke(SumOfFirst2);
+ Action<int(int, int, bool, int*)> a2 = &SumOfFirst2;
EXPECT_EQ(
23, a2.Perform(std::make_tuple(20, 3, true, static_cast<int*>(nullptr))));
}
@@ -319,13 +320,13 @@ TEST(InvokeTest, MethodWithUnusedParameters) {
// Tests using Invoke() with a functor.
TEST(InvokeTest, Functor) {
- Action<long(long, int)> a = Invoke(plus<long>()); // NOLINT
+ Action<long(long, int)> a = plus<long>(); // NOLINT
EXPECT_EQ(3L, a.Perform(std::make_tuple(1, 2)));
}
// Tests using Invoke(f) as an action of a compatible type.
TEST(InvokeTest, FunctionWithCompatibleType) {
- Action<long(int, short, char, bool)> a = Invoke(SumOf4); // NOLINT
+ Action<long(int, short, char, bool)> a = &SumOf4; // NOLINT
EXPECT_EQ(4321, a.Perform(std::make_tuple(4000, Short(300), Char(20), true)));
}
@@ -446,13 +447,13 @@ TEST(InvokeMethodTest, MethodWithCompatibleType) {
// Tests using WithoutArgs with an action that takes no argument.
TEST(WithoutArgsTest, NoArg) {
- Action<int(int n)> a = WithoutArgs(Invoke(Nullary)); // NOLINT
+ Action<int(int n)> a = WithoutArgs(&Nullary); // NOLINT
EXPECT_EQ(1, a.Perform(std::make_tuple(2)));
}
// Tests using WithArg with an action that takes 1 argument.
TEST(WithArgTest, OneArg) {
- Action<bool(double x, int n)> b = WithArg<1>(Invoke(Unary)); // NOLINT
+ Action<bool(double x, int n)> b = WithArg<1>(&Unary); // NOLINT
EXPECT_TRUE(b.Perform(std::make_tuple(1.5, -1)));
EXPECT_FALSE(b.Perform(std::make_tuple(1.5, 1)));
}
@@ -492,6 +493,34 @@ TEST(SaveArgActionTest, WorksForCompatibleType) {
EXPECT_EQ('a', result);
}
+struct MoveOnly {
+ explicit MoveOnly(int v) : i(v) {}
+ MoveOnly(MoveOnly&& o) {
+ i = o.i;
+ o.i = -1;
+ }
+ MoveOnly& operator=(MoveOnly&& o) {
+ i = o.i;
+ o.i = -1;
+ return *this;
+ }
+ int i;
+};
+
+TEST(SaveArgByMoveActionTest, WorksForSameType) {
+ MoveOnly result{0};
+ const Action<void(MoveOnly v)> a1 = SaveArgByMove<0>(&result);
+ a1.Perform(std::make_tuple(MoveOnly{5}));
+ EXPECT_EQ(5, result.i);
+}
+
+TEST(SaveArgByMoveActionTest, WorksForCompatibleType) {
+ MoveOnly result{0};
+ const Action<void(bool, MoveOnly)> a1 = SaveArgByMove<1>(&result);
+ a1.Perform(std::make_tuple(true, MoveOnly{7}));
+ EXPECT_EQ(7, result.i);
+}
+
TEST(SaveArgPointeeActionTest, WorksForSameType) {
int result = 0;
const int value = 5;
@@ -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");
diff --git a/googlemock/test/gmock-spec-builders_test.cc b/googlemock/test/gmock-spec-builders_test.cc
index aaf88d7..90f00c2 100644
--- a/googlemock/test/gmock-spec-builders_test.cc
+++ b/googlemock/test/gmock-spec-builders_test.cc
@@ -804,9 +804,8 @@ TEST(ExpectCallTest, InfersCardinality1WhenThereIsWillRepeatedly) {
"to be called at least once");
}
-#if defined(GTEST_INTERNAL_CPLUSPLUS_LANG) && \
- GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L
-
+// TODO(b/396121064) - Fix this test under MSVC
+#ifndef _MSC_VER
// It should be possible to return a non-moveable type from a mock action in
// C++17 and above, where it's guaranteed that such a type can be initialized
// from a prvalue returned from a function.
@@ -847,7 +846,7 @@ TEST(ExpectCallTest, NonMoveableType) {
EXPECT_EQ(17, mock.AsStdFunction()().x);
}
-#endif // C++17 and above
+#endif // _MSC_VER
// Tests that the n-th action is taken for the n-th matching
// invocation.
@@ -2046,7 +2045,7 @@ class GMockVerboseFlagTest : public VerboseFlagPreservingFixture {
NaggyMock<MockA> a;
const std::string note =
"NOTE: You can safely ignore the above warning unless this "
- "call should not happen. Do not suppress it by blindly adding "
+ "call should not happen. Do not suppress it by adding "
"an EXPECT_CALL() if you don't mean to enforce the call. "
"See "
"https://github.com/google/googletest/blob/main/docs/"
diff --git a/googlemock/test/gmock_output_test_golden.txt b/googlemock/test/gmock_output_test_golden.txt
index ca88af0..4b47f33 100644
--- a/googlemock/test/gmock_output_test_golden.txt
+++ b/googlemock/test/gmock_output_test_golden.txt
@@ -79,14 +79,14 @@ GMOCK WARNING:
Uninteresting mock function call - returning default value.
Function call: Bar2(0, 1)
Returns: false
-NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call. See https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md#knowing-when-to-expect-useoncall for details.
+NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by adding an EXPECT_CALL() if you don't mean to enforce the call. See https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md#knowing-when-to-expect-useoncall for details.
[ OK ] GMockOutputTest.UninterestingCall
[ RUN ] GMockOutputTest.UninterestingCallToVoidFunction
GMOCK WARNING:
Uninteresting mock function call - returning directly.
Function call: Bar3(0, 1)
-NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call. See https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md#knowing-when-to-expect-useoncall for details.
+NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by adding an EXPECT_CALL() if you don't mean to enforce the call. See https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md#knowing-when-to-expect-useoncall for details.
[ OK ] GMockOutputTest.UninterestingCallToVoidFunction
[ RUN ] GMockOutputTest.RetiredExpectation
unknown file: Failure
@@ -283,14 +283,14 @@ Uninteresting mock function call - taking default action specified at:
FILE:#:
Function call: Bar2(2, 2)
Returns: true
-NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call. See https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md#knowing-when-to-expect-useoncall for details.
+NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by adding an EXPECT_CALL() if you don't mean to enforce the call. See https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md#knowing-when-to-expect-useoncall for details.
GMOCK WARNING:
Uninteresting mock function call - taking default action specified at:
FILE:#:
Function call: Bar2(1, 1)
Returns: false
-NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call. See https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md#knowing-when-to-expect-useoncall for details.
+NOTE: You can safely ignore the above warning unless this call should not happen. Do not suppress it by adding an EXPECT_CALL() if you don't mean to enforce the call. See https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md#knowing-when-to-expect-useoncall for details.
[ OK ] GMockOutputTest.UninterestingCallWithDefaultAction
[ RUN ] GMockOutputTest.ExplicitActionsRunOutWithDefaultAction
diff --git a/googletest/CMakeLists.txt b/googletest/CMakeLists.txt
index dce6a7c..2e53889 100644
--- a/googletest/CMakeLists.txt
+++ b/googletest/CMakeLists.txt
@@ -132,9 +132,6 @@ if(GTEST_HAS_ABSL)
absl::flags_reflection
absl::flags_usage
absl::strings
- absl::any
- absl::optional
- absl::variant
re2::re2
)
endif()
diff --git a/googletest/README.md b/googletest/README.md
index 7c35174..26e48d1 100644
--- a/googletest/README.md
+++ b/googletest/README.md
@@ -25,7 +25,7 @@ When building GoogleTest as a standalone project, the typical workflow starts
with
```
-git clone https://github.com/google/googletest.git -b v1.15.2
+git clone https://github.com/google/googletest.git -b v1.17.0
cd googletest # Main directory of the cloned repository.
mkdir build # Create a directory to hold the build output.
cd build
@@ -124,9 +124,9 @@ match the project in which it is included.
#### C++ Standard Version
-An environment that supports C++14 is required in order to successfully build
+An environment that supports C++17 is required in order to successfully build
GoogleTest. One way to ensure this is to specify the standard in the top-level
-project, for example by using the `set(CMAKE_CXX_STANDARD 14)` command along
+project, for example by using the `set(CMAKE_CXX_STANDARD 17)` command along
with `set(CMAKE_CXX_STANDARD_REQUIRED ON)`. If this is not feasible, for example
in a C project using GoogleTest for validation, then it can be specified by
adding it to the options for cmake via the`-DCMAKE_CXX_FLAGS` option.
@@ -145,9 +145,9 @@ We list the most frequently used macros below. For a complete list, see file
### Multi-threaded Tests
GoogleTest is thread-safe where the pthread library is available. After
-`#include <gtest/gtest.h>`, you can check the
-`GTEST_IS_THREADSAFE` macro to see whether this is the case (yes if the macro is
-`#defined` to 1, no if it's undefined.).
+`#include <gtest/gtest.h>`, you can check the `GTEST_IS_THREADSAFE` macro to see
+whether this is the case (yes if the macro is `#defined` to 1, no if it's
+undefined.).
If GoogleTest doesn't correctly detect whether pthread is available in your
environment, you can force it with
diff --git a/googletest/cmake/internal_utils.cmake b/googletest/cmake/internal_utils.cmake
index 580ac1c..7ca256a 100644
--- a/googletest/cmake/internal_utils.cmake
+++ b/googletest/cmake/internal_utils.cmake
@@ -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()
########################################################################
diff --git a/googletest/include/gtest/gtest-assertion-result.h b/googletest/include/gtest/gtest-assertion-result.h
index 74eb2b1..954e7c4 100644
--- a/googletest/include/gtest/gtest-assertion-result.h
+++ b/googletest/include/gtest/gtest-assertion-result.h
@@ -129,6 +129,13 @@ namespace testing {
//
// Expected: Foo() is even
// Actual: it's 5
+//
+
+// Returned AssertionResult objects may not be ignored.
+// Note: Disabled for SWIG as it doesn't parse attributes correctly.
+#if !defined(SWIG)
+class [[nodiscard]] AssertionResult;
+#endif // !SWIG
class GTEST_API_ AssertionResult {
public:
diff --git a/googletest/include/gtest/gtest-matchers.h b/googletest/include/gtest/gtest-matchers.h
index 78160f0..93643db 100644
--- a/googletest/include/gtest/gtest-matchers.h
+++ b/googletest/include/gtest/gtest-matchers.h
@@ -773,6 +773,35 @@ class GeMatcher
static const char* NegatedDesc() { return "isn't >="; }
};
+// Same as `EqMatcher<Rhs>`, except that the `rhs` is stored as `StoredRhs` and
+// must be implicitly convertible to `Rhs`.
+template <typename Rhs, typename StoredRhs>
+class ImplicitCastEqMatcher {
+ public:
+ explicit ImplicitCastEqMatcher(const StoredRhs& rhs) : stored_rhs_(rhs) {}
+
+ using is_gtest_matcher = void;
+
+ template <typename Lhs>
+ bool MatchAndExplain(const Lhs& lhs, std::ostream*) const {
+ return lhs == rhs();
+ }
+
+ void DescribeTo(std::ostream* os) const {
+ *os << "is equal to ";
+ UniversalPrint(rhs(), os);
+ }
+ void DescribeNegationTo(std::ostream* os) const {
+ *os << "isn't equal to ";
+ UniversalPrint(rhs(), os);
+ }
+
+ private:
+ Rhs rhs() const { return ImplicitCast_<Rhs>(stored_rhs_); }
+
+ StoredRhs stored_rhs_;
+};
+
template <typename T, typename = typename std::enable_if<
std::is_constructible<std::string, T>::value>::type>
using StringLike = T;
diff --git a/googletest/include/gtest/gtest-param-test.h b/googletest/include/gtest/gtest-param-test.h
index 55ee088..9e023f9 100644
--- a/googletest/include/gtest/gtest-param-test.h
+++ b/googletest/include/gtest/gtest-param-test.h
@@ -174,6 +174,7 @@ TEST_P(DerivedTest, DoesBlah) {
#endif // 0
+#include <functional>
#include <iterator>
#include <utility>
@@ -413,7 +414,8 @@ internal::CartesianProductHolder<Generator...> Combine(const Generator&... g) {
// Synopsis:
// ConvertGenerator<T>(gen)
// - returns a generator producing the same elements as generated by gen, but
-// each element is static_cast to type T before being returned
+// each T-typed element is static_cast to a type deduced from the interface
+// that accepts this generator, and then returned
//
// It is useful when using the Combine() function to get the generated
// parameters in a custom type instead of std::tuple
@@ -441,10 +443,65 @@ internal::CartesianProductHolder<Generator...> Combine(const Generator&... g) {
// Combine(Values("cat", "dog"),
// Values(BLACK, WHITE))));
//
-template <typename T>
-internal::ParamConverterGenerator<T> ConvertGenerator(
- internal::ParamGenerator<T> gen) {
- return internal::ParamConverterGenerator<T>(gen);
+template <typename RequestedT>
+internal::ParamConverterGenerator<RequestedT> ConvertGenerator(
+ internal::ParamGenerator<RequestedT> gen) {
+ return internal::ParamConverterGenerator<RequestedT>(std::move(gen));
+}
+
+// As above, but takes a callable as a second argument. The callable converts
+// the generated parameter to the test fixture's parameter type. This allows you
+// to use a parameter type that does not have a converting constructor from the
+// generated type.
+//
+// Example:
+//
+// This will instantiate tests in test suite AnimalTest each one with
+// the parameter values tuple("cat", BLACK), tuple("cat", WHITE),
+// tuple("dog", BLACK), and tuple("dog", WHITE):
+//
+// enum Color { BLACK, GRAY, WHITE };
+// struct ParamType {
+// std::string animal;
+// Color color;
+// };
+// class AnimalTest
+// : public testing::TestWithParam<ParamType> {...};
+//
+// TEST_P(AnimalTest, AnimalLooksNice) {...}
+//
+// INSTANTIATE_TEST_SUITE_P(
+// AnimalVariations, AnimalTest,
+// ConvertGenerator(Combine(Values("cat", "dog"), Values(BLACK, WHITE)),
+// [](std::tuple<std::string, Color> t) {
+// return ParamType{.animal = std::get<0>(t),
+// .color = std::get<1>(t)};
+// }));
+//
+template <typename T, int&... ExplicitArgumentBarrier, typename Gen,
+ typename Func,
+ typename StdFunction = decltype(std::function(std::declval<Func>()))>
+internal::ParamConverterGenerator<T, StdFunction> ConvertGenerator(Gen&& gen,
+ Func&& f) {
+ return internal::ParamConverterGenerator<T, StdFunction>(
+ std::forward<Gen>(gen), std::forward<Func>(f));
+}
+
+// As above, but infers the T from the supplied std::function instead of
+// having the caller specify it.
+template <int&... ExplicitArgumentBarrier, typename Gen, typename Func,
+ typename StdFunction = decltype(std::function(std::declval<Func>()))>
+auto ConvertGenerator(Gen&& gen, Func&& f) {
+ constexpr bool is_single_arg_std_function =
+ internal::IsSingleArgStdFunction<StdFunction>::value;
+ if constexpr (is_single_arg_std_function) {
+ return ConvertGenerator<
+ typename internal::FuncSingleParamType<StdFunction>::type>(
+ std::forward<Gen>(gen), std::forward<Func>(f));
+ } else {
+ static_assert(is_single_arg_std_function,
+ "The call signature must contain a single argument.");
+ }
}
#define TEST_P(test_suite_name, test_name) \
@@ -469,7 +526,7 @@ internal::ParamConverterGenerator<T> ConvertGenerator(
::testing::internal::CodeLocation(__FILE__, __LINE__)); \
return 0; \
} \
- GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static int gtest_registering_dummy_; \
+ [[maybe_unused]] static int gtest_registering_dummy_; \
}; \
int GTEST_TEST_CLASS_NAME_(test_suite_name, \
test_name)::gtest_registering_dummy_ = \
@@ -493,39 +550,38 @@ internal::ParamConverterGenerator<T> ConvertGenerator(
#define GTEST_GET_FIRST_(first, ...) first
#define GTEST_GET_SECOND_(first, second, ...) second
-#define INSTANTIATE_TEST_SUITE_P(prefix, test_suite_name, ...) \
- static ::testing::internal::ParamGenerator<test_suite_name::ParamType> \
- gtest_##prefix##test_suite_name##_EvalGenerator_() { \
- return GTEST_EXPAND_(GTEST_GET_FIRST_(__VA_ARGS__, DUMMY_PARAM_)); \
- } \
- static ::std::string gtest_##prefix##test_suite_name##_EvalGenerateName_( \
- const ::testing::TestParamInfo<test_suite_name::ParamType>& info) { \
- if (::testing::internal::AlwaysFalse()) { \
- ::testing::internal::TestNotEmpty(GTEST_EXPAND_(GTEST_GET_SECOND_( \
- __VA_ARGS__, \
- ::testing::internal::DefaultParamName<test_suite_name::ParamType>, \
- DUMMY_PARAM_))); \
- auto t = std::make_tuple(__VA_ARGS__); \
- static_assert(std::tuple_size<decltype(t)>::value <= 2, \
- "Too Many Args!"); \
- } \
- return ((GTEST_EXPAND_(GTEST_GET_SECOND_( \
- __VA_ARGS__, \
- ::testing::internal::DefaultParamName<test_suite_name::ParamType>, \
- DUMMY_PARAM_))))(info); \
- } \
- GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static int \
- gtest_##prefix##test_suite_name##_dummy_ = \
- ::testing::UnitTest::GetInstance() \
- ->parameterized_test_registry() \
- .GetTestSuitePatternHolder<test_suite_name>( \
- GTEST_STRINGIFY_(test_suite_name), \
- ::testing::internal::CodeLocation(__FILE__, __LINE__)) \
- ->AddTestSuiteInstantiation( \
- GTEST_STRINGIFY_(prefix), \
- &gtest_##prefix##test_suite_name##_EvalGenerator_, \
- &gtest_##prefix##test_suite_name##_EvalGenerateName_, \
- __FILE__, __LINE__)
+#define INSTANTIATE_TEST_SUITE_P(prefix, test_suite_name, ...) \
+ static ::testing::internal::ParamGenerator<test_suite_name::ParamType> \
+ gtest_##prefix##test_suite_name##_EvalGenerator_() { \
+ return GTEST_EXPAND_(GTEST_GET_FIRST_(__VA_ARGS__, DUMMY_PARAM_)); \
+ } \
+ static ::std::string gtest_##prefix##test_suite_name##_EvalGenerateName_( \
+ const ::testing::TestParamInfo<test_suite_name::ParamType>& info) { \
+ if (::testing::internal::AlwaysFalse()) { \
+ ::testing::internal::TestNotEmpty(GTEST_EXPAND_(GTEST_GET_SECOND_( \
+ __VA_ARGS__, \
+ ::testing::internal::DefaultParamName<test_suite_name::ParamType>, \
+ DUMMY_PARAM_))); \
+ auto t = std::make_tuple(__VA_ARGS__); \
+ static_assert(std::tuple_size<decltype(t)>::value <= 2, \
+ "Too Many Args!"); \
+ } \
+ return ((GTEST_EXPAND_(GTEST_GET_SECOND_( \
+ __VA_ARGS__, \
+ ::testing::internal::DefaultParamName<test_suite_name::ParamType>, \
+ DUMMY_PARAM_))))(info); \
+ } \
+ [[maybe_unused]] static int gtest_##prefix##test_suite_name##_dummy_ = \
+ ::testing::UnitTest::GetInstance() \
+ ->parameterized_test_registry() \
+ .GetTestSuitePatternHolder<test_suite_name>( \
+ GTEST_STRINGIFY_(test_suite_name), \
+ ::testing::internal::CodeLocation(__FILE__, __LINE__)) \
+ ->AddTestSuiteInstantiation( \
+ GTEST_STRINGIFY_(prefix), \
+ &gtest_##prefix##test_suite_name##_EvalGenerator_, \
+ &gtest_##prefix##test_suite_name##_EvalGenerateName_, __FILE__, \
+ __LINE__)
// Allow Marking a Parameterized test class as not needing to be instantiated.
#define GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(T) \
diff --git a/googletest/include/gtest/gtest-printers.h b/googletest/include/gtest/gtest-printers.h
index 198a769..048c32d 100644
--- a/googletest/include/gtest/gtest-printers.h
+++ b/googletest/include/gtest/gtest-printers.h
@@ -104,15 +104,19 @@
#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
#define GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+#include <any>
#include <functional>
#include <memory>
+#include <optional>
#include <ostream> // NOLINT
#include <sstream>
#include <string>
+#include <string_view>
#include <tuple>
#include <type_traits>
#include <typeinfo>
#include <utility>
+#include <variant>
#include <vector>
#ifdef GTEST_HAS_ABSL
@@ -245,8 +249,8 @@ struct StreamPrinter {
// ADL (possibly involving implicit conversions).
// (Use SFINAE via return type, because it seems GCC < 12 doesn't handle name
// lookup properly when we do it in the template parameter list.)
- static auto PrintValue(const T& value,
- ::std::ostream* os) -> decltype((void)(*os << value)) {
+ static auto PrintValue(const T& value, ::std::ostream* os)
+ -> decltype((void)(*os << value)) {
// Call streaming operator found by ADL, possibly with implicit conversions
// of the arguments.
*os << value;
@@ -521,11 +525,15 @@ GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os);
GTEST_API_ void PrintTo(char32_t c, ::std::ostream* os);
inline void PrintTo(char16_t c, ::std::ostream* os) {
- PrintTo(ImplicitCast_<char32_t>(c), os);
+ // TODO(b/418738869): Incorrect for values not representing valid codepoints.
+ // Also see https://github.com/google/googletest/issues/4762.
+ PrintTo(static_cast<char32_t>(c), os);
}
#ifdef __cpp_lib_char8_t
inline void PrintTo(char8_t c, ::std::ostream* os) {
- PrintTo(ImplicitCast_<char32_t>(c), os);
+ // TODO(b/418738869): Incorrect for values not representing valid codepoints.
+ // Also see https://github.com/google/googletest/issues/4762.
+ PrintTo(static_cast<char32_t>(c), os);
}
#endif
@@ -695,44 +703,63 @@ void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) {
}
}
-// Overloads for ::std::string.
-GTEST_API_ void PrintStringTo(const ::std::string& s, ::std::ostream* os);
+// Overloads for ::std::string and ::std::string_view
+GTEST_API_ void PrintStringTo(::std::string_view s, ::std::ostream* os);
inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
PrintStringTo(s, os);
}
+inline void PrintTo(::std::string_view s, ::std::ostream* os) {
+ PrintStringTo(s, os);
+}
-// Overloads for ::std::u8string
+// Overloads for ::std::u8string and ::std::u8string_view
#ifdef __cpp_lib_char8_t
-GTEST_API_ void PrintU8StringTo(const ::std::u8string& s, ::std::ostream* os);
+GTEST_API_ void PrintU8StringTo(::std::u8string_view s, ::std::ostream* os);
inline void PrintTo(const ::std::u8string& s, ::std::ostream* os) {
PrintU8StringTo(s, os);
}
+inline void PrintTo(::std::u8string_view s, ::std::ostream* os) {
+ PrintU8StringTo(s, os);
+}
#endif
-// Overloads for ::std::u16string
-GTEST_API_ void PrintU16StringTo(const ::std::u16string& s, ::std::ostream* os);
+// Overloads for ::std::u16string and ::std::u16string_view
+GTEST_API_ void PrintU16StringTo(::std::u16string_view s, ::std::ostream* os);
inline void PrintTo(const ::std::u16string& s, ::std::ostream* os) {
PrintU16StringTo(s, os);
}
+inline void PrintTo(::std::u16string_view s, ::std::ostream* os) {
+ PrintU16StringTo(s, os);
+}
-// Overloads for ::std::u32string
-GTEST_API_ void PrintU32StringTo(const ::std::u32string& s, ::std::ostream* os);
+// Overloads for ::std::u32string and ::std::u32string_view
+GTEST_API_ void PrintU32StringTo(::std::u32string_view s, ::std::ostream* os);
inline void PrintTo(const ::std::u32string& s, ::std::ostream* os) {
PrintU32StringTo(s, os);
}
+inline void PrintTo(::std::u32string_view s, ::std::ostream* os) {
+ PrintU32StringTo(s, os);
+}
-// Overloads for ::std::wstring.
+// Overloads for ::std::wstring and ::std::wstring_view
#if GTEST_HAS_STD_WSTRING
-GTEST_API_ void PrintWideStringTo(const ::std::wstring& s, ::std::ostream* os);
+GTEST_API_ void PrintWideStringTo(::std::wstring_view s, ::std::ostream* os);
inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
PrintWideStringTo(s, os);
}
+inline void PrintTo(::std::wstring_view s, ::std::ostream* os) {
+ PrintWideStringTo(s, os);
+}
#endif // GTEST_HAS_STD_WSTRING
#if GTEST_INTERNAL_HAS_STRING_VIEW
-// Overload for internal::StringView.
+// Overload for internal::StringView. Needed for build configurations where
+// internal::StringView is an alias for absl::string_view, but absl::string_view
+// is a distinct type from std::string_view.
+template <int&... ExplicitArgumentBarrier, typename T = internal::StringView,
+ std::enable_if_t<!std::is_same_v<T, ::std::string_view>, int> = 0>
inline void PrintTo(internal::StringView sp, ::std::ostream* os) {
- PrintTo(::std::string(sp), os);
+ PrintStringTo(sp, os);
}
#endif // GTEST_INTERNAL_HAS_STRING_VIEW
@@ -890,14 +917,11 @@ class UniversalPrinter {
template <typename T>
class UniversalPrinter<const T> : public UniversalPrinter<T> {};
-#if GTEST_INTERNAL_HAS_ANY
-
-// Printer for std::any / absl::any
-
+// Printer for std::any
template <>
-class UniversalPrinter<Any> {
+class UniversalPrinter<std::any> {
public:
- static void Print(const Any& value, ::std::ostream* os) {
+ static void Print(const std::any& value, ::std::ostream* os) {
if (value.has_value()) {
*os << "value of type " << GetTypeName(value);
} else {
@@ -906,7 +930,7 @@ class UniversalPrinter<Any> {
}
private:
- static std::string GetTypeName(const Any& value) {
+ static std::string GetTypeName(const std::any& value) {
#if GTEST_HAS_RTTI
return internal::GetTypeName(value.type());
#else
@@ -916,16 +940,11 @@ class UniversalPrinter<Any> {
}
};
-#endif // GTEST_INTERNAL_HAS_ANY
-
-#if GTEST_INTERNAL_HAS_OPTIONAL
-
-// Printer for std::optional / absl::optional
-
+// Printer for std::optional
template <typename T>
-class UniversalPrinter<Optional<T>> {
+class UniversalPrinter<std::optional<T>> {
public:
- static void Print(const Optional<T>& value, ::std::ostream* os) {
+ static void Print(const std::optional<T>& value, ::std::ostream* os) {
*os << '(';
if (!value) {
*os << "nullopt";
@@ -937,29 +956,18 @@ class UniversalPrinter<Optional<T>> {
};
template <>
-class UniversalPrinter<decltype(Nullopt())> {
+class UniversalPrinter<std::nullopt_t> {
public:
- static void Print(decltype(Nullopt()), ::std::ostream* os) {
- *os << "(nullopt)";
- }
+ static void Print(std::nullopt_t, ::std::ostream* os) { *os << "(nullopt)"; }
};
-#endif // GTEST_INTERNAL_HAS_OPTIONAL
-
-#if GTEST_INTERNAL_HAS_VARIANT
-
-// Printer for std::variant / absl::variant
-
+// Printer for std::variant
template <typename... T>
-class UniversalPrinter<Variant<T...>> {
+class UniversalPrinter<std::variant<T...>> {
public:
- static void Print(const Variant<T...>& value, ::std::ostream* os) {
+ static void Print(const std::variant<T...>& value, ::std::ostream* os) {
*os << '(';
-#ifdef GTEST_HAS_ABSL
- absl::visit(Visitor{os, value.index()}, value);
-#else
std::visit(Visitor{os, value.index()}, value);
-#endif // GTEST_HAS_ABSL
*os << ')';
}
@@ -976,8 +984,6 @@ class UniversalPrinter<Variant<T...>> {
};
};
-#endif // GTEST_INTERNAL_HAS_VARIANT
-
// UniversalPrintArray(begin, len, os) prints an array of 'len'
// elements, starting at address 'begin'.
template <typename T>
diff --git a/googletest/include/gtest/gtest-typed-test.h b/googletest/include/gtest/gtest-typed-test.h
index 305b0b5..ae24f94 100644
--- a/googletest/include/gtest/gtest-typed-test.h
+++ b/googletest/include/gtest/gtest-typed-test.h
@@ -48,15 +48,15 @@ template <typename T>
class FooTest : public testing::Test {
public:
...
- typedef std::list<T> List;
+ using List = ::std::list<T>;
static T shared_;
T value_;
};
// Next, associate a list of types with the test suite, which will be
-// repeated for each type in the list. The typedef is necessary for
+// repeated for each type in the list. The using-declaration is necessary for
// the macro to parse correctly.
-typedef testing::Types<char, int, unsigned int> MyTypes;
+using MyTypes = ::testing::Types<char, int, unsigned int>;
TYPED_TEST_SUITE(FooTest, MyTypes);
// If the type list contains only one type, you can write that type
@@ -157,7 +157,7 @@ REGISTER_TYPED_TEST_SUITE_P(FooTest,
// argument to the INSTANTIATE_* macro is a prefix that will be added
// to the actual test suite name. Remember to pick unique prefixes for
// different instances.
-typedef testing::Types<char, int, unsigned int> MyTypes;
+using MyTypes = ::testing::Types<char, int, unsigned int>;
INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
// If the type list contains only one type, you can write that type
@@ -194,34 +194,33 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \
GTEST_NAME_GENERATOR_(CaseName)
-#define TYPED_TEST(CaseName, TestName) \
- static_assert(sizeof(GTEST_STRINGIFY_(TestName)) > 1, \
- "test-name must not be empty"); \
- template <typename gtest_TypeParam_> \
- class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
- : public CaseName<gtest_TypeParam_> { \
- private: \
- typedef CaseName<gtest_TypeParam_> TestFixture; \
- typedef gtest_TypeParam_ TypeParam; \
- void TestBody() override; \
- }; \
- GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool \
- gtest_##CaseName##_##TestName##_registered_ = \
- ::testing::internal::TypeParameterizedTest< \
- CaseName, \
- ::testing::internal::TemplateSel<GTEST_TEST_CLASS_NAME_( \
- CaseName, TestName)>, \
- GTEST_TYPE_PARAMS_( \
- CaseName)>::Register("", \
- ::testing::internal::CodeLocation( \
- __FILE__, __LINE__), \
- GTEST_STRINGIFY_(CaseName), \
- GTEST_STRINGIFY_(TestName), 0, \
- ::testing::internal::GenerateNames< \
- GTEST_NAME_GENERATOR_(CaseName), \
- GTEST_TYPE_PARAMS_(CaseName)>()); \
- template <typename gtest_TypeParam_> \
- void GTEST_TEST_CLASS_NAME_(CaseName, \
+#define TYPED_TEST(CaseName, TestName) \
+ static_assert(sizeof(GTEST_STRINGIFY_(TestName)) > 1, \
+ "test-name must not be empty"); \
+ template <typename gtest_TypeParam_> \
+ class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
+ : public CaseName<gtest_TypeParam_> { \
+ private: \
+ typedef CaseName<gtest_TypeParam_> TestFixture; \
+ typedef gtest_TypeParam_ TypeParam; \
+ void TestBody() override; \
+ }; \
+ [[maybe_unused]] static bool gtest_##CaseName##_##TestName##_registered_ = \
+ ::testing::internal::TypeParameterizedTest< \
+ CaseName, \
+ ::testing::internal::TemplateSel<GTEST_TEST_CLASS_NAME_(CaseName, \
+ TestName)>, \
+ GTEST_TYPE_PARAMS_( \
+ CaseName)>::Register("", \
+ ::testing::internal::CodeLocation( \
+ __FILE__, __LINE__), \
+ GTEST_STRINGIFY_(CaseName), \
+ GTEST_STRINGIFY_(TestName), 0, \
+ ::testing::internal::GenerateNames< \
+ GTEST_NAME_GENERATOR_(CaseName), \
+ GTEST_TYPE_PARAMS_(CaseName)>()); \
+ template <typename gtest_TypeParam_> \
+ void GTEST_TEST_CLASS_NAME_(CaseName, \
TestName)<gtest_TypeParam_>::TestBody()
// Legacy API is deprecated but still available
@@ -268,23 +267,22 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
TYPED_TEST_SUITE_P
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-#define TYPED_TEST_P(SuiteName, TestName) \
- namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \
- template <typename gtest_TypeParam_> \
- class TestName : public SuiteName<gtest_TypeParam_> { \
- private: \
- typedef SuiteName<gtest_TypeParam_> TestFixture; \
- typedef gtest_TypeParam_ TypeParam; \
- void TestBody() override; \
- }; \
- GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool \
- gtest_##TestName##_defined_ = \
- GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).AddTestName( \
- __FILE__, __LINE__, GTEST_STRINGIFY_(SuiteName), \
- GTEST_STRINGIFY_(TestName)); \
- } \
- template <typename gtest_TypeParam_> \
- void GTEST_SUITE_NAMESPACE_( \
+#define TYPED_TEST_P(SuiteName, TestName) \
+ namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \
+ template <typename gtest_TypeParam_> \
+ class TestName : public SuiteName<gtest_TypeParam_> { \
+ private: \
+ typedef SuiteName<gtest_TypeParam_> TestFixture; \
+ typedef gtest_TypeParam_ TypeParam; \
+ void TestBody() override; \
+ }; \
+ [[maybe_unused]] static bool gtest_##TestName##_defined_ = \
+ GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).AddTestName( \
+ __FILE__, __LINE__, GTEST_STRINGIFY_(SuiteName), \
+ GTEST_STRINGIFY_(TestName)); \
+ } \
+ template <typename gtest_TypeParam_> \
+ void GTEST_SUITE_NAMESPACE_( \
SuiteName)::TestName<gtest_TypeParam_>::TestBody()
// Note: this won't work correctly if the trailing arguments are macros.
@@ -292,8 +290,8 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \
typedef ::testing::internal::Templates<__VA_ARGS__> gtest_AllTests_; \
} \
- GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static const char* const \
- GTEST_REGISTERED_TEST_NAMES_(SuiteName) = \
+ [[maybe_unused]] static const char* const GTEST_REGISTERED_TEST_NAMES_( \
+ SuiteName) = \
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).VerifyRegisteredTestNames( \
GTEST_STRINGIFY_(SuiteName), __FILE__, __LINE__, #__VA_ARGS__)
@@ -305,24 +303,22 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
REGISTER_TYPED_TEST_SUITE_P
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-#define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...) \
- static_assert(sizeof(GTEST_STRINGIFY_(Prefix)) > 1, \
- "test-suit-prefix must not be empty"); \
- GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool \
- gtest_##Prefix##_##SuiteName = \
- ::testing::internal::TypeParameterizedTestSuite< \
- SuiteName, GTEST_SUITE_NAMESPACE_(SuiteName)::gtest_AllTests_, \
- ::testing::internal::GenerateTypeList<Types>::type>:: \
- Register( \
- GTEST_STRINGIFY_(Prefix), \
- ::testing::internal::CodeLocation(__FILE__, __LINE__), \
- &GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName), \
- GTEST_STRINGIFY_(SuiteName), \
- GTEST_REGISTERED_TEST_NAMES_(SuiteName), \
- ::testing::internal::GenerateNames< \
- ::testing::internal::NameGeneratorSelector< \
- __VA_ARGS__>::type, \
- ::testing::internal::GenerateTypeList<Types>::type>())
+#define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...) \
+ static_assert(sizeof(GTEST_STRINGIFY_(Prefix)) > 1, \
+ "test-suit-prefix must not be empty"); \
+ [[maybe_unused]] static bool gtest_##Prefix##_##SuiteName = \
+ ::testing::internal::TypeParameterizedTestSuite< \
+ SuiteName, GTEST_SUITE_NAMESPACE_(SuiteName)::gtest_AllTests_, \
+ ::testing::internal::GenerateTypeList<Types>::type>:: \
+ Register(GTEST_STRINGIFY_(Prefix), \
+ ::testing::internal::CodeLocation(__FILE__, __LINE__), \
+ &GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName), \
+ GTEST_STRINGIFY_(SuiteName), \
+ GTEST_REGISTERED_TEST_NAMES_(SuiteName), \
+ ::testing::internal::GenerateNames< \
+ ::testing::internal::NameGeneratorSelector< \
+ __VA_ARGS__>::type, \
+ ::testing::internal::GenerateTypeList<Types>::type>())
// Legacy API is deprecated but still available
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
diff --git a/googletest/include/gtest/gtest.h b/googletest/include/gtest/gtest.h
index c899669..69994ee 100644
--- a/googletest/include/gtest/gtest.h
+++ b/googletest/include/gtest/gtest.h
@@ -1123,7 +1123,7 @@ class GTEST_API_ UnitTest {
// This method can only be called from the main thread.
//
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
- int Run() GTEST_MUST_USE_RESULT_;
+ [[nodiscard]] int Run();
// Returns the working directory when the first TEST() or TEST_F()
// was executed. The UnitTest object owns the string.
@@ -1610,6 +1610,8 @@ GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1,
double val1, double val2,
double abs_error);
+using GoogleTest_NotSupported_OnFunctionReturningNonVoid = void;
+
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
// A class that enables one to stream messages to assertion macros
class GTEST_API_ AssertHelper {
@@ -1621,7 +1623,8 @@ class GTEST_API_ AssertHelper {
// Message assignment is a semantic trick to enable assertion
// streaming; see the GTEST_MESSAGE_ macro below.
- void operator=(const Message& message) const;
+ GoogleTest_NotSupported_OnFunctionReturningNonVoid operator=(
+ const Message& message) const;
private:
// We put our data in a struct so that the size of the AssertHelper class can
@@ -1693,7 +1696,7 @@ class WithParamInterface {
// The current parameter value. Is also available in the test fixture's
// constructor.
- static const ParamType& GetParam() {
+ [[nodiscard]] static const ParamType& GetParam() {
GTEST_CHECK_(parameter_ != nullptr)
<< "GetParam() can only be called inside a value-parameterized test "
<< "-- did you intend to write TEST_P instead of TEST_F?";
@@ -2329,7 +2332,7 @@ TestInfo* RegisterTest(const char* test_suite_name, const char* test_name,
//
// This function was formerly a macro; thus, it is in the global
// namespace and has an all-caps name.
-int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_;
+[[nodiscard]] int RUN_ALL_TESTS();
inline int RUN_ALL_TESTS() { return ::testing::UnitTest::GetInstance()->Run(); }
diff --git a/googletest/include/gtest/internal/gtest-internal.h b/googletest/include/gtest/internal/gtest-internal.h
index 7e55dc6..808d89b 100644
--- a/googletest/include/gtest/internal/gtest-internal.h
+++ b/googletest/include/gtest/internal/gtest-internal.h
@@ -290,17 +290,17 @@ class FloatingPoint {
// around may change its bits, although the new value is guaranteed
// to be also a NAN. Therefore, don't expect this constructor to
// preserve the bits in x when x is a NAN.
- explicit FloatingPoint(const RawType& x) { u_.value_ = x; }
+ explicit FloatingPoint(RawType x) { memcpy(&bits_, &x, sizeof(x)); }
// Static methods
// Reinterprets a bit pattern as a floating-point number.
//
// This function is needed to test the AlmostEquals() method.
- static RawType ReinterpretBits(const Bits bits) {
- FloatingPoint fp(0);
- fp.u_.bits_ = bits;
- return fp.u_.value_;
+ static RawType ReinterpretBits(Bits bits) {
+ RawType fp;
+ memcpy(&fp, &bits, sizeof(fp));
+ return fp;
}
// Returns the floating-point number that represent positive infinity.
@@ -309,16 +309,16 @@ class FloatingPoint {
// Non-static methods
// Returns the bits that represents this number.
- const Bits& bits() const { return u_.bits_; }
+ const Bits& bits() const { return bits_; }
// Returns the exponent bits of this number.
- Bits exponent_bits() const { return kExponentBitMask & u_.bits_; }
+ Bits exponent_bits() const { return kExponentBitMask & bits_; }
// Returns the fraction bits of this number.
- Bits fraction_bits() const { return kFractionBitMask & u_.bits_; }
+ Bits fraction_bits() const { return kFractionBitMask & bits_; }
// Returns the sign bit of this number.
- Bits sign_bit() const { return kSignBitMask & u_.bits_; }
+ Bits sign_bit() const { return kSignBitMask & bits_; }
// Returns true if and only if this is NAN (not a number).
bool is_nan() const {
@@ -332,23 +332,16 @@ class FloatingPoint {
//
// - returns false if either number is (or both are) NAN.
// - treats really large numbers as almost equal to infinity.
- // - thinks +0.0 and -0.0 are 0 DLP's apart.
+ // - thinks +0.0 and -0.0 are 0 ULP's apart.
bool AlmostEquals(const FloatingPoint& rhs) const {
// The IEEE standard says that any comparison operation involving
// a NAN must return false.
if (is_nan() || rhs.is_nan()) return false;
- return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_) <=
- kMaxUlps;
+ return DistanceBetweenSignAndMagnitudeNumbers(bits_, rhs.bits_) <= kMaxUlps;
}
private:
- // The data type used to store the actual floating-point number.
- union FloatingPointUnion {
- RawType value_; // The raw floating-point number.
- Bits bits_; // The bits that represent the number.
- };
-
// Converts an integer from the sign-and-magnitude representation to
// the biased representation. More precisely, let N be 2 to the
// power of (kBitCount - 1), an integer x is represented by the
@@ -364,7 +357,7 @@ class FloatingPoint {
//
// Read https://en.wikipedia.org/wiki/Signed_number_representations
// for more details on signed number representations.
- static Bits SignAndMagnitudeToBiased(const Bits& sam) {
+ static Bits SignAndMagnitudeToBiased(Bits sam) {
if (kSignBitMask & sam) {
// sam represents a negative number.
return ~sam + 1;
@@ -376,14 +369,13 @@ class FloatingPoint {
// Given two numbers in the sign-and-magnitude representation,
// returns the distance between them as an unsigned number.
- static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits& sam1,
- const Bits& sam2) {
+ static Bits DistanceBetweenSignAndMagnitudeNumbers(Bits sam1, Bits sam2) {
const Bits biased1 = SignAndMagnitudeToBiased(sam1);
const Bits biased2 = SignAndMagnitudeToBiased(sam2);
return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
}
- FloatingPointUnion u_;
+ Bits bits_; // The bits that represent the number.
};
// Typedefs the instances of the FloatingPoint template class that we
@@ -894,11 +886,6 @@ class HasDebugStringAndShortDebugString {
HasDebugStringType::value && HasShortDebugStringType::value;
};
-#ifdef GTEST_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-template <typename T>
-constexpr bool HasDebugStringAndShortDebugString<T>::value;
-#endif
-
// When the compiler sees expression IsContainerTest<C>(0), if C is an
// STL-style container class, the first overload of IsContainerTest
// will be viable (since both C::iterator* and C::const_iterator* are
@@ -1241,30 +1228,40 @@ class FlatTuple
// Utility functions to be called with static_assert to induce deprecation
// warnings.
-GTEST_INTERNAL_DEPRECATED(
+[[deprecated(
"INSTANTIATE_TEST_CASE_P is deprecated, please use "
- "INSTANTIATE_TEST_SUITE_P")
-constexpr bool InstantiateTestCase_P_IsDeprecated() { return true; }
+ "INSTANTIATE_TEST_SUITE_P")]]
+constexpr bool InstantiateTestCase_P_IsDeprecated() {
+ return true;
+}
-GTEST_INTERNAL_DEPRECATED(
+[[deprecated(
"TYPED_TEST_CASE_P is deprecated, please use "
- "TYPED_TEST_SUITE_P")
-constexpr bool TypedTestCase_P_IsDeprecated() { return true; }
+ "TYPED_TEST_SUITE_P")]]
+constexpr bool TypedTestCase_P_IsDeprecated() {
+ return true;
+}
-GTEST_INTERNAL_DEPRECATED(
+[[deprecated(
"TYPED_TEST_CASE is deprecated, please use "
- "TYPED_TEST_SUITE")
-constexpr bool TypedTestCaseIsDeprecated() { return true; }
+ "TYPED_TEST_SUITE")]]
+constexpr bool TypedTestCaseIsDeprecated() {
+ return true;
+}
-GTEST_INTERNAL_DEPRECATED(
+[[deprecated(
"REGISTER_TYPED_TEST_CASE_P is deprecated, please use "
- "REGISTER_TYPED_TEST_SUITE_P")
-constexpr bool RegisterTypedTestCase_P_IsDeprecated() { return true; }
+ "REGISTER_TYPED_TEST_SUITE_P")]]
+constexpr bool RegisterTypedTestCase_P_IsDeprecated() {
+ return true;
+}
-GTEST_INTERNAL_DEPRECATED(
+[[deprecated(
"INSTANTIATE_TYPED_TEST_CASE_P is deprecated, please use "
- "INSTANTIATE_TYPED_TEST_SUITE_P")
-constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; }
+ "INSTANTIATE_TYPED_TEST_SUITE_P")]]
+constexpr bool InstantiateTypedTestCase_P_IsDeprecated() {
+ return true;
+}
} // namespace internal
} // namespace testing
@@ -1501,8 +1498,7 @@ class NeverThrown {
\
private: \
void TestBody() override; \
- GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static ::testing::TestInfo* const \
- test_info_; \
+ [[maybe_unused]] static ::testing::TestInfo* const test_info_; \
}; \
\
::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name, \
diff --git a/googletest/include/gtest/internal/gtest-param-util.h b/googletest/include/gtest/internal/gtest-param-util.h
index cc7ea53..a092a86 100644
--- a/googletest/include/gtest/internal/gtest-param-util.h
+++ b/googletest/include/gtest/internal/gtest-param-util.h
@@ -39,6 +39,7 @@
#include <ctype.h>
#include <cassert>
+#include <functional>
#include <iterator>
#include <map>
#include <memory>
@@ -529,8 +530,7 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
// prefix). test_base_name is the name of an individual test without
// parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
// test suite base name and DoBar is test base name.
- void AddTestPattern(const char*,
- const char* test_base_name,
+ void AddTestPattern(const char*, const char* test_base_name,
TestMetaFactoryBase<ParamType>* meta_factory,
CodeLocation code_location) {
tests_.emplace_back(
@@ -952,11 +952,11 @@ class CartesianProductHolder {
std::tuple<Gen...> generators_;
};
-template <typename From, typename To>
+template <typename From, typename To, typename Func>
class ParamGeneratorConverter : public ParamGeneratorInterface<To> {
public:
- ParamGeneratorConverter(ParamGenerator<From> gen) // NOLINT
- : generator_(std::move(gen)) {}
+ ParamGeneratorConverter(ParamGenerator<From> gen, Func converter) // NOLINT
+ : generator_(std::move(gen)), converter_(std::move(converter)) {}
ParamIteratorInterface<To>* Begin() const override {
return new Iterator(this, generator_.begin(), generator_.end());
@@ -965,13 +965,21 @@ class ParamGeneratorConverter : public ParamGeneratorInterface<To> {
return new Iterator(this, generator_.end(), generator_.end());
}
+ // Returns the std::function wrapping the user-supplied converter callable. It
+ // is used by the iterator (see class Iterator below) to convert the object
+ // (of type FROM) returned by the ParamGenerator to an object of a type that
+ // can be static_cast to type TO.
+ const Func& TypeConverter() const { return converter_; }
+
private:
class Iterator : public ParamIteratorInterface<To> {
public:
- Iterator(const ParamGeneratorInterface<To>* base, ParamIterator<From> it,
+ Iterator(const ParamGeneratorConverter* base, ParamIterator<From> it,
ParamIterator<From> end)
: base_(base), it_(it), end_(end) {
- if (it_ != end_) value_ = std::make_shared<To>(static_cast<To>(*it_));
+ if (it_ != end_)
+ value_ =
+ std::make_shared<To>(static_cast<To>(base->TypeConverter()(*it_)));
}
~Iterator() override = default;
@@ -980,7 +988,9 @@ class ParamGeneratorConverter : public ParamGeneratorInterface<To> {
}
void Advance() override {
++it_;
- if (it_ != end_) value_ = std::make_shared<To>(static_cast<To>(*it_));
+ if (it_ != end_)
+ value_ =
+ std::make_shared<To>(static_cast<To>(base_->TypeConverter()(*it_)));
}
ParamIteratorInterface<To>* Clone() const override {
return new Iterator(*this);
@@ -1000,30 +1010,54 @@ class ParamGeneratorConverter : public ParamGeneratorInterface<To> {
private:
Iterator(const Iterator& other) = default;
- const ParamGeneratorInterface<To>* const base_;
+ const ParamGeneratorConverter* const base_;
ParamIterator<From> it_;
ParamIterator<From> end_;
std::shared_ptr<To> value_;
}; // class ParamGeneratorConverter::Iterator
ParamGenerator<From> generator_;
+ Func converter_;
}; // class ParamGeneratorConverter
-template <class Gen>
+template <class GeneratedT,
+ typename StdFunction =
+ std::function<const GeneratedT&(const GeneratedT&)>>
class ParamConverterGenerator {
public:
- ParamConverterGenerator(ParamGenerator<Gen> g) // NOLINT
- : generator_(std::move(g)) {}
+ ParamConverterGenerator(ParamGenerator<GeneratedT> g) // NOLINT
+ : generator_(std::move(g)), converter_(Identity) {}
+
+ ParamConverterGenerator(ParamGenerator<GeneratedT> g, StdFunction converter)
+ : generator_(std::move(g)), converter_(std::move(converter)) {}
template <typename T>
operator ParamGenerator<T>() const { // NOLINT
- return ParamGenerator<T>(new ParamGeneratorConverter<Gen, T>(generator_));
+ return ParamGenerator<T>(
+ new ParamGeneratorConverter<GeneratedT, T, StdFunction>(generator_,
+ converter_));
}
private:
- ParamGenerator<Gen> generator_;
+ static const GeneratedT& Identity(const GeneratedT& v) { return v; }
+
+ ParamGenerator<GeneratedT> generator_;
+ StdFunction converter_;
+};
+
+// Template to determine the param type of a single-param std::function.
+template <typename T>
+struct FuncSingleParamType;
+template <typename R, typename P>
+struct FuncSingleParamType<std::function<R(P)>> {
+ using type = std::remove_cv_t<std::remove_reference_t<P>>;
};
+template <typename T>
+struct IsSingleArgStdFunction : public std::false_type {};
+template <typename R, typename P>
+struct IsSingleArgStdFunction<std::function<R(P)>> : public std::true_type {};
+
} // namespace internal
} // namespace testing
diff --git a/googletest/include/gtest/internal/gtest-port.h b/googletest/include/gtest/internal/gtest-port.h
index ca18513..9bd41cd 100644
--- a/googletest/include/gtest/internal/gtest-port.h
+++ b/googletest/include/gtest/internal/gtest-port.h
@@ -194,26 +194,12 @@
//
// Macros for basic C++ coding:
// GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning.
-// GTEST_MUST_USE_RESULT_ - declares that a function's result must be used.
// GTEST_INTENTIONAL_CONST_COND_PUSH_ - start code section where MSVC C4127 is
// suppressed (constant conditional).
// GTEST_INTENTIONAL_CONST_COND_POP_ - finish code section where MSVC C4127
// is suppressed.
-// GTEST_INTERNAL_HAS_ANY - for enabling UniversalPrinter<std::any> or
-// UniversalPrinter<absl::any> specializations.
-// Always defined to 0 or 1.
-// GTEST_INTERNAL_HAS_OPTIONAL - for enabling UniversalPrinter<std::optional>
-// or
-// UniversalPrinter<absl::optional>
-// specializations. Always defined to 0 or 1.
// GTEST_INTERNAL_HAS_STD_SPAN - for enabling UniversalPrinter<std::span>
// specializations. Always defined to 0 or 1
-// GTEST_INTERNAL_HAS_STRING_VIEW - for enabling Matcher<std::string_view> or
-// Matcher<absl::string_view>
-// specializations. Always defined to 0 or 1.
-// GTEST_INTERNAL_HAS_VARIANT - for enabling UniversalPrinter<std::variant> or
-// UniversalPrinter<absl::variant>
-// specializations. Always defined to 0 or 1.
// GTEST_USE_OWN_FLAGFILE_FLAG_ - Always defined to 0 or 1.
// GTEST_HAS_CXXABI_H_ - Always defined to 0 or 1.
// GTEST_CAN_STREAM_RESULTS_ - Always defined to 0 or 1.
@@ -260,11 +246,6 @@
// BoolFromGTestEnv() - parses a bool environment variable.
// Int32FromGTestEnv() - parses an int32_t environment variable.
// StringFromGTestEnv() - parses a string environment variable.
-//
-// Deprecation warnings:
-// GTEST_INTERNAL_DEPRECATED(message) - attribute marking a function as
-// deprecated; calling a marked function
-// should generate a compiler warning
// The definition of GTEST_INTERNAL_CPLUSPLUS_LANG comes first because it can
// potentially be used as an #include guard.
@@ -275,8 +256,8 @@
#endif
#if !defined(GTEST_INTERNAL_CPLUSPLUS_LANG) || \
- GTEST_INTERNAL_CPLUSPLUS_LANG < 201402L
-#error C++ versions less than C++14 are not supported.
+ GTEST_INTERNAL_CPLUSPLUS_LANG < 201703L
+#error C++ versions less than C++17 are not supported.
#endif
// MSVC >= 19.11 (VS 2017 Update 3) supports __has_include.
@@ -288,10 +269,14 @@
// Detect C++ feature test macros as gracefully as possible.
// MSVC >= 19.15, Clang >= 3.4.1, and GCC >= 4.1.2 support feature test macros.
-#if GTEST_INTERNAL_CPLUSPLUS_LANG >= 202002L && \
- (!defined(__has_include) || GTEST_INTERNAL_HAS_INCLUDE(<version>))
-#include <version> // C++20 and later
-#elif (!defined(__has_include) || GTEST_INTERNAL_HAS_INCLUDE(<ciso646>))
+//
+// GCC15 warns that <ciso646> is deprecated in C++17 and suggests using
+// <version> instead, even though <version> is not available in C++17 mode prior
+// to GCC9.
+#if GTEST_INTERNAL_CPLUSPLUS_LANG >= 202002L || \
+ GTEST_INTERNAL_HAS_INCLUDE(<version>)
+#include <version> // C++20 or <version> support.
+#else
#include <ciso646> // Pre-C++20
#endif
@@ -772,25 +757,6 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
#define GTEST_HAVE_FEATURE_(x) 0
#endif
-// Use this annotation after a variable or parameter declaration to tell the
-// compiler the variable/parameter may be used.
-// Example:
-//
-// GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED int foo = bar();
-//
-// This can be removed once we only support only C++17 or newer and
-// [[maybe_unused]] is available on all supported platforms.
-#if GTEST_INTERNAL_HAVE_CPP_ATTRIBUTE(maybe_unused)
-#define GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED [[maybe_unused]]
-#elif GTEST_HAVE_ATTRIBUTE_(unused)
-// This is inferior to [[maybe_unused]] as it can produce a
-// -Wused-but-marked-unused warning on optionally used symbols, but it is all we
-// have.
-#define GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED __attribute__((__unused__))
-#else
-#define GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED
-#endif
-
// Use this annotation before a function that takes a printf format string.
#if GTEST_HAVE_ATTRIBUTE_(format) && defined(__MINGW_PRINTF_FORMAT)
// MinGW has two different printf implementations. Ensure the format macro
@@ -805,17 +771,6 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
#define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check)
#endif
-// Tell the compiler to warn about unused return values for functions declared
-// with this macro. The macro should be used on function declarations
-// following the argument list:
-//
-// Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_;
-#if GTEST_HAVE_ATTRIBUTE_(warn_unused_result)
-#define GTEST_MUST_USE_RESULT_ __attribute__((warn_unused_result))
-#else
-#define GTEST_MUST_USE_RESULT_
-#endif
-
// MS C++ compiler emits warning when a conditional expression is compile time
// constant. In some contexts this warning is false positive and needs to be
// suppressed. Use the following two macros in such cases:
@@ -1430,9 +1385,9 @@ class GTEST_API_ Mutex {
Mutex();
~Mutex();
- void Lock();
+ void lock();
- void Unlock();
+ void unlock();
// Does nothing if the current thread holds the mutex. Otherwise, crashes
// with high probability.
@@ -1469,9 +1424,9 @@ class GTEST_API_ Mutex {
// "MutexLock l(&mu)". Hence the typedef trick below.
class GTestMutexLock {
public:
- explicit GTestMutexLock(Mutex* mutex) : mutex_(mutex) { mutex_->Lock(); }
+ explicit GTestMutexLock(Mutex* mutex) : mutex_(mutex) { mutex_->lock(); }
- ~GTestMutexLock() { mutex_->Unlock(); }
+ ~GTestMutexLock() { mutex_->unlock(); }
private:
Mutex* const mutex_;
@@ -1686,14 +1641,14 @@ class ThreadLocal : public ThreadLocalBase {
class MutexBase {
public:
// Acquires this mutex.
- void Lock() {
+ void lock() {
GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_));
owner_ = pthread_self();
has_owner_ = true;
}
// Releases this mutex.
- void Unlock() {
+ void unlock() {
// Since the lock is being released the owner_ field should no longer be
// considered valid. We don't protect writing to has_owner_ here, as it's
// the caller's responsibility to ensure that the current thread holds the
@@ -1761,9 +1716,9 @@ class Mutex : public MutexBase {
// "MutexLock l(&mu)". Hence the typedef trick below.
class GTestMutexLock {
public:
- explicit GTestMutexLock(MutexBase* mutex) : mutex_(mutex) { mutex_->Lock(); }
+ explicit GTestMutexLock(MutexBase* mutex) : mutex_(mutex) { mutex_->lock(); }
- ~GTestMutexLock() { mutex_->Unlock(); }
+ ~GTestMutexLock() { mutex_->unlock(); }
private:
MutexBase* const mutex_;
@@ -1909,8 +1864,8 @@ class GTEST_API_ ThreadLocal {
class Mutex {
public:
Mutex() {}
- void Lock() {}
- void Unlock() {}
+ void lock() {}
+ void unlock() {}
void AssertHeld() const {}
};
@@ -2367,93 +2322,6 @@ const char* StringFromGTestEnv(const char* flag, const char* default_val);
} // namespace internal
} // namespace testing
-#if !defined(GTEST_INTERNAL_DEPRECATED)
-
-// Internal Macro to mark an API deprecated, for googletest usage only
-// Usage: class GTEST_INTERNAL_DEPRECATED(message) MyClass or
-// GTEST_INTERNAL_DEPRECATED(message) <return_type> myFunction(); Every usage of
-// a deprecated entity will trigger a warning when compiled with
-// `-Wdeprecated-declarations` option (clang, gcc, any __GNUC__ compiler).
-// For msvc /W3 option will need to be used
-// Note that for 'other' compilers this macro evaluates to nothing to prevent
-// compilations errors.
-#if defined(_MSC_VER)
-#define GTEST_INTERNAL_DEPRECATED(message) __declspec(deprecated(message))
-#elif defined(__GNUC__)
-#define GTEST_INTERNAL_DEPRECATED(message) __attribute__((deprecated(message)))
-#else
-#define GTEST_INTERNAL_DEPRECATED(message)
-#endif
-
-#endif // !defined(GTEST_INTERNAL_DEPRECATED)
-
-#ifdef GTEST_HAS_ABSL
-// Always use absl::any for UniversalPrinter<> specializations if googletest
-// is built with absl support.
-#define GTEST_INTERNAL_HAS_ANY 1
-#include "absl/types/any.h"
-namespace testing {
-namespace internal {
-using Any = ::absl::any;
-} // namespace internal
-} // namespace testing
-#else
-#if defined(__cpp_lib_any) || (GTEST_INTERNAL_HAS_INCLUDE(<any>) && \
- GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L && \
- (!defined(_MSC_VER) || GTEST_HAS_RTTI))
-// Otherwise for C++17 and higher use std::any for UniversalPrinter<>
-// specializations.
-#define GTEST_INTERNAL_HAS_ANY 1
-#include <any>
-namespace testing {
-namespace internal {
-using Any = ::std::any;
-} // namespace internal
-} // namespace testing
-// The case where absl is configured NOT to alias std::any is not
-// supported.
-#endif // __cpp_lib_any
-#endif // GTEST_HAS_ABSL
-
-#ifndef GTEST_INTERNAL_HAS_ANY
-#define GTEST_INTERNAL_HAS_ANY 0
-#endif
-
-#ifdef GTEST_HAS_ABSL
-// Always use absl::optional for UniversalPrinter<> specializations if
-// googletest is built with absl support.
-#define GTEST_INTERNAL_HAS_OPTIONAL 1
-#include "absl/types/optional.h"
-namespace testing {
-namespace internal {
-template <typename T>
-using Optional = ::absl::optional<T>;
-inline ::absl::nullopt_t Nullopt() { return ::absl::nullopt; }
-} // namespace internal
-} // namespace testing
-#else
-#if defined(__cpp_lib_optional) || (GTEST_INTERNAL_HAS_INCLUDE(<optional>) && \
- GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L)
-// Otherwise for C++17 and higher use std::optional for UniversalPrinter<>
-// specializations.
-#define GTEST_INTERNAL_HAS_OPTIONAL 1
-#include <optional>
-namespace testing {
-namespace internal {
-template <typename T>
-using Optional = ::std::optional<T>;
-inline ::std::nullopt_t Nullopt() { return ::std::nullopt; }
-} // namespace internal
-} // namespace testing
-// The case where absl is configured NOT to alias std::optional is not
-// supported.
-#endif // __cpp_lib_optional
-#endif // GTEST_HAS_ABSL
-
-#ifndef GTEST_INTERNAL_HAS_OPTIONAL
-#define GTEST_INTERNAL_HAS_OPTIONAL 0
-#endif
-
#if defined(__cpp_lib_span) || (GTEST_INTERNAL_HAS_INCLUDE(<span>) && \
GTEST_INTERNAL_CPLUSPLUS_LANG >= 202002L)
#define GTEST_INTERNAL_HAS_STD_SPAN 1
@@ -2495,44 +2363,6 @@ using StringView = ::std::string_view;
#define GTEST_INTERNAL_HAS_STRING_VIEW 0
#endif
-#ifdef GTEST_HAS_ABSL
-// Always use absl::variant for UniversalPrinter<> specializations if googletest
-// is built with absl support.
-#define GTEST_INTERNAL_HAS_VARIANT 1
-#include "absl/types/variant.h"
-namespace testing {
-namespace internal {
-template <typename... T>
-using Variant = ::absl::variant<T...>;
-} // namespace internal
-} // namespace testing
-#else
-#if defined(__cpp_lib_variant) || (GTEST_INTERNAL_HAS_INCLUDE(<variant>) && \
- GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L)
-// Otherwise for C++17 and higher use std::variant for UniversalPrinter<>
-// specializations.
-#define GTEST_INTERNAL_HAS_VARIANT 1
-#include <variant>
-namespace testing {
-namespace internal {
-template <typename... T>
-using Variant = ::std::variant<T...>;
-} // namespace internal
-} // namespace testing
-// The case where absl is configured NOT to alias std::variant is not supported.
-#endif // __cpp_lib_variant
-#endif // GTEST_HAS_ABSL
-
-#ifndef GTEST_INTERNAL_HAS_VARIANT
-#define GTEST_INTERNAL_HAS_VARIANT 0
-#endif
-
-#if (defined(__cpp_constexpr) && !defined(__cpp_inline_variables)) || \
- (defined(GTEST_INTERNAL_CPLUSPLUS_LANG) && \
- GTEST_INTERNAL_CPLUSPLUS_LANG < 201703L)
-#define GTEST_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL 1
-#endif
-
#if (defined(__cpp_lib_three_way_comparison) || \
(GTEST_INTERNAL_HAS_INCLUDE(<compare>) && \
GTEST_INTERNAL_CPLUSPLUS_LANG >= 201907L))
diff --git a/googletest/src/gtest-internal-inl.h b/googletest/src/gtest-internal-inl.h
index cc6f004..6a39b93 100644
--- a/googletest/src/gtest-internal-inl.h
+++ b/googletest/src/gtest-internal-inl.h
@@ -826,6 +826,10 @@ class GTEST_API_ UnitTestImpl {
bool catch_exceptions() const { return catch_exceptions_; }
private:
+ // Returns true if a warning should be issued if no tests match the test
+ // filter flag.
+ bool ShouldWarnIfNoTestsMatchFilter() const;
+
struct CompareTestSuitesByPointer {
bool operator()(const TestSuite* lhs, const TestSuite* rhs) const {
return lhs->name_ < rhs->name_;
diff --git a/googletest/src/gtest-port.cc b/googletest/src/gtest-port.cc
index 1038ad7..490dbb5 100644
--- a/googletest/src/gtest-port.cc
+++ b/googletest/src/gtest-port.cc
@@ -320,13 +320,13 @@ Mutex::~Mutex() {
}
}
-void Mutex::Lock() {
+void Mutex::lock() {
ThreadSafeLazyInit();
::EnterCriticalSection(critical_section_);
owner_thread_id_ = ::GetCurrentThreadId();
}
-void Mutex::Unlock() {
+void Mutex::unlock() {
ThreadSafeLazyInit();
// We don't protect writing to owner_thread_id_ here, as it's the
// caller's responsibility to ensure that the current thread holds the
diff --git a/googletest/src/gtest-printers.cc b/googletest/src/gtest-printers.cc
index e3acecb..f655730 100644
--- a/googletest/src/gtest-printers.cc
+++ b/googletest/src/gtest-printers.cc
@@ -50,7 +50,7 @@
#include <iomanip>
#include <ios>
#include <ostream> // NOLINT
-#include <string>
+#include <string_view>
#include <type_traits>
#include "gtest/internal/gtest-port.h"
@@ -333,14 +333,14 @@ void PrintTo(__int128_t v, ::std::ostream* os) {
// Prints the given array of characters to the ostream. CharType must be either
// char, char8_t, char16_t, char32_t, or wchar_t.
-// The array starts at begin, the length is len, it may include '\0' characters
-// and may not be NUL-terminated.
+// The array starts at begin (which may be nullptr) and contains len characters.
+// The array may include '\0' characters and may not be NUL-terminated.
template <typename CharType>
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ static CharFormat
PrintCharsAsStringTo(const CharType* begin, size_t len, ostream* os) {
- const char* const quote_prefix = GetCharWidthPrefix(*begin);
+ const char* const quote_prefix = GetCharWidthPrefix(CharType());
*os << quote_prefix << "\"";
bool is_previous_hex = false;
CharFormat print_format = kAsIs;
@@ -516,13 +516,13 @@ bool IsValidUTF8(const char* str, size_t length) {
void ConditionalPrintAsText(const char* str, size_t length, ostream* os) {
if (!ContainsUnprintableControlCodes(str, length) &&
IsValidUTF8(str, length)) {
- *os << "\n As Text: \"" << str << "\"";
+ *os << "\n As Text: \"" << ::std::string_view(str, length) << "\"";
}
}
} // anonymous namespace
-void PrintStringTo(const ::std::string& s, ostream* os) {
+void PrintStringTo(::std::string_view s, ostream* os) {
if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) {
if (GTEST_FLAG_GET(print_utf8)) {
ConditionalPrintAsText(s.data(), s.size(), os);
@@ -531,21 +531,21 @@ void PrintStringTo(const ::std::string& s, ostream* os) {
}
#ifdef __cpp_lib_char8_t
-void PrintU8StringTo(const ::std::u8string& s, ostream* os) {
+void PrintU8StringTo(::std::u8string_view s, ostream* os) {
PrintCharsAsStringTo(s.data(), s.size(), os);
}
#endif
-void PrintU16StringTo(const ::std::u16string& s, ostream* os) {
+void PrintU16StringTo(::std::u16string_view s, ostream* os) {
PrintCharsAsStringTo(s.data(), s.size(), os);
}
-void PrintU32StringTo(const ::std::u32string& s, ostream* os) {
+void PrintU32StringTo(::std::u32string_view s, ostream* os) {
PrintCharsAsStringTo(s.data(), s.size(), os);
}
#if GTEST_HAS_STD_WSTRING
-void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
+void PrintWideStringTo(::std::wstring_view s, ostream* os) {
PrintCharsAsStringTo(s.data(), s.size(), os);
}
#endif // GTEST_HAS_STD_WSTRING
diff --git a/googletest/src/gtest.cc b/googletest/src/gtest.cc
index 3c1cac6..cd218c9 100644
--- a/googletest/src/gtest.cc
+++ b/googletest/src/gtest.cc
@@ -192,12 +192,17 @@ static const char kDefaultOutputFormat[] = "xml";
// The default output file.
static const char kDefaultOutputFile[] = "test_detail";
+// These environment variables are set by Bazel.
+// https://bazel.build/reference/test-encyclopedia#initial-conditions
+//
// The environment variable name for the test shard index.
static const char kTestShardIndex[] = "GTEST_SHARD_INDEX";
// The environment variable name for the total number of test shards.
static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS";
// The environment variable name for the test shard status file.
static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE";
+// The environment variable name for the test output warnings file.
+static const char kTestWarningsOutputFile[] = "TEST_WARNINGS_OUTPUT_FILE";
namespace internal {
@@ -259,6 +264,19 @@ GTEST_DEFINE_bool_(
"True if and only if a test failure should stop further test execution.");
GTEST_DEFINE_bool_(
+ fail_if_no_test_linked,
+ testing::internal::BoolFromGTestEnv("fail_if_no_test_linked", false),
+ "True if and only if the test should fail if no test case (including "
+ "disabled test cases) is linked.");
+
+GTEST_DEFINE_bool_(
+ fail_if_no_test_selected,
+ testing::internal::BoolFromGTestEnv("fail_if_no_test_selected", false),
+ "True if and only if the test should fail if no test case is selected to "
+ "run. A test case is selected to run if it is not disabled and is matched "
+ "by the filter flag so that it starts executing.");
+
+GTEST_DEFINE_bool_(
also_run_disabled_tests,
testing::internal::BoolFromGTestEnv("also_run_disabled_tests", false),
"Run disabled tests too, in addition to the tests normally being run.");
@@ -695,7 +713,7 @@ std::string UnitTestOptions::GetAbsolutePathToOutputFile() {
const char* const gtest_output_flag = s.c_str();
std::string format = GetOutputFormat();
- if (format.empty()) format = std::string(kDefaultOutputFormat);
+ if (format.empty()) format = kDefaultOutputFormat;
const char* const colon = strchr(gtest_output_flag, ':');
if (colon == nullptr)
@@ -1477,17 +1495,17 @@ class Hunk {
// Print a unified diff header for one hunk.
// The format is
// "@@ -<left_start>,<left_length> +<right_start>,<right_length> @@"
- // where the left/right parts are omitted if unnecessary.
+ // where the left/right lengths are omitted if unnecessary.
void PrintHeader(std::ostream* ss) const {
- *ss << "@@ ";
- if (removes_) {
- *ss << "-" << left_start_ << "," << (removes_ + common_);
- }
- if (removes_ && adds_) {
- *ss << " ";
+ size_t left_length = removes_ + common_;
+ size_t right_length = adds_ + common_;
+ *ss << "@@ " << "-" << left_start_;
+ if (left_length != 1) {
+ *ss << "," << left_length;
}
- if (adds_) {
- *ss << "+" << right_start_ << "," << (adds_ + common_);
+ *ss << " " << "+" << right_start_;
+ if (right_length != 1) {
+ *ss << "," << right_length;
}
*ss << " @@\n";
}
@@ -3287,6 +3305,7 @@ bool ShouldUseColor(bool stdout_is_tty) {
const bool term_supports_color =
term != nullptr && (String::CStringEquals(term, "xterm") ||
String::CStringEquals(term, "xterm-color") ||
+ String::CStringEquals(term, "xterm-ghostty") ||
String::CStringEquals(term, "xterm-kitty") ||
String::CStringEquals(term, "alacritty") ||
String::CStringEquals(term, "screen") ||
@@ -4012,16 +4031,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_;
@@ -4341,8 +4355,8 @@ void XmlUnitTestResultPrinter::OutputXmlTestResult(::std::ostream* stream,
internal::FormatCompilerIndependentFileLocation(part.file_name(),
part.line_number());
const std::string summary = location + "\n" + part.summary();
- *stream << " <skipped message=\""
- << EscapeXmlAttribute(summary.c_str()) << "\">";
+ *stream << " <skipped message=\"" << EscapeXmlAttribute(summary)
+ << "\">";
const std::string detail = location + "\n" + part.message();
OutputXmlCDataSection(stream, RemoveInvalidXmlCharacters(detail).c_str());
*stream << "</skipped>\n";
@@ -4355,7 +4369,7 @@ void XmlUnitTestResultPrinter::OutputXmlTestResult(::std::ostream* stream,
if (failures == 0 && skips == 0) {
*stream << ">\n";
}
- OutputXmlTestProperties(stream, result);
+ OutputXmlTestProperties(stream, result, /*indent=*/" ");
*stream << " </testcase>\n";
}
}
@@ -4384,9 +4398,10 @@ 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));
@@ -4424,11 +4439,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));
@@ -4465,21 +4481,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";
@@ -4487,15 +4490,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
@@ -5885,6 +5888,23 @@ TestSuite* UnitTestImpl::GetTestSuite(
static void SetUpEnvironment(Environment* env) { env->SetUp(); }
static void TearDownEnvironment(Environment* env) { env->TearDown(); }
+// If the environment variable TEST_WARNINGS_OUTPUT_FILE was provided, appends
+// `str` to the file, creating the file if necessary.
+#if GTEST_HAS_FILE_SYSTEM
+static void AppendToTestWarningsOutputFile(const std::string& str) {
+ const char* const filename = posix::GetEnv(kTestWarningsOutputFile);
+ if (filename == nullptr) {
+ return;
+ }
+ auto* const file = posix::FOpen(filename, "a");
+ if (file == nullptr) {
+ return;
+ }
+ GTEST_CHECK_(fwrite(str.data(), 1, str.size(), file) == str.size());
+ GTEST_CHECK_(posix::FClose(file) == 0);
+}
+#endif // GTEST_HAS_FILE_SYSTEM
+
// Runs all tests in this UnitTest object, prints the result, and
// returns true if all tests are successful. If any exception is
// thrown during a test, the test is considered to be failed, but the
@@ -5906,6 +5926,28 @@ bool UnitTestImpl::RunAllTests() {
// user didn't call InitGoogleTest.
PostFlagParsingInit();
+ // Handle the case where the program has no tests linked.
+ // Sometimes this is a programmer mistake, but sometimes it is intended.
+ if (total_test_count() == 0) {
+ constexpr char kNoTestLinkedMessage[] =
+ "This test program does NOT link in any test case.";
+ constexpr char kNoTestLinkedFatal[] =
+ "This is INVALID. Please make sure to link in at least one test case.";
+ constexpr char kNoTestLinkedWarning[] =
+ "Please make sure this is intended.";
+ const bool fail_if_no_test_linked = GTEST_FLAG_GET(fail_if_no_test_linked);
+ ColoredPrintf(
+ GTestColor::kRed, "%s %s\n", kNoTestLinkedMessage,
+ fail_if_no_test_linked ? kNoTestLinkedFatal : kNoTestLinkedWarning);
+ if (fail_if_no_test_linked) {
+ return false;
+ }
+#if GTEST_HAS_FILE_SYSTEM
+ AppendToTestWarningsOutputFile(std::string(kNoTestLinkedMessage) + ' ' +
+ kNoTestLinkedWarning + '\n');
+#endif // GTEST_HAS_FILE_SYSTEM
+ }
+
#if GTEST_HAS_FILE_SYSTEM
// Even if sharding is not on, test runners may want to use the
// GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding
@@ -6045,6 +6087,18 @@ bool UnitTestImpl::RunAllTests() {
TearDownEnvironment);
repeater->OnEnvironmentsTearDownEnd(*parent_);
}
+ } else if (GTEST_FLAG_GET(fail_if_no_test_selected)) {
+ // If there were no tests to run, bail if we were requested to be strict.
+ constexpr char kNoTestsSelectedMessage[] =
+ "No tests were selected to run. Please make sure at least one test "
+ "exists and is not disabled! If the test is sharded, you may have "
+ "defined more shards than test cases, which is wasteful. If you also "
+ "defined --gtest_filter, that filter is taken into account, so "
+ "shards with no matching test cases will hit this error. Either "
+ "disable sharding, set --gtest_fail_if_no_test_selected=false, or "
+ "remove the filter to resolve this error.";
+ ColoredPrintf(GTestColor::kRed, "%s\n", kNoTestsSelectedMessage);
+ return false;
}
elapsed_time_ = timer.Elapsed();
@@ -6079,6 +6133,17 @@ bool UnitTestImpl::RunAllTests() {
environments_.clear();
}
+ // Try to warn the user if no tests matched the test filter.
+ if (ShouldWarnIfNoTestsMatchFilter()) {
+ const std::string filter_warning =
+ std::string("filter \"") + GTEST_FLAG_GET(filter) +
+ "\" did not match any test; no tests were run\n";
+ ColoredPrintf(GTestColor::kRed, "WARNING: %s", filter_warning.c_str());
+#if GTEST_HAS_FILE_SYSTEM
+ AppendToTestWarningsOutputFile(filter_warning);
+#endif // GTEST_HAS_FILE_SYSTEM
+ }
+
if (!gtest_is_initialized_before_run_all_tests) {
ColoredPrintf(
GTestColor::kRed,
@@ -6247,6 +6312,30 @@ int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
return num_selected_tests;
}
+// Returns true if a warning should be issued if no tests match the test filter
+// flag. We can't simply count the number of tests that ran because, for
+// instance, test sharding and death tests might mean no tests are expected to
+// run in this process, but will run in another process.
+bool UnitTestImpl::ShouldWarnIfNoTestsMatchFilter() const {
+ if (total_test_count() == 0) {
+ // No tests were linked in to program.
+ // This case is handled by a different warning.
+ return false;
+ }
+ const PositiveAndNegativeUnitTestFilter gtest_flag_filter(
+ GTEST_FLAG_GET(filter));
+ for (auto* test_suite : test_suites_) {
+ const std::string& test_suite_name = test_suite->name_;
+ for (TestInfo* test_info : test_suite->test_info_list()) {
+ const std::string& test_name = test_info->name_;
+ if (gtest_flag_filter.MatchesTest(test_suite_name, test_name)) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
// Prints the given C-string on a single line by replacing all '\n'
// characters with string "\\n". If the output takes more than
// max_length characters, only prints the first max_length characters
@@ -6693,6 +6782,8 @@ static bool ParseGoogleTestFlag(const char* const arg) {
GTEST_INTERNAL_PARSE_FLAG(death_test_style);
GTEST_INTERNAL_PARSE_FLAG(death_test_use_fork);
GTEST_INTERNAL_PARSE_FLAG(fail_fast);
+ GTEST_INTERNAL_PARSE_FLAG(fail_if_no_test_linked);
+ GTEST_INTERNAL_PARSE_FLAG(fail_if_no_test_selected);
GTEST_INTERNAL_PARSE_FLAG(filter);
GTEST_INTERNAL_PARSE_FLAG(internal_run_death_test);
GTEST_INTERNAL_PARSE_FLAG(list_tests);
diff --git a/googletest/test/BUILD.bazel b/googletest/test/BUILD.bazel
index 1890b6f..c561ef8 100644
--- a/googletest/test/BUILD.bazel
+++ b/googletest/test/BUILD.bazel
@@ -45,36 +45,38 @@ cc_test(
"gtest-*.cc",
"googletest-*.cc",
"*.h",
- "googletest/include/gtest/**/*.h",
],
exclude = [
- "gtest-unittest-api_test.cc",
- "googletest/src/gtest-all.cc",
- "gtest_all_test.cc",
- "gtest-death-test_ex_test.cc",
- "gtest-listener_test.cc",
- "gtest-unittest-api_test.cc",
- "googletest-param-test-test.cc",
- "googletest-param-test2-test.cc",
+ # go/keep-sorted start
+ "googletest-break-on-failure-unittest_.cc",
"googletest-catch-exceptions-test_.cc",
"googletest-color-test_.cc",
+ "googletest-death-test_ex_test.cc",
"googletest-env-var-test_.cc",
+ "googletest-fail-if-no-test-linked-test-with-disabled-test_.cc",
+ "googletest-fail-if-no-test-linked-test-with-enabled-test_.cc",
"googletest-failfast-unittest_.cc",
"googletest-filter-unittest_.cc",
"googletest-global-environment-unittest_.cc",
- "googletest-break-on-failure-unittest_.cc",
+ "googletest-list-tests-unittest_.cc",
"googletest-listener-test.cc",
"googletest-message-test.cc",
"googletest-output-test_.cc",
- "googletest-list-tests-unittest_.cc",
- "googletest-shuffle-test_.cc",
- "googletest-setuptestsuite-test_.cc",
- "googletest-uninitialized-test_.cc",
- "googletest-death-test_ex_test.cc",
- "googletest-param-test-test",
- "googletest-throw-on-failure-test_.cc",
"googletest-param-test-invalid-name1-test_.cc",
"googletest-param-test-invalid-name2-test_.cc",
+ "googletest-param-test-test",
+ "googletest-param-test-test.cc",
+ "googletest-param-test2-test.cc",
+ "googletest-setuptestsuite-test_.cc",
+ "googletest-shuffle-test_.cc",
+ "googletest-throw-on-failure-test_.cc",
+ "googletest-uninitialized-test_.cc",
+ "googletest/src/gtest-all.cc",
+ "gtest-death-test_ex_test.cc",
+ "gtest-listener_test.cc",
+ "gtest-unittest-api_test.cc",
+ "gtest_all_test.cc",
+ # go/keep-sorted end
],
) + select({
"//:windows": [],
@@ -324,6 +326,26 @@ cc_binary(
deps = ["//:gtest"],
)
+cc_binary(
+ name = "googletest-fail-if-no-test-linked-test-without-test_",
+ testonly = 1,
+ deps = ["//:gtest_main"],
+)
+
+cc_binary(
+ name = "googletest-fail-if-no-test-linked-test-with-disabled-test_",
+ testonly = 1,
+ srcs = ["googletest-fail-if-no-test-linked-test-with-disabled-test_.cc"],
+ deps = ["//:gtest_main"],
+)
+
+cc_binary(
+ name = "googletest-fail-if-no-test-linked-test-with-enabled-test_",
+ testonly = 1,
+ srcs = ["googletest-fail-if-no-test-linked-test-with-enabled-test_.cc"],
+ deps = ["//:gtest_main"],
+)
+
cc_test(
name = "gtest_skip_test",
size = "small",
@@ -364,6 +386,18 @@ py_test(
deps = [":gtest_test_utils"],
)
+py_test(
+ name = "googletest-fail-if-no-test-linked-test",
+ size = "small",
+ srcs = ["googletest-fail-if-no-test-linked-test.py"],
+ data = [
+ ":googletest-fail-if-no-test-linked-test-with-disabled-test_",
+ ":googletest-fail-if-no-test-linked-test-with-enabled-test_",
+ ":googletest-fail-if-no-test-linked-test-without-test_",
+ ],
+ deps = [":gtest_test_utils"],
+)
+
cc_binary(
name = "googletest-shuffle-test_",
srcs = ["googletest-shuffle-test_.cc"],
diff --git a/googletest/test/googletest-color-test.py b/googletest/test/googletest-color-test.py
index 8968cf1..76ca8e0 100755
--- a/googletest/test/googletest-color-test.py
+++ b/googletest/test/googletest-color-test.py
@@ -79,6 +79,7 @@ class GTestColorTest(gtest_test_utils.TestCase):
self.assertTrue(UsesColor('cygwin', None, None))
self.assertTrue(UsesColor('xterm', None, None))
self.assertTrue(UsesColor('xterm-color', None, None))
+ self.assertTrue(UsesColor('xterm-ghostty', None, None))
self.assertTrue(UsesColor('xterm-kitty', None, None))
self.assertTrue(UsesColor('alacritty', None, None))
self.assertTrue(UsesColor('xterm-256color', None, None))
diff --git a/googletest/test/googletest-death-test-test.cc b/googletest/test/googletest-death-test-test.cc
index 44b8046..8770315 100644
--- a/googletest/test/googletest-death-test-test.cc
+++ b/googletest/test/googletest-death-test-test.cc
@@ -291,7 +291,7 @@ TEST(ExitStatusPredicateTest, KilledBySignal) {
const int status_kill = KilledExitStatus(SIGKILL);
const testing::KilledBySignal pred_segv(SIGSEGV);
const testing::KilledBySignal pred_kill(SIGKILL);
-#if !(defined(GTEST_OS_LINUX_ANDROID) && __ANDROID_API__ <= 21)
+#if !(defined(GTEST_OS_LINUX_ANDROID) && __ANDROID_API__ <= 23)
EXPECT_PRED1(pred_segv, status_segv);
#endif
EXPECT_PRED1(pred_kill, status_kill);
diff --git a/googletest/test/googletest-fail-if-no-test-linked-test-with-disabled-test_.cc b/googletest/test/googletest-fail-if-no-test-linked-test-with-disabled-test_.cc
new file mode 100644
index 0000000..56d2690
--- /dev/null
+++ b/googletest/test/googletest-fail-if-no-test-linked-test-with-disabled-test_.cc
@@ -0,0 +1,38 @@
+// Copyright 2025, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Unit test for Google Test's --gtest_fail_if_no_test_linked flag.
+//
+// This program will be invoked from a Python test.
+// Don't run it directly.
+
+#include "gtest/gtest.h"
+
+// A dummy test that is disabled.
+TEST(SomeTest, DISABLED_Test1) {}
diff --git a/googletest/test/googletest-fail-if-no-test-linked-test-with-enabled-test_.cc b/googletest/test/googletest-fail-if-no-test-linked-test-with-enabled-test_.cc
new file mode 100644
index 0000000..1ed2034
--- /dev/null
+++ b/googletest/test/googletest-fail-if-no-test-linked-test-with-enabled-test_.cc
@@ -0,0 +1,38 @@
+// Copyright 2025, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Unit test for Google Test's --gtest_fail_if_no_test_linked flag.
+//
+// This program will be invoked from a Python test.
+// Don't run it directly.
+
+#include "gtest/gtest.h"
+
+// A dummy test that is enabled.
+TEST(SomeTest, Test1) {}
diff --git a/googletest/test/googletest-fail-if-no-test-linked-test.py b/googletest/test/googletest-fail-if-no-test-linked-test.py
new file mode 100755
index 0000000..e62bfb2
--- /dev/null
+++ b/googletest/test/googletest-fail-if-no-test-linked-test.py
@@ -0,0 +1,165 @@
+#!/usr/bin/env python3 # pylint: disable=g-interpreter-mismatch
+#
+# Copyright 2025, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Tests for Google Test's --gtest_fail_if_no_test_linked flag."""
+
+import os
+from googletest.test import gtest_test_utils
+
+# The command line flag for enabling the fail-if-no-test-linked behavior.
+FAIL_IF_NO_TEST_LINKED_FLAG = "gtest_fail_if_no_test_linked"
+
+# The environment variable for the test output warnings file.
+TEST_WARNINGS_OUTPUT_FILE = "TEST_WARNINGS_OUTPUT_FILE"
+
+
+class GTestFailIfNoTestLinkedTest(gtest_test_utils.TestCase):
+ """Tests the --gtest_fail_if_no_test_linked flag."""
+
+ def Run(self, program_name, flag=None, env=None):
+ """Run the given program with the given flag.
+
+ Args:
+ program_name: Name of the program to run.
+ flag: The command line flag to pass to the program, or None.
+ env: Dictionary with environment to pass to the subprocess.
+
+ Returns:
+ True if the program exits with code 0, false otherwise.
+ """
+
+ exe_path = gtest_test_utils.GetTestExecutablePath(program_name)
+ args = [exe_path]
+ if flag is not None:
+ args += [flag]
+ process = gtest_test_utils.Subprocess(args, capture_stderr=False, env=env)
+ return process.exited and process.exit_code == 0
+
+ def testSucceedsIfNoTestLinkedAndFlagNotSpecified(self):
+ """Tests the behavior of no test linked and flag not specified."""
+ self.assertTrue(
+ self.Run("googletest-fail-if-no-test-linked-test-without-test_")
+ )
+
+ def testSucceedsIfNoTestLinkedAndFlagNotSpecifiedWithWarningFile(self):
+ """Tests that no test linked results in warning file output."""
+
+ warning_file = os.path.join(gtest_test_utils.GetTempDir(), "NO_TEST_LINKED")
+ self.assertTrue(
+ self.Run(
+ "googletest-fail-if-no-test-linked-test-without-test_",
+ env={TEST_WARNINGS_OUTPUT_FILE: warning_file},
+ )
+ )
+ warning_file_contents = open(warning_file, "r").read()
+ self.assertIn("does NOT link", warning_file_contents)
+
+ def testFailsIfNoTestLinkedAndFlagSpecified(self):
+ """Tests the behavior of no test linked and flag specified."""
+
+ warning_file = os.path.join(
+ gtest_test_utils.GetTempDir(), "SHOULD_NOT_EXIST"
+ )
+ self.assertFalse(
+ self.Run(
+ "googletest-fail-if-no-test-linked-test-without-test_",
+ f"--{FAIL_IF_NO_TEST_LINKED_FLAG}",
+ env={TEST_WARNINGS_OUTPUT_FILE: warning_file},
+ )
+ )
+ with self.assertRaises(FileNotFoundError):
+ open(warning_file, "r")
+
+ def testSucceedsIfEnabledTestLinkedAndFlagNotSpecified(self):
+ """Tests the behavior of enabled test linked and flag not specified."""
+
+ warning_file = os.path.join(
+ gtest_test_utils.GetTempDir(), "SHOULD_NOT_EXIST"
+ )
+ self.assertTrue(
+ self.Run(
+ "googletest-fail-if-no-test-linked-test-with-enabled-test_",
+ env={TEST_WARNINGS_OUTPUT_FILE: warning_file},
+ )
+ )
+ with self.assertRaises(FileNotFoundError):
+ open(warning_file, "r")
+
+ def testSucceedsIfEnabledTestLinkedAndFlagSpecified(self):
+ """Tests the behavior of enabled test linked and flag specified."""
+
+ warning_file = os.path.join(
+ gtest_test_utils.GetTempDir(), "SHOULD_NOT_EXIST"
+ )
+ self.assertTrue(
+ self.Run(
+ "googletest-fail-if-no-test-linked-test-with-enabled-test_",
+ f"--{FAIL_IF_NO_TEST_LINKED_FLAG}",
+ env={TEST_WARNINGS_OUTPUT_FILE: warning_file},
+ )
+ )
+ with self.assertRaises(FileNotFoundError):
+ open(warning_file, "r")
+
+ def testSucceedsIfDisabledTestLinkedAndFlagNotSpecified(self):
+ """Tests the behavior of disabled test linked and flag not specified."""
+
+ warning_file = os.path.join(
+ gtest_test_utils.GetTempDir(), "SHOULD_NOT_EXIST"
+ )
+ self.assertTrue(
+ self.Run(
+ "googletest-fail-if-no-test-linked-test-with-disabled-test_",
+ env={TEST_WARNINGS_OUTPUT_FILE: warning_file},
+ )
+ )
+ with self.assertRaises(FileNotFoundError):
+ open(warning_file, "r")
+
+ def testSucceedsIfDisabledTestLinkedAndFlagSpecified(self):
+ """Tests the behavior of disabled test linked and flag specified."""
+
+ warning_file = os.path.join(
+ gtest_test_utils.GetTempDir(), "SHOULD_NOT_EXIST"
+ )
+ self.assertTrue(
+ self.Run(
+ "googletest-fail-if-no-test-linked-test-with-disabled-test_",
+ f"--{FAIL_IF_NO_TEST_LINKED_FLAG}",
+ env={TEST_WARNINGS_OUTPUT_FILE: warning_file},
+ )
+ )
+ with self.assertRaises(FileNotFoundError):
+ open(warning_file, "r")
+
+
+if __name__ == "__main__":
+ gtest_test_utils.Main()
diff --git a/googletest/test/googletest-fail-if-no-test-selected-test.py b/googletest/test/googletest-fail-if-no-test-selected-test.py
new file mode 100644
index 0000000..03a324c
--- /dev/null
+++ b/googletest/test/googletest-fail-if-no-test-selected-test.py
@@ -0,0 +1,91 @@
+#!/usr/bin/env python3 # pylint: disable=g-interpreter-mismatch
+#
+# Copyright 2025, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+"""Tests for Google Test's --gtest_fail_if_no_test_selected flag."""
+
+from googletest.test import gtest_test_utils
+
+
+# The command line flag for enabling the fail-if-no-test-selected behavior.
+FAIL_IF_NO_TEST_SELECTED_FLAG = "gtest_fail_if_no_test_selected"
+
+# The environment variable for the test output warnings file.
+TEST_WARNINGS_OUTPUT_FILE = "TEST_WARNINGS_OUTPUT_FILE"
+
+
+class GTestFailIfNoTestSelectedTest(gtest_test_utils.TestCase):
+ """Tests the --gtest_fail_if_no_test_selected flag."""
+
+ def Run(self, program_name, flags=None, env=None):
+ """Run the given program with the given flag.
+
+ Args:
+ program_name: Name of the program to run.
+ flags: The command line flags to pass to the program, or None.
+ env: Dictionary with environment to pass to the subprocess.
+
+ Returns:
+ True if the program exits with code 0, false otherwise.
+ """
+
+ exe_path = gtest_test_utils.GetTestExecutablePath(program_name)
+ args = [exe_path]
+ if flags is not None:
+ args.extend(flags)
+ process = gtest_test_utils.Subprocess(args, capture_stderr=False, env=env)
+ return process.exited and process.exit_code == 0
+
+ def testSucceedsWhenFlagIsNotSetAndOnlyDisabledTestsPresent(self):
+ """Tests that no test selected results in success without the flag set."""
+ self.assertTrue(
+ self.Run("googletest-fail-if-no-test-linked-test-with-disabled-test_"),
+ )
+
+ def testFailsWhenFlagIsSetAndOnlyDisabledTestsPresent(self):
+ """Tests that no test selected results in failure with the flag set."""
+ self.assertFalse(
+ self.Run(
+ "googletest-fail-if-no-test-linked-test-with-disabled-test_",
+ flags=[f"--{FAIL_IF_NO_TEST_SELECTED_FLAG}"],
+ ),
+ )
+
+ def testSucceedsWhenFlagIsSetAndEnabledTestsPresent(self):
+ """Tests that a test running still succeeds when the flag is set."""
+ self.assertTrue(
+ self.Run(
+ "googletest-fail-if-no-test-linked-test-with-enabled-test_",
+ flags=[f"--{FAIL_IF_NO_TEST_SELECTED_FLAG}"],
+ ),
+ )
+
+
+if __name__ == "__main__":
+ gtest_test_utils.Main()
diff --git a/googletest/test/googletest-filter-unittest.py b/googletest/test/googletest-filter-unittest.py
index f1f3c7a..a44882a 100755
--- a/googletest/test/googletest-filter-unittest.py
+++ b/googletest/test/googletest-filter-unittest.py
@@ -97,6 +97,9 @@ TOTAL_SHARDS_ENV_VAR = 'GTEST_TOTAL_SHARDS'
SHARD_INDEX_ENV_VAR = 'GTEST_SHARD_INDEX'
SHARD_STATUS_FILE_ENV_VAR = 'GTEST_SHARD_STATUS_FILE'
+# The environment variable for the test warnings output file.
+TEST_WARNINGS_OUTPUT_FILE = 'TEST_WARNINGS_OUTPUT_FILE'
+
# The command line flag for specifying the test filters.
FILTER_FLAG = 'gtest_filter'
@@ -419,6 +422,22 @@ class GTestFilterUnitTest(gtest_test_utils.TestCase):
self.RunAndVerify('BadFilter', [])
self.RunAndVerifyAllowingDisabled('BadFilter', [])
+ def testBadFilterWithWarningFile(self):
+ """Tests the warning file when a filter that matches nothing."""
+
+ warning_file = os.path.join(
+ gtest_test_utils.GetTempDir(), 'testBadFilterWithWarningFile'
+ )
+ extra_env = {TEST_WARNINGS_OUTPUT_FILE: warning_file}
+ args = ['--%s=%s' % (FILTER_FLAG, 'BadFilter')]
+ InvokeWithModifiedEnv(extra_env, RunAndReturnOutput, args)
+ with open(warning_file, 'r') as f:
+ warning_file_contents = f.read()
+ self.assertEqual(
+ warning_file_contents,
+ 'filter "BadFilter" did not match any test; no tests were run\n',
+ )
+
def testFullName(self):
"""Tests filtering by full name."""
diff --git a/googletest/test/googletest-json-output-unittest.py b/googletest/test/googletest-json-output-unittest.py
index 270de05..c75051c 100644
--- a/googletest/test/googletest-json-output-unittest.py
+++ b/googletest/test/googletest-json-output-unittest.py
@@ -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': '*',
@@ -431,7 +433,7 @@ EXPECTED_NON_EMPTY = {
{
'name': 'NoopPassingTest',
'file': 'gtest_xml_output_unittest_.cc',
- 'line': 168,
+ 'line': 172,
'status': 'RUN',
'result': 'SKIPPED',
'timestamp': '*',
@@ -471,7 +473,7 @@ EXPECTED_NON_EMPTY = {
{
'name': 'NoopPassingTest',
'file': 'gtest_xml_output_unittest_.cc',
- 'line': 175,
+ 'line': 179,
'status': 'RUN',
'result': 'COMPLETED',
'timestamp': '*',
@@ -508,7 +510,7 @@ EXPECTED_NON_EMPTY = {
'name': 'HasTypeParamAttribute',
'type_param': 'int',
'file': 'gtest_xml_output_unittest_.cc',
- 'line': 189,
+ 'line': 193,
'status': 'RUN',
'result': 'COMPLETED',
'time': '*',
@@ -528,7 +530,7 @@ EXPECTED_NON_EMPTY = {
'name': 'HasTypeParamAttribute',
'type_param': 'long',
'file': 'gtest_xml_output_unittest_.cc',
- 'line': 189,
+ 'line': 193,
'status': 'RUN',
'result': 'COMPLETED',
'time': '*',
@@ -548,7 +550,7 @@ EXPECTED_NON_EMPTY = {
'name': 'HasTypeParamAttribute',
'type_param': 'int',
'file': 'gtest_xml_output_unittest_.cc',
- 'line': 196,
+ 'line': 200,
'status': 'RUN',
'result': 'COMPLETED',
'time': '*',
@@ -568,7 +570,7 @@ EXPECTED_NON_EMPTY = {
'name': 'HasTypeParamAttribute',
'type_param': 'long',
'file': 'gtest_xml_output_unittest_.cc',
- 'line': 196,
+ 'line': 200,
'status': 'RUN',
'result': 'COMPLETED',
'time': '*',
@@ -589,7 +591,7 @@ EXPECTED_NON_EMPTY = {
'name': 'HasValueParamAttribute/0',
'value_param': '33',
'file': 'gtest_xml_output_unittest_.cc',
- 'line': 180,
+ 'line': 184,
'status': 'RUN',
'result': 'COMPLETED',
'time': '*',
@@ -600,7 +602,7 @@ EXPECTED_NON_EMPTY = {
'name': 'HasValueParamAttribute/1',
'value_param': '42',
'file': 'gtest_xml_output_unittest_.cc',
- 'line': 180,
+ 'line': 184,
'status': 'RUN',
'result': 'COMPLETED',
'time': '*',
@@ -611,7 +613,7 @@ EXPECTED_NON_EMPTY = {
'name': 'AnotherTestThatHasValueParamAttribute/0',
'value_param': '33',
'file': 'gtest_xml_output_unittest_.cc',
- 'line': 181,
+ 'line': 185,
'status': 'RUN',
'result': 'COMPLETED',
'time': '*',
@@ -622,7 +624,7 @@ EXPECTED_NON_EMPTY = {
'name': 'AnotherTestThatHasValueParamAttribute/1',
'value_param': '42',
'file': 'gtest_xml_output_unittest_.cc',
- 'line': 181,
+ 'line': 185,
'status': 'RUN',
'result': 'COMPLETED',
'time': '*',
diff --git a/googletest/test/googletest-output-test-golden-lin.txt b/googletest/test/googletest-output-test-golden-lin.txt
index 533eb8c..57f7d1a 100644
--- a/googletest/test/googletest-output-test-golden-lin.txt
+++ b/googletest/test/googletest-output-test-golden-lin.txt
@@ -62,7 +62,7 @@ Expected equality of these values:
Which is: "\"Line\0 1\"\nLine 2"
"Line 2"
With diff:
-@@ -1,2 @@
+@@ -1,2 +1 @@
-\"Line\0 1\"
Line 2
diff --git a/googletest/test/googletest-param-test-test.cc b/googletest/test/googletest-param-test-test.cc
index c9c5e78..fab977e 100644
--- a/googletest/test/googletest-param-test-test.cc
+++ b/googletest/test/googletest-param-test-test.cc
@@ -35,12 +35,17 @@
#include "test/googletest-param-test-test.h"
#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <functional>
#include <iostream>
#include <list>
#include <set>
#include <sstream>
#include <string>
+#include <string_view>
#include <tuple>
+#include <type_traits>
#include <vector>
#include "gtest/gtest.h"
@@ -583,6 +588,71 @@ TEST(ConvertTest, NonDefaultConstructAssign) {
EXPECT_TRUE(it == gen.end());
}
+TEST(ConvertTest, WithConverterLambdaAndDeducedType) {
+ const ParamGenerator<ConstructFromT<int8_t>> gen =
+ ConvertGenerator(Values("0", std::string("1")), [](const std::string& s) {
+ size_t pos;
+ int64_t value = std::stoll(s, &pos);
+ EXPECT_EQ(pos, s.size());
+ return value;
+ });
+
+ ConstructFromT<int8_t> expected_values[] = {ConstructFromT<int8_t>(0),
+ ConstructFromT<int8_t>(1)};
+ VerifyGenerator(gen, expected_values);
+}
+
+TEST(ConvertTest, WithConverterLambdaAndExplicitType) {
+ auto convert_generator = ConvertGenerator<std::string>(
+ Values("0", std::string("1")), [](std::string_view s) {
+ size_t pos;
+ int64_t value = std::stoll(std::string(s), &pos);
+ EXPECT_EQ(pos, s.size());
+ return value;
+ });
+ constexpr bool is_correct_type = std::is_same_v<
+ decltype(convert_generator),
+ testing::internal::ParamConverterGenerator<
+ std::string, std::function<int64_t(std::string_view)>>>;
+ EXPECT_TRUE(is_correct_type);
+ const ParamGenerator<ConstructFromT<int8_t>> gen = convert_generator;
+
+ ConstructFromT<int8_t> expected_values[] = {ConstructFromT<int8_t>(0),
+ ConstructFromT<int8_t>(1)};
+ VerifyGenerator(gen, expected_values);
+}
+
+TEST(ConvertTest, WithConverterFunctionPointer) {
+ int64_t (*func_ptr)(const std::string&) = [](const std::string& s) {
+ size_t pos;
+ int64_t value = std::stoll(s, &pos);
+ EXPECT_EQ(pos, s.size());
+ return value;
+ };
+ const ParamGenerator<ConstructFromT<int8_t>> gen =
+ ConvertGenerator(Values("0", std::string("1")), func_ptr);
+
+ ConstructFromT<int8_t> expected_values[] = {ConstructFromT<int8_t>(0),
+ ConstructFromT<int8_t>(1)};
+ VerifyGenerator(gen, expected_values);
+}
+
+TEST(ConvertTest, WithConverterFunctionReference) {
+ int64_t (*func_ptr)(const std::string&) = [](const std::string& s) {
+ size_t pos;
+ int64_t value = std::stoll(s, &pos);
+ EXPECT_EQ(pos, s.size());
+ return value;
+ };
+ int64_t (&func_ref)(const std::string&) = *func_ptr;
+ const ParamGenerator<ConstructFromT<int8_t>> gen =
+ ConvertGenerator(Values("0", std::string("1")), func_ref);
+
+ ConstructFromT<int8_t> expected_values[] = {ConstructFromT<int8_t>(0),
+ ConstructFromT<int8_t>(1)};
+ VerifyGenerator(gen, expected_values);
+}
+
// Tests that an generator produces correct sequence after being
// assigned from another generator.
TEST(ParamGeneratorTest, AssignmentWorks) {
@@ -1104,7 +1174,7 @@ TEST_P(ParameterizedDerivedTest, SeesSequence) {
class ParameterizedDeathTest : public ::testing::TestWithParam<int> {};
TEST_F(ParameterizedDeathTest, GetParamDiesFromTestF) {
- EXPECT_DEATH_IF_SUPPORTED(GetParam(), ".* value-parameterized test .*");
+ EXPECT_DEATH_IF_SUPPORTED((void)GetParam(), ".* value-parameterized test .*");
}
INSTANTIATE_TEST_SUITE_P(RangeZeroToFive, ParameterizedDerivedTest,
diff --git a/googletest/test/googletest-port-test.cc b/googletest/test/googletest-port-test.cc
index 9f05a01..975b2fc 100644
--- a/googletest/test/googletest-port-test.cc
+++ b/googletest/test/googletest-port-test.cc
@@ -288,8 +288,8 @@ TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownFileAndLine) {
defined(GTEST_OS_OPENBSD) || defined(GTEST_OS_GNU_HURD)
void* ThreadFunc(void* data) {
internal::Mutex* mutex = static_cast<internal::Mutex*>(data);
- mutex->Lock();
- mutex->Unlock();
+ mutex->lock();
+ mutex->unlock();
return nullptr;
}
diff --git a/googletest/test/googletest-printers-test.cc b/googletest/test/googletest-printers-test.cc
index cf49af0..c5d9756 100644
--- a/googletest/test/googletest-printers-test.cc
+++ b/googletest/test/googletest-printers-test.cc
@@ -32,6 +32,7 @@
// This file tests the universal value printer.
#include <algorithm>
+#include <any>
#include <cctype>
#include <cstdint>
#include <cstring>
@@ -42,14 +43,17 @@
#include <list>
#include <map>
#include <memory>
+#include <optional>
#include <ostream>
#include <set>
#include <sstream>
#include <string>
+#include <string_view>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <utility>
+#include <variant>
#include <vector>
#include "gtest/gtest-printers.h"
@@ -62,7 +66,7 @@
#if GTEST_INTERNAL_HAS_STD_SPAN
#include <span> // NOLINT
-#endif // GTEST_INTERNAL_HAS_STD_SPAN
+#endif // GTEST_INTERNAL_HAS_STD_SPAN
#if GTEST_INTERNAL_HAS_COMPARE_LIB
#include <compare> // NOLINT
@@ -121,6 +125,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;
};
@@ -572,6 +579,8 @@ TEST(PrintU8StringTest, Null) {
}
// Tests that u8 strings are escaped properly.
+// TODO(b/396121064) - Fix this test under MSVC
+#ifndef _MSC_VER
TEST(PrintU8StringTest, EscapesProperly) {
const char8_t* p = u8"'\"?\\\a\b\f\n\r\t\v\x7F\xFF hello 世界";
EXPECT_EQ(PrintPointer(p) +
@@ -579,7 +588,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) {
@@ -790,7 +800,7 @@ struct Foo {
TEST(PrintPointerTest, MemberVariablePointer) {
EXPECT_TRUE(HasPrefix(Print(&Foo::value),
Print(sizeof(&Foo::value)) + "-byte object "));
- int Foo::*p = NULL; // NOLINT
+ int Foo::* p = NULL; // NOLINT
EXPECT_TRUE(HasPrefix(Print(p), Print(sizeof(p)) + "-byte object "));
}
@@ -917,7 +927,7 @@ TEST(PrintArrayTest, BigArray) {
PrintArrayHelper(a));
}
-// Tests printing ::string and ::std::string.
+// Tests printing ::std::string and ::string_view.
// ::std::string.
TEST(PrintStringTest, StringInStdNamespace) {
@@ -927,6 +937,13 @@ TEST(PrintStringTest, StringInStdNamespace) {
Print(str));
}
+TEST(PrintStringTest, StringViewInStdNamespace) {
+ const char s[] = "'\"?\\\a\b\f\n\0\r\t\v\x7F\xFF a";
+ const ::std::string_view str(s, sizeof(s));
+ EXPECT_EQ("\"'\\\"?\\\\\\a\\b\\f\\n\\0\\r\\t\\v\\x7F\\xFF a\\0\"",
+ Print(str));
+}
+
TEST(PrintStringTest, StringAmbiguousHex) {
// "\x6BANANA" is ambiguous, it can be interpreted as starting with either of:
// '\x6', '\x6B', or '\x6BA'.
@@ -944,7 +961,7 @@ TEST(PrintStringTest, StringAmbiguousHex) {
EXPECT_EQ("\"!\\x5-!\"", Print(::std::string("!\x5-!")));
}
-// Tests printing ::std::wstring.
+// Tests printing ::std::wstring and ::std::wstring_view.
#if GTEST_HAS_STD_WSTRING
// ::std::wstring.
TEST(PrintWideStringTest, StringInStdNamespace) {
@@ -956,6 +973,15 @@ TEST(PrintWideStringTest, StringInStdNamespace) {
Print(str));
}
+TEST(PrintWideStringTest, StringViewInStdNamespace) {
+ const wchar_t s[] = L"'\"?\\\a\b\f\n\0\r\t\v\xD3\x576\x8D3\xC74D a";
+ const ::std::wstring_view str(s, sizeof(s) / sizeof(wchar_t));
+ EXPECT_EQ(
+ "L\"'\\\"?\\\\\\a\\b\\f\\n\\0\\r\\t\\v"
+ "\\xD3\\x576\\x8D3\\xC74D a\\0\"",
+ Print(str));
+}
+
TEST(PrintWideStringTest, StringAmbiguousHex) {
// same for wide strings.
EXPECT_EQ("L\"0\\x12\" L\"3\"", Print(::std::wstring(L"0\x12"
@@ -974,6 +1000,12 @@ TEST(PrintStringTest, U8String) {
EXPECT_EQ(str, str); // Verify EXPECT_EQ compiles with this type.
EXPECT_EQ("u8\"Hello, \\xE4\\xB8\\x96\\xE7\\x95\\x8C\"", Print(str));
}
+
+TEST(PrintStringTest, U8StringView) {
+ std::u8string_view str = u8"Hello, 世界";
+ EXPECT_EQ(str, str); // Verify EXPECT_EQ compiles with this type.
+ EXPECT_EQ("u8\"Hello, \\xE4\\xB8\\x96\\xE7\\x95\\x8C\"", Print(str));
+}
#endif
TEST(PrintStringTest, U16String) {
@@ -982,12 +1014,24 @@ TEST(PrintStringTest, U16String) {
EXPECT_EQ("u\"Hello, \\x4E16\\x754C\"", Print(str));
}
+TEST(PrintStringTest, U16StringView) {
+ std::u16string_view str = u"Hello, 世界";
+ EXPECT_EQ(str, str); // Verify EXPECT_EQ compiles with this type.
+ EXPECT_EQ("u\"Hello, \\x4E16\\x754C\"", Print(str));
+}
+
TEST(PrintStringTest, U32String) {
std::u32string str = U"Hello, 🗺️";
EXPECT_EQ(str, str); // Verify EXPECT_EQ compiles with this type
EXPECT_EQ("U\"Hello, \\x1F5FA\\xFE0F\"", Print(str));
}
+TEST(PrintStringTest, U32StringView) {
+ std::u32string_view str = U"Hello, 🗺️";
+ EXPECT_EQ(str, str); // Verify EXPECT_EQ compiles with this type
+ EXPECT_EQ("U\"Hello, \\x1F5FA\\xFE0F\"", Print(str));
+}
+
// Tests printing types that support generic streaming (i.e. streaming
// to std::basic_ostream<Char, CharTraits> for any valid Char and
// CharTraits types).
@@ -1447,7 +1491,7 @@ TEST(PrintReferenceTest, HandlesMemberFunctionPointer) {
// Tests that the universal printer prints a member variable pointer
// passed by reference.
TEST(PrintReferenceTest, HandlesMemberVariablePointer) {
- int Foo::*p = &Foo::value; // NOLINT
+ int Foo::* p = &Foo::value; // NOLINT
EXPECT_TRUE(HasPrefix(PrintByRef(p), "@" + PrintPointer(&p) + " " +
Print(sizeof(p)) + "-byte object "));
}
@@ -1885,6 +1929,22 @@ TEST(UniversalPrintTest, SmartPointers) {
PrintToString(std::shared_ptr<void>(p.get(), [](void*) {})));
}
+TEST(UniversalPrintTest, StringViewNonZeroTerminated) {
+ // Craft a non-ASCII UTF-8 input (to trigger a special path in
+ // `ConditionalPrintAsText`). Use array notation instead of the string
+ // literal syntax, to avoid placing a terminating 0 at the end of the input.
+ const char s[] = {'\357', '\243', '\242', 'X'};
+ // Only include the first 3 bytes in the `string_view` and leave the last one
+ // ('X') outside. This way, if the code tries to use `str.data()` with
+ // `strlen` instead of `str.size()`, it will include 'X' and cause a visible
+ // difference (in addition to ASAN tests detecting a buffer overflow due to
+ // the missing 0 at the end).
+ const ::std::string_view str(s, 3);
+ ::std::stringstream ss;
+ UniversalPrint(str, &ss);
+ EXPECT_EQ("\"\\xEF\\xA3\\xA2\"\n As Text: \"\xEF\xA3\xA2\"", ss.str());
+}
+
TEST(UniversalTersePrintTupleFieldsToStringsTestWithStd, PrintsEmptyTuple) {
Strings result = UniversalTersePrintTupleFieldsToStrings(::std::make_tuple());
EXPECT_EQ(0u, result.size());
@@ -1914,7 +1974,6 @@ TEST(UniversalTersePrintTupleFieldsToStringsTestWithStd, PrintsTersely) {
EXPECT_EQ("\"a\"", result[1]);
}
-#if GTEST_INTERNAL_HAS_ANY
class PrintAnyTest : public ::testing::Test {
protected:
template <typename T>
@@ -1928,12 +1987,12 @@ class PrintAnyTest : public ::testing::Test {
};
TEST_F(PrintAnyTest, Empty) {
- internal::Any any;
+ std::any any;
EXPECT_EQ("no value", PrintToString(any));
}
TEST_F(PrintAnyTest, NonEmpty) {
- internal::Any any;
+ std::any any;
constexpr int val1 = 10;
const std::string val2 = "content";
@@ -1944,27 +2003,23 @@ TEST_F(PrintAnyTest, NonEmpty) {
EXPECT_EQ("value of type " + ExpectedTypeName<std::string>(),
PrintToString(any));
}
-#endif // GTEST_INTERNAL_HAS_ANY
-#if GTEST_INTERNAL_HAS_OPTIONAL
TEST(PrintOptionalTest, Basic) {
- EXPECT_EQ("(nullopt)", PrintToString(internal::Nullopt()));
- internal::Optional<int> value;
+ EXPECT_EQ("(nullopt)", PrintToString(std::nullopt));
+ std::optional<int> value;
EXPECT_EQ("(nullopt)", PrintToString(value));
value = {7};
EXPECT_EQ("(7)", PrintToString(value));
- EXPECT_EQ("(1.1)", PrintToString(internal::Optional<double>{1.1}));
- EXPECT_EQ("(\"A\")", PrintToString(internal::Optional<std::string>{"A"}));
+ EXPECT_EQ("(1.1)", PrintToString(std::optional<double>{1.1}));
+ EXPECT_EQ("(\"A\")", PrintToString(std::optional<std::string>{"A"}));
}
-#endif // GTEST_INTERNAL_HAS_OPTIONAL
-#if GTEST_INTERNAL_HAS_VARIANT
struct NonPrintable {
unsigned char contents = 17;
};
TEST(PrintOneofTest, Basic) {
- using Type = internal::Variant<int, StreamableInGlobal, NonPrintable>;
+ using Type = std::variant<int, StreamableInGlobal, NonPrintable>;
EXPECT_EQ("('int(index = 0)' with value 7)", PrintToString(Type(7)));
EXPECT_EQ("('StreamableInGlobal(index = 1)' with value StreamableInGlobal)",
PrintToString(Type(StreamableInGlobal{})));
@@ -1973,7 +2028,6 @@ TEST(PrintOneofTest, Basic) {
"1-byte object <11>)",
PrintToString(Type(NonPrintable{})));
}
-#endif // GTEST_INTERNAL_HAS_VARIANT
#if GTEST_INTERNAL_HAS_COMPARE_LIB
TEST(PrintOrderingTest, Basic) {
diff --git a/googletest/test/googletest-setuptestsuite-test_.cc b/googletest/test/googletest-setuptestsuite-test_.cc
index d20899f..f4c43cc 100644
--- a/googletest/test/googletest-setuptestsuite-test_.cc
+++ b/googletest/test/googletest-setuptestsuite-test_.cc
@@ -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) {}
diff --git a/googletest/test/gtest_unittest.cc b/googletest/test/gtest_unittest.cc
index 2d48dee..a31b7ba 100644
--- a/googletest/test/gtest_unittest.cc
+++ b/googletest/test/gtest_unittest.cc
@@ -2163,7 +2163,7 @@ class UnitTestRecordPropertyTestEnvironment : public Environment {
};
// This will test property recording outside of any test or test case.
-GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static Environment* record_property_env =
+[[maybe_unused]] static Environment* record_property_env =
AddGlobalTestEnvironment(new UnitTestRecordPropertyTestEnvironment);
// This group of tests is for predicate assertions (ASSERT_PRED*, etc)
@@ -3579,13 +3579,13 @@ TEST(EditDistance, TestSuites) {
{__LINE__, "A", "A", " ", ""},
{__LINE__, "ABCDE", "ABCDE", " ", ""},
// Simple adds.
- {__LINE__, "X", "XA", " +", "@@ +1,2 @@\n X\n+A\n"},
- {__LINE__, "X", "XABCD", " ++++", "@@ +1,5 @@\n X\n+A\n+B\n+C\n+D\n"},
+ {__LINE__, "X", "XA", " +", "@@ -1 +1,2 @@\n X\n+A\n"},
+ {__LINE__, "X", "XABCD", " ++++", "@@ -1 +1,5 @@\n X\n+A\n+B\n+C\n+D\n"},
// Simple removes.
- {__LINE__, "XA", "X", " -", "@@ -1,2 @@\n X\n-A\n"},
- {__LINE__, "XABCD", "X", " ----", "@@ -1,5 @@\n X\n-A\n-B\n-C\n-D\n"},
+ {__LINE__, "XA", "X", " -", "@@ -1,2 +1 @@\n X\n-A\n"},
+ {__LINE__, "XABCD", "X", " ----", "@@ -1,5 +1 @@\n X\n-A\n-B\n-C\n-D\n"},
// Simple replaces.
- {__LINE__, "A", "a", "/", "@@ -1,1 +1,1 @@\n-A\n+a\n"},
+ {__LINE__, "A", "a", "/", "@@ -1 +1 @@\n-A\n+a\n"},
{__LINE__, "ABCD", "abcd", "////",
"@@ -1,4 +1,4 @@\n-A\n-B\n-C\n-D\n+a\n+b\n+c\n+d\n"},
// Path finding.
@@ -6717,6 +6717,9 @@ TEST(ColoredOutputTest, UsesColorsWhenTermSupportsColors) {
SetEnv("TERM", "xterm-color"); // TERM supports colors.
EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
+ SetEnv("TERM", "xterm-ghostty"); // TERM supports colors.
+ EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
+
SetEnv("TERM", "xterm-kitty"); // TERM supports colors.
EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
@@ -6754,9 +6757,8 @@ TEST(ColoredOutputTest, UsesColorsWhenTermSupportsColors) {
// Verifies that StaticAssertTypeEq works in a namespace scope.
-GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool dummy1 =
- StaticAssertTypeEq<bool, bool>();
-GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool dummy2 =
+[[maybe_unused]] static bool dummy1 = StaticAssertTypeEq<bool, bool>();
+[[maybe_unused]] static bool dummy2 =
StaticAssertTypeEq<const int, const int>();
// Verifies that StaticAssertTypeEq works in a class.
diff --git a/googletest/test/gtest_xml_output_unittest.py b/googletest/test/gtest_xml_output_unittest.py
index f2fc9b9..87a7683 100755
--- a/googletest/test/gtest_xml_output_unittest.py
+++ b/googletest/test/gtest_xml_output_unittest.py
@@ -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="28" 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,49 +135,55 @@ 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="168" status="run" result="skipped" time="*" timestamp="*" classname="SetupFailTest">
+ <testcase name="NoopPassingTest" file="gtest_xml_output_unittest_.cc" line="172" status="run" result="skipped" time="*" timestamp="*" classname="SetupFailTest">
<skipped message="gtest_xml_output_unittest_.cc:*&#x0A;"><![CDATA[gtest_xml_output_unittest_.cc:*
]]></skipped>
</testcase>
@@ -186,7 +195,7 @@ Expected equality of these values:
</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="175" status="run" result="completed" time="*" timestamp="*" classname="TearDownFailTest"/>
+ <testcase name="NoopPassingTest" file="gtest_xml_output_unittest_.cc" line="179" status="run" result="completed" time="*" timestamp="*" classname="TearDownFailTest"/>
<testcase name="" status="run" result="completed" classname="" time="*" timestamp="*">
<failure message="gtest_xml_output_unittest_.cc:*&#x0A;Expected equality of these values:&#x0A; 1&#x0A; 2%(stack_entity)s" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
Expected equality of these values:
@@ -195,22 +204,22 @@ Expected equality of these values:
</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="180" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
- <testcase name="HasValueParamAttribute/1" file="gtest_xml_output_unittest_.cc" line="180" value_param="42" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
- <testcase name="AnotherTestThatHasValueParamAttribute/0" file="gtest_xml_output_unittest_.cc" line="181" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
- <testcase name="AnotherTestThatHasValueParamAttribute/1" file="gtest_xml_output_unittest_.cc" line="181" 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="189" 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="189" 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="196" 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="196" 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,
@@ -218,46 +227,39 @@ Expected equality of these values:
}
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"/>
</testsuite>
</testsuites>"""
-ACTUAL_OUTPUT = """<?xml version="1.0" encoding="UTF-8"?>
-<testsuites tests="3" failures="0" disabled="0" errors="0" time="*" timestamp="*" ad_hoc_property="42" name="AllTests">
- <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">
- <properties>
- <property name="key_int" value="1"/>
- </properties>
- </testcase>
- </testsuite>
- <testsuite name="Single/TypeParameterizedTestSuite/0" tests="1" failures="0" disabled="0" skipped="0" errors="0" time="*" timestamp="*">
- <testcase name="HasTypeParamAttribute" type_param="int" file="gtest_xml_output_unittest_.cc" line="196" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/0"/>
- </testsuite>
-</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/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="196" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/0" />
+ <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>"""
diff --git a/googletest/test/gtest_xml_output_unittest_.cc b/googletest/test/gtest_xml_output_unittest_.cc
index 4a39157..fe196b6 100644
--- a/googletest/test/gtest_xml_output_unittest_.cc
+++ b/googletest/test/gtest_xml_output_unittest_.cc
@@ -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");
}
};
diff --git a/googletest_deps.bzl b/googletest_deps.bzl
index 281af5c..e5fc4be 100644
--- a/googletest_deps.bzl
+++ b/googletest_deps.bzl
@@ -17,9 +17,9 @@ def googletest_deps():
if not native.existing_rule("abseil-cpp"):
http_archive(
name = "abseil-cpp",
- 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"],
+ sha256 = "9b2b72d4e8367c0b843fa2bcfa2b08debbe3cee34f7aaa27de55a6cbb3e843db",
+ strip_prefix = "abseil-cpp-20250814.0",
+ urls = ["https://github.com/abseil/abseil-cpp/releases/download/20250814.0/abseil-cpp-20250814.0.tar.gz"],
)
if not native.existing_rule("fuchsia_sdk"):