xref: /aosp_15_r20/external/grpc-grpc/test/core/end2end/end2end_test_fuzzer.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1 // Copyright 2023 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "test/core/end2end/end2end_test_fuzzer.h"
16 
17 #include <stdio.h>
18 
19 #include <algorithm>
20 #include <chrono>
21 #include <memory>
22 #include <string>
23 #include <type_traits>
24 #include <utility>
25 #include <vector>
26 
27 #include <gtest/gtest.h>
28 
29 #include <grpc/event_engine/event_engine.h>
30 #include <grpc/support/log.h>
31 
32 #include "src/core/lib/config/config_vars.h"
33 #include "src/core/lib/event_engine/default_event_engine.h"
34 #include "src/core/lib/experiments/config.h"
35 #include "src/core/lib/gprpp/env.h"
36 #include "src/core/lib/iomgr/exec_ctx.h"
37 #include "src/core/lib/iomgr/executor.h"
38 #include "src/core/lib/iomgr/timer_manager.h"
39 #include "test/core/end2end/end2end_tests.h"
40 #include "test/core/end2end/fixtures/h2_tls_common.h"
41 #include "test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.h"
42 #include "test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.pb.h"
43 #include "test/core/util/fuzz_config_vars.h"
44 
45 using ::grpc_event_engine::experimental::FuzzingEventEngine;
46 using ::grpc_event_engine::experimental::GetDefaultEventEngine;
47 
48 bool squelch = true;
dont_log(gpr_log_func_args *)49 static void dont_log(gpr_log_func_args* /*args*/) {}
50 
51 namespace grpc_core {
52 
RunEnd2endFuzzer(const core_end2end_test_fuzzer::Msg & msg)53 void RunEnd2endFuzzer(const core_end2end_test_fuzzer::Msg& msg) {
54   struct Test {
55     std::string name;
56     absl::AnyInvocable<std::unique_ptr<CoreEnd2endTest>() const> factory;
57   };
58 
59   static const auto only_suite = GetEnv("GRPC_TEST_FUZZER_SUITE");
60   static const auto only_test = GetEnv("GRPC_TEST_FUZZER_TEST");
61   static const auto only_config = GetEnv("GRPC_TEST_FUZZER_CONFIG");
62 
63   static const auto all_tests = CoreEnd2endTestRegistry::Get().AllTests();
64   static const auto tests = []() {
65     g_is_fuzzing_core_e2e_tests = true;
66     ForceEnableExperiment("event_engine_client", true);
67     ForceEnableExperiment("event_engine_listener", true);
68 
69     std::vector<Test> tests;
70     for (const auto& test : all_tests) {
71       if (test.config->feature_mask & FEATURE_MASK_DO_NOT_FUZZ) continue;
72       if (only_suite.has_value() && test.suite != only_suite.value()) continue;
73       if (only_test.has_value() && test.name != only_test.value()) continue;
74       if (only_config.has_value() && test.config->name != only_config.value()) {
75         continue;
76       }
77       std::string test_name =
78           absl::StrCat(test.suite, ".", test.name, "/", test.config->name);
79       tests.emplace_back(Test{std::move(test_name), [&test]() {
80                                 return std::unique_ptr<CoreEnd2endTest>(
81                                     test.make_test(test.config));
82                               }});
83     }
84     std::sort(tests.begin(), tests.end(),
85               [](const Test& a, const Test& b) { return a.name < b.name; });
86     return tests;
87   }();
88   if (tests.empty()) return;
89 
90   const int test_id = msg.test_id() % tests.size();
91 
92   if (squelch && !GetEnv("GRPC_TRACE_FUZZER").has_value()) {
93     gpr_set_log_function(dont_log);
94   }
95 
96   // TODO(ctiller): make this per fixture?
97   ConfigVars::Overrides overrides =
98       OverridesFromFuzzConfigVars(msg.config_vars());
99   overrides.default_ssl_roots_file_path = CA_CERT_PATH;
100   ConfigVars::SetOverrides(overrides);
101   TestOnlyReloadExperimentsFromConfigVariables();
102   grpc_event_engine::experimental::SetEventEngineFactory(
103       [actions = msg.event_engine_actions()]() {
104         FuzzingEventEngine::Options options;
105         options.max_delay_run_after = std::chrono::milliseconds(500);
106         options.max_delay_write = std::chrono::microseconds(5);
107         return std::make_unique<FuzzingEventEngine>(options, actions);
108       });
109   auto engine =
110       std::dynamic_pointer_cast<FuzzingEventEngine>(GetDefaultEventEngine());
111 
112   if (!squelch) {
113     fprintf(stderr, "RUN TEST: %s\n", tests[test_id].name.c_str());
114   }
115   auto test = tests[test_id].factory();
116   test->SetQuiesceEventEngine(
117       [](std::shared_ptr<grpc_event_engine::experimental::EventEngine>&& ee) {
118         static_cast<FuzzingEventEngine*>(ee.get())->TickUntilIdle();
119       });
120   test->SetCqVerifierStepFn(
121       [engine = std::move(engine)](
122           grpc_event_engine::experimental::EventEngine::Duration max_step) {
123         ApplicationCallbackExecCtx callback_exec_ctx;
124         ExecCtx exec_ctx;
125         engine->Tick(max_step);
126         grpc_timer_manager_tick();
127       });
128   test->SetPostGrpcInitFunc([]() {
129     grpc_timer_manager_set_threading(false);
130     ExecCtx exec_ctx;
131     Executor::SetThreadingAll(false);
132   });
133   test->SetUp();
134   test->RunTest();
135   test->TearDown();
136   GPR_ASSERT(!::testing::Test::HasFailure());
137 }
138 
139 }  // namespace grpc_core
140