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

2023-10-12 15:30

本文主要是介绍Google Test源码浅析(三) -------- RUN_ALL_TESTS,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

      • 一、例子引入:
      • 二、源码分析
        • 2.1 UnitTest::Run()
        • 2.2 UnitTestImpl::RunAllTests()
        • 2.4 TestCase::Run()
        • 2.3 TestInfo::Run()
      • 三、总结

一、例子引入:

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当中的虚函数)

三、总结

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

这篇关于Google Test源码浅析(三) -------- RUN_ALL_TESTS的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/196764

相关文章

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、

Spring 源码解读:自定义实现Bean定义的注册与解析

引言 在Spring框架中,Bean的注册与解析是整个依赖注入流程的核心步骤。通过Bean定义,Spring容器知道如何创建、配置和管理每个Bean实例。本篇文章将通过实现一个简化版的Bean定义注册与解析机制,帮助你理解Spring框架背后的设计逻辑。我们还将对比Spring中的BeanDefinition和BeanDefinitionRegistry,以全面掌握Bean注册和解析的核心原理。

音视频入门基础:WAV专题(10)——FFmpeg源码中计算WAV音频文件每个packet的pts、dts的实现

一、引言 从文章《音视频入门基础:WAV专题(6)——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道,通过FFprobe命令可以打印WAV音频文件每个packet(也称为数据包或多媒体包)的信息,这些信息包含该packet的pts、dts: 打印出来的“pts”实际是AVPacket结构体中的成员变量pts,是以AVStream->time_base为单位的显

kubelet组件的启动流程源码分析

概述 摘要: 本文将总结kubelet的作用以及原理,在有一定基础认识的前提下,通过阅读kubelet源码,对kubelet组件的启动流程进行分析。 正文 kubelet的作用 这里对kubelet的作用做一个简单总结。 节点管理 节点的注册 节点状态更新 容器管理(pod生命周期管理) 监听apiserver的容器事件 容器的创建、删除(CRI) 容器的网络的创建与删除

消除安卓SDK更新时的“https://dl-ssl.google.com refused”异常的方法

消除安卓SDK更新时的“https://dl-ssl.google.com refused”异常的方法   消除安卓SDK更新时的“https://dl-ssl.google.com refused”异常的方法 [转载]原地址:http://blog.csdn.net/x605940745/article/details/17911115 消除SDK更新时的“

论文翻译:ICLR-2024 PROVING TEST SET CONTAMINATION IN BLACK BOX LANGUAGE MODELS

PROVING TEST SET CONTAMINATION IN BLACK BOX LANGUAGE MODELS https://openreview.net/forum?id=KS8mIvetg2 验证测试集污染在黑盒语言模型中 文章目录 验证测试集污染在黑盒语言模型中摘要1 引言 摘要 大型语言模型是在大量互联网数据上训练的,这引发了人们的担忧和猜测,即它们可能已