diff --git a/src/tree_data.c b/src/tree_data.c index 142b15db3..7f9c90cd5 100644 --- a/src/tree_data.c +++ b/src/tree_data.c @@ -102,7 +102,6 @@ lyd_parse(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct LY_ERR r = LY_SUCCESS, rc = LY_SUCCESS; struct lyd_ctx *lydctx = NULL; struct ly_set parsed = {0}; - struct lyd_node *first; uint32_t i, int_opts = 0; ly_bool subtree_sibling = 0; @@ -148,11 +147,9 @@ lyd_parse(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct } } - if (parent) { - /* get first top-level sibling */ - for (first = parent; first->parent; first = lyd_parent(first)) {} - first = lyd_first_sibling(first); - first_p = &first; + if (parent && parsed.count) { + /* use the first parsed node */ + first_p = &parsed.dnodes[0]; } if (!(parse_opts & LYD_PARSE_ONLY)) { diff --git a/src/validation.c b/src/validation.c index 7e678a265..418f5469a 100644 --- a/src/validation.c +++ b/src/validation.c @@ -1834,7 +1834,7 @@ lyd_validate(struct lyd_node **tree, const struct lys_module *module, const stru } /* validate new top-level nodes of this module, autodelete */ - r = lyd_validate_new(first2, NULL, mod, val_opts, diff); + r = lyd_validate_new(first2, *first2 ? lysc_data_parent((*first2)->schema) : NULL, mod, val_opts, diff); LY_VAL_ERR_GOTO(r, rc = r, val_opts, cleanup); /* add all top-level defaults for this module, if going to validate subtree, do not add into unres sets @@ -1846,7 +1846,7 @@ lyd_validate(struct lyd_node **tree, const struct lys_module *module, const stru if (val_opts & LYD_VALIDATE_NO_DEFAULTS) { impl_opts |= LYD_IMPLICIT_NO_DEFAULTS; } - r = lyd_new_implicit_r(NULL, first2, NULL, mod, validate_subtree ? NULL : node_when_p, + r = lyd_new_implicit_r(lyd_parent(*first2), first2, NULL, mod, validate_subtree ? NULL : node_when_p, validate_subtree ? NULL : node_types_p, validate_subtree ? NULL : ext_node_p, impl_opts, diff); LY_CHECK_ERR_GOTO(r, rc = r, cleanup); diff --git a/tests/utests/data/test_parser_xml.c b/tests/utests/data/test_parser_xml.c index d651253bf..4f33f0035 100644 --- a/tests/utests/data/test_parser_xml.c +++ b/tests/utests/data/test_parser_xml.c @@ -977,6 +977,38 @@ test_metadata(void **state) CHECK_LOG_CTX("Invalid enumeration value \"value\".", "Path \"/a:c/x/@a:attr\", line number 1."); } +static void +test_subtree(void **state) +{ + const char *data; + struct ly_in *in; + struct lyd_node *tree; + + /* prepare data with the parent */ + data = "\n" + " val_a\n" + " val_b\n" + " 1\n" + "\n"; + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree)); + + /* parse a subtree of it */ + data = "\n" + " true\n" + "\n"; + assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); + assert_int_equal(LY_SUCCESS, lyd_parse_data(UTEST_LYCTX, tree, in, LYD_XML, 0, LYD_VALIDATE_PRESENT, NULL)); + ly_in_free(in, 0); + + /* parse another container, fails */ + assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in)); + assert_int_equal(LY_EVALID, lyd_parse_data(UTEST_LYCTX, tree, in, LYD_XML, 0, LYD_VALIDATE_PRESENT, NULL)); + ly_in_free(in, 0); + CHECK_LOG_CTX("Duplicate instance of \"cont\".", "Data location \"/a:l1[a='val_a'][b='val_b'][c='1']/cont\"."); + + lyd_free_all(tree); +} + int main(void) { @@ -999,6 +1031,7 @@ main(void) UTEST(test_filter_attributes, setup), UTEST(test_data_skip, setup), UTEST(test_metadata, setup), + UTEST(test_subtree, setup), }; return cmocka_run_group_tests(tests, NULL, NULL); diff --git a/tests/utests/data/test_validation.c b/tests/utests/data/test_validation.c index a953330c9..d02dcc4e1 100644 --- a/tests/utests/data/test_validation.c +++ b/tests/utests/data/test_validation.c @@ -1203,6 +1203,7 @@ test_multi_error(void **state) CHECK_LOG_CTX_APPTAG("l leaf is not left", "Data location \"/ii:cont/l3\".", "not-left"); CHECK_LOG_CTX_APPTAG("Must condition \"../l = 'right'\" not satisfied.", "Data location \"/ii:cont/l2\".", "must-violation"); CHECK_LOG_CTX_APPTAG("Duplicate instance of \"l\".", "Data location \"/ii:cont/l\", line number 7.", NULL); + CHECK_LOG_CTX_APPTAG("Duplicate instance of \"l\".", "Data location \"/ii:cont/l\", line number 7.", NULL); CHECK_LOG_CTX_APPTAG("Invalid type uint32 value \"ahoy\".", "Data location \"/ii:cont/ll\", line number 6.", NULL); /* json */ @@ -1220,6 +1221,7 @@ test_multi_error(void **state) CHECK_LOG_CTX_APPTAG("l leaf is not left", "Data location \"/ii:cont/l3\".", "not-left"); CHECK_LOG_CTX_APPTAG("Must condition \"../l = 'right'\" not satisfied.", "Data location \"/ii:cont/l2\".", "must-violation"); CHECK_LOG_CTX_APPTAG("Duplicate instance of \"l\".", "Data location \"/ii:cont/l\", line number 9.", NULL); + CHECK_LOG_CTX_APPTAG("Duplicate instance of \"l\".", "Data location \"/ii:cont/l\", line number 9.", NULL); CHECK_LOG_CTX_APPTAG("Invalid non-number-encoded uint32 value \"ahoy\".", "Data location \"/ii:cont/ll\", line number 7.", NULL); /* validation */ @@ -1239,6 +1241,7 @@ test_multi_error(void **state) CHECK_LOG_CTX_APPTAG("l leaf is not left", "Data location \"/ii:cont/l3\".", "not-left"); CHECK_LOG_CTX_APPTAG("Must condition \"../l = 'right'\" not satisfied.", "Data location \"/ii:cont/l2\".", "must-violation"); CHECK_LOG_CTX_APPTAG("Duplicate instance of \"l\".", "Data location \"/ii:cont/l\".", NULL); + CHECK_LOG_CTX_APPTAG("Duplicate instance of \"l\".", "Data location \"/ii:cont/l\".", NULL); } const char *schema_j =