inproc_callback_test.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. /*
  2. *
  3. * Copyright 2018 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 <grpc/support/alloc.h>
  20. #include <grpc/support/log.h>
  21. #include <grpc/support/sync.h>
  22. #include "src/core/ext/transport/inproc/inproc_transport.h"
  23. #include "src/core/lib/surface/channel.h"
  24. #include "src/core/lib/surface/completion_queue.h"
  25. #include "src/core/lib/surface/server.h"
  26. #include "test/core/end2end/end2end_tests.h"
  27. #include "test/core/util/port.h"
  28. #include "test/core/util/test_config.h"
  29. typedef struct inproc_fixture_data {
  30. bool phony; // reserved for future expansion. Struct can't be empty
  31. } inproc_fixture_data;
  32. namespace {
  33. template <typename F>
  34. class CQDeletingCallback : public grpc_completion_queue_functor {
  35. public:
  36. explicit CQDeletingCallback(F f) : func_(f) {
  37. functor_run = &CQDeletingCallback::Run;
  38. inlineable = false;
  39. }
  40. ~CQDeletingCallback() {}
  41. static void Run(grpc_completion_queue_functor* cb, int ok) {
  42. auto* callback = static_cast<CQDeletingCallback*>(cb);
  43. callback->func_(static_cast<bool>(ok));
  44. delete callback;
  45. }
  46. private:
  47. F func_;
  48. };
  49. template <typename F>
  50. grpc_completion_queue_functor* NewDeletingCallback(F f) {
  51. return new CQDeletingCallback<F>(f);
  52. }
  53. class ShutdownCallback : public grpc_completion_queue_functor {
  54. public:
  55. ShutdownCallback() : done_(false) {
  56. functor_run = &ShutdownCallback::StaticRun;
  57. inlineable = false;
  58. gpr_mu_init(&mu_);
  59. gpr_cv_init(&cv_);
  60. }
  61. ~ShutdownCallback() {
  62. gpr_mu_destroy(&mu_);
  63. gpr_cv_destroy(&cv_);
  64. }
  65. static void StaticRun(grpc_completion_queue_functor* cb, int ok) {
  66. auto* callback = static_cast<ShutdownCallback*>(cb);
  67. callback->Run(static_cast<bool>(ok));
  68. }
  69. void Run(bool /*ok*/) {
  70. gpr_log(GPR_DEBUG, "CQ shutdown notification invoked");
  71. gpr_mu_lock(&mu_);
  72. done_ = true;
  73. gpr_cv_broadcast(&cv_);
  74. gpr_mu_unlock(&mu_);
  75. }
  76. // The Wait function waits for a specified amount of
  77. // time for the completion of the shutdown and returns
  78. // whether it was successfully shut down
  79. bool Wait(gpr_timespec deadline) {
  80. gpr_mu_lock(&mu_);
  81. while (!done_ && !gpr_cv_wait(&cv_, &mu_, deadline)) {
  82. }
  83. bool ret = done_;
  84. gpr_mu_unlock(&mu_);
  85. return ret;
  86. }
  87. private:
  88. bool done_;
  89. gpr_mu mu_;
  90. gpr_cv cv_;
  91. };
  92. ShutdownCallback* g_shutdown_callback;
  93. } // namespace
  94. // The following global structure is the tag collection. It holds
  95. // all information related to tags expected and tags received
  96. // during the execution, with each callback setting a tag.
  97. // The tag sets are implemented and checked using arrays and
  98. // linear lookups (rather than maps) so that this test doesn't
  99. // need the C++ standard library.
  100. static gpr_mu tags_mu;
  101. static gpr_cv tags_cv;
  102. const size_t kAvailableTags = 4;
  103. bool tags[kAvailableTags];
  104. bool tags_valid[kAvailableTags];
  105. bool tags_expected[kAvailableTags];
  106. bool tags_needed[kAvailableTags];
  107. // Mark that a tag is expected; this function must be executed in the
  108. // main thread only while there are no other threads altering the
  109. // expectation set (e.g., by calling expect_tag or verify_tags)
  110. static void expect_tag(intptr_t tag, bool ok) {
  111. size_t idx = static_cast<size_t>(tag);
  112. GPR_ASSERT(idx < kAvailableTags);
  113. tags_needed[idx] = true;
  114. tags_expected[idx] = ok;
  115. }
  116. // Check that the expected tags have reached, within a certain
  117. // deadline. This must also be executed only on the main thread while
  118. // there are no other threads altering the expectation set (e.g., by
  119. // calling expect_tag or verify_tags). The tag verifier doesn't have
  120. // to drive the CQ at all (unlike the next-based end2end tests)
  121. // because the tags will get set when the callbacks are executed,
  122. // which happens when a particular batch related to a callback is
  123. // complete.
  124. static void verify_tags(gpr_timespec deadline) {
  125. bool done = false;
  126. gpr_mu_lock(&tags_mu);
  127. while (!done) {
  128. done = gpr_time_cmp(gpr_now(GPR_CLOCK_MONOTONIC), deadline) > 0;
  129. for (size_t i = 0; i < kAvailableTags; i++) {
  130. if (tags_needed[i]) {
  131. if (tags_valid[i]) {
  132. gpr_log(GPR_DEBUG, "Verifying tag %d", static_cast<int>(i));
  133. if (tags[i] != tags_expected[i]) {
  134. gpr_log(GPR_ERROR, "Got wrong result (%d instead of %d) for tag %d",
  135. tags[i], tags_expected[i], static_cast<int>(i));
  136. GPR_ASSERT(false);
  137. }
  138. tags_valid[i] = false;
  139. tags_needed[i] = false;
  140. } else if (done) {
  141. gpr_log(GPR_ERROR, "Didn't get tag %d", static_cast<int>(i));
  142. GPR_ASSERT(false);
  143. }
  144. }
  145. }
  146. bool empty = true;
  147. for (size_t i = 0; i < kAvailableTags; i++) {
  148. if (tags_needed[i]) {
  149. empty = false;
  150. }
  151. }
  152. done = done || empty;
  153. if (done) {
  154. for (size_t i = 0; i < kAvailableTags; i++) {
  155. if (tags_valid[i]) {
  156. gpr_log(GPR_ERROR, "Got unexpected tag %d and result %d",
  157. static_cast<int>(i), tags[i]);
  158. GPR_ASSERT(false);
  159. }
  160. tags_valid[i] = false;
  161. }
  162. } else {
  163. gpr_cv_wait(&tags_cv, &tags_mu, deadline);
  164. }
  165. }
  166. gpr_mu_unlock(&tags_mu);
  167. }
  168. // This function creates a callback functor that emits the
  169. // desired tag into the global tag set
  170. static grpc_completion_queue_functor* tag(intptr_t t) {
  171. auto func = [t](bool ok) {
  172. gpr_mu_lock(&tags_mu);
  173. gpr_log(GPR_DEBUG, "Completing operation %" PRIdPTR, t);
  174. bool was_empty = true;
  175. for (size_t i = 0; i < kAvailableTags; i++) {
  176. if (tags_valid[i]) {
  177. was_empty = false;
  178. }
  179. }
  180. size_t idx = static_cast<size_t>(t);
  181. tags[idx] = ok;
  182. tags_valid[idx] = true;
  183. if (was_empty) {
  184. gpr_cv_signal(&tags_cv);
  185. }
  186. gpr_mu_unlock(&tags_mu);
  187. };
  188. auto cb = NewDeletingCallback(func);
  189. return cb;
  190. }
  191. static grpc_end2end_test_fixture inproc_create_fixture(
  192. const grpc_channel_args* /*client_args*/,
  193. const grpc_channel_args* /*server_args*/) {
  194. grpc_end2end_test_fixture f;
  195. inproc_fixture_data* ffd = static_cast<inproc_fixture_data*>(
  196. gpr_malloc(sizeof(inproc_fixture_data)));
  197. memset(&f, 0, sizeof(f));
  198. f.fixture_data = ffd;
  199. g_shutdown_callback = new ShutdownCallback();
  200. f.cq =
  201. grpc_completion_queue_create_for_callback(g_shutdown_callback, nullptr);
  202. f.shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr);
  203. return f;
  204. }
  205. void inproc_init_client(grpc_end2end_test_fixture* f,
  206. const grpc_channel_args* client_args) {
  207. f->client = grpc_inproc_channel_create(f->server, client_args, nullptr);
  208. GPR_ASSERT(f->client);
  209. }
  210. void inproc_init_server(grpc_end2end_test_fixture* f,
  211. const grpc_channel_args* server_args) {
  212. if (f->server) {
  213. grpc_server_destroy(f->server);
  214. }
  215. f->server = grpc_server_create(server_args, nullptr);
  216. grpc_server_register_completion_queue(f->server, f->cq, nullptr);
  217. grpc_server_start(f->server);
  218. }
  219. void inproc_tear_down(grpc_end2end_test_fixture* f) {
  220. inproc_fixture_data* ffd = static_cast<inproc_fixture_data*>(f->fixture_data);
  221. gpr_free(ffd);
  222. }
  223. static grpc_end2end_test_fixture begin_test(
  224. grpc_end2end_test_config config, const char* test_name,
  225. const grpc_channel_args* client_args,
  226. const grpc_channel_args* server_args) {
  227. grpc_end2end_test_fixture f;
  228. gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
  229. f = config.create_fixture(client_args, server_args);
  230. config.init_server(&f, server_args);
  231. config.init_client(&f, client_args);
  232. return f;
  233. }
  234. static gpr_timespec n_seconds_from_now(int n) {
  235. return grpc_timeout_seconds_to_deadline(n);
  236. }
  237. static gpr_timespec five_seconds_from_now() { return n_seconds_from_now(5); }
  238. static void drain_cq(grpc_completion_queue* /*cq*/) {
  239. // Wait for the shutdown callback to arrive, or fail the test
  240. GPR_ASSERT(g_shutdown_callback->Wait(five_seconds_from_now()));
  241. gpr_log(GPR_DEBUG, "CQ shutdown wait complete");
  242. delete g_shutdown_callback;
  243. }
  244. static void shutdown_server(grpc_end2end_test_fixture* f) {
  245. if (!f->server) return;
  246. grpc_server_shutdown_and_notify(
  247. f->server, f->shutdown_cq,
  248. reinterpret_cast<void*>(static_cast<intptr_t>(1000)));
  249. GPR_ASSERT(
  250. grpc_completion_queue_pluck(f->shutdown_cq, (void*)((intptr_t)1000),
  251. grpc_timeout_seconds_to_deadline(5), nullptr)
  252. .type == GRPC_OP_COMPLETE);
  253. grpc_server_destroy(f->server);
  254. f->server = nullptr;
  255. }
  256. static void shutdown_client(grpc_end2end_test_fixture* f) {
  257. if (!f->client) return;
  258. grpc_channel_destroy(f->client);
  259. f->client = nullptr;
  260. }
  261. static void end_test(grpc_end2end_test_fixture* f) {
  262. shutdown_server(f);
  263. shutdown_client(f);
  264. grpc_completion_queue_shutdown(f->cq);
  265. drain_cq(f->cq);
  266. grpc_completion_queue_destroy(f->cq);
  267. grpc_completion_queue_destroy(f->shutdown_cq);
  268. }
  269. static void simple_request_body(grpc_end2end_test_config /* config */,
  270. grpc_end2end_test_fixture f) {
  271. grpc_call* c;
  272. grpc_call* s;
  273. grpc_op ops[6];
  274. grpc_op* op;
  275. grpc_metadata_array initial_metadata_recv;
  276. grpc_metadata_array trailing_metadata_recv;
  277. grpc_metadata_array request_metadata_recv;
  278. grpc_call_details call_details;
  279. grpc_status_code status;
  280. const char* error_string;
  281. grpc_call_error error;
  282. grpc_slice details;
  283. int was_cancelled = 2;
  284. char* peer;
  285. gpr_timespec deadline = five_seconds_from_now();
  286. c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
  287. grpc_slice_from_static_string("/foo"), nullptr,
  288. deadline, nullptr);
  289. GPR_ASSERT(c);
  290. peer = grpc_call_get_peer(c);
  291. GPR_ASSERT(peer != nullptr);
  292. gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer);
  293. gpr_free(peer);
  294. grpc_metadata_array_init(&initial_metadata_recv);
  295. grpc_metadata_array_init(&trailing_metadata_recv);
  296. grpc_metadata_array_init(&request_metadata_recv);
  297. grpc_call_details_init(&call_details);
  298. // Create a basic client unary request batch (no payload)
  299. memset(ops, 0, sizeof(ops));
  300. op = ops;
  301. op->op = GRPC_OP_SEND_INITIAL_METADATA;
  302. op->data.send_initial_metadata.count = 0;
  303. op->flags = 0;
  304. op->reserved = nullptr;
  305. op++;
  306. op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
  307. op->flags = 0;
  308. op->reserved = nullptr;
  309. op++;
  310. op->op = GRPC_OP_RECV_INITIAL_METADATA;
  311. op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
  312. op->flags = 0;
  313. op->reserved = nullptr;
  314. op++;
  315. op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
  316. op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
  317. op->data.recv_status_on_client.status = &status;
  318. op->data.recv_status_on_client.status_details = &details;
  319. op->data.recv_status_on_client.error_string = &error_string;
  320. op->flags = 0;
  321. op->reserved = nullptr;
  322. op++;
  323. error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(1),
  324. nullptr);
  325. GPR_ASSERT(GRPC_CALL_OK == error);
  326. // Register a call at the server-side to match the incoming client call
  327. error = grpc_server_request_call(f.server, &s, &call_details,
  328. &request_metadata_recv, f.cq, f.cq, tag(2));
  329. GPR_ASSERT(GRPC_CALL_OK == error);
  330. // We expect that the server call creation callback (and no others) will
  331. // execute now since no other batch should be complete.
  332. expect_tag(2, true);
  333. verify_tags(deadline);
  334. peer = grpc_call_get_peer(s);
  335. GPR_ASSERT(peer != nullptr);
  336. gpr_log(GPR_DEBUG, "server_peer=%s", peer);
  337. gpr_free(peer);
  338. peer = grpc_call_get_peer(c);
  339. GPR_ASSERT(peer != nullptr);
  340. gpr_log(GPR_DEBUG, "client_peer=%s", peer);
  341. gpr_free(peer);
  342. // Create the server response batch (no payload)
  343. memset(ops, 0, sizeof(ops));
  344. op = ops;
  345. op->op = GRPC_OP_SEND_INITIAL_METADATA;
  346. op->data.send_initial_metadata.count = 0;
  347. op->flags = 0;
  348. op->reserved = nullptr;
  349. op++;
  350. op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
  351. op->data.send_status_from_server.trailing_metadata_count = 0;
  352. op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
  353. grpc_slice status_details = grpc_slice_from_static_string("xyz");
  354. op->data.send_status_from_server.status_details = &status_details;
  355. op->flags = 0;
  356. op->reserved = nullptr;
  357. op++;
  358. op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
  359. op->data.recv_close_on_server.cancelled = &was_cancelled;
  360. op->flags = 0;
  361. op->reserved = nullptr;
  362. op++;
  363. error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops), tag(3),
  364. nullptr);
  365. GPR_ASSERT(GRPC_CALL_OK == error);
  366. // Both the client request and server response batches should get complete
  367. // now and we should see that their callbacks have been executed
  368. expect_tag(3, true);
  369. expect_tag(1, true);
  370. verify_tags(deadline);
  371. GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
  372. GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
  373. // the following sanity check makes sure that the requested error string is
  374. // correctly populated by the core. It looks for certain substrings that are
  375. // not likely to change much. Some parts of the error, like time created,
  376. // obviously are not checked.
  377. GPR_ASSERT(nullptr != strstr(error_string, "xyz"));
  378. GPR_ASSERT(nullptr != strstr(error_string, "Error received from peer"));
  379. GPR_ASSERT(nullptr != strstr(error_string, "grpc_message"));
  380. GPR_ASSERT(nullptr != strstr(error_string, "grpc_status"));
  381. GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
  382. GPR_ASSERT(0 == call_details.flags);
  383. GPR_ASSERT(was_cancelled == 0);
  384. grpc_slice_unref(details);
  385. gpr_free(static_cast<void*>(const_cast<char*>(error_string)));
  386. grpc_metadata_array_destroy(&initial_metadata_recv);
  387. grpc_metadata_array_destroy(&trailing_metadata_recv);
  388. grpc_metadata_array_destroy(&request_metadata_recv);
  389. grpc_call_details_destroy(&call_details);
  390. grpc_call_unref(c);
  391. grpc_call_unref(s);
  392. }
  393. static void test_invoke_simple_request(grpc_end2end_test_config config) {
  394. grpc_end2end_test_fixture f;
  395. f = begin_test(config, "test_invoke_simple_request", nullptr, nullptr);
  396. simple_request_body(config, f);
  397. end_test(&f);
  398. config.tear_down_data(&f);
  399. }
  400. static void test_invoke_10_simple_requests(grpc_end2end_test_config config) {
  401. int i;
  402. grpc_end2end_test_fixture f =
  403. begin_test(config, "test_invoke_10_simple_requests", nullptr, nullptr);
  404. for (i = 0; i < 10; i++) {
  405. simple_request_body(config, f);
  406. gpr_log(GPR_INFO, "Running test: Passed simple request %d", i);
  407. }
  408. end_test(&f);
  409. config.tear_down_data(&f);
  410. }
  411. static void test_invoke_many_simple_requests(grpc_end2end_test_config config) {
  412. int i;
  413. const int many = 1000;
  414. grpc_end2end_test_fixture f =
  415. begin_test(config, "test_invoke_many_simple_requests", nullptr, nullptr);
  416. gpr_timespec t1 = gpr_now(GPR_CLOCK_MONOTONIC);
  417. for (i = 0; i < many; i++) {
  418. simple_request_body(config, f);
  419. }
  420. double us =
  421. gpr_timespec_to_micros(gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), t1)) /
  422. many;
  423. gpr_log(GPR_INFO, "Time per ping %f us", us);
  424. end_test(&f);
  425. config.tear_down_data(&f);
  426. }
  427. static void simple_request(grpc_end2end_test_config config) {
  428. int i;
  429. for (i = 0; i < 10; i++) {
  430. test_invoke_simple_request(config);
  431. }
  432. test_invoke_10_simple_requests(config);
  433. test_invoke_many_simple_requests(config);
  434. }
  435. static void simple_request_pre_init() {
  436. gpr_mu_init(&tags_mu);
  437. gpr_cv_init(&tags_cv);
  438. }
  439. /* All test configurations */
  440. static grpc_end2end_test_config configs[] = {
  441. {"inproc-callback", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, nullptr,
  442. inproc_create_fixture, inproc_init_client, inproc_init_server,
  443. inproc_tear_down},
  444. };
  445. int main(int argc, char** argv) {
  446. grpc::testing::TestEnvironment env(argc, argv);
  447. grpc_init();
  448. simple_request_pre_init();
  449. simple_request(configs[0]);
  450. grpc_shutdown();
  451. return 0;
  452. }