diff options
43 files changed, 736 insertions, 443 deletions
diff --git a/BUILD.bazel b/BUILD.bazel index 5350145..3ca5735 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -151,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({ @@ -164,7 +161,6 @@ 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": [], @@ -174,8 +170,8 @@ cc_library( # `gtest`, but testonly. See guidance on `gtest` for when to use this. alias( name = "gtest_for_library", - actual = ":gtest", testonly = True, + actual = ":gtest", ) # Implements main() for tests using gtest. Prefer to depend on `gtest` as well diff --git a/MODULE.bazel b/MODULE.bazel index 66eee54..c2fb850 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -41,20 +41,20 @@ module( bazel_dep( name = "abseil-cpp", - version = "20250127.0", + version = "20250512.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 = "1.1.0", + version = "1.3.0", dev_dependency = True, ) @@ -2,30 +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.16.0`). - #### 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.16.0 +#### Release 1.17.0 -[Release 1.16.0](https://github.com/google/googletest/releases/tag/v1.16.0) is +[Release 1.17.0](https://github.com/google/googletest/releases/tag/v1.17.0) is now available. -The 1.16.x branch requires at least C++14. - -The 1.16.x branch will be the last to support C++14. Future development will -[require at least C++17](https://opensource.google/documentation/policies/cplusplus-support#c_language_standard). +The 1.17.x branch +[requires at least C++17](https://opensource.google/documentation/policies/cplusplus-support#c_language_standard). #### Continuous Integration @@ -37,9 +37,9 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( name = "rules_python", - sha256 = "9c6e26911a79fbf510a8f06d8eedb40f412023cf7fa6d1461def27116bff022c", - strip_prefix = "rules_python-1.1.0", - url = "https://github.com/bazelbuild/rules_python/releases/download/1.1.0/rules_python-1.1.0.tar.gz", + sha256 = "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/1.1.0 load("@rules_python//python:repositories.bzl", "py_repositories") @@ -54,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 6491e79..c4ad579 100644 --- a/ci/linux-presubmit.sh +++ b/ci/linux-presubmit.sh @@ -31,15 +31,23 @@ set -euox pipefail -readonly LINUX_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20241218" -readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20250205" +readonly LINUX_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest: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++17 c++20" + STD="c++17 c++20 c++23" fi # Test CMake + GCC @@ -93,18 +101,21 @@ time docker run \ --rm \ --env="CC=/usr/local/bin/gcc" \ --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 @@ -115,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 @@ -139,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 5370ed6..63cf814 100644 --- a/ci/macos-presubmit.sh +++ b/ci/macos-presubmit.sh @@ -56,7 +56,7 @@ done # Test the Bazel build # If we are running on Kokoro, check for a versioned Bazel binary. -KOKORO_GFILE_BAZEL_BIN="bazel-8.0.0-darwin-x86_64" +KOKORO_GFILE_BAZEL_BIN="bazel-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} @@ -64,6 +64,12 @@ 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 ... \ @@ -76,5 +82,6 @@ for absl in 0 1; do --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 e2664c5..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-8.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 @@ -48,6 +48,14 @@ RMDIR /S /Q %CMAKE_BUILD_PATH% :: --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 ^ @@ -58,7 +66,8 @@ SET BAZEL_VS=C:\Program Files\Microsoft Visual Studio\2022\Community --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 :: C++20 @@ -71,5 +80,6 @@ IF %errorlevel% neq 0 EXIT /B 1 --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 9b1220a..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,8 @@ EXPECT_TRUE(IsCorrectPointIntVector(point_ints)) ``` For more details regarding `AbslStringify()` and its integration with other -libraries, see go/abslstringify. +libraries, see +[the documentation](https://abseil.io/docs/cpp/guides/abslstringify). ## Regular Expression Syntax @@ -1448,17 +1450,19 @@ are two cases to consider: To test them, we use the following special techniques: * Both static functions and definitions/declarations in an unnamed namespace - are only visible within the same translation unit. To test them, you can - `#include` the entire `.cc` file being tested in your `*_test.cc` file. - (#including `.cc` files is not a good way to reuse code - you should not do - this in production code!) - - 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 @@ -1471,10 +1475,7 @@ To test them, we use the following special techniques: Another way to test private members is to refactor them into an implementation class, which is then declared in a `*-internal.h` file. Your - clients aren't allowed to include this header but your tests can. Such is - called the - [Pimpl](https://www.gamedev.net/articles/programming/general-and-gameplay-programming/the-c-pimpl-r1794/) - (Private Implementation) idiom. + clients aren't allowed to include this header but your tests can. Or, you can declare an individual test as a friend of your class by adding this line in the class body: @@ -1943,6 +1944,21 @@ 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 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 0ebdc1e..2ca3a9f 100644 --- a/docs/reference/actions.md +++ b/docs/reference/actions.md @@ -48,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 8ff9e0b..8b3d140 100644 --- a/docs/reference/matchers.md +++ b/docs/reference/matchers.md @@ -111,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)` diff --git a/docs/reference/testing.md b/docs/reference/testing.md index d7dc5cf..ea43721 100644 --- a/docs/reference/testing.md +++ b/docs/reference/testing.md @@ -203,7 +203,7 @@ class MyParam { INSTANTIATE_TEST_SUITE_P(MyInstantiation, MyTestSuite, ConvertGenerator(Combine(Values(1, 1.2), Bool()), - [](const std::tuple<int i, bool>& t){ + [](const std::tuple<int, bool>& t){ const auto [i, b] = t; return MyParam(i, b); })); diff --git a/googlemock/include/gmock/gmock-actions.h b/googlemock/include/gmock/gmock-actions.h index 5fe50e3..2746edd 100644 --- a/googlemock/include/gmock/gmock-actions.h +++ b/googlemock/include/gmock/gmock-actions.h @@ -1866,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. @@ -2035,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); } diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h index 402dd69..236d3e5 100644 --- a/googlemock/include/gmock/gmock-matchers.h +++ b/googlemock/include/gmock/gmock-matchers.h @@ -258,7 +258,6 @@ #include <algorithm> #include <cmath> #include <cstddef> -#include <exception> #include <functional> #include <initializer_list> #include <ios> @@ -268,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" @@ -376,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 @@ -391,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 @@ -1312,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. @@ -1431,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. @@ -3415,6 +3437,35 @@ auto UnpackStructImpl(const T& in, std::make_index_sequence<22>, char) { 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> @@ -4118,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) @@ -4453,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()); 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..b681fee 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/" diff --git a/googlemock/test/gmock-actions_test.cc b/googlemock/test/gmock-actions_test.cc index 46b0e91..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. @@ -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); @@ -1872,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(); @@ -1896,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-comparisons_test.cc b/googlemock/test/gmock-matchers-comparisons_test.cc index a331aec..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> @@ -621,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 { @@ -2396,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-more-actions_test.cc b/googlemock/test/gmock-more-actions_test.cc index 5b8b566..7c44eb0 100644 --- a/googlemock/test/gmock-more-actions_test.cc +++ b/googlemock/test/gmock-more-actions_test.cc @@ -202,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))); } @@ -253,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"), @@ -264,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"), @@ -276,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"), @@ -288,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"), @@ -298,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)))); } @@ -320,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))); } @@ -447,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))); } diff --git a/googlemock/test/gmock-spec-builders_test.cc b/googlemock/test/gmock-spec-builders_test.cc index 9e68aa0..90f00c2 100644 --- a/googlemock/test/gmock-spec-builders_test.cc +++ b/googlemock/test/gmock-spec-builders_test.cc @@ -2045,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 5de23c5..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.16.0 +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/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-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 442e00b..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 diff --git a/googletest/include/gtest/gtest.h b/googletest/include/gtest/gtest.h index 7be0caa..69994ee 100644 --- a/googletest/include/gtest/gtest.h +++ b/googletest/include/gtest/gtest.h @@ -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?"; diff --git a/googletest/include/gtest/internal/gtest-internal.h b/googletest/include/gtest/internal/gtest-internal.h index 9ee0eca..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 { @@ -338,17 +338,10 @@ class FloatingPoint { // 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 diff --git a/googletest/include/gtest/internal/gtest-port.h b/googletest/include/gtest/internal/gtest-port.h index 4cfc16c..06a5a8e 100644 --- a/googletest/include/gtest/internal/gtest-port.h +++ b/googletest/include/gtest/internal/gtest-port.h @@ -198,21 +198,8 @@ // 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. @@ -282,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 @@ -2331,73 +2322,6 @@ const char* StringFromGTestEnv(const char* flag, const char* default_val); } // namespace internal } // namespace testing -#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 @@ -2439,38 +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_lib_three_way_comparison) || \ (GTEST_INTERNAL_HAS_INCLUDE(<compare>) && \ GTEST_INTERNAL_CPLUSPLUS_LANG >= 201907L)) 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 09af151..cd218c9 100644 --- a/googletest/src/gtest.cc +++ b/googletest/src/gtest.cc @@ -270,6 +270,13 @@ GTEST_DEFINE_bool_( "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."); @@ -706,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) @@ -1488,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_); + size_t left_length = removes_ + common_; + size_t right_length = adds_ + common_; + *ss << "@@ " << "-" << left_start_; + if (left_length != 1) { + *ss << "," << left_length; } - if (removes_ && adds_) { - *ss << " "; - } - if (adds_) { - *ss << "+" << right_start_ << "," << (adds_ + common_); + *ss << " " << "+" << right_start_; + if (right_length != 1) { + *ss << "," << right_length; } *ss << " @@\n"; } @@ -3298,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") || @@ -4347,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"; @@ -6079,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(); @@ -6763,6 +6783,7 @@ static bool ParseGoogleTestFlag(const char* const arg) { 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/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.py b/googletest/test/googletest-fail-if-no-test-linked-test.py index f5854ba..e62bfb2 100755 --- a/googletest/test/googletest-fail-if-no-test-linked-test.py +++ b/googletest/test/googletest-fail-if-no-test-linked-test.py @@ -80,11 +80,7 @@ class GTestFailIfNoTestLinkedTest(gtest_test_utils.TestCase): ) ) warning_file_contents = open(warning_file, "r").read() - self.assertEqual( - warning_file_contents, - "This test program does NOT link in any test case. Please make sure" - " this is intended.\n", - ) + self.assertIn("does NOT link", warning_file_contents) def testFailsIfNoTestLinkedAndFlagSpecified(self): """Tests the behavior of no test linked and flag specified.""" 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-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 bc13060..fab977e 100644 --- a/googletest/test/googletest-param-test-test.cc +++ b/googletest/test/googletest-param-test-test.cc @@ -1174,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-printers-test.cc b/googletest/test/googletest-printers-test.cc index 52b2c49..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 @@ -796,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 ")); } @@ -923,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) { @@ -933,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'. @@ -950,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) { @@ -962,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" @@ -980,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) { @@ -988,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). @@ -1453,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 ")); } @@ -1891,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()); @@ -1920,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> @@ -1934,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"; @@ -1950,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{}))); @@ -1979,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/gtest_unittest.cc b/googletest/test/gtest_unittest.cc index 559d34c..a31b7ba 100644 --- a/googletest/test/gtest_unittest.cc +++ b/googletest/test/gtest_unittest.cc @@ -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. diff --git a/googletest_deps.bzl b/googletest_deps.bzl index d3dd03e..9eb7270 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 = "16242f394245627e508ec6bb296b433c90f8d914f73b9c026fddb905e27276e8", - strip_prefix = "abseil-cpp-20250127.0", - urls = ["https://github.com/abseil/abseil-cpp/releases/download/20250127.0/abseil-cpp-20250127.0.tar.gz"], + sha256 = "7262daa7c1711406248c10f41026d685e88223bc92817d16fb93c19adb57f669", + strip_prefix = "abseil-cpp-20250512.0", + urls = ["https://github.com/abseil/abseil-cpp/releases/download/20250512.0/abseil-cpp-20250512.0.tar.gz"], ) if not native.existing_rule("fuchsia_sdk"): |