[asterisk-commits] mmichelson: branch group/dns r432452 - in /team/group/dns: include/asterisk/ ...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Mar 4 12:50:26 CST 2015


Author: mmichelson
Date: Wed Mar  4 12:50:24 2015
New Revision: 432452

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=432452
Log:
Commit progress on some unit tests.

I decided to make this commit now to save some progress made on
unit tests. In addition, this makes a few DNS API changes:

* Structures are defined in dns_internal.h. This is useful for
unit tests that wish to create DNS queries without having to
perform a resolution.
* Some parameters have been constified.


Added:
    team/group/dns/include/asterisk/dns_internal.h   (with props)
    team/group/dns/tests/test_dns.c   (with props)
Modified:
    team/group/dns/include/asterisk/dns_resolver.h
    team/group/dns/main/dns_core.c

Added: team/group/dns/include/asterisk/dns_internal.h
URL: http://svnview.digium.com/svn/asterisk/team/group/dns/include/asterisk/dns_internal.h?view=auto&rev=432452
==============================================================================
--- team/group/dns/include/asterisk/dns_internal.h (added)
+++ team/group/dns/include/asterisk/dns_internal.h Wed Mar  4 12:50:24 2015
@@ -1,0 +1,109 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2015, Digium, Inc.
+ *
+ * Joshua Colp <jcolp at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Internal DNS structure definitions
+ *
+ * \author Joshua Colp <jcolp at digium.com>
+ */
+
+/*! \brief Generic DNS record information */
+struct ast_dns_record {
+	/*! \brief Resource record type */
+	int rr_type;
+	/*! \brief Resource record class */
+	int rr_class;
+	/*! \brief Time-to-live of the record */
+	int ttl;
+	/*! \brief The raw DNS record */
+	char *data;
+	/*! \brief The size of the raw DNS record */
+	size_t data_len;
+	/*! \brief Linked list information */
+	AST_LIST_ENTRY(ast_dns_record) list;
+};
+
+/*! \brief An SRV record */
+struct ast_dns_srv_record {
+	/*! \brief Generic DNS record information */
+	struct ast_dns_record generic;
+	/*! \brief The hostname in the SRV record */
+	const char *host;
+	/*! \brief The priority of the SRV record */
+	unsigned short priority;
+	/*! \brief The weight of the SRV record */
+	unsigned short weight;
+	/*! \brief The port in the SRV record */
+	unsigned short port;
+};
+
+/*! \brief A NAPTR record */
+struct ast_dns_naptr_record {
+	/*! \brief Generic DNS record information */
+	struct ast_dns_record generic;
+	/*! \brief The flags from the NAPTR record */
+	const char *flags;
+	/*! \brief The service from the NAPTR record */
+	const char *service;
+	/*! \brief The regular expression from the NAPTR record */
+	const char *regexp;
+	/*! \brief The replacement from the NAPTR record */
+	const char *replacement;
+	/*! \brief The order for the NAPTR record */
+	unsigned short order;
+	/*! \brief The preference of the NAPTR record */
+	unsigned short preference;
+};
+
+/*! \brief The result of a DNS query */
+struct ast_dns_result {
+	/*! \brief Whether the domain was not found */
+	unsigned int nxdomain;
+	/*! \brief Whether the result is secure */
+	unsigned int secure;
+	/*! \brief Whether the result is bogus */
+	unsigned int bogus;
+	/*! \brief The canonical name */
+	const char *canonical;
+	/*! \brief Records returned */
+	AST_LIST_HEAD_NOLOCK(, ast_dns_record) records;
+};
+
+/*! \brief A DNS query */
+struct ast_dns_query {
+	/*! \brief Callback to invoke upon completion */
+	ast_dns_resolve_callback callback;
+	/*! \brief User-specific data */
+	void *user_data;
+	/*! \brief The resolver in use for this query */
+	struct ast_dns_resolver *resolver;
+	/*! \brief Resolver-specific data */
+	void *resolver_data;
+	/*! \brief Result of the DNS query */
+	struct ast_dns_result *result;
+	/*! \brief Timer for recurring resolution */
+	int timer;
+	/*! \brief Resource record type */
+	int rr_type;
+	/*! \brief Resource record class */
+	int rr_class;
+	/*! \brief The name of what is being resolved */
+	char name[0];
+};
+

Propchange: team/group/dns/include/asterisk/dns_internal.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/group/dns/include/asterisk/dns_internal.h
------------------------------------------------------------------------------
    svn:keywords = 'Author Date Id Revision'

Propchange: team/group/dns/include/asterisk/dns_internal.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: team/group/dns/include/asterisk/dns_resolver.h
URL: http://svnview.digium.com/svn/asterisk/team/group/dns/include/asterisk/dns_resolver.h?view=diff&rev=432452&r1=432451&r2=432452
==============================================================================
--- team/group/dns/include/asterisk/dns_resolver.h (original)
+++ team/group/dns/include/asterisk/dns_resolver.h Wed Mar  4 12:50:24 2015
@@ -86,7 +86,7 @@
  * \retval 0 success
  * \retval -1 failure
  */
-int ast_dns_resolver_add_record(struct ast_dns_query *query, int rr_type, int rr_class, int ttl, char *data, size_t size);
+int ast_dns_resolver_add_record(struct ast_dns_query *query, int rr_type, int rr_class, int ttl, const char *data, const size_t size);
 
 /*!
  * \brief Mark a DNS query as having been completed

Modified: team/group/dns/main/dns_core.c
URL: http://svnview.digium.com/svn/asterisk/team/group/dns/main/dns_core.c?view=diff&rev=432452&r1=432451&r2=432452
==============================================================================
--- team/group/dns/main/dns_core.c (original)
+++ team/group/dns/main/dns_core.c Wed Mar  4 12:50:24 2015
@@ -40,92 +40,9 @@
 #include "asterisk/dns_srv.h"
 #include "asterisk/dns_tlsa.h"
 #include "asterisk/dns_resolver.h"
+#include "asterisk/dns_internal.h"
 
 AST_RWLIST_HEAD_STATIC(resolvers, ast_dns_resolver);
-
-/*! \brief Generic DNS record information */
-struct ast_dns_record {
-	/*! \brief Resource record type */
-	int rr_type;
-	/*! \brief Resource record class */
-	int rr_class;
-	/*! \brief Time-to-live of the record */
-	int ttl;
-	/*! \brief The raw DNS record */
-	char *data;
-	/*! \brief The size of the raw DNS record */
-	size_t data_len;
-	/*! \brief Linked list information */
-	AST_LIST_ENTRY(ast_dns_record) list;
-};
-
-/*! \brief An SRV record */
-struct ast_dns_srv_record {
-	/*! \brief Generic DNS record information */
-	struct ast_dns_record generic;
-	/*! \brief The hostname in the SRV record */
-	const char *host;
-	/*! \brief The priority of the SRV record */
-	unsigned short priority;
-	/*! \brief The weight of the SRV record */
-	unsigned short weight;
-	/*! \brief The port in the SRV record */
-	unsigned short port;
-};
-
-/*! \brief A NAPTR record */
-struct ast_dns_naptr_record {
-	/*! \brief Generic DNS record information */
-	struct ast_dns_record generic;
-	/*! \brief The flags from the NAPTR record */
-	const char *flags;
-	/*! \brief The service from the NAPTR record */
-	const char *service;
-	/*! \brief The regular expression from the NAPTR record */
-	const char *regexp;
-	/*! \brief The replacement from the NAPTR record */
-	const char *replacement;
-	/*! \brief The order for the NAPTR record */
-	unsigned short order;
-	/*! \brief The preference of the NAPTR record */
-	unsigned short preference;
-};
-
-/*! \brief The result of a DNS query */
-struct ast_dns_result {
-	/*! \brief Whether the domain was not found */
-	unsigned int nxdomain;
-	/*! \brief Whether the result is secure */
-	unsigned int secure;
-	/*! \brief Whether the result is bogus */
-	unsigned int bogus;
-	/*! \brief The canonical name */
-	const char *canonical;
-	/*! \brief Records returned */
-	AST_LIST_HEAD_NOLOCK(, ast_dns_record) records;
-};
-
-/*! \brief A DNS query */
-struct ast_dns_query {
-	/*! \brief Callback to invoke upon completion */
-	ast_dns_resolve_callback callback;
-	/*! \brief User-specific data */
-	void *user_data;
-	/*! \brief The resolver in use for this query */
-	struct ast_dns_resolver *resolver;
-	/*! \brief Resolver-specific data */
-	void *resolver_data;
-	/*! \brief Result of the DNS query */
-	struct ast_dns_result *result;
-	/*! \brief Timer for recurring resolution */
-	int timer;
-	/*! \brief Resource record type */
-	int rr_type;
-	/*! \brief Resource record class */
-	int rr_class;
-	/*! \brief The name of what is being resolved */
-	char name[0];
-};
 
 const char *ast_dns_query_get_name(const struct ast_dns_query *query)
 {
@@ -426,7 +343,7 @@
 	query->result = NULL;
 }
 
-int ast_dns_resolver_add_record(struct ast_dns_query *query, int rr_type, int rr_class, int ttl, char *data, size_t size)
+int ast_dns_resolver_add_record(struct ast_dns_query *query, int rr_type, int rr_class, int ttl, const char *data, const size_t size)
 {
 	if (!query->result) {
 		return -1;
@@ -509,4 +426,4 @@
 	AST_RWLIST_UNLOCK(&resolvers);
 
 	ast_verb(2, "Unregistered DNS resolver '%s'\n", resolver->name);
-}
+}

Added: team/group/dns/tests/test_dns.c
URL: http://svnview.digium.com/svn/asterisk/team/group/dns/tests/test_dns.c?view=auto&rev=432452
==============================================================================
--- team/group/dns/tests/test_dns.c (added)
+++ team/group/dns/tests/test_dns.c Wed Mar  4 12:50:24 2015
@@ -1,0 +1,384 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2015, Mark Michelson
+ *
+ * Mark Michelson <mmichelson at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*** MODULEINFO
+	<depend>TEST_FRAMEWORK</depend>
+	<support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+#include <arpa/nameser.h>
+
+#include "asterisk/test.h"
+#include "asterisk/module.h"
+#include "asterisk/dns_core.h"
+#include "asterisk/dns_resolver.h"
+#include "asterisk/dns_internal.h"
+
+/* Used when a stub is needed for certain tests */
+static int stub_resolve(struct ast_dns_query *query)
+{
+	return 0;
+}
+
+/* Used when a stub is needed for certain tests */
+static int stub_cancel(struct ast_dns_query *query)
+{
+	return 0;
+}
+
+AST_TEST_DEFINE(resolver_register_unregister)
+{
+	struct ast_dns_resolver cool_guy_resolver = {
+		.name = "A snake that swallowed a deer",
+		.priority = 19890504,
+		.resolve = stub_resolve,
+		.cancel = stub_cancel,
+	};
+
+	switch (cmd) {
+	case TEST_INIT:
+		info->name = "resolver_register_unregister";
+		info->category = "/main/dns/";
+		info->summary = "Test nominal resolver registration and unregistration";
+		info->description =
+			"The test performs the following steps:\n"
+			"\t* Register a valid resolver.\n"
+			"\t* Unregister the resolver.\n"
+			"If either step fails, the test fails\n";
+		return AST_TEST_NOT_RUN;
+	case TEST_EXECUTE:
+		break;
+	}
+
+	if (ast_dns_resolver_register(&cool_guy_resolver)) {
+		ast_test_status_update(test, "Unable to register a perfectly good resolver\n");
+		return AST_TEST_FAIL;
+	}
+
+	ast_dns_resolver_unregister(&cool_guy_resolver);
+
+	return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(resolver_register_off_nominal)
+{
+	struct ast_dns_resolver valid = {
+		.name = "valid",
+		.resolve = stub_resolve,
+		.cancel = stub_cancel,
+	};
+
+	struct ast_dns_resolver incomplete1 = {
+		.name = NULL,
+		.resolve = stub_resolve,
+		.cancel = stub_cancel,
+	};
+
+	struct ast_dns_resolver incomplete2 = {
+		.name = "incomplete2",
+		.resolve = NULL,
+		.cancel = stub_cancel,
+	};
+
+	struct ast_dns_resolver incomplete3 = {
+		.name = "incomplete3",
+		.resolve = stub_resolve,
+		.cancel = NULL,
+	};
+
+	switch (cmd) {
+	case TEST_INIT:
+		info->name = "resolver_register_off_nominal";
+		info->category = "/main/dns/";
+		info->summary = "Test off-nominal resolver registration";
+		info->description =
+			"Test off-nominal resolver registration:\n"
+			"\t* Register a duplicate resolver\n"
+			"\t* Register a resolver without a name\n"
+			"\t* Register a resolver without a resolve() method\n"
+			"\t* Register a resolver without a cancel() method\n";
+		return AST_TEST_NOT_RUN;
+	case TEST_EXECUTE:
+		break;
+	}
+
+	if (ast_dns_resolver_register(&valid)) {
+		ast_test_status_update(test, "Failed to register valid resolver\n");
+		return AST_TEST_FAIL;
+	}
+
+	if (!ast_dns_resolver_register(&valid)) {
+		ast_test_status_update(test, "Successfully registered the same resolver multiple times\n");
+		return AST_TEST_FAIL;
+	}
+
+	ast_dns_resolver_unregister(&valid);
+
+	if (!ast_dns_resolver_register(NULL)) {
+		ast_test_status_update(test, "Successfully registered a NULL resolver\n");
+		return AST_TEST_FAIL;
+	}
+
+	if (!ast_dns_resolver_register(&incomplete1)) {
+		ast_test_status_update(test, "Successfully registered a DNS resolver with no name\n");
+		return AST_TEST_FAIL;
+	}
+
+	if (!ast_dns_resolver_register(&incomplete2)) {
+		ast_test_status_update(test, "Successfully registered a DNS resolver with no resolve() method\n");
+		return AST_TEST_FAIL;
+	}
+
+	if (!ast_dns_resolver_register(&incomplete3)) {
+		ast_test_status_update(test, "Successfully registered a DNS resolver with no cancel() method\n");
+		return AST_TEST_FAIL;
+	}
+
+	return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(resolver_unregister_off_nominal)
+{
+	struct ast_dns_resolver non_existent = {
+		.name = "I do not exist",
+		.priority = 20141004,
+		.resolve = stub_resolve,
+		.cancel = stub_cancel,
+	};
+
+	switch (cmd) {
+	case TEST_INIT:
+		info->name = "resolver_unregister_off_nominal";
+		info->category = "/main/dns/";
+		info->summary = "Test off-nominal DNS resolver unregister";
+		info->description =
+			"The test attempts the following:\n"
+			"\t* Unregister a resolver that is not registered.\n"
+			"\t* Unregister a NULL pointer.\n"
+			"Because unregistering a resolver does not return an indicator of success, the best\n"
+			"this test can do is verify that nothing blows up when this is attempted.\n";
+		return AST_TEST_NOT_RUN;
+	case TEST_EXECUTE:
+		break;
+	}
+
+	ast_dns_resolver_unregister(&non_existent);
+	ast_dns_resolver_unregister(NULL);
+
+	return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(resolver_data)
+{
+	struct ast_dns_query some_query;
+
+	struct digits {
+		int fingers;
+		int toes;
+	};
+	
+	struct digits average = {
+		.fingers = 10,
+		.toes = 10,
+	};
+
+	struct digits polydactyl = {
+		.fingers = 12,
+		.toes = 10,
+	};
+
+	struct digits *data_ptr;
+
+	switch (cmd) {
+	case TEST_INIT:
+		info->name = "resolver_data";
+		info->category = "/main/dns/";
+		info->summary = "Test getting and setting data on a DNS resolver";
+		/* XXX Better description required */
+		info->description = "Sup dawg";
+		return AST_TEST_NOT_RUN;
+	case TEST_EXECUTE:
+		break;
+	}
+
+	memset(&some_query, 0, sizeof(some_query));
+
+	/* Ensure that NULL is retrieved if we haven't set anything on the query */
+	data_ptr = ast_dns_resolver_get_data(&some_query);
+	if (data_ptr) {
+		ast_test_status_update(test, "Retrieved non-NULL resolver data from query unexpectedly\n");
+		return AST_TEST_FAIL;
+	}
+
+	ast_dns_resolver_set_data(&some_query, &average);
+
+	/* Ensure that data can be set and retrieved */
+	data_ptr = ast_dns_resolver_get_data(&some_query);
+	if (!data_ptr) {
+		ast_test_status_update(test, "Unable to retrieve resolver data from DNS query\n");
+		return AST_TEST_FAIL;
+	}
+
+	if (data_ptr->fingers != average.fingers || data_ptr->toes != average.toes) {
+		ast_test_status_update(test, "Unexpected resolver data retrieved from DNS query\n");
+		return AST_TEST_FAIL;
+	}
+
+	/* Ensure that we can set new resolver data even if there already is resolver data on the query */
+	ast_dns_resolver_set_data(&some_query, &polydactyl);
+
+	data_ptr = ast_dns_resolver_get_data(&some_query);
+	if (!data_ptr) {
+		ast_test_status_update(test, "Unable to retrieve resolver data from DNS query\n");
+		return AST_TEST_FAIL;
+	}
+
+	if (data_ptr->fingers != polydactyl.fingers || data_ptr->toes != polydactyl.toes) {
+		ast_test_status_update(test, "Unexpected resolver data retrieved from DNS query\n");
+		return AST_TEST_FAIL;
+	}
+
+	/* Ensure that ast_dns_resolver_completed() removes resolver data from the query */
+	ast_dns_resolver_completed(&some_query);
+
+	data_ptr = ast_dns_resolver_get_data(&some_query);
+	if (data_ptr) {
+		ast_test_status_update(test, "Query still has resolver data after query completed\n");
+		return AST_TEST_FAIL;
+	}
+
+	return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(resolver_add_record)
+{
+	struct ast_dns_query some_query;
+	/* XXX I know this isn't what an A record looks like, but just trying to get something compiling right now */
+	static const char *CLEAN_ADDR = "127.0.0.1";
+
+	switch (cmd) {
+	case TEST_INIT:
+		/* XXX Add details */
+		return AST_TEST_NOT_RUN;
+	case TEST_EXECUTE:
+		break;
+	}
+
+	memset(&some_query, 0, sizeof(some_query));
+
+	/* Nominal Record */
+	if (ast_dns_resolver_add_record(&some_query, ns_t_a, ns_c_in, 12345, CLEAN_ADDR, strlen(CLEAN_ADDR))) {
+		ast_test_status_update(test, "Unable to add nominal record to query\n");
+		return AST_TEST_FAIL;
+	}
+
+	/* Invalid RR types */
+	if (!ast_dns_resolver_add_record(&some_query, -1, ns_c_in, 12345, CLEAN_ADDR, strlen(CLEAN_ADDR))) {
+		ast_test_status_update(test, "Successfully added DNS record with negative RR type\n");
+		return AST_TEST_FAIL;
+	}
+	
+	if (!ast_dns_resolver_add_record(&some_query, ns_t_max + 1, ns_c_in, 12345, CLEAN_ADDR, strlen(CLEAN_ADDR))) {
+		ast_test_status_update(test, "Successfully added DNS record with too large RR type\n");
+		return AST_TEST_FAIL;
+	}
+
+	/* Invalid RR classes */
+	if (!ast_dns_resolver_add_record(&some_query, ns_t_a, -1, 12345, CLEAN_ADDR, strlen(CLEAN_ADDR))) {
+		ast_test_status_update(test, "Successfully added DNS record with negative RR class\n");
+		return AST_TEST_FAIL;
+	}
+
+	if (!ast_dns_resolver_add_record(&some_query, ns_t_a, ns_c_max + 1, 12345, CLEAN_ADDR, strlen(CLEAN_ADDR))) {
+		ast_test_status_update(test, "Successfully added DNS record with too large RR class\n");
+		return AST_TEST_FAIL;
+	}
+
+	/* Invalid TTL */
+	if (!ast_dns_resolver_add_record(&some_query, ns_t_a, ns_c_in, -1, CLEAN_ADDR, strlen(CLEAN_ADDR))) {
+		ast_test_status_update(test, "Successfully added DNS record with negative TTL\n");
+		return AST_TEST_FAIL;
+	}
+
+	/* No data */
+	if (!ast_dns_resolver_add_record(&some_query, ns_t_a, ns_c_in, 12345, NULL, 0)) {
+		ast_test_status_update(test, "Successfully added a DNS record with no data\n");
+		return AST_TEST_FAIL;
+	}
+
+	/* Lie about the length */
+	/* XXX I don't know how valid these tests actually are. */
+	if (!ast_dns_resolver_add_record(&some_query, ns_t_a, ns_c_in, 12345, CLEAN_ADDR, 0)) {
+		ast_test_status_update(test, "Successfully added a DNS record with length zero\n");
+		return AST_TEST_FAIL;
+	}
+	
+	if (!ast_dns_resolver_add_record(&some_query, ns_t_a, ns_c_in, 12345, CLEAN_ADDR, strlen(CLEAN_ADDR) * 3)) {
+		ast_test_status_update(test, "Successfully added a DNS record with overly-large length\n");
+		return AST_TEST_FAIL;
+	}
+
+	return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(resolver_set_result)
+{
+	struct ast_dns_query some_query;
+
+	switch (cmd) {
+	case TEST_INIT:
+		/* XXX Add details */
+		return AST_TEST_NOT_RUN;
+	case TEST_EXECUTE:
+		break;
+	}
+
+	memset(&some_query, 0, sizeof(some_query));
+
+	/* XXX Not sure what to set for canonical on results */
+
+	return AST_TEST_PASS;
+}
+
+static int unload_module(void)
+{
+	AST_TEST_UNREGISTER(resolver_register_unregister);
+	AST_TEST_UNREGISTER(resolver_register_off_nominal);
+	AST_TEST_UNREGISTER(resolver_unregister_off_nominal);
+	AST_TEST_UNREGISTER(resolver_data);
+	AST_TEST_UNREGISTER(resolver_add_record);
+	AST_TEST_UNREGISTER(resolver_set_result);
+
+	return 0;
+}
+
+static int load_module(void)
+{
+	AST_TEST_REGISTER(resolver_register_unregister);
+	AST_TEST_REGISTER(resolver_register_off_nominal);
+	AST_TEST_REGISTER(resolver_unregister_off_nominal);
+	AST_TEST_REGISTER(resolver_data);
+	AST_TEST_REGISTER(resolver_add_record);
+	AST_TEST_REGISTER(resolver_set_result);
+
+	return AST_MODULE_LOAD_SUCCESS;
+}
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "DNS API Tests");

Propchange: team/group/dns/tests/test_dns.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/group/dns/tests/test_dns.c
------------------------------------------------------------------------------
    svn:keywords = 'Author Date Id Revision'

Propchange: team/group/dns/tests/test_dns.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain




More information about the asterisk-commits mailing list