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 <grpc/event_engine/event_engine.h>
18 #include <gtest/gtest.h>
19 #include <stdio.h>
20
21 #include <algorithm>
22 #include <chrono>
23 #include <memory>
24 #include <string>
25 #include <type_traits>
26 #include <utility>
27 #include <vector>
28
29 #include "absl/log/check.h"
30 #include "src/core/config/config_vars.h"
31 #include "src/core/lib/event_engine/default_event_engine.h"
32 #include "src/core/lib/experiments/config.h"
33 #include "src/core/lib/iomgr/exec_ctx.h"
34 #include "src/core/lib/iomgr/executor.h"
35 #include "src/core/lib/iomgr/timer_manager.h"
36 #include "src/core/util/env.h"
37 #include "test/core/end2end/end2end_tests.h"
38 #include "test/core/end2end/fixtures/h2_tls_common.h"
39 #include "test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.h"
40 #include "test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.pb.h"
41 #include "test/core/test_util/fuzz_config_vars.h"
42 #include "test/core/test_util/test_config.h"
43
44 using ::grpc_event_engine::experimental::FuzzingEventEngine;
45 using ::grpc_event_engine::experimental::GetDefaultEventEngine;
46
47 bool squelch = true;
48
49 namespace grpc_core {
50
RunEnd2endFuzzer(const core_end2end_test_fuzzer::Msg & msg)51 void RunEnd2endFuzzer(const core_end2end_test_fuzzer::Msg& msg) {
52 struct Test {
53 std::string name;
54 absl::AnyInvocable<std::unique_ptr<CoreEnd2endTest>() const> factory;
55 };
56
57 static const auto only_suite = GetEnv("GRPC_TEST_FUZZER_SUITE");
58 static const auto only_test = GetEnv("GRPC_TEST_FUZZER_TEST");
59 static const auto only_config = GetEnv("GRPC_TEST_FUZZER_CONFIG");
60
61 static const auto all_tests = CoreEnd2endTestRegistry::Get().AllTests();
62 static const auto tests = []() {
63 g_is_fuzzing_core_e2e_tests = true;
64 ForceEnableExperiment("event_engine_client", true);
65 ForceEnableExperiment("event_engine_listener", true);
66
67 std::vector<Test> tests;
68 for (const auto& test : all_tests) {
69 if (test.config->feature_mask & FEATURE_MASK_DO_NOT_FUZZ) continue;
70 if (only_suite.has_value() && test.suite != only_suite.value()) continue;
71 if (only_test.has_value() && test.name != only_test.value()) continue;
72 if (only_config.has_value() && test.config->name != only_config.value()) {
73 continue;
74 }
75 std::string test_name =
76 absl::StrCat(test.suite, ".", test.name, "/", test.config->name);
77 tests.emplace_back(Test{std::move(test_name), [&test]() {
78 return std::unique_ptr<CoreEnd2endTest>(
79 test.make_test(test.config));
80 }});
81 }
82 std::sort(tests.begin(), tests.end(),
83 [](const Test& a, const Test& b) { return a.name < b.name; });
84 return tests;
85 }();
86 if (tests.empty()) return;
87
88 const int test_id = msg.test_id() % tests.size();
89
90 if (squelch && !GetEnv("GRPC_TRACE_FUZZER").has_value()) {
91 grpc_disable_all_absl_logs();
92 }
93
94 // TODO(ctiller): make this per fixture?
95 ConfigVars::Overrides overrides =
96 OverridesFromFuzzConfigVars(msg.config_vars());
97 overrides.default_ssl_roots_file_path = CA_CERT_PATH;
98 ConfigVars::SetOverrides(overrides);
99 TestOnlyReloadExperimentsFromConfigVariables();
100 grpc_event_engine::experimental::SetEventEngineFactory(
101 [actions = msg.event_engine_actions()]() {
102 FuzzingEventEngine::Options options;
103 options.max_delay_run_after = std::chrono::milliseconds(500);
104 options.max_delay_write = std::chrono::microseconds(5);
105 return std::make_unique<FuzzingEventEngine>(options, actions);
106 });
107 auto engine =
108 std::dynamic_pointer_cast<FuzzingEventEngine>(GetDefaultEventEngine());
109
110 if (!squelch) {
111 fprintf(stderr, "RUN TEST: %s\n", tests[test_id].name.c_str());
112 }
113 auto test = tests[test_id].factory();
114 test->SetQuiesceEventEngine(
115 [](std::shared_ptr<grpc_event_engine::experimental::EventEngine>&& ee) {
116 static_cast<FuzzingEventEngine*>(ee.get())->TickUntilIdle();
117 });
118 test->SetCqVerifierStepFn(
119 [engine = std::move(engine)](
120 grpc_event_engine::experimental::EventEngine::Duration max_step) {
121 ApplicationCallbackExecCtx callback_exec_ctx;
122 ExecCtx exec_ctx;
123 engine->Tick(max_step);
124 grpc_timer_manager_tick();
125 });
126 test->SetPostGrpcInitFunc([]() {
127 grpc_timer_manager_set_threading(false);
128 ExecCtx exec_ctx;
129 Executor::SetThreadingAll(false);
130 });
131 test->SetUp();
132 test->RunTest();
133 test->TearDown();
134 CHECK(!::testing::Test::HasFailure());
135 }
136
137 } // namespace grpc_core
138