threadproc_ret _callconv TestRunner::run(void* pUserData) { const ThreadInfo* pInfo = static_cast<const ThreadInfo*>(pUserData); assert(pInfo); assert(pInfo->pRunner); TestRunner* pRunner = pInfo->pRunner; assert(pRunner->m_testSuiteList); assert(pRunner->m_nbTestSuites); RTErrorProtector errorProtector(pRunner->m_pTestListener, pInfo->threadIdx); TestEvent event; stats::CodeTimer suiteTimer; stats::CodeTimer caseTimer; for (;;) { bool bStopRequested = pRunner->m_bStopRequested.load(std::memory_order_relaxed); if (bStopRequested) break; #ifndef EASYTEST_NO_THREADS size_t idx = pRunner->m_nextTestSuiteIdx.fetch_add(1, std::memory_order_relaxed); #else //EASYTEST_NO_THREADS is defined size_t idx = pRunner->m_nextTestSuiteIdx++; #endif //!EASYTEST_NO_THREADS if (idx >= pRunner->m_nbTestSuites) break; suiteTimer.start(); const TestSuiteRegistrar* pRegistrar = pRunner->m_testSuiteList[idx]; bool bTestSuiteSuccess = false; TestSuite* pTestSuite = errorProtector.createProtectedTestSuite(pRegistrar); if (pTestSuite) { assert(pRegistrar); bTestSuiteSuccess = true; const size_t nbTotalCases = pTestSuite->getTestCaseCount(); size_t nbSuccessCases = 0; size_t nbFailedCases = 0; if (pRunner->m_pTestListener) { event.type = TestEventType::TESTSUITE_START; event.testSuiteStart.workerThreadIdx = pInfo->threadIdx; event.testSuiteStart.testSuiteName = pRegistrar->getTestSuiteName(); event.testSuiteStart.nbTotalCases = nbTotalCases; pRunner->m_pTestListener->onEvent(event); } const TestCaseRegistrar** caseRegListBegin = pTestSuite->getTestCaseList(); const TestCaseRegistrar** caseRegListEnd = caseRegListBegin + nbTotalCases; for (const TestCaseRegistrar** ppCaseReg = caseRegListBegin; ppCaseReg < caseRegListEnd; ++ppCaseReg) { assert(*ppCaseReg); bStopRequested = pRunner->m_bStopRequested.load(std::memory_order_relaxed); if (bStopRequested) { bTestSuiteSuccess = false; break; } caseTimer.start(); if (pRunner->m_pTestListener) { event.type = TestEventType::TESTCASE_START; event.testCaseStart.testCaseName = (*ppCaseReg)->getTestName(); pRunner->m_pTestListener->onEvent(event); } if (errorProtector.executeProtectedTestCase(*ppCaseReg)) { event.testCaseFinish.bSuccess = true; nbSuccessCases++; } else { event.testCaseFinish.bSuccess = false; nbFailedCases++; bTestSuiteSuccess = false; } caseTimer.stop(); if (pRunner->m_pTestListener) { event.type = TestEventType::TESTCASE_FINISH; event.testCaseFinish.pTimer = &caseTimer; pRunner->m_pTestListener->onEvent(event); } } errorProtector.deleteProtectedTestSuite(); suiteTimer.stop(); if (pRunner->m_pTestListener) { event.type = TestEventType::TESTSUITE_FINISH; event.testSuiteFinish.nbTotalCases = nbTotalCases; event.testSuiteFinish.nbSuccessCases = nbSuccessCases; event.testSuiteFinish.nbFailedCases = nbFailedCases; event.testSuiteFinish.pTimer = &suiteTimer; pRunner->m_pTestListener->onEvent(event); } } else suiteTimer.stop(); if (!bTestSuiteSuccess) { #ifndef EASYTEST_NO_THREADS pRunner->m_nbFailedTestSuites.fetch_add(1, std::memory_order_relaxed); #else //EASYTEST_NO_THREADS is defined pRunner->m_nbFailedTestSuites++; #endif //!EASYTEST_NO_THREADS } if (bStopRequested) break; } return 0; }