Author: mmichelson
Date: Fri Mar  6 14:16:28 2015
New Revision: 432531

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=432531
Log:
Clean up DNS unit test file.

* Put tests in same order they are registered in module load function
* Add doxygen to structures and helper functions.


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=432531&r1=432530&r2=432531
==============================================================================
--- team/group/dns/tests/test_dns.c (original)
+++ team/group/dns/tests/test_dns.c Fri Mar  6 14:16:28 2015
@@ -210,8 +210,7 @@
                        "\t* Ensure that setting resolver data does not result 
in an error.\n"
                        "\t* Ensure that retrieving the set resolver data 
returns the data we expect\n"
                        "\t* Ensure that setting new resolver data on the query 
does not result in an error\n"
-                       "\t* Ensure that retrieving the resolver data returns 
the new data that we set\n"
-                       "\t* Ensure that ast_dns_resolver_completed() removes 
resolver data from the query\n";
+                       "\t* Ensure that retrieving the resolver data returns 
the new data that we set\n";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -500,11 +499,11 @@
        }
 
        for (record = ast_dns_result_get_records(result); record; record = 
ast_dns_record_get_next(record)) {
-               /* The order of returned records is not specified. We use the 
record type as the discriminator
-                * to determine which record data to expect.
+               int res;
+
+               /* The order of returned records is not specified by the API. 
We use the record type
+                * as the discriminator to determine which record data to 
expect.
                 */
-               int res;
-
                if (ast_dns_record_get_rr_type(record) == records[0].type) {
                        res = test_record(test, record, records[0].type, 
records[0].class, records[0].ttl, records[0].data, records[0].size);
                        records[0].visited = 1;
@@ -619,14 +618,38 @@
        return AST_TEST_PASS;
 }
 
+/*!
+ * \brief File-scoped data used during resolver tests
+ *
+ * This data has to live at file-scope since it needs to be
+ * accessible by multiple threads.
+ */
 static struct resolver_data {
+       /*! True if the resolver's resolve() method has been called */
        int resolve_called;
+       /*! True if the resolver's cancel() method has been called */
        int canceled;
+       /*! True if resolution successfully completed. This is mutually 
exclusive with \ref canceled */
        int resolution_complete;
+       /*! Lock used for protecting \ref cancel_cond */
        ast_mutex_t lock;
+       /*! Condition variable used to coordinate canceling a query */
        ast_cond_t cancel_cond;
 } test_resolver_data;
 
+/*!
+ * \brief Thread spawned by the mock resolver
+ *
+ * All DNS resolvers are required to be asynchronous. The mock resolver
+ * spawns this thread for every DNS query that is executed.
+ *
+ * This thread waits for 5 seconds and then returns the same A record
+ * every time. The 5 second wait is to allow for the query to be
+ * canceled if desired
+ *
+ * \param dns_query The ast_dns_query that is being resolved
+ * \return NULL
+ */
 static void *resolution_thread(void *dns_query)
 {
        struct ast_dns_query *query = dns_query;
@@ -665,6 +688,13 @@
        return NULL;
 }
 
+/*!
+ * \brief Mock resolver's resolve method
+ *
+ * \param query The query to resolve
+ * \retval 0 Successfully spawned resolution thread
+ * \retval non-zero Failed to spawn the resolution thread
+ */
 static int test_resolve(struct ast_dns_query *query)
 {
        pthread_t resolver_thread;
@@ -673,6 +703,14 @@
        return ast_pthread_create_detached(&resolver_thread, NULL, 
resolution_thread, ao2_bump(query));
 }
 
+/*!
+ * \brief Mock resolver's cancel method
+ *
+ * This signals the resolution thread not to return any DNS results.
+ *
+ * \param query DNS query to cancel
+ * \return 0
+ */
 static int test_cancel(struct ast_dns_query *query)
 {
        ast_mutex_lock(&test_resolver_data.lock);
@@ -683,6 +721,11 @@
        return 0;
 }
 
+/*!
+ * \brief Initialize global mock resolver data.
+ *
+ * This must be called at the beginning of tests that use the mock resolver
+ */
 static void resolver_data_init(void)
 {
        test_resolver_data.resolve_called = 0;
@@ -693,12 +736,24 @@
        ast_cond_init(&test_resolver_data.cancel_cond, NULL);
 }
 
+/*!
+ * \brief Cleanup global mock resolver data
+ *
+ * This must be called at the end of tests that use the mock resolver
+ */
 static void resolver_data_cleanup(void)
 {
        ast_mutex_destroy(&test_resolver_data.lock);
        ast_cond_destroy(&test_resolver_data.cancel_cond);
 }
 
+/*!
+ * \brief The mock resolver
+ *
+ * The mock resolver does not care about the DNS query that is
+ * actually being made on it. It simply regurgitates the same
+ * DNS record no matter what.
+ */
 static struct ast_dns_resolver test_resolver = {
        .name = "test",
        .priority = 0,
@@ -776,143 +831,12 @@
        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 async_resolution_data *, async_data, NULL, 
ao2_cleanup); 
-       RAII_VAR(struct ast_dns_query *, query, NULL, ao2_cleanup);
-       struct ast_dns_result *result;
-       enum ast_test_result_state res = AST_TEST_PASS;
-       struct timespec timeout;
-
-       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.canceled) {
-               ast_test_status_update(test, "Resolver's cancel() method called 
for no reason\n");
-               res = AST_TEST_FAIL;
-               goto cleanup;
-       }
-
-       clock_gettime(CLOCK_REALTIME, &timeout);
-       timeout.tv_sec += 10;
-       ast_mutex_lock(&async_data->lock);
-       while (!async_data->complete) {
-               if (ast_cond_timedwait(&async_data->cond, &async_data->lock, 
&timeout) == ETIMEDOUT) {
-                       break;
-               }
-       }
-       ast_mutex_unlock(&async_data->lock);
-
-       if (!async_data->complete) {
-               ast_test_status_update(test, "Asynchronous resolution timed 
out\n");
-               res = AST_TEST_FAIL;
-               goto cleanup;
-       }
-
-       if (!test_resolver_data.resolution_complete) {
-               ast_test_status_update(test, "Asynchronous resolution completed 
early?\n");
-               res = AST_TEST_FAIL;
-               goto cleanup;
-       }
-       
-       result = ast_dns_query_get_result(query);
-       if (!result) {
-               ast_test_status_update(test, "Asynchronous resolution yielded 
no result\n");
-               res = AST_TEST_FAIL;
-               goto cleanup;
-       }
-
-       if (!ast_dns_result_get_records(result)) {
-               ast_test_status_update(test, "Asynchronous result had no 
records\n");
-               res = AST_TEST_FAIL;
-               goto cleanup;
-       }
-
-cleanup:
-       ast_dns_resolver_unregister(&test_resolver);
-       resolver_data_cleanup();
-       return res;
-}
-
+/*!
+ * \brief A resolve() method that simply fails
+ *
+ * \param query The DNS query to resolve. This is ignored.
+ * \return -1
+ */
 static int fail_resolve(struct ast_dns_query *query)
 {
        return -1;
@@ -1005,6 +929,173 @@
        return res;
 }
 
+/*!
+ * \brief Data used by async result callback
+ *
+ * This is the typical combination of boolean, lock, and condition
+ * used to synchronize the activities of two threads. In this case,
+ * the testing thread waits on the condition, and the async callback
+ * signals the condition when the asynchronous callback is complete.
+ */
+struct async_resolution_data {
+       int complete;
+       ast_mutex_t lock;
+       ast_cond_t cond;
+};
+
+/*!
+ * \brief Destructor for async_resolution_data
+ */
+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);
+}
+
+/*!
+ * \brief Allocation/initialization for async_resolution_data
+ *
+ * The DNS core mandates that a query's user data has to be ao2 allocated,
+ * so this is a helper method for doing that.
+ *
+ * \retval NULL Failed allocation
+ * \retval non-NULL Newly allocated async_resolution_data
+ */
+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;
+}
+
+/*!
+ * \brief Async DNS callback
+ *
+ * This is called when an async query completes, either because it resolved or
+ * because it was canceled. In our case, this callback is used to signal to the
+ * test that it can continue
+ *
+ * \param query The DNS query that has completed
+ */
+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 async_resolution_data *, async_data, NULL, 
ao2_cleanup); 
+       RAII_VAR(struct ast_dns_query *, query, NULL, ao2_cleanup);
+       struct ast_dns_result *result;
+       enum ast_test_result_state res = AST_TEST_PASS;
+       struct timespec timeout;
+
+       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.canceled) {
+               ast_test_status_update(test, "Resolver's cancel() method called 
for no reason\n");
+               res = AST_TEST_FAIL;
+               goto cleanup;
+       }
+
+       clock_gettime(CLOCK_REALTIME, &timeout);
+       timeout.tv_sec += 10;
+       ast_mutex_lock(&async_data->lock);
+       while (!async_data->complete) {
+               if (ast_cond_timedwait(&async_data->cond, &async_data->lock, 
&timeout) == ETIMEDOUT) {
+                       break;
+               }
+       }
+       ast_mutex_unlock(&async_data->lock);
+
+       if (!async_data->complete) {
+               ast_test_status_update(test, "Asynchronous resolution timed 
out\n");
+               res = AST_TEST_FAIL;
+               goto cleanup;
+       }
+
+       if (!test_resolver_data.resolution_complete) {
+               ast_test_status_update(test, "Asynchronous resolution completed 
early?\n");
+               res = AST_TEST_FAIL;
+               goto cleanup;
+       }
+       
+       result = ast_dns_query_get_result(query);
+       if (!result) {
+               ast_test_status_update(test, "Asynchronous resolution yielded 
no result\n");
+               res = AST_TEST_FAIL;
+               goto cleanup;
+       }
+
+       if (!ast_dns_result_get_records(result)) {
+               ast_test_status_update(test, "Asynchronous result had no 
records\n");
+               res = AST_TEST_FAIL;
+               goto cleanup;
+       }
+
+cleanup:
+       ast_dns_resolver_unregister(&test_resolver);
+       resolver_data_cleanup();
+       return res;
+}
+
+/*! Stub async resolution callback */
 static void stub_callback(const struct ast_dns_query *query)
 {
        return;


-- 
_____________________________________________________________________
-- 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

Reply via email to