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 *)(&notifs[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 (&notifs[u] != exclude && notifs[u].module == ctx->mod && !strcmp(name, notifs[u].name)) {
+        if (CHECK_NODE(&notifs[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),