int main(int argc, char **argv) { grpc_test_init(argc, argv); grpc_init(); gpr_mu_init(&g_mu); grpc_blocking_resolve_address = my_resolve_address; grpc_resolver *resolver = create_resolver("dns:test"); grpc_resolver_result *result = (grpc_resolver_result *)1; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; gpr_event ev1; gpr_event_init(&ev1); grpc_resolver_next(&exec_ctx, resolver, &result, grpc_closure_create(on_done, &ev1)); grpc_exec_ctx_flush(&exec_ctx); GPR_ASSERT(wait_loop(5, &ev1)); GPR_ASSERT(result == NULL); gpr_event ev2; gpr_event_init(&ev2); grpc_resolver_next(&exec_ctx, resolver, &result, grpc_closure_create(on_done, &ev2)); grpc_exec_ctx_flush(&exec_ctx); GPR_ASSERT(wait_loop(30, &ev2)); GPR_ASSERT(result != NULL); grpc_resolver_result_unref(&exec_ctx, result); GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test"); grpc_exec_ctx_finish(&exec_ctx); grpc_shutdown(); gpr_mu_destroy(&g_mu); }
void grpc_iocp_init(void) { gpr_thd_id id; g_iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, (ULONG_PTR)NULL, 0); GPR_ASSERT(g_iocp); gpr_event_init(&g_iocp_done); gpr_event_init(&g_shutdown_iocp); gpr_thd_new(&id, iocp_loop, NULL, NULL); }
void test_succeeds(void) { struct sockaddr_in addr; socklen_t addr_len = sizeof(addr); int svr_fd; int r; gpr_event ev; gpr_event_init(&ev); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; /* create a dummy server */ svr_fd = socket(AF_INET, SOCK_STREAM, 0); GPR_ASSERT(svr_fd >= 0); GPR_ASSERT(0 == bind(svr_fd, (struct sockaddr *)&addr, addr_len)); GPR_ASSERT(0 == listen(svr_fd, 1)); /* connect to it */ GPR_ASSERT(getsockname(svr_fd, (struct sockaddr *)&addr, &addr_len) == 0); grpc_tcp_client_connect(must_succeed, &ev, (struct sockaddr *)&addr, addr_len, gpr_inf_future); /* await the connection */ do { addr_len = sizeof(addr); r = accept(svr_fd, (struct sockaddr *)&addr, &addr_len); } while (r == -1 && errno == EINTR); GPR_ASSERT(r >= 0); close(r); /* wait for the connection callback to finish */ GPR_ASSERT(gpr_event_wait(&ev, test_deadline())); }
static void run_test(const char *response_payload, size_t response_payload_length, grpc_status_code expected_status, const char *expected_detail) { test_tcp_server test_server; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; gpr_event ev; grpc_init(); gpr_event_init(&ev); server_port = grpc_pick_unused_port_or_die(); test_tcp_server_init(&test_server, on_connect, &test_server); test_tcp_server_start(&test_server, server_port); state.response_payload = response_payload; state.response_payload_length = response_payload_length; /* poll server until sending out the response */ poll_server_until_read_done(&test_server, &ev); start_rpc(server_port, expected_status, expected_detail); gpr_event_wait(&ev, gpr_inf_future(GPR_CLOCK_REALTIME)); /* clean up */ grpc_endpoint_shutdown(&exec_ctx, state.tcp); grpc_endpoint_destroy(&exec_ctx, state.tcp); grpc_exec_ctx_finish(&exec_ctx); cleanup_rpc(); test_tcp_server_destroy(&test_server); grpc_shutdown(); }
static void shutdown_during_write_test(grpc_endpoint_test_config config, size_t slice_size) { /* test that shutdown with a pending write creates no leaks */ gpr_timespec deadline; size_t size; size_t nblocks; int current_data = 1; shutdown_during_write_test_state read_st; shutdown_during_write_test_state write_st; gpr_slice *slices; grpc_endpoint_test_fixture f = begin_test(config, __FUNCTION__, slice_size); gpr_log(GPR_INFO, "testing shutdown during a write"); read_st.ep = f.client_ep; write_st.ep = f.server_ep; gpr_event_init(&read_st.ev); gpr_event_init(&write_st.ev); grpc_endpoint_notify_on_read( read_st.ep, shutdown_during_write_test_read_handler, &read_st); for (size = 1;; size *= 2) { slices = allocate_blocks(size, 1, &nblocks, ¤t_data); switch (grpc_endpoint_write(write_st.ep, slices, nblocks, shutdown_during_write_test_write_handler, &write_st)) { case GRPC_ENDPOINT_WRITE_DONE: break; case GRPC_ENDPOINT_WRITE_ERROR: gpr_log(GPR_ERROR, "error writing"); abort(); case GRPC_ENDPOINT_WRITE_PENDING: grpc_endpoint_shutdown(write_st.ep); deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10); GPR_ASSERT(gpr_event_wait(&write_st.ev, deadline)); grpc_endpoint_destroy(write_st.ep); GPR_ASSERT(gpr_event_wait(&read_st.ev, deadline)); gpr_free(slices); end_test(config); return; } gpr_free(slices); } gpr_log(GPR_ERROR, "should never reach here"); abort(); }
void args_init(grpc_exec_ctx *exec_ctx, args_struct *args) { gpr_event_init(&args->ev); args->pollset = gpr_zalloc(grpc_pollset_size()); grpc_pollset_init(args->pollset, &args->mu); args->pollset_set = grpc_pollset_set_create(); grpc_pollset_set_add_pollset(exec_ctx, args->pollset_set, args->pollset); args->addrs = NULL; }
static void test_initial_string(test_tcp_server *server, int secure) { gpr_event ev; gpr_event_init(&ev); grpc_test_set_initial_connect_string_function(set_magic_initial_string); poll_server_until_read_done(server, &ev); start_rpc(secure, server_port); gpr_event_wait(&ev, gpr_inf_future(GPR_CLOCK_REALTIME)); match_initial_magic_string(&state.incoming_buffer); cleanup_rpc(); }
void grpc_iomgr_init(void) { gpr_thd_id id; gpr_mu_init(&g_mu); gpr_cv_init(&g_cv); gpr_cv_init(&g_rcv); grpc_alarm_list_init(gpr_now()); g_refs = 0; grpc_iomgr_platform_init(); gpr_event_init(&g_background_callback_executor_done); gpr_thd_new(&id, background_callback_executor, NULL, NULL); }
void grpc_iomgr_init(void) { gpr_thd_id id; gpr_mu_init(&g_mu); gpr_cv_init(&g_rcv); grpc_alarm_list_init(gpr_now()); g_root_object.next = g_root_object.prev = &g_root_object; g_root_object.name = "root"; grpc_iomgr_platform_init(); gpr_event_init(&g_background_callback_executor_done); gpr_thd_new(&id, background_callback_executor, NULL, NULL); }
void test_times_out(void) { struct sockaddr_in addr; socklen_t addr_len = sizeof(addr); int svr_fd; #define NUM_CLIENT_CONNECTS 10 int client_fd[NUM_CLIENT_CONNECTS]; int i; int r; gpr_event ev; gpr_timespec connect_deadline; gpr_event_init(&ev); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; /* create a dummy server */ svr_fd = socket(AF_INET, SOCK_STREAM, 0); GPR_ASSERT(svr_fd >= 0); GPR_ASSERT(0 == bind(svr_fd, (struct sockaddr *)&addr, addr_len)); GPR_ASSERT(0 == listen(svr_fd, 1)); /* Get its address */ GPR_ASSERT(getsockname(svr_fd, (struct sockaddr *)&addr, &addr_len) == 0); /* tie up the listen buffer, which is somewhat arbitrarily sized. */ for (i = 0; i < NUM_CLIENT_CONNECTS; ++i) { client_fd[i] = socket(AF_INET, SOCK_STREAM, 0); grpc_set_socket_nonblocking(client_fd[i], 1); do { r = connect(client_fd[i], (struct sockaddr *)&addr, addr_len); } while (r == -1 && errno == EINTR); GPR_ASSERT(r < 0); GPR_ASSERT(errno == EWOULDBLOCK || errno == EINPROGRESS); } /* connect to dummy server address */ connect_deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1); grpc_tcp_client_connect(must_fail, &ev, (struct sockaddr *)&addr, addr_len, connect_deadline); /* Make sure the event doesn't trigger early */ GPR_ASSERT(!gpr_event_wait(&ev, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(500))); /* Now wait until it should have triggered */ sleep(1); /* wait for the connection callback to finish */ GPR_ASSERT(gpr_event_wait(&ev, test_deadline())); close(svr_fd); for (i = 0; i < NUM_CLIENT_CONNECTS; ++i) { close(client_fd[i]); } }
static void test_invalid_ip_addresses(void) { const char* const kCases[] = { "293.283.1238.3:1", "[2001:db8::11111]:1", }; unsigned i; for (i = 0; i < sizeof(kCases) / sizeof(*kCases); i++) { gpr_event ev; gpr_event_init(&ev); grpc_resolve_address(kCases[i], NULL, must_fail, &ev); GPR_ASSERT(gpr_event_wait(&ev, test_deadline())); } }
static void test_ipv6_without_port(void) { const char* const kCases[] = { "2001:db8::1", "2001:db8::1.2.3.4", "[2001:db8::1]", }; unsigned i; for (i = 0; i < sizeof(kCases) / sizeof(*kCases); i++) { gpr_event ev; gpr_event_init(&ev); grpc_resolve_address(kCases[i], "80", must_succeed, &ev); GPR_ASSERT(gpr_event_wait(&ev, test_deadline())); } }
static void test_unparseable_hostports(void) { const char* const kCases[] = { "[", "[::1", "[::1]bad", "[1.2.3.4]", "[localhost]", "[localhost]:1", }; unsigned i; for (i = 0; i < sizeof(kCases) / sizeof(*kCases); i++) { gpr_event ev; gpr_event_init(&ev); grpc_resolve_address(kCases[i], "1", must_fail, &ev); GPR_ASSERT(gpr_event_wait(&ev, test_deadline())); } }
static void test_initial_string_with_redirect(test_tcp_server *server, int secure) { gpr_event ev; gpr_event_init(&ev); int another_port = grpc_pick_unused_port_or_die(); grpc_test_set_initial_connect_string_function( reset_addr_and_set_magic_string); poll_server_until_read_done(server, &ev); start_rpc(secure, another_port); gpr_event_wait(&ev, gpr_inf_future(GPR_CLOCK_REALTIME)); match_initial_magic_string(&state.incoming_buffer); cleanup_rpc(); }
void gpr_cancellable_cancel(gpr_cancellable *c) { if (!gpr_cancellable_is_cancelled(c)) { int failures; int backoff = 1; do { struct gpr_cancellable_list_ *l; struct gpr_cancellable_list_ *nl; gpr_mu *omu = 0; /* one-element cache of a processed gpr_mu */ gpr_cv *ocv = 0; /* one-element cache of a processd gpr_cv */ gpr_mu_lock(&c->mu); gpr_atm_rel_store(&c->cancelled, 1); failures = 0; for (l = c->waiters.next; l != &c->waiters; l = nl) { nl = l->next; if (omu != l->mu) { omu = l->mu; if (gpr_mu_trylock(l->mu)) { gpr_mu_unlock(l->mu); l->next->prev = l->prev; /* remove *l from list */ l->prev->next = l->next; /* allow unconditional dequeue in gpr_cv_cancellable_wait() */ l->next = l; l->prev = l; ocv = 0; /* force broadcast */ } else { failures++; } } if (ocv != l->cv) { ocv = l->cv; gpr_cv_broadcast(l->cv); } } gpr_mu_unlock(&c->mu); if (failures != 0) { if (backoff < 10) { volatile int i; for (i = 0; i != (1 << backoff); i++) { } backoff++; } else { gpr_event ev; gpr_event_init(&ev); gpr_event_wait( &ev, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_micros(1000, GPR_TIMESPAN))); } } } while (failures != 0); } }
int main(int argc, char **argv) { grpc_test_init(argc, argv); grpc_init(); gpr_mu_init(&g_mu); g_combiner = grpc_combiner_create(); grpc_resolve_address = my_resolve_address; grpc_dns_lookup_ares = my_dns_lookup_ares; grpc_channel_args *result = (grpc_channel_args *)1; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resolver *resolver = create_resolver(&exec_ctx, "dns:test"); gpr_event ev1; gpr_event_init(&ev1); call_resolver_next_after_locking( &exec_ctx, resolver, &result, GRPC_CLOSURE_CREATE(on_done, &ev1, grpc_schedule_on_exec_ctx)); grpc_exec_ctx_flush(&exec_ctx); GPR_ASSERT(wait_loop(5, &ev1)); GPR_ASSERT(result == NULL); gpr_event ev2; gpr_event_init(&ev2); call_resolver_next_after_locking( &exec_ctx, resolver, &result, GRPC_CLOSURE_CREATE(on_done, &ev2, grpc_schedule_on_exec_ctx)); grpc_exec_ctx_flush(&exec_ctx); GPR_ASSERT(wait_loop(30, &ev2)); GPR_ASSERT(result != NULL); grpc_channel_args_destroy(&exec_ctx, result); GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test"); GRPC_COMBINER_UNREF(&exec_ctx, g_combiner, "test"); grpc_exec_ctx_finish(&exec_ctx); grpc_shutdown(); gpr_mu_destroy(&g_mu); }
static void test_get(int use_ssl) { grpc_httpcli_request req; gpr_log(GPR_INFO, "running %s with use_ssl=%d.", "test_get", use_ssl); gpr_event_init(&g_done); memset(&req, 0, sizeof(req)); req.host = "www.google.com"; req.path = "/"; req.use_ssl = use_ssl; grpc_httpcli_get(&req, n_seconds_time(15), on_finish, (void *)42); GPR_ASSERT(gpr_event_wait(&g_done, n_seconds_time(20))); }
void test_fails(void) { struct sockaddr_in addr; socklen_t addr_len = sizeof(addr); gpr_event ev; gpr_event_init(&ev); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; /* connect to a broken address */ grpc_tcp_client_connect(must_fail, &ev, (struct sockaddr *)&addr, addr_len, gpr_inf_future); /* wait for the connection callback to finish */ GPR_ASSERT(gpr_event_wait(&ev, test_deadline())); }
/* Return pointer to a new struct test. */ static struct test *test_new(int threads, gpr_int64 iterations) { struct test *m = gpr_malloc(sizeof(*m)); m->threads = threads; m->iterations = iterations; m->counter = 0; m->thread_count = 0; m->done = threads; gpr_mu_init(&m->mu); gpr_cv_init(&m->cv); gpr_cv_init(&m->done_cv); queue_init(&m->q); gpr_stats_init(&m->stats_counter, 0); gpr_ref_init(&m->refcount, 0); gpr_ref_init(&m->thread_refcount, threads); gpr_event_init(&m->event); return m; }
static void test_mt_multipop(void) { gpr_log(GPR_DEBUG, "test_mt_multipop"); gpr_event start; gpr_event_init(&start); gpr_thd_id thds[100]; gpr_thd_id pull_thds[100]; thd_args ta[GPR_ARRAY_SIZE(thds)]; gpr_mpscq q; gpr_mpscq_init(&q); for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { gpr_thd_options options = gpr_thd_options_default(); gpr_thd_options_set_joinable(&options); ta[i].ctr = 0; ta[i].q = &q; ta[i].start = &start; GPR_ASSERT(gpr_thd_new(&thds[i], test_thread, &ta[i], &options)); } pull_args pa; pa.ta = ta; pa.num_thds = GPR_ARRAY_SIZE(thds); pa.spins = 0; pa.num_done = 0; pa.q = &q; pa.start = &start; gpr_mu_init(&pa.mu); for (size_t i = 0; i < GPR_ARRAY_SIZE(pull_thds); i++) { gpr_thd_options options = gpr_thd_options_default(); gpr_thd_options_set_joinable(&options); GPR_ASSERT(gpr_thd_new(&pull_thds[i], pull_thread, &pa, &options)); } gpr_event_set(&start, (void *)1); for (size_t i = 0; i < GPR_ARRAY_SIZE(pull_thds); i++) { gpr_thd_join(pull_thds[i]); } gpr_log(GPR_DEBUG, "spins: %" PRIdPTR, pa.spins); for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { gpr_thd_join(thds[i]); } gpr_mpscq_destroy(&q); }
static void test_mt(void) { gpr_log(GPR_DEBUG, "test_mt"); gpr_event start; gpr_event_init(&start); gpr_thd_id thds[100]; thd_args ta[GPR_ARRAY_SIZE(thds)]; gpr_mpscq q; gpr_mpscq_init(&q); for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { gpr_thd_options options = gpr_thd_options_default(); gpr_thd_options_set_joinable(&options); ta[i].ctr = 0; ta[i].q = &q; ta[i].start = &start; GPR_ASSERT(gpr_thd_new(&thds[i], test_thread, &ta[i], &options)); } size_t num_done = 0; size_t spins = 0; gpr_event_set(&start, (void *)1); while (num_done != GPR_ARRAY_SIZE(thds)) { gpr_mpscq_node *n; while ((n = gpr_mpscq_pop(&q)) == NULL) { spins++; } test_node *tn = (test_node *)n; GPR_ASSERT(*tn->ctr == tn->i - 1); *tn->ctr = tn->i; if (tn->i == THREAD_ITERATIONS) num_done++; gpr_free(tn); } gpr_log(GPR_DEBUG, "spins: %" PRIdPTR, spins); for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { gpr_thd_join(thds[i]); } gpr_mpscq_destroy(&q); }
void grpc_run_bad_client_test(const char *name, const char *client_payload, size_t client_payload_length, grpc_bad_client_server_side_validator validator) { grpc_endpoint_pair sfd; thd_args a; gpr_thd_id id; gpr_slice slice = gpr_slice_from_copied_buffer(client_payload, client_payload_length); /* Add a debug log */ gpr_log(GPR_INFO, "TEST: %s", name); /* Init grpc */ grpc_init(); /* Create endpoints */ sfd = grpc_iomgr_create_endpoint_pair(65536); /* Create server, completion events */ a.server = grpc_server_create_from_filters(NULL, 0, NULL); a.cq = grpc_completion_queue_create(); gpr_event_init(&a.done_thd); gpr_event_init(&a.done_write); a.validator = validator; grpc_server_register_completion_queue(a.server, a.cq); grpc_server_start(a.server); grpc_create_chttp2_transport(server_setup_transport, &a, NULL, sfd.server, NULL, 0, grpc_mdctx_create(), 0); /* Bind everything into the same pollset */ grpc_endpoint_add_to_pollset(sfd.client, grpc_cq_pollset(a.cq)); grpc_endpoint_add_to_pollset(sfd.server, grpc_cq_pollset(a.cq)); /* Check a ground truth */ GPR_ASSERT(grpc_server_has_open_connections(a.server)); /* Start validator */ gpr_thd_new(&id, thd_func, &a, NULL); /* Write data */ switch (grpc_endpoint_write(sfd.client, &slice, 1, done_write, &a)) { case GRPC_ENDPOINT_WRITE_DONE: done_write(&a, 1); break; case GRPC_ENDPOINT_WRITE_PENDING: break; case GRPC_ENDPOINT_WRITE_ERROR: done_write(&a, 0); break; } /* Await completion */ GPR_ASSERT( gpr_event_wait(&a.done_write, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5))); GPR_ASSERT(gpr_event_wait(&a.done_thd, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5))); /* Shutdown */ grpc_endpoint_destroy(sfd.client); grpc_server_destroy(a.server); grpc_completion_queue_destroy(a.cq); grpc_shutdown(); }
static void test_threading(int producers, int consumers) { test_thread_options *options = gpr_malloc((producers + consumers) * sizeof(test_thread_options)); gpr_event phase1 = GPR_EVENT_INIT; gpr_event phase2 = GPR_EVENT_INIT; grpc_completion_queue *cc = grpc_completion_queue_create(NULL); int i; int total_consumed = 0; static int optid = 101; gpr_log(GPR_INFO, "%s: %d producers, %d consumers", "test_threading", producers, consumers); /* start all threads: they will wait for phase1 */ for (i = 0; i < producers + consumers; i++) { gpr_thd_id id; gpr_event_init(&options[i].on_started); gpr_event_init(&options[i].on_phase1_done); gpr_event_init(&options[i].on_finished); options[i].phase1 = &phase1; options[i].phase2 = &phase2; options[i].events_triggered = 0; options[i].cc = cc; options[i].id = optid++; GPR_ASSERT(gpr_thd_new(&id, i < producers ? producer_thread : consumer_thread, options + i, NULL)); gpr_event_wait(&options[i].on_started, ten_seconds_time()); } /* start phase1: producers will pre-declare all operations they will complete */ gpr_log(GPR_INFO, "start phase 1"); gpr_event_set(&phase1, (void *)(gpr_intptr)1); gpr_log(GPR_INFO, "wait phase 1"); for (i = 0; i < producers + consumers; i++) { GPR_ASSERT(gpr_event_wait(&options[i].on_phase1_done, ten_seconds_time())); } gpr_log(GPR_INFO, "done phase 1"); /* start phase2: operations will complete, and consumers will consume them */ gpr_log(GPR_INFO, "start phase 2"); gpr_event_set(&phase2, (void *)(gpr_intptr)1); /* in parallel, we shutdown the completion channel - all events should still be consumed */ grpc_completion_queue_shutdown(cc); /* join all threads */ gpr_log(GPR_INFO, "wait phase 2"); for (i = 0; i < producers + consumers; i++) { GPR_ASSERT(gpr_event_wait(&options[i].on_finished, ten_seconds_time())); } gpr_log(GPR_INFO, "done phase 2"); /* destroy the completion channel */ grpc_completion_queue_destroy(cc); /* verify that everything was produced and consumed */ for (i = 0; i < producers + consumers; i++) { if (i < producers) { GPR_ASSERT(options[i].events_triggered == TEST_THREAD_EVENTS); } else { total_consumed += options[i].events_triggered; } } GPR_ASSERT(total_consumed == producers * TEST_THREAD_EVENTS); gpr_free(options); }
static void test(void) { int i; gpr_thd_id thd; struct test t; int n = 1; gpr_timespec interval; gpr_mu_init(&t.mu); gpr_cv_init(&t.cv); gpr_event_init(&t.ev); gpr_event_init(&t.done); gpr_cancellable_init(&t.cancel); /* A gpr_cancellable starts not cancelled. */ GPR_ASSERT(!gpr_cancellable_is_cancelled(&t.cancel)); /* Test timeout on event wait for uncancelled gpr_cancellable */ interval = gpr_now(GPR_CLOCK_REALTIME); gpr_event_cancellable_wait( &t.ev, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_micros(1000000, GPR_TIMESPAN)), &t.cancel); interval = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), interval); GPR_ASSERT( gpr_time_cmp(interval, gpr_time_from_micros(500000, GPR_TIMESPAN)) >= 0); GPR_ASSERT( gpr_time_cmp(gpr_time_from_micros(2000000, GPR_TIMESPAN), interval) >= 0); /* Test timeout on cv wait for uncancelled gpr_cancellable */ gpr_mu_lock(&t.mu); interval = gpr_now(GPR_CLOCK_REALTIME); while (!gpr_cv_cancellable_wait( &t.cv, &t.mu, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_micros(1000000, GPR_TIMESPAN)), &t.cancel)) { } interval = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), interval); GPR_ASSERT( gpr_time_cmp(interval, gpr_time_from_micros(500000, GPR_TIMESPAN)) >= 0); GPR_ASSERT( gpr_time_cmp(gpr_time_from_micros(2000000, GPR_TIMESPAN), interval) >= 0); gpr_mu_unlock(&t.mu); /* Create some threads. They all wait until cancelled; the last to finish sets t.done. */ t.n = n; for (i = 0; i != n; i++) { GPR_ASSERT(gpr_thd_new(&thd, &thd_body, &t, NULL)); } /* Check that t.cancel still is not cancelled. */ GPR_ASSERT(!gpr_cancellable_is_cancelled(&t.cancel)); /* Wait a second, and check that no threads have finished waiting. */ gpr_mu_lock(&t.mu); gpr_cv_wait(&t.cv, &t.mu, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_micros(1000000, GPR_TIMESPAN))); GPR_ASSERT(t.n == n); gpr_mu_unlock(&t.mu); /* Check that t.cancel still is not cancelled, but when cancelled it retports that it is cacncelled. */ GPR_ASSERT(!gpr_cancellable_is_cancelled(&t.cancel)); gpr_cancellable_cancel(&t.cancel); GPR_ASSERT(gpr_cancellable_is_cancelled(&t.cancel)); /* Wait for threads to finish. */ gpr_event_wait(&t.done, gpr_inf_future(GPR_CLOCK_REALTIME)); GPR_ASSERT(t.n == 0); /* Test timeout on cv wait for cancelled gpr_cancellable */ gpr_mu_lock(&t.mu); interval = gpr_now(GPR_CLOCK_REALTIME); while (!gpr_cv_cancellable_wait( &t.cv, &t.mu, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_micros(1000000, GPR_TIMESPAN)), &t.cancel)) { } interval = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), interval); GPR_ASSERT( gpr_time_cmp(gpr_time_from_micros(100000, GPR_TIMESPAN), interval) >= 0); gpr_mu_unlock(&t.mu); /* Test timeout on event wait for cancelled gpr_cancellable */ interval = gpr_now(GPR_CLOCK_REALTIME); gpr_event_cancellable_wait( &t.ev, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_micros(1000000, GPR_TIMESPAN)), &t.cancel); interval = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), interval); GPR_ASSERT( gpr_time_cmp(gpr_time_from_micros(100000, GPR_TIMESPAN), interval) >= 0); gpr_mu_destroy(&t.mu); gpr_cv_destroy(&t.cv); gpr_cancellable_destroy(&t.cancel); }
// This test launches a gRPC server on a separate thread and then establishes a // TLS handshake via a minimal TLS client. The TLS client has configurable (via // alpn_list) ALPN settings and can probe at the supported ALPN preferences // using this (via alpn_expected). static bool server_ssl_test(const char *alpn_list[], unsigned int alpn_list_len, const char *alpn_expected) { bool success = true; grpc_init(); int port = grpc_pick_unused_port_or_die(); gpr_event_init(&client_handshake_complete); // Launch the gRPC server thread. gpr_thd_options thdopt = gpr_thd_options_default(); gpr_thd_id thdid; gpr_thd_options_set_joinable(&thdopt); GPR_ASSERT(gpr_thd_new(&thdid, server_thread, &port, &thdopt)); SSL_load_error_strings(); OpenSSL_add_ssl_algorithms(); const SSL_METHOD *method = TLSv1_2_client_method(); SSL_CTX *ctx = SSL_CTX_new(method); if (!ctx) { perror("Unable to create SSL context"); ERR_print_errors_fp(stderr); abort(); } // Load key pair. if (SSL_CTX_use_certificate_file(ctx, SSL_CERT_PATH, SSL_FILETYPE_PEM) < 0) { ERR_print_errors_fp(stderr); abort(); } if (SSL_CTX_use_PrivateKey_file(ctx, SSL_KEY_PATH, SSL_FILETYPE_PEM) < 0) { ERR_print_errors_fp(stderr); abort(); } // Set the cipher list to match the one expressed in // src/core/lib/tsi/ssl_transport_security.c. const char *cipher_list = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-" "SHA384:ECDHE-RSA-AES256-GCM-SHA384"; if (!SSL_CTX_set_cipher_list(ctx, cipher_list)) { ERR_print_errors_fp(stderr); gpr_log(GPR_ERROR, "Couldn't set server cipher list."); abort(); } // Configure ALPN list the client will send to the server. This must match the // wire format, see documentation for SSL_CTX_set_alpn_protos. unsigned int alpn_protos_len = alpn_list_len; for (unsigned int i = 0; i < alpn_list_len; ++i) { alpn_protos_len += (unsigned int)strlen(alpn_list[i]); } unsigned char *alpn_protos = gpr_malloc(alpn_protos_len); unsigned char *p = alpn_protos; for (unsigned int i = 0; i < alpn_list_len; ++i) { const uint8_t len = (uint8_t)strlen(alpn_list[i]); *p++ = len; memcpy(p, alpn_list[i], len); p += len; } GPR_ASSERT(SSL_CTX_set_alpn_protos(ctx, alpn_protos, alpn_protos_len) == 0); // Try and connect to server. We allow a bounded number of retries as we might // be racing with the server setup on its separate thread. int retries = 10; int sock = -1; while (sock == -1 && retries-- > 0) { sock = create_socket(port); if (sock < 0) { sleep(1); } } GPR_ASSERT(sock > 0); gpr_log(GPR_INFO, "Connected to server on port %d", port); // Establish a SSL* and connect at SSL layer. SSL *ssl = SSL_new(ctx); GPR_ASSERT(ssl); SSL_set_fd(ssl, sock); if (SSL_connect(ssl) <= 0) { ERR_print_errors_fp(stderr); gpr_log(GPR_ERROR, "Handshake failed."); success = false; } else { gpr_log(GPR_INFO, "Handshake successful."); // Validate ALPN preferred by server matches alpn_expected. const unsigned char *alpn_selected; unsigned int alpn_selected_len; SSL_get0_alpn_selected(ssl, &alpn_selected, &alpn_selected_len); if (strlen(alpn_expected) != alpn_selected_len || strncmp((const char *)alpn_selected, alpn_expected, alpn_selected_len) != 0) { gpr_log(GPR_ERROR, "Unexpected ALPN protocol preference"); success = false; } } gpr_event_set(&client_handshake_complete, &client_handshake_complete); SSL_free(ssl); gpr_free(alpn_protos); SSL_CTX_free(ctx); EVP_cleanup(); close(sock); gpr_thd_join(thdid); grpc_shutdown(); return success; }
int run_concurrent_connectivity_test() { struct server_thread_args args; memset(&args, 0, sizeof(args)); grpc_init(); gpr_thd_id threads[NUM_THREADS]; gpr_thd_id server; char *localhost = gpr_strdup("localhost:54321"); gpr_thd_options options = gpr_thd_options_default(); gpr_thd_options_set_joinable(&options); /* First round, no server */ gpr_log(GPR_DEBUG, "Wave 1"); for (size_t i = 0; i < NUM_THREADS; ++i) { gpr_thd_new(&threads[i], create_loop_destroy, localhost, &options); } for (size_t i = 0; i < NUM_THREADS; ++i) { gpr_thd_join(threads[i]); } gpr_free(localhost); /* Second round, actual grpc server */ gpr_log(GPR_DEBUG, "Wave 2"); int port = grpc_pick_unused_port_or_die(); gpr_asprintf(&args.addr, "localhost:%d", port); args.server = grpc_server_create(NULL, NULL); grpc_server_add_insecure_http2_port(args.server, args.addr); args.cq = grpc_completion_queue_create_for_next(NULL); grpc_server_register_completion_queue(args.server, args.cq, NULL); grpc_server_start(args.server); gpr_thd_new(&server, server_thread, &args, &options); for (size_t i = 0; i < NUM_THREADS; ++i) { gpr_thd_new(&threads[i], create_loop_destroy, args.addr, &options); } for (size_t i = 0; i < NUM_THREADS; ++i) { gpr_thd_join(threads[i]); } grpc_server_shutdown_and_notify(args.server, args.cq, tag(0xd1e)); gpr_thd_join(server); grpc_server_destroy(args.server); grpc_completion_queue_destroy(args.cq); gpr_free(args.addr); /* Third round, bogus tcp server */ gpr_log(GPR_DEBUG, "Wave 3"); args.pollset = gpr_zalloc(grpc_pollset_size()); grpc_pollset_init(args.pollset, &args.mu); gpr_event_init(&args.ready); gpr_thd_new(&server, bad_server_thread, &args, &options); gpr_event_wait(&args.ready, gpr_inf_future(GPR_CLOCK_MONOTONIC)); for (size_t i = 0; i < NUM_THREADS; ++i) { gpr_thd_new(&threads[i], create_loop_destroy, args.addr, &options); } for (size_t i = 0; i < NUM_THREADS; ++i) { gpr_thd_join(threads[i]); } gpr_atm_rel_store(&args.stop, 1); gpr_thd_join(server); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_pollset_shutdown(&exec_ctx, args.pollset, GRPC_CLOSURE_CREATE(done_pollset_shutdown, args.pollset, grpc_schedule_on_exec_ctx)); grpc_exec_ctx_finish(&exec_ctx); grpc_shutdown(); return 0; }
static void test_connectivity(grpc_end2end_test_config config) { grpc_end2end_test_fixture f = config.create_fixture(NULL, NULL); grpc_connectivity_state state; cq_verifier *cqv = cq_verifier_create(f.cq); child_events ce; gpr_thd_options thdopt = gpr_thd_options_default(); gpr_thd_id thdid; config.init_client(&f, NULL); ce.channel = f.client; ce.cq = f.cq; gpr_event_init(&ce.started); gpr_thd_options_set_joinable(&thdopt); GPR_ASSERT(gpr_thd_new(&thdid, child_thread, &ce, &thdopt)); gpr_event_wait(&ce.started, gpr_inf_future(GPR_CLOCK_MONOTONIC)); /* channels should start life in IDLE, and stay there */ GPR_ASSERT(grpc_channel_check_connectivity_state(f.client, 0) == GRPC_CHANNEL_IDLE); gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100)); GPR_ASSERT(grpc_channel_check_connectivity_state(f.client, 0) == GRPC_CHANNEL_IDLE); /* start watching for a change */ gpr_log(GPR_DEBUG, "watching"); grpc_channel_watch_connectivity_state( f.client, GRPC_CHANNEL_IDLE, gpr_now(GPR_CLOCK_MONOTONIC), f.cq, tag(1)); /* eventually the child thread completion should trigger */ gpr_thd_join(thdid); /* check that we're still in idle, and start connecting */ GPR_ASSERT(grpc_channel_check_connectivity_state(f.client, 1) == GRPC_CHANNEL_IDLE); /* start watching for a change */ grpc_channel_watch_connectivity_state(f.client, GRPC_CHANNEL_IDLE, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), f.cq, tag(2)); /* and now the watch should trigger */ cq_expect_completion(cqv, tag(2), 1); cq_verify(cqv); state = grpc_channel_check_connectivity_state(f.client, 0); GPR_ASSERT(state == GRPC_CHANNEL_TRANSIENT_FAILURE || state == GRPC_CHANNEL_CONNECTING); /* quickly followed by a transition to TRANSIENT_FAILURE */ grpc_channel_watch_connectivity_state(f.client, GRPC_CHANNEL_CONNECTING, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), f.cq, tag(3)); cq_expect_completion(cqv, tag(3), 1); cq_verify(cqv); state = grpc_channel_check_connectivity_state(f.client, 0); GPR_ASSERT(state == GRPC_CHANNEL_TRANSIENT_FAILURE || state == GRPC_CHANNEL_CONNECTING); gpr_log(GPR_DEBUG, "*** STARTING SERVER ***"); /* now let's bring up a server to connect to */ config.init_server(&f, NULL); gpr_log(GPR_DEBUG, "*** STARTED SERVER ***"); /* we'll go through some set of transitions (some might be missed), until READY is reached */ while (state != GRPC_CHANNEL_READY) { grpc_channel_watch_connectivity_state( f.client, state, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), f.cq, tag(4)); cq_expect_completion(cqv, tag(4), 1); cq_verify(cqv); state = grpc_channel_check_connectivity_state(f.client, 0); GPR_ASSERT(state == GRPC_CHANNEL_READY || state == GRPC_CHANNEL_CONNECTING || state == GRPC_CHANNEL_TRANSIENT_FAILURE); } /* bring down the server again */ /* we should go immediately to TRANSIENT_FAILURE */ gpr_log(GPR_DEBUG, "*** SHUTTING DOWN SERVER ***"); grpc_channel_watch_connectivity_state(f.client, GRPC_CHANNEL_READY, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), f.cq, tag(5)); grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead)); cq_expect_completion(cqv, tag(5), 1); cq_expect_completion(cqv, tag(0xdead), 1); cq_verify(cqv); state = grpc_channel_check_connectivity_state(f.client, 0); GPR_ASSERT(state == GRPC_CHANNEL_TRANSIENT_FAILURE || state == GRPC_CHANNEL_CONNECTING || state == GRPC_CHANNEL_IDLE); /* cleanup server */ grpc_server_destroy(f.server); gpr_log(GPR_DEBUG, "*** SHUTDOWN SERVER ***"); grpc_channel_destroy(f.client); grpc_completion_queue_shutdown(f.cq); grpc_completion_queue_destroy(f.cq); config.tear_down_data(&f); cq_verifier_destroy(cqv); }
void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator, const char *client_payload, size_t client_payload_length, gpr_uint32 flags) { grpc_endpoint_pair sfd; thd_args a; gpr_thd_id id; char *hex; grpc_transport *transport; grpc_mdctx *mdctx = grpc_mdctx_create(); gpr_slice slice = gpr_slice_from_copied_buffer(client_payload, client_payload_length); hex = gpr_dump(client_payload, client_payload_length, GPR_DUMP_HEX | GPR_DUMP_ASCII); /* Add a debug log */ gpr_log(GPR_INFO, "TEST: %s", hex); gpr_free(hex); /* Init grpc */ grpc_init(); /* Create endpoints */ sfd = grpc_iomgr_create_endpoint_pair("fixture", 65536); /* Create server, completion events */ a.server = grpc_server_create_from_filters(NULL, 0, NULL); a.cq = grpc_completion_queue_create(NULL); gpr_event_init(&a.done_thd); gpr_event_init(&a.done_write); a.validator = validator; grpc_server_register_completion_queue(a.server, a.cq, NULL); grpc_server_start(a.server); transport = grpc_create_chttp2_transport(NULL, sfd.server, mdctx, 0); server_setup_transport(&a, transport, mdctx); grpc_chttp2_transport_start_reading(transport, NULL, 0); /* Bind everything into the same pollset */ grpc_endpoint_add_to_pollset(sfd.client, grpc_cq_pollset(a.cq)); grpc_endpoint_add_to_pollset(sfd.server, grpc_cq_pollset(a.cq)); /* Check a ground truth */ GPR_ASSERT(grpc_server_has_open_connections(a.server)); /* Start validator */ gpr_thd_new(&id, thd_func, &a, NULL); /* Write data */ switch (grpc_endpoint_write(sfd.client, &slice, 1, done_write, &a)) { case GRPC_ENDPOINT_WRITE_DONE: done_write(&a, 1); break; case GRPC_ENDPOINT_WRITE_PENDING: break; case GRPC_ENDPOINT_WRITE_ERROR: done_write(&a, 0); break; } /* Await completion */ GPR_ASSERT( gpr_event_wait(&a.done_write, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5))); if (flags & GRPC_BAD_CLIENT_DISCONNECT) { grpc_endpoint_destroy(sfd.client); sfd.client = NULL; } GPR_ASSERT(gpr_event_wait(&a.done_thd, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5))); /* Shutdown */ if (sfd.client) { grpc_endpoint_destroy(sfd.client); } grpc_server_shutdown_and_notify(a.server, a.cq, NULL); GPR_ASSERT(grpc_completion_queue_pluck( a.cq, NULL, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1), NULL) .type == GRPC_OP_COMPLETE); grpc_server_destroy(a.server); grpc_completion_queue_destroy(a.cq); grpc_shutdown(); }
/* Test grpc_alarm add and cancel. */ static void test_grpc_alarm(void) { grpc_alarm alarm; grpc_alarm alarm_to_cancel; /* Timeout on the alarm cond. var, so make big enough to absorb time deviations. Otherwise, operations after wait will not be properly ordered */ gpr_timespec alarm_deadline; gpr_timespec followup_deadline; alarm_arg arg; alarm_arg arg2; void *fdone; grpc_iomgr_init(); arg.counter = 0; arg.success = SUCCESS_NOT_SET; arg.done_success_ctr = 0; arg.done_cancel_ctr = 0; arg.done = 0; gpr_mu_init(&arg.mu); gpr_cv_init(&arg.cv); gpr_event_init(&arg.fcb_arg); grpc_alarm_init(&alarm, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100), alarm_cb, &arg, gpr_now()); alarm_deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1); gpr_mu_lock(&arg.mu); while (arg.done == 0) { if (gpr_cv_wait(&arg.cv, &arg.mu, alarm_deadline)) { gpr_log(GPR_ERROR, "alarm deadline exceeded"); break; } } gpr_mu_unlock(&arg.mu); followup_deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5); fdone = gpr_event_wait(&arg.fcb_arg, followup_deadline); if (arg.counter != 1) { gpr_log(GPR_ERROR, "Alarm callback not called"); GPR_ASSERT(0); } else if (arg.done_success_ctr != 1) { gpr_log(GPR_ERROR, "Alarm done callback not called with success"); GPR_ASSERT(0); } else if (arg.done_cancel_ctr != 0) { gpr_log(GPR_ERROR, "Alarm done callback called with cancel"); GPR_ASSERT(0); } else if (arg.success == SUCCESS_NOT_SET) { gpr_log(GPR_ERROR, "Alarm callback without status"); GPR_ASSERT(0); } else { gpr_log(GPR_INFO, "Alarm callback called successfully"); } if (fdone != (void *)&arg.fcb_arg) { gpr_log(GPR_ERROR, "Followup callback #1 not invoked properly %p %p", fdone, &arg.fcb_arg); GPR_ASSERT(0); } gpr_cv_destroy(&arg.cv); gpr_mu_destroy(&arg.mu); arg2.counter = 0; arg2.success = SUCCESS_NOT_SET; arg2.done_success_ctr = 0; arg2.done_cancel_ctr = 0; arg2.done = 0; gpr_mu_init(&arg2.mu); gpr_cv_init(&arg2.cv); gpr_event_init(&arg2.fcb_arg); grpc_alarm_init(&alarm_to_cancel, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100), alarm_cb, &arg2, gpr_now()); grpc_alarm_cancel(&alarm_to_cancel); alarm_deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1); gpr_mu_lock(&arg2.mu); while (arg2.done == 0) { gpr_cv_wait(&arg2.cv, &arg2.mu, alarm_deadline); } gpr_mu_unlock(&arg2.mu); gpr_log(GPR_INFO, "alarm done = %d", arg2.done); followup_deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5); fdone = gpr_event_wait(&arg2.fcb_arg, followup_deadline); if (arg2.counter != arg2.done_success_ctr) { gpr_log(GPR_ERROR, "Alarm callback called but didn't lead to done success"); GPR_ASSERT(0); } else if (arg2.done_success_ctr && arg2.done_cancel_ctr) { gpr_log(GPR_ERROR, "Alarm done callback called with success and cancel"); GPR_ASSERT(0); } else if (arg2.done_cancel_ctr + arg2.done_success_ctr != 1) { gpr_log(GPR_ERROR, "Alarm done callback called incorrect number of times"); GPR_ASSERT(0); } else if (arg2.success == SUCCESS_NOT_SET) { gpr_log(GPR_ERROR, "Alarm callback without status"); GPR_ASSERT(0); } else if (arg2.done_success_ctr) { gpr_log(GPR_INFO, "Alarm callback executed before cancel"); gpr_log(GPR_INFO, "Current value of triggered is %d\n", alarm_to_cancel.triggered); } else if (arg2.done_cancel_ctr) { gpr_log(GPR_INFO, "Alarm callback canceled"); gpr_log(GPR_INFO, "Current value of triggered is %d\n", alarm_to_cancel.triggered); } else { gpr_log(GPR_ERROR, "Alarm cancel test should not be here"); GPR_ASSERT(0); } if (fdone != (void *)&arg2.fcb_arg) { gpr_log(GPR_ERROR, "Followup callback #2 not invoked properly %p %p", fdone, &arg2.fcb_arg); GPR_ASSERT(0); } gpr_cv_destroy(&arg2.cv); gpr_mu_destroy(&arg2.mu); grpc_iomgr_shutdown(); }
static void test_ipv6_with_port(void) { gpr_event ev; gpr_event_init(&ev); grpc_resolve_address("[2001:db8::1]:1", NULL, must_succeed, &ev); GPR_ASSERT(gpr_event_wait(&ev, test_deadline())); }