15#if defined(LIBCOTASK_MACRO_ENABLED) && defined(LIBCOPP_MACRO_ENABLE_WIN_FIBER) && LIBCOPP_MACRO_ENABLE_WIN_FIBER
16struct test_context_task_fiber_default_test_macro {
17 using stack_allocator_type = copp::allocator::stack_allocator_malloc;
18 using coroutine_type = copp::coroutine_context_fiber_container<stack_allocator_type>;
22static int g_test_coroutine_task_fiber_status = 0;
23static int g_test_coroutine_task_fiber_on_finished = 0;
24class test_context_task_fiber_action_base :
public cotask::impl::task_action_impl {
27 virtual int operator()() = 0;
29 int operator()(
void *priv_data)
override {
30 ++g_test_coroutine_task_fiber_status;
34 CASE_EXPECT_EQ(cotask::EN_TS_RUNNING, cotask::this_task::get_task()->get_status());
35 cotask::this_task::get_task()->yield(&priv_data);
36 CASE_EXPECT_EQ(cotask::EN_TS_RUNNING, cotask::this_task::get_task()->get_status());
40 ++g_test_coroutine_task_fiber_status;
45 virtual int on_finished(cotask::impl::task_impl &)
override {
46 ++g_test_coroutine_task_fiber_on_finished;
51class test_context_task_fiber_action :
public test_context_task_fiber_action_base {
53 using test_context_task_fiber_action_base::operator();
56 int operator()()
override {
return 0; }
59CASE_TEST(coroutine_task_fiber, custom_action) {
60 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
61 g_test_coroutine_task_fiber_status = 0;
62 g_test_coroutine_task_fiber_on_finished = 0;
66 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_action());
67 task_ptr_type co_another_task = cotask::task<test_context_task_fiber_default_test_macro>::create(
68 test_context_task_fiber_action());
71 CASE_EXPECT_EQ(cotask::EN_TS_CREATED, co_another_task->get_status());
73 CASE_EXPECT_EQ(0, co_task->start(&g_test_coroutine_task_fiber_status));
80 CASE_EXPECT_EQ(0, co_another_task->start(&g_test_coroutine_task_fiber_status));
84 CASE_EXPECT_EQ(cotask::EN_TS_WAITING, co_another_task->get_status());
100 CASE_EXPECT_GT(0, co_another_task->resume(co_another_task.get()));
103 ++g_test_coroutine_task_fiber_status;
112struct test_context_task_fiber_functor {
114 int operator()(
void *)
const {
115 ++g_test_coroutine_task_fiber_status;
118 cotask::this_task::get_task()->yield();
120 ++g_test_coroutine_task_fiber_status;
127CASE_TEST(coroutine_task_fiber, functor_action) {
128 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
130 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_functor());
131 g_test_coroutine_task_fiber_status = 0;
135 ++g_test_coroutine_task_fiber_status;
143 ++g_test_coroutine_task_fiber_status;
149static int test_context_task_fiber_function_1(
void *) {
150 ++g_test_coroutine_task_fiber_status;
153 cotask::this_task::get_task()->yield();
155 ++g_test_coroutine_task_fiber_status;
161static void test_context_task_fiber_function_2(
void *) {
162 ++g_test_coroutine_task_fiber_status;
165 cotask::this_task::get_task()->yield();
167 ++g_test_coroutine_task_fiber_status;
171CASE_TEST(coroutine_task_fiber, function_action) {
173 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
175 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_function_1);
176 g_test_coroutine_task_fiber_status = 0;
180 ++g_test_coroutine_task_fiber_status;
188 ++g_test_coroutine_task_fiber_status;
190 CASE_EXPECT_EQ(co_task->get_coroutine_context()->get_ret_code(), 100);
194 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
196 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_function_2);
197 g_test_coroutine_task_fiber_status = 0;
201 ++g_test_coroutine_task_fiber_status;
209 ++g_test_coroutine_task_fiber_status;
215 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
217 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_function_1);
218 g_test_coroutine_task_fiber_status = 0;
222 ++g_test_coroutine_task_fiber_status;
232static void test_context_task_fiber_function_3(
void *) {
233 ++g_test_coroutine_task_fiber_status;
236 CASE_EXPECT_EQ(cotask::EN_TS_RUNNING, cotask::this_task::get_task()->get_status());
238 copp::this_fiber::yield();
241 cotask::this_task::get<cotask::task<test_context_task_fiber_default_test_macro> >()->get_status());
243 ++g_test_coroutine_task_fiber_status;
247CASE_TEST(coroutine_task_fiber, coroutine_context_yield) {
248 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
250 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_function_3);
251 g_test_coroutine_task_fiber_status = 0;
255 ++g_test_coroutine_task_fiber_status;
264 ++g_test_coroutine_task_fiber_status;
270struct test_context_task_fiber_mem_function {
271 cotask::task<test_context_task_fiber_default_test_macro>::id_t task_id_;
273 int real_run(
void *) {
274 ++g_test_coroutine_task_fiber_status;
277 CASE_EXPECT_EQ(task_id_, cotask::task<test_context_task_fiber_default_test_macro>::this_task()->get_id());
278 cotask::task<test_context_task_fiber_default_test_macro>::this_task()->yield();
279 CASE_EXPECT_EQ(task_id_, cotask::task<test_context_task_fiber_default_test_macro>::this_task()->get_id());
281 ++g_test_coroutine_task_fiber_status;
288CASE_TEST(coroutine_task_fiber, mem_function_action) {
289 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
290 test_context_task_fiber_mem_function obj;
291 task_ptr_type co_task = cotask::task<test_context_task_fiber_default_test_macro>::create(
292 &test_context_task_fiber_mem_function::real_run, &obj);
293 g_test_coroutine_task_fiber_status = 0;
294 obj.task_id_ = co_task->get_id();
298 ++g_test_coroutine_task_fiber_status;
306 ++g_test_coroutine_task_fiber_status;
309 CASE_EXPECT_NE(co_task->get_coroutine_context()->get_ret_code(), -1);
312CASE_TEST(coroutine_task_fiber, auto_finish) {
313 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
315 test_context_task_fiber_mem_function obj;
316 task_ptr_type co_task = cotask::task<test_context_task_fiber_default_test_macro>::create(
317 &test_context_task_fiber_mem_function::real_run, &obj);
318 g_test_coroutine_task_fiber_status = 0;
319 obj.task_id_ = co_task->get_id();
324 test_context_task_fiber_mem_function obj;
325 task_ptr_type co_task = cotask::task<test_context_task_fiber_default_test_macro>::create(
326 &test_context_task_fiber_mem_function::real_run, &obj);
327 g_test_coroutine_task_fiber_status = 0;
328 obj.task_id_ = co_task->get_id();
332 ++g_test_coroutine_task_fiber_status;
338 ++g_test_coroutine_task_fiber_status;
342struct test_context_task_fiber_next_action :
public cotask::impl::task_action_impl {
345 test_context_task_fiber_next_action(
int s,
int c) : cotask::
impl::task_action_impl(), set_(s), check_(c) {}
347 int operator()(
void *)
override {
349 g_test_coroutine_task_fiber_status = set_;
351 CASE_EXPECT_EQ(copp::COPP_EC_IS_RUNNING, cotask::this_task::get_task()->start());
353 ++g_test_coroutine_task_fiber_on_finished;
359 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
362 g_test_coroutine_task_fiber_status = 0;
365 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_next_action(15, 0));
366 co_task->next(test_context_task_fiber_next_action(7, 15))
367 ->next(test_context_task_fiber_next_action(99, 7))
368 ->next(test_context_task_fiber_next_action(1023, 99))
369 ->next(test_context_task_fiber_next_action(5, 1023));
379 g_test_coroutine_task_fiber_status = 0;
381 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_next_action(2, 1));
383 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_function_1);
386 co_task_a->next(co_task_b);
394struct test_context_task_fiber_functor_drived :
public cotask::impl::task_action_impl {
398 test_context_task_fiber_functor_drived(
int a,
int b) : a_(a), b_(b) {}
400 int operator()(
void *)
override {
408CASE_TEST(coroutine_task_fiber, functor_drived_action) {
409 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
410 cotask::task<test_context_task_fiber_default_test_macro>::coroutine_type::allocator_type alloc;
412 cotask::task<test_context_task_fiber_default_test_macro>::create_with<test_context_task_fiber_functor_drived>(
417static int test_context_task_fiber_priavte_buffer(
void *) {
418 void *priv_data = cotask::task<test_context_task_fiber_default_test_macro>::this_task()->get_private_buffer();
419 size_t priv_sz = cotask::task<test_context_task_fiber_default_test_macro>::this_task()->get_private_buffer_size();
423 if (priv_sz >= 256) {
424 char checked_data[256];
425 memset(checked_data, 0x5e, 256);
433CASE_TEST(coroutine_task_fiber, priavte_buffer) {
434 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
435 task_ptr_type co_task = cotask::task<test_context_task_fiber_default_test_macro>::create(
436 test_context_task_fiber_priavte_buffer, 16384, 256);
438 void *priv_data = co_task->get_private_buffer();
439 memset(priv_data, 0x5e, 256);
444static int test_context_task_fiber_timeout(
void *) {
445 cotask::task<test_context_task_fiber_default_test_macro>::this_task()->yield();
447 CASE_EXPECT_TRUE(cotask::task<test_context_task_fiber_default_test_macro>::this_task()->is_timeout());
448 CASE_EXPECT_TRUE(cotask::task<test_context_task_fiber_default_test_macro>::this_task()->is_faulted());
449 CASE_EXPECT_FALSE(cotask::task<test_context_task_fiber_default_test_macro>::this_task()->is_completed());
450 CASE_EXPECT_TRUE(cotask::task<test_context_task_fiber_default_test_macro>::this_task()->is_exiting());
455CASE_TEST(coroutine_task_fiber, kill_and_timeout) {
456 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
458 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_timeout, 16384, 256);
460 void *priv_data = co_task->get_private_buffer();
461 memset(priv_data, 0x5e, 256);
477static int test_context_task_fiber_await_1(
void *) {
478 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
480 task_ptr_type self = cotask::task<test_context_task_fiber_default_test_macro>::this_task();
482 CASE_EXPECT_EQ(copp::COPP_EC_ARGS_ERROR, self->await_task(
nullptr));
483 CASE_EXPECT_EQ(copp::COPP_EC_TASK_CAN_NOT_WAIT_SELF, self->await_task(self));
485 void *priv_data = self->get_private_buffer();
486 cotask::task<test_context_task_fiber_default_test_macro>::self_t *other_task =
487 *
reinterpret_cast<cotask::task<test_context_task_fiber_default_test_macro>::self_t **
>(priv_data);
489 if (other_task->is_exiting()) {
490 CASE_EXPECT_EQ(copp::COPP_EC_TASK_IS_EXITING, self->await_task(other_task));
492 if (self->is_exiting()) {
493 CASE_EXPECT_EQ(copp::COPP_EC_TASK_IS_EXITING, self->await_task(other_task));
502static int test_context_task_fiber_await_2(
void *) {
return 0; }
504CASE_TEST(coroutine_task_fiber, await_task) {
505 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
509 task_ptr_type co_task_1 = cotask::task<test_context_task_fiber_default_test_macro>::create(
510 test_context_task_fiber_await_1, 16384,
511 sizeof(cotask::task<test_context_task_fiber_default_test_macro>::self_t *));
513 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_await_2, 16384);
515 void *priv_data = co_task_1->get_private_buffer();
517 *
reinterpret_cast<cotask::task<test_context_task_fiber_default_test_macro>::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));
534 task_ptr_type co_task_1 = cotask::task<test_context_task_fiber_default_test_macro>::create(
535 test_context_task_fiber_await_1, 16384,
536 sizeof(cotask::task<test_context_task_fiber_default_test_macro>::self_t *));
538 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_await_2, 16384);
540 void *priv_data = co_task_1->get_private_buffer();
542 CASE_EXPECT_EQ(copp::COPP_EC_ARGS_ERROR, co_task_1->await_task(
nullptr));
543 CASE_EXPECT_EQ(copp::COPP_EC_TASK_CAN_NOT_WAIT_SELF, co_task_1->await_task(co_task_1));
545 *
reinterpret_cast<cotask::task<test_context_task_fiber_default_test_macro>::self_t **
>(priv_data) = co_task_2.get();
546 CASE_EXPECT_EQ(copp::COPP_EC_TASK_NOT_IN_ACTION, co_task_1->await_task(co_task_2));
551 co_task_1->kill(cotask::EN_TS_TIMEOUT);
564 task_ptr_type co_task_1 = cotask::task<test_context_task_fiber_default_test_macro>::create(
565 test_context_task_fiber_await_1, 16384,
566 sizeof(cotask::task<test_context_task_fiber_default_test_macro>::self_t *));
568 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_await_2, 16384);
570 void *priv_data = co_task_1->get_private_buffer();
572 *
reinterpret_cast<cotask::task<test_context_task_fiber_default_test_macro>::self_t **
>(priv_data) = co_task_2.get();
573 CASE_EXPECT_EQ(copp::COPP_EC_TASK_NOT_IN_ACTION, co_task_1->await_task(co_task_2));
588static int test_context_task_fiber_then_action_func(
void *priv_data) {
590 ++g_test_coroutine_task_fiber_on_finished;
595 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
596 g_test_coroutine_task_fiber_status = 0;
597 g_test_coroutine_task_fiber_on_finished = 0;
600 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_next_action(15, 0));
601 co_task->then(test_context_task_fiber_next_action(7, 15))
602 ->then(test_context_task_fiber_next_action(99, 7))
603 ->then(test_context_task_fiber_next_action(1023, 99))
604 ->then(test_context_task_fiber_next_action(5, 1023));
614 co_task->then(test_context_task_fiber_next_action(127, 5))
615 ->then(test_context_task_fiber_then_action_func, &g_test_coroutine_task_fiber_status);
620typedef copp::stack_pool<copp::allocator::stack_allocator_malloc> test_context_task_fiber_stack_pool_t;
621struct test_context_task_fiber_stack_pool_test_macro_coroutine {
622 using stack_allocator_type = copp::allocator::stack_allocator_pool<test_context_task_fiber_stack_pool_t>;
623 using coroutine_type = copp::coroutine_context_fiber_container<stack_allocator_type>;
627typedef cotask::task<test_context_task_fiber_stack_pool_test_macro_coroutine>
628 test_context_task_fiber_stack_pool_test_task_t;
630CASE_TEST(coroutine_task_fiber, then_with_stack_pool) {
631 typedef test_context_task_fiber_stack_pool_test_task_t::ptr_t
task_ptr_type;
632 test_context_task_fiber_stack_pool_t::ptr_t
stack_pool = test_context_task_fiber_stack_pool_t::create();
634 g_test_coroutine_task_fiber_on_finished = 0;
635 g_test_coroutine_task_fiber_status = 0;
637 copp::allocator::stack_allocator_pool<test_context_task_fiber_stack_pool_t> base_alloc(
stack_pool);
639 test_context_task_fiber_stack_pool_test_task_t::create(test_context_task_fiber_next_action(15, 0), base_alloc);
640 tp->then(test_context_task_fiber_next_action(127, 15))
641 ->then(test_context_task_fiber_then_action_func, &g_test_coroutine_task_fiber_status);
647 tp->then(test_context_task_fiber_next_action(255, 127))
648 ->then(test_context_task_fiber_then_action_func, &g_test_coroutine_task_fiber_status);
655# if LIBCOPP_MACRO_ENABLE_MULTI_THREAD
656static LIBCOPP_COPP_NAMESPACE_ID::util::lock::atomic_int_type<int> g_test_context_task_fiber_test_atomic;
657static constexpr const int g_test_context_task_fiber_test_mt_run_times = 10000;
658static size_t g_test_context_task_fiber_test_mt_max_run_thread_number = 0;
660 test_context_task_fiber_test_mt_thread_num = 100,
661 test_context_task_fiber_test_mt_task_num = 1000,
664struct test_context_task_fiber_test_action_mt_thread :
public cotask::impl::task_action_impl {
668 test_context_task_fiber_test_action_mt_thread() : run_count(0) {}
670 int operator()(
void *thread_func_address)
override {
671 std::set<void *> thread_counter;
673 while (run_count < g_test_context_task_fiber_test_mt_run_times) {
675 ++g_test_context_task_fiber_test_atomic;
677 thread_counter.insert(thread_func_address);
679 cotask::this_task::get_task()->yield(&thread_func_address);
682 if (g_test_context_task_fiber_test_mt_max_run_thread_number < thread_counter.size()) {
683 g_test_context_task_fiber_test_mt_max_run_thread_number = thread_counter.size();
689struct test_context_task_fiber_test_mt_thread_runner {
690 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
692 std::vector<task_ptr_type> *task_pool;
693 test_context_task_fiber_test_mt_thread_runner(std::vector<task_ptr_type> *pool) : task_pool(pool) {}
696 bool need_continue =
true;
697 while (need_continue) {
698 need_continue =
false;
700 for (
size_t i = 0; i < task_pool->size(); ++i) {
701 if (
false == (*task_pool)[i]->is_completed()) {
702 need_continue =
true;
703 (*task_pool)[i]->resume(
this);
711CASE_TEST(coroutine_task_fiber, mt_run_competition) {
712 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
713 std::vector<task_ptr_type> task_pool;
714 task_pool.reserve(test_context_task_fiber_test_mt_task_num);
715 for (
int i = 0; i < test_context_task_fiber_test_mt_task_num; ++i) {
716 task_pool.push_back(cotask::task<test_context_task_fiber_default_test_macro>::create(
717 test_context_task_fiber_test_action_mt_thread(), 16 * 1024));
720 g_test_context_task_fiber_test_atomic.store(0);
721 g_test_context_task_fiber_test_mt_max_run_thread_number = 0;
723 std::unique_ptr<std::thread> thds[test_context_task_fiber_test_mt_thread_num];
724 for (
int i = 0; i < test_context_task_fiber_test_mt_thread_num; ++i) {
725 thds[i].reset(
new std::thread(test_context_task_fiber_test_mt_thread_runner(&task_pool)));
728 for (
int i = 0; i < test_context_task_fiber_test_mt_thread_num; ++i) {
732 CASE_EXPECT_EQ(g_test_context_task_fiber_test_mt_run_times * test_context_task_fiber_test_mt_task_num,
733 g_test_context_task_fiber_test_atomic.load());
734 CASE_MSG_INFO() <<
"Fiber tasks are run on " << g_test_context_task_fiber_test_mt_max_run_thread_number
735 <<
" threads at most." << std::endl;
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)