From 512300d4a86a112cc722e2babcb12d9a89687775 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 28 Jan 2025 19:39:35 -0800 Subject: [PATCH] x --- test/core/handshake/handshaker_fuzzer.cc | 54 ++++++++++ test/core/handshake/test_handshake.cc | 121 +++++++++++++++++++++++ test/core/handshake/test_handshake.h | 33 +++++++ 3 files changed, 208 insertions(+) create mode 100644 test/core/handshake/handshaker_fuzzer.cc create mode 100644 test/core/handshake/test_handshake.cc create mode 100644 test/core/handshake/test_handshake.h diff --git a/test/core/handshake/handshaker_fuzzer.cc b/test/core/handshake/handshaker_fuzzer.cc new file mode 100644 index 0000000000000..551f5233d7378 --- /dev/null +++ b/test/core/handshake/handshaker_fuzzer.cc @@ -0,0 +1,54 @@ +// Copyright 2025 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "fuzztest/fuzztest.h" +#include "test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.pb.h" +#include "test/core/handshake/test_handshake.h" +#include "test/core/test_util/fuzzing_channel_args.h" +#include "test/core/test_util/fuzzing_channel_args.pb.h" + +namespace grpc_core { +namespace { + +auto BaseChannelArgs() { return ChannelArgs(); } + +auto AnyChannelArgs() { + return ::fuzztest::Map( + [](const grpc::testing::FuzzingChannelArgs& args) { + testing::FuzzingEnvironment env; + return testing::CreateChannelArgsFromFuzzingConfiguration(args, env); + }, + ::fuzztest::Arbitrary()); +} + +// Without supplying channel args, we should expect basic TCP connections to +// succeed every time. +void BasicHandshakeSucceeds(const fuzzing_event_engine::Actions& actions) { + CHECK_OK(TestHandshake(BaseChannelArgs(), BaseChannelArgs(), actions)); +} +FUZZ_TEST(HandshakerFuzzer, BasicHandshakeSucceeds); + +// Supplying effectively random channel args, we should expect no crashes (but +// hey, maybe we don't connect). +void RandomChannelArgsDontCauseCrashes( + const ChannelArgs& client_args, const ChannelArgs& server_args, + const fuzzing_event_engine::Actions& actions) { + std::ignore = TestHandshake(client_args, server_args, actions); +} +FUZZ_TEST(HandshakerFuzzer, RandomChannelArgsDontCauseCrashes) + .WithDomains(AnyChannelArgs(), AnyChannelArgs(), + ::fuzztest::Arbitrary()); + +} // namespace +} // namespace grpc_core diff --git a/test/core/handshake/test_handshake.cc b/test/core/handshake/test_handshake.cc new file mode 100644 index 0000000000000..495227e98de3a --- /dev/null +++ b/test/core/handshake/test_handshake.cc @@ -0,0 +1,121 @@ +// Copyright 2025 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "test/core/handshake/test_handshake.h" + +#include + +#include "src/core/handshaker/handshaker.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/event_engine/channel_args_endpoint_config.h" +#include "src/core/lib/event_engine/memory_allocator_factory.h" +#include "src/core/lib/event_engine/tcp_socket_utils.h" +#include "src/core/lib/iomgr/event_engine_shims/endpoint.h" +#include "src/core/lib/resource_quota/resource_quota.h" +#include "test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.h" + +using ::grpc_event_engine::experimental::ChannelArgsEndpointConfig; +using ::grpc_event_engine::experimental::EventEngine; +using ::grpc_event_engine::experimental::FuzzingEventEngine; +using ::grpc_event_engine::experimental::grpc_event_engine_endpoint_create; +using ::grpc_event_engine::experimental::MemoryQuotaBasedMemoryAllocatorFactory; +using ::grpc_event_engine::experimental::ResolvedAddressMakeWild4; +using ::grpc_event_engine::experimental::SetDefaultEventEngine; +using ::grpc_event_engine::experimental::ShutdownDefaultEventEngine; + +namespace grpc_core { + +namespace { +void Handshake(std::unique_ptr endpoint, + const ChannelArgs& channel_args, + absl::optional>* output) { + auto handshake_mgr = MakeRefCounted(); + handshake_mgr->DoHandshake( + OrphanablePtr( + grpc_event_engine_endpoint_create(std::move(endpoint))), + channel_args, Timestamp::Now() + Duration::Hours(24), nullptr, + [handshake_mgr, output](absl::StatusOr result) { + if (!result.ok()) { + output->emplace(result.status()); + } else { + output->emplace((*result)->args); + } + }); +} +} // namespace + +absl::StatusOr> TestHandshake( + ChannelArgs client_args, ChannelArgs server_args, + const fuzzing_event_engine::Actions& actions) { + const int kPort = 1234; + // Configure default event engine + auto engine = std::make_shared( + FuzzingEventEngine::Options(), actions); + // Pass event engine down + client_args = client_args.SetObject( + std::static_pointer_cast(engine)); + server_args = server_args.SetObject( + std::static_pointer_cast(engine)); + // Address - just ok for fuzzing ee + const auto addr = ResolvedAddressMakeWild4(kPort); + // Start listening + absl::optional> output_server_args; + auto listener = engine->CreateListener( + [output_server_args = &output_server_args, server_args]( + std::unique_ptr endpoint, MemoryAllocator) { + Handshake(std::move(endpoint), server_args, output_server_args); + }, + [](const absl::Status&) {}, ChannelArgsEndpointConfig(server_args), + std::make_unique( + ResourceQuota::Default()->memory_quota())); + if (!listener.ok()) return listener.status(); + const auto bind_status = (*listener)->Bind(addr); + if (!bind_status.ok()) return bind_status.status(); + const auto listen_status = (*listener)->Start(); + if (!listen_status.ok()) return listen_status; + // Connect client + absl::optional> output_client_args; + std::ignore = engine->Connect( + [output_client_args = &output_client_args, client_args]( + absl::StatusOr> endpoint) { + if (!endpoint.ok()) { + output_client_args->emplace(endpoint.status()); + } else { + Handshake(std::move(*endpoint), client_args, output_client_args); + } + }, + addr, ChannelArgsEndpointConfig(client_args), + ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator( + "connection"), + Duration::Hours(24)); + // Await completion + std::optional>> result; + while (!result.has_value()) { + if (output_client_args.has_value() && !output_client_args->ok()) { + result.emplace(output_client_args->status()); + } else if (output_server_args.has_value() && !output_server_args->ok()) { + result.emplace(output_server_args->status()); + } else if (output_client_args.has_value() && + output_server_args.has_value()) { + result.emplace(std::make_tuple(std::move(**output_client_args), + std::move(**output_server_args))); + } else { + engine->Tick(); + } + } + engine->TickUntilIdle(); + return *result; +} + +} // namespace grpc_core diff --git a/test/core/handshake/test_handshake.h b/test/core/handshake/test_handshake.h new file mode 100644 index 0000000000000..cb1b2007b1ce3 --- /dev/null +++ b/test/core/handshake/test_handshake.h @@ -0,0 +1,33 @@ +// Copyright 2025 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef GRPC_TEST_CORE_TEST_HANDSHAKE_H +#define GRPC_TEST_CORE_TEST_HANDSHAKE_H + +#include "src/core/lib/channel/channel_args.h" +#include "test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.pb.h" + +namespace grpc_core { + +// Create client, server connections, perform a handshake, return the result. +// Runs under a fuzzing event engine, and fuzzing parameters can be supplied as +// the last argument. +absl::StatusOr> TestHandshake( + ChannelArgs client_args, ChannelArgs server_args, + const fuzzing_event_engine::Actions& actions = + fuzzing_event_engine::Actions()); + +} // namespace grpc_core + +#endif