httpscli_test.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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 <string.h>
  19. #include <gmock/gmock.h>
  20. #include <gtest/gtest.h>
  21. #include <grpc/grpc.h>
  22. #include <grpc/support/alloc.h>
  23. #include <grpc/support/log.h>
  24. #include <grpc/support/string_util.h>
  25. #include <grpc/support/sync.h>
  26. #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
  27. #include "src/core/lib/gpr/env.h"
  28. #include "src/core/lib/gprpp/time.h"
  29. #include "src/core/lib/http/httpcli.h"
  30. #include "src/core/lib/http/httpcli_ssl_credentials.h"
  31. #include "src/core/lib/iomgr/iomgr.h"
  32. #include "test/core/http/httpcli_test_util.h"
  33. #include "test/core/util/fake_udp_and_tcp_server.h"
  34. #include "test/core/util/port.h"
  35. #include "test/core/util/subprocess.h"
  36. #include "test/core/util/test_config.h"
  37. namespace {
  38. grpc_core::Timestamp NSecondsTime(int seconds) {
  39. return grpc_core::Timestamp::FromTimespecRoundUp(
  40. grpc_timeout_seconds_to_deadline(seconds));
  41. }
  42. absl::Time AbslDeadlineSeconds(int s) {
  43. return grpc_core::ToAbslTime(grpc_timeout_seconds_to_deadline(s));
  44. }
  45. int g_argc;
  46. char** g_argv;
  47. int g_server_port;
  48. gpr_subprocess* g_server;
  49. class HttpsCliTest : public ::testing::Test {
  50. public:
  51. HttpsCliTest() {
  52. grpc_init();
  53. grpc_core::ExecCtx exec_ctx;
  54. grpc_pollset* pollset =
  55. static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));
  56. grpc_pollset_init(pollset, &mu_);
  57. pops_ = grpc_polling_entity_create_from_pollset(pollset);
  58. }
  59. ~HttpsCliTest() override {
  60. {
  61. grpc_core::ExecCtx exec_ctx;
  62. grpc_pollset_shutdown(
  63. grpc_polling_entity_pollset(&pops_),
  64. GRPC_CLOSURE_CREATE(DestroyPops, &pops_, grpc_schedule_on_exec_ctx));
  65. }
  66. grpc_shutdown();
  67. }
  68. void RunAndKick(const std::function<void()>& f) {
  69. grpc_core::MutexLockForGprMu lock(mu_);
  70. f();
  71. GPR_ASSERT(GRPC_LOG_IF_ERROR(
  72. "pollset_kick",
  73. grpc_pollset_kick(grpc_polling_entity_pollset(&pops_), nullptr)));
  74. }
  75. void PollUntil(const std::function<bool()>& predicate, absl::Time deadline) {
  76. gpr_mu_lock(mu_);
  77. while (!predicate()) {
  78. GPR_ASSERT(absl::Now() < deadline);
  79. grpc_pollset_worker* worker = nullptr;
  80. GPR_ASSERT(GRPC_LOG_IF_ERROR(
  81. "pollset_work", grpc_pollset_work(grpc_polling_entity_pollset(&pops_),
  82. &worker, NSecondsTime(1))));
  83. gpr_mu_unlock(mu_);
  84. gpr_mu_lock(mu_);
  85. }
  86. gpr_mu_unlock(mu_);
  87. }
  88. grpc_polling_entity* pops() { return &pops_; }
  89. protected:
  90. static void SetUpTestSuite() {
  91. auto test_server = grpc_core::testing::StartHttpRequestTestServer(
  92. g_argc, g_argv, true /* use_ssl */);
  93. g_server = test_server.server;
  94. g_server_port = test_server.port;
  95. }
  96. static void TearDownTestSuite() { gpr_subprocess_destroy(g_server); }
  97. private:
  98. static void DestroyPops(void* p, grpc_error_handle /*error*/) {
  99. grpc_polling_entity* pops = static_cast<grpc_polling_entity*>(p);
  100. grpc_pollset_destroy(grpc_polling_entity_pollset(pops));
  101. gpr_free(grpc_polling_entity_pollset(pops));
  102. }
  103. gpr_mu* mu_;
  104. grpc_polling_entity pops_;
  105. };
  106. struct RequestState {
  107. explicit RequestState(HttpsCliTest* test) : test(test) {}
  108. ~RequestState() {
  109. grpc_core::ExecCtx exec_ctx;
  110. grpc_http_response_destroy(&response);
  111. }
  112. HttpsCliTest* test;
  113. bool done = false;
  114. grpc_http_response response = {};
  115. };
  116. void OnFinish(void* arg, grpc_error_handle error) {
  117. RequestState* request_state = static_cast<RequestState*>(arg);
  118. const char* expect =
  119. "<html><head><title>Hello world!</title></head>"
  120. "<body><p>This is a test</p></body></html>";
  121. GPR_ASSERT(error == GRPC_ERROR_NONE);
  122. grpc_http_response response = request_state->response;
  123. gpr_log(GPR_INFO, "response status=%d error=%s", response.status,
  124. grpc_error_std_string(error).c_str());
  125. GPR_ASSERT(response.status == 200);
  126. GPR_ASSERT(response.body_length == strlen(expect));
  127. GPR_ASSERT(0 == memcmp(expect, response.body, response.body_length));
  128. request_state->test->RunAndKick(
  129. [request_state]() { request_state->done = true; });
  130. }
  131. void OnFinishExpectFailure(void* arg, grpc_error_handle error) {
  132. RequestState* request_state = static_cast<RequestState*>(arg);
  133. grpc_http_response response = request_state->response;
  134. gpr_log(GPR_INFO, "response status=%d error=%s", response.status,
  135. grpc_error_std_string(error).c_str());
  136. GPR_ASSERT(error != GRPC_ERROR_NONE);
  137. request_state->test->RunAndKick(
  138. [request_state]() { request_state->done = true; });
  139. }
  140. TEST_F(HttpsCliTest, Get) {
  141. RequestState request_state(this);
  142. grpc_http_request req;
  143. grpc_core::ExecCtx exec_ctx;
  144. std::string host = absl::StrFormat("localhost:%d", g_server_port);
  145. gpr_log(GPR_INFO, "requesting from %s", host.c_str());
  146. memset(&req, 0, sizeof(req));
  147. grpc_arg ssl_override_arg = grpc_channel_arg_string_create(
  148. const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
  149. const_cast<char*>("foo.test.google.fr"));
  150. grpc_channel_args args = {1, &ssl_override_arg};
  151. auto uri = grpc_core::URI::Create("https", host, "/get",
  152. {} /* query params */, "" /* fragment */);
  153. GPR_ASSERT(uri.ok());
  154. grpc_core::OrphanablePtr<grpc_core::HttpRequest> http_request =
  155. grpc_core::HttpRequest::Get(
  156. std::move(*uri), &args, pops(), &req, NSecondsTime(15),
  157. GRPC_CLOSURE_CREATE(OnFinish, &request_state,
  158. grpc_schedule_on_exec_ctx),
  159. &request_state.response,
  160. grpc_core::CreateHttpRequestSSLCredentials());
  161. http_request->Start();
  162. PollUntil([&request_state]() { return request_state.done; },
  163. AbslDeadlineSeconds(60));
  164. }
  165. TEST_F(HttpsCliTest, Post) {
  166. RequestState request_state(this);
  167. grpc_http_request req;
  168. grpc_core::ExecCtx exec_ctx;
  169. std::string host = absl::StrFormat("localhost:%d", g_server_port);
  170. gpr_log(GPR_INFO, "posting to %s", host.c_str());
  171. memset(&req, 0, sizeof(req));
  172. req.body = const_cast<char*>("hello");
  173. req.body_length = 5;
  174. grpc_arg ssl_override_arg = grpc_channel_arg_string_create(
  175. const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
  176. const_cast<char*>("foo.test.google.fr"));
  177. grpc_channel_args args = {1, &ssl_override_arg};
  178. auto uri = grpc_core::URI::Create("https", host, "/post",
  179. {} /* query params */, "" /* fragment */);
  180. GPR_ASSERT(uri.ok());
  181. grpc_core::OrphanablePtr<grpc_core::HttpRequest> http_request =
  182. grpc_core::HttpRequest::Post(
  183. std::move(*uri), &args /* channel args */, pops(), &req,
  184. NSecondsTime(15),
  185. GRPC_CLOSURE_CREATE(OnFinish, &request_state,
  186. grpc_schedule_on_exec_ctx),
  187. &request_state.response,
  188. grpc_core::CreateHttpRequestSSLCredentials());
  189. http_request->Start();
  190. PollUntil([&request_state]() { return request_state.done; },
  191. AbslDeadlineSeconds(60));
  192. }
  193. // The goal of this test is to make sure that we can cancel HTTP requests
  194. // while they're waiting for a response from the server to finish their
  195. // SSL handshakes. Note that the main focus of this test is to just exercise
  196. // the relevant code paths and make sure there aren't any crashes etc., rather
  197. // than to make sure that cancellation happens in a timely manner.
  198. TEST_F(HttpsCliTest, CancelGetDuringSSLHandshake) {
  199. // Start up a fake TCP server which accepts connections and then hangs,
  200. // i.e. it won't send any bytes back to the client.
  201. grpc_core::testing::FakeUdpAndTcpServer fake_http_server(
  202. grpc_core::testing::FakeUdpAndTcpServer::AcceptMode::
  203. kWaitForClientToSendFirstBytes,
  204. grpc_core::testing::FakeUdpAndTcpServer::CloseSocketUponCloseFromPeer);
  205. // Use multiple threads to try to trigger races etc.
  206. int kNumThreads = 100;
  207. std::vector<std::thread> threads;
  208. threads.reserve(kNumThreads);
  209. for (int i = 0; i < kNumThreads; i++) {
  210. grpc_core::testing::FakeUdpAndTcpServer* fake_http_server_ptr =
  211. &fake_http_server;
  212. threads.push_back(std::thread([this, fake_http_server_ptr]() {
  213. RequestState request_state(this);
  214. grpc_http_request req;
  215. grpc_core::ExecCtx exec_ctx;
  216. memset(&req, 0, sizeof(req));
  217. grpc_arg ssl_override_arg = grpc_channel_arg_string_create(
  218. const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
  219. const_cast<char*>("foo.test.google.fr"));
  220. grpc_channel_args args = {1, &ssl_override_arg};
  221. auto uri = grpc_core::URI::Create(
  222. "https", fake_http_server_ptr->address(), "/get",
  223. {} /* query params */, "" /* fragment */);
  224. grpc_core::OrphanablePtr<grpc_core::HttpRequest> http_request =
  225. grpc_core::HttpRequest::Get(
  226. std::move(*uri), &args, pops(), &req, NSecondsTime(120),
  227. GRPC_CLOSURE_CREATE(OnFinishExpectFailure, &request_state,
  228. grpc_schedule_on_exec_ctx),
  229. &request_state.response,
  230. grpc_core::CreateHttpRequestSSLCredentials());
  231. // Start a request. It will establish a TCP connection to the
  232. // server and then begin an SSL handshake. The server won't send
  233. // anything back though, so it will be stuck in its SSL handshake,
  234. // waiting for the firt response from the server.
  235. http_request->Start();
  236. exec_ctx.Flush();
  237. std::thread cancel_thread([&http_request]() {
  238. // Give one second to let the client get into the middle of its
  239. // SSL handshake, and then cancel the request.
  240. gpr_sleep_until(grpc_timeout_seconds_to_deadline(1));
  241. grpc_core::ExecCtx exec_ctx;
  242. http_request.reset();
  243. });
  244. // Poll with a deadline explicitly lower than the request timeout, so
  245. // that we know that the request timeout isn't just kicking in.
  246. PollUntil([&request_state]() { return request_state.done; },
  247. AbslDeadlineSeconds(60));
  248. cancel_thread.join();
  249. }));
  250. }
  251. for (auto& t : threads) {
  252. t.join();
  253. }
  254. }
  255. } // namespace
  256. int main(int argc, char** argv) {
  257. ::testing::InitGoogleTest(&argc, argv);
  258. grpc::testing::TestEnvironment env(argc, argv);
  259. // launch the test server later, so that --gtest_list_tests works
  260. g_argc = argc;
  261. g_argv = argv;
  262. // run tests
  263. return RUN_ALL_TESTS();
  264. }