27#if !(defined(THREAD_TLS_USE_PTHREAD) && THREAD_TLS_USE_PTHREAD)
34# if (defined(__cplusplus) && __cplusplus >= 201402L) || ((defined(_MSVC_LANG) && _MSVC_LANG >= 201402L))
35static_assert(std::is_trivially_copyable<test_manager_tls_block_t>::value,
36 "test_manager_tls_block_t must be trivially copyable");
37# elif (defined(__cplusplus) && __cplusplus >= 201103L) || ((defined(_MSVC_LANG) && _MSVC_LANG >= 201103L))
38static_assert(std::is_trivial<test_manager_tls_block_t>::value,
"test_manager_tls_block_t must be trially");
40static_assert(std::is_pod<test_manager_tls_block_t>::value,
"test_manager_tls_block_t must be POD");
51struct test_manager_tls_block_t {
57static pthread_once_t gt_test_manager_tls_block_once = PTHREAD_ONCE_INIT;
58static pthread_key_t gt_test_manager_tls_block_key;
60static void dtor_pthread_test_manager_tls_block(
void *p) {
61 test_manager_tls_block_t *block =
reinterpret_cast<test_manager_tls_block_t *
>(p);
62 if (
nullptr != block) {
67static void init_pthread_test_manager_tls_block() {
68 (void)pthread_key_create(>_test_manager_tls_block_key, dtor_pthread_test_manager_tls_block);
73 (void)pthread_once(>_test_manager_tls_block_once, init_pthread_test_manager_tls_block);
74 test_manager_tls_block_t *block =
75 reinterpret_cast<test_manager_tls_block_t *
>(pthread_getspecific(gt_test_manager_tls_block_key));
76 if (
nullptr == block) {
78 pthread_setspecific(gt_test_manager_tls_block_key, block);
83struct gt_test_manager_tls_block_main_thread_dtor_t {
84 test_manager_tls_block_t *block_ptr;
85 gt_test_manager_tls_block_main_thread_dtor_t() {
87 if (
nullptr != block_ptr) {
88 block_ptr->success_counter_ptr =
nullptr;
89 block_ptr->failed_counter_ptr =
nullptr;
93 ~gt_test_manager_tls_block_main_thread_dtor_t() {
94 pthread_setspecific(gt_test_manager_tls_block_key,
nullptr);
95 dtor_pthread_test_manager_tls_block(
reinterpret_cast<void *
>(block_ptr));
98static gt_test_manager_tls_block_main_thread_dtor_t gt_test_manager_tls_block_main_thread_dtor;
117 tests_[test_name].push_back(std::make_pair(case_name, ptr));
128#ifdef UTILS_TEST_MACRO_TEST_ENABLE_BOOST_TEST
130boost::unit_test::test_suite *&test_manager::test_suit() {
131 static boost::unit_test::test_suite *ret =
nullptr;
136 using namespace boost::unit_test;
138 for (test_data_type::iterator iter =
tests_.begin(); iter !=
tests_.end(); ++iter) {
139 test_suit() = BOOST_TEST_SUITE(iter->first.c_str());
141 for (test_type::iterator iter2 = iter->second.begin(); iter2 != iter->second.end(); ++iter2) {
142 test_suit()->add(make_test_case(callback0<>(iter2->second->func_), iter2->first.c_str()));
143 iter2->second->run();
146 framework::master_test_suite().add(test_suit());
154static void topological_sort(std::unordered_map<std::string, detail::topological_sort_object_t> &in,
155 std::vector<detail::topological_sort_object_t *> &out) {
156 using index_by_name_t = std::unordered_map<std::string, detail::topological_sort_object_t>;
157 out.reserve(in.size());
159 for (index_by_name_t::iterator iter = in.begin(); iter != in.end(); ++iter) {
160 if (0 == iter->second.dependency_count) {
161 out.push_back(&iter->second);
165 for (
size_t i = 0; i < out.size(); ++i) {
166 for (std::list<detail::topological_sort_object_t *>::iterator iter = out[i]->depend_by.begin();
167 iter != out[i]->depend_by.end(); ++iter) {
168 if ((*iter)->dependency_count > 0) {
169 --(*iter)->dependency_count;
171 if (0 == (*iter)->dependency_count) {
172 out.push_back(*iter);
154static void topological_sort(std::unordered_map<std::string, detail::topological_sort_object_t> &in, {
…}
181 using index_by_name_t = std::unordered_map<std::string, detail::topological_sort_object_t>;
182 index_by_name_t index_by_name;
193 for (test_on_start_base::after_set_t::iterator iter =
evt_on_starts_[i].second->after.begin();
195 index_by_name_t::iterator dep_iter = index_by_name.find(*iter);
196 if (dep_iter == index_by_name.end()) {
200 <<
evt_on_starts_[i].first <<
" is configured run after " << (*iter) <<
", but " << (*iter) <<
"not found."
206 dep_iter->second.depend_by.push_back(&obj);
210 std::vector<detail::topological_sort_object_t *> run_order;
213 for (
size_t i = 0; i < run_order.size(); ++i) {
225 using index_by_name_t = std::unordered_map<std::string, detail::topological_sort_object_t>;
227 index_by_name_t index_by_name;
238 for (test_on_exit_base::before_set_t::iterator iter =
evt_on_exits_[i].second->before.begin();
240 index_by_name_t::iterator dep_iter = index_by_name.find(*iter);
241 if (dep_iter == index_by_name.end()) {
245 <<
evt_on_exits_[i].first <<
" is configured run before " << (*iter) <<
", but " << (*iter) <<
"not found."
251 dep_iter->second.depend_by.push_back(&obj);
255 std::vector<detail::topological_sort_object_t *> run_order;
258 for (
size_t i = 0; i < run_order.size(); ++i) {
259 size_t idx = run_order.size() - 1 - i;
274 clock_t all_begin_time = clock();
278 <<
" test(s)" << std::endl;
280 for (test_data_type::iterator iter =
tests_.begin(); iter !=
tests_.end(); ++iter) {
281 bool check_test_group_passed =
run_cases_.empty();
282 bool check_test_group_has_cases =
false;
284 if (!check_test_group_passed) {
288 if (!check_test_group_passed) {
293 if (!check_test_group_passed && !check_test_group_has_cases) {
297 size_t run_group_count = 0;
302 <<
" test case(s) from " << iter->first << std::endl;
304 clock_t test_begin_time = clock();
305 for (test_type::iterator iter2 = iter->second.begin(); iter2 != iter->second.end(); ++iter2) {
306 bool check_test_case_passed =
run_cases_.empty() || check_test_group_passed;
307 if (!check_test_case_passed) {
310 if (!check_test_case_passed) {
311 std::string full_name;
312 full_name.reserve(iter->first.size() + 1 + iter2->first.size());
313 full_name = iter->first +
"." + iter2->first;
319 if (!check_test_case_passed) {
326 clock_t case_begin_time = clock();
327 iter2->second->run();
328 clock_t case_end_time = clock();
330 if (0 == iter2->second->failed_) {
334 <<
get_expire_time(case_begin_time, case_end_time) <<
")" << std::endl;
339 <<
get_expire_time(case_begin_time, case_end_time) <<
")" << std::endl;
345 clock_t test_end_time = clock();
348 <<
" test case(s) from " << iter->first <<
" (" <<
get_expire_time(test_begin_time, test_end_time) <<
" total)"
352 clock_t all_end_time = clock();
355 <<
" test(s) ran." <<
" (" <<
get_expire_time(all_begin_time, all_end_time) <<
" total)" << std::endl;
364 for (test_data_type::iterator iter =
tests_.begin(); iter !=
tests_.end(); ++iter) {
365 for (test_type::iterator iter2 = iter->second.begin(); iter2 != iter->second.end(); ++iter2) {
366 if (iter2->second->failed_ > 0) {
383 for (
size_t i = 0; i < case_names.size(); ++i) {
385 std::string::size_type split_idx = case_names[i].find(
'.');
386 if (split_idx != std::string::npos) {
387 run_groups_.insert(case_names[i].substr(0, split_idx));
398 std::stringstream ss;
399 double ms = 1000.0 *
static_cast<double>(end - begin) / CLOCKS_PER_SEC;
408 if (
nullptr != block) {
426 <<
"Expect expression can not be used when not running test case." << std::endl;
439 <<
"Expect expression can not be used when not running test case." << std::endl;
447 std::vector<std::string> run_cases;
448 const char *version =
"1.0.0";
449 bool is_help =
false;
450 bool is_show_version =
false;
454 ->set_help_msg(
" show help message and exit.");
456 ->set_help_msg(
" show version and exit.");
458 ->set_help_msg(
"[case names...] only run specify cases.");
460 cmd_opts->start(argc, argv);
462 std::cout << *cmd_opts << std::endl;
466 if (is_show_version) {
467 std::cout << version << std::endl;
static std::string get_expire_time(clock_t begin, clock_t end)
void set_cases(const std::vector< std::string > &case_names)
static test_manager & me()
void append_event_on_start(const std::string &event_name, on_start_ptr_type)
event_on_exit_type evt_on_exits_
static void set_counter_ptr(int *success_counter_ptr, int *failed_counter_ptr)
event_on_start_type evt_on_starts_
void append_event_on_exit(const std::string &event_name, on_exit_ptr_type)
std::unordered_set< std::string > run_groups_
static void inc_failed_counter()
static void inc_success_counter()
std::unordered_set< std::string > run_cases_
void append_test_case(const std::string &test_name, const std::string &case_name, case_ptr_type)
std::shared_ptr< cmd_option_bind > ptr_type
#define LIBCOPP_UTIL_LIKELY_CONDITION(__C)
static test_manager_tls_block_t g_global_counter_cache
test_manager_tls_block_t * get_test_manager_tls_block()
push_back_t< T > push_back(T &t)
set_const_t< T > set_const(T &t, const T &v)
int * success_counter_ptr
std::list< topological_sort_object_t * > depend_by
static void topological_sort(std::unordered_map< std::string, detail::topological_sort_object_t > &in, std::vector< detail::topological_sort_object_t * > &out)
int run_tests(int argc, char *argv[])