1 // 2 // 3 // Copyright 2023 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_FUZZERS_FUZZING_COMMON_H 20 #define GRPC_TEST_CORE_END2END_FUZZERS_FUZZING_COMMON_H 21 22 #include <grpc/grpc.h> 23 #include <stddef.h> 24 #include <stdint.h> 25 26 #include <algorithm> 27 #include <functional> 28 #include <memory> 29 #include <utility> 30 #include <vector> 31 32 #include "absl/log/check.h" 33 #include "absl/types/span.h" 34 #include "src/core/lib/resource_quota/resource_quota.h" 35 #include "src/core/util/ref_counted_ptr.h" 36 #include "src/core/util/time.h" 37 #include "test/core/end2end/fuzzers/api_fuzzer.pb.h" 38 #include "test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.h" 39 #include "test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.pb.h" 40 41 namespace grpc_core { 42 namespace testing { 43 44 class Validator { 45 public: Validator(std::function<void (bool)> impl)46 explicit Validator(std::function<void(bool)> impl) : impl_(std::move(impl)) {} 47 ~Validator()48 virtual ~Validator() {} Run(bool success)49 void Run(bool success) { 50 impl_(success); 51 delete this; 52 } 53 54 private: 55 std::function<void(bool)> impl_; 56 }; 57 MakeValidator(std::function<void (bool)> impl)58inline Validator* MakeValidator(std::function<void(bool)> impl) { 59 return new Validator(std::move(impl)); 60 } 61 AssertSuccessAndDecrement(int * counter)62inline Validator* AssertSuccessAndDecrement(int* counter) { 63 return MakeValidator([counter](bool success) { 64 CHECK(success); 65 --*counter; 66 }); 67 } 68 Decrement(int * counter)69inline Validator* Decrement(int* counter) { 70 return MakeValidator([counter](bool) { --*counter; }); 71 } 72 73 class Call; 74 75 class BasicFuzzer { 76 public: 77 explicit BasicFuzzer(const fuzzing_event_engine::Actions& actions); 78 79 enum Result { kPending = 0, kComplete = 1, kFailed = 2, kNotSupported = 3 }; 80 virtual Result ExecuteAction(const api_fuzzer::Action& action); 81 Call* ActiveCall(); 82 83 bool Continue(); 84 virtual void Tick(); 85 86 void Run(absl::Span<const api_fuzzer::Action* const> actions); 87 88 protected: 89 ~BasicFuzzer(); 90 server_finished_shutting_down()91 bool server_finished_shutting_down() { 92 return server() != nullptr && server_shutdown_ && 93 pending_server_shutdowns_ == 0; 94 } server_shutdown_called()95 bool server_shutdown_called() { return server_shutdown_; } 96 97 void ShutdownCalls(); ResetServerState()98 void ResetServerState() { 99 server_shutdown_ = false; 100 CHECK_EQ(pending_server_shutdowns_, 0); 101 } 102 103 // Poll any created completion queue to drive the RPC forward. 104 Result PollCq(); 105 106 // Shutdown the active server. 107 Result ShutdownServer(); 108 resource_quota()109 RefCountedPtr<ResourceQuota> resource_quota() { return resource_quota_; } 110 111 std::shared_ptr<grpc_event_engine::experimental::FuzzingEventEngine> engine()112 engine() { 113 return engine_; 114 } 115 cq()116 grpc_completion_queue* cq() { return cq_; } 117 UpdateMinimumRunTime(Duration minimum_run_time)118 void UpdateMinimumRunTime(Duration minimum_run_time) { 119 minimum_run_time_ = std::max(minimum_run_time, minimum_run_time_); 120 } 121 122 private: 123 // Channel specific actions. 124 // Create an active channel with the specified parameters. 125 virtual Result CreateChannel( 126 const api_fuzzer::CreateChannel& create_channel) = 0; 127 128 // Close the active channel. 129 Result CloseChannel(); 130 // Check whether the channel is connected and optionally try to connect if it 131 // is not connected. 132 Result CheckConnectivity(bool try_to_connect); 133 // Watch whether the channel connects within the specified duration. 134 Result WatchConnectivity(uint32_t duration_us); 135 // Verify that the channel target can be reliably queried. 136 Result ValidateChannelTarget(); 137 138 // Server specific actions 139 // Create an active server. 140 virtual Result CreateServer( 141 const api_fuzzer::CreateServer& create_server) = 0; 142 // Destroy the active server. 143 Result DestroyServerIfReady(); 144 145 // Request to be notified of a new RPC on the active server. 146 Result ServerRequestCall(); 147 // Cancel all server calls. 148 Result CancelAllCallsIfShutdown(); 149 150 // Call specific actions. 151 // Create a call on the active channel with the specified parameters. Also add 152 // it the list of managed calls. 153 Result CreateCall(const api_fuzzer::CreateCall& create_call); 154 // Choose a different active call from the list of managed calls. 155 Result ChangeActiveCall(); 156 // Queue a batch of operations to be executed on the active call. 157 Result QueueBatchForActiveCall(const api_fuzzer::Batch& queue_batch); 158 // Cancel the active call. 159 Result CancelActiveCall(); 160 // Validate that the peer can be reliably queried for the active call. 161 Result ValidatePeerForActiveCall(); 162 // Cancel and destroy the active call. 163 Result DestroyActiveCall(); 164 // Pause the run loop for some time 165 Result Pause(Duration duration); 166 167 // Other actions. 168 // Change the resource quota limits. 169 Result ResizeResourceQuota(uint32_t resize_resource_quota); 170 171 void TryShutdown(); 172 173 virtual grpc_server* server() = 0; 174 virtual grpc_channel* channel() = 0; 175 virtual void DestroyServer() = 0; 176 virtual void DestroyChannel() = 0; 177 178 std::shared_ptr<grpc_event_engine::experimental::FuzzingEventEngine> engine_; 179 grpc_completion_queue* cq_; 180 bool server_shutdown_ = false; 181 int pending_server_shutdowns_ = 0; 182 int pending_channel_watches_ = 0; 183 int paused_ = 0; 184 std::vector<std::shared_ptr<Call>> calls_; 185 RefCountedPtr<ResourceQuota> resource_quota_; 186 size_t active_call_ = 0; 187 Duration minimum_run_time_ = Duration::Zero(); 188 }; 189 190 } // namespace testing 191 } // namespace grpc_core 192 193 #endif // GRPC_TEST_CORE_END2END_FUZZERS_FUZZING_COMMON_H 194