Bug 1875885 - Update googletest to 8495449f075543dbac005d6c33118e58ad770d75, r=jmaher

Differential Revision: https://phabricator.services.mozilla.com/D211280
This commit is contained in:
Andrew Halberstadt
2024-05-23 13:13:26 +00:00
parent c4167a3cc6
commit 3c574242db
34 changed files with 879 additions and 604 deletions

View File

@@ -56,6 +56,12 @@ config_setting(
constraint_values = ["@platforms//os:openbsd"], constraint_values = ["@platforms//os:openbsd"],
) )
# NOTE: Fuchsia is not an officially supported platform.
config_setting(
name = "fuchsia",
constraint_values = ["@platforms//os:fuchsia"],
)
config_setting( config_setting(
name = "msvc_compiler", name = "msvc_compiler",
flag_values = { flag_values = {
@@ -147,6 +153,17 @@ cc_library(
"@com_googlesource_code_re2//:re2", "@com_googlesource_code_re2//:re2",
], ],
"//conditions:default": [], "//conditions:default": [],
}) + select({
# `gtest-death-test.cc` has `EXPECT_DEATH` that spawns a process,
# expects it to crash and inspects its logs with the given matcher,
# so that's why these libraries are needed.
# Otherwise, builds targeting Fuchsia would fail to compile.
":fuchsia": [
"@fuchsia_sdk//pkg/fdio",
"@fuchsia_sdk//pkg/syslog",
"@fuchsia_sdk//pkg/zx",
],
"//conditions:default": [],
}), }),
) )

View File

@@ -55,6 +55,7 @@ Russ Cox <rsc@google.com>
Russ Rufer <russ@pentad.com> Russ Rufer <russ@pentad.com>
Sean Mcafee <eefacm@gmail.com> Sean Mcafee <eefacm@gmail.com>
Sigurður Ásgeirsson <siggi@google.com> Sigurður Ásgeirsson <siggi@google.com>
Soyeon Kim <sxshx818@naver.com>
Sverre Sundsdal <sundsdal@gmail.com> Sverre Sundsdal <sundsdal@gmail.com>
Szymon Sobik <sobik.szymon@gmail.com> Szymon Sobik <sobik.szymon@gmail.com>
Takeshi Yoshino <tyoshino@google.com> Takeshi Yoshino <tyoshino@google.com>

61
third_party/googletest/MODULE.bazel vendored Normal file
View File

@@ -0,0 +1,61 @@
# Copyright 2024 Google Inc.
# All Rights Reserved.
#
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# https://bazel.build/external/overview#bzlmod
module(
name = "googletest",
version = "head",
compatibility_level = 1,
)
# Only direct dependencies need to be listed below.
# Please keep the versions in sync with the versions in the WORKSPACE file.
bazel_dep(name = "abseil-cpp",
version = "20240116.0",
repo_name = "com_google_absl")
bazel_dep(name = "platforms",
version = "0.0.8")
bazel_dep(name = "re2",
repo_name = "com_googlesource_code_re2",
version = "2023-11-01")
bazel_dep(name = "rules_python",
version = "0.29.0")
fake_fuchsia_sdk = use_repo_rule("//:fake_fuchsia_sdk.bzl", "fake_fuchsia_sdk")
fake_fuchsia_sdk(name = "fuchsia_sdk")
# https://github.com/bazelbuild/rules_python/blob/main/BZLMOD_SUPPORT.md#default-toolchain-is-not-the-local-system-python
register_toolchains("@bazel_tools//tools/python:autodetecting_toolchain")

View File

@@ -6,22 +6,24 @@ googletest_deps()
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive( http_archive(
name = "rules_python", # 2023-07-31T20:39:27Z name = "rules_python",
sha256 = "1250b59a33c591a1c4ba68c62e95fc88a84c334ec35a2e23f46cbc1b9a5a8b55", sha256 = "d71d2c67e0bce986e1c5a7731b4693226867c45bfe0b7c5e0067228a536fc580",
strip_prefix = "rules_python-e355becc30275939d87116a4ec83dad4bb50d9e1", strip_prefix = "rules_python-0.29.0",
urls = ["https://github.com/bazelbuild/rules_python/archive/e355becc30275939d87116a4ec83dad4bb50d9e1.zip"], urls = ["https://github.com/bazelbuild/rules_python/releases/download/0.29.0/rules_python-0.29.0.tar.gz"],
)
# https://github.com/bazelbuild/rules_python/releases/tag/0.29.0
load("@rules_python//python:repositories.bzl", "py_repositories")
py_repositories()
http_archive(
name = "bazel_skylib",
sha256 = "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94",
urls = ["https://github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz"],
) )
http_archive( http_archive(
name = "bazel_skylib", # 2023-05-31T19:24:07Z name = "platforms",
sha256 = "08c0386f45821ce246bbbf77503c973246ed6ee5c3463e41efc197fa9bc3a7f4", sha256 = "8150406605389ececb6da07cbcb509d5637a3ab9a24bc69b1101531367d89d74",
strip_prefix = "bazel-skylib-288731ef9f7f688932bd50e704a91a45ec185f9b", urls = ["https://github.com/bazelbuild/platforms/releases/download/0.0.8/platforms-0.0.8.tar.gz"],
urls = ["https://github.com/bazelbuild/bazel-skylib/archive/288731ef9f7f688932bd50e704a91a45ec185f9b.zip"],
)
http_archive(
name = "platforms", # 2023-07-28T19:44:27Z
sha256 = "40eb313613ff00a5c03eed20aba58890046f4d38dec7344f00bb9a8867853526",
strip_prefix = "platforms-4ad40ef271da8176d4fc0194d2089b8a76e19d7b",
urls = ["https://github.com/bazelbuild/platforms/archive/4ad40ef271da8176d4fc0194d2089b8a76e19d7b.zip"],
) )

35
third_party/googletest/WORKSPACE.bzlmod vendored Normal file
View File

@@ -0,0 +1,35 @@
# Copyright 2024 Google Inc.
# All Rights Reserved.
#
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# https://bazel.build/external/migration#workspace.bzlmod
#
# This file is intentionally empty. When bzlmod is enabled and this
# file exists, the content of WORKSPACE is ignored. This prevents
# bzlmod builds from unintentionally depending on the WORKSPACE file.

View File

@@ -0,0 +1,33 @@
"""Provides a fake @fuchsia_sdk implementation that's used when the real one isn't available.
This is needed since bazel queries on targets that depend on //:gtest (eg:
`bazel query "deps(set(//googletest/test:gtest_all_test))"`) will fail if @fuchsia_sdk is not
defined when bazel is evaluating the transitive closure of the query target.
See https://github.com/google/googletest/issues/4472.
"""
def _fake_fuchsia_sdk_impl(repo_ctx):
for stub_target in repo_ctx.attr._stub_build_targets:
stub_package = stub_target
stub_target_name = stub_target.split("/")[-1]
repo_ctx.file("%s/BUILD.bazel" % stub_package, """
filegroup(
name = "%s",
)
""" % stub_target_name)
fake_fuchsia_sdk = repository_rule(
doc = "Used to create a fake @fuchsia_sdk repository with stub build targets.",
implementation = _fake_fuchsia_sdk_impl,
attrs = {
"_stub_build_targets": attr.string_list(
doc = "The stub build targets to initialize.",
default = [
"pkg/fdio",
"pkg/syslog",
"pkg/zx",
],
),
},
)

View File

@@ -65,12 +65,13 @@ endif()
config_compiler_and_linker() # from ${gtest_dir}/cmake/internal_utils.cmake config_compiler_and_linker() # from ${gtest_dir}/cmake/internal_utils.cmake
# Adds Google Mock's and Google Test's header directories to the search path. # Adds Google Mock's and Google Test's header directories to the search path.
# Get Google Test's include dirs from the target, gtest_SOURCE_DIR is broken
# when using fetch-content with the name "GTest".
get_target_property(gtest_include_dirs gtest INCLUDE_DIRECTORIES)
set(gmock_build_include_dirs set(gmock_build_include_dirs
"${gmock_SOURCE_DIR}/include" "${gmock_SOURCE_DIR}/include"
"${gmock_SOURCE_DIR}" "${gmock_SOURCE_DIR}"
"${gtest_SOURCE_DIR}/include" "${gtest_include_dirs}")
# This directory is needed to build directly from Google Test sources.
"${gtest_SOURCE_DIR}")
include_directories(${gmock_build_include_dirs}) include_directories(${gmock_build_include_dirs})
######################################################################## ########################################################################

View File

@@ -2135,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
@@ -2174,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

@@ -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_)...));
@@ -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

@@ -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

@@ -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

@@ -531,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

@@ -147,7 +147,7 @@ target_include_directories(gtest SYSTEM INTERFACE
target_include_directories(gtest_main SYSTEM INTERFACE target_include_directories(gtest_main SYSTEM INTERFACE
"$<BUILD_INTERFACE:${dirs}>" "$<BUILD_INTERFACE:${dirs}>"
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>") "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
if(CMAKE_SYSTEM_NAME MATCHES "QNX") if(CMAKE_SYSTEM_NAME MATCHES "QNX" AND CMAKE_SYSTEM_VERSION VERSION_GREATER_EQUAL 7.1)
target_link_libraries(gtest PUBLIC regex) target_link_libraries(gtest PUBLIC regex)
endif() endif()
target_link_libraries(gtest_main PUBLIC gtest) target_link_libraries(gtest_main PUBLIC gtest)

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

@@ -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

@@ -124,7 +124,7 @@
#if GTEST_INTERNAL_HAS_STD_SPAN #if GTEST_INTERNAL_HAS_STD_SPAN
#include <span> // NOLINT #include <span> // NOLINT
#endif // GTEST_INTERNAL_HAS_STD_SPAN #endif // GTEST_INTERNAL_HAS_STD_SPAN
namespace testing { namespace testing {
@@ -241,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;
@@ -552,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

@@ -60,21 +60,19 @@
#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"
#include "mozilla/Attributes.h"
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
/* class A needs to have dll-interface to be used by clients of class B */) /* class A needs to have dll-interface to be used by clients of class B */)
@@ -327,7 +325,7 @@ class GTEST_API_ Test {
// //
// DO NOT OVERRIDE THIS FUNCTION DIRECTLY IN A USER PROGRAM. // DO NOT OVERRIDE THIS FUNCTION DIRECTLY IN A USER PROGRAM.
// Instead, use the TEST or TEST_F macro. // Instead, use the TEST or TEST_F macro.
MOZ_CAN_RUN_SCRIPT virtual void TestBody() = 0; virtual void TestBody() = 0;
// Sets up, executes, and tears down the test. // Sets up, executes, and tears down the test.
void Run(); void Run();
@@ -609,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,
@@ -617,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,
@@ -685,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);
@@ -1264,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_; }
@@ -1272,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;
@@ -2310,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,6 +46,7 @@
#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);
@@ -55,6 +56,28 @@ namespace internal {
// Name of the flag (needed for parsing Google Test flag). // Name of the flag (needed for parsing Google Test flag).
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 \
@@ -71,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:
@@ -168,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

@@ -474,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;
@@ -555,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
@@ -564,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);
@@ -595,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;
} }
@@ -700,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>()) {
@@ -712,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.
@@ -725,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);
} }
}; };
@@ -739,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>& =
@@ -786,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);
@@ -1142,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
@@ -1184,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.
@@ -1195,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 {};
@@ -1222,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)
@@ -1259,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;
@@ -1540,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,34 +554,31 @@ 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
@@ -592,23 +590,25 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
<< "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 ...
@@ -621,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;
@@ -639,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),
@@ -704,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;
@@ -740,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_
@@ -750,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;
@@ -776,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;
@@ -805,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>())...};
} }
@@ -840,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,
@@ -931,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).
@@ -338,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"
@@ -608,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
@@ -658,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
@@ -670,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) || \
@@ -748,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
@@ -759,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.
@@ -2005,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;
@@ -2016,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
@@ -2045,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.
@@ -2100,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) {
@@ -2245,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) \
@@ -2270,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) \
@@ -2312,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_)

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
@@ -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

@@ -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"
@@ -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

@@ -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;
} }
@@ -1033,12 +1048,12 @@ 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 { namespace {
#if defined(GTEST_OS_LINUX_ANDROID) || defined(GTEST_OS_IOS) #if defined(GTEST_OS_LINUX_ANDROID) || defined(GTEST_OS_IOS)
@@ -1333,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

@@ -162,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;
@@ -375,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,
@@ -447,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)
@@ -459,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
} }
@@ -517,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"
@@ -558,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) {
@@ -569,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(
@@ -596,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(" +
@@ -779,7 +801,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(
@@ -2318,7 +2340,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"};
@@ -2718,18 +2740,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),
@@ -2762,19 +2782,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"
@@ -2814,14 +2834,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(
@@ -2839,7 +2858,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");
} }
@@ -2851,15 +2870,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();
@@ -2868,12 +2886,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
@@ -2927,7 +2946,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),
@@ -2969,8 +2988,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();
@@ -3000,7 +3018,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()");
@@ -3025,7 +3043,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()");
@@ -3036,15 +3054,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();
@@ -3066,7 +3083,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.
@@ -3167,9 +3184,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) {
@@ -3253,6 +3270,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") ||
@@ -3283,11 +3301,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);
@@ -3297,9 +3313,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.
@@ -4422,8 +4438,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();
} }
@@ -4727,28 +4743,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) << "}";
} }
@@ -4885,8 +4926,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();
} }
@@ -5284,6 +5325,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(); }
@@ -5443,7 +5500,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);
@@ -5713,29 +5770,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
@@ -5749,19 +5783,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?
@@ -5974,6 +6016,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(
@@ -6107,12 +6155,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 =
@@ -6653,17 +6700,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--;
@@ -6685,7 +6732,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;
@@ -6771,11 +6818,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);

View File

@@ -1,22 +1,28 @@
"""Load dependencies needed to use the googletest library as a 3rd-party consumer.""" """Load dependencies needed to use the googletest library as a 3rd-party consumer."""
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load("//:fake_fuchsia_sdk.bzl", "fake_fuchsia_sdk")
def googletest_deps(): def googletest_deps():
"""Loads common dependencies needed to use the googletest library.""" """Loads common dependencies needed to use the googletest library."""
if not native.existing_rule("com_googlesource_code_re2"): if not native.existing_rule("com_googlesource_code_re2"):
http_archive( http_archive(
name = "com_googlesource_code_re2", # 2023-03-17T11:36:51Z name = "com_googlesource_code_re2",
sha256 = "cb8b5312a65f2598954545a76e8bce913f35fbb3a21a5c88797a4448e9f9b9d9", sha256 = "828341ad08524618a626167bd320b0c2acc97bd1c28eff693a9ea33a7ed2a85f",
strip_prefix = "re2-578843a516fd1da7084ae46209a75f3613b6065e", strip_prefix = "re2-2023-11-01",
urls = ["https://github.com/google/re2/archive/578843a516fd1da7084ae46209a75f3613b6065e.zip"], urls = ["https://github.com/google/re2/releases/download/2023-11-01/re2-2023-11-01.zip"],
) )
if not native.existing_rule("com_google_absl"): if not native.existing_rule("com_google_absl"):
http_archive( http_archive(
name = "com_google_absl", # 2023-09-13T14:58:42Z name = "com_google_absl",
sha256 = "7766815ef6293dc7bca58fef59a96d7d3230874412dcd36dafb0e313ed1356f2", sha256 = "338420448b140f0dfd1a1ea3c3ce71b3bc172071f24f4d9a57d59b45037da440",
strip_prefix = "abseil-cpp-9e1789ffea47fdeb3133aa42aa9592f3673fb6ed", strip_prefix = "abseil-cpp-20240116.0",
urls = ["https://github.com/abseil/abseil-cpp/archive/9e1789ffea47fdeb3133aa42aa9592f3673fb6ed.zip"], urls = ["https://github.com/abseil/abseil-cpp/releases/download/20240116.0/abseil-cpp-20240116.0.tar.gz"],
)
if not native.existing_rule("fuchsia_sdk"):
fake_fuchsia_sdk(
name = "fuchsia_sdk",
) )

View File

@@ -10,9 +10,9 @@ origin:
url: https://google.github.io/googletest/ url: https://google.github.io/googletest/
release: 8495449f075543dbac005d6c33118e58ad770d75 (2023-12-18T18:14:49Z). release: 9b4993ca7d1279dec5c5d41ba327cb11a77bdc00 (2024-05-21T19:08:38Z).
revision: 8495449f075543dbac005d6c33118e58ad770d75 revision: 9b4993ca7d1279dec5c5d41ba327cb11a77bdc00
license: BSD-3-Clause license: BSD-3-Clause
license-file: LICENSE license-file: LICENSE