From 4984c93490eeeb7d3d1979b30a39a21cad07cba5 Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Fri, 6 Mar 2009 01:20:15 +0000 Subject: Implements death tests on Windows (by Vlad Losev); enables POSIX regex on Mac and Cygwin; fixes build issue on some Linux versions due to PATH_MAX. --- test/gtest-death-test_test.cc | 268 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 259 insertions(+), 9 deletions(-) (limited to 'test/gtest-death-test_test.cc') diff --git a/test/gtest-death-test_test.cc b/test/gtest-death-test_test.cc index 6d8a3f89..4151ef0e 100644 --- a/test/gtest-death-test_test.cc +++ b/test/gtest-death-test_test.cc @@ -36,8 +36,16 @@ #if GTEST_HAS_DEATH_TEST -#include +#if GTEST_OS_WINDOWS +#include // For chdir(). +#else #include +#include // For std::numeric_limits. +#endif // GTEST_OS_WINDOWS + +#include +#include +#include #include // Indicates that this translation unit is part of Google Test's @@ -49,8 +57,13 @@ #include "src/gtest-internal-inl.h" #undef GTEST_IMPLEMENTATION_ +using testing::Message; + using testing::internal::DeathTest; using testing::internal::DeathTestFactory; +using testing::internal::GetLastSystemErrorMessage; +using testing::internal::ParseNaturalNumber; +using testing::internal::String; namespace testing { namespace internal { @@ -88,6 +101,7 @@ class TestForDeathTest : public testing::Test { // A static member function that's expected to die. static void StaticMemberFunction() { fprintf(stderr, "%s", "death inside StaticMemberFunction()."); + fflush(stderr); // We call _exit() instead of exit(), as the former is a direct // system call and thus safer in the presence of threads. exit() // will invoke user-defined exit-hooks, which may do dangerous @@ -99,6 +113,7 @@ class TestForDeathTest : public testing::Test { void MemberFunction() { if (should_die_) { fprintf(stderr, "%s", "death inside MemberFunction()."); + fflush(stderr); _exit(1); } } @@ -165,6 +180,21 @@ int DieInDebugElse12(int* sideeffect) { return 12; } +#if GTEST_OS_WINDOWS + +// Tests the ExitedWithCode predicate. +TEST(ExitStatusPredicateTest, ExitedWithCode) { + // On Windows, the process's exit code is the same as its exit status, + // so the predicate just compares the its input with its parameter. + EXPECT_TRUE(testing::ExitedWithCode(0)(0)); + EXPECT_TRUE(testing::ExitedWithCode(1)(1)); + EXPECT_TRUE(testing::ExitedWithCode(42)(42)); + EXPECT_FALSE(testing::ExitedWithCode(0)(1)); + EXPECT_FALSE(testing::ExitedWithCode(1)(0)); +} + +#else + // Returns the exit status of a process that calls _exit(2) with a // given exit code. This is a helper function for the // ExitStatusPredicateTest test suite. @@ -222,6 +252,8 @@ TEST(ExitStatusPredicateTest, KilledBySignal) { EXPECT_FALSE(pred_kill(status_segv)); } +#endif // GTEST_OS_WINDOWS + // Tests that the death test macros expand to code which may or may not // be followed by operator<<, and that in either case the complete text // comprises only a single C++ statement. @@ -248,6 +280,7 @@ TEST_F(TestForDeathTest, SingleStatement) { void DieWithEmbeddedNul() { fprintf(stderr, "Hello%cworld.\n", '\0'); + fflush(stderr); _exit(1); } @@ -263,6 +296,13 @@ TEST_F(TestForDeathTest, DISABLED_EmbeddedNulInMessage) { // Tests that death test macros expand to code which interacts well with switch // statements. TEST_F(TestForDeathTest, SwitchStatement) { +// Microsoft compiler usually complains about switch statements without +// case labels. We suppress that warning for this test. +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4065) +#endif // _MSC_VER + switch (0) default: ASSERT_DEATH(_exit(1), "") << "exit in default switch handler"; @@ -270,6 +310,10 @@ TEST_F(TestForDeathTest, SwitchStatement) { switch (0) case 0: EXPECT_DEATH(_exit(1), "") << "exit in switch case"; + +#ifdef _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER } // Tests that a static member function can be used in a "fast" style @@ -287,15 +331,23 @@ TEST_F(TestForDeathTest, MemberFunctionFastStyle) { EXPECT_DEATH(MemberFunction(), "inside.*MemberFunction"); } +void ChangeToRootDir() { +#if GTEST_OS_WINDOWS + _chdir("\\"); +#else + chdir("/"); +#endif // GTEST_OS_WINDOWS +} + // Tests that death tests work even if the current directory has been // changed. TEST_F(TestForDeathTest, FastDeathTestInChangedDir) { testing::GTEST_FLAG(death_test_style) = "fast"; - chdir("/"); + ChangeToRootDir(); EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), ""); - chdir("/"); + ChangeToRootDir(); ASSERT_DEATH(_exit(1), ""); } @@ -322,10 +374,10 @@ TEST_F(TestForDeathTest, ThreadsafeDeathTestInLoop) { TEST_F(TestForDeathTest, ThreadsafeDeathTestInChangedDir) { testing::GTEST_FLAG(death_test_style) = "threadsafe"; - chdir("/"); + ChangeToRootDir(); EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), ""); - chdir("/"); + ChangeToRootDir(); ASSERT_DEATH(_exit(1), ""); } @@ -346,6 +398,8 @@ void SetPthreadFlag() { } // namespace +#if !GTEST_OS_WINDOWS + TEST_F(TestForDeathTest, DoesNotExecuteAtforkHooks) { if (!testing::GTEST_FLAG(death_test_use_fork)) { testing::GTEST_FLAG(death_test_style) = "threadsafe"; @@ -356,6 +410,8 @@ TEST_F(TestForDeathTest, DoesNotExecuteAtforkHooks) { } } +#endif // !GTEST_OS_WINDOWS + // Tests that a method of another class can be used in a death test. TEST_F(TestForDeathTest, MethodOfAnotherClass) { const MayDie x(true); @@ -537,6 +593,30 @@ void ExpectDebugDeathHelper(bool* aborted) { *aborted = false; } +#if GTEST_OS_WINDOWS +TEST(TestForPopUps, DoesNotShowPopUpOnAbort) { + printf("This test should be considered failing if it shows " + "any pop-up dialogs.\n"); + fflush(stdout); + + EXPECT_DEATH({ + testing::GTEST_FLAG(catch_exceptions) = false; + abort(); + }, ""); +} + +TEST(TestForPopUps, DoesNotShowPopUpOnThrow) { + printf("This test should be considered failing if it shows " + "any pop-up dialogs.\n"); + fflush(stdout); + + EXPECT_DEATH({ + testing::GTEST_FLAG(catch_exceptions) = false; + throw 1; + }, ""); +} +#endif // GTEST_OS_WINDOWS + // Tests that EXPECT_DEBUG_DEATH in debug mode does not abort // the function. TEST_F(TestForDeathTest, ExpectDebugDeathDoesNotAbort) { @@ -566,18 +646,38 @@ TEST_F(TestForDeathTest, AssertDebugDeathAborts) { 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"; - ASSERT_EXIT(raise(SIGUSR2), testing::KilledBySignal(SIGUSR2), "") << "bar"; + +#if GTEST_OS_WINDOWS + EXPECT_EXIT({ + testing::GTEST_FLAG(catch_exceptions) = false; + *static_cast(NULL) = 1; + }, testing::ExitedWithCode(0xC0000005), "") << "foo"; EXPECT_NONFATAL_FAILURE({ // NOLINT - EXPECT_EXIT(raise(SIGSEGV), testing::ExitedWithCode(0), "") - << "This failure is expected."; + EXPECT_EXIT({ + testing::GTEST_FLAG(catch_exceptions) = false; + *static_cast(NULL) = 1; + }, testing::ExitedWithCode(0), "") << "This failure is expected."; }, "This failure is expected."); + // Of all signals effects on the process exit code, only those of SIGABRT + // are documented on Windows. + // See http://msdn.microsoft.com/en-us/library/dwwzkt4c(VS.71).aspx. + EXPECT_EXIT(raise(SIGABRT), testing::ExitedWithCode(3), ""); +#else + EXPECT_EXIT(raise(SIGKILL), testing::KilledBySignal(SIGKILL), "") << "foo"; + ASSERT_EXIT(raise(SIGUSR2), testing::KilledBySignal(SIGUSR2), "") << "bar"; + EXPECT_FATAL_FAILURE({ // NOLINT ASSERT_EXIT(_exit(0), testing::KilledBySignal(SIGSEGV), "") << "This failure is expected, too."; }, "This failure is expected, too."); +#endif // GTEST_OS_WINDOWS + + EXPECT_NONFATAL_FAILURE({ // NOLINT + EXPECT_EXIT(raise(SIGSEGV), testing::ExitedWithCode(0), "") + << "This failure is expected."; + }, "This failure is expected."); } TEST_F(TestForDeathTest, ExitMacros) { @@ -873,6 +973,156 @@ TEST(StreamingAssertionsDeathTest, DeathTest) { }, "expected failure"); } +// Tests that GetLastSystemErrorMessage returns an empty string when the +// last error is 0 and non-empty string when it is non-zero. +TEST(GetLastSystemErrorMessageTest, GetLastSystemErrorMessageWorks) { +#if GTEST_OS_WINDOWS + ::SetLastError(ERROR_FILE_NOT_FOUND); + EXPECT_STRNE("", GetLastSystemErrorMessage().c_str()); + ::SetLastError(0); + EXPECT_STREQ("", GetLastSystemErrorMessage().c_str()); +#else + errno = ENOENT; + EXPECT_STRNE("", GetLastSystemErrorMessage().c_str()); + errno = 0; + EXPECT_STREQ("", GetLastSystemErrorMessage().c_str()); +#endif +} + +#if GTEST_OS_WINDOWS +TEST(AutoHandleTest, AutoHandleWorks) { + HANDLE handle = ::CreateEvent(NULL, FALSE, FALSE, NULL); + ASSERT_NE(INVALID_HANDLE_VALUE, handle); + + // Tests that the AutoHandle is correctly initialized with a handle. + testing::internal::AutoHandle auto_handle(handle); + EXPECT_EQ(handle, auto_handle.Get()); + + // Tests that Reset assigns INVALID_HANDLE_VALUE. + // Note that this cannot verify whether the original handle is closed. + auto_handle.Reset(); + EXPECT_EQ(INVALID_HANDLE_VALUE, auto_handle.Get()); + + // Tests that Reset assigns the new handle. + // Note that this cannot verify whether the original handle is closed. + handle = ::CreateEvent(NULL, FALSE, FALSE, NULL); + ASSERT_NE(INVALID_HANDLE_VALUE, handle); + auto_handle.Reset(handle); + EXPECT_EQ(handle, auto_handle.Get()); + + // Tests that AutoHandle contains INVALID_HANDLE_VALUE by default. + testing::internal::AutoHandle auto_handle2; + EXPECT_EQ(INVALID_HANDLE_VALUE, auto_handle2.Get()); +} +#endif // GTEST_OS_WINDOWS + +#if GTEST_OS_WINDOWS +typedef unsigned __int64 BiggestParsable; +typedef signed __int64 BiggestSignedParsable; +const BiggestParsable kBiggestParsableMax = ULLONG_MAX; +const BiggestParsable kBiggestSignedParsableMax = LLONG_MAX; +#else +typedef unsigned long long BiggestParsable; +typedef signed long long BiggestSignedParsable; +const BiggestParsable kBiggestParsableMax = + ::std::numeric_limits::max(); +const BiggestSignedParsable kBiggestSignedParsableMax = + ::std::numeric_limits::max(); +#endif // GTEST_OS_WINDOWS + +TEST(ParseNaturalNumberTest, RejectsInvalidFormat) { + BiggestParsable result = 0; + + // Rejects non-numbers. + EXPECT_FALSE(ParseNaturalNumber(String("non-number string"), &result)); + + // Rejects numbers with whitespace prefix. + EXPECT_FALSE(ParseNaturalNumber(String(" 123"), &result)); + + // Rejects negative numbers. + EXPECT_FALSE(ParseNaturalNumber(String("-123"), &result)); + + // Rejects numbers starting with a plus sign. + EXPECT_FALSE(ParseNaturalNumber(String("+123"), &result)); + errno = 0; +} + +TEST(ParseNaturalNumberTest, RejectsOverflownNumbers) { + BiggestParsable result = 0; + + EXPECT_FALSE(ParseNaturalNumber(String("99999999999999999999999"), &result)); + + signed char char_result = 0; + EXPECT_FALSE(ParseNaturalNumber(String("200"), &char_result)); + errno = 0; +} + +TEST(ParseNaturalNumberTest, AcceptsValidNumbers) { + BiggestParsable result = 0; + + result = 0; + ASSERT_TRUE(ParseNaturalNumber(String("123"), &result)); + EXPECT_EQ(123, result); + + // Check 0 as an edge case. + result = 1; + ASSERT_TRUE(ParseNaturalNumber(String("0"), &result)); + EXPECT_EQ(0, result); + + result = 1; + ASSERT_TRUE(ParseNaturalNumber(String("00000"), &result)); + EXPECT_EQ(0, result); +} + +TEST(ParseNaturalNumberTest, AcceptsTypeLimits) { + Message msg; + msg << kBiggestParsableMax; + + BiggestParsable result = 0; + EXPECT_TRUE(ParseNaturalNumber(msg.GetString(), &result)); + EXPECT_EQ(kBiggestParsableMax, result); + + Message msg2; + msg2 << kBiggestSignedParsableMax; + + BiggestSignedParsable signed_result = 0; + EXPECT_TRUE(ParseNaturalNumber(msg2.GetString(), &signed_result)); + EXPECT_EQ(kBiggestSignedParsableMax, signed_result); + + Message msg3; + msg3 << INT_MAX; + + int int_result = 0; + EXPECT_TRUE(ParseNaturalNumber(msg3.GetString(), &int_result)); + EXPECT_EQ(INT_MAX, int_result); + + Message msg4; + msg4 << UINT_MAX; + + unsigned int uint_result = 0; + EXPECT_TRUE(ParseNaturalNumber(msg4.GetString(), &uint_result)); + EXPECT_EQ(UINT_MAX, uint_result); +} + +TEST(ParseNaturalNumberTest, WorksForShorterIntegers) { + short short_result = 0; + ASSERT_TRUE(ParseNaturalNumber(String("123"), &short_result)); + EXPECT_EQ(123, short_result); + + signed char char_result = 0; + ASSERT_TRUE(ParseNaturalNumber(String("123"), &char_result)); + EXPECT_EQ(123, char_result); +} + +#if GTEST_OS_WINDOWS +TEST(EnvironmentTest, HandleFitsIntoSizeT) { + // TODO(vladl@google.com): Remove this test after this condition is verified + // in a static assertion in gtest-death-test.cc in the function + // GetStatusFileDescriptor. + ASSERT_TRUE(sizeof(HANDLE) <= sizeof(size_t)); +} +#endif // GTEST_OS_WINDOWS + #endif // GTEST_HAS_DEATH_TEST // Tests that a test case whose name ends with "DeathTest" works fine -- cgit v1.2.3