From 44f22083d7b7e64c061d1cb94c429e3fd17d586d Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Mon, 15 Jun 2026 20:53:52 -0700 Subject: [PATCH 01/13] Automated Code Change PiperOrigin-RevId: 932837091 Change-Id: Ie65ce7e76ecb97b62483b8ee0ba95e5a96b8039e --- googletest/src/gtest-printers.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/googletest/src/gtest-printers.cc b/googletest/src/gtest-printers.cc index f65573077..6d1de6d95 100644 --- a/googletest/src/gtest-printers.cc +++ b/googletest/src/gtest-printers.cc @@ -114,8 +114,7 @@ void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count, // char32_t. template char32_t ToChar32(CharType in) { - return static_cast( - static_cast::type>(in)); + return static_cast(static_cast>(in)); } } // namespace From 0b1e895ba4226c2fda5ee0178c9b5b1195a741aa Mon Sep 17 00:00:00 2001 From: Clayton Knittel Date: Tue, 16 Jun 2026 13:31:36 -0700 Subject: [PATCH 02/13] Specialize testing::WhenDynamicCastTo for protobuf messages. Protobuf messages have a custom dynamic_cast, for when RTTI is not available on the messages. PiperOrigin-RevId: 933270097 Change-Id: Iaeb50bce3fe1b746306a7507ab1985b111c03416 --- googlemock/include/gmock/gmock-matchers.h | 36 +++++++++++++++++-- .../include/gtest/internal/gtest-internal.h | 6 ++++ .../gmock_dynamic_cast_message_test.proto | 9 +++++ 3 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 googletest/test/custom/gmock_dynamic_cast_message_test.proto diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h index bdd8084d5..5cfa0b71c 100644 --- a/googlemock/include/gmock/gmock-matchers.h +++ b/googlemock/include/gmock/gmock-matchers.h @@ -275,6 +275,7 @@ #include "gmock/internal/gmock-internal-utils.h" #include "gmock/internal/gmock-pp.h" #include "gtest/gtest.h" +#include "gtest/internal/gtest-internal.h" // MSVC warning C5046 is new as of VS2017 version 15.8. #if defined(_MSC_VER) && _MSC_VER >= 1915 @@ -2059,6 +2060,15 @@ class [[nodiscard]] PointerMatcher { }; #if GTEST_HAS_RTTI +// A type trait to essentially determine if `DynamicCastMessage` is available, +// since older versions of protobuf don't have this function. +template +static constexpr bool kHasDynamicCastMessage = false; +template +static constexpr bool kHasDynamicCastMessage< + T, std::void_t( + std::declval()))>> = true; + // Implements the WhenDynamicCastTo(m) matcher that matches a pointer or // reference that matches inner_matcher when dynamic_cast is applied. // The result of dynamic_cast is forwarded to the inner matcher. @@ -2086,6 +2096,27 @@ class [[nodiscard]] WhenDynamicCastToMatcherBase { static std::string GetToName() { return GetTypeName(); } + template + static auto DoDynamicCast(From& from) { + using ToType = + std::remove_const_t>>; + + if constexpr (std::is_base_of_v && + kHasDynamicCastMessage) { + if constexpr (std::is_pointer_v) { + return proto2::DynamicCastMessage(from); + } else { + // We don't want an std::bad_cast here, so do the cast with pointers. + return proto2::DynamicCastMessage(&from); + } + } else if constexpr (std::is_pointer_v) { + return dynamic_cast(from); + } else { + // We don't want an std::bad_cast here, so do the cast with pointers. + return dynamic_cast*>(&from); + } + } + private: static void GetCastTypeDescription(::std::ostream* os) { *os << "when dynamic_cast to " << GetToName() << ", "; @@ -2103,7 +2134,7 @@ class [[nodiscard]] WhenDynamicCastToMatcher template bool MatchAndExplain(From from, MatchResultListener* listener) const { - To to = dynamic_cast(from); + To to = this->DoDynamicCast(from); return MatchPrintAndExplain(to, this->matcher_, listener); } }; @@ -2119,8 +2150,7 @@ WhenDynamicCastToMatcher : public WhenDynamicCastToMatcherBase { template bool MatchAndExplain(From& from, MatchResultListener* listener) const { - // We don't want an std::bad_cast here, so do the cast with pointers. - To* to = dynamic_cast(&from); + To* to = this->DoDynamicCast(from); if (to == nullptr) { *listener << "which cannot be dynamic_cast to " << this->GetToName(); return false; diff --git a/googletest/include/gtest/internal/gtest-internal.h b/googletest/include/gtest/internal/gtest-internal.h index 7096355d5..8f66d1b35 100644 --- a/googletest/include/gtest/internal/gtest-internal.h +++ b/googletest/include/gtest/internal/gtest-internal.h @@ -96,6 +96,12 @@ namespace proto2 { class [[nodiscard]] MessageLite; + +// Dummy forward declaration of `DynamicCastMessage`. Does not match any actual +// overloads of `DynamicCastMessage`, but can be used to assist name resolution +// in templates. +template +T DynamicCastMessage() = delete; } namespace testing { diff --git a/googletest/test/custom/gmock_dynamic_cast_message_test.proto b/googletest/test/custom/gmock_dynamic_cast_message_test.proto new file mode 100644 index 000000000..eacc45945 --- /dev/null +++ b/googletest/test/custom/gmock_dynamic_cast_message_test.proto @@ -0,0 +1,9 @@ +edition = "2024"; + +package testing.internal.dynamic_cast_message_test; + +message FooMessage { + int32 int_field = 1; +} + +message BarMessage {} From 1fc11dea107bde2a92dad7a9ed1b960978f1065a Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Mon, 22 Jun 2026 00:44:06 -0700 Subject: [PATCH 03/13] Automated Code Change PiperOrigin-RevId: 935893961 Change-Id: I90f8e57a7337f66a2afd37a2f0bc0e418e1ef51e --- .../include/gtest/gtest-assertion-result.h | 3 +- googletest/include/gtest/gtest-matchers.h | 49 +++++++++---------- googletest/include/gtest/gtest-printers.h | 6 +-- googletest/include/gtest/gtest.h | 4 +- 4 files changed, 29 insertions(+), 33 deletions(-) diff --git a/googletest/include/gtest/gtest-assertion-result.h b/googletest/include/gtest/gtest-assertion-result.h index 52a6d62c7..7a5e223fa 100644 --- a/googletest/include/gtest/gtest-assertion-result.h +++ b/googletest/include/gtest/gtest-assertion-result.h @@ -161,8 +161,7 @@ class GTEST_API_ [[nodiscard]] AssertionResult { template explicit AssertionResult( const T& success, - typename std::enable_if< - !std::is_convertible::value>::type* + std::enable_if_t>* /*enabler*/ = nullptr) : success_(success) {} diff --git a/googletest/include/gtest/gtest-matchers.h b/googletest/include/gtest/gtest-matchers.h index 6d2ab14d2..d7bdd047f 100644 --- a/googletest/include/gtest/gtest-matchers.h +++ b/googletest/include/gtest/gtest-matchers.h @@ -277,8 +277,8 @@ class [[nodiscard]] MatcherBase : private MatcherDescriberInterface { Init(impl); } - template ::type::is_gtest_matcher> + template ::is_gtest_matcher> MatcherBase(M&& m) : vtable_(nullptr), buffer_() { // NOLINT Init(std::forward(m)); } @@ -363,11 +363,10 @@ class [[nodiscard]] MatcherBase : private MatcherDescriberInterface { // from the impl, but some users really want to get their impl back when // they call GetDescriber(). // We use std::get on a tuple as a workaround of not having `if constexpr`. - return std::get<( - std::is_convertible::value - ? 1 - : 0)>(std::make_tuple(&m, &P::Get(m))); + return std::get<(std::is_convertible_v + ? 1 + : 0)>(std::make_tuple(&m, &P::Get(m))); } template @@ -396,8 +395,8 @@ class [[nodiscard]] MatcherBase : private MatcherDescriberInterface { template static constexpr bool IsInlined() { return sizeof(M) <= sizeof(Buffer) && alignof(M) <= alignof(Buffer) && - std::is_trivially_copy_constructible::value && - std::is_trivially_destructible::value; + std::is_trivially_copy_constructible_v && + std::is_trivially_destructible_v; } template ()> @@ -444,7 +443,7 @@ class [[nodiscard]] MatcherBase : private MatcherDescriberInterface { template void Init(M&& m) { - using MM = typename std::decay::type; + using MM = std::decay_t; using Policy = ValuePolicy; vtable_ = GetVTable(); Policy::Init(*this, std::forward(m)); @@ -473,14 +472,12 @@ class [[nodiscard]] Matcher : public internal::MatcherBase { : internal::MatcherBase(impl) {} template - explicit Matcher( - const MatcherInterface* impl, - typename std::enable_if::value>::type* = - nullptr) + explicit Matcher(const MatcherInterface* impl, + std::enable_if_t>* = nullptr) : internal::MatcherBase(impl) {} - template ::type::is_gtest_matcher> + template ::is_gtest_matcher> Matcher(M&& m) : internal::MatcherBase(std::forward(m)) {} // NOLINT // Implicit constructor here allows people to write @@ -509,8 +506,8 @@ Matcher : public internal::MatcherBase { explicit Matcher(const MatcherInterface* impl) : internal::MatcherBase(impl) {} - template ::type::is_gtest_matcher> + template ::is_gtest_matcher> Matcher(M&& m) // NOLINT : internal::MatcherBase(std::forward(m)) {} @@ -533,8 +530,8 @@ Matcher : public internal::MatcherBase { explicit Matcher(const MatcherInterface* impl) : internal::MatcherBase(impl) {} - template ::type::is_gtest_matcher> + template ::is_gtest_matcher> Matcher(M&& m) // NOLINT : internal::MatcherBase(std::forward(m)) {} @@ -559,8 +556,8 @@ class GTEST_API_ [[nodiscard]] Matcher explicit Matcher(const MatcherInterface* impl) : internal::MatcherBase(impl) {} - template ::type::is_gtest_matcher> + template ::is_gtest_matcher> Matcher(M&& m) // NOLINT : internal::MatcherBase(std::forward(m)) { } @@ -587,8 +584,8 @@ class GTEST_API_ [[nodiscard]] Matcher explicit Matcher(const MatcherInterface* impl) : internal::MatcherBase(impl) {} - template ::type::is_gtest_matcher> + template ::is_gtest_matcher> Matcher(M&& m) // NOLINT : internal::MatcherBase(std::forward(m)) {} @@ -815,8 +812,8 @@ class [[nodiscard]] ImplicitCastEqMatcher { StoredRhs stored_rhs_; }; -template ::value>::type> +template >> using StringLike = T; // Implements polymorphic matchers MatchesRegex(regex) and diff --git a/googletest/include/gtest/gtest-printers.h b/googletest/include/gtest/gtest-printers.h index d1704bb75..a13815733 100644 --- a/googletest/include/gtest/gtest-printers.h +++ b/googletest/include/gtest/gtest-printers.h @@ -863,8 +863,8 @@ void PrintTupleTo(const T& t, std::integral_constant, GTEST_INTENTIONAL_CONST_COND_POP_() *os << ", "; } - UniversalPrinter::type>::Print( - std::get(t), os); + UniversalPrinter>::Print(std::get(t), + os); } template @@ -1218,7 +1218,7 @@ template Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) { Strings result; TersePrintPrefixToStrings( - value, std::integral_constant::value>(), + value, std::integral_constant>(), &result); return result; } diff --git a/googletest/include/gtest/gtest.h b/googletest/include/gtest/gtest.h index f4a91ee44..a7193379b 100644 --- a/googletest/include/gtest/gtest.h +++ b/googletest/include/gtest/gtest.h @@ -2164,7 +2164,7 @@ class GTEST_API_ [[nodiscard]] ScopedTrace { // to cause a compiler error. template constexpr bool StaticAssertTypeEq() noexcept { - static_assert(std::is_same::value, "T1 and T2 are not the same type"); + static_assert(std::is_same_v, "T1 and T2 are not the same type"); return true; } @@ -2310,7 +2310,7 @@ template TestInfo* RegisterTest(const char* test_suite_name, const char* test_name, const char* type_param, const char* value_param, const char* file, int line, Factory factory) { - using TestT = typename std::remove_pointer::type; + using TestT = std::remove_pointer_t; class FactoryImpl : public internal::TestFactoryBase { public: From d4a1a3599b36f37b14422a6c8150f927582f6606 Mon Sep 17 00:00:00 2001 From: Brent Murphy Date: Mon, 22 Jun 2026 18:27:35 +1000 Subject: [PATCH 04/13] cmake: Fix PDB output dir for install of static and shared lib PR https://github.com/google/googletest/pull/3940 added COMPILE_PDB_OUTPUT_DIRECTORY without updating the install command to accommodate the two PDB properties. COMPILE_PDB_* and PDB_* properties are two distinct properties that affect static (COMPILE_PDB_*) and shared (PDB_*) separately. This commit adds cmake install rule for both types (optionally) to install when available --- googletest/cmake/internal_utils.cmake | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/googletest/cmake/internal_utils.cmake b/googletest/cmake/internal_utils.cmake index ca76f42d7..5f4e85a8a 100644 --- a/googletest/cmake/internal_utils.cmake +++ b/googletest/cmake/internal_utils.cmake @@ -320,11 +320,15 @@ function(install_project) foreach(t ${ARGN}) get_target_property(t_pdb_name ${t} COMPILE_PDB_NAME) get_target_property(t_pdb_name_debug ${t} COMPILE_PDB_NAME_DEBUG) - get_target_property(t_pdb_output_directory ${t} PDB_OUTPUT_DIRECTORY) + get_target_property(t_pdb_output_directory ${t} COMPILE_PDB_OUTPUT_DIRECTORY) + get_target_property(t_shared_pdb_name ${t} PDB_NAME) + get_target_property(t_shared_pdb_name_debug ${t} PDB_NAME_DEBUG) + get_target_property(t_shared_pdb_output_directory ${t} PDB_OUTPUT_DIRECTORY) install(FILES - "${t_pdb_output_directory}/\${CMAKE_INSTALL_CONFIG_NAME}/$<$:${t_pdb_name_debug}>$<$>:${t_pdb_name}>.pdb" + "$<$,STATIC_LIBRARY>:${t_pdb_output_directory}/\${CMAKE_INSTALL_CONFIG_NAME}/$,${t_pdb_name_debug},${t_pdb_name}>.pdb>" + "$<$,SHARED_LIBRARY>:${t_shared_pdb_output_directory}/\${CMAKE_INSTALL_CONFIG_NAME}/$,${t_shared_pdb_name_debug},${t_shared_pdb_name}>.pdb" COMPONENT "${PROJECT_NAME}" - DESTINATION ${CMAKE_INSTALL_LIBDIR} + DESTINATION $,STATIC_LIBRARY>,${CMAKE_INSTALL_LIBDIR},${CMAKE_INSTALL_BINDIR}> OPTIONAL) endforeach() endif() From aa40ee603ebbc0d4ebef4224ece54a6ae4382d0e Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Tue, 23 Jun 2026 06:02:44 -0700 Subject: [PATCH 05/13] Automated Code Change PiperOrigin-RevId: 936616624 Change-Id: I3a05afadf807fc372337186c26b5d73a2bc21410 --- googlemock/test/gmock-actions_test.cc | 109 +++++++++--------- googlemock/test/gmock-function-mocker_test.cc | 2 +- googlemock/test/gmock-matchers-misc_test.cc | 2 +- googlemock/test/gmock-matchers_test.h | 3 +- 4 files changed, 56 insertions(+), 60 deletions(-) diff --git a/googlemock/test/gmock-actions_test.cc b/googlemock/test/gmock-actions_test.cc index 1bc304088..507db6b2a 100644 --- a/googlemock/test/gmock-actions_test.cc +++ b/googlemock/test/gmock-actions_test.cc @@ -66,30 +66,30 @@ using ::testing::internal::BuiltInDefaultValue; TEST(TypeTraits, Negation) { // Direct use with std types. - static_assert(std::is_base_of>::value, - ""); + static_assert( + std::is_base_of_v>, + ""); - static_assert(std::is_base_of>::value, - ""); + static_assert( + std::is_base_of_v>, + ""); // With other types that fit the requirement of a value member that is // convertible to bool. - static_assert(std::is_base_of< - std::true_type, - internal::negation>>::value, - ""); + static_assert( + std::is_base_of_v>>, + ""); - static_assert(std::is_base_of< - std::false_type, - internal::negation>>::value, - ""); + static_assert( + std::is_base_of_v>>, + ""); - static_assert(std::is_base_of< - std::false_type, - internal::negation>>::value, - ""); + static_assert( + std::is_base_of_v>>, + ""); } // Weird false/true types that aren't actually bool constants (but should still @@ -108,79 +108,76 @@ struct MyTrue : std::integral_constant {}; TEST(TypeTraits, Conjunction) { // Base case: always true. - static_assert(std::is_base_of>::value, - ""); + static_assert(std::is_base_of_v>, ""); // One predicate: inherits from that predicate, regardless of value. static_assert( - std::is_base_of, internal::conjunction>>::value, - ""); + std::is_base_of_v, internal::conjunction>>, ""); - static_assert( - std::is_base_of, internal::conjunction>>::value, ""); + static_assert(std::is_base_of_v, internal::conjunction>>, + ""); // Multiple predicates, with at least one false: inherits from that one. static_assert( - std::is_base_of, internal::conjunction, MyFalse<1>, - MyTrue<2>>>::value, + std::is_base_of_v< + MyFalse<1>, internal::conjunction, MyFalse<1>, MyTrue<2>>>, ""); static_assert( - std::is_base_of, internal::conjunction, MyFalse<1>, - MyFalse<2>>>::value, + std::is_base_of_v< + MyFalse<1>, internal::conjunction, MyFalse<1>, MyFalse<2>>>, ""); // Short circuiting: in the case above, additional predicates need not even // define a value member. struct Empty {}; static_assert( - std::is_base_of, internal::conjunction, MyFalse<1>, - Empty>>::value, + std::is_base_of_v, + internal::conjunction, MyFalse<1>, Empty>>, ""); // All predicates true: inherits from the last. static_assert( - std::is_base_of, internal::conjunction, MyTrue<1>, - MyTrue<2>>>::value, + std::is_base_of_v, + internal::conjunction, MyTrue<1>, MyTrue<2>>>, ""); } TEST(TypeTraits, Disjunction) { // Base case: always false. - static_assert( - std::is_base_of>::value, ""); + static_assert(std::is_base_of_v>, + ""); // One predicate: inherits from that predicate, regardless of value. static_assert( - std::is_base_of, internal::disjunction>>::value, - ""); + std::is_base_of_v, internal::disjunction>>, ""); - static_assert( - std::is_base_of, internal::disjunction>>::value, ""); + static_assert(std::is_base_of_v, internal::disjunction>>, + ""); // Multiple predicates, with at least one true: inherits from that one. static_assert( - std::is_base_of, internal::disjunction, MyTrue<1>, - MyFalse<2>>>::value, + std::is_base_of_v< + MyTrue<1>, internal::disjunction, MyTrue<1>, MyFalse<2>>>, ""); static_assert( - std::is_base_of, internal::disjunction, MyTrue<1>, - MyTrue<2>>>::value, + std::is_base_of_v< + MyTrue<1>, internal::disjunction, MyTrue<1>, MyTrue<2>>>, ""); // Short circuiting: in the case above, additional predicates need not even // define a value member. struct Empty {}; static_assert( - std::is_base_of, internal::disjunction, MyTrue<1>, - Empty>>::value, + std::is_base_of_v, + internal::disjunction, MyTrue<1>, Empty>>, ""); // All predicates false: inherits from the last. static_assert( - std::is_base_of, internal::disjunction, MyFalse<1>, - MyFalse<2>>>::value, + std::is_base_of_v, internal::disjunction< + MyFalse<0>, MyFalse<1>, MyFalse<2>>>, ""); } @@ -747,8 +744,8 @@ TEST(ReturnTest, ConversionRequiresConstLvalueReference) { using R = int; using U = std::reference_wrapper; - static_assert(std::is_convertible::value, ""); - static_assert(!std::is_convertible::value, ""); + static_assert(std::is_convertible_v, ""); + static_assert(!std::is_convertible_v, ""); MockFunction mock; EXPECT_CALL(mock, Call).WillOnce(Return(17)).WillRepeatedly(Return(19)); @@ -771,11 +768,11 @@ TEST(ReturnTest, ConversionRequiresMutableLvalueReference) { S(std::string&) {} // NOLINT }; - static_assert(std::is_convertible::value, ""); + static_assert(std::is_convertible_v, ""); #ifndef _MSC_VER - static_assert(!std::is_convertible::value, ""); + static_assert(!std::is_convertible_v, ""); #endif - static_assert(!std::is_convertible::value, ""); + static_assert(!std::is_convertible_v, ""); // It shouldn't be possible to use the result of Return(std::string) in a // context where an S is needed. @@ -784,9 +781,9 @@ TEST(ReturnTest, ConversionRequiresMutableLvalueReference) { // implementation of is_convertible causes our SFINAE to be wrong. using RA = decltype(Return(std::string())); - static_assert(!std::is_convertible>::value, ""); + static_assert(!std::is_convertible_v>, ""); #ifndef _MSC_VER - static_assert(!std::is_convertible>::value, ""); + static_assert(!std::is_convertible_v>, ""); #endif } @@ -803,8 +800,8 @@ TEST(ReturnTest, MoveOnlyResultType) { // The result of Return should not be convertible to Action (so it can't be // used with WillRepeatedly). - static_assert(!std::is_convertible())), - Action()>>::value, + static_assert(!std::is_convertible_v())), + Action()>>, ""); } @@ -2196,7 +2193,7 @@ TEST(MoveOnlyArgumentsTest, ReturningActions) { EXPECT_EQ(x, 3); } -ACTION(ReturnArity) { return std::tuple_size::value; } +ACTION(ReturnArity) { return std::tuple_size_v; } TEST(ActionMacro, LargeArity) { EXPECT_EQ( diff --git a/googlemock/test/gmock-function-mocker_test.cc b/googlemock/test/gmock-function-mocker_test.cc index 05e26c8c4..240debd9a 100644 --- a/googlemock/test/gmock-function-mocker_test.cc +++ b/googlemock/test/gmock-function-mocker_test.cc @@ -937,7 +937,7 @@ namespace { template static constexpr bool IsMockFunctionTemplateArgumentDeducedTo( const internal::MockFunction&) { - return std::is_same::value; + return std::is_same_v; } } // namespace diff --git a/googlemock/test/gmock-matchers-misc_test.cc b/googlemock/test/gmock-matchers-misc_test.cc index 0161169f2..16d62be24 100644 --- a/googlemock/test/gmock-matchers-misc_test.cc +++ b/googlemock/test/gmock-matchers-misc_test.cc @@ -789,7 +789,7 @@ class SampleVariantIntString { template friend bool holds_alternative(const SampleVariantIntString& value) { - return value.has_int_ == std::is_same::value; + return value.has_int_ == std::is_same_v; } template diff --git a/googlemock/test/gmock-matchers_test.h b/googlemock/test/gmock-matchers_test.h index 56956076d..23b8abd8b 100644 --- a/googlemock/test/gmock-matchers_test.h +++ b/googlemock/test/gmock-matchers_test.h @@ -123,8 +123,7 @@ struct GtestGreaterThanMatcher { }; template -GtestGreaterThanMatcher::type> GtestGreaterThan( - T&& rhs) { +GtestGreaterThanMatcher> GtestGreaterThan(T&& rhs) { return {rhs}; } From 8b53336594cc52213c6c2c7a0b29194fa896d039 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Tue, 23 Jun 2026 06:45:04 -0700 Subject: [PATCH 06/13] Automated Code Change PiperOrigin-RevId: 936635684 Change-Id: I3b1bfa2ef921cdc3d0aaa1fc95986b64a9ad0282 --- .../gmock/internal/gmock-internal-utils.h | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/googlemock/include/gmock/internal/gmock-internal-utils.h b/googlemock/include/gmock/internal/gmock-internal-utils.h index 258397a4f..2982c244e 100644 --- a/googlemock/include/gmock/internal/gmock-internal-utils.h +++ b/googlemock/include/gmock/internal/gmock-internal-utils.h @@ -194,11 +194,11 @@ using LosslessArithmeticConvertibleImpl = std::integral_constant< // Converting between integers of different widths is allowed so long // as the conversion does not go from signed to unsigned. (((sizeof(From) < sizeof(To)) && - !(std::is_signed::value && !std::is_signed::value)) || + !(std::is_signed_v && !std::is_signed_v)) || // Converting between integers of the same width only requires the // two types to have the same signedness. ((sizeof(From) == sizeof(To)) && - (std::is_signed::value == std::is_signed::value))) + (std::is_signed_v == std::is_signed_v))) ) ? true // Floating point conversions are lossless if and only if `To` is at least // as wide as `From`. @@ -364,7 +364,7 @@ class [[nodiscard]] StlContainerView { typedef const type& const_reference; static const_reference ConstReference(const RawContainer& container) { - static_assert(!std::is_const::value, + static_assert(!std::is_const_v, "RawContainer type must not be const"); return container; } @@ -385,7 +385,7 @@ class [[nodiscard]] StlContainerView { typedef const type const_reference; static const_reference ConstReference(const Element (&array)[N]) { - static_assert(std::is_same::value, + static_assert(std::is_same_v, "Element type must not be const"); return type(array, N, RelationToSourceReference()); } @@ -447,14 +447,13 @@ auto ApplyImpl(F&& f, Tuple&& args, std::index_sequence) // Apply the function to a tuple of arguments. template -auto Apply(F&& f, Tuple&& args) - -> decltype(ApplyImpl( - std::forward(f), std::forward(args), - std::make_index_sequence::type>::value>())) { +auto Apply(F&& f, Tuple&& args) -> decltype(ApplyImpl( + std::forward(f), std::forward(args), + std::make_index_sequence< + std::tuple_size_v>>())) { return ApplyImpl(std::forward(f), std::forward(args), - std::make_index_sequence::type>::value>()); + std::make_index_sequence< + std::tuple_size_v>>()); } // Template struct Function, where F must be a function type, contains @@ -490,7 +489,7 @@ struct Function { // See: https://github.com/google/googletest/issues/3931 // Can be replaced with std::tuple_element_t in C++14. template -using TupleElement = typename std::tuple_element::type; +using TupleElement = std::tuple_element_t; bool Base64Unescape(const std::string& encoded, std::string* decoded); From 973323ed64a05b128418e7eab67016db5ba049df Mon Sep 17 00:00:00 2001 From: Clayton Knittel Date: Tue, 30 Jun 2026 12:20:38 -0700 Subject: [PATCH 07/13] Delay name resolution by un-qualifying `DynamicCastMessage` calls from gMock. Since we can't directly depend on proto headers, we rely on ADL + proto headers being included by calling code for this matcher to choose the right overload of `DynamicCastMessage`. PiperOrigin-RevId: 940593408 Change-Id: I7374aed3c5cfe61a183d28ea02e6583ab340f647 --- googlemock/include/gmock/gmock-matchers.h | 56 +++++++++++++++++------ 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h index 5cfa0b71c..7407e119e 100644 --- a/googlemock/include/gmock/gmock-matchers.h +++ b/googlemock/include/gmock/gmock-matchers.h @@ -284,6 +284,44 @@ #define GMOCK_MAYBE_5046_ #endif +#if GTEST_HAS_RTTI +namespace proto2 { +namespace internal { + +// A type trait to essentially determine if `DynamicCastMessage` is available, +// since older versions of protobuf don't have this function. +template +static constexpr bool kHasDynamicCastMessage = false; +template +static constexpr bool kHasDynamicCastMessage< + T, std::void_t( + std::declval()))>> = true; + +// A helper function to call `DynamicCastMessage` if available, otherwise +// falling back to `dynamic_cast`. Note that we must declare this function in +// the `proto2` namespace because we need ADL to find the right +// `DynamicCastMessage`, and ADL only applies to unqualified function calls. +template +const T* DynamicCastMessageForGtest(const proto2::MessageLite* msg) { + if constexpr (kHasDynamicCastMessage) { + return DynamicCastMessage(msg); + } else { + return dynamic_cast(msg); + } +} +template +T* DynamicCastMessageForGtest(proto2::MessageLite* msg) { + if constexpr (kHasDynamicCastMessage) { + return DynamicCastMessage(msg); + } else { + return dynamic_cast(msg); + } +} + +} // namespace internal +} // namespace proto2 +#endif // GTEST_HAS_RTTI + GTEST_DISABLE_MSC_WARNINGS_PUSH_( 4251 GMOCK_MAYBE_5046_ /* class A needs to have dll-interface to be used by clients of class B */ @@ -2060,15 +2098,6 @@ class [[nodiscard]] PointerMatcher { }; #if GTEST_HAS_RTTI -// A type trait to essentially determine if `DynamicCastMessage` is available, -// since older versions of protobuf don't have this function. -template -static constexpr bool kHasDynamicCastMessage = false; -template -static constexpr bool kHasDynamicCastMessage< - T, std::void_t( - std::declval()))>> = true; - // Implements the WhenDynamicCastTo(m) matcher that matches a pointer or // reference that matches inner_matcher when dynamic_cast is applied. // The result of dynamic_cast is forwarded to the inner matcher. @@ -2101,13 +2130,12 @@ class [[nodiscard]] WhenDynamicCastToMatcherBase { using ToType = std::remove_const_t>>; - if constexpr (std::is_base_of_v && - kHasDynamicCastMessage) { - if constexpr (std::is_pointer_v) { - return proto2::DynamicCastMessage(from); + if constexpr (std::is_base_of_v) { + if constexpr (std::is_pointer_v) { + return proto2::internal::DynamicCastMessageForGtest(from); } else { // We don't want an std::bad_cast here, so do the cast with pointers. - return proto2::DynamicCastMessage(&from); + return proto2::internal::DynamicCastMessageForGtest(&from); } } else if constexpr (std::is_pointer_v) { return dynamic_cast(from); From 5b39f4c876478da1620e1fe4b0bba8e6f5ea139f Mon Sep 17 00:00:00 2001 From: Tejas Sharma Date: Sat, 4 Jul 2026 21:54:09 +0530 Subject: [PATCH 08/13] Add missing public flags to --help output --- googletest/src/gtest.cc | 15 +++++++++++++++ googletest/test/gtest_help_test.py | 13 ++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/googletest/src/gtest.cc b/googletest/src/gtest.cc index ac90786a0..b38f551e0 100644 --- a/googletest/src/gtest.cc +++ b/googletest/src/gtest.cc @@ -6732,6 +6732,12 @@ static const char kColorEncodedHelpMessage[] = "recreate_environments_when_repeating@D\n" " Sets up and tears down the global test environment on each repeat\n" " of the test.\n" + " @G--" GTEST_FLAG_PREFIX_ + "fail_fast@D\n" + " Stop running tests after the first failure.\n" + " @G--" GTEST_FLAG_PREFIX_ + "fail_if_no_test_linked@D\n" + " Fail if no test is linked into the test program.\n" "\n" "Test Output:\n" " @G--" GTEST_FLAG_PREFIX_ @@ -6744,6 +6750,9 @@ static const char kColorEncodedHelpMessage[] = "print_time=0@D\n" " Don't print the elapsed time of each test.\n" " @G--" GTEST_FLAG_PREFIX_ + "print_utf8=0@D\n" + " Don't print UTF-8 characters as text.\n" + " @G--" GTEST_FLAG_PREFIX_ "output=@Y(@Gjson@Y|@Gxml@Y)[@G:@YDIRECTORY_PATH@G" GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n" " Generate a JSON or XML report in the given directory or with the " @@ -6760,6 +6769,9 @@ static const char kColorEncodedHelpMessage[] = " @G--" GTEST_FLAG_PREFIX_ "death_test_style=@Y(@Gfast@Y|@Gthreadsafe@Y)@D\n" " Set the default death test style.\n" + " @G--" GTEST_FLAG_PREFIX_ + "death_test_use_fork@D\n" + " Use fork() instead of clone() to spawn death test child processes.\n" #endif // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS " @G--" GTEST_FLAG_PREFIX_ "break_on_failure@D\n" @@ -6772,6 +6784,9 @@ static const char kColorEncodedHelpMessage[] = "catch_exceptions=0@D\n" " Do not report exceptions as test failures. Instead, allow them\n" " to crash the program or throw a pop-up (on Windows).\n" + " @G--" GTEST_FLAG_PREFIX_ + "stack_trace_depth=@Y[NUMBER]@D\n" + " Maximum number of stack frames to print when an assertion fails.\n" "\n" "Except for @G--" GTEST_FLAG_PREFIX_ "list_tests@D, you can alternatively set " diff --git a/googletest/test/gtest_help_test.py b/googletest/test/gtest_help_test.py index 38fc90ff1..977accfed 100755 --- a/googletest/test/gtest_help_test.py +++ b/googletest/test/gtest_help_test.py @@ -64,6 +64,7 @@ IS_WINDOWS = os.name == 'nt' PROGRAM_PATH = gtest_test_utils.GetTestExecutablePath('gtest_help_test_') FLAG_PREFIX = '--gtest_' DEATH_TEST_STYLE_FLAG = FLAG_PREFIX + 'death_test_style' +DEATH_TEST_USE_FORK_FLAG = FLAG_PREFIX + 'death_test_use_fork' STREAM_RESULT_TO_FLAG = FLAG_PREFIX + 'stream_result_to' LIST_TESTS_FLAG = FLAG_PREFIX + 'list_tests' INTERNAL_FLAG_FOR_TESTING = FLAG_PREFIX + 'internal_flag_for_testing' @@ -90,19 +91,27 @@ HELP_REGEX = re.compile( + FLAG_PREFIX + r'random_seed=.*' + FLAG_PREFIX + + r'fail_fast.*' + + FLAG_PREFIX + + r'fail_if_no_test_linked.*' + + FLAG_PREFIX + r'color=.*' + FLAG_PREFIX + r'brief.*' + FLAG_PREFIX + r'print_time.*' + FLAG_PREFIX + + r'print_utf8.*' + + FLAG_PREFIX + r'output=.*' + FLAG_PREFIX + r'break_on_failure.*' + FLAG_PREFIX + r'throw_on_failure.*' + FLAG_PREFIX - + r'catch_exceptions=0.*', + + r'catch_exceptions=0.*' + + FLAG_PREFIX + + r'stack_trace_depth=.*', re.DOTALL, ) @@ -151,8 +160,10 @@ class GTestHelpTest(gtest_test_utils.TestCase): if SUPPORTS_DEATH_TESTS and not IS_WINDOWS: self.assertIn(DEATH_TEST_STYLE_FLAG, output) + self.assertIn(DEATH_TEST_USE_FORK_FLAG, output) else: self.assertNotIn(DEATH_TEST_STYLE_FLAG, output) + self.assertNotIn(DEATH_TEST_USE_FORK_FLAG, output) def test_runs_tests_without_help_flag(self): """Verifies correct behavior when no help flag is specified. From 1c2082e8bd391683de14c8e2cb7c10c384198fbc Mon Sep 17 00:00:00 2001 From: "Manikandan K. S." Date: Sat, 4 Jul 2026 22:14:52 +0530 Subject: [PATCH 09/13] docs: add missing full stops to feature descriptions in README --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 1584c793d..24d5681f9 100644 --- a/README.md +++ b/README.md @@ -44,35 +44,35 @@ More information about building GoogleTest can be found at * xUnit test framework: \ Googletest is based on the [xUnit](https://en.wikipedia.org/wiki/XUnit) - testing framework, a popular architecture for unit testing + testing framework, a popular architecture for unit testing. * Test discovery: \ Googletest automatically discovers and runs your tests, eliminating the need - to manually register your tests + to manually register your tests. * Rich set of assertions: \ Googletest provides a variety of assertions, such as equality, inequality, - exceptions, and more, making it easy to test your code + exceptions, and more, making it easy to test your code. * User-defined assertions: \ You can define your own assertions with Googletest, making it simple to - write tests that are specific to your code + write tests that are specific to your code. * Death tests: \ Googletest supports death tests, which verify that your code exits in a - certain way, making it useful for testing error-handling code + certain way, making it useful for testing error-handling code. * Fatal and non-fatal failures: \ You can specify whether a test failure should be treated as fatal or non-fatal with Googletest, allowing tests to continue running even if a - failure occurs + failure occurs. * Value-parameterized tests: \ Googletest supports value-parameterized tests, which run multiple times with different input values, making it useful for testing functions that take - different inputs + different inputs. * Type-parameterized tests: \ Googletest also supports type-parameterized tests, which run with different data types, making it useful for testing functions that work with different - data types + data types. * Various options for running tests: \ Googletest provides many options for running tests including running individual tests, running tests in a specific order and running tests in - parallel + parallel. ## Supported Platforms From df4fdc5cfd2888d51a03ca45ab75a9a305ef065a Mon Sep 17 00:00:00 2001 From: "Manikandan K. S." Date: Sat, 4 Jul 2026 22:50:12 +0530 Subject: [PATCH 10/13] fix: add C-style wide string overload to IsEmpty matcher --- googlemock/include/gmock/gmock-more-matchers.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/googlemock/include/gmock/gmock-more-matchers.h b/googlemock/include/gmock/gmock-more-matchers.h index 39aad4c1a..b64e832f7 100644 --- a/googlemock/include/gmock/gmock-more-matchers.h +++ b/googlemock/include/gmock/gmock-more-matchers.h @@ -79,6 +79,12 @@ class [[nodiscard]] IsEmptyMatcher { return MatchAndExplain(std::string(s), listener); } + // Matches C-style wide strings. + bool MatchAndExplain(const wchar_t* s, + MatchResultListener* listener) const { + return MatchAndExplain(std::wstring(s), listener); + } + // Describes what this matcher matches. void DescribeTo(std::ostream* os) const { *os << "is empty"; } From 22bda2ba1538a7995501cf5b2fbc5cdfc5b444ab Mon Sep 17 00:00:00 2001 From: "Manikandan K. S." Date: Sun, 5 Jul 2026 08:54:29 +0530 Subject: [PATCH 11/13] chore: bump main branch version to 1.18.0 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c784f3c7c..793c8d3cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.16) project(googletest-distribution) -set(GOOGLETEST_VERSION 1.16.0) +set(GOOGLETEST_VERSION 1.18.0) if(NOT CYGWIN AND NOT MSYS AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL QNX) set(CMAKE_CXX_EXTENSIONS OFF) From 18c6bc3dc4123f688943824d3a1cf31dc29c1642 Mon Sep 17 00:00:00 2001 From: "Manikandan K. S." Date: Sun, 5 Jul 2026 09:03:35 +0530 Subject: [PATCH 12/13] fix: only use __cpp_lib_three_way_comparison for detection The fallback check GTEST_INTERNAL_HAS_INCLUDE() && C++20 causes build failures on Android NDK 24 which has the header but lacks the full comparison operators needed by PrintTo. The feature test macro __cpp_lib_three_way_comparison is the reliable indicator. Fixes #4933 --- googletest/include/gtest/internal/gtest-port.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/googletest/include/gtest/internal/gtest-port.h b/googletest/include/gtest/internal/gtest-port.h index b607e0ade..650a04558 100644 --- a/googletest/include/gtest/internal/gtest-port.h +++ b/googletest/include/gtest/internal/gtest-port.h @@ -2411,9 +2411,7 @@ using StringView = ::std::string_view; #define GTEST_INTERNAL_HAS_STRING_VIEW 0 #endif -#if (defined(__cpp_lib_three_way_comparison) || \ - (GTEST_INTERNAL_HAS_INCLUDE() && \ - GTEST_INTERNAL_CPLUSPLUS_LANG >= 201907L)) +#if defined(__cpp_lib_three_way_comparison) #define GTEST_INTERNAL_HAS_COMPARE_LIB 1 #else #define GTEST_INTERNAL_HAS_COMPARE_LIB 0 From 7d012aa1624ecb83925d2ff9135610a40526f370 Mon Sep 17 00:00:00 2001 From: Mike Kruskal Date: Tue, 7 Jul 2026 15:08:58 -0700 Subject: [PATCH 13/13] Fail smoothly for nullptr on c-style strings in IsEmpty PiperOrigin-RevId: 944115454 Change-Id: I99284439b0c0e0acee1cb4e12f2d0b8d422c83ba --- googlemock/include/gmock/gmock-more-matchers.h | 6 ++++++ googlemock/test/gmock-matchers-comparisons_test.cc | 2 ++ 2 files changed, 8 insertions(+) diff --git a/googlemock/include/gmock/gmock-more-matchers.h b/googlemock/include/gmock/gmock-more-matchers.h index d29123a67..9d9688ef0 100644 --- a/googlemock/include/gmock/gmock-more-matchers.h +++ b/googlemock/include/gmock/gmock-more-matchers.h @@ -76,12 +76,18 @@ class [[nodiscard]] IsEmptyMatcher { // Matches C-style strings. bool MatchAndExplain(const char* s, MatchResultListener* listener) const { + if (s == nullptr) { + return false; + } return MatchAndExplain(std::string(s), listener); } #if GTEST_HAS_STD_WSTRING // Matches C-style wide strings. bool MatchAndExplain(const wchar_t* s, MatchResultListener* listener) const { + if (s == nullptr) { + return false; + } return MatchAndExplain(std::wstring(s), listener); } #endif // GTEST_HAS_STD_WSTRING diff --git a/googlemock/test/gmock-matchers-comparisons_test.cc b/googlemock/test/gmock-matchers-comparisons_test.cc index 8a9981fcd..b800f1e8b 100644 --- a/googlemock/test/gmock-matchers-comparisons_test.cc +++ b/googlemock/test/gmock-matchers-comparisons_test.cc @@ -1092,6 +1092,7 @@ TEST(IsEmptyTest, MatchesCString) { const char b[] = "x"; EXPECT_TRUE(m.Matches(a)); EXPECT_FALSE(m.Matches(b)); + EXPECT_FALSE(m.Matches(nullptr)); } #if GTEST_HAS_STD_WSTRING @@ -1101,6 +1102,7 @@ TEST(IsEmptyTest, MatchesCWideString) { const wchar_t b[] = L"x"; EXPECT_TRUE(m.Matches(a)); EXPECT_FALSE(m.Matches(b)); + EXPECT_FALSE(m.Matches(nullptr)); } #endif // GTEST_HAS_STD_WSTRING