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