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
- 参考
- RUN_ALL_TESTS源码分析
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()
- 如果忽略死亡测试和支持跨平台及异常处理的逻辑,其实现可以简化为:
int UnitTest::Run() { return internal::HandleExceptionsInMethodIfSupported( impl(), &internal::UnitTestImpl::RunAllTests, "auxiliary test code (environments or event listeners)") ? 0 : 1;}
- 如果我们在剔除HandleExceptionsInMethodIfSupported对支持跨平台及异常处理的逻辑,其实现直接简化为:
int UnitTest::Run() { return impl->RunAllTests();}
- 全部源码如下:
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
阅读全文
0 0
- GTest源码剖析(六)——RUN_ALL_TESTS
- GTest源码剖析(一)——概述
- GTest源码剖析(二)——TEST宏
- GTest源码剖析(三)——TEST_F宏
- GTest源码剖析(四)——TEST_P宏
- GTest源码剖析(七)——断言
- GTest源码剖析(五)——传入参数分析及InitGoogleTest
- Atlas源码剖析(六)
- 《STL源码剖析》学习笔记系列之六——算法(1)
- udhcp源码剖析(六)——DHCP客户端的superloop
- Mina2.0框架源码剖析(六)
- Mina2.0框架源码剖析(六)
- Mina2.0框架源码剖析(六)
- Lucene 源码剖析 六
- spring源码剖析(六)AOP实现原理剖析
- Google Test(GTest)使用方法和源码解析——概况
- 数据库连接池DBPool分析(六):gtest
- libevent源码深度剖析六
- Java用户登陆界面
- GTest源码剖析(五)——传入参数分析及InitGoogleTest
- 单链表的各种操作(增删查改)
- Harris角点检测算子
- 【BS学习】牛腩新闻发布系统——设计说明书
- GTest源码剖析(六)——RUN_ALL_TESTS
- 用帝国cms7.2做网站的一些性能优化建议
- this关键字
- 学习笔记33-生成式模型-判别式模型
- nginx(一)基本配置讲解
- JVM调优总结(一)-- 一些概念
- 硬币找零
- eclipse中项目与svn失去关联
- GTest源码剖析(七)——断言