Implements the --gtest_death_test_use_fork flag and StaticAssertTypeEq.
This commit is contained in:
parent
0efb17dc54
commit
53e0dc4041
|
@ -1242,6 +1242,52 @@ AssertionResult DoubleLE(const char* expr1, const char* expr2,
|
|||
::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\
|
||||
__FILE__, __LINE__, ::testing::Message() << (message))
|
||||
|
||||
namespace internal {
|
||||
|
||||
// This template is declared, but intentionally undefined.
|
||||
template <typename T1, typename T2>
|
||||
struct StaticAssertTypeEqHelper;
|
||||
|
||||
template <typename T>
|
||||
struct StaticAssertTypeEqHelper<T, T> {};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Compile-time assertion for type equality.
|
||||
// StaticAssertTypeEq<type1, type2>() compiles iff type1 and type2 are
|
||||
// the same type. The value it returns is not interesting.
|
||||
//
|
||||
// Instead of making StaticAssertTypeEq a class template, we make it a
|
||||
// function template that invokes a helper class template. This
|
||||
// prevents a user from misusing StaticAssertTypeEq<T1, T2> by
|
||||
// defining objects of that type.
|
||||
//
|
||||
// CAVEAT:
|
||||
//
|
||||
// When used inside a method of a class template,
|
||||
// StaticAssertTypeEq<T1, T2>() is effective ONLY IF the method is
|
||||
// instantiated. For example, given:
|
||||
//
|
||||
// template <typename T> class Foo {
|
||||
// public:
|
||||
// void Bar() { testing::StaticAssertTypeEq<int, T>(); }
|
||||
// };
|
||||
//
|
||||
// the code:
|
||||
//
|
||||
// void Test1() { Foo<bool> foo; }
|
||||
//
|
||||
// will NOT generate a compiler error, as Foo<bool>::Bar() is never
|
||||
// actually instantiated. Instead, you need:
|
||||
//
|
||||
// void Test2() { Foo<bool> foo; foo.Bar(); }
|
||||
//
|
||||
// to cause a compiler error.
|
||||
template <typename T1, typename T2>
|
||||
bool StaticAssertTypeEq() {
|
||||
internal::StaticAssertTypeEqHelper<T1, T2>();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Defines a test.
|
||||
//
|
||||
|
|
|
@ -46,6 +46,7 @@ GTEST_DECLARE_string_(internal_run_death_test);
|
|||
|
||||
// Names of the flags (needed for parsing Google Test flags).
|
||||
const char kDeathTestStyleFlag[] = "death_test_style";
|
||||
const char kDeathTestUseFork[] = "death_test_use_fork";
|
||||
const char kInternalRunDeathTestFlag[] = "internal_run_death_test";
|
||||
|
||||
#ifdef GTEST_HAS_DEATH_TEST
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
// This header file declares classes and functions used internally by
|
||||
// Google Test. They are subject to change without notice.
|
||||
//
|
||||
// This file is #included in testing/base/internal/gtest-internal.h
|
||||
// This file is #included in <gtest/internal/gtest-internal.h>.
|
||||
// Do not include this header file separately!
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
// Google Test. They are subject to change without notice. They should not used
|
||||
// by code external to Google Test.
|
||||
//
|
||||
// This header file is #included by testing/base/internal/gtest-internal.h.
|
||||
// This header file is #included by <gtest/internal/gtest-internal.h>.
|
||||
// It should not be #included by other files.
|
||||
|
||||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
|
||||
|
|
|
@ -68,6 +68,17 @@ GTEST_DEFINE_string_(
|
|||
"\"fast\" (child process runs the death test immediately "
|
||||
"after forking).");
|
||||
|
||||
GTEST_DEFINE_bool_(
|
||||
death_test_use_fork,
|
||||
internal::BoolFromGTestEnv("death_test_use_fork", false),
|
||||
"Instructs to use fork()/_exit() instead of clone() in death tests. "
|
||||
"Useful when running under valgrind or similar tools if those "
|
||||
"do not support clone(). Valgrind 3.3.1 will just fail if "
|
||||
"it sees an unsupported combination of clone() flags. "
|
||||
"It is not recommended to use this flag w/o valgrind though it will "
|
||||
"work in 99% of the cases. Once valgrind is fixed, this flag will "
|
||||
"most likely be removed.");
|
||||
|
||||
namespace internal {
|
||||
GTEST_DEFINE_string_(
|
||||
internal_run_death_test, "",
|
||||
|
@ -603,8 +614,18 @@ static pid_t ExecDeathTestFork(char* const* argv, int close_fd) {
|
|||
void* const stack_top =
|
||||
static_cast<char*>(stack) + (stack_grows_down ? stack_size : 0);
|
||||
ExecDeathTestArgs args = { argv, close_fd };
|
||||
const pid_t child_pid = clone(&ExecDeathTestChildMain, stack_top,
|
||||
SIGCHLD, &args);
|
||||
pid_t child_pid;
|
||||
if (GTEST_FLAG(death_test_use_fork)) {
|
||||
// Valgrind-friendly version. As of valgrind 3.3.1 the clone() call below
|
||||
// is not supported (valgrind will fail with an error message).
|
||||
if ((child_pid = fork()) == 0) {
|
||||
ExecDeathTestChildMain(&args);
|
||||
_exit(0);
|
||||
}
|
||||
} else {
|
||||
child_pid = clone(&ExecDeathTestChildMain, stack_top,
|
||||
SIGCHLD, &args);
|
||||
}
|
||||
GTEST_DEATH_TEST_CHECK_(child_pid != -1);
|
||||
GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
|
||||
return child_pid;
|
||||
|
|
|
@ -66,6 +66,7 @@ namespace testing {
|
|||
GTEST_DECLARE_bool_(break_on_failure);
|
||||
GTEST_DECLARE_bool_(catch_exceptions);
|
||||
GTEST_DECLARE_string_(color);
|
||||
GTEST_DECLARE_bool_(death_test_use_fork);
|
||||
GTEST_DECLARE_string_(filter);
|
||||
GTEST_DECLARE_bool_(list_tests);
|
||||
GTEST_DECLARE_string_(output);
|
||||
|
@ -100,6 +101,7 @@ class GTestFlagSaver {
|
|||
catch_exceptions_ = GTEST_FLAG(catch_exceptions);
|
||||
color_ = GTEST_FLAG(color);
|
||||
death_test_style_ = GTEST_FLAG(death_test_style);
|
||||
death_test_use_fork_ = GTEST_FLAG(death_test_use_fork);
|
||||
filter_ = GTEST_FLAG(filter);
|
||||
internal_run_death_test_ = GTEST_FLAG(internal_run_death_test);
|
||||
list_tests_ = GTEST_FLAG(list_tests);
|
||||
|
@ -114,6 +116,7 @@ class GTestFlagSaver {
|
|||
GTEST_FLAG(catch_exceptions) = catch_exceptions_;
|
||||
GTEST_FLAG(color) = color_;
|
||||
GTEST_FLAG(death_test_style) = death_test_style_;
|
||||
GTEST_FLAG(death_test_use_fork) = death_test_use_fork_;
|
||||
GTEST_FLAG(filter) = filter_;
|
||||
GTEST_FLAG(internal_run_death_test) = internal_run_death_test_;
|
||||
GTEST_FLAG(list_tests) = list_tests_;
|
||||
|
@ -127,6 +130,7 @@ class GTestFlagSaver {
|
|||
bool catch_exceptions_;
|
||||
String color_;
|
||||
String death_test_style_;
|
||||
bool death_test_use_fork_;
|
||||
String filter_;
|
||||
String internal_run_death_test_;
|
||||
bool list_tests_;
|
||||
|
|
|
@ -3867,6 +3867,8 @@ void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
|
|||
ParseStringFlag(arg, kColorFlag, >EST_FLAG(color)) ||
|
||||
ParseStringFlag(arg, kDeathTestStyleFlag,
|
||||
>EST_FLAG(death_test_style)) ||
|
||||
ParseBoolFlag(arg, kDeathTestUseFork,
|
||||
>EST_FLAG(death_test_use_fork)) ||
|
||||
ParseStringFlag(arg, kFilterFlag, >EST_FLAG(filter)) ||
|
||||
ParseStringFlag(arg, kInternalRunDeathTestFlag,
|
||||
>EST_FLAG(internal_run_death_test)) ||
|
||||
|
|
|
@ -347,11 +347,13 @@ void SetPthreadFlag() {
|
|||
} // namespace
|
||||
|
||||
TEST_F(TestForDeathTest, DoesNotExecuteAtforkHooks) {
|
||||
testing::GTEST_FLAG(death_test_style) = "threadsafe";
|
||||
pthread_flag = false;
|
||||
ASSERT_EQ(0, pthread_atfork(&SetPthreadFlag, NULL, NULL));
|
||||
ASSERT_DEATH(_exit(1), "");
|
||||
ASSERT_FALSE(pthread_flag);
|
||||
if (!testing::GTEST_FLAG(death_test_use_fork)) {
|
||||
testing::GTEST_FLAG(death_test_style) = "threadsafe";
|
||||
pthread_flag = false;
|
||||
ASSERT_EQ(0, pthread_atfork(&SetPthreadFlag, NULL, NULL));
|
||||
ASSERT_DEATH(_exit(1), "");
|
||||
ASSERT_FALSE(pthread_flag);
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that a method of another class can be used in a death test.
|
||||
|
@ -561,7 +563,7 @@ TEST_F(TestForDeathTest, AssertDebugDeathAborts) {
|
|||
#endif // _NDEBUG
|
||||
|
||||
// Tests the *_EXIT family of macros, using a variety of predicates.
|
||||
TEST_F(TestForDeathTest, ExitMacros) {
|
||||
static void TestExitMacros() {
|
||||
EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), "");
|
||||
ASSERT_EXIT(_exit(42), testing::ExitedWithCode(42), "");
|
||||
EXPECT_EXIT(raise(SIGKILL), testing::KilledBySignal(SIGKILL), "") << "foo";
|
||||
|
@ -578,6 +580,15 @@ TEST_F(TestForDeathTest, ExitMacros) {
|
|||
}, "This failure is expected, too.");
|
||||
}
|
||||
|
||||
TEST_F(TestForDeathTest, ExitMacros) {
|
||||
TestExitMacros();
|
||||
}
|
||||
|
||||
TEST_F(TestForDeathTest, ExitMacrosUsingFork) {
|
||||
testing::GTEST_FLAG(death_test_use_fork) = true;
|
||||
TestExitMacros();
|
||||
}
|
||||
|
||||
TEST_F(TestForDeathTest, InvalidStyle) {
|
||||
testing::GTEST_FLAG(death_test_style) = "rococo";
|
||||
EXPECT_NONFATAL_FAILURE({ // NOLINT
|
||||
|
|
|
@ -109,6 +109,7 @@ def TestEnvVarAffectsFlag(command):
|
|||
if IS_LINUX:
|
||||
TestFlag(command, 'stack_trace_depth', '0', '100')
|
||||
TestFlag(command, 'death_test_style', 'thread-safe', 'fast')
|
||||
TestFlag(command, 'death_test_use_fork', '1', '0')
|
||||
|
||||
|
||||
if IS_WINDOWS:
|
||||
|
|
|
@ -71,6 +71,11 @@ void PrintFlag(const char* flag) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (strcmp(flag, "death_test_use_fork") == 0) {
|
||||
cout << GTEST_FLAG(death_test_use_fork);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(flag, "filter") == 0) {
|
||||
cout << GTEST_FLAG(filter);
|
||||
return;
|
||||
|
|
|
@ -181,6 +181,47 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, testing::Types<int>);
|
|||
// Wrong name prefix: "My" has been used.
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, testing::Types<double>);
|
||||
|
||||
#elif defined(TEST_STATIC_ASSERT_TYPE_EQ_IS_NOT_A_TYPE)
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
// Tests that StaticAssertTypeEq<T1, T2> cannot be used as a type.
|
||||
testing::StaticAssertTypeEq<int, int> dummy;
|
||||
|
||||
#elif defined(TEST_STATIC_ASSERT_TYPE_EQ_WORKS_IN_NAMESPACE)
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
// Tests that StaticAssertTypeEq<T1, T2> works in a namespace scope.
|
||||
static bool dummy = testing::StaticAssertTypeEq<int, const int>();
|
||||
|
||||
#elif defined(TEST_STATIC_ASSERT_TYPE_EQ_WORKS_IN_CLASS)
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
template <typename T>
|
||||
class Helper {
|
||||
public:
|
||||
// Tests that StaticAssertTypeEq<T1, T2> works in a class.
|
||||
Helper() { testing::StaticAssertTypeEq<int, T>(); }
|
||||
|
||||
void DoSomething() {}
|
||||
};
|
||||
|
||||
void Test() {
|
||||
Helper<bool> h;
|
||||
h.DoSomething(); // To avoid the "unused variable" warning.
|
||||
}
|
||||
|
||||
#elif defined(TEST_STATIC_ASSERT_TYPE_EQ_WORKS_IN_FUNCTION)
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
void Test() {
|
||||
// Tests that StaticAssertTypeEq<T1, T2> works inside a function.
|
||||
testing::StaticAssertTypeEq<const int, int>();
|
||||
}
|
||||
|
||||
#else
|
||||
// A sanity test. This should compile.
|
||||
|
||||
|
|
|
@ -78,6 +78,18 @@ class GTestNCTest(unittest.TestCase):
|
|||
('CATCHES_INSTANTIATE_TYPED_TESET_CASE_P_WITH_SAME_NAME_PREFIX',
|
||||
[r'redefinition of.*My.*FooTest']),
|
||||
|
||||
('STATIC_ASSERT_TYPE_EQ_IS_NOT_A_TYPE',
|
||||
[r'StaticAssertTypeEq.* does not name a type']),
|
||||
|
||||
('STATIC_ASSERT_TYPE_EQ_WORKS_IN_NAMESPACE',
|
||||
[r'StaticAssertTypeEq.*int.*const int']),
|
||||
|
||||
('STATIC_ASSERT_TYPE_EQ_WORKS_IN_CLASS',
|
||||
[r'StaticAssertTypeEq.*int.*bool']),
|
||||
|
||||
('STATIC_ASSERT_TYPE_EQ_WORKS_IN_FUNCTION',
|
||||
[r'StaticAssertTypeEq.*const int.*int']),
|
||||
|
||||
('SANITY',
|
||||
None)
|
||||
]
|
||||
|
|
|
@ -86,6 +86,7 @@ using testing::DoubleLE;
|
|||
using testing::FloatLE;
|
||||
using testing::GTEST_FLAG(break_on_failure);
|
||||
using testing::GTEST_FLAG(catch_exceptions);
|
||||
using testing::GTEST_FLAG(death_test_use_fork);
|
||||
using testing::GTEST_FLAG(color);
|
||||
using testing::GTEST_FLAG(filter);
|
||||
using testing::GTEST_FLAG(list_tests);
|
||||
|
@ -98,6 +99,7 @@ using testing::IsNotSubstring;
|
|||
using testing::IsSubstring;
|
||||
using testing::Message;
|
||||
using testing::ScopedFakeTestPartResultReporter;
|
||||
using testing::StaticAssertTypeEq;
|
||||
using testing::Test;
|
||||
using testing::TestPartResult;
|
||||
using testing::TestPartResultArray;
|
||||
|
@ -1128,6 +1130,7 @@ class GTestFlagSaverTest : public Test {
|
|||
|
||||
GTEST_FLAG(break_on_failure) = false;
|
||||
GTEST_FLAG(catch_exceptions) = false;
|
||||
GTEST_FLAG(death_test_use_fork) = false;
|
||||
GTEST_FLAG(color) = "auto";
|
||||
GTEST_FLAG(filter) = "";
|
||||
GTEST_FLAG(list_tests) = false;
|
||||
|
@ -1149,6 +1152,7 @@ class GTestFlagSaverTest : public Test {
|
|||
EXPECT_FALSE(GTEST_FLAG(break_on_failure));
|
||||
EXPECT_FALSE(GTEST_FLAG(catch_exceptions));
|
||||
EXPECT_STREQ("auto", GTEST_FLAG(color).c_str());
|
||||
EXPECT_FALSE(GTEST_FLAG(death_test_use_fork));
|
||||
EXPECT_STREQ("", GTEST_FLAG(filter).c_str());
|
||||
EXPECT_FALSE(GTEST_FLAG(list_tests));
|
||||
EXPECT_STREQ("", GTEST_FLAG(output).c_str());
|
||||
|
@ -1158,6 +1162,7 @@ class GTestFlagSaverTest : public Test {
|
|||
GTEST_FLAG(break_on_failure) = true;
|
||||
GTEST_FLAG(catch_exceptions) = true;
|
||||
GTEST_FLAG(color) = "no";
|
||||
GTEST_FLAG(death_test_use_fork) = true;
|
||||
GTEST_FLAG(filter) = "abc";
|
||||
GTEST_FLAG(list_tests) = true;
|
||||
GTEST_FLAG(output) = "xml:foo.xml";
|
||||
|
@ -4064,6 +4069,7 @@ struct Flags {
|
|||
// Constructs a Flags struct where each flag has its default value.
|
||||
Flags() : break_on_failure(false),
|
||||
catch_exceptions(false),
|
||||
death_test_use_fork(false),
|
||||
filter(""),
|
||||
list_tests(false),
|
||||
output(""),
|
||||
|
@ -4088,6 +4094,14 @@ struct Flags {
|
|||
return flags;
|
||||
}
|
||||
|
||||
// Creates a Flags struct where the gtest_death_test_use_fork flag has
|
||||
// the given value.
|
||||
static Flags DeathTestUseFork(bool death_test_use_fork) {
|
||||
Flags flags;
|
||||
flags.death_test_use_fork = death_test_use_fork;
|
||||
return flags;
|
||||
}
|
||||
|
||||
// Creates a Flags struct where the gtest_filter flag has the given
|
||||
// value.
|
||||
static Flags Filter(const char* filter) {
|
||||
|
@ -4131,6 +4145,7 @@ struct Flags {
|
|||
// These fields store the flag values.
|
||||
bool break_on_failure;
|
||||
bool catch_exceptions;
|
||||
bool death_test_use_fork;
|
||||
const char* filter;
|
||||
bool list_tests;
|
||||
const char* output;
|
||||
|
@ -4145,6 +4160,7 @@ class InitGoogleTestTest : public Test {
|
|||
virtual void SetUp() {
|
||||
GTEST_FLAG(break_on_failure) = false;
|
||||
GTEST_FLAG(catch_exceptions) = false;
|
||||
GTEST_FLAG(death_test_use_fork) = false;
|
||||
GTEST_FLAG(filter) = "";
|
||||
GTEST_FLAG(list_tests) = false;
|
||||
GTEST_FLAG(output) = "";
|
||||
|
@ -4167,6 +4183,7 @@ class InitGoogleTestTest : public Test {
|
|||
static void CheckFlags(const Flags& expected) {
|
||||
EXPECT_EQ(expected.break_on_failure, GTEST_FLAG(break_on_failure));
|
||||
EXPECT_EQ(expected.catch_exceptions, GTEST_FLAG(catch_exceptions));
|
||||
EXPECT_EQ(expected.death_test_use_fork, GTEST_FLAG(death_test_use_fork));
|
||||
EXPECT_STREQ(expected.filter, GTEST_FLAG(filter).c_str());
|
||||
EXPECT_EQ(expected.list_tests, GTEST_FLAG(list_tests));
|
||||
EXPECT_STREQ(expected.output, GTEST_FLAG(output).c_str());
|
||||
|
@ -4373,6 +4390,22 @@ TEST_F(InitGoogleTestTest, CatchExceptions) {
|
|||
TEST_PARSING_FLAGS(argv, argv2, Flags::CatchExceptions(true));
|
||||
}
|
||||
|
||||
// Tests parsing --gtest_death_test_use_fork.
|
||||
TEST_F(InitGoogleTestTest, DeathTestUseFork) {
|
||||
const char* argv[] = {
|
||||
"foo.exe",
|
||||
"--gtest_death_test_use_fork",
|
||||
NULL
|
||||
};
|
||||
|
||||
const char* argv2[] = {
|
||||
"foo.exe",
|
||||
NULL
|
||||
};
|
||||
|
||||
TEST_PARSING_FLAGS(argv, argv2, Flags::DeathTestUseFork(true));
|
||||
}
|
||||
|
||||
// Tests having the same flag twice with different values. The
|
||||
// expected behavior is that the one coming last takes precedence.
|
||||
TEST_F(InitGoogleTestTest, DuplicatedFlags) {
|
||||
|
@ -5000,6 +5033,32 @@ TEST(ColoredOutputTest, UsesColorsWhenTermSupportsColors) {
|
|||
#endif // GTEST_OS_WINDOWS
|
||||
}
|
||||
|
||||
// Verifies that StaticAssertTypeEq works in a namespace scope.
|
||||
|
||||
static bool dummy1 = StaticAssertTypeEq<bool, bool>();
|
||||
static bool dummy2 = StaticAssertTypeEq<const int, const int>();
|
||||
|
||||
// Verifies that StaticAssertTypeEq works in a class.
|
||||
|
||||
template <typename T>
|
||||
class StaticAssertTypeEqTestHelper {
|
||||
public:
|
||||
StaticAssertTypeEqTestHelper() { StaticAssertTypeEq<bool, T>(); }
|
||||
};
|
||||
|
||||
TEST(StaticAssertTypeEqTest, WorksInClass) {
|
||||
StaticAssertTypeEqTestHelper<bool>();
|
||||
}
|
||||
|
||||
// Verifies that StaticAssertTypeEq works inside a function.
|
||||
|
||||
typedef int IntAlias;
|
||||
|
||||
TEST(StaticAssertTypeEqTest, CompilesForEqualTypes) {
|
||||
StaticAssertTypeEq<int, IntAlias>();
|
||||
StaticAssertTypeEq<int*, IntAlias*>();
|
||||
}
|
||||
|
||||
TEST(ThreadLocalTest, DefaultConstructor) {
|
||||
ThreadLocal<int> t1;
|
||||
EXPECT_EQ(0, t1.get());
|
||||
|
|
Loading…
Reference in New Issue
Block a user