1
2 //
3 //
4 // Copyright 2015 gRPC authors.
5 //
6 // Licensed under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 // You may obtain a copy of the License at
9 //
10 // http://www.apache.org/licenses/LICENSE-2.0
11 //
12 // Unless required by applicable law or agreed to in writing, software
13 // distributed under the License is distributed on an "AS IS" BASIS,
14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 // See the License for the specific language governing permissions and
16 // limitations under the License.
17 //
18 //
19
20 #include "test/core/end2end/end2end_tests.h"
21
22 #include <regex>
23 #include <tuple>
24
25 #include "absl/log/check.h"
26 #include "absl/log/log.h"
27 #include "absl/memory/memory.h"
28 #include "absl/random/random.h"
29
30 #include <grpc/byte_buffer_reader.h>
31 #include <grpc/compression.h>
32 #include <grpc/grpc.h>
33
34 #include "src/core/config/core_configuration.h"
35 #include "src/core/lib/event_engine/default_event_engine.h"
36 #include "src/core/util/no_destruct.h"
37 #include "test/core/end2end/cq_verifier.h"
38
39 namespace grpc_core {
40
41 bool g_is_fuzzing_core_e2e_tests = false;
42
RandomSlice(size_t length)43 Slice RandomSlice(size_t length) {
44 size_t i;
45 static const char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890";
46 std::vector<char> output;
47 output.resize(length);
48 for (i = 0; i < length; ++i) {
49 output[i] = chars[rand() % static_cast<int>(sizeof(chars) - 1)];
50 }
51 return Slice::FromCopiedBuffer(output);
52 }
53
RandomBinarySlice(size_t length)54 Slice RandomBinarySlice(size_t length) {
55 size_t i;
56 std::vector<uint8_t> output;
57 output.resize(length);
58 for (i = 0; i < length; ++i) {
59 output[i] = rand();
60 }
61 return Slice::FromCopiedBuffer(output);
62 }
63
SetUp()64 void CoreEnd2endTest::SetUp() {
65 CoreConfiguration::Reset();
66 initialized_ = false;
67 grpc_prewarm_os_for_tests();
68 }
69
TearDown()70 void CoreEnd2endTest::TearDown() {
71 const bool do_shutdown = fixture_ != nullptr;
72 std::shared_ptr<grpc_event_engine::experimental::EventEngine> ee;
73 if (grpc_is_initialized()) {
74 ee = grpc_event_engine::experimental::GetDefaultEventEngine();
75 }
76 ShutdownAndDestroyClient();
77 ShutdownAndDestroyServer();
78 cq_verifier_.reset();
79 if (cq_ != nullptr) {
80 grpc_completion_queue_shutdown(cq_);
81 grpc_event ev;
82 do {
83 ev = grpc_completion_queue_next(cq_, grpc_timeout_seconds_to_deadline(5),
84 nullptr);
85 } while (ev.type != GRPC_QUEUE_SHUTDOWN);
86 grpc_completion_queue_destroy(cq_);
87 cq_ = nullptr;
88 }
89 fixture_.reset();
90 // Creating an EventEngine requires gRPC initialization, which the NoOp test
91 // does not do. Skip the EventEngine check if unnecessary.
92 if (ee != nullptr) {
93 quiesce_event_engine_(std::move(ee));
94 }
95 if (do_shutdown) {
96 grpc_shutdown_blocking();
97 // This will wait until gRPC shutdown has actually happened to make sure
98 // no gRPC resources (such as thread) are active. (timeout = 10s)
99 if (!grpc_wait_until_shutdown(10)) {
100 LOG(ERROR) << "Timeout in waiting for gRPC shutdown";
101 }
102 }
103 CHECK_EQ(client_, nullptr);
104 CHECK_EQ(server_, nullptr);
105 initialized_ = false;
106 }
107
Create()108 CoreEnd2endTest::Call CoreEnd2endTest::ClientCallBuilder::Create() {
109 if (auto* u = absl::get_if<UnregisteredCall>(&call_selector_)) {
110 absl::optional<Slice> host;
111 if (u->host.has_value()) host = Slice::FromCopiedString(*u->host);
112 test_.ForceInitialized();
113 return Call(
114 grpc_channel_create_call(
115 test_.client(), parent_call_, propagation_mask_, test_.cq(),
116 Slice::FromCopiedString(u->method).c_slice(),
117 host.has_value() ? &host->c_slice() : nullptr, deadline_, nullptr),
118 &test_);
119 } else {
120 return Call(grpc_channel_create_registered_call(
121 test_.client(), parent_call_, propagation_mask_, test_.cq(),
122 absl::get<void*>(call_selector_), deadline_, nullptr),
123 &test_);
124 }
125 }
126
ServerRegisteredMethod(CoreEnd2endTest * test,absl::string_view name,grpc_server_register_method_payload_handling payload_handling)127 CoreEnd2endTest::ServerRegisteredMethod::ServerRegisteredMethod(
128 CoreEnd2endTest* test, absl::string_view name,
129 grpc_server_register_method_payload_handling payload_handling) {
130 CHECK_EQ(test->server_, nullptr);
131 test->pre_server_start_ = [old = std::move(test->pre_server_start_),
132 handle = handle_, name = std::string(name),
133 payload_handling](grpc_server* server) mutable {
134 *handle = grpc_server_register_method(server, name.c_str(), nullptr,
135 payload_handling, 0);
136 old(server);
137 };
138 }
139
IncomingCall(CoreEnd2endTest & test,int tag)140 CoreEnd2endTest::IncomingCall::IncomingCall(CoreEnd2endTest& test, int tag)
141 : impl_(std::make_unique<Impl>(&test)) {
142 test.ForceInitialized();
143 EXPECT_EQ(
144 grpc_server_request_call(test.server(), impl_->call.call_ptr(),
145 &impl_->call_details, &impl_->request_metadata,
146 test.cq(), test.cq(), CqVerifier::tag(tag)),
147 GRPC_CALL_OK);
148 }
149
IncomingCall(CoreEnd2endTest & test,void * method,IncomingMessage * message,int tag)150 CoreEnd2endTest::IncomingCall::IncomingCall(CoreEnd2endTest& test, void* method,
151 IncomingMessage* message, int tag)
152 : impl_(std::make_unique<Impl>(&test)) {
153 test.ForceInitialized();
154 impl_->call_details.method = grpc_empty_slice();
155 EXPECT_EQ(grpc_server_request_registered_call(
156 test.server(), method, impl_->call.call_ptr(),
157 &impl_->call_details.deadline, &impl_->request_metadata,
158 message == nullptr ? nullptr : message->raw_payload_ptr(),
159 test.cq(), test.cq(), CqVerifier::tag(tag)),
160 GRPC_CALL_OK);
161 }
162
GetInitialMetadata(absl::string_view key) const163 absl::optional<std::string> CoreEnd2endTest::IncomingCall::GetInitialMetadata(
164 absl::string_view key) const {
165 return FindInMetadataArray(impl_->request_metadata, key);
166 }
167
ForceInitialized()168 void CoreEnd2endTest::ForceInitialized() {
169 if (!initialized_) {
170 initialized_ = true;
171 InitServer(ChannelArgs());
172 InitClient(ChannelArgs());
173 }
174 }
175
RegisterTest(absl::string_view suite,absl::string_view name,MakeTestFn make_test,SourceLocation)176 void CoreEnd2endTestRegistry::RegisterTest(absl::string_view suite,
177 absl::string_view name,
178 MakeTestFn make_test,
179 SourceLocation) {
180 if (absl::StartsWith(name, "DISABLED_")) return;
181 auto& tests = tests_by_suite_[suite];
182 CHECK_EQ(tests.count(name), 0u);
183 tests[name] = std::move(make_test);
184 }
185
RegisterSuite(absl::string_view suite,std::vector<const CoreTestConfiguration * > configs,SourceLocation)186 void CoreEnd2endTestRegistry::RegisterSuite(
187 absl::string_view suite, std::vector<const CoreTestConfiguration*> configs,
188 SourceLocation) {
189 CHECK_EQ(suites_.count(suite), 0u);
190 suites_[suite] = std::move(configs);
191 }
192
193 namespace {
194 template <typename Map>
KeysFrom(const Map & map)195 std::vector<absl::string_view> KeysFrom(const Map& map) {
196 std::vector<absl::string_view> out;
197 out.reserve(map.size());
198 for (const auto& elem : map) {
199 out.push_back(elem.first);
200 }
201 return out;
202 }
203 } // namespace
204
AllTests()205 std::vector<CoreEnd2endTestRegistry::Test> CoreEnd2endTestRegistry::AllTests() {
206 std::vector<Test> tests;
207 // Sort inputs to ensure outputs are deterministic
208 for (auto& suite_configs : suites_) {
209 std::sort(suite_configs.second.begin(), suite_configs.second.end(),
210 [](const auto* a, const auto* b) { return a->name < b->name; });
211 }
212 for (const auto& suite_configs : suites_) {
213 if (suite_configs.second.empty()) {
214 fprintf(
215 stderr, "%s\n",
216 absl::StrCat("Suite ", suite_configs.first, " has no tests").c_str());
217 }
218 for (const auto& test_factory : tests_by_suite_[suite_configs.first]) {
219 for (const auto* config : suite_configs.second) {
220 tests.push_back(Test{suite_configs.first, test_factory.first, config,
221 test_factory.second});
222 }
223 }
224 }
225 return tests;
226 }
227
228 } // namespace grpc_core
229