Compare commits

...
13 Commits
Author SHA1 Message Date
Copybara-Service 7260682388 Merge pull request #5046 from UditDewan:fix/print-invalid-char-code-units
PiperOrigin-RevId: 968678073
Change-Id: I669221b694231e385acb9a0bf6640e6f1c319e1e
2026-08-21 14:02:47 -07:00
Copybara-Service 0daf775f8c Merge pull request #4824 from DoDoENT:fix/emscripten-without-threads
PiperOrigin-RevId: 967351125
Change-Id: I4637dd19dfbd8c39d31a4a2bb6f4068e0f631e15
2026-08-19 12:35:58 -07:00
Nenad Mikša 1a447fdce7 avoid -lpthread link option when building with emscripten without threads
- having this flag causes emscripten to generate binary with pthread
  support, which is not compatible with browsers that do not support
  pthreads or with web pages that do not enable pthread support
2026-08-19 17:40:01 +02:00
Abseil Team 91c99b6ffe Add missing const in INSTANTIATE_TEST_SUITE_P.
Dropping this causes tools like [misc-const-correctness](http://clang.llvm.org/extra/clang-tidy/checks/misc/const-correctness.html) to flag GTEST macro invocations as non-const-correct.

PiperOrigin-RevId: 966588433
Change-Id: I896acca9e079288e971a2912c7aa6d17ec6a15e4
2026-08-18 07:44:33 -07:00
Abseil Team 7358557f03 Remove wchar_t overloads if GTEST_HAS_STD_WSTRING is disabled
PiperOrigin-RevId: 966053142
Change-Id: I6535e5577b430186a57ad9c401877aaa83cf37d1
2026-08-17 10:35:06 -07:00
Abseil Team 71edd0ef29 Extract GTEST_HAS_NATIVE_WCHAR
Define `GTEST_HAS_NATIVE_WCHAR` as a replacement for the `!defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)` condition used to remove `wchar_t*` overloads when `wchar_t` is a typedef. Remove `GMOCK_WCHAR_T_IS_NATIVE_` and migrate its uses to the GTest define.

PiperOrigin-RevId: 966022317
Change-Id: Ic929f45763566b9e8d194f280d1f32f5a582ff61
2026-08-17 09:42:15 -07:00
Abseil Team a2118f6587 Use std::make_unique to avoid clang-tidy false positive in GTEST_TEST_ macro.
PiperOrigin-RevId: 965352463
Change-Id: I4062f4f7a48cba6bf514abd7860d422f6e98cee7
2026-08-15 18:34:42 -07:00
Abseil Team 49495eacfd Use STL capabilities to choose GTEST_HAS_STD_WSTRING default
If the standard library claims not to support wide character strings, disable `GTEST_HAS_STD_WSTRING` and disallow users overriding it. If the standard library implementation can't be recognized, fall back to using the existing list of OSes with a known lack of support.

PiperOrigin-RevId: 964237076
Change-Id: I906f296259f8f17099990d51447a0d0d04dead66
2026-08-13 12:44:03 -07:00
Abseil Team aa1eefe02c Don't reference std::char_traits<wchar_t> when !GTEST_HAS_STD_WSTRING
If the standard library doesn't support wide character strings, `std::char_traits<Char>` won't be defined, so the definition of `PrintTo` shouldn't reference it. Use `wstrlen` directly instead.

PiperOrigin-RevId: 964168903
Change-Id: Ic628e6583679073b47bb1218dcf52b4c9eadaaf6
2026-08-13 10:39:39 -07:00
Abseil Team 002d14757f When Return is passed to WillOnce (i.e. converted to OnceAction) delegate to be equivalent to Return(ByMove(...))
This should eliminate most required usages of ByMove(...).

PiperOrigin-RevId: 964026018
Change-Id: I2dd5a56842ae3823b200c16b575960b6c367ca20
2026-08-13 05:34:04 -07:00
Abseil Team 02e50550c6 Default-enable wstring support for Android API level 21 and above.
Android started supporting std::wstring with API Level 21 (Lollipop). On Android, unless `GTEST_HAS_STD_WSTRING` is explicitly defined, set it based on the current Android API level.

PiperOrigin-RevId: 963538624
Change-Id: I1a19c4e5b0fef841e0650a1f95b45fa3439dee92
2026-08-12 10:47:59 -07:00
Prashant Kumar 963dd8ea18 Update version strings to 1.18
PiperOrigin-RevId: 962756240
Change-Id: Ibb440cda59a55a1dafc721f00140cbe0d726d077
2026-08-11 06:59:21 -07:00
uditDewan 806b89cf63 Print char8_t/char16_t code units that aren't code points as code units
PrintTo(char8_t) and PrintTo(char16_t) widened their argument to char32_t
and printed it with the U+XXXX notation. That notation names a code point,
but char8_t and char16_t hold code units, so it is wrong for every value
that does not encode a code point on its own: any non-ASCII char8_t (always
part of a multi-unit UTF-8 sequence) and the UTF-16 surrogates D800-DFFF.
For example, PrintTo(char8_t(0x80)) printed "U+0080", the code point of a
character that value cannot represent.

Print those values as code units instead, using the same escape-plus-code
form already used for char, unsigned char and wchar_t: char8_t(0x80) now
prints as u8'\x80' (128) and char16_t(0xD800) as u'\xD800' (55296). Values
that do encode a code point keep the U+XXXX notation.

Fixes #4762
2026-07-26 15:58:15 -04:00
17 changed files with 274 additions and 160 deletions
+13
View File
@@ -58,6 +58,16 @@ config_setting(
constraint_values = ["@platforms//os:openbsd"],
)
config_setting(
name = "emscripten_without_threads",
constraint_values = [
"@platforms//os:emscripten",
],
values = {
"features": "-use_pthreads",
},
)
# NOTE: Fuchsia is not an officially supported platform.
config_setting(
name = "fuchsia",
@@ -113,10 +123,12 @@ cc_library(
copts = select({
":qnx": [],
":windows": [],
":emscripten_without_threads": [],
"//conditions:default": ["-pthread"],
}),
defines = select({
":has_absl": ["GTEST_HAS_ABSL=1"],
":emscripten_without_threads": ["GTEST_HAS_PTHREAD=0"],
"//conditions:default": [],
}),
features = select({
@@ -140,6 +152,7 @@ cc_library(
"-lm",
"-pthread",
],
":emscripten_without_threads": [],
"//conditions:default": ["-pthread"],
}),
deps = select({
+3 -3
View File
@@ -8,12 +8,12 @@ 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.17.0
#### Release 1.18.0
[Release 1.17.0](https://github.com/google/googletest/releases/tag/v1.17.0) is
[Release 1.18.0](https://github.com/google/googletest/releases/tag/v1.18.0) is
now available.
The 1.17.x branch
The 1.18.x branch
[requires at least C++17](https://opensource.google/documentation/policies/cplusplus-support#c_language_standard).
#### Continuous Integration
+1 -1
View File
@@ -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.17.0")
bazel_dep(name = "googletest", version = "1.18.0")
```
Now you're ready to build C++ code that uses GoogleTest.
+20 -21
View File
@@ -146,6 +146,7 @@
#include "gmock/internal/gmock-internal-utils.h"
#include "gmock/internal/gmock-port.h"
#include "gmock/internal/gmock-pp.h"
#include "gtest/gtest.h"
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4100)
@@ -249,7 +250,7 @@ GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(char, '\0');
// There's also no need for a default action for unsigned wchar_t, as
// that type is the same as unsigned int for gcc, and invalid for
// MSVC.
#if GMOCK_WCHAR_T_IS_NATIVE_
#if GTEST_HAS_NATIVE_WCHAR
GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(wchar_t, 0U); // NOLINT
#endif
@@ -940,7 +941,7 @@ class [[nodiscard]] ReturnAction final {
std::is_convertible<R, U>, //
std::is_move_constructible<U>>::value>::type>
operator OnceAction<U(Args...)>() && { // NOLINT
return Impl<U>(std::move(value_));
return OnceImpl<U>(std::move(value_));
}
template <typename U, typename... Args,
@@ -959,13 +960,6 @@ class [[nodiscard]] ReturnAction final {
template <typename U>
class Impl final {
public:
// The constructor used when the return value is allowed to move from the
// input value (i.e. we are converting to OnceAction).
explicit Impl(R&& input_value)
: state_(new State(std::move(input_value))) {}
// The constructor used when the return value is not allowed to move from
// the input value (i.e. we are converting to Action).
explicit Impl(const R& input_value) : state_(new State(input_value)) {}
U operator()() && { return std::move(state_->value); }
@@ -996,18 +990,6 @@ class [[nodiscard]] ReturnAction final {
// explicit constructor from R.
value(ImplicitCast_<U>(internal::as_const(input_value))) {}
// As above, but for the case where we're moving from the ReturnAction
// object because it's being used as a OnceAction.
explicit State(R&& input_value_in)
: input_value(std::move(input_value_in)),
// For the same reason as above we make an implicit conversion to U
// before initializing the value.
//
// Unlike above we provide the input value as an rvalue to the
// implicit conversion because this is a OnceAction: it's fine if it
// wants to consume the input value.
value(ImplicitCast_<U>(std::move(input_value))) {}
// A copy of the value originally provided by the user. We retain this in
// addition to the value of the mock function's result type below in case
// the latter is a reference-like type. See the std::string_view example
@@ -1085,6 +1067,23 @@ class [[nodiscard]] ReturnAction final {
const std::shared_ptr<State> state_;
};
// Implements the Return(x) action for a mock function that returns type U,
// but is only executed at most once. This allows us to store the original
// value and move construct the return value type on the first (and only)
// call.
template <typename U>
class OnceImpl final {
public:
explicit OnceImpl(R&& input_value)
: input_value_(new R(std::move(input_value))) {}
U operator()() && { return std::move(*input_value_); }
private:
// Move the input value to the heap and make it copyable.
const std::shared_ptr<R> input_value_;
};
R value_;
};
@@ -111,16 +111,6 @@ inline Element* GetRawPointer(Element* p) {
#define GMOCK_INTERNAL_WARNING_POP() _Pragma("clang diagnostic pop")
#endif
// MSVC treats wchar_t as a native type usually, but treats it as the
// same as unsigned short when the compiler option /Zc:wchar_t- is
// specified. It defines _NATIVE_WCHAR_T_DEFINED symbol when wchar_t
// is a native type.
#if defined(_MSC_VER) && !defined(_NATIVE_WCHAR_T_DEFINED)
// wchar_t is a typedef.
#else
#define GMOCK_WCHAR_T_IS_NATIVE_ 1
#endif
// In what follows, we use the term "kind" to indicate whether a type
// is bool, an integer type (excluding bool), a floating-point type,
// or none of them. This categorization is useful for determining
@@ -156,7 +146,7 @@ GMOCK_DECLARE_KIND_(unsigned long, kInteger); // NOLINT
GMOCK_DECLARE_KIND_(long long, kInteger); // NOLINT
GMOCK_DECLARE_KIND_(unsigned long long, kInteger); // NOLINT
#if GMOCK_WCHAR_T_IS_NATIVE_
#if GTEST_HAS_NATIVE_WCHAR
GMOCK_DECLARE_KIND_(wchar_t, kInteger);
#endif
+4 -6
View File
@@ -270,7 +270,7 @@ TEST(BuiltInDefaultValueTest, IsZeroForNumericTypes) {
EXPECT_EQ(0U, BuiltInDefaultValue<unsigned char>::Get());
EXPECT_EQ(0, BuiltInDefaultValue<signed char>::Get());
EXPECT_EQ(0, BuiltInDefaultValue<char>::Get());
#if GMOCK_WCHAR_T_IS_NATIVE_
#if GTEST_HAS_NATIVE_WCHAR
#if !defined(__WCHAR_UNSIGNED__)
EXPECT_EQ(0, BuiltInDefaultValue<wchar_t>::Get());
#else
@@ -299,7 +299,7 @@ TEST(BuiltInDefaultValueTest, ExistsForNumericTypes) {
EXPECT_TRUE(BuiltInDefaultValue<unsigned char>::Exists());
EXPECT_TRUE(BuiltInDefaultValue<signed char>::Exists());
EXPECT_TRUE(BuiltInDefaultValue<char>::Exists());
#if GMOCK_WCHAR_T_IS_NATIVE_
#if GTEST_HAS_NATIVE_WCHAR
EXPECT_TRUE(BuiltInDefaultValue<wchar_t>::Exists());
#endif
EXPECT_TRUE(BuiltInDefaultValue<unsigned short>::Exists()); // NOLINT
@@ -1101,6 +1101,7 @@ TEST(SetArgPointeeTest, AcceptsStringLiteral) {
EXPECT_STREQ("world", ptr);
}
#if GTEST_HAS_STD_WSTRING
TEST(SetArgPointeeTest, AcceptsWideStringLiteral) {
typedef void MyFunction(const wchar_t**);
Action<MyFunction> a = SetArgPointee<0>(L"world");
@@ -1108,16 +1109,13 @@ TEST(SetArgPointeeTest, AcceptsWideStringLiteral) {
a.Perform(std::make_tuple(&ptr));
EXPECT_STREQ(L"world", ptr);
#if GTEST_HAS_STD_WSTRING
typedef void MyStringFunction(std::wstring*);
Action<MyStringFunction> a2 = SetArgPointee<0>(L"world");
std::wstring str = L"";
a2.Perform(std::make_tuple(&str));
EXPECT_EQ(L"world", str);
#endif
}
#endif
// Tests that SetArgPointee<N>() accepts a char pointer.
TEST(SetArgPointeeTest, AcceptsCharPointer) {
+6 -3
View File
@@ -87,10 +87,10 @@ TEST(InitGoogleMockTest, ParsesSingleFlag) {
TEST(InitGoogleMockTest, ParsesMultipleFlags) {
int old_default_behavior = GMOCK_FLAG_GET(default_mock_behavior);
const wchar_t* argv[] = {L"foo.exe", L"--gmock_verbose=info",
L"--gmock_default_mock_behavior=2", nullptr};
const char* argv[] = {"foo.exe", "--gmock_verbose=info",
"--gmock_default_mock_behavior=2", nullptr};
const wchar_t* new_argv[] = {L"foo.exe", nullptr};
const char* new_argv[] = {"foo.exe", nullptr};
TestInitGoogleMock(argv, new_argv, "info");
EXPECT_EQ(2, GMOCK_FLAG_GET(default_mock_behavior));
@@ -115,6 +115,8 @@ TEST(InitGoogleMockTest, ParsesGoogleMockFlagAndUnrecognizedFlag) {
TestInitGoogleMock(argv, new_argv, "error");
}
#if GTEST_HAS_STD_WSTRING
TEST(WideInitGoogleMockTest, ParsesInvalidCommandLine) {
const wchar_t* argv[] = {nullptr};
@@ -168,6 +170,7 @@ TEST(WideInitGoogleMockTest, ParsesGoogleMockFlagAndUnrecognizedFlag) {
TestInitGoogleMock(argv, new_argv, "error");
}
#endif // GTEST_HAS_STD_WSTRING
#endif // !defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
+1 -1
View File
@@ -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.17.0
git clone https://github.com/google/googletest.git -b v1.18.0
cd googletest # Main directory of the cloned repository.
mkdir build # Create a directory to hold the build output.
cd build
+2 -2
View File
@@ -552,7 +552,7 @@ auto ConvertGenerator(Gen&& gen, Func&& f) {
#define INSTANTIATE_TEST_SUITE_P(prefix, test_suite_name, ...) \
static ::testing::internal::ParamGenerator<test_suite_name::ParamType> \
gtest_##prefix##test_suite_name##_EvalGenerator_() { \
gtest_##prefix##test_suite_name##_EvalGenerator_() { \
return GTEST_EXPAND_(GTEST_GET_FIRST_(__VA_ARGS__, DUMMY_PARAM_)); \
} \
static ::std::string gtest_##prefix##test_suite_name##_EvalGenerateName_( \
@@ -562,7 +562,7 @@ auto ConvertGenerator(Gen&& gen, Func&& f) {
__VA_ARGS__, \
::testing::internal::DefaultParamName<test_suite_name::ParamType>, \
DUMMY_PARAM_))); \
auto t = std::make_tuple(__VA_ARGS__); \
const auto t = std::make_tuple(__VA_ARGS__); \
static_assert(std::tuple_size<decltype(t)>::value <= 2, \
"Too Many Args!"); \
} \
+17 -23
View File
@@ -522,17 +522,14 @@ inline void PrintTo(bool x, ::std::ostream* os) {
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) {
// 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);
}
// Overloads for the UTF-8 and UTF-16 code unit types. A code unit that
// encodes a code point all by itself is printed with the U+XXXX notation;
// one that does not (any non-ASCII char8_t, and the UTF-16 surrogates) is
// printed as a code unit instead, the way wchar_t is.
GTEST_API_ void PrintTo(char16_t c, ::std::ostream* os);
#ifdef __cpp_lib_char8_t
inline void PrintTo(char8_t c, ::std::ostream* 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);
}
GTEST_API_ void PrintTo(char8_t c, ::std::ostream* os);
#endif
// gcc/clang __{u,}int128_t
@@ -674,12 +671,12 @@ inline void PrintTo(char32_t* s, ::std::ostream* os) {
PrintTo(ImplicitCast_<const char32_t*>(s), os);
}
// MSVC can be configured to define wchar_t as a typedef of unsigned
// short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native
// type. When wchar_t is a typedef, defining an overload for const
// wchar_t* would cause unsigned short* be printed as a wide string,
// possibly causing invalid memory accesses.
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
// Only add an overload for printing wchar_t* if:
// 1. Wide string support is enabled.
// 2. wchar_t is a distinct native type. (If it's a typedef, the overload could
// cause a pointer to the underlying type to be mistakenly treated as a
// string.)
#if GTEST_HAS_STD_WSTRING && GTEST_HAS_NATIVE_WCHAR
// Overloads for wide C strings
GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os);
inline void PrintTo(wchar_t* s, ::std::ostream* os) {
@@ -1173,15 +1170,12 @@ class [[nodiscard]] UniversalTersePrinter<const wchar_t*> {
}
}
};
#endif
template <>
class [[nodiscard]] UniversalTersePrinter<wchar_t*> {
public:
static void Print(wchar_t* str, ::std::ostream* os) {
UniversalTersePrinter<const wchar_t*>::Print(str, os);
}
};
class [[nodiscard]] UniversalTersePrinter<wchar_t*>
: public UniversalTersePrinter<const wchar_t*> {};
#endif // GTEST_HAS_STD_WSTRING
template <typename T>
void UniversalTersePrint(const T& value, ::std::ostream* os) {
+13 -9
View File
@@ -71,7 +71,7 @@
#include "gtest/gtest-typed-test.h" // IWYU pragma: export
#include "gtest/gtest_pred_impl.h" // IWYU pragma: export
#include "gtest/gtest_prod.h" // IWYU pragma: export
#include "gtest/internal/gtest-internal.h"
#include "gtest/internal/gtest-internal.h" // IWYU pragma: export
#include "gtest/internal/gtest-string.h"
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
@@ -1514,6 +1514,8 @@ GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
const char* s2_expression,
const char* s1, const char* s2);
#if GTEST_HAS_STD_WSTRING
// Helper function for *_STREQ on wide strings.
//
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
@@ -1528,6 +1530,8 @@ GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
const char* s2_expression,
const wchar_t* s1, const wchar_t* s2);
#endif // GTEST_HAS_STD_WSTRING
} // namespace internal
// IsSubstring() and IsNotSubstring() are intended to be used as the
@@ -1542,18 +1546,10 @@ GTEST_API_ AssertionResult IsSubstring(const char* needle_expr,
const char* haystack_expr,
const char* needle,
const char* haystack);
GTEST_API_ AssertionResult IsSubstring(const char* needle_expr,
const char* haystack_expr,
const wchar_t* needle,
const wchar_t* haystack);
GTEST_API_ AssertionResult IsNotSubstring(const char* needle_expr,
const char* haystack_expr,
const char* needle,
const char* haystack);
GTEST_API_ AssertionResult IsNotSubstring(const char* needle_expr,
const char* haystack_expr,
const wchar_t* needle,
const wchar_t* haystack);
GTEST_API_ AssertionResult IsSubstring(const char* needle_expr,
const char* haystack_expr,
const ::std::string& needle,
@@ -1564,6 +1560,14 @@ GTEST_API_ AssertionResult IsNotSubstring(const char* needle_expr,
const ::std::string& haystack);
#if GTEST_HAS_STD_WSTRING
GTEST_API_ AssertionResult IsSubstring(const char* needle_expr,
const char* haystack_expr,
const wchar_t* needle,
const wchar_t* haystack);
GTEST_API_ AssertionResult IsNotSubstring(const char* needle_expr,
const char* haystack_expr,
const wchar_t* needle,
const wchar_t* haystack);
GTEST_API_ AssertionResult IsSubstring(const char* needle_expr,
const char* haystack_expr,
const ::std::wstring& needle,
@@ -39,7 +39,7 @@
#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
#include "gtest/internal/gtest-port.h"
#include "gtest/internal/gtest-port.h" // IWYU pragma: export
#ifdef GTEST_OS_LINUX
#include <stdlib.h>
@@ -1516,8 +1516,9 @@ class [[nodiscard]] NeverThrown {
parent_class>::GetSetUpCaseOrSuite(__FILE__, __LINE__), \
::testing::internal::SuiteApiResolver< \
parent_class>::GetTearDownCaseOrSuite(__FILE__, __LINE__), \
new ::testing::internal::TestFactoryImpl<GTEST_TEST_CLASS_NAME_( \
test_suite_name, test_name)>); \
::std::make_unique<::testing::internal::TestFactoryImpl< \
GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)>>() \
.release()); \
void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody()
#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
+74 -14
View File
@@ -500,22 +500,82 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
#endif // defined(_MSC_VER) || defined(__BORLANDC__)
#endif // GTEST_HAS_EXCEPTIONS
#ifndef GTEST_HAS_STD_WSTRING
// The user didn't tell us whether ::std::wstring is available, so we need
// to figure it out.
// Cygwin 1.7 and below doesn't support ::std::wstring.
// Solaris' libc++ doesn't support it either. Android has
// no support for it at least as recent as Froyo (2.2).
#if (!(defined(GTEST_OS_LINUX_ANDROID) || defined(GTEST_OS_CYGWIN) || \
defined(GTEST_OS_SOLARIS) || defined(GTEST_OS_HAIKU) || \
defined(GTEST_OS_ESP32) || defined(GTEST_OS_ESP8266) || \
defined(GTEST_OS_XTENSA) || defined(GTEST_OS_QURT) || \
defined(GTEST_OS_NXP_QN9090) || defined(GTEST_OS_NRF52)))
#define GTEST_HAS_STD_WSTRING 1
// MSVC either defines wchar_t as a typedef of unsigned short, or as a native
// type (in which case, it defines _NATIVE_WCHAR_T_DEFINED). When wchar_t is a
// typedef, defining an overload for const wchar_t* would cause unsigned short*
// be printed as a wide string, possibly causing invalid memory accesses, so we
// omit wchar_t overloads in that case.
#if defined(_MSC_VER) && !defined(_NATIVE_WCHAR_T_DEFINED)
#define GTEST_HAS_NATIVE_WCHAR 0
#else
#define GTEST_HAS_STD_WSTRING 0
#define GTEST_HAS_NATIVE_WCHAR 1
#endif
// 1. Calculate default GTEST_HAS_STD_WSTRING values based on STL capabilities.
#if defined(_MSVC_STL_VERSION)
// Microsoft's STL implementation always supports ::std::wstring.
#define GTEST_HAS_STD_WSTRING_DEFAULT 1
#elif defined(_LIBCPP_VERSION)
// Modern libc++ always defines _LIBCPP_HAS_WIDE_CHARACTERS; its value
// determines whether wide characters are supported.
// Older libc++ omits a definition for _LIBCPP_HAS_NO_WIDE_CHARACTERS when wide
// characters are supported.
#if (defined(_LIBCPP_HAS_WIDE_CHARACTERS) && !_LIBCPP_HAS_WIDE_CHARACTERS) || \
defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS)
#define GTEST_HAS_STD_WSTRING_DEFAULT 0
#else
#define GTEST_HAS_STD_WSTRING_DEFAULT 1
#endif
#elif defined(__GLIBCXX__)
#if defined(_GLIBCXX_USE_WCHAR_T) && _GLIBCXX_USE_WCHAR_T
#define GTEST_HAS_STD_WSTRING_DEFAULT 1
#else
#define GTEST_HAS_STD_WSTRING_DEFAULT 0
#endif
#else
// Unknown standard library implementation; fall back looking at the OS.
//
// Always let the user override the defaults in this case; they might have more
// information about what's supported than we do.
#if defined(GTEST_OS_LINUX_ANDROID)
// Android started supporting std::wstring with API Level 21 (Lollipop).
#define GTEST_HAS_STD_WSTRING_DEFAULT (__ANDROID_API__ >= 21)
// The following platforms are known not to support ::std::wstring; assume it's
// supported on all others.
//
// Cygwin 1.7 and below doesn't support ::std::wstring.
// Solaris' libc++ doesn't support it either.
#elif defined(GTEST_OS_CYGWIN) || defined(GTEST_OS_SOLARIS) || \
defined(GTEST_OS_HAIKU) || defined(GTEST_OS_ESP32) || \
defined(GTEST_OS_ESP8266) || defined(GTEST_OS_XTENSA) || \
defined(GTEST_OS_QURT) || defined(GTEST_OS_NXP_QN9090) || \
defined(GTEST_OS_NRF52)
#define GTEST_HAS_STD_WSTRING_DEFAULT 0
#else
#define GTEST_HAS_STD_WSTRING_DEFAULT 1
#endif
#endif
// 2. Validate explicit user overrides (if user passed -DGTEST_HAS_*=1) against
// what the standard library implementation tells us it supports.
#if defined(GTEST_HAS_STD_WSTRING) && GTEST_HAS_STD_WSTRING
#if defined(_LIBCPP_VERSION) && \
((defined(_LIBCPP_HAS_WIDE_CHARACTERS) && !_LIBCPP_HAS_WIDE_CHARACTERS) || \
defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS))
#error Cannot explicitly enable GTEST_HAS_STD_WSTRING without libc++ wide character support.
#elif defined(__GLIBCXX__) && \
!(defined(_GLIBCXX_USE_WCHAR_T) && _GLIBCXX_USE_WCHAR_T)
#error Cannot explicitly enable GTEST_HAS_STD_WSTRING without libstdc++ wide character support.
#endif
#endif
// 3. Set final values if not explicitly overridden by user
#if !defined(GTEST_HAS_STD_WSTRING)
#define GTEST_HAS_STD_WSTRING GTEST_HAS_STD_WSTRING_DEFAULT
#endif
#endif // GTEST_HAS_STD_WSTRING
#ifndef GTEST_HAS_FILE_SYSTEM
// Most platforms support a file system.
+48 -10
View File
@@ -50,6 +50,7 @@
#include <iomanip>
#include <ios>
#include <ostream> // NOLINT
#include <string>
#include <string_view>
#include <type_traits>
@@ -285,6 +286,28 @@ void PrintTo(char32_t c, ::std::ostream* os) {
<< static_cast<uint32_t>(c);
}
// char8_t and char16_t hold code units, not code points, so the U+XXXX
// notation only applies to the values that encode a code point on their own.
// The rest -- non-ASCII char8_t, which are always part of a multi-unit UTF-8
// sequence, and the UTF-16 surrogates -- are printed as code units.
void PrintTo(char16_t c, ::std::ostream* os) {
if (c >= 0xD800 && c <= 0xDFFF) {
PrintCharAndCodeTo(c, os);
} else {
PrintTo(static_cast<char32_t>(c), os);
}
}
#ifdef __cpp_lib_char8_t
void PrintTo(char8_t c, ::std::ostream* os) {
if (c >= 0x80) {
PrintCharAndCodeTo(c, os);
} else {
PrintTo(static_cast<char32_t>(c), os);
}
}
#endif
// gcc/clang __{u,}int128_t
#if defined(__SIZEOF_INT128__)
void PrintTo(__uint128_t v, ::std::ostream* os) {
@@ -422,6 +445,28 @@ void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) {
namespace {
template <typename Char>
size_t GetLength(const Char* s) {
return std::char_traits<Char>::length(s);
}
#if !GTEST_HAS_STD_WSTRING
// If GTEST_HAS_STD_WSTRING is unset because the standard library has disabled
// wide character support, std::char_traits<wchar_t> won't be defined, which
// will cause a compile error, even if user code never actually could print a
// wide cstring. In that case, instead use `wcslen` directly.
//
// If `libc` _also_ lacks wide character support, this (and a bunch of other
// calls to wc functions) will fail to link, but only if user code actually
// uses them.
template <>
size_t GetLength<wchar_t>(const wchar_t* s) {
return wcslen(s);
}
#endif // GTEST_HAS_STD_WSTRING
// Prints a null-terminated C-style string to the ostream.
template <typename Char>
void PrintCStringTo(const Char* s, ostream* os) {
@@ -429,7 +474,7 @@ void PrintCStringTo(const Char* s, ostream* os) {
*os << "NULL";
} else {
*os << ImplicitCast_<const void*>(s) << " pointing to ";
PrintCharsAsStringTo(s, std::char_traits<Char>::length(s), os);
PrintCharsAsStringTo(s, GetLength(s), os);
}
}
@@ -445,16 +490,9 @@ void PrintTo(const char16_t* s, ostream* os) { PrintCStringTo(s, os); }
void PrintTo(const char32_t* s, ostream* os) { PrintCStringTo(s, os); }
// MSVC compiler can be configured to define whar_t as a typedef
// of unsigned short. Defining an overload for const wchar_t* in that case
// would cause pointers to unsigned shorts be printed as wide strings,
// possibly accessing more memory than intended and causing invalid
// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
// wchar_t is implemented as a native type.
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
// Prints the given wide C string to the ostream.
#if GTEST_HAS_STD_WSTRING && GTEST_HAS_NATIVE_WCHAR
void PrintTo(const wchar_t* s, ostream* os) { PrintCStringTo(s, os); }
#endif // wchar_t is native
#endif
namespace {
+15 -11
View File
@@ -1876,11 +1876,13 @@ bool IsSubstringPred(const char* needle, const char* haystack) {
return strstr(haystack, needle) != nullptr;
}
#if GTEST_HAS_STD_WSTRING
bool IsSubstringPred(const wchar_t* needle, const wchar_t* haystack) {
if (needle == nullptr || haystack == nullptr) return needle == haystack;
return wcsstr(haystack, needle) != nullptr;
}
#endif // GTEST_HAS_STD_WSTRING
// StringType here can be either ::std::string or ::std::wstring.
template <typename StringType>
@@ -1922,23 +1924,12 @@ AssertionResult IsSubstring(const char* needle_expr, const char* haystack_expr,
return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
}
AssertionResult IsSubstring(const char* needle_expr, const char* haystack_expr,
const wchar_t* needle, const wchar_t* haystack) {
return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
}
AssertionResult IsNotSubstring(const char* needle_expr,
const char* haystack_expr, const char* needle,
const char* haystack) {
return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
}
AssertionResult IsNotSubstring(const char* needle_expr,
const char* haystack_expr, const wchar_t* needle,
const wchar_t* haystack) {
return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
}
AssertionResult IsSubstring(const char* needle_expr, const char* haystack_expr,
const ::std::string& needle,
const ::std::string& haystack) {
@@ -1953,6 +1944,17 @@ AssertionResult IsNotSubstring(const char* needle_expr,
}
#if GTEST_HAS_STD_WSTRING
AssertionResult IsSubstring(const char* needle_expr, const char* haystack_expr,
const wchar_t* needle, const wchar_t* haystack) {
return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
}
AssertionResult IsNotSubstring(const char* needle_expr,
const char* haystack_expr, const wchar_t* needle,
const wchar_t* haystack) {
return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
}
AssertionResult IsSubstring(const char* needle_expr, const char* haystack_expr,
const ::std::wstring& needle,
const ::std::wstring& haystack) {
@@ -2182,6 +2184,7 @@ bool String::WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs) {
return wcscmp(lhs, rhs) == 0;
}
#if GTEST_HAS_STD_WSTRING
// Helper function for *_STREQ on wide strings.
AssertionResult CmpHelperSTREQ(const char* lhs_expression,
const char* rhs_expression, const wchar_t* lhs,
@@ -2206,6 +2209,7 @@ AssertionResult CmpHelperSTRNE(const char* s1_expression,
<< "Expected: (" << s1_expression << ") != (" << s2_expression
<< "), actual: " << PrintToString(s1) << " vs " << PrintToString(s2);
}
#endif // GTEST_HAS_STD_WSTRING
// Compares two C strings, ignoring case. Returns true if and only if they have
// the same content.
+19 -11
View File
@@ -396,12 +396,24 @@ TEST(PrintCharTest, UnsignedChar) {
EXPECT_EQ("'b' (98, 0x62)", Print(static_cast<unsigned char>('b')));
}
TEST(PrintCharTest, Char16) { EXPECT_EQ("U+0041", Print(u'A')); }
TEST(PrintCharTest, Char16) {
EXPECT_EQ("U+0041", Print(u'A'));
EXPECT_EQ("U+754C", Print(u''));
// Surrogates are not code points, so they are printed as code units.
EXPECT_EQ("u'\\xD800' (55296)", Print(static_cast<char16_t>(0xD800)));
EXPECT_EQ("u'\\xDFFF' (57343)", Print(static_cast<char16_t>(0xDFFF)));
}
TEST(PrintCharTest, Char32) { EXPECT_EQ("U+0041", Print(U'A')); }
#ifdef __cpp_lib_char8_t
TEST(PrintCharTest, Char8) { EXPECT_EQ("U+0041", Print(u8'A')); }
TEST(PrintCharTest, Char8) {
EXPECT_EQ("U+0041", Print(u8'A'));
// Only ASCII code units encode a code point on their own; the rest are
// printed as code units.
EXPECT_EQ("u8'\\x80' (128)", Print(static_cast<char8_t>(0x80)));
EXPECT_EQ("u8'\\xFF' (255)", Print(static_cast<char8_t>(0xFF)));
}
#endif
// Tests printing other simple, built-in types.
@@ -456,7 +468,7 @@ TEST(PrintBuiltInTypeTest, Integer) {
#ifdef __cpp_lib_char8_t
EXPECT_EQ("U+0000",
Print(std::numeric_limits<char8_t>::min())); // char8_t
EXPECT_EQ("U+00FF",
EXPECT_EQ("u8'\\xFF' (255)",
Print(std::numeric_limits<char8_t>::max())); // char8_t
#endif
EXPECT_EQ("U+0000",
@@ -648,13 +660,8 @@ TEST(PrintU32StringTest, EscapesProperly) {
Print(p));
}
// MSVC compiler can be configured to define whar_t as a typedef
// of unsigned short. Defining an overload for const wchar_t* in that case
// would cause pointers to unsigned shorts be printed as wide strings,
// possibly accessing more memory than intended and causing invalid
// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
// wchar_t is implemented as a native type.
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
#if GTEST_HAS_NATIVE_WCHAR
#if GTEST_HAS_STD_WSTRING
// const wchar_t*.
TEST(PrintWideCStringTest, Const) {
@@ -685,7 +692,8 @@ TEST(PrintWideCStringTest, EscapesProperly) {
"\\n\\r\\t\\v\\xD3\\x576\\x8D3\\xC74D a\"",
Print(static_cast<const wchar_t*>(s)));
}
#endif // native wchar_t
#endif // GTEST_HAS_STD_WSTRING
#endif // GTEST_HAS_NATIVE_WCHAR
// Tests printing pointers to other char types.
+33 -31
View File
@@ -2564,6 +2564,7 @@ TEST(StringAssertionTest, ASSERT_STRCASENE) {
EXPECT_FATAL_FAILURE(ASSERT_STRCASENE("Hi", "hi"), "(ignoring case)");
}
#if GTEST_HAS_STD_WSTRING
// Tests *_STREQ on wide strings.
TEST(StringAssertionTest, STREQ_Wide) {
// NULL strings.
@@ -2619,6 +2620,7 @@ TEST(StringAssertionTest, STRNE_Wide) {
// The streaming variation.
ASSERT_STRNE(L"abc\x8119", L"abc\x8120") << "This shouldn't happen";
}
#endif // GTEST_HAS_STD_WSTRING
// Tests for ::testing::IsSubstring().
@@ -2633,18 +2635,6 @@ TEST(IsSubstringTest, ReturnsCorrectResultForCString) {
EXPECT_TRUE(IsSubstring("", "", "needle", "two needles"));
}
// Tests that IsSubstring() returns the correct result when the input
// argument type is const wchar_t*.
TEST(IsSubstringTest, ReturnsCorrectResultForWideCString) {
EXPECT_FALSE(IsSubstring("", "", kNull, L"a"));
EXPECT_FALSE(IsSubstring("", "", L"b", kNull));
EXPECT_FALSE(IsSubstring("", "", L"needle", L"haystack"));
EXPECT_TRUE(
IsSubstring("", "", static_cast<const wchar_t*>(nullptr), nullptr));
EXPECT_TRUE(IsSubstring("", "", L"needle", L"two needles"));
}
// Tests that IsSubstring() generates the correct message when the input
// argument type is const char*.
TEST(IsSubstringTest, GeneratesCorrectMessageForCString) {
@@ -2665,6 +2655,18 @@ TEST(IsSubstringTest, ReturnsCorrectResultsForStdString) {
}
#if GTEST_HAS_STD_WSTRING
// Tests that IsSubstring() returns the correct result when the input
// argument type is const wchar_t*.
TEST(IsSubstringTest, ReturnsCorrectResultForWideCString) {
EXPECT_FALSE(IsSubstring("", "", kNull, L"a"));
EXPECT_FALSE(IsSubstring("", "", L"b", kNull));
EXPECT_FALSE(IsSubstring("", "", L"needle", L"haystack"));
EXPECT_TRUE(
IsSubstring("", "", static_cast<const wchar_t*>(nullptr), nullptr));
EXPECT_TRUE(IsSubstring("", "", L"needle", L"two needles"));
}
// Tests that IsSubstring returns the correct result when the input
// argument type is ::std::wstring.
TEST(IsSubstringTest, ReturnsCorrectResultForStdWstring) {
@@ -2696,25 +2698,6 @@ TEST(IsNotSubstringTest, ReturnsCorrectResultForCString) {
EXPECT_FALSE(IsNotSubstring("", "", "needle", "two needles"));
}
// Tests that IsNotSubstring() returns the correct result when the input
// argument type is const wchar_t*.
TEST(IsNotSubstringTest, ReturnsCorrectResultForWideCString) {
EXPECT_TRUE(IsNotSubstring("", "", L"needle", L"haystack"));
EXPECT_FALSE(IsNotSubstring("", "", L"needle", L"two needles"));
}
// Tests that IsNotSubstring() generates the correct message when the input
// argument type is const wchar_t*.
TEST(IsNotSubstringTest, GeneratesCorrectMessageForWideCString) {
EXPECT_STREQ(
"Value of: needle_expr\n"
" Actual: L\"needle\"\n"
"Expected: not a substring of haystack_expr\n"
"Which is: L\"two needles\"",
IsNotSubstring("needle_expr", "haystack_expr", L"needle", L"two needles")
.failure_message());
}
// Tests that IsNotSubstring returns the correct result when the input
// argument type is ::std::string.
TEST(IsNotSubstringTest, ReturnsCorrectResultsForStdString) {
@@ -2736,6 +2719,25 @@ TEST(IsNotSubstringTest, GeneratesCorrectMessageForStdString) {
#if GTEST_HAS_STD_WSTRING
// Tests that IsNotSubstring() returns the correct result when the input
// argument type is const wchar_t*.
TEST(IsNotSubstringTest, ReturnsCorrectResultForWideCString) {
EXPECT_TRUE(IsNotSubstring("", "", L"needle", L"haystack"));
EXPECT_FALSE(IsNotSubstring("", "", L"needle", L"two needles"));
}
// Tests that IsNotSubstring() generates the correct message when the input
// argument type is const wchar_t*.
TEST(IsNotSubstringTest, GeneratesCorrectMessageForWideCString) {
EXPECT_STREQ(
"Value of: needle_expr\n"
" Actual: L\"needle\"\n"
"Expected: not a substring of haystack_expr\n"
"Which is: L\"two needles\"",
IsNotSubstring("needle_expr", "haystack_expr", L"needle", L"two needles")
.failure_message());
}
// Tests that IsNotSubstring returns the correct result when the input
// argument type is ::std::wstring.
TEST(IsNotSubstringTest, ReturnsCorrectResultForStdWstring) {