diff options
author | Jason Carey <jcarey@argv.me> | 2018-11-20 18:27:59 -0500 |
---|---|---|
committer | Jason Carey <jcarey@argv.me> | 2018-12-06 14:35:57 -0500 |
commit | 963710b5c75e454d7217fda41d9ed98908d2b753 (patch) | |
tree | fe33ddcb42042ef5e2045baa78176e3dc88a3173 /src/mongo/util/future_test_future_move_only.cpp | |
parent | 9176275df0282d9f153a25b5ce5a33a53d51b045 (diff) | |
download | mongo-963710b5c75e454d7217fda41d9ed98908d2b753.tar.gz |
SERVER-38184 add onCompletion to future
a then() style callback that also covers the error case
Diffstat (limited to 'src/mongo/util/future_test_future_move_only.cpp')
-rw-r--r-- | src/mongo/util/future_test_future_move_only.cpp | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/src/mongo/util/future_test_future_move_only.cpp b/src/mongo/util/future_test_future_move_only.cpp index f7b706ecee3..5a428601023 100644 --- a/src/mongo/util/future_test_future_move_only.cpp +++ b/src/mongo/util/future_test_future_move_only.cpp @@ -564,5 +564,215 @@ TEST(Future_MoveOnly, Fail_tapAll_Overloaded) { }); } +TEST(Future_MoveOnly, Success_onCompletionSimple) { + FUTURE_SUCCESS_TEST( + [] { return Widget(1); }, + [](Future<Widget>&& fut) { + ASSERT_EQ(std::move(fut) + .onCompletion([](StatusWith<Widget> i) { return i.getValue() + 2; }) + .get(), + 3); + }); +} + +TEST(Future_MoveOnly, Success_onCompletionMultiOverload) { + FUTURE_SUCCESS_TEST([] { return Widget(1); }, + [](Future<Widget>&& fut) { + struct Callback { + Widget operator()(const Widget& i) { + called = true; + return i + 2; + } + Widget operator()(Status status) { + MONGO_UNREACHABLE; + } + bool called = false; + }; + Callback callback; + + ASSERT_EQ(std::move(fut).onCompletion(std::ref(callback)).get(), 3); + + ASSERT(callback.called); + }); +} + +TEST(Future_MoveOnly, Success_onCompletionVoid) { + FUTURE_SUCCESS_TEST( + [] { return Widget(1); }, + [](Future<Widget>&& fut) { + ASSERT_EQ(std::move(fut) + .onCompletion([](StatusWith<Widget> i) { ASSERT_EQ(i.getValue(), 1); }) + .onCompletion([](Status s) { + ASSERT_OK(s); + return Widget(3); + }) + .get(), + 3); + }); +} + +TEST(Future_MoveOnly, Success_onCompletionStatus) { + FUTURE_SUCCESS_TEST([] { return Widget(1); }, + [](Future<Widget>&& fut) { + ASSERT_EQ(std::move(fut) + .onCompletion([](StatusWith<Widget> i) { + ASSERT_EQ(i.getValue(), 1); + return Status::OK(); + }) + .onCompletion([](Status s) { + ASSERT_OK(s); + return Widget(3); + }) + .get(), + 3); + }); +} + +TEST(Future_MoveOnly, Success_onCompletionError_Status) { + FUTURE_SUCCESS_TEST([] { return Widget(1); }, + [](Future<Widget>&& fut) { + auto fut2 = std::move(fut).onCompletion([](StatusWith<Widget> i) { + return Status(ErrorCodes::BadValue, "oh no!"); + }); + MONGO_STATIC_ASSERT(std::is_same<decltype(fut2), Future<void>>::value); + ASSERT_EQ(fut2.getNoThrow(), ErrorCodes::BadValue); + }); +} + +TEST(Future_MoveOnly, Success_onCompletionError_StatusWith) { + FUTURE_SUCCESS_TEST([] { return Widget(1); }, + [](Future<Widget>&& fut) { + auto fut2 = std::move(fut).onCompletion([](StatusWith<Widget> i) { + return StatusWith<double>(ErrorCodes::BadValue, "oh no!"); + }); + MONGO_STATIC_ASSERT( + std::is_same<decltype(fut2), Future<double>>::value); + ASSERT_EQ(fut2.getNoThrow(), ErrorCodes::BadValue); + }); +} + +TEST(Future_MoveOnly, Success_onCompletionFutureImmediate) { + FUTURE_SUCCESS_TEST([] { return Widget(1); }, + [](Future<Widget>&& fut) { + ASSERT_EQ(std::move(fut) + .onCompletion([](StatusWith<Widget> i) { + return Future<Widget>::makeReady( + Widget(i.getValue() + 2)); + }) + .get(), + 3); + }); +} + +TEST(Future_MoveOnly, Success_onCompletionFutureReady) { + FUTURE_SUCCESS_TEST([] { return Widget(1); }, + [](Future<Widget>&& fut) { + ASSERT_EQ(std::move(fut) + .onCompletion([](StatusWith<Widget> i) { + auto pf = makePromiseFuture<Widget>(); + pf.promise.emplaceValue(i.getValue() + 2); + return std::move(pf.future); + }) + .get(), + 3); + }); +} + +TEST(Future_MoveOnly, Success_onCompletionFutureAsync) { + FUTURE_SUCCESS_TEST([] { return Widget(1); }, + [](Future<Widget>&& fut) { + ASSERT_EQ(std::move(fut) + .onCompletion([&](StatusWith<Widget> i) { + return async( + [i = i.getValue().val] { return Widget(i + 2); }); + }) + .get(), + 3); + }); +} + +TEST(Future_MoveOnly, Success_onCompletionFutureAsyncThrow) { + FUTURE_SUCCESS_TEST([] { return Widget(1); }, + [](Future<Widget>&& fut) { + ASSERT_EQ(std::move(fut) + .onCompletion([](StatusWith<Widget> i) { + uasserted(ErrorCodes::BadValue, "oh no!"); + return Future<Widget>(); + }) + .getNoThrow(), + ErrorCodes::BadValue); + }); +} + +TEST(Future_MoveOnly, Fail_onCompletionSimple) { + FUTURE_FAIL_TEST<Widget>([](Future<Widget>&& fut) { + ASSERT_EQ(std::move(fut) + .onCompletion([](StatusWith<Widget> i) { + ASSERT_NOT_OK(i); + return i.getStatus(); + }) + .getNoThrow(), + failStatus()); + }); +} + +TEST(Future_MoveOnly, Fail_onCompletionFutureAsync) { + FUTURE_FAIL_TEST<Widget>([](Future<Widget>&& fut) { + ASSERT_EQ(std::move(fut) + .onCompletion([](StatusWith<Widget> i) { + ASSERT_NOT_OK(i); + return i.getStatus(); + }) + .getNoThrow(), + failStatus()); + }); +} + +TEST(Future_MoveOnly, Fail_onCompletionError_throw) { + FUTURE_FAIL_TEST<Widget>([](Future<Widget>&& fut) { + auto fut2 = std::move(fut).onCompletion([](StatusWith<Widget> s) -> Widget { + ASSERT_EQ(s.getStatus(), failStatus()); + uasserted(ErrorCodes::BadValue, "oh no!"); + }); + ASSERT_EQ(std::move(fut2).getNoThrow(), ErrorCodes::BadValue); + }); +} + +TEST(Future_MoveOnly, Fail_onCompletionError_StatusWith) { + FUTURE_FAIL_TEST<Widget>([](Future<Widget>&& fut) { + auto fut2 = std::move(fut).onCompletion([](StatusWith<Widget> s) { + ASSERT_EQ(s.getStatus(), failStatus()); + return StatusWith<Widget>(ErrorCodes::BadValue, "oh no!"); + }); + ASSERT_EQ(std::move(fut2).getNoThrow(), ErrorCodes::BadValue); + }); +} + +TEST(Future_MoveOnly, Fail_onCompletionFutureImmediate) { + FUTURE_FAIL_TEST<Widget>([](Future<Widget>&& fut) { + ASSERT_EQ(std::move(fut) + .onCompletion([](StatusWith<Widget> s) { + ASSERT_EQ(s.getStatus(), failStatus()); + return Future<Widget>::makeReady(Widget(3)); + }) + .get(), + 3); + }); +} + +TEST(Future_MoveOnly, Fail_onCompletionFutureReady) { + FUTURE_FAIL_TEST<Widget>([](Future<Widget>&& fut) { + ASSERT_EQ(std::move(fut) + .onCompletion([](StatusWith<Widget> s) { + ASSERT_EQ(s.getStatus(), failStatus()); + auto pf = makePromiseFuture<Widget>(); + pf.promise.emplaceValue(3); + return std::move(pf.future); + }) + .get(), + 3); + }); +} + } // namespace } // namespace mongo |