Google Test源码浅析(三) -------- RUN_ALL_TESTS

一、例子引入:

TEST(TestCaseName1, TestName1){                                                                                                  
      cout << "hello1" << endl;                                                                                                    
 }                                                                                                                                

 int main(int argc,char* argv[])                                                                                                  
 {                                                                                                                                
   testing::InitGoogleTest(&argc, argv);                                                                                          
   return RUN_ALL_TESTS();                                                                                                        
  }  

分析:上述例子当中,看到RUN_ALL_TESTS()这个宏,从名字上来看,这是运行所有的测试用例,这才是我们运行测试用例的真正入口,下面来看一下具体的源码实现

二、源码分析

  RUN_ALL_TESTS()之前是一个宏,将其实现为函数,在这里,调用了UnitTest单例的Run函数

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

接着去看调用过程,可以看到,依次调用的过程是:
1. UnitTest::Run()
2. UnitTestImpl::RunAllTests()
3. TestCase::Run()
4. TestInfo::Run()
5. Test::Run()

2.1 UnitTest::Run()

int UnitTest::Run() {   
    //关于死亡测试                                                                                                           
    const bool in_death_test_child_process =                                                                                         
       internal::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  // !GTEST_OS_WINDOWS_MOBILE                                                                                               

  # 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,                                    // Clear the following flags:                                                    
            _WRITE_ABORT_MSG | _CALL_REPORTFAULT);  // pop-up window, core dump.                                                     
  # endif                                                                                                                            
    }                                                                                                                                
  #endif  // GTEST_HAS_SEH   
  //以上全是关于死亡测试和跨平台异常的的一些设定,下面才是真正实现其功能的地方                                         
  return internal::HandleExceptionsInMethodIfSupported(                                                                            
        impl(),                                                                                                                      
        &internal::UnitTestImpl::RunAllTests,                                                                                        
        "auxiliary test code (environments or event listeners)") ? 0 : 1;                                                            
  }                                                                                                                         

如果不涉及源码中的死亡测试以及跨平台可能出现异常的一些问题,其简化为

int UnitTest::Run() 
{
  return internal::HandleExceptionsInMethodIfSupported(                                                                            
        impl(),                                                                                                                      
        &internal::UnitTestImpl::RunAllTests,                                                                                        
        "auxiliary test code (environments or event listeners)") ? 0 : 1;     
}

在将其简化,可以发现由impl对象指针调用了RunAllTests();

int UnitTest::Run() 
{
  return impl->RunAllTests();  
}

这里使用了impl()方法,该方法返回了一个UnitTestImpl对象指针impl_,由指针调用了RunAllTest,

UnitTest::UnitTest() {                                                                                                             
    impl_ = new internal::UnitTestImpl(this);                                                                                        
  }                    

2.2 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;   
    //重复对后标记解析初始化的调用,以防万一用户没有调用InitGoogleTest。                                                                                        
    PostFlagParsingInit();                                                                                                           

    //关于对用户提供的设计                                                                                                                  
    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  // defined(GTEST_EXTRA_DEATH_TEST_CHILD_SETUP_)                                                                           
  #endif  // GTEST_HAS_DEATH_TEST                                                                                                    
    //与环境相关的设置,暂时不关心                                                                                                                                 
    const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex,                                                         
                                          in_subprocess_for_death_test);   

 // 匹配测试用例,对所有的测试用例进行匹配,决定要执行哪一个测试用例                                                                                                                                                                           
    const bool has_tests_to_run = FilterTests(should_shard                                                                           
                                                ? HONOR_SHARDING_PROTOCOL                                                            
                                                : IGNORE_SHARDING_PROTOCOL) > 0;                                                     


    //如果指定了gtestlisttest标志,则列出测试和出口。                                                      
    if (GTEST_FLAG(list_tests)) {                                                                                                    
      // This must be called *after* FilterTests() has been called.                                                                  
      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();                                                                           
     //上报事件OnTestProgramStart                                                                                                                                 
    start_timestamp_ = GetTimeInMillis();                                                                                            
    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();                                                                                  

      if (has_tests_to_run && GTEST_FLAG(shuffle)) {                                                                                 
        random()->Reseed(random_seed_);                                                                                              

        ShuffleTests();                                                                                                              
      }                                                                                                                              

      repeater->OnTestIterationStart(*parent_, i);                                                                                   

      if (has_tests_to_run) {                                                                                                                                                                                   
        repeater->OnEnvironmentsSetUpStart(*parent_);                                                                                
        ForEach(environments_, SetUpEnvironment);                                                                                    
        repeater->OnEnvironmentsSetUpEnd(*parent_);                                                                                                          

        if (!Test::HasFatalFailure()) { //核心代码                                                                                             
          for (int test_index = 0; test_index < total_test_case_count();                                                             
               test_index++) {                                                                                                       
            GetMutableTestCase(test_index)->Run(); //逐个运行测试用例,执行后面的TestBody()                                                                                  
          }                                                                                                                          
        }                                                                                                                            

        repeater->OnEnvironmentsTearDownStart(*parent_);                                                                             
        std::for_each(environments_.rbegin(), environments_.rend(),                                                                  
                      TearDownEnvironment);                                                                                          
        repeater->OnEnvironmentsTearDownEnd(*parent_);                                                                               
      }                                                                                                                              

      elapsed_time_ = GetTimeInMillis() - start;       
      repeater->OnTestIterationEnd(*parent_, i);                                                                                     

      if (!Passed()) {                                                                                                               
        failed = true;                                                                                                               
      }                                                                                                                              

      UnshuffleTests();                                                                                                              

      if (GTEST_FLAG(shuffle)) {                                                                                                     
        // Picks a new random seed for each iteration.                                                                               
        random_seed_ = GetNextRandomSeed(random_seed_);                                                                              
      }                                                                                                                              
    }     
     repeater->OnTestProgramEnd(*parent_);                                                                                            

    return !failed;                                                                                                                  
  }                                                                                    

上述源码中,提取出最核心的代码,如下:

 for (int test_index = 0; test_index < total_test_case_count();                                                             
               test_index++) {                                                                                                       
            GetMutableTestCase(test_index)->Run(); //逐个运行测试用例,执行后面的TestBody()                                                                                  
          }              

分析:上一篇看TEST宏的源码中,我们看到所有的测试用例都存放在一个数组当中,这里就利用这一特点,通过返回UnitTestImpl对象成员变量test_cases_中的元素——各个测试用例对象指针,然后调用测试用例的Run方法。

std::vector<TestCase*> test_cases_;

2.4 TestCase::Run()

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();                                                   

    repeater->OnTestCaseStart(*this);                                                                                                
    impl->os_stack_trace_getter()->UponLeavingGTest();                                                                               
    internal::HandleExceptionsInMethodIfSupported(                                                                                   
        this, &TestCase::RunSetUpTestCase, "SetUpTestCase()");                                                                       

    const internal::TimeInMillis start = internal::GetTimeInMillis();    
    //核心代码                                                            
    for (int i = 0; i < total_test_count(); i++) {                                                                                   
      GetMutableTestInfo(i)->Run();                                                                                                  
    }                                                                                                                                
    elapsed_time_ = internal::GetTimeInMillis() - start;                                                                             

    impl->os_stack_trace_getter()->UponLeavingGTest();                                                                               
    internal::HandleExceptionsInMethodIfSupported(
      this, &TestCase::RunTearDownTestCase, "TearDownTestCase()");                                                                 

    repeater->OnTestCaseEnd(*this);                                                                                                  
    impl->set_current_test_case(NULL);                                                                                               
  }                                      

分析:和上面 UnitTestImpl::RunAllTests思想类似,其中核心的源码如下,这里还是获取特例信息,调用Run方法

   for (int i = 0; i < total_test_count(); i++) {                                                                                   
      GetMutableTestInfo(i)->Run();                                                                                                  
    }                              

2.3 TestInfo::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(); 
    const TimeInMillis start = internal::GetTimeInMillis();                                                                          

    impl->os_stack_trace_getter()->UponLeavingGTest();                                                                               

    // Creates the test object. 核心代码,后面单独进行分析                                                                                                  
    Test* const test = internal::HandleExceptionsInMethodIfSupported(                                                                
        factory_, &internal::TestFactoryBase::CreateTest,                                                                            
        "the test fixture's constructor");                                                                  
    if ((test != NULL) && !Test::HasFatalFailure()) {                                                                                                                                                                           
      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);                                                                                               
  }                                            

核心源码分析:

  Test* const test = internal::HandleExceptionsInMethodIfSupported(                                                                
        factory_, &internal::TestFactoryBase::CreateTest,                                                                            
        "the test fixture's constructor");                                                                  
    if ((test != NULL) && !Test::HasFatalFailure()) {                                                                                                                                                                           
      test->Run();                                                                                                                   
    }   

这里是创造一个对象:将工厂类对象指针调用的Create Test方法传入构造函数,new出一个TEST宏的一个类对象的指针,用这个对象指针去调用父类的Run方法,从而去调用TestBody方法(注:TestBody是上一篇中提到的TEST当中的虚函数)

三、总结

  上面已经将调用过程所有的源码看完,下面来梳理一下这个过程这里写图片描述
  

猜你喜欢

转载自blog.csdn.net/zhangye3017/article/details/81206059