• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)58 inline Validator* MakeValidator(std::function<void(bool)> impl) {
59   return new Validator(std::move(impl));
60 }
61 
AssertSuccessAndDecrement(int * counter)62 inline Validator* AssertSuccessAndDecrement(int* counter) {
63   return MakeValidator([counter](bool success) {
64     CHECK(success);
65     --*counter;
66   });
67 }
68 
Decrement(int * counter)69 inline 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