|
|
|
@ -55,6 +55,7 @@ typedef struct on_resolution_arg { |
|
|
|
|
gpr_event ev; |
|
|
|
|
} on_resolution_arg; |
|
|
|
|
|
|
|
|
|
// Callback to check the resolution result is as expected.
|
|
|
|
|
void on_resolution_cb(void* arg, grpc_error* error) { |
|
|
|
|
on_resolution_arg* res = static_cast<on_resolution_arg*>(arg); |
|
|
|
|
// We only check the addresses channel arg because that's the only one
|
|
|
|
@ -71,85 +72,167 @@ void on_resolution_cb(void* arg, grpc_error* error) { |
|
|
|
|
gpr_event_set(&res->ev, (void*)1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void test_fake_resolver() { |
|
|
|
|
grpc_core::ExecCtx exec_ctx; |
|
|
|
|
grpc_combiner* combiner = grpc_combiner_create(); |
|
|
|
|
// Create resolver.
|
|
|
|
|
grpc_fake_resolver_response_generator* response_generator = |
|
|
|
|
grpc_fake_resolver_response_generator_create(); |
|
|
|
|
grpc_resolver* resolver = build_fake_resolver(combiner, response_generator); |
|
|
|
|
GPR_ASSERT(resolver != nullptr); |
|
|
|
|
|
|
|
|
|
// Setup expectations.
|
|
|
|
|
grpc_uri* uris[] = {grpc_uri_parse("ipv4:10.2.1.1:1234", true), |
|
|
|
|
grpc_uri_parse("ipv4:127.0.0.1:4321", true)}; |
|
|
|
|
const char* balancer_names[] = {"name1", "name2"}; |
|
|
|
|
const bool is_balancer[] = {true, false}; |
|
|
|
|
grpc_lb_addresses* addresses = grpc_lb_addresses_create(3, nullptr); |
|
|
|
|
for (size_t i = 0; i < GPR_ARRAY_SIZE(uris); ++i) { |
|
|
|
|
// Create a new resolution containing 2 addresses.
|
|
|
|
|
static grpc_channel_args* create_new_resolver_result() { |
|
|
|
|
static size_t test_counter = 0; |
|
|
|
|
const size_t num_addresses = 2; |
|
|
|
|
char* uri_string; |
|
|
|
|
char* balancer_name; |
|
|
|
|
// Create grpc_lb_addresses.
|
|
|
|
|
grpc_lb_addresses* addresses = |
|
|
|
|
grpc_lb_addresses_create(num_addresses, nullptr); |
|
|
|
|
for (size_t i = 0; i < num_addresses; ++i) { |
|
|
|
|
gpr_asprintf(&uri_string, "ipv4:127.0.0.1:100%" PRIuPTR, |
|
|
|
|
test_counter * num_addresses + i); |
|
|
|
|
grpc_uri* uri = grpc_uri_parse(uri_string, true); |
|
|
|
|
gpr_asprintf(&balancer_name, "balancer%" PRIuPTR, |
|
|
|
|
test_counter * num_addresses + i); |
|
|
|
|
grpc_lb_addresses_set_address_from_uri( |
|
|
|
|
addresses, i, uris[i], is_balancer[i], balancer_names[i], nullptr); |
|
|
|
|
grpc_uri_destroy(uris[i]); |
|
|
|
|
addresses, i, uri, bool(num_addresses % 2), balancer_name, nullptr); |
|
|
|
|
gpr_free(balancer_name); |
|
|
|
|
grpc_uri_destroy(uri); |
|
|
|
|
gpr_free(uri_string); |
|
|
|
|
} |
|
|
|
|
// Convert grpc_lb_addresses to grpc_channel_args.
|
|
|
|
|
const grpc_arg addresses_arg = |
|
|
|
|
grpc_lb_addresses_create_channel_arg(addresses); |
|
|
|
|
grpc_channel_args* results = |
|
|
|
|
grpc_channel_args_copy_and_add(nullptr, &addresses_arg, 1); |
|
|
|
|
grpc_lb_addresses_destroy(addresses); |
|
|
|
|
++test_counter; |
|
|
|
|
return results; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static on_resolution_arg create_on_resolution_arg(grpc_channel_args* results) { |
|
|
|
|
on_resolution_arg on_res_arg; |
|
|
|
|
memset(&on_res_arg, 0, sizeof(on_res_arg)); |
|
|
|
|
on_res_arg.expected_resolver_result = results; |
|
|
|
|
gpr_event_init(&on_res_arg.ev); |
|
|
|
|
return on_res_arg; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void test_fake_resolver() { |
|
|
|
|
grpc_core::ExecCtx exec_ctx; |
|
|
|
|
grpc_combiner* combiner = grpc_combiner_create(); |
|
|
|
|
// Create resolver.
|
|
|
|
|
grpc_fake_resolver_response_generator* response_generator = |
|
|
|
|
grpc_fake_resolver_response_generator_create(); |
|
|
|
|
grpc_resolver* resolver = build_fake_resolver(combiner, response_generator); |
|
|
|
|
GPR_ASSERT(resolver != nullptr); |
|
|
|
|
// Test 1: normal resolution.
|
|
|
|
|
// next_results != NULL, results_upon_error == NULL, last_used_results ==
|
|
|
|
|
// NULL. Expected response is next_results.
|
|
|
|
|
grpc_channel_args* results = create_new_resolver_result(); |
|
|
|
|
on_resolution_arg on_res_arg = create_on_resolution_arg(results); |
|
|
|
|
grpc_closure* on_resolution = GRPC_CLOSURE_CREATE( |
|
|
|
|
on_resolution_cb, &on_res_arg, grpc_combiner_scheduler(combiner)); |
|
|
|
|
|
|
|
|
|
// Set resolver results and trigger first resolution. on_resolution_cb
|
|
|
|
|
// performs the checks.
|
|
|
|
|
// Resolution won't be triggered until next_results is set.
|
|
|
|
|
grpc_resolver_next_locked(resolver, &on_res_arg.resolver_result, |
|
|
|
|
on_resolution); |
|
|
|
|
grpc_fake_resolver_response_generator_set_response(response_generator, |
|
|
|
|
results); |
|
|
|
|
grpc_core::ExecCtx::Get()->Flush(); |
|
|
|
|
GPR_ASSERT(gpr_event_wait(&on_res_arg.ev, |
|
|
|
|
grpc_timeout_seconds_to_deadline(5)) != nullptr); |
|
|
|
|
// Test 2: update resolution.
|
|
|
|
|
// next_results != NULL, results_upon_error == NULL, last_used_results !=
|
|
|
|
|
// NULL. Expected response is next_results.
|
|
|
|
|
results = create_new_resolver_result(); |
|
|
|
|
grpc_channel_args* last_used_results = grpc_channel_args_copy(results); |
|
|
|
|
on_res_arg = create_on_resolution_arg(results); |
|
|
|
|
on_resolution = GRPC_CLOSURE_CREATE(on_resolution_cb, &on_res_arg, |
|
|
|
|
grpc_combiner_scheduler(combiner)); |
|
|
|
|
// Resolution won't be triggered until next_results is set.
|
|
|
|
|
grpc_resolver_next_locked(resolver, &on_res_arg.resolver_result, |
|
|
|
|
on_resolution); |
|
|
|
|
grpc_fake_resolver_response_generator_set_response(response_generator, |
|
|
|
|
results); |
|
|
|
|
grpc_core::ExecCtx::Get()->Flush(); |
|
|
|
|
GPR_ASSERT(gpr_event_wait(&on_res_arg.ev, |
|
|
|
|
grpc_timeout_seconds_to_deadline(5)) != nullptr); |
|
|
|
|
|
|
|
|
|
// Setup update.
|
|
|
|
|
grpc_uri* uris_update[] = {grpc_uri_parse("ipv4:192.168.1.0:31416", true)}; |
|
|
|
|
const char* balancer_names_update[] = {"name3"}; |
|
|
|
|
const bool is_balancer_update[] = {false}; |
|
|
|
|
grpc_lb_addresses* addresses_update = grpc_lb_addresses_create(1, nullptr); |
|
|
|
|
for (size_t i = 0; i < GPR_ARRAY_SIZE(uris_update); ++i) { |
|
|
|
|
grpc_lb_addresses_set_address_from_uri(addresses_update, i, uris_update[i], |
|
|
|
|
is_balancer_update[i], |
|
|
|
|
balancer_names_update[i], nullptr); |
|
|
|
|
grpc_uri_destroy(uris_update[i]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_arg addresses_update_arg = |
|
|
|
|
grpc_lb_addresses_create_channel_arg(addresses_update); |
|
|
|
|
grpc_channel_args* results_update = |
|
|
|
|
grpc_channel_args_copy_and_add(nullptr, &addresses_update_arg, 1); |
|
|
|
|
grpc_lb_addresses_destroy(addresses_update); |
|
|
|
|
|
|
|
|
|
// Setup expectations for the update.
|
|
|
|
|
on_resolution_arg on_res_arg_update; |
|
|
|
|
memset(&on_res_arg_update, 0, sizeof(on_res_arg_update)); |
|
|
|
|
on_res_arg_update.expected_resolver_result = results_update; |
|
|
|
|
gpr_event_init(&on_res_arg_update.ev); |
|
|
|
|
on_resolution = GRPC_CLOSURE_CREATE(on_resolution_cb, &on_res_arg_update, |
|
|
|
|
// Test 3: fallback re-resolution.
|
|
|
|
|
// next_results == NULL, results_upon_error == NULL, last_used_results !=
|
|
|
|
|
// NULL. Expected response is last_used_results.
|
|
|
|
|
on_res_arg = create_on_resolution_arg(last_used_results); |
|
|
|
|
on_resolution = GRPC_CLOSURE_CREATE(on_resolution_cb, &on_res_arg, |
|
|
|
|
grpc_combiner_scheduler(combiner)); |
|
|
|
|
|
|
|
|
|
// Set updated resolver results and trigger a second resolution.
|
|
|
|
|
grpc_resolver_next_locked(resolver, &on_res_arg.resolver_result, |
|
|
|
|
on_resolution); |
|
|
|
|
// Trigger a re-resolution.
|
|
|
|
|
grpc_resolver_channel_saw_error_locked(resolver); |
|
|
|
|
grpc_core::ExecCtx::Get()->Flush(); |
|
|
|
|
GPR_ASSERT(gpr_event_wait(&on_res_arg.ev, |
|
|
|
|
grpc_timeout_seconds_to_deadline(5)) != nullptr); |
|
|
|
|
// Test 4: normal re-resolution.
|
|
|
|
|
// next_results == NULL, results_upon_error != NULL, last_used_results !=
|
|
|
|
|
// NULL. Expected response is results_upon_error.
|
|
|
|
|
grpc_channel_args* results_upon_error = create_new_resolver_result(); |
|
|
|
|
on_res_arg = |
|
|
|
|
create_on_resolution_arg(grpc_channel_args_copy(results_upon_error)); |
|
|
|
|
on_resolution = GRPC_CLOSURE_CREATE(on_resolution_cb, &on_res_arg, |
|
|
|
|
grpc_combiner_scheduler(combiner)); |
|
|
|
|
grpc_resolver_next_locked(resolver, &on_res_arg.resolver_result, |
|
|
|
|
on_resolution); |
|
|
|
|
// Set results_upon_error.
|
|
|
|
|
grpc_fake_resolver_response_generator_set_response_upon_error( |
|
|
|
|
response_generator, results_upon_error); |
|
|
|
|
// Flush here to guarantee that the response has been set.
|
|
|
|
|
grpc_core::ExecCtx::Get()->Flush(); |
|
|
|
|
// Trigger a re-resolution.
|
|
|
|
|
grpc_resolver_channel_saw_error_locked(resolver); |
|
|
|
|
grpc_core::ExecCtx::Get()->Flush(); |
|
|
|
|
GPR_ASSERT(gpr_event_wait(&on_res_arg.ev, |
|
|
|
|
grpc_timeout_seconds_to_deadline(5)) != nullptr); |
|
|
|
|
// Test 5: repeat re-resolution.
|
|
|
|
|
// next_results == NULL, results_upon_error != NULL, last_used_results !=
|
|
|
|
|
// NULL. Expected response is results_upon_error.
|
|
|
|
|
on_res_arg = create_on_resolution_arg(results_upon_error); |
|
|
|
|
on_resolution = GRPC_CLOSURE_CREATE(on_resolution_cb, &on_res_arg, |
|
|
|
|
grpc_combiner_scheduler(combiner)); |
|
|
|
|
grpc_resolver_next_locked(resolver, &on_res_arg.resolver_result, |
|
|
|
|
on_resolution); |
|
|
|
|
// Trigger a re-resolution.
|
|
|
|
|
grpc_resolver_channel_saw_error_locked(resolver); |
|
|
|
|
grpc_core::ExecCtx::Get()->Flush(); |
|
|
|
|
GPR_ASSERT(gpr_event_wait(&on_res_arg.ev, |
|
|
|
|
grpc_timeout_seconds_to_deadline(5)) != nullptr); |
|
|
|
|
// Test 6: normal resolution.
|
|
|
|
|
// next_results != NULL, results_upon_error != NULL, last_used_results !=
|
|
|
|
|
// NULL. Expected response is next_results.
|
|
|
|
|
results = create_new_resolver_result(); |
|
|
|
|
last_used_results = grpc_channel_args_copy(results); |
|
|
|
|
on_res_arg = create_on_resolution_arg(results); |
|
|
|
|
on_resolution = GRPC_CLOSURE_CREATE(on_resolution_cb, &on_res_arg, |
|
|
|
|
grpc_combiner_scheduler(combiner)); |
|
|
|
|
// Resolution won't be triggered until next_results is set.
|
|
|
|
|
grpc_resolver_next_locked(resolver, &on_res_arg.resolver_result, |
|
|
|
|
on_resolution); |
|
|
|
|
grpc_fake_resolver_response_generator_set_response(response_generator, |
|
|
|
|
results_update); |
|
|
|
|
grpc_resolver_next_locked(resolver, &on_res_arg_update.resolver_result, |
|
|
|
|
results); |
|
|
|
|
grpc_core::ExecCtx::Get()->Flush(); |
|
|
|
|
GPR_ASSERT(gpr_event_wait(&on_res_arg.ev, |
|
|
|
|
grpc_timeout_seconds_to_deadline(5)) != nullptr); |
|
|
|
|
// Test 7: fallback re-resolution.
|
|
|
|
|
// next_results == NULL, results_upon_error == NULL, last_used_results !=
|
|
|
|
|
// NULL. Expected response is last_used_results.
|
|
|
|
|
on_res_arg = create_on_resolution_arg(last_used_results); |
|
|
|
|
on_resolution = GRPC_CLOSURE_CREATE(on_resolution_cb, &on_res_arg, |
|
|
|
|
grpc_combiner_scheduler(combiner)); |
|
|
|
|
grpc_resolver_next_locked(resolver, &on_res_arg.resolver_result, |
|
|
|
|
on_resolution); |
|
|
|
|
// Reset results_upon_error.
|
|
|
|
|
grpc_fake_resolver_response_generator_set_response_upon_error( |
|
|
|
|
response_generator, nullptr); |
|
|
|
|
// Flush here to guarantee that results_upon_error has been reset.
|
|
|
|
|
grpc_core::ExecCtx::Get()->Flush(); |
|
|
|
|
// Trigger a re-resolution.
|
|
|
|
|
grpc_resolver_channel_saw_error_locked(resolver); |
|
|
|
|
grpc_core::ExecCtx::Get()->Flush(); |
|
|
|
|
GPR_ASSERT(gpr_event_wait(&on_res_arg_update.ev, |
|
|
|
|
GPR_ASSERT(gpr_event_wait(&on_res_arg.ev, |
|
|
|
|
grpc_timeout_seconds_to_deadline(5)) != nullptr); |
|
|
|
|
|
|
|
|
|
// Requesting a new resolution without re-senting the response shouldn't
|
|
|
|
|
// trigger the resolution callback.
|
|
|
|
|
// Test 8: no-op.
|
|
|
|
|
// Requesting a new resolution without setting the response shouldn't trigger
|
|
|
|
|
// the resolution callback.
|
|
|
|
|
memset(&on_res_arg, 0, sizeof(on_res_arg)); |
|
|
|
|
grpc_resolver_next_locked(resolver, &on_res_arg.resolver_result, |
|
|
|
|
on_resolution); |
|
|
|
@ -157,10 +240,9 @@ static void test_fake_resolver() { |
|
|
|
|
GPR_ASSERT(gpr_event_wait(&on_res_arg.ev, |
|
|
|
|
grpc_timeout_milliseconds_to_deadline(100)) == |
|
|
|
|
nullptr); |
|
|
|
|
|
|
|
|
|
// Clean up.
|
|
|
|
|
GRPC_COMBINER_UNREF(combiner, "test_fake_resolver"); |
|
|
|
|
GRPC_RESOLVER_UNREF(resolver, "test_fake_resolver"); |
|
|
|
|
|
|
|
|
|
grpc_fake_resolver_response_generator_unref(response_generator); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|