You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by kg...@apache.org on 2017/08/09 17:52:21 UTC
[5/8] qpid-dispatch git commit: DISPATCH-731: add parse tree unit
tests
DISPATCH-731: add parse tree unit tests
Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/f6dab30f
Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/f6dab30f
Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/f6dab30f
Branch: refs/heads/master
Commit: f6dab30fbeba609b227c1ed8eab5911428f10257
Parents: 778a9dd
Author: Kenneth Giusti <kg...@apache.org>
Authored: Tue Aug 1 15:07:05 2017 -0400
Committer: Kenneth Giusti <kg...@apache.org>
Committed: Wed Aug 2 10:28:13 2017 -0400
----------------------------------------------------------------------
src/parse_tree.c | 67 +++++-
src/parse_tree.h | 7 +-
tests/CMakeLists.txt | 1 +
tests/parse_tree_tests.c | 470 ++++++++++++++++++++++++++++++++++++++++++
tests/run_unit_tests.c | 3 +
5 files changed, 542 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/f6dab30f/src/parse_tree.c
----------------------------------------------------------------------
diff --git a/src/parse_tree.c b/src/parse_tree.c
index bd93ed9..3fe877a 100644
--- a/src/parse_tree.c
+++ b/src/parse_tree.c
@@ -181,6 +181,7 @@ struct qd_parse_node {
struct qd_parse_node *star_child;
struct qd_parse_node *hash_child;
void *payload; // data returned on match against this node
+ qd_log_source_t *log_source;
};
ALLOC_DECLARE(qd_parse_node_t);
ALLOC_DEFINE(qd_parse_node_t);
@@ -195,6 +196,7 @@ static qd_parse_node_t *new_parse_node(const token_t *t)
n->payload = NULL;
n->pattern = NULL;
n->star_child = n->hash_child = NULL;
+ n->log_source = qd_log_source("DEFAULT");
if (t) {
const size_t tlen = TOKEN_LEN(*t);
@@ -399,6 +401,12 @@ static bool parse_node_find(qd_parse_node_t *, token_iterator_t *,
static bool parse_node_find_children(qd_parse_node_t *node, token_iterator_t *value,
qd_parse_tree_visit_t *callback, void *handle)
{
+ qd_log(node->log_source, QD_LOG_DEBUG,
+ "find_children token=%s pattern=%s input=%s",
+ node->token ? node->token : "NULL",
+ node->pattern ? node->pattern : "NULL",
+ value->token);
+
if (!token_iterator_done(value)) {
// check exact match first (precedence)
@@ -437,9 +445,16 @@ static bool parse_node_find_children(qd_parse_node_t *node, token_iterator_t *va
static bool parse_node_find_token(qd_parse_node_t *node, token_iterator_t *value,
qd_parse_tree_visit_t *callback, void *handle)
{
+ qd_log(node->log_source, QD_LOG_DEBUG,
+ "find_token token=%s pattern=%s input=%s",
+ node->token ? node->token : "NULL",
+ node->pattern ? node->pattern : "NULL",
+ value->token);
+
if (token_iterator_done(value) && node->pattern) {
// exact match current node
- return callback(handle, node->pattern, node->payload);
+ if (!callback(handle, node->pattern, node->payload))
+ return false;
}
// no payload or more tokens. Continue to lower sub-trees. Even if no more
@@ -453,6 +468,12 @@ static bool parse_node_find_token(qd_parse_node_t *node, token_iterator_t *value
static bool parse_node_find_star(qd_parse_node_t *node, token_iterator_t *value,
qd_parse_tree_visit_t *callback, void *handle)
{
+ qd_log(node->log_source, QD_LOG_DEBUG,
+ "find_star token=%s pattern=%s input=%s",
+ node->token ? node->token : "NULL",
+ node->pattern ? node->pattern : "NULL",
+ value->token);
+
// must match exactly one token:
if (token_iterator_done(value))
return true; // no match here, but continue searching
@@ -476,6 +497,12 @@ static bool parse_node_find_star(qd_parse_node_t *node, token_iterator_t *value,
static bool parse_node_find_hash(qd_parse_node_t *node, token_iterator_t *value,
qd_parse_tree_visit_t *callback, void *handle)
{
+ qd_log(node->log_source, QD_LOG_DEBUG,
+ "find_hash token=%s pattern=%s input=%s",
+ node->token ? node->token : "NULL",
+ node->pattern ? node->pattern : "NULL",
+ value->token);
+
// consume each token and look for a match on the
// remaining key.
while (!token_iterator_done(value)) {
@@ -496,6 +523,12 @@ static bool parse_node_find_hash(qd_parse_node_t *node, token_iterator_t *value,
static bool parse_node_find(qd_parse_node_t *node, token_iterator_t *value,
qd_parse_tree_visit_t *callback, void *handle)
{
+ qd_log(node->log_source, QD_LOG_DEBUG,
+ "node_find token=%s pattern=%s input=%s",
+ node->token ? node->token : "NULL",
+ node->pattern ? node->pattern : "NULL",
+ value->token);
+
if (node->is_star)
return parse_node_find_star(node, value, callback, handle);
else if (node->is_hash)
@@ -578,7 +611,7 @@ void *qd_parse_tree_add_pattern(qd_parse_node_t *node,
char *str = (char *)qd_iterator_copy(dup);
normalize_pattern(str);
- qd_log(qd_log_source("DEFAULT"), QD_LOG_DEBUG,
+ qd_log(node->log_source, QD_LOG_DEBUG,
"Parse tree add address pattern '%s'", str);
token_iterator_init(&key, str);
@@ -601,7 +634,7 @@ bool qd_parse_tree_get_pattern(qd_parse_node_t *node,
char *str = (char *)qd_iterator_copy(dup);
normalize_pattern((char *)str);
- qd_log(qd_log_source("DEFAULT"), QD_LOG_DEBUG,
+ qd_log(node->log_source, QD_LOG_DEBUG,
"Parse tree get address pattern '%s'", str);
token_iterator_init(&key, str);
@@ -624,7 +657,7 @@ void *qd_parse_tree_remove_pattern(qd_parse_node_t *node,
char *str = (char *)qd_iterator_copy(dup);
normalize_pattern(str);
- qd_log(qd_log_source("DEFAULT"), QD_LOG_DEBUG,
+ qd_log(node->log_source, QD_LOG_DEBUG,
"Parse tree remove address pattern '%s'", str);
token_iterator_init(&key, str);
@@ -634,6 +667,32 @@ void *qd_parse_tree_remove_pattern(qd_parse_node_t *node,
}
+bool qd_parse_tree_walk(qd_parse_node_t *node, qd_parse_tree_visit_t *callback, void *handle)
+{
+ if (node->pattern) { // terminal node for pattern
+ if (!callback(handle, node->pattern, node->payload))
+ return false;
+ }
+
+ qd_parse_node_t *child = DEQ_HEAD(node->children);
+ while (child) {
+ if (!qd_parse_tree_walk(child, callback, handle))
+ return false;
+ child = DEQ_NEXT(child);
+ }
+
+ if (node->star_child)
+ if (!qd_parse_tree_walk(node->star_child, callback, handle))
+ return false;
+
+ if (node->hash_child)
+ if (!qd_parse_tree_walk(node->hash_child, callback, handle))
+ return false;
+
+ return true;
+}
+
+
#if 0
#include <stdio.h>
void qd_parse_tree_dump(qd_parse_node_t *node, int depth)
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/f6dab30f/src/parse_tree.h
----------------------------------------------------------------------
diff --git a/src/parse_tree.h b/src/parse_tree.h
index d616e48..2e53269 100644
--- a/src/parse_tree.h
+++ b/src/parse_tree.h
@@ -71,15 +71,18 @@ bool qd_parse_tree_retrieve_match(qd_parse_node_t *node,
void **payload);
// parse tree traversal
-// visit each matching pattern that matches value in the order based on the
-// above precedence rules
// return false to stop tree transversal
typedef bool qd_parse_tree_visit_t(void *handle,
const char *pattern,
void *payload);
+// visit each matching pattern that matches value in the order based on the
+// above precedence rules
void qd_parse_tree_search(qd_parse_node_t *node, const qd_iterator_t *value,
qd_parse_tree_visit_t *callback, void *handle);
+// visit each terminal node on the tree, returns last value returned by callback
+bool qd_parse_tree_walk(qd_parse_node_t *node, qd_parse_tree_visit_t *callback, void *handle);
+
#endif /* parse_tree.h */
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/f6dab30f/tests/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index bc62232..8a5cbd1 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -32,6 +32,7 @@ set(unit_test_SOURCES
tool_test.c
failoverlist_test.c
timer_test.c
+ parse_tree_tests
)
if (USE_MEMORY_POOL)
list(APPEND unit_test_SOURCES alloc_test.c)
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/f6dab30f/tests/parse_tree_tests.c
----------------------------------------------------------------------
diff --git a/tests/parse_tree_tests.c b/tests/parse_tree_tests.c
new file mode 100644
index 0000000..347f6df
--- /dev/null
+++ b/tests/parse_tree_tests.c
@@ -0,0 +1,470 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "test_case.h"
+#include <stdio.h>
+#include <string.h>
+#include "parse_tree.h"
+
+
+static char *test_add_remove(void *context)
+{
+ qd_iterator_t *piter = qd_iterator_string("I.am.Sam", ITER_VIEW_ALL);
+ qd_iterator_t *piter2 = qd_iterator_string("Sam.I.Am", ITER_VIEW_ALL);
+ qd_parse_node_t *node = qd_parse_tree_new();
+ void *payload;
+
+ if (qd_parse_tree_remove_pattern(node, piter))
+ return "Failed to remove a non-existing pattern";
+
+ if (qd_parse_tree_get_pattern(node, piter, &payload))
+ return "Got a non-existing pattern";
+
+ if (qd_parse_tree_add_pattern(node, piter, "Hi Sam"))
+ return "Add returned existing value";
+
+ if (qd_parse_tree_add_pattern(node, piter2, "Bye Sam"))
+ return "Add returned existing value";
+
+ if (!qd_parse_tree_get_pattern(node, piter, &payload))
+ return "Could not get pattern";
+
+ if (!payload || strcmp("Hi Sam", (char *)payload))
+ return "Got bad pattern";
+
+ if (!qd_parse_tree_get_pattern(node, piter2, &payload))
+ return "Could not get pattern";
+
+ if (!payload || strcmp("Bye Sam", (char *)payload))
+ return "Got bad pattern";
+
+ if (!qd_parse_tree_remove_pattern(node, piter))
+ return "Failed to remove an existing pattern";
+
+ if (!qd_parse_tree_remove_pattern(node, piter2))
+ return "Failed to remove an existing pattern";
+
+ qd_parse_tree_free(node);
+ qd_iterator_free(piter);
+ qd_iterator_free(piter2);
+ return NULL;
+}
+
+// for pattern match callback
+typedef struct {
+ int count;
+ const char **patterns;
+ void **payloads;
+} visit_handle_t;
+
+
+// callback to visit all matching patterns in tree
+static bool visit_all(void *handle,
+ const char *pattern,
+ void *payload)
+{
+ visit_handle_t *h = (visit_handle_t *)handle;
+ h->patterns[h->count] = pattern;
+ h->payloads[h->count] = payload;
+ h->count++;
+ return true;
+}
+
+
+// callback to return first (best) match
+static bool find_best(void *handle,
+ const char *pattern,
+ void *payload)
+{
+ visit_handle_t *h = (visit_handle_t *)handle;
+ h->patterns[0] = pattern;
+ h->payloads[0] = payload;
+ h->count = 1;
+ return false;
+}
+
+
+// check if input patterns are correctly "normalized" (see parse_tree.c)
+static char *check_normalize(const char *input,
+ const char *expected)
+{
+ const char *patterns[1];
+ void *payloads[1];
+ visit_handle_t vh = {0, patterns, payloads};
+ qd_parse_node_t *node = qd_parse_tree_new();
+ qd_iterator_t *iter = qd_iterator_string(input, ITER_VIEW_ALL);
+ void *payload;
+
+ if (qd_parse_tree_add_pattern(node, iter, (void *)input) != NULL)
+ return "Unexpected duplicate pattern";
+ if (!qd_parse_tree_get_pattern(node, iter, &payload))
+ return "Could not find added pattern";
+ if (!payload || strcmp((const char *)payload, input))
+ return "Failed to find pattern";
+
+ qd_parse_tree_walk(node, visit_all, &vh);
+ if (vh.count != 1)
+ return "Did not find expected pattern";
+ if (strcmp(vh.payloads[0], input))
+ return "Unexpected payload!";
+ if (strcmp(vh.patterns[0], expected)) {
+ fprintf(stderr, "%s %s\n", vh.patterns[0], expected);
+ return "Incorrect normalization";
+ }
+
+ payload = qd_parse_tree_remove_pattern(node, iter);
+ if (!payload || strcmp((const char *)payload, input))
+ return "Failed to remove pattern";
+
+ qd_parse_tree_free(node);
+ qd_iterator_free(iter);
+ return NULL;
+}
+
+
+static char *test_normalization(void *context)
+{
+ char *rc = NULL;
+ char *patterns[][2] = {
+ // normalized raw
+ {"", ""},
+ {"a.b.c", "a.b.c"},
+ {"a.*.c", "a.*.c"},
+ {"#", "#"},
+ {"#", "#.#.#.#"},
+ {"*.*.*.#", "#.*.#.*.#.#.*"},
+ {"a.*.*.*.#", "a.*.#.*.#.*.#"},
+ {"a.*.*.*.#", "a.*.#.*.#.*"},
+ {"*.*.*.#", "*.#.#.*.*.#"},
+ {NULL, NULL}
+ };
+
+ for (int i = 0; !rc && patterns[i][0]; i++)
+ rc = check_normalize(patterns[i][1], patterns[i][0]);
+
+ return rc;
+}
+
+
+typedef struct {
+ const char *address;
+ bool match;
+} match_test_t;
+
+static char *match_test(const char *pattern,
+ const match_test_t *tests)
+{
+ char *rc = NULL;
+ qd_iterator_t *piter = qd_iterator_string(pattern, ITER_VIEW_ALL);
+ qd_parse_node_t *node = qd_parse_tree_new();
+ void *payload = (void *)"found";
+
+ if (qd_parse_tree_add_pattern(node, piter, payload))
+ return "Unexpected payload when adding pattern";
+
+ for (int i = 0; tests[i].address && !rc; i++) {
+ qd_iterator_t *iter = qd_iterator_string(tests[i].address, ITER_VIEW_ALL);
+ bool match = (int)qd_parse_tree_retrieve_match(node, iter, &payload);
+ if (match != tests[i].match) {
+ printf("match address '%s' to pattern '%s': expected %d got %d\n",
+ tests[i].address, pattern, (int)tests[i].match, (int)match);
+ return "Match test failed";
+ }
+ qd_iterator_free(iter);
+ }
+
+ qd_parse_tree_free(node);
+ qd_iterator_free(piter);
+ return NULL;
+}
+
+
+// check various pattern matches
+static char *test_matches(void *context)
+{
+ match_test_t test1[] = {
+ { "ab.cd.e", true},
+ { "abx.cd.e", false},
+ { "ab.cd", false},
+ { "ab.cd.ef.", false},
+ { "ab.cd.E", false},
+ { "x.ab.cd.e", false},
+ {NULL, false}
+ };
+
+ char *rc = match_test("ab.cd.e", test1);
+ if (rc) return rc;
+
+ match_test_t test2[] = {
+ {"", true},
+ {NULL, false},
+ };
+ rc = match_test("", test2);
+ if (rc) return rc;
+
+ match_test_t test3[] = {
+ {".", true},
+ {NULL, false},
+ };
+ rc = match_test(".", test3);
+ if (rc) return rc;
+
+ match_test_t test4[] = {
+ {"a.xx.b", true},
+ {"a.b", false},
+ {NULL, false}
+ };
+ rc = match_test("a.*.b", test4);
+ if (rc) return rc;
+
+ match_test_t test5[] = {
+ {"y.x", true},
+ {"x", false},
+ {"x.y", false},
+ {NULL, false}
+ };
+ rc = match_test("*.x", test5);
+ if (rc) return rc;
+
+ match_test_t test6[] = {
+ {"x.x.y", true},
+ {"x.x", false},
+ {"y.x.x", false},
+ {"q.x.y", false},
+ {NULL, false}
+ };
+ rc = match_test("x.x.*", test6);
+ if (rc) return rc;
+
+
+ match_test_t test7[] = {
+ {"a.b", true},
+ {"a.x.b", true},
+ {"a..x.y.zz.b", true},
+ {"a.b.z", false},
+ {"z.a.b", false},
+ {"q.x.b", false},
+ {NULL, false}
+ };
+ rc = match_test("a.#.b", test7);
+ if (rc) return rc;
+
+ match_test_t test8[] = {
+ {"a", true},
+ {"a.b", true},
+ {"a.b.c", true},
+ {"b.a", false},
+ {NULL, false}
+ };
+ rc = match_test("a.#", test8);
+ if (rc) return rc;
+
+ match_test_t test9[] = {
+ {"a", true},
+ {"x.y.a", true},
+ {"a.b", false},
+ {NULL, false}
+ };
+ rc = match_test("#.a", test9);
+ if (rc) return rc;
+
+ match_test_t test10[] = {
+ {"a.b.c", true},
+ {"a.x.b.y.c", true},
+ {"a.x.x.b.y.y.c", true},
+ {"a.b", false},
+ {NULL, false}
+ };
+ rc = match_test("a.#.b.#.c", test10);
+ if (rc) return rc;
+
+ match_test_t test11[] = {
+ {"a.x.y", true},
+ {"a.x.p.qq.y", true},
+ {"a.a.x.y", false},
+ {"aa.x.b.c", false},
+ {"x.p.qq.y", false},
+ {"a.x.p.qq.y.b", false},
+ {NULL, false}
+ };
+ rc = match_test("*.x.#.y", test11);
+ if (rc) return rc;
+
+ match_test_t test12[] = {
+ {"a.b.x", true},
+ {"a.x.x.x.b.x", true},
+ {"a.b.b.b.b.y", true},
+ {"a.b.b.b.b", true},
+ {"a.b", false},
+ {NULL, false}
+ };
+ rc = match_test("a.#.b.*", test12);
+ if (rc) return rc;
+
+ match_test_t test13[] = {
+ {"x/y/z", true},
+ {"x.y.z/a.b.c", true},
+ {"x.y/z", true},
+ {"x.y", false},
+ {"x/y", false},
+ {"x", false},
+ {NULL, false}
+ };
+ rc = match_test("*.*.*.#", test13);
+ if (rc) return rc;
+
+ match_test_t test14[] = {
+ {"x", false},
+ {"x.y", true},
+ {"x.y.z", true},
+ {"x.y.z.y.z.y.z", true},
+ {NULL, false}
+ };
+ rc = match_test("*/#/*", test14);
+
+ return rc;
+}
+
+// For debug (see parse_tree.c)
+// void qd_parse_tree_dump(qd_parse_node_t *node, int depth);
+
+// search a full parse tree for multiple and best matches
+static char *test_multiple_matches(void *context)
+{
+#define PCOUNT 17
+ const char *patterns[PCOUNT] =
+ { "alpha",
+ "bravo",
+ "alpha.bravo",
+ "bravo.charlie",
+ "alpha.bravo.charlie.delta",
+ "bravo.charlie.delta.echo",
+ "alpha.*",
+ "alpha.#",
+ "alpha.*.#",
+ "#.bravo",
+ "*.bravo",
+ "*.#.bravo",
+ "alpha.*.bravo",
+ "alpha.#.bravo",
+ "alpha.*.#.bravo",
+ "*.bravo.*",
+ "#.bravo.#",
+ };
+ const char *_patterns[PCOUNT] = {NULL};
+ void *_payloads[PCOUNT] = {NULL};
+ visit_handle_t vh = {0, _patterns, _payloads};
+ qd_parse_node_t *node = qd_parse_tree_new();
+
+ // build the tree
+ for (int i = 0; i < PCOUNT; i++) {
+ qd_iterator_t *pattern = qd_iterator_string(patterns[i], ITER_VIEW_ALL);
+ if (qd_parse_tree_add_pattern(node, pattern, (void *)patterns[i])) {
+ printf("Failed to add pattern %s to parse tree\n", patterns[i]);
+ return "failed adding pattern to tree";
+ }
+ qd_iterator_free(pattern);
+ }
+
+ {
+ // read all patterns and verify all are present
+ qd_parse_tree_walk(node, visit_all, &vh);
+ if (vh.count != PCOUNT)
+ return "Not all patterns in tree";
+ for (int i = 0; i < PCOUNT; i++) {
+ bool found = false;
+ for (int j = 0; j < PCOUNT; j++) {
+ if (strcmp(patterns[i], vh.patterns[j]) == 0)
+ found = true;
+ }
+ if (!found)
+ return "All patterns not visited";
+ }
+ }
+
+ // matches are listed in order of best->least best match
+ struct {
+ const char *address;
+ const int count;
+ const char *matches[PCOUNT];
+ } tests[] = {
+ {"alpha", 2, {"alpha", "alpha.#"}},
+ {"alpha.zulu", 3, { "alpha.*", "alpha.*.#", "alpha.#"}},
+ {"alpha.bravo", 9, {"alpha.bravo", "alpha.*", "alpha.*.#", "alpha.#.bravo", "alpha.#", "*.bravo", "*.#.bravo", "#.bravo", "#.bravo.#"}},
+ {"bravo", 3, {"bravo", "#.bravo", "#.bravo.#"}},
+ {"xray.bravo", 4, {"*.bravo", "*.#.bravo", "#.bravo", "#.bravo.#"}},
+ {"alpha.bravo.charlie", 4, {"alpha.*.#", "alpha.#", "*.bravo.*", "#.bravo.#"}},
+ {"xray.yankee.zulu.bravo", 3, {"*.#.bravo", "#.bravo", "#.bravo.#"}},
+ {"alpha.bravo.charlie.delta", 4, {"alpha.bravo.charlie.delta", "alpha.*.#","alpha.#", "#.bravo.#"}},
+ {"alpha.charlie.charlie.bravo", 7, {"alpha.*.#.bravo", "alpha.*.#", "alpha.#.bravo", "alpha.#", "*.#.bravo", "#.bravo", "#.bravo.#"}},
+ {"xray.yankeee.zulu.bravo.alpha.bravo.charlie", 2, {"#.bravo.#", "#.bravo.#"}},
+ {"I.match.nothing", 0, {NULL}},
+ {NULL, 0, {NULL}}
+ };
+
+ // verify all matching patterns are hit and in the correct order
+ for (int k = 0; tests[k].address; k++) {
+ qd_iterator_t *find_me = qd_iterator_string(tests[k].address, ITER_VIEW_ALL);
+ vh.count = 0;
+ qd_parse_tree_search(node, find_me, visit_all, (void *)&vh);
+ // printf("Matches for %s:\n", tests[k].address);
+ // for (int i = 0; i < vh.count; i++)
+ // printf("%s, ", vh.patterns[i]);
+ // printf("count = %d\n", vh.count);
+ if (vh.count != tests[k].count)
+ return "Unexpected match count";
+ for (int i = 0; i < tests[k].count; i++) {
+ if (strcmp(vh.patterns[i], tests[k].matches[i]))
+ return "Unexpected pattern match";
+ }
+ qd_iterator_free(find_me);
+ }
+
+ // verify 'best' match is found
+ for (int k = 0; tests[k].address; k++) {
+ qd_iterator_t *find_me = qd_iterator_string(tests[k].address, ITER_VIEW_ALL);
+ vh.count = 0;
+ qd_parse_tree_search(node, find_me, find_best, (void *)&vh);
+ // printf("best match for %s: %s\n", tests[k].address, vh.patterns[0]);
+ if (tests[k].count == 0) {
+ if (vh.count != 0) {
+ return "Did not expect to find a best match!";
+ }
+ } else if (vh.count == 0 || strcmp(vh.patterns[0], tests[k].matches[0]))
+ return "Unexpected best pattern match";
+ qd_iterator_free(find_me);
+ }
+
+ qd_parse_tree_free(node);
+
+ return NULL;
+}
+
+
+int parse_tree_tests(void)
+{
+ int result = 0;
+ char *test_group = "parse_tree_tests";
+
+ TEST_CASE(test_add_remove, 0);
+ TEST_CASE(test_normalization, 0);
+ TEST_CASE(test_matches, 0);
+ TEST_CASE(test_multiple_matches, 0);
+ return result;
+}
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/f6dab30f/tests/run_unit_tests.c
----------------------------------------------------------------------
diff --git a/tests/run_unit_tests.c b/tests/run_unit_tests.c
index c8c4ef3..4c2b469 100644
--- a/tests/run_unit_tests.c
+++ b/tests/run_unit_tests.c
@@ -29,6 +29,7 @@ int alloc_tests(void);
int compose_tests(void);
int policy_tests(void);
int failoverlist_tests(void);
+int parse_tree_tests(void);
int main(int argc, char** argv)
{
@@ -60,6 +61,8 @@ int main(int argc, char** argv)
#endif
result += policy_tests();
result += failoverlist_tests();
+ result += parse_tree_tests();
+
qd_dispatch_free(qd); // dispatch_free last.
return result;
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org