plugins types BUGFIX support for leafref values with both ' and "
diff --git a/src/plugins_types.c b/src/plugins_types.c
index 87515a9..6d83ca7 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -957,6 +957,7 @@
struct lyxp_expr *target_path = NULL;
struct lyxp_set set = {0};
const char *val_str, *xp_err_msg;
+ uint32_t i;
int r;
LY_CHECK_ARG_RET(NULL, lref, node, value, errmsg, LY_EINVAL);
@@ -968,19 +969,21 @@
/* get the canonical value */
val_str = lyd_value_get_canonical(LYD_CTX(node), value);
- /* get the path with the value */
- r = lyplg_type_resolve_leafref_get_target_path(lref->path, node->schema, LY_VALUE_SCHEMA_RESOLVED, lref->prefixes,
- val_str, &target_path);
- if (r == LY_ENOT) {
- goto cleanup;
- } else if (r) {
- rc = r;
- goto cleanup;
- }
+ if (!strchr(val_str, '\"') || !strchr(val_str, '\'')) {
+ /* get the path with the value */
+ r = lyplg_type_resolve_leafref_get_target_path(lref->path, node->schema, LY_VALUE_SCHEMA_RESOLVED, lref->prefixes,
+ val_str, &target_path);
+ if (r == LY_ENOT) {
+ goto cleanup;
+ } else if (r) {
+ rc = r;
+ goto cleanup;
+ }
+ } /* else value with both ' and ", XPath does not support that */
- /* find the target data instance */
- rc = lyxp_eval(LYD_CTX(node), target_path, node->schema->module, LY_VALUE_SCHEMA_RESOLVED, lref->prefixes,
- node, node, tree, NULL, &set, LYXP_IGNORE_WHEN);
+ /* find the target data instance(s) */
+ rc = lyxp_eval(LYD_CTX(node), target_path ? target_path : lref->path, node->schema->module,
+ LY_VALUE_SCHEMA_RESOLVED, lref->prefixes, node, node, tree, NULL, &set, LYXP_IGNORE_WHEN);
if (rc) {
if (ly_errcode(LYD_CTX(node)) == rc) {
xp_err_msg = ly_errmsg(LYD_CTX(node));
@@ -1001,7 +1004,25 @@
}
/* check the result */
- if (!set.used) {
+ if (target_path) {
+ /* no or exact match */
+ assert(!set.used || (set.used == 1));
+ i = 0;
+ } else {
+ /* check whether any matches */
+ for (i = 0; i < set.used; ++i) {
+ if (set.val.nodes[i].type != LYXP_NODE_ELEM) {
+ continue;
+ }
+
+ if (!lref->plugin->compare(&((struct lyd_node_term *)set.val.nodes[i].node)->value, value)) {
+ break;
+ }
+ }
+ }
+
+ if (i == set.used) {
+ /* no match found */
rc = LY_ENOTFOUND;
if (asprintf(errmsg, LY_ERRMSG_NOLREF_VAL, val_str, lref->path->expr) == -1) {
*errmsg = NULL;
@@ -1009,10 +1030,8 @@
}
goto cleanup;
}
- assert(set.used == 1);
-
if (target) {
- *target = set.val.nodes[0].node;
+ *target = set.val.nodes[i].node;
}
cleanup:
diff --git a/tests/utests/types/leafref.c b/tests/utests/types/leafref.c
index d304b2e..e208aec 100644
--- a/tests/utests/types/leafref.c
+++ b/tests/utests/types/leafref.c
@@ -64,8 +64,8 @@
static void
test_data_xml(void **state)
{
- const char *schema, *schema2, *data2;
- struct lyd_node *tree2;
+ const char *schema, *schema2, *schema3, *data;
+ struct lyd_node *tree;
/* xml test */
schema = MODULE_CREATE_YANG("defs", "leaf lref {type leafref {path /leaflisttarget; require-instance true;}}"
@@ -97,21 +97,35 @@
"<str-norestr xmlns=\"urn:tests:defs\">y</str-norestr>",
"defs", "xmlns:a=\"urn:tests:defs\"", "a:lref2", "y", STRING, "y");
- data2 = "<str-norestr xmlns=\"urn:tests:defs\">y</str-norestr>"
+ data = "<str-norestr xmlns=\"urn:tests:defs\">y</str-norestr>"
"<c xmlns=\"urn:tests:leafrefs\"><l><id>x</id><value>x</value><lr1>y</lr1></l></c>";
- CHECK_PARSE_LYD_PARAM(data2, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree2);
- CHECK_LYD_NODE_TERM((struct lyd_node_term *)lyd_child(lyd_child(tree2->next->next)->next)->next->next,
+ CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
+ CHECK_LYD_NODE_TERM((struct lyd_node_term *)lyd_child(lyd_child(tree->next->next)->next)->next->next,
0, 0, 0, 1, 1, STRING, "y");
- lyd_free_all(tree2);
+ lyd_free_all(tree);
- data2 = "<list xmlns=\"urn:tests:defs\"><id>x</id><targets>a</targets><targets>b</targets></list>"
+ data = "<list xmlns=\"urn:tests:defs\"><id>x</id><targets>a</targets><targets>b</targets></list>"
"<list xmlns=\"urn:tests:defs\"><id>y</id><targets>c</targets><targets>d</targets></list>"
"<c xmlns=\"urn:tests:leafrefs\"><x><x>y</x></x>"
"<l><id>x</id><value>x</value><lr3>c</lr3></l></c>";
- CHECK_PARSE_LYD_PARAM(data2, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree2);
- CHECK_LYD_NODE_TERM((struct lyd_node_term *)lyd_child(lyd_child(tree2->next->next->next)->next)->next->next,
+ CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
+ CHECK_LYD_NODE_TERM((struct lyd_node_term *)lyd_child(lyd_child(tree->next->next->next)->next)->next->next,
0, 0, 0, 1, 1, STRING, "c");
- lyd_free_all(tree2);
+ lyd_free_all(tree);
+
+ schema3 = MODULE_CREATE_YANG("simple", "leaf l1 {type leafref {path \"../target\";}}"
+ "leaf target {type string;}");
+ UTEST_ADD_MODULE(schema3, LYS_IN_YANG, NULL, NULL);
+
+ data = "<l1 xmlns=\"urn:tests:simple\">"*"'</l1>"
+ "<target xmlns=\"urn:tests:simple\">"*"'</target>";
+ CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
+ lyd_free_all(tree);
+
+ data = "<l1 xmlns=\"urn:tests:simple\">"*'"</l1>"
+ "<target xmlns=\"urn:tests:simple\">"*'"</target>";
+ CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
+ lyd_free_all(tree);
/* invalid value */
TEST_ERROR_XML2("<leaflisttarget xmlns=\"urn:tests:defs\">x</leaflisttarget>",
@@ -158,6 +172,32 @@
}
static void
+test_data_json(void **state)
+{
+ const char *schema, *data;
+ struct lyd_node *tree;
+
+ /* json test */
+ schema = MODULE_CREATE_YANG("simple", "leaf l1 {type leafref {path \"../target\";}}"
+ "leaf target {type string;}");
+ UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
+
+ data = "{"
+ " \"simple:l1\":\"\\\"*\\\"'\","
+ " \"simple:target\":\"\\\"*\\\"'\""
+ "}";
+ CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
+ lyd_free_all(tree);
+
+ data = "{"
+ " \"simple:l1\":\"\\\"*'\\\"\","
+ " \"simple:target\":\"\\\"*'\\\"\""
+ "}";
+ CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
+ lyd_free_all(tree);
+}
+
+static void
test_plugin_lyb(void **state)
{
const char *schema;
@@ -174,6 +214,7 @@
{
const struct CMUnitTest tests[] = {
UTEST(test_data_xml),
+ UTEST(test_data_json),
UTEST(test_plugin_lyb),
};