From 9441f974de76af159826f61171ad1d6fc2229522 Mon Sep 17 00:00:00 2001 From: c9s Date: Mon, 2 Jun 2014 09:48:00 +0800 Subject: [PATCH] test compile fail --- include/r3.h | 2 +- src/edge.c | 4 +- src/node.c | 31 ++---- src/slug.c | 7 +- tests/check_tree.c | 233 +++++++++++++++++++++++++++++++++++++++++---- 5 files changed, 230 insertions(+), 47 deletions(-) diff --git a/include/r3.h b/include/r3.h index ea9f356..d91f4a5 100644 --- a/include/r3.h +++ b/include/r3.h @@ -144,7 +144,7 @@ node * r3_tree_matchl(const node * n, const char * path, int path_len, match_ent bool r3_node_has_slug_edges(const node *n); -edge * r3_edge_create(const char * pattern, int pattern_len, node * child); +edge * r3_edge_createl(const char * pattern, int pattern_len, node * child); node * r3_edge_branch(edge *e, int dl); diff --git a/src/edge.c b/src/edge.c index 7305243..ad6eb7f 100644 --- a/src/edge.c +++ b/src/edge.c @@ -24,7 +24,7 @@ #include "slug.h" #include "zmalloc.h" -edge * r3_edge_create(const char * pattern, int pattern_len, node * child) { +edge * r3_edge_createl(const char * pattern, int pattern_len, node * child) { edge * e = (edge*) zmalloc( sizeof(edge) ); e->pattern = (char*) pattern; e->pattern_len = pattern_len; @@ -54,7 +54,7 @@ node * r3_edge_branch(edge *e, int dl) { // the suffix edge of the leaf new_child = r3_tree_create(3); s1_len = e->pattern_len - dl; - e1 = r3_edge_create(zstrndup(s1, s1_len), s1_len, new_child); + e1 = r3_edge_createl(zstrndup(s1, s1_len), s1_len, new_child); // Migrate the child edges to the new edge we just created. for ( int i = 0 ; i < e->child->edge_len ; i++ ) { diff --git a/src/node.c b/src/node.c index d7cb14e..c288c24 100644 --- a/src/node.c +++ b/src/node.c @@ -99,7 +99,7 @@ edge * r3_node_connectl(node * n, const char * pat, int len, int dupl, node *chi if (dupl) { pat = zstrndup(pat, len); } - e = r3_edge_create(pat, len, child); + e = r3_edge_createl(pat, len, child); CHECK_PTR(e); r3_node_append_edge(n, e); return e; @@ -520,7 +520,7 @@ edge * r3_node_find_common_prefix(node *n, char *path, int path_len, int *prefix slug = r3_slug_new(path, path_len); do { - ret = r3_slug_parse(slug, path, path_len, path, NULL); + ret = r3_slug_parse(slug, path, path_len, offset, NULL); // found slug if (ret == 1) { // inside slug, backtrace to the begin of the slug @@ -529,13 +529,15 @@ edge * r3_node_find_common_prefix(node *n, char *path, int path_len, int *prefix break; } else if ( p < slug->begin ) { break; - } else if ( p > slug->end && p < (path + path_len) ) { - offset = slug->end; + } else if ( p >= slug->end && p < (path + path_len) ) { + offset = slug->end + 1; + prefix = p - path; continue; - // XXX: see if it's in another slug } else { break; } + } else { + break; } } while(ret == 1); } @@ -558,25 +560,10 @@ node * r3_tree_insert_pathl_(node *tree, const char *path, int path_len, route * // common edge edge * e = NULL; + /* length of common prefix */ int prefix_len = 0; - for( int i = 0 ; i < n->edge_len ; i++ ) { - // ignore all edges with slug - prefix_len = strndiff( (char*) path, n->edges[i]->pattern, n->edges[i]->pattern_len); - - // no common, consider insert a new edge - if ( prefix_len > 0 ) { - e = n->edges[i]; - break; - } - } - - - // branch the edge at correct position (avoid broken slugs) - const char *slug_s; - if ( (slug_s = inside_slug(path, path_len, ((char*) path + prefix_len), NULL)) != NULL ) { - prefix_len = slug_s - path; - } + e = r3_node_find_common_prefix(tree, path, path_len, &prefix_len); const char * subpath = path + prefix_len; const int subpath_len = path_len - prefix_len; diff --git a/src/slug.c b/src/slug.c index 2df0733..12cfd23 100644 --- a/src/slug.c +++ b/src/slug.c @@ -76,7 +76,7 @@ int r3_slug_parse(r3_slug_t *s, char *needle, int needle_len, char *offset, char s->path = needle; s->path_len = needle_len; - if (!offset) { + if (offset == NULL) { offset = (char*) needle; // from the begining of the needle } @@ -90,7 +90,6 @@ int r3_slug_parse(r3_slug_t *s, char *needle, int needle_len, char *offset, char char * p = offset; while( (p-needle) < needle_len) { - // escape one character if (*p == '\\' ) { p++; p++; @@ -133,13 +132,13 @@ int r3_slug_parse(r3_slug_t *s, char *needle, int needle_len, char *offset, char p++; }; - if (state > 0) { + if (state != 0) { if (errstr) { asprintf(errstr, "Incomplete slug pattern. PATH (%d): '%s', OFFSET: %ld, STATE: %d", needle_len, needle, p - needle, state); } return -1; } - // found slug + info("found slug\n"); return 1; } diff --git a/tests/check_tree.c b/tests/check_tree.c index 75a87c4..f3042ae 100644 --- a/tests/check_tree.c +++ b/tests/check_tree.c @@ -9,10 +9,11 @@ #include "bench.h" + START_TEST (test_find_common_prefix) { node * n = r3_tree_create(10); - edge * e = r3_edge_create("/foo/{slug}", sizeof("/foo/{slug}")-1, NULL); + edge * e = r3_edge_createl(zstrdup("/foo/{slug}"), sizeof("/foo/{slug}")-1, NULL); r3_node_append_edge(n,e); int prefix_len; @@ -57,6 +58,9 @@ START_TEST (test_find_common_prefix) ret_edge = r3_node_find_common_prefix(n, "{bar}", sizeof("{bar}")-1, &prefix_len); ck_assert(!ret_edge); ck_assert_int_eq(prefix_len, 0); + + + r3_tree_free(n); } END_TEST @@ -64,6 +68,136 @@ END_TEST +START_TEST (test_find_common_prefix_after) +{ + node * n = r3_tree_create(10); + edge * e = r3_edge_createl(zstrdup("{slug}/foo"), sizeof("{slug}/foo")-1, NULL); + r3_node_append_edge(n,e); + + int prefix_len; + edge *ret_edge = NULL; + + + prefix_len = 0; + ret_edge = r3_node_find_common_prefix(n, "/foo", sizeof("/foo")-1, &prefix_len); + ck_assert(ret_edge == NULL); + ck_assert_int_eq(prefix_len, 0); + + + prefix_len = 0; + ret_edge = r3_node_find_common_prefix(n, "{slug}/bar", sizeof("{slug}/bar")-1, &prefix_len); + ck_assert(ret_edge); + ck_assert_int_eq(prefix_len, 7); + + + prefix_len = 0; + ret_edge = r3_node_find_common_prefix(n, "{slug}/foo", sizeof("{slug}/foo")-1, &prefix_len); + ck_assert(ret_edge); + ck_assert_int_eq(prefix_len, 10); + + + r3_tree_free(n); +} +END_TEST + + + +START_TEST (test_find_common_prefix_double_middle) +{ + node * n = r3_tree_create(10); + edge * e = r3_edge_createl(zstrdup("{slug}/foo/{name}"), sizeof("{slug}/foo/{name}")-1, NULL); + r3_node_append_edge(n,e); + + int prefix_len; + edge *ret_edge = NULL; + + prefix_len = 0; + ret_edge = r3_node_find_common_prefix(n, "{slug}/foo/{number}", sizeof("{slug}/foo/{number}")-1, &prefix_len); + ck_assert(ret_edge); + ck_assert_int_eq(prefix_len, 11); + + r3_tree_free(n); +} +END_TEST + + + +START_TEST (test_find_common_prefix_middle) +{ + node * n = r3_tree_create(10); + edge * e = r3_edge_createl(zstrdup("/foo/{slug}/hate"), sizeof("/foo/{slug}/hate")-1, NULL); + r3_node_append_edge(n,e); + + int prefix_len; + edge *ret_edge = NULL; + + prefix_len = 0; + ret_edge = r3_node_find_common_prefix(n, "/foo/{slug}/bar", sizeof("/foo/{slug}/bar")-1, &prefix_len); + ck_assert(ret_edge); + ck_assert_int_eq(prefix_len, 12); + + prefix_len = 0; + ret_edge = r3_node_find_common_prefix(n, "/fo/{slug}/bar", sizeof("/fo/{slug}/bar")-1, &prefix_len); + ck_assert(ret_edge); + ck_assert_int_eq(prefix_len, 3); + + r3_tree_free(n); +} +END_TEST + +START_TEST (test_find_common_prefix_same_pattern) +{ + node * n = r3_tree_create(10); + edge * e = r3_edge_createl(zstrdup("/foo/{slug:xxx}/hate"), sizeof("/foo/{slug:xxx}/hate")-1, NULL); + r3_node_append_edge(n,e); + + int prefix_len; + edge *ret_edge = NULL; + + prefix_len = 0; + ret_edge = r3_node_find_common_prefix(n, "/foo/{slug:yyy}/hate", sizeof("/foo/{slug:yyy}/hate")-1, &prefix_len); + ck_assert(ret_edge); + ck_assert_int_eq(prefix_len, 5); + + + prefix_len = 0; + ret_edge = r3_node_find_common_prefix(n, "/foo/{slug}/hate", sizeof("/foo/{slug}/hate")-1, &prefix_len); + ck_assert(ret_edge); + ck_assert_int_eq(prefix_len, 5); + + r3_tree_free(n); +} +END_TEST + +START_TEST (test_find_common_prefix_same_pattern2) +{ + node * n = r3_tree_create(10); + edge * e = r3_edge_createl(zstrdup("{slug:xxx}/hate"), sizeof("{slug:xxx}/hate")-1, NULL); + r3_node_append_edge(n,e); + + int prefix_len; + edge *ret_edge = NULL; + + prefix_len = 0; + ret_edge = r3_node_find_common_prefix(n, "{slug:yyy}/hate", sizeof("{slug:yyy}/hate")-1, &prefix_len); + ck_assert(ret_edge); + ck_assert_int_eq(prefix_len, 0); + + r3_tree_free(n); +} +END_TEST + + + + + + + + + + + + @@ -75,7 +209,7 @@ START_TEST (test_ltrim_slash) } END_TEST -START_TEST (test_r3_node_construct_and_free) +START_TEST (test_node_construct_and_free) { node * n = r3_tree_create(10); node * another_tree = r3_tree_create(3); @@ -301,38 +435,96 @@ END_TEST -START_TEST (testr3_tree_insert_pathl) +START_TEST (test_insert_pathl) { node * n = r3_tree_create(10); - r3_tree_insert_path(n, "/foo/bar", NULL); - // r3_tree_dump(n, 0); + node * ret; - r3_tree_insert_path(n, "/foo/zoo", NULL); - // r3_tree_dump(n, 0); + ret = r3_tree_insert_path(n, "/foo/bar", NULL); + ck_assert(ret); + ret = r3_tree_insert_path(n, "/foo/zoo", NULL); + ck_assert(ret); + ret = r3_tree_insert_path(n, "/foo/{id}", NULL); + ck_assert(ret); + ret = r3_tree_insert_path(n, "/foo/{number:\\d+}", NULL); + ck_assert(ret); + ret = r3_tree_insert_path(n, "/foo/{name:\\w+}", NULL); + ck_assert(ret); + ret = r3_tree_insert_path(n, "/foo/{name:\\d+}", NULL); + ck_assert(ret); - r3_tree_insert_path(n, "/f/id" , NULL); - // r3_tree_dump(n, 0); + ret = r3_tree_insert_path(n, "/foo/{name:\\d{5}}", NULL); + ck_assert(ret); - r3_tree_insert_path(n, "/post/{id}", NULL); - // r3_tree_dump(n, 0); + ret = r3_tree_insert_path(n, "/foo/{idx}/{idy}", NULL); + ck_assert(ret); - r3_tree_insert_path(n, "/post/{handle}", NULL); + ret = r3_tree_insert_path(n, "/foo/{idx}/{idh}", NULL); + ck_assert(ret); - r3_tree_insert_path(n, "/post/{handle}-{id}", NULL); + ret = r3_tree_insert_path(n, "/f/id" , NULL); + ck_assert(ret); + ret = r3_tree_insert_path(n, "/post/{id}", NULL); + ck_assert(ret); + ret = r3_tree_insert_path(n, "/post/{handle}", NULL); + ck_assert(ret); + ret = r3_tree_insert_path(n, "/post/{handle}-{id}", NULL); + ck_assert(ret); char * errstr = NULL; r3_tree_compile(n, &errstr); + ck_assert(errstr == NULL); -#ifdef DEBUG r3_tree_dump(n, 0); -#endif r3_tree_free(n); } END_TEST +START_TEST (test_compile_fail) +{ + node * n = r3_tree_create(10); + + node * ret; + + ret = r3_tree_insert_path(n, "/foo/{idx}/{idy:)}", NULL); + ck_assert(ret); + + ret = r3_tree_insert_path(n, "/foo/{idx}/{idh:(}", NULL); + ck_assert(ret); + + char * errstr = NULL; + r3_tree_compile(n, &errstr); + ck_assert(errstr); + fprintf(stderr, "Compile failed: %s\n", errstr); + free(errstr); + + r3_tree_dump(n, 0); + r3_tree_free(n); +} +END_TEST + + + + + + + + + + + + + + + + + + + + @@ -459,11 +651,16 @@ Suite* r3_suite (void) { TCase *tcase = tcase_create("testcase"); tcase_add_test(tcase, test_find_common_prefix); - + tcase_add_test(tcase, test_find_common_prefix_after); + tcase_add_test(tcase, test_find_common_prefix_double_middle); + tcase_add_test(tcase, test_find_common_prefix_middle); + tcase_add_test(tcase, test_find_common_prefix_same_pattern); + tcase_add_test(tcase, test_find_common_prefix_same_pattern2); + tcase_add_test(tcase, test_insert_pathl); + tcase_add_test(tcase, test_compile_fail); + tcase_add_test(tcase, test_node_construct_and_free); /* - tcase_add_test(tcase, test_r3_node_construct_and_free); tcase_add_test(tcase, test_ltrim_slash); - tcase_add_test(tcase, testr3_tree_insert_pathl); tcase_add_test(tcase, test_compile); tcase_add_test(tcase, test_route_cmp); tcase_add_test(tcase, test_insert_route);