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