httpcli_test.cc 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  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. #include "src/core/lib/http/httpcli.h"
  19. #include <string.h>
  20. #include <gmock/gmock.h>
  21. #include <gtest/gtest.h>
  22. #include <grpc/grpc.h>
  23. #include <grpc/support/alloc.h>
  24. #include <grpc/support/log.h>
  25. #include <grpc/support/string_util.h>
  26. #include <grpc/support/sync.h>
  27. #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
  28. #include "src/core/lib/gprpp/time.h"
  29. #include "src/core/lib/iomgr/iomgr.h"
  30. #include "test/core/http/httpcli_test_util.h"
  31. #include "test/core/util/fake_udp_and_tcp_server.h"
  32. #include "test/core/util/port.h"
  33. #include "test/core/util/subprocess.h"
  34. #include "test/core/util/test_config.h"
  35. namespace {
  36. grpc_core::Timestamp NSecondsTime(int seconds) {
  37. return grpc_core::Timestamp::FromTimespecRoundUp(
  38. grpc_timeout_seconds_to_deadline(seconds));
  39. }
  40. absl::Time AbslDeadlineSeconds(int s) {
  41. return grpc_core::ToAbslTime(grpc_timeout_seconds_to_deadline(s));
  42. }
  43. int g_argc;
  44. char** g_argv;
  45. int g_server_port;
  46. gpr_subprocess* g_server;
  47. class HttpRequestTest : public ::testing::Test {
  48. public:
  49. HttpRequestTest() {
  50. grpc_init();
  51. grpc_core::ExecCtx exec_ctx;
  52. grpc_pollset* pollset =
  53. static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));
  54. grpc_pollset_init(pollset, &mu_);
  55. pops_ = grpc_polling_entity_create_from_pollset(pollset);
  56. }
  57. ~HttpRequestTest() override {
  58. {
  59. grpc_core::ExecCtx exec_ctx;
  60. grpc_pollset_shutdown(
  61. grpc_polling_entity_pollset(&pops_),
  62. GRPC_CLOSURE_CREATE(DestroyPops, &pops_, grpc_schedule_on_exec_ctx));
  63. }
  64. grpc_shutdown();
  65. }
  66. void RunAndKick(const std::function<void()>& f) {
  67. grpc_core::MutexLockForGprMu lock(mu_);
  68. f();
  69. GPR_ASSERT(GRPC_LOG_IF_ERROR(
  70. "pollset_kick",
  71. grpc_pollset_kick(grpc_polling_entity_pollset(&pops_), nullptr)));
  72. }
  73. void PollUntil(const std::function<bool()>& predicate, absl::Time deadline) {
  74. gpr_mu_lock(mu_);
  75. while (!predicate()) {
  76. GPR_ASSERT(absl::Now() < deadline);
  77. grpc_pollset_worker* worker = nullptr;
  78. GPR_ASSERT(GRPC_LOG_IF_ERROR(
  79. "pollset_work", grpc_pollset_work(grpc_polling_entity_pollset(&pops_),
  80. &worker, NSecondsTime(1))));
  81. gpr_mu_unlock(mu_);
  82. gpr_mu_lock(mu_);
  83. }
  84. gpr_mu_unlock(mu_);
  85. }
  86. grpc_polling_entity* pops() { return &pops_; }
  87. protected:
  88. static void SetUpTestSuite() {
  89. auto test_server = grpc_core::testing::StartHttpRequestTestServer(
  90. g_argc, g_argv, false /* use_ssl */);
  91. g_server = test_server.server;
  92. g_server_port = test_server.port;
  93. }
  94. static void TearDownTestSuite() { gpr_subprocess_destroy(g_server); }
  95. private:
  96. static void DestroyPops(void* p, grpc_error_handle /*error*/) {
  97. grpc_polling_entity* pops = static_cast<grpc_polling_entity*>(p);
  98. grpc_pollset_destroy(grpc_polling_entity_pollset(pops));
  99. gpr_free(grpc_polling_entity_pollset(pops));
  100. }
  101. gpr_mu* mu_;
  102. grpc_polling_entity pops_;
  103. };
  104. struct RequestState {
  105. explicit RequestState(HttpRequestTest* test) : test(test) {}
  106. ~RequestState() {
  107. grpc_core::ExecCtx exec_ctx;
  108. grpc_http_response_destroy(&response);
  109. }
  110. HttpRequestTest* test;
  111. bool done = false;
  112. grpc_http_response response = {};
  113. grpc_pollset_set* pollset_set_to_destroy_eagerly = nullptr;
  114. };
  115. void OnFinish(void* arg, grpc_error_handle error) {
  116. RequestState* request_state = static_cast<RequestState*>(arg);
  117. if (request_state->pollset_set_to_destroy_eagerly != nullptr) {
  118. // Destroy the request's polling entity param. The goal is to try to catch a
  119. // bug where we might still be referencing the polling entity by
  120. // a pending TCP connect.
  121. grpc_pollset_set_destroy(request_state->pollset_set_to_destroy_eagerly);
  122. }
  123. const char* expect =
  124. "<html><head><title>Hello world!</title></head>"
  125. "<body><p>This is a test</p></body></html>";
  126. GPR_ASSERT(error == GRPC_ERROR_NONE);
  127. grpc_http_response response = request_state->response;
  128. gpr_log(GPR_INFO, "response status=%d error=%s", response.status,
  129. grpc_error_std_string(error).c_str());
  130. GPR_ASSERT(response.status == 200);
  131. GPR_ASSERT(response.body_length == strlen(expect));
  132. GPR_ASSERT(0 == memcmp(expect, response.body, response.body_length));
  133. request_state->test->RunAndKick(
  134. [request_state]() { request_state->done = true; });
  135. }
  136. void OnFinishExpectFailure(void* arg, grpc_error_handle error) {
  137. RequestState* request_state = static_cast<RequestState*>(arg);
  138. if (request_state->pollset_set_to_destroy_eagerly != nullptr) {
  139. // Destroy the request's polling entity param. The goal is to try to catch a
  140. // bug where we might still be referencing the polling entity by
  141. // a pending TCP connect.
  142. grpc_pollset_set_destroy(request_state->pollset_set_to_destroy_eagerly);
  143. }
  144. grpc_http_response response = request_state->response;
  145. gpr_log(GPR_INFO, "response status=%d error=%s", response.status,
  146. grpc_error_std_string(error).c_str());
  147. GPR_ASSERT(error != GRPC_ERROR_NONE);
  148. request_state->test->RunAndKick(
  149. [request_state]() { request_state->done = true; });
  150. }
  151. TEST_F(HttpRequestTest, Get) {
  152. RequestState request_state(this);
  153. grpc_http_request req;
  154. grpc_core::ExecCtx exec_ctx;
  155. std::string host = absl::StrFormat("localhost:%d", g_server_port);
  156. gpr_log(GPR_INFO, "requesting from %s", host.c_str());
  157. memset(&req, 0, sizeof(req));
  158. auto uri = grpc_core::URI::Create("http", host, "/get", {} /* query params */,
  159. "" /* fragment */);
  160. GPR_ASSERT(uri.ok());
  161. grpc_core::OrphanablePtr<grpc_core::HttpRequest> http_request =
  162. grpc_core::HttpRequest::Get(
  163. std::move(*uri), nullptr /* channel args */, pops(), &req,
  164. NSecondsTime(15),
  165. GRPC_CLOSURE_CREATE(OnFinish, &request_state,
  166. grpc_schedule_on_exec_ctx),
  167. &request_state.response,
  168. grpc_core::RefCountedPtr<grpc_channel_credentials>(
  169. grpc_insecure_credentials_create()));
  170. http_request->Start();
  171. PollUntil([&request_state]() { return request_state.done; },
  172. AbslDeadlineSeconds(60));
  173. }
  174. TEST_F(HttpRequestTest, Post) {
  175. RequestState request_state(this);
  176. grpc_http_request req;
  177. grpc_core::ExecCtx exec_ctx;
  178. std::string host = absl::StrFormat("localhost:%d", g_server_port);
  179. gpr_log(GPR_INFO, "posting to %s", host.c_str());
  180. memset(&req, 0, sizeof(req));
  181. req.body = const_cast<char*>("hello");
  182. req.body_length = 5;
  183. auto uri = grpc_core::URI::Create("http", host, "/post",
  184. {} /* query params */, "" /* fragment */);
  185. GPR_ASSERT(uri.ok());
  186. grpc_core::OrphanablePtr<grpc_core::HttpRequest> http_request =
  187. grpc_core::HttpRequest::Post(
  188. std::move(*uri), nullptr /* channel args */, pops(), &req,
  189. NSecondsTime(15),
  190. GRPC_CLOSURE_CREATE(OnFinish, &request_state,
  191. grpc_schedule_on_exec_ctx),
  192. &request_state.response,
  193. grpc_core::RefCountedPtr<grpc_channel_credentials>(
  194. grpc_insecure_credentials_create()));
  195. http_request->Start();
  196. PollUntil([&request_state]() { return request_state.done; },
  197. AbslDeadlineSeconds(60));
  198. }
  199. int g_fake_non_responsive_dns_server_port;
  200. void InjectNonResponsiveDNSServer(ares_channel channel) {
  201. gpr_log(GPR_DEBUG,
  202. "Injecting broken nameserver list. Bad server address:|[::1]:%d|.",
  203. g_fake_non_responsive_dns_server_port);
  204. // Configure a non-responsive DNS server at the front of c-ares's nameserver
  205. // list.
  206. struct ares_addr_port_node dns_server_addrs[1];
  207. dns_server_addrs[0].family = AF_INET6;
  208. (reinterpret_cast<char*>(&dns_server_addrs[0].addr.addr6))[15] = 0x1;
  209. dns_server_addrs[0].tcp_port = g_fake_non_responsive_dns_server_port;
  210. dns_server_addrs[0].udp_port = g_fake_non_responsive_dns_server_port;
  211. dns_server_addrs[0].next = nullptr;
  212. GPR_ASSERT(ares_set_servers_ports(channel, dns_server_addrs) == ARES_SUCCESS);
  213. }
  214. TEST_F(HttpRequestTest, CancelGetDuringDNSResolution) {
  215. // Inject an unresponsive DNS server into the resolver's DNS server config
  216. grpc_core::testing::FakeUdpAndTcpServer fake_dns_server(
  217. grpc_core::testing::FakeUdpAndTcpServer::AcceptMode::
  218. kWaitForClientToSendFirstBytes,
  219. grpc_core::testing::FakeUdpAndTcpServer::CloseSocketUponCloseFromPeer);
  220. g_fake_non_responsive_dns_server_port = fake_dns_server.port();
  221. void (*prev_test_only_inject_config)(ares_channel channel) =
  222. grpc_ares_test_only_inject_config;
  223. grpc_ares_test_only_inject_config = InjectNonResponsiveDNSServer;
  224. // Run the same test on several threads in parallel to try to trigger races
  225. // etc.
  226. int kNumThreads = 100;
  227. std::vector<std::thread> threads;
  228. threads.reserve(kNumThreads);
  229. for (int i = 0; i < kNumThreads; i++) {
  230. threads.push_back(std::thread([this]() {
  231. RequestState request_state(this);
  232. grpc_http_request req;
  233. grpc_core::ExecCtx exec_ctx;
  234. memset(&req, 0, sizeof(grpc_http_request));
  235. auto uri = grpc_core::URI::Create(
  236. "http", "dont-care-since-wont-be-resolved.test.com:443", "/get",
  237. {} /* query params */, "" /* fragment */);
  238. GPR_ASSERT(uri.ok());
  239. grpc_core::OrphanablePtr<grpc_core::HttpRequest> http_request =
  240. grpc_core::HttpRequest::Get(
  241. std::move(*uri), nullptr /* channel args */, pops(), &req,
  242. NSecondsTime(120),
  243. GRPC_CLOSURE_CREATE(OnFinishExpectFailure, &request_state,
  244. grpc_schedule_on_exec_ctx),
  245. &request_state.response,
  246. grpc_core::RefCountedPtr<grpc_channel_credentials>(
  247. grpc_insecure_credentials_create()));
  248. http_request->Start();
  249. std::thread cancel_thread([&http_request]() {
  250. gpr_sleep_until(grpc_timeout_seconds_to_deadline(1));
  251. grpc_core::ExecCtx exec_ctx;
  252. http_request.reset();
  253. });
  254. // Poll with a deadline explicitly lower than the request timeout, so
  255. // that we know that the request timeout isn't just kicking in.
  256. PollUntil([&request_state]() { return request_state.done; },
  257. AbslDeadlineSeconds(60));
  258. cancel_thread.join();
  259. }));
  260. }
  261. for (auto& t : threads) {
  262. t.join();
  263. }
  264. grpc_ares_test_only_inject_config = prev_test_only_inject_config;
  265. }
  266. TEST_F(HttpRequestTest, CancelGetWhileReadingResponse) {
  267. // Start up a fake HTTP server which just accepts connections
  268. // and then hangs, i.e. does not send back any bytes to the client.
  269. // The goal here is to get the client to connect to this fake server
  270. // and send a request, and then sit waiting for a response. Then, a
  271. // separate thread will cancel the HTTP request, and that should let it
  272. // complete.
  273. grpc_core::testing::FakeUdpAndTcpServer fake_http_server(
  274. grpc_core::testing::FakeUdpAndTcpServer::AcceptMode::
  275. kWaitForClientToSendFirstBytes,
  276. grpc_core::testing::FakeUdpAndTcpServer::CloseSocketUponCloseFromPeer);
  277. // Run the same test on several threads in parallel to try to trigger races
  278. // etc.
  279. int kNumThreads = 100;
  280. std::vector<std::thread> threads;
  281. threads.reserve(kNumThreads);
  282. for (int i = 0; i < kNumThreads; i++) {
  283. grpc_core::testing::FakeUdpAndTcpServer* fake_http_server_ptr =
  284. &fake_http_server;
  285. threads.push_back(std::thread([this, fake_http_server_ptr]() {
  286. RequestState request_state(this);
  287. grpc_http_request req;
  288. grpc_core::ExecCtx exec_ctx;
  289. memset(&req, 0, sizeof(req));
  290. auto uri = grpc_core::URI::Create("http", fake_http_server_ptr->address(),
  291. "/get", {} /* query params */,
  292. "" /* fragment */);
  293. GPR_ASSERT(uri.ok());
  294. grpc_core::OrphanablePtr<grpc_core::HttpRequest> http_request =
  295. grpc_core::HttpRequest::Get(
  296. std::move(*uri), nullptr /* channel args */, pops(), &req,
  297. NSecondsTime(120),
  298. GRPC_CLOSURE_CREATE(OnFinishExpectFailure, &request_state,
  299. grpc_schedule_on_exec_ctx),
  300. &request_state.response,
  301. grpc_core::RefCountedPtr<grpc_channel_credentials>(
  302. grpc_insecure_credentials_create()));
  303. http_request->Start();
  304. exec_ctx.Flush();
  305. std::thread cancel_thread([&http_request]() {
  306. gpr_sleep_until(grpc_timeout_seconds_to_deadline(1));
  307. grpc_core::ExecCtx exec_ctx;
  308. http_request.reset();
  309. });
  310. // Poll with a deadline explicitly lower than the request timeout, so
  311. // that we know that the request timeout isn't just kicking in.
  312. PollUntil([&request_state]() { return request_state.done; },
  313. AbslDeadlineSeconds(60));
  314. cancel_thread.join();
  315. }));
  316. }
  317. for (auto& t : threads) {
  318. t.join();
  319. }
  320. }
  321. // The main point of this test is just to exercise the machinery around
  322. // cancellation during TCP connection establishment, to make sure there are no
  323. // crashes/races etc. This test doesn't actually verify that cancellation during
  324. // TCP setup is happening, though. For that, we would need to induce packet loss
  325. // in the test.
  326. TEST_F(HttpRequestTest, CancelGetRacesWithConnectionFailure) {
  327. // Grab an unoccupied port but don't listen on it. The goal
  328. // here is just to have a server address that will reject
  329. // TCP connection setups.
  330. // Note that because the server is rejecting TCP connections, we
  331. // don't really need to cancel the HTTP requests in this test case
  332. // in order for them proceeed i.e. in order for them to pass. The test
  333. // is still beneficial though because it can exercise the same code paths
  334. // that would get taken if the HTTP request was cancelled while the TCP
  335. // connect attempt was actually hanging.
  336. int fake_server_port = grpc_pick_unused_port_or_die();
  337. std::string fake_server_address =
  338. absl::StrCat("[::1]:", std::to_string(fake_server_port));
  339. // Run the same test on several threads in parallel to try to trigger races
  340. // etc.
  341. int kNumThreads = 100;
  342. std::vector<std::thread> threads;
  343. threads.reserve(kNumThreads);
  344. for (int i = 0; i < kNumThreads; i++) {
  345. threads.push_back(std::thread([this, fake_server_address]() {
  346. RequestState request_state(this);
  347. grpc_http_request req;
  348. grpc_core::ExecCtx exec_ctx;
  349. memset(&req, 0, sizeof(req));
  350. auto uri =
  351. grpc_core::URI::Create("http", fake_server_address, "/get",
  352. {} /* query params */, "" /* fragment */);
  353. GPR_ASSERT(uri.ok());
  354. grpc_core::OrphanablePtr<grpc_core::HttpRequest> http_request =
  355. grpc_core::HttpRequest::Get(
  356. std::move(*uri), nullptr /* channel args */, pops(), &req,
  357. NSecondsTime(120),
  358. GRPC_CLOSURE_CREATE(OnFinishExpectFailure, &request_state,
  359. grpc_schedule_on_exec_ctx),
  360. &request_state.response,
  361. grpc_core::RefCountedPtr<grpc_channel_credentials>(
  362. grpc_insecure_credentials_create()));
  363. // Start the HTTP request. We will ~immediately begin a TCP connect
  364. // attempt because there's no name to resolve.
  365. http_request->Start();
  366. exec_ctx.Flush();
  367. // Spawn a separate thread which ~immediately cancels the HTTP request.
  368. // Note that even though the server is rejecting TCP connections, it can
  369. // still take some time for the client to receive that rejection. So
  370. // cancelling the request now can trigger the code paths that would get
  371. // taken if the TCP connection was truly hanging e.g. from packet loss.
  372. // The goal is just to make sure there are no crashes, races, etc.
  373. std::thread cancel_thread([&http_request]() {
  374. grpc_core::ExecCtx exec_ctx;
  375. http_request.reset();
  376. });
  377. // Poll with a deadline explicitly lower than the request timeout, so
  378. // that we know that the request timeout isn't just kicking in.
  379. PollUntil([&request_state]() { return request_state.done; },
  380. AbslDeadlineSeconds(60));
  381. cancel_thread.join();
  382. }));
  383. }
  384. for (auto& t : threads) {
  385. t.join();
  386. }
  387. }
  388. // The pollent parameter passed to HttpRequest::Get or Post is owned by
  389. // the caller and must not be referenced by the HttpRequest after the
  390. // requests's on_done callback is invoked. This test verifies that this
  391. // isn't happening by destroying the request's pollset set within the
  392. // on_done callback.
  393. TEST_F(HttpRequestTest, CallerPollentsAreNotReferencedAfterCallbackIsRan) {
  394. // Grab an unoccupied port but don't listen on it. The goal
  395. // here is just to have a server address that will reject
  396. // TCP connection setups.
  397. // Note that we could have used a different server for this test case, e.g.
  398. // one which accepts TCP connections. All we need here is something for the
  399. // client to connect to, since it will be cancelled roughly during the
  400. // connection attempt anyways.
  401. int fake_server_port = grpc_pick_unused_port_or_die();
  402. std::string fake_server_address =
  403. absl::StrCat("[::1]:", std::to_string(fake_server_port));
  404. RequestState request_state(this);
  405. grpc_http_request req;
  406. grpc_core::ExecCtx exec_ctx;
  407. memset(&req, 0, sizeof(req));
  408. req.path = const_cast<char*>("/get");
  409. request_state.pollset_set_to_destroy_eagerly = grpc_pollset_set_create();
  410. grpc_polling_entity_add_to_pollset_set(
  411. pops(), request_state.pollset_set_to_destroy_eagerly);
  412. grpc_polling_entity wrapped_pollset_set_to_destroy_eagerly =
  413. grpc_polling_entity_create_from_pollset_set(
  414. request_state.pollset_set_to_destroy_eagerly);
  415. auto uri = grpc_core::URI::Create("http", fake_server_address, "/get",
  416. {} /* query params */, "" /* fragment */);
  417. GPR_ASSERT(uri.ok());
  418. grpc_core::OrphanablePtr<grpc_core::HttpRequest> http_request =
  419. grpc_core::HttpRequest::Get(
  420. std::move(*uri), nullptr /* channel args */,
  421. &wrapped_pollset_set_to_destroy_eagerly, &req, NSecondsTime(15),
  422. GRPC_CLOSURE_CREATE(OnFinishExpectFailure, &request_state,
  423. grpc_schedule_on_exec_ctx),
  424. &request_state.response,
  425. grpc_core::RefCountedPtr<grpc_channel_credentials>(
  426. grpc_insecure_credentials_create()));
  427. // Start the HTTP request. We'll start the TCP connect attempt right away.
  428. http_request->Start();
  429. exec_ctx.Flush();
  430. http_request.reset(); // cancel the request
  431. // Since the request was cancelled, the on_done callback should be flushed
  432. // out on the ExecCtx flush below. When the on_done callback is ran, it will
  433. // eagerly destroy 'request_state.pollset_set_to_destroy_eagerly'. Thus, we
  434. // can't poll on that pollset here.
  435. exec_ctx.Flush();
  436. }
  437. void CancelRequest(grpc_core::HttpRequest* req) {
  438. gpr_log(
  439. GPR_INFO,
  440. "test only HttpRequest::OnHandshakeDone intercept orphaning request: %p",
  441. req);
  442. req->Orphan();
  443. }
  444. // This exercises the code paths that happen when we cancel an HTTP request
  445. // before the security handshake callback runs, but after that callback has
  446. // already been scheduled with a success result. This case is interesting
  447. // because the current security handshake API transfers ownership of output
  448. // arguments to the caller only if the handshake is successful, rendering
  449. // this code path as something that only occurs with just the right timing.
  450. TEST_F(HttpRequestTest,
  451. CancelDuringSecurityHandshakeButHandshakeStillSucceeds) {
  452. RequestState request_state(this);
  453. grpc_http_request req;
  454. grpc_core::ExecCtx exec_ctx;
  455. std::string host = absl::StrFormat("localhost:%d", g_server_port);
  456. gpr_log(GPR_INFO, "requesting from %s", host.c_str());
  457. memset(&req, 0, sizeof(req));
  458. auto uri = grpc_core::URI::Create("http", host, "/get", {} /* query params */,
  459. "" /* fragment */);
  460. GPR_ASSERT(uri.ok());
  461. grpc_core::OrphanablePtr<grpc_core::HttpRequest> http_request =
  462. grpc_core::HttpRequest::Get(
  463. std::move(*uri), nullptr /* channel args */, pops(), &req,
  464. NSecondsTime(15),
  465. GRPC_CLOSURE_CREATE(OnFinishExpectFailure, &request_state,
  466. grpc_schedule_on_exec_ctx),
  467. &request_state.response,
  468. grpc_core::RefCountedPtr<grpc_channel_credentials>(
  469. grpc_insecure_credentials_create()));
  470. grpc_core::HttpRequest::TestOnlySetOnHandshakeDoneIntercept(CancelRequest);
  471. http_request->Start();
  472. (void)http_request.release(); // request will be orphaned by CancelRequest
  473. exec_ctx.Flush();
  474. PollUntil([&request_state]() { return request_state.done; },
  475. AbslDeadlineSeconds(60));
  476. grpc_core::HttpRequest::TestOnlySetOnHandshakeDoneIntercept(nullptr);
  477. }
  478. } // namespace
  479. int main(int argc, char** argv) {
  480. ::testing::InitGoogleTest(&argc, argv);
  481. grpc::testing::TestEnvironment env(argc, argv);
  482. // launch the test server later, so that --gtest_list_tests works
  483. g_argc = argc;
  484. g_argv = argv;
  485. // run tests
  486. return RUN_ALL_TESTS();
  487. }