]> git.proxmox.com Git - ceph.git/blame - ceph/src/seastar/tests/unit/abort_source_test.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / seastar / tests / unit / abort_source_test.cc
CommitLineData
11fdf7f2
TL
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) 2017 ScyllaDB
20 */
21
22#include <seastar/testing/test_case.hh>
1e59de90 23#include <seastar/testing/thread_test_case.hh>
11fdf7f2
TL
24
25#include <seastar/core/gate.hh>
26#include <seastar/core/sleep.hh>
9f95a23c 27#include <seastar/core/do_with.hh>
11fdf7f2
TL
28
29using namespace seastar;
30using namespace std::chrono_literals;
31
32SEASTAR_TEST_CASE(test_abort_source_notifies_subscriber) {
33 bool signalled = false;
34 auto as = abort_source();
f67539c2 35 auto st_opt = as.subscribe([&signalled] () noexcept {
11fdf7f2
TL
36 signalled = true;
37 });
38 BOOST_REQUIRE_EQUAL(true, bool(st_opt));
39 as.request_abort();
40 BOOST_REQUIRE_EQUAL(true, signalled);
20effc67 41 BOOST_REQUIRE_EQUAL(false, bool(st_opt));
1e59de90 42 BOOST_REQUIRE_THROW(as.check(), abort_requested_exception);
11fdf7f2
TL
43 return make_ready_future<>();
44}
45
46SEASTAR_TEST_CASE(test_abort_source_subscription_unregister) {
47 bool signalled = false;
48 auto as = abort_source();
f67539c2 49 auto st_opt = as.subscribe([&signalled] () noexcept {
11fdf7f2
TL
50 signalled = true;
51 });
52 BOOST_REQUIRE_EQUAL(true, bool(st_opt));
53 st_opt = { };
54 as.request_abort();
55 BOOST_REQUIRE_EQUAL(false, signalled);
56 return make_ready_future<>();
57}
58
59SEASTAR_TEST_CASE(test_abort_source_rejects_subscription) {
60 auto as = abort_source();
61 as.request_abort();
f67539c2 62 auto st_opt = as.subscribe([] () noexcept { });
11fdf7f2
TL
63 BOOST_REQUIRE_EQUAL(false, bool(st_opt));
64 return make_ready_future<>();
65}
66
67SEASTAR_TEST_CASE(test_sleep_abortable) {
68 auto as = std::make_unique<abort_source>();
69 auto f = sleep_abortable(100s, *as).then_wrapped([] (auto&& f) {
70 try {
71 f.get();
72 BOOST_FAIL("should have failed");
73 } catch (const sleep_aborted& e) {
74 // expected
75 } catch (...) {
76 BOOST_FAIL("unexpected exception");
77 }
78 });
79 as->request_abort();
80 return f.finally([as = std::move(as)] { });
81}
9f95a23c
TL
82
83// Verify that negative sleep does not sleep forever. It should not sleep
84// at all.
85SEASTAR_TEST_CASE(test_negative_sleep_abortable) {
86 return do_with(abort_source(), [] (abort_source& as) {
87 return sleep_abortable(-10s, as);
88 });
89}
1e59de90
TL
90
91SEASTAR_TEST_CASE(test_request_abort_with_exception) {
92 abort_source as;
93 optimized_optional<abort_source::subscription> st_opt;
94 std::optional<std::exception_ptr> aborted_ex;
95 auto expected_message = "expected";
96
97 auto make_abort_source = [&] () {
98 as = abort_source();
99 st_opt = as.subscribe([&aborted_ex] (const std::optional<std::exception_ptr>& opt_ex) noexcept {
100 aborted_ex = opt_ex;
101 });
102 aborted_ex = std::nullopt;
103 };
104
105 make_abort_source();
106 auto ex = make_exception_ptr(std::runtime_error(expected_message));
107 as.request_abort_ex(ex);
108 BOOST_REQUIRE(aborted_ex.has_value());
109 bool caught_exception = false;
110 try {
111 std::rethrow_exception(*aborted_ex);
112 } catch (const std::runtime_error& e) {
113 BOOST_REQUIRE_EQUAL(e.what(), expected_message);
114 caught_exception = true;
115 }
116 BOOST_REQUIRE(caught_exception);
117 BOOST_REQUIRE_THROW(as.check(), std::runtime_error);
118
119 make_abort_source();
120 as.request_abort_ex(make_exception_ptr(std::runtime_error(expected_message)));
121 BOOST_REQUIRE(aborted_ex.has_value());
122 caught_exception = false;
123 try {
124 std::rethrow_exception(*aborted_ex);
125 } catch (const std::runtime_error& e) {
126 BOOST_REQUIRE_EQUAL(e.what(), expected_message);
127 caught_exception = true;
128 }
129 BOOST_REQUIRE(caught_exception);
130 BOOST_REQUIRE_THROW(as.check(), std::runtime_error);
131
132
133 make_abort_source();
134 as.request_abort_ex(std::runtime_error(expected_message));
135 BOOST_REQUIRE(aborted_ex.has_value());
136 caught_exception = false;
137 try {
138 std::rethrow_exception(*aborted_ex);
139 } catch (const std::runtime_error& e) {
140 BOOST_REQUIRE_EQUAL(e.what(), expected_message);
141 caught_exception = true;
142 }
143 BOOST_REQUIRE(caught_exception);
144 BOOST_REQUIRE_THROW(as.check(), std::runtime_error);
145
146 return make_ready_future<>();
147}
148
149SEASTAR_THREAD_TEST_CASE(test_sleep_abortable_with_exception) {
150 abort_source as;
151 auto f = sleep_abortable(10s, as);
152 auto expected_message = "expected";
153 as.request_abort_ex(std::runtime_error(expected_message));
154
155 bool caught_exception = false;
156 try {
157 f.get();
158 } catch (const std::runtime_error& e) {
159 BOOST_REQUIRE_EQUAL(e.what(), expected_message);
160 caught_exception = true;
161 }
162 BOOST_REQUIRE(caught_exception);
163}
164
165SEASTAR_THREAD_TEST_CASE(test_destroy_with_moved_subscriptions) {
166 auto as = std::make_unique<abort_source>();
167 int aborted = 0;
168 auto sub1 = as->subscribe([&] () noexcept { ++aborted; });
169 auto sub2 = std::move(sub1);
170 optimized_optional<abort_source::subscription> sub3;
171 sub3 = std::move(sub2);
172 auto sub4 = as->subscribe([&] () noexcept { ++aborted; });
173 sub4 = std::move(sub3);
174 as.reset();
175 BOOST_REQUIRE_EQUAL(aborted, 0);
176}