libcopp  2.2.0
task_promise_test.cpp
Go to the documentation of this file.
1 // Copyright 2023 owent
2 
7 
8 #include <cstdio>
9 #include <cstring>
10 #include <iostream>
11 #include <list>
12 #include <string>
13 
14 #include "frame/test_macros.h"
15 
16 #if defined(LIBCOPP_MACRO_ENABLE_STD_COROUTINE) && LIBCOPP_MACRO_ENABLE_STD_COROUTINE
17 
18 namespace {
19 struct task_future_private_data {
20  int data;
21 };
22 
23 using task_future_int_type = cotask::task_future<int, task_future_private_data>;
24 using task_future_void_type = cotask::task_future<void, task_future_private_data>;
25 using task_future_int_type_no_private_data = cotask::task_future<int, void>;
26 using task_future_void_type_no_private_data = cotask::task_future<void, void>;
27 using callable_future_int_type = copp::callable_future<int>;
28 using callable_future_void_type = copp::callable_future<void>;
29 using generator_future_int_type = copp::generator_future<int>;
30 using generator_future_void_type = copp::generator_future<void>;
31 
32 std::list<generator_future_int_type::context_pointer_type> g_task_future_pending_int_contexts;
33 std::list<generator_future_void_type::context_pointer_type> g_task_future_pending_void_contexts;
34 size_t g_task_future_resume_generator_count = 0;
35 size_t g_task_future_suspend_generator_count = 0;
36 
37 static size_t resume_pending_contexts(std::list<int> values, int max_count = 32767) {
38  size_t ret = 0;
39  while (max_count > 0 &&
40  (!g_task_future_pending_int_contexts.empty() || !g_task_future_pending_void_contexts.empty())) {
41  --max_count;
42  if (!g_task_future_pending_int_contexts.empty()) {
43  auto ctx = *g_task_future_pending_int_contexts.begin();
44  g_task_future_pending_int_contexts.pop_front();
45 
46  if (!values.empty()) {
47  int val = values.front();
48  values.pop_front();
49  ctx->set_value(val);
50  } else {
51  ctx->set_value(0);
52  }
53 
54  ++ret;
55  }
56 
57  if (!g_task_future_pending_void_contexts.empty()) {
58  auto ctx = *g_task_future_pending_void_contexts.begin();
59  g_task_future_pending_void_contexts.pop_front();
60  ctx->set_value();
61 
62  ++ret;
63  }
64  }
65 
66  return ret;
67 }
68 
69 static void generator_int_suspend_callback(generator_future_int_type::context_pointer_type ctx) {
70  ++g_task_future_suspend_generator_count;
71  g_task_future_pending_int_contexts.push_back(ctx);
72 }
73 static void generator_int_resume_callback(const generator_future_int_type::context_type &) {
74  ++g_task_future_resume_generator_count;
75 }
76 
77 static callable_future_int_type task_future_func_int_l1(int inout) {
78  CASE_MSG_INFO() << "callable inner future ready int: " << inout << std::endl;
79  co_return inout;
80 }
81 
82 static callable_future_int_type task_future_func_int_l2(int inout) {
83  generator_future_int_type generator{generator_int_suspend_callback, generator_int_resume_callback};
84  auto gen_res = co_await generator;
85  if (gen_res < 0) {
86  co_return gen_res;
87  }
88  co_return inout + gen_res;
89 }
90 
91 static callable_future_int_type task_future_func_await_int() {
92  auto v = task_future_func_int_l1(3);
93  auto u = task_future_func_int_l2(11);
94  int x = (co_await v + co_await u);
95  co_return x;
96 }
97 
98 static task_future_int_type task_func_await_int() {
99  auto current_status = co_yield task_future_void_type::yield_status();
100  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kRunning), static_cast<int>(current_status));
101  auto private_data = co_yield task_future_int_type::yield_private_data();
102  private_data->data = 121000;
103 
104  CASE_MSG_INFO() << "task await int" << std::endl;
105  auto v = task_future_func_await_int();
106  int x = co_await v;
107  CASE_MSG_INFO() << "task return int" << std::endl;
108  co_return x;
109 }
110 
111 static callable_future_int_type task_future_func_no_wait_int() {
112  auto v = task_future_func_int_l1(7);
113  auto u = task_future_func_int_l1(19);
114  int x = (co_await v + co_await u);
115  co_return x;
116 }
117 
118 static task_future_int_type task_func_no_wait_int() {
119  auto current_status = co_yield task_future_void_type::yield_status();
120  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kRunning), static_cast<int>(current_status));
121  auto private_data = co_yield cotask::task_private_data<task_future_private_data>();
122  private_data->data = 121000;
123 
124  CASE_MSG_INFO() << "task await int" << std::endl;
125  auto v = task_future_func_no_wait_int();
126  int x = co_await v;
127  CASE_MSG_INFO() << "task return int" << std::endl;
128  co_return x;
129 }
130 
131 static void generator_void_suspend_callback(generator_future_void_type::context_pointer_type ctx) {
132  ++g_task_future_suspend_generator_count;
133  g_task_future_pending_void_contexts.push_back(ctx);
134 }
135 static void generator_void_resume_callback(const generator_future_void_type::context_type &) {
136  ++g_task_future_resume_generator_count;
137 }
138 
139 static callable_future_void_type task_future_func_void_l1() {
140  CASE_MSG_INFO() << "callable inner future ready void" << std::endl;
141  co_return;
142 }
143 
144 static callable_future_void_type task_future_func_void_l2() {
145  generator_future_void_type generator{generator_void_suspend_callback, generator_void_resume_callback};
146  co_await generator;
147  co_return;
148 }
149 
150 static callable_future_void_type task_future_func_await_void() {
151  auto v = task_future_func_void_l1();
152  auto u = task_future_func_void_l2();
153  co_await v;
154  co_await u;
155  co_return;
156 }
157 
158 static task_future_void_type task_func_await_void() {
159  auto current_status = co_yield task_future_void_type::yield_status();
160  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kRunning), static_cast<int>(current_status));
161  auto private_data = co_yield task_future_void_type::yield_private_data();
162  private_data->data = 123000;
163 
164  CASE_MSG_INFO() << "task await void" << std::endl;
165  auto v = task_future_func_await_void();
166  co_await v;
167  CASE_MSG_INFO() << "task return void" << std::endl;
168  co_return;
169 }
170 
171 static callable_future_void_type task_future_func_no_wait_void() {
172  auto v = task_future_func_void_l1();
173  auto u = task_future_func_void_l1();
174  co_await v;
175  co_await u;
176  co_return;
177 }
178 
179 static task_future_void_type task_func_no_wait_void() {
180  auto current_status = co_yield task_future_void_type::yield_status();
181  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kRunning), static_cast<int>(current_status));
182  auto private_data = co_yield cotask::task_private_data<task_future_private_data>();
183  private_data->data = 123000;
184 
185  CASE_MSG_INFO() << "task await void" << std::endl;
186  auto v = task_future_func_no_wait_void();
187  co_await v;
188  CASE_MSG_INFO() << "task return void" << std::endl;
189  co_return;
190 }
191 
192 static task_future_void_type_no_private_data task_func_await_pick_task_id(
193  task_future_void_type_no_private_data::id_type &output) {
194  output = co_yield task_future_void_type_no_private_data::yield_task_id();
195 
196  co_return;
197 }
198 
199 } // namespace
200 
201 CASE_TEST(task_promise, task_future_void_yield_task_id) {
202  task_future_void_type_no_private_data::id_type task_id = 0;
203  task_future_void_type_no_private_data t = task_func_await_pick_task_id(task_id);
204 
205  CASE_EXPECT_NE(0, t.get_id());
206  CASE_EXPECT_EQ(0, task_id);
207  CASE_EXPECT_TRUE(t.start());
208 
209  CASE_EXPECT_EQ(t.get_id(), task_id);
210 
211  CASE_EXPECT_TRUE(t.valid());
212  CASE_EXPECT_TRUE(t);
213 }
214 
215 CASE_TEST(task_promise, task_future_integer_need_resume) {
216  size_t old_resume_generator_count = g_task_future_resume_generator_count;
217  size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
218 
219  task_future_int_type t = task_func_await_int();
220  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kCreated), static_cast<int>(t.get_status()));
221  CASE_EXPECT_FALSE(t.is_canceled());
222  CASE_EXPECT_FALSE(t.is_faulted());
223  CASE_EXPECT_FALSE(t.is_timeout());
224  CASE_EXPECT_FALSE(t.is_exiting());
225  CASE_EXPECT_FALSE(t.is_completed());
226 
227  CASE_EXPECT_TRUE(t.start());
228  CASE_EXPECT_EQ(121000, t.get_private_data()->data);
229  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kRunning), static_cast<int>(t.get_status()));
230  CASE_EXPECT_FALSE(t.is_canceled());
231  CASE_EXPECT_FALSE(t.is_faulted());
232  CASE_EXPECT_FALSE(t.is_timeout());
233  CASE_EXPECT_FALSE(t.is_exiting());
234  CASE_EXPECT_FALSE(t.is_completed());
235 
236  resume_pending_contexts({100});
237  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kDone), static_cast<int>(t.get_status()));
238  CASE_EXPECT_FALSE(t.is_canceled());
239  CASE_EXPECT_FALSE(t.is_faulted());
240  CASE_EXPECT_FALSE(t.is_timeout());
241  CASE_EXPECT_TRUE(t.is_exiting());
242  CASE_EXPECT_TRUE(t.is_completed());
243  CASE_EXPECT_EQ(114, *t.get_context()->data());
244 
245  CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
246  CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
247 }
248 
249 CASE_TEST(task_promise, task_future_void_need_resume) {
250  size_t old_resume_generator_count = g_task_future_resume_generator_count;
251  size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
252 
253  task_future_void_type t = task_func_await_void();
254  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kCreated), static_cast<int>(t.get_status()));
255  CASE_EXPECT_FALSE(t.is_canceled());
256  CASE_EXPECT_FALSE(t.is_faulted());
257  CASE_EXPECT_FALSE(t.is_timeout());
258  CASE_EXPECT_FALSE(t.is_exiting());
259  CASE_EXPECT_FALSE(t.is_completed());
260 
261  CASE_EXPECT_TRUE(t.start());
262  CASE_EXPECT_EQ(123000, t.get_private_data()->data);
263  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kRunning), static_cast<int>(t.get_status()));
264  CASE_EXPECT_FALSE(t.is_canceled());
265  CASE_EXPECT_FALSE(t.is_faulted());
266  CASE_EXPECT_FALSE(t.is_timeout());
267  CASE_EXPECT_FALSE(t.is_exiting());
268  CASE_EXPECT_FALSE(t.is_completed());
269 
270  resume_pending_contexts({100});
271  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kDone), static_cast<int>(t.get_status()));
272  CASE_EXPECT_FALSE(t.is_canceled());
273  CASE_EXPECT_FALSE(t.is_faulted());
274  CASE_EXPECT_FALSE(t.is_timeout());
275  CASE_EXPECT_TRUE(t.is_exiting());
276  CASE_EXPECT_TRUE(t.is_completed());
277 
278  CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
279  CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
280 }
281 
282 CASE_TEST(task_promise, task_future_integer_no_resume) {
283  size_t old_resume_generator_count = g_task_future_resume_generator_count;
284  size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
285 
286  task_future_int_type t = task_func_no_wait_int();
287  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kCreated), static_cast<int>(t.get_status()));
288  CASE_EXPECT_FALSE(t.is_canceled());
289  CASE_EXPECT_FALSE(t.is_faulted());
290  CASE_EXPECT_FALSE(t.is_timeout());
291  CASE_EXPECT_FALSE(t.is_exiting());
292  CASE_EXPECT_FALSE(t.is_completed());
293 
294  CASE_EXPECT_TRUE(t.start());
295  CASE_EXPECT_EQ(121000, t.get_private_data()->data);
296  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kDone), static_cast<int>(t.get_status()));
297  CASE_EXPECT_FALSE(t.is_canceled());
298  CASE_EXPECT_FALSE(t.is_faulted());
299  CASE_EXPECT_FALSE(t.is_timeout());
300  CASE_EXPECT_TRUE(t.is_exiting());
301  CASE_EXPECT_TRUE(t.is_completed());
302  CASE_EXPECT_EQ(26, *t.get_context()->data());
303 
304  CASE_EXPECT_EQ(old_resume_generator_count, g_task_future_resume_generator_count);
305  CASE_EXPECT_EQ(old_suspend_generator_count, g_task_future_suspend_generator_count);
306 }
307 
308 CASE_TEST(task_promise, task_future_void_no_resume) {
309  size_t old_resume_generator_count = g_task_future_resume_generator_count;
310  size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
311 
312  task_future_void_type t = task_func_no_wait_void();
313  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kCreated), static_cast<int>(t.get_status()));
314  CASE_EXPECT_FALSE(t.is_canceled());
315  CASE_EXPECT_FALSE(t.is_faulted());
316  CASE_EXPECT_FALSE(t.is_timeout());
317  CASE_EXPECT_FALSE(t.is_exiting());
318  CASE_EXPECT_FALSE(t.is_completed());
319 
320  CASE_EXPECT_TRUE(t.start());
321  CASE_EXPECT_EQ(123000, t.get_private_data()->data);
322  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kDone), static_cast<int>(t.get_status()));
323  CASE_EXPECT_FALSE(t.is_canceled());
324  CASE_EXPECT_FALSE(t.is_faulted());
325  CASE_EXPECT_FALSE(t.is_timeout());
326  CASE_EXPECT_TRUE(t.is_exiting());
327  CASE_EXPECT_TRUE(t.is_completed());
328 
329  CASE_EXPECT_EQ(old_resume_generator_count, g_task_future_resume_generator_count);
330  CASE_EXPECT_EQ(old_suspend_generator_count, g_task_future_suspend_generator_count);
331 }
332 
333 namespace {
334 static task_future_int_type task_func_await_int_generator() {
335  generator_future_int_type generator{generator_int_suspend_callback, generator_int_resume_callback};
336  auto res = co_await generator;
337  co_return 235 + res;
338 }
339 
340 static callable_future_int_type task_future_func_await_int_task() {
341  task_future_int_type t = task_func_await_int_generator();
342  t.start();
343  auto res = co_await t;
344  co_return res;
345 }
346 
347 static task_future_int_type task_func_await_int_task() {
348  task_future_int_type t = task_func_await_int_generator();
349  t.start();
350  auto res = co_await t;
351  co_return res;
352 }
353 } // namespace
354 
355 CASE_TEST(task_promise, callable_future_await_task) {
356  size_t old_resume_generator_count = g_task_future_resume_generator_count;
357  size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
358 
359  callable_future_int_type f = task_future_func_await_int_task();
360  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kRunning), static_cast<int>(f.get_status()));
361 
362  CASE_EXPECT_FALSE(f.is_ready());
363 
364  resume_pending_contexts({1000});
365  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kDone), static_cast<int>(f.get_status()));
366  CASE_EXPECT_TRUE(f.is_ready());
367  CASE_EXPECT_EQ(1235, f.get_internal_promise().data());
368 
369  CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
370  CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
371 }
372 
373 CASE_TEST(task_promise, task_future_await_task) {
374  size_t old_resume_generator_count = g_task_future_resume_generator_count;
375  size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
376 
377  task_future_int_type t = task_func_await_int_task();
378  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kCreated), static_cast<int>(t.get_status()));
379  CASE_EXPECT_FALSE(t.is_canceled());
380  CASE_EXPECT_FALSE(t.is_faulted());
381  CASE_EXPECT_FALSE(t.is_timeout());
382  CASE_EXPECT_FALSE(t.is_exiting());
383  CASE_EXPECT_FALSE(t.is_completed());
384 
385  CASE_EXPECT_TRUE(t.start());
386  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kRunning), static_cast<int>(t.get_status()));
387  CASE_EXPECT_FALSE(t.is_canceled());
388  CASE_EXPECT_FALSE(t.is_faulted());
389  CASE_EXPECT_FALSE(t.is_timeout());
390  CASE_EXPECT_FALSE(t.is_exiting());
391  CASE_EXPECT_FALSE(t.is_completed());
392 
393  resume_pending_contexts({2000});
394  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kDone), static_cast<int>(t.get_status()));
395  CASE_EXPECT_FALSE(t.is_canceled());
396  CASE_EXPECT_FALSE(t.is_faulted());
397  CASE_EXPECT_FALSE(t.is_timeout());
398  CASE_EXPECT_TRUE(t.is_exiting());
399  CASE_EXPECT_TRUE(t.is_completed());
400  CASE_EXPECT_EQ(2235, *t.get_context()->data());
401 
402  CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
403  CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
404 }
405 
406 namespace {
407 static callable_future_int_type task_func_await_callable_and_be_killed() {
408  auto u = task_future_func_int_l2(13);
409  int x = co_await u;
410  co_return x;
411 }
412 
413 static task_future_int_type task_func_await_and_be_killed_by_caller() {
414  auto v = task_func_await_callable_and_be_killed();
415  int x = co_await v;
416  co_return x;
417 }
418 
419 std::shared_ptr<task_future_int_type> g_task_promise_killed_by_callee;
420 static task_future_int_type task_func_await_and_be_killed_by_callee(task_future_int_type::task_status_type status) {
421  g_task_promise_killed_by_callee->kill(status);
422  auto v = task_func_await_callable_and_be_killed();
423  int x = co_await v;
424  co_return x;
425 }
426 
427 } // namespace
428 
429 // kill
430 CASE_TEST(task_promise, killed_by_caller) {
431  size_t old_resume_generator_count = g_task_future_resume_generator_count;
432  size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
433 
434  task_future_int_type t = task_func_await_and_be_killed_by_caller();
435  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kCreated), static_cast<int>(t.get_status()));
436  CASE_EXPECT_FALSE(t.is_canceled());
437  CASE_EXPECT_FALSE(t.is_faulted());
438  CASE_EXPECT_FALSE(t.is_timeout());
439  CASE_EXPECT_FALSE(t.is_exiting());
440  CASE_EXPECT_FALSE(t.is_completed());
441 
442  CASE_EXPECT_TRUE(t.start());
443  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kRunning), static_cast<int>(t.get_status()));
444  CASE_EXPECT_FALSE(t.is_canceled());
445  CASE_EXPECT_FALSE(t.is_faulted());
446  CASE_EXPECT_FALSE(t.is_timeout());
447  CASE_EXPECT_FALSE(t.is_exiting());
448  CASE_EXPECT_FALSE(t.is_completed());
449 
450  CASE_EXPECT_TRUE(t.kill(task_future_int_type::task_status_type::kKilled));
451  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kKilled), static_cast<int>(t.get_status()));
452  CASE_EXPECT_FALSE(t.is_canceled());
453  CASE_EXPECT_TRUE(t.is_faulted());
454  CASE_EXPECT_FALSE(t.is_timeout());
455  CASE_EXPECT_TRUE(t.is_exiting());
456  CASE_EXPECT_TRUE(t.is_completed());
457  CASE_EXPECT_EQ(-static_cast<int>(copp::promise_status::kKilled), *t.get_context()->data());
458 
459  CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
460  CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
461 
462  resume_pending_contexts({100});
463  CASE_EXPECT_EQ(-static_cast<int>(copp::promise_status::kKilled), *t.get_context()->data());
464  CASE_EXPECT_FALSE(t.is_canceled());
465  CASE_EXPECT_TRUE(t.is_faulted());
466  CASE_EXPECT_FALSE(t.is_timeout());
467  CASE_EXPECT_TRUE(t.is_exiting());
468  CASE_EXPECT_TRUE(t.is_completed());
469 
470  CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
471  CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
472 }
473 
474 CASE_TEST(task_promise, killed_by_callee) {
475  size_t old_resume_generator_count = g_task_future_resume_generator_count;
476  size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
477 
478  task_future_int_type t = task_func_await_and_be_killed_by_callee(copp::promise_status::kKilled);
479  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kCreated), static_cast<int>(t.get_status()));
480  CASE_EXPECT_FALSE(t.is_canceled());
481  CASE_EXPECT_FALSE(t.is_faulted());
482  CASE_EXPECT_FALSE(t.is_timeout());
483  CASE_EXPECT_FALSE(t.is_exiting());
484  CASE_EXPECT_FALSE(t.is_completed());
485 
486  g_task_promise_killed_by_callee = std::make_shared<task_future_int_type>(t);
487  CASE_EXPECT_TRUE(t.start());
488  g_task_promise_killed_by_callee.reset();
489 
490  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kKilled), static_cast<int>(t.get_status()));
491  CASE_EXPECT_FALSE(t.is_canceled());
492  CASE_EXPECT_TRUE(t.is_faulted());
493  CASE_EXPECT_FALSE(t.is_timeout());
494  CASE_EXPECT_TRUE(t.is_exiting());
495  CASE_EXPECT_TRUE(t.is_completed());
496  CASE_EXPECT_EQ(-static_cast<int>(copp::promise_status::kKilled), *t.get_context()->data());
497 
498  CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
499  CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
500 
501  resume_pending_contexts({100});
502  CASE_EXPECT_EQ(-static_cast<int>(copp::promise_status::kKilled), *t.get_context()->data());
503  CASE_EXPECT_FALSE(t.is_canceled());
504  CASE_EXPECT_TRUE(t.is_faulted());
505  CASE_EXPECT_FALSE(t.is_timeout());
506  CASE_EXPECT_TRUE(t.is_exiting());
507  CASE_EXPECT_TRUE(t.is_completed());
508 
509  CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
510  CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
511 }
512 
513 // Cancel
514 CASE_TEST(task_promise, cancel_by_caller) {
515  size_t old_resume_generator_count = g_task_future_resume_generator_count;
516  size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
517 
518  task_future_int_type t = task_func_await_and_be_killed_by_caller();
519  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kCreated), static_cast<int>(t.get_status()));
520  CASE_EXPECT_FALSE(t.is_canceled());
521  CASE_EXPECT_FALSE(t.is_faulted());
522  CASE_EXPECT_FALSE(t.is_timeout());
523  CASE_EXPECT_FALSE(t.is_exiting());
524  CASE_EXPECT_FALSE(t.is_completed());
525 
526  CASE_EXPECT_TRUE(t.start());
527  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kRunning), static_cast<int>(t.get_status()));
528  CASE_EXPECT_FALSE(t.is_canceled());
529  CASE_EXPECT_FALSE(t.is_faulted());
530  CASE_EXPECT_FALSE(t.is_timeout());
531  CASE_EXPECT_FALSE(t.is_exiting());
532  CASE_EXPECT_FALSE(t.is_completed());
533 
534  CASE_EXPECT_TRUE(t.kill(task_future_int_type::task_status_type::kCancle));
535  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kCancle), static_cast<int>(t.get_status()));
536  CASE_EXPECT_TRUE(t.is_canceled());
537  CASE_EXPECT_FALSE(t.is_faulted());
538  CASE_EXPECT_FALSE(t.is_timeout());
539  CASE_EXPECT_TRUE(t.is_exiting());
540  CASE_EXPECT_TRUE(t.is_completed());
541  CASE_EXPECT_EQ(-static_cast<int>(copp::promise_status::kCancle), *t.get_context()->data());
542 
543  CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
544  CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
545 
546  resume_pending_contexts({100});
547  CASE_EXPECT_EQ(-static_cast<int>(copp::promise_status::kCancle), *t.get_context()->data());
548  CASE_EXPECT_TRUE(t.is_canceled());
549  CASE_EXPECT_FALSE(t.is_faulted());
550  CASE_EXPECT_FALSE(t.is_timeout());
551  CASE_EXPECT_TRUE(t.is_exiting());
552  CASE_EXPECT_TRUE(t.is_completed());
553 
554  CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
555  CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
556 }
557 
558 // Timeout
559 CASE_TEST(task_promise, timeout_by_caller) {
560  size_t old_resume_generator_count = g_task_future_resume_generator_count;
561  size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
562 
563  task_future_int_type t = task_func_await_and_be_killed_by_caller();
564  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kCreated), static_cast<int>(t.get_status()));
565  CASE_EXPECT_FALSE(t.is_canceled());
566  CASE_EXPECT_FALSE(t.is_faulted());
567  CASE_EXPECT_FALSE(t.is_timeout());
568  CASE_EXPECT_FALSE(t.is_exiting());
569  CASE_EXPECT_FALSE(t.is_completed());
570 
571  CASE_EXPECT_TRUE(t.start());
572  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kRunning), static_cast<int>(t.get_status()));
573  CASE_EXPECT_FALSE(t.is_canceled());
574  CASE_EXPECT_FALSE(t.is_faulted());
575  CASE_EXPECT_FALSE(t.is_timeout());
576  CASE_EXPECT_FALSE(t.is_exiting());
577  CASE_EXPECT_FALSE(t.is_completed());
578 
579  CASE_EXPECT_TRUE(t.kill(task_future_int_type::task_status_type::kTimeout));
580  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kTimeout), static_cast<int>(t.get_status()));
581  CASE_EXPECT_FALSE(t.is_canceled());
582  CASE_EXPECT_TRUE(t.is_faulted());
583  CASE_EXPECT_TRUE(t.is_timeout());
584  CASE_EXPECT_TRUE(t.is_exiting());
585  CASE_EXPECT_TRUE(t.is_completed());
586  CASE_EXPECT_EQ(-static_cast<int>(copp::promise_status::kTimeout), *t.get_context()->data());
587 
588  CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
589  CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
590 
591  resume_pending_contexts({100});
592  CASE_EXPECT_EQ(-static_cast<int>(copp::promise_status::kTimeout), *t.get_context()->data());
593  CASE_EXPECT_FALSE(t.is_canceled());
594  CASE_EXPECT_TRUE(t.is_faulted());
595  CASE_EXPECT_TRUE(t.is_timeout());
596  CASE_EXPECT_TRUE(t.is_exiting());
597  CASE_EXPECT_TRUE(t.is_completed());
598 
599  CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
600  CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
601 }
602 
603 CASE_TEST(task_promise, timeout_by_callee) {
604  size_t old_resume_generator_count = g_task_future_resume_generator_count;
605  size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
606 
607  task_future_int_type t = task_func_await_and_be_killed_by_callee(copp::promise_status::kTimeout);
608  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kCreated), static_cast<int>(t.get_status()));
609  CASE_EXPECT_FALSE(t.is_canceled());
610  CASE_EXPECT_FALSE(t.is_faulted());
611  CASE_EXPECT_FALSE(t.is_timeout());
612  CASE_EXPECT_FALSE(t.is_exiting());
613  CASE_EXPECT_FALSE(t.is_completed());
614 
615  g_task_promise_killed_by_callee = std::make_shared<task_future_int_type>(t);
616  CASE_EXPECT_TRUE(t.start());
617  g_task_promise_killed_by_callee.reset();
618 
619  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kTimeout), static_cast<int>(t.get_status()));
620  CASE_EXPECT_FALSE(t.is_canceled());
621  CASE_EXPECT_TRUE(t.is_faulted());
622  CASE_EXPECT_TRUE(t.is_timeout());
623  CASE_EXPECT_TRUE(t.is_exiting());
624  CASE_EXPECT_TRUE(t.is_completed());
625  CASE_EXPECT_EQ(-static_cast<int>(copp::promise_status::kTimeout), *t.get_context()->data());
626 
627  CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
628  CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
629 
630  resume_pending_contexts({100});
631  CASE_EXPECT_EQ(-static_cast<int>(copp::promise_status::kTimeout), *t.get_context()->data());
632  CASE_EXPECT_FALSE(t.is_canceled());
633  CASE_EXPECT_TRUE(t.is_faulted());
634  CASE_EXPECT_TRUE(t.is_timeout());
635  CASE_EXPECT_TRUE(t.is_exiting());
636  CASE_EXPECT_TRUE(t.is_completed());
637 
638  CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
639  CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
640 }
641 
642 namespace {
643 static task_future_int_type task_func_await_child_task_child() {
644  auto u = task_future_func_int_l2(53);
645  int x = co_await u;
646  co_return x;
647 }
648 
649 static task_future_int_type task_func_await_child_task_parent(task_future_int_type &out) {
650  out = task_func_await_child_task_child();
651  int x = co_await out;
652  co_return x;
653 }
654 
655 static task_future_int_type task_func_await_empty() {
656  task_future_int_type empty;
657  int x = co_await empty;
658  CASE_EXPECT_EQ(-1, x);
659  co_return x;
660 }
661 } // namespace
662 
663 // kill parent task and the child task will not be effected
664 CASE_TEST(task_promise, kill_parent_only) {
665  size_t old_resume_generator_count = g_task_future_resume_generator_count;
666  size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
667 
668  task_future_int_type child;
669  task_future_int_type parent = task_func_await_child_task_parent(child);
670  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kCreated), static_cast<int>(parent.get_status()));
671  CASE_EXPECT_FALSE(parent.is_canceled());
672  CASE_EXPECT_FALSE(parent.is_faulted());
673  CASE_EXPECT_FALSE(parent.is_timeout());
674  CASE_EXPECT_FALSE(parent.is_exiting());
675  CASE_EXPECT_FALSE(parent.is_completed());
676 
677  CASE_EXPECT_TRUE(parent.start());
678  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kRunning), static_cast<int>(parent.get_status()));
679  CASE_EXPECT_FALSE(parent.is_canceled());
680  CASE_EXPECT_FALSE(parent.is_faulted());
681  CASE_EXPECT_FALSE(parent.is_timeout());
682  CASE_EXPECT_FALSE(parent.is_exiting());
683  CASE_EXPECT_FALSE(parent.is_completed());
684 
685  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kCreated), static_cast<int>(child.get_status()));
686  CASE_EXPECT_EQ(old_resume_generator_count, g_task_future_resume_generator_count);
687  CASE_EXPECT_EQ(old_suspend_generator_count, g_task_future_suspend_generator_count);
688  child.start();
689  CASE_EXPECT_EQ(old_resume_generator_count, g_task_future_resume_generator_count);
690  CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
691 
692  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kRunning), static_cast<int>(child.get_status()));
693  CASE_EXPECT_FALSE(child.is_canceled());
694  CASE_EXPECT_FALSE(child.is_faulted());
695  CASE_EXPECT_FALSE(child.is_timeout());
696  CASE_EXPECT_FALSE(child.is_exiting());
697  CASE_EXPECT_FALSE(child.is_completed());
698 
699  CASE_EXPECT_TRUE(parent.kill(task_future_int_type::task_status_type::kTimeout));
700  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kTimeout), static_cast<int>(parent.get_status()));
701  CASE_EXPECT_FALSE(parent.is_canceled());
702  CASE_EXPECT_TRUE(parent.is_faulted());
703  CASE_EXPECT_TRUE(parent.is_timeout());
704  CASE_EXPECT_TRUE(parent.is_exiting());
705  CASE_EXPECT_TRUE(parent.is_completed());
706  CASE_EXPECT_EQ(-static_cast<int>(copp::promise_status::kTimeout), *parent.get_context()->data());
707 
708  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kRunning), static_cast<int>(child.get_status()));
709  CASE_EXPECT_FALSE(child.is_canceled());
710  CASE_EXPECT_FALSE(child.is_faulted());
711  CASE_EXPECT_FALSE(child.is_timeout());
712  CASE_EXPECT_FALSE(child.is_exiting());
713  CASE_EXPECT_FALSE(child.is_completed());
714 
715  resume_pending_contexts({1000});
716  CASE_EXPECT_EQ(-static_cast<int>(copp::promise_status::kTimeout), *parent.get_context()->data());
717  CASE_EXPECT_FALSE(parent.is_canceled());
718  CASE_EXPECT_TRUE(parent.is_faulted());
719  CASE_EXPECT_TRUE(parent.is_timeout());
720  CASE_EXPECT_TRUE(parent.is_exiting());
721  CASE_EXPECT_TRUE(parent.is_completed());
722 
723  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kDone), static_cast<int>(child.get_status()));
724  CASE_EXPECT_FALSE(child.is_canceled());
725  CASE_EXPECT_FALSE(child.is_faulted());
726  CASE_EXPECT_FALSE(child.is_timeout());
727  CASE_EXPECT_TRUE(child.is_exiting());
728  CASE_EXPECT_TRUE(child.is_completed());
729  CASE_EXPECT_EQ(1053, *child.get_context()->data());
730 
731  CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
732  CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
733 }
734 
735 CASE_TEST(task_promise, empty_task) {
736  task_future_int_type t = task_func_await_empty();
737  t.start();
738 
739  task_future_int_type empty;
740  CASE_EXPECT_FALSE(empty.start());
741  CASE_EXPECT_FALSE(empty.kill(task_future_int_type::task_status_type::kKilled));
742 
743  CASE_EXPECT_EQ(static_cast<int>(copp::promise_status::kInvalid), static_cast<int>(empty.get_status()));
744  CASE_EXPECT_EQ(nullptr, empty.get_private_data());
745  CASE_EXPECT_EQ(0, empty.get_id());
746  CASE_EXPECT_EQ(0, empty.get_ref_future_count());
747  CASE_EXPECT_EQ(nullptr, empty.get_context().get());
748 }
749 
750 // task destroy and auto resume
751 CASE_TEST(task_promise, task_destroy_and_auto_resume) {
752  task_future_int_type parent;
753  {
754  task_future_int_type child;
755  parent = task_func_await_child_task_parent(child);
756  CASE_EXPECT_TRUE(parent.start());
757  child.start();
758 
759  CASE_EXPECT_EQ(1, parent.get_ref_future_count());
760  CASE_EXPECT_EQ(1, child.get_ref_future_count());
761 
762  CASE_EXPECT_TRUE(child.valid());
763  CASE_EXPECT_TRUE(child);
764 
765  task_future_int_type move_child_assign = std::move(child);
766  CASE_EXPECT_EQ(0, child.get_ref_future_count());
767  CASE_EXPECT_EQ(1, move_child_assign.get_ref_future_count());
768  CASE_EXPECT_FALSE(child.valid());
769  CASE_EXPECT_FALSE(child);
770  CASE_EXPECT_TRUE(move_child_assign.valid());
771  CASE_EXPECT_TRUE(move_child_assign);
772 
773  task_future_int_type move_child_ctor{std::move(move_child_assign)};
774  CASE_EXPECT_EQ(0, move_child_assign.get_ref_future_count());
775  CASE_EXPECT_EQ(1, move_child_ctor.get_ref_future_count());
776 
777  task_future_int_type copy_child_assign = move_child_ctor;
778  task_future_int_type copy_child_ctor{move_child_ctor};
779 
780  CASE_EXPECT_EQ(3, copy_child_ctor.get_ref_future_count());
781  CASE_EXPECT_EQ(3, copy_child_assign.get_ref_future_count());
782  CASE_EXPECT_EQ(3, move_child_ctor.get_ref_future_count());
783 
784  CASE_EXPECT_EQ(copy_child_assign.get_context(), copy_child_ctor.get_context());
785  CASE_EXPECT_EQ(copy_child_assign.get_context(), move_child_ctor.get_context());
786 
787  CASE_EXPECT_EQ(copy_child_assign.get_id(), copy_child_ctor.get_id());
788  CASE_EXPECT_EQ(copy_child_assign.get_id(), move_child_ctor.get_id());
789 
790  CASE_EXPECT_FALSE(parent.is_exiting());
791  CASE_EXPECT_FALSE(parent.is_completed());
792  }
793 
794  CASE_EXPECT_TRUE(parent.is_exiting());
795  CASE_EXPECT_TRUE(parent.is_completed());
796  CASE_EXPECT_EQ(-static_cast<int>(copp::promise_status::kKilled), *parent.get_context()->data());
797 
798  resume_pending_contexts({});
799 }
800 
801 namespace {
802 static task_future_int_type task_func_await_int_simple() {
803  auto u = task_future_func_int_l2(91);
804  int x = co_await u;
805  co_return x;
806 }
807 
808 static task_future_void_type task_func_await_void_simple() {
809  auto u = task_future_func_void_l2();
810  co_await u;
811  co_return;
812 }
813 
814 static callable_future_int_type task_func_callable_await_task_int_simple() {
815  auto u = task_func_await_int_simple();
816  // forget to start here
817  int x = co_await u;
818  co_return x;
819 }
820 
821 } // namespace
822 
823 CASE_TEST(task_promise, forget_to_start) {
824  // This should be safe here
825  { auto f = task_func_callable_await_task_int_simple(); }
826 
827  resume_pending_contexts({});
828 }
829 
830 CASE_TEST(task_promise, callable_then_12_1_task_return_int_and_thenable_return_normal_int) {
831  auto t = task_func_await_int_simple();
832  auto f = t.then([](task_future_int_type::context_pointer_type, task_future_int_type::value_type value) {
833  CASE_EXPECT_EQ(2091, value);
834  CASE_MSG_INFO() << "thenable return int" << std::endl;
835  return value;
836  });
837 
838  CASE_EXPECT_FALSE(f.is_ready());
839  t.start();
840  CASE_EXPECT_FALSE(f.is_ready());
841 
842  resume_pending_contexts({2000});
843  CASE_EXPECT_TRUE(f.is_ready());
844 
845  CASE_EXPECT_EQ(2091, f.get_internal_promise().data());
846 }
847 
848 CASE_TEST(task_promise, callable_then_12_2_task_return_int_and_thenable_return_normal_void) {
849  auto t = task_func_await_int_simple();
850  auto f = t.then([](const task_future_int_type::context_pointer_type &, task_future_int_type::value_type value) {
851  CASE_EXPECT_EQ(2091, value);
852  CASE_MSG_INFO() << "thenable return void" << std::endl;
853  });
854 
855  CASE_EXPECT_FALSE(f.is_ready());
856  t.start();
857  CASE_EXPECT_FALSE(f.is_ready());
858 
859  resume_pending_contexts({2000});
860  CASE_EXPECT_TRUE(f.is_ready());
861 }
862 
863 CASE_TEST(task_promise, callable_then_12_3_task_return_int_and_thenable_return_callable_int) {
864  auto t = task_func_await_int_simple();
865  auto f = t.then([](task_future_int_type::context_pointer_type &&,
866  task_future_int_type::value_type value) -> copp::callable_future<int> {
867  CASE_EXPECT_EQ(2091, value);
868  CASE_MSG_INFO() << "thenable return callable_future<int>" << std::endl;
869  co_return value;
870  });
871 
872  CASE_EXPECT_FALSE(f.is_ready());
873  t.start();
874  CASE_EXPECT_FALSE(f.is_ready());
875 
876  resume_pending_contexts({2000});
877  CASE_EXPECT_TRUE(f.is_ready());
878 
879  CASE_EXPECT_EQ(2091, f.get_internal_promise().data());
880 }
881 
882 CASE_TEST(task_promise, callable_then_12_4_task_return_int_and_thenable_return_callable_void) {
883  auto t = task_func_await_int_simple();
884  auto f = t.then([](const task_future_int_type::context_pointer_type &,
885  task_future_int_type::value_type value) -> copp::callable_future<void> {
886  CASE_EXPECT_EQ(2091, value);
887  CASE_MSG_INFO() << "thenable return callable_future<void>" << std::endl;
888  co_return;
889  });
890 
891  CASE_EXPECT_FALSE(f.is_ready());
892  t.start();
893  CASE_EXPECT_FALSE(f.is_ready());
894 
895  resume_pending_contexts({2000});
896  CASE_EXPECT_TRUE(f.is_ready());
897 }
898 
899 CASE_TEST(task_promise, callable_then_12_5_task_return_int_and_thenable_return_callable_int) {
900  auto t = task_func_await_int_simple();
901  auto f = t.then([](task_future_int_type::context_pointer_type,
902  task_future_int_type::value_type value) -> cotask::task_future<int, void> {
903  CASE_EXPECT_EQ(2091, value);
904  CASE_MSG_INFO() << "thenable return task_future<int>" << std::endl;
905  co_return value;
906  });
907 
908  CASE_EXPECT_FALSE(f.is_ready());
909  t.start();
910  CASE_EXPECT_FALSE(f.is_ready());
911 
912  resume_pending_contexts({2000});
913  CASE_EXPECT_TRUE(f.is_ready());
914 
915  CASE_EXPECT_EQ(2091, f.get_internal_promise().data());
916 }
917 
918 CASE_TEST(task_promise, callable_then_12_6_task_return_int_and_thenable_return_callable_void) {
919  auto t = task_func_await_int_simple();
920  auto f = t.then([](task_future_int_type::context_pointer_type &&,
921  task_future_int_type::value_type value) -> cotask::task_future<void, void> {
922  CASE_EXPECT_EQ(2091, value);
923  CASE_MSG_INFO() << "thenable return task_future<void>" << std::endl;
924  co_return;
925  });
926 
927  CASE_EXPECT_FALSE(f.is_ready());
928  t.start();
929  CASE_EXPECT_FALSE(f.is_ready());
930 
931  resume_pending_contexts({2000});
932  CASE_EXPECT_TRUE(f.is_ready());
933 }
934 
935 CASE_TEST(task_promise, callable_then_12_7_task_return_void_and_thenable_return_normal_int) {
936  auto t = task_func_await_void_simple();
937  auto f = t.then([](task_future_void_type::context_pointer_type) {
938  CASE_MSG_INFO() << "thenable return int" << std::endl;
939  return 2111;
940  });
941 
942  CASE_EXPECT_FALSE(f.is_ready());
943  t.start();
944  CASE_EXPECT_FALSE(f.is_ready());
945 
946  resume_pending_contexts({});
947  CASE_EXPECT_TRUE(f.is_ready());
948 
949  CASE_EXPECT_EQ(2111, f.get_internal_promise().data());
950 }
951 
952 CASE_TEST(task_promise, callable_then_12_8_task_return_void_and_thenable_return_normal_void) {
953  auto t = task_func_await_void_simple();
954  auto f = t.then([](const task_future_void_type::context_pointer_type &) {
955  CASE_MSG_INFO() << "thenable return void" << std::endl;
956  });
957 
958  CASE_EXPECT_FALSE(f.is_ready());
959  t.start();
960  CASE_EXPECT_FALSE(f.is_ready());
961 
962  resume_pending_contexts({});
963  CASE_EXPECT_TRUE(f.is_ready());
964 }
965 
966 CASE_TEST(task_promise, callable_then_12_9_task_return_void_and_thenable_return_callable_int) {
967  auto t = task_func_await_void_simple();
968  auto f = t.then([](task_future_void_type::context_pointer_type) -> copp::callable_future<int> {
969  CASE_MSG_INFO() << "thenable return callable_future<int>" << std::endl;
970  co_return 2111;
971  });
972 
973  CASE_EXPECT_FALSE(f.is_ready());
974  t.start();
975  CASE_EXPECT_FALSE(f.is_ready());
976 
977  resume_pending_contexts({});
978  CASE_EXPECT_TRUE(f.is_ready());
979 
980  CASE_EXPECT_EQ(2111, f.get_internal_promise().data());
981 }
982 
983 CASE_TEST(task_promise, callable_then_12_10_task_return_void_and_thenable_return_callable_void) {
984  auto t = task_func_await_void_simple();
985  auto f = t.then([](const task_future_void_type::context_pointer_type &) -> copp::callable_future<void> {
986  CASE_MSG_INFO() << "thenable return callable_future<void>" << std::endl;
987  co_return;
988  });
989 
990  CASE_EXPECT_FALSE(f.is_ready());
991  t.start();
992  CASE_EXPECT_FALSE(f.is_ready());
993 
994  resume_pending_contexts({});
995  CASE_EXPECT_TRUE(f.is_ready());
996 }
997 
998 CASE_TEST(task_promise, callable_then_12_11_task_return_void_and_thenable_return_callable_int) {
999  auto t = task_func_await_void_simple();
1000  auto f = t.then([](task_future_void_type::context_pointer_type) -> cotask::task_future<int, void> {
1001  CASE_MSG_INFO() << "thenable return task_future<int>" << std::endl;
1002  co_return 2111;
1003  });
1004 
1005  CASE_EXPECT_FALSE(f.is_ready());
1006  t.start();
1007  CASE_EXPECT_FALSE(f.is_ready());
1008 
1009  resume_pending_contexts({});
1010  CASE_EXPECT_TRUE(f.is_ready());
1011 
1012  CASE_EXPECT_EQ(2111, f.get_internal_promise().data());
1013 }
1014 
1015 CASE_TEST(task_promise, callable_then_12_12_task_return_void_and_thenable_return_callable_void) {
1016  auto t = task_func_await_void_simple();
1017  auto f = t.then([](const task_future_void_type::context_pointer_type &) -> cotask::task_future<void, void> {
1018  CASE_MSG_INFO() << "thenable return task_future<void>" << std::endl;
1019  co_return;
1020  });
1021 
1022  CASE_EXPECT_FALSE(f.is_ready());
1023  t.start();
1024  CASE_EXPECT_FALSE(f.is_ready());
1025 
1026  resume_pending_contexts({});
1027  CASE_EXPECT_TRUE(f.is_ready());
1028 }
1029 
1030 CASE_TEST(task_promise, then_kill_task) {
1031  auto t = task_func_await_int_simple();
1032  auto f = t.then([](task_future_int_type::context_pointer_type ctx, task_future_int_type::value_type value) {
1033  CASE_EXPECT_EQ(static_cast<int>(ctx->get_status()),
1034  static_cast<int>(task_future_int_type::task_status_type::kTimeout));
1035  CASE_EXPECT_EQ(-static_cast<int>(task_future_int_type::task_status_type::kTimeout), value);
1036  CASE_MSG_INFO() << "thenable of timeout task return int" << std::endl;
1037  return value;
1038  });
1039 
1040  CASE_EXPECT_FALSE(f.is_ready());
1041  t.start();
1042  CASE_EXPECT_FALSE(f.is_ready());
1043 
1044  t.kill(task_future_int_type::task_status_type::kTimeout);
1045  CASE_EXPECT_TRUE(f.is_ready());
1046 
1047  CASE_EXPECT_EQ(-static_cast<int>(task_future_int_type::task_status_type::kTimeout), f.get_internal_promise().data());
1048 
1049  resume_pending_contexts({});
1050 }
1051 
1052 CASE_TEST(task_promise, then_empty_task) {
1053  task_future_int_type t;
1054  auto f = t.then([](task_future_int_type::context_pointer_type ctx, task_future_int_type::value_type value) {
1055  CASE_EXPECT_TRUE(!ctx);
1056  CASE_EXPECT_EQ(-1, value);
1057  CASE_MSG_INFO() << "thenable of empty task return int" << std::endl;
1058  return value;
1059  });
1060 
1061  CASE_EXPECT_TRUE(f.is_ready());
1062 
1063  CASE_EXPECT_EQ(-1, f.get_internal_promise().data());
1064 
1065  resume_pending_contexts({});
1066 }
1067 
1068 CASE_TEST(task_promise, then_exiting_task) {
1069  auto t = task_func_await_int_simple();
1070  t.start();
1071 
1072  resume_pending_contexts({3000});
1073 
1074  auto f = t.then([](task_future_int_type::context_pointer_type ctx, task_future_int_type::value_type value) {
1075  CASE_EXPECT_EQ(static_cast<int>(ctx->get_status()),
1076  static_cast<int>(task_future_int_type::task_status_type::kDone));
1077  CASE_EXPECT_EQ(3091, value);
1078  CASE_MSG_INFO() << "thenable of exiting task return int" << std::endl;
1079  return value;
1080  });
1081 
1082  CASE_EXPECT_TRUE(f.is_ready());
1083 
1084  CASE_EXPECT_EQ(3091, f.get_internal_promise().data());
1085 }
1086 
1087 CASE_TEST(task_promise, task_then_12_1_task_return_int_and_thenable_return_normal_int) {
1088  auto t = task_func_await_int_simple();
1089  auto f = t.then(
1090  [](task_future_int_type::context_pointer_type, task_future_int_type::value_type value) {
1091  CASE_EXPECT_EQ(2091, value);
1092  CASE_MSG_INFO() << "first thenable return int" << std::endl;
1093  return value;
1094  },
1095  3000)
1096  .then(
1097  [](cotask::task_future<int, int>::context_pointer_type ctx, task_future_int_type::value_type value) {
1098  CASE_EXPECT_EQ(2091, value);
1099  CASE_MSG_INFO() << "second thenable return int" << std::endl;
1100  return value + ctx->get_private_data();
1101  },
1102  nullptr);
1103 
1104  CASE_EXPECT_FALSE(f.is_exiting());
1105  t.start();
1106  CASE_EXPECT_FALSE(f.is_exiting());
1107 
1108  resume_pending_contexts({2000});
1109  CASE_EXPECT_TRUE(f.is_exiting());
1110 
1111  CASE_EXPECT_EQ(5091, *f.get_context()->data());
1112 }
1113 
1114 CASE_TEST(task_promise, task_then_12_2_task_return_int_and_thenable_return_normal_void) {
1115  auto t = task_func_await_int_simple();
1116  auto f = t.then(
1117  [](const task_future_int_type::context_pointer_type &, task_future_int_type::value_type value) {
1118  CASE_EXPECT_EQ(2091, value);
1119  CASE_MSG_INFO() << "first thenable return void" << std::endl;
1120  },
1121  3000)
1122  .then(
1123  [](cotask::task_future<void, int>::context_pointer_type ctx) {
1124  CASE_EXPECT_EQ(3000, ctx->get_private_data());
1125  CASE_MSG_INFO() << "second thenable return void" << std::endl;
1126  },
1127  nullptr);
1128 
1129  CASE_EXPECT_FALSE(f.is_exiting());
1130  t.start();
1131  CASE_EXPECT_FALSE(f.is_exiting());
1132 
1133  resume_pending_contexts({2000});
1134  CASE_EXPECT_TRUE(f.is_exiting());
1135 }
1136 
1137 CASE_TEST(task_promise, task_then_12_3_task_return_int_and_thenable_return_callable_int) {
1138  auto t = task_func_await_int_simple();
1139  auto f = t.then(
1140  [](task_future_int_type::context_pointer_type &&,
1141  task_future_int_type::value_type value) -> copp::callable_future<int> {
1142  CASE_EXPECT_EQ(2091, value);
1143  CASE_MSG_INFO() << "first thenable return callable_future<int>" << std::endl;
1144  co_return value;
1145  },
1146  3000)
1147  .then(
1148  [](cotask::task_future<int, int>::context_pointer_type ctx, task_future_int_type::value_type value) {
1149  CASE_EXPECT_EQ(2091, value);
1150  CASE_MSG_INFO() << "second thenable return int" << std::endl;
1151  return value + ctx->get_private_data();
1152  },
1153  nullptr);
1154 
1155  CASE_EXPECT_FALSE(f.is_exiting());
1156  t.start();
1157  CASE_EXPECT_FALSE(f.is_exiting());
1158 
1159  resume_pending_contexts({2000});
1160  CASE_EXPECT_TRUE(f.is_exiting());
1161 
1162  CASE_EXPECT_EQ(5091, *f.get_context()->data());
1163 }
1164 
1165 CASE_TEST(task_promise, task_then_12_4_task_return_int_and_thenable_return_callable_void) {
1166  auto t = task_func_await_int_simple();
1167  auto f = t.then(
1168  [](const task_future_int_type::context_pointer_type &,
1169  task_future_int_type::value_type value) -> copp::callable_future<void> {
1170  CASE_EXPECT_EQ(2091, value);
1171  CASE_MSG_INFO() << "first thenable return callable_future<void>" << std::endl;
1172  co_return;
1173  },
1174  3000)
1175  .then(
1176  [](cotask::task_future<void, int>::context_pointer_type ctx) {
1177  CASE_EXPECT_EQ(3000, ctx->get_private_data());
1178  CASE_MSG_INFO() << "second thenable return void" << std::endl;
1179  },
1180  nullptr);
1181 
1182  CASE_EXPECT_FALSE(f.is_exiting());
1183  t.start();
1184  CASE_EXPECT_FALSE(f.is_exiting());
1185 
1186  resume_pending_contexts({2000});
1187  CASE_EXPECT_TRUE(f.is_exiting());
1188 }
1189 
1190 CASE_TEST(task_promise, task_then_12_5_task_return_int_and_thenable_return_callable_int) {
1191  auto t = task_func_await_int_simple();
1192  auto f = t.then(
1193  [](task_future_int_type::context_pointer_type,
1194  task_future_int_type::value_type value) -> cotask::task_future<int, void> {
1195  CASE_EXPECT_EQ(2091, value);
1196  CASE_MSG_INFO() << "first thenable return task_future<int>" << std::endl;
1197  co_return value;
1198  },
1199  3000)
1200  .then(
1201  [](cotask::task_future<int, int>::context_pointer_type ctx, task_future_int_type::value_type value) {
1202  CASE_EXPECT_EQ(2091, value);
1203  CASE_MSG_INFO() << "second thenable return int" << std::endl;
1204  return value + ctx->get_private_data();
1205  },
1206  nullptr);
1207 
1208  CASE_EXPECT_FALSE(f.is_exiting());
1209  t.start();
1210  CASE_EXPECT_FALSE(f.is_exiting());
1211 
1212  resume_pending_contexts({2000});
1213  CASE_EXPECT_TRUE(f.is_exiting());
1214 
1215  CASE_EXPECT_EQ(5091, *f.get_context()->data());
1216 }
1217 
1218 CASE_TEST(task_promise, task_then_12_6_task_return_int_and_thenable_return_callable_void) {
1219  auto t = task_func_await_int_simple();
1220  auto f = t.then(
1221  [](task_future_int_type::context_pointer_type &&,
1222  task_future_int_type::value_type value) -> cotask::task_future<void, void> {
1223  CASE_EXPECT_EQ(2091, value);
1224  CASE_MSG_INFO() << "first thenable return task_future<void>" << std::endl;
1225  co_return;
1226  },
1227  3000)
1228  .then(
1229  [](cotask::task_future<void, int>::context_pointer_type ctx) {
1230  CASE_EXPECT_EQ(3000, ctx->get_private_data());
1231  CASE_MSG_INFO() << "second thenable return void" << std::endl;
1232  },
1233  nullptr);
1234 
1235  CASE_EXPECT_FALSE(f.is_exiting());
1236  t.start();
1237  CASE_EXPECT_FALSE(f.is_exiting());
1238 
1239  resume_pending_contexts({2000});
1240  CASE_EXPECT_TRUE(f.is_exiting());
1241 }
1242 
1243 CASE_TEST(task_promise, task_then_12_7_task_return_void_and_thenable_return_normal_int) {
1244  auto t = task_func_await_void_simple();
1245  auto f = t.then(
1246  [](task_future_void_type::context_pointer_type) {
1247  CASE_MSG_INFO() << "first thenable return int" << std::endl;
1248  return 2111;
1249  },
1250  3000)
1251  .then(
1252  [](cotask::task_future<int, int>::context_pointer_type ctx, task_future_int_type::value_type value) {
1253  CASE_EXPECT_EQ(2111, value);
1254  CASE_MSG_INFO() << "second thenable return int" << std::endl;
1255  return value + ctx->get_private_data();
1256  },
1257  nullptr);
1258 
1259  CASE_EXPECT_FALSE(f.is_exiting());
1260  t.start();
1261  CASE_EXPECT_FALSE(f.is_exiting());
1262 
1263  resume_pending_contexts({});
1264  CASE_EXPECT_TRUE(f.is_exiting());
1265 
1266  CASE_EXPECT_EQ(5111, *f.get_context()->data());
1267 }
1268 
1269 CASE_TEST(task_promise, task_then_12_8_task_return_void_and_thenable_return_normal_void) {
1270  auto t = task_func_await_void_simple();
1271  auto f = t.then(
1272  [](const task_future_void_type::context_pointer_type &) {
1273  CASE_MSG_INFO() << "first thenable return void" << std::endl;
1274  },
1275  3000)
1276  .then(
1277  [](cotask::task_future<void, int>::context_pointer_type ctx) {
1278  CASE_EXPECT_EQ(3000, ctx->get_private_data());
1279  CASE_MSG_INFO() << "second thenable return void" << std::endl;
1280  },
1281  nullptr);
1282 
1283  CASE_EXPECT_FALSE(f.is_exiting());
1284  t.start();
1285  CASE_EXPECT_FALSE(f.is_exiting());
1286 
1287  resume_pending_contexts({});
1288  CASE_EXPECT_TRUE(f.is_exiting());
1289 }
1290 
1291 CASE_TEST(task_promise, task_then_12_9_task_return_void_and_thenable_return_callable_int) {
1292  auto t = task_func_await_void_simple();
1293  auto f = t.then(
1294  [](task_future_void_type::context_pointer_type) -> copp::callable_future<int> {
1295  CASE_MSG_INFO() << "first thenable return callable_future<int>" << std::endl;
1296  co_return 2111;
1297  },
1298  3000)
1299  .then(
1300  [](cotask::task_future<int, int>::context_pointer_type ctx, task_future_int_type::value_type value) {
1301  CASE_EXPECT_EQ(2111, value);
1302  CASE_MSG_INFO() << "second thenable return int" << std::endl;
1303  return value + ctx->get_private_data();
1304  },
1305  nullptr);
1306 
1307  CASE_EXPECT_FALSE(f.is_exiting());
1308  t.start();
1309  CASE_EXPECT_FALSE(f.is_exiting());
1310 
1311  resume_pending_contexts({});
1312  CASE_EXPECT_TRUE(f.is_exiting());
1313 
1314  CASE_EXPECT_EQ(5111, *f.get_context()->data());
1315 }
1316 
1317 CASE_TEST(task_promise, task_then_12_10_task_return_void_and_thenable_return_callable_void) {
1318  auto t = task_func_await_void_simple();
1319  auto f = t.then(
1320  [](const task_future_void_type::context_pointer_type &) -> copp::callable_future<void> {
1321  CASE_MSG_INFO() << "first thenable return callable_future<void>" << std::endl;
1322  co_return;
1323  },
1324  3000)
1325  .then(
1326  [](cotask::task_future<void, int>::context_pointer_type ctx) {
1327  CASE_EXPECT_EQ(3000, ctx->get_private_data());
1328  CASE_MSG_INFO() << "second thenable return void" << std::endl;
1329  },
1330  nullptr);
1331 
1332  CASE_EXPECT_FALSE(f.is_exiting());
1333  t.start();
1334  CASE_EXPECT_FALSE(f.is_exiting());
1335 
1336  resume_pending_contexts({});
1337  CASE_EXPECT_TRUE(f.is_exiting());
1338 }
1339 
1340 CASE_TEST(task_promise, task_then_12_11_task_return_void_and_thenable_return_callable_int) {
1341  auto t = task_func_await_void_simple();
1342  auto f = t.then(
1343  [](task_future_void_type::context_pointer_type) -> cotask::task_future<int, void> {
1344  CASE_MSG_INFO() << "first thenable return task_future<int>" << std::endl;
1345  co_return 2111;
1346  },
1347  3000)
1348  .then(
1349  [](cotask::task_future<int, int>::context_pointer_type ctx, task_future_int_type::value_type value) {
1350  CASE_EXPECT_EQ(2111, value);
1351  CASE_MSG_INFO() << "second thenable return int" << std::endl;
1352  return value + ctx->get_private_data();
1353  },
1354  nullptr);
1355 
1356  CASE_EXPECT_FALSE(f.is_exiting());
1357  t.start();
1358  CASE_EXPECT_FALSE(f.is_exiting());
1359 
1360  resume_pending_contexts({});
1361  CASE_EXPECT_TRUE(f.is_exiting());
1362 
1363  CASE_EXPECT_EQ(5111, *f.get_context()->data());
1364 }
1365 
1366 CASE_TEST(task_promise, task_then_12_12_task_return_void_and_thenable_return_callable_void) {
1367  auto t = task_func_await_void_simple();
1368  auto f = t.then(
1369  [](const task_future_void_type::context_pointer_type &) -> cotask::task_future<void, void> {
1370  CASE_MSG_INFO() << "first thenable return task_future<void>" << std::endl;
1371  co_return;
1372  },
1373  3000)
1374  .then(
1375  [](cotask::task_future<void, int>::context_pointer_type ctx) {
1376  CASE_EXPECT_EQ(3000, ctx->get_private_data());
1377  CASE_MSG_INFO() << "second thenable return void" << std::endl;
1378  },
1379  nullptr);
1380 
1381  CASE_EXPECT_FALSE(f.is_exiting());
1382  t.start();
1383  CASE_EXPECT_FALSE(f.is_exiting());
1384 
1385  resume_pending_contexts({});
1386  CASE_EXPECT_TRUE(f.is_exiting());
1387 }
1388 
1389 namespace {
1390 static cotask::task_future<int, void> task_func_some_any_all_callable_suspend() {
1391  auto suspend_callback = [](generator_future_int_type::context_pointer_type ctx) {
1392  ++g_task_future_suspend_generator_count;
1393  g_task_future_pending_int_contexts.push_back(ctx);
1394  };
1395  auto resume_callback = [](const generator_future_int_type::context_type &) {
1396  ++g_task_future_resume_generator_count;
1397  };
1398 
1399  auto value = co_await generator_future_int_type(suspend_callback, resume_callback);
1400  co_return value;
1401 }
1402 
1403 static copp::callable_future<int> task_future_func_some_callable_in_container(size_t expect_ready_count,
1404  copp::promise_status expect_status) {
1405  size_t old_resume_generator_count = g_task_future_resume_generator_count;
1406  size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
1407 
1408  size_t resume_ready_count = 0;
1409 
1410  std::vector<cotask::task_future<int, void>> tasks;
1411  tasks.emplace_back(task_func_some_any_all_callable_suspend());
1412  tasks.emplace_back(task_func_some_any_all_callable_suspend());
1413  tasks.emplace_back(task_func_some_any_all_callable_suspend());
1414  for (auto &task_object : tasks) {
1415  task_object.start();
1416  }
1417 
1418  copp::some_ready<cotask::task_future<int, void>>::type readys;
1419  auto some_result = co_await copp::some(readys, 2, tasks);
1420  CASE_EXPECT_EQ(static_cast<int>(expect_status), static_cast<int>(some_result));
1421 
1422  int result = 1;
1423  for (auto &ready_task : readys) {
1424  if (ready_task->is_exiting()) {
1425  result += *ready_task->get_context()->data();
1426  ++resume_ready_count;
1427  }
1428  }
1429 
1430  CASE_EXPECT_EQ(expect_ready_count, resume_ready_count);
1431 
1432  // Nothing happend here if we await the tasks again.
1433  some_result = co_await copp::some(readys, 2, tasks);
1434  CASE_EXPECT_EQ(static_cast<int>(expect_status), static_cast<int>(some_result));
1435 
1436  // If it's killed, await will trigger suspend and resume again, or it will return directly.
1437  CASE_EXPECT_EQ(expect_ready_count, resume_ready_count);
1438 
1439  CASE_EXPECT_EQ(old_resume_generator_count + expect_ready_count, g_task_future_resume_generator_count);
1440  CASE_EXPECT_EQ(old_suspend_generator_count + 3, g_task_future_suspend_generator_count);
1441  CASE_EXPECT_EQ(expect_ready_count, resume_ready_count);
1442 
1443  co_return result;
1444 }
1445 } // namespace
1446 
1447 CASE_TEST(task_promise, finish_some_in_container) {
1448  auto f = task_future_func_some_callable_in_container(2, copp::promise_status::kDone);
1449 
1450  CASE_EXPECT_FALSE(f.is_ready());
1451 
1452  // partly resume
1453  resume_pending_contexts({471}, 1);
1454  CASE_EXPECT_FALSE(f.is_ready());
1455  resume_pending_contexts({473}, 1);
1456 
1457  CASE_EXPECT_TRUE(f.is_ready());
1458  CASE_EXPECT_EQ(945, f.get_internal_promise().data());
1459 
1460  resume_pending_contexts({});
1461 }
1462 
1463 CASE_TEST(task_promise, kill_some_in_container) {
1464  auto f = task_future_func_some_callable_in_container(0, copp::promise_status::kKilled);
1465 
1466  CASE_EXPECT_FALSE(f.is_ready());
1467 
1468  // partly resume
1469  f.kill();
1470 
1471  CASE_EXPECT_TRUE(f.is_ready());
1472  CASE_EXPECT_EQ(1, f.get_internal_promise().data());
1473 
1474  resume_pending_contexts({});
1475 }
1476 
1477 static copp::callable_future<int> task_future_func_some_callable_in_initialize_list(
1478  size_t expect_ready_count, copp::promise_status expect_status) {
1479  size_t old_resume_generator_count = g_task_future_resume_generator_count;
1480  size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
1481 
1482  size_t resume_ready_count = 0;
1483 
1484  cotask::task_future<int, void> task1 = task_func_some_any_all_callable_suspend();
1485  cotask::task_future<int, void> task2 = task_func_some_any_all_callable_suspend();
1486  cotask::task_future<int, void> task3 = task_func_some_any_all_callable_suspend();
1487  task1.start();
1488  task2.start();
1489  task3.start();
1490 
1491  copp::some_ready<cotask::task_future<int, void>>::type readys;
1492  std::reference_wrapper<cotask::task_future<int, void>> pending[] = {task1, task2, task3};
1493  auto some_result = co_await copp::some(readys, 2, pending);
1494  CASE_EXPECT_EQ(static_cast<int>(expect_status), static_cast<int>(some_result));
1495 
1496  int result = 1;
1497  for (auto &ready_task : readys) {
1498  if (ready_task->is_exiting()) {
1499  result += *ready_task->get_context()->data();
1500  ++resume_ready_count;
1501  }
1502  }
1503 
1504  CASE_EXPECT_EQ(old_resume_generator_count + expect_ready_count, g_task_future_resume_generator_count);
1505  CASE_EXPECT_EQ(old_suspend_generator_count + 3, g_task_future_suspend_generator_count);
1506  CASE_EXPECT_EQ(expect_ready_count, resume_ready_count);
1507 
1508  co_return result;
1509 }
1510 
1511 CASE_TEST(task_promise, finish_some_in_initialize_list) {
1512  auto f = task_future_func_some_callable_in_initialize_list(2, copp::promise_status::kDone);
1513 
1514  CASE_EXPECT_FALSE(f.is_ready());
1515 
1516  // partly resume
1517  resume_pending_contexts({471}, 1);
1518  CASE_EXPECT_FALSE(f.is_ready());
1519  resume_pending_contexts({473}, 1);
1520 
1521  CASE_EXPECT_TRUE(f.is_ready());
1522  CASE_EXPECT_EQ(945, f.get_internal_promise().data());
1523 
1524  resume_pending_contexts({});
1525 }
1526 
1527 namespace {
1528 static copp::callable_future<int> task_future_func_any_callable_in_container(size_t expect_ready_count,
1529  copp::promise_status expect_status) {
1530  size_t old_resume_generator_count = g_task_future_resume_generator_count;
1531  size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
1532 
1533  size_t resume_ready_count = 0;
1534 
1535  std::vector<cotask::task_future<int, void>> tasks;
1536  tasks.emplace_back(task_func_some_any_all_callable_suspend());
1537  tasks.emplace_back(task_func_some_any_all_callable_suspend());
1538  tasks.emplace_back(task_func_some_any_all_callable_suspend());
1539  for (auto &task_object : tasks) {
1540  task_object.start();
1541  }
1542 
1543  copp::any_ready<cotask::task_future<int, void>>::type readys;
1544  auto any_result = co_await copp::any(readys, tasks);
1545  CASE_EXPECT_EQ(static_cast<int>(expect_status), static_cast<int>(any_result));
1546 
1547  int result = 1;
1548  for (auto &ready_task : readys) {
1549  if (ready_task->is_exiting()) {
1550  result += *ready_task->get_context()->data();
1551  ++resume_ready_count;
1552  }
1553  }
1554 
1555  CASE_EXPECT_EQ(old_resume_generator_count + expect_ready_count, g_task_future_resume_generator_count);
1556  CASE_EXPECT_EQ(old_suspend_generator_count + 3, g_task_future_suspend_generator_count);
1557  CASE_EXPECT_EQ(expect_ready_count, resume_ready_count);
1558 
1559  // Nothing happend here if we await the tasks again.
1560  any_result = co_await copp::any(readys, tasks);
1561  CASE_EXPECT_EQ(static_cast<int>(expect_status), static_cast<int>(any_result));
1562 
1563  // If it's killed, await will trigger suspend and resume again, or it will return directly.
1564  CASE_EXPECT_EQ(expect_ready_count, resume_ready_count);
1565 
1566  CASE_EXPECT_EQ(old_resume_generator_count + expect_ready_count, g_task_future_resume_generator_count);
1567  CASE_EXPECT_EQ(old_suspend_generator_count + 3, g_task_future_suspend_generator_count);
1568  CASE_EXPECT_EQ(expect_ready_count, resume_ready_count);
1569 
1570  co_return result;
1571 }
1572 } // namespace
1573 
1574 CASE_TEST(task_promise, finish_any_in_container) {
1575  auto f = task_future_func_any_callable_in_container(1, copp::promise_status::kDone);
1576 
1577  CASE_EXPECT_FALSE(f.is_ready());
1578 
1579  // partly resume
1580  resume_pending_contexts({671}, 1);
1581 
1582  CASE_EXPECT_TRUE(f.is_ready());
1583  CASE_EXPECT_EQ(672, f.get_internal_promise().data());
1584 
1585  resume_pending_contexts({});
1586 }
1587 
1588 namespace {
1589 static copp::callable_future<int> task_future_func_all_callable_in_container(size_t expect_ready_count,
1590  copp::promise_status expect_status) {
1591  size_t old_resume_generator_count = g_task_future_resume_generator_count;
1592  size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
1593 
1594  size_t resume_ready_count = 0;
1595 
1596  std::vector<cotask::task_future<int, void>> tasks;
1597  tasks.emplace_back(task_func_some_any_all_callable_suspend());
1598  tasks.emplace_back(task_func_some_any_all_callable_suspend());
1599  tasks.emplace_back(task_func_some_any_all_callable_suspend());
1600  for (auto &task_object : tasks) {
1601  task_object.start();
1602  }
1603 
1604  copp::all_ready<cotask::task_future<int, void>>::type readys;
1605  auto all_result = co_await copp::all(readys, tasks);
1606  CASE_EXPECT_EQ(static_cast<int>(expect_status), static_cast<int>(all_result));
1607 
1608  int result = 1;
1609  for (auto &ready_task : readys) {
1610  if (ready_task->is_exiting()) {
1611  result += *ready_task->get_context()->data();
1612  ++resume_ready_count;
1613  }
1614  }
1615 
1616  CASE_EXPECT_EQ(old_resume_generator_count + 3, g_task_future_resume_generator_count);
1617  CASE_EXPECT_EQ(old_suspend_generator_count + 3, g_task_future_suspend_generator_count);
1618  CASE_EXPECT_EQ(expect_ready_count, resume_ready_count);
1619 
1620  // Nothing happend here if we await the tasks again.
1621  all_result = co_await copp::all(readys, tasks);
1622  CASE_EXPECT_EQ(static_cast<int>(expect_status), static_cast<int>(all_result));
1623 
1624  // If it's killed, await will trigger suspend and resume again, or it will return directly.
1625  CASE_EXPECT_EQ(expect_ready_count, resume_ready_count);
1626 
1627  CASE_EXPECT_EQ(old_resume_generator_count + expect_ready_count, g_task_future_resume_generator_count);
1628  CASE_EXPECT_EQ(old_suspend_generator_count + 3, g_task_future_suspend_generator_count);
1629  CASE_EXPECT_EQ(expect_ready_count, resume_ready_count);
1630 
1631  co_return result;
1632 }
1633 } // namespace
1634 
1635 CASE_TEST(task_promise, finish_all_in_container) {
1636  auto f = task_future_func_all_callable_in_container(3, copp::promise_status::kDone);
1637 
1638  CASE_EXPECT_FALSE(f.is_ready());
1639 
1640  // partly resume
1641  resume_pending_contexts({671}, 1);
1642  CASE_EXPECT_FALSE(f.is_ready());
1643 
1644  resume_pending_contexts({791, 793}, 2);
1645 
1646  CASE_EXPECT_TRUE(f.is_ready());
1647  CASE_EXPECT_EQ(2256, f.get_internal_promise().data());
1648 
1649  resume_pending_contexts({});
1650 }
1651 
1652 #else
1653 CASE_TEST(task_promise, disabled) {}
1654 #endif
constexpr auto data(TCONTAINER &&container) -> decltype(container.data())
Definition: span.h:54
std::shared_ptr< cli::cmd_option_value > value_type
Definition: cmd_option.h:50
CASE_TEST(task_promise, disabled)
#define CASE_MSG_INFO()
Definition: test_macros.h:114
#define CASE_EXPECT_FALSE(c)
Definition: test_macros.h:95
#define CASE_EXPECT_EQ(l, r)
Definition: test_macros.h:96
#define CASE_EXPECT_NE(l, r)
Definition: test_macros.h:97
#define CASE_EXPECT_TRUE(c)
Definition: test_macros.h:94