• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 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 #ifndef GRPC_TEST_CORE_END2END_END2END_TESTS_H
16 #define GRPC_TEST_CORE_END2END_END2END_TESTS_H
17 
18 #include <grpc/byte_buffer.h>
19 #include <grpc/compression.h>
20 #include <grpc/credentials.h>
21 #include <grpc/event_engine/event_engine.h>
22 #include <grpc/grpc.h>
23 #include <grpc/grpc_security.h>
24 #include <grpc/impl/propagation_bits.h>
25 #include <grpc/status.h>
26 #include <grpc/support/alloc.h>
27 #include <grpc/support/time.h>
28 #include <stdint.h>
29 #include <stdio.h>
30 
31 #include <algorithm>
32 #include <functional>
33 #include <initializer_list>
34 #include <map>
35 #include <memory>
36 #include <string>
37 #include <utility>
38 #include <vector>
39 
40 #include "absl/functional/any_invocable.h"
41 #include "absl/log/check.h"
42 #include "absl/memory/memory.h"
43 #include "absl/meta/type_traits.h"
44 #include "absl/strings/str_cat.h"
45 #include "absl/strings/string_view.h"
46 #include "absl/types/optional.h"
47 #include "absl/types/variant.h"
48 #include "gtest/gtest.h"
49 #include "src/core/config/config_vars.h"
50 #include "src/core/lib/channel/channel_args.h"
51 #include "src/core/lib/slice/slice.h"
52 #include "src/core/lib/slice/slice_internal.h"
53 #include "src/core/lib/surface/call_test_only.h"
54 #include "src/core/lib/surface/channel.h"
55 #include "src/core/util/bitset.h"
56 #include "src/core/util/debug_location.h"
57 #include "src/core/util/time.h"
58 #include "test/core/call/batch_builder.h"
59 #include "test/core/end2end/cq_verifier.h"
60 #include "test/core/event_engine/event_engine_test_utils.h"
61 #include "test/core/test_util/test_config.h"
62 
63 // Test feature flags.
64 #define FEATURE_MASK_DOES_NOT_SUPPORT_RETRY (1 << 0)
65 #define FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION (1 << 1)
66 // Feature mask supports call credentials with a minimum security level of
67 // GRPC_PRIVACY_AND_INTEGRITY.
68 #define FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS (1 << 2)
69 // Feature mask supports call credentials with a minimum security level of
70 // GRPC_SECURITY_NONE.
71 #define FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS_LEVEL_INSECURE (1 << 3)
72 #define FEATURE_MASK_SUPPORTS_REQUEST_PROXYING (1 << 4)
73 #define FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL (1 << 5)
74 #define FEATURE_MASK_IS_HTTP2 (1 << 6)
75 #define FEATURE_MASK_ENABLES_TRACES (1 << 7)
76 #define FEATURE_MASK_1BYTE_AT_A_TIME (1 << 8)
77 #define FEATURE_MASK_DOES_NOT_SUPPORT_WRITE_BUFFERING (1 << 9)
78 #define FEATURE_MASK_DOES_NOT_SUPPORT_CLIENT_HANDSHAKE_COMPLETE_FIRST (1 << 10)
79 #define FEATURE_MASK_IS_MINSTACK (1 << 11)
80 #define FEATURE_MASK_IS_SECURE (1 << 12)
81 #define FEATURE_MASK_DO_NOT_FUZZ (1 << 13)
82 // Exclude this fixture from experiment runs
83 #define FEATURE_MASK_EXCLUDE_FROM_EXPERIMENT_RUNS (1 << 14)
84 #define FEATURE_MASK_IS_CALL_V3 (1 << 15)
85 #define FEATURE_MASK_IS_LOCAL_TCP_CREDS (1 << 16)
86 
87 #define FAIL_AUTH_CHECK_SERVER_ARG_NAME "fail_auth_check"
88 
89 namespace grpc_core {
90 
91 extern bool g_is_fuzzing_core_e2e_tests;
92 
93 class CoreTestFixture {
94  public:
95   virtual ~CoreTestFixture() = default;
96 
97   virtual grpc_server* MakeServer(
98       const ChannelArgs& args, grpc_completion_queue* cq,
99       absl::AnyInvocable<void(grpc_server*)>& pre_server_start) = 0;
100   virtual grpc_channel* MakeClient(const ChannelArgs& args,
101                                    grpc_completion_queue* cq) = 0;
102 };
103 
104 Slice RandomSlice(size_t length);
105 Slice RandomBinarySlice(size_t length);
106 
107 struct CoreTestConfiguration {
108   // A descriptive name for this test fixture.
109   const char* name;
110 
111   // Which features are supported by this fixture. See feature flags above.
112   uint32_t feature_mask;
113 
114   // If the call host is setup by the fixture (for example, via the
115   // GRPC_SSL_TARGET_NAME_OVERRIDE_ARG channel arg), which value should the
116   // test expect to find in call_details.host
117   const char* overridden_call_host;
118 
119   std::function<std::unique_ptr<CoreTestFixture>(
120       const ChannelArgs& client_args, const ChannelArgs& server_args)>
121       create_fixture;
122 };
123 
124 // Base class for e2e tests.
125 //
126 // Initialization:
127 //
128 // At the start of a test, nothing is initialized. CoreConfiguration is reset,
129 // and there's certainly no server nor client.
130 // A test can then register whatever builders it wants into the
131 // CoreConfiguration and have them picked up. If it does not, it will get the
132 // default CoreConfiguration.
133 //
134 // The test may choose to then create a client and server with InitClient() and
135 // InitServer(). It does not matter which order they are called, nor whether one
136 // or both are called. It's necessary to call these if the test demands that
137 // non-empty channel args should be passed to either the client or server.
138 //
139 // If a test does not call InitClient() or InitServer(), then upon the first
140 // call to either NewClientCall() or NewServerCall(), the client and server will
141 // be instantiated - this saves substantial boilerplate in the most common case
142 // for our tests.
143 //
144 // Notes:
145 // - older compilers fail matching absl::string_view with some gmock matchers on
146 //   older compilers, and it's tremendously convenient to be able to do so. So
147 //   we use std::string for return types here - performance isn't particularly
148 //   important, so an extra copy is fine.
149 class CoreEnd2endTest : public ::testing::Test {
150  public:
TestInfrastructureSetParam(const CoreTestConfiguration * param)151   void TestInfrastructureSetParam(const CoreTestConfiguration* param) {
152     param_ = param;
153   }
GetParam()154   const CoreTestConfiguration* GetParam() { return param_; }
155 
156   void SetUp() override;
157   void TearDown() override;
158   virtual void RunTest() = 0;
159 
SetCqVerifierStepFn(absl::AnyInvocable<void (grpc_event_engine::experimental::EventEngine::Duration)const> step_fn)160   void SetCqVerifierStepFn(
161       absl::AnyInvocable<
162           void(grpc_event_engine::experimental::EventEngine::Duration) const>
163           step_fn) {
164     step_fn_ = std::move(step_fn);
165   }
SetQuiesceEventEngine(absl::AnyInvocable<void (std::shared_ptr<grpc_event_engine::experimental::EventEngine> &&)> quiesce_event_engine)166   void SetQuiesceEventEngine(
167       absl::AnyInvocable<
168           void(std::shared_ptr<grpc_event_engine::experimental::EventEngine>&&)>
169           quiesce_event_engine) {
170     quiesce_event_engine_ = std::move(quiesce_event_engine);
171   }
172 
173   class Call;
174   struct RegisteredCall {
175     void* p;
176   };
177 
178   // Safe notification to use for core e2e tests.
179   // Since when we're fuzzing we don't run background threads, the normal
180   // Notification type isn't safe to wait on (for some background timer to fire
181   // for instance...), consequently we need to use this.
182   class TestNotification {
183    public:
TestNotification(CoreEnd2endTest * test)184     explicit TestNotification(CoreEnd2endTest* test) : test_(test) {}
185 
WaitForNotificationWithTimeout(absl::Duration wait_time)186     void WaitForNotificationWithTimeout(absl::Duration wait_time) {
187       if (g_is_fuzzing_core_e2e_tests) {
188         Timestamp end = Timestamp::Now() + Duration::NanosecondsRoundUp(
189                                                ToInt64Nanoseconds(wait_time));
190         while (true) {
191           if (base_.HasBeenNotified()) return;
192           auto now = Timestamp::Now();
193           if (now >= end) return;
194           test_->step_fn_(now - end);
195         }
196       } else {
197         base_.WaitForNotificationWithTimeout(wait_time);
198       }
199     }
200 
Notify()201     void Notify() { base_.Notify(); }
202 
203    private:
204     Notification base_;
205     CoreEnd2endTest* const test_;
206   };
207 
208   // CallBuilder - results in a call to either grpc_channel_create_call or
209   // grpc_channel_create_registered_call.
210   // Affords a fluent interface to specify optional arguments.
211   class ClientCallBuilder {
212    public:
ClientCallBuilder(CoreEnd2endTest & test,std::string method)213     ClientCallBuilder(CoreEnd2endTest& test, std::string method)
214         : test_(test),
215           call_selector_(UnregisteredCall{std::move(method), absl::nullopt}) {}
ClientCallBuilder(CoreEnd2endTest & test,RegisteredCall registered_call)216     ClientCallBuilder(CoreEnd2endTest& test, RegisteredCall registered_call)
217         : test_(test), call_selector_(registered_call.p) {}
218 
219     // Specify the host (otherwise nullptr is passed)
Host(std::string host)220     ClientCallBuilder& Host(std::string host) {
221       absl::get<UnregisteredCall>(call_selector_).host = std::move(host);
222       return *this;
223     }
224     // Specify the timeout (otherwise gpr_inf_future is passed) - this time is
225     // scaled according to the test environment.
Timeout(Duration timeout)226     ClientCallBuilder& Timeout(Duration timeout) {
227       if (timeout == Duration::Infinity()) {
228         deadline_ = gpr_inf_future(GPR_CLOCK_REALTIME);
229         return *this;
230       }
231       deadline_ = grpc_timeout_milliseconds_to_deadline(timeout.millis());
232       return *this;
233     }
234     // Finally create the call.
235     Call Create();
236 
237    private:
238     CoreEnd2endTest& test_;
239     struct UnregisteredCall {
240       std::string method;
241       absl::optional<std::string> host;
242     };
243     absl::variant<void*, UnregisteredCall> call_selector_;
244     grpc_call* parent_call_ = nullptr;
245     uint32_t propagation_mask_ = GRPC_PROPAGATE_DEFAULTS;
246     gpr_timespec deadline_ = gpr_inf_future(GPR_CLOCK_REALTIME);
247   };
248 
249   // Wrapper around a grpc_call.
250   // Instantiated by ClientCallBuilder via NewClientCall for client calls.
251   // Wrapped by IncomingCall for server calls.
252   class Call {
253    public:
Call(grpc_call * call,CoreEnd2endTest * test)254     Call(grpc_call* call, CoreEnd2endTest* test) : call_(call), test_(test) {}
255     Call(const Call&) = delete;
256     Call& operator=(const Call&) = delete;
Call(Call && other)257     Call(Call&& other) noexcept
258         : call_(std::exchange(other.call_, nullptr)),
259           test_(std::exchange(other.test_, nullptr)) {}
~Call()260     ~Call() {
261       if (call_ != nullptr) grpc_call_unref(call_);
262     }
263     // Construct a batch with a tag - upon destruction of the BatchBuilder the
264     // operation will occur.
NewBatch(int tag)265     BatchBuilder NewBatch(int tag) {
266       return BatchBuilder(call_, &test_->cq_verifier(), tag);
267     }
268     // Cancel the call
Cancel()269     void Cancel() { grpc_call_cancel(call_, nullptr); }
CancelWithStatus(grpc_status_code status,const char * message)270     void CancelWithStatus(grpc_status_code status, const char* message) {
271       grpc_call_cancel_with_status(call_, status, message, nullptr);
272     }
273     // Access the peer structure (returns a string that can be matched, etc) -
274     // or nullopt if grpc_call_get_peer returns nullptr.
GetPeer()275     absl::optional<std::string> GetPeer() {
276       char* peer = grpc_call_get_peer(call_);
277       if (peer == nullptr) return absl::nullopt;
278       std::string result(peer);
279       gpr_free(peer);
280       return result;
281     }
282 
283     // Set call credentials.
284     // Takes ownership of creds.
SetCredentials(grpc_call_credentials * creds)285     void SetCredentials(grpc_call_credentials* creds) {
286       EXPECT_EQ(grpc_call_set_credentials(call_, creds), GRPC_CALL_OK);
287       grpc_call_credentials_release(creds);
288     }
289 
290     // Retrieve the auth context.
291     std::unique_ptr<grpc_auth_context, void (*)(grpc_auth_context*)>
GetAuthContext()292     GetAuthContext() {
293       return std::unique_ptr<grpc_auth_context, void (*)(grpc_auth_context*)>(
294           grpc_call_auth_context(call_), grpc_auth_context_release);
295     }
296 
call_ptr()297     grpc_call** call_ptr() { return &call_; }
c_call()298     grpc_call* c_call() const { return call_; }
299 
300    private:
301     grpc_call* call_ = nullptr;
302     CoreEnd2endTest* test_;
303   };
304 
305   // Wrapper around a server call.
306   class IncomingCall {
307    public:
308     IncomingCall(CoreEnd2endTest& test, int tag);
309     IncomingCall(CoreEnd2endTest& test, void* method, IncomingMessage* message,
310                  int tag);
311     IncomingCall(const IncomingCall&) = delete;
312     IncomingCall& operator=(const IncomingCall&) = delete;
313     IncomingCall(IncomingCall&&) noexcept = default;
314 
315     // Construct a batch with a tag - upon destruction of the BatchBuilder the
316     // operation will occur. Must have received the call first!
NewBatch(int tag)317     BatchBuilder NewBatch(int tag) { return impl_->call.NewBatch(tag); }
Cancel()318     void Cancel() { impl_->call.Cancel(); }
319 
320     // Return the method being called.
method()321     std::string method() const {
322       return std::string(StringViewFromSlice(impl_->call_details.method));
323     }
324 
325     // Return the host being called.
host()326     std::string host() const {
327       return std::string(StringViewFromSlice(impl_->call_details.host));
328     }
329 
330     // Return some initial metadata.
331     absl::optional<std::string> GetInitialMetadata(absl::string_view key) const;
332 
333     // Return the peer address.
GetPeer()334     absl::optional<std::string> GetPeer() { return impl_->call.GetPeer(); }
335 
336     // Return the auth context.
337     std::unique_ptr<grpc_auth_context, void (*)(grpc_auth_context*)>
GetAuthContext()338     GetAuthContext() {
339       return impl_->call.GetAuthContext();
340     }
341 
342     // Return the underlying C call object
c_call()343     grpc_call* c_call() { return impl_->call.c_call(); }
344 
345     // Return the encodings accepted by the peer.
GetEncodingsAcceptedByPeer()346     BitSet<GRPC_COMPRESS_ALGORITHMS_COUNT> GetEncodingsAcceptedByPeer() {
347       return BitSet<GRPC_COMPRESS_ALGORITHMS_COUNT>::FromInt(
348           grpc_call_test_only_get_encodings_accepted_by_peer(c_call()));
349     }
350 
351    private:
352     struct Impl {
ImplImpl353       explicit Impl(CoreEnd2endTest* test) : call(nullptr, test) {
354         grpc_call_details_init(&call_details);
355         grpc_metadata_array_init(&request_metadata);
356       }
~ImplImpl357       ~Impl() {
358         grpc_call_details_destroy(&call_details);
359         grpc_metadata_array_destroy(&request_metadata);
360       }
361       Call call;
362       grpc_call_details call_details;
363       grpc_metadata_array request_metadata;
364     };
365     std::unique_ptr<Impl> impl_;
366   };
367 
368   class ServerRegisteredMethod {
369    public:
370     ServerRegisteredMethod(
371         CoreEnd2endTest* test, absl::string_view name,
372         grpc_server_register_method_payload_handling payload_handling);
373 
handle()374     void* handle() { return *handle_; }
375 
376    private:
377     std::shared_ptr<void*> handle_ = std::make_shared<void*>(nullptr);
378   };
379 
RegisterServerMethod(absl::string_view name,grpc_server_register_method_payload_handling payload_handling)380   ServerRegisteredMethod RegisterServerMethod(
381       absl::string_view name,
382       grpc_server_register_method_payload_handling payload_handling) {
383     return ServerRegisteredMethod(this, name, payload_handling);
384   }
385 
386   // Begin construction of a client call.
NewClientCall(std::string method)387   ClientCallBuilder NewClientCall(std::string method) {
388     return ClientCallBuilder(*this, std::move(method));
389   }
NewClientCall(RegisteredCall registered_method)390   ClientCallBuilder NewClientCall(RegisteredCall registered_method) {
391     return ClientCallBuilder(*this, registered_method);
392   }
393   // Request a call on the server - notifies `tag` when complete.
RequestCall(int tag)394   IncomingCall RequestCall(int tag) { return IncomingCall(*this, tag); }
395   // Request a call on the server - notifies `tag` when complete.
RequestRegisteredCall(ServerRegisteredMethod method,int tag)396   IncomingCall RequestRegisteredCall(ServerRegisteredMethod method, int tag) {
397     return IncomingCall(*this, method.handle(), nullptr, tag);
398   }
RequestRegisteredCall(ServerRegisteredMethod method,IncomingMessage * message,int tag)399   IncomingCall RequestRegisteredCall(ServerRegisteredMethod method,
400                                      IncomingMessage* message, int tag) {
401     return IncomingCall(*this, method.handle(), message, tag);
402   }
403 
404   // Pull in CqVerifier types for ergonomics
405   using ExpectedResult = CqVerifier::ExpectedResult;
406   using Maybe = CqVerifier::Maybe;
407   using PerformAction = CqVerifier::PerformAction;
408   using MaybePerformAction = CqVerifier::MaybePerformAction;
409   using AnyStatus = CqVerifier::AnyStatus;
410   // Expect a tag with some result.
411   void Expect(int tag, ExpectedResult result, SourceLocation whence = {}) {
412     expectations_++;
413     cq_verifier().Expect(CqVerifier::tag(tag), std::move(result), whence);
414   }
415   // Step the system until expectations are met or until timeout is reached.
416   // If there are no expectations logged, then step for 1 second and verify that
417   // no events occur.
418   void Step(absl::optional<Duration> timeout = absl::nullopt,
419             SourceLocation whence = {}) {
420     if (expectations_ == 0) {
421       cq_verifier().VerifyEmpty(timeout.value_or(Duration::Seconds(1)), whence);
422       return;
423     }
424     expectations_ = 0;
425     cq_verifier().Verify(
426         timeout.value_or(g_is_fuzzing_core_e2e_tests ? Duration::Minutes(10)
427                                                      : Duration::Seconds(10)),
428         whence);
429   }
430 
431   // Initialize the client.
432   // If called, then InitServer must be called to create a server (otherwise one
433   // will be provided).
InitClient(const ChannelArgs & args)434   void InitClient(const ChannelArgs& args) {
435     initialized_ = true;
436     if (client_ != nullptr) ShutdownAndDestroyClient();
437     auto& f = fixture();
438     client_ = f.MakeClient(args, cq_);
439     CHECK_NE(client_, nullptr);
440   }
441   // Initialize the server.
442   // If called, then InitClient must be called to create a client (otherwise one
443   // will be provided).
InitServer(const ChannelArgs & args)444   void InitServer(const ChannelArgs& args) {
445     initialized_ = true;
446     if (server_ != nullptr) ShutdownAndDestroyServer();
447     auto& f = fixture();
448     server_ = f.MakeServer(args, cq_, pre_server_start_);
449     CHECK_NE(server_, nullptr);
450   }
451   // Remove the client.
ShutdownAndDestroyClient()452   void ShutdownAndDestroyClient() {
453     if (client_ == nullptr) return;
454     grpc_channel_destroy(client_);
455     client_ = nullptr;
456   }
457   // Shutdown the server; notify tag on completion.
ShutdownServerAndNotify(int tag)458   void ShutdownServerAndNotify(int tag) {
459     grpc_server_shutdown_and_notify(server_, cq_, CqVerifier::tag(tag));
460   }
461   // Destroy the server.
DestroyServer()462   void DestroyServer() {
463     if (server_ == nullptr) return;
464     grpc_server_destroy(server_);
465     server_ = nullptr;
466   }
467   // Shutdown then destroy the server.
ShutdownAndDestroyServer()468   void ShutdownAndDestroyServer() {
469     if (server_ == nullptr) return;
470     ShutdownServerAndNotify(-1);
471     Expect(-1, AnyStatus{});
472     Step();
473     DestroyServer();
474   }
475   // Cancel any calls on the server.
CancelAllCallsOnServer()476   void CancelAllCallsOnServer() { grpc_server_cancel_all_calls(server_); }
477   // Ping the server from the client
PingServerFromClient(int tag)478   void PingServerFromClient(int tag) {
479     grpc_channel_ping(client_, cq_, CqVerifier::tag(tag), nullptr);
480   }
481   // Register a call on the client, return its handle.
RegisterCallOnClient(const char * method,const char * host)482   RegisteredCall RegisterCallOnClient(const char* method, const char* host) {
483     ForceInitialized();
484     return RegisteredCall{
485         grpc_channel_register_call(client_, method, host, nullptr)};
486   }
487 
488   // Return the current connectivity state of the client.
CheckConnectivityState(bool try_to_connect)489   grpc_connectivity_state CheckConnectivityState(bool try_to_connect) {
490     return grpc_channel_check_connectivity_state(client_, try_to_connect);
491   }
492 
493   // Watch the connectivity state of the client.
WatchConnectivityState(grpc_connectivity_state last_observed_state,Duration deadline,int tag)494   void WatchConnectivityState(grpc_connectivity_state last_observed_state,
495                               Duration deadline, int tag) {
496     grpc_channel_watch_connectivity_state(
497         client_, last_observed_state,
498         grpc_timeout_milliseconds_to_deadline(deadline.millis()), cq_,
499         CqVerifier::tag(tag));
500   }
501 
502   // Return the client channel.
client()503   grpc_channel* client() {
504     ForceInitialized();
505     return client_;
506   }
507 
508   // Return the server channel.
server()509   grpc_server* server() {
510     ForceInitialized();
511     return server_;
512   }
513 
cq()514   grpc_completion_queue* cq() {
515     ForceInitialized();
516     return cq_;
517   }
518 
519   // Given a duration, return a timestamp that is that duration in the future -
520   // with dilation according to test environment (eg sanitizers)
TimestampAfterDuration(Duration duration)521   Timestamp TimestampAfterDuration(Duration duration) {
522     return Timestamp::FromTimespecRoundUp(
523         grpc_timeout_milliseconds_to_deadline(duration.millis()));
524   }
525 
SetPostGrpcInitFunc(absl::AnyInvocable<void ()> fn)526   void SetPostGrpcInitFunc(absl::AnyInvocable<void()> fn) {
527     CHECK(fixture_ == nullptr);
528     post_grpc_init_func_ = std::move(fn);
529   }
530 
531  private:
532   void ForceInitialized();
533 
fixture()534   CoreTestFixture& fixture() {
535     if (fixture_ == nullptr) {
536       grpc_init();
537       post_grpc_init_func_();
538       cq_ = grpc_completion_queue_create_for_next(nullptr);
539       fixture_ = GetParam()->create_fixture(ChannelArgs(), ChannelArgs());
540     }
541     return *fixture_;
542   }
543 
cq_verifier()544   CqVerifier& cq_verifier() {
545     if (cq_verifier_ == nullptr) {
546       fixture();  // ensure cq_ present
547       cq_verifier_ = absl::make_unique<CqVerifier>(
548           cq_,
549           g_is_fuzzing_core_e2e_tests ? CqVerifier::FailUsingGprCrashWithStdio
550                                       : CqVerifier::FailUsingGprCrash,
551           step_fn_ == nullptr
552               ? nullptr
553               : absl::AnyInvocable<void(
554                     grpc_event_engine::experimental::EventEngine::Duration)
555                                        const>(
556                     [this](
557                         grpc_event_engine::experimental::EventEngine::Duration
558                             d) { step_fn_(d); }));
559     }
560     return *cq_verifier_;
561   }
562 
563   const CoreTestConfiguration* param_ = nullptr;
564   std::unique_ptr<CoreTestFixture> fixture_;
565   grpc_completion_queue* cq_ = nullptr;
566   grpc_server* server_ = nullptr;
567   grpc_channel* client_ = nullptr;
568   std::unique_ptr<CqVerifier> cq_verifier_;
569   absl::AnyInvocable<void(grpc_server*)> pre_server_start_ = [](grpc_server*) {
570   };
571   int expectations_ = 0;
572   bool initialized_ = false;
573   absl::AnyInvocable<void()> post_grpc_init_func_ = []() {};
574   absl::AnyInvocable<void(
575       grpc_event_engine::experimental::EventEngine::Duration) const>
576       step_fn_ = nullptr;
577   absl::AnyInvocable<void(
578       std::shared_ptr<grpc_event_engine::experimental::EventEngine>&&)>
579       quiesce_event_engine_ =
580           grpc_event_engine::experimental::WaitForSingleOwner;
581 };
582 
583 // Define names for additional test suites.
584 // These make no changes to the actual class, but define new names to register
585 // tests against. Each new name gets a differing set of configurations in
586 // end2end_test_main.cc to customize the set of fixtures the tests run against.
587 
588 // Test suite for tests that rely on a secure transport
589 class SecureEnd2endTest : public CoreEnd2endTest {};
590 // Test suite for tests that send rather large messages/metadata
591 class CoreLargeSendTest : public CoreEnd2endTest {};
592 // Test suite for tests that need a client channel
593 class CoreClientChannelTest : public CoreEnd2endTest {};
594 // Test suite for tests that require deadline handling
595 class CoreDeadlineTest : public CoreEnd2endTest {};
596 // Test suite for tests that require deadline handling
597 class CoreDeadlineSingleHopTest : public CoreEnd2endTest {};
598 // Test suite for http2 tests that only work over a single hop (unproxyable)
599 class Http2SingleHopTest : public CoreEnd2endTest {};
600 // Test suite for fullstack single hop http2 tests (require client channel)
601 class Http2FullstackSingleHopTest : public CoreEnd2endTest {};
602 // Test suite for tests that require retry features
603 class RetryTest : public CoreEnd2endTest {};
604 // Test suite for write buffering
605 class WriteBufferingTest : public CoreEnd2endTest {};
606 // Test suite for http2 tests
607 class Http2Test : public CoreEnd2endTest {};
608 // Test suite for http2 tests that require retry features
609 class RetryHttp2Test : public CoreEnd2endTest {};
610 // Test suite for tests that require resource quota
611 class ResourceQuotaTest : public CoreEnd2endTest {};
612 // Test suite for tests that require a transport that supports secure call
613 // credentials
614 class PerCallCredsTest : public CoreEnd2endTest {};
615 // Test suite for tests that require a transport that supports insecure call
616 // credentials
617 class PerCallCredsOnInsecureTest : public CoreEnd2endTest {};
618 // Test suite for tests that verify lack of logging in particular situations
619 class NoLoggingTest : public CoreEnd2endTest {};
620 // Test suite for tests that verify proxy authentication
621 class ProxyAuthTest : public CoreEnd2endTest {};
622 
623 using MakeTestFn = absl::AnyInvocable<CoreEnd2endTest*(
624     const CoreTestConfiguration* config) const>;
625 
626 class CoreEnd2endTestRegistry {
627  public:
628   CoreEnd2endTestRegistry(const CoreEnd2endTestRegistry&) = delete;
629   CoreEnd2endTestRegistry& operator=(const CoreEnd2endTestRegistry&) = delete;
630 
Get()631   static CoreEnd2endTestRegistry& Get() {
632     static CoreEnd2endTestRegistry* singleton = new CoreEnd2endTestRegistry;
633     return *singleton;
634   }
635 
636   struct Test {
637     absl::string_view suite;
638     absl::string_view name;
639     const CoreTestConfiguration* config;
640     const MakeTestFn& make_test;
641   };
642 
643   void RegisterTest(absl::string_view suite, absl::string_view name,
644                     MakeTestFn make_test, SourceLocation where = {});
645 
646   void RegisterSuite(absl::string_view suite,
647                      std::vector<const CoreTestConfiguration*> configs,
648                      SourceLocation where);
649 
650   std::vector<Test> AllTests();
651 
652   // Enforce passing a type so that we can check it exists (saves typos)
653   template <typename T>
654   absl::void_t<T> RegisterSuiteT(
655       absl::string_view suite,
656       std::vector<const CoreTestConfiguration*> configs,
657       SourceLocation where = {}) {
658     return RegisterSuite(suite, std::move(configs), where);
659   }
660 
661  private:
662   CoreEnd2endTestRegistry() = default;
663 
664   std::map<absl::string_view, std::vector<const CoreTestConfiguration*>>
665       suites_;
666   std::map<absl::string_view, std::map<absl::string_view, MakeTestFn>>
667       tests_by_suite_;
668 };
669 
670 }  // namespace grpc_core
671 
672 // If this test fixture is being run under minstack, skip the test.
673 #define SKIP_IF_MINSTACK()                                 \
674   if (GetParam()->feature_mask & FEATURE_MASK_IS_MINSTACK) \
675   GTEST_SKIP() << "Skipping test for minstack"
676 
677 #define SKIP_IF_FUZZING() \
678   if (g_is_fuzzing_core_e2e_tests) GTEST_SKIP() << "Skipping test for fuzzing"
679 
680 #define SKIP_IF_V3()                                        \
681   if (GetParam()->feature_mask & FEATURE_MASK_IS_CALL_V3) { \
682     GTEST_SKIP() << "Disabled for initial v3 testing";      \
683   }
684 
685 #define SKIP_IF_LOCAL_TCP_CREDS()                                   \
686   if (GetParam()->feature_mask & FEATURE_MASK_IS_LOCAL_TCP_CREDS) { \
687     GTEST_SKIP() << "Disabled for Local TCP Connection";            \
688   }
689 
690 #define CORE_END2END_TEST(suite, name)                                       \
691   class CoreEnd2endTest_##suite##_##name : public grpc_core::suite {         \
692    public:                                                                   \
693     CoreEnd2endTest_##suite##_##name() {}                                    \
694     void TestBody() override {                                               \
695       if ((GetParam()->feature_mask & FEATURE_MASK_IS_CALL_V3) &&            \
696           (grpc_core::ConfigVars::Get().PollStrategy() == "poll")) {         \
697         GTEST_SKIP() << "call-v3 not supported with poll poller";            \
698       }                                                                      \
699       RunTest();                                                             \
700     }                                                                        \
701     void RunTest() override;                                                 \
702                                                                              \
703    private:                                                                  \
704     static grpc_core::CoreEnd2endTest* Run(                                  \
705         const grpc_core::CoreTestConfiguration* config) {                    \
706       auto* test = new CoreEnd2endTest_##suite##_##name;                     \
707       test->TestInfrastructureSetParam(config);                              \
708       return test;                                                           \
709     }                                                                        \
710     static int registered_;                                                  \
711   };                                                                         \
712   int CoreEnd2endTest_##suite##_##name::registered_ =                        \
713       (grpc_core::CoreEnd2endTestRegistry::Get().RegisterTest(#suite, #name, \
714                                                               &Run),         \
715        0);                                                                   \
716   void CoreEnd2endTest_##suite##_##name::RunTest()
717 
718 #define CORE_END2END_TEST_SUITE(suite, configs)              \
719   static int registered_##suite =                            \
720       (grpc_core::CoreEnd2endTestRegistry::Get()             \
721            .template RegisterSuiteT<suite>(#suite, configs), \
722        0)
723 
724 #endif  // GRPC_TEST_CORE_END2END_END2END_TESTS_H
725