Skip to content

Commit 83f4849

Browse files
authored
tree_data BUGFIX union leafref linking (#2424)
This patch fixes the problem of missing leafref linking in case of using leafref within union types
1 parent 1f45a87 commit 83f4849

File tree

2 files changed

+103
-37
lines changed

2 files changed

+103
-37
lines changed

src/tree_data.c

Lines changed: 57 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3825,17 +3825,65 @@ lyd_link_leafref_node(const struct lyd_node_term *node, const struct lyd_node_te
38253825
return LY_SUCCESS;
38263826
}
38273827

3828+
/**
3829+
* @brief Traverse through data tree node suitable types and adds leafrefs links to the given nodes
3830+
*
3831+
* This API requires usage of ::LY_CTX_LEAFREF_LINKING context flag.
3832+
*
3833+
* @param[in] tree The data tree root node.
3834+
* @param[in] cur_node The current data node.
3835+
* @param[in] value The current node value.
3836+
* @param[in] type The leaf/leaf-list type of given data node.
3837+
*
3838+
* @return LY_SUCCESS on success.
3839+
* @return LY_ERR value on error.
3840+
*/
3841+
static LY_ERR
3842+
lyd_leafref_link_node_tree_type(const struct lyd_node *tree, const struct lyd_node *cur_node, struct lyd_value *value, const struct lysc_type *type)
3843+
{
3844+
char *errmsg;
3845+
struct ly_set *targets = NULL;
3846+
LY_ERR ret = LY_SUCCESS;
3847+
struct lysc_type_leafref *lref;
3848+
struct lysc_type_union *un;
3849+
LY_ARRAY_COUNT_TYPE u;
3850+
uint32_t i;
3851+
struct lyd_node_term *leafref_node = (struct lyd_node_term *)cur_node;
3852+
3853+
if (type->basetype == LY_TYPE_LEAFREF) {
3854+
lref = (struct lysc_type_leafref *)type;
3855+
ly_set_free(targets, NULL);
3856+
if (lyplg_type_resolve_leafref(lref, cur_node, value, tree, NULL, &targets, &errmsg)) {
3857+
/* leafref target not found */
3858+
free(errmsg);
3859+
} else {
3860+
/* leafref target found, link it */
3861+
for (i = 0; i < targets->count; ++i) {
3862+
if (targets->dnodes[i]->schema->nodetype & LYD_NODE_TERM) {
3863+
ret = lyd_link_leafref_node((struct lyd_node_term *)targets->dnodes[i], leafref_node);
3864+
LY_CHECK_GOTO(ret, cleanup);
3865+
}
3866+
}
3867+
}
3868+
} else if (type->basetype == LY_TYPE_UNION) {
3869+
un = (struct lysc_type_union *)type;
3870+
LY_ARRAY_FOR(un->types, u) {
3871+
ret = lyd_leafref_link_node_tree_type(tree, cur_node, &leafref_node->value.subvalue->value, un->types[u]);
3872+
LY_CHECK_GOTO(ret, cleanup)
3873+
}
3874+
}
3875+
3876+
cleanup:
3877+
ly_set_free(targets, NULL);
3878+
return ret;
3879+
}
3880+
38283881
LIBYANG_API_DEF LY_ERR
38293882
lyd_leafref_link_node_tree(const struct lyd_node *tree)
38303883
{
38313884
const struct lyd_node *sibling, *elem;
3832-
struct ly_set *targets = NULL;
3833-
char *errmsg;
3834-
struct lyd_node_term *leafref_node;
3885+
struct lyd_node_term *cur_node;
38353886
struct lysc_node_leaf *leaf_schema;
3836-
struct lysc_type_leafref *lref;
3837-
LY_ERR ret = LY_SUCCESS;
3838-
uint32_t i;
38393887

38403888
LY_CHECK_ARG_RET(NULL, tree, LY_EINVAL);
38413889

@@ -3846,33 +3894,15 @@ lyd_leafref_link_node_tree(const struct lyd_node *tree)
38463894
LY_LIST_FOR(tree, sibling) {
38473895
LYD_TREE_DFS_BEGIN(sibling, elem) {
38483896
if (elem->schema && (elem->schema->nodetype & LYD_NODE_TERM)) {
3849-
leafref_node = (struct lyd_node_term *)elem;
38503897
leaf_schema = (struct lysc_node_leaf *)elem->schema;
3851-
3852-
if (leaf_schema->type->basetype == LY_TYPE_LEAFREF) {
3853-
lref = (struct lysc_type_leafref *)leaf_schema->type;
3854-
ly_set_free(targets, NULL);
3855-
if (lyplg_type_resolve_leafref(lref, elem, &leafref_node->value, tree, NULL, &targets, &errmsg)) {
3856-
/* leafref target not found */
3857-
free(errmsg);
3858-
} else {
3859-
/* leafref target found, link it */
3860-
for (i = 0; i < targets->count; ++i) {
3861-
if (targets->dnodes[i]->schema->nodetype & LYD_NODE_TERM) {
3862-
ret = lyd_link_leafref_node((struct lyd_node_term *)targets->dnodes[i], leafref_node);
3863-
LY_CHECK_GOTO(ret, cleanup);
3864-
}
3865-
}
3866-
}
3867-
}
3898+
cur_node = (struct lyd_node_term *)elem;
3899+
LY_CHECK_RET(lyd_leafref_link_node_tree_type(tree, elem, &cur_node->value, leaf_schema->type));
38683900
}
38693901
LYD_TREE_DFS_END(sibling, elem);
38703902
}
38713903
}
38723904

3873-
cleanup:
3874-
ly_set_free(targets, NULL);
3875-
return ret;
3905+
return LY_SUCCESS;
38763906
}
38773907

38783908
LY_ERR

tests/utests/data/test_tree_data.c

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,7 @@ static void
596596
test_data_leafref_nodes(void **state)
597597
{
598598
struct lyd_node *tree, *iter;
599-
struct lyd_node_term *target_node = NULL, *leafref_node;
599+
struct lyd_node_term *target_node = NULL, *leafref_node, *leafref_node2;
600600
const struct lyd_leafref_links_rec *rec;
601601
const char *schema, *data, *value;
602602

@@ -622,6 +622,14 @@ test_data_leafref_nodes(void **state)
622622
" path \"../ll\";"
623623
" }"
624624
" }"
625+
" leaf ref3 {"
626+
" type union {"
627+
" type leafref {"
628+
" path \"../ll\";"
629+
" }"
630+
" type string;"
631+
" }"
632+
" }"
625633
"}";
626634

627635
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
@@ -630,11 +638,12 @@ test_data_leafref_nodes(void **state)
630638
"{"
631639
" \"test-data-hash:ll\": [\"qwe\", \"asd\"],"
632640
" \"test-data-hash:c1\": { \"ref1\": \"qwe\"},"
633-
" \"test-data-hash:ref2\": \"asd\""
641+
" \"test-data-hash:ref2\": \"asd\","
642+
" \"test-data-hash:ref3\": \"asd\""
634643
"}";
635644

636645
/* The run must not crash due to the assert that checks the hash. */
637-
CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
646+
CHECK_PARSE_LYD_PARAM(data, LYD_JSON, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
638647
LY_LIST_FOR(tree, iter) {
639648
if (strcmp(iter->schema->name, "ll") == 0) {
640649
value = lyd_get_value(iter);
@@ -645,46 +654,73 @@ test_data_leafref_nodes(void **state)
645654
if (strcmp(iter->schema->name, "ref2") == 0) {
646655
leafref_node = (struct lyd_node_term *)iter;
647656
}
657+
if (strcmp(iter->schema->name, "ref3") == 0) {
658+
leafref_node2 = (struct lyd_node_term *)iter;
659+
}
648660
}
649661

650662
/* verify state after leafref plugin validation */
651663
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(target_node, &rec));
652-
assert_int_equal(1, LY_ARRAY_COUNT(rec->leafref_nodes));
653-
assert_ptr_equal(rec->leafref_nodes[0], leafref_node);
664+
assert_int_equal(2, LY_ARRAY_COUNT(rec->leafref_nodes));
665+
assert_ptr_equal(rec->leafref_nodes[1], leafref_node);
666+
assert_ptr_equal(rec->leafref_nodes[0], leafref_node2);
654667
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(leafref_node, &rec));
655668
assert_int_equal(1, LY_ARRAY_COUNT(rec->target_nodes));
656669
assert_ptr_equal(rec->target_nodes[0], target_node);
670+
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(leafref_node2, &rec));
671+
assert_int_equal(1, LY_ARRAY_COUNT(rec->target_nodes));
672+
assert_ptr_equal(rec->target_nodes[0], target_node);
657673
/* value modification of target */
658674
assert_int_equal(LY_SUCCESS, lyd_change_term((struct lyd_node *)target_node, "ASD"));
659675
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(target_node, &rec));
660676
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(leafref_node, &rec));
677+
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(leafref_node2, &rec));
661678
/* change back to original value */
662679
assert_int_equal(LY_SUCCESS, lyd_change_term((struct lyd_node *)target_node, "asd"));
663680
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(target_node, &rec));
664681
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(leafref_node, &rec));
682+
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(leafref_node2, &rec));
665683
/* linking the whole tree again */
666684
assert_int_equal(LY_SUCCESS, lyd_leafref_link_node_tree(tree));
667685
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(target_node, &rec));
668-
assert_int_equal(1, LY_ARRAY_COUNT(rec->leafref_nodes));
686+
assert_int_equal(2, LY_ARRAY_COUNT(rec->leafref_nodes));
669687
assert_ptr_equal(rec->leafref_nodes[0], leafref_node);
688+
assert_ptr_equal(rec->leafref_nodes[1], leafref_node2);
670689
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(leafref_node, &rec));
671690
assert_int_equal(1, LY_ARRAY_COUNT(rec->target_nodes));
672691
assert_ptr_equal(rec->target_nodes[0], target_node);
692+
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(leafref_node2, &rec));
693+
assert_int_equal(1, LY_ARRAY_COUNT(rec->target_nodes));
694+
assert_ptr_equal(rec->target_nodes[0], target_node);
673695
/* value modification of leafref */
674696
assert_int_equal(LY_SUCCESS, lyd_change_term((struct lyd_node *)leafref_node, "qwe"));
675-
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(target_node, &rec));
676697
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(leafref_node, &rec));
698+
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(target_node, &rec));
699+
assert_int_equal(1, LY_ARRAY_COUNT(rec->leafref_nodes));
700+
assert_ptr_equal(rec->leafref_nodes[0], leafref_node2);
701+
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(leafref_node2, &rec));
702+
assert_int_equal(1, LY_ARRAY_COUNT(rec->target_nodes));
703+
assert_ptr_equal(rec->target_nodes[0], target_node);
677704
assert_int_equal(LY_SUCCESS, lyd_change_term((struct lyd_node *)leafref_node, "asd"));
678-
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(target_node, &rec));
679705
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(leafref_node, &rec));
706+
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(target_node, &rec));
707+
assert_int_equal(1, LY_ARRAY_COUNT(rec->leafref_nodes));
708+
assert_ptr_equal(rec->leafref_nodes[0], leafref_node2);
709+
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(leafref_node2, &rec));
710+
assert_int_equal(1, LY_ARRAY_COUNT(rec->target_nodes));
711+
assert_ptr_equal(rec->target_nodes[0], target_node);
680712
/* linking the whole tree again */
681713
assert_int_equal(LY_SUCCESS, lyd_leafref_link_node_tree(tree));
682714
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(target_node, &rec));
683-
assert_int_equal(1, LY_ARRAY_COUNT(rec->leafref_nodes));
684-
assert_ptr_equal(rec->leafref_nodes[0], leafref_node);
715+
assert_int_equal(2, LY_ARRAY_COUNT(rec->leafref_nodes));
716+
assert_ptr_equal(rec->leafref_nodes[1], leafref_node);
717+
assert_ptr_equal(rec->leafref_nodes[0], leafref_node2);
685718
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(leafref_node, &rec));
686719
assert_int_equal(1, LY_ARRAY_COUNT(rec->target_nodes));
687720
assert_ptr_equal(rec->target_nodes[0], target_node);
721+
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(leafref_node2, &rec));
722+
assert_int_equal(1, LY_ARRAY_COUNT(rec->target_nodes));
723+
assert_ptr_equal(rec->target_nodes[0], target_node);
688724
/* freeing whole tree */
689725
lyd_free_all(tree);
690726
}

0 commit comments

Comments
 (0)