27 #if !(defined(THREAD_TLS_USE_PTHREAD) && THREAD_TLS_USE_PTHREAD)
34 # if (defined(__cplusplus) && __cplusplus >= 201402L) || ((defined(_MSVC_LANG) && _MSVC_LANG >= 201402L))
35 static_assert(std::is_trivially_copyable<test_manager_tls_block_t>::value,
"test_manager_tls_block_t must be trially");
36 # elif (defined(__cplusplus) && __cplusplus >= 201103L) || ((defined(_MSVC_LANG) && _MSVC_LANG >= 201103L))
37 static_assert(std::is_trivial<test_manager_tls_block_t>::value,
"test_manager_tls_block_t must be trially");
39 static_assert(std::is_pod<test_manager_tls_block_t>::value,
"test_manager_tls_block_t must be POD");
50 struct test_manager_tls_block_t {
56 static pthread_once_t gt_test_manager_tls_block_once = PTHREAD_ONCE_INIT;
57 static pthread_key_t gt_test_manager_tls_block_key;
59 static void dtor_pthread_test_manager_tls_block(
void *p) {
60 test_manager_tls_block_t *block =
reinterpret_cast<test_manager_tls_block_t *
>(p);
61 if (
nullptr != block) {
66 static void init_pthread_test_manager_tls_block() {
67 (void)pthread_key_create(>_test_manager_tls_block_key, dtor_pthread_test_manager_tls_block);
72 (void)pthread_once(>_test_manager_tls_block_once, init_pthread_test_manager_tls_block);
73 test_manager_tls_block_t *block =
74 reinterpret_cast<test_manager_tls_block_t *
>(pthread_getspecific(gt_test_manager_tls_block_key));
75 if (
nullptr == block) {
77 pthread_setspecific(gt_test_manager_tls_block_key, block);
82 struct gt_test_manager_tls_block_main_thread_dtor_t {
83 test_manager_tls_block_t *block_ptr;
84 gt_test_manager_tls_block_main_thread_dtor_t() {
86 if (
nullptr != block_ptr) {
87 block_ptr->success_counter_ptr =
nullptr;
88 block_ptr->failed_counter_ptr =
nullptr;
92 ~gt_test_manager_tls_block_main_thread_dtor_t() {
93 pthread_setspecific(gt_test_manager_tls_block_key,
nullptr);
94 dtor_pthread_test_manager_tls_block(
reinterpret_cast<void *
>(block_ptr));
97 static gt_test_manager_tls_block_main_thread_dtor_t gt_test_manager_tls_block_main_thread_dtor;
112 return strcmp(str_, other.
str_) == 0;
114 #ifdef __cpp_impl_three_way_comparison
115 std::strong_ordering test_manager::pick_param_str_t::operator<=>(
const pick_param_str_t &other)
const {
116 int res = strcmp(str_, other.
str_);
118 return std::strong_ordering::less;
119 }
else if (res > 0) {
120 return std::strong_ordering::greater;
123 return std::strong_ordering::equal;
127 return strcmp(str_, other.
str_) != 0;
130 return strcmp(str_, other.
str_) >= 0;
133 return strcmp(str_, other.
str_) > 0;
136 return strcmp(str_, other.
str_) <= 0;
139 return strcmp(str_, other.
str_) < 0;
151 tests_[test_name].push_back(std::make_pair(case_name, ptr));
162 #ifdef UTILS_TEST_MACRO_TEST_ENABLE_BOOST_TEST
164 boost::unit_test::test_suite *&test_manager::test_suit() {
165 static boost::unit_test::test_suite *ret =
nullptr;
170 using namespace boost::unit_test;
172 for (test_data_type::iterator iter =
tests_.begin(); iter !=
tests_.end(); ++iter) {
173 test_suit() = BOOST_TEST_SUITE(iter->first.c_str());
175 for (test_type::iterator iter2 = iter->second.begin(); iter2 != iter->second.end(); ++iter2) {
176 test_suit()->add(make_test_case(callback0<>(iter2->second->func_), iter2->first.c_str()));
177 iter2->second->run();
180 framework::master_test_suite().add(test_suit());
189 std::vector<detail::topological_sort_object_t *> &out) {
191 out.reserve(in.size());
193 for (index_by_name_t::iterator iter = in.begin(); iter != in.end(); ++iter) {
194 if (0 == iter->second.dependency_count) {
195 out.push_back(&iter->second);
199 for (
size_t i = 0; i < out.size(); ++i) {
200 for (std::list<detail::topological_sort_object_t *>::iterator iter = out[i]->depend_by.begin();
201 iter != out[i]->depend_by.end(); ++iter) {
202 if ((*iter)->dependency_count > 0) {
203 --(*iter)->dependency_count;
205 if (0 == (*iter)->dependency_count) {
206 out.push_back(*iter);
216 index_by_name_t index_by_name;
227 for (test_on_start_base::after_set_t::iterator iter =
evt_on_starts_[i].second->after.begin();
229 index_by_name_t::iterator dep_iter = index_by_name.find(*iter);
230 if (dep_iter == index_by_name.end()) {
234 <<
evt_on_starts_[i].first <<
" is configured run after " << (*iter) <<
", but " << (*iter) <<
"not found."
240 dep_iter->second.depend_by.push_back(&obj);
244 std::vector<detail::topological_sort_object_t *> run_order;
247 for (
size_t i = 0; i < run_order.size(); ++i) {
261 index_by_name_t index_by_name;
272 for (test_on_exit_base::before_set_t::iterator iter =
evt_on_exits_[i].second->before.begin();
274 index_by_name_t::iterator dep_iter = index_by_name.find(*iter);
275 if (dep_iter == index_by_name.end()) {
279 <<
evt_on_exits_[i].first <<
" is configured run before " << (*iter) <<
", but " << (*iter) <<
"not found."
285 dep_iter->second.depend_by.push_back(&obj);
289 std::vector<detail::topological_sort_object_t *> run_order;
292 for (
size_t i = 0; i < run_order.size(); ++i) {
293 size_t idx = run_order.size() - 1 - i;
308 clock_t all_begin_time = clock();
312 <<
" test(s)" << std::endl;
314 for (test_data_type::iterator iter =
tests_.begin(); iter !=
tests_.end(); ++iter) {
315 bool check_test_group_passed = run_cases_.empty();
316 bool check_test_group_has_cases =
false;
318 if (!check_test_group_passed) {
319 check_test_group_passed = run_cases_.end() != run_cases_.find(iter->first);
322 if (!check_test_group_passed) {
323 check_test_group_has_cases = run_groups_.end() != run_groups_.find(iter->first);
327 if (!check_test_group_passed && !check_test_group_has_cases) {
331 size_t run_group_count = 0;
336 <<
" test case(s) from " << iter->first << std::endl;
338 clock_t test_begin_time = clock();
339 for (test_type::iterator iter2 = iter->second.begin(); iter2 != iter->second.end(); ++iter2) {
340 bool check_test_case_passed = run_cases_.empty() || check_test_group_passed;
341 if (!check_test_case_passed) {
342 check_test_case_passed = run_cases_.end() != run_cases_.find(iter2->first);
344 if (!check_test_case_passed) {
345 std::string full_name;
346 full_name.reserve(iter->first.size() + 1 + iter2->first.size());
347 full_name = iter->first +
"." + iter2->first;
348 check_test_case_passed = run_cases_.end() != run_cases_.find(full_name);
353 if (!check_test_case_passed) {
360 clock_t case_begin_time = clock();
361 iter2->second->run();
362 clock_t case_end_time = clock();
364 if (0 == iter2->second->failed_) {
368 <<
get_expire_time(case_begin_time, case_end_time) <<
")" << std::endl;
373 <<
get_expire_time(case_begin_time, case_end_time) <<
")" << std::endl;
379 clock_t test_end_time = clock();
382 <<
" test case(s) from " << iter->first <<
" (" <<
get_expire_time(test_begin_time, test_end_time) <<
" total)"
386 clock_t all_end_time = clock();
390 <<
" (" <<
get_expire_time(all_begin_time, all_end_time) <<
" total)" << std::endl;
399 for (test_data_type::iterator iter =
tests_.begin(); iter !=
tests_.end(); ++iter) {
400 for (test_type::iterator iter2 = iter->second.begin(); iter2 != iter->second.end(); ++iter2) {
401 if (iter2->second->failed_ > 0) {
418 for (
size_t i = 0; i < case_names.size(); ++i) {
419 run_cases_.insert(case_names[i]);
420 std::string::size_type split_idx = case_names[i].find(
'.');
421 if (split_idx != std::string::npos) {
422 run_groups_.insert(case_names[i].substr(0, split_idx));
433 std::stringstream ss;
434 double ms = 1000.0 * (end - begin) / CLOCKS_PER_SEC;
443 if (
nullptr != block) {
461 <<
"Expect expression can not be used when not running test case." << std::endl;
474 <<
"Expect expression can not be used when not running test case." << std::endl;
482 std::vector<std::string> run_cases;
483 const char *version =
"1.0.0";
484 bool is_help =
false;
485 bool is_show_version =
false;
489 ->set_help_msg(
" show help message and exit.");
491 ->set_help_msg(
" show version and exit.");
493 ->set_help_msg(
"[case names...] only run specify cases.");
495 cmd_opts->start(argc, argv);
497 std::cout << *cmd_opts << std::endl;
501 if (is_show_version) {
502 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)
static void inc_failed_counter()
static void inc_success_counter()
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 COPP_LIKELY_IF(...)
test_manager_tls_block_t * get_test_manager_tls_block()
static test_manager_tls_block_t g_global_counter_cache
set_const_t< T > set_const(T &t, const T &v)
push_back_t< T > push_back(T &t)
int * success_counter_ptr
std::list< topological_sort_object_t * > depend_by
bool operator>=(const pick_param_str_t &other) const
bool operator!=(const pick_param_str_t &other) const
pick_param_str_t(const char *in)
bool operator==(const pick_param_str_t &other) const
bool operator>(const pick_param_str_t &other) const
bool operator<=(const pick_param_str_t &other) const
bool operator<(const pick_param_str_t &other) const
#define UTIL_UNIT_TEST_MACRO_AUTO_MAP(...)
static void topological_sort(UTIL_UNIT_TEST_MACRO_AUTO_MAP(std::string, detail::topological_sort_object_t) &in, std::vector< detail::topological_sort_object_t * > &out)
int run_tests(int argc, char *argv[])