From: Olivier Matz Date: Tue, 13 Mar 2018 22:07:53 +0000 (+0100) Subject: test coverage for ec_node X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=0668238b755cec97680d828de701fc850f9dc276;hp=38e5638bb3b4e2e8a409184d4f07977594a5e773;p=protos%2Flibecoli.git test coverage for ec_node --- diff --git a/lib/ecoli_complete.c b/lib/ecoli_complete.c index e488e0e..14012ad 100644 --- a/lib/ecoli_complete.c +++ b/lib/ecoli_complete.c @@ -69,7 +69,7 @@ ec_node_complete_child(const struct ec_node *node, struct ec_comp_group *cur_group; int ret; - if (node->type->complete == NULL) + if (ec_node_type(node)->complete == NULL) return -ENOTSUP; /* save previous parse state, prepare child state */ @@ -85,7 +85,7 @@ ec_node_complete_child(const struct ec_node *node, comp->cur_group = NULL; /* fill the comp struct with items */ - ret = node->type->complete(node, comp, strvec); + ret = ec_node_type(node)->complete(node, comp, strvec); /* restore parent parse state */ if (cur_state != NULL) { @@ -507,7 +507,7 @@ void ec_comp_dump(FILE *out, const struct ec_comp *comp) TAILQ_FOREACH(grp, &comp->groups, next) { fprintf(out, "node=%p, node_type=%s\n", - grp->node, grp->node->type->name); + grp->node, ec_node_type(grp->node)->name); TAILQ_FOREACH(item, &grp->items, next) { const char *typestr; diff --git a/lib/ecoli_node.c b/lib/ecoli_node.c index 2b667a6..ba3d98f 100644 --- a/lib/ecoli_node.c +++ b/lib/ecoli_node.c @@ -14,14 +14,19 @@ #include #include #include +#include #include +#include +#include + EC_LOG_TYPE_REGISTER(node); static struct ec_node_type_list node_type_list = TAILQ_HEAD_INITIALIZER(node_type_list); -struct ec_node_type *ec_node_type_lookup(const char *name) +const struct ec_node_type * +ec_node_type_lookup(const char *name) { struct ec_node_type *type; @@ -102,7 +107,7 @@ struct ec_node *__ec_node(const struct ec_node_type *type, const char *id) struct ec_node *ec_node(const char *typename, const char *id) { - struct ec_node_type *type; + const struct ec_node_type *type; type = ec_node_type_lookup(typename); if (type == NULL) { @@ -129,7 +134,7 @@ void ec_node_free(struct ec_node *node) ec_free(node->children); ec_free(node->id); ec_free(node->desc); - ec_free(node->attrs); + ec_keyval_free(node->attrs); ec_free(node); } @@ -180,6 +185,7 @@ fail: return -1; } +#if 0 /* later */ int ec_node_del_child(struct ec_node *node, struct ec_node *child) { size_t i, n; @@ -200,6 +206,7 @@ fail: errno = EINVAL; return -1; } +#endif struct ec_node *ec_node_find(struct ec_node *node, const char *id) { @@ -221,6 +228,11 @@ struct ec_node *ec_node_find(struct ec_node *node, const char *id) return NULL; } +const struct ec_node_type *ec_node_type(const struct ec_node *node) +{ + return node->type; +} + struct ec_keyval *ec_node_attrs(const struct ec_node *node) { return node->attrs; @@ -281,3 +293,104 @@ int ec_node_check_type(const struct ec_node *node, } return 0; } + +/* LCOV_EXCL_START */ +static int ec_node_testcase(void) +{ + struct ec_node *node = NULL; + const struct ec_node *child; + const struct ec_node_type *type; + FILE *f = NULL; + char *buf = NULL; + size_t buflen = 0; + int testres = 0; + int ret; + + f = open_memstream(&buf, &buflen); + if (f == NULL) + goto fail; + + node = EC_NODE_SEQ(EC_NO_ID, + ec_node_str("id_x", "x"), + ec_node_str("id_y", "y")); + if (node == NULL) + goto fail; + + ec_node_dump(f, node); + ec_node_type_dump(f); + ec_node_dump(f, NULL); + fclose(f); + f = NULL; + + testres |= EC_TEST_CHECK( + strstr(buf, "type=seq id=no-id"), "bad dump\n"); + testres |= EC_TEST_CHECK( + strstr(buf, "type=str id=id_x") && + strstr(strstr(buf, "type=str id=id_x") + 1, + "type=str id=id_y"), + "bad dump\n"); + free(buf); + + testres |= EC_TEST_CHECK( + ec_node_get_children_count(node) == 2, + "bad children count\n"); + child = ec_node_get_child(node, 0); + testres |= EC_TEST_CHECK(child != NULL && + !strcmp(ec_node_type(child)->name, "str") && + !strcmp(ec_node_id(child), "id_x"), + "bad child 0"); + child = ec_node_get_child(node, 1); + testres |= EC_TEST_CHECK(child != NULL && + !strcmp(ec_node_type(child)->name, "str") && + !strcmp(ec_node_id(child), "id_y"), + "bad child 1"); + child = ec_node_get_child(node, 2); + testres |= EC_TEST_CHECK(child == NULL, + "child 2 should be NULL"); + + child = ec_node_find(node, "id_x"); + testres |= EC_TEST_CHECK(child != NULL && + !strcmp(ec_node_type(child)->name, "str") && + !strcmp(ec_node_id(child), "id_x"), + "bad child id_x"); + child = ec_node_find(node, "id_dezdex"); + testres |= EC_TEST_CHECK(child == NULL, + "child with wrong id should be NULL"); + + ret = ec_keyval_set(ec_node_attrs(node), "key", "val", NULL); + testres |= EC_TEST_CHECK(ret == 0, + "cannot set node attribute\n"); + + type = ec_node_type_lookup("seq"); + testres |= EC_TEST_CHECK(type != NULL && + ec_node_check_type(node, type) == 0, + "cannot get seq node type"); + type = ec_node_type_lookup("str"); + testres |= EC_TEST_CHECK(type != NULL && + ec_node_check_type(node, type) < 0, + "node type should not be str"); + + ec_node_free(node); + node = NULL; + + node = ec_node("deznuindez", EC_NO_ID); + testres |= EC_TEST_CHECK(node == NULL, + "should not be able to create node\n"); + + return testres; + +fail: + ec_node_free(node); + if (f != NULL) + fclose(f); + + return -1; +} +/* LCOV_EXCL_STOP */ + +static struct ec_test ec_node_test = { + .name = "node", + .test = ec_node_testcase, +}; + +EC_TEST_REGISTER(ec_node_test); diff --git a/lib/ecoli_node.h b/lib/ecoli_node.h index e371a8b..b6380b0 100644 --- a/lib/ecoli_node.h +++ b/lib/ecoli_node.h @@ -88,7 +88,6 @@ typedef void (*ec_node_free_priv_t)(struct ec_node *); struct ec_node_type { TAILQ_ENTRY(ec_node_type) next; /**< Next in list. */ const char *name; /**< Node type name. */ - ec_node_build_t build; /**< (Re)build the node */ ec_node_parse_t parse; ec_node_complete_t complete; ec_node_desc_t desc; @@ -116,7 +115,7 @@ int ec_node_type_register(struct ec_node_type *type); * @return * The node type if found, or NULL on error. */ -struct ec_node_type *ec_node_type_lookup(const char *name); +const struct ec_node_type *ec_node_type_lookup(const char *name); /** * Dump registered log types @@ -150,6 +149,7 @@ int ec_node_add_child(struct ec_node *node, struct ec_node *child); int ec_node_del_child(struct ec_node *node, struct ec_node *child); /* XXX add more accessors */ +const struct ec_node_type *ec_node_type(const struct ec_node *node); struct ec_keyval *ec_node_attrs(const struct ec_node *node); const char *ec_node_id(const struct ec_node *node); const char *ec_node_desc(const struct ec_node *node); diff --git a/lib/ecoli_parse.c b/lib/ecoli_parse.c index 7f36226..87dda7a 100644 --- a/lib/ecoli_parse.c +++ b/lib/ecoli_parse.c @@ -36,7 +36,7 @@ static int __ec_node_parse_child(const struct ec_node *node, struct ec_parse *child = NULL; int ret; - if (node->type->parse == NULL) + if (ec_node_type(node)->parse == NULL) return -ENOTSUP; if (!is_root) { @@ -48,7 +48,7 @@ static int __ec_node_parse_child(const struct ec_node *node, } else { child = state; } - ret = node->type->parse(node, child, strvec); + ret = ec_node_type(node)->parse(node, child, strvec); if (ret < 0 || ret == EC_PARSE_NOMATCH) goto free; @@ -243,7 +243,7 @@ static void __ec_parse_dump(FILE *out, /* node can be null when parsing is incomplete */ if (parse->node != NULL) { id = parse->node->id; - typename = parse->node->type->name; + typename = ec_node_type(parse->node)->name; } fprintf(out, "%*s" "type=%s id=%s vec=",