[asterisk-commits] mmichelson: branch mmichelson/rls-subscribe r417727 - /team/mmichelson/rls-su...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Jul 1 14:19:17 CDT 2014


Author: mmichelson
Date: Tue Jul  1 14:19:14 2014
New Revision: 417727

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=417727
Log:
Add some more unit tests.

These tests mostly test off-nominal paths, and they even
uncovered some bugs!


Modified:
    team/mmichelson/rls-subscribe/res/res_pjsip_pubsub.c

Modified: team/mmichelson/rls-subscribe/res/res_pjsip_pubsub.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/rls-subscribe/res/res_pjsip_pubsub.c?view=diff&rev=417727&r1=417726&r2=417727
==============================================================================
--- team/mmichelson/rls-subscribe/res/res_pjsip_pubsub.c (original)
+++ team/mmichelson/rls-subscribe/res/res_pjsip_pubsub.c Tue Jul  1 14:19:14 2014
@@ -640,12 +640,26 @@
 	char resource[0];
 };
 
-static struct resource_list *retrieve_resource_list(const char *resource)
-{
-	return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "resource_list", resource);
-}
-
-static struct tree_node *tree_node_alloc(const char *resource)
+static struct resource_list *retrieve_resource_list(const char *resource, const char *event)
+{
+	struct resource_list *list;
+	
+	list = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "resource_list", resource);
+	if (!list) {
+		return NULL;
+	}
+
+	if (strcmp(list->event, event)) {
+		ast_log(LOG_WARNING, "Found resource list %s, but its event type (%s) does not match SUBSCRIBE's (%s)\n",
+				resource, list->event, event);
+		ao2_cleanup(list);
+		return NULL;
+	}
+
+	return list;
+}
+
+static struct tree_node *tree_node_alloc(const char *resource, struct resources *visited)
 {
 	struct tree_node *node;
 
@@ -656,6 +670,10 @@
 
 	strcpy(node->resource, resource);
 	AST_VECTOR_INIT(&node->children, 4);
+
+	if (visited) {
+		AST_VECTOR_APPEND(visited, resource);
+	}
 	return node;
 }
 
@@ -700,21 +718,22 @@
 			continue;
 		}
 
-		child_list = retrieve_resource_list(resource);
+		child_list = retrieve_resource_list(resource, list->event);
 		if (!child_list) {
 			int resp = handler->notifier->new_subscribe(endpoint, resource);
 			if (PJSIP_IS_STATUS_IN_CLASS(resp, 200)) {
-				current = tree_node_alloc(resource);
+				current = tree_node_alloc(resource, visited);
 				AST_VECTOR_APPEND(&parent->children, current);
 			}
 		} else {
-			current = tree_node_alloc(resource);
+			current = tree_node_alloc(resource, visited);
 			recurse_list(endpoint, handler, child_list, current, visited);
 			if (AST_VECTOR_SIZE(&current->children) > 0) {
 				AST_VECTOR_APPEND(&parent->children, current);
 			} else {
 				tree_node_destroy(current);
 			}
+			ao2_cleanup(child_list);
 		}
 	}
 }
@@ -736,18 +755,17 @@
 	struct resource_list *list;
 	struct resources visited;
 
-	list = retrieve_resource_list(resource);
-
-	tree->root = tree_node_alloc(resource);
-
-	/* Simple shortcut in case the requested resource is not a list */
+	list = retrieve_resource_list(resource, handler->event_name);
 	if (!list) {
+		tree->root = tree_node_alloc(resource, NULL);
 		return handler->notifier->new_subscribe(endpoint, resource);
 	}
 
 	AST_VECTOR_INIT(&visited, AST_VECTOR_SIZE(&list->items));
+	tree->root = tree_node_alloc(resource, &visited);
 	recurse_list(endpoint, handler, list, tree->root, &visited);
 	AST_VECTOR_FREE(&visited);
+	ao2_cleanup(list);
 
 	if (AST_VECTOR_SIZE(&tree->root->children) > 0) {
 		return 200;
@@ -2597,15 +2615,18 @@
 };
 
 struct ast_sip_subscription_handler test_handler = {
+	.event_name = "test",
 	.notifier = &test_notifier,
 };
 
-static int fill_in_resources(struct resource_list *list, const char **resources, size_t num_resources)
+static int populate_list(struct resource_list *list, const char *event, const char **resources, size_t num_resources)
 {
 	int i;
 
+	ast_copy_string(list->event, event, sizeof(list->event));
+
 	for (i = 0; i < num_resources; ++i) {
-		if (AST_VECTOR_APPEND(&list->items, resources[i])) {
+		if (AST_VECTOR_APPEND(&list->items, ast_strdup(resources[i]))) {
 			return -1;
 		}
 	}
@@ -2623,7 +2644,7 @@
 }
 
 static struct resource_list *create_resource_list(struct ast_test *test,
-		const char *list_name, const char **resources, size_t size)
+		const char *list_name, const char *event,const char **resources, size_t size)
 {
 	struct resource_list *list;
 
@@ -2634,12 +2655,12 @@
 	}
 
 	if (ast_sorcery_create(ast_sip_get_sorcery(), list)) {
-		ast_test_status_update(test, "Could not store the resource list and stuff\n");
+		ast_test_status_update(test, "Could not store the resource list in sorcery\n");
 		ao2_cleanup(list);
 		return NULL;
 	}
 
-	if (fill_in_resources(list, resources, size)) {
+	if (populate_list(list, event, resources, size)) {
 		ast_test_status_update(test, "Could not add resources to the resource list\n");
 		cleanup_resource_list(list);
 		return NULL;
@@ -2692,7 +2713,7 @@
 		break;
 	}
 
-	list = create_resource_list(test, "foo", resources, ARRAY_LEN(resources));
+	list = create_resource_list(test, "foo", "test", resources, ARRAY_LEN(resources));
 	if (!list) {
 		return AST_TEST_FAIL;
 	}
@@ -2751,12 +2772,12 @@
 		break;
 	}
 	
-	list_1 = create_resource_list(test, "foo", resources_1, ARRAY_LEN(resources_1));
+	list_1 = create_resource_list(test, "foo", "test", resources_1, ARRAY_LEN(resources_1));
 	if (!list_1) {
 		return AST_TEST_FAIL;
 	}
 
-	list_2 = create_resource_list(test, "dwarves", resources_2, ARRAY_LEN(resources_2));
+	list_2 = create_resource_list(test, "dwarves", "test", resources_2, ARRAY_LEN(resources_2));
 	if (!list_2) {
 		return AST_TEST_FAIL;
 	}
@@ -2810,7 +2831,7 @@
 		break;
 	}
 
-	list = create_resource_list(test, "foo", resources, ARRAY_LEN(resources));
+	list = create_resource_list(test, "foo", "test", resources, ARRAY_LEN(resources));
 	if (!list) {
 		return AST_TEST_FAIL;
 	}
@@ -2867,11 +2888,11 @@
 		break;
 	}
 
-	list_1 = create_resource_list(test, "foo", resources_1, ARRAY_LEN(resources_1));
+	list_1 = create_resource_list(test, "foo", "test", resources_1, ARRAY_LEN(resources_1));
 	if (!list_1) {
 		return AST_TEST_FAIL;
 	}
-	list_2 = create_resource_list(test, "gross", resources_2, ARRAY_LEN(resources_2));
+	list_2 = create_resource_list(test, "gross", "test", resources_2, ARRAY_LEN(resources_2));
 	if (!list_2) {
 		return AST_TEST_FAIL;
 	}
@@ -2894,6 +2915,173 @@
 
 	return AST_TEST_PASS;
 
+}
+
+AST_TEST_DEFINE(duplicate_resource)
+{
+	RAII_VAR(struct resource_list *, list_1, NULL, cleanup_resource_list);
+	RAII_VAR(struct resource_list *, list_2, NULL, cleanup_resource_list);
+	RAII_VAR(struct resource_tree *, tree, NULL, resource_tree_destroy);
+	const char *resources_1[] = {
+		"huey",
+		"ducks",
+		"dewey",
+		"louie",
+	};
+	const char *resources_2[] = {
+		"donald",
+		"daisy",
+		"scrooge",
+		"dewey",
+		"louie",
+		"huey",
+	};
+	int resp;
+	struct tree_node *node;
+
+	switch (cmd) {
+	case TEST_INIT:
+		info->name = "duplicate_resource";
+		info->category = "/res/res_pjsip_pubsub/";
+		info->summary = "Ensure duplicated resources do not end up in the tree";
+		info->description =
+			"Create a resource list with a single duplicated resource. Ensure the duplicated resource does not end up in the tree.";
+		return AST_TEST_NOT_RUN;
+	case TEST_EXECUTE:
+		break;
+	}
+
+	list_1 = create_resource_list(test, "foo", "test", resources_1, ARRAY_LEN(resources_1));
+	if (!list_1) {
+		return AST_TEST_FAIL;
+	}
+
+	list_2 = create_resource_list(test, "ducks", "test", resources_2, ARRAY_LEN(resources_2));
+	if (!list_2) {
+		return AST_TEST_FAIL;
+	}
+
+	tree = ast_calloc(1, sizeof(*tree));
+	resp = build_resource_tree(NULL, &test_handler, "foo", tree);
+	if (resp != 200) {
+		ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);
+		return AST_TEST_FAIL;
+	}
+
+	if (!tree->root) {
+		ast_test_status_update(test, "Resource tree has no root\n");
+		return AST_TEST_FAIL;
+	}
+
+	node = tree->root;
+	/* This node should have "huey" and "ducks". "dewey" and "louie" should not
+	 * be present since they were found in the "ducks" list.
+	 */
+	if (check_node(test, node, resources_1, ARRAY_LEN(resources_1) - 2)) {
+		return AST_TEST_FAIL;
+	}
+
+	/* This node should have "donald", "daisy", "scrooge", "dewey", and "louie".
+	 * "huey" is not here since that was already encountered in the parent list */
+	node = AST_VECTOR_GET(&node->children, 1);
+	if (check_node(test, node, resources_2, ARRAY_LEN(resources_2) - 1)) {
+		return AST_TEST_FAIL;
+	}
+
+	return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(loop)
+{
+	RAII_VAR(struct resource_list *, list_1, NULL, cleanup_resource_list);
+	RAII_VAR(struct resource_list *, list_2, NULL, cleanup_resource_list);
+	RAII_VAR(struct resource_tree *, tree, NULL, resource_tree_destroy);
+	const char *resources_1[] = {
+		"derp",
+	};
+	const char *resources_2[] = {
+		"herp",
+	};
+	int resp;
+
+	switch (cmd) {
+	case TEST_INIT:
+		info->name = "loop";
+		info->category = "/res/res_pjsip_pubsub/";
+		info->summary = "Test that loops are properly detected.";
+		info->description =
+			"Create two resource lists that refer to each other. Ensure that attempting to build a tree\n"
+			"results in an empty tree.";
+		return AST_TEST_NOT_RUN;
+	case TEST_EXECUTE:
+		break;
+	}
+
+	list_1 = create_resource_list(test, "herp", "test", resources_1, ARRAY_LEN(resources_1));
+	if (!list_1) {
+		return AST_TEST_FAIL;
+	}
+	list_2 = create_resource_list(test, "derp", "test", resources_2, ARRAY_LEN(resources_2));
+	if (!list_2) {
+		return AST_TEST_FAIL;
+	}
+
+	tree = ast_calloc(1, sizeof(*tree));
+	resp = build_resource_tree(NULL, &test_handler, "herp", tree);
+	if (resp == 200) {
+		ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);
+		return AST_TEST_FAIL;
+	}
+
+	return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(bad_event)
+{
+	RAII_VAR(struct resource_list *, list, NULL, cleanup_resource_list);
+	RAII_VAR(struct resource_tree *, tree, NULL, resource_tree_destroy);
+	const char *resources[] = {
+		"huey",
+		"dewey",
+		"louie",
+	};
+	int resp;
+
+	switch (cmd) {
+	case TEST_INIT:
+		info->name = "bad_event";
+		info->category = "/res/res_pjsip_pubsub/";
+		info->summary = "Ensure that list with wrong event specified is not retrieved";
+		info->description =
+			"Create a simple resource list for event 'tsetse'. Ensure that trying to retrieve the list for event 'test' fails.";
+		return AST_TEST_NOT_RUN;
+	case TEST_EXECUTE:
+		break;
+	}
+
+	list = create_resource_list(test, "foo", "tsetse", resources, ARRAY_LEN(resources));
+	if (!list) {
+		return AST_TEST_FAIL;
+	}
+
+	tree = ast_calloc(1, sizeof(*tree));
+	resp = build_resource_tree(NULL, &test_handler, "foo", tree);
+	if (resp != 200) {
+		ast_test_status_update(test, "Unexpected response %d when building resource tree\n", resp);
+		return AST_TEST_FAIL;
+	}
+
+	if (!tree->root) {
+		ast_test_status_update(test, "Resource tree has no root\n");
+		return AST_TEST_FAIL;
+	}
+
+	if (strcmp(tree->root->resource, "foo")) {
+		ast_test_status_update(test, "Unexpected resource %s found in tree\n", tree->root->resource);
+		return AST_TEST_FAIL;
+	}
+
+	return AST_TEST_PASS;
 }
 
 #endif
@@ -2976,6 +3164,9 @@
 	AST_TEST_REGISTER(complex_resource_tree);
 	AST_TEST_REGISTER(bad_resource);
 	AST_TEST_REGISTER(bad_branch);
+	AST_TEST_REGISTER(duplicate_resource);
+	AST_TEST_REGISTER(loop);
+	AST_TEST_REGISTER(bad_event);
 
 	return AST_MODULE_LOAD_SUCCESS;
 }
@@ -2994,6 +3185,9 @@
 	AST_TEST_UNREGISTER(complex_resource_tree);
 	AST_TEST_UNREGISTER(bad_resource);
 	AST_TEST_UNREGISTER(bad_branch);
+	AST_TEST_UNREGISTER(duplicate_resource);
+	AST_TEST_UNREGISTER(loop);
+	AST_TEST_UNREGISTER(bad_event);
 
 	return 0;
 }




More information about the asterisk-commits mailing list