diff options
-rw-r--r-- | SConstruct | 6 | ||||
-rw-r--r-- | src/mongo/util/future_test_executor_future.cpp | 115 | ||||
-rw-r--r-- | src/mongo/util/future_test_future_int.cpp | 403 | ||||
-rw-r--r-- | src/mongo/util/future_test_future_move_only.cpp | 624 | ||||
-rw-r--r-- | src/mongo/util/future_test_future_void.cpp | 508 | ||||
-rw-r--r-- | src/mongo/util/future_test_utils.h | 7 |
6 files changed, 789 insertions, 874 deletions
diff --git a/SConstruct b/SConstruct index 38baba8e897..c5113604c86 100644 --- a/SConstruct +++ b/SConstruct @@ -3648,12 +3648,6 @@ def doConfigure(myenv): # myenv.Append( CCFLAGS=["/Zc:inline"]) - if myenv.ToolchainIs('msvc') and get_option('cxx-std') == "20": - # Disable the updated lambda processor, which is on by default in - # /std:C++20 mode. The new lambda processor cannot compile the nested - # lambda expression usage in util/future_test_* files. See - # SERVER-62480. Must appear after `/std:c++20` to override it. - env.Append( CCFLAGS=["/Zc:lambda-"] ) if myenv.ToolchainIs('gcc', 'clang'): diff --git a/src/mongo/util/future_test_executor_future.cpp b/src/mongo/util/future_test_executor_future.cpp index c4d2b43a520..779aeb749a6 100644 --- a/src/mongo/util/future_test_executor_future.cpp +++ b/src/mongo/util/future_test_executor_future.cpp @@ -36,9 +36,10 @@ namespace mongo { namespace { + TEST(Executor_Future, Success_getAsync) { FUTURE_SUCCESS_TEST([] {}, - [](/*Future<void>*/ auto&& fut) { + [](auto&& fut) { auto exec = InlineQueuedCountingExecutor::make(); auto pf = makePromiseFuture<void>(); ExecutorFuture<void>(exec).thenRunOn(exec).getAsync( @@ -53,7 +54,7 @@ TEST(Executor_Future, Success_getAsync) { TEST(Executor_Future, Reject_getAsync) { FUTURE_SUCCESS_TEST([] {}, - [](/*Future<void>*/ auto&& fut) { + [](auto&& fut) { auto exec = RejectingExecutor::make(); auto pf = makePromiseFuture<void>(); std::move(fut).thenRunOn(exec).getAsync( @@ -69,7 +70,7 @@ TEST(Executor_Future, Reject_getAsync) { TEST(Executor_Future, Success_then) { FUTURE_SUCCESS_TEST([] {}, - [](/*Future<void>*/ auto&& fut) { + [](auto&& fut) { auto exec = InlineQueuedCountingExecutor::make(); ASSERT_EQ(std::move(fut).thenRunOn(exec).then([]() { return 3; }).get(), 3); @@ -78,7 +79,7 @@ TEST(Executor_Future, Success_then) { } TEST(Executor_Future, Reject_then) { FUTURE_SUCCESS_TEST([] {}, - [](/*Future<void>*/ auto&& fut) { + [](auto&& fut) { auto exec = RejectingExecutor::make(); ASSERT_EQ(std::move(fut) .thenRunOn(exec) @@ -92,7 +93,7 @@ TEST(Executor_Future, Reject_then) { } TEST(Executor_Future, Fail_then) { - FUTURE_FAIL_TEST<void>([](/*Future<void>*/ auto&& fut) { + FUTURE_FAIL_TEST<void>([](auto&& fut) { auto exec = InlineQueuedCountingExecutor::make(); ASSERT_EQ(std::move(fut) .thenRunOn(exec) @@ -108,7 +109,7 @@ TEST(Executor_Future, Fail_then) { TEST(Executor_Future, Success_onError) { FUTURE_SUCCESS_TEST([] { return 3; }, - [](/*Future<int>*/ auto&& fut) { + [](auto&& fut) { auto exec = InlineQueuedCountingExecutor::make(); ASSERT_EQ(std::move(fut) .thenRunOn(exec) @@ -123,11 +124,11 @@ TEST(Executor_Future, Success_onError) { } TEST(Executor_Future, Fail_onErrorSimple) { - FUTURE_FAIL_TEST<int>([](/*Future<int>*/ auto&& fut) { + FUTURE_FAIL_TEST<int>([](auto&& fut) { auto exec = InlineQueuedCountingExecutor::make(); ASSERT_EQ(std::move(fut) .thenRunOn(exec) - .onError([](Status s) { + .onError([](Status s) FTU_LAMBDA_R(int) { ASSERT_EQ(s, failStatus()); return 3; }) @@ -138,63 +139,65 @@ TEST(Executor_Future, Fail_onErrorSimple) { } TEST(Executor_Future, Fail_onErrorCode_OtherCode) { - FUTURE_FAIL_TEST<void>([](/*Future<void>*/ auto&& fut) { + FUTURE_FAIL_TEST<void>([](auto&& fut) { auto exec = InlineQueuedCountingExecutor::make(); - ASSERT_EQ( - std::move(fut) - .thenRunOn(exec) - .template onError<ErrorCodes::BadValue>([](Status s) { FAIL("wrong code, sir"); }) - .getNoThrow(), - failStatus()); + ASSERT_EQ(std::move(fut) + .thenRunOn(exec) + .template onError<ErrorCodes::BadValue>( + [](Status s) FTU_LAMBDA_R(void) { FAIL("wrong code, sir"); }) + .getNoThrow(), + failStatus()); ASSERT_EQ(exec->tasksRun.load(), 0); }); } TEST(Executor_Future, Success_then_onError_onError_then) { - FUTURE_SUCCESS_TEST([] {}, - [](/*Future<void>*/ auto&& fut) { - auto exec = InlineQueuedCountingExecutor::make(); - ASSERT_EQ( - std::move(fut) - .thenRunOn(exec) - .then([] { return failStatus(); }) - .onError([](Status s) { ASSERT_EQ(s, failStatus()); }) - .onError([](Status) { FAIL("how did you get this number?"); }) - .then([] { return 3; }) - .get(), - 3); - - // 1 would also be valid if we did the optimization to not reschedule if - // running on the same executor. - ASSERT_EQ(exec->tasksRun.load(), 3); - }); + FUTURE_SUCCESS_TEST( + [] {}, + [](auto&& fut) { + auto exec = InlineQueuedCountingExecutor::make(); + ASSERT_EQ(std::move(fut) + .thenRunOn(exec) + .then([] { return failStatus(); }) + .onError([](Status s) FTU_LAMBDA_R(void) { ASSERT_EQ(s, failStatus()); }) + .onError([](Status) + FTU_LAMBDA_R(void) { FAIL("how did you get this number?"); }) + .then([] { return 3; }) + .get(), + 3); + + // 1 would also be valid if we did the optimization to not reschedule if + // running on the same executor. + ASSERT_EQ(exec->tasksRun.load(), 3); + }); } TEST(Executor_Future, Success_reject_recoverToFallback) { - FUTURE_SUCCESS_TEST([] {}, - [](/*Future<void>*/ auto&& fut) { - auto rejecter = RejectingExecutor::make(); - auto accepter = InlineQueuedCountingExecutor::make(); - - auto res = std::move(fut) - .thenRunOn(rejecter) - .then([] { FAIL("then()"); }) - .onError([](Status) { FAIL("onError()"); }) - .onCompletion([](Status) { FAIL("onCompletion()"); }) - .thenRunOn(accepter) - .then([] { - FAIL("error?"); - return 42; - }) - .onError([](Status s) { - ASSERT_EQ(s, ErrorCodes::ShutdownInProgress); - return 3; - }) - .get(); - ASSERT_EQ(res, 3); - - ASSERT_EQ(accepter->tasksRun.load(), 1); - }); + FUTURE_SUCCESS_TEST( + [] {}, + [](auto&& fut) { + auto rejecter = RejectingExecutor::make(); + auto accepter = InlineQueuedCountingExecutor::make(); + + auto res = std::move(fut) + .thenRunOn(rejecter) + .then([] { FAIL("then()"); }) + .onError([](Status) FTU_LAMBDA_R(void) { FAIL("onError()"); }) + .onCompletion([](Status) FTU_LAMBDA_R(void) { FAIL("onCompletion()"); }) + .thenRunOn(accepter) + .then([] { + FAIL("error?"); + return 42; + }) + .onError([](Status s) FTU_LAMBDA_R(int) { + ASSERT_EQ(s, ErrorCodes::ShutdownInProgress); + return 3; + }) + .get(); + ASSERT_EQ(res, 3); + + ASSERT_EQ(accepter->tasksRun.load(), 1); + }); } } // namespace } // namespace mongo diff --git a/src/mongo/util/future_test_future_int.cpp b/src/mongo/util/future_test_future_int.cpp index 96023b210d3..edb7394cc77 100644 --- a/src/mongo/util/future_test_future_int.cpp +++ b/src/mongo/util/future_test_future_int.cpp @@ -40,45 +40,38 @@ namespace mongo { namespace { TEST(Future, Success_getLvalue) { - FUTURE_SUCCESS_TEST([] { return 1; }, - [](/*Future<int>*/ auto&& fut) { ASSERT_EQ(fut.get(), 1); }); + FUTURE_SUCCESS_TEST([] { return 1; }, [](auto&& fut) { ASSERT_EQ(fut.get(), 1); }); } TEST(Future, Success_getConstLvalue) { - FUTURE_SUCCESS_TEST([] { return 1; }, - [](const /*Future<int>*/ auto& fut) { ASSERT_EQ(fut.get(), 1); }); + FUTURE_SUCCESS_TEST([] { return 1; }, [](const auto& fut) { ASSERT_EQ(fut.get(), 1); }); } TEST(Future, Success_getRvalue) { - FUTURE_SUCCESS_TEST([] { return 1; }, - [](/*Future<int>*/ auto&& fut) { ASSERT_EQ(std::move(fut).get(), 1); }); + FUTURE_SUCCESS_TEST([] { return 1; }, [](auto&& fut) { ASSERT_EQ(std::move(fut).get(), 1); }); } TEST(Future, Success_getNothrowLvalue) { - FUTURE_SUCCESS_TEST([] { return 1; }, - [](/*Future<int>*/ auto&& fut) { ASSERT_EQ(fut.getNoThrow(), 1); }); + FUTURE_SUCCESS_TEST([] { return 1; }, [](auto&& fut) { ASSERT_EQ(fut.getNoThrow(), 1); }); } TEST(Future, Success_getNothrowConstLvalue) { - FUTURE_SUCCESS_TEST([] { return 1; }, - [](const /*Future<int>*/ auto& fut) { ASSERT_EQ(fut.getNoThrow(), 1); }); + FUTURE_SUCCESS_TEST([] { return 1; }, [](const auto& fut) { ASSERT_EQ(fut.getNoThrow(), 1); }); } TEST(Future, Success_getNothrowRvalue) { - FUTURE_SUCCESS_TEST( - [] { return 1; }, - [](/*Future<int>*/ auto&& fut) { ASSERT_EQ(std::move(fut).getNoThrow(), 1); }); + FUTURE_SUCCESS_TEST([] { return 1; }, + [](auto&& fut) { ASSERT_EQ(std::move(fut).getNoThrow(), 1); }); } TEST(Future, Success_semi_get) { - FUTURE_SUCCESS_TEST( - [] { return 1; }, - [](/*Future<int>*/ auto&& fut) { ASSERT_EQ(std::move(fut).semi().get(), 1); }); + FUTURE_SUCCESS_TEST([] { return 1; }, + [](auto&& fut) { ASSERT_EQ(std::move(fut).semi().get(), 1); }); } TEST(Future, Success_getAsync) { FUTURE_SUCCESS_TEST([] { return 1; }, - [](/*Future<int>*/ auto&& fut) { + [](auto&& fut) { auto pf = makePromiseFuture<int>(); std::move(fut).getAsync( [outside = std::move(pf.promise)](StatusWith<int> sw) mutable { @@ -90,41 +83,36 @@ TEST(Future, Success_getAsync) { } TEST(Future, Fail_getLvalue) { - FUTURE_FAIL_TEST<int>([](/*Future<int>*/ auto&& fut) { ASSERT_THROWS_failStatus(fut.get()); }); + FUTURE_FAIL_TEST<int>([](auto&& fut) { ASSERT_THROWS_failStatus(fut.get()); }); } TEST(Future, Fail_getConstLvalue) { - FUTURE_FAIL_TEST<int>( - [](const /*Future<int>*/ auto& fut) { ASSERT_THROWS_failStatus(fut.get()); }); + FUTURE_FAIL_TEST<int>([](const auto& fut) { ASSERT_THROWS_failStatus(fut.get()); }); } TEST(Future, Fail_getRvalue) { - FUTURE_FAIL_TEST<int>( - [](/*Future<int>*/ auto&& fut) { ASSERT_THROWS_failStatus(std::move(fut).get()); }); + FUTURE_FAIL_TEST<int>([](auto&& fut) { ASSERT_THROWS_failStatus(std::move(fut).get()); }); } TEST(Future, Fail_getNothrowLvalue) { - FUTURE_FAIL_TEST<int>( - [](/*Future<int>*/ auto&& fut) { ASSERT_EQ(fut.getNoThrow(), failStatus()); }); + FUTURE_FAIL_TEST<int>([](auto&& fut) { ASSERT_EQ(fut.getNoThrow(), failStatus()); }); } TEST(Future, Fail_getNothrowConstLvalue) { - FUTURE_FAIL_TEST<int>( - [](const /*Future<int>*/ auto& fut) { ASSERT_EQ(fut.getNoThrow(), failStatus()); }); + FUTURE_FAIL_TEST<int>([](const auto& fut) { ASSERT_EQ(fut.getNoThrow(), failStatus()); }); } TEST(Future, Fail_getNothrowRvalue) { - FUTURE_FAIL_TEST<int>( - [](/*Future<int>*/ auto&& fut) { ASSERT_EQ(std::move(fut).getNoThrow(), failStatus()); }); + FUTURE_FAIL_TEST<int>([](auto&& fut) { ASSERT_EQ(std::move(fut).getNoThrow(), failStatus()); }); } TEST(Future, Fail_semi_get) { FUTURE_FAIL_TEST<int>( - [](/*Future<int>*/ auto&& fut) { ASSERT_THROWS_failStatus(std::move(fut).semi().get()); }); + [](auto&& fut) { ASSERT_THROWS_failStatus(std::move(fut).semi().get()); }); } TEST(Future, Fail_getAsync) { - FUTURE_FAIL_TEST<int>([](/*Future<int>*/ auto&& fut) { + FUTURE_FAIL_TEST<int>([](auto&& fut) { auto pf = makePromiseFuture<int>(); std::move(fut).getAsync([outside = std::move(pf.promise)](StatusWith<int> sw) mutable { ASSERT(!sw.isOK()); @@ -136,7 +124,7 @@ TEST(Future, Fail_getAsync) { TEST(Future, Success_isReady) { FUTURE_SUCCESS_TEST([] { return 1; }, - [](/*Future<int>*/ auto&& fut) { + [](auto&& fut) { const auto id = stdx::this_thread::get_id(); while (!fut.isReady()) { } @@ -148,7 +136,7 @@ TEST(Future, Success_isReady) { } TEST(Future, Fail_isReady) { - FUTURE_FAIL_TEST<int>([](/*Future<int>*/ auto&& fut) { + FUTURE_FAIL_TEST<int>([](auto&& fut) { const auto id = stdx::this_thread::get_id(); while (!fut.isReady()) { } @@ -161,7 +149,7 @@ TEST(Future, Fail_isReady) { TEST(Future, Success_wait) { FUTURE_SUCCESS_TEST([] { return 1; }, - [](/*Future<int>*/ auto&& fut) { + [](auto&& fut) { fut.wait(); ASSERT_EQ(fut.get(), 1); }); @@ -169,21 +157,21 @@ TEST(Future, Success_wait) { TEST(Future, Success_waitNoThrow) { FUTURE_SUCCESS_TEST([] { return 1; }, - [](/*Future<int>*/ auto&& fut) { + [](auto&& fut) { ASSERT_OK(fut.waitNoThrow()); ASSERT_EQ(fut.get(), 1); }); } TEST(Future, Fail_wait) { - FUTURE_FAIL_TEST<int>([](/*Future<int>*/ auto&& fut) { + FUTURE_FAIL_TEST<int>([](auto&& fut) { fut.wait(); ASSERT_THROWS_failStatus(fut.get()); }); } TEST(Future, Fail_waitNoThrow) { - FUTURE_FAIL_TEST<int>([](/*Future<int>*/ auto&& fut) { + FUTURE_FAIL_TEST<int>([](auto&& fut) { ASSERT_OK(fut.waitNoThrow()); ASSERT_THROWS_failStatus(fut.get()); }); @@ -204,23 +192,21 @@ TEST(Future, isReady_TSAN_OK) { } TEST(Future, Success_thenSimple) { - FUTURE_SUCCESS_TEST([] { return 1; }, - [](/*Future<int>*/ auto&& fut) { - ASSERT_EQ(std::move(fut).then([](int i) { return i + 2; }).get(), 3); - }); + FUTURE_SUCCESS_TEST( + [] { return 1; }, + [](auto&& fut) { ASSERT_EQ(std::move(fut).then([](int i) { return i + 2; }).get(), 3); }); } TEST(Future, Success_thenSimpleAuto) { - FUTURE_SUCCESS_TEST([] { return 1; }, - [](/*Future<int>*/ auto&& fut) { - ASSERT_EQ(std::move(fut).then([](auto i) { return i + 2; }).get(), 3); - }); + FUTURE_SUCCESS_TEST( + [] { return 1; }, + [](auto&& fut) { ASSERT_EQ(std::move(fut).then([](auto i) { return i + 2; }).get(), 3); }); } TEST(Future, Success_thenVoid) { FUTURE_SUCCESS_TEST( [] { return 1; }, - [](/*Future<int>*/ auto&& fut) { + [](auto&& fut) { ASSERT_EQ( std::move(fut).then([](int i) { ASSERT_EQ(i, 1); }).then([] { return 3; }).get(), 3); @@ -229,7 +215,7 @@ TEST(Future, Success_thenVoid) { TEST(Future, Success_thenStatus) { FUTURE_SUCCESS_TEST([] { return 1; }, - [](/*Future<int>*/ auto&& fut) { + [](auto&& fut) { ASSERT_EQ(std::move(fut) .then([](int i) { ASSERT_EQ(i, 1); @@ -244,7 +230,7 @@ TEST(Future, Success_thenStatus) { TEST(Future, Success_thenError_Status) { FUTURE_SUCCESS_TEST( [] { return 1; }, - [](/*Future<int>*/ auto&& fut) { + [](auto&& fut) { auto fut2 = std::move(fut).then([](int i) { return Status(ErrorCodes::BadValue, "oh no!"); }); static_assert(future_details::isFutureLike<decltype(fut2)>); @@ -256,7 +242,7 @@ TEST(Future, Success_thenError_Status) { TEST(Future, Success_thenError_StatusWith) { FUTURE_SUCCESS_TEST( [] { return 1; }, - [](/*Future<int>*/ auto&& fut) { + [](auto&& fut) { auto fut2 = std::move(fut).then( [](int i) { return StatusWith<double>(ErrorCodes::BadValue, "oh no!"); }); static_assert(future_details::isFutureLike<decltype(fut2)>); @@ -268,7 +254,7 @@ TEST(Future, Success_thenError_StatusWith) { TEST(Future, Success_thenFutureImmediate) { FUTURE_SUCCESS_TEST( [] { return 1; }, - [](/*Future<int>*/ auto&& fut) { + [](auto&& fut) { ASSERT_EQ( std::move(fut).then([](int i) { return Future<int>::makeReady(i + 2); }).get(), 3); }); @@ -276,7 +262,7 @@ TEST(Future, Success_thenFutureImmediate) { TEST(Future, Success_thenFutureReady) { FUTURE_SUCCESS_TEST([] { return 1; }, - [](/*Future<int>*/ auto&& fut) { + [](auto&& fut) { ASSERT_EQ(std::move(fut) .then([](int i) { auto pf = makePromiseFuture<int>(); @@ -291,7 +277,7 @@ TEST(Future, Success_thenFutureReady) { TEST(Future, Success_thenFutureAsync) { FUTURE_SUCCESS_TEST( [] { return 1; }, - [](/*Future<int>*/ auto&& fut) { + [](auto&& fut) { ASSERT_EQ(std::move(fut).then([](int i) { return async([i] { return i + 2; }); }).get(), 3); }); @@ -299,7 +285,7 @@ TEST(Future, Success_thenFutureAsync) { TEST(Future, Success_thenSemiFutureAsync) { FUTURE_SUCCESS_TEST([] { return 1; }, - [](/*Future<int>*/ auto&& fut) { + [](auto&& fut) { ASSERT_EQ( std::move(fut) .then([](int i) { return async([i] { return i + 2; }).semi(); }) @@ -310,7 +296,7 @@ TEST(Future, Success_thenSemiFutureAsync) { TEST(Future, Success_thenFutureAsyncThrow) { FUTURE_SUCCESS_TEST([] { return 1; }, - [](/*Future<int>*/ auto&& fut) { + [](auto&& fut) { ASSERT_EQ(std::move(fut) .then([](int i) { uasserted(ErrorCodes::BadValue, "oh no!"); @@ -322,7 +308,7 @@ TEST(Future, Success_thenFutureAsyncThrow) { } TEST(Future, Fail_thenSimple) { - FUTURE_FAIL_TEST<int>([](/*Future<int>*/ auto&& fut) { + FUTURE_FAIL_TEST<int>([](auto&& fut) { ASSERT_EQ(std::move(fut) .then([](int i) { FAIL("then() callback was called"); @@ -334,7 +320,7 @@ TEST(Future, Fail_thenSimple) { } TEST(Future, Fail_thenFutureAsync) { - FUTURE_FAIL_TEST<int>([](/*Future<int>*/ auto&& fut) { + FUTURE_FAIL_TEST<int>([](auto&& fut) { ASSERT_EQ(std::move(fut) .then([](int i) { FAIL("then() callback was called"); @@ -347,9 +333,9 @@ TEST(Future, Fail_thenFutureAsync) { TEST(Future, Success_onErrorSimple) { FUTURE_SUCCESS_TEST([] { return 1; }, - [](/*Future<int>*/ auto&& fut) { + [](auto&& fut) { ASSERT_EQ(std::move(fut) - .onError([](Status) { + .onError([](Status) FTU_LAMBDA_R(int) { FAIL("onError() callback was called"); return 0; }) @@ -361,9 +347,9 @@ TEST(Future, Success_onErrorSimple) { TEST(Future, Success_onErrorFutureAsync) { FUTURE_SUCCESS_TEST([] { return 1; }, - [](/*Future<int>*/ auto&& fut) { + [](auto&& fut) { ASSERT_EQ(std::move(fut) - .onError([](Status) { + .onError([](Status) FTU_LAMBDA_R(Future<int>) { FAIL("onError() callback was called"); return Future<int>(); }) @@ -374,9 +360,9 @@ TEST(Future, Success_onErrorFutureAsync) { } TEST(Future, Fail_onErrorSimple) { - FUTURE_FAIL_TEST<int>([](/*Future<int>*/ auto&& fut) { + FUTURE_FAIL_TEST<int>([](auto&& fut) { ASSERT_EQ(std::move(fut) - .onError([](Status s) { + .onError([](Status s) FTU_LAMBDA_R(int) { ASSERT_EQ(s, failStatus()); return 3; }) @@ -386,7 +372,7 @@ TEST(Future, Fail_onErrorSimple) { } TEST(Future, Fail_onErrorError_throw) { - FUTURE_FAIL_TEST<int>([](/*Future<int>*/ auto&& fut) { + FUTURE_FAIL_TEST<int>([](auto&& fut) { auto fut2 = std::move(fut).onError([](Status s) -> int { ASSERT_EQ(s, failStatus()); uasserted(ErrorCodes::BadValue, "oh no!"); @@ -396,8 +382,8 @@ TEST(Future, Fail_onErrorError_throw) { } TEST(Future, Fail_onErrorError_StatusWith) { - FUTURE_FAIL_TEST<int>([](/*Future<int>*/ auto&& fut) { - auto fut2 = std::move(fut).onError([](Status s) { + FUTURE_FAIL_TEST<int>([](auto&& fut) { + auto fut2 = std::move(fut).onError([](Status s) FTU_LAMBDA_R(StatusWith<int>) { ASSERT_EQ(s, failStatus()); return StatusWith<int>(ErrorCodes::BadValue, "oh no!"); }); @@ -406,9 +392,9 @@ TEST(Future, Fail_onErrorError_StatusWith) { } TEST(Future, Fail_onErrorFutureImmediate) { - FUTURE_FAIL_TEST<int>([](/*Future<int>*/ auto&& fut) { + FUTURE_FAIL_TEST<int>([](auto&& fut) { ASSERT_EQ(std::move(fut) - .onError([](Status s) { + .onError([](Status s) FTU_LAMBDA_R(Future<int>) { ASSERT_EQ(s, failStatus()); return Future<int>::makeReady(3); }) @@ -418,9 +404,9 @@ TEST(Future, Fail_onErrorFutureImmediate) { } TEST(Future, Fail_onErrorFutureReady) { - FUTURE_FAIL_TEST<int>([](/*Future<int>*/ auto&& fut) { + FUTURE_FAIL_TEST<int>([](auto&& fut) { ASSERT_EQ(std::move(fut) - .onError([](Status s) { + .onError([](Status s) FTU_LAMBDA_R(Future<int>) { ASSERT_EQ(s, failStatus()); auto pf = makePromiseFuture<int>(); pf.promise.emplaceValue(3); @@ -432,7 +418,7 @@ TEST(Future, Fail_onErrorFutureReady) { } TEST(Future, Fail_onErrorFutureAsync) { - FUTURE_FAIL_TEST<int>([](/*Future<int>*/ auto&& fut) { + FUTURE_FAIL_TEST<int>([](auto&& fut) { ASSERT_EQ(std::move(fut) .onError([](Status s) { ASSERT_EQ(s, failStatus()); @@ -445,12 +431,13 @@ TEST(Future, Fail_onErrorFutureAsync) { TEST(Future, Success_onErrorCode) { FUTURE_SUCCESS_TEST([] { return 1; }, - [](/*Future<int>*/ auto&& fut) { + [](auto&& fut) { ASSERT_EQ(std::move(fut) - .template onError<ErrorCodes::InternalError>([](Status) { - FAIL("onError<code>() callback was called"); - return 0; - }) + .template onError<ErrorCodes::InternalError>( + [](Status) FTU_LAMBDA_R(int) { + FAIL("onError<code>() callback was called"); + return 0; + }) .then([](int i) { return i + 2; }) .get(), 3); @@ -458,41 +445,42 @@ TEST(Future, Success_onErrorCode) { } TEST(Future, Fail_onErrorCodeMatch) { - FUTURE_FAIL_TEST<int>([](/*Future<int>*/ auto&& fut) { - auto res = std::move(fut) - .onError([](Status s) { - ASSERT_EQ(s, failStatus()); - return StatusWith<int>(ErrorCodes::InternalError, ""); - }) - .template onError<ErrorCodes::InternalError>( - [](Status&&) { return StatusWith<int>(3); }) - .getNoThrow(); + FUTURE_FAIL_TEST<int>([](auto&& fut) { + auto res = + std::move(fut) + .onError([](Status s) FTU_LAMBDA_R(StatusWith<int>) { + ASSERT_EQ(s, failStatus()); + return StatusWith<int>(ErrorCodes::InternalError, ""); + }) + .template onError<ErrorCodes::InternalError>( + [](Status&&) FTU_LAMBDA_R(StatusWith<int>) { return StatusWith<int>(3); }) + .getNoThrow(); ASSERT_EQ(res, 3); }); } TEST(Future, Fail_onErrorCodeMatchFuture) { - FUTURE_FAIL_TEST<int>([](/*Future<int>*/ auto&& fut) { + FUTURE_FAIL_TEST<int>([](auto&& fut) { auto res = std::move(fut) - .onError([](Status s) { + .onError([](Status s) FTU_LAMBDA_R(StatusWith<int>) { ASSERT_EQ(s, failStatus()); return StatusWith<int>(ErrorCodes::InternalError, ""); }) .template onError<ErrorCodes::InternalError>( - [](Status&&) { return Future<int>(3); }) + [](Status&&) FTU_LAMBDA_R(Future<int>) { return Future<int>(3); }) .getNoThrow(); ASSERT_EQ(res, 3); }); } TEST(Future, Fail_onErrorCodeMismatch) { - FUTURE_FAIL_TEST<int>([](/*Future<int>*/ auto&& fut) { + FUTURE_FAIL_TEST<int>([](auto&& fut) { ASSERT_EQ(std::move(fut) .template onError<ErrorCodes::InternalError>([](Status s) -> int { FAIL("Why was this called?") << s; MONGO_UNREACHABLE; }) - .onError([](Status s) { + .onError([](Status s) FTU_LAMBDA_R(int) { ASSERT_EQ(s, failStatus()); return 3; }) @@ -502,42 +490,44 @@ TEST(Future, Fail_onErrorCodeMismatch) { } TEST(Future, Success_onErrorCategory) { - FUTURE_SUCCESS_TEST( - [] { return 1; }, - [](/*Future<int>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .template onErrorCategory<ErrorCategory::NetworkError>([](Status) { - FAIL("onErrorCategory<category>() callback was called"); - return 0; - }) - .then([](int i) { return i + 2; }) - .get(), - 3); - }); + FUTURE_SUCCESS_TEST([] { return 1; }, + [](auto&& fut) { + ASSERT_EQ( + std::move(fut) + .template onErrorCategory<ErrorCategory::NetworkError>( + [](Status) FTU_LAMBDA_R(int) { + FAIL("onErrorCategory<category>() callback was called"); + return 0; + }) + .then([](int i) { return i + 2; }) + .get(), + 3); + }); } TEST(Future, Fail_onErrorCategoryMatch) { - FUTURE_FAIL_TEST<int>([](/*Future<int>*/ auto&& fut) { - auto res = std::move(fut) - .onError([](Status s) { - ASSERT_EQ(s, failStatus()); - return StatusWith<int>(ErrorCodes::HostUnreachable, ""); - }) - .template onErrorCategory<ErrorCategory::NetworkError>( - [](Status&&) { return StatusWith<int>(3); }) - .getNoThrow(); + FUTURE_FAIL_TEST<int>([](auto&& fut) { + auto res = + std::move(fut) + .onError([](Status s) FTU_LAMBDA_R(StatusWith<int>) { + ASSERT_EQ(s, failStatus()); + return StatusWith<int>(ErrorCodes::HostUnreachable, ""); + }) + .template onErrorCategory<ErrorCategory::NetworkError>( + [](Status&&) FTU_LAMBDA_R(StatusWith<int>) { return StatusWith<int>(3); }) + .getNoThrow(); ASSERT_EQ(res, 3); }); } TEST(Future, Fail_onErrorCategoryMismatch) { - FUTURE_FAIL_TEST<int>([](/*Future<int>*/ auto&& fut) { + FUTURE_FAIL_TEST<int>([](auto&& fut) { ASSERT_EQ(std::move(fut) .template onErrorCategory<ErrorCategory::NetworkError>([](Status s) -> int { FAIL("Why was this called?") << s; MONGO_UNREACHABLE; }) - .onError([](Status s) { + .onError([](Status s) FTU_LAMBDA_R(int) { ASSERT_EQ(s, failStatus()); return 3; }) @@ -548,7 +538,7 @@ TEST(Future, Fail_onErrorCategoryMismatch) { TEST(Future, Success_tap) { FUTURE_SUCCESS_TEST<kNoExecutorFuture_needsTap>([] { return 1; }, - [](/*Future<int>*/ auto&& fut) { + [](auto&& fut) { bool tapCalled = false; ASSERT_EQ( std::move(fut) @@ -566,9 +556,11 @@ TEST(Future, Success_tap) { TEST(Future, Success_tapError) { FUTURE_SUCCESS_TEST<kNoExecutorFuture_needsTap>( [] { return 1; }, - [](/*Future<int>*/ auto&& fut) { + [](auto&& fut) { ASSERT_EQ(std::move(fut) - .tapError([](Status s) { FAIL("tapError() callback was called"); }) + .tapError([](Status s) FTU_LAMBDA_R(void) { + FAIL("tapError() callback was called"); + }) .then([](int i) { return i + 2; }) .get(), 3); @@ -578,7 +570,7 @@ TEST(Future, Success_tapError) { TEST(Future, Success_tapAll_StatusWith) { FUTURE_SUCCESS_TEST<kNoExecutorFuture_needsTap>( [] { return 1; }, - [](/*Future<int>*/ auto&& fut) { + [](auto&& fut) { bool tapCalled = false; ASSERT_EQ(std::move(fut) .tapAll([&tapCalled](StatusWith<int> sw) { @@ -593,10 +585,10 @@ TEST(Future, Success_tapAll_StatusWith) { } TEST(Future, Fail_tap) { - FUTURE_FAIL_TEST<int, kNoExecutorFuture_needsTap>([](/*Future<int>*/ auto&& fut) { + FUTURE_FAIL_TEST<int, kNoExecutorFuture_needsTap>([](auto&& fut) { ASSERT_EQ(std::move(fut) .tap([](int i) { FAIL("tap() callback was called"); }) - .onError([](Status s) { + .onError([](Status s) FTU_LAMBDA_R(int) { ASSERT_EQ(s, failStatus()); return 3; }) @@ -606,14 +598,14 @@ TEST(Future, Fail_tap) { } TEST(Future, Fail_tapError) { - FUTURE_FAIL_TEST<int, kNoExecutorFuture_needsTap>([](/*Future<int>*/ auto&& fut) { + FUTURE_FAIL_TEST<int, kNoExecutorFuture_needsTap>([](auto&& fut) { bool tapCalled = false; ASSERT_EQ(std::move(fut) .tapError([&tapCalled](Status s) { ASSERT_EQ(s, failStatus()); tapCalled = true; }) - .onError([](Status s) { + .onError([](Status s) FTU_LAMBDA_R(int) { ASSERT_EQ(s, failStatus()); return 3; }) @@ -624,14 +616,14 @@ TEST(Future, Fail_tapError) { } TEST(Future, Fail_tapAll_StatusWith) { - FUTURE_FAIL_TEST<int, kNoExecutorFuture_needsTap>([](/*Future<int>*/ auto&& fut) { + FUTURE_FAIL_TEST<int, kNoExecutorFuture_needsTap>([](auto&& fut) { bool tapCalled = false; ASSERT_EQ(std::move(fut) .tapAll([&tapCalled](StatusWith<int> sw) { ASSERT_EQ(sw.getStatus(), failStatus()); tapCalled = true; }) - .onError([](Status s) { + .onError([](Status s) FTU_LAMBDA_R(int) { ASSERT_EQ(s, failStatus()); return 3; }) @@ -642,40 +634,42 @@ TEST(Future, Fail_tapAll_StatusWith) { } TEST(Future, Success_onCompletionSimple) { - FUTURE_SUCCESS_TEST( - [] { return 1; }, - [](/*Future<int>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .onCompletion([](StatusWith<int> i) { return i.getValue() + 2; }) - .get(), - 3); - }); + FUTURE_SUCCESS_TEST([] { return 1; }, + [](auto&& fut) { + ASSERT_EQ(std::move(fut) + .onCompletion([](StatusWith<int> i) FTU_LAMBDA_R(int) { + return i.getValue() + 2; + }) + .get(), + 3); + }); } TEST(Future, Success_onCompletionVoid) { - FUTURE_SUCCESS_TEST( - [] { return 1; }, - [](/*Future<int>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .onCompletion([](StatusWith<int> i) { ASSERT_EQ(i.getValue(), 1); }) - .onCompletion([](Status s) { - ASSERT_OK(s); - return 3; - }) - .get(), - 3); - }); + FUTURE_SUCCESS_TEST([] { return 1; }, + [](auto&& fut) { + ASSERT_EQ(std::move(fut) + .onCompletion([](StatusWith<int> i) FTU_LAMBDA_R(void) { + ASSERT_EQ(i.getValue(), 1); + }) + .onCompletion([](Status s) FTU_LAMBDA_R(int) { + ASSERT_OK(s); + return 3; + }) + .get(), + 3); + }); } TEST(Future, Success_onCompletionStatus) { FUTURE_SUCCESS_TEST([] { return 1; }, - [](/*Future<int>*/ auto&& fut) { + [](auto&& fut) { ASSERT_EQ(std::move(fut) - .onCompletion([](StatusWith<int> i) { + .onCompletion([](StatusWith<int> i) FTU_LAMBDA_R(Status) { ASSERT_EQ(i, 1); return Status::OK(); }) - .onCompletion([](Status s) { + .onCompletion([](Status s) FTU_LAMBDA_R(int) { ASSERT_OK(s); return 3; }) @@ -687,83 +681,91 @@ TEST(Future, Success_onCompletionStatus) { TEST(Future, Success_onCompletionError_Status) { FUTURE_SUCCESS_TEST( [] { return 1; }, - [](/*Future<int>*/ auto&& fut) { - auto fut2 = std::move(fut).onCompletion( - [](StatusWith<int> i) { return Status(ErrorCodes::BadValue, "oh no!"); }); + [](auto&& fut) { + auto fut2 = std::move(fut).onCompletion([](StatusWith<int> i) FTU_LAMBDA_R(Status) { + return Status(ErrorCodes::BadValue, "oh no!"); + }); +#ifndef _MSC_VER static_assert(future_details::isFutureLike<decltype(fut2)>); static_assert(std::is_same_v<typename decltype(fut2)::value_type, void>); +#endif ASSERT_THROWS(fut2.get(), ExceptionFor<ErrorCodes::BadValue>); }); } TEST(Future, Success_onCompletionError_StatusWith) { - FUTURE_SUCCESS_TEST([] { return 1; }, - [](/*Future<int>*/ auto&& fut) { - auto fut2 = std::move(fut).onCompletion([](StatusWith<int> i) { - return StatusWith<double>(ErrorCodes::BadValue, "oh no!"); - }); - static_assert(future_details::isFutureLike<decltype(fut2)>); - static_assert( - std::is_same_v<typename decltype(fut2)::value_type, double>); - ASSERT_THROWS(fut2.get(), ExceptionFor<ErrorCodes::BadValue>); - }); + FUTURE_SUCCESS_TEST( + [] { return 1; }, + [](auto&& fut) { + auto fut2 = + std::move(fut).onCompletion([](StatusWith<int> i) FTU_LAMBDA_R(StatusWith<double>) { + return StatusWith<double>(ErrorCodes::BadValue, "oh no!"); + }); + static_assert(future_details::isFutureLike<decltype(fut2)>); + static_assert(std::is_same_v<typename decltype(fut2)::value_type, double>); + ASSERT_THROWS(fut2.get(), ExceptionFor<ErrorCodes::BadValue>); + }); } TEST(Future, Success_onCompletionFutureImmediate) { FUTURE_SUCCESS_TEST([] { return 1; }, - [](/*Future<int>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .onCompletion([](StatusWith<int> i) { - return Future<int>::makeReady(i.getValue() + 2); - }) - .get(), - 3); + [](auto&& fut) { + ASSERT_EQ( + std::move(fut) + .onCompletion([](StatusWith<int> i) FTU_LAMBDA_R(Future<int>) { + return Future<int>::makeReady(i.getValue() + 2); + }) + .get(), + 3); }); } TEST(Future, Success_onCompletionFutureReady) { FUTURE_SUCCESS_TEST([] { return 1; }, - [](/*Future<int>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .onCompletion([](StatusWith<int> i) { - auto pf = makePromiseFuture<int>(); - pf.promise.emplaceValue(i.getValue() + 2); - return std::move(pf.future); - }) - .get(), - 3); + [](auto&& fut) { + ASSERT_EQ( + std::move(fut) + .onCompletion([](StatusWith<int> i) FTU_LAMBDA_R(Future<int>) { + auto pf = makePromiseFuture<int>(); + pf.promise.emplaceValue(i.getValue() + 2); + return std::move(pf.future); + }) + .get(), + 3); }); } TEST(Future, Success_onCompletionFutureAsync) { FUTURE_SUCCESS_TEST([] { return 1; }, - [](/*Future<int>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .onCompletion([](StatusWith<int> i) { - return async([i = i.getValue()] { return i + 2; }); - }) - .get(), - 3); + [](auto&& fut) { + ASSERT_EQ( + std::move(fut) + .onCompletion([](StatusWith<int> i) FTU_LAMBDA_R(Future<int>) { + return async([i = i.getValue()] { return i + 2; }); + }) + .get(), + 3); }); } TEST(Future, Success_onCompletionFutureAsyncThrow) { FUTURE_SUCCESS_TEST([] { return 1; }, - [](/*Future<int>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .onCompletion([](StatusWith<int> i) { - uasserted(ErrorCodes::BadValue, "oh no!"); - return Future<int>(); - }) - .getNoThrow(), - ErrorCodes::BadValue); + [](auto&& fut) { + ASSERT_EQ( + std::move(fut) + .onCompletion([](StatusWith<int> i) FTU_LAMBDA_R(Future<int>) { + uasserted(ErrorCodes::BadValue, "oh no!"); + return Future<int>(); + }) + .getNoThrow(), + ErrorCodes::BadValue); }); } TEST(Future, Fail_onCompletionSimple) { - FUTURE_FAIL_TEST<int>([](/*Future<int>*/ auto&& fut) { + FUTURE_FAIL_TEST<int>([](auto&& fut) { ASSERT_EQ(std::move(fut) - .onCompletion([](StatusWith<int> i) { + .onCompletion([](StatusWith<int> i) FTU_LAMBDA_R(Status) { ASSERT_NOT_OK(i); return i.getStatus(); @@ -774,7 +776,7 @@ TEST(Future, Fail_onCompletionSimple) { } TEST(Future, Fail_onCompletionError_throw) { - FUTURE_FAIL_TEST<int>([](/*Future<int>*/ auto&& fut) { + FUTURE_FAIL_TEST<int>([](auto&& fut) { auto fut2 = std::move(fut).onCompletion([](StatusWith<int> s) -> int { ASSERT_EQ(s.getStatus(), failStatus()); uasserted(ErrorCodes::BadValue, "oh no!"); @@ -784,19 +786,20 @@ TEST(Future, Fail_onCompletionError_throw) { } TEST(Future, Fail_onCompletionError_StatusWith) { - FUTURE_FAIL_TEST<int>([](/*Future<int>*/ auto&& fut) { - auto fut2 = std::move(fut).onCompletion([](StatusWith<int> s) { - ASSERT_EQ(s.getStatus(), failStatus()); - return StatusWith<int>(ErrorCodes::BadValue, "oh no!"); - }); + FUTURE_FAIL_TEST<int>([](auto&& fut) { + auto fut2 = + std::move(fut).onCompletion([](StatusWith<int> s) FTU_LAMBDA_R(StatusWith<int>) { + ASSERT_EQ(s.getStatus(), failStatus()); + return StatusWith<int>(ErrorCodes::BadValue, "oh no!"); + }); ASSERT_EQ(fut2.getNoThrow(), ErrorCodes::BadValue); }); } TEST(Future, Fail_onCompletionFutureImmediate) { - FUTURE_FAIL_TEST<int>([](/*Future<int>*/ auto&& fut) { + FUTURE_FAIL_TEST<int>([](auto&& fut) { ASSERT_EQ(std::move(fut) - .onCompletion([](StatusWith<int> s) { + .onCompletion([](StatusWith<int> s) FTU_LAMBDA_R(Future<int>) { ASSERT_EQ(s.getStatus(), failStatus()); return Future<int>::makeReady(3); }) @@ -806,9 +809,9 @@ TEST(Future, Fail_onCompletionFutureImmediate) { } TEST(Future, Fail_onCompletionFutureReady) { - FUTURE_FAIL_TEST<int>([](/*Future<int>*/ auto&& fut) { + FUTURE_FAIL_TEST<int>([](auto&& fut) { ASSERT_EQ(std::move(fut) - .onCompletion([](StatusWith<int> s) { + .onCompletion([](StatusWith<int> s) FTU_LAMBDA_R(Future<int>) { ASSERT_EQ(s.getStatus(), failStatus()); auto pf = makePromiseFuture<int>(); pf.promise.emplaceValue(3); diff --git a/src/mongo/util/future_test_future_move_only.cpp b/src/mongo/util/future_test_future_move_only.cpp index 41b4a711788..3047d4ab19d 100644 --- a/src/mongo/util/future_test_future_move_only.cpp +++ b/src/mongo/util/future_test_future_move_only.cpp @@ -54,12 +54,8 @@ struct Widget { Widget(const Widget&) = delete; Widget& operator=(const Widget&) = delete; - Widget operator+(int i) const { - return Widget(val + i); - } - - bool operator==(int i) const { - return val == i; + friend Widget operator+(const Widget& w, int i) { + return Widget(w.val + i); } friend bool operator==(const Widget& a, const Widget& b) { @@ -81,123 +77,108 @@ std::ostream& operator<<(std::ostream& stream, const Widget& widget) { return stream << "Widget(" << widget.val << ')'; } +/* Run the success tests using a Widget(1) completion function. */ +template <DoExecutorFuture doExecutorFuture = kDoExecutorFuture, typename F> +void runTests(F&& f) { + FUTURE_SUCCESS_TEST<doExecutorFuture>([] { return Widget(1); }, std::forward<F>(f)); +} + TEST(Future_MoveOnly, Success_getLvalue) { - FUTURE_SUCCESS_TEST([] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { ASSERT_EQ(fut.get(), 1); }); + runTests([](auto&& fut) { ASSERT_EQ(fut.get(), Widget(1)); }); } TEST(Future_MoveOnly, Success_getConstLvalue) { - FUTURE_SUCCESS_TEST([] { return Widget(1); }, - [](const /*Future<Widget>*/ auto& fut) { ASSERT_EQ(fut.get(), 1); }); + runTests([](const auto& fut) { ASSERT_EQ(fut.get(), Widget(1)); }); } TEST(Future_MoveOnly, Success_getRvalue) { - FUTURE_SUCCESS_TEST([] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { ASSERT_EQ(std::move(fut).get(), 1); }); + runTests([](auto&& fut) { ASSERT_EQ(std::move(fut).get(), Widget(1)); }); } TEST(Future_MoveOnly, Success_semi_get) { - FUTURE_SUCCESS_TEST( - [] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { ASSERT_EQ(std::move(fut).semi().get(), 1); }); + runTests([](auto&& fut) { ASSERT_EQ(std::move(fut).semi().get(), Widget(1)); }); } #if 0 // Needs copy TEST(Future_MoveOnly, Success_shared_get) { - FUTURE_SUCCESS_TEST( - [] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { ASSERT_EQ(std::move(fut).share().get(), 1); }); + runTests([](auto&& fut) { ASSERT_EQ(std::move(fut).share().get(), Widget(1)); }); } TEST(Future_MoveOnly, Success_getNothrowLvalue) { - FUTURE_SUCCESS_TEST([] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { ASSERT_EQ(fut.getNoThrow(), 1); }); + runTests([](auto&& fut) { ASSERT_EQ(fut.getNoThrow(), Widget(1)); }); } TEST(Future_MoveOnly, Success_getNothrowConstLvalue) { - FUTURE_SUCCESS_TEST([] { return Widget(1); }, - [](const /*Future<Widget>*/ auto& fut) { ASSERT_EQ(fut.getNoThrow(), 1); }); + runTests([](auto&& fut) { ASSERT_EQ(fut.getNoThrow(), Widget(1)); }); } TEST(Future_MoveOnly, Success_shared_getNothrow) { - FUTURE_SUCCESS_TEST( - [] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { ASSERT_EQ(std::move(fut).share().getNoThrow(), 1); }); + runTests([](auto&& fut) { ASSERT_EQ(std::move(fut).share().getNoThrow(), Widget(1)); }); } #endif TEST(Future_MoveOnly, Success_getNothrowRvalue) { - FUTURE_SUCCESS_TEST([] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { - ASSERT_EQ(uassertStatusOK(std::move(fut).getNoThrow()).val, 1); - }); + runTests([](auto&& fut) { ASSERT_EQ(uassertStatusOK(std::move(fut).getNoThrow()).val, 1); }); } TEST(Future_MoveOnly, Success_getAsync) { - FUTURE_SUCCESS_TEST([] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { - auto pf = makePromiseFuture<Widget>(); - std::move(fut).getAsync( - [outside = std::move(pf.promise)](StatusWith<Widget> sw) mutable { - ASSERT_OK(sw); - outside.emplaceValue(std::move(sw.getValue())); - }); - ASSERT_EQ(std::move(pf.future).get(), 1); - }); + runTests([](auto&& fut) { + auto pf = makePromiseFuture<Widget>(); + std::move(fut).getAsync([outside = std::move(pf.promise)](StatusWith<Widget> sw) mutable { + ASSERT_OK(sw); + outside.emplaceValue(std::move(sw.getValue())); + }); + ASSERT_EQ(std::move(pf.future).get(), Widget(1)); + }); } TEST(Future_MoveOnly, Fail_getLvalue) { - FUTURE_FAIL_TEST<Widget>( - [](/*Future<Widget>*/ auto&& fut) { ASSERT_THROWS_failStatus(fut.get()); }); + FUTURE_FAIL_TEST<Widget>([](auto&& fut) { ASSERT_THROWS_failStatus(fut.get()); }); } TEST(Future_MoveOnly, Fail_getConstLvalue) { - FUTURE_FAIL_TEST<Widget>( - [](const /*Future<Widget>*/ auto& fut) { ASSERT_THROWS_failStatus(fut.get()); }); + FUTURE_FAIL_TEST<Widget>([](const auto& fut) { ASSERT_THROWS_failStatus(fut.get()); }); } TEST(Future_MoveOnly, Fail_getRvalue) { - FUTURE_FAIL_TEST<Widget>( - [](/*Future<Widget>*/ auto&& fut) { ASSERT_THROWS_failStatus(std::move(fut).get()); }); + FUTURE_FAIL_TEST<Widget>([](auto&& fut) { ASSERT_THROWS_failStatus(std::move(fut).get()); }); } TEST(Future_MoveOnly, Fail_semi_get) { - FUTURE_FAIL_TEST<Widget>([](/*Future<Widget>*/ auto&& fut) { - ASSERT_THROWS_failStatus(std::move(fut).semi().get()); - }); + FUTURE_FAIL_TEST<Widget>( + [](auto&& fut) { ASSERT_THROWS_failStatus(std::move(fut).semi().get()); }); } #if 0 // Needs copy TEST(Future_MoveOnly, Fail_shared_get) { - FUTURE_FAIL_TEST<Widget>([](/*Future<Widget>*/ auto&& fut) { + FUTURE_FAIL_TEST<Widget>([](auto&& fut) { ASSERT_THROWS_failStatus(std::move(fut).share().get()); }); } TEST(Future_MoveOnly, Fail_getNothrowLvalue) { - FUTURE_FAIL_TEST<Widget>([](/*Future<Widget>*/ auto&& fut) { ASSERT_EQ(fut.getNoThrow(), failStatus); }); + FUTURE_FAIL_TEST<Widget>([](auto&& fut) { ASSERT_EQ(fut.getNoThrow(), failStatus); }); } TEST(Future_MoveOnly, Fail_getNothrowConstLvalue) { FUTURE_FAIL_TEST<Widget>( - [](const /*Future<Widget>*/ auto& fut) { ASSERT_EQ(fut.getNoThrow(), failStatus); }); + [](const auto& fut) { ASSERT_EQ(fut.getNoThrow(), failStatus); }); } TEST(Future_MoveOnly, Fail_shared_getNothrow) { - FUTURE_FAIL_TEST<Widget>([](/*Future<Widget>*/ auto&& fut) { + FUTURE_FAIL_TEST<Widget>([](auto&& fut) { ASSERT_EQ(std::move(fut).share().getNoThrow().getStatus(), failStatus()); }); } #endif TEST(Future_MoveOnly, Fail_getNothrowRvalue) { - FUTURE_FAIL_TEST<Widget>([](/*Future<Widget>*/ auto&& fut) { - ASSERT_EQ(std::move(fut).getNoThrow().getStatus(), failStatus()); - }); + FUTURE_FAIL_TEST<Widget>( + [](auto&& fut) { ASSERT_EQ(std::move(fut).getNoThrow().getStatus(), failStatus()); }); } TEST(Future_MoveOnly, Fail_getAsync) { - FUTURE_FAIL_TEST<Widget>([](/*Future<Widget>*/ auto&& fut) { + FUTURE_FAIL_TEST<Widget>([](auto&& fut) { auto pf = makePromiseFuture<Widget>(); std::move(fut).getAsync([outside = std::move(pf.promise)](StatusWith<Widget> sw) mutable { ASSERT(!sw.isOK()); @@ -208,135 +189,121 @@ TEST(Future_MoveOnly, Fail_getAsync) { } TEST(Future_MoveOnly, Success_thenSimple) { - FUTURE_SUCCESS_TEST([] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { - ASSERT_EQ(std::move(fut).then([](Widget i) { return i + 2; }).get(), 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut).then([](Widget i) FTU_LAMBDA_R(Widget) { return i + 2; }).get(), + Widget(3)); + }); } TEST(Future_MoveOnly, Success_thenSimpleAuto) { - FUTURE_SUCCESS_TEST([] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { - ASSERT_EQ(std::move(fut).then([](auto&& i) { return i + 2; }).get(), 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut).then([](auto&& i) { return i + 2; }).get(), Widget(3)); + }); } TEST(Future_MoveOnly, Success_thenVoid) { - FUTURE_SUCCESS_TEST([] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .then([](Widget i) { ASSERT_EQ(i, 1); }) - .then([] { return Widget(3); }) - .get(), - 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut) + .then([](Widget i) FTU_LAMBDA_R(void) { ASSERT_EQ(i, Widget(1)); }) + .then([]() FTU_LAMBDA_R(Widget) { return Widget(3); }) + .get(), + Widget(3)); + }); } TEST(Future_MoveOnly, Success_thenStatus) { - FUTURE_SUCCESS_TEST([] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .then([](Widget i) { - ASSERT_EQ(i, 1); - return Status::OK(); - }) - .then([] { return Widget(3); }) - .get(), - 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut) + .then([](Widget i) FTU_LAMBDA_R(Status) { + ASSERT_EQ(i, Widget(1)); + return Status::OK(); + }) + .then([] { return Widget(3); }) + .get(), + Widget(3)); + }); } TEST(Future_MoveOnly, Success_thenError_Status) { - FUTURE_SUCCESS_TEST([] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { - auto fut2 = std::move(fut).then( - [](Widget i) { return Status(ErrorCodes::BadValue, "oh no!"); }); - static_assert(future_details::isFutureLike<decltype(fut2)>); - static_assert( - std::is_same_v<typename decltype(fut2)::value_type, void>); - ASSERT_EQ(fut2.getNoThrow(), ErrorCodes::BadValue); - }); + runTests([](auto&& fut) { + auto fut2 = std::move(fut).then( + [](Widget i) FTU_LAMBDA_R(Status) { return Status(ErrorCodes::BadValue, "oh no!"); }); + static_assert(future_details::isFutureLike<decltype(fut2)>); + static_assert(std::is_same_v<typename decltype(fut2)::value_type, void>); + ASSERT_EQ(fut2.getNoThrow(), ErrorCodes::BadValue); + }); } TEST(Future_MoveOnly, Success_thenError_StatusWith) { - FUTURE_SUCCESS_TEST( - [] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { - auto fut2 = std::move(fut).then( - [](Widget i) { return StatusWith<double>(ErrorCodes::BadValue, "oh no!"); }); - static_assert(future_details::isFutureLike<decltype(fut2)>); - static_assert(std::is_same_v<typename decltype(fut2)::value_type, double>); - ASSERT_EQ(fut2.getNoThrow(), ErrorCodes::BadValue); + runTests([](auto&& fut) { + auto fut2 = std::move(fut).then([](Widget i) FTU_LAMBDA_R(StatusWith<double>) { + return StatusWith<double>(ErrorCodes::BadValue, "oh no!"); }); + static_assert(future_details::isFutureLike<decltype(fut2)>); + static_assert(std::is_same_v<typename decltype(fut2)::value_type, double>); + ASSERT_EQ(fut2.getNoThrow(), ErrorCodes::BadValue); + }); } TEST(Future_MoveOnly, Success_thenFutureImmediate) { - FUTURE_SUCCESS_TEST( - [] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .then([](Widget i) { return Future<Widget>::makeReady(Widget(i + 2)); }) - .get(), - 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut) + .then([](Widget i) FTU_LAMBDA_R(Future<Widget>) { + return Future<Widget>::makeReady(Widget(i + 2)); + }) + .get(), + Widget(3)); + }); } TEST(Future_MoveOnly, Success_thenFutureReady) { - FUTURE_SUCCESS_TEST([] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .then([](Widget i) { - auto pf = makePromiseFuture<Widget>(); - pf.promise.emplaceValue(i + 2); - return std::move(pf.future); - }) - .get(), - 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut) + .then([](Widget i) FTU_LAMBDA_R(Future<Widget>) { + auto pf = makePromiseFuture<Widget>(); + pf.promise.emplaceValue(i + 2); + return std::move(pf.future); + }) + .get(), + Widget(3)); + }); } TEST(Future_MoveOnly, Success_thenFutureAsync) { - FUTURE_SUCCESS_TEST([] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .then([&](Widget i) { - return async([i = i.val] { return Widget(i + 2); }); - }) - .get(), - 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut) + .then([&](Widget i) { return async([i = i.val] { return Widget(i + 2); }); }) + .get(), + Widget(3)); + }); } TEST(Future_MoveOnly, Success_thenSemiFutureAsync) { - FUTURE_SUCCESS_TEST([] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { - ASSERT_EQ( - std::move(fut) - .then([&](Widget i) { - return async([i = i.val] { return Widget(i + 2); }).semi(); - }) - .get(), - 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ( + std::move(fut) + .then([&](Widget i) { return async([i = i.val] { return Widget(i + 2); }).semi(); }) + .get(), + Widget(3)); + }); } TEST(Future_MoveOnly, Success_thenFutureAsyncThrow) { - FUTURE_SUCCESS_TEST([] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .then([](Widget i) { - uasserted(ErrorCodes::BadValue, "oh no!"); - return Future<Widget>(); - }) - .getNoThrow(), - ErrorCodes::BadValue); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut) + .then([](Widget i) { + uasserted(ErrorCodes::BadValue, "oh no!"); + return Future<Widget>(); + }) + .getNoThrow(), + ErrorCodes::BadValue); + }); } TEST(Future_MoveOnly, Fail_thenSimple) { - FUTURE_FAIL_TEST<Widget>([](/*Future<Widget>*/ auto&& fut) { + FUTURE_FAIL_TEST<Widget>([](auto&& fut) { ASSERT_EQ(std::move(fut) - .then([](Widget i) { + .then([](Widget i) FTU_LAMBDA_R(Widget) { FAIL("then() callback was called"); return Widget(0); }) @@ -346,9 +313,9 @@ TEST(Future_MoveOnly, Fail_thenSimple) { } TEST(Future_MoveOnly, Fail_thenFutureAsync) { - FUTURE_FAIL_TEST<Widget>([](/*Future<Widget>*/ auto&& fut) { + FUTURE_FAIL_TEST<Widget>([](auto&& fut) { ASSERT_EQ(std::move(fut) - .then([](Widget i) { + .then([](Widget i) FTU_LAMBDA_R(Future<Widget>) { FAIL("then() callback was called"); return Future<Widget>(); }) @@ -358,46 +325,44 @@ TEST(Future_MoveOnly, Fail_thenFutureAsync) { } TEST(Future_MoveOnly, Success_onErrorSimple) { - FUTURE_SUCCESS_TEST([] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .onError([](Status) { - FAIL("onError() callback was called"); - return Widget(0); - }) - .then([](Widget i) { return i + 2; }) - .get(), - 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut) + .onError([](Status) FTU_LAMBDA_R(Widget) { + FAIL("onError() callback was called"); + return Widget(0); + }) + .then([](Widget i) FTU_LAMBDA_R(Widget) { return i + 2; }) + .get(), + Widget(3)); + }); } TEST(Future_MoveOnly, Success_onErrorFutureAsync) { - FUTURE_SUCCESS_TEST([] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .onError([](Status) { - FAIL("onError() callback was called"); - return Future<Widget>(); - }) - .then([](Widget i) { return i + 2; }) - .get(), - 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut) + .onError([](Status) FTU_LAMBDA_R(Future<Widget>) { + FAIL("onError() callback was called"); + return Future<Widget>(); + }) + .then([](Widget i) FTU_LAMBDA_R(Widget) { return i + 2; }) + .get(), + Widget(3)); + }); } TEST(Future_MoveOnly, Fail_onErrorSimple) { - FUTURE_FAIL_TEST<Widget>([](/*Future<Widget>*/ auto&& fut) { + FUTURE_FAIL_TEST<Widget>([](auto&& fut) { ASSERT_EQ(uassertStatusOK(std::move(fut) - .onError([](Status s) { + .onError([](Status s) FTU_LAMBDA_R(Widget) { ASSERT_EQ(s, failStatus()); return Widget(3); }) .getNoThrow()), - 3); + Widget(3)); }); } TEST(Future_MoveOnly, Fail_onErrorError_throw) { - FUTURE_FAIL_TEST<Widget>([](/*Future<Widget>*/ auto&& fut) { + FUTURE_FAIL_TEST<Widget>([](auto&& fut) { auto fut2 = std::move(fut).onError([](Status s) -> Widget { ASSERT_EQ(s, failStatus()); uasserted(ErrorCodes::BadValue, "oh no!"); @@ -407,8 +372,8 @@ TEST(Future_MoveOnly, Fail_onErrorError_throw) { } TEST(Future_MoveOnly, Fail_onErrorError_StatusWith) { - FUTURE_FAIL_TEST<Widget>([](/*Future<Widget>*/ auto&& fut) { - auto fut2 = std::move(fut).onError([](Status s) { + FUTURE_FAIL_TEST<Widget>([](auto&& fut) { + auto fut2 = std::move(fut).onError([](Status s) FTU_LAMBDA_R(StatusWith<Widget>) { ASSERT_EQ(s, failStatus()); return StatusWith<Widget>(ErrorCodes::BadValue, "oh no!"); }); @@ -417,77 +382,72 @@ TEST(Future_MoveOnly, Fail_onErrorError_StatusWith) { } TEST(Future_MoveOnly, Fail_onErrorFutureImmediate) { - FUTURE_FAIL_TEST<Widget>([](/*Future<Widget>*/ auto&& fut) { + FUTURE_FAIL_TEST<Widget>([](auto&& fut) { ASSERT_EQ(std::move(fut) - .onError([](Status s) { + .onError([](Status s) FTU_LAMBDA_R(Future<Widget>) { ASSERT_EQ(s, failStatus()); return Future<Widget>::makeReady(Widget(3)); }) .get(), - 3); + Widget(3)); }); } TEST(Future_MoveOnly, Fail_onErrorFutureReady) { - FUTURE_FAIL_TEST<Widget>([](/*Future<Widget>*/ auto&& fut) { + FUTURE_FAIL_TEST<Widget>([](auto&& fut) { ASSERT_EQ(std::move(fut) - .onError([](Status s) { + .onError([](Status s) FTU_LAMBDA_R(Future<Widget>) { ASSERT_EQ(s, failStatus()); auto pf = makePromiseFuture<Widget>(); pf.promise.emplaceValue(3); return std::move(pf.future); }) .get(), - 3); + Widget(3)); }); } TEST(Future_MoveOnly, Fail_onErrorFutureAsync) { - FUTURE_FAIL_TEST<Widget>([](/*Future<Widget>*/ auto&& fut) { + FUTURE_FAIL_TEST<Widget>([](auto&& fut) { ASSERT_EQ(std::move(fut) - .onError([&](Status s) { + .onError([&](Status s) FTU_LAMBDA_R(Future<Widget>) { ASSERT_EQ(s, failStatus()); return async([] { return Widget(3); }); }) .get(), - 3); + Widget(3)); }); } TEST(Future_MoveOnly, Success_tap) { - FUTURE_SUCCESS_TEST<kNoExecutorFuture_needsTap>( - [] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { - bool tapCalled = false; - ASSERT_EQ(std::move(fut) - .tap([&tapCalled](const Widget& i) { - ASSERT_EQ(i, 1); - tapCalled = true; - }) - .then([](Widget i) { return i + 2; }) - .get(), - 3); - ASSERT(tapCalled); - }); + runTests<kNoExecutorFuture_needsTap>([](auto&& fut) { + bool tapCalled = false; + ASSERT_EQ(std::move(fut) + .tap([&tapCalled](const Widget& i) { + ASSERT_EQ(i, Widget(1)); + tapCalled = true; + }) + .then([](Widget i) FTU_LAMBDA_R(Widget) { return i + 2; }) + .get(), + Widget(3)); + ASSERT(tapCalled); + }); } TEST(Future_MoveOnly, Success_tapError) { - FUTURE_SUCCESS_TEST<kNoExecutorFuture_needsTap>( - [] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .tapError([](Status s) { FAIL("tapError() callback was called"); }) - .then([](Widget i) { return i + 2; }) - .get(), - 3); - }); + runTests<kNoExecutorFuture_needsTap>([](auto&& fut) { + ASSERT_EQ(std::move(fut) + .tapError([](Status s) + FTU_LAMBDA_R(void) { FAIL("tapError() callback was called"); }) + .then([](Widget i) FTU_LAMBDA_R(Widget) { return i + 2; }) + .get(), + Widget(3)); + }); } #if 0 // Needs copy TEST(Future_MoveOnly, Success_tapAll_StatusWith) { - FUTURE_SUCCESS_TEST<kNoExecutorFuture_needsTap>( - [] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { + runTests<kNoExecutorFuture_needsTap>([](auto&& fut) { bool tapCalled = false; ASSERT_EQ(std::move(fut) .tapAll([&tapCalled](StatusWith<Widget> sw) { @@ -496,46 +456,46 @@ TEST(Future_MoveOnly, Success_tapAll_StatusWith) { }) .then([](Widget i) { return i + 2; }) .get(), - 3); + Widget(3)); ASSERT(tapCalled); }); } #endif TEST(Future_MoveOnly, Fail_tap) { - FUTURE_FAIL_TEST<Widget, kNoExecutorFuture_needsTap>([](/*Future<Widget>*/ auto&& fut) { + FUTURE_FAIL_TEST<Widget, kNoExecutorFuture_needsTap>([](auto&& fut) { ASSERT_EQ(std::move(fut) .tap([](const Widget& i) { FAIL("tap() callback was called"); }) - .onError([](Status s) { + .onError([](Status s) FTU_LAMBDA_R(Widget) { ASSERT_EQ(s, failStatus()); return Widget(3); }) .get(), - 3); + Widget(3)); }); } TEST(Future_MoveOnly, Fail_tapError) { - FUTURE_FAIL_TEST<Widget, kNoExecutorFuture_needsTap>([](/*Future<Widget>*/ auto&& fut) { + FUTURE_FAIL_TEST<Widget, kNoExecutorFuture_needsTap>([](auto&& fut) { bool tapCalled = false; ASSERT_EQ(std::move(fut) .tapError([&tapCalled](Status s) { ASSERT_EQ(s, failStatus()); tapCalled = true; }) - .onError([](Status s) { + .onError([](Status s) FTU_LAMBDA_R(Widget) { ASSERT_EQ(s, failStatus()); return Widget(3); }) .get(), - 3); + Widget(3)); ASSERT(tapCalled); }); } #if 0 // Needs copy TEST(Future_MoveOnly, Fail_tapAll_StatusWith) { - FUTURE_FAIL_TEST<Widget, kNoExecutorFuture_needsTap>( [](/*Future<Widget>*/ auto&& fut) { + FUTURE_FAIL_TEST<Widget, kNoExecutorFuture_needsTap>( [](auto&& fut) { bool tapCalled = false; ASSERT_EQ(std::move(fut) .tapAll([&tapCalled](StatusWith<Widget> sw) { @@ -554,130 +514,119 @@ TEST(Future_MoveOnly, Fail_tapAll_StatusWith) { #endif TEST(Future_MoveOnly, Success_onCompletionSimple) { - FUTURE_SUCCESS_TEST( - [] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .onCompletion([](StatusWith<Widget> i) { return i.getValue() + 2; }) - .get(), - 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut) + .onCompletion([](StatusWith<Widget> i) + FTU_LAMBDA_R(Widget) { return i.getValue() + 2; }) + .get(), + Widget(3)); + }); } TEST(Future_MoveOnly, Success_onCompletionVoid) { - FUTURE_SUCCESS_TEST( - [] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& 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); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut) + .onCompletion([](StatusWith<Widget> i) + FTU_LAMBDA_R(void) { ASSERT_EQ(i.getValue(), Widget(1)); }) + .onCompletion([](Status s) FTU_LAMBDA_R(Widget) { + ASSERT_OK(s); + return Widget(3); + }) + .get(), + Widget(3)); + }); } TEST(Future_MoveOnly, Success_onCompletionStatus) { - FUTURE_SUCCESS_TEST([] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& 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); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut) + .onCompletion([](StatusWith<Widget> i) FTU_LAMBDA_R(Status) { + ASSERT_EQ(i.getValue(), Widget(1)); + return Status::OK(); + }) + .onCompletion([](Status s) FTU_LAMBDA_R(Widget) { + ASSERT_OK(s); + return Widget(3); + }) + .get(), + Widget(3)); + }); } TEST(Future_MoveOnly, Success_onCompletionError_Status) { - FUTURE_SUCCESS_TEST( - [] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { - auto fut2 = std::move(fut).onCompletion( - [](StatusWith<Widget> i) { return Status(ErrorCodes::BadValue, "oh no!"); }); - static_assert(future_details::isFutureLike<decltype(fut2)>); - static_assert(std::is_same_v<typename decltype(fut2)::value_type, void>); - ASSERT_EQ(fut2.getNoThrow(), ErrorCodes::BadValue); + runTests([](auto&& fut) { + auto fut2 = std::move(fut).onCompletion([](StatusWith<Widget> i) FTU_LAMBDA_R(Status) { + return Status(ErrorCodes::BadValue, "oh no!"); }); + static_assert(future_details::isFutureLike<decltype(fut2)>); + static_assert(std::is_same_v<typename decltype(fut2)::value_type, void>); + ASSERT_EQ(fut2.getNoThrow(), ErrorCodes::BadValue); + }); } TEST(Future_MoveOnly, Success_onCompletionError_StatusWith) { - FUTURE_SUCCESS_TEST([] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { - auto fut2 = std::move(fut).onCompletion([](StatusWith<Widget> i) { - return StatusWith<double>(ErrorCodes::BadValue, "oh no!"); - }); - static_assert(future_details::isFutureLike<decltype(fut2)>); - static_assert( - std::is_same_v<typename decltype(fut2)::value_type, double>); - ASSERT_EQ(fut2.getNoThrow(), ErrorCodes::BadValue); - }); + runTests([](auto&& fut) { + auto fut2 = + std::move(fut).onCompletion([](StatusWith<Widget> i) FTU_LAMBDA_R(StatusWith<double>) { + return StatusWith<double>(ErrorCodes::BadValue, "oh no!"); + }); + static_assert(future_details::isFutureLike<decltype(fut2)>); + static_assert(std::is_same_v<typename decltype(fut2)::value_type, double>); + ASSERT_EQ(fut2.getNoThrow(), ErrorCodes::BadValue); + }); } TEST(Future_MoveOnly, Success_onCompletionFutureImmediate) { - FUTURE_SUCCESS_TEST([] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .onCompletion([](StatusWith<Widget> i) { - return Future<Widget>::makeReady( - Widget(i.getValue() + 2)); - }) - .get(), - 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut) + .onCompletion([](StatusWith<Widget> i) FTU_LAMBDA_R(Future<Widget>) { + return Future<Widget>::makeReady(Widget(i.getValue() + 2)); + }) + .get(), + Widget(3)); + }); } TEST(Future_MoveOnly, Success_onCompletionFutureReady) { - FUTURE_SUCCESS_TEST([] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& 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); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut) + .onCompletion([](StatusWith<Widget> i) FTU_LAMBDA_R(Future<Widget>) { + auto pf = makePromiseFuture<Widget>(); + pf.promise.emplaceValue(i.getValue() + 2); + return std::move(pf.future); + }) + .get(), + Widget(3)); + }); } TEST(Future_MoveOnly, Success_onCompletionFutureAsync) { - FUTURE_SUCCESS_TEST([] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .onCompletion([&](StatusWith<Widget> i) { - return async( - [i = i.getValue().val] { return Widget(i + 2); }); - }) - .get(), - 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut) + .onCompletion([&](StatusWith<Widget> i) { + return async([i = i.getValue().val] { return Widget(i + 2); }); + }) + .get(), + Widget(3)); + }); } TEST(Future_MoveOnly, Success_onCompletionFutureAsyncThrow) { - FUTURE_SUCCESS_TEST([] { return Widget(1); }, - [](/*Future<Widget>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .onCompletion([](StatusWith<Widget> i) { - uasserted(ErrorCodes::BadValue, "oh no!"); - return Future<Widget>(); - }) - .getNoThrow(), - ErrorCodes::BadValue); - }); + runTests([](auto&& 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>*/ auto&& fut) { + FUTURE_FAIL_TEST<Widget>([](auto&& fut) { ASSERT_EQ(std::move(fut) - .onCompletion([](StatusWith<Widget> i) { + .onCompletion([](StatusWith<Widget> i) FTU_LAMBDA_R(Status) { ASSERT_NOT_OK(i); return i.getStatus(); }) @@ -687,9 +636,9 @@ TEST(Future_MoveOnly, Fail_onCompletionSimple) { } TEST(Future_MoveOnly, Fail_onCompletionFutureAsync) { - FUTURE_FAIL_TEST<Widget>([](/*Future<Widget>*/ auto&& fut) { + FUTURE_FAIL_TEST<Widget>([](auto&& fut) { ASSERT_EQ(std::move(fut) - .onCompletion([](StatusWith<Widget> i) { + .onCompletion([](StatusWith<Widget> i) FTU_LAMBDA_R(Status) { ASSERT_NOT_OK(i); return i.getStatus(); }) @@ -699,7 +648,7 @@ TEST(Future_MoveOnly, Fail_onCompletionFutureAsync) { } TEST(Future_MoveOnly, Fail_onCompletionError_throw) { - FUTURE_FAIL_TEST<Widget>([](/*Future<Widget>*/ auto&& fut) { + FUTURE_FAIL_TEST<Widget>([](auto&& fut) { auto fut2 = std::move(fut).onCompletion([](StatusWith<Widget> s) -> Widget { ASSERT_EQ(s.getStatus(), failStatus()); uasserted(ErrorCodes::BadValue, "oh no!"); @@ -709,38 +658,39 @@ TEST(Future_MoveOnly, Fail_onCompletionError_throw) { } TEST(Future_MoveOnly, Fail_onCompletionError_StatusWith) { - FUTURE_FAIL_TEST<Widget>([](/*Future<Widget>*/ auto&& fut) { - auto fut2 = std::move(fut).onCompletion([](StatusWith<Widget> s) { - ASSERT_EQ(s.getStatus(), failStatus()); - return StatusWith<Widget>(ErrorCodes::BadValue, "oh no!"); - }); + FUTURE_FAIL_TEST<Widget>([](auto&& fut) { + auto fut2 = + std::move(fut).onCompletion([](StatusWith<Widget> s) FTU_LAMBDA_R(StatusWith<Widget>) { + 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>*/ auto&& fut) { + FUTURE_FAIL_TEST<Widget>([](auto&& fut) { ASSERT_EQ(std::move(fut) - .onCompletion([](StatusWith<Widget> s) { + .onCompletion([](StatusWith<Widget> s) FTU_LAMBDA_R(Future<Widget>) { ASSERT_EQ(s.getStatus(), failStatus()); return Future<Widget>::makeReady(Widget(3)); }) .get(), - 3); + Widget(3)); }); } TEST(Future_MoveOnly, Fail_onCompletionFutureReady) { - FUTURE_FAIL_TEST<Widget>([](/*Future<Widget>*/ auto&& fut) { + FUTURE_FAIL_TEST<Widget>([](auto&& fut) { ASSERT_EQ(std::move(fut) - .onCompletion([](StatusWith<Widget> s) { + .onCompletion([](StatusWith<Widget> s) FTU_LAMBDA_R(Future<Widget>) { ASSERT_EQ(s.getStatus(), failStatus()); auto pf = makePromiseFuture<Widget>(); pf.promise.emplaceValue(3); return std::move(pf.future); }) .get(), - 3); + Widget(3)); }); } @@ -752,7 +702,7 @@ TEST(Future_MoveOnly, Success_vector) { vec.emplace_back(1); return vec; }, - [](auto&& fut) { ASSERT_EQ(fut.get()[0], 1); }); + [](auto&& fut) { ASSERT_EQ(fut.get()[0], Widget(1)); }); } TEST(Future_MoveOnly, Success_list) { @@ -762,7 +712,7 @@ TEST(Future_MoveOnly, Success_list) { lst.emplace_back(1); return lst; }, - [](auto&& fut) { ASSERT_EQ(fut.get().front(), 1); }); + [](auto&& fut) { ASSERT_EQ(fut.get().front(), Widget(1)); }); } TEST(Future_MoveOnly, Success_set) { @@ -792,8 +742,8 @@ TEST(Future_MoveOnly, Success_pair) { }, [](auto&& fut) { auto&& pair = fut.get(); - ASSERT_EQ(pair.first, 1); - ASSERT_EQ(pair.second, 1); + ASSERT_EQ(pair.first, Widget(1)); + ASSERT_EQ(pair.second, Widget(1)); }); } @@ -827,7 +777,7 @@ TEST(Future_MoveOnly, Success_nested_container) { return outer; }, - [](auto&& fut) { ASSERT_EQ(fut.get()[0][0], 1); }); + [](auto&& fut) { ASSERT_EQ(fut.get()[0][0], Widget(1)); }); } diff --git a/src/mongo/util/future_test_future_void.cpp b/src/mongo/util/future_test_future_void.cpp index c9e9f5dfa51..a8e0c9f3515 100644 --- a/src/mongo/util/future_test_future_void.cpp +++ b/src/mongo/util/future_test_future_void.cpp @@ -40,88 +40,85 @@ namespace mongo { namespace { +template <DoExecutorFuture doExecutorFuture = kDoExecutorFuture, typename F> +void runTests(F&& f) { + FUTURE_SUCCESS_TEST<doExecutorFuture>([] {}, std::forward<F>(f)); +} + +template <DoExecutorFuture doExecutorFuture = kDoExecutorFuture, typename F> +void runFailureTests(F&& f) { + FUTURE_FAIL_TEST<void, doExecutorFuture>(std::forward<F>(f)); +} + TEST(Future_Void, Success_getLvalue) { - FUTURE_SUCCESS_TEST([] {}, [](/*Future<void>*/ auto&& fut) { fut.get(); }); + runTests([](auto&& fut) { fut.get(); }); } TEST(Future_Void, Success_getConstLvalue) { - FUTURE_SUCCESS_TEST([] {}, [](const /*Future<void>*/ auto& fut) { fut.get(); }); + runTests([](const auto& fut) { fut.get(); }); } TEST(Future_Void, Success_getRvalue) { - FUTURE_SUCCESS_TEST([] {}, [](/*Future<void>*/ auto&& fut) { std::move(fut).get(); }); + runTests([](auto&& fut) { std::move(fut).get(); }); } TEST(Future_Void, Success_getNothrowLvalue) { - FUTURE_SUCCESS_TEST( - [] {}, [](/*Future<void>*/ auto&& fut) { ASSERT_EQ(fut.getNoThrow(), Status::OK()); }); + runTests([](auto&& fut) { ASSERT_EQ(fut.getNoThrow(), Status::OK()); }); } TEST(Future_Void, Success_getNothrowConstLvalue) { - FUTURE_SUCCESS_TEST( - [] {}, [](const /*Future<void>*/ auto& fut) { ASSERT_EQ(fut.getNoThrow(), Status::OK()); }); + runTests([](const auto& fut) { ASSERT_EQ(fut.getNoThrow(), Status::OK()); }); } TEST(Future_Void, Success_getNothrowRvalue) { - FUTURE_SUCCESS_TEST( - [] {}, - [](/*Future<void>*/ auto&& fut) { ASSERT_EQ(std::move(fut).getNoThrow(), Status::OK()); }); + runTests([](auto&& fut) { ASSERT_EQ(std::move(fut).getNoThrow(), Status::OK()); }); } TEST(Future_Void, Success_semi_get) { - FUTURE_SUCCESS_TEST([] {}, [](/*Future<void>*/ auto&& fut) { std::move(fut).semi().get(); }); + runTests([](auto&& fut) { std::move(fut).semi().get(); }); } TEST(Future_Void, Success_getAsync) { - FUTURE_SUCCESS_TEST([] {}, - [](/*Future<void>*/ auto&& fut) { - auto pf = makePromiseFuture<void>(); - std::move(fut).getAsync( - [outside = std::move(pf.promise)](Status status) mutable { - ASSERT_OK(status); - outside.emplaceValue(); - }); - ASSERT_EQ(std::move(pf.future).getNoThrow(), Status::OK()); - }); + runTests([](auto&& fut) { + auto pf = makePromiseFuture<void>(); + std::move(fut).getAsync([outside = std::move(pf.promise)](Status status) mutable { + ASSERT_OK(status); + outside.emplaceValue(); + }); + ASSERT_EQ(std::move(pf.future).getNoThrow(), Status::OK()); + }); } TEST(Future_Void, Fail_getLvalue) { - FUTURE_FAIL_TEST<void>( - [](/*Future<void>*/ auto&& fut) { ASSERT_THROWS_failStatus(fut.get()); }); + runFailureTests([](auto&& fut) { ASSERT_THROWS_failStatus(fut.get()); }); } TEST(Future_Void, Fail_getConstLvalue) { - FUTURE_FAIL_TEST<void>( - [](const /*Future<void>*/ auto& fut) { ASSERT_THROWS_failStatus(fut.get()); }); + runFailureTests([](const auto& fut) { ASSERT_THROWS_failStatus(fut.get()); }); } TEST(Future_Void, Fail_getRvalue) { - FUTURE_FAIL_TEST<void>( - [](/*Future<void>*/ auto&& fut) { ASSERT_THROWS_failStatus(std::move(fut).get()); }); + runFailureTests([](auto&& fut) { ASSERT_THROWS_failStatus(std::move(fut).get()); }); } TEST(Future_Void, Fail_getNothrowLvalue) { - FUTURE_FAIL_TEST<void>( - [](/*Future<void>*/ auto&& fut) { ASSERT_EQ(fut.getNoThrow(), failStatus()); }); + runFailureTests([](auto&& fut) { ASSERT_EQ(fut.getNoThrow(), failStatus()); }); } TEST(Future_Void, Fail_getNothrowConstLvalue) { - FUTURE_FAIL_TEST<void>( - [](const /*Future<void>*/ auto& fut) { ASSERT_EQ(fut.getNoThrow(), failStatus()); }); + runFailureTests([](const auto& fut) { ASSERT_EQ(fut.getNoThrow(), failStatus()); }); } TEST(Future_Void, Fail_getNothrowRvalue) { - FUTURE_FAIL_TEST<void>( - [](/*Future<void>*/ auto&& fut) { ASSERT_EQ(std::move(fut).getNoThrow(), failStatus()); }); + runFailureTests([](auto&& fut) { ASSERT_EQ(std::move(fut).getNoThrow(), failStatus()); }); } TEST(Future_Void, Fail_semi_get) { - FUTURE_FAIL_TEST<void>( - [](/*Future<void>*/ auto&& fut) { ASSERT_THROWS_failStatus(std::move(fut).semi().get()); }); + runFailureTests([](auto&& fut) { ASSERT_THROWS_failStatus(std::move(fut).semi().get()); }); } TEST(Future_Void, Fail_getAsync) { - FUTURE_FAIL_TEST<void>([](/*Future<void>*/ auto&& fut) { + runFailureTests([](auto&& fut) { auto pf = makePromiseFuture<void>(); std::move(fut).getAsync([outside = std::move(pf.promise)](Status status) mutable { ASSERT(!status.isOK()); @@ -132,20 +129,19 @@ TEST(Future_Void, Fail_getAsync) { } TEST(Future_Void, Success_isReady) { - FUTURE_SUCCESS_TEST([] {}, - [](/*Future<void>*/ auto&& fut) { - const auto id = stdx::this_thread::get_id(); - while (!fut.isReady()) { - } - std::move(fut).getAsync([&](Status status) { - ASSERT_EQ(stdx::this_thread::get_id(), id); - ASSERT_OK(status); - }); - }); + runTests([](auto&& fut) { + const auto id = stdx::this_thread::get_id(); + while (!fut.isReady()) { + } + std::move(fut).getAsync([&](Status status) { + ASSERT_EQ(stdx::this_thread::get_id(), id); + ASSERT_OK(status); + }); + }); } TEST(Future_Void, Fail_isReady) { - FUTURE_FAIL_TEST<void>([](/*Future<void>*/ auto&& fut) { + runFailureTests([](auto&& fut) { const auto id = stdx::this_thread::get_id(); while (!fut.isReady()) { } @@ -168,91 +164,71 @@ TEST(Future_Void, isReady_TSAN_OK) { } TEST(Future_Void, Success_thenSimple) { - FUTURE_SUCCESS_TEST([] {}, - [](/*Future<void>*/ auto&& fut) { - ASSERT_EQ(std::move(fut).then([]() { return 3; }).get(), 3); - }); + runTests([](auto&& fut) { ASSERT_EQ(std::move(fut).then([]() { return 3; }).get(), 3); }); } TEST(Future_Void, Success_thenVoid) { - FUTURE_SUCCESS_TEST([] {}, - [](/*Future<void>*/ auto&& fut) { - ASSERT_EQ(std::move(fut).then([] {}).then([] { return 3; }).get(), 3); - }); + runTests( + [](auto&& fut) { ASSERT_EQ(std::move(fut).then([] {}).then([] { return 3; }).get(), 3); }); } TEST(Future_Void, Success_thenStatus) { - FUTURE_SUCCESS_TEST([] {}, - [](/*Future<void>*/ auto&& fut) { - ASSERT_EQ(std::move(fut).then([] {}).then([] { return 3; }).get(), 3); - }); + runTests( + [](auto&& fut) { ASSERT_EQ(std::move(fut).then([] {}).then([] { return 3; }).get(), 3); }); } TEST(Future_Void, Success_thenError_Status) { - FUTURE_SUCCESS_TEST( - [] {}, - [](/*Future<void>*/ auto&& fut) { - auto fut2 = - std::move(fut).then([]() { return Status(ErrorCodes::BadValue, "oh no!"); }); - static_assert(future_details::isFutureLike<decltype(fut2)>); - static_assert(std::is_same_v<typename decltype(fut2)::value_type, void>); - ASSERT_EQ(fut2.getNoThrow(), ErrorCodes::BadValue); - }); + runTests([](auto&& fut) { + auto fut2 = std::move(fut).then([]() { return Status(ErrorCodes::BadValue, "oh no!"); }); + static_assert(future_details::isFutureLike<decltype(fut2)>); + static_assert(std::is_same_v<typename decltype(fut2)::value_type, void>); + ASSERT_EQ(fut2.getNoThrow(), ErrorCodes::BadValue); + }); } TEST(Future_Void, Success_thenError_StatusWith) { - FUTURE_SUCCESS_TEST( - [] {}, - [](/*Future<void>*/ auto&& fut) { - auto fut2 = std::move(fut).then( - []() { return StatusWith<double>(ErrorCodes::BadValue, "oh no!"); }); - static_assert(future_details::isFutureLike<decltype(fut2)>); - static_assert(std::is_same_v<typename decltype(fut2)::value_type, double>); - ASSERT_EQ(fut2.getNoThrow(), ErrorCodes::BadValue); - }); + runTests([](auto&& fut) { + auto fut2 = std::move(fut).then( + []() { return StatusWith<double>(ErrorCodes::BadValue, "oh no!"); }); + static_assert(future_details::isFutureLike<decltype(fut2)>); + static_assert(std::is_same_v<typename decltype(fut2)::value_type, double>); + ASSERT_EQ(fut2.getNoThrow(), ErrorCodes::BadValue); + }); } TEST(Future_Void, Success_thenFutureImmediate) { - FUTURE_SUCCESS_TEST( - [] {}, - [](/*Future<void>*/ auto&& fut) { - ASSERT_EQ(std::move(fut).then([]() { return Future<int>::makeReady(3); }).get(), 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut).then([]() { return Future<int>::makeReady(3); }).get(), 3); + }); } TEST(Future_Void, Success_thenFutureReady) { - FUTURE_SUCCESS_TEST([] {}, - [](/*Future<void>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .then([]() { - auto pf = makePromiseFuture<int>(); - pf.promise.emplaceValue(3); - return std::move(pf.future); - }) - .get(), - 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut) + .then([]() { + auto pf = makePromiseFuture<int>(); + pf.promise.emplaceValue(3); + return std::move(pf.future); + }) + .get(), + 3); + }); } TEST(Future_Void, Success_thenFutureAsync) { - FUTURE_SUCCESS_TEST( - [] {}, - [](/*Future<void>*/ auto&& fut) { - ASSERT_EQ(std::move(fut).then([]() { return async([] { return 3; }); }).get(), 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut).then([]() { return async([] { return 3; }); }).get(), 3); + }); } TEST(Future_Void, Success_thenSemiFutureAsync) { - FUTURE_SUCCESS_TEST( - [] {}, - [](/*Future<void>*/ auto&& fut) { - ASSERT_EQ(std::move(fut).then([]() { return async([] { return 3; }).semi(); }).get(), - 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut).then([]() { return async([] { return 3; }).semi(); }).get(), 3); + }); } TEST(Future_Void, Fail_thenSimple) { - FUTURE_FAIL_TEST<void>([](/*Future<void>*/ auto&& fut) { + runFailureTests([](auto&& fut) { ASSERT_EQ(std::move(fut) .then([]() { FAIL("then() callback was called"); @@ -264,7 +240,7 @@ TEST(Future_Void, Fail_thenSimple) { } TEST(Future_Void, Fail_thenFutureAsync) { - FUTURE_FAIL_TEST<void>([](/*Future<void>*/ auto&& fut) { + runFailureTests([](auto&& fut) { ASSERT_EQ(std::move(fut) .then([]() { FAIL("then() callback was called"); @@ -276,35 +252,33 @@ TEST(Future_Void, Fail_thenFutureAsync) { } TEST(Future_Void, Success_onErrorSimple) { - FUTURE_SUCCESS_TEST([] {}, - [](/*Future<void>*/ auto&& fut) { - ASSERT_EQ( - std::move(fut) - .onError([](Status) { FAIL("onError() callback was called"); }) - .then([] { return 3; }) - .get(), - 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ( + std::move(fut) + .onError([](Status) FTU_LAMBDA_R(void) { FAIL("onError() callback was called"); }) + .then([] { return 3; }) + .get(), + 3); + }); } TEST(Future_Void, Success_onErrorFutureAsync) { - FUTURE_SUCCESS_TEST([] {}, - [](/*Future<void>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .onError([](Status) { - FAIL("onError() callback was called"); - return Future<void>(); - }) - .then([] { return 3; }) - .get(), - 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut) + .onError([](Status) FTU_LAMBDA_R(Future<void>) { + FAIL("onError() callback was called"); + return Future<void>(); + }) + .then([] { return 3; }) + .get(), + 3); + }); } TEST(Future_Void, Fail_onErrorSimple) { - FUTURE_FAIL_TEST<void>([](/*Future<void>*/ auto&& fut) { + runFailureTests([](auto&& fut) { ASSERT_EQ(std::move(fut) - .onError([](Status s) { ASSERT_EQ(s, failStatus()); }) + .onError([](Status s) FTU_LAMBDA_R(void) { ASSERT_EQ(s, failStatus()); }) .then([] { return 3; }) .getNoThrow(), 3); @@ -312,7 +286,7 @@ TEST(Future_Void, Fail_onErrorSimple) { } TEST(Future_Void, Fail_onErrorError_throw) { - FUTURE_FAIL_TEST<void>([](/*Future<void>*/ auto&& fut) { + runFailureTests([](auto&& fut) { auto fut2 = std::move(fut).onError([](Status s) { ASSERT_EQ(s, failStatus()); uasserted(ErrorCodes::BadValue, "oh no!"); @@ -322,8 +296,8 @@ TEST(Future_Void, Fail_onErrorError_throw) { } TEST(Future_Void, Fail_onErrorError_Status) { - FUTURE_FAIL_TEST<void>([](/*Future<void>*/ auto&& fut) { - auto fut2 = std::move(fut).onError([](Status s) { + runFailureTests([](auto&& fut) { + auto fut2 = std::move(fut).onError([](Status s) FTU_LAMBDA_R(Status) { ASSERT_EQ(s, failStatus()); return Status(ErrorCodes::BadValue, "oh no!"); }); @@ -332,9 +306,9 @@ TEST(Future_Void, Fail_onErrorError_Status) { } TEST(Future_Void, Fail_onErrorFutureImmediate) { - FUTURE_FAIL_TEST<void>([](/*Future<void>*/ auto&& fut) { + runFailureTests([](auto&& fut) { ASSERT_EQ(std::move(fut) - .onError([](Status s) { + .onError([](Status s) FTU_LAMBDA_R(Future<void>) { ASSERT_EQ(s, failStatus()); return Future<void>::makeReady(); }) @@ -345,9 +319,9 @@ TEST(Future_Void, Fail_onErrorFutureImmediate) { } TEST(Future_Void, Fail_onErrorFutureReady) { - FUTURE_FAIL_TEST<void>([](/*Future<void>*/ auto&& fut) { + runFailureTests([](auto&& fut) { ASSERT_EQ(std::move(fut) - .onError([](Status s) { + .onError([](Status s) FTU_LAMBDA_R(Future<void>) { ASSERT_EQ(s, failStatus()); auto pf = makePromiseFuture<void>(); pf.promise.emplaceValue(); @@ -360,9 +334,9 @@ TEST(Future_Void, Fail_onErrorFutureReady) { } TEST(Future_Void, Fail_onErrorFutureAsync) { - FUTURE_FAIL_TEST<void>([](/*Future<void>*/ auto&& fut) { + runFailureTests([](auto&& fut) { ASSERT_EQ(std::move(fut) - .onError([&](Status s) { + .onError([&](Status s) FTU_LAMBDA_R(Future<void>) { ASSERT_EQ(s, failStatus()); return async([] {}); }) @@ -373,24 +347,23 @@ TEST(Future_Void, Fail_onErrorFutureAsync) { } TEST(Future_Void, Success_onErrorCode) { - FUTURE_SUCCESS_TEST([] {}, - [](/*Future<void>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .template onError<ErrorCodes::InternalError>([](Status) { - FAIL("onError<code>() callback was called"); - }) - .then([] { return 3; }) - .get(), - 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut) + .template onError<ErrorCodes::InternalError>([](Status) FTU_LAMBDA_R(void) { + FAIL("onError<code>() callback was called"); + }) + .then([] { return 3; }) + .get(), + 3); + }); } TEST(Future_Void, Fail_onErrorCodeMatch) { - FUTURE_FAIL_TEST<void>([](/*Future<void>*/ auto&& fut) { + runFailureTests([](auto&& fut) { bool called = false; auto res = std::move(fut) - .onError([](Status s) { + .onError([](Status s) FTU_LAMBDA_R(Status) { ASSERT_EQ(s, failStatus()); return Status(ErrorCodes::InternalError, ""); }) @@ -403,10 +376,10 @@ TEST(Future_Void, Fail_onErrorCodeMatch) { } TEST(Future_Void, Fail_onErrorCodeMatchFuture) { - FUTURE_FAIL_TEST<void>([](/*Future<void>*/ auto&& fut) { + runFailureTests([](auto&& fut) { bool called = false; auto res = std::move(fut) - .onError([](Status s) { + .onError([](Status s) FTU_LAMBDA_R(Status) { ASSERT_EQ(s, failStatus()); return Status(ErrorCodes::InternalError, ""); }) @@ -422,11 +395,11 @@ TEST(Future_Void, Fail_onErrorCodeMatchFuture) { } TEST(Future_Void, Fail_onErrorCodeMismatch) { - FUTURE_FAIL_TEST<void>([](/*Future<void>*/ auto&& fut) { + runFailureTests([](auto&& fut) { ASSERT_EQ(std::move(fut) .template onError<ErrorCodes::InternalError>( - [](Status s) { FAIL("Why was this called?") << s; }) - .onError([](Status s) { ASSERT_EQ(s, failStatus()); }) + [](Status s) FTU_LAMBDA_R(void) { FAIL("Why was this called?") << s; }) + .onError([](Status s) FTU_LAMBDA_R(void) { ASSERT_EQ(s, failStatus()); }) .then([] { return 3; }) .getNoThrow(), 3); @@ -434,51 +407,45 @@ TEST(Future_Void, Fail_onErrorCodeMismatch) { } TEST(Future_Void, Success_tap) { - FUTURE_SUCCESS_TEST<kNoExecutorFuture_needsTap>( - [] {}, - [](/*Future<void>*/ auto&& fut) { - bool tapCalled = false; - ASSERT_EQ( - std::move(fut).tap([&tapCalled] { tapCalled = true; }).then([] { return 3; }).get(), - 3); - ASSERT(tapCalled); - }); + runTests<kNoExecutorFuture_needsTap>([](auto&& fut) { + bool tapCalled = false; + ASSERT_EQ( + std::move(fut).tap([&tapCalled] { tapCalled = true; }).then([] { return 3; }).get(), 3); + ASSERT(tapCalled); + }); } TEST(Future_Void, Success_tapError) { - FUTURE_SUCCESS_TEST<kNoExecutorFuture_needsTap>( - [] {}, - [](/*Future<void>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .tapError([](Status s) { FAIL("tapError() callback was called"); }) - .then([] { return 3; }) - .get(), - 3); - }); + runTests<kNoExecutorFuture_needsTap>([](auto&& fut) { + ASSERT_EQ(std::move(fut) + .tapError([](Status s) + FTU_LAMBDA_R(void) { FAIL("tapError() callback was called"); }) + .then([] { return 3; }) + .get(), + 3); + }); } TEST(Future_Void, Success_tapAll_StatusWith) { - FUTURE_SUCCESS_TEST<kNoExecutorFuture_needsTap>([] {}, - [](/*Future<void>*/ auto&& fut) { - bool tapCalled = false; - ASSERT_EQ( - std::move(fut) - .tapAll([&tapCalled](Status s) { - ASSERT_OK(s); - tapCalled = true; - }) - .then([] { return 3; }) - .get(), - 3); - ASSERT(tapCalled); - }); + runTests<kNoExecutorFuture_needsTap>([](auto&& fut) { + bool tapCalled = false; + ASSERT_EQ(std::move(fut) + .tapAll([&tapCalled](Status s) { + ASSERT_OK(s); + tapCalled = true; + }) + .then([] { return 3; }) + .get(), + 3); + ASSERT(tapCalled); + }); } TEST(Future_Void, Fail_tap) { - FUTURE_FAIL_TEST<void, kNoExecutorFuture_needsTap>([](/*Future<void>*/ auto&& fut) { + runFailureTests<kNoExecutorFuture_needsTap>([](auto&& fut) { ASSERT_EQ(std::move(fut) .tap([] { FAIL("tap() callback was called"); }) - .onError([](Status s) { ASSERT_EQ(s, failStatus()); }) + .onError([](Status s) FTU_LAMBDA_R(void) { ASSERT_EQ(s, failStatus()); }) .then([] { return 3; }) .get(), 3); @@ -486,14 +453,14 @@ TEST(Future_Void, Fail_tap) { } TEST(Future_Void, Fail_tapError) { - FUTURE_FAIL_TEST<void, kNoExecutorFuture_needsTap>([](/*Future<void>*/ auto&& fut) { + runFailureTests<kNoExecutorFuture_needsTap>([](auto&& fut) { bool tapCalled = false; ASSERT_EQ(std::move(fut) .tapError([&tapCalled](Status s) { ASSERT_EQ(s, failStatus()); tapCalled = true; }) - .onError([](Status s) { ASSERT_EQ(s, failStatus()); }) + .onError([](Status s) FTU_LAMBDA_R(void) { ASSERT_EQ(s, failStatus()); }) .then([] { return 3; }) .get(), 3); @@ -502,14 +469,14 @@ TEST(Future_Void, Fail_tapError) { } TEST(Future_Void, Fail_tapAll_StatusWith) { - FUTURE_FAIL_TEST<void, kNoExecutorFuture_needsTap>([](/*Future<void>*/ auto&& fut) { + runFailureTests<kNoExecutorFuture_needsTap>([](auto&& fut) { bool tapCalled = false; ASSERT_EQ(std::move(fut) .tapAll([&tapCalled](Status sw) { ASSERT_EQ(sw, failStatus()); tapCalled = true; }) - .onError([](Status s) { ASSERT_EQ(s, failStatus()); }) + .onError([](Status s) FTU_LAMBDA_R(void) { ASSERT_EQ(s, failStatus()); }) .then([] { return 3; }) .get(), 3); @@ -518,102 +485,93 @@ TEST(Future_Void, Fail_tapAll_StatusWith) { } TEST(Future_Void, Success_onCompletionSimple) { - FUTURE_SUCCESS_TEST([] {}, - [](/*Future<void>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .onCompletion([](Status status) { - ASSERT_OK(status); - return 3; - }) - .get(), - 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut) + .onCompletion([](Status status) FTU_LAMBDA_R(int) { + ASSERT_OK(status); + return 3; + }) + .get(), + 3); + }); } TEST(Future_Void, Success_onCompletionVoid) { - FUTURE_SUCCESS_TEST([] {}, - [](/*Future<void>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .onCompletion([](Status status) { ASSERT_OK(status); }) - .then([]() { return 3; }) - .get(), - 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut) + .onCompletion([](Status status) FTU_LAMBDA_R(void) { ASSERT_OK(status); }) + .then([]() { return 3; }) + .get(), + 3); + }); } TEST(Future_Void, Success_onCompletionError_Status) { - FUTURE_SUCCESS_TEST([] {}, - [](/*Future<void>*/ auto&& fut) { - auto fut2 = std::move(fut).onCompletion([](Status status) { - ASSERT_OK(status); - return Status(ErrorCodes::BadValue, "oh no!"); - }); - static_assert(future_details::isFutureLike<decltype(fut2)>); - static_assert( - std::is_same_v<typename decltype(fut2)::value_type, void>); - ASSERT_EQ(fut2.getNoThrow(), ErrorCodes::BadValue); - }); + runTests([](auto&& fut) { + auto fut2 = std::move(fut).onCompletion([](Status status) FTU_LAMBDA_R(Status) { + ASSERT_OK(status); + return Status(ErrorCodes::BadValue, "oh no!"); + }); + static_assert(future_details::isFutureLike<decltype(fut2)>); + static_assert(std::is_same_v<typename decltype(fut2)::value_type, void>); + ASSERT_EQ(fut2.getNoThrow(), ErrorCodes::BadValue); + }); } TEST(Future_Void, Success_onCompletionError_StatusWith) { - FUTURE_SUCCESS_TEST([] {}, - [](/*Future<void>*/ auto&& fut) { - auto fut2 = std::move(fut).onCompletion([](Status status) { - ASSERT_OK(status); - return StatusWith<double>(ErrorCodes::BadValue, "oh no!"); - }); - static_assert(future_details::isFutureLike<decltype(fut2)>); - static_assert( - std::is_same_v<typename decltype(fut2)::value_type, double>); - ASSERT_EQ(fut2.getNoThrow(), ErrorCodes::BadValue); - }); + runTests([](auto&& fut) { + auto fut2 = std::move(fut).onCompletion([](Status status) FTU_LAMBDA_R(StatusWith<double>) { + ASSERT_OK(status); + return StatusWith<double>(ErrorCodes::BadValue, "oh no!"); + }); + static_assert(future_details::isFutureLike<decltype(fut2)>); + static_assert(std::is_same_v<typename decltype(fut2)::value_type, double>); + ASSERT_EQ(fut2.getNoThrow(), ErrorCodes::BadValue); + }); } TEST(Future_Void, Success_onCompletionFutureImmediate) { - FUTURE_SUCCESS_TEST([] {}, - [](/*Future<void>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .onCompletion([](Status status) { - ASSERT_OK(status); - return Future<int>::makeReady(3); - }) - .get(), - 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut) + .onCompletion([](Status status) FTU_LAMBDA_R(Future<int>) { + ASSERT_OK(status); + return Future<int>::makeReady(3); + }) + .get(), + 3); + }); } TEST(Future_Void, Success_onCompletionFutureReady) { - FUTURE_SUCCESS_TEST([] {}, - [](/*Future<void>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .onCompletion([](Status status) { - ASSERT_OK(status); - auto pf = makePromiseFuture<int>(); - pf.promise.emplaceValue(3); - return std::move(pf.future); - }) - .get(), - 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut) + .onCompletion([](Status status) FTU_LAMBDA_R(Future<int>) { + ASSERT_OK(status); + auto pf = makePromiseFuture<int>(); + pf.promise.emplaceValue(3); + return std::move(pf.future); + }) + .get(), + 3); + }); } TEST(Future_Void, Success_onCompletionFutureAsync) { - FUTURE_SUCCESS_TEST([] {}, - [](/*Future<void>*/ auto&& fut) { - ASSERT_EQ(std::move(fut) - .onCompletion([](Status status) { - ASSERT_OK(status); - return async([] { return 3; }); - }) - .get(), - 3); - }); + runTests([](auto&& fut) { + ASSERT_EQ(std::move(fut) + .onCompletion([](Status status) { + ASSERT_OK(status); + return async([] { return 3; }); + }) + .get(), + 3); + }); } TEST(Future_Void, Fail_onCompletionSimple) { - FUTURE_FAIL_TEST<void>([](/*Future<void>*/ auto&& fut) { + runFailureTests([](auto&& fut) { ASSERT_EQ(std::move(fut) - .onCompletion([](Status s) { ASSERT_EQ(s, failStatus()); }) + .onCompletion([](Status s) FTU_LAMBDA_R(void) { ASSERT_EQ(s, failStatus()); }) .then([] { return 3; }) .getNoThrow(), 3); @@ -621,7 +579,7 @@ TEST(Future_Void, Fail_onCompletionSimple) { } TEST(Future_Void, Fail_onCompletionError_throw) { - FUTURE_FAIL_TEST<void>([](/*Future<void>*/ auto&& fut) { + runFailureTests([](auto&& fut) { auto fut2 = std::move(fut).onCompletion([](Status s) { ASSERT_EQ(s, failStatus()); uasserted(ErrorCodes::BadValue, "oh no!"); @@ -631,8 +589,8 @@ TEST(Future_Void, Fail_onCompletionError_throw) { } TEST(Future_Void, Fail_onCompletionError_Status) { - FUTURE_FAIL_TEST<void>([](/*Future<void>*/ auto&& fut) { - auto fut2 = std::move(fut).onCompletion([](Status s) { + runFailureTests([](auto&& fut) { + auto fut2 = std::move(fut).onCompletion([](Status s) FTU_LAMBDA_R(Status) { ASSERT_EQ(s, failStatus()); return Status(ErrorCodes::BadValue, "oh no!"); }); @@ -641,9 +599,9 @@ TEST(Future_Void, Fail_onCompletionError_Status) { } TEST(Future_Void, Fail_onCompletionFutureImmediate) { - FUTURE_FAIL_TEST<void>([](/*Future<void>*/ auto&& fut) { + runFailureTests([](auto&& fut) { ASSERT_EQ(std::move(fut) - .onCompletion([](Status s) { + .onCompletion([](Status s) FTU_LAMBDA_R(Future<void>) { ASSERT_EQ(s, failStatus()); return Future<void>::makeReady(); }) @@ -654,9 +612,9 @@ TEST(Future_Void, Fail_onCompletionFutureImmediate) { } TEST(Future_Void, Fail_onCompletionFutureReady) { - FUTURE_FAIL_TEST<void>([](/*Future<void>*/ auto&& fut) { + runFailureTests([](auto&& fut) { ASSERT_EQ(std::move(fut) - .onCompletion([](Status s) { + .onCompletion([](Status s) FTU_LAMBDA_R(Future<void>) { ASSERT_EQ(s, failStatus()); auto pf = makePromiseFuture<void>(); pf.promise.emplaceValue(); @@ -669,9 +627,9 @@ TEST(Future_Void, Fail_onCompletionFutureReady) { } TEST(Future_Void, Fail_onCompletionFutureAsync) { - FUTURE_FAIL_TEST<void>([](/*Future<void>*/ auto&& fut) { + runFailureTests([](auto&& fut) { ASSERT_EQ(std::move(fut) - .onCompletion([&](Status s) { + .onCompletion([&](Status s) FTU_LAMBDA_R(Future<void>) { ASSERT_EQ(s, failStatus()); return async([] {}); }) diff --git a/src/mongo/util/future_test_utils.h b/src/mongo/util/future_test_utils.h index ecf44d67470..8bbecfd1faa 100644 --- a/src/mongo/util/future_test_utils.h +++ b/src/mongo/util/future_test_utils.h @@ -41,6 +41,13 @@ #define __has_feature(x) 0 #endif +/** Workaround for bug in MSVC 2022's lambda processor. See SERVER-62480. */ +#ifdef _MSC_VER +#define FTU_LAMBDA_R(...) ->__VA_ARGS__ +#else +#define FTU_LAMBDA_R(...) +#endif + namespace mongo { enum DoExecutorFuture : bool { |