test compile fail
This commit is contained in:
parent
fd1e5f7f50
commit
9441f974de
5 changed files with 230 additions and 47 deletions
|
@ -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);
|
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);
|
node * r3_edge_branch(edge *e, int dl);
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include "slug.h"
|
#include "slug.h"
|
||||||
#include "zmalloc.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) );
|
edge * e = (edge*) zmalloc( sizeof(edge) );
|
||||||
e->pattern = (char*) pattern;
|
e->pattern = (char*) pattern;
|
||||||
e->pattern_len = pattern_len;
|
e->pattern_len = pattern_len;
|
||||||
|
@ -54,7 +54,7 @@ node * r3_edge_branch(edge *e, int dl) {
|
||||||
// the suffix edge of the leaf
|
// the suffix edge of the leaf
|
||||||
new_child = r3_tree_create(3);
|
new_child = r3_tree_create(3);
|
||||||
s1_len = e->pattern_len - dl;
|
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.
|
// Migrate the child edges to the new edge we just created.
|
||||||
for ( int i = 0 ; i < e->child->edge_len ; i++ ) {
|
for ( int i = 0 ; i < e->child->edge_len ; i++ ) {
|
||||||
|
|
31
src/node.c
31
src/node.c
|
@ -99,7 +99,7 @@ edge * r3_node_connectl(node * n, const char * pat, int len, int dupl, node *chi
|
||||||
if (dupl) {
|
if (dupl) {
|
||||||
pat = zstrndup(pat, len);
|
pat = zstrndup(pat, len);
|
||||||
}
|
}
|
||||||
e = r3_edge_create(pat, len, child);
|
e = r3_edge_createl(pat, len, child);
|
||||||
CHECK_PTR(e);
|
CHECK_PTR(e);
|
||||||
r3_node_append_edge(n, e);
|
r3_node_append_edge(n, e);
|
||||||
return 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);
|
slug = r3_slug_new(path, path_len);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ret = r3_slug_parse(slug, path, path_len, path, NULL);
|
ret = r3_slug_parse(slug, path, path_len, offset, NULL);
|
||||||
// found slug
|
// found slug
|
||||||
if (ret == 1) {
|
if (ret == 1) {
|
||||||
// inside slug, backtrace to the begin of the slug
|
// 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;
|
break;
|
||||||
} else if ( p < slug->begin ) {
|
} else if ( p < slug->begin ) {
|
||||||
break;
|
break;
|
||||||
} else if ( p > slug->end && p < (path + path_len) ) {
|
} else if ( p >= slug->end && p < (path + path_len) ) {
|
||||||
offset = slug->end;
|
offset = slug->end + 1;
|
||||||
|
prefix = p - path;
|
||||||
continue;
|
continue;
|
||||||
// XXX: see if it's in another slug
|
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} while(ret == 1);
|
} while(ret == 1);
|
||||||
}
|
}
|
||||||
|
@ -558,25 +560,10 @@ node * r3_tree_insert_pathl_(node *tree, const char *path, int path_len, route *
|
||||||
// common edge
|
// common edge
|
||||||
edge * e = NULL;
|
edge * e = NULL;
|
||||||
|
|
||||||
|
|
||||||
/* length of common prefix */
|
/* length of common prefix */
|
||||||
int prefix_len = 0;
|
int prefix_len = 0;
|
||||||
for( int i = 0 ; i < n->edge_len ; i++ ) {
|
e = r3_node_find_common_prefix(tree, path, path_len, &prefix_len);
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char * subpath = path + prefix_len;
|
const char * subpath = path + prefix_len;
|
||||||
const int subpath_len = path_len - prefix_len;
|
const int subpath_len = path_len - prefix_len;
|
||||||
|
|
|
@ -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 = needle;
|
||||||
s->path_len = needle_len;
|
s->path_len = needle_len;
|
||||||
|
|
||||||
if (!offset) {
|
if (offset == NULL) {
|
||||||
offset = (char*) needle; // from the begining of the needle
|
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;
|
char * p = offset;
|
||||||
|
|
||||||
while( (p-needle) < needle_len) {
|
while( (p-needle) < needle_len) {
|
||||||
|
|
||||||
// escape one character
|
// escape one character
|
||||||
if (*p == '\\' ) {
|
if (*p == '\\' ) {
|
||||||
p++; p++;
|
p++; p++;
|
||||||
|
@ -133,13 +132,13 @@ int r3_slug_parse(r3_slug_t *s, char *needle, int needle_len, char *offset, char
|
||||||
p++;
|
p++;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (state > 0) {
|
if (state != 0) {
|
||||||
if (errstr) {
|
if (errstr) {
|
||||||
asprintf(errstr, "Incomplete slug pattern. PATH (%d): '%s', OFFSET: %ld, STATE: %d", needle_len, needle, p - needle, state);
|
asprintf(errstr, "Incomplete slug pattern. PATH (%d): '%s', OFFSET: %ld, STATE: %d", needle_len, needle, p - needle, state);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// found slug
|
info("found slug\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,11 @@
|
||||||
#include "bench.h"
|
#include "bench.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
START_TEST (test_find_common_prefix)
|
START_TEST (test_find_common_prefix)
|
||||||
{
|
{
|
||||||
node * n = r3_tree_create(10);
|
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);
|
r3_node_append_edge(n,e);
|
||||||
|
|
||||||
int prefix_len;
|
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);
|
ret_edge = r3_node_find_common_prefix(n, "{bar}", sizeof("{bar}")-1, &prefix_len);
|
||||||
ck_assert(!ret_edge);
|
ck_assert(!ret_edge);
|
||||||
ck_assert_int_eq(prefix_len, 0);
|
ck_assert_int_eq(prefix_len, 0);
|
||||||
|
|
||||||
|
|
||||||
|
r3_tree_free(n);
|
||||||
}
|
}
|
||||||
END_TEST
|
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
|
END_TEST
|
||||||
|
|
||||||
START_TEST (test_r3_node_construct_and_free)
|
START_TEST (test_node_construct_and_free)
|
||||||
{
|
{
|
||||||
node * n = r3_tree_create(10);
|
node * n = r3_tree_create(10);
|
||||||
node * another_tree = r3_tree_create(3);
|
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);
|
node * n = r3_tree_create(10);
|
||||||
|
|
||||||
r3_tree_insert_path(n, "/foo/bar", NULL);
|
node * ret;
|
||||||
// r3_tree_dump(n, 0);
|
|
||||||
|
|
||||||
r3_tree_insert_path(n, "/foo/zoo", NULL);
|
ret = r3_tree_insert_path(n, "/foo/bar", NULL);
|
||||||
// r3_tree_dump(n, 0);
|
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);
|
ret = r3_tree_insert_path(n, "/foo/{name:\\d{5}}", NULL);
|
||||||
// r3_tree_dump(n, 0);
|
ck_assert(ret);
|
||||||
|
|
||||||
r3_tree_insert_path(n, "/post/{id}", NULL);
|
ret = r3_tree_insert_path(n, "/foo/{idx}/{idy}", NULL);
|
||||||
// r3_tree_dump(n, 0);
|
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;
|
char * errstr = NULL;
|
||||||
r3_tree_compile(n, &errstr);
|
r3_tree_compile(n, &errstr);
|
||||||
|
ck_assert(errstr == NULL);
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
r3_tree_dump(n, 0);
|
r3_tree_dump(n, 0);
|
||||||
#endif
|
|
||||||
r3_tree_free(n);
|
r3_tree_free(n);
|
||||||
}
|
}
|
||||||
END_TEST
|
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 *tcase = tcase_create("testcase");
|
||||||
|
|
||||||
tcase_add_test(tcase, test_find_common_prefix);
|
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, test_ltrim_slash);
|
||||||
tcase_add_test(tcase, testr3_tree_insert_pathl);
|
|
||||||
tcase_add_test(tcase, test_compile);
|
tcase_add_test(tcase, test_compile);
|
||||||
tcase_add_test(tcase, test_route_cmp);
|
tcase_add_test(tcase, test_route_cmp);
|
||||||
tcase_add_test(tcase, test_insert_route);
|
tcase_add_test(tcase, test_insert_route);
|
||||||
|
|
Loading…
Reference in a new issue