/** @file * @author Edouard DUPIN * @copyright 2011, Edouard DUPIN, all right reserved * @license MPL v2.0 (see license file) */ #include #include #include #include #include #include #include #include static int32_t nbTimeInit = 0; static etk::Vector& getListOfTest() { static etk::Vector s_listOfData; return s_listOfData; } static etk::String filterGroup; static etk::String filterTest; void etest::unInit() { if (nbTimeInit > 1) { nbTimeInit--; // not the time to un-init return; } nbTimeInit--; if (nbTimeInit < 0) { ETEST_ERROR("ETEST system un-init More un-init than init ..."); nbTimeInit = 0; return; } ETEST_INFO("ETEST system un-init (BEGIN)"); ETEST_INFO("ETEST system un-init (END)"); elog::unInit(); } static etk::Vector getListGroupSpecific(const etk::Vector& _value) { etk::Vector listGroup; for (auto &it: _value) { if (etk::isIn(it->getTestGroup(), listGroup) == true) { continue; } listGroup.pushBack(it->getTestGroup()); } return listGroup; } static etk::Vector getListGroup() { return getListGroupSpecific(getListOfTest()); } static etk::Vector getListFiltered() { if (filterGroup == "") { return getListOfTest(); } etk::Vector out; for (auto &it: getListOfTest()) { if (it->getTestGroup() != filterGroup) { continue; } if (filterTest == "") { out.pushBack(it); continue; } if (filterTest == it->getTestName()) { out.pushBack(it); continue; } } return out; } static void listAllTest() { ETEST_PRINT("We have " << getListOfTest().size() << " tests:"); etk::Vector listGroup = getListGroup(); for (auto &itGroup: listGroup) { ETEST_PRINT("Group: " << itGroup); for (auto &it: getListOfTest()) { if (it->getTestGroup() == itGroup) { ETEST_PRINT(" - " << itGroup << "." << it->getTestName()); } } } } void etest::init(int32_t _argc, const char** _argv) { if (nbTimeInit > 0) { nbTimeInit++; // already init return; } nbTimeInit++; elog::init(_argc, _argv); etk::initDefaultFolder("ewolApplNoName"); ETEST_INFO("ETEST system init (BEGIN) "); for (int32_t iii=0; iii<_argc ; ++iii) { etk::String data = _argv[iii]; if ( data == "-h" || data == "--help") { ETEST_PRINT("etest - help : "); if (_argc >= 1) { ETEST_PRINT(" " << _argv[0] << " [options]"); ETEST_PRINT(" --etest-list List all test names"); ETEST_PRINT(" --etest-filter=XXX filter group or test: XXX or WWW.yyy"); } ETEST_PRINT(" -h/--help: this help"); } else if (data == "--etest-list") { listAllTest(); exit(0); } else if (data == "--etest-filter=") { ETEST_PRINT("Missing data in the filter list..."); exit(0); } else if (data.startWith("--etest-filter=") == true) { etk::String filter = &data[15]; ETEST_PRINT(" Filter: " << filter); etk::Vector tmp = filter.split("."); if (tmp.size() == 1) { // Filter only the groups filterGroup = filter; ETEST_VERBOSE("filter group:" << filterGroup); } else if (tmp.size() == 2) { filterGroup = tmp[0]; filterTest = tmp[1]; ETEST_VERBOSE("filter group:" << filterGroup << " & test:" << filterTest); } else { ETEST_CRITICAL("Can not parse the argument : '" << data << "' ==> more than 1 '.'"); } } else if (data.startWith("--etest") == true) { ETEST_ERROR("Can not parse the argument : '" << data << "'"); } } ETEST_INFO("ETEST system init (END)"); } etest::GenericTest::GenericTest(const char* _file, uint32_t _line, const char* _testGroup, const char* _testName): m_file(_file), m_line(_line), m_testGroup(_testGroup), m_testName(_testName) { } const etk::String& etest::GenericTest::getFileName() const { return m_file; } uint32_t etest::GenericTest::getFileLine() const { return m_line; } const etk::String& etest::GenericTest::getTestGroup() const { return m_testGroup; } const etk::String& etest::GenericTest::getTestName() const { return m_testName; } bool etest::GenericTest::getError() const { return m_haveError; } uint32_t etest::GenericTest::getNumberCheck() const { return m_numberCheck; } uint32_t etest::GenericTest::getNumberCheckError() const { return m_numberCheckFail; } void etest::GenericTest::testResult(bool _result, const etk::String& _test1Value, const etk::String& _test1, const etk::String& _test2Value, const etk::String& _test2, uint32_t _line) { if (_result == true) { return; } ETEST_ERROR("Detect an error: " << m_file << ":" << _line << ":"); if (_test1 != _test1Value) { ETEST_ERROR(" have: " << _test1 << " = " << _test1Value); } else { ETEST_ERROR(" have: " << _test1); } if (_test2 != _test2Value) { ETEST_ERROR(" expect: " << _test2 << " = " << _test2Value); } else { ETEST_ERROR(" expect: " << _test2); } m_haveError = true; m_numberCheckFail++; } void etest::GenericTest::clearLocal() { m_haveError = false; m_numberCheck = 0; m_numberCheckFail = 0; } etest::GenericTest* etest::g_currentTest = nullptr; int32_t etest::runAllTest() { int32_t errorCount = 0; etk::Vector runList = getListFiltered(); etk::Vector listGroup = getListGroupSpecific(runList); ETEST_PRINT("[==========] Running " << runList.size() << " tests from " << listGroup.size() << " test group."); echrono::Steady tic = echrono::Steady::now(); uint32_t nbTotalCheck = 0; uint32_t nbTotalCheckFail = 0; for (auto &itGroup: listGroup) { int32_t count = 0; for (auto &it: getListOfTest()) { if (it->getTestGroup() == itGroup) { count++; } } ETEST_PRINT("[++++++++++] " << count << " test from " << itGroup << ":"); uint32_t nbCheck = 0; uint32_t nbCheckFail = 0; echrono::Steady ticGroup = echrono::Steady::now(); for (auto &it: runList) { if (it->getTestGroup() != itGroup) { continue; } bool localFail = false; #if ETK_MEMORY_CHECKER > 0 uint64_t* memorySnapShoot = etk::memory::createSnapshoot(); #endif { ETEST_PRINT("[ RUN ] " << itGroup << "." << it->getTestName()); it->clearLocal(); g_currentTest = it; echrono::Steady ticTest = echrono::Steady::now(); it->run(); echrono::Steady tocTest = echrono::Steady::now(); g_currentTest = nullptr; if (it->getError() == true) { ETEST_PRINT("[ FAIL ] " << itGroup << "." << it->getTestName() << " (" << (tocTest - ticTest) << ") " << it->getNumberCheckError() << " fails"); errorCount++; localFail = true; } else { ETEST_PRINT("[ OK ] " << itGroup << "." << it->getTestName() << " (" << (tocTest - ticTest) << ")"); } nbCheck += it->getNumberCheck(); nbCheckFail += it->getNumberCheckError(); } #if ETK_MEMORY_CHECKER > 0 ETEST_DEBUG("[ MEM ] CHECK memory properties"); bool ret = etk::memory::checkSnapshoot(memorySnapShoot); etk::memory::clearSnapshoot(memorySnapShoot); memorySnapShoot = nullptr; ETEST_DEBUG("[ MEM ] CHECK memory properties (done)"); nbCheck++; if (ret == false) { if (localFail == false) { errorCount++; } ETEST_PRINT("[ FAIL ] " << itGroup << "." << it->getTestName() << " ==> in memory LEAK test"); nbCheckFail++; } #endif } echrono::Steady tocGroup = echrono::Steady::now(); ETEST_PRINT("[++++++++++] " << count << " test [" << nbCheck << " check / " << nbCheckFail << " fails] from " << itGroup << " (" << (tocGroup - ticGroup) << ")"); nbTotalCheck += nbCheck; nbTotalCheckFail += nbCheckFail; } echrono::Steady toc = echrono::Steady::now(); ETEST_PRINT("[==========] All done [" << nbTotalCheck << " check / " << nbTotalCheckFail << " fails] in " << (toc - tic)); if (errorCount != 0) { ETEST_PRINT("[== FAIL ==] Have " << errorCount << " test fail "); } ETK_MEM_SHOW_LOG(); return -errorCount; } uint32_t etest::registerTest(etest::GenericTest* _element) { if (_element == nullptr) { return -1; } getListOfTest().pushBack(_element); return getListOfTest().size()-1; } /* 7h55'30 [P] elog | Log in file: '/tmp/elog_etk-test.log' [==========] Running 13 tests from 4 test cases. [----------] Global test environment set-up. [----------] 1 test from TestEtkColor [ RUN ] TestEtkColor.RGBA8 [ OK ] TestEtkColor.RGBA8 (0 ms) [----------] 1 test from TestEtkColor (0 ms total) [----------] 1 test from TestEtkFSNode [ RUN ] TestEtkFSNode.checkType [ OK ] TestEtkFSNode.checkType (1 ms) [----------] 1 test from TestEtkFSNode (1 ms total) [----------] 8 tests from TestEtkHash [ RUN ] TestEtkHash.Creation [ OK ] TestEtkHash.Creation (0 ms) [ RUN ] TestEtkHash.AddElement [ OK ] TestEtkHash.AddElement (0 ms) [ RUN ] TestEtkHash.OverWriteElement [ OK ] TestEtkHash.OverWriteElement (0 ms) [ RUN ] TestEtkHash.RemoveElement [ OK ] TestEtkHash.RemoveElement (0 ms) [ RUN ] TestEtkHash.ExistElement [ OK ] TestEtkHash.ExistElement (0 ms) [ RUN ] TestEtkHash.clear [ OK ] TestEtkHash.clear (0 ms) [ RUN ] TestEtkHash.getKey [ OK ] TestEtkHash.getKey (0 ms) [ RUN ] TestEtkHash.getKeys [ OK ] TestEtkHash.getKeys (0 ms) [----------] 8 tests from TestEtkHash (0 ms total) [----------] 3 tests from TestSTDSharedPtr [ RUN ] TestSTDSharedPtr.testBaseLocal create Example [0] Remove Example [0] [ OK ] TestSTDSharedPtr.testBaseLocal (0 ms) [ RUN ] TestSTDSharedPtr.testBaseShared create Example [1] Remove Example [1] [ OK ] TestSTDSharedPtr.testBaseShared (0 ms) [ RUN ] TestSTDSharedPtr.testBaseSharedDouble create Example [2] Remove Example [2] [ OK ] TestSTDSharedPtr.testBaseSharedDouble (0 ms) [----------] 3 tests from TestSTDSharedPtr (0 ms total) [----------] Global test environment tear-down [==========] 13 tests from 4 test cases ran. (2 ms total) [ PASSED ] 13 tests. */