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