From d9bf91fc5a344999e1e0a00652ba970fbe541013 Mon Sep 17 00:00:00 2001 From: Max Regan Date: Sun, 2 Apr 2017 22:26:41 -0700 Subject: [PATCH] tri: fix autocomplete when one string is a prefix of another Also add a bunch of unit tests for all of the various tri functions. Signed-off-by: Max Regan --- src/apps/tri-test.c | 59 +++++++++++++++++++++++++++++++++++++++++++++ src/tri.c | 17 ++++++++----- 2 files changed, 70 insertions(+), 6 deletions(-) diff --git a/src/apps/tri-test.c b/src/apps/tri-test.c index 0154bbf..0ac9ffa 100644 --- a/src/apps/tri-test.c +++ b/src/apps/tri-test.c @@ -54,12 +54,71 @@ static void test_tri_prefix_match(void) tri_free(&tri); } +static void test_tri_autocomplete(void) +{ + struct tri tri; + bool ambiguous; + + tri_init(&tri); + + g_assert_cmpint(tri_add_string(&tri, "pr", TO_PTR(1)), ==, 0); + g_assert_cmpint(tri_add_string(&tri, "pref", TO_PTR(2)), ==, 0); + g_assert_cmpint(tri_add_string(&tri, "Z", TO_PTR(3)), ==, 0); + g_assert_cmpint(tri_add_string(&tri, "prefix", TO_PTR(4)), ==, 0); + g_assert_cmpint(tri_add_string(&tri, "blah", TO_PTR(5)), ==, 0); + + + g_assert_null(tri_get_string_autocomplete(&tri, "p", &ambiguous)); + g_assert_true(ambiguous); + + g_assert_null(tri_get_string_autocomplete(&tri, "pr", &ambiguous)); + g_assert_true(ambiguous); + + g_assert_null(tri_get_string_autocomplete(&tri, "pre", &ambiguous)); + g_assert_true(ambiguous); + + g_assert_null(tri_get_string_autocomplete(&tri, "pref", &ambiguous)); + g_assert_true(ambiguous); + + g_assert_null(tri_get_string_autocomplete(&tri, "prefix10", &ambiguous)); + g_assert_false(ambiguous); + + g_assert_null(tri_get_string_autocomplete(&tri, "asdfasdf", &ambiguous)); + g_assert_false(ambiguous); + + g_assert_cmpint(TO_INT(tri_get_string_autocomplete(&tri, "bla", &ambiguous)), ==, 5); + g_assert_false(ambiguous); + + g_assert_cmpint(TO_INT(tri_get_string_autocomplete(&tri, "prefi", &ambiguous)), ==, 4); + g_assert_false(ambiguous); + + g_assert_cmpint(TO_INT(tri_get_string_autocomplete(&tri, "prefix", &ambiguous)), ==, 4); + g_assert_false(ambiguous); + + g_assert_cmpint(TO_INT(tri_get_string_autocomplete(&tri, "Z", &ambiguous)), ==, 3); + g_assert_false(ambiguous); + + tri_free(&tri); +} + +static void test_tri_null(void) +{ + struct tri tri; + + tri_init(&tri); + + g_assert_cmpint(tri_add_string(&tri, NULL, TO_PTR(1)), ==, -1); + g_assert_null(tri_prefix_match(&tri, NULL)); +} + int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); g_test_add_func("/tri/get_string", test_tri_get_string); g_test_add_func("/tri/prefix_match", test_tri_prefix_match); + g_test_add_func("/tri/autocomplete", test_tri_autocomplete); + g_test_add_func("/tri/null", test_tri_null); return g_test_run(); } diff --git a/src/tri.c b/src/tri.c index 3a10a6a..bde1921 100644 --- a/src/tri.c +++ b/src/tri.c @@ -115,23 +115,28 @@ void *tri_get_string_autocomplete(struct tri *tri, const char *string, bool *amb while(1) { struct tri_node *next_node = NULL; + int num_paths = 0; for (j = 0; j < ARRAY_SIZE(node->nodes); j++) { - - if (node->nodes[j] != NULL && next_node == NULL) { + if (node->nodes[j] != NULL) { next_node = node->nodes[j]; - } else if (node->nodes[j] != NULL && next_node != NULL) { - *ambiguous = true; - return NULL; + num_paths++; + if (num_paths > 1) { + *ambiguous = true; + return NULL; + } } } if (next_node == NULL) { return node->value; + } else if (node->value != NULL && next_node != NULL) { + *ambiguous = true; + return NULL; } else { node = next_node; - i++; } } + return node->value; }