xref: /aosp_15_r20/external/grpc-grpc/test/core/transport/call_filters_test.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1 // Copyright 2024 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/core/lib/transport/call_filters.h"
16 
17 #include <vector>
18 
19 #include "gmock/gmock.h"
20 #include "gtest/gtest.h"
21 
22 using testing::Mock;
23 using testing::StrictMock;
24 
25 namespace grpc_core {
26 
27 namespace {
28 // Offset a void pointer by a given amount
Offset(void * base,size_t amt)29 void* Offset(void* base, size_t amt) { return static_cast<char*>(base) + amt; }
30 
31 // A mock activity that can be activated and deactivated.
32 class MockActivity : public Activity, public Wakeable {
33  public:
34   MOCK_METHOD(void, WakeupRequested, ());
35 
ForceImmediateRepoll(WakeupMask)36   void ForceImmediateRepoll(WakeupMask /*mask*/) override { WakeupRequested(); }
Orphan()37   void Orphan() override {}
MakeOwningWaker()38   Waker MakeOwningWaker() override { return Waker(this, 0); }
MakeNonOwningWaker()39   Waker MakeNonOwningWaker() override { return Waker(this, 0); }
Wakeup(WakeupMask)40   void Wakeup(WakeupMask /*mask*/) override { WakeupRequested(); }
WakeupAsync(WakeupMask)41   void WakeupAsync(WakeupMask /*mask*/) override { WakeupRequested(); }
Drop(WakeupMask)42   void Drop(WakeupMask /*mask*/) override {}
DebugTag() const43   std::string DebugTag() const override { return "MockActivity"; }
ActivityDebugTag(WakeupMask) const44   std::string ActivityDebugTag(WakeupMask /*mask*/) const override {
45     return DebugTag();
46   }
47 
Activate()48   void Activate() {
49     if (scoped_activity_ == nullptr) {
50       scoped_activity_ = std::make_unique<ScopedActivity>(this);
51     }
52   }
53 
Deactivate()54   void Deactivate() { scoped_activity_.reset(); }
55 
56  private:
57   std::unique_ptr<ScopedActivity> scoped_activity_;
58 };
59 
60 MATCHER(IsPending, "") {
61   if (arg.ready()) {
62     *result_listener << "is ready";
63     return false;
64   }
65   return true;
66 }
67 
68 MATCHER(IsReady, "") {
69   if (arg.pending()) {
70     *result_listener << "is pending";
71     return false;
72   }
73   return true;
74 }
75 
76 MATCHER_P(IsReady, value, "") {
77   if (arg.pending()) {
78     *result_listener << "is pending";
79     return false;
80   }
81   if (arg.value() != value) {
82     *result_listener << "is " << ::testing::PrintToString(arg.value());
83     return false;
84   }
85   return true;
86 }
87 
88 }  // namespace
89 
90 ////////////////////////////////////////////////////////////////////////////////
91 // Layout
92 
93 namespace filters_detail {
94 
TEST(LayoutTest,Empty)95 TEST(LayoutTest, Empty) {
96   Layout<FallibleOperator<ClientMetadataHandle>> l;
97   ASSERT_EQ(l.ops.size(), 0u);
98   EXPECT_EQ(l.promise_size, 0u);
99   EXPECT_EQ(l.promise_alignment, 0u);
100 }
101 
TEST(LayoutTest,Add)102 TEST(LayoutTest, Add) {
103   Layout<FallibleOperator<ClientMetadataHandle>> l;
104   l.Add(1, 4,
105         FallibleOperator<ClientMetadataHandle>{&l, 120, nullptr, nullptr,
106                                                nullptr});
107   ASSERT_EQ(l.ops.size(), 1u);
108   EXPECT_EQ(l.promise_size, 1u);
109   EXPECT_EQ(l.promise_alignment, 4u);
110   EXPECT_EQ(l.ops[0].call_offset, 120);
111 }
112 
113 }  // namespace filters_detail
114 
115 ////////////////////////////////////////////////////////////////////////////////
116 // StackData
117 
118 namespace filters_detail {
119 
TEST(StackDataTest,Empty)120 TEST(StackDataTest, Empty) {
121   StackData d;
122   EXPECT_EQ(d.call_data_alignment, 1u);
123   EXPECT_EQ(d.call_data_size, 0u);
124 }
125 
TEST(StackDataTest,OneByteAlignmentAndSize)126 TEST(StackDataTest, OneByteAlignmentAndSize) {
127   struct Filter1 {
128     struct Call {
129       char c;
130     };
131   };
132   static_assert(alignof(typename Filter1::Call) == 1,
133                 "Expect 1 byte alignment");
134   static_assert(sizeof(typename Filter1::Call) == 1, "Expect 1 byte size");
135   StackData d;
136   Filter1 f1;
137   d.AddFilter(&f1);
138   EXPECT_EQ(d.call_data_alignment, 1);
139   EXPECT_EQ(d.call_data_size, 1);
140   ASSERT_EQ(d.filter_constructor.size(), 1u);
141   ASSERT_EQ(d.filter_destructor.size(), 0u);
142   // Check channel data
143   EXPECT_EQ(d.filter_constructor[0].channel_data, &f1);
144   // Check call offsets
145   EXPECT_EQ(d.filter_constructor[0].call_offset, 0);
146 }
147 
TEST(StackDataTest,PointerAlignmentAndSize)148 TEST(StackDataTest, PointerAlignmentAndSize) {
149   struct Filter1 {
150     struct Call {
151       void* p;
152     };
153   };
154   static_assert(alignof(typename Filter1::Call) == alignof(void*),
155                 "Expect pointer alignment");
156   static_assert(sizeof(typename Filter1::Call) == sizeof(void*),
157                 "Expect pointer size");
158   StackData d;
159   Filter1 f1;
160   d.AddFilter(&f1);
161   EXPECT_EQ(d.call_data_alignment, alignof(void*));
162   EXPECT_EQ(d.call_data_size, sizeof(void*));
163   ASSERT_EQ(d.filter_constructor.size(), 1u);
164   ASSERT_EQ(d.filter_destructor.size(), 0u);
165   // Check channel data
166   EXPECT_EQ(d.filter_constructor[0].channel_data, &f1);
167   // Check call offsets
168   EXPECT_EQ(d.filter_constructor[0].call_offset, 0);
169 }
170 
TEST(StackDataTest,PointerAndOneByteAlignmentAndSize)171 TEST(StackDataTest, PointerAndOneByteAlignmentAndSize) {
172   struct Filter1 {
173     struct Call {
174       char c;
175     };
176   };
177   static_assert(alignof(typename Filter1::Call) == 1,
178                 "Expect 1 byte alignment");
179   static_assert(sizeof(typename Filter1::Call) == 1, "Expect 1 byte size");
180   struct Filter2 {
181     struct Call {
182       void* p;
183     };
184   };
185   static_assert(alignof(typename Filter2::Call) == alignof(void*),
186                 "Expect pointer alignment");
187   static_assert(sizeof(typename Filter2::Call) == sizeof(void*),
188                 "Expect pointer size");
189   StackData d;
190   Filter1 f1;
191   Filter2 f2;
192   d.AddFilter(&f1);
193   d.AddFilter(&f2);
194   EXPECT_EQ(d.call_data_alignment, alignof(void*));
195   // Padding added after 1-byte element to align pointer.
196   EXPECT_EQ(d.call_data_size, 2 * sizeof(void*));
197   ASSERT_EQ(d.filter_constructor.size(), 2u);
198   ASSERT_EQ(d.filter_destructor.size(), 0u);
199   // Check channel data
200   EXPECT_EQ(d.filter_constructor[0].channel_data, &f1);
201   EXPECT_EQ(d.filter_constructor[1].channel_data, &f2);
202   // Check call offsets
203   EXPECT_EQ(d.filter_constructor[0].call_offset, 0);
204   EXPECT_EQ(d.filter_constructor[1].call_offset, sizeof(void*));
205 }
206 
TEST(StackDataTest,PointerAndOneByteAlignmentAndSizeBackwards)207 TEST(StackDataTest, PointerAndOneByteAlignmentAndSizeBackwards) {
208   struct Filter1 {
209     struct Call {
210       char c;
211     };
212   };
213   static_assert(alignof(typename Filter1::Call) == 1,
214                 "Expect 1 byte alignment");
215   static_assert(sizeof(typename Filter1::Call) == 1, "Expect 1 byte size");
216   struct Filter2 {
217     struct Call {
218       void* p;
219     };
220   };
221   static_assert(alignof(typename Filter2::Call) == alignof(void*),
222                 "Expect pointer alignment");
223   static_assert(sizeof(typename Filter2::Call) == sizeof(void*),
224                 "Expect pointer size");
225   StackData d;
226   Filter1 f1;
227   Filter2 f2;
228   d.AddFilter(&f2);
229   d.AddFilter(&f1);
230   EXPECT_EQ(d.call_data_alignment, alignof(void*));
231   // No padding needed, so just the sum of sizes.
232   EXPECT_EQ(d.call_data_size, sizeof(void*) + 1);
233   ASSERT_EQ(d.filter_constructor.size(), 2u);
234   ASSERT_EQ(d.filter_destructor.size(), 0u);
235   // Check channel data
236   EXPECT_EQ(d.filter_constructor[0].channel_data, &f2);
237   EXPECT_EQ(d.filter_constructor[1].channel_data, &f1);
238   // Check call offsets
239   EXPECT_EQ(d.filter_constructor[0].call_offset, 0);
240   EXPECT_EQ(d.filter_constructor[1].call_offset, sizeof(void*));
241 }
242 
TEST(StackDataTest,EmptyFilter)243 TEST(StackDataTest, EmptyFilter) {
244   struct Filter1 {
245     struct Call {};
246   };
247   static_assert(std::is_empty<typename Filter1::Call>::value,
248                 "Expect empty filter");
249   StackData d;
250   Filter1 f1;
251   d.AddFilter(&f1);
252   EXPECT_EQ(d.call_data_size, 0);
253 }
254 
TEST(StackDataTest,OneFilterThenManyEmptyThenOneNonEmpty)255 TEST(StackDataTest, OneFilterThenManyEmptyThenOneNonEmpty) {
256   struct Filter1 {
257     struct Call {
258       char c;
259     };
260   };
261   struct Filter2 {
262     struct Call {};
263   };
264   StackData d;
265   // Declare filters
266   Filter1 f1a;
267   Filter2 f2a;
268   Filter2 f2b;
269   Filter2 f2c;
270   Filter2 f2d;
271   Filter1 f1b;
272   // Add filters
273   d.AddFilter(&f1a);
274   d.AddFilter(&f2a);
275   d.AddFilter(&f2b);
276   d.AddFilter(&f2c);
277   d.AddFilter(&f2d);
278   d.AddFilter(&f1b);
279   // Check overall size
280   EXPECT_EQ(d.call_data_size, 2);
281   ASSERT_EQ(d.filter_constructor.size(), 2u);
282   ASSERT_EQ(d.filter_destructor.size(), 0u);
283   // Check channel data
284   EXPECT_EQ(d.filter_constructor[0].channel_data, &f1a);
285   EXPECT_EQ(d.filter_constructor[1].channel_data, &f1b);
286   // Check call offsets
287   EXPECT_EQ(d.filter_constructor[0].call_offset, 0);
288   EXPECT_EQ(d.filter_constructor[1].call_offset, 1);
289 }
290 
TEST(StackDataTest,FilterInit)291 TEST(StackDataTest, FilterInit) {
292   struct Filter1 {
293     struct Call {
294       std::unique_ptr<int> p{new int(42)};
295     };
296   };
297   StackData d;
298   Filter1 f1;
299   d.AddFilter(&f1);
300   ASSERT_EQ(d.filter_constructor.size(), 1u);
301   ASSERT_EQ(d.filter_destructor.size(), 1u);
302   EXPECT_EQ(d.filter_constructor[0].channel_data, &f1);
303   EXPECT_EQ(d.filter_constructor[0].call_offset, 0);
304   EXPECT_EQ(d.filter_destructor[0].call_offset, 0);
305   void* p = gpr_malloc_aligned(d.call_data_size, d.call_data_alignment);
306   d.filter_constructor[0].call_init(p, &f1);
307   EXPECT_EQ(*static_cast<Filter1::Call*>(p)->p, 42);
308   d.filter_destructor[0].call_destroy(p);
309   gpr_free_aligned(p);
310 }
311 
TEST(StackDataTest,FilterInitWithArg)312 TEST(StackDataTest, FilterInitWithArg) {
313   struct Filter1 {
314     struct Call {
315       explicit Call(Filter1* f) : p(new Filter1*(f)) {}
316       std::unique_ptr<Filter1*> p;
317     };
318   };
319   StackData d;
320   Filter1 f1;
321   d.AddFilter(&f1);
322   ASSERT_EQ(d.filter_constructor.size(), 1u);
323   ASSERT_EQ(d.filter_destructor.size(), 1u);
324   EXPECT_EQ(d.filter_constructor[0].channel_data, &f1);
325   EXPECT_EQ(d.filter_constructor[0].call_offset, 0);
326   EXPECT_EQ(d.filter_destructor[0].call_offset, 0);
327   void* p = gpr_malloc_aligned(d.call_data_size, d.call_data_alignment);
328   d.filter_constructor[0].call_init(p, &f1);
329   EXPECT_EQ(*static_cast<Filter1::Call*>(p)->p, &f1);
330   d.filter_destructor[0].call_destroy(p);
331   gpr_free_aligned(p);
332 }
333 
TEST(StackDataTest,InstantClientInitialMetadataReturningVoid)334 TEST(StackDataTest, InstantClientInitialMetadataReturningVoid) {
335   struct Filter1 {
336     struct Call {
337       void OnClientInitialMetadata(ClientMetadata& md) {
338         md.Set(HttpPathMetadata(), Slice::FromStaticString("hello"));
339       }
340     };
341   };
342   StackData d;
343   Filter1 f1;
344   const size_t call_offset = d.AddFilter(&f1);
345   EXPECT_EQ(call_offset, 0);
346   EXPECT_EQ(d.call_data_size, 0);
347   d.AddClientInitialMetadataOp(&f1, call_offset);
348   ASSERT_EQ(d.filter_constructor.size(), 0u);
349   ASSERT_EQ(d.filter_destructor.size(), 0u);
350   ASSERT_EQ(d.client_initial_metadata.ops.size(), 1u);
351   EXPECT_EQ(d.client_initial_metadata.ops[0].call_offset, call_offset);
352   EXPECT_EQ(d.client_initial_metadata.ops[0].channel_data, &f1);
353   // Instant => no poll/early destroy
354   EXPECT_EQ(d.client_initial_metadata.ops[0].poll, nullptr);
355   EXPECT_EQ(d.client_initial_metadata.ops[0].early_destroy, nullptr);
356   // Check promise init
357   auto md = Arena::MakePooled<ClientMetadata>();
358   EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
359   char call_data;
360   auto r = d.client_initial_metadata.ops[0].promise_init(
361       nullptr, &call_data, d.client_initial_metadata.ops[0].channel_data,
362       std::move(md));
363   EXPECT_TRUE(r.ready());
364   EXPECT_EQ(r.value().ok->get_pointer(HttpPathMetadata())->as_string_view(),
365             "hello");
366 }
367 
TEST(StackDataTest,InstantClientInitialMetadataReturningVoidTakingChannelPtr)368 TEST(StackDataTest, InstantClientInitialMetadataReturningVoidTakingChannelPtr) {
369   struct Filter1 {
370     struct Call {
371       void OnClientInitialMetadata(ClientMetadata& md, Filter1* p) {
372         p->v.push_back(42);
373         md.Set(HttpPathMetadata(), Slice::FromStaticString("hello"));
374       }
375     };
376     std::vector<int> v;
377   };
378   StackData d;
379   Filter1 f1;
380   const size_t call_offset = d.AddFilter(&f1);
381   EXPECT_EQ(call_offset, 0);
382   EXPECT_EQ(d.call_data_size, 0);
383   d.AddClientInitialMetadataOp(&f1, call_offset);
384   ASSERT_EQ(d.filter_constructor.size(), 0u);
385   ASSERT_EQ(d.client_initial_metadata.ops.size(), 1u);
386   EXPECT_EQ(d.client_initial_metadata.ops[0].call_offset, call_offset);
387   EXPECT_EQ(d.client_initial_metadata.ops[0].channel_data, &f1);
388   // Instant => no poll/early destroy
389   EXPECT_EQ(d.client_initial_metadata.ops[0].poll, nullptr);
390   EXPECT_EQ(d.client_initial_metadata.ops[0].early_destroy, nullptr);
391   // Check promise init
392   auto md = Arena::MakePooled<ClientMetadata>();
393   EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
394   char call_data;
395   auto r = d.client_initial_metadata.ops[0].promise_init(
396       nullptr, &call_data, d.client_initial_metadata.ops[0].channel_data,
397       std::move(md));
398   EXPECT_TRUE(r.ready());
399   EXPECT_EQ(r.value().ok->get_pointer(HttpPathMetadata())->as_string_view(),
400             "hello");
401   EXPECT_THAT(f1.v, ::testing::ElementsAre(42));
402 }
403 
TEST(StackDataTest,InstantClientInitialMetadataReturningAbslStatus)404 TEST(StackDataTest, InstantClientInitialMetadataReturningAbslStatus) {
405   struct Filter1 {
406     class Call {
407      public:
408       absl::Status OnClientInitialMetadata(ClientMetadata& md) {
409         md.Set(HttpPathMetadata(), Slice::FromStaticString("hello"));
410         bool first = std::exchange(first_, false);
411         return first ? absl::OkStatus() : absl::CancelledError();
412       }
413 
414      private:
415       bool first_ = true;
416     };
417   };
418   StackData d;
419   Filter1 f1;
420   const size_t call_offset = d.AddFilter(&f1);
421   EXPECT_EQ(call_offset, 0);
422   d.AddClientInitialMetadataOp(&f1, call_offset);
423   ASSERT_EQ(d.filter_constructor.size(), 1u);
424   ASSERT_EQ(d.filter_destructor.size(), 0u);
425   EXPECT_EQ(d.filter_constructor[0].channel_data, &f1);
426   EXPECT_EQ(d.filter_constructor[0].call_offset, call_offset);
427   ASSERT_EQ(d.client_initial_metadata.ops.size(), 1u);
428   EXPECT_EQ(d.client_initial_metadata.ops[0].call_offset, call_offset);
429   EXPECT_EQ(d.client_initial_metadata.ops[0].channel_data, &f1);
430   // Instant => no poll/early destroy
431   EXPECT_EQ(d.client_initial_metadata.ops[0].poll, nullptr);
432   EXPECT_EQ(d.client_initial_metadata.ops[0].early_destroy, nullptr);
433   // Check promise init
434   void* call_data = gpr_malloc_aligned(d.call_data_size, d.call_data_alignment);
435   d.filter_constructor[0].call_init(call_data, &f1);
436   auto memory_allocator =
437       MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
438   auto arena = MakeScopedArena(1024, &memory_allocator);
439   auto md = Arena::MakePooled<ClientMetadata>();
440   promise_detail::Context<Arena> ctx(arena.get());
441   // A succeeding call
442   EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
443   auto r = d.client_initial_metadata.ops[0].promise_init(
444       nullptr, call_data, d.client_initial_metadata.ops[0].channel_data,
445       std::move(md));
446   EXPECT_TRUE(r.ready());
447   EXPECT_EQ(r.value().ok->get_pointer(HttpPathMetadata())->as_string_view(),
448             "hello");
449   // A failing call
450   md = Arena::MakePooled<ClientMetadata>();
451   EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
452   r = d.client_initial_metadata.ops[0].promise_init(
453       nullptr, call_data, d.client_initial_metadata.ops[0].channel_data,
454       std::move(md));
455   EXPECT_TRUE(r.ready());
456   EXPECT_EQ(r.value().ok, nullptr);
457   EXPECT_EQ(r.value().error->get(GrpcStatusMetadata()), GRPC_STATUS_CANCELLED);
458   gpr_free_aligned(call_data);
459 }
460 
TEST(StackDataTest,InstantClientInitialMetadataReturningAbslStatusTakingChannelPtr)461 TEST(StackDataTest,
462      InstantClientInitialMetadataReturningAbslStatusTakingChannelPtr) {
463   struct Filter1 {
464     class Call {
465      public:
466       absl::Status OnClientInitialMetadata(ClientMetadata& md, Filter1* p) {
467         md.Set(HttpPathMetadata(), Slice::FromStaticString("hello"));
468         const bool first = std::exchange(first_, false);
469         p->v.push_back(first ? 11 : 22);
470         return first ? absl::OkStatus() : absl::CancelledError();
471       }
472 
473      private:
474       bool first_ = true;
475     };
476     std::vector<int> v;
477   };
478   StackData d;
479   Filter1 f1;
480   const size_t call_offset = d.AddFilter(&f1);
481   EXPECT_EQ(call_offset, 0);
482   d.AddClientInitialMetadataOp(&f1, call_offset);
483   ASSERT_EQ(d.filter_constructor.size(), 1u);
484   ASSERT_EQ(d.filter_destructor.size(), 0u);
485   EXPECT_EQ(d.filter_constructor[0].channel_data, &f1);
486   EXPECT_EQ(d.filter_constructor[0].call_offset, call_offset);
487   ASSERT_EQ(d.client_initial_metadata.ops.size(), 1u);
488   EXPECT_EQ(d.client_initial_metadata.ops[0].call_offset, call_offset);
489   EXPECT_EQ(d.client_initial_metadata.ops[0].channel_data, &f1);
490   // Instant => no poll/early destroy
491   EXPECT_EQ(d.client_initial_metadata.ops[0].poll, nullptr);
492   EXPECT_EQ(d.client_initial_metadata.ops[0].early_destroy, nullptr);
493   // Check promise init
494   void* call_data = gpr_malloc_aligned(d.call_data_size, d.call_data_alignment);
495   d.filter_constructor[0].call_init(call_data, &f1);
496   auto memory_allocator =
497       MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
498   auto arena = MakeScopedArena(1024, &memory_allocator);
499   auto md = Arena::MakePooled<ClientMetadata>();
500   promise_detail::Context<Arena> ctx(arena.get());
501   // A succeeding call
502   EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
503   auto r = d.client_initial_metadata.ops[0].promise_init(
504       nullptr, call_data, d.client_initial_metadata.ops[0].channel_data,
505       std::move(md));
506   EXPECT_TRUE(r.ready());
507   EXPECT_EQ(r.value().ok->get_pointer(HttpPathMetadata())->as_string_view(),
508             "hello");
509   // A failing call
510   md = Arena::MakePooled<ClientMetadata>();
511   EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
512   r = d.client_initial_metadata.ops[0].promise_init(
513       nullptr, call_data, d.client_initial_metadata.ops[0].channel_data,
514       std::move(md));
515   EXPECT_TRUE(r.ready());
516   EXPECT_EQ(r.value().ok, nullptr);
517   EXPECT_EQ(r.value().error->get(GrpcStatusMetadata()), GRPC_STATUS_CANCELLED);
518   gpr_free_aligned(call_data);
519   EXPECT_THAT(f1.v, ::testing::ElementsAre(11, 22));
520 }
521 
TEST(StackDataTest,InstantClientInitialMetadataReturningServerMetadata)522 TEST(StackDataTest, InstantClientInitialMetadataReturningServerMetadata) {
523   struct Filter1 {
524     class Call {
525      public:
526       ServerMetadataHandle OnClientInitialMetadata(ClientMetadata& md) {
527         md.Set(HttpPathMetadata(), Slice::FromStaticString("hello"));
528         bool first = std::exchange(first_, false);
529         return first ? nullptr
530                      : ServerMetadataFromStatus(absl::CancelledError());
531       }
532 
533      private:
534       bool first_ = true;
535     };
536   };
537   StackData d;
538   Filter1 f1;
539   const size_t call_offset = d.AddFilter(&f1);
540   EXPECT_EQ(call_offset, 0);
541   d.AddClientInitialMetadataOp(&f1, call_offset);
542   ASSERT_EQ(d.filter_constructor.size(), 1u);
543   ASSERT_EQ(d.filter_destructor.size(), 0u);
544   EXPECT_EQ(d.filter_constructor[0].channel_data, &f1);
545   EXPECT_EQ(d.filter_constructor[0].call_offset, call_offset);
546   ASSERT_EQ(d.client_initial_metadata.ops.size(), 1u);
547   EXPECT_EQ(d.client_initial_metadata.ops[0].call_offset, call_offset);
548   EXPECT_EQ(d.client_initial_metadata.ops[0].channel_data, &f1);
549   // Instant => no poll/early destroy
550   EXPECT_EQ(d.client_initial_metadata.ops[0].poll, nullptr);
551   EXPECT_EQ(d.client_initial_metadata.ops[0].early_destroy, nullptr);
552   // Check promise init
553   void* call_data = gpr_malloc_aligned(d.call_data_size, d.call_data_alignment);
554   d.filter_constructor[0].call_init(call_data, &f1);
555   auto memory_allocator =
556       MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
557   auto arena = MakeScopedArena(1024, &memory_allocator);
558   auto md = Arena::MakePooled<ClientMetadata>();
559   promise_detail::Context<Arena> ctx(arena.get());
560   // A succeeding call
561   EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
562   auto r = d.client_initial_metadata.ops[0].promise_init(
563       nullptr, call_data, d.client_initial_metadata.ops[0].channel_data,
564       std::move(md));
565   EXPECT_TRUE(r.ready());
566   EXPECT_EQ(r.value().ok->get_pointer(HttpPathMetadata())->as_string_view(),
567             "hello");
568   // A failing call
569   md = Arena::MakePooled<ClientMetadata>();
570   EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
571   r = d.client_initial_metadata.ops[0].promise_init(
572       nullptr, call_data, d.client_initial_metadata.ops[0].channel_data,
573       std::move(md));
574   EXPECT_TRUE(r.ready());
575   EXPECT_EQ(r.value().ok, nullptr);
576   EXPECT_EQ(r.value().error->get(GrpcStatusMetadata()), GRPC_STATUS_CANCELLED);
577   gpr_free_aligned(call_data);
578 }
579 
TEST(StackDataTest,InstantClientInitialMetadataReturningServerMetadataTakingChannelPtr)580 TEST(StackDataTest,
581      InstantClientInitialMetadataReturningServerMetadataTakingChannelPtr) {
582   struct Filter1 {
583     class Call {
584      public:
585       ServerMetadataHandle OnClientInitialMetadata(ClientMetadata& md,
586                                                    Filter1* p) {
587         md.Set(HttpPathMetadata(), Slice::FromStaticString("hello"));
588         const bool first = std::exchange(first_, false);
589         p->v.push_back(first ? 11 : 22);
590         return first ? nullptr
591                      : ServerMetadataFromStatus(absl::CancelledError());
592       }
593 
594      private:
595       bool first_ = true;
596     };
597     std::vector<int> v;
598   };
599   StackData d;
600   Filter1 f1;
601   const size_t call_offset = d.AddFilter(&f1);
602   EXPECT_EQ(call_offset, 0);
603   d.AddClientInitialMetadataOp(&f1, call_offset);
604   ASSERT_EQ(d.filter_constructor.size(), 1u);
605   ASSERT_EQ(d.filter_destructor.size(), 0u);
606   EXPECT_EQ(d.filter_constructor[0].channel_data, &f1);
607   EXPECT_EQ(d.filter_constructor[0].call_offset, call_offset);
608   ASSERT_EQ(d.client_initial_metadata.ops.size(), 1u);
609   EXPECT_EQ(d.client_initial_metadata.ops[0].call_offset, call_offset);
610   EXPECT_EQ(d.client_initial_metadata.ops[0].channel_data, &f1);
611   // Instant => no poll/early destroy
612   EXPECT_EQ(d.client_initial_metadata.ops[0].poll, nullptr);
613   EXPECT_EQ(d.client_initial_metadata.ops[0].early_destroy, nullptr);
614   // Check promise init
615   void* call_data = gpr_malloc_aligned(d.call_data_size, d.call_data_alignment);
616   d.filter_constructor[0].call_init(call_data, &f1);
617   auto memory_allocator =
618       MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
619   auto arena = MakeScopedArena(1024, &memory_allocator);
620   auto md = Arena::MakePooled<ClientMetadata>();
621   promise_detail::Context<Arena> ctx(arena.get());
622   // A succeeding call
623   EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
624   auto r = d.client_initial_metadata.ops[0].promise_init(
625       nullptr, call_data, d.client_initial_metadata.ops[0].channel_data,
626       std::move(md));
627   EXPECT_TRUE(r.ready());
628   EXPECT_EQ(r.value().ok->get_pointer(HttpPathMetadata())->as_string_view(),
629             "hello");
630   // A failing call
631   md = Arena::MakePooled<ClientMetadata>();
632   EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
633   r = d.client_initial_metadata.ops[0].promise_init(
634       nullptr, call_data, d.client_initial_metadata.ops[0].channel_data,
635       std::move(md));
636   EXPECT_TRUE(r.ready());
637   EXPECT_EQ(r.value().ok, nullptr);
638   EXPECT_EQ(r.value().error->get(GrpcStatusMetadata()), GRPC_STATUS_CANCELLED);
639   gpr_free_aligned(call_data);
640   EXPECT_THAT(f1.v, ::testing::ElementsAre(11, 22));
641 }
642 
TEST(StackDataTest,PromiseClientInitialMetadataReturningAbslStatus)643 TEST(StackDataTest, PromiseClientInitialMetadataReturningAbslStatus) {
644   struct Filter1 {
645     class Call {
646      public:
647       auto OnClientInitialMetadata(ClientMetadata& md) {
648         return [this, i = std::make_unique<int>(3),
649                 md = &md]() mutable -> Poll<absl::Status> {
650           --*i;
651           if (*i > 0) return Pending{};
652           md->Set(HttpPathMetadata(), Slice::FromStaticString("hello"));
653           bool first = std::exchange(first_, false);
654           return first ? absl::OkStatus() : absl::CancelledError();
655         };
656       }
657 
658      private:
659       bool first_ = true;
660     };
661   };
662   StackData d;
663   Filter1 f1;
664   const size_t call_offset = d.AddFilter(&f1);
665   EXPECT_EQ(call_offset, 0);
666   d.AddClientInitialMetadataOp(&f1, call_offset);
667   ASSERT_EQ(d.filter_constructor.size(), 1u);
668   ASSERT_EQ(d.filter_destructor.size(), 0u);
669   EXPECT_EQ(d.filter_constructor[0].channel_data, &f1);
670   EXPECT_EQ(d.filter_constructor[0].call_offset, call_offset);
671   ASSERT_EQ(d.client_initial_metadata.ops.size(), 1u);
672   EXPECT_EQ(d.client_initial_metadata.ops[0].call_offset, call_offset);
673   EXPECT_EQ(d.client_initial_metadata.ops[0].channel_data, &f1);
674   // Check promise init
675   void* call_data = gpr_malloc_aligned(d.call_data_size, d.call_data_alignment);
676   d.filter_constructor[0].call_init(call_data, &f1);
677   auto memory_allocator =
678       MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
679   auto arena = MakeScopedArena(1024, &memory_allocator);
680   auto md = Arena::MakePooled<ClientMetadata>();
681   promise_detail::Context<Arena> ctx(arena.get());
682   // A succeeding call
683   EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
684   void* promise_data =
685       gpr_malloc_aligned(d.client_initial_metadata.promise_size,
686                          d.client_initial_metadata.promise_alignment);
687   auto r = d.client_initial_metadata.ops[0].promise_init(
688       promise_data, call_data, d.client_initial_metadata.ops[0].channel_data,
689       std::move(md));
690   EXPECT_FALSE(r.ready());
691   r = d.client_initial_metadata.ops[0].poll(promise_data);
692   EXPECT_FALSE(r.ready());
693   r = d.client_initial_metadata.ops[0].poll(promise_data);
694   EXPECT_TRUE(r.ready());
695   EXPECT_EQ(r.value().ok->get_pointer(HttpPathMetadata())->as_string_view(),
696             "hello");
697   // A failing call
698   md = Arena::MakePooled<ClientMetadata>();
699   EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
700   r = d.client_initial_metadata.ops[0].promise_init(
701       promise_data, call_data, d.client_initial_metadata.ops[0].channel_data,
702       std::move(md));
703   EXPECT_FALSE(r.ready());
704   r = d.client_initial_metadata.ops[0].poll(promise_data);
705   EXPECT_FALSE(r.ready());
706   r = d.client_initial_metadata.ops[0].poll(promise_data);
707   EXPECT_TRUE(r.ready());
708   EXPECT_EQ(r.value().ok, nullptr);
709   EXPECT_EQ(r.value().error->get(GrpcStatusMetadata()), GRPC_STATUS_CANCELLED);
710   // A cancelled call
711   md = Arena::MakePooled<ClientMetadata>();
712   EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
713   r = d.client_initial_metadata.ops[0].promise_init(
714       promise_data, call_data, d.client_initial_metadata.ops[0].channel_data,
715       std::move(md));
716   EXPECT_FALSE(r.ready());
717   d.client_initial_metadata.ops[0].early_destroy(promise_data);
718   // ASAN will trigger if things aren't cleaned up
719   gpr_free_aligned(promise_data);
720   gpr_free_aligned(call_data);
721 }
722 
TEST(StackDataTest,PromiseClientInitialMetadataReturningAbslStatusTakingChannelPtr)723 TEST(StackDataTest,
724      PromiseClientInitialMetadataReturningAbslStatusTakingChannelPtr) {
725   struct Filter1 {
726     class Call {
727      public:
728       auto OnClientInitialMetadata(ClientMetadata& md, Filter1* p) {
729         return [this, p, i = std::make_unique<int>(3),
730                 md = &md]() mutable -> Poll<absl::Status> {
731           --*i;
732           if (*i > 0) return Pending{};
733           md->Set(HttpPathMetadata(), Slice::FromStaticString("hello"));
734           bool first = std::exchange(first_, false);
735           p->v.push_back(first ? 11 : 22);
736           return first ? absl::OkStatus() : absl::CancelledError();
737         };
738       }
739 
740      private:
741       bool first_ = true;
742     };
743     std::vector<int> v;
744   };
745   StackData d;
746   Filter1 f1;
747   const size_t call_offset = d.AddFilter(&f1);
748   EXPECT_EQ(call_offset, 0);
749   d.AddClientInitialMetadataOp(&f1, call_offset);
750   ASSERT_EQ(d.filter_constructor.size(), 1u);
751   ASSERT_EQ(d.filter_destructor.size(), 0u);
752   EXPECT_EQ(d.filter_constructor[0].channel_data, &f1);
753   EXPECT_EQ(d.filter_constructor[0].call_offset, call_offset);
754   ASSERT_EQ(d.client_initial_metadata.ops.size(), 1u);
755   EXPECT_EQ(d.client_initial_metadata.ops[0].call_offset, call_offset);
756   EXPECT_EQ(d.client_initial_metadata.ops[0].channel_data, &f1);
757   // Check promise init
758   void* call_data = gpr_malloc_aligned(d.call_data_size, d.call_data_alignment);
759   d.filter_constructor[0].call_init(call_data, &f1);
760   auto memory_allocator =
761       MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
762   auto arena = MakeScopedArena(1024, &memory_allocator);
763   auto md = Arena::MakePooled<ClientMetadata>();
764   promise_detail::Context<Arena> ctx(arena.get());
765   // A succeeding call
766   EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
767   void* promise_data =
768       gpr_malloc_aligned(d.client_initial_metadata.promise_size,
769                          d.client_initial_metadata.promise_alignment);
770   auto r = d.client_initial_metadata.ops[0].promise_init(
771       promise_data, call_data, d.client_initial_metadata.ops[0].channel_data,
772       std::move(md));
773   EXPECT_FALSE(r.ready());
774   r = d.client_initial_metadata.ops[0].poll(promise_data);
775   EXPECT_FALSE(r.ready());
776   r = d.client_initial_metadata.ops[0].poll(promise_data);
777   EXPECT_TRUE(r.ready());
778   EXPECT_EQ(r.value().ok->get_pointer(HttpPathMetadata())->as_string_view(),
779             "hello");
780   // A failing call
781   md = Arena::MakePooled<ClientMetadata>();
782   EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
783   r = d.client_initial_metadata.ops[0].promise_init(
784       promise_data, call_data, d.client_initial_metadata.ops[0].channel_data,
785       std::move(md));
786   EXPECT_FALSE(r.ready());
787   r = d.client_initial_metadata.ops[0].poll(promise_data);
788   EXPECT_FALSE(r.ready());
789   r = d.client_initial_metadata.ops[0].poll(promise_data);
790   EXPECT_TRUE(r.ready());
791   EXPECT_EQ(r.value().ok, nullptr);
792   EXPECT_EQ(r.value().error->get(GrpcStatusMetadata()), GRPC_STATUS_CANCELLED);
793   // A cancelled call
794   md = Arena::MakePooled<ClientMetadata>();
795   EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
796   r = d.client_initial_metadata.ops[0].promise_init(
797       promise_data, call_data, d.client_initial_metadata.ops[0].channel_data,
798       std::move(md));
799   EXPECT_FALSE(r.ready());
800   d.client_initial_metadata.ops[0].early_destroy(promise_data);
801   // ASAN will trigger if things aren't cleaned up
802   gpr_free_aligned(promise_data);
803   gpr_free_aligned(call_data);
804   EXPECT_THAT(f1.v, ::testing::ElementsAre(11, 22));
805 }
806 
TEST(StackDataTest,InstantServerInitialMetadataReturningVoid)807 TEST(StackDataTest, InstantServerInitialMetadataReturningVoid) {
808   struct Filter1 {
809     struct Call {
810       void OnServerInitialMetadata(ServerMetadata& md) {
811         md.Set(HttpPathMetadata(), Slice::FromStaticString("hello"));
812       }
813     };
814   };
815   StackData d;
816   Filter1 f1;
817   const size_t call_offset = d.AddFilter(&f1);
818   EXPECT_EQ(call_offset, 0);
819   EXPECT_EQ(d.call_data_size, 0);
820   d.AddServerInitialMetadataOp(&f1, call_offset);
821   ASSERT_EQ(d.filter_constructor.size(), 0);
822   ASSERT_EQ(d.filter_destructor.size(), 0);
823   ASSERT_EQ(d.server_initial_metadata.ops.size(), 1u);
824   EXPECT_EQ(d.server_initial_metadata.ops[0].call_offset, call_offset);
825   EXPECT_EQ(d.server_initial_metadata.ops[0].channel_data, &f1);
826   // Instant => no poll/early destroy
827   EXPECT_EQ(d.server_initial_metadata.ops[0].poll, nullptr);
828   EXPECT_EQ(d.server_initial_metadata.ops[0].early_destroy, nullptr);
829   // Check promise init
830   auto memory_allocator =
831       MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
832   auto arena = MakeScopedArena(1024, &memory_allocator);
833   auto md = Arena::MakePooled<ServerMetadata>();
834   EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
835   char call_data;
836   auto r = d.server_initial_metadata.ops[0].promise_init(
837       nullptr, &call_data, d.server_initial_metadata.ops[0].channel_data,
838       std::move(md));
839   EXPECT_TRUE(r.ready());
840   EXPECT_EQ(r.value().ok->get_pointer(HttpPathMetadata())->as_string_view(),
841             "hello");
842 }
843 
TEST(StackDataTest,InstantClientToServerMessagesReturningVoid)844 TEST(StackDataTest, InstantClientToServerMessagesReturningVoid) {
845   struct Filter1 {
846     struct Call {
847       void OnClientToServerMessage(Message& message) {
848         message.mutable_flags() |= 1;
849       }
850     };
851   };
852   StackData d;
853   Filter1 f1;
854   const size_t call_offset = d.AddFilter(&f1);
855   EXPECT_EQ(call_offset, 0);
856   EXPECT_EQ(d.call_data_size, 0);
857   d.AddClientToServerMessageOp(&f1, call_offset);
858   ASSERT_EQ(d.filter_constructor.size(), 0u);
859   ASSERT_EQ(d.filter_destructor.size(), 0u);
860   ASSERT_EQ(d.client_to_server_messages.ops.size(), 1u);
861   EXPECT_EQ(d.client_to_server_messages.ops[0].call_offset, call_offset);
862   EXPECT_EQ(d.client_to_server_messages.ops[0].channel_data, &f1);
863   // Instant => no poll/early destroy
864   EXPECT_EQ(d.client_to_server_messages.ops[0].poll, nullptr);
865   EXPECT_EQ(d.client_to_server_messages.ops[0].early_destroy, nullptr);
866   // Check promise init
867   auto memory_allocator =
868       MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
869   auto arena = MakeScopedArena(1024, &memory_allocator);
870   auto message = Arena::MakePooled<Message>(SliceBuffer(), 0);
871   char call_data;
872   auto r = d.client_to_server_messages.ops[0].promise_init(
873       nullptr, &call_data, d.client_to_server_messages.ops[0].channel_data,
874       std::move(message));
875   EXPECT_TRUE(r.ready());
876   EXPECT_EQ(r.value().ok->flags(), 1u);
877 }
878 
TEST(StackDataTest,InstantServerToClientMessagesReturningVoid)879 TEST(StackDataTest, InstantServerToClientMessagesReturningVoid) {
880   struct Filter1 {
881     struct Call {
882       void OnServerToClientMessage(Message& message) {
883         message.mutable_flags() |= 1;
884       }
885     };
886   };
887   StackData d;
888   Filter1 f1;
889   const size_t call_offset = d.AddFilter(&f1);
890   EXPECT_EQ(call_offset, 0);
891   EXPECT_EQ(d.call_data_size, 0);
892   d.AddServerToClientMessageOp(&f1, call_offset);
893   ASSERT_EQ(d.filter_constructor.size(), 0u);
894   ASSERT_EQ(d.filter_destructor.size(), 0u);
895   ASSERT_EQ(d.server_to_client_messages.ops.size(), 1u);
896   EXPECT_EQ(d.server_to_client_messages.ops[0].call_offset, call_offset);
897   EXPECT_EQ(d.server_to_client_messages.ops[0].channel_data, &f1);
898   // Instant => no poll/early destroy
899   EXPECT_EQ(d.server_to_client_messages.ops[0].poll, nullptr);
900   EXPECT_EQ(d.server_to_client_messages.ops[0].early_destroy, nullptr);
901   // Check promise init
902   auto memory_allocator =
903       MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
904   auto arena = MakeScopedArena(1024, &memory_allocator);
905   auto message = Arena::MakePooled<Message>(SliceBuffer(), 0);
906   char call_data;
907   auto r = d.server_to_client_messages.ops[0].promise_init(
908       nullptr, &call_data, d.server_to_client_messages.ops[0].channel_data,
909       std::move(message));
910   EXPECT_TRUE(r.ready());
911   EXPECT_EQ(r.value().ok->flags(), 1u);
912 }
913 
TEST(StackDataTest,InstantServerTrailingMetadataReturningVoid)914 TEST(StackDataTest, InstantServerTrailingMetadataReturningVoid) {
915   struct Filter1 {
916     struct Call {
917       void OnServerTrailingMetadata(ServerMetadata& md) {
918         md.Set(HttpPathMetadata(), Slice::FromStaticString("hello"));
919       }
920     };
921   };
922   StackData d;
923   Filter1 f1;
924   const size_t call_offset = d.AddFilter(&f1);
925   EXPECT_EQ(call_offset, 0);
926   EXPECT_EQ(d.call_data_size, 0);
927   d.AddServerTrailingMetadataOp(&f1, call_offset);
928   ASSERT_EQ(d.filter_constructor.size(), 0u);
929   ASSERT_EQ(d.filter_destructor.size(), 0u);
930   ASSERT_EQ(d.server_trailing_metadata.ops.size(), 1u);
931   EXPECT_EQ(d.server_trailing_metadata.ops[0].call_offset, call_offset);
932   EXPECT_EQ(d.server_trailing_metadata.ops[0].channel_data, &f1);
933   // Instant => no poll/early destroy
934   EXPECT_EQ(d.server_trailing_metadata.ops[0].poll, nullptr);
935   EXPECT_EQ(d.server_trailing_metadata.ops[0].early_destroy, nullptr);
936   // Check promise init
937   auto memory_allocator =
938       MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
939   auto arena = MakeScopedArena(1024, &memory_allocator);
940   auto md = Arena::MakePooled<ServerMetadata>();
941   EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
942   char call_data;
943   auto r = d.server_trailing_metadata.ops[0].promise_init(
944       nullptr, &call_data, d.server_trailing_metadata.ops[0].channel_data,
945       std::move(md));
946   EXPECT_TRUE(r.ready());
947   EXPECT_EQ(r.value()->get_pointer(HttpPathMetadata())->as_string_view(),
948             "hello");
949 }
950 
TEST(StackDataTest,InstantServerTrailingMetadataReturningVoidTakingChannelPtr)951 TEST(StackDataTest,
952      InstantServerTrailingMetadataReturningVoidTakingChannelPtr) {
953   struct Filter1 {
954     struct Call {
955       void OnServerTrailingMetadata(ServerMetadata& md, Filter1* p) {
956         p->v.push_back(42);
957         md.Set(HttpPathMetadata(), Slice::FromStaticString("hello"));
958       }
959     };
960     std::vector<int> v;
961   };
962   StackData d;
963   Filter1 f1;
964   const size_t call_offset = d.AddFilter(&f1);
965   EXPECT_EQ(call_offset, 0);
966   EXPECT_EQ(d.call_data_size, 0);
967   d.AddServerTrailingMetadataOp(&f1, call_offset);
968   ASSERT_EQ(d.filter_constructor.size(), 0u);
969   ASSERT_EQ(d.filter_destructor.size(), 0u);
970   ASSERT_EQ(d.server_trailing_metadata.ops.size(), 1u);
971   EXPECT_EQ(d.server_trailing_metadata.ops[0].call_offset, call_offset);
972   EXPECT_EQ(d.server_trailing_metadata.ops[0].channel_data, &f1);
973   // Instant => no poll/early destroy
974   EXPECT_EQ(d.server_trailing_metadata.ops[0].poll, nullptr);
975   EXPECT_EQ(d.server_trailing_metadata.ops[0].early_destroy, nullptr);
976   // Check promise init
977   auto memory_allocator =
978       MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
979   auto arena = MakeScopedArena(1024, &memory_allocator);
980   auto md = Arena::MakePooled<ServerMetadata>();
981   EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
982   char call_data;
983   auto r = d.server_trailing_metadata.ops[0].promise_init(
984       nullptr, &call_data, d.server_trailing_metadata.ops[0].channel_data,
985       std::move(md));
986   EXPECT_TRUE(r.ready());
987   EXPECT_EQ(r.value()->get_pointer(HttpPathMetadata())->as_string_view(),
988             "hello");
989   EXPECT_THAT(f1.v, ::testing::ElementsAre(42));
990 }
991 
992 }  // namespace filters_detail
993 
994 ///////////////////////////////////////////////////////////////////////////////
995 // StackBuilder
996 
997 class CallFilters::StackTestSpouse {
998  public:
StackDataFrom(const Stack & stack)999   static const filters_detail::StackData& StackDataFrom(const Stack& stack) {
1000     return stack.data_;
1001   }
1002 };
1003 
TEST(StackBuilderTest,AddOnServerTrailingMetadata)1004 TEST(StackBuilderTest, AddOnServerTrailingMetadata) {
1005   CallFilters::StackBuilder b;
1006   b.AddOnServerTrailingMetadata(
1007       [x = std::make_unique<int>(42)](ServerMetadata&) { EXPECT_EQ(*x, 42); });
1008   auto stack = b.Build();
1009   const auto& data = CallFilters::StackTestSpouse().StackDataFrom(*stack);
1010   ASSERT_EQ(data.server_trailing_metadata.ops.size(), 1u);
1011   ASSERT_EQ(data.client_initial_metadata.ops.size(), 0u);
1012   ASSERT_EQ(data.client_to_server_messages.ops.size(), 0u);
1013   ASSERT_EQ(data.server_to_client_messages.ops.size(), 0u);
1014   ASSERT_EQ(data.server_initial_metadata.ops.size(), 0u);
1015   EXPECT_EQ(data.server_trailing_metadata.ops[0].call_offset, 0);
1016   EXPECT_NE(data.server_trailing_metadata.ops[0].channel_data, nullptr);
1017 }
1018 
1019 ///////////////////////////////////////////////////////////////////////////////
1020 // OperationExecutor
1021 
1022 namespace filters_detail {
1023 
TEST(OperationExecutorTest,NoOp)1024 TEST(OperationExecutorTest, NoOp) {
1025   OperationExecutor<ClientMetadataHandle> pipe;
1026   EXPECT_FALSE(pipe.IsRunning());
1027 }
1028 
TEST(OperationExecutorTest,InstantTwo)1029 TEST(OperationExecutorTest, InstantTwo) {
1030   class Filter1 {
1031    public:
1032     class Call {
1033      public:
1034       absl::Status OnClientInitialMetadata(ClientMetadata& md) {
1035         bool first = std::exchange(first_, false);
1036         if (!first) {
1037           EXPECT_EQ(md.get_pointer(HttpPathMetadata()), nullptr);
1038         }
1039         if (md.get_pointer(HttpPathMetadata()) != nullptr) {
1040           md.Set(HttpPathMetadata(), Slice::FromStaticString("world"));
1041         } else {
1042           md.Set(HttpPathMetadata(), Slice::FromStaticString("hello"));
1043         }
1044         return first ? absl::OkStatus() : absl::CancelledError();
1045       }
1046 
1047      private:
1048       bool first_ = true;
1049     };
1050   };
1051   StackData d;
1052   Filter1 f1;
1053   Filter1 f2;
1054   const size_t call_offset1 = d.AddFilter(&f1);
1055   const size_t call_offset2 = d.AddFilter(&f2);
1056   d.AddClientInitialMetadataOp(&f1, call_offset1);
1057   d.AddClientInitialMetadataOp(&f2, call_offset2);
1058   ASSERT_EQ(d.filter_constructor.size(), 2u);
1059   ASSERT_EQ(d.filter_destructor.size(), 0u);
1060   ASSERT_EQ(d.client_initial_metadata.ops.size(), 2u);
1061   void* call_data1 =
1062       gpr_malloc_aligned(d.call_data_size, d.call_data_alignment);
1063   void* call_data2 = Offset(call_data1, d.filter_constructor[1].call_offset);
1064   d.filter_constructor[0].call_init(call_data1, &f1);
1065   d.filter_constructor[1].call_init(call_data2, &f2);
1066   OperationExecutor<ClientMetadataHandle> transformer;
1067   auto memory_allocator =
1068       MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
1069   auto arena = MakeScopedArena(1024, &memory_allocator);
1070   promise_detail::Context<Arena> ctx(arena.get());
1071   // First call succeeds
1072   auto md = Arena::MakePooled<ServerMetadata>();
1073   EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
1074   auto r =
1075       transformer.Start(&d.client_initial_metadata, std::move(md), call_data1);
1076   EXPECT_TRUE(r.ready());
1077   EXPECT_EQ(r.value().ok->get_pointer(HttpPathMetadata())->as_string_view(),
1078             "world");
1079   // Second fails
1080   md = Arena::MakePooled<ServerMetadata>();
1081   EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
1082   r = transformer.Start(&d.client_initial_metadata, std::move(md), call_data1);
1083   EXPECT_TRUE(r.ready());
1084   EXPECT_EQ(r.value().ok, nullptr);
1085   EXPECT_EQ(r.value().error->get(GrpcStatusMetadata()), GRPC_STATUS_CANCELLED);
1086   gpr_free_aligned(call_data1);
1087 }
1088 
TEST(OperationExecutorTest,PromiseTwo)1089 TEST(OperationExecutorTest, PromiseTwo) {
1090   class Filter1 {
1091    public:
1092     class Call {
1093      public:
1094       auto OnClientInitialMetadata(ClientMetadata& md) {
1095         return [md = &md, this,
1096                 i = std::make_unique<int>(3)]() mutable -> Poll<absl::Status> {
1097           --*i;
1098           if (*i > 0) return Pending{};
1099           bool first = std::exchange(first_, false);
1100           if (!first) {
1101             EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
1102           }
1103           if (md->get_pointer(HttpPathMetadata()) != nullptr) {
1104             md->Set(HttpPathMetadata(), Slice::FromStaticString("world"));
1105           } else {
1106             md->Set(HttpPathMetadata(), Slice::FromStaticString("hello"));
1107           }
1108           return first ? absl::OkStatus() : absl::CancelledError();
1109         };
1110       }
1111 
1112      private:
1113       bool first_ = true;
1114     };
1115   };
1116   StackData d;
1117   Filter1 f1;
1118   Filter1 f2;
1119   const size_t call_offset1 = d.AddFilter(&f1);
1120   const size_t call_offset2 = d.AddFilter(&f2);
1121   d.AddClientInitialMetadataOp(&f1, call_offset1);
1122   d.AddClientInitialMetadataOp(&f2, call_offset2);
1123   ASSERT_EQ(d.filter_constructor.size(), 2u);
1124   ASSERT_EQ(d.filter_destructor.size(), 0u);
1125   ASSERT_EQ(d.client_initial_metadata.ops.size(), 2u);
1126   void* call_data1 =
1127       gpr_malloc_aligned(d.call_data_size, d.call_data_alignment);
1128   void* call_data2 = Offset(call_data1, d.filter_constructor[1].call_offset);
1129   d.filter_constructor[0].call_init(call_data1, &f1);
1130   d.filter_constructor[1].call_init(call_data2, &f2);
1131   OperationExecutor<ClientMetadataHandle> transformer;
1132   auto memory_allocator =
1133       MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
1134   auto arena = MakeScopedArena(1024, &memory_allocator);
1135   promise_detail::Context<Arena> ctx(arena.get());
1136   // First call succeeds after two sets of two step delays.
1137   auto md = Arena::MakePooled<ServerMetadata>();
1138   EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
1139   auto r =
1140       transformer.Start(&d.client_initial_metadata, std::move(md), call_data1);
1141   EXPECT_FALSE(r.ready());
1142   r = transformer.Step(call_data1);
1143   EXPECT_FALSE(r.ready());
1144   r = transformer.Step(call_data1);
1145   EXPECT_FALSE(r.ready());
1146   r = transformer.Step(call_data1);
1147   EXPECT_FALSE(r.ready());
1148   r = transformer.Step(call_data1);
1149   EXPECT_TRUE(r.ready());
1150   EXPECT_EQ(r.value().ok->get_pointer(HttpPathMetadata())->as_string_view(),
1151             "world");
1152   // Second fails after one set of two step delays.
1153   md = Arena::MakePooled<ServerMetadata>();
1154   EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
1155   r = transformer.Start(&d.client_initial_metadata, std::move(md), call_data1);
1156   EXPECT_FALSE(r.ready());
1157   r = transformer.Step(call_data1);
1158   EXPECT_FALSE(r.ready());
1159   r = transformer.Step(call_data1);
1160   EXPECT_TRUE(r.ready());
1161   EXPECT_EQ(r.value().ok, nullptr);
1162   EXPECT_EQ(r.value().error->get(GrpcStatusMetadata()), GRPC_STATUS_CANCELLED);
1163   gpr_free_aligned(call_data1);
1164 }
1165 
1166 }  // namespace filters_detail
1167 
1168 ///////////////////////////////////////////////////////////////////////////////
1169 // InfallibleOperationExecutor
1170 
1171 namespace filters_detail {
1172 
TEST(InfallibleOperationExecutor,NoOp)1173 TEST(InfallibleOperationExecutor, NoOp) {
1174   OperationExecutor<ServerMetadataHandle> pipe;
1175   EXPECT_FALSE(pipe.IsRunning());
1176 }
1177 
TEST(InfallibleOperationExecutor,InstantTwo)1178 TEST(InfallibleOperationExecutor, InstantTwo) {
1179   class Filter1 {
1180    public:
1181     class Call {
1182      public:
1183       void OnServerTrailingMetadata(ClientMetadata& md) {
1184         if (md.get_pointer(HttpPathMetadata()) != nullptr) {
1185           md.Set(HttpPathMetadata(), Slice::FromStaticString("world"));
1186         } else {
1187           md.Set(HttpPathMetadata(), Slice::FromStaticString("hello"));
1188         }
1189       }
1190     };
1191   };
1192   StackData d;
1193   Filter1 f1;
1194   Filter1 f2;
1195   const size_t call_offset1 = d.AddFilter(&f1);
1196   const size_t call_offset2 = d.AddFilter(&f2);
1197   d.AddServerTrailingMetadataOp(&f1, call_offset1);
1198   d.AddServerTrailingMetadataOp(&f2, call_offset2);
1199   ASSERT_EQ(d.filter_constructor.size(), 0u);
1200   ASSERT_EQ(d.filter_destructor.size(), 0u);
1201   ASSERT_EQ(d.server_trailing_metadata.ops.size(), 2u);
1202   void* call_data = gpr_malloc_aligned(d.call_data_size, d.call_data_alignment);
1203   InfallibleOperationExecutor<ServerMetadataHandle> transformer;
1204   auto memory_allocator =
1205       MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
1206   auto arena = MakeScopedArena(1024, &memory_allocator);
1207   promise_detail::Context<Arena> ctx(arena.get());
1208   auto md = Arena::MakePooled<ServerMetadata>();
1209   EXPECT_EQ(md->get_pointer(HttpPathMetadata()), nullptr);
1210   auto r =
1211       transformer.Start(&d.server_trailing_metadata, std::move(md), call_data);
1212   EXPECT_TRUE(r.ready());
1213   EXPECT_EQ(r.value()->get_pointer(HttpPathMetadata())->as_string_view(),
1214             "world");
1215   gpr_free_aligned(call_data);
1216 }
1217 
1218 }  // namespace filters_detail
1219 
1220 ///////////////////////////////////////////////////////////////////////////////
1221 // PipeState
1222 
1223 namespace filters_detail {
1224 
TEST(PipeStateTest,NoOp)1225 TEST(PipeStateTest, NoOp) { PipeState(); }
1226 
TEST(PipeStateTest,OnePull)1227 TEST(PipeStateTest, OnePull) {
1228   PipeState ps;
1229   StrictMock<MockActivity> activity;
1230   activity.Activate();
1231   // initially: not started, should only see pending from pulls
1232   EXPECT_THAT(ps.PollPull(), IsPending());
1233   EXPECT_THAT(ps.PollPull(), IsPending());
1234   // start it, should see a wakeup
1235   EXPECT_CALL(activity, WakeupRequested());
1236   ps.Start();
1237   Mock::VerifyAndClearExpectations(&activity);
1238   // should still see pending! nothing's been pushed
1239   EXPECT_THAT(ps.PollPull(), IsPending());
1240   EXPECT_THAT(ps.PollPull(), IsPending());
1241   // begin a push, should see a wakeup
1242   EXPECT_CALL(activity, WakeupRequested());
1243   ps.BeginPush();
1244   Mock::VerifyAndClearExpectations(&activity);
1245   // now we should see a value on the pull poll
1246   EXPECT_THAT(ps.PollPull(), IsReady(true));
1247   // push should be pending though!
1248   EXPECT_THAT(ps.PollPush(), IsPending());
1249   // ack the pull, should see a wakeup
1250   EXPECT_CALL(activity, WakeupRequested());
1251   ps.AckPull();
1252   Mock::VerifyAndClearExpectations(&activity);
1253   // now the push is complete
1254   EXPECT_THAT(ps.PollPush(), IsReady(Success()));
1255   ps.DropPush();
1256   ps.DropPull();
1257   EXPECT_FALSE(ps.holds_error());
1258 }
1259 
TEST(PipeStateTest,StartThenPull)1260 TEST(PipeStateTest, StartThenPull) {
1261   PipeState ps;
1262   StrictMock<MockActivity> activity;
1263   activity.Activate();
1264   ps.Start();
1265   // pull is pending! nothing's been pushed
1266   EXPECT_THAT(ps.PollPull(), IsPending());
1267   EXPECT_THAT(ps.PollPull(), IsPending());
1268   // begin a push, should see a wakeup
1269   EXPECT_CALL(activity, WakeupRequested());
1270   ps.BeginPush();
1271   Mock::VerifyAndClearExpectations(&activity);
1272   // now we should see a value on the pull poll
1273   EXPECT_THAT(ps.PollPull(), IsReady(true));
1274   // push should be pending though!
1275   EXPECT_THAT(ps.PollPush(), IsPending());
1276   // ack the pull, should see a wakeup
1277   EXPECT_CALL(activity, WakeupRequested());
1278   ps.AckPull();
1279   Mock::VerifyAndClearExpectations(&activity);
1280   // now the push is complete
1281   EXPECT_THAT(ps.PollPush(), IsReady(Success()));
1282   ps.DropPush();
1283   ps.DropPull();
1284   EXPECT_FALSE(ps.holds_error());
1285 }
1286 
TEST(PipeStateTest,PushFirst)1287 TEST(PipeStateTest, PushFirst) {
1288   PipeState ps;
1289   StrictMock<MockActivity> activity;
1290   activity.Activate();
1291   // start immediately, and push immediately
1292   ps.Start();
1293   ps.BeginPush();
1294   // push should be pending
1295   EXPECT_THAT(ps.PollPush(), IsPending());
1296   // pull should immediately see a value
1297   EXPECT_THAT(ps.PollPull(), IsReady(true));
1298   // push should still be pending though!
1299   EXPECT_THAT(ps.PollPush(), IsPending());
1300   // ack the pull, should see a wakeup
1301   EXPECT_CALL(activity, WakeupRequested());
1302   ps.AckPull();
1303   Mock::VerifyAndClearExpectations(&activity);
1304   // now the push is complete
1305   EXPECT_THAT(ps.PollPush(), IsReady(Success()));
1306   ps.DropPush();
1307   ps.DropPull();
1308   EXPECT_FALSE(ps.holds_error());
1309 }
1310 
TEST(PipeStateTest,DropPushing)1311 TEST(PipeStateTest, DropPushing) {
1312   PipeState ps;
1313   StrictMock<MockActivity> activity;
1314   activity.Activate();
1315   ps.BeginPush();
1316   ps.DropPush();
1317   EXPECT_TRUE(ps.holds_error());
1318   EXPECT_THAT(ps.PollPull(), IsReady(Failure()));
1319   ps.BeginPush();
1320   EXPECT_THAT(ps.PollPush(), IsReady(Failure()));
1321   ps.DropPush();
1322 }
1323 
TEST(PipeStateTest,DropPulling)1324 TEST(PipeStateTest, DropPulling) {
1325   PipeState ps;
1326   StrictMock<MockActivity> activity;
1327   activity.Activate();
1328   EXPECT_THAT(ps.PollPull(), IsPending());
1329   ps.DropPull();
1330   EXPECT_TRUE(ps.holds_error());
1331   EXPECT_THAT(ps.PollPull(), IsReady(Failure()));
1332   ps.DropPull();
1333   EXPECT_THAT(ps.PollPush(), IsReady(Failure()));
1334 }
1335 
TEST(PipeStateTest,DropProcessing)1336 TEST(PipeStateTest, DropProcessing) {
1337   PipeState ps;
1338   StrictMock<MockActivity> activity;
1339   activity.Activate();
1340   ps.Start();
1341   ps.BeginPush();
1342   EXPECT_THAT(ps.PollPull(), IsReady(true));
1343   ps.DropPull();
1344   EXPECT_TRUE(ps.holds_error());
1345   EXPECT_THAT(ps.PollPull(), IsReady(Failure()));
1346   EXPECT_THAT(ps.PollPush(), IsReady(Failure()));
1347 }
1348 
1349 }  // namespace filters_detail
1350 
1351 ///////////////////////////////////////////////////////////////////////////////
1352 // CallFilters
1353 
TEST(CallFiltersTest,CanBuildStack)1354 TEST(CallFiltersTest, CanBuildStack) {
1355   struct Filter {
1356     struct Call {
1357       void OnClientInitialMetadata(ClientMetadata&) {}
1358       void OnServerInitialMetadata(ServerMetadata&) {}
1359       void OnClientToServerMessage(Message&) {}
1360       void OnServerToClientMessage(Message&) {}
1361       void OnServerTrailingMetadata(ServerMetadata&) {}
1362       void OnFinalize(const grpc_call_final_info*) {}
1363     };
1364   };
1365   CallFilters::StackBuilder builder;
1366   Filter f;
1367   builder.Add(&f);
1368   auto stack = builder.Build();
1369   EXPECT_NE(stack, nullptr);
1370 }
1371 
TEST(CallFiltersTest,UnaryCall)1372 TEST(CallFiltersTest, UnaryCall) {
1373   struct Filter {
1374     struct Call {
1375       void OnClientInitialMetadata(ClientMetadata&, Filter* f) {
1376         f->steps.push_back(absl::StrCat(f->label, ":OnClientInitialMetadata"));
1377       }
1378       void OnServerInitialMetadata(ServerMetadata&, Filter* f) {
1379         f->steps.push_back(absl::StrCat(f->label, ":OnServerInitialMetadata"));
1380       }
1381       void OnClientToServerMessage(Message&, Filter* f) {
1382         f->steps.push_back(absl::StrCat(f->label, ":OnClientToServerMessage"));
1383       }
1384       void OnServerToClientMessage(Message&, Filter* f) {
1385         f->steps.push_back(absl::StrCat(f->label, ":OnServerToClientMessage"));
1386       }
1387       void OnServerTrailingMetadata(ServerMetadata&, Filter* f) {
1388         f->steps.push_back(absl::StrCat(f->label, ":OnServerTrailingMetadata"));
1389       }
1390       void OnFinalize(const grpc_call_final_info*, Filter* f) {
1391         f->steps.push_back(absl::StrCat(f->label, ":OnFinalize"));
1392       }
1393       std::unique_ptr<int> i = std::make_unique<int>(3);
1394     };
1395 
1396     const std::string label;
1397     std::vector<std::string>& steps;
1398   };
1399   std::vector<std::string> steps;
1400   Filter f1{"f1", steps};
1401   Filter f2{"f2", steps};
1402   CallFilters::StackBuilder builder;
1403   builder.Add(&f1);
1404   builder.Add(&f2);
1405   auto memory_allocator =
1406       MakeMemoryQuota("test-quota")->CreateMemoryAllocator("foo");
1407   auto arena = MakeScopedArena(1024, &memory_allocator);
1408   CallFilters filters(Arena::MakePooled<ClientMetadata>());
1409   filters.SetStack(builder.Build());
1410   promise_detail::Context<Arena> ctx(arena.get());
1411   StrictMock<MockActivity> activity;
1412   activity.Activate();
1413   // Pull client initial metadata
1414   auto pull_client_initial_metadata = filters.PullClientInitialMetadata();
1415   EXPECT_THAT(pull_client_initial_metadata(), IsReady());
1416   Mock::VerifyAndClearExpectations(&activity);
1417   // Push client to server message
1418   auto push_client_to_server_message = filters.PushClientToServerMessage(
1419       Arena::MakePooled<Message>(SliceBuffer(), 0));
1420   EXPECT_THAT(push_client_to_server_message(), IsPending());
1421   auto pull_client_to_server_message = filters.PullClientToServerMessage();
1422   // Pull client to server message, expect a wakeup
1423   EXPECT_CALL(activity, WakeupRequested());
1424   EXPECT_THAT(pull_client_to_server_message(), IsReady());
1425   Mock::VerifyAndClearExpectations(&activity);
1426   // Push should be done
1427   EXPECT_THAT(push_client_to_server_message(), IsReady(Success{}));
1428   // Push server initial metadata
1429   auto push_server_initial_metadata =
1430       filters.PushServerInitialMetadata(Arena::MakePooled<ServerMetadata>());
1431   EXPECT_THAT(push_server_initial_metadata(), IsPending());
1432   auto pull_server_initial_metadata = filters.PullServerInitialMetadata();
1433   // Pull server initial metadata, expect a wakeup
1434   EXPECT_CALL(activity, WakeupRequested());
1435   EXPECT_THAT(pull_server_initial_metadata(), IsReady());
1436   Mock::VerifyAndClearExpectations(&activity);
1437   // Push should be done
1438   EXPECT_THAT(push_server_initial_metadata(), IsReady(Success{}));
1439   // Push server to client message
1440   auto push_server_to_client_message = filters.PushServerToClientMessage(
1441       Arena::MakePooled<Message>(SliceBuffer(), 0));
1442   EXPECT_THAT(push_server_to_client_message(), IsPending());
1443   auto pull_server_to_client_message = filters.PullServerToClientMessage();
1444   // Pull server to client message, expect a wakeup
1445   EXPECT_CALL(activity, WakeupRequested());
1446   EXPECT_THAT(pull_server_to_client_message(), IsReady());
1447   Mock::VerifyAndClearExpectations(&activity);
1448   // Push should be done
1449   EXPECT_THAT(push_server_to_client_message(), IsReady(Success{}));
1450   // Push server trailing metadata
1451   filters.PushServerTrailingMetadata(Arena::MakePooled<ServerMetadata>());
1452   // Pull server trailing metadata
1453   auto pull_server_trailing_metadata = filters.PullServerTrailingMetadata();
1454   // Should be done
1455   EXPECT_THAT(pull_server_trailing_metadata(), IsReady());
1456   filters.Finalize(nullptr);
1457   EXPECT_THAT(steps,
1458               ::testing::ElementsAre(
1459                   "f1:OnClientInitialMetadata", "f2:OnClientInitialMetadata",
1460                   "f1:OnClientToServerMessage", "f2:OnClientToServerMessage",
1461                   "f2:OnServerInitialMetadata", "f1:OnServerInitialMetadata",
1462                   "f2:OnServerToClientMessage", "f1:OnServerToClientMessage",
1463                   "f2:OnServerTrailingMetadata", "f1:OnServerTrailingMetadata",
1464                   "f1:OnFinalize", "f2:OnFinalize"));
1465 }
1466 
1467 }  // namespace grpc_core
1468 
main(int argc,char ** argv)1469 int main(int argc, char** argv) {
1470   ::testing::InitGoogleTest(&argc, argv);
1471   return RUN_ALL_TESTS();
1472 }
1473