From ceb56839cc1fcab8c5f0b902c3f7d0e9e0949bdc Mon Sep 17 00:00:00 2001 From: bhumong Date: Thu, 30 Apr 2026 16:54:41 +0700 Subject: [PATCH 1/3] feat: add new test case yang namespace collision --- test/test_xml_bind_namespace_collision.sh | 197 ++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100755 test/test_xml_bind_namespace_collision.sh diff --git a/test/test_xml_bind_namespace_collision.sh b/test/test_xml_bind_namespace_collision.sh new file mode 100755 index 000000000..aa6c47c4b --- /dev/null +++ b/test/test_xml_bind_namespace_collision.sh @@ -0,0 +1,197 @@ +#!/usr/bin/env bash +# Reproduce sibling namespace collision during XML/YANG bind/translate. +# Two modules use the same local root/container/list names, but different +# namespaces. The UM branch is valid in its own module, but show/translate +# currently binds its subtree against the locald module. + +# Magic line must be first in script (see README.md) +s="$_" ; . ./lib.sh || if [ "$s" = "$0" ]; then exit 0; else return 0; fi + +APPNAME=example + +cfg=$dir/conf_yang.xml +clispec=$dir/clispec +mkdir -p "$clispec" + +cat < $cfg + + $cfg + *:* + ${YANG_INSTALLDIR} + $dir + $dir + $clispec + $APPNAME + $dir/$APPNAME.sock + $dir/$APPNAME.pidfile + $dir + +EOF + +cat < $dir/example_cli.cli +CLICON_MODE="$APPNAME"; +CLICON_PROMPT="%U@%H %W> "; + +show("Show a particular state of the system"){ + configuration("Show configuration"), cli_show_config("candidate", "xml", "/"); +} +quit("Quit"), cli_quit(); +EOF + +cat <<'EOF' > $dir/Cisco-IOS-XR-aaa-lib-cfg@2020-10-22.yang +module Cisco-IOS-XR-aaa-lib-cfg { + yang-version 1.1; + namespace "http://cisco.com/ns/yang/Cisco-IOS-XR-aaa-lib-cfg"; + prefix aaa-lib; + + revision 2020-10-22; + + container aaa; +} +EOF + +cat <<'EOF' > $dir/Cisco-IOS-XR-aaa-locald-cfg@2022-11-28.yang +module Cisco-IOS-XR-aaa-locald-cfg { + yang-version 1.1; + namespace "http://cisco.com/ns/yang/Cisco-IOS-XR-aaa-locald-cfg"; + prefix aaa-locald; + + import Cisco-IOS-XR-aaa-lib-cfg { + prefix aaa-lib; + } + + revision 2022-11-28; + + augment "/aaa-lib:aaa" { + container usernames { + list username { + key "ordering-index name"; + leaf ordering-index { + type uint32; + } + leaf name { + type string; + } + container secret { + leaf type { + type enumeration { + enum type10; + } + } + leaf secret10 { + when "../type = 'type10'"; + type string; + } + } + } + } + } +} +EOF + +cat <<'EOF' > $dir/Cisco-IOS-XR-um-aaa-cfg@2023-09-07.yang +module Cisco-IOS-XR-um-aaa-cfg { + yang-version 1.1; + namespace "http://cisco.com/ns/yang/Cisco-IOS-XR-um-aaa-cfg"; + prefix um-aaa; + + revision 2023-09-07; + + container aaa; +} +EOF + +cat <<'EOF' > $dir/Cisco-IOS-XR-um-aaa-task-user-cfg@2023-02-15.yang +module Cisco-IOS-XR-um-aaa-task-user-cfg { + yang-version 1.1; + namespace "http://cisco.com/ns/yang/Cisco-IOS-XR-um-aaa-task-user-cfg"; + prefix um-aaa-task-user; + + import Cisco-IOS-XR-um-aaa-cfg { + prefix um-aaa; + } + + revision 2023-02-15; + + augment "/um-aaa:aaa" { + container usernames { + list username { + key "ordering-index name"; + leaf ordering-index { + type uint32; + } + leaf name { + type string; + } + container secret { + leaf ten { + type string; + } + } + } + } + } +} +EOF + +cat <<'EOF' > $dir/startup_db + + + + + 0 + root + + type10 + xx + + + + + + + + 0 + root + + xx + + + + + +EOF + +new "test params: -f $cfg" +if [ $BE -ne 0 ]; then + new "kill old backend" + $clixon_backend -z -f $cfg >/dev/null 2>&1 || true + new "start backend -s startup -f $cfg" + $clixon_backend -D $DBG -s startup -f $cfg + if [ $? -ne 0 ]; then + err + fi +fi + +new "wait backend" +wait_backend + +new "show configuration reproduces namespace collision" +expectpart "$($clixon_cli -1 -f $cfg show configuration 2>&1)" 255 \ + "Failed to find YANG spec of XML node: ten with parent: secret" \ + "http://cisco.com/ns/yang/Cisco-IOS-XR-um-aaa-task-user-cfg" \ + "Cisco-IOS-XR-aaa-locald-cfg@2022-11-28.yang" \ + "ten" + +if [ $BE -ne 0 ]; then + new "Kill backend" + $clixon_backend -z -f $cfg + if [ $? -ne 0 ]; then + err "kill backend" + fi +fi + +rm -rf "$dir" + +new "endtest" +endtest From 3c7914e5a1f96205d8621b3048912a28b62ecd70 Mon Sep 17 00:00:00 2001 From: bhumong Date: Tue, 5 May 2026 10:31:45 +0700 Subject: [PATCH 2/3] fix(xml_bind): namespace collision --- lib/src/clixon_xml_bind.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/src/clixon_xml_bind.c b/lib/src/clixon_xml_bind.c index e7c1f0456..b79b54885 100644 --- a/lib/src/clixon_xml_bind.c +++ b/lib/src/clixon_xml_bind.c @@ -167,13 +167,22 @@ populate_self_parent(clixon_handle h, yang_stmt *yspec1; yang_stmt *ymod; int ret; + int ns_resolved = 0; name = xml_name(xt); /* optimization for massive lists - use the first element as role model */ if (xsibling && xml_child_nr_type(xt, CX_ATTR) == 0){ - y = xml_spec(xsibling); - goto set; + if ((y = xml_spec(xsibling)) != NULL){ + if (xml2ns(xt, xml_prefix(xt), &ns) < 0) + goto done; + ns_resolved++; + nsy = yang_find_mynamespace(y); + if (nsy != NULL && ns != NULL && strcmp(ns, nsy) == 0) + goto set; + y = NULL; + nsy = NULL; + } } if ((xp = xml_parent(xt)) == NULL){ if (xerr && @@ -193,7 +202,8 @@ populate_self_parent(clixon_handle h, retval = 2; goto done; } - if (xml2ns(xt, xml_prefix(xt), &ns) < 0) + if (!ns_resolved && + xml2ns(xt, xml_prefix(xt), &ns) < 0) goto done; /* Special case since action is not a datanode */ if ((y = yang_find(yparent, Y_ACTION, name)) == NULL){ From 846d7b9595fecb4b0f2a6f2cb4616321f9f96969 Mon Sep 17 00:00:00 2001 From: bhumong Date: Tue, 12 May 2026 10:14:33 +0700 Subject: [PATCH 3/3] fix: test fail on the newest build --- test/test_xml_bind_namespace_collision.sh | 37 ++++++++++++++--------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/test/test_xml_bind_namespace_collision.sh b/test/test_xml_bind_namespace_collision.sh index aa6c47c4b..a331b2628 100755 --- a/test/test_xml_bind_namespace_collision.sh +++ b/test/test_xml_bind_namespace_collision.sh @@ -9,10 +9,16 @@ s="$_" ; . ./lib.sh || if [ "$s" = "$0" ]; then exit 0; else return 0; fi APPNAME=example -cfg=$dir/conf_yang.xml -clispec=$dir/clispec +clispec=$dir/$APPNAME/clispec mkdir -p "$clispec" +dbdir=$(mktemp -d "$dir/${APPNAME}.xmldb.XXXXXX") +rundir=$(mktemp -d "$dir/${APPNAME}.run.XXXXXX") + +chmod 777 "$dbdir" "$rundir" + +cfg=$dir/conf_yang.xml + cat < $cfg $cfg @@ -22,18 +28,18 @@ cat < $cfg $dir $clispec $APPNAME - $dir/$APPNAME.sock - $dir/$APPNAME.pidfile - $dir + $rundir/$APPNAME.sock + $rundir/$APPNAME.pidfile + $dbdir EOF -cat < $dir/example_cli.cli +cat < $clispec/example_cli.cli CLICON_MODE="$APPNAME"; CLICON_PROMPT="%U@%H %W> "; show("Show a particular state of the system"){ - configuration("Show configuration"), cli_show_config("candidate", "xml", "/"); + configuration("Show configuration"), cli_show_config("running", "xml", "/"); } quit("Quit"), cli_quit(); EOF @@ -134,7 +140,7 @@ module Cisco-IOS-XR-um-aaa-task-user-cfg { } EOF -cat <<'EOF' > $dir/startup_db +cat <<'EOF' > $dbdir/startup_db @@ -176,12 +182,15 @@ fi new "wait backend" wait_backend -new "show configuration reproduces namespace collision" -expectpart "$($clixon_cli -1 -f $cfg show configuration 2>&1)" 255 \ - "Failed to find YANG spec of XML node: ten with parent: secret" \ - "http://cisco.com/ns/yang/Cisco-IOS-XR-um-aaa-task-user-cfg" \ - "Cisco-IOS-XR-aaa-locald-cfg@2022-11-28.yang" \ - "ten" +new "show configuration preserves namespace-specific secret leaves" +expectpart "$($clixon_cli -1 -f $cfg show configuration 2>&1)" 0 \ + "" \ + "" \ + "type10" \ + "xx" \ + "" \ + "" \ + "xx" if [ $BE -ne 0 ]; then new "Kill backend"