16#ifdef LIBCOTASK_MACRO_ENABLED
17static int g_test_coroutine_task_status = 0;
18static int g_test_coroutine_task_on_finished = 0;
19class test_context_task_action_base :
public cotask::impl::task_action_impl {
22 virtual int operator()() = 0;
24 int operator()(
void *priv_data)
override {
25 ++g_test_coroutine_task_status;
29 CASE_EXPECT_EQ(cotask::EN_TS_RUNNING, cotask::this_task::get_task()->get_status());
30 cotask::this_task::get_task()->yield(&priv_data);
31 CASE_EXPECT_EQ(cotask::EN_TS_RUNNING, cotask::this_task::get_task()->get_status());
35 ++g_test_coroutine_task_status;
40 int on_finished(cotask::impl::task_impl &)
override {
41 ++g_test_coroutine_task_on_finished;
46class test_context_task_action :
public test_context_task_action_base {
48 using test_context_task_action_base::operator();
51 int operator()()
override {
return 0; }
56 g_test_coroutine_task_status = 0;
57 g_test_coroutine_task_on_finished = 0;
60 task_ptr_type co_task = cotask::task<>::create(test_context_task_action());
61 task_ptr_type co_another_task = cotask::task<>::create(test_context_task_action());
64 CASE_EXPECT_EQ(cotask::EN_TS_CREATED, co_another_task->get_status());
73 CASE_EXPECT_EQ(0, co_another_task->start(&g_test_coroutine_task_status));
77 CASE_EXPECT_EQ(cotask::EN_TS_WAITING, co_another_task->get_status());
96 ++g_test_coroutine_task_status;
105struct test_context_task_functor {
107 int operator()(
void *)
const {
108 ++g_test_coroutine_task_status;
111 cotask::this_task::get_task()->yield();
113 ++g_test_coroutine_task_status;
120CASE_TEST(coroutine_task, functor_action) {
122 task_ptr_type co_task = cotask::task<>::create(test_context_task_functor());
123 g_test_coroutine_task_status = 0;
127 ++g_test_coroutine_task_status;
135 ++g_test_coroutine_task_status;
141static int test_context_task_function_1(
void *) {
142 ++g_test_coroutine_task_status;
145 cotask::this_task::get_task()->yield();
147 ++g_test_coroutine_task_status;
153static void test_context_task_function_2(
void *) {
154 ++g_test_coroutine_task_status;
157 cotask::this_task::get_task()->yield();
159 ++g_test_coroutine_task_status;
163CASE_TEST(coroutine_task, function_action) {
166 task_ptr_type co_task = cotask::task<>::create(test_context_task_function_1);
167 g_test_coroutine_task_status = 0;
171 ++g_test_coroutine_task_status;
179 ++g_test_coroutine_task_status;
181 CASE_EXPECT_EQ(co_task->get_coroutine_context()->get_ret_code(), 100);
186 task_ptr_type co_task = cotask::task<>::create(test_context_task_function_2);
187 g_test_coroutine_task_status = 0;
191 ++g_test_coroutine_task_status;
199 ++g_test_coroutine_task_status;
206 task_ptr_type co_task = cotask::task<>::create(test_context_task_function_1);
207 g_test_coroutine_task_status = 0;
211 ++g_test_coroutine_task_status;
221static void test_context_task_function_3(
void *) {
222 ++g_test_coroutine_task_status;
225 CASE_EXPECT_EQ(cotask::EN_TS_RUNNING, cotask::this_task::get_task()->get_status());
227 copp::this_coroutine::yield();
229 CASE_EXPECT_EQ(cotask::EN_TS_RUNNING, cotask::this_task::get<cotask::task<> >()->get_status());
231 ++g_test_coroutine_task_status;
235CASE_TEST(coroutine_task, coroutine_context_yield) {
237 task_ptr_type co_task = cotask::task<>::create(test_context_task_function_3);
238 g_test_coroutine_task_status = 0;
242 ++g_test_coroutine_task_status;
251 ++g_test_coroutine_task_status;
257struct test_context_task_mem_function {
258 cotask::task<>::id_t task_id_;
260 int real_run(
void *) {
261 ++g_test_coroutine_task_status;
265 cotask::task<>::this_task()->yield();
268 ++g_test_coroutine_task_status;
275CASE_TEST(coroutine_task, mem_function_action) {
277 test_context_task_mem_function obj;
278 task_ptr_type co_task = cotask::task<>::create(&test_context_task_mem_function::real_run, &obj);
279 g_test_coroutine_task_status = 0;
280 obj.task_id_ = co_task->get_id();
284 ++g_test_coroutine_task_status;
292 ++g_test_coroutine_task_status;
295 CASE_EXPECT_NE(co_task->get_coroutine_context()->get_ret_code(), -1);
301 test_context_task_mem_function obj;
302 task_ptr_type co_task = cotask::task<>::create(&test_context_task_mem_function::real_run, &obj);
303 g_test_coroutine_task_status = 0;
304 obj.task_id_ = co_task->get_id();
309 test_context_task_mem_function obj;
310 task_ptr_type co_task = cotask::task<>::create(&test_context_task_mem_function::real_run, &obj);
311 g_test_coroutine_task_status = 0;
312 obj.task_id_ = co_task->get_id();
316 ++g_test_coroutine_task_status;
322 ++g_test_coroutine_task_status;
326struct test_context_task_next_action :
public cotask::impl::task_action_impl {
329 test_context_task_next_action(
int s,
int c) : cotask::
impl::task_action_impl(), set_(s), check_(c) {}
331 int operator()(
void *)
override {
333 g_test_coroutine_task_status = set_;
335 CASE_EXPECT_EQ(copp::COPP_EC_IS_RUNNING, cotask::this_task::get_task()->start());
337 ++g_test_coroutine_task_on_finished;
346 g_test_coroutine_task_status = 0;
348 task_ptr_type co_task = cotask::task<>::create(test_context_task_next_action(15, 0));
349 co_task->next(test_context_task_next_action(7, 15))
350 ->next(test_context_task_next_action(99, 7))
351 ->next(test_context_task_next_action(1023, 99))
352 ->next(test_context_task_next_action(5, 1023));
362 g_test_coroutine_task_status = 0;
363 task_ptr_type co_task_a = cotask::task<>::create(test_context_task_next_action(2, 1));
364 task_ptr_type co_task_b = cotask::task<>::create(test_context_task_function_1);
367 co_task_a->next(co_task_b);
375struct test_context_task_functor_drived :
public cotask::impl::task_action_impl {
379 test_context_task_functor_drived(
int a,
int b) : a_(a), b_(b) {}
381 int operator()(
void *)
override {
389CASE_TEST(coroutine_task, functor_drived_action) {
391 cotask::task<>::coroutine_type::allocator_type alloc;
392 task_ptr_type co_task = cotask::task<>::create_with<test_context_task_functor_drived>(alloc, 0, 0, 1, 3);
396static int test_context_task_priavte_buffer(
void *) {
397 void *priv_data = cotask::task<>::this_task()->get_private_buffer();
398 size_t priv_sz = cotask::task<>::this_task()->get_private_buffer_size();
402 if (priv_sz >= 256) {
403 char checked_data[256];
404 memset(checked_data, 0x5e, 256);
412CASE_TEST(coroutine_task, priavte_buffer) {
414 task_ptr_type co_task = cotask::task<>::create(test_context_task_priavte_buffer, 16384, 256);
416 void *priv_data = co_task->get_private_buffer();
417 memset(priv_data, 0x5e, 256);
422static int test_context_task_timeout(
void *) {
423 cotask::task<>::this_task()->yield();
433CASE_TEST(coroutine_task, kill_and_timeout) {
435 task_ptr_type co_task = cotask::task<>::create(test_context_task_timeout, 16384, 256);
437 void *priv_data = co_task->get_private_buffer();
438 memset(priv_data, 0x5e, 256);
454static int test_context_task_await_1(
void *) {
459 CASE_EXPECT_EQ(copp::COPP_EC_ARGS_ERROR, self->await_task(
nullptr));
460 CASE_EXPECT_EQ(copp::COPP_EC_TASK_CAN_NOT_WAIT_SELF, self->await_task(self));
462 void *priv_data = self->get_private_buffer();
463 cotask::task<>::self_t *other_task = *
reinterpret_cast<cotask::task<>::self_t **
>(priv_data);
465 if (other_task->is_exiting()) {
466 CASE_EXPECT_EQ(copp::COPP_EC_TASK_IS_EXITING, self->await_task(other_task));
468 if (self->is_exiting()) {
469 CASE_EXPECT_EQ(copp::COPP_EC_TASK_IS_EXITING, self->await_task(other_task));
478static int test_context_task_await_2(
void *) {
return 0; }
486 cotask::task<>::create(test_context_task_await_1, 16384,
sizeof(cotask::task<>::self_t *));
487 task_ptr_type co_task_2 = cotask::task<>::create(test_context_task_await_2, 16384);
489 void *priv_data = co_task_1->get_private_buffer();
491 *
reinterpret_cast<cotask::task<>::self_t **
>(priv_data) = co_task_2.get();
492 CASE_EXPECT_EQ(copp::COPP_EC_TASK_NOT_IN_ACTION, co_task_1->await_task(co_task_2));
509 cotask::task<>::create(test_context_task_await_1, 16384,
sizeof(cotask::task<>::self_t *));
510 task_ptr_type co_task_2 = cotask::task<>::create(test_context_task_await_2, 16384);
512 void *priv_data = co_task_1->get_private_buffer();
514 CASE_EXPECT_EQ(copp::COPP_EC_ARGS_ERROR, co_task_1->await_task(
nullptr));
515 CASE_EXPECT_EQ(copp::COPP_EC_TASK_CAN_NOT_WAIT_SELF, co_task_1->await_task(co_task_1));
517 *
reinterpret_cast<cotask::task<>::self_t **
>(priv_data) = co_task_2.get();
518 CASE_EXPECT_EQ(copp::COPP_EC_TASK_NOT_IN_ACTION, co_task_1->await_task(co_task_2));
523 co_task_1->kill(cotask::EN_TS_TIMEOUT);
537 cotask::task<>::create(test_context_task_await_1, 16384,
sizeof(cotask::task<>::self_t *));
538 task_ptr_type co_task_2 = cotask::task<>::create(test_context_task_await_2, 16384);
540 void *priv_data = co_task_1->get_private_buffer();
542 *
reinterpret_cast<cotask::task<>::self_t **
>(priv_data) = co_task_2.get();
543 CASE_EXPECT_EQ(copp::COPP_EC_TASK_NOT_IN_ACTION, co_task_1->await_task(co_task_2));
558static int test_context_task_then_action_func(
void *priv_data) {
560 ++g_test_coroutine_task_on_finished;
566 g_test_coroutine_task_status = 0;
567 g_test_coroutine_task_on_finished = 0;
569 task_ptr_type co_task = cotask::task<>::create(test_context_task_next_action(15, 0));
570 co_task->then(test_context_task_next_action(7, 15))
571 ->then(test_context_task_next_action(99, 7))
572 ->then(test_context_task_next_action(1023, 99))
573 ->then(test_context_task_next_action(5, 1023));
583 co_task->then(test_context_task_next_action(127, 5))
584 ->then(test_context_task_then_action_func, &g_test_coroutine_task_status);
589typedef copp::stack_pool<copp::allocator::stack_allocator_malloc> test_context_task_stack_pool_t;
590struct test_context_task_stack_pool_test_macro_coroutine {
591 using stack_allocator_type = copp::allocator::stack_allocator_pool<test_context_task_stack_pool_t>;
592 using coroutine_type = copp::coroutine_context_container<stack_allocator_type>;
596typedef cotask::task<test_context_task_stack_pool_test_macro_coroutine> test_context_task_stack_pool_test_task_t;
598CASE_TEST(coroutine_task, then_with_stack_pool) {
599 typedef test_context_task_stack_pool_test_task_t::ptr_t
task_ptr_type;
600 test_context_task_stack_pool_t::ptr_t
stack_pool = test_context_task_stack_pool_t::create();
602 g_test_coroutine_task_on_finished = 0;
603 g_test_coroutine_task_status = 0;
605 copp::allocator::stack_allocator_pool<test_context_task_stack_pool_t> base_alloc(
stack_pool);
606 task_ptr_type tp = test_context_task_stack_pool_test_task_t::create(test_context_task_next_action(15, 0), base_alloc);
607 tp->then(test_context_task_next_action(127, 15))
608 ->then(test_context_task_then_action_func, &g_test_coroutine_task_status);
614 tp->then(test_context_task_next_action(255, 127))
615 ->then(test_context_task_then_action_func, &g_test_coroutine_task_status);
624class task_action_of_issue18 {
626 task_action_of_issue18() {}
627 int operator()(
void *) {
return 0; }
630CASE_TEST(coroutine_task, github_issues_18) {
631 using simple_task_t = cotask::task<>;
634 simple_task_t::ptr_t co_task = simple_task_t::create(task_action_of_issue18());
636 co_task->then(task_action_of_issue18());
641 task_action_of_issue18 copy_action;
642 simple_task_t::ptr_t co_task = simple_task_t::create(copy_action);
644 co_task->then(copy_action);
649# if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
650static LIBCOPP_COPP_NAMESPACE_ID::util::lock::atomic_int_type<int> g_test_context_task_test_atomic;
651static constexpr const int g_test_context_task_test_mt_run_times = 10000;
652static size_t g_test_context_task_test_mt_max_run_thread_number = 0;
654 test_context_task_test_mt_thread_num = 100,
655 test_context_task_test_mt_task_num = 1000,
658struct test_context_task_test_action_mt_thread :
public cotask::impl::task_action_impl {
662 test_context_task_test_action_mt_thread() : run_count(0) {}
664 int operator()(
void *thread_func_address)
override {
665 std::set<void *> thread_counter;
667 while (run_count < g_test_context_task_test_mt_run_times) {
669 ++g_test_context_task_test_atomic;
671 thread_counter.insert(thread_func_address);
673 cotask::this_task::get_task()->yield(&thread_func_address);
676 if (g_test_context_task_test_mt_max_run_thread_number < thread_counter.size()) {
677 g_test_context_task_test_mt_max_run_thread_number = thread_counter.size();
683struct test_context_task_test_mt_thread_runner {
686 std::vector<task_ptr_type> *task_pool;
687 test_context_task_test_mt_thread_runner(std::vector<task_ptr_type> *pool) : task_pool(pool) {}
690 bool need_continue =
true;
691 while (need_continue) {
692 need_continue =
false;
694 for (
size_t i = 0; i < task_pool->size(); ++i) {
695 if (
false == (*task_pool)[i]->is_completed()) {
696 need_continue =
true;
697 (*task_pool)[i]->resume(
this);
705CASE_TEST(coroutine_task, mt_run_competition) {
707 std::vector<task_ptr_type> task_pool;
708 task_pool.reserve(test_context_task_test_mt_task_num);
709 for (
int i = 0; i < test_context_task_test_mt_task_num; ++i) {
711 cotask::task<>::create(test_context_task_test_action_mt_thread(), 16 * 1024));
714 g_test_context_task_test_atomic.store(0);
715 g_test_context_task_test_mt_max_run_thread_number = 0;
717 std::unique_ptr<std::thread> thds[test_context_task_test_mt_thread_num];
718 for (
int i = 0; i < test_context_task_test_mt_thread_num; ++i) {
719 thds[i].reset(
new std::thread(test_context_task_test_mt_thread_runner(&task_pool)));
722 for (
int i = 0; i < test_context_task_test_mt_thread_num; ++i) {
726 CASE_EXPECT_EQ(g_test_context_task_test_mt_run_times * test_context_task_test_mt_task_num,
727 g_test_context_task_test_atomic.load());
728 CASE_MSG_INFO() <<
"Coroutine tasks are run on " << g_test_context_task_test_mt_max_run_thread_number
729 <<
" threads at most." << std::endl;
733# if defined(LIBCOPP_MACRO_ENABLE_STD_COROUTINE) && LIBCOPP_MACRO_ENABLE_STD_COROUTINE
734static copp::callable_future<int> call_for_await_cotask(
const cotask::task<>::ptr_t &t) {
736 co_return co_await t;
742static int cotask_action_callback(
void *) {
745 cotask::this_task::get_task()->yield(&ptr);
746 if (ptr !=
nullptr) {
747 ret = *
reinterpret_cast<int *
>(ptr);
752CASE_TEST(coroutine_task, callable_future_co_await) {
753 cotask::task<>::ptr_t co_task = cotask::task<>::create(cotask_action_callback);
755 auto t = call_for_await_cotask(co_task);
760 co_task->resume(
reinterpret_cast<void *
>(&res));
767CASE_TEST(coroutine_task, callable_future_co_await_do_not_start) {
768 cotask::task<>::ptr_t co_task = cotask::task<>::create(cotask_action_callback);
770 auto t = call_for_await_cotask(co_task);
777 CASE_EXPECT_EQ(LIBCOPP_COPP_NAMESPACE_ID::COPP_EC_TASK_IS_KILLED, t.get_internal_promise().data());
const limit_t & get_limit() const
std::shared_ptr< cli::cmd_option_value > value_type
my_task_t::ptr_t task_ptr_type
#define CASE_EXPECT_FALSE(c)
#define CASE_EXPECT_EQ(l, r)
#define CASE_EXPECT_GT(l, r)
#define CASE_EXPECT_NE(l, r)
#define CASE_TEST(test_name, case_name)
#define CASE_EXPECT_TRUE(c)
#define CASE_EXPECT_GE(l, r)