* Fixed problems with XPATH composite operations and functions in netconf get/get-config operations.

* See [XPATH issues #219](https://github.com/clicon/clixon/issues/219)
This commit is contained in:
Olof hagsand 2021-05-17 10:07:09 +02:00
parent 5baf8642ea
commit 376f2a8143
6 changed files with 65 additions and 22 deletions

View file

@ -65,6 +65,8 @@ Users may have to change how they access the system
### Corrected Bugs ### Corrected Bugs
* Fixed problems with XPATH composite operations and functions in netconf get/get-config operations.
* See [XPATH issues #219](https://github.com/clicon/clixon/issues/219)
* Fix Union in xpath [XPATH issues #219](https://github.com/clicon/clixon/issues/219) * Fix Union in xpath [XPATH issues #219](https://github.com/clicon/clixon/issues/219)
* Fix: XPath:s used in netconf (eg get-config) did not correctly access default values * Fix: XPath:s used in netconf (eg get-config) did not correctly access default values
* [RESTCONF GET request of single-key list with empty string returns all elements #213](https://github.com/clicon/clixon/issues/213) * [RESTCONF GET request of single-key list with empty string returns all elements #213](https://github.com/clicon/clixon/issues/213)

View file

@ -239,7 +239,7 @@ xpath_tree_print(FILE *f,
* @param[in] xs XPATH tree * @param[in] xs XPATH tree
* @param[out] xpath XPath string as CLIgen buf * @param[out] xpath XPath string as CLIgen buf
* @see xpath_tree_print * @see xpath_tree_print
* @note NOT COMPLETE, just simple xpaths eg a/b * @note XXX Not complete
*/ */
int int
xpath_tree2cbuf(xpath_tree *xs, xpath_tree2cbuf(xpath_tree *xs,
@ -248,22 +248,11 @@ xpath_tree2cbuf(xpath_tree *xs,
int retval = -1; int retval = -1;
switch (xs->xs_type){ switch (xs->xs_type){
case XP_NODE: /* s0 is namespace prefix, s1 is name */
if (xs->xs_s0)
cprintf(xcb, "%s:", xs->xs_s0);
cprintf(xcb, "%s", xs->xs_s1);
break;
case XP_ABSPATH: case XP_ABSPATH:
if (xs->xs_int == A_DESCENDANT_OR_SELF) if (xs->xs_int == A_DESCENDANT_OR_SELF)
cprintf(xcb, "/"); cprintf(xcb, "/");
cprintf(xcb, "/"); cprintf(xcb, "/");
break; break;
case XP_PRIME_STR:
cprintf(xcb, "'%s'", xs->xs_s0?xs->xs_s0:"");
break;
case XP_PRIME_NR:
cprintf(xcb, "%s", xs->xs_strnr?xs->xs_strnr:"0");
break;
case XP_STEP: case XP_STEP:
switch (xs->xs_int){ switch (xs->xs_int){
case A_SELF: case A_SELF:
@ -276,12 +265,34 @@ xpath_tree2cbuf(xpath_tree *xs,
break; break;
} }
break; break;
case XP_NODE: /* s0 is namespace prefix, s1 is name */
if (xs->xs_s0)
cprintf(xcb, "%s:", xs->xs_s0);
cprintf(xcb, "%s", xs->xs_s1);
break;
case XP_PRIME_NR:
cprintf(xcb, "%s", xs->xs_strnr?xs->xs_strnr:"0");
break;
case XP_PRIME_STR:
cprintf(xcb, "'%s'", xs->xs_s0?xs->xs_s0:"");
break;
case XP_PRIME_FN:
if (xs->xs_s0)
cprintf(xcb, "%s(", xs->xs_s0);
break;
default: default:
break; break;
} }
if (xs->xs_c0 && xpath_tree2cbuf(xs->xs_c0, xcb) < 0) if (xs->xs_c0 && xpath_tree2cbuf(xs->xs_c0, xcb) < 0)
goto done; goto done;
switch (xs->xs_type){ switch (xs->xs_type){
case XP_AND: /* and or */
case XP_ADD: /* div mod + * - */
case XP_RELEX: /* !=, >= <= < > = */
case XP_UNION:
if (xs->xs_c1)
cprintf(xcb, " %s ", clicon_int2str(xpopmap, xs->xs_int));
break;
case XP_RELLOCPATH: case XP_RELLOCPATH:
if (xs->xs_c1){ if (xs->xs_c1){
if (xs->xs_int == A_DESCENDANT_OR_SELF) if (xs->xs_int == A_DESCENDANT_OR_SELF)
@ -293,9 +304,9 @@ xpath_tree2cbuf(xpath_tree *xs,
if (xs->xs_c1) if (xs->xs_c1)
cprintf(xcb, "["); cprintf(xcb, "[");
break; break;
case XP_RELEX: case XP_EXP:
if (xs->xs_c1) if (xs->xs_c0 && xs->xs_c1) /* Function name and two arguments, insert , */
cprintf(xcb, "%s", clicon_int2str(xpopmap, xs->xs_int)); cprintf(xcb, ",");
break; break;
default: default:
break; break;
@ -307,6 +318,9 @@ xpath_tree2cbuf(xpath_tree *xs,
if (xs->xs_c1) if (xs->xs_c1)
cprintf(xcb, "]"); cprintf(xcb, "]");
break; break;
case XP_PRIME_FN:
if (xs->xs_s0)
cprintf(xcb, ")");
default: default:
break; break;
} }

View file

@ -80,6 +80,33 @@ expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get><filte
new "get xpath one" new "get xpath one"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get><filter type='xpath' select=\"/fi:x/fi:y[fi:a='1']\" xmlns:fi='urn:example:filter' /></get></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><data><x xmlns=\"urn:example:filter\"><y><a>1</a><b>1</b></y></x></data></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get><filter type='xpath' select=\"/fi:x/fi:y[fi:a='1']\" xmlns:fi='urn:example:filter' /></get></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><data><x xmlns=\"urn:example:filter\"><y><a>1</a><b>1</b></y></x></data></rpc-reply>]]>]]>$"
new "put more entries"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><x xmlns=\"urn:example:filter\"><y><a>3</a><b>1345</b></y><y><a>4</a><b>2567</b></y><y><a>5</a></y></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
new "netconf commit"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><commit/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
new "get xpath function not b=1"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get><filter type='xpath' select=\"/fi:x/fi:y[not(fi:b='1')]\" xmlns:fi='urn:example:filter' /></get></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><data><x xmlns=\"urn:example:filter\"><y><a>2</a><b>2</b></y><y><a>3</a><b>1345</b></y><y><a>4</a><b>2567</b></y><y><a>5</a></y></x></data></rpc-reply>]]>]]>$"
new "get xpath function not(b)"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get><filter type='xpath' select=\"/fi:x/fi:y[not(fi:b)]\" xmlns:fi='urn:example:filter' /></get></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><data><x xmlns=\"urn:example:filter\"><y><a>5</a></y></x></data></rpc-reply>]]>]]>$"
new "get xpath function contains"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get><filter type='xpath' select=\"/fi:x/fi:y[contains(fi:b,'2')]\" xmlns:fi='urn:example:filter' /></get></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><data><x xmlns=\"urn:example:filter\"><y><a>2</a><b>2</b></y><y><a>4</a><b>2567</b></y></x></data></rpc-reply>]]>]]>$"
new "get xpath function not(contains(fib,2))"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get><filter type='xpath' select=\"/fi:x/fi:y[not(contains(fi:b,'2'))]\" xmlns:fi='urn:example:filter' /></get></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><data><x xmlns=\"urn:example:filter\"><y><a>1</a><b>1</b></y><y><a>3</a><b>1345</b></y><y><a>5</a></y></x></data></rpc-reply>]]>]]>$"
new "get xpath function or"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get><filter type='xpath' select=\"/fi:x/fi:y[fi:a='3' or fi:b='2567']\" xmlns:fi='urn:example:filter' /></get></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><data><x xmlns=\"urn:example:filter\"><y><a>3</a><b>1345</b></y><y><a>4</a><b>2567</b></y></x></data></rpc-reply>]]>]]>$"
new "get xpath function and"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get><filter type='xpath' select=\"/fi:x/fi:y[not(fi:a='3') and contains(fi:b,'1')]\" xmlns:fi='urn:example:filter' /></get></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><data><x xmlns=\"urn:example:filter\"><y><a>1</a><b>1</b></y></x></data></rpc-reply>]]>]]>$"
new "get xpath function union"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get><filter type='xpath' select=\"/fi:x/fi:y[fi:b='1']|/fi:x/fi:y[fi:a='5']\" xmlns:fi='urn:example:filter' /></get></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><data><x xmlns=\"urn:example:filter\"><y><a>1</a><b>1</b></y><y><a>5</a></y></x></data></rpc-reply>]]>]]>$"
if [ $BE -ne 0 ]; then if [ $BE -ne 0 ]; then
new "Kill backend" new "Kill backend"
# Check if premature kill # Check if premature kill

View file

@ -13,7 +13,7 @@
# - IPv6 by default disabled since docker does not support it out-of-the box # - IPv6 by default disabled since docker does not support it out-of-the box
# (4) local/backend config. Native only # (4) local/backend config. Native only
# - The tests runs through both (if compiled with native) # - The tests runs through both (if compiled with native)
# See also test_restconf2.sh # See also test_restconf_op.sh
# See test_restconf_rpc.sh for cases when CLICON_BACKEND_RESTCONF_PROCESS is set # See test_restconf_rpc.sh for cases when CLICON_BACKEND_RESTCONF_PROCESS is set
# Magic line must be first in script (see README.md) # Magic line must be first in script (see README.md)

View file

@ -48,19 +48,19 @@ new "xpath canonical form (other)"
expectpart "$($clixon_util_xpath -c -y $ydir -p /i:x/j:y -n i:urn:example:a -n j:urn:example:b)" 0 '/a:x/b:y' '0 : a = "urn:example:a"' '1 : b = "urn:example:b"' expectpart "$($clixon_util_xpath -c -y $ydir -p /i:x/j:y -n i:urn:example:a -n j:urn:example:b)" 0 '/a:x/b:y' '0 : a = "urn:example:a"' '1 : b = "urn:example:b"'
new "xpath canonical form predicate 1" new "xpath canonical form predicate 1"
expectpart "$($clixon_util_xpath -c -y $ydir -p "/i:x[j:y='e1']" -n i:urn:example:a -n j:urn:example:b)" 0 "/a:x\[b:y='e1'\]" '0 : a = "urn:example:a"' '1 : b = "urn:example:b"' expectpart "$($clixon_util_xpath -c -y $ydir -p "/i:x[j:y='e1']" -n i:urn:example:a -n j:urn:example:b)" 0 "/a:x\[b:y = 'e1'\]" '0 : a = "urn:example:a"' '1 : b = "urn:example:b"'
new "xpath canonical form predicate self" new "xpath canonical form predicate self"
expectpart "$($clixon_util_xpath -c -y $ydir -p "/i:x[.='42']" -n i:urn:example:a -n j:urn:example:b)" 0 "/a:x\[.='42'\]" '0 : a = "urn:example:a"' expectpart "$($clixon_util_xpath -c -y $ydir -p "/i:x[.='42']" -n i:urn:example:a -n j:urn:example:b)" 0 "/a:x\[. = '42'\]" '0 : a = "urn:example:a"'
new "xpath canonical form descendants" new "xpath canonical form descendants"
expectpart "$($clixon_util_xpath -c -y $ydir -p "//x[.='42']" -n null:urn:example:a -n j:urn:example:b)" 0 "//a:x\[.='42'\]" '0 : a = "urn:example:a"' expectpart "$($clixon_util_xpath -c -y $ydir -p "//x[.='42']" -n null:urn:example:a -n j:urn:example:b)" 0 "//a:x\[. = '42'\]" '0 : a = "urn:example:a"'
new "xpath canonical form (no default should fail)" new "xpath canonical form (no default should fail)"
expectpart "$($clixon_util_xpath -c -y $ydir -p /x/j:y -n i:urn:example:a -n j:urn:example:b)" 255 expectpart "$($clixon_util_xpath -c -y $ydir -p /x/j:y -n i:urn:example:a -n j:urn:example:b 2> /dev/null)" 255
new "xpath canonical form (wrong namespace should fail)" new "xpath canonical form (wrong namespace should fail)"
expectpart "$($clixon_util_xpath -c -y $ydir -p /i:x/j:y -n i:urn:example:c -n j:urn:example:b)" 255 expectpart "$($clixon_util_xpath -c -y $ydir -p /i:x/j:y -n i:urn:example:c -n j:urn:example:b 2>/dev/null)" 255
rm -rf $dir rm -rf $dir

View file

@ -1,5 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# From both: # test xpath functions in YANG conditionals
# XPATH base https://www.w3.org/TR/xpath-10/ # XPATH base https://www.w3.org/TR/xpath-10/
# YANG XPATH functions: https://tools.ietf.org/html/rfc7950 # YANG XPATH functions: https://tools.ietf.org/html/rfc7950
# Tests: # Tests: