3rdparty: Update googletest to v1.15.2

This commit is contained in:
JordanTheToaster 2024-12-06 22:18:32 +00:00 committed by Ty
parent ba36d4b0c8
commit 2cb311dd24
32 changed files with 904 additions and 684 deletions

View File

@ -9,7 +9,7 @@ GoogleTest now follows the
We recommend 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). [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 We do publish occasional semantic versions, tagged with
`v${major}.${minor}.${patch}` (e.g. `v1.13.0`). `v${major}.${minor}.${patch}` (e.g. `v1.15.0`).
#### Documentation Updates #### Documentation Updates
@ -17,25 +17,21 @@ Our documentation is now live on GitHub Pages at
https://google.github.io/googletest/. We recommend browsing the documentation on https://google.github.io/googletest/. We recommend browsing the documentation on
GitHub Pages rather than directly in the repository. GitHub Pages rather than directly in the repository.
#### Release 1.13.0 #### Release 1.15.0
[Release 1.13.0](https://github.com/google/googletest/releases/tag/v1.13.0) is [Release 1.15.0](https://github.com/google/googletest/releases/tag/v1.15.0) is
now available. now available.
The 1.13.x branch requires at least C++14. The 1.15.x branch requires at least C++14.
#### Continuous Integration #### Continuous Integration
We use Google's internal systems for continuous integration. \ We use Google's internal systems for continuous integration.
GitHub Actions were added for the convenience of open-source contributors. They
are exclusively maintained by the open-source community and not used by the
GoogleTest team.
#### Coming Soon #### Coming Soon
* We are planning to take a dependency on * We are planning to take a dependency on
[Abseil](https://github.com/abseil/abseil-cpp). [Abseil](https://github.com/abseil/abseil-cpp).
* More documentation improvements are planned.
## Welcome to **GoogleTest**, Google's C++ test framework! ## Welcome to **GoogleTest**, Google's C++ test framework!
@ -100,12 +96,12 @@ tools.
In addition to many internal projects at Google, GoogleTest is also used by the In addition to many internal projects at Google, GoogleTest is also used by the
following notable projects: following notable projects:
* The [Chromium projects](http://www.chromium.org/) (behind the Chrome browser * The [Chromium projects](https://www.chromium.org/) (behind the Chrome
and Chrome OS). browser and Chrome OS).
* The [LLVM](http://llvm.org/) compiler. * The [LLVM](https://llvm.org/) compiler.
* [Protocol Buffers](https://github.com/google/protobuf), Google's data * [Protocol Buffers](https://github.com/google/protobuf), Google's data
interchange format. interchange format.
* The [OpenCV](http://opencv.org/) computer vision library. * The [OpenCV](https://opencv.org/) computer vision library.
## Related Open Source Projects ## Related Open Source Projects

View File

@ -8,8 +8,8 @@ derive better designs of your system and write better tests.
It is inspired by: It is inspired by:
* [jMock](http://www.jmock.org/) * [jMock](http://www.jmock.org/)
* [EasyMock](http://www.easymock.org/) * [EasyMock](https://easymock.org/)
* [Hamcrest](http://code.google.com/p/hamcrest/) * [Hamcrest](https://code.google.com/p/hamcrest/)
It is designed with C++'s specifics in mind. It is designed with C++'s specifics in mind.
@ -36,5 +36,5 @@ Details and examples can be found here:
* [gMock Cheat Sheet](https://google.github.io/googletest/gmock_cheat_sheet.html) * [gMock Cheat Sheet](https://google.github.io/googletest/gmock_cheat_sheet.html)
GoogleMock is a part of GoogleMock is a part of
[GoogleTest C++ testing framework](http://github.com/google/googletest/) and a [GoogleTest C++ testing framework](https://github.com/google/googletest/) and a
subject to the same requirements. subject to the same requirements.

View File

@ -135,6 +135,7 @@
#endif #endif
#include <algorithm> #include <algorithm>
#include <exception>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <string> #include <string>
@ -175,9 +176,15 @@ struct BuiltInDefaultValueGetter<T, false> {
static T Get() { static T Get() {
Assert(false, __FILE__, __LINE__, Assert(false, __FILE__, __LINE__,
"Default action undefined for the function return type."); "Default action undefined for the function return type.");
return internal::Invalid<T>(); #if defined(__GNUC__) || defined(__clang__)
__builtin_unreachable();
#elif defined(_MSC_VER)
__assume(0);
#else
return Invalid<T>();
// The above statement will never be reached, but is required in // The above statement will never be reached, but is required in
// order for this function to compile. // order for this function to compile.
#endif
} }
}; };
@ -1740,6 +1747,13 @@ struct ThrowAction {
return [copy](Args...) -> R { throw copy; }; return [copy](Args...) -> R { throw copy; };
} }
}; };
struct RethrowAction {
std::exception_ptr exception;
template <typename R, typename... Args>
operator Action<R(Args...)>() const { // NOLINT
return [ex = exception](Args...) -> R { std::rethrow_exception(ex); };
}
};
#endif // GTEST_HAS_EXCEPTIONS #endif // GTEST_HAS_EXCEPTIONS
} // namespace internal } // namespace internal
@ -2056,13 +2070,23 @@ internal::ReturnPointeeAction<Ptr> ReturnPointee(Ptr pointer) {
return {pointer}; return {pointer};
} }
// Action Throw(exception) can be used in a mock function of any type
// to throw the given exception. Any copyable value can be thrown.
#if GTEST_HAS_EXCEPTIONS #if GTEST_HAS_EXCEPTIONS
// Action Throw(exception) can be used in a mock function of any type
// to throw the given exception. Any copyable value can be thrown,
// except for std::exception_ptr, which is likely a mistake if
// thrown directly.
template <typename T> template <typename T>
internal::ThrowAction<typename std::decay<T>::type> Throw(T&& exception) { typename std::enable_if<
!std::is_base_of<std::exception_ptr, typename std::decay<T>::type>::value,
internal::ThrowAction<typename std::decay<T>::type>>::type
Throw(T&& exception) {
return {std::forward<T>(exception)}; return {std::forward<T>(exception)};
} }
// Action Rethrow(exception_ptr) can be used in a mock function of any type
// to rethrow any exception_ptr. Note that the same object is thrown each time.
inline internal::RethrowAction Rethrow(std::exception_ptr exception) {
return {std::move(exception)};
}
#endif // GTEST_HAS_EXCEPTIONS #endif // GTEST_HAS_EXCEPTIONS
namespace internal { namespace internal {
@ -2111,13 +2135,13 @@ struct ActionImpl<R(Args...), Impl> : ImplBase<Impl>::type {
R operator()(Args&&... arg) const { R operator()(Args&&... arg) const {
static constexpr size_t kMaxArgs = static constexpr size_t kMaxArgs =
sizeof...(Args) <= 10 ? sizeof...(Args) : 10; sizeof...(Args) <= 10 ? sizeof...(Args) : 10;
return Apply(MakeIndexSequence<kMaxArgs>{}, return Apply(std::make_index_sequence<kMaxArgs>{},
MakeIndexSequence<10 - kMaxArgs>{}, std::make_index_sequence<10 - kMaxArgs>{},
args_type{std::forward<Args>(arg)...}); args_type{std::forward<Args>(arg)...});
} }
template <std::size_t... arg_id, std::size_t... excess_id> template <std::size_t... arg_id, std::size_t... excess_id>
R Apply(IndexSequence<arg_id...>, IndexSequence<excess_id...>, R Apply(std::index_sequence<arg_id...>, std::index_sequence<excess_id...>,
const args_type& args) const { const args_type& args) const {
// Impl need not be specific to the signature of action being implemented; // Impl need not be specific to the signature of action being implemented;
// only the implementing function body needs to have all of the specific // only the implementing function body needs to have all of the specific
@ -2150,9 +2174,9 @@ template <typename F, typename Impl>
} }
#define GMOCK_INTERNAL_ARG_UNUSED(i, data, el) \ #define GMOCK_INTERNAL_ARG_UNUSED(i, data, el) \
, const arg##i##_type& arg##i GTEST_ATTRIBUTE_UNUSED_ , GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED const arg##i##_type& arg##i
#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_ \ #define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_ \
const args_type& args GTEST_ATTRIBUTE_UNUSED_ GMOCK_PP_REPEAT( \ GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED const args_type& args GMOCK_PP_REPEAT( \
GMOCK_INTERNAL_ARG_UNUSED, , 10) GMOCK_INTERNAL_ARG_UNUSED, , 10)
#define GMOCK_INTERNAL_ARG(i, data, el) , const arg##i##_type& arg##i #define GMOCK_INTERNAL_ARG(i, data, el) , const arg##i##_type& arg##i

View File

@ -37,6 +37,7 @@
#ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_FUNCTION_MOCKER_H_ #ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_FUNCTION_MOCKER_H_
#define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_FUNCTION_MOCKER_H_ #define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_FUNCTION_MOCKER_H_
#include <cstddef>
#include <type_traits> // IWYU pragma: keep #include <type_traits> // IWYU pragma: keep
#include <utility> // IWYU pragma: keep #include <utility> // IWYU pragma: keep
@ -69,22 +70,22 @@ constexpr bool PrefixOf(const char* a, const char* b) {
return *a == 0 || (*a == *b && internal::PrefixOf(a + 1, b + 1)); return *a == 0 || (*a == *b && internal::PrefixOf(a + 1, b + 1));
} }
template <int N, int M> template <size_t N, size_t M>
constexpr bool StartsWith(const char (&prefix)[N], const char (&str)[M]) { constexpr bool StartsWith(const char (&prefix)[N], const char (&str)[M]) {
return N <= M && internal::PrefixOf(prefix, str); return N <= M && internal::PrefixOf(prefix, str);
} }
template <int N, int M> template <size_t N, size_t M>
constexpr bool EndsWith(const char (&suffix)[N], const char (&str)[M]) { constexpr bool EndsWith(const char (&suffix)[N], const char (&str)[M]) {
return N <= M && internal::PrefixOf(suffix, str + M - N); return N <= M && internal::PrefixOf(suffix, str + M - N);
} }
template <int N, int M> template <size_t N, size_t M>
constexpr bool Equals(const char (&a)[N], const char (&b)[M]) { constexpr bool Equals(const char (&a)[N], const char (&b)[M]) {
return N == M && internal::PrefixOf(a, b); return N == M && internal::PrefixOf(a, b);
} }
template <int N> template <size_t N>
constexpr bool ValidateSpec(const char (&spec)[N]) { constexpr bool ValidateSpec(const char (&spec)[N]) {
return internal::Equals("const", spec) || return internal::Equals("const", spec) ||
internal::Equals("override", spec) || internal::Equals("override", spec) ||

View File

@ -490,12 +490,12 @@ class MatcherBaseImpl<Derived<Ts...>> {
template <typename F> template <typename F>
operator ::testing::Matcher<F>() const { // NOLINT(runtime/explicit) operator ::testing::Matcher<F>() const { // NOLINT(runtime/explicit)
return Apply<F>(MakeIndexSequence<sizeof...(Ts)>{}); return Apply<F>(std::make_index_sequence<sizeof...(Ts)>{});
} }
private: private:
template <typename F, std::size_t... tuple_ids> template <typename F, std::size_t... tuple_ids>
::testing::Matcher<F> Apply(IndexSequence<tuple_ids...>) const { ::testing::Matcher<F> Apply(std::index_sequence<tuple_ids...>) const {
return ::testing::Matcher<F>( return ::testing::Matcher<F>(
new typename Derived<Ts...>::template gmock_Impl<F>( new typename Derived<Ts...>::template gmock_Impl<F>(
std::get<tuple_ids>(params_)...)); std::get<tuple_ids>(params_)...));
@ -1048,7 +1048,7 @@ class StartsWithMatcher {
template <typename MatcheeStringType> template <typename MatcheeStringType>
bool MatchAndExplain(const MatcheeStringType& s, bool MatchAndExplain(const MatcheeStringType& s,
MatchResultListener* /* listener */) const { MatchResultListener* /* listener */) const {
const StringType& s2(s); const StringType s2(s);
return s2.length() >= prefix_.length() && return s2.length() >= prefix_.length() &&
s2.substr(0, prefix_.length()) == prefix_; s2.substr(0, prefix_.length()) == prefix_;
} }
@ -1102,7 +1102,7 @@ class EndsWithMatcher {
template <typename MatcheeStringType> template <typename MatcheeStringType>
bool MatchAndExplain(const MatcheeStringType& s, bool MatchAndExplain(const MatcheeStringType& s,
MatchResultListener* /* listener */) const { MatchResultListener* /* listener */) const {
const StringType& s2(s); const StringType s2(s);
return s2.length() >= suffix_.length() && return s2.length() >= suffix_.length() &&
s2.substr(s2.length() - suffix_.length()) == suffix_; s2.substr(s2.length() - suffix_.length()) == suffix_;
} }
@ -2920,26 +2920,27 @@ class EachMatcher {
const M inner_matcher_; const M inner_matcher_;
}; };
struct Rank1 {}; // Use go/ranked-overloads for dispatching.
struct Rank0 : Rank1 {}; struct Rank0 {};
struct Rank1 : Rank0 {};
namespace pair_getters { namespace pair_getters {
using std::get; using std::get;
template <typename T> template <typename T>
auto First(T& x, Rank1) -> decltype(get<0>(x)) { // NOLINT auto First(T& x, Rank0) -> decltype(get<0>(x)) { // NOLINT
return get<0>(x); return get<0>(x);
} }
template <typename T> template <typename T>
auto First(T& x, Rank0) -> decltype((x.first)) { // NOLINT auto First(T& x, Rank1) -> decltype((x.first)) { // NOLINT
return x.first; return x.first;
} }
template <typename T> template <typename T>
auto Second(T& x, Rank1) -> decltype(get<1>(x)) { // NOLINT auto Second(T& x, Rank0) -> decltype(get<1>(x)) { // NOLINT
return get<1>(x); return get<1>(x);
} }
template <typename T> template <typename T>
auto Second(T& x, Rank0) -> decltype((x.second)) { // NOLINT auto Second(T& x, Rank1) -> decltype((x.second)) { // NOLINT
return x.second; return x.second;
} }
} // namespace pair_getters } // namespace pair_getters
@ -2965,7 +2966,7 @@ class KeyMatcherImpl : public MatcherInterface<PairType> {
MatchResultListener* listener) const override { MatchResultListener* listener) const override {
StringMatchResultListener inner_listener; StringMatchResultListener inner_listener;
const bool match = inner_matcher_.MatchAndExplain( const bool match = inner_matcher_.MatchAndExplain(
pair_getters::First(key_value, Rank0()), &inner_listener); pair_getters::First(key_value, Rank1()), &inner_listener);
const std::string explanation = inner_listener.str(); const std::string explanation = inner_listener.str();
if (!explanation.empty()) { if (!explanation.empty()) {
*listener << "whose first field is a value " << explanation; *listener << "whose first field is a value " << explanation;
@ -3087,18 +3088,18 @@ class PairMatcherImpl : public MatcherInterface<PairType> {
if (!listener->IsInterested()) { if (!listener->IsInterested()) {
// If the listener is not interested, we don't need to construct the // If the listener is not interested, we don't need to construct the
// explanation. // explanation.
return first_matcher_.Matches(pair_getters::First(a_pair, Rank0())) && return first_matcher_.Matches(pair_getters::First(a_pair, Rank1())) &&
second_matcher_.Matches(pair_getters::Second(a_pair, Rank0())); second_matcher_.Matches(pair_getters::Second(a_pair, Rank1()));
} }
StringMatchResultListener first_inner_listener; StringMatchResultListener first_inner_listener;
if (!first_matcher_.MatchAndExplain(pair_getters::First(a_pair, Rank0()), if (!first_matcher_.MatchAndExplain(pair_getters::First(a_pair, Rank1()),
&first_inner_listener)) { &first_inner_listener)) {
*listener << "whose first field does not match"; *listener << "whose first field does not match";
PrintIfNotEmpty(first_inner_listener.str(), listener->stream()); PrintIfNotEmpty(first_inner_listener.str(), listener->stream());
return false; return false;
} }
StringMatchResultListener second_inner_listener; StringMatchResultListener second_inner_listener;
if (!second_matcher_.MatchAndExplain(pair_getters::Second(a_pair, Rank0()), if (!second_matcher_.MatchAndExplain(pair_getters::Second(a_pair, Rank1()),
&second_inner_listener)) { &second_inner_listener)) {
*listener << "whose second field does not match"; *listener << "whose second field does not match";
PrintIfNotEmpty(second_inner_listener.str(), listener->stream()); PrintIfNotEmpty(second_inner_listener.str(), listener->stream());
@ -3151,8 +3152,8 @@ class PairMatcher {
}; };
template <typename T, size_t... I> template <typename T, size_t... I>
auto UnpackStructImpl(const T& t, IndexSequence<I...>, int) auto UnpackStructImpl(const T& t, std::index_sequence<I...>,
-> decltype(std::tie(get<I>(t)...)) { int) -> decltype(std::tie(get<I>(t)...)) {
static_assert(std::tuple_size<T>::value == sizeof...(I), static_assert(std::tuple_size<T>::value == sizeof...(I),
"Number of arguments doesn't match the number of fields."); "Number of arguments doesn't match the number of fields.");
return std::tie(get<I>(t)...); return std::tie(get<I>(t)...);
@ -3160,97 +3161,97 @@ auto UnpackStructImpl(const T& t, IndexSequence<I...>, int)
#if defined(__cpp_structured_bindings) && __cpp_structured_bindings >= 201606 #if defined(__cpp_structured_bindings) && __cpp_structured_bindings >= 201606
template <typename T> template <typename T>
auto UnpackStructImpl(const T& t, MakeIndexSequence<1>, char) { auto UnpackStructImpl(const T& t, std::make_index_sequence<1>, char) {
const auto& [a] = t; const auto& [a] = t;
return std::tie(a); return std::tie(a);
} }
template <typename T> template <typename T>
auto UnpackStructImpl(const T& t, MakeIndexSequence<2>, char) { auto UnpackStructImpl(const T& t, std::make_index_sequence<2>, char) {
const auto& [a, b] = t; const auto& [a, b] = t;
return std::tie(a, b); return std::tie(a, b);
} }
template <typename T> template <typename T>
auto UnpackStructImpl(const T& t, MakeIndexSequence<3>, char) { auto UnpackStructImpl(const T& t, std::make_index_sequence<3>, char) {
const auto& [a, b, c] = t; const auto& [a, b, c] = t;
return std::tie(a, b, c); return std::tie(a, b, c);
} }
template <typename T> template <typename T>
auto UnpackStructImpl(const T& t, MakeIndexSequence<4>, char) { auto UnpackStructImpl(const T& t, std::make_index_sequence<4>, char) {
const auto& [a, b, c, d] = t; const auto& [a, b, c, d] = t;
return std::tie(a, b, c, d); return std::tie(a, b, c, d);
} }
template <typename T> template <typename T>
auto UnpackStructImpl(const T& t, MakeIndexSequence<5>, char) { auto UnpackStructImpl(const T& t, std::make_index_sequence<5>, char) {
const auto& [a, b, c, d, e] = t; const auto& [a, b, c, d, e] = t;
return std::tie(a, b, c, d, e); return std::tie(a, b, c, d, e);
} }
template <typename T> template <typename T>
auto UnpackStructImpl(const T& t, MakeIndexSequence<6>, char) { auto UnpackStructImpl(const T& t, std::make_index_sequence<6>, char) {
const auto& [a, b, c, d, e, f] = t; const auto& [a, b, c, d, e, f] = t;
return std::tie(a, b, c, d, e, f); return std::tie(a, b, c, d, e, f);
} }
template <typename T> template <typename T>
auto UnpackStructImpl(const T& t, MakeIndexSequence<7>, char) { auto UnpackStructImpl(const T& t, std::make_index_sequence<7>, char) {
const auto& [a, b, c, d, e, f, g] = t; const auto& [a, b, c, d, e, f, g] = t;
return std::tie(a, b, c, d, e, f, g); return std::tie(a, b, c, d, e, f, g);
} }
template <typename T> template <typename T>
auto UnpackStructImpl(const T& t, MakeIndexSequence<8>, char) { auto UnpackStructImpl(const T& t, std::make_index_sequence<8>, char) {
const auto& [a, b, c, d, e, f, g, h] = t; const auto& [a, b, c, d, e, f, g, h] = t;
return std::tie(a, b, c, d, e, f, g, h); return std::tie(a, b, c, d, e, f, g, h);
} }
template <typename T> template <typename T>
auto UnpackStructImpl(const T& t, MakeIndexSequence<9>, char) { auto UnpackStructImpl(const T& t, std::make_index_sequence<9>, char) {
const auto& [a, b, c, d, e, f, g, h, i] = t; const auto& [a, b, c, d, e, f, g, h, i] = t;
return std::tie(a, b, c, d, e, f, g, h, i); return std::tie(a, b, c, d, e, f, g, h, i);
} }
template <typename T> template <typename T>
auto UnpackStructImpl(const T& t, MakeIndexSequence<10>, char) { auto UnpackStructImpl(const T& t, std::make_index_sequence<10>, char) {
const auto& [a, b, c, d, e, f, g, h, i, j] = t; const auto& [a, b, c, d, e, f, g, h, i, j] = t;
return std::tie(a, b, c, d, e, f, g, h, i, j); return std::tie(a, b, c, d, e, f, g, h, i, j);
} }
template <typename T> template <typename T>
auto UnpackStructImpl(const T& t, MakeIndexSequence<11>, char) { auto UnpackStructImpl(const T& t, std::make_index_sequence<11>, char) {
const auto& [a, b, c, d, e, f, g, h, i, j, k] = t; const auto& [a, b, c, d, e, f, g, h, i, j, k] = t;
return std::tie(a, b, c, d, e, f, g, h, i, j, k); return std::tie(a, b, c, d, e, f, g, h, i, j, k);
} }
template <typename T> template <typename T>
auto UnpackStructImpl(const T& t, MakeIndexSequence<12>, char) { auto UnpackStructImpl(const T& t, std::make_index_sequence<12>, char) {
const auto& [a, b, c, d, e, f, g, h, i, j, k, l] = t; const auto& [a, b, c, d, e, f, g, h, i, j, k, l] = t;
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l); return std::tie(a, b, c, d, e, f, g, h, i, j, k, l);
} }
template <typename T> template <typename T>
auto UnpackStructImpl(const T& t, MakeIndexSequence<13>, char) { auto UnpackStructImpl(const T& t, std::make_index_sequence<13>, char) {
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m] = t; const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m] = t;
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m); return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m);
} }
template <typename T> template <typename T>
auto UnpackStructImpl(const T& t, MakeIndexSequence<14>, char) { auto UnpackStructImpl(const T& t, std::make_index_sequence<14>, char) {
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n] = t; const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n] = t;
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n); return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n);
} }
template <typename T> template <typename T>
auto UnpackStructImpl(const T& t, MakeIndexSequence<15>, char) { auto UnpackStructImpl(const T& t, std::make_index_sequence<15>, char) {
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o] = t; const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o] = t;
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o); return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o);
} }
template <typename T> template <typename T>
auto UnpackStructImpl(const T& t, MakeIndexSequence<16>, char) { auto UnpackStructImpl(const T& t, std::make_index_sequence<16>, char) {
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p] = t; const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p] = t;
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p); return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p);
} }
template <typename T> template <typename T>
auto UnpackStructImpl(const T& t, MakeIndexSequence<17>, char) { auto UnpackStructImpl(const T& t, std::make_index_sequence<17>, char) {
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q] = t; const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q] = t;
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q); return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q);
} }
template <typename T> template <typename T>
auto UnpackStructImpl(const T& t, MakeIndexSequence<18>, char) { auto UnpackStructImpl(const T& t, std::make_index_sequence<18>, char) {
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r] = t; const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r] = t;
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r); return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r);
} }
template <typename T> template <typename T>
auto UnpackStructImpl(const T& t, MakeIndexSequence<19>, char) { auto UnpackStructImpl(const T& t, std::make_index_sequence<19>, char) {
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s] = t; const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s] = t;
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s); return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s);
} }
@ -3258,8 +3259,8 @@ auto UnpackStructImpl(const T& t, MakeIndexSequence<19>, char) {
template <size_t I, typename T> template <size_t I, typename T>
auto UnpackStruct(const T& t) auto UnpackStruct(const T& t)
-> decltype((UnpackStructImpl)(t, MakeIndexSequence<I>{}, 0)) { -> decltype((UnpackStructImpl)(t, std::make_index_sequence<I>{}, 0)) {
return (UnpackStructImpl)(t, MakeIndexSequence<I>{}, 0); return (UnpackStructImpl)(t, std::make_index_sequence<I>{}, 0);
} }
// Helper function to do comma folding in C++11. // Helper function to do comma folding in C++11.
@ -3272,7 +3273,7 @@ template <typename Struct, typename StructSize>
class FieldsAreMatcherImpl; class FieldsAreMatcherImpl;
template <typename Struct, size_t... I> template <typename Struct, size_t... I>
class FieldsAreMatcherImpl<Struct, IndexSequence<I...>> class FieldsAreMatcherImpl<Struct, std::index_sequence<I...>>
: public MatcherInterface<Struct> { : public MatcherInterface<Struct> {
using UnpackedType = using UnpackedType =
decltype(UnpackStruct<sizeof...(I)>(std::declval<const Struct&>())); decltype(UnpackStruct<sizeof...(I)>(std::declval<const Struct&>()));
@ -3354,8 +3355,8 @@ class FieldsAreMatcher {
template <typename Struct> template <typename Struct>
operator Matcher<Struct>() const { // NOLINT operator Matcher<Struct>() const { // NOLINT
return Matcher<Struct>( return Matcher<Struct>(
new FieldsAreMatcherImpl<const Struct&, IndexSequenceFor<Inner...>>( new FieldsAreMatcherImpl<const Struct&,
matchers_)); std::index_sequence_for<Inner...>>(matchers_));
} }
private: private:
@ -5444,47 +5445,47 @@ PolymorphicMatcher<internal::ExceptionMatcherImpl<Err>> ThrowsMessage(
::testing::internal::MakePredicateFormatterFromMatcher(matcher), value) ::testing::internal::MakePredicateFormatterFromMatcher(matcher), value)
// MATCHER* macros itself are listed below. // MATCHER* macros itself are listed below.
#define MATCHER(name, description) \ #define MATCHER(name, description) \
class name##Matcher \ class name##Matcher \
: public ::testing::internal::MatcherBaseImpl<name##Matcher> { \ : public ::testing::internal::MatcherBaseImpl<name##Matcher> { \
public: \ public: \
template <typename arg_type> \ template <typename arg_type> \
class gmock_Impl : public ::testing::MatcherInterface<const arg_type&> { \ class gmock_Impl : public ::testing::MatcherInterface<const arg_type&> { \
public: \ public: \
gmock_Impl() {} \ gmock_Impl() {} \
bool MatchAndExplain( \ bool MatchAndExplain( \
const arg_type& arg, \ const arg_type& arg, \
::testing::MatchResultListener* result_listener) const override; \ ::testing::MatchResultListener* result_listener) const override; \
void DescribeTo(::std::ostream* gmock_os) const override { \ void DescribeTo(::std::ostream* gmock_os) const override { \
*gmock_os << FormatDescription(false); \ *gmock_os << FormatDescription(false); \
} \ } \
void DescribeNegationTo(::std::ostream* gmock_os) const override { \ void DescribeNegationTo(::std::ostream* gmock_os) const override { \
*gmock_os << FormatDescription(true); \ *gmock_os << FormatDescription(true); \
} \ } \
\ \
private: \ private: \
::std::string FormatDescription(bool negation) const { \ ::std::string FormatDescription(bool negation) const { \
/* NOLINTNEXTLINE readability-redundant-string-init */ \ /* NOLINTNEXTLINE readability-redundant-string-init */ \
::std::string gmock_description = (description); \ ::std::string gmock_description = (description); \
if (!gmock_description.empty()) { \ if (!gmock_description.empty()) { \
return gmock_description; \ return gmock_description; \
} \ } \
return ::testing::internal::FormatMatcherDescription(negation, #name, \ return ::testing::internal::FormatMatcherDescription(negation, #name, \
{}, {}); \ {}, {}); \
} \ } \
}; \ }; \
}; \ }; \
inline name##Matcher GMOCK_INTERNAL_WARNING_PUSH() \ inline name##Matcher GMOCK_INTERNAL_WARNING_PUSH() \
GMOCK_INTERNAL_WARNING_CLANG(ignored, "-Wunused-function") \ GMOCK_INTERNAL_WARNING_CLANG(ignored, "-Wunused-function") \
GMOCK_INTERNAL_WARNING_CLANG(ignored, "-Wunused-member-function") \ GMOCK_INTERNAL_WARNING_CLANG(ignored, "-Wunused-member-function") \
name GMOCK_INTERNAL_WARNING_POP()() { \ name GMOCK_INTERNAL_WARNING_POP()() { \
return {}; \ return {}; \
} \ } \
template <typename arg_type> \ template <typename arg_type> \
bool name##Matcher::gmock_Impl<arg_type>::MatchAndExplain( \ bool name##Matcher::gmock_Impl<arg_type>::MatchAndExplain( \
const arg_type& arg, \ const arg_type& arg, \
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_) \ GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED ::testing::MatchResultListener* \
const result_listener) const
#define MATCHER_P(name, p0, description) \ #define MATCHER_P(name, p0, description) \
GMOCK_INTERNAL_MATCHER(name, name##MatcherP, description, (#p0), (p0)) GMOCK_INTERNAL_MATCHER(name, name##MatcherP, description, (#p0), (p0))
@ -5566,11 +5567,11 @@ PolymorphicMatcher<internal::ExceptionMatcherImpl<Err>> ThrowsMessage(
} \ } \
template <GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args)> \ template <GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args)> \
template <typename arg_type> \ template <typename arg_type> \
bool full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>::gmock_Impl< \ bool full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>:: \
arg_type>::MatchAndExplain(const arg_type& arg, \ gmock_Impl<arg_type>::MatchAndExplain( \
::testing::MatchResultListener* \ const arg_type& arg, \
result_listener GTEST_ATTRIBUTE_UNUSED_) \ GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED ::testing:: \
const MatchResultListener* result_listener) const
#define GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args) \ #define GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args) \
GMOCK_PP_TAIL( \ GMOCK_PP_TAIL( \
@ -5605,8 +5606,8 @@ PolymorphicMatcher<internal::ExceptionMatcherImpl<Err>> ThrowsMessage(
#define GMOCK_INTERNAL_MATCHER_ARGS_USAGE(args) \ #define GMOCK_INTERNAL_MATCHER_ARGS_USAGE(args) \
GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_ARG_USAGE, , args)) GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_ARG_USAGE, , args))
#define GMOCK_INTERNAL_MATCHER_ARG_USAGE(i, data_unused, arg_unused) \ #define GMOCK_INTERNAL_MATCHER_ARG_USAGE(i, data_unused, arg) \
, gmock_p##i , ::std::forward<arg##_type>(gmock_p##i)
// To prevent ADL on certain functions we put them on a separate namespace. // To prevent ADL on certain functions we put them on a separate namespace.
using namespace no_adl; // NOLINT using namespace no_adl; // NOLINT

View File

@ -592,8 +592,9 @@ namespace internal {
// Overloads for other custom-callables are provided in the // Overloads for other custom-callables are provided in the
// internal/custom/gmock-generated-actions.h header. // internal/custom/gmock-generated-actions.h header.
template <typename F, typename... Args> template <typename F, typename... Args>
auto InvokeArgument(F f, Args... args) -> decltype(f(args...)) { auto InvokeArgument(F &&f,
return f(args...); Args... args) -> decltype(std::forward<F>(f)(args...)) {
return std::forward<F>(f)(args...);
} }
template <std::size_t index, typename... Params> template <std::size_t index, typename... Params>
@ -606,7 +607,7 @@ struct InvokeArgumentAction {
internal::FlatTuple<Args &&...> args_tuple(FlatTupleConstructTag{}, internal::FlatTuple<Args &&...> args_tuple(FlatTupleConstructTag{},
std::forward<Args>(args)...); std::forward<Args>(args)...);
return params.Apply([&](const Params &...unpacked_params) { return params.Apply([&](const Params &...unpacked_params) {
auto &&callable = args_tuple.template Get<index>(); auto &&callable = std::move(args_tuple.template Get<index>());
return internal::InvokeArgument( return internal::InvokeArgument(
std::forward<decltype(callable)>(callable), unpacked_params...); std::forward<decltype(callable)>(callable), unpacked_params...);
}); });

View File

@ -53,13 +53,14 @@
// //
// where all clauses are optional and WillOnce() can be repeated. // where all clauses are optional and WillOnce() can be repeated.
#include "gmock/gmock-actions.h" #include "gmock/gmock-actions.h" // IWYU pragma: export
#include "gmock/gmock-cardinalities.h" #include "gmock/gmock-cardinalities.h" // IWYU pragma: export
#include "gmock/gmock-function-mocker.h" #include "gmock/gmock-function-mocker.h" // IWYU pragma: export
#include "gmock/gmock-matchers.h" #include "gmock/gmock-matchers.h" // IWYU pragma: export
#include "gmock/gmock-more-actions.h" #include "gmock/gmock-more-actions.h" // IWYU pragma: export
#include "gmock/gmock-more-matchers.h" #include "gmock/gmock-more-matchers.h" // IWYU pragma: export
#include "gmock/gmock-nice-strict.h" #include "gmock/gmock-nice-strict.h" // IWYU pragma: export
#include "gmock/gmock-spec-builders.h" // IWYU pragma: export
#include "gmock/internal/gmock-internal-utils.h" #include "gmock/internal/gmock-internal-utils.h"
#include "gmock/internal/gmock-port.h" #include "gmock/internal/gmock-port.h"

View File

@ -44,6 +44,7 @@
#include <ostream> // NOLINT #include <ostream> // NOLINT
#include <string> #include <string>
#include <type_traits> #include <type_traits>
#include <utility>
#include <vector> #include <vector>
#include "gmock/internal/gmock-port.h" #include "gmock/internal/gmock-port.h"
@ -420,7 +421,7 @@ struct RemoveConstFromKey<std::pair<const K, V> > {
GTEST_API_ void IllegalDoDefault(const char* file, int line); GTEST_API_ void IllegalDoDefault(const char* file, int line);
template <typename F, typename Tuple, size_t... Idx> template <typename F, typename Tuple, size_t... Idx>
auto ApplyImpl(F&& f, Tuple&& args, IndexSequence<Idx...>) auto ApplyImpl(F&& f, Tuple&& args, std::index_sequence<Idx...>)
-> decltype(std::forward<F>(f)( -> decltype(std::forward<F>(f)(
std::get<Idx>(std::forward<Tuple>(args))...)) { std::get<Idx>(std::forward<Tuple>(args))...)) {
return std::forward<F>(f)(std::get<Idx>(std::forward<Tuple>(args))...); return std::forward<F>(f)(std::get<Idx>(std::forward<Tuple>(args))...);
@ -428,12 +429,13 @@ auto ApplyImpl(F&& f, Tuple&& args, IndexSequence<Idx...>)
// Apply the function to a tuple of arguments. // Apply the function to a tuple of arguments.
template <typename F, typename Tuple> template <typename F, typename Tuple>
auto Apply(F&& f, Tuple&& args) -> decltype(ApplyImpl( auto Apply(F&& f, Tuple&& args)
std::forward<F>(f), std::forward<Tuple>(args), -> decltype(ApplyImpl(
MakeIndexSequence<std::tuple_size< std::forward<F>(f), std::forward<Tuple>(args),
typename std::remove_reference<Tuple>::type>::value>())) { std::make_index_sequence<std::tuple_size<
typename std::remove_reference<Tuple>::type>::value>())) {
return ApplyImpl(std::forward<F>(f), std::forward<Tuple>(args), return ApplyImpl(std::forward<F>(f), std::forward<Tuple>(args),
MakeIndexSequence<std::tuple_size< std::make_index_sequence<std::tuple_size<
typename std::remove_reference<Tuple>::type>::value>()); typename std::remove_reference<Tuple>::type>::value>());
} }

View File

@ -56,7 +56,7 @@
#include "gmock/internal/custom/gmock-port.h" #include "gmock/internal/custom/gmock-port.h"
#include "gtest/internal/gtest-port.h" #include "gtest/internal/gtest-port.h"
#ifdef GTEST_HAS_ABSL #if defined(GTEST_HAS_ABSL) && !defined(GTEST_NO_ABSL_FLAGS)
#include "absl/flags/declare.h" #include "absl/flags/declare.h"
#include "absl/flags/flag.h" #include "absl/flags/flag.h"
#endif #endif
@ -73,7 +73,7 @@
#define GMOCK_FLAG(name) FLAGS_gmock_##name #define GMOCK_FLAG(name) FLAGS_gmock_##name
// Pick a command line flags implementation. // Pick a command line flags implementation.
#ifdef GTEST_HAS_ABSL #if defined(GTEST_HAS_ABSL) && !defined(GTEST_NO_ABSL_FLAGS)
// Macros for defining flags. // Macros for defining flags.
#define GMOCK_DEFINE_bool_(name, default_val, doc) \ #define GMOCK_DEFINE_bool_(name, default_val, doc) \
@ -95,7 +95,7 @@
#define GMOCK_FLAG_SET(name, value) \ #define GMOCK_FLAG_SET(name, value) \
(void)(::absl::SetFlag(&GMOCK_FLAG(name), value)) (void)(::absl::SetFlag(&GMOCK_FLAG(name), value))
#else // GTEST_HAS_ABSL #else // defined(GTEST_HAS_ABSL) && !defined(GTEST_NO_ABSL_FLAGS)
// Macros for defining flags. // Macros for defining flags.
#define GMOCK_DEFINE_bool_(name, default_val, doc) \ #define GMOCK_DEFINE_bool_(name, default_val, doc) \
@ -134,6 +134,6 @@
#define GMOCK_FLAG_GET(name) ::testing::GMOCK_FLAG(name) #define GMOCK_FLAG_GET(name) ::testing::GMOCK_FLAG(name)
#define GMOCK_FLAG_SET(name, value) (void)(::testing::GMOCK_FLAG(name) = value) #define GMOCK_FLAG_SET(name, value) (void)(::testing::GMOCK_FLAG(name) = value)
#endif // GTEST_HAS_ABSL #endif // defined(GTEST_HAS_ABSL) && !defined(GTEST_NO_ABSL_FLAGS)
#endif // GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_ #endif // GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_

View File

@ -44,6 +44,7 @@
#include <iostream> #include <iostream>
#include <ostream> // NOLINT #include <ostream> // NOLINT
#include <string> #include <string>
#include <utility>
#include <vector> #include <vector>
#include "gmock/gmock.h" #include "gmock/gmock.h"
@ -211,14 +212,14 @@ constexpr char UnBase64Impl(char c, const char* const base64, char carry) {
} }
template <size_t... I> template <size_t... I>
constexpr std::array<char, 256> UnBase64Impl(IndexSequence<I...>, constexpr std::array<char, 256> UnBase64Impl(std::index_sequence<I...>,
const char* const base64) { const char* const base64) {
return { return {
{UnBase64Impl(UndoWebSafeEncoding(static_cast<char>(I)), base64, 0)...}}; {UnBase64Impl(UndoWebSafeEncoding(static_cast<char>(I)), base64, 0)...}};
} }
constexpr std::array<char, 256> UnBase64(const char* const base64) { constexpr std::array<char, 256> UnBase64(const char* const base64) {
return UnBase64Impl(MakeIndexSequence<256>{}, base64); return UnBase64Impl(std::make_index_sequence<256>{}, base64);
} }
static constexpr char kBase64[] = static constexpr char kBase64[] =

View File

@ -120,7 +120,7 @@ GTEST_API_ std::string FormatMatcherDescription(
// [1] Cormen, et al (2001). "Section 26.2: The Ford-Fulkerson method". // [1] Cormen, et al (2001). "Section 26.2: The Ford-Fulkerson method".
// "Introduction to Algorithms (Second ed.)", pp. 651-664. // "Introduction to Algorithms (Second ed.)", pp. 651-664.
// [2] "Ford-Fulkerson algorithm", Wikipedia, // [2] "Ford-Fulkerson algorithm", Wikipedia,
// 'http://en.wikipedia.org/wiki/Ford%E2%80%93Fulkerson_algorithm' // 'https://en.wikipedia.org/wiki/Ford%E2%80%93Fulkerson_algorithm'
class MaxBipartiteMatchState { class MaxBipartiteMatchState {
public: public:
explicit MaxBipartiteMatchState(const MatchMatrix& graph) explicit MaxBipartiteMatchState(const MatchMatrix& graph)
@ -236,9 +236,8 @@ static void LogElementMatcherPairVec(const ElementMatcherPairs& pairs,
os << "{"; os << "{";
const char* sep = ""; const char* sep = "";
for (Iter it = pairs.begin(); it != pairs.end(); ++it) { for (Iter it = pairs.begin(); it != pairs.end(); ++it) {
os << sep << "\n (" os << sep << "\n (" << "element #" << it->first << ", " << "matcher #"
<< "element #" << it->first << ", " << it->second << ")";
<< "matcher #" << it->second << ")";
sep = ","; sep = ",";
} }
os << "\n}"; os << "\n}";
@ -374,20 +373,20 @@ bool UnorderedElementsAreMatcherImplBase::VerifyMatchMatrix(
return true; return true;
} }
if (match_flags() == UnorderedMatcherRequire::ExactMatch) { const bool is_exact_match_with_size_discrepency =
if (matrix.LhsSize() != matrix.RhsSize()) { match_flags() == UnorderedMatcherRequire::ExactMatch &&
// The element count doesn't match. If the container is empty, matrix.LhsSize() != matrix.RhsSize();
// there's no need to explain anything as Google Mock already if (is_exact_match_with_size_discrepency) {
// prints the empty container. Otherwise we just need to show // The element count doesn't match. If the container is empty,
// how many elements there actually are. // there's no need to explain anything as Google Mock already
if (matrix.LhsSize() != 0 && listener->IsInterested()) { // prints the empty container. Otherwise we just need to show
*listener << "which has " << Elements(matrix.LhsSize()); // how many elements there actually are.
} if (matrix.LhsSize() != 0 && listener->IsInterested()) {
return false; *listener << "which has " << Elements(matrix.LhsSize()) << "\n";
} }
} }
bool result = true; bool result = !is_exact_match_with_size_discrepency;
::std::vector<char> element_matched(matrix.LhsSize(), 0); ::std::vector<char> element_matched(matrix.LhsSize(), 0);
::std::vector<char> matcher_matched(matrix.RhsSize(), 0); ::std::vector<char> matcher_matched(matrix.RhsSize(), 0);

View File

@ -490,6 +490,7 @@ class MockObjectRegistry {
// failure, unless the user explicitly asked us to ignore it. // failure, unless the user explicitly asked us to ignore it.
~MockObjectRegistry() { ~MockObjectRegistry() {
if (!GMOCK_FLAG_GET(catch_leaked_mocks)) return; if (!GMOCK_FLAG_GET(catch_leaked_mocks)) return;
internal::MutexLock l(&internal::g_gmock_mutex);
int leaked_count = 0; int leaked_count = 0;
for (StateMap::const_iterator it = states_.begin(); it != states_.end(); for (StateMap::const_iterator it = states_.begin(); it != states_.end();
@ -530,7 +531,7 @@ class MockObjectRegistry {
#ifdef GTEST_OS_QURT #ifdef GTEST_OS_QURT
qurt_exception_raise_fatal(); qurt_exception_raise_fatal();
#else #else
_exit(1); // We cannot call exit() as it is not reentrant and _Exit(1); // We cannot call exit() as it is not reentrant and
// may already have been called. // may already have been called.
#endif #endif
} }

View File

@ -12,7 +12,7 @@ GoogleTest comes with a CMake build script
([CMakeLists.txt](https://github.com/google/googletest/blob/main/CMakeLists.txt)) ([CMakeLists.txt](https://github.com/google/googletest/blob/main/CMakeLists.txt))
that can be used on a wide range of platforms ("C" stands for cross-platform.). that can be used on a wide range of platforms ("C" stands for cross-platform.).
If you don't have CMake installed already, you can download it for free from If you don't have CMake installed already, you can download it for free from
<http://www.cmake.org/>. <https://cmake.org/>.
CMake works by generating native makefiles or build projects that can be used in CMake works by generating native makefiles or build projects that can be used in
the compiler environment of your choice. You can either build GoogleTest as a the compiler environment of your choice. You can either build GoogleTest as a
@ -25,7 +25,7 @@ When building GoogleTest as a standalone project, the typical workflow starts
with with
``` ```
git clone https://github.com/google/googletest.git -b v1.13.0 git clone https://github.com/google/googletest.git -b v1.15.0
cd googletest # Main directory of the cloned repository. cd googletest # Main directory of the cloned repository.
mkdir build # Create a directory to hold the build output. mkdir build # Create a directory to hold the build output.
cd build cd build

View File

@ -129,7 +129,7 @@ namespace testing {
// //
// Expected: Foo() is even // Expected: Foo() is even
// Actual: it's 5 // Actual: it's 5
//
class GTEST_API_ AssertionResult { class GTEST_API_ AssertionResult {
public: public:
// Copy constructor. // Copy constructor.

View File

@ -293,8 +293,8 @@ class GTEST_API_ KilledBySignal {
// statement is compiled but not executed, to ensure that // statement is compiled but not executed, to ensure that
// EXPECT_DEATH_IF_SUPPORTED compiles with a certain // EXPECT_DEATH_IF_SUPPORTED compiles with a certain
// parameter if and only if EXPECT_DEATH compiles with it. // parameter if and only if EXPECT_DEATH compiles with it.
// regex - A regex that a macro such as EXPECT_DEATH would use to test // regex_or_matcher - A regex that a macro such as EXPECT_DEATH would use
// the output of statement. This parameter has to be // to test the output of statement. This parameter has to be
// compiled but not evaluated by this macro, to ensure that // compiled but not evaluated by this macro, to ensure that
// this macro only accepts expressions that a macro such as // this macro only accepts expressions that a macro such as
// EXPECT_DEATH would accept. // EXPECT_DEATH would accept.
@ -311,13 +311,13 @@ class GTEST_API_ KilledBySignal {
// statement unconditionally returns or throws. The Message constructor at // statement unconditionally returns or throws. The Message constructor at
// the end allows the syntax of streaming additional messages into the // the end allows the syntax of streaming additional messages into the
// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH. // macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
#define GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, terminator) \ #define GTEST_UNSUPPORTED_DEATH_TEST(statement, regex_or_matcher, terminator) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::AlwaysTrue()) { \ if (::testing::internal::AlwaysTrue()) { \
GTEST_LOG_(WARNING) << "Death tests are not supported on this platform.\n" \ GTEST_LOG_(WARNING) << "Death tests are not supported on this platform.\n" \
<< "Statement '" #statement "' cannot be verified."; \ << "Statement '" #statement "' cannot be verified."; \
} else if (::testing::internal::AlwaysFalse()) { \ } else if (::testing::internal::AlwaysFalse()) { \
::testing::internal::RE::PartialMatch(".*", (regex)); \ ::testing::internal::MakeDeathTestMatcher(regex_or_matcher); \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
terminator; \ terminator; \
} else \ } else \

View File

@ -59,7 +59,7 @@
#ifdef GTEST_HAS_ABSL #ifdef GTEST_HAS_ABSL
#include <type_traits> #include <type_traits>
#include "absl/strings/internal/has_absl_stringify.h" #include "absl/strings/has_absl_stringify.h"
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
#endif // GTEST_HAS_ABSL #endif // GTEST_HAS_ABSL
@ -121,14 +121,14 @@ class GTEST_API_ Message {
// Streams a non-pointer value to this object. If building a version of // Streams a non-pointer value to this object. If building a version of
// GoogleTest with ABSL, this overload is only enabled if the value does not // GoogleTest with ABSL, this overload is only enabled if the value does not
// have an AbslStringify definition. // have an AbslStringify definition.
template <typename T template <
typename T
#ifdef GTEST_HAS_ABSL #ifdef GTEST_HAS_ABSL
, ,
typename std::enable_if< typename std::enable_if<!absl::HasAbslStringify<T>::value, // NOLINT
!absl::strings_internal::HasAbslStringify<T>::value, // NOLINT int>::type = 0
int>::type = 0
#endif // GTEST_HAS_ABSL #endif // GTEST_HAS_ABSL
> >
inline Message& operator<<(const T& val) { inline Message& operator<<(const T& val) {
// Some libraries overload << for STL containers. These // Some libraries overload << for STL containers. These
// overloads are defined in the global namespace instead of ::std. // overloads are defined in the global namespace instead of ::std.
@ -153,9 +153,8 @@ class GTEST_API_ Message {
// Streams a non-pointer value with an AbslStringify definition to this // Streams a non-pointer value with an AbslStringify definition to this
// object. // object.
template <typename T, template <typename T,
typename std::enable_if< typename std::enable_if<absl::HasAbslStringify<T>::value, // NOLINT
absl::strings_internal::HasAbslStringify<T>::value, // NOLINT int>::type = 0>
int>::type = 0>
inline Message& operator<<(const T& val) { inline Message& operator<<(const T& val) {
// ::operator<< is needed here for a similar reason as with the non-Abseil // ::operator<< is needed here for a similar reason as with the non-Abseil
// version above // version above

View File

@ -178,7 +178,7 @@ TEST_P(DerivedTest, DoesBlah) {
#include <utility> #include <utility>
#include "gtest/internal/gtest-internal.h" #include "gtest/internal/gtest-internal.h"
#include "gtest/internal/gtest-param-util.h" #include "gtest/internal/gtest-param-util.h" // IWYU pragma: export
#include "gtest/internal/gtest-port.h" #include "gtest/internal/gtest-port.h"
namespace testing { namespace testing {
@ -469,7 +469,7 @@ internal::ParamConverterGenerator<T> ConvertGenerator(
::testing::internal::CodeLocation(__FILE__, __LINE__)); \ ::testing::internal::CodeLocation(__FILE__, __LINE__)); \
return 0; \ return 0; \
} \ } \
static int gtest_registering_dummy_ GTEST_ATTRIBUTE_UNUSED_; \ GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static int gtest_registering_dummy_; \
}; \ }; \
int GTEST_TEST_CLASS_NAME_(test_suite_name, \ int GTEST_TEST_CLASS_NAME_(test_suite_name, \
test_name)::gtest_registering_dummy_ = \ test_name)::gtest_registering_dummy_ = \
@ -514,8 +514,8 @@ internal::ParamConverterGenerator<T> ConvertGenerator(
::testing::internal::DefaultParamName<test_suite_name::ParamType>, \ ::testing::internal::DefaultParamName<test_suite_name::ParamType>, \
DUMMY_PARAM_))))(info); \ DUMMY_PARAM_))))(info); \
} \ } \
static int gtest_##prefix##test_suite_name##_dummy_ \ GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static int \
GTEST_ATTRIBUTE_UNUSED_ = \ gtest_##prefix##test_suite_name##_dummy_ = \
::testing::UnitTest::GetInstance() \ ::testing::UnitTest::GetInstance() \
->parameterized_test_registry() \ ->parameterized_test_registry() \
.GetTestSuitePatternHolder<test_suite_name>( \ .GetTestSuitePatternHolder<test_suite_name>( \

View File

@ -116,12 +116,16 @@
#include <vector> #include <vector>
#ifdef GTEST_HAS_ABSL #ifdef GTEST_HAS_ABSL
#include "absl/strings/internal/has_absl_stringify.h" #include "absl/strings/has_absl_stringify.h"
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
#endif // GTEST_HAS_ABSL #endif // GTEST_HAS_ABSL
#include "gtest/internal/gtest-internal.h" #include "gtest/internal/gtest-internal.h"
#include "gtest/internal/gtest-port.h" #include "gtest/internal/gtest-port.h"
#if GTEST_INTERNAL_HAS_STD_SPAN
#include <span> // NOLINT
#endif // GTEST_INTERNAL_HAS_STD_SPAN
namespace testing { namespace testing {
// Definitions in the internal* namespaces are subject to change without notice. // Definitions in the internal* namespaces are subject to change without notice.
@ -131,13 +135,32 @@ namespace internal {
template <typename T> template <typename T>
void UniversalPrint(const T& value, ::std::ostream* os); void UniversalPrint(const T& value, ::std::ostream* os);
template <typename T>
struct IsStdSpan {
static constexpr bool value = false;
};
#if GTEST_INTERNAL_HAS_STD_SPAN
template <typename E>
struct IsStdSpan<std::span<E>> {
static constexpr bool value = true;
};
#endif // GTEST_INTERNAL_HAS_STD_SPAN
// Used to print an STL-style container when the user doesn't define // Used to print an STL-style container when the user doesn't define
// a PrintTo() for it. // a PrintTo() for it.
//
// NOTE: Since std::span does not have const_iterator until C++23, it would
// fail IsContainerTest before C++23. However, IsContainerTest only uses
// the presence of const_iterator to avoid treating iterators as containers
// because of iterator::iterator. Which means std::span satisfies the *intended*
// condition of IsContainerTest.
struct ContainerPrinter { struct ContainerPrinter {
template <typename T, template <typename T,
typename = typename std::enable_if< typename = typename std::enable_if<
(sizeof(IsContainerTest<T>(0)) == sizeof(IsContainer)) && ((sizeof(IsContainerTest<T>(0)) == sizeof(IsContainer)) &&
!IsRecursiveContainer<T>::value>::type> !IsRecursiveContainer<T>::value) ||
IsStdSpan<T>::value>::type>
static void PrintValue(const T& container, std::ostream* os) { static void PrintValue(const T& container, std::ostream* os) {
const size_t kMaxCount = 32; // The maximum number of elements to print. const size_t kMaxCount = 32; // The maximum number of elements to print.
*os << '{'; *os << '{';
@ -218,8 +241,8 @@ struct StreamPrinter {
// ADL (possibly involving implicit conversions). // ADL (possibly involving implicit conversions).
// (Use SFINAE via return type, because it seems GCC < 12 doesn't handle name // (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.) // lookup properly when we do it in the template parameter list.)
static auto PrintValue(const T& value, ::std::ostream* os) static auto PrintValue(const T& value,
-> decltype((void)(*os << value)) { ::std::ostream* os) -> decltype((void)(*os << value)) {
// Call streaming operator found by ADL, possibly with implicit conversions // Call streaming operator found by ADL, possibly with implicit conversions
// of the arguments. // of the arguments.
*os << value; *os << value;
@ -269,10 +292,9 @@ struct ConvertibleToStringViewPrinter {
#ifdef GTEST_HAS_ABSL #ifdef GTEST_HAS_ABSL
struct ConvertibleToAbslStringifyPrinter { struct ConvertibleToAbslStringifyPrinter {
template < template <typename T,
typename T, typename = typename std::enable_if<
typename = typename std::enable_if< absl::HasAbslStringify<T>::value>::type> // NOLINT
absl::strings_internal::HasAbslStringify<T>::value>::type> // NOLINT
static void PrintValue(const T& value, ::std::ostream* os) { static void PrintValue(const T& value, ::std::ostream* os) {
*os << absl::StrCat(value); *os << absl::StrCat(value);
} }
@ -530,49 +552,63 @@ int AppropriateResolution(FloatType val) {
int full = std::numeric_limits<FloatType>::max_digits10; int full = std::numeric_limits<FloatType>::max_digits10;
if (val < 0) val = -val; if (val < 0) val = -val;
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
if (val < 1000000) { if (val < 1000000) {
FloatType mulfor6 = 1e10; FloatType mulfor6 = 1e10;
if (val >= 100000.0) { // 100,000 to 999,999 // Without these static casts, the template instantiation for float would
// fail to compile when -Wdouble-promotion is enabled, as the arithmetic and
// comparison logic would promote floats to doubles.
if (val >= static_cast<FloatType>(100000.0)) { // 100,000 to 999,999
mulfor6 = 1.0; mulfor6 = 1.0;
} else if (val >= 10000.0) { } else if (val >= static_cast<FloatType>(10000.0)) {
mulfor6 = 1e1; mulfor6 = 1e1;
} else if (val >= 1000.0) { } else if (val >= static_cast<FloatType>(1000.0)) {
mulfor6 = 1e2; mulfor6 = 1e2;
} else if (val >= 100.0) { } else if (val >= static_cast<FloatType>(100.0)) {
mulfor6 = 1e3; mulfor6 = 1e3;
} else if (val >= 10.0) { } else if (val >= static_cast<FloatType>(10.0)) {
mulfor6 = 1e4; mulfor6 = 1e4;
} else if (val >= 1.0) { } else if (val >= static_cast<FloatType>(1.0)) {
mulfor6 = 1e5; mulfor6 = 1e5;
} else if (val >= 0.1) { } else if (val >= static_cast<FloatType>(0.1)) {
mulfor6 = 1e6; mulfor6 = 1e6;
} else if (val >= 0.01) { } else if (val >= static_cast<FloatType>(0.01)) {
mulfor6 = 1e7; mulfor6 = 1e7;
} else if (val >= 0.001) { } else if (val >= static_cast<FloatType>(0.001)) {
mulfor6 = 1e8; mulfor6 = 1e8;
} else if (val >= 0.0001) { } else if (val >= static_cast<FloatType>(0.0001)) {
mulfor6 = 1e9; mulfor6 = 1e9;
} }
if (static_cast<FloatType>(static_cast<int32_t>(val * mulfor6 + 0.5)) / if (static_cast<FloatType>(static_cast<int32_t>(
val * mulfor6 + (static_cast<FloatType>(0.5)))) /
mulfor6 == mulfor6 ==
val) val)
return 6; return 6;
} else if (val < 1e10) { } else if (val < static_cast<FloatType>(1e10)) {
FloatType divfor6 = 1.0; FloatType divfor6 = static_cast<FloatType>(1.0);
if (val >= 1e9) { // 1,000,000,000 to 9,999,999,999 if (val >= static_cast<FloatType>(1e9)) { // 1,000,000,000 to 9,999,999,999
divfor6 = 10000; divfor6 = 10000;
} else if (val >= 1e8) { // 100,000,000 to 999,999,999 } else if (val >=
static_cast<FloatType>(1e8)) { // 100,000,000 to 999,999,999
divfor6 = 1000; divfor6 = 1000;
} else if (val >= 1e7) { // 10,000,000 to 99,999,999 } else if (val >=
static_cast<FloatType>(1e7)) { // 10,000,000 to 99,999,999
divfor6 = 100; divfor6 = 100;
} else if (val >= 1e6) { // 1,000,000 to 9,999,999 } else if (val >= static_cast<FloatType>(1e6)) { // 1,000,000 to 9,999,999
divfor6 = 10; divfor6 = 10;
} }
if (static_cast<FloatType>(static_cast<int32_t>(val / divfor6 + 0.5)) * if (static_cast<FloatType>(static_cast<int32_t>(
val / divfor6 + (static_cast<FloatType>(0.5)))) *
divfor6 == divfor6 ==
val) val)
return 6; return 6;
} }
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
return full; return full;
} }

View File

@ -194,33 +194,34 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \ typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \
GTEST_NAME_GENERATOR_(CaseName) GTEST_NAME_GENERATOR_(CaseName)
#define TYPED_TEST(CaseName, TestName) \ #define TYPED_TEST(CaseName, TestName) \
static_assert(sizeof(GTEST_STRINGIFY_(TestName)) > 1, \ static_assert(sizeof(GTEST_STRINGIFY_(TestName)) > 1, \
"test-name must not be empty"); \ "test-name must not be empty"); \
template <typename gtest_TypeParam_> \ template <typename gtest_TypeParam_> \
class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \ class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
: public CaseName<gtest_TypeParam_> { \ : public CaseName<gtest_TypeParam_> { \
private: \ private: \
typedef CaseName<gtest_TypeParam_> TestFixture; \ typedef CaseName<gtest_TypeParam_> TestFixture; \
typedef gtest_TypeParam_ TypeParam; \ typedef gtest_TypeParam_ TypeParam; \
void TestBody() override; \ void TestBody() override; \
}; \ }; \
static bool gtest_##CaseName##_##TestName##_registered_ \ GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool \
GTEST_ATTRIBUTE_UNUSED_ = ::testing::internal::TypeParameterizedTest< \ gtest_##CaseName##_##TestName##_registered_ = \
CaseName, \ ::testing::internal::TypeParameterizedTest< \
::testing::internal::TemplateSel<GTEST_TEST_CLASS_NAME_(CaseName, \ CaseName, \
TestName)>, \ ::testing::internal::TemplateSel<GTEST_TEST_CLASS_NAME_( \
GTEST_TYPE_PARAMS_( \ CaseName, TestName)>, \
CaseName)>::Register("", \ GTEST_TYPE_PARAMS_( \
::testing::internal::CodeLocation( \ CaseName)>::Register("", \
__FILE__, __LINE__), \ ::testing::internal::CodeLocation( \
GTEST_STRINGIFY_(CaseName), \ __FILE__, __LINE__), \
GTEST_STRINGIFY_(TestName), 0, \ GTEST_STRINGIFY_(CaseName), \
::testing::internal::GenerateNames< \ GTEST_STRINGIFY_(TestName), 0, \
GTEST_NAME_GENERATOR_(CaseName), \ ::testing::internal::GenerateNames< \
GTEST_TYPE_PARAMS_(CaseName)>()); \ GTEST_NAME_GENERATOR_(CaseName), \
template <typename gtest_TypeParam_> \ GTEST_TYPE_PARAMS_(CaseName)>()); \
void GTEST_TEST_CLASS_NAME_(CaseName, \ template <typename gtest_TypeParam_> \
void GTEST_TEST_CLASS_NAME_(CaseName, \
TestName)<gtest_TypeParam_>::TestBody() TestName)<gtest_TypeParam_>::TestBody()
// Legacy API is deprecated but still available // Legacy API is deprecated but still available
@ -267,22 +268,23 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
TYPED_TEST_SUITE_P TYPED_TEST_SUITE_P
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ #endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
#define TYPED_TEST_P(SuiteName, TestName) \ #define TYPED_TEST_P(SuiteName, TestName) \
namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \ namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \
template <typename gtest_TypeParam_> \ template <typename gtest_TypeParam_> \
class TestName : public SuiteName<gtest_TypeParam_> { \ class TestName : public SuiteName<gtest_TypeParam_> { \
private: \ private: \
typedef SuiteName<gtest_TypeParam_> TestFixture; \ typedef SuiteName<gtest_TypeParam_> TestFixture; \
typedef gtest_TypeParam_ TypeParam; \ typedef gtest_TypeParam_ TypeParam; \
void TestBody() override; \ void TestBody() override; \
}; \ }; \
static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \ GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool \
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).AddTestName( \ gtest_##TestName##_defined_ = \
__FILE__, __LINE__, GTEST_STRINGIFY_(SuiteName), \ GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).AddTestName( \
GTEST_STRINGIFY_(TestName)); \ __FILE__, __LINE__, GTEST_STRINGIFY_(SuiteName), \
} \ GTEST_STRINGIFY_(TestName)); \
template <typename gtest_TypeParam_> \ } \
void GTEST_SUITE_NAMESPACE_( \ template <typename gtest_TypeParam_> \
void GTEST_SUITE_NAMESPACE_( \
SuiteName)::TestName<gtest_TypeParam_>::TestBody() SuiteName)::TestName<gtest_TypeParam_>::TestBody()
// Note: this won't work correctly if the trailing arguments are macros. // Note: this won't work correctly if the trailing arguments are macros.
@ -290,8 +292,8 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \ namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \
typedef ::testing::internal::Templates<__VA_ARGS__> gtest_AllTests_; \ typedef ::testing::internal::Templates<__VA_ARGS__> gtest_AllTests_; \
} \ } \
static const char* const GTEST_REGISTERED_TEST_NAMES_( \ GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static const char* const \
SuiteName) GTEST_ATTRIBUTE_UNUSED_ = \ GTEST_REGISTERED_TEST_NAMES_(SuiteName) = \
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).VerifyRegisteredTestNames( \ GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).VerifyRegisteredTestNames( \
GTEST_STRINGIFY_(SuiteName), __FILE__, __LINE__, #__VA_ARGS__) GTEST_STRINGIFY_(SuiteName), __FILE__, __LINE__, #__VA_ARGS__)
@ -303,22 +305,24 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
REGISTER_TYPED_TEST_SUITE_P REGISTER_TYPED_TEST_SUITE_P
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ #endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
#define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...) \ #define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...) \
static_assert(sizeof(GTEST_STRINGIFY_(Prefix)) > 1, \ static_assert(sizeof(GTEST_STRINGIFY_(Prefix)) > 1, \
"test-suit-prefix must not be empty"); \ "test-suit-prefix must not be empty"); \
static bool gtest_##Prefix##_##SuiteName GTEST_ATTRIBUTE_UNUSED_ = \ GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool \
::testing::internal::TypeParameterizedTestSuite< \ gtest_##Prefix##_##SuiteName = \
SuiteName, GTEST_SUITE_NAMESPACE_(SuiteName)::gtest_AllTests_, \ ::testing::internal::TypeParameterizedTestSuite< \
::testing::internal::GenerateTypeList<Types>::type>:: \ SuiteName, GTEST_SUITE_NAMESPACE_(SuiteName)::gtest_AllTests_, \
Register(GTEST_STRINGIFY_(Prefix), \ ::testing::internal::GenerateTypeList<Types>::type>:: \
::testing::internal::CodeLocation(__FILE__, __LINE__), \ Register( \
&GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName), \ GTEST_STRINGIFY_(Prefix), \
GTEST_STRINGIFY_(SuiteName), \ ::testing::internal::CodeLocation(__FILE__, __LINE__), \
GTEST_REGISTERED_TEST_NAMES_(SuiteName), \ &GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName), \
::testing::internal::GenerateNames< \ GTEST_STRINGIFY_(SuiteName), \
::testing::internal::NameGeneratorSelector< \ GTEST_REGISTERED_TEST_NAMES_(SuiteName), \
__VA_ARGS__>::type, \ ::testing::internal::GenerateNames< \
::testing::internal::GenerateTypeList<Types>::type>()) ::testing::internal::NameGeneratorSelector< \
__VA_ARGS__>::type, \
::testing::internal::GenerateTypeList<Types>::type>())
// Legacy API is deprecated but still available // Legacy API is deprecated but still available
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_

View File

@ -51,7 +51,6 @@
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <iomanip>
#include <limits> #include <limits>
#include <memory> #include <memory>
#include <ostream> #include <ostream>
@ -61,16 +60,16 @@
#include <type_traits> #include <type_traits>
#include <vector> #include <vector>
#include "gtest/gtest-assertion-result.h" #include "gtest/gtest-assertion-result.h" // IWYU pragma: export
#include "gtest/gtest-death-test.h" #include "gtest/gtest-death-test.h" // IWYU pragma: export
#include "gtest/gtest-matchers.h" #include "gtest/gtest-matchers.h" // IWYU pragma: export
#include "gtest/gtest-message.h" #include "gtest/gtest-message.h" // IWYU pragma: export
#include "gtest/gtest-param-test.h" #include "gtest/gtest-param-test.h" // IWYU pragma: export
#include "gtest/gtest-printers.h" #include "gtest/gtest-printers.h" // IWYU pragma: export
#include "gtest/gtest-test-part.h" #include "gtest/gtest-test-part.h" // IWYU pragma: export
#include "gtest/gtest-typed-test.h" #include "gtest/gtest-typed-test.h" // IWYU pragma: export
#include "gtest/gtest_pred_impl.h" #include "gtest/gtest_pred_impl.h" // IWYU pragma: export
#include "gtest/gtest_prod.h" #include "gtest/gtest_prod.h" // IWYU pragma: export
#include "gtest/internal/gtest-internal.h" #include "gtest/internal/gtest-internal.h"
#include "gtest/internal/gtest-string.h" #include "gtest/internal/gtest-string.h"
@ -608,7 +607,7 @@ class GTEST_API_ TestInfo {
friend class internal::UnitTestImpl; friend class internal::UnitTestImpl;
friend class internal::StreamingListenerTest; friend class internal::StreamingListenerTest;
friend TestInfo* internal::MakeAndRegisterTestInfo( friend TestInfo* internal::MakeAndRegisterTestInfo(
const char* test_suite_name, const char* name, const char* type_param, std::string test_suite_name, const char* name, const char* type_param,
const char* value_param, internal::CodeLocation code_location, const char* value_param, internal::CodeLocation code_location,
internal::TypeId fixture_class_id, internal::SetUpTestSuiteFunc set_up_tc, internal::TypeId fixture_class_id, internal::SetUpTestSuiteFunc set_up_tc,
internal::TearDownTestSuiteFunc tear_down_tc, internal::TearDownTestSuiteFunc tear_down_tc,
@ -616,7 +615,7 @@ class GTEST_API_ TestInfo {
// Constructs a TestInfo object. The newly constructed instance assumes // Constructs a TestInfo object. The newly constructed instance assumes
// ownership of the factory object. // ownership of the factory object.
TestInfo(const std::string& test_suite_name, const std::string& name, TestInfo(std::string test_suite_name, std::string name,
const char* a_type_param, // NULL if not a type-parameterized test const char* a_type_param, // NULL if not a type-parameterized test
const char* a_value_param, // NULL if not a value-parameterized test const char* a_value_param, // NULL if not a value-parameterized test
internal::CodeLocation a_code_location, internal::CodeLocation a_code_location,
@ -684,7 +683,7 @@ class GTEST_API_ TestSuite {
// this is not a type-parameterized test. // this is not a type-parameterized test.
// set_up_tc: pointer to the function that sets up the test suite // set_up_tc: pointer to the function that sets up the test suite
// tear_down_tc: pointer to the function that tears down the test suite // tear_down_tc: pointer to the function that tears down the test suite
TestSuite(const char* name, const char* a_type_param, TestSuite(const std::string& name, const char* a_type_param,
internal::SetUpTestSuiteFunc set_up_tc, internal::SetUpTestSuiteFunc set_up_tc,
internal::TearDownTestSuiteFunc tear_down_tc); internal::TearDownTestSuiteFunc tear_down_tc);
@ -1263,6 +1262,20 @@ class GTEST_API_ UnitTest {
// total_test_suite_count() - 1. If i is not in that range, returns NULL. // total_test_suite_count() - 1. If i is not in that range, returns NULL.
TestSuite* GetMutableTestSuite(int i); TestSuite* GetMutableTestSuite(int i);
// Invokes OsStackTrackGetterInterface::UponLeavingGTest. UponLeavingGTest()
// should be called immediately before Google Test calls user code. It saves
// some information about the current stack that CurrentStackTrace() will use
// to find and hide Google Test stack frames.
void UponLeavingGTest();
// Sets the TestSuite object for the test that's currently running.
void set_current_test_suite(TestSuite* a_current_test_suite)
GTEST_LOCK_EXCLUDED_(mutex_);
// Sets the TestInfo object for the test that's currently running.
void set_current_test_info(TestInfo* a_current_test_info)
GTEST_LOCK_EXCLUDED_(mutex_);
// Accessors for the implementation object. // Accessors for the implementation object.
internal::UnitTestImpl* impl() { return impl_; } internal::UnitTestImpl* impl() { return impl_; }
const internal::UnitTestImpl* impl() const { return impl_; } const internal::UnitTestImpl* impl() const { return impl_; }
@ -1271,6 +1284,8 @@ class GTEST_API_ UnitTest {
// members of UnitTest. // members of UnitTest.
friend class ScopedTrace; friend class ScopedTrace;
friend class Test; friend class Test;
friend class TestInfo;
friend class TestSuite;
friend class internal::AssertHelper; friend class internal::AssertHelper;
friend class internal::StreamingListenerTest; friend class internal::StreamingListenerTest;
friend class internal::UnitTestRecordPropertyTestHelper; friend class internal::UnitTestRecordPropertyTestHelper;
@ -1574,12 +1589,12 @@ AssertionResult CmpHelperFloatingPointEQ(const char* lhs_expression,
} }
::std::stringstream lhs_ss; ::std::stringstream lhs_ss;
lhs_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2) lhs_ss.precision(std::numeric_limits<RawType>::digits10 + 2);
<< lhs_value; lhs_ss << lhs_value;
::std::stringstream rhs_ss; ::std::stringstream rhs_ss;
rhs_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2) rhs_ss.precision(std::numeric_limits<RawType>::digits10 + 2);
<< rhs_value; rhs_ss << rhs_value;
return EqFailure(lhs_expression, rhs_expression, return EqFailure(lhs_expression, rhs_expression,
StringStreamToString(&lhs_ss), StringStreamToString(&rhs_ss), StringStreamToString(&lhs_ss), StringStreamToString(&rhs_ss),
@ -1752,6 +1767,7 @@ class TestWithParam : public Test, public WithParamInterface<T> {};
// generic name and clashes with some other libraries. // generic name and clashes with some other libraries.
#if !(defined(GTEST_DONT_DEFINE_FAIL) && GTEST_DONT_DEFINE_FAIL) #if !(defined(GTEST_DONT_DEFINE_FAIL) && GTEST_DONT_DEFINE_FAIL)
#define FAIL() GTEST_FAIL() #define FAIL() GTEST_FAIL()
#define FAIL_AT(file, line) GTEST_FAIL_AT(file, line)
#endif #endif
// Generates a success with a generic message. // Generates a success with a generic message.
@ -2308,7 +2324,8 @@ TestInfo* RegisterTest(const char* test_suite_name, const char* test_name,
// tests are successful, or 1 otherwise. // tests are successful, or 1 otherwise.
// //
// RUN_ALL_TESTS() should be invoked after the command line has been // RUN_ALL_TESTS() should be invoked after the command line has been
// parsed by InitGoogleTest(). // parsed by InitGoogleTest(). RUN_ALL_TESTS will tear down and delete any
// installed environments and should only be called once per binary.
// //
// This function was formerly a macro; thus, it is in the global // This function was formerly a macro; thus, it is in the global
// namespace and has an all-caps name. // namespace and has an all-caps name.

View File

@ -46,17 +46,38 @@
#include "gtest/gtest-matchers.h" #include "gtest/gtest-matchers.h"
#include "gtest/internal/gtest-internal.h" #include "gtest/internal/gtest-internal.h"
#include "gtest/internal/gtest-port.h"
GTEST_DECLARE_string_(internal_run_death_test); GTEST_DECLARE_string_(internal_run_death_test);
namespace testing { namespace testing {
namespace internal { namespace internal {
// Names of the flags (needed for parsing Google Test flags). // Name of the flag (needed for parsing Google Test flag).
const char kDeathTestStyleFlag[] = "death_test_style";
const char kDeathTestUseFork[] = "death_test_use_fork";
const char kInternalRunDeathTestFlag[] = "internal_run_death_test"; const char kInternalRunDeathTestFlag[] = "internal_run_death_test";
// A string passed to EXPECT_DEATH (etc.) is caught by one of these overloads
// and interpreted as a regex (rather than an Eq matcher) for legacy
// compatibility.
inline Matcher<const ::std::string&> MakeDeathTestMatcher(
::testing::internal::RE regex) {
return ContainsRegex(regex.pattern());
}
inline Matcher<const ::std::string&> MakeDeathTestMatcher(const char* regex) {
return ContainsRegex(regex);
}
inline Matcher<const ::std::string&> MakeDeathTestMatcher(
const ::std::string& regex) {
return ContainsRegex(regex);
}
// If a Matcher<const ::std::string&> is passed to EXPECT_DEATH (etc.), it's
// used directly.
inline Matcher<const ::std::string&> MakeDeathTestMatcher(
Matcher<const ::std::string&> matcher) {
return matcher;
}
#ifdef GTEST_HAS_DEATH_TEST #ifdef GTEST_HAS_DEATH_TEST
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
@ -73,7 +94,7 @@ GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
// //
// exit status: The integer exit information in the format specified // exit status: The integer exit information in the format specified
// by wait(2) // by wait(2)
// exit code: The integer code passed to exit(3), _exit(2), or // exit code: The integer code passed to exit(3), _Exit(2), or
// returned from main() // returned from main()
class GTEST_API_ DeathTest { class GTEST_API_ DeathTest {
public: public:
@ -170,28 +191,6 @@ class DefaultDeathTestFactory : public DeathTestFactory {
// by a signal, or exited normally with a nonzero exit code. // by a signal, or exited normally with a nonzero exit code.
GTEST_API_ bool ExitedUnsuccessfully(int exit_status); GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
// A string passed to EXPECT_DEATH (etc.) is caught by one of these overloads
// and interpreted as a regex (rather than an Eq matcher) for legacy
// compatibility.
inline Matcher<const ::std::string&> MakeDeathTestMatcher(
::testing::internal::RE regex) {
return ContainsRegex(regex.pattern());
}
inline Matcher<const ::std::string&> MakeDeathTestMatcher(const char* regex) {
return ContainsRegex(regex);
}
inline Matcher<const ::std::string&> MakeDeathTestMatcher(
const ::std::string& regex) {
return ContainsRegex(regex);
}
// If a Matcher<const ::std::string&> is passed to EXPECT_DEATH (etc.), it's
// used directly.
inline Matcher<const ::std::string&> MakeDeathTestMatcher(
Matcher<const ::std::string&> matcher) {
return matcher;
}
// Traps C++ exceptions escaping statement and reports them as test // Traps C++ exceptions escaping statement and reports them as test
// failures. Note that trapping SEH exceptions is not implemented here. // failures. Note that trapping SEH exceptions is not implemented here.
#if GTEST_HAS_EXCEPTIONS #if GTEST_HAS_EXCEPTIONS

View File

@ -43,6 +43,7 @@
#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ #define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
#include <string> #include <string>
#include <utility>
#include "gtest/internal/gtest-port.h" #include "gtest/internal/gtest-port.h"
#include "gtest/internal/gtest-string.h" #include "gtest/internal/gtest-string.h"
@ -70,8 +71,9 @@ class GTEST_API_ FilePath {
public: public:
FilePath() : pathname_("") {} FilePath() : pathname_("") {}
FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) {} FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) {}
FilePath(FilePath&& rhs) noexcept : pathname_(std::move(rhs.pathname_)) {}
explicit FilePath(const std::string& pathname) : pathname_(pathname) { explicit FilePath(std::string pathname) : pathname_(std::move(pathname)) {
Normalize(); Normalize();
} }
@ -79,6 +81,10 @@ class GTEST_API_ FilePath {
Set(rhs); Set(rhs);
return *this; return *this;
} }
FilePath& operator=(FilePath&& rhs) noexcept {
pathname_ = std::move(rhs.pathname_);
return *this;
}
void Set(const FilePath& rhs) { pathname_ = rhs.pathname_; } void Set(const FilePath& rhs) { pathname_ = rhs.pathname_; }

View File

@ -58,7 +58,6 @@
#include <cstdint> #include <cstdint>
#include <functional> #include <functional>
#include <iomanip>
#include <limits> #include <limits>
#include <map> #include <map>
#include <set> #include <set>
@ -79,7 +78,7 @@
// //
// will result in the token foo__LINE__, instead of foo followed by // will result in the token foo__LINE__, instead of foo followed by
// the current line number. For more details, see // the current line number. For more details, see
// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6 // https://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6
#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar) #define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar)
#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo##bar #define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo##bar
@ -170,7 +169,7 @@ namespace edit_distance {
// All edits cost the same, with replace having lower priority than // All edits cost the same, with replace having lower priority than
// add/remove. // add/remove.
// Simple implementation of the Wagner-Fischer algorithm. // Simple implementation of the Wagner-Fischer algorithm.
// See http://en.wikipedia.org/wiki/Wagner-Fischer_algorithm // See https://en.wikipedia.org/wiki/Wagner-Fischer_algorithm
enum EditType { kMatch, kAdd, kRemove, kReplace }; enum EditType { kMatch, kAdd, kRemove, kReplace };
GTEST_API_ std::vector<EditType> CalculateOptimalEdits( GTEST_API_ std::vector<EditType> CalculateOptimalEdits(
const std::vector<size_t>& left, const std::vector<size_t>& right); const std::vector<size_t>& left, const std::vector<size_t>& right);
@ -237,7 +236,7 @@ GTEST_API_ std::string GetBoolAssertionFailureMessage(
// For double, there are 11 exponent bits and 52 fraction bits. // For double, there are 11 exponent bits and 52 fraction bits.
// //
// More details can be found at // More details can be found at
// http://en.wikipedia.org/wiki/IEEE_floating-point_standard. // https://en.wikipedia.org/wiki/IEEE_floating-point_standard.
// //
// Template parameter: // Template parameter:
// //
@ -282,7 +281,7 @@ class FloatingPoint {
// bits. Therefore, 4 should be enough for ordinary use. // bits. Therefore, 4 should be enough for ordinary use.
// //
// See the following article for more details on ULP: // See the following article for more details on ULP:
// http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ // https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
static const uint32_t kMaxUlps = 4; static const uint32_t kMaxUlps = 4;
// Constructs a FloatingPoint from a raw floating-point number. // Constructs a FloatingPoint from a raw floating-point number.
@ -363,7 +362,7 @@ class FloatingPoint {
// N - 1 (the biggest number representable using // N - 1 (the biggest number representable using
// sign-and-magnitude) is represented by 2N - 1. // sign-and-magnitude) is represented by 2N - 1.
// //
// Read http://en.wikipedia.org/wiki/Signed_number_representations // Read https://en.wikipedia.org/wiki/Signed_number_representations
// for more details on signed number representations. // for more details on signed number representations.
static Bits SignAndMagnitudeToBiased(const Bits& sam) { static Bits SignAndMagnitudeToBiased(const Bits& sam) {
if (kSignBitMask & sam) { if (kSignBitMask & sam) {
@ -475,8 +474,8 @@ using SetUpTestSuiteFunc = void (*)();
using TearDownTestSuiteFunc = void (*)(); using TearDownTestSuiteFunc = void (*)();
struct CodeLocation { struct CodeLocation {
CodeLocation(const std::string& a_file, int a_line) CodeLocation(std::string a_file, int a_line)
: file(a_file), line(a_line) {} : file(std::move(a_file)), line(a_line) {}
std::string file; std::string file;
int line; int line;
@ -556,7 +555,7 @@ struct SuiteApiResolver : T {
// type_param: the name of the test's type parameter, or NULL if // type_param: the name of the test's type parameter, or NULL if
// this is not a typed or a type-parameterized test. // this is not a typed or a type-parameterized test.
// value_param: text representation of the test's value parameter, // value_param: text representation of the test's value parameter,
// or NULL if this is not a type-parameterized test. // or NULL if this is not a value-parameterized test.
// code_location: code location where the test is defined // code_location: code location where the test is defined
// fixture_class_id: ID of the test fixture class // fixture_class_id: ID of the test fixture class
// set_up_tc: pointer to the function that sets up the test suite // set_up_tc: pointer to the function that sets up the test suite
@ -565,7 +564,7 @@ struct SuiteApiResolver : T {
// The newly created TestInfo instance will assume // The newly created TestInfo instance will assume
// ownership of the factory object. // ownership of the factory object.
GTEST_API_ TestInfo* MakeAndRegisterTestInfo( GTEST_API_ TestInfo* MakeAndRegisterTestInfo(
const char* test_suite_name, const char* name, const char* type_param, std::string test_suite_name, const char* name, const char* type_param,
const char* value_param, CodeLocation code_location, const char* value_param, CodeLocation code_location,
TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc, TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc,
TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory); TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory);
@ -596,8 +595,7 @@ class GTEST_API_ TypedTestSuitePState {
fflush(stderr); fflush(stderr);
posix::Abort(); posix::Abort();
} }
registered_tests_.insert( registered_tests_.emplace(test_name, CodeLocation(file, line));
::std::make_pair(test_name, CodeLocation(file, line)));
return true; return true;
} }
@ -701,7 +699,7 @@ class TypeParameterizedTest {
// specified in INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, TestSuite, // specified in INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, TestSuite,
// Types). Valid values for 'index' are [0, N - 1] where N is the // Types). Valid values for 'index' are [0, N - 1] where N is the
// length of Types. // length of Types.
static bool Register(const char* prefix, const CodeLocation& code_location, static bool Register(const char* prefix, CodeLocation code_location,
const char* case_name, const char* test_names, int index, const char* case_name, const char* test_names, int index,
const std::vector<std::string>& type_names = const std::vector<std::string>& type_names =
GenerateNames<DefaultNameGenerator, Types>()) { GenerateNames<DefaultNameGenerator, Types>()) {
@ -713,8 +711,7 @@ class TypeParameterizedTest {
// list. // list.
MakeAndRegisterTestInfo( MakeAndRegisterTestInfo(
(std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name + (std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name +
"/" + type_names[static_cast<size_t>(index)]) "/" + type_names[static_cast<size_t>(index)]),
.c_str(),
StripTrailingSpaces(GetPrefixUntilComma(test_names)).c_str(), StripTrailingSpaces(GetPrefixUntilComma(test_names)).c_str(),
GetTypeName<Type>().c_str(), GetTypeName<Type>().c_str(),
nullptr, // No value parameter. nullptr, // No value parameter.
@ -726,13 +723,9 @@ class TypeParameterizedTest {
new TestFactoryImpl<TestClass>); new TestFactoryImpl<TestClass>);
// Next, recurses (at compile time) with the tail of the type list. // Next, recurses (at compile time) with the tail of the type list.
return TypeParameterizedTest<Fixture, TestSel, return TypeParameterizedTest<Fixture, TestSel, typename Types::Tail>::
typename Types::Tail>::Register(prefix, Register(prefix, std::move(code_location), case_name, test_names,
code_location, index + 1, type_names);
case_name,
test_names,
index + 1,
type_names);
} }
}; };
@ -740,7 +733,7 @@ class TypeParameterizedTest {
template <GTEST_TEMPLATE_ Fixture, class TestSel> template <GTEST_TEMPLATE_ Fixture, class TestSel>
class TypeParameterizedTest<Fixture, TestSel, internal::None> { class TypeParameterizedTest<Fixture, TestSel, internal::None> {
public: public:
static bool Register(const char* /*prefix*/, const CodeLocation&, static bool Register(const char* /*prefix*/, CodeLocation,
const char* /*case_name*/, const char* /*test_names*/, const char* /*case_name*/, const char* /*test_names*/,
int /*index*/, int /*index*/,
const std::vector<std::string>& = const std::vector<std::string>& =
@ -787,7 +780,8 @@ class TypeParameterizedTestSuite {
// Next, recurses (at compile time) with the tail of the test list. // Next, recurses (at compile time) with the tail of the test list.
return TypeParameterizedTestSuite<Fixture, typename Tests::Tail, return TypeParameterizedTestSuite<Fixture, typename Tests::Tail,
Types>::Register(prefix, code_location, Types>::Register(prefix,
std::move(code_location),
state, case_name, state, case_name,
SkipComma(test_names), SkipComma(test_names),
type_names); type_names);
@ -1143,40 +1137,6 @@ class NativeArray {
void (NativeArray::*clone_)(const Element*, size_t); void (NativeArray::*clone_)(const Element*, size_t);
}; };
// Backport of std::index_sequence.
template <size_t... Is>
struct IndexSequence {
using type = IndexSequence;
};
// Double the IndexSequence, and one if plus_one is true.
template <bool plus_one, typename T, size_t sizeofT>
struct DoubleSequence;
template <size_t... I, size_t sizeofT>
struct DoubleSequence<true, IndexSequence<I...>, sizeofT> {
using type = IndexSequence<I..., (sizeofT + I)..., 2 * sizeofT>;
};
template <size_t... I, size_t sizeofT>
struct DoubleSequence<false, IndexSequence<I...>, sizeofT> {
using type = IndexSequence<I..., (sizeofT + I)...>;
};
// Backport of std::make_index_sequence.
// It uses O(ln(N)) instantiation depth.
template <size_t N>
struct MakeIndexSequenceImpl
: DoubleSequence<N % 2 == 1, typename MakeIndexSequenceImpl<N / 2>::type,
N / 2>::type {};
template <>
struct MakeIndexSequenceImpl<0> : IndexSequence<> {};
template <size_t N>
using MakeIndexSequence = typename MakeIndexSequenceImpl<N>::type;
template <typename... T>
using IndexSequenceFor = typename MakeIndexSequence<sizeof...(T)>::type;
template <size_t> template <size_t>
struct Ignore { struct Ignore {
Ignore(...); // NOLINT Ignore(...); // NOLINT
@ -1185,7 +1145,7 @@ struct Ignore {
template <typename> template <typename>
struct ElemFromListImpl; struct ElemFromListImpl;
template <size_t... I> template <size_t... I>
struct ElemFromListImpl<IndexSequence<I...>> { struct ElemFromListImpl<std::index_sequence<I...>> {
// We make Ignore a template to solve a problem with MSVC. // We make Ignore a template to solve a problem with MSVC.
// A non-template Ignore would work fine with `decltype(Ignore(I))...`, but // A non-template Ignore would work fine with `decltype(Ignore(I))...`, but
// MSVC doesn't understand how to deal with that pack expansion. // MSVC doesn't understand how to deal with that pack expansion.
@ -1196,9 +1156,8 @@ struct ElemFromListImpl<IndexSequence<I...>> {
template <size_t N, typename... T> template <size_t N, typename... T>
struct ElemFromList { struct ElemFromList {
using type = using type = decltype(ElemFromListImpl<std::make_index_sequence<N>>::Apply(
decltype(ElemFromListImpl<typename MakeIndexSequence<N>::type>::Apply( static_cast<T (*)()>(nullptr)...));
static_cast<T (*)()>(nullptr)...));
}; };
struct FlatTupleConstructTag {}; struct FlatTupleConstructTag {};
@ -1223,9 +1182,9 @@ template <typename Derived, typename Idx>
struct FlatTupleBase; struct FlatTupleBase;
template <size_t... Idx, typename... T> template <size_t... Idx, typename... T>
struct FlatTupleBase<FlatTuple<T...>, IndexSequence<Idx...>> struct FlatTupleBase<FlatTuple<T...>, std::index_sequence<Idx...>>
: FlatTupleElemBase<FlatTuple<T...>, Idx>... { : FlatTupleElemBase<FlatTuple<T...>, Idx>... {
using Indices = IndexSequence<Idx...>; using Indices = std::index_sequence<Idx...>;
FlatTupleBase() = default; FlatTupleBase() = default;
template <typename... Args> template <typename... Args>
explicit FlatTupleBase(FlatTupleConstructTag, Args&&... args) explicit FlatTupleBase(FlatTupleConstructTag, Args&&... args)
@ -1260,14 +1219,15 @@ struct FlatTupleBase<FlatTuple<T...>, IndexSequence<Idx...>>
// implementations. // implementations.
// FlatTuple and ElemFromList are not recursive and have a fixed depth // FlatTuple and ElemFromList are not recursive and have a fixed depth
// regardless of T... // regardless of T...
// MakeIndexSequence, on the other hand, it is recursive but with an // std::make_index_sequence, on the other hand, it is recursive but with an
// instantiation depth of O(ln(N)). // instantiation depth of O(ln(N)).
template <typename... T> template <typename... T>
class FlatTuple class FlatTuple
: private FlatTupleBase<FlatTuple<T...>, : private FlatTupleBase<FlatTuple<T...>,
typename MakeIndexSequence<sizeof...(T)>::type> { std::make_index_sequence<sizeof...(T)>> {
using Indices = typename FlatTupleBase< using Indices =
FlatTuple<T...>, typename MakeIndexSequence<sizeof...(T)>::type>::Indices; typename FlatTupleBase<FlatTuple<T...>,
std::make_index_sequence<sizeof...(T)>>::Indices;
public: public:
FlatTuple() = default; FlatTuple() = default;
@ -1541,7 +1501,8 @@ class NeverThrown {
\ \
private: \ private: \
void TestBody() override; \ void TestBody() override; \
static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_; \ GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static ::testing::TestInfo* const \
test_info_; \
}; \ }; \
\ \
::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name, \ ::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name, \

View File

@ -47,6 +47,7 @@
#include <string> #include <string>
#include <tuple> #include <tuple>
#include <type_traits> #include <type_traits>
#include <unordered_map>
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -85,7 +86,7 @@ namespace internal {
// TEST_P macro is used to define two tests with the same name // TEST_P macro is used to define two tests with the same name
// but in different namespaces. // but in different namespaces.
GTEST_API_ void ReportInvalidTestSuiteType(const char* test_suite_name, GTEST_API_ void ReportInvalidTestSuiteType(const char* test_suite_name,
CodeLocation code_location); const CodeLocation& code_location);
template <typename> template <typename>
class ParamGeneratorInterface; class ParamGeneratorInterface;
@ -379,9 +380,7 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
// integer test parameter index. // integer test parameter index.
template <class ParamType> template <class ParamType>
std::string DefaultParamName(const TestParamInfo<ParamType>& info) { std::string DefaultParamName(const TestParamInfo<ParamType>& info) {
Message name_stream; return std::to_string(info.index);
name_stream << info.index;
return name_stream.GetString();
} }
template <typename T = int> template <typename T = int>
@ -513,9 +512,10 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
typedef ParamGenerator<ParamType>(GeneratorCreationFunc)(); typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
using ParamNameGeneratorFunc = std::string(const TestParamInfo<ParamType>&); using ParamNameGeneratorFunc = std::string(const TestParamInfo<ParamType>&);
explicit ParameterizedTestSuiteInfo(const char* name, explicit ParameterizedTestSuiteInfo(std::string name,
CodeLocation code_location) CodeLocation code_location)
: test_suite_name_(name), code_location_(code_location) {} : test_suite_name_(std::move(name)),
code_location_(std::move(code_location)) {}
// Test suite base name for display purposes. // Test suite base name for display purposes.
const std::string& GetTestSuiteName() const override { const std::string& GetTestSuiteName() const override {
@ -529,20 +529,21 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
// prefix). test_base_name is the name of an individual test without // prefix). test_base_name is the name of an individual test without
// parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
// test suite base name and DoBar is test base name. // test suite base name and DoBar is test base name.
void AddTestPattern(const char* test_suite_name, const char* test_base_name, void AddTestPattern(const char*,
const char* test_base_name,
TestMetaFactoryBase<ParamType>* meta_factory, TestMetaFactoryBase<ParamType>* meta_factory,
CodeLocation code_location) { CodeLocation code_location) {
tests_.push_back(std::shared_ptr<TestInfo>(new TestInfo( tests_.emplace_back(
test_suite_name, test_base_name, meta_factory, code_location))); new TestInfo(test_base_name, meta_factory, std::move(code_location)));
} }
// INSTANTIATE_TEST_SUITE_P macro uses AddGenerator() to record information // INSTANTIATE_TEST_SUITE_P macro uses AddGenerator() to record information
// about a generator. // about a generator.
int AddTestSuiteInstantiation(const std::string& instantiation_name, int AddTestSuiteInstantiation(std::string instantiation_name,
GeneratorCreationFunc* func, GeneratorCreationFunc* func,
ParamNameGeneratorFunc* name_func, ParamNameGeneratorFunc* name_func,
const char* file, int line) { const char* file, int line) {
instantiations_.push_back( instantiations_.emplace_back(std::move(instantiation_name), func, name_func,
InstantiationInfo(instantiation_name, func, name_func, file, line)); file, line);
return 0; // Return value used only to run this method in namespace scope. return 0; // Return value used only to run this method in namespace scope.
} }
// UnitTest class invokes this method to register tests in this test suite // UnitTest class invokes this method to register tests in this test suite
@ -553,60 +554,61 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
void RegisterTests() override { void RegisterTests() override {
bool generated_instantiations = false; bool generated_instantiations = false;
for (typename TestInfoContainer::iterator test_it = tests_.begin(); std::string test_suite_name;
test_it != tests_.end(); ++test_it) { std::string test_name;
std::shared_ptr<TestInfo> test_info = *test_it; for (const std::shared_ptr<TestInfo>& test_info : tests_) {
for (typename InstantiationContainer::iterator gen_it = for (const InstantiationInfo& instantiation : instantiations_) {
instantiations_.begin(); const std::string& instantiation_name = instantiation.name;
gen_it != instantiations_.end(); ++gen_it) { ParamGenerator<ParamType> generator((*instantiation.generator)());
const std::string& instantiation_name = gen_it->name; ParamNameGeneratorFunc* name_func = instantiation.name_func;
ParamGenerator<ParamType> generator((*gen_it->generator)()); const char* file = instantiation.file;
ParamNameGeneratorFunc* name_func = gen_it->name_func; int line = instantiation.line;
const char* file = gen_it->file;
int line = gen_it->line;
std::string test_suite_name;
if (!instantiation_name.empty()) if (!instantiation_name.empty())
test_suite_name = instantiation_name + "/"; test_suite_name = instantiation_name + "/";
test_suite_name += test_info->test_suite_base_name; else
test_suite_name.clear();
test_suite_name += test_suite_name_;
size_t i = 0; size_t i = 0;
std::set<std::string> test_param_names; std::set<std::string> test_param_names;
for (typename ParamGenerator<ParamType>::iterator param_it = for (const auto& param : generator) {
generator.begin();
param_it != generator.end(); ++param_it, ++i) {
generated_instantiations = true; generated_instantiations = true;
Message test_name_stream; test_name.clear();
std::string param_name = std::string param_name =
name_func(TestParamInfo<ParamType>(*param_it, i)); name_func(TestParamInfo<ParamType>(param, i));
GTEST_CHECK_(IsValidParamName(param_name)) GTEST_CHECK_(IsValidParamName(param_name))
<< "Parameterized test name '" << param_name << "Parameterized test name '" << param_name
<< "' is invalid, in " << file << " line " << line << std::endl; << "' is invalid (contains spaces, dashes, or any "
"non-alphanumeric characters other than underscores), in "
<< file << " line " << line << "" << std::endl;
GTEST_CHECK_(test_param_names.count(param_name) == 0) GTEST_CHECK_(test_param_names.count(param_name) == 0)
<< "Duplicate parameterized test name '" << param_name << "', in " << "Duplicate parameterized test name '" << param_name << "', in "
<< file << " line " << line << std::endl; << file << " line " << line << std::endl;
test_param_names.insert(param_name);
if (!test_info->test_base_name.empty()) { if (!test_info->test_base_name.empty()) {
test_name_stream << test_info->test_base_name << "/"; test_name.append(test_info->test_base_name).append("/");
} }
test_name_stream << param_name; test_name += param_name;
test_param_names.insert(std::move(param_name));
MakeAndRegisterTestInfo( MakeAndRegisterTestInfo(
test_suite_name.c_str(), test_name_stream.GetString().c_str(), test_suite_name, test_name.c_str(),
nullptr, // No type parameter. nullptr, // No type parameter.
PrintToString(*param_it).c_str(), test_info->code_location, PrintToString(param).c_str(), test_info->code_location,
GetTestSuiteTypeId(), GetTestSuiteTypeId(),
SuiteApiResolver<TestSuite>::GetSetUpCaseOrSuite(file, line), SuiteApiResolver<TestSuite>::GetSetUpCaseOrSuite(file, line),
SuiteApiResolver<TestSuite>::GetTearDownCaseOrSuite(file, line), SuiteApiResolver<TestSuite>::GetTearDownCaseOrSuite(file, line),
test_info->test_meta_factory->CreateTestFactory(*param_it)); test_info->test_meta_factory->CreateTestFactory(param));
} // for param_it ++i;
} // for gen_it } // for param
} // for test_it } // for instantiation
} // for test_info
if (!generated_instantiations) { if (!generated_instantiations) {
// There are no generaotrs, or they all generate nothing ... // There are no generaotrs, or they all generate nothing ...
@ -619,15 +621,13 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
// LocalTestInfo structure keeps information about a single test registered // LocalTestInfo structure keeps information about a single test registered
// with TEST_P macro. // with TEST_P macro.
struct TestInfo { struct TestInfo {
TestInfo(const char* a_test_suite_base_name, const char* a_test_base_name, TestInfo(const char* a_test_base_name,
TestMetaFactoryBase<ParamType>* a_test_meta_factory, TestMetaFactoryBase<ParamType>* a_test_meta_factory,
CodeLocation a_code_location) CodeLocation a_code_location)
: test_suite_base_name(a_test_suite_base_name), : test_base_name(a_test_base_name),
test_base_name(a_test_base_name),
test_meta_factory(a_test_meta_factory), test_meta_factory(a_test_meta_factory),
code_location(a_code_location) {} code_location(std::move(a_code_location)) {}
const std::string test_suite_base_name;
const std::string test_base_name; const std::string test_base_name;
const std::unique_ptr<TestMetaFactoryBase<ParamType>> test_meta_factory; const std::unique_ptr<TestMetaFactoryBase<ParamType>> test_meta_factory;
const CodeLocation code_location; const CodeLocation code_location;
@ -637,11 +637,10 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
// <Instantiation name, Sequence generator creation function, // <Instantiation name, Sequence generator creation function,
// Name generator function, Source file, Source line> // Name generator function, Source file, Source line>
struct InstantiationInfo { struct InstantiationInfo {
InstantiationInfo(const std::string& name_in, InstantiationInfo(std::string name_in, GeneratorCreationFunc* generator_in,
GeneratorCreationFunc* generator_in,
ParamNameGeneratorFunc* name_func_in, const char* file_in, ParamNameGeneratorFunc* name_func_in, const char* file_in,
int line_in) int line_in)
: name(name_in), : name(std::move(name_in)),
generator(generator_in), generator(generator_in),
name_func(name_func_in), name_func(name_func_in),
file(file_in), file(file_in),
@ -702,29 +701,32 @@ class ParameterizedTestSuiteRegistry {
// tests and instantiations of a particular test suite. // tests and instantiations of a particular test suite.
template <class TestSuite> template <class TestSuite>
ParameterizedTestSuiteInfo<TestSuite>* GetTestSuitePatternHolder( ParameterizedTestSuiteInfo<TestSuite>* GetTestSuitePatternHolder(
const char* test_suite_name, CodeLocation code_location) { std::string test_suite_name, CodeLocation code_location) {
ParameterizedTestSuiteInfo<TestSuite>* typed_test_info = nullptr; ParameterizedTestSuiteInfo<TestSuite>* typed_test_info = nullptr;
for (auto& test_suite_info : test_suite_infos_) {
if (test_suite_info->GetTestSuiteName() == test_suite_name) { auto item_it = suite_name_to_info_index_.find(test_suite_name);
if (test_suite_info->GetTestSuiteTypeId() != GetTypeId<TestSuite>()) { if (item_it != suite_name_to_info_index_.end()) {
// Complain about incorrect usage of Google Test facilities auto* test_suite_info = test_suite_infos_[item_it->second];
// and terminate the program since we cannot guaranty correct if (test_suite_info->GetTestSuiteTypeId() != GetTypeId<TestSuite>()) {
// test suite setup and tear-down in this case. // Complain about incorrect usage of Google Test facilities
ReportInvalidTestSuiteType(test_suite_name, code_location); // and terminate the program since we cannot guaranty correct
posix::Abort(); // test suite setup and tear-down in this case.
} else { ReportInvalidTestSuiteType(test_suite_name.c_str(), code_location);
// At this point we are sure that the object we found is of the same posix::Abort();
// type we are looking for, so we downcast it to that type } else {
// without further checks. // At this point we are sure that the object we found is of the same
typed_test_info = CheckedDowncastToActualType< // type we are looking for, so we downcast it to that type
ParameterizedTestSuiteInfo<TestSuite>>(test_suite_info); // without further checks.
} typed_test_info =
break; CheckedDowncastToActualType<ParameterizedTestSuiteInfo<TestSuite>>(
test_suite_info);
} }
} }
if (typed_test_info == nullptr) { if (typed_test_info == nullptr) {
typed_test_info = new ParameterizedTestSuiteInfo<TestSuite>( typed_test_info = new ParameterizedTestSuiteInfo<TestSuite>(
test_suite_name, code_location); test_suite_name, std::move(code_location));
suite_name_to_info_index_.emplace(std::move(test_suite_name),
test_suite_infos_.size());
test_suite_infos_.push_back(typed_test_info); test_suite_infos_.push_back(typed_test_info);
} }
return typed_test_info; return typed_test_info;
@ -738,8 +740,9 @@ class ParameterizedTestSuiteRegistry {
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
template <class TestCase> template <class TestCase>
ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder( ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
const char* test_case_name, CodeLocation code_location) { std::string test_case_name, CodeLocation code_location) {
return GetTestSuitePatternHolder<TestCase>(test_case_name, code_location); return GetTestSuitePatternHolder<TestCase>(std::move(test_case_name),
std::move(code_location));
} }
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ #endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
@ -748,6 +751,7 @@ class ParameterizedTestSuiteRegistry {
using TestSuiteInfoContainer = ::std::vector<ParameterizedTestSuiteInfoBase*>; using TestSuiteInfoContainer = ::std::vector<ParameterizedTestSuiteInfoBase*>;
TestSuiteInfoContainer test_suite_infos_; TestSuiteInfoContainer test_suite_infos_;
::std::unordered_map<std::string, size_t> suite_name_to_info_index_;
ParameterizedTestSuiteRegistry(const ParameterizedTestSuiteRegistry&) = ParameterizedTestSuiteRegistry(const ParameterizedTestSuiteRegistry&) =
delete; delete;
@ -774,7 +778,7 @@ class TypeParameterizedTestSuiteRegistry {
private: private:
struct TypeParameterizedTestSuiteInfo { struct TypeParameterizedTestSuiteInfo {
explicit TypeParameterizedTestSuiteInfo(CodeLocation c) explicit TypeParameterizedTestSuiteInfo(CodeLocation c)
: code_location(c), instantiated(false) {} : code_location(std::move(c)), instantiated(false) {}
CodeLocation code_location; CodeLocation code_location;
bool instantiated; bool instantiated;
@ -803,12 +807,12 @@ class ValueArray {
template <typename T> template <typename T>
operator ParamGenerator<T>() const { // NOLINT operator ParamGenerator<T>() const { // NOLINT
return ValuesIn(MakeVector<T>(MakeIndexSequence<sizeof...(Ts)>())); return ValuesIn(MakeVector<T>(std::make_index_sequence<sizeof...(Ts)>()));
} }
private: private:
template <typename T, size_t... I> template <typename T, size_t... I>
std::vector<T> MakeVector(IndexSequence<I...>) const { std::vector<T> MakeVector(std::index_sequence<I...>) const {
return std::vector<T>{static_cast<T>(v_.template Get<I>())...}; return std::vector<T>{static_cast<T>(v_.template Get<I>())...};
} }
@ -838,7 +842,7 @@ class CartesianProductGenerator
template <class I> template <class I>
class IteratorImpl; class IteratorImpl;
template <size_t... I> template <size_t... I>
class IteratorImpl<IndexSequence<I...>> class IteratorImpl<std::index_sequence<I...>>
: public ParamIteratorInterface<ParamType> { : public ParamIteratorInterface<ParamType> {
public: public:
IteratorImpl(const ParamGeneratorInterface<ParamType>* base, IteratorImpl(const ParamGeneratorInterface<ParamType>* base,
@ -929,7 +933,7 @@ class CartesianProductGenerator
std::shared_ptr<ParamType> current_value_; std::shared_ptr<ParamType> current_value_;
}; };
using Iterator = IteratorImpl<typename MakeIndexSequence<sizeof...(T)>::type>; using Iterator = IteratorImpl<std::make_index_sequence<sizeof...(T)>>;
std::tuple<ParamGenerator<T>...> generators_; std::tuple<ParamGenerator<T>...> generators_;
}; };

View File

@ -56,6 +56,8 @@
#elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE) #elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE)
#define GTEST_OS_WINDOWS_PHONE 1 #define GTEST_OS_WINDOWS_PHONE 1
#define GTEST_OS_WINDOWS_TV_TITLE 1 #define GTEST_OS_WINDOWS_TV_TITLE 1
#elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_GAMES)
#define GTEST_OS_WINDOWS_GAMES 1
#else #else
// WINAPI_FAMILY defined but no known partition matched. // WINAPI_FAMILY defined but no known partition matched.
// Default to desktop. // Default to desktop.

View File

@ -194,8 +194,6 @@
// //
// Macros for basic C++ coding: // Macros for basic C++ coding:
// GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning. // GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning.
// GTEST_ATTRIBUTE_UNUSED_ - declares that a class' instances or a
// variable don't have to be used.
// GTEST_MUST_USE_RESULT_ - declares that a function's result must be used. // GTEST_MUST_USE_RESULT_ - declares that a function's result must be used.
// GTEST_INTENTIONAL_CONST_COND_PUSH_ - start code section where MSVC C4127 is // GTEST_INTENTIONAL_CONST_COND_PUSH_ - start code section where MSVC C4127 is
// suppressed (constant conditional). // suppressed (constant conditional).
@ -208,6 +206,8 @@
// or // or
// UniversalPrinter<absl::optional> // UniversalPrinter<absl::optional>
// specializations. Always defined to 0 or 1. // 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 // GTEST_INTERNAL_HAS_STRING_VIEW - for enabling Matcher<std::string_view> or
// Matcher<absl::string_view> // Matcher<absl::string_view>
// specializations. Always defined to 0 or 1. // specializations. Always defined to 0 or 1.
@ -279,6 +279,22 @@
#error C++ versions less than C++14 are not supported. #error C++ versions less than C++14 are not supported.
#endif #endif
// MSVC >= 19.11 (VS 2017 Update 3) supports __has_include.
#ifdef __has_include
#define GTEST_INTERNAL_HAS_INCLUDE __has_include
#else
#define GTEST_INTERNAL_HAS_INCLUDE(...) 0
#endif
// 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>))
#include <ciso646> // Pre-C++20
#endif
#include <ctype.h> // for isspace, etc #include <ctype.h> // for isspace, etc
#include <stddef.h> // for ptrdiff_t #include <stddef.h> // for ptrdiff_t
#include <stdio.h> #include <stdio.h>
@ -320,7 +336,8 @@
#define GTEST_HAS_NOTIFICATION_ 0 #define GTEST_HAS_NOTIFICATION_ 0
#endif #endif
#ifdef GTEST_HAS_ABSL #if defined(GTEST_HAS_ABSL) && !defined(GTEST_NO_ABSL_FLAGS)
#define GTEST_INTERNAL_HAS_ABSL_FLAGS // Used only in this file.
#include "absl/flags/declare.h" #include "absl/flags/declare.h"
#include "absl/flags/flag.h" #include "absl/flags/flag.h"
#include "absl/flags/reflection.h" #include "absl/flags/reflection.h"
@ -590,7 +607,8 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
defined(GTEST_OS_NETBSD) || defined(GTEST_OS_FUCHSIA) || \ defined(GTEST_OS_NETBSD) || defined(GTEST_OS_FUCHSIA) || \
defined(GTEST_OS_DRAGONFLY) || defined(GTEST_OS_GNU_KFREEBSD) || \ defined(GTEST_OS_DRAGONFLY) || defined(GTEST_OS_GNU_KFREEBSD) || \
defined(GTEST_OS_OPENBSD) || defined(GTEST_OS_HAIKU) || \ defined(GTEST_OS_OPENBSD) || defined(GTEST_OS_HAIKU) || \
defined(GTEST_OS_GNU_HURD)) defined(GTEST_OS_GNU_HURD) || defined(GTEST_OS_SOLARIS) || \
defined(GTEST_OS_AIX) || defined(GTEST_OS_ZOS))
#define GTEST_HAS_PTHREAD 1 #define GTEST_HAS_PTHREAD 1
#else #else
#define GTEST_HAS_PTHREAD 0 #define GTEST_HAS_PTHREAD 0
@ -609,7 +627,7 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
// Determines whether clone(2) is supported. // Determines whether clone(2) is supported.
// Usually it will only be available on Linux, excluding // Usually it will only be available on Linux, excluding
// Linux on the Itanium architecture. // Linux on the Itanium architecture.
// Also see http://linux.die.net/man/2/clone. // Also see https://linux.die.net/man/2/clone.
#ifndef GTEST_HAS_CLONE #ifndef GTEST_HAS_CLONE
// The user didn't tell us, so we need to figure it out. // The user didn't tell us, so we need to figure it out.
@ -640,9 +658,9 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
// platforms except known mobile / embedded ones. Also, if the port doesn't have // platforms except known mobile / embedded ones. Also, if the port doesn't have
// a file system, stream redirection is not supported. // a file system, stream redirection is not supported.
#if defined(GTEST_OS_WINDOWS_MOBILE) || defined(GTEST_OS_WINDOWS_PHONE) || \ #if defined(GTEST_OS_WINDOWS_MOBILE) || defined(GTEST_OS_WINDOWS_PHONE) || \
defined(GTEST_OS_WINDOWS_RT) || defined(GTEST_OS_ESP8266) || \ defined(GTEST_OS_WINDOWS_RT) || defined(GTEST_OS_WINDOWS_GAMES) || \
defined(GTEST_OS_XTENSA) || defined(GTEST_OS_QURT) || \ defined(GTEST_OS_ESP8266) || defined(GTEST_OS_XTENSA) || \
!GTEST_HAS_FILE_SYSTEM defined(GTEST_OS_QURT) || !GTEST_HAS_FILE_SYSTEM
#define GTEST_HAS_STREAM_REDIRECTION 0 #define GTEST_HAS_STREAM_REDIRECTION 0
#else #else
#define GTEST_HAS_STREAM_REDIRECTION 1 #define GTEST_HAS_STREAM_REDIRECTION 1
@ -652,7 +670,7 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
// Determines whether to support death tests. // Determines whether to support death tests.
// pops up a dialog window that cannot be suppressed programmatically. // pops up a dialog window that cannot be suppressed programmatically.
#if (defined(GTEST_OS_LINUX) || defined(GTEST_OS_CYGWIN) || \ #if (defined(GTEST_OS_LINUX) || defined(GTEST_OS_CYGWIN) || \
defined(GTEST_OS_SOLARIS) || \ defined(GTEST_OS_SOLARIS) || defined(GTEST_OS_ZOS) || \
(defined(GTEST_OS_MAC) && !defined(GTEST_OS_IOS)) || \ (defined(GTEST_OS_MAC) && !defined(GTEST_OS_IOS)) || \
(defined(GTEST_OS_WINDOWS_DESKTOP) && _MSC_VER) || \ (defined(GTEST_OS_WINDOWS_DESKTOP) && _MSC_VER) || \
defined(GTEST_OS_WINDOWS_MINGW) || defined(GTEST_OS_AIX) || \ defined(GTEST_OS_WINDOWS_MINGW) || defined(GTEST_OS_AIX) || \
@ -730,6 +748,20 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
#define GTEST_HAVE_ATTRIBUTE_(x) 0 #define GTEST_HAVE_ATTRIBUTE_(x) 0
#endif #endif
// GTEST_INTERNAL_HAVE_CPP_ATTRIBUTE
//
// A function-like feature checking macro that accepts C++11 style attributes.
// It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6
// (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't
// find `__has_cpp_attribute`, will evaluate to 0.
#if defined(__has_cpp_attribute)
// NOTE: requiring __cplusplus above should not be necessary, but
// works around https://bugs.llvm.org/show_bug.cgi?id=23435.
#define GTEST_INTERNAL_HAVE_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
#else
#define GTEST_INTERNAL_HAVE_CPP_ATTRIBUTE(x) 0
#endif
// GTEST_HAVE_FEATURE_ // GTEST_HAVE_FEATURE_
// //
// A function-like feature checking macro that is a wrapper around // A function-like feature checking macro that is a wrapper around
@ -741,14 +773,22 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
#endif #endif
// Use this annotation after a variable or parameter declaration to tell the // Use this annotation after a variable or parameter declaration to tell the
// compiler the variable/parameter does not have to be used. // compiler the variable/parameter may be used.
// Example: // Example:
// //
// GTEST_ATTRIBUTE_UNUSED_ int foo = bar(); // GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED int foo = bar();
#if GTEST_HAVE_ATTRIBUTE_(unused) //
#define GTEST_ATTRIBUTE_UNUSED_ __attribute__((unused)) // This can be removed once we only support only C++17 or newer and
// [[maybe_unused]] is available on all supported platforms.
#if GTEST_INTERNAL_HAVE_CPP_ATTRIBUTE(maybe_unused)
#define GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED [[maybe_unused]]
#elif GTEST_HAVE_ATTRIBUTE_(unused)
// This is inferior to [[maybe_unused]] as it can produce a
// -Wused-but-marked-unused warning on optionally used symbols, but it is all we
// have.
#define GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED __attribute__((__unused__))
#else #else
#define GTEST_ATTRIBUTE_UNUSED_ #define GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED
#endif #endif
// Use this annotation before a function that takes a printf format string. // Use this annotation before a function that takes a printf format string.
@ -827,9 +867,9 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
#ifndef GTEST_API_ #ifndef GTEST_API_
#ifdef _MSC_VER #ifdef _MSC_VER
#if GTEST_LINKED_AS_SHARED_LIBRARY #if defined(GTEST_LINKED_AS_SHARED_LIBRARY) && GTEST_LINKED_AS_SHARED_LIBRARY
#define GTEST_API_ __declspec(dllimport) #define GTEST_API_ __declspec(dllimport)
#elif GTEST_CREATE_SHARED_LIBRARY #elif defined(GTEST_CREATE_SHARED_LIBRARY) && GTEST_CREATE_SHARED_LIBRARY
#define GTEST_API_ __declspec(dllexport) #define GTEST_API_ __declspec(dllexport)
#endif #endif
#elif GTEST_HAVE_ATTRIBUTE_(visibility) #elif GTEST_HAVE_ATTRIBUTE_(visibility)
@ -1987,7 +2027,9 @@ inline std::string StripTrailingSpaces(std::string str) {
namespace posix { namespace posix {
// File system porting. // File system porting.
#if GTEST_HAS_FILE_SYSTEM // Note: Not every I/O-related function is related to file systems, so don't
// just disable all of them here. For example, fileno() and isatty(), etc. must
// always be available in order to detect if a pipe points to a terminal.
#ifdef GTEST_OS_WINDOWS #ifdef GTEST_OS_WINDOWS
typedef struct _stat StatStruct; typedef struct _stat StatStruct;
@ -1998,27 +2040,32 @@ inline int FileNo(FILE* file) { return reinterpret_cast<int>(_fileno(file)); }
// time and thus not defined there. // time and thus not defined there.
#else #else
inline int FileNo(FILE* file) { return _fileno(file); } inline int FileNo(FILE* file) { return _fileno(file); }
#if GTEST_HAS_FILE_SYSTEM
inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); } inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); }
inline int RmDir(const char* dir) { return _rmdir(dir); } inline int RmDir(const char* dir) { return _rmdir(dir); }
inline bool IsDir(const StatStruct& st) { return (_S_IFDIR & st.st_mode) != 0; } inline bool IsDir(const StatStruct& st) { return (_S_IFDIR & st.st_mode) != 0; }
#endif
#endif // GTEST_OS_WINDOWS_MOBILE #endif // GTEST_OS_WINDOWS_MOBILE
#elif defined(GTEST_OS_ESP8266) #elif defined(GTEST_OS_ESP8266)
typedef struct stat StatStruct; typedef struct stat StatStruct;
inline int FileNo(FILE* file) { return fileno(file); } inline int FileNo(FILE* file) { return fileno(file); }
#if GTEST_HAS_FILE_SYSTEM
inline int Stat(const char* path, StatStruct* buf) { inline int Stat(const char* path, StatStruct* buf) {
// stat function not implemented on ESP8266 // stat function not implemented on ESP8266
return 0; return 0;
} }
inline int RmDir(const char* dir) { return rmdir(dir); } inline int RmDir(const char* dir) { return rmdir(dir); }
inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); } inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); }
#endif
#else #else
typedef struct stat StatStruct; typedef struct stat StatStruct;
inline int FileNo(FILE* file) { return fileno(file); } inline int FileNo(FILE* file) { return fileno(file); }
#if GTEST_HAS_FILE_SYSTEM
inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); } inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); }
#ifdef GTEST_OS_QURT #ifdef GTEST_OS_QURT
// QuRT doesn't support any directory functions, including rmdir // QuRT doesn't support any directory functions, including rmdir
@ -2027,9 +2074,9 @@ inline int RmDir(const char*) { return 0; }
inline int RmDir(const char* dir) { return rmdir(dir); } inline int RmDir(const char* dir) { return rmdir(dir); }
#endif #endif
inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); } inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); }
#endif
#endif // GTEST_OS_WINDOWS #endif // GTEST_OS_WINDOWS
#endif // GTEST_HAS_FILE_SYSTEM
// Other functions with a different name on Windows. // Other functions with a different name on Windows.
@ -2082,8 +2129,9 @@ GTEST_DISABLE_MSC_DEPRECATED_PUSH_()
// defined there. // defined there.
#if GTEST_HAS_FILE_SYSTEM #if GTEST_HAS_FILE_SYSTEM
#if !defined(GTEST_OS_WINDOWS_MOBILE) && !defined(GTEST_OS_WINDOWS_PHONE) && \ #if !defined(GTEST_OS_WINDOWS_MOBILE) && !defined(GTEST_OS_WINDOWS_PHONE) && \
!defined(GTEST_OS_WINDOWS_RT) && !defined(GTEST_OS_ESP8266) && \ !defined(GTEST_OS_WINDOWS_RT) && !defined(GTEST_OS_WINDOWS_GAMES) && \
!defined(GTEST_OS_XTENSA) && !defined(GTEST_OS_QURT) !defined(GTEST_OS_ESP8266) && !defined(GTEST_OS_XTENSA) && \
!defined(GTEST_OS_QURT)
inline int ChDir(const char* dir) { return chdir(dir); } inline int ChDir(const char* dir) { return chdir(dir); }
#endif #endif
inline FILE* FOpen(const char* path, const char* mode) { inline FILE* FOpen(const char* path, const char* mode) {
@ -2227,7 +2275,7 @@ using TimeInMillis = int64_t; // Represents time in milliseconds.
#endif // !defined(GTEST_FLAG) #endif // !defined(GTEST_FLAG)
// Pick a command line flags implementation. // Pick a command line flags implementation.
#ifdef GTEST_HAS_ABSL #ifdef GTEST_INTERNAL_HAS_ABSL_FLAGS
// Macros for defining flags. // Macros for defining flags.
#define GTEST_DEFINE_bool_(name, default_val, doc) \ #define GTEST_DEFINE_bool_(name, default_val, doc) \
@ -2252,7 +2300,8 @@ using TimeInMillis = int64_t; // Represents time in milliseconds.
(void)(::absl::SetFlag(&GTEST_FLAG(name), value)) (void)(::absl::SetFlag(&GTEST_FLAG(name), value))
#define GTEST_USE_OWN_FLAGFILE_FLAG_ 0 #define GTEST_USE_OWN_FLAGFILE_FLAG_ 0
#else // GTEST_HAS_ABSL #undef GTEST_INTERNAL_HAS_ABSL_FLAGS
#else // ndef GTEST_INTERNAL_HAS_ABSL_FLAGS
// Macros for defining flags. // Macros for defining flags.
#define GTEST_DEFINE_bool_(name, default_val, doc) \ #define GTEST_DEFINE_bool_(name, default_val, doc) \
@ -2294,7 +2343,7 @@ using TimeInMillis = int64_t; // Represents time in milliseconds.
#define GTEST_FLAG_SET(name, value) (void)(::testing::GTEST_FLAG(name) = value) #define GTEST_FLAG_SET(name, value) (void)(::testing::GTEST_FLAG(name) = value)
#define GTEST_USE_OWN_FLAGFILE_FLAG_ 1 #define GTEST_USE_OWN_FLAGFILE_FLAG_ 1
#endif // GTEST_HAS_ABSL #endif // GTEST_INTERNAL_HAS_ABSL_FLAGS
// Thread annotations // Thread annotations
#if !defined(GTEST_EXCLUSIVE_LOCK_REQUIRED_) #if !defined(GTEST_EXCLUSIVE_LOCK_REQUIRED_)
@ -2349,9 +2398,9 @@ using Any = ::absl::any;
} // namespace internal } // namespace internal
} // namespace testing } // namespace testing
#else #else
#ifdef __has_include #if defined(__cpp_lib_any) || (GTEST_INTERNAL_HAS_INCLUDE(<any>) && \
#if __has_include(<any>) && GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L && \ GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L && \
(!defined(_MSC_VER) || GTEST_HAS_RTTI) (!defined(_MSC_VER) || GTEST_HAS_RTTI))
// Otherwise for C++17 and higher use std::any for UniversalPrinter<> // Otherwise for C++17 and higher use std::any for UniversalPrinter<>
// specializations. // specializations.
#define GTEST_INTERNAL_HAS_ANY 1 #define GTEST_INTERNAL_HAS_ANY 1
@ -2363,8 +2412,7 @@ using Any = ::std::any;
} // namespace testing } // namespace testing
// The case where absl is configured NOT to alias std::any is not // The case where absl is configured NOT to alias std::any is not
// supported. // supported.
#endif // __has_include(<any>) && GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L #endif // __cpp_lib_any
#endif // __has_include
#endif // GTEST_HAS_ABSL #endif // GTEST_HAS_ABSL
#ifndef GTEST_INTERNAL_HAS_ANY #ifndef GTEST_INTERNAL_HAS_ANY
@ -2384,8 +2432,8 @@ inline ::absl::nullopt_t Nullopt() { return ::absl::nullopt; }
} // namespace internal } // namespace internal
} // namespace testing } // namespace testing
#else #else
#ifdef __has_include #if defined(__cpp_lib_optional) || (GTEST_INTERNAL_HAS_INCLUDE(<optional>) && \
#if __has_include(<optional>) && GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L)
// Otherwise for C++17 and higher use std::optional for UniversalPrinter<> // Otherwise for C++17 and higher use std::optional for UniversalPrinter<>
// specializations. // specializations.
#define GTEST_INTERNAL_HAS_OPTIONAL 1 #define GTEST_INTERNAL_HAS_OPTIONAL 1
@ -2399,14 +2447,22 @@ inline ::std::nullopt_t Nullopt() { return ::std::nullopt; }
} // namespace testing } // namespace testing
// The case where absl is configured NOT to alias std::optional is not // The case where absl is configured NOT to alias std::optional is not
// supported. // supported.
#endif // __has_include(<optional>) && GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L #endif // __cpp_lib_optional
#endif // __has_include
#endif // GTEST_HAS_ABSL #endif // GTEST_HAS_ABSL
#ifndef GTEST_INTERNAL_HAS_OPTIONAL #ifndef GTEST_INTERNAL_HAS_OPTIONAL
#define GTEST_INTERNAL_HAS_OPTIONAL 0 #define GTEST_INTERNAL_HAS_OPTIONAL 0
#endif #endif
#if defined(__cpp_lib_span) || (GTEST_INTERNAL_HAS_INCLUDE(<span>) && \
GTEST_INTERNAL_CPLUSPLUS_LANG >= 202002L)
#define GTEST_INTERNAL_HAS_STD_SPAN 1
#endif // __cpp_lib_span
#ifndef GTEST_INTERNAL_HAS_STD_SPAN
#define GTEST_INTERNAL_HAS_STD_SPAN 0
#endif
#ifdef GTEST_HAS_ABSL #ifdef GTEST_HAS_ABSL
// Always use absl::string_view for Matcher<> specializations if googletest // Always use absl::string_view for Matcher<> specializations if googletest
// is built with absl support. // is built with absl support.
@ -2418,8 +2474,9 @@ using StringView = ::absl::string_view;
} // namespace internal } // namespace internal
} // namespace testing } // namespace testing
#else #else
#ifdef __has_include #if defined(__cpp_lib_string_view) || \
#if __has_include(<string_view>) && GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L (GTEST_INTERNAL_HAS_INCLUDE(<string_view>) && \
GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L)
// Otherwise for C++17 and higher use std::string_view for Matcher<> // Otherwise for C++17 and higher use std::string_view for Matcher<>
// specializations. // specializations.
#define GTEST_INTERNAL_HAS_STRING_VIEW 1 #define GTEST_INTERNAL_HAS_STRING_VIEW 1
@ -2431,9 +2488,7 @@ using StringView = ::std::string_view;
} // namespace testing } // namespace testing
// The case where absl is configured NOT to alias std::string_view is not // The case where absl is configured NOT to alias std::string_view is not
// supported. // supported.
#endif // __has_include(<string_view>) && GTEST_INTERNAL_CPLUSPLUS_LANG >= #endif // __cpp_lib_string_view
// 201703L
#endif // __has_include
#endif // GTEST_HAS_ABSL #endif // GTEST_HAS_ABSL
#ifndef GTEST_INTERNAL_HAS_STRING_VIEW #ifndef GTEST_INTERNAL_HAS_STRING_VIEW
@ -2452,8 +2507,8 @@ using Variant = ::absl::variant<T...>;
} // namespace internal } // namespace internal
} // namespace testing } // namespace testing
#else #else
#ifdef __has_include #if defined(__cpp_lib_variant) || (GTEST_INTERNAL_HAS_INCLUDE(<variant>) && \
#if __has_include(<variant>) && GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L)
// Otherwise for C++17 and higher use std::variant for UniversalPrinter<> // Otherwise for C++17 and higher use std::variant for UniversalPrinter<>
// specializations. // specializations.
#define GTEST_INTERNAL_HAS_VARIANT 1 #define GTEST_INTERNAL_HAS_VARIANT 1
@ -2465,16 +2520,16 @@ using Variant = ::std::variant<T...>;
} // namespace internal } // namespace internal
} // namespace testing } // namespace testing
// The case where absl is configured NOT to alias std::variant is not supported. // The case where absl is configured NOT to alias std::variant is not supported.
#endif // __has_include(<variant>) && GTEST_INTERNAL_CPLUSPLUS_LANG >= 201703L #endif // __cpp_lib_variant
#endif // __has_include
#endif // GTEST_HAS_ABSL #endif // GTEST_HAS_ABSL
#ifndef GTEST_INTERNAL_HAS_VARIANT #ifndef GTEST_INTERNAL_HAS_VARIANT
#define GTEST_INTERNAL_HAS_VARIANT 0 #define GTEST_INTERNAL_HAS_VARIANT 0
#endif #endif
#if defined(GTEST_INTERNAL_CPLUSPLUS_LANG) && \ #if (defined(__cpp_constexpr) && !defined(__cpp_inline_variables)) || \
GTEST_INTERNAL_CPLUSPLUS_LANG < 201703L (defined(GTEST_INTERNAL_CPLUSPLUS_LANG) && \
GTEST_INTERNAL_CPLUSPLUS_LANG < 201703L)
#define GTEST_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL 1 #define GTEST_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL 1
#endif #endif

View File

@ -71,7 +71,7 @@ inline std::string CanonicalizeForStdLibVersioning(std::string s) {
// Strip redundant spaces in typename to match MSVC // Strip redundant spaces in typename to match MSVC
// For example, std::pair<int, bool> -> std::pair<int,bool> // For example, std::pair<int, bool> -> std::pair<int,bool>
static const char to_search[] = ", "; static const char to_search[] = ", ";
static const char replace_str[] = ","; const char replace_char = ',';
size_t pos = 0; size_t pos = 0;
while (true) { while (true) {
// Get the next occurrence from the current position // Get the next occurrence from the current position
@ -80,8 +80,8 @@ inline std::string CanonicalizeForStdLibVersioning(std::string s) {
break; break;
} }
// Replace this occurrence of substring // Replace this occurrence of substring
s.replace(pos, strlen(to_search), replace_str); s.replace(pos, strlen(to_search), 1, replace_char);
pos += strlen(replace_str); ++pos;
} }
return s; return s;
} }

View File

@ -32,6 +32,8 @@
#include "gtest/gtest-death-test.h" #include "gtest/gtest-death-test.h"
#include <stdlib.h>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <sstream> #include <sstream>
@ -115,7 +117,7 @@ GTEST_DEFINE_string_(
GTEST_DEFINE_bool_( GTEST_DEFINE_bool_(
death_test_use_fork, death_test_use_fork,
testing::internal::BoolFromGTestEnv("death_test_use_fork", false), testing::internal::BoolFromGTestEnv("death_test_use_fork", false),
"Instructs to use fork()/_exit() instead of clone() in death tests. " "Instructs to use fork()/_Exit() instead of clone() in death tests. "
"Ignored and always uses fork() on POSIX systems where clone() is not " "Ignored and always uses fork() on POSIX systems where clone() is not "
"implemented. Useful when running under valgrind or similar tools if " "implemented. Useful when running under valgrind or similar tools if "
"those do not support clone(). Valgrind 3.3.1 will just fail if " "those do not support clone(). Valgrind 3.3.1 will just fail if "
@ -299,7 +301,7 @@ enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW };
fputc(kDeathTestInternalError, parent); fputc(kDeathTestInternalError, parent);
fprintf(parent, "%s", message.c_str()); fprintf(parent, "%s", message.c_str());
fflush(parent); fflush(parent);
_exit(1); _Exit(1);
} else { } else {
fprintf(stderr, "%s", message.c_str()); fprintf(stderr, "%s", message.c_str());
fflush(stderr); fflush(stderr);
@ -511,7 +513,7 @@ std::string DeathTestImpl::GetErrorLogs() { return GetCapturedStderr(); }
// Signals that the death test code which should have exited, didn't. // Signals that the death test code which should have exited, didn't.
// Should be called only in a death test child process. // Should be called only in a death test child process.
// Writes a status byte to the child's status file descriptor, then // Writes a status byte to the child's status file descriptor, then
// calls _exit(1). // calls _Exit(1).
void DeathTestImpl::Abort(AbortReason reason) { void DeathTestImpl::Abort(AbortReason reason) {
// The parent process considers the death test to be a failure if // The parent process considers the death test to be a failure if
// it finds any data in our pipe. So, here we write a single flag byte // it finds any data in our pipe. So, here we write a single flag byte
@ -523,13 +525,13 @@ void DeathTestImpl::Abort(AbortReason reason) {
GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1)); GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1));
// We are leaking the descriptor here because on some platforms (i.e., // We are leaking the descriptor here because on some platforms (i.e.,
// when built as Windows DLL), destructors of global objects will still // when built as Windows DLL), destructors of global objects will still
// run after calling _exit(). On such systems, write_fd_ will be // run after calling _Exit(). On such systems, write_fd_ will be
// indirectly closed from the destructor of UnitTestImpl, causing double // indirectly closed from the destructor of UnitTestImpl, causing double
// close if it is also closed here. On debug configurations, double close // close if it is also closed here. On debug configurations, double close
// may assert. As there are no in-process buffers to flush here, we are // may assert. As there are no in-process buffers to flush here, we are
// relying on the OS to close the descriptor after the process terminates // relying on the OS to close the descriptor after the process terminates
// when the destructors are not run. // when the destructors are not run.
_exit(1); // Exits w/o any normal exit hooks (we were supposed to crash) _Exit(1); // Exits w/o any normal exit hooks (we were supposed to crash)
} }
// Returns an indented copy of stderr output for a death test. // Returns an indented copy of stderr output for a death test.
@ -628,13 +630,13 @@ bool DeathTestImpl::Passed(bool status_ok) {
#ifndef GTEST_OS_WINDOWS #ifndef GTEST_OS_WINDOWS
// Note: The return value points into args, so the return value's lifetime is // Note: The return value points into args, so the return value's lifetime is
// bound to that of args. // bound to that of args.
static std::unique_ptr<char*[]> CreateArgvFromArgs( static std::vector<char*> CreateArgvFromArgs(std::vector<std::string>& args) {
std::vector<std::string>& args) { std::vector<char*> result;
auto result = std::make_unique<char*[]>(args.size() + 1); result.reserve(args.size() + 1);
for (size_t i = 0; i < args.size(); ++i) { for (auto& arg : args) {
result[i] = &args[i][0]; result.push_back(&arg[0]);
} }
result[args.size()] = nullptr; // extra null terminator result.push_back(nullptr); // Extra null terminator.
return result; return result;
} }
#endif #endif
@ -783,7 +785,7 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
StreamableToString(static_cast<unsigned int>(::GetCurrentProcessId())) + StreamableToString(static_cast<unsigned int>(::GetCurrentProcessId())) +
// size_t has the same width as pointers on both 32-bit and 64-bit // size_t has the same width as pointers on both 32-bit and 64-bit
// Windows platforms. // Windows platforms.
// See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx. // See https://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx.
"|" + StreamableToString(reinterpret_cast<size_t>(write_handle)) + "|" + "|" + StreamableToString(reinterpret_cast<size_t>(write_handle)) + "|" +
StreamableToString(reinterpret_cast<size_t>(event_handle_.Get())); StreamableToString(reinterpret_cast<size_t>(event_handle_.Get()));
@ -1034,8 +1036,8 @@ DeathTest::TestRole FuchsiaDeathTest::AssumeRole() {
// "Fuchsia Test Component" which contains a "Fuchsia Component Manifest") // "Fuchsia Test Component" which contains a "Fuchsia Component Manifest")
// Launching processes is a privileged operation in Fuchsia, and the // Launching processes is a privileged operation in Fuchsia, and the
// declaration indicates that the ability is required for the component. // declaration indicates that the ability is required for the component.
std::unique_ptr<char*[]> argv = CreateArgvFromArgs(args); std::vector<char*> argv = CreateArgvFromArgs(args);
status = fdio_spawn_etc(child_job, FDIO_SPAWN_CLONE_ALL, argv[0], argv.get(), status = fdio_spawn_etc(child_job, FDIO_SPAWN_CLONE_ALL, argv[0], argv.data(),
nullptr, 2, spawn_actions, nullptr, 2, spawn_actions,
child_process_.reset_and_get_address(), nullptr); child_process_.reset_and_get_address(), nullptr);
GTEST_DEATH_TEST_CHECK_(status == ZX_OK); GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
@ -1333,7 +1335,7 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
#endif // GTEST_HAS_CLONE #endif // GTEST_HAS_CLONE
if (use_fork && (child_pid = fork()) == 0) { if (use_fork && (child_pid = fork()) == 0) {
_exit(ExecDeathTestChildMain(&args)); _Exit(ExecDeathTestChildMain(&args));
} }
#endif // GTEST_OS_QNX #endif // GTEST_OS_QNX
#ifdef GTEST_OS_LINUX #ifdef GTEST_OS_LINUX
@ -1386,8 +1388,8 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() {
// is necessary. // is necessary.
FlushInfoLog(); FlushInfoLog();
std::unique_ptr<char*[]> argv = CreateArgvFromArgs(args); std::vector<char*> argv = CreateArgvFromArgs(args);
const pid_t child_pid = ExecDeathTestSpawnChild(argv.get(), pipe_fd[0]); const pid_t child_pid = ExecDeathTestSpawnChild(argv.data(), pipe_fd[0]);
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1])); GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
set_child_pid(child_pid); set_child_pid(child_pid);
set_read_fd(pipe_fd[0]); set_read_fd(pipe_fd[0]);

View File

@ -336,7 +336,7 @@ bool FilePath::CreateDirectoriesRecursively() const {
return false; return false;
} }
if (pathname_.length() == 0 || this->DirectoryExists()) { if (pathname_.empty() || this->DirectoryExists()) {
return true; return true;
} }

View File

@ -46,6 +46,7 @@
#include <memory> #include <memory>
#include <set> #include <set>
#include <string> #include <string>
#include <unordered_map>
#include <vector> #include <vector>
#include "gtest/internal/gtest-port.h" #include "gtest/internal/gtest-port.h"
@ -312,7 +313,7 @@ void ShuffleRange(internal::Random* random, int begin, int end,
<< begin << ", " << size << "]."; << begin << ", " << size << "].";
// Fisher-Yates shuffle, from // Fisher-Yates shuffle, from
// http://en.wikipedia.org/wiki/Fisher-Yates_shuffle // https://en.wikipedia.org/wiki/Fisher-Yates_shuffle
for (int range_width = end - begin; range_width >= 2; range_width--) { for (int range_width = end - begin; range_width >= 2; range_width--) {
const int last_in_range = begin + range_width - 1; const int last_in_range = begin + range_width - 1;
const int selected = const int selected =
@ -649,13 +650,15 @@ class GTEST_API_ UnitTestImpl {
// this is not a typed or a type-parameterized test. // this is not a typed or a type-parameterized test.
// set_up_tc: pointer to the function that sets up the test suite // set_up_tc: pointer to the function that sets up the test suite
// tear_down_tc: pointer to the function that tears down the test suite // tear_down_tc: pointer to the function that tears down the test suite
TestSuite* GetTestSuite(const char* test_suite_name, const char* type_param, TestSuite* GetTestSuite(const std::string& test_suite_name,
const char* type_param,
internal::SetUpTestSuiteFunc set_up_tc, internal::SetUpTestSuiteFunc set_up_tc,
internal::TearDownTestSuiteFunc tear_down_tc); internal::TearDownTestSuiteFunc tear_down_tc);
// Legacy API is deprecated but still available // Legacy API is deprecated but still available
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
TestCase* GetTestCase(const char* test_case_name, const char* type_param, TestCase* GetTestCase(const std::string& test_case_name,
const char* type_param,
internal::SetUpTestSuiteFunc set_up_tc, internal::SetUpTestSuiteFunc set_up_tc,
internal::TearDownTestSuiteFunc tear_down_tc) { internal::TearDownTestSuiteFunc tear_down_tc) {
return GetTestSuite(test_case_name, type_param, set_up_tc, tear_down_tc); return GetTestSuite(test_case_name, type_param, set_up_tc, tear_down_tc);
@ -681,13 +684,13 @@ class GTEST_API_ UnitTestImpl {
// AddTestInfo(), which is called to register a TEST or TEST_F // AddTestInfo(), which is called to register a TEST or TEST_F
// before main() is reached. // before main() is reached.
if (original_working_dir_.IsEmpty()) { if (original_working_dir_.IsEmpty()) {
original_working_dir_.Set(FilePath::GetCurrentDir()); original_working_dir_ = FilePath::GetCurrentDir();
GTEST_CHECK_(!original_working_dir_.IsEmpty()) GTEST_CHECK_(!original_working_dir_.IsEmpty())
<< "Failed to get the current working directory."; << "Failed to get the current working directory.";
} }
#endif // GTEST_HAS_FILE_SYSTEM #endif // GTEST_HAS_FILE_SYSTEM
GetTestSuite(test_info->test_suite_name(), test_info->type_param(), GetTestSuite(test_info->test_suite_name_, test_info->type_param(),
set_up_tc, tear_down_tc) set_up_tc, tear_down_tc)
->AddTestInfo(test_info); ->AddTestInfo(test_info);
} }
@ -709,18 +712,6 @@ class GTEST_API_ UnitTestImpl {
return type_parameterized_test_registry_; return type_parameterized_test_registry_;
} }
// Sets the TestSuite object for the test that's currently running.
void set_current_test_suite(TestSuite* a_current_test_suite) {
current_test_suite_ = a_current_test_suite;
}
// Sets the TestInfo object for the test that's currently running. If
// current_test_info is NULL, the assertion results will be stored in
// ad_hoc_test_result_.
void set_current_test_info(TestInfo* a_current_test_info) {
current_test_info_ = a_current_test_info;
}
// Registers all parameterized tests defined using TEST_P and // Registers all parameterized tests defined using TEST_P and
// INSTANTIATE_TEST_SUITE_P, creating regular tests for each test/parameter // INSTANTIATE_TEST_SUITE_P, creating regular tests for each test/parameter
// combination. This method can be called more then once; it has guards // combination. This method can be called more then once; it has guards
@ -835,12 +826,30 @@ class GTEST_API_ UnitTestImpl {
bool catch_exceptions() const { return catch_exceptions_; } bool catch_exceptions() const { return catch_exceptions_; }
private: private:
struct CompareTestSuitesByPointer {
bool operator()(const TestSuite* lhs, const TestSuite* rhs) const {
return lhs->name_ < rhs->name_;
}
};
friend class ::testing::UnitTest; friend class ::testing::UnitTest;
// Used by UnitTest::Run() to capture the state of // Used by UnitTest::Run() to capture the state of
// GTEST_FLAG(catch_exceptions) at the moment it starts. // GTEST_FLAG(catch_exceptions) at the moment it starts.
void set_catch_exceptions(bool value) { catch_exceptions_ = value; } void set_catch_exceptions(bool value) { catch_exceptions_ = value; }
// Sets the TestSuite object for the test that's currently running.
void set_current_test_suite(TestSuite* a_current_test_suite) {
current_test_suite_ = a_current_test_suite;
}
// Sets the TestInfo object for the test that's currently running. If
// current_test_info is NULL, the assertion results will be stored in
// ad_hoc_test_result_.
void set_current_test_info(TestInfo* a_current_test_info) {
current_test_info_ = a_current_test_info;
}
// The UnitTest object that owns this implementation object. // The UnitTest object that owns this implementation object.
UnitTest* const parent_; UnitTest* const parent_;
@ -873,6 +882,9 @@ class GTEST_API_ UnitTestImpl {
// elements in the vector. // elements in the vector.
std::vector<TestSuite*> test_suites_; std::vector<TestSuite*> test_suites_;
// The set of TestSuites by name.
std::unordered_map<std::string, TestSuite*> test_suites_by_name_;
// Provides a level of indirection for the test suite list to allow // Provides a level of indirection for the test suite list to allow
// easy shuffling and restoring the test suite order. The i-th // easy shuffling and restoring the test suite order. The i-th
// element of this vector is the index of the i-th test suite in the // element of this vector is the index of the i-th test suite in the

View File

@ -158,13 +158,13 @@ size_t GetThreadCount() {
// we cannot detect it. // we cannot detect it.
size_t GetThreadCount() { size_t GetThreadCount() {
int mib[] = { int mib[] = {
CTL_KERN, CTL_KERN,
KERN_PROC, KERN_PROC,
KERN_PROC_PID, KERN_PROC_PID,
getpid(), getpid(),
#ifdef GTEST_OS_NETBSD #ifdef GTEST_OS_NETBSD
sizeof(struct kinfo_proc), sizeof(struct kinfo_proc),
1, 1,
#endif #endif
}; };
u_int miblen = sizeof(mib) / sizeof(mib[0]); u_int miblen = sizeof(mib) / sizeof(mib[0]);
@ -587,9 +587,11 @@ class ThreadLocalRegistryImpl {
// thread's ID. // thread's ID.
typedef std::map<DWORD, ThreadLocalValues> ThreadIdToThreadLocals; typedef std::map<DWORD, ThreadLocalValues> ThreadIdToThreadLocals;
// Holds the thread id and thread handle that we pass from struct WatcherThreadParams {
// StartWatcherThreadFor to WatcherThreadFunc. DWORD thread_id;
typedef std::pair<DWORD, HANDLE> ThreadIdAndHandle; HANDLE handle;
Notification has_initialized;
};
static void StartWatcherThreadFor(DWORD thread_id) { static void StartWatcherThreadFor(DWORD thread_id) {
// The returned handle will be kept in thread_map and closed by // The returned handle will be kept in thread_map and closed by
@ -597,15 +599,20 @@ class ThreadLocalRegistryImpl {
HANDLE thread = HANDLE thread =
::OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION, FALSE, thread_id); ::OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION, FALSE, thread_id);
GTEST_CHECK_(thread != nullptr); GTEST_CHECK_(thread != nullptr);
WatcherThreadParams* watcher_thread_params = new WatcherThreadParams;
watcher_thread_params->thread_id = thread_id;
watcher_thread_params->handle = thread;
// We need to pass a valid thread ID pointer into CreateThread for it // We need to pass a valid thread ID pointer into CreateThread for it
// to work correctly under Win98. // to work correctly under Win98.
DWORD watcher_thread_id; DWORD watcher_thread_id;
HANDLE watcher_thread = ::CreateThread( HANDLE watcher_thread =
nullptr, // Default security. ::CreateThread(nullptr, // Default security.
0, // Default stack size 0, // Default stack size
&ThreadLocalRegistryImpl::WatcherThreadFunc, &ThreadLocalRegistryImpl::WatcherThreadFunc,
reinterpret_cast<LPVOID>(new ThreadIdAndHandle(thread_id, thread)), reinterpret_cast<LPVOID>(watcher_thread_params),
CREATE_SUSPENDED, &watcher_thread_id); CREATE_SUSPENDED, &watcher_thread_id);
GTEST_CHECK_(watcher_thread != nullptr) GTEST_CHECK_(watcher_thread != nullptr)
<< "CreateThread failed with error " << ::GetLastError() << "."; << "CreateThread failed with error " << ::GetLastError() << ".";
// Give the watcher thread the same priority as ours to avoid being // Give the watcher thread the same priority as ours to avoid being
@ -614,17 +621,25 @@ class ThreadLocalRegistryImpl {
::GetThreadPriority(::GetCurrentThread())); ::GetThreadPriority(::GetCurrentThread()));
::ResumeThread(watcher_thread); ::ResumeThread(watcher_thread);
::CloseHandle(watcher_thread); ::CloseHandle(watcher_thread);
// Wait for the watcher thread to start to avoid race conditions.
// One specific race condition that can happen is that we have returned
// from main and have started to tear down, the newly spawned watcher
// thread may access already-freed variables, like global shared_ptrs.
watcher_thread_params->has_initialized.WaitForNotification();
} }
// Monitors exit from a given thread and notifies those // Monitors exit from a given thread and notifies those
// ThreadIdToThreadLocals about thread termination. // ThreadIdToThreadLocals about thread termination.
static DWORD WINAPI WatcherThreadFunc(LPVOID param) { static DWORD WINAPI WatcherThreadFunc(LPVOID param) {
const ThreadIdAndHandle* tah = WatcherThreadParams* watcher_thread_params =
reinterpret_cast<const ThreadIdAndHandle*>(param); reinterpret_cast<WatcherThreadParams*>(param);
GTEST_CHECK_(::WaitForSingleObject(tah->second, INFINITE) == WAIT_OBJECT_0); watcher_thread_params->has_initialized.Notify();
OnThreadExit(tah->first); GTEST_CHECK_(::WaitForSingleObject(watcher_thread_params->handle,
::CloseHandle(tah->second); INFINITE) == WAIT_OBJECT_0);
delete tah; OnThreadExit(watcher_thread_params->thread_id);
::CloseHandle(watcher_thread_params->handle);
delete watcher_thread_params;
return 0; return 0;
} }
@ -697,13 +712,24 @@ bool RE::PartialMatch(const char* str, const RE& re) {
void RE::Init(const char* regex) { void RE::Init(const char* regex) {
pattern_ = regex; pattern_ = regex;
// NetBSD (and Android, which takes its regex implemntation from NetBSD) does
// not include the GNU regex extensions (such as Perl style character classes
// like \w) in REG_EXTENDED. REG_EXTENDED is only specified to include the
// [[:alpha:]] style character classes. Enable REG_GNU wherever it is defined
// so users can use those extensions.
#if defined(REG_GNU)
constexpr int reg_flags = REG_EXTENDED | REG_GNU;
#else
constexpr int reg_flags = REG_EXTENDED;
#endif
// Reserves enough bytes to hold the regular expression used for a // Reserves enough bytes to hold the regular expression used for a
// full match. // full match.
const size_t full_regex_len = strlen(regex) + 10; const size_t full_regex_len = strlen(regex) + 10;
char* const full_pattern = new char[full_regex_len]; char* const full_pattern = new char[full_regex_len];
snprintf(full_pattern, full_regex_len, "^(%s)$", regex); snprintf(full_pattern, full_regex_len, "^(%s)$", regex);
is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0; is_valid_ = regcomp(&full_regex_, full_pattern, reg_flags) == 0;
// We want to call regcomp(&partial_regex_, ...) even if the // We want to call regcomp(&partial_regex_, ...) even if the
// previous expression returns false. Otherwise partial_regex_ may // previous expression returns false. Otherwise partial_regex_ may
// not be properly initialized can may cause trouble when it's // not be properly initialized can may cause trouble when it's
@ -714,7 +740,7 @@ void RE::Init(const char* regex) {
// regex. We change it to an equivalent form "()" to be safe. // regex. We change it to an equivalent form "()" to be safe.
if (is_valid_) { if (is_valid_) {
const char* const partial_regex = (*regex == '\0') ? "()" : regex; const char* const partial_regex = (*regex == '\0') ? "()" : regex;
is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0; is_valid_ = regcomp(&partial_regex_, partial_regex, reg_flags) == 0;
} }
EXPECT_TRUE(is_valid_) EXPECT_TRUE(is_valid_)
<< "Regular expression \"" << regex << "Regular expression \"" << regex
@ -1022,11 +1048,21 @@ GTestLog::~GTestLog() {
} }
} }
#if GTEST_HAS_STREAM_REDIRECTION
// Disable Microsoft deprecation warnings for POSIX functions called from // Disable Microsoft deprecation warnings for POSIX functions called from
// this class (creat, dup, dup2, and close) // this class (creat, dup, dup2, and close)
GTEST_DISABLE_MSC_DEPRECATED_PUSH_() GTEST_DISABLE_MSC_DEPRECATED_PUSH_()
#if GTEST_HAS_STREAM_REDIRECTION namespace {
#if defined(GTEST_OS_LINUX_ANDROID) || defined(GTEST_OS_IOS)
bool EndsWithPathSeparator(const std::string& path) {
return !path.empty() && path.back() == GTEST_PATH_SEP_[0];
}
#endif
} // namespace
// Object that captures an output stream (stdout/stderr). // Object that captures an output stream (stdout/stderr).
class CapturedStream { class CapturedStream {
@ -1064,7 +1100,13 @@ class CapturedStream {
// The location /data/local/tmp is directly accessible from native code. // The location /data/local/tmp is directly accessible from native code.
// '/sdcard' and other variants cannot be relied on, as they are not // '/sdcard' and other variants cannot be relied on, as they are not
// guaranteed to be mounted, or may have a delay in mounting. // guaranteed to be mounted, or may have a delay in mounting.
name_template = "/data/local/tmp/"; //
// However, prefer using the TMPDIR environment variable if set, as newer
// devices may have /data/local/tmp read-only.
name_template = TempDir();
if (!EndsWithPathSeparator(name_template))
name_template.push_back(GTEST_PATH_SEP_[0]);
#elif defined(GTEST_OS_IOS) #elif defined(GTEST_OS_IOS)
char user_temp_dir[PATH_MAX + 1]; char user_temp_dir[PATH_MAX + 1];
@ -1084,7 +1126,7 @@ class CapturedStream {
::confstr(_CS_DARWIN_USER_TEMP_DIR, user_temp_dir, sizeof(user_temp_dir)); ::confstr(_CS_DARWIN_USER_TEMP_DIR, user_temp_dir, sizeof(user_temp_dir));
name_template = user_temp_dir; name_template = user_temp_dir;
if (name_template.back() != GTEST_PATH_SEP_[0]) if (!EndsWithPathSeparator(name_template))
name_template.push_back(GTEST_PATH_SEP_[0]); name_template.push_back(GTEST_PATH_SEP_[0]);
#else #else
name_template = "/tmp/"; name_template = "/tmp/";
@ -1306,8 +1348,8 @@ bool ParseInt32(const Message& src_text, const char* str, int32_t* value) {
) { ) {
Message msg; Message msg;
msg << "WARNING: " << src_text msg << "WARNING: " << src_text
<< " is expected to be a 32-bit integer, but actually" << " is expected to be a 32-bit integer, but actually" << " has value "
<< " has value " << str << ", which overflows.\n"; << str << ", which overflows.\n";
printf("%s", msg.GetString().c_str()); printf("%s", msg.GetString().c_str());
fflush(stdout); fflush(stdout);
return false; return false;

View File

@ -43,6 +43,7 @@
#include <algorithm> #include <algorithm>
#include <chrono> // NOLINT #include <chrono> // NOLINT
#include <cmath> #include <cmath>
#include <csignal> // NOLINT: raise(3) is used on some platforms
#include <cstdint> #include <cstdint>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
@ -161,6 +162,10 @@
#define GTEST_HAS_BUILTIN(x) 0 #define GTEST_HAS_BUILTIN(x) 0
#endif // defined(__has_builtin) #endif // defined(__has_builtin)
#if defined(GTEST_HAS_ABSL) && !defined(GTEST_NO_ABSL_FLAGS)
#define GTEST_HAS_ABSL_FLAGS
#endif
namespace testing { namespace testing {
using internal::CountIf; using internal::CountIf;
@ -374,7 +379,7 @@ GTEST_DEFINE_string_(
testing::internal::StringFromGTestEnv("stream_result_to", ""), testing::internal::StringFromGTestEnv("stream_result_to", ""),
"This flag specifies the host name and the port number on which to stream " "This flag specifies the host name and the port number on which to stream "
"test results. Example: \"localhost:555\". The flag is effective only on " "test results. Example: \"localhost:555\". The flag is effective only on "
"Linux."); "Linux and macOS.");
GTEST_DEFINE_bool_( GTEST_DEFINE_bool_(
throw_on_failure, throw_on_failure,
@ -446,6 +451,19 @@ static bool ShouldRunTestSuite(const TestSuite* test_suite) {
return test_suite->should_run(); return test_suite->should_run();
} }
namespace {
// Returns true if test part results of type `type` should include a stack
// trace.
bool ShouldEmitStackTraceForResultType(TestPartResult::Type type) {
// Suppress emission of the stack trace for SUCCEED() since it likely never
// requires investigation, and GTEST_SKIP() since skipping is an intentional
// act by the developer rather than a failure requiring investigation.
return type != TestPartResult::kSuccess && type != TestPartResult::kSkip;
}
} // namespace
// AssertHelper constructor. // AssertHelper constructor.
AssertHelper::AssertHelper(TestPartResult::Type type, const char* file, AssertHelper::AssertHelper(TestPartResult::Type type, const char* file,
int line, const char* message) int line, const char* message)
@ -458,7 +476,9 @@ void AssertHelper::operator=(const Message& message) const {
UnitTest::GetInstance()->AddTestPartResult( UnitTest::GetInstance()->AddTestPartResult(
data_->type, data_->file, data_->line, data_->type, data_->file, data_->line,
AppendUserMessage(data_->message, message), AppendUserMessage(data_->message, message),
UnitTest::GetInstance()->impl()->CurrentOsStackTraceExceptTop(1) ShouldEmitStackTraceForResultType(data_->type)
? UnitTest::GetInstance()->impl()->CurrentOsStackTraceExceptTop(1)
: ""
// Skips the stack frame for this function itself. // Skips the stack frame for this function itself.
); // NOLINT ); // NOLINT
} }
@ -516,7 +536,8 @@ void InsertSyntheticTestCase(const std::string& name, CodeLocation location,
if (ignored.find(name) != ignored.end()) return; if (ignored.find(name) != ignored.end()) return;
const char kMissingInstantiation[] = // const char kMissingInstantiation[] = //
" is defined via TEST_P, but never instantiated. None of the test cases " " is defined via TEST_P, but never instantiated. None of the test "
"cases "
"will run. Either no INSTANTIATE_TEST_SUITE_P is provided or the only " "will run. Either no INSTANTIATE_TEST_SUITE_P is provided or the only "
"ones provided expand to nothing." "ones provided expand to nothing."
"\n\n" "\n\n"
@ -557,7 +578,7 @@ void InsertSyntheticTestCase(const std::string& name, CodeLocation location,
void RegisterTypeParameterizedTestSuite(const char* test_suite_name, void RegisterTypeParameterizedTestSuite(const char* test_suite_name,
CodeLocation code_location) { CodeLocation code_location) {
GetUnitTestImpl()->type_parameterized_test_registry().RegisterTestSuite( GetUnitTestImpl()->type_parameterized_test_registry().RegisterTestSuite(
test_suite_name, code_location); test_suite_name, std::move(code_location));
} }
void RegisterTypeParameterizedTestSuiteInstantiation(const char* case_name) { void RegisterTypeParameterizedTestSuiteInstantiation(const char* case_name) {
@ -568,7 +589,7 @@ void RegisterTypeParameterizedTestSuiteInstantiation(const char* case_name) {
void TypeParameterizedTestSuiteRegistry::RegisterTestSuite( void TypeParameterizedTestSuiteRegistry::RegisterTestSuite(
const char* test_suite_name, CodeLocation code_location) { const char* test_suite_name, CodeLocation code_location) {
suites_.emplace(std::string(test_suite_name), suites_.emplace(std::string(test_suite_name),
TypeParameterizedTestSuiteInfo(code_location)); TypeParameterizedTestSuiteInfo(std::move(code_location)));
} }
void TypeParameterizedTestSuiteRegistry::RegisterInstantiation( void TypeParameterizedTestSuiteRegistry::RegisterInstantiation(
@ -595,10 +616,12 @@ void TypeParameterizedTestSuiteRegistry::CheckForInstantiations() {
"\n\n" "\n\n"
"Ideally, TYPED_TEST_P definitions should only ever be included as " "Ideally, TYPED_TEST_P definitions should only ever be included as "
"part of binaries that intend to use them. (As opposed to, for " "part of binaries that intend to use them. (As opposed to, for "
"example, being placed in a library that may be linked in to get other " "example, being placed in a library that may be linked in to get "
"other "
"utilities.)" "utilities.)"
"\n\n" "\n\n"
"To suppress this error for this test suite, insert the following line " "To suppress this error for this test suite, insert the following "
"line "
"(in a non-header) in the namespace it is defined in:" "(in a non-header) in the namespace it is defined in:"
"\n\n" "\n\n"
"GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(" + "GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(" +
@ -638,11 +661,14 @@ static ::std::vector<std::string> g_argvs;
FilePath GetCurrentExecutableName() { FilePath GetCurrentExecutableName() {
FilePath result; FilePath result;
auto args = GetArgvs();
if (!args.empty()) {
#if defined(GTEST_OS_WINDOWS) || defined(GTEST_OS_OS2) #if defined(GTEST_OS_WINDOWS) || defined(GTEST_OS_OS2)
result.Set(FilePath(GetArgvs()[0]).RemoveExtension("exe")); result.Set(FilePath(args[0]).RemoveExtension("exe"));
#else #else
result.Set(FilePath(GetArgvs()[0])); result.Set(FilePath(args[0]));
#endif // GTEST_OS_WINDOWS #endif // GTEST_OS_WINDOWS
}
return result.RemoveDirectoryName(); return result.RemoveDirectoryName();
} }
@ -778,7 +804,7 @@ class UnitTestFilter {
// Returns true if and only if name matches at least one of the patterns in // Returns true if and only if name matches at least one of the patterns in
// the filter. // the filter.
bool MatchesName(const std::string& name) const { bool MatchesName(const std::string& name) const {
return exact_match_patterns_.count(name) > 0 || return exact_match_patterns_.find(name) != exact_match_patterns_.end() ||
std::any_of(glob_patterns_.begin(), glob_patterns_.end(), std::any_of(glob_patterns_.begin(), glob_patterns_.end(),
[&name](const std::string& pattern) { [&name](const std::string& pattern) {
return PatternMatchesString( return PatternMatchesString(
@ -879,7 +905,7 @@ int UnitTestOptions::GTestProcessSEH(DWORD seh_code, const char* location) {
// apparently). // apparently).
// //
// SEH exception code for C++ exceptions. // SEH exception code for C++ exceptions.
// (see http://support.microsoft.com/kb/185294 for more information). // (see https://support.microsoft.com/kb/185294 for more information).
const DWORD kCxxExceptionCode = 0xe06d7363; const DWORD kCxxExceptionCode = 0xe06d7363;
if (!GTEST_FLAG_GET(catch_exceptions) || seh_code == kCxxExceptionCode || if (!GTEST_FLAG_GET(catch_exceptions) || seh_code == kCxxExceptionCode ||
@ -2317,7 +2343,7 @@ static const char* const kReservedTestCaseAttributes[] = {
"type_param", "value_param", "file", "line"}; "type_param", "value_param", "file", "line"};
// Use a slightly different set for allowed output to ensure existing tests can // Use a slightly different set for allowed output to ensure existing tests can
// still RecordProperty("result") or "RecordProperty(timestamp") // still RecordProperty("result") or RecordProperty("timestamp")
static const char* const kReservedOutputTestCaseAttributes[] = { static const char* const kReservedOutputTestCaseAttributes[] = {
"classname", "name", "status", "time", "type_param", "classname", "name", "status", "time", "type_param",
"value_param", "file", "line", "result", "timestamp"}; "value_param", "file", "line", "result", "timestamp"};
@ -2717,18 +2743,16 @@ bool Test::IsSkipped() {
// Constructs a TestInfo object. It assumes ownership of the test factory // Constructs a TestInfo object. It assumes ownership of the test factory
// object. // object.
TestInfo::TestInfo(const std::string& a_test_suite_name, TestInfo::TestInfo(std::string a_test_suite_name, std::string a_name,
const std::string& a_name, const char* a_type_param, const char* a_type_param, const char* a_value_param,
const char* a_value_param,
internal::CodeLocation a_code_location, internal::CodeLocation a_code_location,
internal::TypeId fixture_class_id, internal::TypeId fixture_class_id,
internal::TestFactoryBase* factory) internal::TestFactoryBase* factory)
: test_suite_name_(a_test_suite_name), : test_suite_name_(std::move(a_test_suite_name)),
// begin()/end() is MSVC 17.3.3 ASAN crash workaround (GitHub issue #3997) name_(std::move(a_name)),
name_(a_name.begin(), a_name.end()),
type_param_(a_type_param ? new std::string(a_type_param) : nullptr), type_param_(a_type_param ? new std::string(a_type_param) : nullptr),
value_param_(a_value_param ? new std::string(a_value_param) : nullptr), value_param_(a_value_param ? new std::string(a_value_param) : nullptr),
location_(a_code_location), location_(std::move(a_code_location)),
fixture_class_id_(fixture_class_id), fixture_class_id_(fixture_class_id),
should_run_(false), should_run_(false),
is_disabled_(false), is_disabled_(false),
@ -2761,19 +2785,19 @@ namespace internal {
// The newly created TestInfo instance will assume // The newly created TestInfo instance will assume
// ownership of the factory object. // ownership of the factory object.
TestInfo* MakeAndRegisterTestInfo( TestInfo* MakeAndRegisterTestInfo(
const char* test_suite_name, const char* name, const char* type_param, std::string test_suite_name, const char* name, const char* type_param,
const char* value_param, CodeLocation code_location, const char* value_param, CodeLocation code_location,
TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc, TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc,
TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory) { TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory) {
TestInfo* const test_info = TestInfo* const test_info =
new TestInfo(test_suite_name, name, type_param, value_param, new TestInfo(std::move(test_suite_name), name, type_param, value_param,
code_location, fixture_class_id, factory); std::move(code_location), fixture_class_id, factory);
GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info); GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);
return test_info; return test_info;
} }
void ReportInvalidTestSuiteType(const char* test_suite_name, void ReportInvalidTestSuiteType(const char* test_suite_name,
CodeLocation code_location) { const CodeLocation& code_location) {
Message errors; Message errors;
errors errors
<< "Attempted redefinition of test suite " << test_suite_name << ".\n" << "Attempted redefinition of test suite " << test_suite_name << ".\n"
@ -2813,14 +2837,13 @@ void TestInfo::Run() {
} }
// Tells UnitTest where to store test result. // Tells UnitTest where to store test result.
internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); UnitTest::GetInstance()->set_current_test_info(this);
impl->set_current_test_info(this);
// Notifies the unit test event listeners that a test is about to start. // Notifies the unit test event listeners that a test is about to start.
repeater->OnTestStart(*this); repeater->OnTestStart(*this);
result_.set_start_timestamp(internal::GetTimeInMillis()); result_.set_start_timestamp(internal::GetTimeInMillis());
internal::Timer timer; internal::Timer timer;
impl->os_stack_trace_getter()->UponLeavingGTest(); UnitTest::GetInstance()->UponLeavingGTest();
// Creates the test object. // Creates the test object.
Test* const test = internal::HandleExceptionsInMethodIfSupported( Test* const test = internal::HandleExceptionsInMethodIfSupported(
@ -2838,7 +2861,7 @@ void TestInfo::Run() {
if (test != nullptr) { if (test != nullptr) {
// Deletes the test object. // Deletes the test object.
impl->os_stack_trace_getter()->UponLeavingGTest(); UnitTest::GetInstance()->UponLeavingGTest();
internal::HandleExceptionsInMethodIfSupported( internal::HandleExceptionsInMethodIfSupported(
test, &Test::DeleteSelf_, "the test fixture's destructor"); test, &Test::DeleteSelf_, "the test fixture's destructor");
} }
@ -2850,15 +2873,14 @@ void TestInfo::Run() {
// Tells UnitTest to stop associating assertion results to this // Tells UnitTest to stop associating assertion results to this
// test. // test.
impl->set_current_test_info(nullptr); UnitTest::GetInstance()->set_current_test_info(nullptr);
} }
// Skip and records a skipped test result for this object. // Skip and records a skipped test result for this object.
void TestInfo::Skip() { void TestInfo::Skip() {
if (!should_run_) return; if (!should_run_) return;
internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); UnitTest::GetInstance()->set_current_test_info(this);
impl->set_current_test_info(this);
TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
@ -2867,12 +2889,13 @@ void TestInfo::Skip() {
const TestPartResult test_part_result = const TestPartResult test_part_result =
TestPartResult(TestPartResult::kSkip, this->file(), this->line(), ""); TestPartResult(TestPartResult::kSkip, this->file(), this->line(), "");
impl->GetTestPartResultReporterForCurrentThread()->ReportTestPartResult( internal::GetUnitTestImpl()
test_part_result); ->GetTestPartResultReporterForCurrentThread()
->ReportTestPartResult(test_part_result);
// Notifies the unit test event listener that a test has just finished. // Notifies the unit test event listener that a test has just finished.
repeater->OnTestEnd(*this); repeater->OnTestEnd(*this);
impl->set_current_test_info(nullptr); UnitTest::GetInstance()->set_current_test_info(nullptr);
} }
// class TestSuite // class TestSuite
@ -2926,7 +2949,7 @@ int TestSuite::total_test_count() const {
// this is not a typed or a type-parameterized test suite. // this is not a typed or a type-parameterized test suite.
// set_up_tc: pointer to the function that sets up the test suite // set_up_tc: pointer to the function that sets up the test suite
// tear_down_tc: pointer to the function that tears down the test suite // tear_down_tc: pointer to the function that tears down the test suite
TestSuite::TestSuite(const char* a_name, const char* a_type_param, TestSuite::TestSuite(const std::string& a_name, const char* a_type_param,
internal::SetUpTestSuiteFunc set_up_tc, internal::SetUpTestSuiteFunc set_up_tc,
internal::TearDownTestSuiteFunc tear_down_tc) internal::TearDownTestSuiteFunc tear_down_tc)
: name_(a_name), : name_(a_name),
@ -2968,8 +2991,7 @@ void TestSuite::AddTestInfo(TestInfo* test_info) {
void TestSuite::Run() { void TestSuite::Run() {
if (!should_run_) return; if (!should_run_) return;
internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); UnitTest::GetInstance()->set_current_test_suite(this);
impl->set_current_test_suite(this);
TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
@ -2999,7 +3021,7 @@ void TestSuite::Run() {
repeater->OnTestCaseStart(*this); repeater->OnTestCaseStart(*this);
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ #endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
impl->os_stack_trace_getter()->UponLeavingGTest(); UnitTest::GetInstance()->UponLeavingGTest();
internal::HandleExceptionsInMethodIfSupported( internal::HandleExceptionsInMethodIfSupported(
this, &TestSuite::RunSetUpTestSuite, "SetUpTestSuite()"); this, &TestSuite::RunSetUpTestSuite, "SetUpTestSuite()");
@ -3024,7 +3046,7 @@ void TestSuite::Run() {
} }
elapsed_time_ = timer.Elapsed(); elapsed_time_ = timer.Elapsed();
impl->os_stack_trace_getter()->UponLeavingGTest(); UnitTest::GetInstance()->UponLeavingGTest();
internal::HandleExceptionsInMethodIfSupported( internal::HandleExceptionsInMethodIfSupported(
this, &TestSuite::RunTearDownTestSuite, "TearDownTestSuite()"); this, &TestSuite::RunTearDownTestSuite, "TearDownTestSuite()");
@ -3035,15 +3057,14 @@ void TestSuite::Run() {
repeater->OnTestCaseEnd(*this); repeater->OnTestCaseEnd(*this);
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ #endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
impl->set_current_test_suite(nullptr); UnitTest::GetInstance()->set_current_test_suite(nullptr);
} }
// Skips all tests under this TestSuite. // Skips all tests under this TestSuite.
void TestSuite::Skip() { void TestSuite::Skip() {
if (!should_run_) return; if (!should_run_) return;
internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); UnitTest::GetInstance()->set_current_test_suite(this);
impl->set_current_test_suite(this);
TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
@ -3065,7 +3086,7 @@ void TestSuite::Skip() {
repeater->OnTestCaseEnd(*this); repeater->OnTestCaseEnd(*this);
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ #endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
impl->set_current_test_suite(nullptr); UnitTest::GetInstance()->set_current_test_suite(nullptr);
} }
// Clears the results of all tests in this test suite. // Clears the results of all tests in this test suite.
@ -3166,9 +3187,9 @@ static void PrintTestPartResult(const TestPartResult& test_part_result) {
} }
// class PrettyUnitTestResultPrinter // class PrettyUnitTestResultPrinter
#if defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_WINDOWS_MOBILE) && \ #if defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_WINDOWS_MOBILE) && \
!defined(GTEST_OS_WINDOWS_PHONE) && !defined(GTEST_OS_WINDOWS_RT) && \ !defined(GTEST_OS_WINDOWS_GAMES) && !defined(GTEST_OS_WINDOWS_PHONE) && \
!defined(GTEST_OS_WINDOWS_MINGW) !defined(GTEST_OS_WINDOWS_RT) && !defined(GTEST_OS_WINDOWS_MINGW)
// Returns the character attribute for the given color. // Returns the character attribute for the given color.
static WORD GetColorAttribute(GTestColor color) { static WORD GetColorAttribute(GTestColor color) {
@ -3228,7 +3249,8 @@ static const char* GetAnsiColorCode(GTestColor color) {
case GTestColor::kYellow: case GTestColor::kYellow:
return "3"; return "3";
default: default:
return nullptr; assert(false);
return "9";
} }
} }
@ -3251,6 +3273,7 @@ bool ShouldUseColor(bool stdout_is_tty) {
term != nullptr && (String::CStringEquals(term, "xterm") || term != nullptr && (String::CStringEquals(term, "xterm") ||
String::CStringEquals(term, "xterm-color") || String::CStringEquals(term, "xterm-color") ||
String::CStringEquals(term, "xterm-kitty") || String::CStringEquals(term, "xterm-kitty") ||
String::CStringEquals(term, "alacritty") ||
String::CStringEquals(term, "screen") || String::CStringEquals(term, "screen") ||
String::CStringEquals(term, "tmux") || String::CStringEquals(term, "tmux") ||
String::CStringEquals(term, "rxvt-unicode") || String::CStringEquals(term, "rxvt-unicode") ||
@ -3281,11 +3304,9 @@ static void ColoredPrintf(GTestColor color, const char* fmt, ...) {
va_start(args, fmt); va_start(args, fmt);
static const bool in_color_mode = static const bool in_color_mode =
#if GTEST_HAS_FILE_SYSTEM // We don't condition this on GTEST_HAS_FILE_SYSTEM because we still need
// to be able to detect terminal I/O regardless.
ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0); ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0);
#else
false;
#endif // GTEST_HAS_FILE_SYSTEM
const bool use_color = in_color_mode && (color != GTestColor::kDefault); const bool use_color = in_color_mode && (color != GTestColor::kDefault);
@ -3295,9 +3316,9 @@ static void ColoredPrintf(GTestColor color, const char* fmt, ...) {
return; return;
} }
#if defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_WINDOWS_MOBILE) && \ #if defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_WINDOWS_MOBILE) && \
!defined(GTEST_OS_WINDOWS_PHONE) && !defined(GTEST_OS_WINDOWS_RT) && \ !defined(GTEST_OS_WINDOWS_GAMES) && !defined(GTEST_OS_WINDOWS_PHONE) && \
!defined(GTEST_OS_WINDOWS_MINGW) !defined(GTEST_OS_WINDOWS_RT) && !defined(GTEST_OS_WINDOWS_MINGW)
const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
// Gets the current text color. // Gets the current text color.
@ -4420,8 +4441,8 @@ std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
Message attributes; Message attributes;
for (int i = 0; i < result.test_property_count(); ++i) { for (int i = 0; i < result.test_property_count(); ++i) {
const TestProperty& property = result.GetTestProperty(i); const TestProperty& property = result.GetTestProperty(i);
attributes << " " << property.key() << "=" attributes << " " << property.key() << "=" << "\""
<< "\"" << EscapeXmlAttribute(property.value()) << "\""; << EscapeXmlAttribute(property.value()) << "\"";
} }
return attributes.GetString(); return attributes.GetString();
} }
@ -4725,28 +4746,53 @@ void JsonUnitTestResultPrinter::OutputJsonTestResult(::std::ostream* stream,
const TestResult& result) { const TestResult& result) {
const std::string kIndent = Indent(10); const std::string kIndent = Indent(10);
int failures = 0; {
for (int i = 0; i < result.total_part_count(); ++i) { int failures = 0;
const TestPartResult& part = result.GetTestPartResult(i); for (int i = 0; i < result.total_part_count(); ++i) {
if (part.failed()) { const TestPartResult& part = result.GetTestPartResult(i);
*stream << ",\n"; if (part.failed()) {
if (++failures == 1) { *stream << ",\n";
*stream << kIndent << "\"" if (++failures == 1) {
<< "failures" *stream << kIndent << "\"" << "failures" << "\": [\n";
<< "\": [\n"; }
const std::string location =
internal::FormatCompilerIndependentFileLocation(part.file_name(),
part.line_number());
const std::string message =
EscapeJson(location + "\n" + part.message());
*stream << kIndent << " {\n"
<< kIndent << " \"failure\": \"" << message << "\",\n"
<< kIndent << " \"type\": \"\"\n"
<< kIndent << " }";
} }
const std::string location =
internal::FormatCompilerIndependentFileLocation(part.file_name(),
part.line_number());
const std::string message = EscapeJson(location + "\n" + part.message());
*stream << kIndent << " {\n"
<< kIndent << " \"failure\": \"" << message << "\",\n"
<< kIndent << " \"type\": \"\"\n"
<< kIndent << " }";
} }
if (failures > 0) *stream << "\n" << kIndent << "]";
}
{
int skipped = 0;
for (int i = 0; i < result.total_part_count(); ++i) {
const TestPartResult& part = result.GetTestPartResult(i);
if (part.skipped()) {
*stream << ",\n";
if (++skipped == 1) {
*stream << kIndent << "\"" << "skipped" << "\": [\n";
}
const std::string location =
internal::FormatCompilerIndependentFileLocation(part.file_name(),
part.line_number());
const std::string message =
EscapeJson(location + "\n" + part.message());
*stream << kIndent << " {\n"
<< kIndent << " \"message\": \"" << message << "\"\n"
<< kIndent << " }";
}
}
if (skipped > 0) *stream << "\n" << kIndent << "]";
} }
if (failures > 0) *stream << "\n" << kIndent << "]";
*stream << "\n" << Indent(8) << "}"; *stream << "\n" << Indent(8) << "}";
} }
@ -4883,8 +4929,8 @@ std::string JsonUnitTestResultPrinter::TestPropertiesAsJson(
for (int i = 0; i < result.test_property_count(); ++i) { for (int i = 0; i < result.test_property_count(); ++i) {
const TestProperty& property = result.GetTestProperty(i); const TestProperty& property = result.GetTestProperty(i);
attributes << ",\n" attributes << ",\n"
<< indent << "\"" << property.key() << "\": " << indent << "\"" << property.key() << "\": " << "\""
<< "\"" << EscapeJson(property.value()) << "\""; << EscapeJson(property.value()) << "\"";
} }
return attributes.GetString(); return attributes.GetString();
} }
@ -5282,6 +5328,22 @@ TestSuite* UnitTest::GetMutableTestSuite(int i) {
return impl()->GetMutableSuiteCase(i); return impl()->GetMutableSuiteCase(i);
} }
void UnitTest::UponLeavingGTest() {
impl()->os_stack_trace_getter()->UponLeavingGTest();
}
// Sets the TestSuite object for the test that's currently running.
void UnitTest::set_current_test_suite(TestSuite* a_current_test_suite) {
internal::MutexLock lock(&mutex_);
impl_->set_current_test_suite(a_current_test_suite);
}
// Sets the TestInfo object for the test that's currently running.
void UnitTest::set_current_test_info(TestInfo* a_current_test_info) {
internal::MutexLock lock(&mutex_);
impl_->set_current_test_info(a_current_test_info);
}
// Returns the list of event listeners that can be used to track events // Returns the list of event listeners that can be used to track events
// inside Google Test. // inside Google Test.
TestEventListeners& UnitTest::listeners() { return *impl()->listeners(); } TestEventListeners& UnitTest::listeners() { return *impl()->listeners(); }
@ -5399,7 +5461,7 @@ void UnitTest::RecordProperty(const std::string& key,
int UnitTest::Run() { int UnitTest::Run() {
#ifdef GTEST_HAS_DEATH_TEST #ifdef GTEST_HAS_DEATH_TEST
const bool in_death_test_child_process = const bool in_death_test_child_process =
GTEST_FLAG_GET(internal_run_death_test).length() > 0; !GTEST_FLAG_GET(internal_run_death_test).empty();
// Google Test implements this protocol for catching that a test // Google Test implements this protocol for catching that a test
// program exits before returning control to Google Test: // program exits before returning control to Google Test:
@ -5441,7 +5503,7 @@ int UnitTest::Run() {
// about crashes - they are expected. // about crashes - they are expected.
if (impl()->catch_exceptions() || in_death_test_child_process) { if (impl()->catch_exceptions() || in_death_test_child_process) {
#if !defined(GTEST_OS_WINDOWS_MOBILE) && !defined(GTEST_OS_WINDOWS_PHONE) && \ #if !defined(GTEST_OS_WINDOWS_MOBILE) && !defined(GTEST_OS_WINDOWS_PHONE) && \
!defined(GTEST_OS_WINDOWS_RT) !defined(GTEST_OS_WINDOWS_RT) && !defined(GTEST_OS_WINDOWS_GAMES)
// SetErrorMode doesn't exist on CE. // SetErrorMode doesn't exist on CE.
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
@ -5711,29 +5773,6 @@ void UnitTestImpl::PostFlagParsingInit() {
} }
} }
// A predicate that checks the name of a TestSuite against a known
// value.
//
// This is used for implementation of the UnitTest class only. We put
// it in the anonymous namespace to prevent polluting the outer
// namespace.
//
// TestSuiteNameIs is copyable.
class TestSuiteNameIs {
public:
// Constructor.
explicit TestSuiteNameIs(const std::string& name) : name_(name) {}
// Returns true if and only if the name of test_suite matches name_.
bool operator()(const TestSuite* test_suite) const {
return test_suite != nullptr &&
strcmp(test_suite->name(), name_.c_str()) == 0;
}
private:
std::string name_;
};
// Finds and returns a TestSuite with the given name. If one doesn't // Finds and returns a TestSuite with the given name. If one doesn't
// exist, creates one and returns it. It's the CALLER'S // exist, creates one and returns it. It's the CALLER'S
// RESPONSIBILITY to ensure that this function is only called WHEN THE // RESPONSIBILITY to ensure that this function is only called WHEN THE
@ -5747,19 +5786,27 @@ class TestSuiteNameIs {
// set_up_tc: pointer to the function that sets up the test suite // set_up_tc: pointer to the function that sets up the test suite
// tear_down_tc: pointer to the function that tears down the test suite // tear_down_tc: pointer to the function that tears down the test suite
TestSuite* UnitTestImpl::GetTestSuite( TestSuite* UnitTestImpl::GetTestSuite(
const char* test_suite_name, const char* type_param, const std::string& test_suite_name, const char* type_param,
internal::SetUpTestSuiteFunc set_up_tc, internal::SetUpTestSuiteFunc set_up_tc,
internal::TearDownTestSuiteFunc tear_down_tc) { internal::TearDownTestSuiteFunc tear_down_tc) {
// Can we find a TestSuite with the given name? // During initialization, all TestInfos for a given suite are added in
const auto test_suite = // sequence. To optimize this case, see if the most recently added suite is
std::find_if(test_suites_.rbegin(), test_suites_.rend(), // the one being requested now.
TestSuiteNameIs(test_suite_name)); if (!test_suites_.empty() &&
(*test_suites_.rbegin())->name_ == test_suite_name) {
return *test_suites_.rbegin();
}
if (test_suite != test_suites_.rend()) return *test_suite; // Fall back to searching the collection.
auto item_it = test_suites_by_name_.find(test_suite_name);
if (item_it != test_suites_by_name_.end()) {
return item_it->second;
}
// No. Let's create one. // Not found. Create a new instance.
auto* const new_test_suite = auto* const new_test_suite =
new TestSuite(test_suite_name, type_param, set_up_tc, tear_down_tc); new TestSuite(test_suite_name, type_param, set_up_tc, tear_down_tc);
test_suites_by_name_.emplace(test_suite_name, new_test_suite);
const UnitTestFilter death_test_suite_filter(kDeathTestSuiteFilter); const UnitTestFilter death_test_suite_filter(kDeathTestSuiteFilter);
// Is this a death test suite? // Is this a death test suite?
@ -5972,6 +6019,12 @@ bool UnitTestImpl::RunAllTests() {
} }
repeater->OnTestProgramEnd(*parent_); repeater->OnTestProgramEnd(*parent_);
// Destroy environments in normal code, not in static teardown.
bool delete_environment_on_teardown = true;
if (delete_environment_on_teardown) {
ForEach(environments_, internal::Delete<Environment>);
environments_.clear();
}
if (!gtest_is_initialized_before_run_all_tests) { if (!gtest_is_initialized_before_run_all_tests) {
ColoredPrintf( ColoredPrintf(
@ -6105,12 +6158,11 @@ int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
int num_runnable_tests = 0; int num_runnable_tests = 0;
int num_selected_tests = 0; int num_selected_tests = 0;
for (auto* test_suite : test_suites_) { for (auto* test_suite : test_suites_) {
const std::string& test_suite_name = test_suite->name(); const std::string& test_suite_name = test_suite->name_;
test_suite->set_should_run(false); test_suite->set_should_run(false);
for (size_t j = 0; j < test_suite->test_info_list().size(); j++) { for (TestInfo* test_info : test_suite->test_info_list()) {
TestInfo* const test_info = test_suite->test_info_list()[j]; const std::string& test_name = test_info->name_;
const std::string test_name(test_info->name());
// A test is disabled if test suite name or test name matches // A test is disabled if test suite name or test name matches
// kDisableTestFilter. // kDisableTestFilter.
const bool is_disabled = const bool is_disabled =
@ -6201,8 +6253,8 @@ void UnitTestImpl::ListTestsMatchingFilter() {
#if GTEST_HAS_FILE_SYSTEM #if GTEST_HAS_FILE_SYSTEM
const std::string& output_format = UnitTestOptions::GetOutputFormat(); const std::string& output_format = UnitTestOptions::GetOutputFormat();
if (output_format == "xml" || output_format == "json") { if (output_format == "xml" || output_format == "json") {
FILE* fileout = OpenFileForWriting( FILE* fileout =
UnitTestOptions::GetAbsolutePathToOutputFile().c_str()); OpenFileForWriting(UnitTestOptions::GetAbsolutePathToOutputFile());
std::stringstream stream; std::stringstream stream;
if (output_format == "xml") { if (output_format == "xml") {
XmlUnitTestResultPrinter( XmlUnitTestResultPrinter(
@ -6651,17 +6703,17 @@ void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
} }
if (remove_flag) { if (remove_flag) {
// Shift the remainder of the argv list left by one. Note // Shift the remainder of the argv list left by one.
// that argv has (*argc + 1) elements, the last one always being for (int j = i + 1; j < *argc; ++j) {
// NULL. The following loop moves the trailing NULL element as argv[j - 1] = argv[j];
// well.
for (int j = i; j != *argc; j++) {
argv[j] = argv[j + 1];
} }
// Decrements the argument count. // Decrements the argument count.
(*argc)--; (*argc)--;
// Terminate the array with nullptr.
argv[*argc] = nullptr;
// We also need to decrement the iterator as we just removed // We also need to decrement the iterator as we just removed
// an element. // an element.
i--; i--;
@ -6683,7 +6735,7 @@ void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
// remain in place. Unrecognized flags are not reported and do not cause the // remain in place. Unrecognized flags are not reported and do not cause the
// program to exit. // program to exit.
void ParseGoogleTestFlagsOnly(int* argc, char** argv) { void ParseGoogleTestFlagsOnly(int* argc, char** argv) {
#ifdef GTEST_HAS_ABSL #ifdef GTEST_HAS_ABSL_FLAGS
if (*argc <= 0) return; if (*argc <= 0) return;
std::vector<char*> positional_args; std::vector<char*> positional_args;
@ -6769,11 +6821,13 @@ void InitGoogleTestImpl(int* argc, CharType** argv) {
#ifdef GTEST_HAS_ABSL #ifdef GTEST_HAS_ABSL
absl::InitializeSymbolizer(g_argvs[0].c_str()); absl::InitializeSymbolizer(g_argvs[0].c_str());
#ifdef GTEST_HAS_ABSL_FLAGS
// When using the Abseil Flags library, set the program usage message to the // When using the Abseil Flags library, set the program usage message to the
// help message, but remove the color-encoding from the message first. // help message, but remove the color-encoding from the message first.
absl::SetProgramUsageMessage(absl::StrReplaceAll( absl::SetProgramUsageMessage(absl::StrReplaceAll(
kColorEncodedHelpMessage, kColorEncodedHelpMessage,
{{"@D", ""}, {"@R", ""}, {"@G", ""}, {"@Y", ""}, {"@@", "@"}})); {{"@D", ""}, {"@R", ""}, {"@G", ""}, {"@Y", ""}, {"@@", "@"}}));
#endif // GTEST_HAS_ABSL_FLAGS
#endif // GTEST_HAS_ABSL #endif // GTEST_HAS_ABSL
ParseGoogleTestFlagsOnly(argc, argv); ParseGoogleTestFlagsOnly(argc, argv);