Author: mmichelson Date: Thu Mar 5 16:04:46 2015 New Revision: 432509 URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=432509 Log: Add nominal synchronous and asynchronous tests.
These tests do a bare-bones synchronous and asynchronous resolution to be sure the resolver is called into as expected. Modified: team/group/dns/tests/test_dns.c Modified: team/group/dns/tests/test_dns.c URL: http://svnview.digium.com/svn/asterisk/team/group/dns/tests/test_dns.c?view=diff&rev=432509&r1=432508&r2=432509 ============================================================================== --- team/group/dns/tests/test_dns.c (original) +++ team/group/dns/tests/test_dns.c Thu Mar 5 16:04:46 2015 @@ -587,6 +587,235 @@ return AST_TEST_PASS; } +static struct resolver_data { + int resolve_called; + int cancel_called; + int resolution_complete; +} test_resolver_data; + +static void *resolution_thread(void *dns_query) +{ + struct ast_dns_query *query = dns_query; + + static const char *V4 = "127.0.0.1"; + static const size_t V4_BUFSIZE = sizeof(struct in_addr); + char v4_buf[V4_BUFSIZE]; + + ast_dns_resolver_set_result(query, 0, 0, 0, 0, "asterisk.org"); + + inet_pton(AF_INET, V4, v4_buf); + + ast_dns_resolver_add_record(query, ns_t_a, ns_c_in, 12345, v4_buf, V4_BUFSIZE); + test_resolver_data.resolution_complete = 1; + ast_dns_resolver_completed(query); + + ao2_ref(query, -1); + return NULL; +} + +static int test_resolve(struct ast_dns_query *query) +{ + pthread_t resolver_thread; + + test_resolver_data.resolve_called = 1; + return ast_pthread_create_detached(&resolver_thread, NULL, resolution_thread, ao2_bump(query)); +} + +static int test_cancel(struct ast_dns_query *query) +{ + test_resolver_data.cancel_called = 1; + return 0; +} + +static void resolver_data_init(void) +{ + test_resolver_data.resolve_called = 0; + test_resolver_data.cancel_called = 0; + test_resolver_data.resolution_complete = 0; +} + +static struct ast_dns_resolver test_resolver = { + .name = "test", + .priority = 0, + .resolve = test_resolve, + .cancel = test_cancel, +}; + +AST_TEST_DEFINE(resolver_resolve_sync) +{ + RAII_VAR(struct ast_dns_result *, result, NULL, ast_dns_result_free); + enum ast_test_result_state res = AST_TEST_PASS; + + switch (cmd) { + case TEST_INIT: + info->name = "resolver_resolve_sync"; + info->category = "/main/dns/"; + info->summary = "Test a nominal synchronous DNS resolution"; + info->description = + "This test performs a synchronous DNS resolution of a domain. The goal of this\n" + "test is not to check the records for accuracy. Rather, the goal is to ensure that\n" + "the resolver is called into as expected, that the query completes entirely before\n" + "returning from the synchronous resolution, and to ensure that nothing tried to\n" + "cancel the resolution."; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + if (ast_dns_resolver_register(&test_resolver)) { + ast_test_status_update(test, "Unable to register test resolver\n"); + return AST_TEST_FAIL; + } + + resolver_data_init(); + + if (ast_dns_resolve("asterisk.org", ns_t_a, ns_c_in, &result)) { + ast_test_status_update(test, "Resolution of address failed\n"); + res = AST_TEST_FAIL; + goto cleanup; + } + + if (!result) { + ast_test_status_update(test, "DNS resolution returned a NULL result\n"); + res = AST_TEST_FAIL; + goto cleanup; + } + + if (!test_resolver_data.resolve_called) { + ast_test_status_update(test, "DNS resolution did not call resolver's resolve() method\n"); + res = AST_TEST_FAIL; + goto cleanup; + } + + if (test_resolver_data.cancel_called) { + ast_test_status_update(test, "Resolver's cancel() method called for no reason\n"); + res = AST_TEST_FAIL; + goto cleanup; + } + + if (!test_resolver_data.resolution_complete) { + ast_test_status_update(test, "Synchronous resolution completed early?\n"); + res = AST_TEST_FAIL; + goto cleanup; + } + +cleanup: + ast_dns_resolver_unregister(&test_resolver); + return res; +} + +struct async_resolution_data { + int complete; + ast_mutex_t lock; + ast_cond_t cond; +}; + +static void async_data_destructor(void *obj) +{ + struct async_resolution_data *async_data = obj; + + ast_mutex_destroy(&async_data->lock); + ast_cond_destroy(&async_data->cond); +} + +static struct async_resolution_data *async_data_alloc(void) +{ + struct async_resolution_data *async_data; + + async_data = ao2_alloc(sizeof(*async_data), async_data_destructor); + if (!async_data) { + return NULL; + } + + async_data->complete = 0; + ast_mutex_init(&async_data->lock); + ast_cond_init(&async_data->cond, NULL); + + return async_data; +} + +static void async_callback(const struct ast_dns_query *query) +{ + struct async_resolution_data *async_data = ast_dns_query_get_data(query); + + ast_mutex_lock(&async_data->lock); + async_data->complete = 1; + ast_cond_signal(&async_data->cond); + ast_mutex_unlock(&async_data->lock); +} + +AST_TEST_DEFINE(resolver_resolve_async) +{ + RAII_VAR(struct ast_dns_result *, result, NULL, ast_dns_result_free); + RAII_VAR(struct async_resolution_data *, async_data, NULL, ao2_cleanup); + RAII_VAR(struct ast_dns_query *, query, NULL, ao2_cleanup); + enum ast_test_result_state res = AST_TEST_PASS; + + switch (cmd) { + case TEST_INIT: + info->name = "resolver_resolve_async"; + info->category = "/main/dns/"; + info->summary = "Test a nominal asynchronous DNS resolution"; + info->description = + "This test performs an asynchronous DNS resolution of a domain. The goal of this\n" + "test is not to check the records for accuracy. Rather, the goal is to ensure that\n" + "the resolver is called into as expected, that we regain control before the query\n" + "is completed, and to ensure that nothing tried to cancel the resolution."; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + if (ast_dns_resolver_register(&test_resolver)) { + ast_test_status_update(test, "Unable to register test resolver\n"); + return AST_TEST_FAIL; + } + + resolver_data_init(); + + async_data = async_data_alloc(); + if (!async_data) { + ast_test_status_update(test, "Failed to allocate asynchronous data\n"); + res = AST_TEST_FAIL; + goto cleanup; + } + + query = ast_dns_resolve_async("asterisk.org", ns_t_a, ns_c_in, async_callback, async_data); + if (!query) { + ast_test_status_update(test, "Asynchronous resolution of address failed\n"); + res = AST_TEST_FAIL; + goto cleanup; + } + + if (!test_resolver_data.resolve_called) { + ast_test_status_update(test, "DNS resolution did not call resolver's resolve() method\n"); + res = AST_TEST_FAIL; + goto cleanup; + } + + if (test_resolver_data.cancel_called) { + ast_test_status_update(test, "Resolver's cancel() method called for no reason\n"); + res = AST_TEST_FAIL; + goto cleanup; + } + + ast_mutex_lock(&async_data->lock); + while (!async_data->complete) { + ast_cond_wait(&async_data->cond, &async_data->lock); + } + ast_mutex_unlock(&async_data->lock); + + if (!test_resolver_data.resolution_complete) { + ast_test_status_update(test, "Asynchronous resolution completed early?\n"); + res = AST_TEST_FAIL; + goto cleanup; + } + +cleanup: + ast_dns_resolver_unregister(&test_resolver); + return res; +} + static int unload_module(void) { AST_TEST_UNREGISTER(resolver_register_unregister); @@ -597,6 +826,8 @@ AST_TEST_UNREGISTER(resolver_set_result_off_nominal); AST_TEST_UNREGISTER(resolver_add_record); AST_TEST_UNREGISTER(resolver_add_record_off_nominal); + AST_TEST_UNREGISTER(resolver_resolve_sync); + AST_TEST_UNREGISTER(resolver_resolve_async); return 0; } @@ -611,6 +842,8 @@ AST_TEST_REGISTER(resolver_set_result_off_nominal); AST_TEST_REGISTER(resolver_add_record); AST_TEST_REGISTER(resolver_add_record_off_nominal); + AST_TEST_REGISTER(resolver_resolve_sync); + AST_TEST_REGISTER(resolver_resolve_async); return AST_MODULE_LOAD_SUCCESS; } -- _____________________________________________________________________ -- Bandwidth and Colocation Provided by http://www.api-digital.com -- svn-commits mailing list To UNSUBSCRIBE or update options visit: http://lists.digium.com/mailman/listinfo/svn-commits