aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/gtest/gtest.h46
-rw-r--r--include/gtest/internal/gtest-death-test-internal.h1
-rw-r--r--include/gtest/internal/gtest-filepath.h2
-rw-r--r--include/gtest/internal/gtest-string.h2
-rw-r--r--src/gtest-death-test.cc25
-rw-r--r--src/gtest-internal-inl.h4
-rw-r--r--src/gtest.cc2
-rw-r--r--test/gtest-death-test_test.cc23
-rwxr-xr-xtest/gtest_env_var_test.py1
-rw-r--r--test/gtest_env_var_test_.cc5
-rw-r--r--test/gtest_nc.cc41
-rwxr-xr-xtest/gtest_nc_test.py12
-rw-r--r--test/gtest_unittest.cc59
13 files changed, 213 insertions, 10 deletions
diff --git a/include/gtest/gtest.h b/include/gtest/gtest.h
index ebd3123b..dfa338b2 100644
--- a/include/gtest/gtest.h
+++ b/include/gtest/gtest.h
@@ -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.
//
diff --git a/include/gtest/internal/gtest-death-test-internal.h b/include/gtest/internal/gtest-death-test-internal.h
index 0769fcaa..3b90c495 100644
--- a/include/gtest/internal/gtest-death-test-internal.h
+++ b/include/gtest/internal/gtest-death-test-internal.h
@@ -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
diff --git a/include/gtest/internal/gtest-filepath.h b/include/gtest/internal/gtest-filepath.h
index 9a0682af..07fb86ae 100644
--- a/include/gtest/internal/gtest-filepath.h
+++ b/include/gtest/internal/gtest-filepath.h
@@ -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_
diff --git a/include/gtest/internal/gtest-string.h b/include/gtest/internal/gtest-string.h
index 178f14e1..566a6b57 100644
--- a/include/gtest/internal/gtest-string.h
+++ b/include/gtest/internal/gtest-string.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_
diff --git a/src/gtest-death-test.cc b/src/gtest-death-test.cc
index b667682f..6499842c 100644
--- a/src/gtest-death-test.cc
+++ b/src/gtest-death-test.cc
@@ -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;
diff --git a/src/gtest-internal-inl.h b/src/gtest-internal-inl.h
index b8f67c18..353c40a6 100644
--- a/src/gtest-internal-inl.h
+++ b/src/gtest-internal-inl.h
@@ -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_;
diff --git a/src/gtest.cc b/src/gtest.cc
index a9ca334a..ae20d874 100644
--- a/src/gtest.cc
+++ b/src/gtest.cc
@@ -3867,6 +3867,8 @@ void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
ParseStringFlag(arg, kColorFlag, &GTEST_FLAG(color)) ||
ParseStringFlag(arg, kDeathTestStyleFlag,
&GTEST_FLAG(death_test_style)) ||
+ ParseBoolFlag(arg, kDeathTestUseFork,
+ &GTEST_FLAG(death_test_use_fork)) ||
ParseStringFlag(arg, kFilterFlag, &GTEST_FLAG(filter)) ||
ParseStringFlag(arg, kInternalRunDeathTestFlag,
&GTEST_FLAG(internal_run_death_test)) ||
diff --git a/test/gtest-death-test_test.cc b/test/gtest-death-test_test.cc
index 07268d00..204ec413 100644
--- a/test/gtest-death-test_test.cc
+++ b/test/gtest-death-test_test.cc
@@ -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
diff --git a/test/gtest_env_var_test.py b/test/gtest_env_var_test.py
index 1b86b5a9..67a22493 100755
--- a/test/gtest_env_var_test.py
+++ b/test/gtest_env_var_test.py
@@ -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:
diff --git a/test/gtest_env_var_test_.cc b/test/gtest_env_var_test_.cc
index 16b31103..bbccd462 100644
--- a/test/gtest_env_var_test_.cc
+++ b/test/gtest_env_var_test_.cc
@@ -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;
diff --git a/test/gtest_nc.cc b/test/gtest_nc.cc
index 5cbaeefa..73b5db6d 100644
--- a/test/gtest_nc.cc
+++ b/test/gtest_nc.cc
@@ -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.
diff --git a/test/gtest_nc_test.py b/test/gtest_nc_test.py
index 683bd370..6e77d708 100755
--- a/test/gtest_nc_test.py
+++ b/test/gtest_nc_test.py
@@ -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)
]
diff --git a/test/gtest_unittest.cc b/test/gtest_unittest.cc
index 1cbb27f6..2794f7ec 100644
--- a/test/gtest_unittest.cc
+++ b/test/gtest_unittest.cc
@@ -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());