1 // 2 // 3 // Copyright 2015 gRPC authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 // 17 // 18 19 #ifndef GRPC_TEST_CORE_END2END_END2END_TESTS_H 20 #define GRPC_TEST_CORE_END2END_END2END_TESTS_H 21 22 #include <stdint.h> 23 #include <stdio.h> 24 25 #include <algorithm> 26 #include <functional> 27 #include <initializer_list> 28 #include <map> 29 #include <memory> 30 #include <string> 31 #include <utility> 32 #include <vector> 33 34 #include "absl/functional/any_invocable.h" 35 #include "absl/memory/memory.h" 36 #include "absl/meta/type_traits.h" 37 #include "absl/strings/str_cat.h" 38 #include "absl/strings/string_view.h" 39 #include "absl/types/optional.h" 40 #include "absl/types/variant.h" 41 #include "gtest/gtest.h" 42 43 #include <grpc/byte_buffer.h> 44 #include <grpc/compression.h> 45 #include <grpc/event_engine/event_engine.h> 46 #include <grpc/grpc.h> 47 #include <grpc/grpc_security.h> 48 #include <grpc/impl/propagation_bits.h> 49 #include <grpc/status.h> 50 #include <grpc/support/alloc.h> 51 #include <grpc/support/log.h> 52 #include <grpc/support/time.h> 53 54 #include "src/core/lib/channel/channel_args.h" 55 #include "src/core/lib/gprpp/bitset.h" 56 #include "src/core/lib/gprpp/debug_location.h" 57 #include "src/core/lib/gprpp/time.h" 58 #include "src/core/lib/slice/slice.h" 59 #include "src/core/lib/slice/slice_internal.h" 60 #include "src/core/lib/surface/call_test_only.h" 61 #include "src/core/lib/surface/channel.h" 62 #include "test/core/end2end/cq_verifier.h" 63 #include "test/core/event_engine/event_engine_test_utils.h" 64 #include "test/core/util/test_config.h" 65 66 // Test feature flags. 67 #define FEATURE_MASK_DOES_NOT_SUPPORT_RETRY (1 << 0) 68 #define FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION (1 << 1) 69 // Feature mask supports call credentials with a minimum security level of 70 // GRPC_PRIVACY_AND_INTEGRITY. 71 #define FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS (1 << 2) 72 // Feature mask supports call credentials with a minimum security level of 73 // GRPC_SECURTITY_NONE. 74 #define FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS_LEVEL_INSECURE (1 << 3) 75 #define FEATURE_MASK_SUPPORTS_REQUEST_PROXYING (1 << 4) 76 #define FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL (1 << 5) 77 #define FEATURE_MASK_IS_HTTP2 (1 << 6) 78 #define FEATURE_MASK_ENABLES_TRACES (1 << 7) 79 #define FEATURE_MASK_1BYTE_AT_A_TIME (1 << 8) 80 #define FEATURE_MASK_DOES_NOT_SUPPORT_WRITE_BUFFERING (1 << 9) 81 #define FEATURE_MASK_DOES_NOT_SUPPORT_CLIENT_HANDSHAKE_COMPLETE_FIRST (1 << 10) 82 #define FEATURE_MASK_IS_MINSTACK (1 << 11) 83 #define FEATURE_MASK_IS_SECURE (1 << 12) 84 #define FEATURE_MASK_DO_NOT_FUZZ (1 << 13) 85 // Exclude this fixture from experiment runs 86 #define FEATURE_MASK_EXCLUDE_FROM_EXPERIMENT_RUNS (1 << 14) 87 88 #define FAIL_AUTH_CHECK_SERVER_ARG_NAME "fail_auth_check" 89 90 namespace grpc_core { 91 92 extern bool g_is_fuzzing_core_e2e_tests; 93 94 class CoreTestFixture { 95 public: 96 virtual ~CoreTestFixture() = default; 97 98 virtual grpc_server* MakeServer( 99 const ChannelArgs& args, grpc_completion_queue* cq, 100 absl::AnyInvocable<void(grpc_server*)>& pre_server_start) = 0; 101 virtual grpc_channel* MakeClient(const ChannelArgs& args, 102 grpc_completion_queue* cq) = 0; 103 }; 104 105 Slice RandomSlice(size_t length); 106 Slice RandomBinarySlice(size_t length); 107 using ByteBufferUniquePtr = 108 std::unique_ptr<grpc_byte_buffer, void (*)(grpc_byte_buffer*)>; 109 ByteBufferUniquePtr ByteBufferFromSlice(Slice slice); 110 111 struct CoreTestConfiguration { 112 // A descriptive name for this test fixture. 113 const char* name; 114 115 // Which features are supported by this fixture. See feature flags above. 116 uint32_t feature_mask; 117 118 // If the call host is setup by the fixture (for example, via the 119 // GRPC_SSL_TARGET_NAME_OVERRIDE_ARG channel arg), which value should the 120 // test expect to find in call_details.host 121 const char* overridden_call_host; 122 123 std::function<std::unique_ptr<CoreTestFixture>( 124 const ChannelArgs& client_args, const ChannelArgs& server_args)> 125 create_fixture; 126 }; 127 128 // Base class for e2e tests. 129 // 130 // Initialization: 131 // 132 // At the start of a test, nothing is initialized. CoreConfiguration is reset, 133 // and there's certainly no server nor client. 134 // A test can then register whatever builders it wants into the 135 // CoreConfiguration and have them picked up. If it does not, it will get the 136 // default CoreConfiguration. 137 // 138 // The test may choose to then create a client and server with InitClient() and 139 // InitServer(). It does not matter which order they are called, nor whether one 140 // or both are called. It's necessary to call these if the test demands that 141 // non-empty channel args should be passed to either the client or server. 142 // 143 // If a test does not call InitClient() or InitServer(), then upon the first 144 // call to either NewClientCall() or NewServerCall(), the client and server will 145 // be instantiated - this saves substantial boilerplate in the most common case 146 // for our tests. 147 // 148 // Notes: 149 // - older compilers fail matching absl::string_view with some gmock matchers on 150 // older compilers, and it's tremendously convenient to be able to do so. So 151 // we use std::string for return types here - performance isn't particularly 152 // important, so an extra copy is fine. 153 class CoreEnd2endTest : public ::testing::Test { 154 public: TestInfrastructureSetParam(const CoreTestConfiguration * param)155 void TestInfrastructureSetParam(const CoreTestConfiguration* param) { 156 param_ = param; 157 } GetParam()158 const CoreTestConfiguration* GetParam() { return param_; } 159 160 void SetUp() override; 161 void TearDown() override; 162 virtual void RunTest() = 0; 163 SetCqVerifierStepFn(absl::AnyInvocable<void (grpc_event_engine::experimental::EventEngine::Duration)const> step_fn)164 void SetCqVerifierStepFn( 165 absl::AnyInvocable< 166 void(grpc_event_engine::experimental::EventEngine::Duration) const> 167 step_fn) { 168 step_fn_ = std::move(step_fn); 169 } SetQuiesceEventEngine(absl::AnyInvocable<void (std::shared_ptr<grpc_event_engine::experimental::EventEngine> &&)> quiesce_event_engine)170 void SetQuiesceEventEngine( 171 absl::AnyInvocable< 172 void(std::shared_ptr<grpc_event_engine::experimental::EventEngine>&&)> 173 quiesce_event_engine) { 174 quiesce_event_engine_ = std::move(quiesce_event_engine); 175 } 176 177 class Call; 178 struct RegisteredCall { 179 void* p; 180 }; 181 182 // CallBuilder - results in a call to either grpc_channel_create_call or 183 // grpc_channel_create_registered_call. 184 // Affords a fluent interface to specify optional arguments. 185 class ClientCallBuilder { 186 public: ClientCallBuilder(CoreEnd2endTest & test,std::string method)187 ClientCallBuilder(CoreEnd2endTest& test, std::string method) 188 : test_(test), 189 call_selector_(UnregisteredCall{std::move(method), absl::nullopt}) {} ClientCallBuilder(CoreEnd2endTest & test,RegisteredCall registered_call)190 ClientCallBuilder(CoreEnd2endTest& test, RegisteredCall registered_call) 191 : test_(test), call_selector_(registered_call.p) {} 192 193 // Specify the host (otherwise nullptr is passed) Host(std::string host)194 ClientCallBuilder& Host(std::string host) { 195 absl::get<UnregisteredCall>(call_selector_).host = std::move(host); 196 return *this; 197 } 198 // Specify the timeout (otherwise gpr_inf_future is passed) - this time is 199 // scaled according to the test environment. Timeout(Duration timeout)200 ClientCallBuilder& Timeout(Duration timeout) { 201 if (timeout == Duration::Infinity()) { 202 deadline_ = gpr_inf_future(GPR_CLOCK_REALTIME); 203 return *this; 204 } 205 deadline_ = grpc_timeout_milliseconds_to_deadline(timeout.millis()); 206 return *this; 207 } 208 // Finally create the call. 209 Call Create(); 210 211 private: 212 CoreEnd2endTest& test_; 213 struct UnregisteredCall { 214 std::string method; 215 absl::optional<std::string> host; 216 }; 217 absl::variant<void*, UnregisteredCall> call_selector_; 218 grpc_call* parent_call_ = nullptr; 219 uint32_t propagation_mask_ = GRPC_PROPAGATE_DEFAULTS; 220 gpr_timespec deadline_ = gpr_inf_future(GPR_CLOCK_REALTIME); 221 }; 222 223 // Receiving container for incoming metadata. 224 class IncomingMetadata final : public CqVerifier::SuccessfulStateString { 225 public: 226 IncomingMetadata() = default; ~IncomingMetadata()227 ~IncomingMetadata() { 228 if (metadata_ != nullptr) grpc_metadata_array_destroy(metadata_.get()); 229 } 230 231 // Lookup a metadata value by key. 232 absl::optional<std::string> Get(absl::string_view key) const; 233 234 // Make a GRPC_RECV_INITIAL_METADATA op - intended for the framework, not 235 // for tests. 236 grpc_op MakeOp(); 237 238 std::string GetSuccessfulStateString() override; 239 240 private: 241 std::unique_ptr<grpc_metadata_array> metadata_ = 242 std::make_unique<grpc_metadata_array>( 243 grpc_metadata_array{0, 0, nullptr}); 244 }; 245 246 class IncomingCall; 247 248 // Receiving container for one incoming message. 249 class IncomingMessage final : public CqVerifier::SuccessfulStateString { 250 public: 251 IncomingMessage() = default; 252 IncomingMessage(const IncomingMessage&) = delete; 253 IncomingMessage& operator=(const IncomingMessage&) = delete; ~IncomingMessage()254 ~IncomingMessage() { 255 if (payload_ != nullptr) grpc_byte_buffer_destroy(payload_); 256 } 257 258 // Get the payload of the message - concatenated together into a string for 259 // easy verification. 260 std::string payload() const; 261 // Check if the message is the end of the stream. is_end_of_stream()262 bool is_end_of_stream() const { return payload_ == nullptr; } 263 // Get the type of the message. byte_buffer_type()264 grpc_byte_buffer_type byte_buffer_type() const { return payload_->type; } 265 // Get the compression algorithm used for the message. compression()266 grpc_compression_algorithm compression() const { 267 return payload_->data.raw.compression; 268 } 269 std::string GetSuccessfulStateString() override; 270 271 // Make a GRPC_OP_RECV_MESSAGE op - intended for the framework, not for 272 // tests. 273 grpc_op MakeOp(); 274 275 private: 276 friend class IncomingCall; 277 grpc_byte_buffer* payload_ = nullptr; 278 }; 279 280 // Receiving container for incoming status on the client from the server. 281 class IncomingStatusOnClient final 282 : public CqVerifier::SuccessfulStateString { 283 public: 284 IncomingStatusOnClient() = default; 285 IncomingStatusOnClient(const IncomingStatusOnClient&) = delete; 286 IncomingStatusOnClient& operator=(const IncomingStatusOnClient&) = delete; 287 IncomingStatusOnClient(IncomingStatusOnClient&& other) noexcept = default; 288 IncomingStatusOnClient& operator=(IncomingStatusOnClient&& other) noexcept = 289 default; ~IncomingStatusOnClient()290 ~IncomingStatusOnClient() { 291 if (data_ != nullptr) { 292 grpc_metadata_array_destroy(&data_->trailing_metadata); 293 gpr_free(const_cast<char*>(data_->error_string)); 294 } 295 } 296 297 // Get the status code. status()298 grpc_status_code status() const { return data_->status; } 299 // Get the status details. message()300 std::string message() const { 301 return std::string(data_->status_details.as_string_view()); 302 } 303 // Get the error string. error_string()304 std::string error_string() const { 305 return data_->error_string == nullptr ? "" : data_->error_string; 306 } 307 // Get a trailing metadata value by key. 308 absl::optional<std::string> GetTrailingMetadata( 309 absl::string_view key) const; 310 311 std::string GetSuccessfulStateString() override; 312 313 // Make a GRPC_OP_RECV_STATUS_ON_CLIENT op - intended for the framework, not 314 // for tests. 315 grpc_op MakeOp(); 316 317 private: 318 struct Data { 319 grpc_metadata_array trailing_metadata{0, 0, nullptr}; 320 grpc_status_code status; 321 Slice status_details; 322 const char* error_string = nullptr; 323 }; 324 std::unique_ptr<Data> data_ = std::make_unique<Data>(); 325 }; 326 327 // Receiving container for incoming status on the server from the client. 328 class IncomingCloseOnServer final : public CqVerifier::SuccessfulStateString { 329 public: 330 IncomingCloseOnServer() = default; 331 IncomingCloseOnServer(const IncomingCloseOnServer&) = delete; 332 IncomingCloseOnServer& operator=(const IncomingCloseOnServer&) = delete; 333 334 // Get the cancellation bit. was_cancelled()335 bool was_cancelled() const { return cancelled_ != 0; } 336 337 // Make a GRPC_OP_RECV_CLOSE_ON_SERVER op - intended for the framework, not 338 // for tests. 339 grpc_op MakeOp(); 340 GetSuccessfulStateString()341 std::string GetSuccessfulStateString() override { 342 return absl::StrCat("close_on_server: cancelled=", cancelled_); 343 } 344 345 private: 346 int cancelled_; 347 }; 348 349 // Build one batch. Returned from NewBatch (use that to instantiate this!) 350 // Upon destruction of the BatchBuilder, the batch will be executed with any 351 // added batches. 352 class BatchBuilder { 353 public: BatchBuilder(grpc_call * call,CoreEnd2endTest * test,int tag)354 BatchBuilder(grpc_call* call, CoreEnd2endTest* test, int tag) 355 : call_(call), tag_(tag), cq_verifier_(&test->cq_verifier()) { 356 cq_verifier_->ClearSuccessfulStateStrings(CqVerifier::tag(tag_)); 357 } 358 ~BatchBuilder(); 359 360 BatchBuilder(const BatchBuilder&) = delete; 361 BatchBuilder& operator=(const BatchBuilder&) = delete; 362 BatchBuilder(BatchBuilder&&) noexcept = default; 363 364 // Add a GRPC_OP_SEND_INITIAL_METADATA op. 365 // Optionally specify flags, compression level. 366 BatchBuilder& SendInitialMetadata( 367 std::initializer_list<std::pair<absl::string_view, absl::string_view>> 368 md, 369 uint32_t flags = 0, 370 absl::optional<grpc_compression_level> compression_level = 371 absl::nullopt); 372 373 // Add a GRPC_OP_SEND_MESSAGE op. 374 BatchBuilder& SendMessage(Slice payload, uint32_t flags = 0); 375 BatchBuilder& SendMessage(absl::string_view payload, uint32_t flags = 0) { 376 return SendMessage(Slice::FromCopiedString(payload), flags); 377 } 378 379 // Add a GRPC_OP_SEND_CLOSE_FROM_CLIENT op. 380 BatchBuilder& SendCloseFromClient(); 381 382 // Add a GRPC_OP_SEND_STATUS_FROM_SERVER op. 383 BatchBuilder& SendStatusFromServer( 384 grpc_status_code status, absl::string_view message, 385 std::initializer_list<std::pair<absl::string_view, absl::string_view>> 386 md); 387 388 // Add a GRPC_OP_RECV_INITIAL_METADATA op. RecvInitialMetadata(IncomingMetadata & md)389 BatchBuilder& RecvInitialMetadata(IncomingMetadata& md) { 390 cq_verifier_->AddSuccessfulStateString(CqVerifier::tag(tag_), &md); 391 ops_.emplace_back(md.MakeOp()); 392 return *this; 393 } 394 395 // Add a GRPC_OP_RECV_MESSAGE op. RecvMessage(IncomingMessage & msg)396 BatchBuilder& RecvMessage(IncomingMessage& msg) { 397 cq_verifier_->AddSuccessfulStateString(CqVerifier::tag(tag_), &msg); 398 ops_.emplace_back(msg.MakeOp()); 399 return *this; 400 } 401 402 // Add a GRPC_OP_RECV_STATUS_ON_CLIENT op. RecvStatusOnClient(IncomingStatusOnClient & status)403 BatchBuilder& RecvStatusOnClient(IncomingStatusOnClient& status) { 404 cq_verifier_->AddSuccessfulStateString(CqVerifier::tag(tag_), &status); 405 ops_.emplace_back(status.MakeOp()); 406 return *this; 407 } 408 409 // Add a GRPC_OP_RECV_CLOSE_ON_SERVER op. RecvCloseOnServer(IncomingCloseOnServer & close)410 BatchBuilder& RecvCloseOnServer(IncomingCloseOnServer& close) { 411 cq_verifier_->AddSuccessfulStateString(CqVerifier::tag(tag_), &close); 412 ops_.emplace_back(close.MakeOp()); 413 return *this; 414 } 415 416 private: 417 // We need to track little bits of memory up until the batch is executed. 418 // One Thing is one such block of memory. 419 // We specialize it with SpecificThing to track a specific type of memory. 420 // These get placed on things_ and deleted when the batch is executed. 421 class Thing { 422 public: 423 virtual ~Thing() = default; 424 }; 425 template <typename T> 426 class SpecificThing final : public Thing { 427 public: 428 template <typename... Args> SpecificThing(Args &&...args)429 explicit SpecificThing(Args&&... args) 430 : t_(std::forward<Args>(args)...) {} 431 SpecificThing() = default; 432 get()433 T& get() { return t_; } 434 435 private: 436 T t_; 437 }; 438 439 // Make a thing of type T, and return a reference to it. 440 template <typename T, typename... Args> Make(Args &&...args)441 T& Make(Args&&... args) { 442 things_.emplace_back(new SpecificThing<T>(std::forward<Args>(args)...)); 443 return static_cast<SpecificThing<T>*>(things_.back().get())->get(); 444 } 445 446 grpc_call* call_; 447 const int tag_; 448 std::vector<grpc_op> ops_; 449 std::vector<std::unique_ptr<Thing>> things_; 450 CqVerifier* const cq_verifier_; 451 }; 452 453 // Wrapper around a grpc_call. 454 // Instantiated by ClientCallBuilder via NewClientCall for client calls. 455 // Wrapped by IncomingCall for server calls. 456 class Call { 457 public: Call(grpc_call * call,CoreEnd2endTest * test)458 Call(grpc_call* call, CoreEnd2endTest* test) : call_(call), test_(test) {} 459 Call(const Call&) = delete; 460 Call& operator=(const Call&) = delete; Call(Call && other)461 Call(Call&& other) noexcept 462 : call_(std::exchange(other.call_, nullptr)), 463 test_(std::exchange(other.test_, nullptr)) {} ~Call()464 ~Call() { 465 if (call_ != nullptr) grpc_call_unref(call_); 466 } 467 // Construct a batch with a tag - upon destruction of the BatchBuilder the 468 // operation will occur. NewBatch(int tag)469 BatchBuilder NewBatch(int tag) { return BatchBuilder(call_, test_, tag); } 470 // Cancel the call Cancel()471 void Cancel() { grpc_call_cancel(call_, nullptr); } CancelWithStatus(grpc_status_code status,const char * message)472 void CancelWithStatus(grpc_status_code status, const char* message) { 473 grpc_call_cancel_with_status(call_, status, message, nullptr); 474 } 475 // Access the peer structure (returns a string that can be matched, etc) - 476 // or nullopt if grpc_call_get_peer returns nullptr. GetPeer()477 absl::optional<std::string> GetPeer() { 478 char* peer = grpc_call_get_peer(call_); 479 if (peer == nullptr) return absl::nullopt; 480 std::string result(peer); 481 gpr_free(peer); 482 return result; 483 } 484 485 // Set call credentials. 486 // Takes ownership of creds. SetCredentials(grpc_call_credentials * creds)487 void SetCredentials(grpc_call_credentials* creds) { 488 EXPECT_EQ(grpc_call_set_credentials(call_, creds), GRPC_CALL_OK); 489 grpc_call_credentials_release(creds); 490 } 491 492 // Retrieve the auth context. 493 std::unique_ptr<grpc_auth_context, void (*)(grpc_auth_context*)> GetAuthContext()494 GetAuthContext() { 495 return std::unique_ptr<grpc_auth_context, void (*)(grpc_auth_context*)>( 496 grpc_call_auth_context(call_), grpc_auth_context_release); 497 } 498 call_ptr()499 grpc_call** call_ptr() { return &call_; } c_call()500 grpc_call* c_call() const { return call_; } 501 502 private: 503 grpc_call* call_ = nullptr; 504 CoreEnd2endTest* test_; 505 }; 506 507 // Wrapper around a server call. 508 class IncomingCall { 509 public: 510 IncomingCall(CoreEnd2endTest& test, int tag); 511 IncomingCall(CoreEnd2endTest& test, void* method, IncomingMessage* message, 512 int tag); 513 IncomingCall(const IncomingCall&) = delete; 514 IncomingCall& operator=(const IncomingCall&) = delete; 515 IncomingCall(IncomingCall&&) noexcept = default; 516 517 // Construct a batch with a tag - upon destruction of the BatchBuilder the 518 // operation will occur. Must have received the call first! NewBatch(int tag)519 BatchBuilder NewBatch(int tag) { return impl_->call.NewBatch(tag); } Cancel()520 void Cancel() { impl_->call.Cancel(); } 521 522 // Return the method being called. method()523 std::string method() const { 524 return std::string(StringViewFromSlice(impl_->call_details.method)); 525 } 526 527 // Return the host being called. host()528 std::string host() const { 529 return std::string(StringViewFromSlice(impl_->call_details.host)); 530 } 531 532 // Return some initial metadata. 533 absl::optional<std::string> GetInitialMetadata(absl::string_view key) const; 534 535 // Return the peer address. GetPeer()536 absl::optional<std::string> GetPeer() { return impl_->call.GetPeer(); } 537 538 // Return the auth context. 539 std::unique_ptr<grpc_auth_context, void (*)(grpc_auth_context*)> GetAuthContext()540 GetAuthContext() { 541 return impl_->call.GetAuthContext(); 542 } 543 544 // Return the underlying C call object c_call()545 grpc_call* c_call() { return impl_->call.c_call(); } 546 547 // Return the encodings accepted by the peer. GetEncodingsAcceptedByPeer()548 BitSet<GRPC_COMPRESS_ALGORITHMS_COUNT> GetEncodingsAcceptedByPeer() { 549 return BitSet<GRPC_COMPRESS_ALGORITHMS_COUNT>::FromInt( 550 grpc_call_test_only_get_encodings_accepted_by_peer(c_call())); 551 } 552 553 private: 554 struct Impl { ImplImpl555 explicit Impl(CoreEnd2endTest* test) : call(nullptr, test) { 556 grpc_call_details_init(&call_details); 557 grpc_metadata_array_init(&request_metadata); 558 } ~ImplImpl559 ~Impl() { 560 grpc_call_details_destroy(&call_details); 561 grpc_metadata_array_destroy(&request_metadata); 562 } 563 Call call; 564 grpc_call_details call_details; 565 grpc_metadata_array request_metadata; 566 }; 567 std::unique_ptr<Impl> impl_; 568 }; 569 570 class ServerRegisteredMethod { 571 public: 572 ServerRegisteredMethod( 573 CoreEnd2endTest* test, absl::string_view name, 574 grpc_server_register_method_payload_handling payload_handling); 575 handle()576 void* handle() { return *handle_; } 577 578 private: 579 std::shared_ptr<void*> handle_ = std::make_shared<void*>(nullptr); 580 }; 581 RegisterServerMethod(absl::string_view name,grpc_server_register_method_payload_handling payload_handling)582 ServerRegisteredMethod RegisterServerMethod( 583 absl::string_view name, 584 grpc_server_register_method_payload_handling payload_handling) { 585 return ServerRegisteredMethod(this, name, payload_handling); 586 } 587 588 // Begin construction of a client call. NewClientCall(std::string method)589 ClientCallBuilder NewClientCall(std::string method) { 590 return ClientCallBuilder(*this, std::move(method)); 591 } NewClientCall(RegisteredCall registered_method)592 ClientCallBuilder NewClientCall(RegisteredCall registered_method) { 593 return ClientCallBuilder(*this, registered_method); 594 } 595 // Request a call on the server - notifies `tag` when complete. RequestCall(int tag)596 IncomingCall RequestCall(int tag) { return IncomingCall(*this, tag); } 597 // Request a call on the server - notifies `tag` when complete. RequestRegisteredCall(ServerRegisteredMethod method,int tag)598 IncomingCall RequestRegisteredCall(ServerRegisteredMethod method, int tag) { 599 return IncomingCall(*this, method.handle(), nullptr, tag); 600 } RequestRegisteredCall(ServerRegisteredMethod method,IncomingMessage * message,int tag)601 IncomingCall RequestRegisteredCall(ServerRegisteredMethod method, 602 IncomingMessage* message, int tag) { 603 return IncomingCall(*this, method.handle(), message, tag); 604 } 605 606 // Pull in CqVerifier types for ergonomics 607 // TODO(ctiller): evaluate just dropping CqVerifier and folding it in here. 608 using ExpectedResult = CqVerifier::ExpectedResult; 609 using Maybe = CqVerifier::Maybe; 610 using PerformAction = CqVerifier::PerformAction; 611 using MaybePerformAction = CqVerifier::MaybePerformAction; 612 using AnyStatus = CqVerifier::AnyStatus; 613 // Expect a tag with some result. 614 void Expect(int tag, ExpectedResult result, SourceLocation whence = {}) { 615 expectations_++; 616 cq_verifier().Expect(CqVerifier::tag(tag), std::move(result), whence); 617 } 618 // Step the system until expectations are met or until timeout is reached. 619 // If there are no expectations logged, then step for 1 second and verify that 620 // no events occur. 621 void Step(absl::optional<Duration> timeout = absl::nullopt, 622 SourceLocation whence = {}) { 623 if (expectations_ == 0) { 624 cq_verifier().VerifyEmpty(timeout.value_or(Duration::Seconds(1)), whence); 625 return; 626 } 627 expectations_ = 0; 628 cq_verifier().Verify( 629 timeout.value_or(g_is_fuzzing_core_e2e_tests ? Duration::Minutes(10) 630 : Duration::Seconds(10)), 631 whence); 632 } 633 634 // Initialize the client. 635 // If called, then InitServer must be called to create a server (otherwise one 636 // will be provided). InitClient(const ChannelArgs & args)637 void InitClient(const ChannelArgs& args) { 638 initialized_ = true; 639 if (client_ != nullptr) ShutdownAndDestroyClient(); 640 auto& f = fixture(); 641 client_ = f.MakeClient(args, cq_); 642 GPR_ASSERT(client_ != nullptr); 643 } 644 // Initialize the server. 645 // If called, then InitClient must be called to create a client (otherwise one 646 // will be provided). InitServer(const ChannelArgs & args)647 void InitServer(const ChannelArgs& args) { 648 initialized_ = true; 649 if (server_ != nullptr) ShutdownAndDestroyServer(); 650 auto& f = fixture(); 651 server_ = f.MakeServer(args, cq_, pre_server_start_); 652 GPR_ASSERT(server_ != nullptr); 653 } 654 // Remove the client. ShutdownAndDestroyClient()655 void ShutdownAndDestroyClient() { 656 if (client_ == nullptr) return; 657 grpc_channel_destroy(client_); 658 client_ = nullptr; 659 } 660 // Shutdown the server; notify tag on completion. ShutdownServerAndNotify(int tag)661 void ShutdownServerAndNotify(int tag) { 662 grpc_server_shutdown_and_notify(server_, cq_, CqVerifier::tag(tag)); 663 } 664 // Destroy the server. DestroyServer()665 void DestroyServer() { 666 if (server_ == nullptr) return; 667 grpc_server_destroy(server_); 668 server_ = nullptr; 669 } 670 // Shutdown then destroy the server. ShutdownAndDestroyServer()671 void ShutdownAndDestroyServer() { 672 if (server_ == nullptr) return; 673 ShutdownServerAndNotify(-1); 674 Expect(-1, AnyStatus{}); 675 Step(); 676 DestroyServer(); 677 } 678 // Cancel any calls on the server. CancelAllCallsOnServer()679 void CancelAllCallsOnServer() { grpc_server_cancel_all_calls(server_); } 680 // Ping the server from the client PingServerFromClient(int tag)681 void PingServerFromClient(int tag) { 682 grpc_channel_ping(client_, cq_, CqVerifier::tag(tag), nullptr); 683 } 684 // Register a call on the client, return its handle. RegisterCallOnClient(const char * method,const char * host)685 RegisteredCall RegisterCallOnClient(const char* method, const char* host) { 686 ForceInitialized(); 687 return RegisteredCall{ 688 grpc_channel_register_call(client_, method, host, nullptr)}; 689 } 690 691 // Return the current connectivity state of the client. CheckConnectivityState(bool try_to_connect)692 grpc_connectivity_state CheckConnectivityState(bool try_to_connect) { 693 return grpc_channel_check_connectivity_state(client_, try_to_connect); 694 } 695 696 // Watch the connectivity state of the client. WatchConnectivityState(grpc_connectivity_state last_observed_state,Duration deadline,int tag)697 void WatchConnectivityState(grpc_connectivity_state last_observed_state, 698 Duration deadline, int tag) { 699 grpc_channel_watch_connectivity_state( 700 client_, last_observed_state, 701 grpc_timeout_milliseconds_to_deadline(deadline.millis()), cq_, 702 CqVerifier::tag(tag)); 703 } 704 705 // Return the client channel. client()706 grpc_channel* client() { 707 ForceInitialized(); 708 return client_; 709 } 710 711 // Return the server channel. server()712 grpc_server* server() { 713 ForceInitialized(); 714 return server_; 715 } 716 cq()717 grpc_completion_queue* cq() { 718 ForceInitialized(); 719 return cq_; 720 } 721 722 // Given a duration, return a timestamp that is that duration in the future - 723 // with dilation according to test environment (eg sanitizers) TimestampAfterDuration(Duration duration)724 Timestamp TimestampAfterDuration(Duration duration) { 725 return Timestamp::FromTimespecRoundUp( 726 grpc_timeout_milliseconds_to_deadline(duration.millis())); 727 } 728 SetPostGrpcInitFunc(absl::AnyInvocable<void ()> fn)729 void SetPostGrpcInitFunc(absl::AnyInvocable<void()> fn) { 730 GPR_ASSERT(fixture_ == nullptr); 731 post_grpc_init_func_ = std::move(fn); 732 } 733 734 private: 735 void ForceInitialized(); 736 fixture()737 CoreTestFixture& fixture() { 738 if (fixture_ == nullptr) { 739 grpc_init(); 740 post_grpc_init_func_(); 741 cq_ = grpc_completion_queue_create_for_next(nullptr); 742 fixture_ = GetParam()->create_fixture(ChannelArgs(), ChannelArgs()); 743 } 744 return *fixture_; 745 } 746 cq_verifier()747 CqVerifier& cq_verifier() { 748 if (cq_verifier_ == nullptr) { 749 fixture(); // ensure cq_ present 750 cq_verifier_ = absl::make_unique<CqVerifier>( 751 cq_, 752 g_is_fuzzing_core_e2e_tests ? CqVerifier::FailUsingGprCrashWithStdio 753 : CqVerifier::FailUsingGprCrash, 754 std::move(step_fn_)); 755 } 756 return *cq_verifier_; 757 } 758 759 const CoreTestConfiguration* param_ = nullptr; 760 std::unique_ptr<CoreTestFixture> fixture_; 761 grpc_completion_queue* cq_ = nullptr; 762 grpc_server* server_ = nullptr; 763 grpc_channel* client_ = nullptr; 764 std::unique_ptr<CqVerifier> cq_verifier_; 765 absl::AnyInvocable<void(grpc_server*)> pre_server_start_ = [](grpc_server*) { 766 }; 767 int expectations_ = 0; 768 bool initialized_ = false; 769 absl::AnyInvocable<void()> post_grpc_init_func_ = []() {}; 770 absl::AnyInvocable<void( 771 grpc_event_engine::experimental::EventEngine::Duration) const> 772 step_fn_ = nullptr; 773 absl::AnyInvocable<void( 774 std::shared_ptr<grpc_event_engine::experimental::EventEngine>&&)> 775 quiesce_event_engine_ = 776 grpc_event_engine::experimental::WaitForSingleOwner; 777 }; 778 779 // Define names for additional test suites. 780 // These make no changes to the actual class, but define new names to register 781 // tests against. Each new name gets a differing set of configurations in 782 // end2end_test_main.cc to customize the set of fixtures the tests run against. 783 784 // Test suite for tests that rely on a secure transport 785 class SecureEnd2endTest : public CoreEnd2endTest {}; 786 // Test suite for tests that send rather large messages/metadata 787 class CoreLargeSendTest : public CoreEnd2endTest {}; 788 // Test suite for tests that need a client channel 789 class CoreClientChannelTest : public CoreEnd2endTest {}; 790 // Test suite for tests that require deadline handling 791 class CoreDeadlineTest : public CoreEnd2endTest {}; 792 // Test suite for tests that require deadline handling 793 class CoreDeadlineSingleHopTest : public CoreEnd2endTest {}; 794 // Test suite for http2 tests that only work over a single hop (unproxyable) 795 class Http2SingleHopTest : public CoreEnd2endTest {}; 796 // Test suite for fullstack single hop http2 tests (require client channel) 797 class Http2FullstackSingleHopTest : public CoreEnd2endTest {}; 798 // Test suite for tests that require retry features 799 class RetryTest : public CoreEnd2endTest {}; 800 // Test suite for write buffering 801 class WriteBufferingTest : public CoreEnd2endTest {}; 802 // Test suite for http2 tests 803 class Http2Test : public CoreEnd2endTest {}; 804 // Test suite for http2 tests that require retry features 805 class RetryHttp2Test : public CoreEnd2endTest {}; 806 // Test suite for tests that require resource quota 807 class ResourceQuotaTest : public CoreEnd2endTest {}; 808 // Test suite for tests that require a transport that supports secure call 809 // credentials 810 class PerCallCredsTest : public CoreEnd2endTest {}; 811 // Test suite for tests that require a transport that supports insecure call 812 // credentials 813 class PerCallCredsOnInsecureTest : public CoreEnd2endTest {}; 814 // Test suite for tests that verify lack of logging in particular situations 815 class NoLoggingTest : public CoreEnd2endTest {}; 816 // Test suite for tests that verify proxy authentication 817 class ProxyAuthTest : public CoreEnd2endTest {}; 818 819 using MakeTestFn = absl::AnyInvocable<CoreEnd2endTest*( 820 const CoreTestConfiguration* config) const>; 821 822 class CoreEnd2endTestRegistry { 823 public: 824 CoreEnd2endTestRegistry(const CoreEnd2endTestRegistry&) = delete; 825 CoreEnd2endTestRegistry& operator=(const CoreEnd2endTestRegistry&) = delete; 826 Get()827 static CoreEnd2endTestRegistry& Get() { 828 static CoreEnd2endTestRegistry* singleton = new CoreEnd2endTestRegistry; 829 return *singleton; 830 } 831 832 struct Test { 833 absl::string_view suite; 834 absl::string_view name; 835 const CoreTestConfiguration* config; 836 const MakeTestFn& make_test; 837 }; 838 839 void RegisterTest(absl::string_view suite, absl::string_view name, 840 MakeTestFn make_test, SourceLocation where = {}); 841 842 void RegisterSuite(absl::string_view suite, 843 std::vector<const CoreTestConfiguration*> configs, 844 SourceLocation where); 845 846 std::vector<Test> AllTests(); 847 848 // Enforce passing a type so that we can check it exists (saves typos) 849 template <typename T> 850 absl::void_t<T> RegisterSuiteT( 851 absl::string_view suite, 852 std::vector<const CoreTestConfiguration*> configs, 853 SourceLocation where = {}) { 854 return RegisterSuite(suite, std::move(configs), where); 855 } 856 857 private: 858 CoreEnd2endTestRegistry() = default; 859 860 std::map<absl::string_view, std::vector<const CoreTestConfiguration*>> 861 suites_; 862 std::map<absl::string_view, std::map<absl::string_view, MakeTestFn>> 863 tests_by_suite_; 864 }; 865 866 } // namespace grpc_core 867 868 // If this test fixture is being run under minstack, skip the test. 869 #define SKIP_IF_MINSTACK() \ 870 if (GetParam()->feature_mask & FEATURE_MASK_IS_MINSTACK) \ 871 GTEST_SKIP() << "Skipping test for minstack" 872 873 #define SKIP_IF_FUZZING() \ 874 if (g_is_fuzzing_core_e2e_tests) GTEST_SKIP() << "Skipping test for fuzzing" 875 876 #define SKIP_IF_CHAOTIC_GOOD() \ 877 if (IsChaoticGoodEnabled()) { \ 878 GTEST_SKIP() << "Disabled for initial chaotic good testing"; \ 879 } 880 881 #define CORE_END2END_TEST(suite, name) \ 882 class CoreEnd2endTest_##suite##_##name : public grpc_core::suite { \ 883 public: \ 884 CoreEnd2endTest_##suite##_##name() {} \ 885 void TestBody() override { RunTest(); } \ 886 void RunTest() override; \ 887 \ 888 private: \ 889 static grpc_core::CoreEnd2endTest* Run( \ 890 const grpc_core::CoreTestConfiguration* config) { \ 891 auto* test = new CoreEnd2endTest_##suite##_##name; \ 892 test->TestInfrastructureSetParam(config); \ 893 return test; \ 894 } \ 895 static int registered_; \ 896 }; \ 897 int CoreEnd2endTest_##suite##_##name::registered_ = \ 898 (grpc_core::CoreEnd2endTestRegistry::Get().RegisterTest(#suite, #name, \ 899 &Run), \ 900 0); \ 901 void CoreEnd2endTest_##suite##_##name::RunTest() 902 903 #define CORE_END2END_TEST_SUITE(suite, configs) \ 904 static int registered_##suite = \ 905 (grpc_core::CoreEnd2endTestRegistry::Get() \ 906 .template RegisterSuiteT<suite>(#suite, configs), \ 907 0) 908 909 #endif // GRPC_TEST_CORE_END2END_END2END_TESTS_H 910