michael@0: // Copyright 2005, Google Inc. michael@0: // All rights reserved. michael@0: // michael@0: // Redistribution and use in source and binary forms, with or without michael@0: // modification, are permitted provided that the following conditions are michael@0: // met: michael@0: // michael@0: // * Redistributions of source code must retain the above copyright michael@0: // notice, this list of conditions and the following disclaimer. michael@0: // * Redistributions in binary form must reproduce the above michael@0: // copyright notice, this list of conditions and the following disclaimer michael@0: // in the documentation and/or other materials provided with the michael@0: // distribution. michael@0: // * Neither the name of Google Inc. nor the names of its michael@0: // contributors may be used to endorse or promote products derived from michael@0: // this software without specific prior written permission. michael@0: // michael@0: // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS michael@0: // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT michael@0: // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR michael@0: // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT michael@0: // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, michael@0: // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT michael@0: // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, michael@0: // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY michael@0: // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT michael@0: // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE michael@0: // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. michael@0: // michael@0: // Author: wan@google.com (Zhanyong Wan) michael@0: // michael@0: // Tests for death tests. michael@0: michael@0: #include "gtest/gtest-death-test.h" michael@0: #include "gtest/gtest.h" michael@0: #include "gtest/internal/gtest-filepath.h" michael@0: michael@0: using testing::internal::AlwaysFalse; michael@0: using testing::internal::AlwaysTrue; michael@0: michael@0: #if GTEST_HAS_DEATH_TEST michael@0: michael@0: # if GTEST_OS_WINDOWS michael@0: # include // For chdir(). michael@0: # else michael@0: # include michael@0: # include // For waitpid. michael@0: # include // For std::numeric_limits. michael@0: # endif // GTEST_OS_WINDOWS michael@0: michael@0: # include michael@0: # include michael@0: # include michael@0: michael@0: # if GTEST_OS_LINUX michael@0: # include michael@0: # endif // GTEST_OS_LINUX michael@0: michael@0: # include "gtest/gtest-spi.h" michael@0: michael@0: // Indicates that this translation unit is part of Google Test's michael@0: // implementation. It must come before gtest-internal-inl.h is michael@0: // included, or there will be a compiler error. This trick is to michael@0: // prevent a user from accidentally including gtest-internal-inl.h in michael@0: // his code. michael@0: # define GTEST_IMPLEMENTATION_ 1 michael@0: # include "src/gtest-internal-inl.h" michael@0: # undef GTEST_IMPLEMENTATION_ michael@0: michael@0: namespace posix = ::testing::internal::posix; michael@0: michael@0: using testing::Message; michael@0: using testing::internal::DeathTest; michael@0: using testing::internal::DeathTestFactory; michael@0: using testing::internal::FilePath; michael@0: using testing::internal::GetLastErrnoDescription; michael@0: using testing::internal::GetUnitTestImpl; michael@0: using testing::internal::InDeathTestChild; michael@0: using testing::internal::ParseNaturalNumber; michael@0: using testing::internal::String; michael@0: michael@0: namespace testing { michael@0: namespace internal { michael@0: michael@0: // A helper class whose objects replace the death test factory for a michael@0: // single UnitTest object during their lifetimes. michael@0: class ReplaceDeathTestFactory { michael@0: public: michael@0: explicit ReplaceDeathTestFactory(DeathTestFactory* new_factory) michael@0: : unit_test_impl_(GetUnitTestImpl()) { michael@0: old_factory_ = unit_test_impl_->death_test_factory_.release(); michael@0: unit_test_impl_->death_test_factory_.reset(new_factory); michael@0: } michael@0: michael@0: ~ReplaceDeathTestFactory() { michael@0: unit_test_impl_->death_test_factory_.release(); michael@0: unit_test_impl_->death_test_factory_.reset(old_factory_); michael@0: } michael@0: private: michael@0: // Prevents copying ReplaceDeathTestFactory objects. michael@0: ReplaceDeathTestFactory(const ReplaceDeathTestFactory&); michael@0: void operator=(const ReplaceDeathTestFactory&); michael@0: michael@0: UnitTestImpl* unit_test_impl_; michael@0: DeathTestFactory* old_factory_; michael@0: }; michael@0: michael@0: } // namespace internal michael@0: } // namespace testing michael@0: michael@0: void DieWithMessage(const ::std::string& message) { michael@0: fprintf(stderr, "%s", message.c_str()); michael@0: fflush(stderr); // Make sure the text is printed before the process exits. michael@0: michael@0: // We call _exit() instead of exit(), as the former is a direct michael@0: // system call and thus safer in the presence of threads. exit() michael@0: // will invoke user-defined exit-hooks, which may do dangerous michael@0: // things that conflict with death tests. michael@0: // michael@0: // Some compilers can recognize that _exit() never returns and issue the michael@0: // 'unreachable code' warning for code following this function, unless michael@0: // fooled by a fake condition. michael@0: if (AlwaysTrue()) michael@0: _exit(1); michael@0: } michael@0: michael@0: void DieInside(const ::std::string& function) { michael@0: DieWithMessage("death inside " + function + "()."); michael@0: } michael@0: michael@0: // Tests that death tests work. michael@0: michael@0: class TestForDeathTest : public testing::Test { michael@0: protected: michael@0: TestForDeathTest() : original_dir_(FilePath::GetCurrentDir()) {} michael@0: michael@0: virtual ~TestForDeathTest() { michael@0: posix::ChDir(original_dir_.c_str()); michael@0: } michael@0: michael@0: // A static member function that's expected to die. michael@0: static void StaticMemberFunction() { DieInside("StaticMemberFunction"); } michael@0: michael@0: // A method of the test fixture that may die. michael@0: void MemberFunction() { michael@0: if (should_die_) michael@0: DieInside("MemberFunction"); michael@0: } michael@0: michael@0: // True iff MemberFunction() should die. michael@0: bool should_die_; michael@0: const FilePath original_dir_; michael@0: }; michael@0: michael@0: // A class with a member function that may die. michael@0: class MayDie { michael@0: public: michael@0: explicit MayDie(bool should_die) : should_die_(should_die) {} michael@0: michael@0: // A member function that may die. michael@0: void MemberFunction() const { michael@0: if (should_die_) michael@0: DieInside("MayDie::MemberFunction"); michael@0: } michael@0: michael@0: private: michael@0: // True iff MemberFunction() should die. michael@0: bool should_die_; michael@0: }; michael@0: michael@0: // A global function that's expected to die. michael@0: void GlobalFunction() { DieInside("GlobalFunction"); } michael@0: michael@0: // A non-void function that's expected to die. michael@0: int NonVoidFunction() { michael@0: DieInside("NonVoidFunction"); michael@0: return 1; michael@0: } michael@0: michael@0: // A unary function that may die. michael@0: void DieIf(bool should_die) { michael@0: if (should_die) michael@0: DieInside("DieIf"); michael@0: } michael@0: michael@0: // A binary function that may die. michael@0: bool DieIfLessThan(int x, int y) { michael@0: if (x < y) { michael@0: DieInside("DieIfLessThan"); michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: // Tests that ASSERT_DEATH can be used outside a TEST, TEST_F, or test fixture. michael@0: void DeathTestSubroutine() { michael@0: EXPECT_DEATH(GlobalFunction(), "death.*GlobalFunction"); michael@0: ASSERT_DEATH(GlobalFunction(), "death.*GlobalFunction"); michael@0: } michael@0: michael@0: // Death in dbg, not opt. michael@0: int DieInDebugElse12(int* sideeffect) { michael@0: if (sideeffect) *sideeffect = 12; michael@0: michael@0: # ifndef NDEBUG michael@0: michael@0: DieInside("DieInDebugElse12"); michael@0: michael@0: # endif // NDEBUG michael@0: michael@0: return 12; michael@0: } michael@0: michael@0: # if GTEST_OS_WINDOWS michael@0: michael@0: // Tests the ExitedWithCode predicate. michael@0: TEST(ExitStatusPredicateTest, ExitedWithCode) { michael@0: // On Windows, the process's exit code is the same as its exit status, michael@0: // so the predicate just compares the its input with its parameter. michael@0: EXPECT_TRUE(testing::ExitedWithCode(0)(0)); michael@0: EXPECT_TRUE(testing::ExitedWithCode(1)(1)); michael@0: EXPECT_TRUE(testing::ExitedWithCode(42)(42)); michael@0: EXPECT_FALSE(testing::ExitedWithCode(0)(1)); michael@0: EXPECT_FALSE(testing::ExitedWithCode(1)(0)); michael@0: } michael@0: michael@0: # else michael@0: michael@0: // Returns the exit status of a process that calls _exit(2) with a michael@0: // given exit code. This is a helper function for the michael@0: // ExitStatusPredicateTest test suite. michael@0: static int NormalExitStatus(int exit_code) { michael@0: pid_t child_pid = fork(); michael@0: if (child_pid == 0) { michael@0: _exit(exit_code); michael@0: } michael@0: int status; michael@0: waitpid(child_pid, &status, 0); michael@0: return status; michael@0: } michael@0: michael@0: // Returns the exit status of a process that raises a given signal. michael@0: // If the signal does not cause the process to die, then it returns michael@0: // instead the exit status of a process that exits normally with exit michael@0: // code 1. This is a helper function for the ExitStatusPredicateTest michael@0: // test suite. michael@0: static int KilledExitStatus(int signum) { michael@0: pid_t child_pid = fork(); michael@0: if (child_pid == 0) { michael@0: raise(signum); michael@0: _exit(1); michael@0: } michael@0: int status; michael@0: waitpid(child_pid, &status, 0); michael@0: return status; michael@0: } michael@0: michael@0: // Tests the ExitedWithCode predicate. michael@0: TEST(ExitStatusPredicateTest, ExitedWithCode) { michael@0: const int status0 = NormalExitStatus(0); michael@0: const int status1 = NormalExitStatus(1); michael@0: const int status42 = NormalExitStatus(42); michael@0: const testing::ExitedWithCode pred0(0); michael@0: const testing::ExitedWithCode pred1(1); michael@0: const testing::ExitedWithCode pred42(42); michael@0: EXPECT_PRED1(pred0, status0); michael@0: EXPECT_PRED1(pred1, status1); michael@0: EXPECT_PRED1(pred42, status42); michael@0: EXPECT_FALSE(pred0(status1)); michael@0: EXPECT_FALSE(pred42(status0)); michael@0: EXPECT_FALSE(pred1(status42)); michael@0: } michael@0: michael@0: // Tests the KilledBySignal predicate. michael@0: TEST(ExitStatusPredicateTest, KilledBySignal) { michael@0: const int status_segv = KilledExitStatus(SIGSEGV); michael@0: const int status_kill = KilledExitStatus(SIGKILL); michael@0: const testing::KilledBySignal pred_segv(SIGSEGV); michael@0: const testing::KilledBySignal pred_kill(SIGKILL); michael@0: EXPECT_PRED1(pred_segv, status_segv); michael@0: EXPECT_PRED1(pred_kill, status_kill); michael@0: EXPECT_FALSE(pred_segv(status_kill)); michael@0: EXPECT_FALSE(pred_kill(status_segv)); michael@0: } michael@0: michael@0: # endif // GTEST_OS_WINDOWS michael@0: michael@0: // Tests that the death test macros expand to code which may or may not michael@0: // be followed by operator<<, and that in either case the complete text michael@0: // comprises only a single C++ statement. michael@0: TEST_F(TestForDeathTest, SingleStatement) { michael@0: if (AlwaysFalse()) michael@0: // This would fail if executed; this is a compilation test only michael@0: ASSERT_DEATH(return, ""); michael@0: michael@0: if (AlwaysTrue()) michael@0: EXPECT_DEATH(_exit(1), ""); michael@0: else michael@0: // This empty "else" branch is meant to ensure that EXPECT_DEATH michael@0: // doesn't expand into an "if" statement without an "else" michael@0: ; michael@0: michael@0: if (AlwaysFalse()) michael@0: ASSERT_DEATH(return, "") << "did not die"; michael@0: michael@0: if (AlwaysFalse()) michael@0: ; michael@0: else michael@0: EXPECT_DEATH(_exit(1), "") << 1 << 2 << 3; michael@0: } michael@0: michael@0: void DieWithEmbeddedNul() { michael@0: fprintf(stderr, "Hello%cmy null world.\n", '\0'); michael@0: fflush(stderr); michael@0: _exit(1); michael@0: } michael@0: michael@0: # if GTEST_USES_PCRE michael@0: // Tests that EXPECT_DEATH and ASSERT_DEATH work when the error michael@0: // message has a NUL character in it. michael@0: TEST_F(TestForDeathTest, EmbeddedNulInMessage) { michael@0: // TODO(wan@google.com): doesn't support matching strings michael@0: // with embedded NUL characters - find a way to workaround it. michael@0: EXPECT_DEATH(DieWithEmbeddedNul(), "my null world"); michael@0: ASSERT_DEATH(DieWithEmbeddedNul(), "my null world"); michael@0: } michael@0: # endif // GTEST_USES_PCRE michael@0: michael@0: // Tests that death test macros expand to code which interacts well with switch michael@0: // statements. michael@0: TEST_F(TestForDeathTest, SwitchStatement) { michael@0: // Microsoft compiler usually complains about switch statements without michael@0: // case labels. We suppress that warning for this test. michael@0: # ifdef _MSC_VER michael@0: # pragma warning(push) michael@0: # pragma warning(disable: 4065) michael@0: # endif // _MSC_VER michael@0: michael@0: switch (0) michael@0: default: michael@0: ASSERT_DEATH(_exit(1), "") << "exit in default switch handler"; michael@0: michael@0: switch (0) michael@0: case 0: michael@0: EXPECT_DEATH(_exit(1), "") << "exit in switch case"; michael@0: michael@0: # ifdef _MSC_VER michael@0: # pragma warning(pop) michael@0: # endif // _MSC_VER michael@0: } michael@0: michael@0: // Tests that a static member function can be used in a "fast" style michael@0: // death test. michael@0: TEST_F(TestForDeathTest, StaticMemberFunctionFastStyle) { michael@0: testing::GTEST_FLAG(death_test_style) = "fast"; michael@0: ASSERT_DEATH(StaticMemberFunction(), "death.*StaticMember"); michael@0: } michael@0: michael@0: // Tests that a method of the test fixture can be used in a "fast" michael@0: // style death test. michael@0: TEST_F(TestForDeathTest, MemberFunctionFastStyle) { michael@0: testing::GTEST_FLAG(death_test_style) = "fast"; michael@0: should_die_ = true; michael@0: EXPECT_DEATH(MemberFunction(), "inside.*MemberFunction"); michael@0: } michael@0: michael@0: void ChangeToRootDir() { posix::ChDir(GTEST_PATH_SEP_); } michael@0: michael@0: // Tests that death tests work even if the current directory has been michael@0: // changed. michael@0: TEST_F(TestForDeathTest, FastDeathTestInChangedDir) { michael@0: testing::GTEST_FLAG(death_test_style) = "fast"; michael@0: michael@0: ChangeToRootDir(); michael@0: EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), ""); michael@0: michael@0: ChangeToRootDir(); michael@0: ASSERT_DEATH(_exit(1), ""); michael@0: } michael@0: michael@0: # if GTEST_OS_LINUX michael@0: void SigprofAction(int, siginfo_t*, void*) { /* no op */ } michael@0: michael@0: // Sets SIGPROF action and ITIMER_PROF timer (interval: 1ms). michael@0: void SetSigprofActionAndTimer() { michael@0: struct itimerval timer; michael@0: timer.it_interval.tv_sec = 0; michael@0: timer.it_interval.tv_usec = 1; michael@0: timer.it_value = timer.it_interval; michael@0: ASSERT_EQ(0, setitimer(ITIMER_PROF, &timer, NULL)); michael@0: struct sigaction signal_action; michael@0: memset(&signal_action, 0, sizeof(signal_action)); michael@0: sigemptyset(&signal_action.sa_mask); michael@0: signal_action.sa_sigaction = SigprofAction; michael@0: signal_action.sa_flags = SA_RESTART | SA_SIGINFO; michael@0: ASSERT_EQ(0, sigaction(SIGPROF, &signal_action, NULL)); michael@0: } michael@0: michael@0: // Disables ITIMER_PROF timer and ignores SIGPROF signal. michael@0: void DisableSigprofActionAndTimer(struct sigaction* old_signal_action) { michael@0: struct itimerval timer; michael@0: timer.it_interval.tv_sec = 0; michael@0: timer.it_interval.tv_usec = 0; michael@0: timer.it_value = timer.it_interval; michael@0: ASSERT_EQ(0, setitimer(ITIMER_PROF, &timer, NULL)); michael@0: struct sigaction signal_action; michael@0: memset(&signal_action, 0, sizeof(signal_action)); michael@0: sigemptyset(&signal_action.sa_mask); michael@0: signal_action.sa_handler = SIG_IGN; michael@0: ASSERT_EQ(0, sigaction(SIGPROF, &signal_action, old_signal_action)); michael@0: } michael@0: michael@0: // Tests that death tests work when SIGPROF handler and timer are set. michael@0: TEST_F(TestForDeathTest, FastSigprofActionSet) { michael@0: testing::GTEST_FLAG(death_test_style) = "fast"; michael@0: SetSigprofActionAndTimer(); michael@0: EXPECT_DEATH(_exit(1), ""); michael@0: struct sigaction old_signal_action; michael@0: DisableSigprofActionAndTimer(&old_signal_action); michael@0: EXPECT_TRUE(old_signal_action.sa_sigaction == SigprofAction); michael@0: } michael@0: michael@0: TEST_F(TestForDeathTest, ThreadSafeSigprofActionSet) { michael@0: testing::GTEST_FLAG(death_test_style) = "threadsafe"; michael@0: SetSigprofActionAndTimer(); michael@0: EXPECT_DEATH(_exit(1), ""); michael@0: struct sigaction old_signal_action; michael@0: DisableSigprofActionAndTimer(&old_signal_action); michael@0: EXPECT_TRUE(old_signal_action.sa_sigaction == SigprofAction); michael@0: } michael@0: # endif // GTEST_OS_LINUX michael@0: michael@0: // Repeats a representative sample of death tests in the "threadsafe" style: michael@0: michael@0: TEST_F(TestForDeathTest, StaticMemberFunctionThreadsafeStyle) { michael@0: testing::GTEST_FLAG(death_test_style) = "threadsafe"; michael@0: ASSERT_DEATH(StaticMemberFunction(), "death.*StaticMember"); michael@0: } michael@0: michael@0: TEST_F(TestForDeathTest, MemberFunctionThreadsafeStyle) { michael@0: testing::GTEST_FLAG(death_test_style) = "threadsafe"; michael@0: should_die_ = true; michael@0: EXPECT_DEATH(MemberFunction(), "inside.*MemberFunction"); michael@0: } michael@0: michael@0: TEST_F(TestForDeathTest, ThreadsafeDeathTestInLoop) { michael@0: testing::GTEST_FLAG(death_test_style) = "threadsafe"; michael@0: michael@0: for (int i = 0; i < 3; ++i) michael@0: EXPECT_EXIT(_exit(i), testing::ExitedWithCode(i), "") << ": i = " << i; michael@0: } michael@0: michael@0: TEST_F(TestForDeathTest, ThreadsafeDeathTestInChangedDir) { michael@0: testing::GTEST_FLAG(death_test_style) = "threadsafe"; michael@0: michael@0: ChangeToRootDir(); michael@0: EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), ""); michael@0: michael@0: ChangeToRootDir(); michael@0: ASSERT_DEATH(_exit(1), ""); michael@0: } michael@0: michael@0: TEST_F(TestForDeathTest, MixedStyles) { michael@0: testing::GTEST_FLAG(death_test_style) = "threadsafe"; michael@0: EXPECT_DEATH(_exit(1), ""); michael@0: testing::GTEST_FLAG(death_test_style) = "fast"; michael@0: EXPECT_DEATH(_exit(1), ""); michael@0: } michael@0: michael@0: namespace { michael@0: michael@0: bool pthread_flag; michael@0: michael@0: void SetPthreadFlag() { michael@0: pthread_flag = true; michael@0: } michael@0: michael@0: } // namespace michael@0: michael@0: # if GTEST_HAS_CLONE && GTEST_HAS_PTHREAD michael@0: michael@0: TEST_F(TestForDeathTest, DoesNotExecuteAtforkHooks) { michael@0: if (!testing::GTEST_FLAG(death_test_use_fork)) { michael@0: testing::GTEST_FLAG(death_test_style) = "threadsafe"; michael@0: pthread_flag = false; michael@0: ASSERT_EQ(0, pthread_atfork(&SetPthreadFlag, NULL, NULL)); michael@0: ASSERT_DEATH(_exit(1), ""); michael@0: ASSERT_FALSE(pthread_flag); michael@0: } michael@0: } michael@0: michael@0: # endif // GTEST_HAS_CLONE && GTEST_HAS_PTHREAD michael@0: michael@0: // Tests that a method of another class can be used in a death test. michael@0: TEST_F(TestForDeathTest, MethodOfAnotherClass) { michael@0: const MayDie x(true); michael@0: ASSERT_DEATH(x.MemberFunction(), "MayDie\\:\\:MemberFunction"); michael@0: } michael@0: michael@0: // Tests that a global function can be used in a death test. michael@0: TEST_F(TestForDeathTest, GlobalFunction) { michael@0: EXPECT_DEATH(GlobalFunction(), "GlobalFunction"); michael@0: } michael@0: michael@0: // Tests that any value convertible to an RE works as a second michael@0: // argument to EXPECT_DEATH. michael@0: TEST_F(TestForDeathTest, AcceptsAnythingConvertibleToRE) { michael@0: static const char regex_c_str[] = "GlobalFunction"; michael@0: EXPECT_DEATH(GlobalFunction(), regex_c_str); michael@0: michael@0: const testing::internal::RE regex(regex_c_str); michael@0: EXPECT_DEATH(GlobalFunction(), regex); michael@0: michael@0: # if GTEST_HAS_GLOBAL_STRING michael@0: michael@0: const string regex_str(regex_c_str); michael@0: EXPECT_DEATH(GlobalFunction(), regex_str); michael@0: michael@0: # endif // GTEST_HAS_GLOBAL_STRING michael@0: michael@0: const ::std::string regex_std_str(regex_c_str); michael@0: EXPECT_DEATH(GlobalFunction(), regex_std_str); michael@0: } michael@0: michael@0: // Tests that a non-void function can be used in a death test. michael@0: TEST_F(TestForDeathTest, NonVoidFunction) { michael@0: ASSERT_DEATH(NonVoidFunction(), "NonVoidFunction"); michael@0: } michael@0: michael@0: // Tests that functions that take parameter(s) can be used in a death test. michael@0: TEST_F(TestForDeathTest, FunctionWithParameter) { michael@0: EXPECT_DEATH(DieIf(true), "DieIf\\(\\)"); michael@0: EXPECT_DEATH(DieIfLessThan(2, 3), "DieIfLessThan"); michael@0: } michael@0: michael@0: // Tests that ASSERT_DEATH can be used outside a TEST, TEST_F, or test fixture. michael@0: TEST_F(TestForDeathTest, OutsideFixture) { michael@0: DeathTestSubroutine(); michael@0: } michael@0: michael@0: // Tests that death tests can be done inside a loop. michael@0: TEST_F(TestForDeathTest, InsideLoop) { michael@0: for (int i = 0; i < 5; i++) { michael@0: EXPECT_DEATH(DieIfLessThan(-1, i), "DieIfLessThan") << "where i == " << i; michael@0: } michael@0: } michael@0: michael@0: // Tests that a compound statement can be used in a death test. michael@0: TEST_F(TestForDeathTest, CompoundStatement) { michael@0: EXPECT_DEATH({ // NOLINT michael@0: const int x = 2; michael@0: const int y = x + 1; michael@0: DieIfLessThan(x, y); michael@0: }, michael@0: "DieIfLessThan"); michael@0: } michael@0: michael@0: // Tests that code that doesn't die causes a death test to fail. michael@0: TEST_F(TestForDeathTest, DoesNotDie) { michael@0: EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(DieIf(false), "DieIf"), michael@0: "failed to die"); michael@0: } michael@0: michael@0: // Tests that a death test fails when the error message isn't expected. michael@0: TEST_F(TestForDeathTest, ErrorMessageMismatch) { michael@0: EXPECT_NONFATAL_FAILURE({ // NOLINT michael@0: EXPECT_DEATH(DieIf(true), "DieIfLessThan") << "End of death test message."; michael@0: }, "died but not with expected error"); michael@0: } michael@0: michael@0: // On exit, *aborted will be true iff the EXPECT_DEATH() statement michael@0: // aborted the function. michael@0: void ExpectDeathTestHelper(bool* aborted) { michael@0: *aborted = true; michael@0: EXPECT_DEATH(DieIf(false), "DieIf"); // This assertion should fail. michael@0: *aborted = false; michael@0: } michael@0: michael@0: // Tests that EXPECT_DEATH doesn't abort the test on failure. michael@0: TEST_F(TestForDeathTest, EXPECT_DEATH) { michael@0: bool aborted = true; michael@0: EXPECT_NONFATAL_FAILURE(ExpectDeathTestHelper(&aborted), michael@0: "failed to die"); michael@0: EXPECT_FALSE(aborted); michael@0: } michael@0: michael@0: // Tests that ASSERT_DEATH does abort the test on failure. michael@0: TEST_F(TestForDeathTest, ASSERT_DEATH) { michael@0: static bool aborted; michael@0: EXPECT_FATAL_FAILURE({ // NOLINT michael@0: aborted = true; michael@0: ASSERT_DEATH(DieIf(false), "DieIf"); // This assertion should fail. michael@0: aborted = false; michael@0: }, "failed to die"); michael@0: EXPECT_TRUE(aborted); michael@0: } michael@0: michael@0: // Tests that EXPECT_DEATH evaluates the arguments exactly once. michael@0: TEST_F(TestForDeathTest, SingleEvaluation) { michael@0: int x = 3; michael@0: EXPECT_DEATH(DieIf((++x) == 4), "DieIf"); michael@0: michael@0: const char* regex = "DieIf"; michael@0: const char* regex_save = regex; michael@0: EXPECT_DEATH(DieIfLessThan(3, 4), regex++); michael@0: EXPECT_EQ(regex_save + 1, regex); michael@0: } michael@0: michael@0: // Tests that run-away death tests are reported as failures. michael@0: TEST_F(TestForDeathTest, RunawayIsFailure) { michael@0: EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(static_cast(0), "Foo"), michael@0: "failed to die."); michael@0: } michael@0: michael@0: // Tests that death tests report executing 'return' in the statement as michael@0: // failure. michael@0: TEST_F(TestForDeathTest, ReturnIsFailure) { michael@0: EXPECT_FATAL_FAILURE(ASSERT_DEATH(return, "Bar"), michael@0: "illegal return in test statement."); michael@0: } michael@0: michael@0: // Tests that EXPECT_DEBUG_DEATH works as expected, that is, you can stream a michael@0: // message to it, and in debug mode it: michael@0: // 1. Asserts on death. michael@0: // 2. Has no side effect. michael@0: // michael@0: // And in opt mode, it: michael@0: // 1. Has side effects but does not assert. michael@0: TEST_F(TestForDeathTest, TestExpectDebugDeath) { michael@0: int sideeffect = 0; michael@0: michael@0: EXPECT_DEBUG_DEATH(DieInDebugElse12(&sideeffect), "death.*DieInDebugElse12") michael@0: << "Must accept a streamed message"; michael@0: michael@0: # ifdef NDEBUG michael@0: michael@0: // Checks that the assignment occurs in opt mode (sideeffect). michael@0: EXPECT_EQ(12, sideeffect); michael@0: michael@0: # else michael@0: michael@0: // Checks that the assignment does not occur in dbg mode (no sideeffect). michael@0: EXPECT_EQ(0, sideeffect); michael@0: michael@0: # endif michael@0: } michael@0: michael@0: // Tests that ASSERT_DEBUG_DEATH works as expected, that is, you can stream a michael@0: // message to it, and in debug mode it: michael@0: // 1. Asserts on death. michael@0: // 2. Has no side effect. michael@0: // michael@0: // And in opt mode, it: michael@0: // 1. Has side effects but does not assert. michael@0: TEST_F(TestForDeathTest, TestAssertDebugDeath) { michael@0: int sideeffect = 0; michael@0: michael@0: ASSERT_DEBUG_DEATH(DieInDebugElse12(&sideeffect), "death.*DieInDebugElse12") michael@0: << "Must accept a streamed message"; michael@0: michael@0: # ifdef NDEBUG michael@0: michael@0: // Checks that the assignment occurs in opt mode (sideeffect). michael@0: EXPECT_EQ(12, sideeffect); michael@0: michael@0: # else michael@0: michael@0: // Checks that the assignment does not occur in dbg mode (no sideeffect). michael@0: EXPECT_EQ(0, sideeffect); michael@0: michael@0: # endif michael@0: } michael@0: michael@0: # ifndef NDEBUG michael@0: michael@0: void ExpectDebugDeathHelper(bool* aborted) { michael@0: *aborted = true; michael@0: EXPECT_DEBUG_DEATH(return, "") << "This is expected to fail."; michael@0: *aborted = false; michael@0: } michael@0: michael@0: # if GTEST_OS_WINDOWS michael@0: TEST(PopUpDeathTest, DoesNotShowPopUpOnAbort) { michael@0: printf("This test should be considered failing if it shows " michael@0: "any pop-up dialogs.\n"); michael@0: fflush(stdout); michael@0: michael@0: EXPECT_DEATH({ michael@0: testing::GTEST_FLAG(catch_exceptions) = false; michael@0: abort(); michael@0: }, ""); michael@0: } michael@0: # endif // GTEST_OS_WINDOWS michael@0: michael@0: // Tests that EXPECT_DEBUG_DEATH in debug mode does not abort michael@0: // the function. michael@0: TEST_F(TestForDeathTest, ExpectDebugDeathDoesNotAbort) { michael@0: bool aborted = true; michael@0: EXPECT_NONFATAL_FAILURE(ExpectDebugDeathHelper(&aborted), ""); michael@0: EXPECT_FALSE(aborted); michael@0: } michael@0: michael@0: void AssertDebugDeathHelper(bool* aborted) { michael@0: *aborted = true; michael@0: ASSERT_DEBUG_DEATH(return, "") << "This is expected to fail."; michael@0: *aborted = false; michael@0: } michael@0: michael@0: // Tests that ASSERT_DEBUG_DEATH in debug mode aborts the function on michael@0: // failure. michael@0: TEST_F(TestForDeathTest, AssertDebugDeathAborts) { michael@0: static bool aborted; michael@0: aborted = false; michael@0: EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), ""); michael@0: EXPECT_TRUE(aborted); michael@0: } michael@0: michael@0: # endif // _NDEBUG michael@0: michael@0: // Tests the *_EXIT family of macros, using a variety of predicates. michael@0: static void TestExitMacros() { michael@0: EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), ""); michael@0: ASSERT_EXIT(_exit(42), testing::ExitedWithCode(42), ""); michael@0: michael@0: # if GTEST_OS_WINDOWS michael@0: michael@0: // Of all signals effects on the process exit code, only those of SIGABRT michael@0: // are documented on Windows. michael@0: // See http://msdn.microsoft.com/en-us/library/dwwzkt4c(VS.71).aspx. michael@0: EXPECT_EXIT(raise(SIGABRT), testing::ExitedWithCode(3), "") << "b_ar"; michael@0: michael@0: # else michael@0: michael@0: EXPECT_EXIT(raise(SIGKILL), testing::KilledBySignal(SIGKILL), "") << "foo"; michael@0: ASSERT_EXIT(raise(SIGUSR2), testing::KilledBySignal(SIGUSR2), "") << "bar"; michael@0: michael@0: EXPECT_FATAL_FAILURE({ // NOLINT michael@0: ASSERT_EXIT(_exit(0), testing::KilledBySignal(SIGSEGV), "") michael@0: << "This failure is expected, too."; michael@0: }, "This failure is expected, too."); michael@0: michael@0: # endif // GTEST_OS_WINDOWS michael@0: michael@0: EXPECT_NONFATAL_FAILURE({ // NOLINT michael@0: EXPECT_EXIT(raise(SIGSEGV), testing::ExitedWithCode(0), "") michael@0: << "This failure is expected."; michael@0: }, "This failure is expected."); michael@0: } michael@0: michael@0: TEST_F(TestForDeathTest, ExitMacros) { michael@0: TestExitMacros(); michael@0: } michael@0: michael@0: TEST_F(TestForDeathTest, ExitMacrosUsingFork) { michael@0: testing::GTEST_FLAG(death_test_use_fork) = true; michael@0: TestExitMacros(); michael@0: } michael@0: michael@0: TEST_F(TestForDeathTest, InvalidStyle) { michael@0: testing::GTEST_FLAG(death_test_style) = "rococo"; michael@0: EXPECT_NONFATAL_FAILURE({ // NOLINT michael@0: EXPECT_DEATH(_exit(0), "") << "This failure is expected."; michael@0: }, "This failure is expected."); michael@0: } michael@0: michael@0: TEST_F(TestForDeathTest, DeathTestFailedOutput) { michael@0: testing::GTEST_FLAG(death_test_style) = "fast"; michael@0: EXPECT_NONFATAL_FAILURE( michael@0: EXPECT_DEATH(DieWithMessage("death\n"), michael@0: "expected message"), michael@0: "Actual msg:\n" michael@0: "[ DEATH ] death\n"); michael@0: } michael@0: michael@0: TEST_F(TestForDeathTest, DeathTestUnexpectedReturnOutput) { michael@0: testing::GTEST_FLAG(death_test_style) = "fast"; michael@0: EXPECT_NONFATAL_FAILURE( michael@0: EXPECT_DEATH({ michael@0: fprintf(stderr, "returning\n"); michael@0: fflush(stderr); michael@0: return; michael@0: }, ""), michael@0: " Result: illegal return in test statement.\n" michael@0: " Error msg:\n" michael@0: "[ DEATH ] returning\n"); michael@0: } michael@0: michael@0: TEST_F(TestForDeathTest, DeathTestBadExitCodeOutput) { michael@0: testing::GTEST_FLAG(death_test_style) = "fast"; michael@0: EXPECT_NONFATAL_FAILURE( michael@0: EXPECT_EXIT(DieWithMessage("exiting with rc 1\n"), michael@0: testing::ExitedWithCode(3), michael@0: "expected message"), michael@0: " Result: died but not with expected exit code:\n" michael@0: " Exited with exit status 1\n" michael@0: "Actual msg:\n" michael@0: "[ DEATH ] exiting with rc 1\n"); michael@0: } michael@0: michael@0: TEST_F(TestForDeathTest, DeathTestMultiLineMatchFail) { michael@0: testing::GTEST_FLAG(death_test_style) = "fast"; michael@0: EXPECT_NONFATAL_FAILURE( michael@0: EXPECT_DEATH(DieWithMessage("line 1\nline 2\nline 3\n"), michael@0: "line 1\nxyz\nline 3\n"), michael@0: "Actual msg:\n" michael@0: "[ DEATH ] line 1\n" michael@0: "[ DEATH ] line 2\n" michael@0: "[ DEATH ] line 3\n"); michael@0: } michael@0: michael@0: TEST_F(TestForDeathTest, DeathTestMultiLineMatchPass) { michael@0: testing::GTEST_FLAG(death_test_style) = "fast"; michael@0: EXPECT_DEATH(DieWithMessage("line 1\nline 2\nline 3\n"), michael@0: "line 1\nline 2\nline 3\n"); michael@0: } michael@0: michael@0: // A DeathTestFactory that returns MockDeathTests. michael@0: class MockDeathTestFactory : public DeathTestFactory { michael@0: public: michael@0: MockDeathTestFactory(); michael@0: virtual bool Create(const char* statement, michael@0: const ::testing::internal::RE* regex, michael@0: const char* file, int line, DeathTest** test); michael@0: michael@0: // Sets the parameters for subsequent calls to Create. michael@0: void SetParameters(bool create, DeathTest::TestRole role, michael@0: int status, bool passed); michael@0: michael@0: // Accessors. michael@0: int AssumeRoleCalls() const { return assume_role_calls_; } michael@0: int WaitCalls() const { return wait_calls_; } michael@0: int PassedCalls() const { return passed_args_.size(); } michael@0: bool PassedArgument(int n) const { return passed_args_[n]; } michael@0: int AbortCalls() const { return abort_args_.size(); } michael@0: DeathTest::AbortReason AbortArgument(int n) const { michael@0: return abort_args_[n]; michael@0: } michael@0: bool TestDeleted() const { return test_deleted_; } michael@0: michael@0: private: michael@0: friend class MockDeathTest; michael@0: // If true, Create will return a MockDeathTest; otherwise it returns michael@0: // NULL. michael@0: bool create_; michael@0: // The value a MockDeathTest will return from its AssumeRole method. michael@0: DeathTest::TestRole role_; michael@0: // The value a MockDeathTest will return from its Wait method. michael@0: int status_; michael@0: // The value a MockDeathTest will return from its Passed method. michael@0: bool passed_; michael@0: michael@0: // Number of times AssumeRole was called. michael@0: int assume_role_calls_; michael@0: // Number of times Wait was called. michael@0: int wait_calls_; michael@0: // The arguments to the calls to Passed since the last call to michael@0: // SetParameters. michael@0: std::vector passed_args_; michael@0: // The arguments to the calls to Abort since the last call to michael@0: // SetParameters. michael@0: std::vector abort_args_; michael@0: // True if the last MockDeathTest returned by Create has been michael@0: // deleted. michael@0: bool test_deleted_; michael@0: }; michael@0: michael@0: michael@0: // A DeathTest implementation useful in testing. It returns values set michael@0: // at its creation from its various inherited DeathTest methods, and michael@0: // reports calls to those methods to its parent MockDeathTestFactory michael@0: // object. michael@0: class MockDeathTest : public DeathTest { michael@0: public: michael@0: MockDeathTest(MockDeathTestFactory *parent, michael@0: TestRole role, int status, bool passed) : michael@0: parent_(parent), role_(role), status_(status), passed_(passed) { michael@0: } michael@0: virtual ~MockDeathTest() { michael@0: parent_->test_deleted_ = true; michael@0: } michael@0: virtual TestRole AssumeRole() { michael@0: ++parent_->assume_role_calls_; michael@0: return role_; michael@0: } michael@0: virtual int Wait() { michael@0: ++parent_->wait_calls_; michael@0: return status_; michael@0: } michael@0: virtual bool Passed(bool exit_status_ok) { michael@0: parent_->passed_args_.push_back(exit_status_ok); michael@0: return passed_; michael@0: } michael@0: virtual void Abort(AbortReason reason) { michael@0: parent_->abort_args_.push_back(reason); michael@0: } michael@0: michael@0: private: michael@0: MockDeathTestFactory* const parent_; michael@0: const TestRole role_; michael@0: const int status_; michael@0: const bool passed_; michael@0: }; michael@0: michael@0: michael@0: // MockDeathTestFactory constructor. michael@0: MockDeathTestFactory::MockDeathTestFactory() michael@0: : create_(true), michael@0: role_(DeathTest::OVERSEE_TEST), michael@0: status_(0), michael@0: passed_(true), michael@0: assume_role_calls_(0), michael@0: wait_calls_(0), michael@0: passed_args_(), michael@0: abort_args_() { michael@0: } michael@0: michael@0: michael@0: // Sets the parameters for subsequent calls to Create. michael@0: void MockDeathTestFactory::SetParameters(bool create, michael@0: DeathTest::TestRole role, michael@0: int status, bool passed) { michael@0: create_ = create; michael@0: role_ = role; michael@0: status_ = status; michael@0: passed_ = passed; michael@0: michael@0: assume_role_calls_ = 0; michael@0: wait_calls_ = 0; michael@0: passed_args_.clear(); michael@0: abort_args_.clear(); michael@0: } michael@0: michael@0: michael@0: // Sets test to NULL (if create_ is false) or to the address of a new michael@0: // MockDeathTest object with parameters taken from the last call michael@0: // to SetParameters (if create_ is true). Always returns true. michael@0: bool MockDeathTestFactory::Create(const char* /*statement*/, michael@0: const ::testing::internal::RE* /*regex*/, michael@0: const char* /*file*/, michael@0: int /*line*/, michael@0: DeathTest** test) { michael@0: test_deleted_ = false; michael@0: if (create_) { michael@0: *test = new MockDeathTest(this, role_, status_, passed_); michael@0: } else { michael@0: *test = NULL; michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: // A test fixture for testing the logic of the GTEST_DEATH_TEST_ macro. michael@0: // It installs a MockDeathTestFactory that is used for the duration michael@0: // of the test case. michael@0: class MacroLogicDeathTest : public testing::Test { michael@0: protected: michael@0: static testing::internal::ReplaceDeathTestFactory* replacer_; michael@0: static MockDeathTestFactory* factory_; michael@0: michael@0: static void SetUpTestCase() { michael@0: factory_ = new MockDeathTestFactory; michael@0: replacer_ = new testing::internal::ReplaceDeathTestFactory(factory_); michael@0: } michael@0: michael@0: static void TearDownTestCase() { michael@0: delete replacer_; michael@0: replacer_ = NULL; michael@0: delete factory_; michael@0: factory_ = NULL; michael@0: } michael@0: michael@0: // Runs a death test that breaks the rules by returning. Such a death michael@0: // test cannot be run directly from a test routine that uses a michael@0: // MockDeathTest, or the remainder of the routine will not be executed. michael@0: static void RunReturningDeathTest(bool* flag) { michael@0: ASSERT_DEATH({ // NOLINT michael@0: *flag = true; michael@0: return; michael@0: }, ""); michael@0: } michael@0: }; michael@0: michael@0: testing::internal::ReplaceDeathTestFactory* MacroLogicDeathTest::replacer_ michael@0: = NULL; michael@0: MockDeathTestFactory* MacroLogicDeathTest::factory_ = NULL; michael@0: michael@0: michael@0: // Test that nothing happens when the factory doesn't return a DeathTest: michael@0: TEST_F(MacroLogicDeathTest, NothingHappens) { michael@0: bool flag = false; michael@0: factory_->SetParameters(false, DeathTest::OVERSEE_TEST, 0, true); michael@0: EXPECT_DEATH(flag = true, ""); michael@0: EXPECT_FALSE(flag); michael@0: EXPECT_EQ(0, factory_->AssumeRoleCalls()); michael@0: EXPECT_EQ(0, factory_->WaitCalls()); michael@0: EXPECT_EQ(0, factory_->PassedCalls()); michael@0: EXPECT_EQ(0, factory_->AbortCalls()); michael@0: EXPECT_FALSE(factory_->TestDeleted()); michael@0: } michael@0: michael@0: // Test that the parent process doesn't run the death test code, michael@0: // and that the Passed method returns false when the (simulated) michael@0: // child process exits with status 0: michael@0: TEST_F(MacroLogicDeathTest, ChildExitsSuccessfully) { michael@0: bool flag = false; michael@0: factory_->SetParameters(true, DeathTest::OVERSEE_TEST, 0, true); michael@0: EXPECT_DEATH(flag = true, ""); michael@0: EXPECT_FALSE(flag); michael@0: EXPECT_EQ(1, factory_->AssumeRoleCalls()); michael@0: EXPECT_EQ(1, factory_->WaitCalls()); michael@0: ASSERT_EQ(1, factory_->PassedCalls()); michael@0: EXPECT_FALSE(factory_->PassedArgument(0)); michael@0: EXPECT_EQ(0, factory_->AbortCalls()); michael@0: EXPECT_TRUE(factory_->TestDeleted()); michael@0: } michael@0: michael@0: // Tests that the Passed method was given the argument "true" when michael@0: // the (simulated) child process exits with status 1: michael@0: TEST_F(MacroLogicDeathTest, ChildExitsUnsuccessfully) { michael@0: bool flag = false; michael@0: factory_->SetParameters(true, DeathTest::OVERSEE_TEST, 1, true); michael@0: EXPECT_DEATH(flag = true, ""); michael@0: EXPECT_FALSE(flag); michael@0: EXPECT_EQ(1, factory_->AssumeRoleCalls()); michael@0: EXPECT_EQ(1, factory_->WaitCalls()); michael@0: ASSERT_EQ(1, factory_->PassedCalls()); michael@0: EXPECT_TRUE(factory_->PassedArgument(0)); michael@0: EXPECT_EQ(0, factory_->AbortCalls()); michael@0: EXPECT_TRUE(factory_->TestDeleted()); michael@0: } michael@0: michael@0: // Tests that the (simulated) child process executes the death test michael@0: // code, and is aborted with the correct AbortReason if it michael@0: // executes a return statement. michael@0: TEST_F(MacroLogicDeathTest, ChildPerformsReturn) { michael@0: bool flag = false; michael@0: factory_->SetParameters(true, DeathTest::EXECUTE_TEST, 0, true); michael@0: RunReturningDeathTest(&flag); michael@0: EXPECT_TRUE(flag); michael@0: EXPECT_EQ(1, factory_->AssumeRoleCalls()); michael@0: EXPECT_EQ(0, factory_->WaitCalls()); michael@0: EXPECT_EQ(0, factory_->PassedCalls()); michael@0: EXPECT_EQ(1, factory_->AbortCalls()); michael@0: EXPECT_EQ(DeathTest::TEST_ENCOUNTERED_RETURN_STATEMENT, michael@0: factory_->AbortArgument(0)); michael@0: EXPECT_TRUE(factory_->TestDeleted()); michael@0: } michael@0: michael@0: // Tests that the (simulated) child process is aborted with the michael@0: // correct AbortReason if it does not die. michael@0: TEST_F(MacroLogicDeathTest, ChildDoesNotDie) { michael@0: bool flag = false; michael@0: factory_->SetParameters(true, DeathTest::EXECUTE_TEST, 0, true); michael@0: EXPECT_DEATH(flag = true, ""); michael@0: EXPECT_TRUE(flag); michael@0: EXPECT_EQ(1, factory_->AssumeRoleCalls()); michael@0: EXPECT_EQ(0, factory_->WaitCalls()); michael@0: EXPECT_EQ(0, factory_->PassedCalls()); michael@0: // This time there are two calls to Abort: one since the test didn't michael@0: // die, and another from the ReturnSentinel when it's destroyed. The michael@0: // sentinel normally isn't destroyed if a test doesn't die, since michael@0: // _exit(2) is called in that case by ForkingDeathTest, but not by michael@0: // our MockDeathTest. michael@0: ASSERT_EQ(2, factory_->AbortCalls()); michael@0: EXPECT_EQ(DeathTest::TEST_DID_NOT_DIE, michael@0: factory_->AbortArgument(0)); michael@0: EXPECT_EQ(DeathTest::TEST_ENCOUNTERED_RETURN_STATEMENT, michael@0: factory_->AbortArgument(1)); michael@0: EXPECT_TRUE(factory_->TestDeleted()); michael@0: } michael@0: michael@0: // Tests that a successful death test does not register a successful michael@0: // test part. michael@0: TEST(SuccessRegistrationDeathTest, NoSuccessPart) { michael@0: EXPECT_DEATH(_exit(1), ""); michael@0: EXPECT_EQ(0, GetUnitTestImpl()->current_test_result()->total_part_count()); michael@0: } michael@0: michael@0: TEST(StreamingAssertionsDeathTest, DeathTest) { michael@0: EXPECT_DEATH(_exit(1), "") << "unexpected failure"; michael@0: ASSERT_DEATH(_exit(1), "") << "unexpected failure"; michael@0: EXPECT_NONFATAL_FAILURE({ // NOLINT michael@0: EXPECT_DEATH(_exit(0), "") << "expected failure"; michael@0: }, "expected failure"); michael@0: EXPECT_FATAL_FAILURE({ // NOLINT michael@0: ASSERT_DEATH(_exit(0), "") << "expected failure"; michael@0: }, "expected failure"); michael@0: } michael@0: michael@0: // Tests that GetLastErrnoDescription returns an empty string when the michael@0: // last error is 0 and non-empty string when it is non-zero. michael@0: TEST(GetLastErrnoDescription, GetLastErrnoDescriptionWorks) { michael@0: errno = ENOENT; michael@0: EXPECT_STRNE("", GetLastErrnoDescription().c_str()); michael@0: errno = 0; michael@0: EXPECT_STREQ("", GetLastErrnoDescription().c_str()); michael@0: } michael@0: michael@0: # if GTEST_OS_WINDOWS michael@0: TEST(AutoHandleTest, AutoHandleWorks) { michael@0: HANDLE handle = ::CreateEvent(NULL, FALSE, FALSE, NULL); michael@0: ASSERT_NE(INVALID_HANDLE_VALUE, handle); michael@0: michael@0: // Tests that the AutoHandle is correctly initialized with a handle. michael@0: testing::internal::AutoHandle auto_handle(handle); michael@0: EXPECT_EQ(handle, auto_handle.Get()); michael@0: michael@0: // Tests that Reset assigns INVALID_HANDLE_VALUE. michael@0: // Note that this cannot verify whether the original handle is closed. michael@0: auto_handle.Reset(); michael@0: EXPECT_EQ(INVALID_HANDLE_VALUE, auto_handle.Get()); michael@0: michael@0: // Tests that Reset assigns the new handle. michael@0: // Note that this cannot verify whether the original handle is closed. michael@0: handle = ::CreateEvent(NULL, FALSE, FALSE, NULL); michael@0: ASSERT_NE(INVALID_HANDLE_VALUE, handle); michael@0: auto_handle.Reset(handle); michael@0: EXPECT_EQ(handle, auto_handle.Get()); michael@0: michael@0: // Tests that AutoHandle contains INVALID_HANDLE_VALUE by default. michael@0: testing::internal::AutoHandle auto_handle2; michael@0: EXPECT_EQ(INVALID_HANDLE_VALUE, auto_handle2.Get()); michael@0: } michael@0: # endif // GTEST_OS_WINDOWS michael@0: michael@0: # if GTEST_OS_WINDOWS michael@0: typedef unsigned __int64 BiggestParsable; michael@0: typedef signed __int64 BiggestSignedParsable; michael@0: const BiggestParsable kBiggestParsableMax = ULLONG_MAX; michael@0: const BiggestSignedParsable kBiggestSignedParsableMax = LLONG_MAX; michael@0: # else michael@0: typedef unsigned long long BiggestParsable; michael@0: typedef signed long long BiggestSignedParsable; michael@0: const BiggestParsable kBiggestParsableMax = michael@0: ::std::numeric_limits::max(); michael@0: const BiggestSignedParsable kBiggestSignedParsableMax = michael@0: ::std::numeric_limits::max(); michael@0: # endif // GTEST_OS_WINDOWS michael@0: michael@0: TEST(ParseNaturalNumberTest, RejectsInvalidFormat) { michael@0: BiggestParsable result = 0; michael@0: michael@0: // Rejects non-numbers. michael@0: EXPECT_FALSE(ParseNaturalNumber(String("non-number string"), &result)); michael@0: michael@0: // Rejects numbers with whitespace prefix. michael@0: EXPECT_FALSE(ParseNaturalNumber(String(" 123"), &result)); michael@0: michael@0: // Rejects negative numbers. michael@0: EXPECT_FALSE(ParseNaturalNumber(String("-123"), &result)); michael@0: michael@0: // Rejects numbers starting with a plus sign. michael@0: EXPECT_FALSE(ParseNaturalNumber(String("+123"), &result)); michael@0: errno = 0; michael@0: } michael@0: michael@0: TEST(ParseNaturalNumberTest, RejectsOverflownNumbers) { michael@0: BiggestParsable result = 0; michael@0: michael@0: EXPECT_FALSE(ParseNaturalNumber(String("99999999999999999999999"), &result)); michael@0: michael@0: signed char char_result = 0; michael@0: EXPECT_FALSE(ParseNaturalNumber(String("200"), &char_result)); michael@0: errno = 0; michael@0: } michael@0: michael@0: TEST(ParseNaturalNumberTest, AcceptsValidNumbers) { michael@0: BiggestParsable result = 0; michael@0: michael@0: result = 0; michael@0: ASSERT_TRUE(ParseNaturalNumber(String("123"), &result)); michael@0: EXPECT_EQ(123U, result); michael@0: michael@0: // Check 0 as an edge case. michael@0: result = 1; michael@0: ASSERT_TRUE(ParseNaturalNumber(String("0"), &result)); michael@0: EXPECT_EQ(0U, result); michael@0: michael@0: result = 1; michael@0: ASSERT_TRUE(ParseNaturalNumber(String("00000"), &result)); michael@0: EXPECT_EQ(0U, result); michael@0: } michael@0: michael@0: TEST(ParseNaturalNumberTest, AcceptsTypeLimits) { michael@0: Message msg; michael@0: msg << kBiggestParsableMax; michael@0: michael@0: BiggestParsable result = 0; michael@0: EXPECT_TRUE(ParseNaturalNumber(msg.GetString(), &result)); michael@0: EXPECT_EQ(kBiggestParsableMax, result); michael@0: michael@0: Message msg2; michael@0: msg2 << kBiggestSignedParsableMax; michael@0: michael@0: BiggestSignedParsable signed_result = 0; michael@0: EXPECT_TRUE(ParseNaturalNumber(msg2.GetString(), &signed_result)); michael@0: EXPECT_EQ(kBiggestSignedParsableMax, signed_result); michael@0: michael@0: Message msg3; michael@0: msg3 << INT_MAX; michael@0: michael@0: int int_result = 0; michael@0: EXPECT_TRUE(ParseNaturalNumber(msg3.GetString(), &int_result)); michael@0: EXPECT_EQ(INT_MAX, int_result); michael@0: michael@0: Message msg4; michael@0: msg4 << UINT_MAX; michael@0: michael@0: unsigned int uint_result = 0; michael@0: EXPECT_TRUE(ParseNaturalNumber(msg4.GetString(), &uint_result)); michael@0: EXPECT_EQ(UINT_MAX, uint_result); michael@0: } michael@0: michael@0: TEST(ParseNaturalNumberTest, WorksForShorterIntegers) { michael@0: short short_result = 0; michael@0: ASSERT_TRUE(ParseNaturalNumber(String("123"), &short_result)); michael@0: EXPECT_EQ(123, short_result); michael@0: michael@0: signed char char_result = 0; michael@0: ASSERT_TRUE(ParseNaturalNumber(String("123"), &char_result)); michael@0: EXPECT_EQ(123, char_result); michael@0: } michael@0: michael@0: # if GTEST_OS_WINDOWS michael@0: TEST(EnvironmentTest, HandleFitsIntoSizeT) { michael@0: // TODO(vladl@google.com): Remove this test after this condition is verified michael@0: // in a static assertion in gtest-death-test.cc in the function michael@0: // GetStatusFileDescriptor. michael@0: ASSERT_TRUE(sizeof(HANDLE) <= sizeof(size_t)); michael@0: } michael@0: # endif // GTEST_OS_WINDOWS michael@0: michael@0: // Tests that EXPECT_DEATH_IF_SUPPORTED/ASSERT_DEATH_IF_SUPPORTED trigger michael@0: // failures when death tests are available on the system. michael@0: TEST(ConditionalDeathMacrosDeathTest, ExpectsDeathWhenDeathTestsAvailable) { michael@0: EXPECT_DEATH_IF_SUPPORTED(DieInside("CondDeathTestExpectMacro"), michael@0: "death inside CondDeathTestExpectMacro"); michael@0: ASSERT_DEATH_IF_SUPPORTED(DieInside("CondDeathTestAssertMacro"), michael@0: "death inside CondDeathTestAssertMacro"); michael@0: michael@0: // Empty statement will not crash, which must trigger a failure. michael@0: EXPECT_NONFATAL_FAILURE(EXPECT_DEATH_IF_SUPPORTED(;, ""), ""); michael@0: EXPECT_FATAL_FAILURE(ASSERT_DEATH_IF_SUPPORTED(;, ""), ""); michael@0: } michael@0: michael@0: #else michael@0: michael@0: using testing::internal::CaptureStderr; michael@0: using testing::internal::GetCapturedStderr; michael@0: using testing::internal::String; michael@0: michael@0: // Tests that EXPECT_DEATH_IF_SUPPORTED/ASSERT_DEATH_IF_SUPPORTED are still michael@0: // defined but do not trigger failures when death tests are not available on michael@0: // the system. michael@0: TEST(ConditionalDeathMacrosTest, WarnsWhenDeathTestsNotAvailable) { michael@0: // Empty statement will not crash, but that should not trigger a failure michael@0: // when death tests are not supported. michael@0: CaptureStderr(); michael@0: EXPECT_DEATH_IF_SUPPORTED(;, ""); michael@0: String output = GetCapturedStderr(); michael@0: ASSERT_TRUE(NULL != strstr(output.c_str(), michael@0: "Death tests are not supported on this platform")); michael@0: ASSERT_TRUE(NULL != strstr(output.c_str(), ";")); michael@0: michael@0: // The streamed message should not be printed as there is no test failure. michael@0: CaptureStderr(); michael@0: EXPECT_DEATH_IF_SUPPORTED(;, "") << "streamed message"; michael@0: output = GetCapturedStderr(); michael@0: ASSERT_TRUE(NULL == strstr(output.c_str(), "streamed message")); michael@0: michael@0: CaptureStderr(); michael@0: ASSERT_DEATH_IF_SUPPORTED(;, ""); // NOLINT michael@0: output = GetCapturedStderr(); michael@0: ASSERT_TRUE(NULL != strstr(output.c_str(), michael@0: "Death tests are not supported on this platform")); michael@0: ASSERT_TRUE(NULL != strstr(output.c_str(), ";")); michael@0: michael@0: CaptureStderr(); michael@0: ASSERT_DEATH_IF_SUPPORTED(;, "") << "streamed message"; // NOLINT michael@0: output = GetCapturedStderr(); michael@0: ASSERT_TRUE(NULL == strstr(output.c_str(), "streamed message")); michael@0: } michael@0: michael@0: void FuncWithAssert(int* n) { michael@0: ASSERT_DEATH_IF_SUPPORTED(return;, ""); michael@0: (*n)++; michael@0: } michael@0: michael@0: // Tests that ASSERT_DEATH_IF_SUPPORTED does not return from the current michael@0: // function (as ASSERT_DEATH does) if death tests are not supported. michael@0: TEST(ConditionalDeathMacrosTest, AssertDeatDoesNotReturnhIfUnsupported) { michael@0: int n = 0; michael@0: FuncWithAssert(&n); michael@0: EXPECT_EQ(1, n); michael@0: } michael@0: #endif // GTEST_HAS_DEATH_TEST michael@0: michael@0: // Tests that the death test macros expand to code which may or may not michael@0: // be followed by operator<<, and that in either case the complete text michael@0: // comprises only a single C++ statement. michael@0: // michael@0: // The syntax should work whether death tests are available or not. michael@0: TEST(ConditionalDeathMacrosSyntaxDeathTest, SingleStatement) { michael@0: if (AlwaysFalse()) michael@0: // This would fail if executed; this is a compilation test only michael@0: ASSERT_DEATH_IF_SUPPORTED(return, ""); michael@0: michael@0: if (AlwaysTrue()) michael@0: EXPECT_DEATH_IF_SUPPORTED(_exit(1), ""); michael@0: else michael@0: // This empty "else" branch is meant to ensure that EXPECT_DEATH michael@0: // doesn't expand into an "if" statement without an "else" michael@0: ; // NOLINT michael@0: michael@0: if (AlwaysFalse()) michael@0: ASSERT_DEATH_IF_SUPPORTED(return, "") << "did not die"; michael@0: michael@0: if (AlwaysFalse()) michael@0: ; // NOLINT michael@0: else michael@0: EXPECT_DEATH_IF_SUPPORTED(_exit(1), "") << 1 << 2 << 3; michael@0: } michael@0: michael@0: // Tests that conditional death test macros expand to code which interacts michael@0: // well with switch statements. michael@0: TEST(ConditionalDeathMacrosSyntaxDeathTest, SwitchStatement) { michael@0: // Microsoft compiler usually complains about switch statements without michael@0: // case labels. We suppress that warning for this test. michael@0: #ifdef _MSC_VER michael@0: # pragma warning(push) michael@0: # pragma warning(disable: 4065) michael@0: #endif // _MSC_VER michael@0: michael@0: switch (0) michael@0: default: michael@0: ASSERT_DEATH_IF_SUPPORTED(_exit(1), "") michael@0: << "exit in default switch handler"; michael@0: michael@0: switch (0) michael@0: case 0: michael@0: EXPECT_DEATH_IF_SUPPORTED(_exit(1), "") << "exit in switch case"; michael@0: michael@0: #ifdef _MSC_VER michael@0: # pragma warning(pop) michael@0: #endif // _MSC_VER michael@0: } michael@0: michael@0: TEST(InDeathTestChildDeathTest, ReportsDeathTestCorrectlyInFastStyle) { michael@0: testing::GTEST_FLAG(death_test_style) = "fast"; michael@0: EXPECT_FALSE(InDeathTestChild()); michael@0: EXPECT_DEATH({ michael@0: fprintf(stderr, InDeathTestChild() ? "Inside" : "Outside"); michael@0: fflush(stderr); michael@0: _exit(1); michael@0: }, "Inside"); michael@0: } michael@0: michael@0: TEST(InDeathTestChildDeathTest, ReportsDeathTestCorrectlyInThreadSafeStyle) { michael@0: testing::GTEST_FLAG(death_test_style) = "threadsafe"; michael@0: EXPECT_FALSE(InDeathTestChild()); michael@0: EXPECT_DEATH({ michael@0: fprintf(stderr, InDeathTestChild() ? "Inside" : "Outside"); michael@0: fflush(stderr); michael@0: _exit(1); michael@0: }, "Inside"); michael@0: } michael@0: michael@0: // Tests that a test case whose name ends with "DeathTest" works fine michael@0: // on Windows. michael@0: TEST(NotADeathTest, Test) { michael@0: SUCCEED(); michael@0: }