Merge branch 'interception-chain' of github.com:ctiller/grpc into interception-chain

pull/36414/head
Craig Tiller 7 months ago
commit 90c8e96973
  1. 80
      src/core/lib/channel/promise_based_filter.h
  2. 2
      src/core/lib/promise/party.cc
  3. 6
      src/core/lib/transport/call_arena_allocator.h
  4. 46
      src/core/lib/transport/call_filters.h
  5. 9
      src/core/lib/transport/interception_chain.cc
  6. 4
      test/core/promise/BUILD
  7. 6
      test/core/promise/poll_matcher.h
  8. 2
      test/core/transport/BUILD
  9. 5
      test/core/transport/chaotic_good/client_transport_error_test.cc
  10. 5
      test/core/transport/chaotic_good/transport_test.h
  11. 5
      test/core/transport/test_suite/test.h

@ -350,7 +350,7 @@ auto MapResult(const NoInterceptor*, Promise x, void*) {
} }
template <typename Promise, typename Derived> template <typename Promise, typename Derived>
auto MapResult(absl::Status (Derived::Call::* fn)(ServerMetadata&), Promise x, auto MapResult(absl::Status (Derived::Call::*fn)(ServerMetadata&), Promise x,
FilterCallData<Derived>* call_data) { FilterCallData<Derived>* call_data) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerTrailingMetadata); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerTrailingMetadata);
return Map(std::move(x), [call_data](ServerMetadataHandle md) { return Map(std::move(x), [call_data](ServerMetadataHandle md) {
@ -361,7 +361,7 @@ auto MapResult(absl::Status (Derived::Call::* fn)(ServerMetadata&), Promise x,
} }
template <typename Promise, typename Derived> template <typename Promise, typename Derived>
auto MapResult(void (Derived::Call::* fn)(ServerMetadata&), Promise x, auto MapResult(void (Derived::Call::*fn)(ServerMetadata&), Promise x,
FilterCallData<Derived>* call_data) { FilterCallData<Derived>* call_data) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerTrailingMetadata); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerTrailingMetadata);
return Map(std::move(x), [call_data](ServerMetadataHandle md) { return Map(std::move(x), [call_data](ServerMetadataHandle md) {
@ -371,7 +371,7 @@ auto MapResult(void (Derived::Call::* fn)(ServerMetadata&), Promise x,
} }
template <typename Promise, typename Derived> template <typename Promise, typename Derived>
auto MapResult(void (Derived::Call::* fn)(ServerMetadata&, Derived*), Promise x, auto MapResult(void (Derived::Call::*fn)(ServerMetadata&, Derived*), Promise x,
FilterCallData<Derived>* call_data) { FilterCallData<Derived>* call_data) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerTrailingMetadata); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerTrailingMetadata);
return Map(std::move(x), [call_data](ServerMetadataHandle md) { return Map(std::move(x), [call_data](ServerMetadataHandle md) {
@ -496,7 +496,7 @@ inline void InterceptClientToServerMessage(const NoInterceptor*, void*,
template <typename Derived> template <typename Derived>
inline void InterceptClientToServerMessage( inline void InterceptClientToServerMessage(
ServerMetadataHandle (Derived::Call::* fn)(const Message&), ServerMetadataHandle (Derived::Call::*fn)(const Message&),
FilterCallData<Derived>* call_data, const CallArgs& call_args) { FilterCallData<Derived>* call_data, const CallArgs& call_args) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientToServerMessage); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientToServerMessage);
call_args.client_to_server_messages->InterceptAndMap( call_args.client_to_server_messages->InterceptAndMap(
@ -511,7 +511,7 @@ inline void InterceptClientToServerMessage(
template <typename Derived> template <typename Derived>
inline void InterceptClientToServerMessage( inline void InterceptClientToServerMessage(
ServerMetadataHandle (Derived::Call::* fn)(const Message&, Derived*), ServerMetadataHandle (Derived::Call::*fn)(const Message&, Derived*),
FilterCallData<Derived>* call_data, const CallArgs& call_args) { FilterCallData<Derived>* call_data, const CallArgs& call_args) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientToServerMessage); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientToServerMessage);
call_args.client_to_server_messages->InterceptAndMap( call_args.client_to_server_messages->InterceptAndMap(
@ -527,7 +527,7 @@ inline void InterceptClientToServerMessage(
template <typename Derived> template <typename Derived>
inline void InterceptClientToServerMessage( inline void InterceptClientToServerMessage(
MessageHandle (Derived::Call::* fn)(MessageHandle, Derived*), MessageHandle (Derived::Call::*fn)(MessageHandle, Derived*),
FilterCallData<Derived>* call_data, const CallArgs& call_args) { FilterCallData<Derived>* call_data, const CallArgs& call_args) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientToServerMessage); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientToServerMessage);
call_args.client_to_server_messages->InterceptAndMap( call_args.client_to_server_messages->InterceptAndMap(
@ -539,8 +539,7 @@ inline void InterceptClientToServerMessage(
template <typename Derived> template <typename Derived>
inline void InterceptClientToServerMessage( inline void InterceptClientToServerMessage(
absl::StatusOr<MessageHandle> (Derived::Call::* fn)(MessageHandle, absl::StatusOr<MessageHandle> (Derived::Call::*fn)(MessageHandle, Derived*),
Derived*),
FilterCallData<Derived>* call_data, const CallArgs& call_args) { FilterCallData<Derived>* call_data, const CallArgs& call_args) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientToServerMessage); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientToServerMessage);
call_args.client_to_server_messages->InterceptAndMap( call_args.client_to_server_messages->InterceptAndMap(
@ -559,7 +558,7 @@ inline void InterceptClientToServerMessage(const NoInterceptor*, void*, void*,
template <typename Derived> template <typename Derived>
inline void InterceptClientToServerMessage( inline void InterceptClientToServerMessage(
ServerMetadataHandle (Derived::Call::* fn)(const Message&), ServerMetadataHandle (Derived::Call::*fn)(const Message&),
typename Derived::Call* call, Derived*, PipeBasedCallSpine* call_spine) { typename Derived::Call* call, Derived*, PipeBasedCallSpine* call_spine) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientToServerMessage); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientToServerMessage);
call_spine->client_to_server_messages().receiver.InterceptAndMap( call_spine->client_to_server_messages().receiver.InterceptAndMap(
@ -573,7 +572,7 @@ inline void InterceptClientToServerMessage(
template <typename Derived> template <typename Derived>
inline void InterceptClientToServerMessage( inline void InterceptClientToServerMessage(
ServerMetadataHandle (Derived::Call::* fn)(const Message&, Derived*), ServerMetadataHandle (Derived::Call::*fn)(const Message&, Derived*),
typename Derived::Call* call, Derived* channel, typename Derived::Call* call, Derived* channel,
PipeBasedCallSpine* call_spine) { PipeBasedCallSpine* call_spine) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientToServerMessage); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientToServerMessage);
@ -589,7 +588,7 @@ inline void InterceptClientToServerMessage(
template <typename Derived> template <typename Derived>
inline void InterceptClientToServerMessage( inline void InterceptClientToServerMessage(
MessageHandle (Derived::Call::* fn)(MessageHandle, Derived*), MessageHandle (Derived::Call::*fn)(MessageHandle, Derived*),
typename Derived::Call* call, Derived* channel, typename Derived::Call* call, Derived* channel,
PipeBasedCallSpine* call_spine) { PipeBasedCallSpine* call_spine) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientToServerMessage); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientToServerMessage);
@ -601,8 +600,7 @@ inline void InterceptClientToServerMessage(
template <typename Derived> template <typename Derived>
inline void InterceptClientToServerMessage( inline void InterceptClientToServerMessage(
absl::StatusOr<MessageHandle> (Derived::Call::* fn)(MessageHandle, absl::StatusOr<MessageHandle> (Derived::Call::*fn)(MessageHandle, Derived*),
Derived*),
typename Derived::Call* call, Derived* channel, typename Derived::Call* call, Derived* channel,
PipeBasedCallSpine* call_spine) { PipeBasedCallSpine* call_spine) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientToServerMessage); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientToServerMessage);
@ -622,8 +620,8 @@ inline void InterceptClientInitialMetadata(const NoInterceptor*, void*, void*,
template <typename Derived> template <typename Derived>
inline void InterceptClientInitialMetadata( inline void InterceptClientInitialMetadata(
void (Derived::Call::* fn)(ClientMetadata& md), void (Derived::Call::*fn)(ClientMetadata& md), typename Derived::Call* call,
typename Derived::Call* call, Derived*, PipeBasedCallSpine* call_spine) { Derived*, PipeBasedCallSpine* call_spine) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientInitialMetadata); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientInitialMetadata);
call_spine->client_initial_metadata().receiver.InterceptAndMap( call_spine->client_initial_metadata().receiver.InterceptAndMap(
[call](ClientMetadataHandle md) { [call](ClientMetadataHandle md) {
@ -634,7 +632,7 @@ inline void InterceptClientInitialMetadata(
template <typename Derived> template <typename Derived>
inline void InterceptClientInitialMetadata( inline void InterceptClientInitialMetadata(
void (Derived::Call::* fn)(ClientMetadata& md, Derived* channel), void (Derived::Call::*fn)(ClientMetadata& md, Derived* channel),
typename Derived::Call* call, Derived* channel, typename Derived::Call* call, Derived* channel,
PipeBasedCallSpine* call_spine) { PipeBasedCallSpine* call_spine) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientInitialMetadata); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientInitialMetadata);
@ -647,7 +645,7 @@ inline void InterceptClientInitialMetadata(
template <typename Derived> template <typename Derived>
inline void InterceptClientInitialMetadata( inline void InterceptClientInitialMetadata(
ServerMetadataHandle (Derived::Call::* fn)(ClientMetadata& md), ServerMetadataHandle (Derived::Call::*fn)(ClientMetadata& md),
typename Derived::Call* call, Derived*, PipeBasedCallSpine* call_spine) { typename Derived::Call* call, Derived*, PipeBasedCallSpine* call_spine) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientInitialMetadata); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientInitialMetadata);
call_spine->client_initial_metadata().receiver.InterceptAndMap( call_spine->client_initial_metadata().receiver.InterceptAndMap(
@ -662,8 +660,8 @@ inline void InterceptClientInitialMetadata(
template <typename Derived> template <typename Derived>
inline void InterceptClientInitialMetadata( inline void InterceptClientInitialMetadata(
ServerMetadataHandle (Derived::Call::* fn)(ClientMetadata& md, ServerMetadataHandle (Derived::Call::*fn)(ClientMetadata& md,
Derived* channel), Derived* channel),
typename Derived::Call* call, Derived* channel, typename Derived::Call* call, Derived* channel,
PipeBasedCallSpine* call_spine) { PipeBasedCallSpine* call_spine) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientInitialMetadata); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientInitialMetadata);
@ -679,7 +677,7 @@ inline void InterceptClientInitialMetadata(
template <typename Derived> template <typename Derived>
inline void InterceptClientInitialMetadata( inline void InterceptClientInitialMetadata(
absl::Status (Derived::Call::* fn)(ClientMetadata& md), absl::Status (Derived::Call::*fn)(ClientMetadata& md),
typename Derived::Call* call, Derived*, PipeBasedCallSpine* call_spine) { typename Derived::Call* call, Derived*, PipeBasedCallSpine* call_spine) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientInitialMetadata); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientInitialMetadata);
call_spine->client_initial_metadata().receiver.InterceptAndMap( call_spine->client_initial_metadata().receiver.InterceptAndMap(
@ -695,7 +693,7 @@ inline void InterceptClientInitialMetadata(
template <typename Derived> template <typename Derived>
inline void InterceptClientInitialMetadata( inline void InterceptClientInitialMetadata(
absl::Status (Derived::Call::* fn)(ClientMetadata& md, Derived* channel), absl::Status (Derived::Call::*fn)(ClientMetadata& md, Derived* channel),
typename Derived::Call* call, Derived* channel, typename Derived::Call* call, Derived* channel,
PipeBasedCallSpine* call_spine) { PipeBasedCallSpine* call_spine) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientInitialMetadata); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnClientInitialMetadata);
@ -715,7 +713,7 @@ inline void InterceptClientInitialMetadata(
template <typename Promise, typename Derived> template <typename Promise, typename Derived>
absl::void_t<decltype(StatusCast<ServerMetadataHandle>( absl::void_t<decltype(StatusCast<ServerMetadataHandle>(
std::declval<PromiseResult<Promise>>))> std::declval<PromiseResult<Promise>>))>
InterceptClientInitialMetadata(Promise (Derived::Call::* promise_factory)( InterceptClientInitialMetadata(Promise (Derived::Call::*promise_factory)(
ClientMetadata& md, Derived* channel), ClientMetadata& md, Derived* channel),
typename Derived::Call* call, Derived* channel, typename Derived::Call* call, Derived* channel,
PipeBasedCallSpine* call_spine) { PipeBasedCallSpine* call_spine) {
@ -741,7 +739,7 @@ inline void InterceptServerInitialMetadata(const NoInterceptor*, void*,
template <typename Derived> template <typename Derived>
inline void InterceptServerInitialMetadata( inline void InterceptServerInitialMetadata(
void (Derived::Call::* fn)(ServerMetadata&), void (Derived::Call::*fn)(ServerMetadata&),
FilterCallData<Derived>* call_data, const CallArgs& call_args) { FilterCallData<Derived>* call_data, const CallArgs& call_args) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerInitialMetadata); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerInitialMetadata);
call_args.server_initial_metadata->InterceptAndMap( call_args.server_initial_metadata->InterceptAndMap(
@ -753,7 +751,7 @@ inline void InterceptServerInitialMetadata(
template <typename Derived> template <typename Derived>
inline void InterceptServerInitialMetadata( inline void InterceptServerInitialMetadata(
absl::Status (Derived::Call::* fn)(ServerMetadata&), absl::Status (Derived::Call::*fn)(ServerMetadata&),
FilterCallData<Derived>* call_data, const CallArgs& call_args) { FilterCallData<Derived>* call_data, const CallArgs& call_args) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerInitialMetadata); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerInitialMetadata);
call_args.server_initial_metadata->InterceptAndMap( call_args.server_initial_metadata->InterceptAndMap(
@ -770,7 +768,7 @@ inline void InterceptServerInitialMetadata(
template <typename Derived> template <typename Derived>
inline void InterceptServerInitialMetadata( inline void InterceptServerInitialMetadata(
void (Derived::Call::* fn)(ServerMetadata&, Derived*), void (Derived::Call::*fn)(ServerMetadata&, Derived*),
FilterCallData<Derived>* call_data, const CallArgs& call_args) { FilterCallData<Derived>* call_data, const CallArgs& call_args) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerInitialMetadata); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerInitialMetadata);
call_args.server_initial_metadata->InterceptAndMap( call_args.server_initial_metadata->InterceptAndMap(
@ -782,7 +780,7 @@ inline void InterceptServerInitialMetadata(
template <typename Derived> template <typename Derived>
inline void InterceptServerInitialMetadata( inline void InterceptServerInitialMetadata(
absl::Status (Derived::Call::* fn)(ServerMetadata&, Derived*), absl::Status (Derived::Call::*fn)(ServerMetadata&, Derived*),
FilterCallData<Derived>* call_data, const CallArgs& call_args) { FilterCallData<Derived>* call_data, const CallArgs& call_args) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerInitialMetadata); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerInitialMetadata);
call_args.server_initial_metadata->InterceptAndMap( call_args.server_initial_metadata->InterceptAndMap(
@ -803,7 +801,7 @@ inline void InterceptServerInitialMetadata(const NoInterceptor*, void*, void*,
template <typename Derived> template <typename Derived>
inline void InterceptServerInitialMetadata( inline void InterceptServerInitialMetadata(
void (Derived::Call::* fn)(ServerMetadata&), typename Derived::Call* call, void (Derived::Call::*fn)(ServerMetadata&), typename Derived::Call* call,
Derived*, PipeBasedCallSpine* call_spine) { Derived*, PipeBasedCallSpine* call_spine) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerInitialMetadata); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerInitialMetadata);
call_spine->server_initial_metadata().sender.InterceptAndMap( call_spine->server_initial_metadata().sender.InterceptAndMap(
@ -815,7 +813,7 @@ inline void InterceptServerInitialMetadata(
template <typename Derived> template <typename Derived>
inline void InterceptServerInitialMetadata( inline void InterceptServerInitialMetadata(
absl::Status (Derived::Call::* fn)(ServerMetadata&), absl::Status (Derived::Call::*fn)(ServerMetadata&),
typename Derived::Call* call, Derived*, PipeBasedCallSpine* call_spine) { typename Derived::Call* call, Derived*, PipeBasedCallSpine* call_spine) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerInitialMetadata); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerInitialMetadata);
call_spine->server_initial_metadata().sender.InterceptAndMap( call_spine->server_initial_metadata().sender.InterceptAndMap(
@ -831,7 +829,7 @@ inline void InterceptServerInitialMetadata(
template <typename Derived> template <typename Derived>
inline void InterceptServerInitialMetadata( inline void InterceptServerInitialMetadata(
void (Derived::Call::* fn)(ServerMetadata&, Derived*), void (Derived::Call::*fn)(ServerMetadata&, Derived*),
typename Derived::Call* call, Derived* channel, typename Derived::Call* call, Derived* channel,
PipeBasedCallSpine* call_spine) { PipeBasedCallSpine* call_spine) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerInitialMetadata); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerInitialMetadata);
@ -844,7 +842,7 @@ inline void InterceptServerInitialMetadata(
template <typename Derived> template <typename Derived>
inline void InterceptServerInitialMetadata( inline void InterceptServerInitialMetadata(
absl::Status (Derived::Call::* fn)(ServerMetadata&, Derived*), absl::Status (Derived::Call::*fn)(ServerMetadata&, Derived*),
typename Derived::Call* call, Derived* channel, typename Derived::Call* call, Derived* channel,
PipeBasedCallSpine* call_spine) { PipeBasedCallSpine* call_spine) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerInitialMetadata); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerInitialMetadata);
@ -864,7 +862,7 @@ inline void InterceptServerToClientMessage(const NoInterceptor*, void*,
template <typename Derived> template <typename Derived>
inline void InterceptServerToClientMessage( inline void InterceptServerToClientMessage(
ServerMetadataHandle (Derived::Call::* fn)(const Message&), ServerMetadataHandle (Derived::Call::*fn)(const Message&),
FilterCallData<Derived>* call_data, const CallArgs& call_args) { FilterCallData<Derived>* call_data, const CallArgs& call_args) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerToClientMessage); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerToClientMessage);
call_args.server_to_client_messages->InterceptAndMap( call_args.server_to_client_messages->InterceptAndMap(
@ -879,7 +877,7 @@ inline void InterceptServerToClientMessage(
template <typename Derived> template <typename Derived>
inline void InterceptServerToClientMessage( inline void InterceptServerToClientMessage(
ServerMetadataHandle (Derived::Call::* fn)(const Message&, Derived*), ServerMetadataHandle (Derived::Call::*fn)(const Message&, Derived*),
FilterCallData<Derived>* call_data, const CallArgs& call_args) { FilterCallData<Derived>* call_data, const CallArgs& call_args) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerToClientMessage); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerToClientMessage);
call_args.server_to_client_messages->InterceptAndMap( call_args.server_to_client_messages->InterceptAndMap(
@ -895,7 +893,7 @@ inline void InterceptServerToClientMessage(
template <typename Derived> template <typename Derived>
inline void InterceptServerToClientMessage( inline void InterceptServerToClientMessage(
MessageHandle (Derived::Call::* fn)(MessageHandle, Derived*), MessageHandle (Derived::Call::*fn)(MessageHandle, Derived*),
FilterCallData<Derived>* call_data, const CallArgs& call_args) { FilterCallData<Derived>* call_data, const CallArgs& call_args) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerToClientMessage); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerToClientMessage);
call_args.server_to_client_messages->InterceptAndMap( call_args.server_to_client_messages->InterceptAndMap(
@ -907,8 +905,7 @@ inline void InterceptServerToClientMessage(
template <typename Derived> template <typename Derived>
inline void InterceptServerToClientMessage( inline void InterceptServerToClientMessage(
absl::StatusOr<MessageHandle> (Derived::Call::* fn)(MessageHandle, absl::StatusOr<MessageHandle> (Derived::Call::*fn)(MessageHandle, Derived*),
Derived*),
FilterCallData<Derived>* call_data, const CallArgs& call_args) { FilterCallData<Derived>* call_data, const CallArgs& call_args) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerToClientMessage); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerToClientMessage);
call_args.server_to_client_messages->InterceptAndMap( call_args.server_to_client_messages->InterceptAndMap(
@ -927,7 +924,7 @@ inline void InterceptServerToClientMessage(const NoInterceptor*, void*, void*,
template <typename Derived> template <typename Derived>
inline void InterceptServerToClientMessage( inline void InterceptServerToClientMessage(
ServerMetadataHandle (Derived::Call::* fn)(const Message&), ServerMetadataHandle (Derived::Call::*fn)(const Message&),
typename Derived::Call* call, Derived*, PipeBasedCallSpine* call_spine) { typename Derived::Call* call, Derived*, PipeBasedCallSpine* call_spine) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerToClientMessage); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerToClientMessage);
call_spine->server_to_client_messages().sender.InterceptAndMap( call_spine->server_to_client_messages().sender.InterceptAndMap(
@ -941,7 +938,7 @@ inline void InterceptServerToClientMessage(
template <typename Derived> template <typename Derived>
inline void InterceptServerToClientMessage( inline void InterceptServerToClientMessage(
ServerMetadataHandle (Derived::Call::* fn)(const Message&, Derived*), ServerMetadataHandle (Derived::Call::*fn)(const Message&, Derived*),
typename Derived::Call* call, Derived* channel, typename Derived::Call* call, Derived* channel,
PipeBasedCallSpine* call_spine) { PipeBasedCallSpine* call_spine) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerToClientMessage); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerToClientMessage);
@ -957,7 +954,7 @@ inline void InterceptServerToClientMessage(
template <typename Derived> template <typename Derived>
inline void InterceptServerToClientMessage( inline void InterceptServerToClientMessage(
MessageHandle (Derived::Call::* fn)(MessageHandle, Derived*), MessageHandle (Derived::Call::*fn)(MessageHandle, Derived*),
typename Derived::Call* call, Derived* channel, typename Derived::Call* call, Derived* channel,
PipeBasedCallSpine* call_spine) { PipeBasedCallSpine* call_spine) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerToClientMessage); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerToClientMessage);
@ -969,8 +966,7 @@ inline void InterceptServerToClientMessage(
template <typename Derived> template <typename Derived>
inline void InterceptServerToClientMessage( inline void InterceptServerToClientMessage(
absl::StatusOr<MessageHandle> (Derived::Call::* fn)(MessageHandle, absl::StatusOr<MessageHandle> (Derived::Call::*fn)(MessageHandle, Derived*),
Derived*),
typename Derived::Call* call, Derived* channel, typename Derived::Call* call, Derived* channel,
PipeBasedCallSpine* call_spine) { PipeBasedCallSpine* call_spine) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerToClientMessage); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnServerToClientMessage);
@ -1014,7 +1010,7 @@ inline void InterceptServerTrailingMetadata(
inline void InterceptFinalize(const NoInterceptor*, void*, void*) {} inline void InterceptFinalize(const NoInterceptor*, void*, void*) {}
template <class Call> template <class Call>
inline void InterceptFinalize(void (Call::* fn)(const grpc_call_final_info*), inline void InterceptFinalize(void (Call::*fn)(const grpc_call_final_info*),
void*, Call* call) { void*, Call* call) {
GPR_DEBUG_ASSERT(fn == &Call::OnFinalize); GPR_DEBUG_ASSERT(fn == &Call::OnFinalize);
GetContext<CallFinalization>()->Add( GetContext<CallFinalization>()->Add(
@ -1025,7 +1021,7 @@ inline void InterceptFinalize(void (Call::* fn)(const grpc_call_final_info*),
template <class Derived> template <class Derived>
inline void InterceptFinalize( inline void InterceptFinalize(
void (Derived::Call::* fn)(const grpc_call_final_info*, Derived*), void (Derived::Call::*fn)(const grpc_call_final_info*, Derived*),
Derived* channel, typename Derived::Call* call) { Derived* channel, typename Derived::Call* call) {
GPR_DEBUG_ASSERT(fn == &Derived::Call::OnFinalize); GPR_DEBUG_ASSERT(fn == &Derived::Call::OnFinalize);
GetContext<CallFinalization>()->Add( GetContext<CallFinalization>()->Add(

@ -109,7 +109,7 @@ class Party::Handle final : public Wakeable {
} }
void WakeupGeneric(WakeupMask wakeup_mask, void WakeupGeneric(WakeupMask wakeup_mask,
void (Party::* wakeup_method)(WakeupMask)) void (Party::*wakeup_method)(WakeupMask))
ABSL_LOCKS_EXCLUDED(mu_) { ABSL_LOCKS_EXCLUDED(mu_) {
mu_.Lock(); mu_.Lock();
// Note that activity refcount can drop to zero, but we could win the lock // Note that activity refcount can drop to zero, but we could win the lock

@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#ifndef GRPC_SRC_CORE_LIB_TRANSPORT_CALL_SIZE_ESTIMATOR_H #ifndef GRPC_SRC_CORE_LIB_TRANSPORT_CALL_ARENA_ALLOCATOR_H
#define GRPC_SRC_CORE_LIB_TRANSPORT_CALL_SIZE_ESTIMATOR_H #define GRPC_SRC_CORE_LIB_TRANSPORT_CALL_ARENA_ALLOCATOR_H
#include <stddef.h> #include <stddef.h>
@ -70,4 +70,4 @@ class CallArenaAllocator : public RefCounted<CallArenaAllocator> {
} // namespace grpc_core } // namespace grpc_core
#endif // GRPC_SRC_CORE_LIB_TRANSPORT_CALL_SIZE_ESTIMATOR_H #endif // GRPC_SRC_CORE_LIB_TRANSPORT_CALL_ARENA_ALLOCATOR_H

@ -274,7 +274,7 @@ struct AddOpImpl<FilterType, T, const NoInterceptor*, which> {
// void $INTERCEPTOR_NAME($VALUE_TYPE&) // void $INTERCEPTOR_NAME($VALUE_TYPE&)
template <typename FilterType, typename T, template <typename FilterType, typename T,
void (FilterType::Call::* impl)(typename T::element_type&)> void (FilterType::Call::*impl)(typename T::element_type&)>
struct AddOpImpl<FilterType, T, struct AddOpImpl<FilterType, T,
void (FilterType::Call::*)(typename T::element_type&), impl> { void (FilterType::Call::*)(typename T::element_type&), impl> {
static void Add(FilterType* channel_data, size_t call_offset, static void Add(FilterType* channel_data, size_t call_offset,
@ -311,8 +311,8 @@ struct AddOpImpl<FilterType, T,
// void $INTERCEPTOR_NAME($VALUE_TYPE&, FilterType*) // void $INTERCEPTOR_NAME($VALUE_TYPE&, FilterType*)
template <typename FilterType, typename T, template <typename FilterType, typename T,
void (FilterType::Call::* impl)(typename T::element_type&, void (FilterType::Call::*impl)(typename T::element_type&,
FilterType*)> FilterType*)>
struct AddOpImpl< struct AddOpImpl<
FilterType, T, FilterType, T,
void (FilterType::Call::*)(typename T::element_type&, FilterType*), impl> { void (FilterType::Call::*)(typename T::element_type&, FilterType*), impl> {
@ -352,7 +352,7 @@ struct AddOpImpl<
// $VALUE_HANDLE $INTERCEPTOR_NAME($VALUE_HANDLE, FilterType*) // $VALUE_HANDLE $INTERCEPTOR_NAME($VALUE_HANDLE, FilterType*)
template <typename FilterType, typename T, template <typename FilterType, typename T,
T (FilterType::Call::* impl)(T, FilterType*)> T (FilterType::Call::*impl)(T, FilterType*)>
struct AddOpImpl<FilterType, T, T (FilterType::Call::*)(T, FilterType*), impl> { struct AddOpImpl<FilterType, T, T (FilterType::Call::*)(T, FilterType*), impl> {
static void Add(FilterType* channel_data, size_t call_offset, static void Add(FilterType* channel_data, size_t call_offset,
Layout<FallibleOperator<T>>& to) { Layout<FallibleOperator<T>>& to) {
@ -394,7 +394,7 @@ struct AddOpImpl<FilterType, T, T (FilterType::Call::*)(T, FilterType*), impl> {
// absl::Status $INTERCEPTOR_NAME($VALUE_TYPE&) // absl::Status $INTERCEPTOR_NAME($VALUE_TYPE&)
template <typename FilterType, typename T, template <typename FilterType, typename T,
absl::Status (FilterType::Call::* impl)(typename T::element_type&)> absl::Status (FilterType::Call::*impl)(typename T::element_type&)>
struct AddOpImpl<FilterType, T, struct AddOpImpl<FilterType, T,
absl::Status (FilterType::Call::*)(typename T::element_type&), absl::Status (FilterType::Call::*)(typename T::element_type&),
impl> { impl> {
@ -439,7 +439,7 @@ struct AddOpImpl<FilterType, T,
// absl::Status $INTERCEPTOR_NAME(const $VALUE_TYPE&) // absl::Status $INTERCEPTOR_NAME(const $VALUE_TYPE&)
template <typename FilterType, typename T, template <typename FilterType, typename T,
absl::Status (FilterType::Call::* impl)( absl::Status (FilterType::Call::*impl)(
const typename T::element_type&)> const typename T::element_type&)>
struct AddOpImpl< struct AddOpImpl<
FilterType, T, FilterType, T,
@ -467,8 +467,8 @@ struct AddOpImpl<
// absl::Status $INTERCEPTOR_NAME($VALUE_TYPE&, FilterType*) // absl::Status $INTERCEPTOR_NAME($VALUE_TYPE&, FilterType*)
template <typename FilterType, typename T, template <typename FilterType, typename T,
absl::Status (FilterType::Call::* impl)(typename T::element_type&, absl::Status (FilterType::Call::*impl)(typename T::element_type&,
FilterType*)> FilterType*)>
struct AddOpImpl<FilterType, T, struct AddOpImpl<FilterType, T,
absl::Status (FilterType::Call::*)(typename T::element_type&, absl::Status (FilterType::Call::*)(typename T::element_type&,
FilterType*), FilterType*),
@ -497,7 +497,7 @@ struct AddOpImpl<FilterType, T,
// absl::Status $INTERCEPTOR_NAME(const $VALUE_TYPE&, FilterType*) // absl::Status $INTERCEPTOR_NAME(const $VALUE_TYPE&, FilterType*)
template <typename FilterType, typename T, template <typename FilterType, typename T,
absl::Status (FilterType::Call::* impl)( absl::Status (FilterType::Call::*impl)(
const typename T::element_type&, FilterType*)> const typename T::element_type&, FilterType*)>
struct AddOpImpl<FilterType, T, struct AddOpImpl<FilterType, T,
absl::Status (FilterType::Call::*)( absl::Status (FilterType::Call::*)(
@ -527,7 +527,7 @@ struct AddOpImpl<FilterType, T,
// absl::StatusOr<$VALUE_HANDLE> $INTERCEPTOR_NAME($VALUE_HANDLE, FilterType*) // absl::StatusOr<$VALUE_HANDLE> $INTERCEPTOR_NAME($VALUE_HANDLE, FilterType*)
template <typename FilterType, typename T, template <typename FilterType, typename T,
absl::StatusOr<T> (FilterType::Call::* impl)(T, FilterType*)> absl::StatusOr<T> (FilterType::Call::*impl)(T, FilterType*)>
struct AddOpImpl<FilterType, T, struct AddOpImpl<FilterType, T,
absl::StatusOr<T> (FilterType::Call::*)(T, FilterType*), absl::StatusOr<T> (FilterType::Call::*)(T, FilterType*),
impl> { impl> {
@ -555,7 +555,7 @@ struct AddOpImpl<FilterType, T,
// ServerMetadataHandle $INTERCEPTOR_NAME($VALUE_TYPE&) // ServerMetadataHandle $INTERCEPTOR_NAME($VALUE_TYPE&)
template <typename FilterType, typename T, template <typename FilterType, typename T,
ServerMetadataHandle (FilterType::Call::* impl)( ServerMetadataHandle (FilterType::Call::*impl)(
typename T::element_type&)> typename T::element_type&)>
struct AddOpImpl<FilterType, T, struct AddOpImpl<FilterType, T,
ServerMetadataHandle (FilterType::Call::*)( ServerMetadataHandle (FilterType::Call::*)(
@ -584,7 +584,7 @@ struct AddOpImpl<FilterType, T,
// ServerMetadataHandle $INTERCEPTOR_NAME(const $VALUE_TYPE&) // ServerMetadataHandle $INTERCEPTOR_NAME(const $VALUE_TYPE&)
template <typename FilterType, typename T, template <typename FilterType, typename T,
ServerMetadataHandle (FilterType::Call::* impl)( ServerMetadataHandle (FilterType::Call::*impl)(
const typename T::element_type&)> const typename T::element_type&)>
struct AddOpImpl<FilterType, T, struct AddOpImpl<FilterType, T,
ServerMetadataHandle (FilterType::Call::*)( ServerMetadataHandle (FilterType::Call::*)(
@ -613,7 +613,7 @@ struct AddOpImpl<FilterType, T,
// ServerMetadataHandle $INTERCEPTOR_NAME($VALUE_TYPE&, FilterType*) // ServerMetadataHandle $INTERCEPTOR_NAME($VALUE_TYPE&, FilterType*)
template <typename FilterType, typename T, template <typename FilterType, typename T,
ServerMetadataHandle (FilterType::Call::* impl)( ServerMetadataHandle (FilterType::Call::*impl)(
typename T::element_type&, FilterType*)> typename T::element_type&, FilterType*)>
struct AddOpImpl<FilterType, T, struct AddOpImpl<FilterType, T,
ServerMetadataHandle (FilterType::Call::*)( ServerMetadataHandle (FilterType::Call::*)(
@ -643,7 +643,7 @@ struct AddOpImpl<FilterType, T,
// ServerMetadataHandle $INTERCEPTOR_NAME(const $VALUE_TYPE&, FilterType*) // ServerMetadataHandle $INTERCEPTOR_NAME(const $VALUE_TYPE&, FilterType*)
template <typename FilterType, typename T, template <typename FilterType, typename T,
ServerMetadataHandle (FilterType::Call::* impl)( ServerMetadataHandle (FilterType::Call::*impl)(
const typename T::element_type&, FilterType*)> const typename T::element_type&, FilterType*)>
struct AddOpImpl<FilterType, T, struct AddOpImpl<FilterType, T,
ServerMetadataHandle (FilterType::Call::*)( ServerMetadataHandle (FilterType::Call::*)(
@ -673,7 +673,7 @@ struct AddOpImpl<FilterType, T,
// PROMISE_RETURNING(absl::Status) $INTERCEPTOR_NAME($VALUE_TYPE&) // PROMISE_RETURNING(absl::Status) $INTERCEPTOR_NAME($VALUE_TYPE&)
template <typename FilterType, typename T, typename R, template <typename FilterType, typename T, typename R,
R (FilterType::Call::* impl)(typename T::element_type&)> R (FilterType::Call::*impl)(typename T::element_type&)>
struct AddOpImpl< struct AddOpImpl<
FilterType, T, R (FilterType::Call::*)(typename T::element_type&), impl, FilterType, T, R (FilterType::Call::*)(typename T::element_type&), impl,
absl::enable_if_t<std::is_same<absl::Status, PromiseResult<R>>::value>> { absl::enable_if_t<std::is_same<absl::Status, PromiseResult<R>>::value>> {
@ -724,7 +724,7 @@ struct AddOpImpl<
// PROMISE_RETURNING(absl::Status) $INTERCEPTOR_NAME($VALUE_TYPE&, FilterType*) // PROMISE_RETURNING(absl::Status) $INTERCEPTOR_NAME($VALUE_TYPE&, FilterType*)
template <typename FilterType, typename T, typename R, template <typename FilterType, typename T, typename R,
R (FilterType::Call::* impl)(typename T::element_type&, FilterType*)> R (FilterType::Call::*impl)(typename T::element_type&, FilterType*)>
struct AddOpImpl< struct AddOpImpl<
FilterType, T, FilterType, T,
R (FilterType::Call::*)(typename T::element_type&, FilterType*), impl, R (FilterType::Call::*)(typename T::element_type&, FilterType*), impl,
@ -780,7 +780,7 @@ struct AddOpImpl<
// PROMISE_RETURNING(absl::StatusOr<$VALUE_HANDLE>) // PROMISE_RETURNING(absl::StatusOr<$VALUE_HANDLE>)
// $INTERCEPTOR_NAME($VALUE_HANDLE, FilterType*) // $INTERCEPTOR_NAME($VALUE_HANDLE, FilterType*)
template <typename FilterType, typename T, typename R, template <typename FilterType, typename T, typename R,
R (FilterType::Call::* impl)(T, FilterType*)> R (FilterType::Call::*impl)(T, FilterType*)>
struct AddOpImpl<FilterType, T, R (FilterType::Call::*)(T, FilterType*), impl, struct AddOpImpl<FilterType, T, R (FilterType::Call::*)(T, FilterType*), impl,
absl::enable_if_t<std::is_same<absl::StatusOr<T>, absl::enable_if_t<std::is_same<absl::StatusOr<T>,
PromiseResult<R>>::value>> { PromiseResult<R>>::value>> {
@ -995,7 +995,7 @@ struct StackData {
template <typename FilterType> template <typename FilterType>
void AddFinalizer(FilterType* channel_data, size_t call_offset, void AddFinalizer(FilterType* channel_data, size_t call_offset,
void (FilterType::Call::* p)(const grpc_call_final_info*)) { void (FilterType::Call::*p)(const grpc_call_final_info*)) {
GPR_DEBUG_ASSERT(p == &FilterType::Call::OnFinalize); GPR_DEBUG_ASSERT(p == &FilterType::Call::OnFinalize);
finalizers.push_back(Finalizer{ finalizers.push_back(Finalizer{
channel_data, channel_data,
@ -1009,8 +1009,8 @@ struct StackData {
template <typename FilterType> template <typename FilterType>
void AddFinalizer(FilterType* channel_data, size_t call_offset, void AddFinalizer(FilterType* channel_data, size_t call_offset,
void (FilterType::Call::* p)(const grpc_call_final_info*, void (FilterType::Call::*p)(const grpc_call_final_info*,
FilterType*)) { FilterType*)) {
GPR_DEBUG_ASSERT(p == &FilterType::Call::OnFinalize); GPR_DEBUG_ASSERT(p == &FilterType::Call::OnFinalize);
finalizers.push_back(Finalizer{ finalizers.push_back(Finalizer{
channel_data, channel_data,
@ -1378,10 +1378,10 @@ class CallFilters {
std::string DebugString() const; std::string DebugString() const;
private: private:
template <filters_detail::PipeState(CallFilters::* state_ptr), template <filters_detail::PipeState(CallFilters::*state_ptr),
void*(CallFilters::* push_ptr), typename T, void*(CallFilters::*push_ptr), typename T,
filters_detail::Layout<filters_detail::FallibleOperator<T>>( filters_detail::Layout<filters_detail::FallibleOperator<T>>(
filters_detail::StackData::* layout_ptr)> filters_detail::StackData::*layout_ptr)>
class PipePromise { class PipePromise {
public: public:
class Push { class Push {

@ -16,11 +16,10 @@
#include <cstddef> #include <cstddef>
#include "call_destination.h"
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include "src/core/lib/gprpp/match.h" #include "src/core/lib/gprpp/match.h"
#include "src/core/lib/transport/call_destination.h"
#include "src/core/lib/transport/call_filters.h" #include "src/core/lib/transport/call_filters.h"
#include "src/core/lib/transport/call_spine.h" #include "src/core/lib/transport/call_spine.h"
#include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata.h"
@ -40,9 +39,9 @@ CallInitiator HijackedCall::MakeCall() {
CallInitiator HijackedCall::MakeCallWithMetadata( CallInitiator HijackedCall::MakeCallWithMetadata(
ClientMetadataHandle metadata) { ClientMetadataHandle metadata) {
auto call = grpc_core::MakeCallPair( auto call = MakeCallPair(std::move(metadata), call_handler_.event_engine(),
std::move(metadata), call_handler_.event_engine(), call_handler_.arena(), call_handler_.arena(), nullptr,
nullptr, call_handler_.legacy_context()); call_handler_.legacy_context());
destination_->StartCall(std::move(call.handler)); destination_->StartCall(std::move(call.handler));
return std::move(call.initiator); return std::move(call.initiator);
} }

@ -23,9 +23,9 @@ grpc_cc_library(
name = "poll_matcher", name = "poll_matcher",
testonly = True, testonly = True,
hdrs = ["poll_matcher.h"], hdrs = ["poll_matcher.h"],
external_deps = ["gtest"],
visibility = ["//test/core:__subpackages__"], visibility = ["//test/core:__subpackages__"],
deps = ["//src/core:poll"], deps = ["//src/core:poll"],
external_deps = ["gtest"],
) )
grpc_cc_library( grpc_cc_library(
@ -505,11 +505,11 @@ grpc_cc_test(
uses_event_engine = False, uses_event_engine = False,
uses_polling = False, uses_polling = False,
deps = [ deps = [
"poll_matcher",
"//src/core:loop", "//src/core:loop",
"//src/core:map", "//src/core:map",
"//src/core:notification", "//src/core:notification",
"//src/core:observable", "//src/core:observable",
"poll_matcher"
], ],
) )

@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#ifndef POLL_MATCHER_H #ifndef GRPC_TEST_CORE_PROMISE_POLL_MATCHER_H
#define POLL_MATCHER_H #define GRPC_TEST_CORE_PROMISE_POLL_MATCHER_H
#include "gmock/gmock.h" #include "gmock/gmock.h"
@ -57,4 +57,4 @@ MATCHER_P(IsReady, value, "") {
} // namespace grpc_core } // namespace grpc_core
#endif #endif // GRPC_TEST_CORE_PROMISE_POLL_MATCHER_H

@ -45,10 +45,10 @@ grpc_cc_test(
uses_event_engine = False, uses_event_engine = False,
uses_polling = False, uses_polling = False,
deps = [ deps = [
"//:grpc_base",
"//src/core:interception_chain", "//src/core:interception_chain",
"//src/core:resource_quota", "//src/core:resource_quota",
"//test/core/promise:poll_matcher", "//test/core/promise:poll_matcher",
"//:grpc_base",
], ],
) )

@ -142,9 +142,8 @@ class ClientTransportTest : public ::testing::Test {
auto MakeCall(ClientMetadataHandle client_initial_metadata) { auto MakeCall(ClientMetadataHandle client_initial_metadata) {
auto* arena = call_arena_allocator_->MakeArena(); auto* arena = call_arena_allocator_->MakeArena();
return grpc_core::MakeCallPair(std::move(client_initial_metadata), return MakeCallPair(std::move(client_initial_metadata), event_engine_.get(),
event_engine_.get(), arena, arena, call_arena_allocator_, nullptr);
call_arena_allocator_, nullptr);
} }
private: private:

@ -44,9 +44,8 @@ class TransportTest : public ::testing::Test {
auto MakeCall(ClientMetadataHandle client_initial_metadata) { auto MakeCall(ClientMetadataHandle client_initial_metadata) {
auto* arena = call_arena_allocator_->MakeArena(); auto* arena = call_arena_allocator_->MakeArena();
return grpc_core::MakeCallPair(std::move(client_initial_metadata), return MakeCallPair(std::move(client_initial_metadata), event_engine_.get(),
event_engine_.get(), arena, arena, call_arena_allocator_, nullptr);
call_arena_allocator_, nullptr);
} }
private: private:

@ -240,9 +240,8 @@ class TransportTest : public ::testing::Test {
auto MakeCall(ClientMetadataHandle client_initial_metadata) { auto MakeCall(ClientMetadataHandle client_initial_metadata) {
auto* arena = call_arena_allocator_->MakeArena(); auto* arena = call_arena_allocator_->MakeArena();
return grpc_core::MakeCallPair(std::move(client_initial_metadata), return MakeCallPair(std::move(client_initial_metadata), event_engine_.get(),
event_engine_.get(), arena, arena, call_arena_allocator_, nullptr);
call_arena_allocator_, nullptr);
} }
// Alternative for Seq for test driver code. // Alternative for Seq for test driver code.

Loading…
Cancel
Save