GTest源码剖析(六)——RUN_ALL_TESTS

来源:互联网 发布:知惠是什么意思 编辑:程序博客网 时间:2024/06/03 18:54

GTest源码剖析——RUN_ALL_TESTS

  • GTest源码剖析RUN_ALL_TESTS
    • RUN_ALL_TESTS源码分析
      • 1 UnitTestRun
      • 2 HandleExceptionsInMethodIfSupported
      • 3 UnitTestImplRunAllTests
      • 5 TestCaseRun
      • 6 TestCaseRun
      • 7 TestRun
    • 参考

1 RUN_ALL_TESTS()源码分析

RUN_ALL_TESTS()之前是宏定义,现在改变为函数。其实际上仅仅是调用了UnitTest单例的Run()函数。

源码如下:
其实现为获取一个UnitTest单例,然后调用其Run()函数

int RUN_ALL_TESTS();inline int RUN_ALL_TESTS() {  return ::testing::UnitTest::GetInstance()->Run();}

实际上,RUN_ALL_TESTS()的操作主要是,依次调用
1. UnitTest::Run()
2. UnitTest::Run()
3. UnitTestImpl::RunAllTests()
4. TestCase::Run()
5. TestCase::Run()
6. Test::Run()
7. Test::TestBody()

并在这些函数里设置相应的操作,以保证测试运行的正确性。

1.1 UnitTest::Run()

UnitTest::Run()主要设置了相关死亡测试的设置。真正的实现交给了RunAllTest()

  1. 如果忽略死亡测试和支持跨平台及异常处理的逻辑,其实现可以简化为:
int UnitTest::Run() {  return internal::HandleExceptionsInMethodIfSupported(      impl(),      &internal::UnitTestImpl::RunAllTests,      "auxiliary test code (environments or event listeners)") ? 0 : 1;}
  1. 如果我们在剔除HandleExceptionsInMethodIfSupported对支持跨平台及异常处理的逻辑,其实现直接简化为:
int UnitTest::Run() {  return impl->RunAllTests();}
  1. 全部源码如下:
int UnitTest::Run() {  const bool in_death_test_child_process = GTEST_FLAG(internal_run_death_test).length() > 0;  const internal::ScopedPrematureExitFile premature_exit_file(      in_death_test_child_process ?      NULL : internal::posix::GetEnv("TEST_PREMATURE_EXIT_FILE"));  impl()->set_catch_exceptions(GTEST_FLAG(catch_exceptions));#if GTEST_HAS_SEH  if (impl()->catch_exceptions() || in_death_test_child_process)   {# if !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT    SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |                 SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);# endif  # if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE    _set_error_mode(_OUT_TO_STDERR);# endif# if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE    if (!GTEST_FLAG(break_on_failure))      _set_abort_behavior(0x0, flags:_WRITE_ABORT_MSG | _CALL_REPORTFAULT); # endif  }#endif  // GTEST_HAS_SEH  return internal::HandleExceptionsInMethodIfSupported(      impl(),      &internal::UnitTestImpl::RunAllTests,      "auxiliary test code (environments or event listeners)") ? 0 : 1;}

1.2 HandleExceptionsInMethodIfSupported

HandleSehExceptionsInMethodIfSupported 主要用于捕获异常和跨平台处理。
这里可以看出GTest对于跨平台的支持和捕获异常的不遗余力。其实这么多代码主要是为了实现如下的功能:

Result HandleExceptionsInMethodIfSupported(T* object, Result (T::*method)(), const char* location) {    return (object->*method)();}

全部源码如下:

template <class T, typename Result>Result HandleExceptionsInMethodIfSupported(T* object, Result (T::*method)(), const char* location) {  if (internal::GetUnitTestImpl()->catch_exceptions())   {#if GTEST_HAS_EXCEPTIONS    try     {      return HandleSehExceptionsInMethodIfSupported(object, method, location);    }     catch (const internal::GoogleTestFailureException&)     {       throw;    }     catch (const std::exception& e)     {       internal::ReportFailureInUnknownLocation(          TestPartResult::kFatalFailure,          FormatCxxExceptionMessage(e.what(), location));    }     catch (...)     {        internal::ReportFailureInUnknownLocation(          TestPartResult::kFatalFailure,          FormatCxxExceptionMessage(NULL, location));    }    return static_cast<Result>(0);#else    return HandleSehExceptionsInMethodIfSupported(object, method, location);#endif  // GTEST_HAS_EXCEPTIONS  }   else   {    return (object->*method)();  }}//HandleSehExceptionsInMethodIfSupported 主要用于捕获异常。template <class T, typename Result>Result HandleSehExceptionsInMethodIfSupported(    T* object, Result (T::*method)(), const char* location) {#if GTEST_HAS_SEH  __try   {    return (object->*method)();  }   __except (internal::UnitTestOptions::GTestShouldProcessSEH( GetExceptionCode()))   {    std::string* exception_message = FormatSehExceptionMessage(        GetExceptionCode(), location);    internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure,                                             *exception_message);    delete exception_message;    return static_cast<Result>(0);  }#else  (void)location;  return (object->*method)();#endif  // GTEST_HAS_SEH}

1.3 UnitTestImpl::RunAllTests()

bool UnitTestImpl::RunAllTests() {  // Makes sure InitGoogleTest() was called.  if (!GTestIsInitialized())   {    printf("%s",           "\nThis test program did NOT call ::testing::InitGoogleTest "           "before calling RUN_ALL_TESTS().  Please fix it.\n");    return false;  }  // Do not run any test if the --help flag was specified.  if (g_help_flag)    return true;  // Repeats the call to the post-flag parsing initialization in case the  // user didn't call InitGoogleTest.  PostFlagParsingInit();  // Even if sharding is not on, test runners may want to use the  // GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding  // protocol.  internal::WriteToShardStatusFileIfNeeded();  //执行死亡测试  bool in_subprocess_for_death_test = false;#if GTEST_HAS_DEATH_TEST  in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL);# if defined(GTEST_EXTRA_DEATH_TEST_CHILD_SETUP_)  if (in_subprocess_for_death_test)   {    GTEST_EXTRA_DEATH_TEST_CHILD_SETUP_();  }# endif#endif  // GTEST_HAS_DEATH_TEST    //应该是检查environments相关的设置,可以暂不关心。  const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex,                                        in_subprocess_for_death_test);    //匹配Filter,对所有的测试用例进行匹配,确定是否需要运行该测试用例  const bool has_tests_to_run = FilterTests(should_shard                                              ? HONOR_SHARDING_PROTOCOL                                              : IGNORE_SHARDING_PROTOCOL) > 0;  // Lists the tests and exits if the --gtest_list_tests flag was specified.  if (GTEST_FLAG(list_tests))   {    ListTestsMatchingFilter();    return true;  }  //设置随机运行测试用例  random_seed_ = GTEST_FLAG(shuffle) ? GetRandomSeedFromFlag(GTEST_FLAG(random_seed)) : 0;  // True iff at least one test has failed.  bool failed = false;  //获取事件监听器,如果用户订阅了某事件,则在适当的时间点上报该事件,让用户进行额外的操作  TestEventListener* repeater = listeners()->repeater();  start_timestamp_ = GetTimeInMillis();  //上报事件OnTestProgramStart  repeater->OnTestProgramStart(*parent_);  const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat);  const bool forever = repeat < 0;  for (int i = 0; forever || i != repeat; i++)   {    //清除所有非AddHoc的测试结果,为后续运行做准备。    ClearNonAdHocTestResult();    const TimeInMillis start = GetTimeInMillis();    // Shuffles test cases and tests if requested.    if (has_tests_to_run && GTEST_FLAG(shuffle))     {      random()->Reseed(random_seed_);      ShuffleTests();    }    // Tells the unit test event listeners that the tests are about to start.    repeater->OnTestIterationStart(*parent_, i);    // Runs each test case if there is at least one test to run.    if (has_tests_to_run)     {      // Sets up all environments beforehand.      repeater->OnEnvironmentsSetUpStart(*parent_);      ForEach(environments_, SetUpEnvironment);      repeater->OnEnvironmentsSetUpEnd(*parent_);      // Runs the tests only if there was no fatal failure during global      // set-up.      if (!Test::HasFatalFailure())       {        //逐个运行TestCase,即最终运行所有的TestBody()        for (int test_index = 0; test_index < total_test_case_count(); test_index++)         {          GetMutableTestCase(test_index)->Run();        }      }      // Tears down all environments in reverse order afterwards.      repeater->OnEnvironmentsTearDownStart(*parent_);      std::for_each(environments_.rbegin(), environments_.rend(),TearDownEnvironment);      repeater->OnEnvironmentsTearDownEnd(*parent_);    }    elapsed_time_ = GetTimeInMillis() - start;    // Tells the unit test event listener that the tests have just finished.    repeater->OnTestIterationEnd(*parent_, i);    // Gets the result and clears it.    if (!Passed())     {      failed = true;    }    UnshuffleTests();    if (GTEST_FLAG(shuffle))     {      // Picks a new random seed for each iteration.      random_seed_ = GetNextRandomSeed(random_seed_);    }  }  //上报事件OnTestProgramEnd  repeater->OnTestProgramEnd(*parent_);  return !failed;}

1.5 TestCase::Run()

// Runs every test in this TestCase.void TestCase::Run() {  if (!should_run_) return;  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();  impl->set_current_test_case(this);  TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();  //上报事件OnTestCaseStart  repeater->OnTestCaseStart(*this);  impl->os_stack_trace_getter()->UponLeavingGTest();  //for TEST_F  internal::HandleExceptionsInMethodIfSupported(      this, &TestCase::RunSetUpTestCase, "SetUpTestCase()");  const internal::TimeInMillis start = internal::GetTimeInMillis();  //逐个运行TestCase里的Test,即最终运行所有的TestBody()  for (int i = 0; i < total_test_count(); i++)   {    GetMutableTestInfo(i)->Run();  }  elapsed_time_ = internal::GetTimeInMillis() - start;  impl->os_stack_trace_getter()->UponLeavingGTest();  //for TEST_F  internal::HandleExceptionsInMethodIfSupported(      this, &TestCase::RunTearDownTestCase, "TearDownTestCase()");  repeater->OnTestCaseEnd(*this);  impl->set_current_test_case(NULL);}

1.6 TestCase::Run()

void TestInfo::Run() {  if (!should_run_) return;  // Tells UnitTest where to store test result.  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();  impl->set_current_test_info(this);  TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();  // Notifies the unit test event listeners that a test is about to start.  repeater->OnTestStart(*this);  const TimeInMillis start = internal::GetTimeInMillis();  impl->os_stack_trace_getter()->UponLeavingGTest();  // Creates the test object.  // 此处确保所有的TEST_P里调用GetParam()的正确性  Test* const test = internal::HandleExceptionsInMethodIfSupported(      factory_, &internal::TestFactoryBase::CreateTest,      "the test fixture's constructor");  // Runs the test only if the test object was created and its  // constructor didn't generate a fatal failure.  if ((test != NULL) && !Test::HasFatalFailure())   {    // This doesn't throw as all user code that can throw are wrapped into    // exception handling code.    test->Run();  }  // Deletes the test object.  impl->os_stack_trace_getter()->UponLeavingGTest();  internal::HandleExceptionsInMethodIfSupported(      test, &Test::DeleteSelf_, "the test fixture's destructor");  result_.set_elapsed_time(internal::GetTimeInMillis() - start);  // Notifies the unit test event listener that a test has just finished.  repeater->OnTestEnd(*this);  // Tells UnitTest to stop associating assertion results to this  // test.  impl->set_current_test_info(NULL);}

1.7 Test::Run()

// Runs the test and updates the test result.void Test::Run() {  if (!HasSameFixtureClass()) return;  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();  impl->os_stack_trace_getter()->UponLeavingGTest();  //for TEST_F  internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()");  // We will run the test only if SetUp() was successful.  if (!HasFatalFailure())   {    impl->os_stack_trace_getter()->UponLeavingGTest();    internal::HandleExceptionsInMethodIfSupported(        this, &Test::TestBody, "the test body");  }  // However, we want to clean up as much as possible.  Hence we will  // always call TearDown(), even if SetUp() or the test body has  // failed.  impl->os_stack_trace_getter()->UponLeavingGTest();  // for TEST_F  internal::HandleExceptionsInMethodIfSupported(      this, &Test::TearDown, "TearDown()");}

2 参考

github: googletest


ZhaiPillar
2017-09-17

原创粉丝点击