Compare commits

...

4 Commits

Author SHA1 Message Date
Charles Giessen
a02d683d41
Merge 0b656495436f57212be8700794a3d5fb14000c5f into 7140cd416cecd7462a8aae488024abeee55598e4 2026-06-11 19:28:11 +02:00
Mike Kruskal
7140cd416c Flip the recommendation about using EXPECT statements inside custom matchers.
PiperOrigin-RevId: 925686474
Change-Id: I7b5d7e82dc8618d6914844446fa260468b947ece
2026-06-02 18:03:04 -07:00
Abseil Team
a721f1b20c Automated Code Change
PiperOrigin-RevId: 924116072
Change-Id: I3e04ebbff65c897e50c37e1a47a2018f31382104
2026-05-30 20:49:30 -07:00
Charles Giessen
0b65649543 Fix gtest_force_shared_crt in CMake 3.15+
With CMake 3.15, a new mechanism was added to control which CRT
libraries link to. Because the minimum CMake version is above 3.15,
googletest can leverage it in the implementation of
gtest_force_shared_crt.

If CMAKE_MSVC_RUNTIME_LIBRARY is already defined, googletest will
respect its value rather than replace it, allowing for users to
customize the exact CRT used by googletest.
2025-12-03 15:52:55 -06:00
3 changed files with 74 additions and 35 deletions

View File

@ -3386,30 +3386,6 @@ With this definition, the above assertion will give a better message:
Actual: 27 (the remainder is 6)
```
#### Using EXPECT_ Statements in Matchers
You can also use `EXPECT_...` statements inside custom matcher definitions. In
many cases, this allows you to write your matcher more concisely while still
providing an informative error message. For example:
```cpp
MATCHER(IsDivisibleBy7, "") {
const auto remainder = arg % 7;
EXPECT_EQ(remainder, 0);
return true;
}
```
If you write a test that includes the line `EXPECT_THAT(27, IsDivisibleBy7());`,
you will get an error something like the following:
```shell
Expected equality of these values:
remainder
Which is: 6
0
```
#### `MatchAndExplain`
You should let `MatchAndExplain()` print *any additional information* that can
@ -3429,6 +3405,66 @@ the value of `(arg % 7) == 0` can be implicitly converted to a `bool`. In the
`arg_type` will be `int`; if it takes an `unsigned long`, `arg_type` will be
`unsigned long`; and so on.
#### Anti-pattern: Using EXPECT_ Statements in Matchers
Using `EXPECT_...` statements inside custom matcher definitions is an
**anti-pattern** and should be avoided.
While it might appear to write matchers more concisely and generate informative
messages, this pattern has critical issues:
1. **Negation Breakage (`Not`):** If wrapped in `Not(IsDivisibleBy7())`,
evaluating it still triggers the internal `EXPECT_EQ`, registering a test
failure on the runner even when the overall assertion is expected to
succeed.
2. **Composition / Container Breakage (`AnyOf`, `AllOf`, `Contains`):** When
composed or used inside container matchers, elements that are expected
mismatches will trigger the internal `EXPECT_` and register spurious
failures.
3. **ASSERT_* compilation errors:** `ASSERT_*` macros use `return;` to abort
from a void function. Since matchers return `bool`, using `ASSERT_` inside
them triggers a compilation error.
4. **Purity Violations:** Matchers must be functionally pure (side-effect
free), whereas registering global failures is a major side effect.
5. **Line Number Confusion:** Failure reports point to the matcher's definition
line rather than the calling `EXPECT_THAT`
line.
##### The Anti-Pattern
```cpp
// Anti-pattern: Do not do this!
MATCHER(IsDivisibleBy7, "") {
const auto remainder = arg % 7;
EXPECT_EQ(remainder, 0); // Spurious failures if negated/composed!
return true;
}
```
##### The Correct Solution
To write concise matchers that delegate to other matchers and safely propagate
the mismatch explanation, use **`::testing::ExplainMatchResult`** instead,
passing it the sub-matcher, the value to check, and the `result_listener`:
```cpp
MATCHER(IsDivisibleBy7, "") {
const auto remainder = arg % 7;
return ::testing::ExplainMatchResult(::testing::Eq(0), remainder,
result_listener);
}
```
If you write a test that includes the line:
```cpp
EXPECT_THAT(28, Not(IsDivisibleBy7()));
```
it will correctly report the mismatch, properly point to the `EXPECT_THAT` line
number, and support negation (`Not`) and composition (`AllOf`, `AnyOf`, etc.)
without registering spurious failures.
### Writing New Parameterized Matchers Quickly
Sometimes you'll want to define a matcher that has parameters. For that you can

View File

@ -28,15 +28,6 @@ macro(fix_default_compiler_settings_)
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
if (NOT BUILD_SHARED_LIBS AND NOT gtest_force_shared_crt)
# When Google Test is built as a shared library, it should also use
# shared runtime libraries. Otherwise, it may end up with multiple
# copies of runtime library data in different modules, resulting in
# hard-to-find crashes. When it is built as a static library, it is
# preferable to use CRT as static libraries, as we don't have to rely
# on CRT DLLs being available. CMake always defaults to using shared
# CRT libraries, so we override that default here.
string(REPLACE "/MD" "-MT" ${flag_var} "${${flag_var}}")
# When using Ninja with Clang, static builds pass -D_DLL on Windows.
# This is incorrect and should not happen, so we fix that here.
string(REPLACE "-D_DLL" "" ${flag_var} "${${flag_var}}")
@ -70,7 +61,19 @@ macro(config_compiler_and_linker)
endif()
fix_default_compiler_settings_()
if (MSVC)
# When Google Test is built as a shared library, it should also use
# shared runtime libraries. Otherwise, it may end up with multiple
# copies of runtime library data in different modules, resulting in
# hard-to-find crashes. When it is built as a static library, it is
# preferable to use CRT as static libraries, as we don't have to rely
# on CRT DLLs being available. CMake defaults to using shared
# CRT libraries, so we change that here.
if (NOT BUILD_SHARED_LIBS AND NOT gtest_force_shared_crt AND NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif()
# Newlines inside flags variables break CMake's NMake generator.
# TODO(vladl@google.com): Add -RTCs and -RTCu to debug builds.
set(cxx_base_flags "-GS -W4 -WX -wd4251 -wd4275 -nologo -J")

View File

@ -129,7 +129,7 @@ class GTEST_API_ Message {
int>::type = 0
#endif // GTEST_HAS_ABSL
>
inline Message& operator<<(const T& val) {
Message& operator<<(const T& val) {
// Some libraries overload << for STL containers. These
// overloads are defined in the global namespace instead of ::std.
//
@ -155,7 +155,7 @@ class GTEST_API_ Message {
template <typename T,
typename std::enable_if<absl::HasAbslStringify<T>::value, // NOLINT
int>::type = 0>
inline Message& operator<<(const T& val) {
Message& operator<<(const T& val) {
// ::operator<< is needed here for a similar reason as with the non-Abseil
// version above
using ::operator<<;