libcopp 2.3.1
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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
18namespace {
19struct task_future_private_data {
20 int data;
21};
22
23using task_future_int_type = cotask::task_future<int, task_future_private_data>;
24using task_future_void_type = cotask::task_future<void, task_future_private_data>;
25using task_future_int_type_no_private_data = cotask::task_future<int, void>;
26using task_future_void_type_no_private_data = cotask::task_future<void, void>;
27using callable_future_int_type = copp::callable_future<int>;
28using callable_future_void_type = copp::callable_future<void>;
29using generator_future_int_type = copp::generator_future<int>;
30using generator_future_void_type = copp::generator_future<void>;
31
32std::list<generator_future_int_type::context_pointer_type> g_task_future_pending_int_contexts;
33std::list<generator_future_void_type::context_pointer_type> g_task_future_pending_void_contexts;
34size_t g_task_future_resume_generator_count = 0;
35size_t g_task_future_suspend_generator_count = 0;
36
37static 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
69static 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}
73static void generator_int_resume_callback(const generator_future_int_type::context_type &) {
74 ++g_task_future_resume_generator_count;
75}
76
77static 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
82static 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
91static 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
98static 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
111static 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
118static 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
131static 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}
135static void generator_void_resume_callback(const generator_future_void_type::context_type &) {
136 ++g_task_future_resume_generator_count;
137}
138
139static 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
144static 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
150static 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
158static 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
171static 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
179static 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
192static 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
201CASE_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());
213}
214
215CASE_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
249CASE_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
282CASE_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
308CASE_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
333namespace {
334static 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
340static 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
347static 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
355CASE_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
373CASE_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
406namespace {
407static 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
413static 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
419std::shared_ptr<task_future_int_type> g_task_promise_killed_by_callee;
420static 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
430CASE_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
474CASE_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
514CASE_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
559CASE_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
603CASE_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
642namespace {
643static 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
649static 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
655static 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
664CASE_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
735CASE_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
751CASE_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
801namespace {
802static 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
808static 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
814static 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
823CASE_TEST(task_promise, forget_to_start) {
824 // This should be safe here
825 {
826 auto f = task_func_callable_await_task_int_simple();
827 }
828
829 resume_pending_contexts({});
830}
831
832CASE_TEST(task_promise, callable_then_12_1_task_return_int_and_thenable_return_normal_int) {
833 auto t = task_func_await_int_simple();
834 auto f = t.then([](task_future_int_type::context_pointer_type, task_future_int_type::value_type value) {
835 CASE_EXPECT_EQ(2091, value);
836 CASE_MSG_INFO() << "thenable return int" << std::endl;
837 return value;
838 });
839
840 CASE_EXPECT_FALSE(f.is_ready());
841 t.start();
842 CASE_EXPECT_FALSE(f.is_ready());
843
844 resume_pending_contexts({2000});
845 CASE_EXPECT_TRUE(f.is_ready());
846
847 CASE_EXPECT_EQ(2091, f.get_internal_promise().data());
848}
849
850CASE_TEST(task_promise, callable_then_12_2_task_return_int_and_thenable_return_normal_void) {
851 auto t = task_func_await_int_simple();
852 auto f = t.then([](const task_future_int_type::context_pointer_type &, task_future_int_type::value_type value) {
853 CASE_EXPECT_EQ(2091, value);
854 CASE_MSG_INFO() << "thenable return void" << std::endl;
855 });
856
857 CASE_EXPECT_FALSE(f.is_ready());
858 t.start();
859 CASE_EXPECT_FALSE(f.is_ready());
860
861 resume_pending_contexts({2000});
862 CASE_EXPECT_TRUE(f.is_ready());
863}
864
865CASE_TEST(task_promise, callable_then_12_3_task_return_int_and_thenable_return_callable_int) {
866 auto t = task_func_await_int_simple();
867 auto f = t.then([](task_future_int_type::context_pointer_type &&,
868 task_future_int_type::value_type value) -> copp::callable_future<int> {
869 CASE_EXPECT_EQ(2091, value);
870 CASE_MSG_INFO() << "thenable return callable_future<int>" << std::endl;
871 co_return value;
872 });
873
874 CASE_EXPECT_FALSE(f.is_ready());
875 t.start();
876 CASE_EXPECT_FALSE(f.is_ready());
877
878 resume_pending_contexts({2000});
879 CASE_EXPECT_TRUE(f.is_ready());
880
881 CASE_EXPECT_EQ(2091, f.get_internal_promise().data());
882}
883
884CASE_TEST(task_promise, callable_then_12_4_task_return_int_and_thenable_return_callable_void) {
885 auto t = task_func_await_int_simple();
886 auto f = t.then([](const task_future_int_type::context_pointer_type &,
887 task_future_int_type::value_type value) -> copp::callable_future<void> {
888 CASE_EXPECT_EQ(2091, value);
889 CASE_MSG_INFO() << "thenable return callable_future<void>" << std::endl;
890 co_return;
891 });
892
893 CASE_EXPECT_FALSE(f.is_ready());
894 t.start();
895 CASE_EXPECT_FALSE(f.is_ready());
896
897 resume_pending_contexts({2000});
898 CASE_EXPECT_TRUE(f.is_ready());
899}
900
901CASE_TEST(task_promise, callable_then_12_5_task_return_int_and_thenable_return_callable_int) {
902 auto t = task_func_await_int_simple();
903 auto f = t.then([](task_future_int_type::context_pointer_type,
904 task_future_int_type::value_type value) -> cotask::task_future<int, void> {
905 CASE_EXPECT_EQ(2091, value);
906 CASE_MSG_INFO() << "thenable return task_future<int>" << std::endl;
907 co_return value;
908 });
909
910 CASE_EXPECT_FALSE(f.is_ready());
911 t.start();
912 CASE_EXPECT_FALSE(f.is_ready());
913
914 resume_pending_contexts({2000});
915 CASE_EXPECT_TRUE(f.is_ready());
916
917 CASE_EXPECT_EQ(2091, f.get_internal_promise().data());
918}
919
920CASE_TEST(task_promise, callable_then_12_6_task_return_int_and_thenable_return_callable_void) {
921 auto t = task_func_await_int_simple();
922 auto f = t.then([](task_future_int_type::context_pointer_type &&,
923 task_future_int_type::value_type value) -> cotask::task_future<void, void> {
924 CASE_EXPECT_EQ(2091, value);
925 CASE_MSG_INFO() << "thenable return task_future<void>" << std::endl;
926 co_return;
927 });
928
929 CASE_EXPECT_FALSE(f.is_ready());
930 t.start();
931 CASE_EXPECT_FALSE(f.is_ready());
932
933 resume_pending_contexts({2000});
934 CASE_EXPECT_TRUE(f.is_ready());
935}
936
937CASE_TEST(task_promise, callable_then_12_7_task_return_void_and_thenable_return_normal_int) {
938 auto t = task_func_await_void_simple();
939 auto f = t.then([](task_future_void_type::context_pointer_type) {
940 CASE_MSG_INFO() << "thenable return int" << std::endl;
941 return 2111;
942 });
943
944 CASE_EXPECT_FALSE(f.is_ready());
945 t.start();
946 CASE_EXPECT_FALSE(f.is_ready());
947
948 resume_pending_contexts({});
949 CASE_EXPECT_TRUE(f.is_ready());
950
951 CASE_EXPECT_EQ(2111, f.get_internal_promise().data());
952}
953
954CASE_TEST(task_promise, callable_then_12_8_task_return_void_and_thenable_return_normal_void) {
955 auto t = task_func_await_void_simple();
956 auto f = t.then([](const task_future_void_type::context_pointer_type &) {
957 CASE_MSG_INFO() << "thenable return void" << std::endl;
958 });
959
960 CASE_EXPECT_FALSE(f.is_ready());
961 t.start();
962 CASE_EXPECT_FALSE(f.is_ready());
963
964 resume_pending_contexts({});
965 CASE_EXPECT_TRUE(f.is_ready());
966}
967
968CASE_TEST(task_promise, callable_then_12_9_task_return_void_and_thenable_return_callable_int) {
969 auto t = task_func_await_void_simple();
970 auto f = t.then([](task_future_void_type::context_pointer_type) -> copp::callable_future<int> {
971 CASE_MSG_INFO() << "thenable return callable_future<int>" << std::endl;
972 co_return 2111;
973 });
974
975 CASE_EXPECT_FALSE(f.is_ready());
976 t.start();
977 CASE_EXPECT_FALSE(f.is_ready());
978
979 resume_pending_contexts({});
980 CASE_EXPECT_TRUE(f.is_ready());
981
982 CASE_EXPECT_EQ(2111, f.get_internal_promise().data());
983}
984
985CASE_TEST(task_promise, callable_then_12_10_task_return_void_and_thenable_return_callable_void) {
986 auto t = task_func_await_void_simple();
987 auto f = t.then([](const task_future_void_type::context_pointer_type &) -> copp::callable_future<void> {
988 CASE_MSG_INFO() << "thenable return callable_future<void>" << std::endl;
989 co_return;
990 });
991
992 CASE_EXPECT_FALSE(f.is_ready());
993 t.start();
994 CASE_EXPECT_FALSE(f.is_ready());
995
996 resume_pending_contexts({});
997 CASE_EXPECT_TRUE(f.is_ready());
998}
999
1000CASE_TEST(task_promise, callable_then_12_11_task_return_void_and_thenable_return_callable_int) {
1001 auto t = task_func_await_void_simple();
1002 auto f = t.then([](task_future_void_type::context_pointer_type) -> cotask::task_future<int, void> {
1003 CASE_MSG_INFO() << "thenable return task_future<int>" << std::endl;
1004 co_return 2111;
1005 });
1006
1007 CASE_EXPECT_FALSE(f.is_ready());
1008 t.start();
1009 CASE_EXPECT_FALSE(f.is_ready());
1010
1011 resume_pending_contexts({});
1012 CASE_EXPECT_TRUE(f.is_ready());
1013
1014 CASE_EXPECT_EQ(2111, f.get_internal_promise().data());
1015}
1016
1017CASE_TEST(task_promise, callable_then_12_12_task_return_void_and_thenable_return_callable_void) {
1018 auto t = task_func_await_void_simple();
1019 auto f = t.then([](const task_future_void_type::context_pointer_type &) -> cotask::task_future<void, void> {
1020 CASE_MSG_INFO() << "thenable return task_future<void>" << std::endl;
1021 co_return;
1022 });
1023
1024 CASE_EXPECT_FALSE(f.is_ready());
1025 t.start();
1026 CASE_EXPECT_FALSE(f.is_ready());
1027
1028 resume_pending_contexts({});
1029 CASE_EXPECT_TRUE(f.is_ready());
1030}
1031
1032CASE_TEST(task_promise, then_kill_task) {
1033 auto t = task_func_await_int_simple();
1034 auto f = t.then([](task_future_int_type::context_pointer_type ctx, task_future_int_type::value_type value) {
1035 CASE_EXPECT_EQ(static_cast<int>(ctx->get_status()),
1036 static_cast<int>(task_future_int_type::task_status_type::kTimeout));
1037 CASE_EXPECT_EQ(-static_cast<int>(task_future_int_type::task_status_type::kTimeout), value);
1038 CASE_MSG_INFO() << "thenable of timeout task return int" << std::endl;
1039 return value;
1040 });
1041
1042 CASE_EXPECT_FALSE(f.is_ready());
1043 t.start();
1044 CASE_EXPECT_FALSE(f.is_ready());
1045
1046 t.kill(task_future_int_type::task_status_type::kTimeout);
1047 CASE_EXPECT_TRUE(f.is_ready());
1048
1049 CASE_EXPECT_EQ(-static_cast<int>(task_future_int_type::task_status_type::kTimeout), f.get_internal_promise().data());
1050
1051 resume_pending_contexts({});
1052}
1053
1054CASE_TEST(task_promise, then_empty_task) {
1055 task_future_int_type t;
1056 auto f = t.then([](task_future_int_type::context_pointer_type ctx, task_future_int_type::value_type value) {
1057 CASE_EXPECT_TRUE(!ctx);
1058 CASE_EXPECT_EQ(-1, value);
1059 CASE_MSG_INFO() << "thenable of empty task return int" << std::endl;
1060 return value;
1061 });
1062
1063 CASE_EXPECT_TRUE(f.is_ready());
1064
1065 CASE_EXPECT_EQ(-1, f.get_internal_promise().data());
1066
1067 resume_pending_contexts({});
1068}
1069
1070CASE_TEST(task_promise, then_exiting_task) {
1071 auto t = task_func_await_int_simple();
1072 t.start();
1073
1074 resume_pending_contexts({3000});
1075
1076 auto f = t.then([](task_future_int_type::context_pointer_type ctx, task_future_int_type::value_type value) {
1077 CASE_EXPECT_EQ(static_cast<int>(ctx->get_status()),
1078 static_cast<int>(task_future_int_type::task_status_type::kDone));
1079 CASE_EXPECT_EQ(3091, value);
1080 CASE_MSG_INFO() << "thenable of exiting task return int" << std::endl;
1081 return value;
1082 });
1083
1084 CASE_EXPECT_TRUE(f.is_ready());
1085
1086 CASE_EXPECT_EQ(3091, f.get_internal_promise().data());
1087}
1088
1089CASE_TEST(task_promise, task_then_12_1_task_return_int_and_thenable_return_normal_int) {
1090 auto t = task_func_await_int_simple();
1091 auto f = t.then(
1092 [](task_future_int_type::context_pointer_type, task_future_int_type::value_type value) {
1093 CASE_EXPECT_EQ(2091, value);
1094 CASE_MSG_INFO() << "first thenable return int" << std::endl;
1095 return value;
1096 },
1097 3000)
1098 .then(
1099 [](cotask::task_future<int, int>::context_pointer_type ctx, task_future_int_type::value_type value) {
1100 CASE_EXPECT_EQ(2091, value);
1101 CASE_MSG_INFO() << "second thenable return int" << std::endl;
1102 return value + ctx->get_private_data();
1103 },
1104 nullptr);
1105
1106 CASE_EXPECT_FALSE(f.is_exiting());
1107 t.start();
1108 CASE_EXPECT_FALSE(f.is_exiting());
1109
1110 resume_pending_contexts({2000});
1111 CASE_EXPECT_TRUE(f.is_exiting());
1112
1113 CASE_EXPECT_EQ(5091, *f.get_context()->data());
1114}
1115
1116CASE_TEST(task_promise, task_then_12_2_task_return_int_and_thenable_return_normal_void) {
1117 auto t = task_func_await_int_simple();
1118 auto f = t.then(
1119 [](const task_future_int_type::context_pointer_type &, task_future_int_type::value_type value) {
1120 CASE_EXPECT_EQ(2091, value);
1121 CASE_MSG_INFO() << "first thenable return void" << std::endl;
1122 },
1123 3000)
1124 .then(
1125 [](cotask::task_future<void, int>::context_pointer_type ctx) {
1126 CASE_EXPECT_EQ(3000, ctx->get_private_data());
1127 CASE_MSG_INFO() << "second thenable return void" << std::endl;
1128 },
1129 nullptr);
1130
1131 CASE_EXPECT_FALSE(f.is_exiting());
1132 t.start();
1133 CASE_EXPECT_FALSE(f.is_exiting());
1134
1135 resume_pending_contexts({2000});
1136 CASE_EXPECT_TRUE(f.is_exiting());
1137}
1138
1139CASE_TEST(task_promise, task_then_12_3_task_return_int_and_thenable_return_callable_int) {
1140 auto t = task_func_await_int_simple();
1141 auto f = t.then(
1142 [](task_future_int_type::context_pointer_type &&,
1143 task_future_int_type::value_type value) -> copp::callable_future<int> {
1144 CASE_EXPECT_EQ(2091, value);
1145 CASE_MSG_INFO() << "first thenable return callable_future<int>" << std::endl;
1146 co_return value;
1147 },
1148 3000)
1149 .then(
1150 [](cotask::task_future<int, int>::context_pointer_type ctx, task_future_int_type::value_type value) {
1151 CASE_EXPECT_EQ(2091, value);
1152 CASE_MSG_INFO() << "second thenable return int" << std::endl;
1153 return value + ctx->get_private_data();
1154 },
1155 nullptr);
1156
1157 CASE_EXPECT_FALSE(f.is_exiting());
1158 t.start();
1159 CASE_EXPECT_FALSE(f.is_exiting());
1160
1161 resume_pending_contexts({2000});
1162 CASE_EXPECT_TRUE(f.is_exiting());
1163
1164 CASE_EXPECT_EQ(5091, *f.get_context()->data());
1165}
1166
1167CASE_TEST(task_promise, task_then_12_4_task_return_int_and_thenable_return_callable_void) {
1168 auto t = task_func_await_int_simple();
1169 auto f = t.then(
1170 [](const task_future_int_type::context_pointer_type &,
1171 task_future_int_type::value_type value) -> copp::callable_future<void> {
1172 CASE_EXPECT_EQ(2091, value);
1173 CASE_MSG_INFO() << "first thenable return callable_future<void>" << std::endl;
1174 co_return;
1175 },
1176 3000)
1177 .then(
1178 [](cotask::task_future<void, int>::context_pointer_type ctx) {
1179 CASE_EXPECT_EQ(3000, ctx->get_private_data());
1180 CASE_MSG_INFO() << "second thenable return void" << std::endl;
1181 },
1182 nullptr);
1183
1184 CASE_EXPECT_FALSE(f.is_exiting());
1185 t.start();
1186 CASE_EXPECT_FALSE(f.is_exiting());
1187
1188 resume_pending_contexts({2000});
1189 CASE_EXPECT_TRUE(f.is_exiting());
1190}
1191
1192CASE_TEST(task_promise, task_then_12_5_task_return_int_and_thenable_return_callable_int) {
1193 auto t = task_func_await_int_simple();
1194 auto f = t.then(
1195 [](task_future_int_type::context_pointer_type,
1196 task_future_int_type::value_type value) -> cotask::task_future<int, void> {
1197 CASE_EXPECT_EQ(2091, value);
1198 CASE_MSG_INFO() << "first thenable return task_future<int>" << std::endl;
1199 co_return value;
1200 },
1201 3000)
1202 .then(
1203 [](cotask::task_future<int, int>::context_pointer_type ctx, task_future_int_type::value_type value) {
1204 CASE_EXPECT_EQ(2091, value);
1205 CASE_MSG_INFO() << "second thenable return int" << std::endl;
1206 return value + ctx->get_private_data();
1207 },
1208 nullptr);
1209
1210 CASE_EXPECT_FALSE(f.is_exiting());
1211 t.start();
1212 CASE_EXPECT_FALSE(f.is_exiting());
1213
1214 resume_pending_contexts({2000});
1215 CASE_EXPECT_TRUE(f.is_exiting());
1216
1217 CASE_EXPECT_EQ(5091, *f.get_context()->data());
1218}
1219
1220CASE_TEST(task_promise, task_then_12_6_task_return_int_and_thenable_return_callable_void) {
1221 auto t = task_func_await_int_simple();
1222 auto f = t.then(
1223 [](task_future_int_type::context_pointer_type &&,
1224 task_future_int_type::value_type value) -> cotask::task_future<void, void> {
1225 CASE_EXPECT_EQ(2091, value);
1226 CASE_MSG_INFO() << "first thenable return task_future<void>" << std::endl;
1227 co_return;
1228 },
1229 3000)
1230 .then(
1231 [](cotask::task_future<void, int>::context_pointer_type ctx) {
1232 CASE_EXPECT_EQ(3000, ctx->get_private_data());
1233 CASE_MSG_INFO() << "second thenable return void" << std::endl;
1234 },
1235 nullptr);
1236
1237 CASE_EXPECT_FALSE(f.is_exiting());
1238 t.start();
1239 CASE_EXPECT_FALSE(f.is_exiting());
1240
1241 resume_pending_contexts({2000});
1242 CASE_EXPECT_TRUE(f.is_exiting());
1243}
1244
1245CASE_TEST(task_promise, task_then_12_7_task_return_void_and_thenable_return_normal_int) {
1246 auto t = task_func_await_void_simple();
1247 auto f = t.then(
1248 [](task_future_void_type::context_pointer_type) {
1249 CASE_MSG_INFO() << "first thenable return int" << std::endl;
1250 return 2111;
1251 },
1252 3000)
1253 .then(
1254 [](cotask::task_future<int, int>::context_pointer_type ctx, task_future_int_type::value_type value) {
1255 CASE_EXPECT_EQ(2111, value);
1256 CASE_MSG_INFO() << "second thenable return int" << std::endl;
1257 return value + ctx->get_private_data();
1258 },
1259 nullptr);
1260
1261 CASE_EXPECT_FALSE(f.is_exiting());
1262 t.start();
1263 CASE_EXPECT_FALSE(f.is_exiting());
1264
1265 resume_pending_contexts({});
1266 CASE_EXPECT_TRUE(f.is_exiting());
1267
1268 CASE_EXPECT_EQ(5111, *f.get_context()->data());
1269}
1270
1271CASE_TEST(task_promise, task_then_12_8_task_return_void_and_thenable_return_normal_void) {
1272 auto t = task_func_await_void_simple();
1273 auto f = t.then(
1274 [](const task_future_void_type::context_pointer_type &) {
1275 CASE_MSG_INFO() << "first thenable return void" << std::endl;
1276 },
1277 3000)
1278 .then(
1279 [](cotask::task_future<void, int>::context_pointer_type ctx) {
1280 CASE_EXPECT_EQ(3000, ctx->get_private_data());
1281 CASE_MSG_INFO() << "second thenable return void" << std::endl;
1282 },
1283 nullptr);
1284
1285 CASE_EXPECT_FALSE(f.is_exiting());
1286 t.start();
1287 CASE_EXPECT_FALSE(f.is_exiting());
1288
1289 resume_pending_contexts({});
1290 CASE_EXPECT_TRUE(f.is_exiting());
1291}
1292
1293CASE_TEST(task_promise, task_then_12_9_task_return_void_and_thenable_return_callable_int) {
1294 auto t = task_func_await_void_simple();
1295 auto f = t.then(
1296 [](task_future_void_type::context_pointer_type) -> copp::callable_future<int> {
1297 CASE_MSG_INFO() << "first thenable return callable_future<int>" << std::endl;
1298 co_return 2111;
1299 },
1300 3000)
1301 .then(
1302 [](cotask::task_future<int, int>::context_pointer_type ctx, task_future_int_type::value_type value) {
1303 CASE_EXPECT_EQ(2111, value);
1304 CASE_MSG_INFO() << "second thenable return int" << std::endl;
1305 return value + ctx->get_private_data();
1306 },
1307 nullptr);
1308
1309 CASE_EXPECT_FALSE(f.is_exiting());
1310 t.start();
1311 CASE_EXPECT_FALSE(f.is_exiting());
1312
1313 resume_pending_contexts({});
1314 CASE_EXPECT_TRUE(f.is_exiting());
1315
1316 CASE_EXPECT_EQ(5111, *f.get_context()->data());
1317}
1318
1319CASE_TEST(task_promise, task_then_12_10_task_return_void_and_thenable_return_callable_void) {
1320 auto t = task_func_await_void_simple();
1321 auto f = t.then(
1322 [](const task_future_void_type::context_pointer_type &) -> copp::callable_future<void> {
1323 CASE_MSG_INFO() << "first thenable return callable_future<void>" << std::endl;
1324 co_return;
1325 },
1326 3000)
1327 .then(
1328 [](cotask::task_future<void, int>::context_pointer_type ctx) {
1329 CASE_EXPECT_EQ(3000, ctx->get_private_data());
1330 CASE_MSG_INFO() << "second thenable return void" << std::endl;
1331 },
1332 nullptr);
1333
1334 CASE_EXPECT_FALSE(f.is_exiting());
1335 t.start();
1336 CASE_EXPECT_FALSE(f.is_exiting());
1337
1338 resume_pending_contexts({});
1339 CASE_EXPECT_TRUE(f.is_exiting());
1340}
1341
1342CASE_TEST(task_promise, task_then_12_11_task_return_void_and_thenable_return_callable_int) {
1343 auto t = task_func_await_void_simple();
1344 auto f = t.then(
1345 [](task_future_void_type::context_pointer_type) -> cotask::task_future<int, void> {
1346 CASE_MSG_INFO() << "first thenable return task_future<int>" << std::endl;
1347 co_return 2111;
1348 },
1349 3000)
1350 .then(
1351 [](cotask::task_future<int, int>::context_pointer_type ctx, task_future_int_type::value_type value) {
1352 CASE_EXPECT_EQ(2111, value);
1353 CASE_MSG_INFO() << "second thenable return int" << std::endl;
1354 return value + ctx->get_private_data();
1355 },
1356 nullptr);
1357
1358 CASE_EXPECT_FALSE(f.is_exiting());
1359 t.start();
1360 CASE_EXPECT_FALSE(f.is_exiting());
1361
1362 resume_pending_contexts({});
1363 CASE_EXPECT_TRUE(f.is_exiting());
1364
1365 CASE_EXPECT_EQ(5111, *f.get_context()->data());
1366}
1367
1368CASE_TEST(task_promise, task_then_12_12_task_return_void_and_thenable_return_callable_void) {
1369 auto t = task_func_await_void_simple();
1370 auto f = t.then(
1371 [](const task_future_void_type::context_pointer_type &) -> cotask::task_future<void, void> {
1372 CASE_MSG_INFO() << "first thenable return task_future<void>" << std::endl;
1373 co_return;
1374 },
1375 3000)
1376 .then(
1377 [](cotask::task_future<void, int>::context_pointer_type ctx) {
1378 CASE_EXPECT_EQ(3000, ctx->get_private_data());
1379 CASE_MSG_INFO() << "second thenable return void" << std::endl;
1380 },
1381 nullptr);
1382
1383 CASE_EXPECT_FALSE(f.is_exiting());
1384 t.start();
1385 CASE_EXPECT_FALSE(f.is_exiting());
1386
1387 resume_pending_contexts({});
1388 CASE_EXPECT_TRUE(f.is_exiting());
1389}
1390
1391namespace {
1392static cotask::task_future<int, void> task_func_some_any_all_callable_suspend() {
1393 auto suspend_callback = [](generator_future_int_type::context_pointer_type ctx) {
1394 ++g_task_future_suspend_generator_count;
1395 g_task_future_pending_int_contexts.push_back(ctx);
1396 };
1397 auto resume_callback = [](const generator_future_int_type::context_type &) {
1398 ++g_task_future_resume_generator_count;
1399 };
1400
1401 auto value = co_await generator_future_int_type(suspend_callback, resume_callback);
1402 co_return value;
1403}
1404
1405static copp::callable_future<int> task_future_func_some_callable_in_container(size_t expect_ready_count,
1406 copp::promise_status expect_status) {
1407 size_t old_resume_generator_count = g_task_future_resume_generator_count;
1408 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
1409
1410 size_t resume_ready_count = 0;
1411
1412 std::vector<cotask::task_future<int, void>> tasks;
1413 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1414 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1415 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1416 for (auto &task_object : tasks) {
1417 task_object.start();
1418 }
1419
1420 copp::some_ready<cotask::task_future<int, void>>::type readys;
1421 auto some_result = co_await copp::some(readys, 2, tasks);
1422 CASE_EXPECT_EQ(static_cast<int>(expect_status), static_cast<int>(some_result));
1423
1424 int result = 1;
1425 for (auto &ready_task : readys) {
1426 if (ready_task->is_exiting()) {
1427 result += *ready_task->get_context()->data();
1428 ++resume_ready_count;
1429 }
1430 }
1431
1432 CASE_EXPECT_EQ(expect_ready_count, resume_ready_count);
1433
1434 // Nothing happend here if we await the tasks again.
1435 some_result = co_await copp::some(readys, 2, tasks);
1436 CASE_EXPECT_EQ(static_cast<int>(expect_status), static_cast<int>(some_result));
1437
1438 // If it's killed, await will trigger suspend and resume again, or it will return directly.
1439 CASE_EXPECT_EQ(expect_ready_count, resume_ready_count);
1440
1441 CASE_EXPECT_EQ(old_resume_generator_count + expect_ready_count, g_task_future_resume_generator_count);
1442 CASE_EXPECT_EQ(old_suspend_generator_count + 3, g_task_future_suspend_generator_count);
1443 CASE_EXPECT_EQ(expect_ready_count, resume_ready_count);
1444
1445 co_return result;
1446}
1447} // namespace
1448
1449CASE_TEST(task_promise, finish_some_in_container) {
1450 auto f = task_future_func_some_callable_in_container(2, copp::promise_status::kDone);
1451
1452 CASE_EXPECT_FALSE(f.is_ready());
1453
1454 // partly resume
1455 resume_pending_contexts({471}, 1);
1456 CASE_EXPECT_FALSE(f.is_ready());
1457 resume_pending_contexts({473}, 1);
1458
1459 CASE_EXPECT_TRUE(f.is_ready());
1460 CASE_EXPECT_EQ(945, f.get_internal_promise().data());
1461
1462 resume_pending_contexts({});
1463}
1464
1465CASE_TEST(task_promise, kill_some_in_container) {
1466 auto f = task_future_func_some_callable_in_container(0, copp::promise_status::kKilled);
1467
1468 CASE_EXPECT_FALSE(f.is_ready());
1469
1470 // partly resume
1471 f.kill();
1472
1473 CASE_EXPECT_TRUE(f.is_ready());
1474 CASE_EXPECT_EQ(1, f.get_internal_promise().data());
1475
1476 resume_pending_contexts({});
1477}
1478
1479static copp::callable_future<int> task_future_func_some_callable_in_initialize_list(
1480 size_t expect_ready_count, copp::promise_status expect_status) {
1481 size_t old_resume_generator_count = g_task_future_resume_generator_count;
1482 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
1483
1484 size_t resume_ready_count = 0;
1485
1486 cotask::task_future<int, void> task1 = task_func_some_any_all_callable_suspend();
1487 cotask::task_future<int, void> task2 = task_func_some_any_all_callable_suspend();
1488 cotask::task_future<int, void> task3 = task_func_some_any_all_callable_suspend();
1489 task1.start();
1490 task2.start();
1491 task3.start();
1492
1493 copp::some_ready<cotask::task_future<int, void>>::type readys;
1494 std::reference_wrapper<cotask::task_future<int, void>> pending[] = {task1, task2, task3};
1495 auto some_result = co_await copp::some(readys, 2, pending);
1496 CASE_EXPECT_EQ(static_cast<int>(expect_status), static_cast<int>(some_result));
1497
1498 int result = 1;
1499 for (auto &ready_task : readys) {
1500 if (ready_task->is_exiting()) {
1501 result += *ready_task->get_context()->data();
1502 ++resume_ready_count;
1503 }
1504 }
1505
1506 CASE_EXPECT_EQ(old_resume_generator_count + expect_ready_count, g_task_future_resume_generator_count);
1507 CASE_EXPECT_EQ(old_suspend_generator_count + 3, g_task_future_suspend_generator_count);
1508 CASE_EXPECT_EQ(expect_ready_count, resume_ready_count);
1509
1510 co_return result;
1511}
1512
1513CASE_TEST(task_promise, finish_some_in_initialize_list) {
1514 auto f = task_future_func_some_callable_in_initialize_list(2, copp::promise_status::kDone);
1515
1516 CASE_EXPECT_FALSE(f.is_ready());
1517
1518 // partly resume
1519 resume_pending_contexts({471}, 1);
1520 CASE_EXPECT_FALSE(f.is_ready());
1521 resume_pending_contexts({473}, 1);
1522
1523 CASE_EXPECT_TRUE(f.is_ready());
1524 CASE_EXPECT_EQ(945, f.get_internal_promise().data());
1525
1526 resume_pending_contexts({});
1527}
1528
1529namespace {
1530static copp::callable_future<int> task_future_func_any_callable_in_container(size_t expect_ready_count,
1531 copp::promise_status expect_status) {
1532 size_t old_resume_generator_count = g_task_future_resume_generator_count;
1533 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
1534
1535 size_t resume_ready_count = 0;
1536
1537 std::vector<cotask::task_future<int, void>> tasks;
1538 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1539 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1540 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1541 for (auto &task_object : tasks) {
1542 task_object.start();
1543 }
1544
1545 copp::any_ready<cotask::task_future<int, void>>::type readys;
1546 auto any_result = co_await copp::any(readys, tasks);
1547 CASE_EXPECT_EQ(static_cast<int>(expect_status), static_cast<int>(any_result));
1548
1549 int result = 1;
1550 for (auto &ready_task : readys) {
1551 if (ready_task->is_exiting()) {
1552 result += *ready_task->get_context()->data();
1553 ++resume_ready_count;
1554 }
1555 }
1556
1557 CASE_EXPECT_EQ(old_resume_generator_count + expect_ready_count, g_task_future_resume_generator_count);
1558 CASE_EXPECT_EQ(old_suspend_generator_count + 3, g_task_future_suspend_generator_count);
1559 CASE_EXPECT_EQ(expect_ready_count, resume_ready_count);
1560
1561 // Nothing happend here if we await the tasks again.
1562 any_result = co_await copp::any(readys, tasks);
1563 CASE_EXPECT_EQ(static_cast<int>(expect_status), static_cast<int>(any_result));
1564
1565 // If it's killed, await will trigger suspend and resume again, or it will return directly.
1566 CASE_EXPECT_EQ(expect_ready_count, resume_ready_count);
1567
1568 CASE_EXPECT_EQ(old_resume_generator_count + expect_ready_count, g_task_future_resume_generator_count);
1569 CASE_EXPECT_EQ(old_suspend_generator_count + 3, g_task_future_suspend_generator_count);
1570 CASE_EXPECT_EQ(expect_ready_count, resume_ready_count);
1571
1572 co_return result;
1573}
1574} // namespace
1575
1576CASE_TEST(task_promise, finish_any_in_container) {
1577 auto f = task_future_func_any_callable_in_container(1, copp::promise_status::kDone);
1578
1579 CASE_EXPECT_FALSE(f.is_ready());
1580
1581 // partly resume
1582 resume_pending_contexts({671}, 1);
1583
1584 CASE_EXPECT_TRUE(f.is_ready());
1585 CASE_EXPECT_EQ(672, f.get_internal_promise().data());
1586
1587 resume_pending_contexts({});
1588}
1589
1590namespace {
1591static copp::callable_future<int> task_future_func_all_callable_in_container(size_t expect_ready_count,
1592 copp::promise_status expect_status) {
1593 size_t old_resume_generator_count = g_task_future_resume_generator_count;
1594 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
1595
1596 size_t resume_ready_count = 0;
1597
1598 std::vector<cotask::task_future<int, void>> tasks;
1599 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1600 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1601 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1602 for (auto &task_object : tasks) {
1603 task_object.start();
1604 }
1605
1606 copp::all_ready<cotask::task_future<int, void>>::type readys;
1607 auto all_result = co_await copp::all(readys, tasks);
1608 CASE_EXPECT_EQ(static_cast<int>(expect_status), static_cast<int>(all_result));
1609
1610 int result = 1;
1611 for (auto &ready_task : readys) {
1612 if (ready_task->is_exiting()) {
1613 result += *ready_task->get_context()->data();
1614 ++resume_ready_count;
1615 }
1616 }
1617
1618 CASE_EXPECT_EQ(old_resume_generator_count + 3, g_task_future_resume_generator_count);
1619 CASE_EXPECT_EQ(old_suspend_generator_count + 3, g_task_future_suspend_generator_count);
1620 CASE_EXPECT_EQ(expect_ready_count, resume_ready_count);
1621
1622 // Nothing happend here if we await the tasks again.
1623 all_result = co_await copp::all(readys, tasks);
1624 CASE_EXPECT_EQ(static_cast<int>(expect_status), static_cast<int>(all_result));
1625
1626 // If it's killed, await will trigger suspend and resume again, or it will return directly.
1627 CASE_EXPECT_EQ(expect_ready_count, resume_ready_count);
1628
1629 CASE_EXPECT_EQ(old_resume_generator_count + expect_ready_count, g_task_future_resume_generator_count);
1630 CASE_EXPECT_EQ(old_suspend_generator_count + 3, g_task_future_suspend_generator_count);
1631 CASE_EXPECT_EQ(expect_ready_count, resume_ready_count);
1632
1633 co_return result;
1634}
1635} // namespace
1636
1637CASE_TEST(task_promise, finish_all_in_container) {
1638 auto f = task_future_func_all_callable_in_container(3, copp::promise_status::kDone);
1639
1640 CASE_EXPECT_FALSE(f.is_ready());
1641
1642 // partly resume
1643 resume_pending_contexts({671}, 1);
1644 CASE_EXPECT_FALSE(f.is_ready());
1645
1646 resume_pending_contexts({791, 793}, 2);
1647
1648 CASE_EXPECT_TRUE(f.is_ready());
1649 CASE_EXPECT_EQ(2256, f.get_internal_promise().data());
1650
1651 resume_pending_contexts({});
1652}
1653
1654#else
1655CASE_TEST(task_promise, disabled) {}
1656#endif
constexpr auto data(TCONTAINER &&container) -> decltype(container.data())
Definition span.h:54
#define CASE_MSG_INFO()
#define CASE_EXPECT_FALSE(c)
Definition test_macros.h:98
#define CASE_EXPECT_EQ(l, r)
Definition test_macros.h:99
#define CASE_EXPECT_NE(l, r)
#define CASE_TEST(test_name, case_name)
Definition test_macros.h:47
#define CASE_EXPECT_TRUE(c)
Definition test_macros.h:97