Skip to content

Commit 7b2acbf

Browse files
validation REFACTOR when-false handling per review
Address the maintainer review on PR #2528. - Move the when-false marking and node_types/node_when descendant cleanup out of lyd_validate_unres_when into a dedicated lyd_validate_when_false helper to keep the caller short. - Apply the LYD_WHEN_FALSE handling only for LYD_VALIDATE_MULTI_ERROR. In single-error validation the first when failure stops validation, so the flag and the cleanup loops are needless work. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 2b51f7e commit 7b2acbf

1 file changed

Lines changed: 59 additions & 37 deletions

File tree

src/validation.c

Lines changed: 59 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,59 @@ lyd_validate_autodel_node_del(struct lyd_node **first, struct lyd_node *del, con
386386
return node_autodel;
387387
}
388388

389+
/**
390+
* @brief Handle a node whose "when" evaluated to false during multi-error validation.
391+
*
392+
* The node is kept in the tree (so validation can continue) and marked ::LYD_WHEN_FALSE so
393+
* that XPath evaluation treats it as non-existent (returns LY_ENOT) instead of LY_EINCOMPLETE.
394+
* Its descendants are removed from @p node_types and @p node_when so their leafrefs and own
395+
* "when" conditions are not validated against the logically non-existent subtree, which would
396+
* produce spurious cascading errors.
397+
*
398+
* @param[in] node Node with a false "when".
399+
* @param[in,out] node_when Set with nodes with "when" conditions, descendants of @p node are removed.
400+
* @param[in,out] node_types Set with nodes with unresolved types, descendants of @p node are removed.
401+
* @param[in,out] idx Index of @p node in @p node_when, refreshed if any descendants were removed.
402+
*/
403+
static void
404+
lyd_validate_when_false(struct lyd_node *node, struct ly_set *node_when, struct ly_set *node_types, uint32_t *idx)
405+
{
406+
struct lyd_node *iter;
407+
uint32_t j, count;
408+
409+
/* mark so subsequent XPath evaluations on this node return "no match" instead of LY_EINCOMPLETE */
410+
node->flags |= LYD_WHEN_FALSE;
411+
412+
/* remove descendants from node_types so their leafrefs are not validated against the
413+
* when-false subtree (mirrors the cleanup done by lyd_validate_autodel_node_del) */
414+
if (node_types && node_types->count) {
415+
LYD_TREE_DFS_BEGIN(node, iter) {
416+
if ((iter->schema->nodetype & LYD_NODE_TERM) &&
417+
LYSC_GET_TYPE_PLG(((struct lysc_node_leaf *)iter->schema)->type->plugin_ref)->validate_tree &&
418+
ly_set_contains(node_types, iter, &j)) {
419+
ly_set_rm_index(node_types, j, NULL);
420+
}
421+
LYD_TREE_DFS_END(node, iter);
422+
}
423+
}
424+
425+
/* remove descendants from node_when so their own "when" conditions are not evaluated; a
426+
* when-false subtree is logically non-existent, so child whens are moot */
427+
if (node_when->count > 1) {
428+
count = node_when->count;
429+
LYD_TREE_DFS_BEGIN(node, iter) {
430+
if ((iter != node) && ly_set_contains(node_when, iter, &j)) {
431+
ly_set_rm_index_ordered(node_when, j, NULL);
432+
}
433+
LYD_TREE_DFS_END(node, iter);
434+
}
435+
if (count > node_when->count) {
436+
/* descendants were removed, refresh the iteration index */
437+
ly_set_contains(node_when, node, idx);
438+
}
439+
}
440+
}
441+
389442
/**
390443
* @brief Evaluate when conditions of collected unres nodes.
391444
*
@@ -436,43 +489,12 @@ lyd_validate_unres_when(struct lyd_node **tree, const struct lys_module *mod, st
436489
/* only a warning */
437490
LOGWRN(LYD_CTX(node), "When condition \"%s\" not satisfied.", disabled->cond->expr);
438491
} else {
439-
/* invalid data; mark the when as resolved-to-false so subsequent XPath
440-
* evaluations on this node return "no match" instead of LY_EINCOMPLETE */
441-
node->flags |= LYD_WHEN_FALSE;
442-
/* remove descendants from node_types so their leafrefs are not validated
443-
* against the when-false subtree, which would produce spurious cascading
444-
* errors (mirrors the cleanup done by lyd_validate_autodel_node_del) */
445-
if (node_types && node_types->count) {
446-
struct lyd_node *iter;
447-
uint32_t idx;
448-
449-
LYD_TREE_DFS_BEGIN(node, iter) {
450-
if ((iter->schema->nodetype & LYD_NODE_TERM) &&
451-
LYSC_GET_TYPE_PLG(((struct lysc_node_leaf *)iter->schema)->type->plugin_ref)->validate_tree &&
452-
ly_set_contains(node_types, iter, &idx)) {
453-
ly_set_rm_index(node_types, idx, NULL);
454-
}
455-
LYD_TREE_DFS_END(node, iter);
456-
}
457-
}
458-
/* remove descendants from node_when so their own when conditions are not
459-
* evaluated; a when-false subtree is logically non-existent, so child
460-
* whens are moot and would otherwise produce spurious cascading errors */
461-
if (node_when->count > 1) {
462-
struct lyd_node *iter;
463-
uint32_t idx;
464-
465-
count = node_when->count;
466-
LYD_TREE_DFS_BEGIN(node, iter) {
467-
if ((iter != node) && ly_set_contains(node_when, iter, &idx)) {
468-
ly_set_rm_index_ordered(node_when, idx, NULL);
469-
}
470-
LYD_TREE_DFS_END(node, iter);
471-
}
472-
if (count > node_when->count) {
473-
/* descendants were removed, refresh the iteration index */
474-
ly_set_contains(node_when, node, &i);
475-
}
492+
/* invalid data; only for multi-error validation keep the node in the tree
493+
* marked as when-false so XPath treats it as non-existent and validation can
494+
* continue without spurious cascading errors. In single-error validation this
495+
* is needless work because validation stops at this error. */
496+
if (val_opts & LYD_VALIDATE_MULTI_ERROR) {
497+
lyd_validate_when_false(node, node_when, node_types, &i);
476498
}
477499
LOGVAL(LYD_CTX(node), node, LY_VCODE_NOWHEN, disabled->cond->expr);
478500
r = LY_EVALID;

0 commit comments

Comments
 (0)