httpscli_test.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #include <string.h>
20 
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23 
24 #include "absl/strings/str_format.h"
25 
26 #include <grpc/grpc.h>
27 #include <grpc/support/alloc.h>
28 #include <grpc/support/log.h>
30 #include <grpc/support/sync.h>
31 
33 #include "src/core/lib/gpr/env.h"
42 #include "test/core/util/port.h"
45 
46 namespace {
47 
48 grpc_core::Timestamp NSecondsTime(int seconds) {
51 }
52 
53 absl::Time AbslDeadlineSeconds(int s) {
55 }
56 
57 int g_argc;
58 char** g_argv;
59 int g_server_port;
61 
62 class HttpsCliTest : public ::testing::Test {
63  public:
64  HttpsCliTest() {
65  grpc_init();
67  grpc_pollset* pollset =
68  static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));
69  grpc_pollset_init(pollset, &mu_);
71  }
72  ~HttpsCliTest() override {
73  {
77  GRPC_CLOSURE_CREATE(DestroyPops, &pops_, grpc_schedule_on_exec_ctx));
78  }
79  grpc_shutdown();
80  }
81 
82  void RunAndKick(const std::function<void()>& f) {
84  f();
86  "pollset_kick",
88  }
89 
90  void PollUntil(const std::function<bool()>& predicate, absl::Time deadline) {
92  while (!predicate()) {
93  GPR_ASSERT(absl::Now() < deadline);
94  grpc_pollset_worker* worker = nullptr;
96  "pollset_work", grpc_pollset_work(grpc_polling_entity_pollset(&pops_),
97  &worker, NSecondsTime(1))));
100  }
102  }
103 
104  grpc_polling_entity* pops() { return &pops_; }
105 
106  protected:
107  static void SetUpTestSuite() {
109  g_argc, g_argv, true /* use_ssl */);
110  g_server = test_server.server;
111  g_server_port = test_server.port;
112  }
113 
115 
116  private:
117  static void DestroyPops(void* p, grpc_error_handle /*error*/) {
118  grpc_polling_entity* pops = static_cast<grpc_polling_entity*>(p);
121  }
122 
123  gpr_mu* mu_;
124  grpc_polling_entity pops_;
125 };
126 
127 struct RequestState {
128  explicit RequestState(HttpsCliTest* test) : test(test) {}
129 
130  ~RequestState() {
133  }
134 
135  HttpsCliTest* test;
136  bool done = false;
138 };
139 
140 void OnFinish(void* arg, grpc_error_handle error) {
141  RequestState* request_state = static_cast<RequestState*>(arg);
142  const char* expect =
143  "<html><head><title>Hello world!</title></head>"
144  "<body><p>This is a test</p></body></html>";
146  grpc_http_response response = request_state->response;
147  gpr_log(GPR_INFO, "response status=%d error=%s", response.status,
149  GPR_ASSERT(response.status == 200);
150  GPR_ASSERT(response.body_length == strlen(expect));
151  GPR_ASSERT(0 == memcmp(expect, response.body, response.body_length));
152  request_state->test->RunAndKick(
153  [request_state]() { request_state->done = true; });
154 }
155 
156 void OnFinishExpectFailure(void* arg, grpc_error_handle error) {
157  RequestState* request_state = static_cast<RequestState*>(arg);
158  grpc_http_response response = request_state->response;
159  gpr_log(GPR_INFO, "response status=%d error=%s", response.status,
162  request_state->test->RunAndKick(
163  [request_state]() { request_state->done = true; });
164 }
165 
166 TEST_F(HttpsCliTest, Get) {
167  RequestState request_state(this);
170  std::string host = absl::StrFormat("localhost:%d", g_server_port);
171  gpr_log(GPR_INFO, "requesting from %s", host.c_str());
172  memset(&req, 0, sizeof(req));
173  grpc_arg ssl_override_arg = grpc_channel_arg_string_create(
174  const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
175  const_cast<char*>("foo.test.google.fr"));
176  grpc_channel_args args = {1, &ssl_override_arg};
177  auto uri = grpc_core::URI::Create("https", host, "/get",
178  {} /* query params */, "" /* fragment */);
179  GPR_ASSERT(uri.ok());
182  std::move(*uri), &args, pops(), &req, NSecondsTime(15),
183  GRPC_CLOSURE_CREATE(OnFinish, &request_state,
184  grpc_schedule_on_exec_ctx),
185  &request_state.response,
187  http_request->Start();
188  PollUntil([&request_state]() { return request_state.done; },
189  AbslDeadlineSeconds(60));
190 }
191 
192 TEST_F(HttpsCliTest, Post) {
193  RequestState request_state(this);
196  std::string host = absl::StrFormat("localhost:%d", g_server_port);
197  gpr_log(GPR_INFO, "posting to %s", host.c_str());
198  memset(&req, 0, sizeof(req));
199  req.body = const_cast<char*>("hello");
200  req.body_length = 5;
201  grpc_arg ssl_override_arg = grpc_channel_arg_string_create(
202  const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
203  const_cast<char*>("foo.test.google.fr"));
204  grpc_channel_args args = {1, &ssl_override_arg};
205  auto uri = grpc_core::URI::Create("https", host, "/post",
206  {} /* query params */, "" /* fragment */);
207  GPR_ASSERT(uri.ok());
210  std::move(*uri), &args /* channel args */, pops(), &req,
211  NSecondsTime(15),
212  GRPC_CLOSURE_CREATE(OnFinish, &request_state,
213  grpc_schedule_on_exec_ctx),
214  &request_state.response,
216  http_request->Start();
217  PollUntil([&request_state]() { return request_state.done; },
218  AbslDeadlineSeconds(60));
219 }
220 
221 // The goal of this test is to make sure that we can cancel HTTP requests
222 // while they're waiting for a response from the server to finish their
223 // SSL handshakes. Note that the main focus of this test is to just exercise
224 // the relevant code paths and make sure there aren't any crashes etc., rather
225 // than to make sure that cancellation happens in a timely manner.
226 TEST_F(HttpsCliTest, CancelGetDuringSSLHandshake) {
227  // Start up a fake TCP server which accepts connections and then hangs,
228  // i.e. it won't send any bytes back to the client.
231  kWaitForClientToSendFirstBytes,
233  // Use multiple threads to try to trigger races etc.
234  int kNumThreads = 100;
235  std::vector<std::thread> threads;
236  threads.reserve(kNumThreads);
237  for (int i = 0; i < kNumThreads; i++) {
238  grpc_core::testing::FakeUdpAndTcpServer* fake_http_server_ptr =
239  &fake_http_server;
240  threads.push_back(std::thread([this, fake_http_server_ptr]() {
241  RequestState request_state(this);
244  memset(&req, 0, sizeof(req));
245  grpc_arg ssl_override_arg = grpc_channel_arg_string_create(
246  const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
247  const_cast<char*>("foo.test.google.fr"));
248  grpc_channel_args args = {1, &ssl_override_arg};
249  auto uri = grpc_core::URI::Create(
250  "https", fake_http_server_ptr->address(), "/get",
251  {} /* query params */, "" /* fragment */);
254  std::move(*uri), &args, pops(), &req, NSecondsTime(120),
255  GRPC_CLOSURE_CREATE(OnFinishExpectFailure, &request_state,
256  grpc_schedule_on_exec_ctx),
257  &request_state.response,
259  // Start a request. It will establish a TCP connection to the
260  // server and then begin an SSL handshake. The server won't send
261  // anything back though, so it will be stuck in its SSL handshake,
262  // waiting for the firt response from the server.
263  http_request->Start();
264  exec_ctx.Flush();
265  std::thread cancel_thread([&http_request]() {
266  // Give one second to let the client get into the middle of its
267  // SSL handshake, and then cancel the request.
270  http_request.reset();
271  });
272  // Poll with a deadline explicitly lower than the request timeout, so
273  // that we know that the request timeout isn't just kicking in.
274  PollUntil([&request_state]() { return request_state.done; },
275  AbslDeadlineSeconds(60));
276  cancel_thread.join();
277  }));
278  }
279  for (auto& t : threads) {
280  t.join();
281  }
282 }
283 
284 } // namespace
285 
286 int main(int argc, char** argv) {
287  ::testing::InitGoogleTest(&argc, argv);
288  grpc::testing::TestEnvironment env(&argc, argv);
289  // launch the test server later, so that --gtest_list_tests works
290  g_argc = argc;
291  g_argv = argv;
292  // run tests
293  return RUN_ALL_TESTS();
294 }
grpc_pollset_worker
struct grpc_pollset_worker grpc_pollset_worker
Definition: pollset.h:39
grpc_arg
Definition: grpc_types.h:103
absl::time_internal::cctz::seconds
std::chrono::duration< std::int_fast64_t > seconds
Definition: abseil-cpp/absl/time/internal/cctz/include/cctz/time_zone.h:40
GPR_INFO
#define GPR_INFO
Definition: include/grpc/impl/codegen/log.h:56
grpc_pollset_size
size_t grpc_pollset_size(void)
Definition: pollset.cc:56
iomgr.h
gpr_mu_unlock
GPRAPI void gpr_mu_unlock(gpr_mu *mu)
grpc_polling_entity_pollset
grpc_pollset * grpc_polling_entity_pollset(grpc_polling_entity *pollent)
Definition: polling_entity.cc:42
grpc_timeout_seconds_to_deadline
gpr_timespec grpc_timeout_seconds_to_deadline(int64_t time_s)
Definition: test/core/util/test_config.cc:81
log.h
port.h
generate.env
env
Definition: generate.py:37
grpc_core::ToAbslTime
absl::Time ToAbslTime(gpr_timespec ts)
Definition: src/core/lib/gprpp/time_util.cc:68
memset
return memset(p, 0, total)
absl::StrFormat
ABSL_MUST_USE_RESULT std::string StrFormat(const FormatSpec< Args... > &format, const Args &... args)
Definition: abseil-cpp/absl/strings/str_format.h:338
absl::Time
Definition: third_party/abseil-cpp/absl/time/time.h:642
grpc_core::MutexLockForGprMu
Definition: src/core/lib/gprpp/sync.h:152
test
Definition: spinlock_test.cc:36
string.h
grpc_core::Timestamp
Definition: src/core/lib/gprpp/time.h:62
testing::Test::SetUpTestSuite
static void SetUpTestSuite()
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:417
gpr_free
GPRAPI void gpr_free(void *ptr)
Definition: alloc.cc:51
test_server
Definition: test_server.py:1
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
error
grpc_error_handle error
Definition: retry_filter.cc:499
time_util.h
env.h
grpc_pollset_work
grpc_error_handle grpc_pollset_work(grpc_pollset *pollset, grpc_pollset_worker **worker, grpc_core::Timestamp deadline)
Definition: pollset.cc:45
GRPC_LOG_IF_ERROR
#define GRPC_LOG_IF_ERROR(what, error)
Definition: error.h:398
grpc_channel_arg_string_create
grpc_arg grpc_channel_arg_string_create(char *name, char *value)
Definition: channel_args.cc:476
grpc_core::HttpRequest::Post
static OrphanablePtr< HttpRequest > Post(URI uri, const grpc_channel_args *args, grpc_polling_entity *pollent, const grpc_http_request *request, Timestamp deadline, grpc_closure *on_done, grpc_http_response *response, RefCountedPtr< grpc_channel_credentials > channel_creds) GRPC_MUST_USE_RESULT
Definition: httpcli.cc:95
xds_manager.p
p
Definition: xds_manager.py:60
GRPC_CLOSURE_CREATE
#define GRPC_CLOSURE_CREATE(cb, cb_arg, scheduler)
Definition: closure.h:160
grpc_core::CreateHttpRequestSSLCredentials
RefCountedPtr< grpc_channel_credentials > CreateHttpRequestSSLCredentials()
Definition: httpcli_security_connector.cc:208
credentials.h
grpc_channel_args
Definition: grpc_types.h:132
threads
static uv_thread_t * threads
Definition: threadpool.c:38
testing::Test
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:402
mu_
Mutex mu_
Definition: oob_backend_metric.cc:115
grpc_pollset_init
void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu)
Definition: pollset.cc:33
gpr_zalloc
GPRAPI void * gpr_zalloc(size_t size)
Definition: alloc.cc:40
absl::synchronization_internal::Get
static GraphId Get(const IdMap &id, int num)
Definition: abseil-cpp/absl/synchronization/internal/graphcycles_test.cc:44
string_util.h
grpc_http_response
Definition: src/core/lib/http/parser.h:85
main
int main(int argc, char **argv)
Definition: httpscli_test.cc:286
httpcli_test_util.h
autogen_x86imm.f
f
Definition: autogen_x86imm.py:9
asyncio_get_stats.args
args
Definition: asyncio_get_stats.py:40
grpc_core::testing::FakeUdpAndTcpServer::address
const char * address()
Definition: fake_udp_and_tcp_server.h:92
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
GPR_ASSERT
#define GPR_ASSERT(x)
Definition: include/grpc/impl/codegen/log.h:94
GRPC_SSL_TARGET_NAME_OVERRIDE_ARG
#define GRPC_SSL_TARGET_NAME_OVERRIDE_ARG
Definition: grpc_types.h:278
gen_stats_data.c_str
def c_str(s, encoding='ascii')
Definition: gen_stats_data.py:38
grpc_core::ExecCtx::Flush
bool Flush()
Definition: exec_ctx.cc:69
req
static uv_connect_t req
Definition: test-connection-fail.c:30
grpc_ares_wrapper.h
gpr_log
GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format,...) GPR_PRINT_FORMAT_CHECK(4
worker
Definition: worker.py:1
grpc_polling_entity_create_from_pollset
grpc_polling_entity grpc_polling_entity_create_from_pollset(grpc_pollset *pollset)
Definition: polling_entity.cc:34
gpr_sleep_until
GPRAPI void gpr_sleep_until(gpr_timespec until)
httpcli_ssl_credentials.h
httpcli.h
grpc_core::testing::FakeUdpAndTcpServer
Definition: fake_udp_and_tcp_server.h:72
grpc.h
done
struct tab * done
Definition: bloaty/third_party/zlib/examples/enough.c:176
arg
Definition: cmdline.cc:40
time.h
gpr_mu_lock
GPRAPI void gpr_mu_lock(gpr_mu *mu)
grpc_http_response_destroy
void grpc_http_response_destroy(grpc_http_response *response)
Definition: src/core/lib/http/parser.cc:434
grpc_polling_entity
Definition: polling_entity.h:38
RUN_ALL_TESTS
int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2471
grpc_core::testing::FakeUdpAndTcpServer::AcceptMode
AcceptMode
Definition: fake_udp_and_tcp_server.h:79
grpc_pollset_kick
grpc_error_handle grpc_pollset_kick(grpc_pollset *pollset, grpc_pollset_worker *specific_worker)
Definition: pollset.cc:51
fake_udp_and_tcp_server.h
grpc_core::ExecCtx
Definition: exec_ctx.h:97
gpr_subprocess
struct gpr_subprocess gpr_subprocess
Definition: test/core/util/subprocess.h:24
subprocess.h
test_config.h
update_failure_list.test
test
Definition: bloaty/third_party/protobuf/conformance/update_failure_list.py:69
absl::Now
ABSL_NAMESPACE_BEGIN Time Now()
Definition: abseil-cpp/absl/time/clock.cc:39
testing::InitGoogleTest
GTEST_API_ void InitGoogleTest(int *argc, char **argv)
Definition: bloaty/third_party/googletest/googletest/src/gtest.cc:6106
grpc_core::HttpRequest::Get
static OrphanablePtr< HttpRequest > Get(URI uri, const grpc_channel_args *args, grpc_polling_entity *pollent, const grpc_http_request *request, Timestamp deadline, grpc_closure *on_done, grpc_http_response *response, RefCountedPtr< grpc_channel_credentials > channel_creds) GRPC_MUST_USE_RESULT
Definition: httpcli.cc:69
testing::Test::TearDownTestSuite
static void TearDownTestSuite()
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:427
gpr_mu
pthread_mutex_t gpr_mu
Definition: impl/codegen/sync_posix.h:47
exec_ctx
grpc_core::ExecCtx exec_ctx
Definition: end2end_binder_transport_test.cc:75
grpc_error_std_string
std::string grpc_error_std_string(grpc_error_handle error)
Definition: error.cc:944
kNumThreads
const int kNumThreads
Definition: thread_stress_test.cc:46
grpc_pollset_shutdown
void grpc_pollset_shutdown(grpc_pollset *pollset, grpc_closure *closure)
Definition: pollset.cc:37
absl::str_format_internal::LengthMod::t
@ t
grpc_core::URI::Create
static absl::StatusOr< URI > Create(std::string scheme, std::string authority, std::string path, std::vector< QueryParam > query_parameter_pairs, std::string fragment)
Definition: uri_parser.cc:289
alloc.h
grpc_core::OrphanablePtr
std::unique_ptr< T, Deleter > OrphanablePtr
Definition: orphanable.h:64
asyncio_get_stats.response
response
Definition: asyncio_get_stats.py:28
grpc::testing::TestEnvironment
Definition: test/core/util/test_config.h:54
g_server
static grpc_server * g_server
Definition: api_fuzzer.cc:69
arg
struct arg arg
gpr_subprocess_destroy
void gpr_subprocess_destroy(gpr_subprocess *p)
grpc_core::testing::FakeUdpAndTcpServer::CloseSocketUponCloseFromPeer
static ProcessReadResult CloseSocketUponCloseFromPeer(int bytes_received_size, int read_error, int s)
Definition: fake_udp_and_tcp_server.cc:179
grpc_core::testing::StartHttpRequestTestServer
HttpRequestTestServer StartHttpRequestTestServer(int argc, char **argv, bool use_ssl)
Definition: httpcli_test_util.cc:40
grpc_init
GRPCAPI void grpc_init(void)
Definition: init.cc:146
grpc_error
Definition: error_internal.h:42
function
std::function< bool(GrpcTool *, int, const char **, const CliCredentials &, GrpcToolOutputCallback)> function
Definition: grpc_tool.cc:250
grpc_core::Timestamp::FromTimespecRoundUp
static Timestamp FromTimespecRoundUp(gpr_timespec t)
Definition: src/core/lib/gprpp/time.cc:136
grpc_pollset
Definition: bm_cq_multiple_threads.cc:37
grpc_pollset_destroy
void grpc_pollset_destroy(grpc_pollset *pollset)
Definition: pollset.cc:41
sync.h
grpc_shutdown
GRPCAPI void grpc_shutdown(void)
Definition: init.cc:209
thread
static uv_thread_t thread
Definition: test-async-null-cb.c:29
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
GRPC_ERROR_IS_NONE
#define GRPC_ERROR_IS_NONE(err)
Definition: error.h:241
grpc_http_request
Definition: src/core/lib/http/parser.h:69
TEST_F
#define TEST_F(test_fixture, test_name)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2367


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:00:14