• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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