]> git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/tests/unit/coroutines_test.cc
import 15.2.0 Octopus source
[ceph.git] / ceph / src / seastar / tests / unit / coroutines_test.cc
1 /*
2 * This file is open source software, licensed to you under the terms
3 * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4 * distributed with this work for additional information regarding copyright
5 * ownership. You may not use this file except in compliance with the License.
6 *
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing,
12 * software distributed under the License is distributed on an
13 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 * KIND, either express or implied. See the License for the
15 * specific language governing permissions and limitations
16 * under the License.
17 */
18 /*
19 * Copyright (C) 2019 ScyllaDB Ltd.
20 */
21
22 #include <seastar/core/coroutine.hh>
23 #include <seastar/core/future-util.hh>
24 #include <seastar/testing/test_case.hh>
25
26 using namespace seastar;
27
28 namespace {
29
30 future<int> old_fashioned_continuations() {
31 return later().then([] {
32 return 42;
33 });
34 }
35
36 future<int> simple_coroutine() {
37 co_await later();
38 co_return 53;
39 }
40
41 future<int> ready_coroutine() {
42 co_return 64;
43 }
44
45 future<int, double> tuple_coroutine() {
46 co_return std::tuple(1, 2.);
47 }
48
49 future<int> failing_coroutine() {
50 co_await later();
51 throw 42;
52 }
53
54 }
55
56 SEASTAR_TEST_CASE(test_simple_coroutines) {
57 BOOST_REQUIRE_EQUAL(co_await old_fashioned_continuations(), 42);
58 BOOST_REQUIRE_EQUAL(co_await simple_coroutine(), 53);
59 BOOST_REQUIRE_EQUAL(ready_coroutine().get0(), 64);
60 BOOST_REQUIRE(co_await tuple_coroutine() == std::tuple(1, 2.));
61 BOOST_REQUIRE_EXCEPTION((void)co_await failing_coroutine(), int, [] (auto v) { return v == 42; });
62 }
63
64 SEASTAR_TEST_CASE(test_abandond_coroutine) {
65 compat::optional<future<int>> f;
66 {
67 auto p1 = promise<>();
68 auto p2 = promise<>();
69 auto p3 = promise<>();
70 f = p1.get_future().then([&] () -> future<int> {
71 p2.set_value();
72 BOOST_CHECK_THROW(co_await p3.get_future(), broken_promise);
73 co_return 1;
74 });
75 p1.set_value();
76 co_await p2.get_future();
77 }
78 BOOST_CHECK_EQUAL(co_await std::move(*f), 1);
79 }
80
81 SEASTAR_TEST_CASE(test_scheduling_group) {
82 auto other_sg = co_await create_scheduling_group("the other group", 10.f);
83
84 auto p1 = promise<>();
85 auto p2 = promise<>();
86
87 auto p1b = promise<>();
88 auto p2b = promise<>();
89 auto f1 = p1b.get_future();
90 auto f2 = p2b.get_future();
91
92 BOOST_REQUIRE(current_scheduling_group() == default_scheduling_group());
93 auto f_ret = with_scheduling_group(other_sg,
94 [other_sg] (future<> f1, future<> f2, promise<> p1, promise<> p2) -> future<int> {
95 BOOST_REQUIRE(current_scheduling_group() == other_sg);
96 BOOST_REQUIRE(other_sg == other_sg);
97 p1.set_value();
98 co_await std::move(f1);
99 BOOST_REQUIRE(current_scheduling_group() == other_sg);
100 p2.set_value();
101 co_await std::move(f2);
102 BOOST_REQUIRE(current_scheduling_group() == other_sg);
103 co_return 42;
104 }, p1.get_future(), p2.get_future(), std::move(p1b), std::move(p2b));
105
106 co_await std::move(f1);
107 BOOST_REQUIRE(current_scheduling_group() == default_scheduling_group());
108 p1.set_value();
109 co_await std::move(f2);
110 BOOST_REQUIRE(current_scheduling_group() == default_scheduling_group());
111 p2.set_value();
112 BOOST_REQUIRE_EQUAL(co_await std::move(f_ret), 42);
113 BOOST_REQUIRE(current_scheduling_group() == default_scheduling_group());
114 }