schema tree REFACTOR compile case like a general node
Change included - all choice data children are not linked
siblings anymore but standard children of their case.
Fixes #1157
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 3d2dcb9..1ec681a 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -112,9 +112,10 @@
next = (struct lysc_node *)(¬ifs[u + 1]);
}
goto repeat;
+ } else {
+ next = last->next;
}
- next = last->next;
repeat:
if (next && parent && parent->nodetype == LYS_CASE && next->parent != parent) {
/* inside case (as an explicit parent, not when diving into it from choice),
@@ -147,8 +148,15 @@
case LYS_ANYDATA:
case LYS_LIST:
case LYS_LEAFLIST:
- case LYS_CASE:
break;
+ case LYS_CASE:
+ if (options & LYS_GETNEXT_WITHCASE) {
+ break;
+ } else {
+ /* go into */
+ next = ((struct lysc_node_case *)next)->child;
+ }
+ goto repeat;
case LYS_CONTAINER:
if (!(((struct lysc_node_container *)next)->flags & LYS_PRESENCE) && (options & LYS_GETNEXT_INTONPCONT)) {
if (((struct lysc_node_container *)next)->child) {
@@ -162,7 +170,7 @@
break;
case LYS_CHOICE:
if (options & LYS_GETNEXT_WITHCHOICE) {
- return next;
+ break;
} else if ((options & LYS_GETNEXT_NOCHOICE) || !((struct lysc_node_choice *)next)->cases) {
next = next->next;
} else {
diff --git a/src/tree_schema_compile.c b/src/tree_schema_compile.c
index 566cacc..139ec0e 100644
--- a/src/tree_schema_compile.c
+++ b/src/tree_schema_compile.c
@@ -3202,40 +3202,86 @@
* structures, but they share the namespace so we need to check their name collisions.
*
* @param[in] ctx Compile context.
- * @param[in] children List (linked list) of data nodes to go through.
- * @param[in] actions List (sized array) of actions or RPCs to go through.
- * @param[in] notifs List (sized array) of Notifications to go through.
+ * @param[in] parent Parent of the nodes to check, can be NULL.
* @param[in] name Name of the item to find in the given lists.
- * @param[in] exclude Pointer to an object to exclude from the name checking - for the case that the object
- * with the @p name being checked is already inserted into one of the list so we need to skip it when searching for duplicity.
+ * @param[in] exclude Node that was just added that should be excluded from the name checking.
* @return LY_SUCCESS in case of unique name, LY_EEXIST otherwise.
*/
static LY_ERR
-lys_compile_node_uniqness(struct lysc_ctx *ctx, const struct lysc_node *children, const struct lysc_action *actions,
- const struct lysc_notif *notifs, const char *name, void *exclude)
+lys_compile_node_uniqness(struct lysc_ctx *ctx, const struct lysc_node *parent, const char *name,
+ const struct lysc_node *exclude)
{
- const struct lysc_node *iter;
+ const struct lysc_node *iter, *iter2;
+ const struct lysc_action *actions;
+ const struct lysc_notif *notifs;
+ uint32_t getnext_flags;
LY_ARRAY_COUNT_TYPE u;
- LY_LIST_FOR(children, iter) {
- if (iter != exclude && iter->module == ctx->mod && !strcmp(name, iter->name)) {
+#define CHECK_NODE(iter, exclude, name) (iter != (void *)exclude && (iter)->module == exclude->module && !strcmp(name, (iter)->name))
+
+ if (exclude->nodetype == LYS_CASE) {
+ /* check restricted only to all the cases */
+ assert(parent->nodetype == LYS_CHOICE);
+ LY_LIST_FOR(lysc_node_children(parent, 0), iter) {
+ if (CHECK_NODE(iter, exclude, name)) {
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_DUPIDENT, name, "case");
+ return LY_EEXIST;
+ }
+ }
+
+ return LY_SUCCESS;
+ }
+
+ /* no reason for our parent to be choice anymore */
+ assert(!parent || (parent->nodetype != LYS_CHOICE));
+
+ if (parent && (parent->nodetype == LYS_CASE)) {
+ /* move to the first data definition parent */
+ parent = lysc_data_parent(parent);
+ }
+
+ getnext_flags = LYS_GETNEXT_NOSTATECHECK | LYS_GETNEXT_WITHCHOICE;
+ if (parent && (parent->nodetype & (LYS_RPC | LYS_ACTION)) && (exclude->flags & LYS_CONFIG_R)) {
+ getnext_flags |= LYS_GETNEXT_OUTPUT;
+ }
+
+ iter = NULL;
+ while ((iter = lys_getnext(iter, parent, ctx->mod->compiled, getnext_flags))) {
+ if (CHECK_NODE(iter, exclude, name)) {
goto error;
}
+
+ /* we must compare with both the choice and all its nested data-definiition nodes (but not recursively) */
+ if (iter->nodetype == LYS_CHOICE) {
+ iter2 = NULL;
+ while ((iter2 = lys_getnext(iter2, iter, NULL, LYS_GETNEXT_NOSTATECHECK))) {
+ if (CHECK_NODE(iter2, exclude, name)) {
+ goto error;
+ }
+ }
+ }
}
+
+ actions = parent ? lysc_node_actions(parent) : ctx->mod->compiled->rpcs;
LY_ARRAY_FOR(actions, u) {
- if (&actions[u] != exclude && actions[u].module == ctx->mod && !strcmp(name, actions[u].name)) {
+ if (CHECK_NODE(&actions[u], exclude, name)) {
goto error;
}
}
+
+ notifs = parent ? lysc_node_notifs(parent) : ctx->mod->compiled->notifs;
LY_ARRAY_FOR(notifs, u) {
- if (¬ifs[u] != exclude && notifs[u].module == ctx->mod && !strcmp(name, notifs[u].name)) {
+ if (CHECK_NODE(¬ifs[u], exclude, name)) {
goto error;
}
}
return LY_SUCCESS;
+
error:
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_DUPIDENT, name, "data definition/RPC/action/notification");
return LY_EEXIST;
+
+#undef CHECK_NODE
}
static LY_ERR lys_compile_node(struct lysc_ctx *ctx, struct lysp_node *node_p, struct lysc_node *parent, uint16_t uses_status);
@@ -3261,12 +3307,12 @@
lysc_update_path(ctx, parent, action_p->name);
- if (lys_compile_node_uniqness(ctx, parent ? lysc_node_children(parent, 0) : ctx->mod->compiled->data,
- parent ? lysc_node_actions(parent) : ctx->mod->compiled->rpcs,
- parent ? lysc_node_notifs(parent) : ctx->mod->compiled->notifs,
- action_p->name, action)) {
- return LY_EVALID;
- }
+ /* member needed for uniqueness check lys_getnext() */
+ action->nodetype = parent ? LYS_ACTION : LYS_RPC;
+ action->module = ctx->mod;
+ action->parent = parent;
+
+ LY_CHECK_RET(lys_compile_node_uniqness(ctx, parent, action_p->name, (struct lysc_node *)action));
if (ctx->options & (LYSC_OPT_RPC_MASK | LYSC_OPT_NOTIFICATION)) {
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
@@ -3275,9 +3321,6 @@
return LY_EVALID;
}
- action->nodetype = parent ? LYS_ACTION : LYS_RPC;
- action->module = ctx->mod;
- action->parent = parent;
if (!(ctx->options & LYSC_OPT_FREE_SP)) {
action->sp = action_p;
}
@@ -3347,12 +3390,12 @@
lysc_update_path(ctx, parent, notif_p->name);
- if (lys_compile_node_uniqness(ctx, parent ? lysc_node_children(parent, 0) : ctx->mod->compiled->data,
- parent ? lysc_node_actions(parent) : ctx->mod->compiled->rpcs,
- parent ? lysc_node_notifs(parent) : ctx->mod->compiled->notifs,
- notif_p->name, notif)) {
- return LY_EVALID;
- }
+ /* member needed for uniqueness check lys_getnext() */
+ notif->nodetype = LYS_NOTIF;
+ notif->module = ctx->mod;
+ notif->parent = parent;
+
+ LY_CHECK_RET(lys_compile_node_uniqness(ctx, parent, notif_p->name, (struct lysc_node *)notif));
if (ctx->options & (LYSC_OPT_RPC_MASK | LYSC_OPT_NOTIFICATION)) {
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
@@ -3361,9 +3404,6 @@
return LY_EVALID;
}
- notif->nodetype = LYS_NOTIF;
- notif->module = ctx->mod;
- notif->parent = parent;
if (!(ctx->options & LYSC_OPT_FREE_SP)) {
notif->sp = notif_p;
}
@@ -3969,7 +4009,49 @@
}
/**
+ * @brief Compile choice children.
+ *
+ * @param[in] ctx Compile context
+ * @param[in] child_p Parsed choice children nodes.
+ * @param[in] node Compiled choice node to compile and add children to.
+ * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
+ */
+static LY_ERR
+lys_compile_node_choice_child(struct lysc_ctx *ctx, struct lysp_node *child_p, struct lysc_node *node)
+{
+ LY_ERR ret = LY_SUCCESS;
+ struct lysp_node *child_next_p;
+ struct lysp_node_case *cs_p;
+
+ if (child_p->nodetype == LYS_CASE) {
+ /* standard case under choice */
+ ret = lys_compile_node(ctx, child_p, node, 0);
+ } else {
+ /* we need the implicit case first, so create a fake parsed case */
+ cs_p = calloc(1, sizeof *cs_p);
+ cs_p->nodetype = LYS_CASE;
+ DUP_STRING(ctx->ctx, child_p->name, cs_p->name);
+ cs_p->child = child_p;
+
+ /* make the child the only case child */
+ child_next_p = child_p->next;
+ child_p->next = NULL;
+
+ /* compile it normally */
+ ret = lys_compile_node(ctx, (struct lysp_node *)cs_p, node, 0);
+
+ /* free the fake parsed node and correct pointers back */
+ cs_p->child = NULL;
+ lysp_node_free(ctx->ctx, (struct lysp_node *)cs_p);
+ child_p->next = child_next_p;
+ }
+
+ return ret;
+}
+
+/**
* @brief Compile parsed choice node information.
+ *
* @param[in] ctx Compile context
* @param[in] node_p Parsed choice node.
* @param[in,out] node Pre-prepared structure from lys_compile_node() with filled generic node information
@@ -3981,17 +4063,13 @@
{
struct lysp_node_choice *ch_p = (struct lysp_node_choice *)node_p;
struct lysc_node_choice *ch = (struct lysc_node_choice *)node;
- struct lysp_node *child_p, *case_child_p;
+ struct lysp_node *child_p;
LY_ERR ret = LY_SUCCESS;
+ assert(node->nodetype == LYS_CHOICE);
+
LY_LIST_FOR(ch_p->child, child_p) {
- if (child_p->nodetype == LYS_CASE) {
- LY_LIST_FOR(((struct lysp_node_case *)child_p)->child, case_child_p) {
- LY_CHECK_RET(lys_compile_node(ctx, case_child_p, node, 0));
- }
- } else {
- LY_CHECK_RET(lys_compile_node(ctx, child_p, node, 0));
- }
+ LY_CHECK_RET(lys_compile_node_choice_child(ctx, child_p, node));
}
/* default branch */
@@ -4050,12 +4128,17 @@
struct lysc_node **children, *start, *end;
const struct lys_module *mod;
- if (node->nodetype == LYS_CASE) {
- children = (struct lysc_node **)&((struct lysc_node_choice *)parent)->cases;
- } else {
- children = lysc_node_children_p(parent, ctx->options);
- }
- if (children) {
+ node->parent = parent;
+
+ if (parent) {
+ if (parent->nodetype == LYS_CHOICE) {
+ assert(node->nodetype == LYS_CASE);
+ children = (struct lysc_node **)&((struct lysc_node_choice *)parent)->cases;
+ } else {
+ children = lysc_node_children_p(parent, ctx->options);
+ }
+ assert(children);
+
if (!(*children)) {
/* first child */
*children = node;
@@ -4090,14 +4173,29 @@
node->prev = (*children)->prev;
(*children)->prev = node;
}
+ }
- /* check the name uniqueness */
- if (lys_compile_node_uniqness(ctx, *children, lysc_node_actions(parent),
- lysc_node_notifs(parent), node->name, node)) {
- return LY_EEXIST;
- }
+ /* check the name uniqueness (even for an only child, it may be in case) */
+ if (lys_compile_node_uniqness(ctx, parent, node->name, node)) {
+ return LY_EEXIST;
+ }
+ } else {
+ /* top-level element */
+ if (!ctx->mod->compiled->data) {
+ ctx->mod->compiled->data = node;
+ } else {
+ /* insert at the end of the module's top-level nodes list */
+ ctx->mod->compiled->data->prev->next = node;
+ node->prev = ctx->mod->compiled->data->prev;
+ ctx->mod->compiled->data->prev = node;
+ }
+
+ /* check the name uniqueness on top-level */
+ if (lys_compile_node_uniqness(ctx, NULL, node->name, node)) {
+ return LY_EEXIST;
}
}
+
return LY_SUCCESS;
}
@@ -4115,78 +4213,24 @@
* @return The case structure where the child node belongs to, NULL in case of error. Note that the child is not connected into the siblings list,
* it is linked from the case structure only in case it is its first child.
*/
-static struct lysc_node_case *
-lys_compile_node_case(struct lysc_ctx *ctx, struct lysp_node *node_p, struct lysc_node_choice *ch, struct lysc_node *child)
+static LY_ERR
+lys_compile_node_case(struct lysc_ctx *ctx, struct lysp_node *node_p, struct lysc_node *node)
{
- struct lysc_node *iter;
- struct lysc_node_case *cs = NULL;
- struct lysc_when **when;
- LY_ARRAY_COUNT_TYPE u;
- LY_ERR ret;
-
-#define UNIQUE_CHECK(NAME, MOD) \
- LY_LIST_FOR((struct lysc_node*)ch->cases, iter) { \
- if (iter->module == MOD && !strcmp(iter->name, NAME)) { \
- LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_DUPIDENT, NAME, "case"); \
- return NULL; \
- } \
- }
+ struct lysp_node *child_p;
+ struct lysp_node_case *cs_p = (struct lysp_node_case *)node_p;
if (node_p->nodetype & (LYS_CHOICE | LYS_AUGMENT | LYS_GROUPING)) {
- UNIQUE_CHECK(child->name, ctx->mod);
-
/* we have to add an implicit case node into the parent choice */
- cs = calloc(1, sizeof(struct lysc_node_case));
- DUP_STRING(ctx->ctx, child->name, cs->name);
- cs->parent = (struct lysc_node *)ch;
- cs->flags = ch->flags & LYS_STATUS_MASK;
} else if (node_p->nodetype == LYS_CASE) {
- if (ch->cases && (node_p == ch->cases->prev->sp)) {
- /* the case is already present since the child is not its first children */
- return (struct lysc_node_case *)ch->cases->prev;
+ /* explicit parent case */
+ LY_LIST_FOR(cs_p->child, child_p) {
+ LY_CHECK_RET(lys_compile_node(ctx, child_p, node, 0));
}
- UNIQUE_CHECK(node_p->name, ctx->mod);
-
- /* explicit parent case is not present (this is its first child) */
- cs = calloc(1, sizeof(struct lysc_node_case));
- DUP_STRING(ctx->ctx, node_p->name, cs->name);
- cs->parent = (struct lysc_node *)ch;
- cs->flags = LYS_STATUS_MASK & node_p->flags;
- cs->sp = node_p;
-
- /* check the case's status (don't need to solve uses_status since case statement cannot be directly in grouping statement */
- LY_CHECK_GOTO(lys_compile_status(ctx, &cs->flags, ch->flags), error);
-
- if (node_p->when) {
- LY_ARRAY_NEW_GOTO(ctx->ctx, cs->when, when, ret, error);
- ret = lys_compile_when(ctx, node_p->when, node_p->flags, (struct lysc_node *)cs, when);
- LY_CHECK_GOTO(ret, error);
-
- if (!(ctx->options & LYSC_OPT_GROUPING)) {
- /* do not check "when" semantics in a grouping */
- ret = ly_set_add(&ctx->xpath, cs, 0, NULL);
- LY_CHECK_GOTO(ret, error);
- }
- }
- COMPILE_ARRAY_GOTO(ctx, node_p->iffeatures, cs->iffeatures, u, lys_compile_iffeature, ret, error);
} else {
- LOGINT(ctx->ctx);
- goto error;
+ LOGINT_RET(ctx->ctx);
}
- cs->module = ctx->mod;
- cs->prev = (struct lysc_node *)cs;
- cs->nodetype = LYS_CASE;
- lys_compile_node_connect(ctx, (struct lysc_node *)ch, (struct lysc_node *)cs);
- cs->child = child;
- return cs;
-error:
- if (cs) {
- lysc_node_free(ctx->ctx, (struct lysc_node *)cs);
- }
- return NULL;
-
-#undef UNIQUE_CHECK
+ return LY_SUCCESS;
}
/**
@@ -4378,7 +4422,7 @@
lys_compile_augment(struct lysc_ctx *ctx, struct lysp_augment *aug_p, const struct lysc_node *parent)
{
LY_ERR ret = LY_SUCCESS, rc;
- struct lysp_node *node_p, *case_node_p;
+ struct lysp_node *node_p;
struct lysc_node *target; /* target target of the augment */
struct lysc_node *node;
struct lysc_when **when, *when_shared;
@@ -4426,12 +4470,10 @@
/* compile the children */
ctx->options |= flags;
- if (node_p->nodetype != LYS_CASE) {
- LY_CHECK_RET(lys_compile_node(ctx, node_p, target, 0));
+ if (target->nodetype == LYS_CHOICE) {
+ LY_CHECK_RET(lys_compile_node_choice_child(ctx, node_p, target));
} else {
- LY_LIST_FOR(((struct lysp_node_case *)node_p)->child, case_node_p) {
- LY_CHECK_RET(lys_compile_node(ctx, case_node_p, target, 0));
- }
+ LY_CHECK_RET(lys_compile_node(ctx, node_p, target, 0));
}
ctx->options = opt_prev;
@@ -4627,7 +4669,7 @@
size_t prefix_len, name_len;
struct lys_module *mod, *mod_old;
struct lysp_refine *rfn;
- LY_ERR rc, ret = LY_EVALID;
+ LY_ERR ret = LY_SUCCESS;
uint32_t min, max;
uint16_t flags;
struct ly_set refined = {0};
@@ -4713,7 +4755,8 @@
ctx->mod_def = mod;
/* check status */
- LY_CHECK_GOTO(lysc_check_status(ctx, uses_p->flags, mod_old, uses_p->name, grp->flags, mod, grp->name), cleanup);
+ ret = lysc_check_status(ctx, uses_p->flags, mod_old, uses_p->name, grp->flags, mod, grp->name);
+ LY_CHECK_GOTO(ret, cleanup);
/* remember the currently last child before processing the uses - it is needed to split the siblings to corretly
* applu refine and augment only to the nodes from the uses */
@@ -4736,7 +4779,8 @@
/* compile data nodes */
LY_LIST_FOR(grp->data, node_p) {
/* 0x3 in uses_status is a special bits combination to be able to detect status flags from uses */
- LY_CHECK_GOTO(lys_compile_node(ctx, node_p, parent, (uses_p->flags & LYS_STATUS_MASK) | 0x3), cleanup);
+ ret = lys_compile_node(ctx, node_p, parent, (uses_p->flags & LYS_STATUS_MASK) | 0x3);
+ LY_CHECK_GOTO(ret, cleanup);
}
/* split the children and add the uses's data into the fake context node */
@@ -4761,12 +4805,13 @@
if (uses_p->when) {
LY_ARRAY_NEW_GOTO(ctx->ctx, iter->when, when, ret, cleanup);
if (!when_shared) {
- LY_CHECK_GOTO(lys_compile_when(ctx, uses_p->when, uses_p->flags, parent, when), cleanup);
+ ret = lys_compile_when(ctx, uses_p->when, uses_p->flags, parent, when);
+ LY_CHECK_GOTO(ret, cleanup);
if (!(ctx->options & LYSC_OPT_GROUPING)) {
/* do not check "when" semantics in a grouping */
- rc = ly_set_add(&ctx->xpath, iter, 0, NULL);
- LY_CHECK_ERR_GOTO(rc, ret = rc, cleanup);
+ ret = ly_set_add(&ctx->xpath, iter, 0, NULL);
+ LY_CHECK_GOTO(ret, cleanup);
}
when_shared = *when;
@@ -4776,8 +4821,8 @@
if (!(ctx->options & LYSC_OPT_GROUPING)) {
/* in this case check "when" again for all children because of dummy node check */
- rc = ly_set_add(&ctx->xpath, iter, 0, NULL);
- LY_CHECK_ERR_GOTO(rc, ret = rc, cleanup);
+ ret = ly_set_add(&ctx->xpath, iter, 0, NULL);
+ LY_CHECK_GOTO(ret, cleanup);
}
}
}
@@ -4810,9 +4855,11 @@
}
/* sort and apply augments */
- LY_CHECK_GOTO(lys_compile_augment_sort(ctx, uses_p->augments, NULL, &augments), cleanup);
+ ret = lys_compile_augment_sort(ctx, uses_p->augments, NULL, &augments);
+ LY_CHECK_GOTO(ret, cleanup);
LY_ARRAY_FOR(augments, u) {
- LY_CHECK_GOTO(lys_compile_augment(ctx, augments[u], (struct lysc_node *)&context_node_fake), cleanup);
+ ret = lys_compile_augment(ctx, augments[u], (struct lysc_node *)&context_node_fake);
+ LY_CHECK_GOTO(ret, cleanup);
}
/* reload previous context's mod_def */
@@ -4823,11 +4870,11 @@
LY_ARRAY_FOR(uses_p->refines, struct lysp_refine, rfn) {
lysc_update_path(ctx, NULL, rfn->nodeid);
- LY_CHECK_GOTO(lysc_resolve_schema_nodeid(ctx, rfn->nodeid, 0, (struct lysc_node *)&context_node_fake, ctx->mod,
- 0, 0, (const struct lysc_node **)&node, &flags),
- cleanup);
- rc = ly_set_add(&refined, node, LY_SET_OPT_USEASLIST, NULL);
- LY_CHECK_ERR_GOTO(rc, ret = rc, cleanup);
+ ret = lysc_resolve_schema_nodeid(ctx, rfn->nodeid, 0, (struct lysc_node *)&context_node_fake, ctx->mod,
+ 0, 0, (const struct lysc_node **)&node, &flags);
+ LY_CHECK_GOTO(ret, cleanup);
+ ret = ly_set_add(&refined, node, LY_SET_OPT_USEASLIST, NULL);
+ LY_CHECK_GOTO(ret, cleanup);
/* default value */
if (rfn->dflts) {
@@ -4835,36 +4882,42 @@
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
"Invalid refine of default - %s cannot hold %"LY_PRI_ARRAY_COUNT_TYPE " default values.",
lys_nodetype2str(node->nodetype), LY_ARRAY_COUNT(rfn->dflts));
+ ret = LY_EVALID;
goto cleanup;
}
if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE))) {
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
"Invalid refine of default - %s cannot hold default value(s).",
lys_nodetype2str(node->nodetype));
+ ret = LY_EVALID;
goto cleanup;
}
if (node->nodetype == LYS_LEAF) {
/* postpone default compilation when the tree is complete */
- LY_CHECK_GOTO(lysc_incomplete_leaf_dflt_add(ctx, (struct lysc_node_leaf *)node, rfn->dflts[0],
- ctx->mod_def), cleanup);
+ ret = lysc_incomplete_leaf_dflt_add(ctx, (struct lysc_node_leaf *)node, rfn->dflts[0], ctx->mod_def);
+ LY_CHECK_GOTO(ret, cleanup);
+
node->flags |= LYS_SET_DFLT;
} else if (node->nodetype == LYS_LEAFLIST) {
if (ctx->mod->version < 2) {
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
"Invalid refine of default in leaf-list - the default statement is allowed only in YANG 1.1 modules.");
+ ret = LY_EVALID;
goto cleanup;
}
/* postpone default compilation when the tree is complete */
- LY_CHECK_GOTO(lysc_incomplete_llist_dflts_add(ctx, (struct lysc_node_leaflist *)node, rfn->dflts,
- ctx->mod_def), cleanup);
+ ret = lysc_incomplete_llist_dflts_add(ctx, (struct lysc_node_leaflist *)node, rfn->dflts, ctx->mod_def);
+ LY_CHECK_GOTO(ret, cleanup);
+
node->flags |= LYS_SET_DFLT;
} else if (node->nodetype == LYS_CHOICE) {
if (((struct lysc_node_choice *)node)->dflt) {
/* unset LYS_SET_DFLT from the current default case */
((struct lysc_node_choice *)node)->dflt->flags &= ~LYS_SET_DFLT;
}
- LY_CHECK_GOTO(lys_compile_node_choice_dflt(ctx, rfn->dflts[0], (struct lysc_node_choice *)node), cleanup);
+ ret = lys_compile_node_choice_dflt(ctx, rfn->dflts[0], (struct lysc_node_choice *)node);
+ LY_CHECK_GOTO(ret, cleanup);
}
}
@@ -4883,7 +4936,8 @@
/* config */
if (rfn->flags & LYS_CONFIG_MASK) {
if (!flags) {
- LY_CHECK_GOTO(lys_compile_change_config(ctx, node, rfn->flags, 0, 1), cleanup);
+ ret = lys_compile_change_config(ctx, node, rfn->flags, 0, 1);
+ LY_CHECK_GOTO(ret, cleanup);
} else {
LOGWRN(ctx->ctx, "Refining config inside %s has no effect (%s).",
flags & LYSC_OPT_NOTIFICATION ? "notification" : "RPC/action", ctx->path);
@@ -4892,7 +4946,8 @@
/* mandatory */
if (rfn->flags & LYS_MAND_MASK) {
- LY_CHECK_GOTO(lys_compile_change_mandatory(ctx, node, rfn->flags, 1), cleanup);
+ ret = lys_compile_change_mandatory(ctx, node, rfn->flags, 1);
+ LY_CHECK_GOTO(ret, cleanup);
}
/* presence */
@@ -4901,6 +4956,7 @@
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
"Invalid refine of presence statement - %s cannot hold the presence statement.",
lys_nodetype2str(node->nodetype));
+ ret = LY_EVALID;
goto cleanup;
}
node->flags |= LYS_PRESENCE;
@@ -4929,10 +4985,11 @@
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
"Invalid refine of must statement - %s cannot hold any must statement.",
lys_nodetype2str(node->nodetype));
+ ret = LY_EVALID;
goto cleanup;
}
- rc = ly_set_add(&ctx->xpath, node, 0, NULL);
- LY_CHECK_ERR_GOTO(rc, ret = rc, cleanup);
+ ret = ly_set_add(&ctx->xpath, node, 0, NULL);
+ LY_CHECK_GOTO(ret, cleanup);
}
/* min/max-elements */
@@ -4972,6 +5029,7 @@
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
"Invalid refine of %s statement - %s cannot hold this statement.",
(rfn->flags & LYS_SET_MAX) ? "max-elements" : "min-elements", lys_nodetype2str(node->nodetype));
+ ret = LY_EVALID;
goto cleanup;
}
}
@@ -4997,6 +5055,7 @@
((node->nodetype & LYS_LEAF) && (node->flags & LYS_SET_DFLT)))) {
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
"Invalid refine of default - the node is mandatory.");
+ ret = LY_EVALID;
goto cleanup;
}
@@ -5012,6 +5071,7 @@
LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
"Invalid refine of %s statement - \"min-elements\" is bigger than \"max-elements\".",
(rfn->flags & LYS_SET_MAX) ? "max-elements" : "min-elements");
+ ret = LY_EVALID;
goto cleanup;
}
}
@@ -5021,7 +5081,6 @@
*first_p = context_node_fake.child;
}
lysc_update_path(ctx, NULL, NULL);
- ret = LY_SUCCESS;
cleanup:
/* fix connection of the children nodes from fake context node back into the parent */
@@ -5163,6 +5222,59 @@
}
/**
+ * @brief Set config flags for a node.
+ *
+ * @param[in] ctx Compile context.
+ * @param[in] node Compiled node config to set.
+ * @param[in] parent Parent of @p node.
+ * @return LY_ERR value.
+ */
+static LY_ERR
+lys_compile_config(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc_node *parent)
+{
+ if (node->nodetype == LYS_CASE) {
+ /* case never has any config */
+ assert(!(node->flags & LYS_CONFIG_MASK));
+ return LY_SUCCESS;
+ }
+
+ /* adjust parent to always get the ancestor with config */
+ if (parent && (parent->nodetype == LYS_CASE)) {
+ parent = parent->parent;
+ assert(parent);
+ }
+
+ if (ctx->options & (LYSC_OPT_RPC_INPUT | LYSC_OPT_RPC_OUTPUT)) {
+ /* ignore config statements inside RPC/action data */
+ node->flags &= ~LYS_CONFIG_MASK;
+ node->flags |= (ctx->options & LYSC_OPT_RPC_INPUT) ? LYS_CONFIG_W : LYS_CONFIG_R;
+ } else if (ctx->options & LYSC_OPT_NOTIFICATION) {
+ /* ignore config statements inside Notification data */
+ node->flags &= ~LYS_CONFIG_MASK;
+ node->flags |= LYS_CONFIG_R;
+ } else if (!(node->flags & LYS_CONFIG_MASK)) {
+ /* config not explicitely set, inherit it from parent */
+ if (parent) {
+ node->flags |= parent->flags & LYS_CONFIG_MASK;
+ } else {
+ /* default is config true */
+ node->flags |= LYS_CONFIG_W;
+ }
+ } else {
+ /* config set explicitely */
+ node->flags |= LYS_SET_CONFIG;
+ }
+
+ if (parent && (parent->flags & LYS_CONFIG_R) && (node->flags & LYS_CONFIG_W)) {
+ LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
+ "Configuration node cannot be child of any state data node.");
+ return LY_EVALID;
+ }
+
+ return LY_SUCCESS;
+}
+
+/**
* @brief Compile parsed schema node information.
* @param[in] ctx Compile context
* @param[in] node_p Parsed schema node.
@@ -5211,24 +5323,17 @@
node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_choice));
node_compile_spec = lys_compile_node_choice;
break;
+ case LYS_CASE:
+ node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_case));
+ node_compile_spec = lys_compile_node_case;
+ break;
case LYS_ANYXML:
case LYS_ANYDATA:
node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_anydata));
node_compile_spec = lys_compile_node_any;
break;
case LYS_USES:
- if (parent && parent->nodetype == LYS_CHOICE) {
- assert(node_p->parent->nodetype == LYS_CASE);
- lysc_update_path(ctx, parent, node_p->parent->name);
- cs = lys_compile_node_case(ctx, node_p->parent, (struct lysc_node_choice *)parent, NULL);
- LY_CHECK_ERR_GOTO(!cs, ret = LY_EVALID, error);
- }
-
ret = lys_compile_uses(ctx, (struct lysp_node_uses *)node_p, cs ? (struct lysc_node *)cs : parent, &node);
- if (cs) {
- cs->child = node;
- lysc_update_path(ctx, NULL, NULL);
- }
lysc_update_path(ctx, NULL, NULL);
lysc_update_path(ctx, NULL, NULL);
return ret;
@@ -5243,34 +5348,10 @@
node->flags = node_p->flags & LYS_FLAGS_COMPILED_MASK;
/* config */
- if (ctx->options & (LYSC_OPT_RPC_INPUT | LYSC_OPT_RPC_OUTPUT)) {
- /* ignore config statements inside RPC/action data */
- node->flags &= ~LYS_CONFIG_MASK;
- node->flags |= (ctx->options & LYSC_OPT_RPC_INPUT) ? LYS_CONFIG_W : LYS_CONFIG_R;
- } else if (ctx->options & LYSC_OPT_NOTIFICATION) {
- /* ignore config statements inside Notification data */
- node->flags &= ~LYS_CONFIG_MASK;
- node->flags |= LYS_CONFIG_R;
- } else if (!(node->flags & LYS_CONFIG_MASK)) {
- /* config not explicitely set, inherit it from parent */
- if (parent) {
- node->flags |= parent->flags & LYS_CONFIG_MASK;
- } else {
- /* default is config true */
- node->flags |= LYS_CONFIG_W;
- }
- } else {
- /* config set explicitely */
- node->flags |= LYS_SET_CONFIG;
- }
- if (parent && (parent->flags & LYS_CONFIG_R) && (node->flags & LYS_CONFIG_W)) {
- LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
- "Configuration node cannot be child of any state data node.");
- ret = LY_EVALID;
- goto error;
- }
+ ret = lys_compile_config(ctx, node, parent);
+ LY_CHECK_GOTO(ret, error);
- /* *list ordering */
+ /* list ordering */
if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
if ((node->flags & LYS_CONFIG_R) && (node->flags & LYS_ORDBY_MASK)) {
LOGWRN(ctx->ctx, "The ordered-by statement is ignored in lists representing %s (%s).",
@@ -5286,11 +5367,7 @@
/* status - it is not inherited by specification, but it does not make sense to have
* current in deprecated or deprecated in obsolete, so we do print warning and inherit status */
- if (!parent || parent->nodetype != LYS_CHOICE) {
- /* in case of choice/case's children, postpone the check to the moment we know if
- * the parent is choice (parent here) or some case (so we have to get its flags to check) */
- LY_CHECK_GOTO(ret = lys_compile_status(ctx, &node->flags, uses_status ? uses_status : (parent ? parent->flags : 0)), error);
- }
+ LY_CHECK_GOTO(ret = lys_compile_status(ctx, &node->flags, uses_status ? uses_status : (parent ? parent->flags : 0)), error);
if (!(ctx->options & LYSC_OPT_FREE_SP)) {
node->sp = node_p;
@@ -5310,145 +5387,48 @@
}
COMPILE_ARRAY_GOTO(ctx, node_p->iffeatures, node->iffeatures, u, lys_compile_iffeature, ret, error);
+ /* insert into parent's children/compiled module (we can no longer free the node separately on error) */
+ LY_CHECK_RET(lys_compile_node_connect(ctx, parent, node));
+
/* nodetype-specific part */
- LY_CHECK_GOTO(ret = node_compile_spec(ctx, node_p, node), error);
+ LY_CHECK_RET(node_compile_spec(ctx, node_p, node));
- COMPILE_EXTS_GOTO(ctx, node_p->exts, node->exts, node, LYEXT_PAR_NODE, ret, error);
-
- /* inherit LYS_MAND_TRUE in parent containers */
+ /* final compilation tasks that require the node to be connected */
+ COMPILE_EXTS_GOTO(ctx, node_p->exts, node->exts, node, LYEXT_PAR_NODE, ret, done);
if (node->flags & LYS_MAND_TRUE) {
+ /* inherit LYS_MAND_TRUE in parent containers */
lys_compile_mandatory_parents(parent, 1);
}
lysc_update_path(ctx, NULL, NULL);
-
- /* insert into parent's children */
- if (parent) {
- if (parent->nodetype == LYS_CHOICE) {
- if (node_p->parent->nodetype == LYS_CASE) {
- lysc_update_path(ctx, parent, node_p->parent->name);
- } else {
- lysc_update_path(ctx, parent, node->name);
- }
- cs = lys_compile_node_case(ctx, node_p->parent, (struct lysc_node_choice *)parent, node);
- LY_CHECK_ERR_GOTO(!cs, ret = LY_EVALID, error);
- if (uses_status) {}
- /* the postponed status check of the node and its real parent - in case of implicit case,
- * it directly gets the same status flags as the choice;
- * uses_status cannot be applied here since uses cannot be child statement of choice */
- LY_CHECK_GOTO(ret = lys_compile_status(ctx, &node->flags, cs->flags), error);
- node->parent = (struct lysc_node *)cs;
- lysc_update_path(ctx, parent, node->name);
- } else { /* other than choice */
- lysc_update_path(ctx, parent, node->name);
- node->parent = parent;
- }
- LY_CHECK_RET(lys_compile_node_connect(ctx, parent->nodetype == LYS_CASE ? parent->parent : parent, node), LY_EVALID);
-
- if (parent->nodetype == LYS_CHOICE) {
- lysc_update_path(ctx, NULL, NULL);
- }
- } else {
- /* top-level element */
- if (!ctx->mod->compiled->data) {
- ctx->mod->compiled->data = node;
- } else {
- /* insert at the end of the module's top-level nodes list */
- ctx->mod->compiled->data->prev->next = node;
- node->prev = ctx->mod->compiled->data->prev;
- ctx->mod->compiled->data->prev = node;
- }
- lysc_update_path(ctx, parent, node->name);
- if (lys_compile_node_uniqness(ctx, ctx->mod->compiled->data, ctx->mod->compiled->rpcs,
- ctx->mod->compiled->notifs, node->name, node)) {
- return LY_EVALID;
- }
- }
- lysc_update_path(ctx, NULL, NULL);
-
return LY_SUCCESS;
error:
lysc_node_free(ctx->ctx, node);
+done:
return ret;
}
static void
-lysc_disconnect(struct lysc_node *node)
+lysc_node_unlink(struct lysc_node *node)
{
- struct lysc_node *parent, *child, *prev = NULL, *next;
- struct lysc_node_case *cs = NULL;
+ struct lysc_node *parent, *child;
struct lysc_module *modc = node->module->compiled;
- uint8_t remove_cs = 0;
parent = node->parent;
/* parent's first child */
- if (parent && parent->nodetype == LYS_CHOICE) {
- cs = (struct lysc_node_case *)node;
- } else if (parent && parent->nodetype == LYS_CASE) {
- /* disconnecting some node in a case */
- cs = (struct lysc_node_case *)parent;
- parent = cs->parent;
- for (child = cs->child; child && child->parent == (struct lysc_node *)cs; child = child->next) {
- if (child == node) {
- if (cs->child == child) {
- if (!child->next || child->next->parent != (struct lysc_node *)cs) {
- /* case with a single child -> remove also the case */
- child->parent = NULL;
- remove_cs = 1;
- } else {
- cs->child = child->next;
- }
- }
- break;
- }
- }
- if (!remove_cs) {
- cs = NULL;
- }
- } else if (parent && lysc_node_children(parent, node->flags) == node) {
+ if (parent && lysc_node_children(parent, node->flags) == node) {
*lysc_node_children_p(parent, node->flags) = node->next;
} else if (modc->data == node) {
modc->data = node->next;
}
- if (cs) {
- if (remove_cs) {
- /* cs has only one child which is being also removed */
- lysc_disconnect((struct lysc_node *)cs);
- lysc_node_free(cs->module->ctx, (struct lysc_node *)cs);
- } else {
- if (((struct lysc_node_choice *)parent)->dflt == cs) {
- /* default case removed */
- ((struct lysc_node_choice *)parent)->dflt = NULL;
- }
- if (((struct lysc_node_choice *)parent)->cases == cs) {
- /* first case removed */
- ((struct lysc_node_choice *)parent)->cases = (struct lysc_node_case *)cs->next;
- }
- if (cs->child) {
- /* cs will be removed and disconnected from its siblings, but we have to take care also about its children */
- if (cs->child->prev->parent != (struct lysc_node *)cs) {
- prev = cs->child->prev;
- } /* else all the children are under a single case */
- LY_LIST_FOR_SAFE(cs->child, next, child) {
- if (child->parent != (struct lysc_node *)cs) {
- break;
- }
- lysc_node_free(node->module->ctx, child);
- }
- if (prev) {
- if (prev->next) {
- prev->next = child;
- }
- if (child) {
- child->prev = prev;
- } else {
- /* link from the first child under the cases */
- ((struct lysc_node_choice *)cs->parent)->cases->child->prev = prev;
- }
- }
- }
+
+ /* special choice case unlinking */
+ if (parent && parent->nodetype == LYS_CHOICE) {
+ if (((struct lysc_node_choice *)parent)->dflt == (struct lysc_node_case *)node) {
+ /* default case removed */
+ ((struct lysc_node_choice *)parent)->dflt = NULL;
}
}
@@ -5458,7 +5438,8 @@
}
if (node->next) {
node->next->prev = node->prev;
- } else if (node->nodetype != LYS_CASE) {
+ } else {
+ /* last child */
if (parent) {
child = (struct lysc_node *)lysc_node_children(parent, node->flags);
} else {
@@ -5467,8 +5448,6 @@
if (child) {
child->prev = node->prev;
}
- } else if (((struct lysc_node_choice *)parent)->cases) {
- ((struct lysc_node_choice *)parent)->cases->prev = node->prev;
}
}
@@ -6372,9 +6351,15 @@
/* remove Notification */
REMOVE_NONDATA(notifs, struct lysc_notif, lysc_node_notifs, lysc_notif_free);
} else {
- /* remove the target node */
- lysc_disconnect(target);
- lysc_node_free(ctx->ctx, target);
+ if (target->parent && (target->parent->nodetype == LYS_CASE) && (target->prev == target)) {
+ /* remove the target node with its parent case node because it is the only node of the case */
+ lysc_node_unlink(target->parent);
+ lysc_node_free(ctx->ctx, target->parent);
+ } else {
+ /* remove the target node */
+ lysc_node_unlink(target);
+ lysc_node_free(ctx->ctx, target);
+ }
}
/* mark the context for later re-compilation of objects that could reference the curently removed node */
diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c
index 062b993..62339fd 100644
--- a/src/tree_schema_free.c
+++ b/src/tree_schema_free.c
@@ -26,7 +26,6 @@
#include "xpath.h"
void lysp_grp_free(struct ly_ctx *ctx, struct lysp_grp *grp);
-void lysp_node_free(struct ly_ctx *ctx, struct lysp_node *node);
void lysc_extension_free(struct ly_ctx *ctx, struct lysc_ext **ext);
static void
@@ -759,13 +758,18 @@
{
struct lysc_node *child, *child_next;
- if (node->cases) {
- LY_LIST_FOR_SAFE(node->cases->child, child_next, child) {
- lysc_node_free(ctx, child);
- }
- LY_LIST_FOR_SAFE((struct lysc_node *)node->cases, child_next, child) {
- lysc_node_free(ctx, child);
- }
+ LY_LIST_FOR_SAFE((struct lysc_node *)node->cases, child_next, child) {
+ lysc_node_free(ctx, child);
+ }
+}
+
+static void
+lysc_node_case_free(struct ly_ctx *ctx, struct lysc_node_case *node)
+{
+ struct lysc_node *child, *child_next;
+
+ LY_LIST_FOR_SAFE(node->child, child_next, child) {
+ lysc_node_free(ctx, child);
}
}
@@ -801,7 +805,7 @@
lysc_node_choice_free(ctx, (struct lysc_node_choice *)node);
break;
case LYS_CASE:
- /* nothing specific */
+ lysc_node_case_free(ctx, (struct lysc_node_case *)node);
break;
case LYS_ANYDATA:
case LYS_ANYXML:
diff --git a/src/tree_schema_helpers.c b/src/tree_schema_helpers.c
index 0623dbd..f239fe1 100644
--- a/src/tree_schema_helpers.c
+++ b/src/tree_schema_helpers.c
@@ -1358,11 +1358,7 @@
case LYS_CONTAINER:
return &((struct lysc_node_container *)node)->child;
case LYS_CHOICE:
- if (((struct lysc_node_choice *)node)->cases) {
- return &((struct lysc_node_choice *)node)->cases->child;
- } else {
- return NULL;
- }
+ return (struct lysc_node **)&((struct lysc_node_choice *)node)->cases;
case LYS_CASE:
return &((struct lysc_node_case *)node)->child;
case LYS_LIST:
diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h
index e0b46b3..86ec511 100644
--- a/src/tree_schema_internal.h
+++ b/src/tree_schema_internal.h
@@ -652,6 +652,14 @@
LY_ERR lysp_stmt_parse(struct lysc_ctx *ctx, const struct lysp_stmt *stmt, enum ly_stmt kw, void **result, struct lysp_ext_instance **exts);
/**
+ * @brief Free a parsed node.
+ *
+ * @param[in] ctx libyang context.
+ * @param[in] node Node to free.
+ */
+void lysp_node_free(struct ly_ctx *ctx, struct lysp_node *node);
+
+/**
* @brief Free the compiled type structure.
* @param[in] ctx libyang context where the string data resides in a dictionary.
* @param[in,out] type Compiled type structure to be freed. The structure has refcount, so it is freed only in case the value is decreased to 0.
diff --git a/tests/utests/schema/test_tree_schema_compile.c b/tests/utests/schema/test_tree_schema_compile.c
index cf30cdc..396f3b8 100644
--- a/tests/utests/schema/test_tree_schema_compile.c
+++ b/tests/utests/schema/test_tree_schema_compile.c
@@ -152,7 +152,7 @@
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_SUCCESS, lys_parse_mem_module(ctx, in, LYS_IN_YANG, 1, NULL, NULL, &mod));
ly_in_free(in, 0);
- assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
+ assert_int_equal(LY_EEXIST, lys_compile(&mod, 0));
logbuf_assert("Duplicate identifier \"a\" of data definition/RPC/action/notification statement. /aa:a");
assert_null(mod);
@@ -161,6 +161,88 @@
}
static void
+test_name_collisions(void **state)
+{
+ (void) state; /* unused */
+
+ struct ly_ctx *ctx;
+ const char *yang_data;
+
+ assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+ /* top-level */
+ yang_data = "module a {namespace urn:a;prefix a;"
+ "container c;"
+ "leaf a {type empty;}"
+ "leaf c {type empty;}"
+ "}";
+ assert_int_equal(LY_EEXIST, lys_parse_mem(ctx, yang_data, LYS_IN_YANG, NULL));
+ logbuf_assert("Duplicate identifier \"c\" of data definition/RPC/action/notification statement. /a:c");
+ logbuf_clean();
+
+ yang_data = "module a {namespace urn:a;prefix a;"
+ "container c;"
+ "leaf a {type empty;}"
+ "notification c;"
+ "}";
+ assert_int_equal(LY_EEXIST, lys_parse_mem(ctx, yang_data, LYS_IN_YANG, NULL));
+ logbuf_assert("Duplicate identifier \"c\" of data definition/RPC/action/notification statement. /a:c");
+ logbuf_clean();
+
+ yang_data = "module a {namespace urn:a;prefix a;"
+ "container c;"
+ "leaf a {type empty;}"
+ "rpc c;"
+ "}";
+ assert_int_equal(LY_EEXIST, lys_parse_mem(ctx, yang_data, LYS_IN_YANG, NULL));
+ logbuf_assert("Duplicate identifier \"c\" of data definition/RPC/action/notification statement. /a:c");
+ logbuf_clean();
+
+ yang_data = "module a {namespace urn:a;prefix a;"
+ "container c;"
+ "leaf a {type empty;}"
+ "choice ch {"
+ "leaf c {type string;}"
+ "case c2 {"
+ "leaf aa {type empty;}"
+ "}"
+ "}"
+ "}";
+ assert_int_equal(LY_EEXIST, lys_parse_mem(ctx, yang_data, LYS_IN_YANG, NULL));
+ logbuf_assert("Duplicate identifier \"c\" of data definition/RPC/action/notification statement. /a:ch/c/c");
+ logbuf_clean();
+
+ /* nested */
+ yang_data = "module a {namespace urn:a;prefix a;container c { list l {key \"k\"; leaf k {type string;}"
+ "leaf-list a {type string;}"
+ "container a;"
+ "}}}";
+ assert_int_equal(LY_EEXIST, lys_parse_mem(ctx, yang_data, LYS_IN_YANG, NULL));
+ logbuf_assert("Duplicate identifier \"a\" of data definition/RPC/action/notification statement. /a:c/l/a");
+ logbuf_clean();
+
+ yang_data = "module a {yang-version 1.1;namespace urn:a;prefix a;container c { list l {key \"k\"; leaf k {type string;}"
+ "leaf-list a {type string;}"
+ "notification a;"
+ "}}}";
+ assert_int_equal(LY_EEXIST, lys_parse_mem(ctx, yang_data, LYS_IN_YANG, NULL));
+ logbuf_assert("Duplicate identifier \"a\" of data definition/RPC/action/notification statement. /a:c/l/a");
+ logbuf_clean();
+
+ yang_data = "module a {yang-version 1.1;namespace urn:a;prefix a;container c { list l {key \"k\"; leaf k {type string;}"
+ "leaf-list a {type string;}"
+ "action a;"
+ "}}}";
+ assert_int_equal(LY_EEXIST, lys_parse_mem(ctx, yang_data, LYS_IN_YANG, NULL));
+ logbuf_assert("Duplicate identifier \"a\" of data definition/RPC/action/notification statement. /a:c/l/a");
+ logbuf_clean();
+
+ /* grouping */
+
+ ly_ctx_destroy(ctx, NULL);
+}
+
+static void
test_node_container(void **state)
{
(void) state; /* unused */
@@ -490,21 +572,18 @@
assert_non_null(cs->child);
assert_string_equal("b", cs->child->name);
assert_ptr_equal(cs, cs->child->parent);
- assert_ptr_equal(ch->cases->child->next, cs->child->prev);
- assert_ptr_equal(ch->cases->child->next->next, cs->child);
- assert_ptr_equal(ch->cases->child->prev, cs->child);
assert_ptr_equal(ch->dflt, cs);
- assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;"
+ assert_int_equal(LY_EEXIST, lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;"
"choice ch {case a {leaf x {type string;}}leaf x {type string;}}}", LYS_IN_YANG, NULL));
logbuf_assert("Duplicate identifier \"x\" of data definition/RPC/action/notification statement. /aa:ch/x/x");
- assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module aa2 {namespace urn:aa2;prefix aa;"
+ assert_int_equal(LY_EEXIST, lys_parse_mem(ctx, "module aa2 {namespace urn:aa2;prefix aa;"
"choice ch {case a {leaf y {type string;}}case b {leaf y {type string;}}}}", LYS_IN_YANG, NULL));
logbuf_assert("Duplicate identifier \"y\" of data definition/RPC/action/notification statement. /aa2:ch/b/y");
- assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;"
+ assert_int_equal(LY_EEXIST, lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;"
"choice ch {case a {leaf x {type string;}}leaf a {type string;}}}", LYS_IN_YANG, NULL));
logbuf_assert("Duplicate identifier \"a\" of case statement. /bb:ch/a");
- assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module bb2 {namespace urn:bb2;prefix bb;"
+ assert_int_equal(LY_EEXIST, lys_parse_mem(ctx, "module bb2 {namespace urn:bb2;prefix bb;"
"choice ch {case b {leaf x {type string;}}case b {leaf y {type string;}}}}", LYS_IN_YANG, NULL));
logbuf_assert("Duplicate identifier \"b\" of case statement. /bb2:ch/b");
@@ -595,15 +674,15 @@
LYS_IN_YANG, NULL));
logbuf_assert("Invalid keyword \"action\" as a child of \"container\" - the statement is allowed only in YANG 1.1 modules. Line number 1.");
- assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;leaf x{type string;} rpc x;}",
+ assert_int_equal(LY_EEXIST, lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;leaf x{type string;} rpc x;}",
LYS_IN_YANG, NULL));
logbuf_assert("Duplicate identifier \"x\" of data definition/RPC/action/notification statement. /bb:x");
- assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module cc {yang-version 1.1; namespace urn:cc;prefix cc;container c {leaf y {type string;} action y;}}", LYS_IN_YANG, NULL));
+ assert_int_equal(LY_EEXIST, lys_parse_mem(ctx, "module cc {yang-version 1.1; namespace urn:cc;prefix cc;container c {leaf y {type string;} action y;}}", LYS_IN_YANG, NULL));
logbuf_assert("Duplicate identifier \"y\" of data definition/RPC/action/notification statement. /cc:c/y");
- assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module dd {yang-version 1.1; namespace urn:dd;prefix dd;container c {action z; action z;}}", LYS_IN_YANG, NULL));
+ assert_int_equal(LY_EEXIST, lys_parse_mem(ctx, "module dd {yang-version 1.1; namespace urn:dd;prefix dd;container c {action z; action z;}}", LYS_IN_YANG, NULL));
logbuf_assert("Duplicate identifier \"z\" of data definition/RPC/action/notification statement. /dd:c/z");
ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule eesub {belongs-to ee {prefix ee;} notification w;}");
- assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module ee {yang-version 1.1; namespace urn:ee;prefix ee;include eesub; rpc w;}", LYS_IN_YANG, NULL));
+ assert_int_equal(LY_EEXIST, lys_parse_mem(ctx, "module ee {yang-version 1.1; namespace urn:ee;prefix ee;include eesub; rpc w;}", LYS_IN_YANG, NULL));
logbuf_assert("Duplicate identifier \"w\" of data definition/RPC/action/notification statement. /ee:w");
assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module ff {yang-version 1.1; namespace urn:ff;prefix ff; rpc test {input {container a {leaf b {type string;}}}}"
@@ -669,14 +748,14 @@
LYS_IN_YANG, NULL));
logbuf_assert("Invalid keyword \"notification\" as a child of \"container\" - the statement is allowed only in YANG 1.1 modules. Line number 1.");
- assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;leaf x{type string;} notification x;}", LYS_IN_YANG, NULL));
+ assert_int_equal(LY_EEXIST, lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;leaf x{type string;} notification x;}", LYS_IN_YANG, NULL));
logbuf_assert("Duplicate identifier \"x\" of data definition/RPC/action/notification statement. /bb:x");
- assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module cc {yang-version 1.1; namespace urn:cc;prefix cc;container c {leaf y {type string;} notification y;}}", LYS_IN_YANG, NULL));
+ assert_int_equal(LY_EEXIST, lys_parse_mem(ctx, "module cc {yang-version 1.1; namespace urn:cc;prefix cc;container c {leaf y {type string;} notification y;}}", LYS_IN_YANG, NULL));
logbuf_assert("Duplicate identifier \"y\" of data definition/RPC/action/notification statement. /cc:c/y");
- assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module dd {yang-version 1.1; namespace urn:dd;prefix dd;container c {notification z; notification z;}}", LYS_IN_YANG, NULL));
+ assert_int_equal(LY_EEXIST, lys_parse_mem(ctx, "module dd {yang-version 1.1; namespace urn:dd;prefix dd;container c {notification z; notification z;}}", LYS_IN_YANG, NULL));
logbuf_assert("Duplicate identifier \"z\" of data definition/RPC/action/notification statement. /dd:c/z");
ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule eesub {belongs-to ee {prefix ee;} rpc w;}");
- assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module ee {yang-version 1.1; namespace urn:ee;prefix ee;include eesub; notification w;}", LYS_IN_YANG, NULL));
+ assert_int_equal(LY_EEXIST, lys_parse_mem(ctx, "module ee {yang-version 1.1; namespace urn:ee;prefix ee;include eesub; notification w;}", LYS_IN_YANG, NULL));
logbuf_assert("Duplicate identifier \"w\" of data definition/RPC/action/notification statement. /ee:w");
assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module ff {yang-version 1.1; namespace urn:ff;prefix ff; rpc test {input {container a {leaf b {type string;}}}}"
@@ -2276,7 +2355,7 @@
assert_int_equal(LY_SUCCESS, lys_parse_mem(ctx, "module g {namespace urn:g;prefix g; grouping grp; uses grp;}", LYS_IN_YANG, &mod));
assert_null(mod->compiled->data);
- /* choise in uses */
+ /* choice in uses */
assert_int_equal(LY_SUCCESS, lys_parse_mem(ctx, "module h {yang-version 1.1;namespace urn:h;prefix h; grouping grp {choice gch {case gc1 { leaf y { type string;}} case gc2 {leaf z {type string;}}}}"
"choice ch {case one { leaf x {type string;}} case two { uses grp;}}}", LYS_IN_YANG, &mod));
assert_non_null(mod->compiled->data);
@@ -2287,8 +2366,7 @@
assert_string_equal("one", cs->name);
assert_non_null(cs->child);
assert_string_equal("x", cs->child->name);
- assert_non_null(cs->child->next);
- assert_string_equal("gch", cs->child->next->name);
+
cs = (struct lysc_node_case *)cs->next;
assert_non_null(cs);
assert_string_equal("two", cs->name);
@@ -2308,7 +2386,7 @@
assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module cc {namespace urn:cc;prefix cc;uses a:missingprefix;}", LYS_IN_YANG, &mod));
logbuf_assert("Invalid prefix used for grouping reference. /cc:{uses='a:missingprefix'}");
- assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module dd {namespace urn:dd;prefix dd;grouping grp{leaf a{type string;}}"
+ assert_int_equal(LY_EEXIST, lys_parse_mem(ctx, "module dd {namespace urn:dd;prefix dd;grouping grp{leaf a{type string;}}"
"leaf a {type string;}uses grp;}", LYS_IN_YANG, &mod));
logbuf_assert("Duplicate identifier \"a\" of data definition/RPC/action/notification statement. /dd:{uses='grp'}/dd:a");
@@ -2316,10 +2394,10 @@
"uses grp {status obsolete;}}", LYS_IN_YANG, &mod));
logbuf_assert("A \"deprecated\" status is in conflict with the parent's \"obsolete\" status. /ee:{uses='grp'}/ee:l");
- assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module ff {namespace urn:ff;prefix ff;grouping grp {leaf l {type string;}}"
+ assert_int_equal(LY_EEXIST, lys_parse_mem(ctx, "module ff {namespace urn:ff;prefix ff;grouping grp {leaf l {type string;}}"
"leaf l {type int8;}uses grp;}", LYS_IN_YANG, &mod));
logbuf_assert("Duplicate identifier \"l\" of data definition/RPC/action/notification statement. /ff:{uses='grp'}/ff:l");
- assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module fg {namespace urn:fg;prefix fg;grouping grp {leaf m {type string;}}"
+ assert_int_equal(LY_EEXIST, lys_parse_mem(ctx, "module fg {namespace urn:fg;prefix fg;grouping grp {leaf m {type string;}}"
"uses grp;leaf m {type int8;}}", LYS_IN_YANG, &mod));
logbuf_assert("Duplicate identifier \"m\" of data definition/RPC/action/notification statement. /fg:m");
@@ -2329,12 +2407,12 @@
"container top {uses grp {augment /g {leaf x {type int8;}}}}}", LYS_IN_YANG, &mod));
logbuf_assert("Invalid descendant-schema-nodeid value \"/g\" - absolute-schema-nodeid used. /gg:top/{uses='grp'}/{augment='/g'}");
- assert_int_equal(LY_SUCCESS, lys_parse_mem(ctx, "module hh {yang-version 1.1;namespace urn:hh;prefix hh;"
+ assert_int_equal(LY_ENOTFOUND, lys_parse_mem(ctx, "module hh {yang-version 1.1;namespace urn:hh;prefix hh;"
"grouping grp {notification g { description \"super g\";}}"
"container top {notification h; uses grp {refine h {description \"ultra h\";}}}}", LYS_IN_YANG, &mod));
logbuf_assert("Invalid descendant-schema-nodeid value \"h\" - target node not found. /hh:top/{uses='grp'}/{refine='h'}");
- assert_int_equal(LY_SUCCESS, lys_parse_mem(ctx, "module ii {yang-version 1.1;namespace urn:ii;prefix ii;"
+ assert_int_equal(LY_ENOTFOUND, lys_parse_mem(ctx, "module ii {yang-version 1.1;namespace urn:ii;prefix ii;"
"grouping grp {action g { description \"super g\";}}"
"container top {action i; uses grp {refine i {description \"ultra i\";}}}}", LYS_IN_YANG, &mod));
logbuf_assert("Invalid descendant-schema-nodeid value \"i\" - target node not found. /ii:top/{uses='grp'}/{refine='i'}");
@@ -2365,7 +2443,7 @@
assert_int_equal(LY_SUCCESS, lys_parse_mem(ctx, "module grp {yang-version 1.1;namespace urn:grp;prefix g; feature f;typedef mytype {type string; default cheers!;}"
"grouping grp {container c {leaf l {type mytype; default goodbye;}"
"leaf-list ll {type mytype; default goodbye; max-elements 6;}"
- "choice ch {default a; leaf a {type int8;}leaf b{type uint8;}}"
+ "choice ch {default ca; leaf ca {type int8;}leaf cb{type uint8;}}"
"leaf x {type mytype; mandatory true; must 1;}"
"anydata a {mandatory false; if-feature f; description original; reference original;}"
"container c {config false; leaf l {type string;}}}}}", LYS_IN_YANG, NULL));
@@ -2373,7 +2451,7 @@
assert_int_equal(LY_SUCCESS, lys_parse_mem(ctx, "module a {yang-version 1.1;namespace urn:a;prefix a;import grp {prefix g;}feature fa;"
"uses g:grp {refine c/l {default hello; config false;}"
"refine c/ll {default hello;default world; min-elements 2; max-elements 5;}"
- "refine c/ch {default b;config true; if-feature fa;}"
+ "refine c/ch {default cb;config true; if-feature fa;}"
"refine c/x {mandatory false; must ../ll;description refined; reference refined;}"
"refine c/a {mandatory true; must 1; if-feature fa;description refined; reference refined;}"
"refine c/c {config true;presence indispensable;}}}", LYS_IN_YANG, &mod));
@@ -2399,7 +2477,7 @@
assert_non_null(child = llist->next);
assert_int_equal(LYS_CHOICE, child->nodetype);
assert_string_equal("ch", child->name);
- assert_string_equal("b", ((struct lysc_node_choice*)child)->dflt->name);
+ assert_string_equal("cb", ((struct lysc_node_choice*)child)->dflt->name);
assert_true(LYS_SET_DFLT & ((struct lysc_node_choice*)child)->dflt->flags);
assert_false(LYS_SET_DFLT & ((struct lysc_node_choice*)child)->cases[0].flags);
assert_non_null(child->iffeatures);
@@ -2465,8 +2543,8 @@
logbuf_assert("Invalid refine of mandatory - choice already has \"default\" statement. /ef:{uses='g:grp'}/{refine='c/ch'}");
assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module ff {namespace urn:ff;prefix ff;import grp {prefix g;}"
- "uses g:grp {refine c/ch/a/a {mandatory true;}}}", LYS_IN_YANG, &mod));
- logbuf_assert("Invalid refine of mandatory under the default case. /ff:{uses='g:grp'}/{refine='c/ch/a/a'}");
+ "uses g:grp {refine c/ch/ca/ca {mandatory true;}}}", LYS_IN_YANG, &mod));
+ logbuf_assert("Invalid refine of mandatory under the default case. /ff:{uses='g:grp'}/{refine='c/ch/ca/ca'}");
assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module gg {namespace urn:gg;prefix gg;import grp {prefix g;}"
"uses g:grp {refine c/x {default hello;}}}", LYS_IN_YANG, &mod));
@@ -2562,7 +2640,6 @@
assert_null(((const struct lysc_node_case*)c)->child->when);
assert_string_equal("lc2", ((const struct lysc_node_case*)c)->child->next->name);
assert_non_null(((const struct lysc_node_case*)c)->child->next->when);
- assert_ptr_equal(ch->cases->child->prev, ((const struct lysc_node_case*)c)->child->next);
assert_null(c->next);
assert_int_equal(LY_SUCCESS, lys_parse_mem(ctx, "module f {namespace urn:f;prefix f;grouping g {leaf a {type string;}}"
@@ -2627,7 +2704,7 @@
"augment /x {leaf a {type int8;}}}", LYS_IN_YANG, &mod));
logbuf_assert("Invalid absolute-schema-nodeid value \"/x\" - target node not found. /aa:{augment='/x'}");
- assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb; container c {leaf a {type string;}}"
+ assert_int_equal(LY_EEXIST, lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb; container c {leaf a {type string;}}"
"augment /c {leaf a {type int8;}}}", LYS_IN_YANG, &mod));
logbuf_assert("Duplicate identifier \"a\" of data definition/RPC/action/notification statement. /bb:{augment='/c'}/a");
@@ -2736,14 +2813,14 @@
assert_null(((struct lysc_node_leaf*)node)->musts);
ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "module e {yang-version 1.1; namespace urn:e;prefix e; typedef mytype {type string; default nothing;}"
- "choice a {default a;leaf a {type string;} leaf b {type string;} leaf c {type string; mandatory true;}}"
- "choice b {default a;leaf a {type string;} leaf b {type string;}}"
+ "choice a {default aa;leaf aa {type string;} leaf ab {type string;} leaf ac {type string; mandatory true;}}"
+ "choice b {default ba;leaf ba {type string;} leaf bb {type string;}}"
"leaf c {default hello; type string;}"
"leaf-list d {default hello; default world; type string;}"
"leaf c2 {type mytype;} leaf-list d2 {type mytype;}}");
assert_int_equal(LY_SUCCESS, lys_parse_mem(ctx, "module f {yang-version 1.1; namespace urn:f;prefix f;import e {prefix x;}"
- "deviation /x:a {deviate delete {default a;}}"
- "deviation /x:b {deviate delete {default x:a;}}"
+ "deviation /x:a {deviate delete {default aa;}}"
+ "deviation /x:b {deviate delete {default x:ba;}}"
"deviation /x:c {deviate delete {default hello;}}"
"deviation /x:d {deviate delete {default world;}}}", LYS_IN_YANG, NULL));
assert_non_null((mod = ly_ctx_get_module_implemented(ctx, "e")));
@@ -2767,7 +2844,7 @@
assert_int_equal(0, dynamic);
assert_int_equal(LY_SUCCESS, lys_parse_mem(ctx, "module g {yang-version 1.1; namespace urn:g;prefix g;import e {prefix x;}"
- "deviation /x:b {deviate add {default x:b;}}"
+ "deviation /x:b {deviate add {default x:ba;}}"
"deviation /x:c {deviate add {default bye;}}"
"deviation /x:d {deviate add {default all; default people;}}"
"deviation /x:c2 {deviate add {default hi; must 1;}}"
@@ -2777,7 +2854,7 @@
assert_null(((struct lysc_node_choice*)node)->dflt);
assert_non_null(node = node->next);
assert_non_null(((struct lysc_node_choice*)node)->dflt);
- assert_string_equal("b", ((struct lysc_node_choice*)node)->dflt->name);
+ assert_string_equal("ba", ((struct lysc_node_choice*)node)->dflt->name);
assert_non_null(leaf = (struct lysc_node_leaf*)node->next);
assert_non_null(leaf->dflt);
assert_string_equal("bye", leaf->dflt->realtype->plugin->print(leaf->dflt, LY_PREF_SCHEMA, NULL, &dynamic));
@@ -2806,14 +2883,14 @@
assert_int_equal(0, dynamic);
assert_int_equal(LY_SUCCESS, lys_parse_mem(ctx, "module h {yang-version 1.1; namespace urn:h;prefix h;import e {prefix x;}"
- "deviation /x:b {deviate replace {default x:a;}}"
+ "deviation /x:b {deviate replace {default x:ba;}}"
"deviation /x:c {deviate replace {default hello;}}}", LYS_IN_YANG, NULL));
assert_non_null((mod = ly_ctx_get_module_implemented(ctx, "e")));
assert_non_null(node = mod->compiled->data);
assert_null(((struct lysc_node_choice*)node)->dflt);
assert_non_null(node = node->next);
assert_non_null(((struct lysc_node_choice*)node)->dflt);
- assert_string_equal("a", ((struct lysc_node_choice*)node)->dflt->name);
+ assert_string_equal("ba", ((struct lysc_node_choice*)node)->dflt->name);
assert_non_null(leaf = (struct lysc_node_leaf*)node->next);
assert_non_null(leaf->dflt);
assert_string_equal("hello", leaf->dflt->realtype->plugin->print(leaf->dflt, LY_PREF_SCHEMA, NULL, &dynamic));
@@ -3033,7 +3110,7 @@
"The prefix does not match any imported module of the deviation module. /ff2:{deviation='/e:b'}");
assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module ff3 {namespace urn:ff3;prefix ff3; import e {prefix e;}"
"deviation /e:b {deviate delete {default e:b;}}}", LYS_IN_YANG, &mod));
- logbuf_assert("Invalid deviation deleting \"default\" property \"e:b\" of choice does not match the default case name \"a\". /ff3:{deviation='/e:b'}");
+ logbuf_assert("Invalid deviation deleting \"default\" property \"e:b\" of choice does not match the default case name \"ba\". /ff3:{deviation='/e:b'}");
assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module ff4 {namespace urn:ff4;prefix ff4; import e {prefix e;}"
"deviation /e:b {deviate delete {default ff4:a;}}}", LYS_IN_YANG, &mod));
logbuf_assert("Invalid deviation deleting \"default\" property \"ff4:a\" of choice. The prefix does not match the default case's module. /ff4:{deviation='/e:b'}");
@@ -3049,7 +3126,7 @@
assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module gg1 {namespace urn:gg1;prefix gg1; import e {prefix e;}"
"deviation /e:b {deviate add {default e:a;}}}", LYS_IN_YANG, &mod));
- logbuf_assert("Invalid deviation adding \"default\" property which already exists (with value \"a\"). /gg1:{deviation='/e:b'}");
+ logbuf_assert("Invalid deviation adding \"default\" property which already exists (with value \"ba\"). /gg1:{deviation='/e:b'}");
assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module gg2 {namespace urn:gg2;prefix gg2; import e {prefix e;}"
"deviation /e:a {deviate add {default x:a;}}}", LYS_IN_YANG, &mod));
logbuf_assert("Invalid deviation adding \"default\" property \"x:a\" of choice. "
@@ -3061,8 +3138,8 @@
"deviation /e:c {deviate add {default hi;}}}", LYS_IN_YANG, &mod));
logbuf_assert("Invalid deviation adding \"default\" property which already exists (with value \"hello\"). /gg4:{deviation='/e:c'}");
assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module gg4 {namespace urn:gg4;prefix gg4; import e {prefix e;}"
- "deviation /e:a {deviate add {default e:c;}}}", LYS_IN_YANG, &mod));
- logbuf_assert("Invalid deviation adding \"default\" property \"e:c\" of choice - mandatory node \"c\" under the default case. /gg4:{deviation='/e:a'}");
+ "deviation /e:a {deviate add {default e:ac;}}}", LYS_IN_YANG, &mod));
+ logbuf_assert("Invalid deviation adding \"default\" property \"e:ac\" of choice - mandatory node \"ac\" under the default case. /gg4:{deviation='/e:a'}");
assert_int_equal(LY_EVALID, lys_parse_mem(ctx, "module gg5 {namespace urn:gg5;prefix gg5; leaf x {type string; mandatory true;}"
"deviation /x {deviate add {default error;}}}", LYS_IN_YANG, &mod));
logbuf_assert("Invalid deviation combining default value and mandatory leaf. /gg5:{deviation='/x'}");
@@ -3311,6 +3388,7 @@
{
const struct CMUnitTest tests[] = {
cmocka_unit_test_setup_teardown(test_module, logger_setup, logger_teardown),
+ cmocka_unit_test_setup_teardown(test_name_collisions, logger_setup, logger_teardown),
cmocka_unit_test_setup_teardown(test_type_length, logger_setup, logger_teardown),
cmocka_unit_test_setup_teardown(test_type_range, logger_setup, logger_teardown),
cmocka_unit_test_setup_teardown(test_type_pattern, logger_setup, logger_teardown),