schema compile CHANGE schema deviating
Fix the order of 1) applying deviations, 2) checking/finishing leafrefs
and 3) finishing incomplete default values.
Also prepare the code for recompiling reference objects (leafrefs,
instance-identifier default values, must, when) when deviation changes
schema tree by deviate-not-supported.
diff --git a/src/common.h b/src/common.h
index 68b0770..af6fede 100644
--- a/src/common.h
+++ b/src/common.h
@@ -215,6 +215,21 @@
};
/**
+ * @defgroup contextflags Context flags
+ * @ingroup context
+ *
+ * Internal context flags.
+ *
+ * Note that the flags 0x00FF are reserved for @ref contextoptions.
+ * @{
+ */
+
+#define LY_CTX_CHANGED_TREE 0x8000 /**< Deviation changed tree of a module(s) in the context, it is necessary to recompile
+ leafref paths, default values and must/when expressions to check that they are still valid */
+
+/**@} contextflags */
+
+/**
* @brief Try to find submodule in the context. Submodules are present only in the parsed (lysp_) schema trees, if only
* the compiled versions of the schemas are present, the submodule cannot be returned even if it was used to compile
* some of the currently present schemas.
diff --git a/src/context.h b/src/context.h
index cbe027f..f8260bf 100644
--- a/src/context.h
+++ b/src/context.h
@@ -44,6 +44,9 @@
* @ingroup context
*
* Options to change context behavior.
+ *
+ * Note that the flags 0xFF00 are reserved for internal use.
+ *
* @{
*/
diff --git a/src/plugins_types.c b/src/plugins_types.c
index ea53c5f..0972653 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -2100,6 +2100,7 @@
lyd_value_free_path(ctx, value->target);
value->target = NULL;
+ /* for the case of LY_EINCOMPLETE result on schema tree */
ly_type_free_canonical(ctx, value);
}
diff --git a/src/tree_schema_compile.c b/src/tree_schema_compile.c
index d29a7b4..cd22014 100644
--- a/src/tree_schema_compile.c
+++ b/src/tree_schema_compile.c
@@ -109,6 +109,51 @@
}
/**
+ * @brief Add record into the compile context's list of incomplete default values.
+ * @param[in] ctx Compile context with the incomplete default values list.
+ * @param[in] context_node Context schema node to store in the record.
+ * @param[in] dflt Incomplete default value to store in the record.
+ * @param[in] dflt_mod Module of the default value definition to store in the record.
+ * @return LY_EMEM in case of memory allocation failure.
+ * @return LY_SUCCESS
+ */
+static LY_ERR
+lysc_incomplete_dflts_add(struct lysc_ctx *ctx, struct lysc_node *context_node, struct lyd_value *dflt, struct lys_module *dflt_mod)
+{
+ struct lysc_incomplete_dflt *r;
+ r = malloc(sizeof *r);
+ LY_CHECK_ERR_RET(!r, LOGMEM(ctx->ctx), LY_EMEM);
+ r->context_node = context_node;
+ r->dflt = dflt;
+ r->dflt_mod = dflt_mod;
+ ly_set_add(&ctx->dflts, r, LY_SET_OPT_USEASLIST);
+
+ return LY_SUCCESS;
+}
+
+/**
+ * @brief Remove record of the given default value from the compile context's list of incomplete default values.
+ * @param[in] ctx Compile context with the incomplete default values list.
+ * @param[in] dflt Incomplete default values identifying the record to remove.
+ */
+static void
+lysc_incomplete_dflts_remove(struct lysc_ctx *ctx, struct lyd_value *dflt)
+{
+ unsigned int u;
+ struct lysc_incomplete_dflt *r;
+
+ for (u = 0; u < ctx->dflts.count; ++u) {
+ r = (struct lysc_incomplete_dflt*)ctx->dflts.objs[u];
+ if (r->dflt == dflt) {
+ free(ctx->dflts.objs[u]);
+ memmove(&ctx->dflts.objs[u], &ctx->dflts.objs[u + 1], (ctx->dflts.count - (u + 1)) * sizeof *ctx->dflts.objs);
+ --ctx->dflts.count;
+ return;
+ }
+ }
+}
+
+/**
* @brief Update path in the compile context.
*
* @param[in] ctx Compile context with the path.
@@ -3154,12 +3199,7 @@
}
if (ret == LY_EINCOMPLETE) {
/* postpone default compilation when the tree is complete */
- struct lysc_incomplete_dflt *r;
- r = malloc(sizeof *r);
- r->context_node = NULL;
- r->dflt = (*type)->dflt;
- r->dflt_mod = (*type)->dflt_mod;
- ly_set_add(&ctx->dflts, r, LY_SET_OPT_USEASLIST);
+ LY_CHECK_GOTO(lysc_incomplete_dflts_add(ctx, NULL, (*type)->dflt, (*type)->dflt_mod), cleanup);
/* but in general result is so far ok */
ret = LY_SUCCESS;
@@ -3545,12 +3585,7 @@
}
if (ret == LY_EINCOMPLETE) {
/* postpone default compilation when the tree is complete */
- struct lysc_incomplete_dflt *r;
- r = malloc(sizeof *r);
- r->context_node = node;
- r->dflt = leaf->dflt;
- r->dflt_mod = leaf->dflt_mod;
- ly_set_add(&ctx->dflts, r, LY_SET_OPT_USEASLIST);
+ LY_CHECK_GOTO(lysc_incomplete_dflts_add(ctx, node, leaf->dflt, leaf->dflt_mod), done);
/* but in general result is so far ok */
ret = LY_SUCCESS;
@@ -3612,12 +3647,7 @@
}
if (ret == LY_EINCOMPLETE) {
/* postpone default compilation when the tree is complete */
- struct lysc_incomplete_dflt *r;
- r = malloc(sizeof *r);
- r->context_node = node;
- r->dflt = llist->dflts[u];
- r->dflt_mod = llist->dflts_mods[u];
- ly_set_add(&ctx->dflts, r, LY_SET_OPT_USEASLIST);
+ LY_CHECK_GOTO(lysc_incomplete_dflts_add(ctx, node, llist->dflts[u], llist->dflts_mods[u]), done);
/* but in general result is so far ok */
ret = LY_SUCCESS;
@@ -4527,6 +4557,10 @@
} else if (((struct lysc_node_leaf*)node)->dflt) {
/* remove the default value taken from the leaf's type */
struct lysc_node_leaf *leaf = (struct lysc_node_leaf*)node;
+
+ /* update the list of incomplete default values if needed */
+ lysc_incomplete_dflts_remove(ctx, leaf->dflt);
+
leaf->dflt->realtype->plugin->free(ctx->ctx, leaf->dflt);
lysc_type_free(ctx->ctx, leaf->dflt->realtype);
free(leaf->dflt);
@@ -4793,6 +4827,7 @@
struct lysc_node_leaf *leaf = (struct lysc_node_leaf*)node;
if (leaf->dflt) {
/* remove the previous default value */
+ lysc_incomplete_dflts_remove(ctx, leaf->dflt);
leaf->dflt->realtype->plugin->free(ctx->ctx, leaf->dflt);
lysc_type_free(ctx->ctx, leaf->dflt->realtype);
} else {
@@ -4814,12 +4849,7 @@
}
if (rc == LY_EINCOMPLETE) {
/* postpone default compilation when the tree is complete */
- struct lysc_incomplete_dflt *r;
- r = malloc(sizeof *r);
- r->context_node = node;
- r->dflt = leaf->dflt;
- r->dflt_mod = leaf->dflt_mod;
- ly_set_add(&ctx->dflts, r, LY_SET_OPT_USEASLIST);
+ LY_CHECK_GOTO(lysc_incomplete_dflts_add(ctx, node, leaf->dflt, leaf->dflt_mod), cleanup);
/* but in general result is so far ok */
rc = LY_SUCCESS;
@@ -4837,6 +4867,7 @@
/* remove previous set of default values */
LY_ARRAY_FOR(llist->dflts, u) {
+ lysc_incomplete_dflts_remove(ctx, llist->dflts[u]);
llist->dflts[u]->realtype->plugin->free(ctx->ctx, llist->dflts[u]);
lysc_type_free(ctx->ctx, llist->dflts[u]->realtype);
free(llist->dflts[u]);
@@ -4868,12 +4899,7 @@
}
if (rc == LY_EINCOMPLETE) {
/* postpone default compilation when the tree is complete */
- struct lysc_incomplete_dflt *r;
- r = malloc(sizeof *r);
- r->context_node = node;
- r->dflt = llist->dflts[u];
- r->dflt_mod = llist->dflts_mods[u];
- ly_set_add(&ctx->dflts, r, LY_SET_OPT_USEASLIST);
+ LY_CHECK_GOTO(lysc_incomplete_dflts_add(ctx, node, llist->dflts[u], llist->dflts_mods[u]), cleanup);
/* but in general result is so far ok */
rc = LY_SUCCESS;
@@ -5706,6 +5732,8 @@
lysc_node_free(ctx->ctx, devs[u]->target);
}
+ /* mark the context for later re-compilation of objects that could reference the curently removed node */
+ ctx->ctx->flags |= LY_CTX_CHANGED_TREE;
continue;
}
@@ -5775,6 +5803,7 @@
DEV_CHECK_NONPRESENCE_VALUE(struct lysc_node_leaf*, (devs[u]->target->flags & LYS_SET_DFLT), dflt, "default", dflt, dflt_mod);
if (leaf->dflt) {
/* first, remove the default value taken from the type */
+ lysc_incomplete_dflts_remove(ctx, leaf->dflt);
leaf->dflt->realtype->plugin->free(ctx->ctx, leaf->dflt);
lysc_type_free(ctx->ctx, leaf->dflt->realtype);
} else {
@@ -5791,6 +5820,7 @@
if (llist->dflts && !(devs[u]->target->flags & LYS_SET_DFLT)) {
/* first, remove the default value taken from the type */
LY_ARRAY_FOR(llist->dflts, x) {
+ lysc_incomplete_dflts_remove(ctx, llist->dflts[x]);
llist->dflts[x]->realtype->plugin->free(ctx->ctx, llist->dflts[x]);
lysc_type_free(ctx->ctx, llist->dflts[x]->realtype);
free(llist->dflts[x]);
@@ -5811,7 +5841,7 @@
llist->dflts[x] = calloc(1, sizeof *llist->dflts[x]);
llist->dflts[x]->realtype = llist->type;
rc = llist->type->plugin->store(ctx->ctx, llist->type, d_add->dflts[x - y], strlen(d_add->dflts[x - y]),
- LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE, lys_resolve_prefix,
+ LY_TYPE_OPTS_INCOMPLETE_DATA |LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE, lys_resolve_prefix,
(void*)llist->dflts_mods[x], LYD_XML, devs[u]->target, NULL, llist->dflts[x], NULL, &err);
llist->dflts[x]->realtype->refcount++;
if (err) {
@@ -5821,6 +5851,13 @@
d_add->dflts[x - y], err->msg);
ly_err_free(err);
}
+ if (rc == LY_EINCOMPLETE) {
+ /* postpone default compilation when the tree is complete */
+ LY_CHECK_GOTO(lysc_incomplete_dflts_add(ctx, devs[u]->target, llist->dflts[x], llist->dflts_mods[x]), cleanup);
+
+ /* but in general result is so far ok */
+ rc = LY_SUCCESS;
+ }
LY_CHECK_GOTO(rc, cleanup);
}
/* mark the new default values as leaf-list's own */
@@ -6027,6 +6064,9 @@
}
dflt = NULL;
+ /* update the list of incomplete default values if needed */
+ lysc_incomplete_dflts_remove(ctx, leaf->dflt);
+
/* remove the default specification */
leaf->dflt->realtype->plugin->free(ctx->ctx, leaf->dflt);
lysc_type_free(ctx->ctx, leaf->dflt->realtype);
@@ -6057,6 +6097,10 @@
"which does not match any of the target's property values.", d_del->dflts[x]);
goto cleanup;
}
+
+ /* update the list of incomplete default values if needed */
+ lysc_incomplete_dflts_remove(ctx, llist->dflts[y]);
+
LY_ARRAY_DECREMENT(llist->dflts_mods);
LY_ARRAY_DECREMENT(llist->dflts);
llist->dflts[y]->realtype->plugin->free(ctx->ctx, llist->dflts[y]);
@@ -6126,6 +6170,9 @@
if (leaf->dflt && !(devs[u]->target->flags & LYS_SET_DFLT)) {
/* the target has default from the previous type - remove it */
if (devs[u]->target->nodetype == LYS_LEAF) {
+ /* update the list of incomplete default values if needed */
+ lysc_incomplete_dflts_remove(ctx, leaf->dflt);
+
leaf->dflt->realtype->plugin->free(ctx->ctx, leaf->dflt);
lysc_type_free(ctx->ctx, leaf->dflt->realtype);
free(leaf->dflt);
@@ -6133,6 +6180,7 @@
leaf->dflt_mod = NULL;
} else { /* LYS_LEAFLIST */
LY_ARRAY_FOR(llist->dflts, x) {
+ lysc_incomplete_dflts_remove(ctx, llist->dflts[x]);
llist->dflts[x]->realtype->plugin->free(ctx->ctx, llist->dflts[x]);
lysc_type_free(ctx->ctx, llist->dflts[x]->realtype);
free(llist->dflts[x]);
@@ -6169,6 +6217,7 @@
DEV_CHECK_PRESENCE(struct lysc_node_leaf*, !(devs[u]->target->flags & LYS_SET_DFLT),
dflt, "replacing", "default", d_rpl->dflt);
/* first, remove the default value taken from the type */
+ lysc_incomplete_dflts_remove(ctx, leaf->dflt);
leaf->dflt->realtype->plugin->free(ctx->ctx, leaf->dflt);
lysc_type_free(ctx->ctx, leaf->dflt->realtype);
dflt = d_rpl->dflt;
@@ -6278,7 +6327,8 @@
/* parse added/changed default value after possible change of the type */
leaf->dflt_mod = ctx->mod_def;
leaf->dflt->realtype = leaf->type;
- rc = leaf->type->plugin->store(ctx->ctx, leaf->type, dflt, strlen(dflt), LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
+ rc = leaf->type->plugin->store(ctx->ctx, leaf->type, dflt, strlen(dflt),
+ LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
lys_resolve_prefix, (void*)leaf->dflt_mod, LYD_XML, devs[u]->target, NULL, leaf->dflt, NULL, &err);
leaf->dflt->realtype->refcount++;
if (err) {
@@ -6287,16 +6337,29 @@
"Invalid deviation setting \"default\" property \"%s\" which does not fit the type (%s).", dflt, err->msg);
ly_err_free(err);
}
+ if (rc == LY_EINCOMPLETE) {
+ /* postpone default compilation when the tree is complete */
+ LY_CHECK_GOTO(lysc_incomplete_dflts_add(ctx, devs[u]->target, leaf->dflt, leaf->dflt_mod), cleanup);
+
+ /* but in general result is so far ok */
+ rc = LY_SUCCESS;
+ }
LY_CHECK_GOTO(rc, cleanup);
} else if (changed_type) {
/* the leaf/leaf-list's type has changed, but there is still a default value for the previous type */
int dynamic;
if (devs[u]->target->nodetype == LYS_LEAF) {
dflt = leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, lys_get_prefix, leaf->dflt_mod, &dynamic);
+
+ /* update the list of incomplete default values if needed */
+ lysc_incomplete_dflts_remove(ctx, leaf->dflt);
+
+ /* remove the previous default */
leaf->dflt->realtype->plugin->free(ctx->ctx, leaf->dflt);
lysc_type_free(ctx->ctx, leaf->dflt->realtype);
leaf->dflt->realtype = leaf->type;
- rc = leaf->type->plugin->store(ctx->ctx, leaf->type, dflt, strlen(dflt), LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
+ rc = leaf->type->plugin->store(ctx->ctx, leaf->type, dflt, strlen(dflt),
+ LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
lys_resolve_prefix, (void*)leaf->dflt_mod, LYD_XML, devs[u]->target, NULL, leaf->dflt, NULL, &err);
leaf->dflt->realtype->refcount++;
if (err) {
@@ -6308,15 +6371,23 @@
if (dynamic) {
free((void*)dflt);
}
- LY_CHECK_GOTO(rc, cleanup);
dflt = NULL;
+ if (rc == LY_EINCOMPLETE) {
+ /* postpone default compilation when the tree is complete */
+ LY_CHECK_GOTO(lysc_incomplete_dflts_add(ctx, devs[u]->target, leaf->dflt, leaf->dflt_mod), cleanup);
+
+ /* but in general result is so far ok */
+ rc = LY_SUCCESS;
+ }
+ LY_CHECK_GOTO(rc, cleanup);
} else { /* LYS_LEAFLIST */
LY_ARRAY_FOR(llist->dflts, x) {
dflt = llist->dflts[x]->realtype->plugin->print(llist->dflts[x], LYD_XML, lys_get_prefix, llist->dflts_mods[x], &dynamic);
llist->dflts[x]->realtype->plugin->free(ctx->ctx, llist->dflts[x]);
lysc_type_free(ctx->ctx, llist->dflts[x]->realtype);
llist->dflts[x]->realtype = llist->type;
- rc = llist->type->plugin->store(ctx->ctx, llist->type, dflt, strlen(dflt), LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
+ rc = llist->type->plugin->store(ctx->ctx, llist->type, dflt, strlen(dflt),
+ LY_TYPE_OPTS_INCOMPLETE_DATA | LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE,
lys_resolve_prefix, (void*)llist->dflts_mods[x], LYD_XML, devs[u]->target, NULL,
llist->dflts[x], NULL, &err);
llist->dflts[x]->realtype->refcount++;
@@ -6331,6 +6402,13 @@
free((void*)dflt);
}
dflt = NULL;
+ if (rc == LY_EINCOMPLETE) {
+ /* postpone default compilation when the tree is complete */
+ LY_CHECK_GOTO(lysc_incomplete_dflts_add(ctx, devs[u]->target, llist->dflts[x], llist->dflts_mods[x]), cleanup);
+
+ /* but in general result is so far ok */
+ rc = LY_SUCCESS;
+ }
LY_CHECK_GOTO(rc, cleanup);
}
}
@@ -6389,6 +6467,7 @@
/* shortcuts */
struct lysp_submodule *submod = inc->submodule;
struct lysc_module *mainmod = ctx->mod->compiled;
+ struct lysp_node *node_p;
if (!mainmod->mod->off_features) {
/* features are compiled directly into the compiled module structure,
@@ -6403,7 +6482,11 @@
COMPILE_ARRAY_UNIQUE_GOTO(ctx, submod->identities, mainmod->identities, u, lys_compile_identity, ret, error);
lysc_update_path(ctx, NULL, NULL);
- /* TODO data nodes */
+ /* data nodes */
+ LY_LIST_FOR(submod->data, node_p) {
+ ret = lys_compile_node(ctx, node_p, NULL, 0);
+ LY_CHECK_GOTO(ret, error);
+ }
COMPILE_ARRAY1_GOTO(ctx, submod->rpcs, mainmod->rpcs, NULL, u, lys_compile_action, 0, ret, error);
COMPILE_ARRAY1_GOTO(ctx, submod->notifs, mainmod->notifs, NULL, u, lys_compile_notif, 0, ret, error);
@@ -6503,25 +6586,7 @@
LY_CHECK_GOTO(ret, error);
}
- /* finish incomplete default values compilation */
- for (u = 0; u < ctx.dflts.count; ++u) {
- struct ly_err_item *err = NULL;
- struct lysc_incomplete_dflt *r = ctx.dflts.objs[u];
- ret = r->dflt->realtype->plugin->store(ctx.ctx, r->dflt->realtype, r->dflt->canonized, strlen(r->dflt->canonized),
- LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE | LY_TYPE_OPTS_SECOND_CALL, lys_resolve_prefix,
- (void*)r->dflt_mod, LYD_XML, r->context_node, NULL, r->dflt, NULL, &err);
- if (err) {
- ly_err_print(err);
- ctx.path[0] = '\0';
- lysc_path(r->context_node, LY_PATH_LOG, ctx.path, LYSC_CTX_BUFSIZE);
- LOGVAL(ctx.ctx, LY_VLOG_STR, ctx.path, LYVE_SEMANTICS,
- "Invalid default - value does not fit the type (%s).", err->msg);
- ly_err_free(err);
- }
- LY_CHECK_GOTO(ret, error);
- }
-
- /* deviations */
+ /* deviations TODO cover deviations from submodules */
ret = lys_compile_deviations(&ctx, sp);
LY_CHECK_GOTO(ret, error);
@@ -6573,6 +6638,24 @@
}
}
+ /* finish incomplete default values compilation */
+ for (u = 0; u < ctx.dflts.count; ++u) {
+ struct ly_err_item *err = NULL;
+ struct lysc_incomplete_dflt *r = ctx.dflts.objs[u];
+ ret = r->dflt->realtype->plugin->store(ctx.ctx, r->dflt->realtype, r->dflt->canonized, strlen(r->dflt->canonized),
+ LY_TYPE_OPTS_SCHEMA | LY_TYPE_OPTS_STORE | LY_TYPE_OPTS_SECOND_CALL, lys_resolve_prefix,
+ (void*)r->dflt_mod, LYD_XML, r->context_node, NULL, r->dflt, NULL, &err);
+ if (err) {
+ ly_err_print(err);
+ ctx.path[0] = '\0';
+ lysc_path(r->context_node, LY_PATH_LOG, ctx.path, LYSC_CTX_BUFSIZE);
+ LOGVAL(ctx.ctx, LY_VLOG_STR, ctx.path, LYVE_SEMANTICS,
+ "Invalid default - value does not fit the type (%s).", err->msg);
+ ly_err_free(err);
+ }
+ LY_CHECK_GOTO(ret, error);
+ }
+
/* validate non-instantiated groupings from the parsed schema,
* without it we would accept even the schemas with invalid grouping specification */
ctx.options |= LYSC_OPT_GROUPING;
@@ -6590,6 +6673,11 @@
}
}
+ if (ctx.ctx->flags & LY_CTX_CHANGED_TREE) {
+ /* TODO Deviation has changed tree of a module(s) in the context (by deviate-not-supported), it is necessary to recompile
+ leafref paths, default values and must/when expressions in all schemas of the context to check that they are still valid */
+ }
+
ly_set_erase(&ctx.dflts, free);
ly_set_erase(&ctx.unres, NULL);
ly_set_erase(&ctx.groupings, NULL);
diff --git a/src/tree_schema_helpers.c b/src/tree_schema_helpers.c
index 7f82482..a3b201d 100644
--- a/src/tree_schema_helpers.c
+++ b/src/tree_schema_helpers.c
@@ -1289,6 +1289,9 @@
struct lys_module *context_mod = (struct lys_module*)private;
unsigned int u;
+ if (context_mod == mod) {
+ return context_mod->prefix;
+ }
LY_ARRAY_FOR(context_mod->compiled->imports, u) {
if (context_mod->compiled->imports[u].module == mod) {
/* match */
diff --git a/tests/src/test_tree_schema_compile.c b/tests/src/test_tree_schema_compile.c
index d731c61..9f93ae1 100644
--- a/tests/src/test_tree_schema_compile.c
+++ b/tests/src/test_tree_schema_compile.c
@@ -2842,6 +2842,7 @@
const struct lysc_node_list *list;
const struct lysc_node_leaflist *llist;
const struct lysc_node_leaf *leaf;
+ const char *str;
int dynamic;
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
@@ -3152,6 +3153,17 @@
assert_null(llist->dflts);
assert_null(llist->dflts_mods);
+ assert_non_null(mod = lys_parse_mem(ctx, "module s {yang-version 1.1; namespace urn:s;prefix s;"
+ "leaf s {type instance-identifier {require-instance true;} default /s:x;}"
+ "leaf x {type string;} leaf y {type string;}"
+ "deviation /s:s {deviate replace {default /s:y;}}}", LYS_IN_YANG));
+ assert_non_null(leaf = (struct lysc_node_leaf*)mod->compiled->data);
+ assert_string_equal("s", leaf->name);
+ assert_non_null(leaf->dflt);
+ assert_non_null(str = leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, lys_get_prefix, mod, &dynamic));
+ assert_string_equal("/s:y", str);
+ if (dynamic) { free((char*)str); }
+
assert_null(lys_parse_mem(ctx, "module aa1 {namespace urn:aa1;prefix aa1;import a {prefix a;}"
"deviation /a:top/a:z {deviate not-supported;}}", LYS_IN_YANG));
logbuf_assert("Invalid absolute-schema-nodeid value \"/a:top/a:z\" - target node not found. /aa1:{deviation='/a:top/a:z'}");
@@ -3350,6 +3362,14 @@
logbuf_assert("Invalid deviation setting \"default\" property \"300\" which does not fit the type "
"(Value \"300\" is out of uint8's min/max bounds.). /oo3:{deviation='/x'}");
+/* TODO recompiling reference object after deviation changes schema tree
+ assert_non_null(lys_parse_mem(ctx, "module pp {namespace urn:pp;prefix pp; leaf l { type leafref {path /c/x;}}"
+ "container c {leaf x {type string;} leaf y {type string;}}}", LYS_IN_YANG));
+ assert_null(lys_parse_mem(ctx, "module pp1 {namespace urn:pp1;prefix pp1; import pp {prefix pp;}"
+ "deviation /pp:c/pp:x {deviate not-supported;}}", LYS_IN_YANG));
+ logbuf_assert("???. /pp:l}");
+*/
+
*state = NULL;
ly_ctx_destroy(ctx, NULL);
}