summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBilly Donahue <billy.donahue@mongodb.com>2022-01-11 23:41:36 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-01-13 06:56:37 +0000
commitf212fff6d910cd717e2a7979ed51687d0fb4832a (patch)
treed920827b951c93ec1f6c88d43cece211d1708133
parentfd6b2a875f8942a4ba7fea916b4c52a913e14f49 (diff)
downloadmongo-f212fff6d910cd717e2a7979ed51687d0fb4832a.tar.gz
SERVER-62564 Trailing return types in complex lambdas in future_test_*
Revert "SERVER-62480 disable new lambda processor in MSVC2022 C++20 mode" This reverts commit cf0d1ffe36d1d787169569989abefa6cbdb2e163.
-rw-r--r--SConstruct6
-rw-r--r--src/mongo/util/future_test_executor_future.cpp115
-rw-r--r--src/mongo/util/future_test_future_int.cpp403
-rw-r--r--src/mongo/util/future_test_future_move_only.cpp624
-rw-r--r--src/mongo/util/future_test_future_void.cpp508
-rw-r--r--src/mongo/util/future_test_utils.h7
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 {