|
|
|
@ -33,6 +33,16 @@ typedef struct { |
|
|
|
|
grpc_completion_queue* cq; |
|
|
|
|
} child_events; |
|
|
|
|
|
|
|
|
|
struct CallbackContext { |
|
|
|
|
grpc_experimental_completion_queue_functor functor; |
|
|
|
|
gpr_event finished; |
|
|
|
|
explicit CallbackContext(void (*cb)( |
|
|
|
|
grpc_experimental_completion_queue_functor* functor, int success)) { |
|
|
|
|
functor.functor_run = cb; |
|
|
|
|
gpr_event_init(&finished); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static void child_thread(void* arg) { |
|
|
|
|
child_events* ce = static_cast<child_events*>(arg); |
|
|
|
|
grpc_event ev; |
|
|
|
@ -163,9 +173,74 @@ static void test_connectivity(grpc_end2end_test_config config) { |
|
|
|
|
cq_verifier_destroy(cqv); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void cb_watch_connectivity( |
|
|
|
|
grpc_experimental_completion_queue_functor* functor, int success) { |
|
|
|
|
CallbackContext* cb_ctx = (CallbackContext*)functor; |
|
|
|
|
|
|
|
|
|
gpr_log(GPR_DEBUG, "cb_watch_connectivity called, verifying"); |
|
|
|
|
|
|
|
|
|
/* callback must not have errors */ |
|
|
|
|
GPR_ASSERT(success != 0); |
|
|
|
|
|
|
|
|
|
gpr_event_set(&cb_ctx->finished, (void*)1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void cb_shutdown(grpc_experimental_completion_queue_functor* functor, |
|
|
|
|
int success) { |
|
|
|
|
CallbackContext* cb_ctx = (CallbackContext*)functor; |
|
|
|
|
|
|
|
|
|
gpr_log(GPR_DEBUG, "cb_shutdown called, nothing to do"); |
|
|
|
|
gpr_event_set(&cb_ctx->finished, (void*)1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void test_watch_connectivity_cq_callback( |
|
|
|
|
grpc_end2end_test_config config) { |
|
|
|
|
CallbackContext cb_ctx(cb_watch_connectivity); |
|
|
|
|
CallbackContext cb_shutdown_ctx(cb_shutdown); |
|
|
|
|
grpc_completion_queue* cq; |
|
|
|
|
grpc_end2end_test_fixture f = config.create_fixture(nullptr, nullptr); |
|
|
|
|
|
|
|
|
|
config.init_client(&f, nullptr); |
|
|
|
|
|
|
|
|
|
/* start connecting */ |
|
|
|
|
grpc_channel_check_connectivity_state(f.client, 1); |
|
|
|
|
|
|
|
|
|
/* create the cq callback */ |
|
|
|
|
cq = grpc_completion_queue_create_for_callback(&cb_shutdown_ctx.functor, |
|
|
|
|
nullptr); |
|
|
|
|
|
|
|
|
|
/* start watching for any change, cb is immediately called
|
|
|
|
|
* and no dead lock should be raised */ |
|
|
|
|
grpc_channel_watch_connectivity_state(f.client, GRPC_CHANNEL_IDLE, |
|
|
|
|
grpc_timeout_seconds_to_deadline(3), cq, |
|
|
|
|
&cb_ctx.functor); |
|
|
|
|
|
|
|
|
|
/* we just check that the callback was executed once notifying a connection
|
|
|
|
|
* transition */ |
|
|
|
|
GPR_ASSERT(gpr_event_wait(&cb_ctx.finished, |
|
|
|
|
gpr_inf_future(GPR_CLOCK_MONOTONIC)) != nullptr); |
|
|
|
|
|
|
|
|
|
/* shutdown, since shutdown cb might be executed in a background thread
|
|
|
|
|
* we actively wait till is executed. */ |
|
|
|
|
grpc_completion_queue_shutdown(cq); |
|
|
|
|
gpr_event_wait(&cb_shutdown_ctx.finished, |
|
|
|
|
gpr_inf_future(GPR_CLOCK_MONOTONIC)); |
|
|
|
|
|
|
|
|
|
/* cleanup */ |
|
|
|
|
grpc_channel_destroy(f.client); |
|
|
|
|
grpc_completion_queue_destroy(cq); |
|
|
|
|
|
|
|
|
|
/* shutdown_cq and cq are not used in this test */ |
|
|
|
|
grpc_completion_queue_destroy(f.cq); |
|
|
|
|
grpc_completion_queue_destroy(f.shutdown_cq); |
|
|
|
|
|
|
|
|
|
config.tear_down_data(&f); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void connectivity(grpc_end2end_test_config config) { |
|
|
|
|
GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION); |
|
|
|
|
test_connectivity(config); |
|
|
|
|
test_watch_connectivity_cq_callback(config); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void connectivity_pre_init(void) {} |
|
|
|
|