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.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
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
19 * Copyright (C) 2014 Cloudius Systems, Ltd.
22 #include <seastar/testing/test_case.hh>
24 #include <seastar/core/shared_ptr.hh>
25 #include <seastar/core/future-util.hh>
26 #include <seastar/core/sleep.hh>
27 #include <seastar/core/do_with.hh>
28 #include <seastar/core/shared_future.hh>
29 #include <seastar/core/thread.hh>
30 #include <boost/iterator/counting_iterator.hpp>
32 using namespace seastar
;
33 using namespace std::chrono_literals
;
35 class expected_exception
: std::runtime_error
{
37 expected_exception() : runtime_error("expected") {}
40 SEASTAR_TEST_CASE(test_finally_is_called_on_success_and_failure
) {
41 auto finally1
= make_shared
<bool>();
42 auto finally2
= make_shared
<bool>();
44 return make_ready_future().then([] {
48 throw std::runtime_error("");
51 }).then_wrapped([=] (auto&& f
) {
52 BOOST_REQUIRE(*finally1
);
53 BOOST_REQUIRE(*finally2
);
63 SEASTAR_TEST_CASE(test_get_on_promise
) {
64 auto p
= promise
<uint32_t>();
66 BOOST_REQUIRE_EQUAL(10u, p
.get_future().get0());
67 return make_ready_future();
70 SEASTAR_TEST_CASE(test_finally_waits_for_inner
) {
71 auto finally
= make_shared
<bool>();
72 auto p
= make_shared
<promise
<>>();
74 auto f
= make_ready_future().then([] {
76 return p
->get_future().then([=] {
80 BOOST_REQUIRE(*finally
);
82 BOOST_REQUIRE(!*finally
);
87 SEASTAR_TEST_CASE(test_finally_is_called_on_success_and_failure__not_ready_to_armed
) {
88 auto finally1
= make_shared
<bool>();
89 auto finally2
= make_shared
<bool>();
92 auto f
= p
.get_future().finally([=] {
95 throw std::runtime_error("");
98 }).then_wrapped([=] (auto &&f
) {
99 BOOST_REQUIRE(*finally1
);
100 BOOST_REQUIRE(*finally2
);
103 } catch (...) {} // silence exceptional future ignored messages
110 SEASTAR_TEST_CASE(test_exception_from_finally_fails_the_target
) {
112 auto f
= pr
.get_future().finally([=] {
113 throw std::runtime_error("");
115 BOOST_REQUIRE(false);
116 }).then_wrapped([] (auto&& f
) {
119 } catch (...) {} // silence exceptional future ignored messages
126 SEASTAR_TEST_CASE(test_exception_from_finally_fails_the_target_on_already_resolved
) {
127 return make_ready_future().finally([=] {
128 throw std::runtime_error("");
130 BOOST_REQUIRE(false);
131 }).then_wrapped([] (auto&& f
) {
134 } catch (...) {} // silence exceptional future ignored messages
138 SEASTAR_TEST_CASE(test_exception_thrown_from_then_wrapped_causes_future_to_fail
) {
139 return make_ready_future().then_wrapped([] (auto&& f
) {
140 throw std::runtime_error("");
141 }).then_wrapped([] (auto&& f
) {
144 BOOST_REQUIRE(false);
149 SEASTAR_TEST_CASE(test_exception_thrown_from_then_wrapped_causes_future_to_fail__async_case
) {
152 auto f
= p
.get_future().then_wrapped([] (auto&& f
) {
153 throw std::runtime_error("");
154 }).then_wrapped([] (auto&& f
) {
157 BOOST_REQUIRE(false);
166 SEASTAR_TEST_CASE(test_failing_intermediate_promise_should_fail_the_master_future
) {
170 auto f
= p1
.get_future().then([f
= std::move(p2
.get_future())] () mutable {
173 BOOST_REQUIRE(false);
177 p2
.set_exception(std::runtime_error("boom"));
179 return std::move(f
).then_wrapped([](auto&& f
) {
182 BOOST_REQUIRE(false);
187 SEASTAR_TEST_CASE(test_future_forwarding__not_ready_to_unarmed
) {
191 auto f1
= p1
.get_future();
192 auto f2
= p2
.get_future();
194 f1
.forward_to(std::move(p2
));
196 BOOST_REQUIRE(!f2
.available());
198 auto called
= f2
.then([] {});
204 SEASTAR_TEST_CASE(test_future_forwarding__not_ready_to_armed
) {
208 auto f1
= p1
.get_future();
209 auto f2
= p2
.get_future();
211 auto called
= f2
.then([] {});
213 f1
.forward_to(std::move(p2
));
215 BOOST_REQUIRE(!f2
.available());
222 SEASTAR_TEST_CASE(test_future_forwarding__ready_to_unarmed
) {
225 auto f1
= make_ready_future
<>();
226 auto f2
= p2
.get_future();
228 std::move(f1
).forward_to(std::move(p2
));
229 BOOST_REQUIRE(f2
.available());
231 return std::move(f2
).then_wrapped([] (future
<> f
) {
232 BOOST_REQUIRE(!f
.failed());
236 SEASTAR_TEST_CASE(test_future_forwarding__ready_to_armed
) {
239 auto f1
= make_ready_future
<>();
240 auto f2
= p2
.get_future();
242 auto called
= std::move(f2
).then([] {});
244 BOOST_REQUIRE(f1
.available());
246 f1
.forward_to(std::move(p2
));
250 static void forward_dead_unarmed_promise_with_dead_future_to(promise
<>& p
) {
252 p
.get_future().forward_to(std::move(p2
));
255 SEASTAR_TEST_CASE(test_future_forwarding__ready_to_unarmed_soon_to_be_dead
) {
257 forward_dead_unarmed_promise_with_dead_future_to(p1
);
258 make_ready_future
<>().forward_to(std::move(p1
));
259 return make_ready_future
<>();
262 SEASTAR_TEST_CASE(test_exception_can_be_thrown_from_do_until_body
) {
263 return do_until([] { return false; }, [] {
264 throw expected_exception();
266 }).then_wrapped([] (auto&& f
) {
269 BOOST_FAIL("should have failed");
270 } catch (const expected_exception
& e
) {
276 SEASTAR_TEST_CASE(test_bare_value_can_be_returned_from_callback
) {
277 return now().then([] {
280 BOOST_REQUIRE(x
== 3);
284 SEASTAR_TEST_CASE(test_when_all_iterator_range
) {
285 std::vector
<future
<size_t>> futures
;
286 for (size_t i
= 0; i
!= 1000000; ++i
) {
287 // .then() usually returns a ready future, but sometimes it
288 // doesn't, so call it a million times. This exercises both
289 // available and unavailable paths in when_all().
290 futures
.push_back(make_ready_future
<>().then([i
] { return i
; }));
292 // Verify the above statement is correct
293 BOOST_REQUIRE(!std::all_of(futures
.begin(), futures
.end(),
294 [] (auto& f
) { return f
.available(); }));
295 auto p
= make_shared(std::move(futures
));
296 return when_all(p
->begin(), p
->end()).then([p
] (std::vector
<future
<size_t>> ret
) {
297 BOOST_REQUIRE(std::all_of(ret
.begin(), ret
.end(), [] (auto& f
) { return f
.available(); }));
298 BOOST_REQUIRE(std::all_of(ret
.begin(), ret
.end(), [&ret
] (auto& f
) { return std::get
<0>(f
.get()) == size_t(&f
- ret
.data()); }));
302 SEASTAR_TEST_CASE(test_map_reduce
) {
303 auto square
= [] (long x
) { return make_ready_future
<long>(x
*x
); };
305 return map_reduce(boost::make_counting_iterator
<long>(0), boost::make_counting_iterator
<long>(n
),
306 square
, long(0), std::plus
<long>()).then([n
] (auto result
) {
307 auto m
= n
- 1; // counting does not include upper bound
308 BOOST_REQUIRE_EQUAL(result
, (m
* (m
+ 1) * (2*m
+ 1)) / 6);
312 // This test doesn't actually test anything - it just waits for the future
313 // returned by sleep to complete. However, a bug we had in sleep() caused
314 // this test to fail the sanitizer in the debug build, so this is a useful
316 SEASTAR_TEST_CASE(test_sleep
) {
317 return sleep(std::chrono::milliseconds(100));
320 SEASTAR_TEST_CASE(test_do_with_1
) {
321 return do_with(1, [] (int& one
) {
322 BOOST_REQUIRE_EQUAL(one
, 1);
323 return make_ready_future
<>();
327 SEASTAR_TEST_CASE(test_do_with_2
) {
328 return do_with(1, 2L, [] (int& one
, long two
) {
329 BOOST_REQUIRE_EQUAL(one
, 1);
330 BOOST_REQUIRE_EQUAL(two
, 2);
331 return make_ready_future
<>();
335 SEASTAR_TEST_CASE(test_do_with_3
) {
336 return do_with(1, 2L, 3, [] (int& one
, long two
, int three
) {
337 BOOST_REQUIRE_EQUAL(one
, 1);
338 BOOST_REQUIRE_EQUAL(two
, 2);
339 BOOST_REQUIRE_EQUAL(three
, 3);
340 return make_ready_future
<>();
344 SEASTAR_TEST_CASE(test_do_with_4
) {
345 return do_with(1, 2L, 3, 4, [] (int& one
, long two
, int three
, int four
) {
346 BOOST_REQUIRE_EQUAL(one
, 1);
347 BOOST_REQUIRE_EQUAL(two
, 2);
348 BOOST_REQUIRE_EQUAL(three
, 3);
349 BOOST_REQUIRE_EQUAL(four
, 4);
350 return make_ready_future
<>();
354 SEASTAR_TEST_CASE(test_do_while_stopping_immediately
) {
355 return do_with(int(0), [] (int& count
) {
356 return repeat([&count
] {
358 return stop_iteration::yes
;
360 BOOST_REQUIRE(count
== 1);
365 SEASTAR_TEST_CASE(test_do_while_stopping_after_two_iterations
) {
366 return do_with(int(0), [] (int& count
) {
367 return repeat([&count
] {
369 return count
== 2 ? stop_iteration::yes
: stop_iteration::no
;
371 BOOST_REQUIRE(count
== 2);
376 SEASTAR_TEST_CASE(test_do_while_failing_in_the_first_step
) {
378 throw expected_exception();
379 return stop_iteration::no
;
380 }).then_wrapped([](auto&& f
) {
383 BOOST_FAIL("should not happen");
384 } catch (const expected_exception
&) {
390 SEASTAR_TEST_CASE(test_do_while_failing_in_the_second_step
) {
391 return do_with(int(0), [] (int& count
) {
392 return repeat([&count
] {
395 throw expected_exception();
397 return later().then([] { return stop_iteration::no
; });
398 }).then_wrapped([&count
](auto&& f
) {
401 BOOST_FAIL("should not happen");
402 } catch (const expected_exception
&) {
403 BOOST_REQUIRE(count
== 2);
409 SEASTAR_TEST_CASE(test_parallel_for_each
) {
412 parallel_for_each(std::vector
<int>(), [] (int) -> future
<> {
413 BOOST_FAIL("should not reach");
418 auto range
= boost::copy_range
<std::vector
<int>>(boost::irange(1, 6));
420 parallel_for_each(range
, [&sum
] (int v
) {
422 return make_ready_future
<>();
424 BOOST_REQUIRE_EQUAL(sum
, 15);
428 parallel_for_each(range
, [&sum
] (int v
) {
429 return later().then([&sum
, v
] {
433 BOOST_REQUIRE_EQUAL(sum
, 15);
435 // throws immediately
436 BOOST_CHECK_EXCEPTION(parallel_for_each(range
, [&sum
] (int) -> future
<> {
438 }).get(), int, [] (int v
) { return v
== 5; });
440 // throws after suspension
441 BOOST_CHECK_EXCEPTION(parallel_for_each(range
, [&sum
] (int) {
442 return later().then([] {
445 }).get(), int, [] (int v
) { return v
== 5; });
449 SEASTAR_TEST_CASE(test_parallel_for_each_early_failure
) {
450 return do_with(0, [] (int& counter
) {
451 return parallel_for_each(boost::irange(0, 11000), [&counter
] (int i
) {
452 using namespace std::chrono_literals
;
454 return sleep((i
% 31 + 1) * 1ms
).then([&counter
, i
] {
456 if (i
% 1777 == 1337) {
457 return make_exception_future
<>(i
);
459 return make_ready_future
<>();
461 }).then_wrapped([&counter
] (future
<> f
) {
462 BOOST_REQUIRE_EQUAL(counter
, 11000);
463 BOOST_REQUIRE(f
.failed());
466 BOOST_FAIL("wanted an exception");
468 BOOST_REQUIRE(i
% 1777 == 1337);
470 BOOST_FAIL("bad exception type");
476 SEASTAR_TEST_CASE(test_parallel_for_each_waits_for_all_fibers_even_if_one_of_them_failed
) {
477 auto can_exit
= make_lw_shared
<bool>(false);
478 return parallel_for_each(boost::irange(0, 2), [can_exit
] (int i
) {
479 return later().then([i
, can_exit
] {
481 throw expected_exception();
483 using namespace std::chrono_literals
;
484 return sleep(300ms
).then([can_exit
] {
489 }).then_wrapped([can_exit
] (auto&& f
) {
495 BOOST_REQUIRE(*can_exit
);
499 #ifndef SEASTAR_SHUFFLE_TASK_QUEUE
500 SEASTAR_TEST_CASE(test_high_priority_task_runs_before_ready_continuations
) {
501 return now().then([] {
502 auto flag
= make_lw_shared
<bool>(false);
503 engine().add_high_priority_task(make_task([flag
] {
506 make_ready_future().then([flag
] {
507 BOOST_REQUIRE(*flag
);
512 SEASTAR_TEST_CASE(test_high_priority_task_runs_in_the_middle_of_loops
) {
513 auto counter
= make_lw_shared
<int>(0);
514 auto flag
= make_lw_shared
<bool>(false);
515 return repeat([counter
, flag
] {
517 BOOST_REQUIRE(*flag
);
518 return stop_iteration::yes
;
520 engine().add_high_priority_task(make_task([flag
] {
524 return stop_iteration::no
;
529 SEASTAR_TEST_CASE(futurize_apply_val_exception
) {
530 return futurize
<int>::apply([] (int arg
) { throw expected_exception(); return arg
; }, 1).then_wrapped([] (future
<int> f
) {
533 BOOST_FAIL("should have thrown");
534 } catch (expected_exception
& e
) {}
538 SEASTAR_TEST_CASE(futurize_apply_val_ok
) {
539 return futurize
<int>::apply([] (int arg
) { return arg
* 2; }, 2).then_wrapped([] (future
<int> f
) {
542 BOOST_REQUIRE_EQUAL(x
, 4);
543 } catch (expected_exception
& e
) {
544 BOOST_FAIL("should not have thrown");
549 SEASTAR_TEST_CASE(futurize_apply_val_future_exception
) {
550 return futurize
<int>::apply([] (int a
) {
551 return sleep(std::chrono::milliseconds(100)).then([] {
552 throw expected_exception();
553 return make_ready_future
<int>(0);
555 }, 0).then_wrapped([] (future
<int> f
) {
558 BOOST_FAIL("should have thrown");
559 } catch (expected_exception
& e
) { }
563 SEASTAR_TEST_CASE(futurize_apply_val_future_ok
) {
564 return futurize
<int>::apply([] (int a
) {
565 return sleep(std::chrono::milliseconds(100)).then([a
] {
566 return make_ready_future
<int>(a
* 100);
568 }, 2).then_wrapped([] (future
<int> f
) {
571 BOOST_REQUIRE_EQUAL(x
, 200);
572 } catch (expected_exception
& e
) {
573 BOOST_FAIL("should not have thrown");
577 SEASTAR_TEST_CASE(futurize_apply_void_exception
) {
578 return futurize
<void>::apply([] (auto arg
) { throw expected_exception(); }, 0).then_wrapped([] (future
<> f
) {
581 BOOST_FAIL("should have thrown");
582 } catch (expected_exception
& e
) {}
586 SEASTAR_TEST_CASE(futurize_apply_void_ok
) {
587 return futurize
<void>::apply([] (auto arg
) { }, 0).then_wrapped([] (future
<> f
) {
590 } catch (expected_exception
& e
) {
591 BOOST_FAIL("should not have thrown");
596 SEASTAR_TEST_CASE(futurize_apply_void_future_exception
) {
597 return futurize
<void>::apply([] (auto a
) {
598 return sleep(std::chrono::milliseconds(100)).then([] {
599 throw expected_exception();
601 }, 0).then_wrapped([] (future
<> f
) {
604 BOOST_FAIL("should have thrown");
605 } catch (expected_exception
& e
) { }
609 SEASTAR_TEST_CASE(futurize_apply_void_future_ok
) {
610 auto a
= make_lw_shared
<int>(1);
611 return futurize
<void>::apply([] (int& a
) {
612 return sleep(std::chrono::milliseconds(100)).then([&a
] {
615 }, *a
).then_wrapped([a
] (future
<> f
) {
618 BOOST_REQUIRE_EQUAL(*a
, 100);
619 } catch (expected_exception
& e
) {
620 BOOST_FAIL("should not have thrown");
625 SEASTAR_TEST_CASE(test_shared_future_propagates_value_to_all
) {
626 return seastar::async([] {
627 promise
<shared_ptr
<int>> p
; // shared_ptr<> to check it deals with emptyable types
628 shared_future
<shared_ptr
<int>> f(p
.get_future());
630 auto f1
= f
.get_future();
631 auto f2
= f
.get_future();
633 p
.set_value(make_shared
<int>(1));
634 BOOST_REQUIRE(*f1
.get0() == 1);
635 BOOST_REQUIRE(*f2
.get0() == 1);
639 template<typename
... T
>
640 void check_fails_with_expected(future
<T
...> f
) {
643 BOOST_FAIL("Should have failed");
644 } catch (expected_exception
&) {
649 SEASTAR_TEST_CASE(test_shared_future_propagates_value_to_copies
) {
650 return seastar::async([] {
652 auto sf1
= shared_future
<int>(p
.get_future());
655 auto f1
= sf1
.get_future();
656 auto f2
= sf2
.get_future();
660 BOOST_REQUIRE(f1
.get0() == 1);
661 BOOST_REQUIRE(f2
.get0() == 1);
665 SEASTAR_TEST_CASE(test_obtaining_future_from_shared_future_after_it_is_resolved
) {
668 auto sf1
= shared_future
<int>(p1
.get_future());
669 auto sf2
= shared_future
<int>(p2
.get_future());
671 p2
.set_exception(expected_exception());
672 return sf2
.get_future().then_wrapped([f1
= sf1
.get_future()] (auto&& f
) mutable {
673 check_fails_with_expected(std::move(f
));
674 return std::move(f1
);
675 }).then_wrapped([] (auto&& f
) {
676 BOOST_REQUIRE(f
.get0() == 1);
680 SEASTAR_TEST_CASE(test_valueless_shared_future
) {
681 return seastar::async([] {
683 shared_future
<> f(p
.get_future());
685 auto f1
= f
.get_future();
686 auto f2
= f
.get_future();
695 SEASTAR_TEST_CASE(test_shared_future_propagates_errors_to_all
) {
697 shared_future
<int> f(p
.get_future());
699 auto f1
= f
.get_future();
700 auto f2
= f
.get_future();
702 p
.set_exception(expected_exception());
704 return f1
.then_wrapped([f2
= std::move(f2
)] (auto&& f
) mutable {
705 check_fails_with_expected(std::move(f
));
706 return std::move(f2
);
707 }).then_wrapped([] (auto&& f
) mutable {
708 check_fails_with_expected(std::move(f
));
712 SEASTAR_TEST_CASE(test_futurize_from_tuple
) {
713 std::tuple
<int> v1
= std::make_tuple(3);
714 std::tuple
<> v2
= {};
715 BOOST_REQUIRE(futurize
<int>::from_tuple(v1
).get() == v1
);
716 BOOST_REQUIRE(futurize
<void>::from_tuple(v2
).get() == v2
);
717 return make_ready_future
<>();
720 SEASTAR_TEST_CASE(test_repeat_until_value
) {
721 return do_with(int(), [] (int& counter
) {
722 return repeat_until_value([&counter
] () -> future
<compat::optional
<int>> {
723 if (counter
== 10000) {
724 return make_ready_future
<compat::optional
<int>>(counter
);
727 return make_ready_future
<compat::optional
<int>>(compat::nullopt
);
729 }).then([&counter
] (int result
) {
730 BOOST_REQUIRE(counter
== 10000);
731 BOOST_REQUIRE(result
== counter
);
736 SEASTAR_TEST_CASE(test_when_allx
) {
737 return when_all(later(), later(), make_ready_future()).discard_result();
740 template<typename E
, typename
... T
>
741 static void check_failed_with(future
<T
...>&& f
) {
742 BOOST_REQUIRE(f
.failed());
745 BOOST_FAIL("exception expected");
746 } catch (const E
& e
) {
749 BOOST_FAIL(format("wrong exception: {}", std::current_exception()));
753 template<typename
... T
>
754 static void check_timed_out(future
<T
...>&& f
) {
755 check_failed_with
<timed_out_error
>(std::move(f
));
758 SEASTAR_TEST_CASE(test_with_timeout_when_it_times_out
) {
759 return seastar::async([] {
761 auto f
= with_timeout(manual_clock::now() + 2s
, pr
.get_future());
763 BOOST_REQUIRE(!f
.available());
765 manual_clock::advance(1s
);
768 BOOST_REQUIRE(!f
.available());
770 manual_clock::advance(1s
);
773 check_timed_out(std::move(f
));
779 SEASTAR_TEST_CASE(test_custom_exception_factory_in_with_timeout
) {
780 return seastar::async([] {
781 class custom_error
: public std::exception
{
783 virtual const char* what() const noexcept
{
787 struct my_exception_factory
{
788 static auto timeout() {
789 return custom_error();
793 auto f
= with_timeout
<my_exception_factory
>(manual_clock::now() + 1s
, pr
.get_future());
795 manual_clock::advance(1s
);
798 check_failed_with
<custom_error
>(std::move(f
));
802 SEASTAR_TEST_CASE(test_with_timeout_when_it_does_not_time_out
) {
803 return seastar::async([] {
806 auto f
= with_timeout(manual_clock::now() + 1s
, pr
.get_future());
810 BOOST_REQUIRE_EQUAL(f
.get0(), 42);
813 // Check that timer was indeed cancelled
814 manual_clock::advance(1s
);
819 SEASTAR_TEST_CASE(test_shared_future_with_timeout
) {
820 return seastar::async([] {
821 shared_promise
<with_clock
<manual_clock
>, int> pr
;
822 auto f1
= pr
.get_shared_future(manual_clock::now() + 1s
);
823 auto f2
= pr
.get_shared_future(manual_clock::now() + 2s
);
824 auto f3
= pr
.get_shared_future();
826 BOOST_REQUIRE(!f1
.available());
827 BOOST_REQUIRE(!f2
.available());
828 BOOST_REQUIRE(!f3
.available());
830 manual_clock::advance(1s
);
833 check_timed_out(std::move(f1
));
834 BOOST_REQUIRE(!f2
.available());
835 BOOST_REQUIRE(!f3
.available());
837 manual_clock::advance(1s
);
840 check_timed_out(std::move(f2
));
841 BOOST_REQUIRE(!f3
.available());
845 BOOST_REQUIRE_EQUAL(42, f3
.get0());
849 SEASTAR_TEST_CASE(test_when_all_succeed_tuples
) {
850 return seastar::when_all_succeed(
851 make_ready_future
<>(),
852 make_ready_future
<sstring
>("hello world"),
853 make_ready_future
<int>(42),
854 make_ready_future
<>(),
855 make_ready_future
<int, sstring
>(84, "hi"),
856 make_ready_future
<bool>(true)
857 ).then([] (sstring msg
, int v
, std::tuple
<int, sstring
> t
, bool b
) {
858 BOOST_REQUIRE_EQUAL(msg
, "hello world");
859 BOOST_REQUIRE_EQUAL(v
, 42);
860 BOOST_REQUIRE_EQUAL(std::get
<0>(t
), 84);
861 BOOST_REQUIRE_EQUAL(std::get
<1>(t
), "hi");
862 BOOST_REQUIRE_EQUAL(b
, true);
864 return seastar::when_all_succeed(
865 make_exception_future
<>(42),
866 make_ready_future
<sstring
>("hello world"),
867 make_exception_future
<int>(43),
868 make_ready_future
<>()
869 ).then([] (sstring
, int) {
870 BOOST_FAIL("shouldn't reach");
872 }).handle_exception([] (auto excp
) {
874 std::rethrow_exception(excp
);
876 BOOST_REQUIRE(v
== 42 || v
== 43);
880 }).then([] (auto ret
) {
886 SEASTAR_TEST_CASE(test_when_all_succeed_vector
) {
887 std::vector
<future
<>> vecs
;
888 vecs
.emplace_back(make_ready_future
<>());
889 vecs
.emplace_back(make_ready_future
<>());
890 vecs
.emplace_back(make_ready_future
<>());
891 vecs
.emplace_back(make_ready_future
<>());
892 return seastar::when_all_succeed(vecs
.begin(), vecs
.end()).then([] {
893 std::vector
<future
<>> vecs
;
894 vecs
.emplace_back(make_ready_future
<>());
895 vecs
.emplace_back(make_ready_future
<>());
896 vecs
.emplace_back(make_exception_future
<>(42));
897 vecs
.emplace_back(make_exception_future
<>(43));
898 return seastar::when_all_succeed(vecs
.begin(), vecs
.end());
900 BOOST_FAIL("shouldn't reach");
902 }).handle_exception([] (auto excp
) {
904 std::rethrow_exception(excp
);
906 BOOST_REQUIRE(v
== 42 || v
== 43);
910 }).then([] (auto ret
) {
913 std::vector
<future
<int>> vecs
;
914 vecs
.emplace_back(make_ready_future
<int>(1));
915 vecs
.emplace_back(make_ready_future
<int>(2));
916 vecs
.emplace_back(make_ready_future
<int>(3));
917 return seastar::when_all_succeed(vecs
.begin(), vecs
.end());
918 }).then([] (std::vector
<int> vals
) {
919 BOOST_REQUIRE_EQUAL(vals
.size(), 3u);
920 BOOST_REQUIRE_EQUAL(vals
[0], 1);
921 BOOST_REQUIRE_EQUAL(vals
[1], 2);
922 BOOST_REQUIRE_EQUAL(vals
[2], 3);
924 std::vector
<future
<int>> vecs
;
925 vecs
.emplace_back(make_ready_future
<int>(1));
926 vecs
.emplace_back(make_ready_future
<int>(2));
927 vecs
.emplace_back(make_exception_future
<int>(42));
928 vecs
.emplace_back(make_exception_future
<int>(43));
929 return seastar::when_all_succeed(vecs
.begin(), vecs
.end());
930 }).then([] (std::vector
<int>) {
931 BOOST_FAIL("shouldn't reach");
933 }).handle_exception([] (auto excp
) {
935 std::rethrow_exception(excp
);
937 BOOST_REQUIRE(v
== 42 || v
== 43);
941 }).then([] (auto ret
) {
946 SEASTAR_TEST_CASE(test_futurize_mutable
) {
948 return seastar::repeat([count
]() mutable {
951 return seastar::stop_iteration::yes
;
953 return seastar::stop_iteration::no
;