* xml_cmp() respects 'ordered-by user' for state nodes, which violates RFC 7950 [https://github.com/clicon/clixon/issues/63. (Thanks JDL)
This commit is contained in:
parent
376b75328c
commit
02d725b2c0
10 changed files with 85 additions and 53 deletions
|
|
@ -142,6 +142,7 @@
|
||||||
* <!DOCTYPE (ie DTD) is not supported.
|
* <!DOCTYPE (ie DTD) is not supported.
|
||||||
|
|
||||||
### Corrected Bugs
|
### Corrected Bugs
|
||||||
|
* xml_cmp() respects 'ordered-by user' for state nodes, which violates RFC 7950 [https://github.com/clicon/clixon/issues/63. (Thanks JDL)
|
||||||
* XML<>JSON conversion problems [https://github.com/clicon/clixon/issues/66]
|
* XML<>JSON conversion problems [https://github.com/clicon/clixon/issues/66]
|
||||||
* CDATA sections stripped from XML when converted to JSON
|
* CDATA sections stripped from XML when converted to JSON
|
||||||
* Restconf returns error when RPC generates "ok" reply [https://github.com/clicon/clixon/issues/69]
|
* Restconf returns error when RPC generates "ok" reply [https://github.com/clicon/clixon/issues/69]
|
||||||
|
|
|
||||||
|
|
@ -201,6 +201,8 @@ example_statedata(clicon_handle h,
|
||||||
*/
|
*/
|
||||||
if (xml_parse_string("<state xmlns=\"urn:example:clixon\">"
|
if (xml_parse_string("<state xmlns=\"urn:example:clixon\">"
|
||||||
"<op>42</op>"
|
"<op>42</op>"
|
||||||
|
"<op>41</op>"
|
||||||
|
"<op>43</op>" /* should not be ordered */
|
||||||
"</state>", NULL, &xstate) < 0)
|
"</state>", NULL, &xstate) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,6 @@
|
||||||
* Prototypes
|
* Prototypes
|
||||||
*/
|
*/
|
||||||
int xml_child_spec(cxobj *x, cxobj *xp, yang_spec *yspec, yang_stmt **yp);
|
int xml_child_spec(cxobj *x, cxobj *xp, yang_spec *yspec, yang_stmt **yp);
|
||||||
int xml_cmp(const void* arg1, const void* arg2);
|
|
||||||
int xml_sort(cxobj *x0, void *arg);
|
int xml_sort(cxobj *x0, void *arg);
|
||||||
cxobj *xml_search(cxobj *x, char *name, int yangi, enum rfc_6020 keyword, int keynr, char **keyvec, char **keyval);
|
cxobj *xml_search(cxobj *x, char *name, int yangi, enum rfc_6020 keyword, int keynr, char **keyvec, char **keyval);
|
||||||
int xml_insert_pos(cxobj *x0, char *name, int yangi, enum rfc_6020 keyword,
|
int xml_insert_pos(cxobj *x0, char *name, int yangi, enum rfc_6020 keyword,
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,7 @@ xml_child_spec(cxobj *x,
|
||||||
* @see xml_cmp1 Similar, but for one object
|
* @see xml_cmp1 Similar, but for one object
|
||||||
* @note empty value/NULL is smallest value
|
* @note empty value/NULL is smallest value
|
||||||
*/
|
*/
|
||||||
int
|
static int
|
||||||
xml_cmp(const void* arg1,
|
xml_cmp(const void* arg1,
|
||||||
const void* arg2)
|
const void* arg2)
|
||||||
{
|
{
|
||||||
|
|
@ -162,11 +162,13 @@ xml_cmp(const void* arg1,
|
||||||
if ((equal = yi1-yi2) != 0)
|
if ((equal = yi1-yi2) != 0)
|
||||||
return equal;
|
return equal;
|
||||||
}
|
}
|
||||||
/* Now y1=y2, same Yang spec, can only be list or leaf-list,
|
/* Now y1==y2, same Yang spec, can only be list or leaf-list,
|
||||||
* sort according to key
|
* But first check exceptions, eg config false or ordered-by user
|
||||||
|
* otherwuse sort according to key
|
||||||
*/
|
*/
|
||||||
if (yang_find((yang_node*)y1, Y_ORDERED_BY, "user") != NULL)
|
if (yang_config(y1)==0 ||
|
||||||
return 0; /* Ordered by user: maintain existing order */
|
yang_find((yang_node*)y1, Y_ORDERED_BY, "user") != NULL)
|
||||||
|
return 0; /* Ordered by user or state data : maintain existing order */
|
||||||
switch (y1->ys_keyword){
|
switch (y1->ys_keyword){
|
||||||
case Y_LEAF_LIST: /* Match with name and value */
|
case Y_LEAF_LIST: /* Match with name and value */
|
||||||
if ((b1 = xml_body(x1)) == NULL)
|
if ((b1 = xml_body(x1)) == NULL)
|
||||||
|
|
@ -262,11 +264,20 @@ xml_cmp1(cxobj *x,
|
||||||
* Assume populated by yang spec.
|
* Assume populated by yang spec.
|
||||||
* @param[in] x0 XML node
|
* @param[in] x0 XML node
|
||||||
* @param[in] arg Dummy so it can be called by xml_apply()
|
* @param[in] arg Dummy so it can be called by xml_apply()
|
||||||
|
* @retval -1 Error, aborted at first error encounter
|
||||||
|
* @retval 0 OK, all nodes traversed (subparts may have been skipped)
|
||||||
|
* @retval 1 OK, aborted on first fn returned 1
|
||||||
|
* @see xml_apply - typically called by recursive apply function
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xml_sort(cxobj *x,
|
xml_sort(cxobj *x,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
|
yang_stmt *ys;
|
||||||
|
|
||||||
|
/* Abort sort if non-config (=state) data */
|
||||||
|
if ((ys = xml_spec(x)) != 0 && yang_config(ys)==0)
|
||||||
|
return 1;
|
||||||
qsort(xml_childvec_get(x), xml_child_nr(x), sizeof(cxobj *), xml_cmp);
|
qsort(xml_childvec_get(x), xml_child_nr(x), sizeof(cxobj *), xml_cmp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -543,7 +554,13 @@ xml_sort_verify(cxobj *x0,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cxobj *x = NULL;
|
cxobj *x = NULL;
|
||||||
cxobj *xprev = NULL;
|
cxobj *xprev = NULL;
|
||||||
|
yang_stmt *ys;
|
||||||
|
|
||||||
|
/* Abort sort if non-config (=state) data */
|
||||||
|
if ((ys = xml_spec(x0)) != 0 && yang_config(ys)==0){
|
||||||
|
retval = 1;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
while ((x = xml_child_each(x0, x, -1)) != NULL) {
|
while ((x = xml_child_each(x0, x, -1)) != NULL) {
|
||||||
if (xprev != NULL){ /* Check xprev <= x */
|
if (xprev != NULL){ /* Check xprev <= x */
|
||||||
if (xml_cmp(&xprev, &x) > 0)
|
if (xml_cmp(&xprev, &x) > 0)
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ fi
|
||||||
|
|
||||||
# Note order of features in ietf-netconf yang is alphabetically: candidate, startup, validate, xpath
|
# Note order of features in ietf-netconf yang is alphabetically: candidate, startup, validate, xpath
|
||||||
new "netconf module ietf-netconf"
|
new "netconf module ietf-netconf"
|
||||||
expect="<module><name>ietf-netconf</name><revision>2011-06-01</revision><namespace>urn:ietf:params:xml:ns:netconf:base:1.0</namespace><feature>candidate</feature><feature>startup</feature><feature>validate</feature><feature>xpath</feature><conformance-type>implement</conformance-type></module>"
|
expect="<module><name>ietf-netconf</name><revision>2011-06-01</revision><namespace>urn:ietf:params:xml:ns:netconf:base:1.0</namespace><feature>candidate</feature><feature>validate</feature><feature>startup</feature><feature>xpath</feature><conformance-type>implement</conformance-type></module>"
|
||||||
match=`echo "$ret" | grep -GZo "$expect"`
|
match=`echo "$ret" | grep -GZo "$expect"`
|
||||||
if [ -z "$match" ]; then
|
if [ -z "$match" ]; then
|
||||||
err "$expect" "$ret"
|
err "$expect" "$ret"
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ sudo su -c "$clixon_restconf -f $cfg -D $DBG -- -a" -s /bin/sh www-data &
|
||||||
sleep $RCWAIT
|
sleep $RCWAIT
|
||||||
|
|
||||||
new "auth get"
|
new "auth get"
|
||||||
expecteq "$(curl -u andy:bar -sS -X GET http://localhost/restconf/data/clixon-example:state)" '{"clixon-example:state": {"op": "42"}}
|
expecteq "$(curl -u andy:bar -sS -X GET http://localhost/restconf/data/clixon-example:state)" '{"clixon-example:state": {"op": ["42","41","43"]}}
|
||||||
'
|
'
|
||||||
|
|
||||||
new "Set x to 0"
|
new "Set x to 0"
|
||||||
|
|
|
||||||
|
|
@ -175,7 +175,7 @@ expecteq "$(curl -u andy:bar -sS -X GET http://localhost/restconf/data/nacm-exam
|
||||||
'
|
'
|
||||||
|
|
||||||
new "admin read state OK"
|
new "admin read state OK"
|
||||||
expecteq "$(curl -u andy:bar -sS -X GET http://localhost/restconf/data/clixon-example:state)" '{"clixon-example:state": {"op": "42"}}
|
expecteq "$(curl -u andy:bar -sS -X GET http://localhost/restconf/data/clixon-example:state)" '{"clixon-example:state": {"op": ["42","41","43"]}}
|
||||||
'
|
'
|
||||||
|
|
||||||
new "admin read top ok (all)"
|
new "admin read top ok (all)"
|
||||||
|
|
@ -204,11 +204,11 @@ expecteq "$(curl -u wilma:bar -sS -X GET http://localhost/restconf/data/nacm-exa
|
||||||
'
|
'
|
||||||
|
|
||||||
new "limit read state OK"
|
new "limit read state OK"
|
||||||
expecteq "$(curl -u wilma:bar -sS -X GET http://localhost/restconf/data/clixon-example:state)" '{"clixon-example:state": {"op": "42"}}
|
expecteq "$(curl -u wilma:bar -sS -X GET http://localhost/restconf/data/clixon-example:state)" '{"clixon-example:state": {"op": ["42","41","43"]}}
|
||||||
'
|
'
|
||||||
|
|
||||||
new "limit read top ok (part)"
|
new "limit read top ok (part)"
|
||||||
expecteq "$(curl -u wilma:bar -sS -X GET http://localhost/restconf/data)" '{"data": {"clixon-example:translate": [{"k": "key42","value": "val42"},{ "k": "key43","value": "val43"}],"clixon-example:state": {"op": "42"}}}
|
expecteq "$(curl -u wilma:bar -sS -X GET http://localhost/restconf/data)" '{"data": {"clixon-example:translate": [{"k": "key42","value": "val42"},{ "k": "key43","value": "val43"}],"clixon-example:state": {"op": ["42","41","43"]}}}
|
||||||
'
|
'
|
||||||
|
|
||||||
#user:guest
|
#user:guest
|
||||||
|
|
|
||||||
|
|
@ -155,7 +155,7 @@ new "netconf edit state operation should fail"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><state xmlns="urn:example:clixon"><op>42</op></state></config></edit-config></rpc>]]>]]>' "^<rpc-reply><rpc-error><error-type>protocol</error-type><error-tag>invalid-value</error-tag>"
|
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><state xmlns="urn:example:clixon"><op>42</op></state></config></edit-config></rpc>]]>]]>' "^<rpc-reply><rpc-error><error-type>protocol</error-type><error-tag>invalid-value</error-tag>"
|
||||||
|
|
||||||
new "netconf get state operation"
|
new "netconf get state operation"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><get><filter type=\"xpath\" select=\"/state\"/></get></rpc>]]>]]>" '^<rpc-reply><data><state xmlns="urn:example:clixon"><op>42</op></state></data></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><get><filter type=\"xpath\" select=\"/state\"/></get></rpc>]]>]]>" '^<rpc-reply><data><state xmlns="urn:example:clixon"><op>42</op><op>41</op><op>43</op></state></data></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
new "netconf lock/unlock"
|
new "netconf lock/unlock"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><lock><target><candidate/></target></lock></rpc>]]>]]><rpc><unlock><target><candidate/></target></unlock></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]><rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><lock><target><candidate/></target></lock></rpc>]]>]]><rpc><unlock><target><candidate/></target></unlock></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]><rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ APPNAME=example
|
||||||
. ./lib.sh
|
. ./lib.sh
|
||||||
cfg=$dir/conf_yang.xml
|
cfg=$dir/conf_yang.xml
|
||||||
fyang=$dir/order.yang
|
fyang=$dir/order.yang
|
||||||
|
tmp=$dir/tmp.x
|
||||||
|
|
||||||
# For memcheck
|
# For memcheck
|
||||||
# clixon_netconf="valgrind --leak-check=full --show-leak-kinds=all clixon_netconf"
|
# clixon_netconf="valgrind --leak-check=full --show-leak-kinds=all clixon_netconf"
|
||||||
|
|
@ -30,6 +31,7 @@ cat <<EOF > $cfg
|
||||||
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||||
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
||||||
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
||||||
|
<CLICON_BACKEND_DIR>/usr/local/lib/example/backend</CLICON_BACKEND_DIR>
|
||||||
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||||
<CLICON_CLI_GENMODEL_COMPLETION>1</CLICON_CLI_GENMODEL_COMPLETION>
|
<CLICON_CLI_GENMODEL_COMPLETION>1</CLICON_CLI_GENMODEL_COMPLETION>
|
||||||
<CLICON_XMLDB_DIR>$dbdir</CLICON_XMLDB_DIR>
|
<CLICON_XMLDB_DIR>$dbdir</CLICON_XMLDB_DIR>
|
||||||
|
|
@ -39,10 +41,13 @@ cat <<EOF > $cfg
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
cat <<EOF > $fyang
|
cat <<EOF > $fyang
|
||||||
module example{
|
module order-example{
|
||||||
yang-version 1.1;
|
yang-version 1.1;
|
||||||
namespace "urn:example:clixon";
|
namespace "urn:example:order";
|
||||||
prefix ex;
|
prefix ex;
|
||||||
|
import clixon-example { /* for state callback */
|
||||||
|
prefix ex;
|
||||||
|
}
|
||||||
container c{
|
container c{
|
||||||
leaf d{
|
leaf d{
|
||||||
type string;
|
type string;
|
||||||
|
|
@ -86,24 +91,24 @@ rm -f $dbdir/candidate_db
|
||||||
# alt
|
# alt
|
||||||
cat <<EOF > $dbdir/running_db
|
cat <<EOF > $dbdir/running_db
|
||||||
<config>
|
<config>
|
||||||
<y0 xmlns="urn:example:clixon">d</y0>
|
<y0 xmlns="urn:example:order">d</y0>
|
||||||
<y1 xmlns="urn:example:clixon">d</y1>
|
<y1 xmlns="urn:example:order">d</y1>
|
||||||
<y2 xmlns="urn:example:clixon"><k>d</k><a>bar</a></y2>
|
<y2 xmlns="urn:example:order"><k>d</k><a>bar</a></y2>
|
||||||
<y3 xmlns="urn:example:clixon"><k>d</k><a>bar</a></y3>
|
<y3 xmlns="urn:example:order"><k>d</k><a>bar</a></y3>
|
||||||
<y0 xmlns="urn:example:clixon">b</y0>
|
<y0 xmlns="urn:example:order">b</y0>
|
||||||
<y1 xmlns="urn:example:clixon">b</y1>
|
<y1 xmlns="urn:example:order">b</y1>
|
||||||
<c xmlns="urn:example:clixon"><d>hej</d></c>
|
<c xmlns="urn:example:order"><d>hej</d></c>
|
||||||
<y0 xmlns="urn:example:clixon">c</y0>
|
<y0 xmlns="urn:example:order">c</y0>
|
||||||
<y1 xmlns="urn:example:clixon">c</y1>
|
<y1 xmlns="urn:example:order">c</y1>
|
||||||
<y2 xmlns="urn:example:clixon"><k>a</k><a>bar</a></y2>
|
<y2 xmlns="urn:example:order"><k>a</k><a>bar</a></y2>
|
||||||
<y3 xmlns="urn:example:clixon"><k>a</k><a>bar</a></y3>
|
<y3 xmlns="urn:example:order"><k>a</k><a>bar</a></y3>
|
||||||
<l xmlns="urn:example:clixon">hopp</l>
|
<l xmlns="urn:example:order">hopp</l>
|
||||||
<y0 xmlns="urn:example:clixon">a</y0>
|
<y0 xmlns="urn:example:order">a</y0>
|
||||||
<y1 xmlns="urn:example:clixon">a</y1>
|
<y1 xmlns="urn:example:order">a</y1>
|
||||||
<y2 xmlns="urn:example:clixon"><k>c</k><a>bar</a></y2>
|
<y2 xmlns="urn:example:order"><k>c</k><a>bar</a></y2>
|
||||||
<y3 xmlns="urn:example:clixon"><k>c</k><a>bar</a></y3>
|
<y3 xmlns="urn:example:order"><k>c</k><a>bar</a></y3>
|
||||||
<y2 xmlns="urn:example:clixon"><k>b</k><a>bar</a></y2>
|
<y2 xmlns="urn:example:order"><k>b</k><a>bar</a></y2>
|
||||||
<y3 xmlns="urn:example:clixon"><k>b</k><a>bar</a></y3>
|
<y3 xmlns="urn:example:order"><k>b</k><a>bar</a></y3>
|
||||||
</config>
|
</config>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
|
@ -122,21 +127,28 @@ if [ $BE -ne 0 ]; then
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# STATE (should not be ordered)
|
||||||
|
new "state data (should be unordered: 42,41,43)"
|
||||||
|
cat <<EOF > $tmp
|
||||||
|
<rpc><get><filter type="xpath" select="state"/></get></rpc>]]>]]>
|
||||||
|
EOF
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "$(cat $tmp)" '<rpc-reply><data><state xmlns="urn:example:clixon"><op>42</op><op>41</op><op>43</op></state></data></rpc-reply>]]>]]>'
|
||||||
|
|
||||||
# Check as file
|
# Check as file
|
||||||
new "verify running from start, should be: c,l,y0,y1,y2,y3; y1 and y3 sorted. Note this fails if CLICON_XML_SORT set to false"
|
new "verify running from start, should be: c,l,y0,y1,y2,y3; y1 and y3 sorted. Note this fails if CLICON_XML_SORT set to false"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get-config><source><running/></source></get-config></rpc>]]>]]>' '^<rpc-reply><data><c xmlns="urn:example:clixon"><d>hej</d></c><l xmlns="urn:example:clixon">hopp</l><y0 xmlns="urn:example:clixon">d</y0><y0 xmlns="urn:example:clixon">b</y0><y0 xmlns="urn:example:clixon">c</y0><y0 xmlns="urn:example:clixon">a</y0><y1 xmlns="urn:example:clixon">a</y1><y1 xmlns="urn:example:clixon">b</y1><y1 xmlns="urn:example:clixon">c</y1><y1 xmlns="urn:example:clixon">d</y1><y2 xmlns="urn:example:clixon"><k>d</k><a>bar</a></y2><y2 xmlns="urn:example:clixon"><k>a</k><a>bar</a></y2><y2 xmlns="urn:example:clixon"><k>c</k><a>bar</a></y2><y2 xmlns="urn:example:clixon"><k>b</k><a>bar</a></y2><y3 xmlns="urn:example:clixon"><k>a</k><a>bar</a></y3><y3 xmlns="urn:example:clixon"><k>b</k><a>bar</a></y3><y3 xmlns="urn:example:clixon"><k>c</k><a>bar</a></y3><y3 xmlns="urn:example:clixon"><k>d</k><a>bar</a></y3></data></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get-config><source><running/></source></get-config></rpc>]]>]]>' '^<rpc-reply><data><c xmlns="urn:example:order"><d>hej</d></c><l xmlns="urn:example:order">hopp</l><y0 xmlns="urn:example:order">d</y0><y0 xmlns="urn:example:order">b</y0><y0 xmlns="urn:example:order">c</y0><y0 xmlns="urn:example:order">a</y0><y1 xmlns="urn:example:order">a</y1><y1 xmlns="urn:example:order">b</y1><y1 xmlns="urn:example:order">c</y1><y1 xmlns="urn:example:order">d</y1><y2 xmlns="urn:example:order"><k>d</k><a>bar</a></y2><y2 xmlns="urn:example:order"><k>a</k><a>bar</a></y2><y2 xmlns="urn:example:order"><k>c</k><a>bar</a></y2><y2 xmlns="urn:example:order"><k>b</k><a>bar</a></y2><y3 xmlns="urn:example:order"><k>a</k><a>bar</a></y3><y3 xmlns="urn:example:order"><k>b</k><a>bar</a></y3><y3 xmlns="urn:example:order"><k>c</k><a>bar</a></y3><y3 xmlns="urn:example:order"><k>d</k><a>bar</a></y3><interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"><interface><name>lo</name><type>ex:loopback</type><enabled>true</enabled></interface></interfaces></data></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
new "get each ordered-by user leaf-list"
|
new "get each ordered-by user leaf-list"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><running/></source><filter type=\"xpath\" select=\"/y2[k='a']\"/></get-config></rpc>]]>]]>" '^<rpc-reply><data><y2 xmlns="urn:example:clixon"><k>a</k><a>bar</a></y2></data></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><running/></source><filter type=\"xpath\" select=\"/y2[k='a']\"/></get-config></rpc>]]>]]>" '^<rpc-reply><data><y2 xmlns="urn:example:order"><k>a</k><a>bar</a></y2></data></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
new "get each ordered-by user leaf-list"
|
new "get each ordered-by user leaf-list"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><running/></source><filter type=\"xpath\" select=\"/y3[k='a']\"/></get-config></rpc>]]>]]>" '^<rpc-reply><data><y3 xmlns="urn:example:clixon"><k>a</k><a>bar</a></y3></data></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><running/></source><filter type=\"xpath\" select=\"/y3[k='a']\"/></get-config></rpc>]]>]]>" '^<rpc-reply><data><y3 xmlns="urn:example:order"><k>a</k><a>bar</a></y3></data></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
new "get each ordered-by user leaf-list"
|
new "get each ordered-by user leaf-list"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><running/></source><filter type=\"xpath\" select=\"/y2[k='b']\"/></get-config></rpc>]]>]]>" '^<rpc-reply><data><y2 xmlns="urn:example:clixon"><k>b</k><a>bar</a></y2></data></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><running/></source><filter type=\"xpath\" select=\"/y2[k='b']\"/></get-config></rpc>]]>]]>" '^<rpc-reply><data><y2 xmlns="urn:example:order"><k>b</k><a>bar</a></y2></data></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
new "get each ordered-by user leaf-list"
|
new "get each ordered-by user leaf-list"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><running/></source><filter type=\"xpath\" select=\"/y3[k='b']\"/></get-config></rpc>]]>]]>" '^<rpc-reply><data><y3 xmlns="urn:example:clixon"><k>b</k><a>bar</a></y3></data></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><running/></source><filter type=\"xpath\" select=\"/y3[k='b']\"/></get-config></rpc>]]>]]>" '^<rpc-reply><data><y3 xmlns="urn:example:order"><k>b</k><a>bar</a></y3></data></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
new "delete candidate"
|
new "delete candidate"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><default-operation>none</default-operation><config operation="delete"/></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><default-operation>none</default-operation><config operation="delete"/></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
@ -144,33 +156,33 @@ expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><can
|
||||||
# LEAF_LISTS
|
# LEAF_LISTS
|
||||||
|
|
||||||
new "add two entries (c,b) to leaf-list user order"
|
new "add two entries (c,b) to leaf-list user order"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><y0 xmlns="urn:example:clixon">c</y0><y0 xmlns="urn:example:clixon">b</y0></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><y0 xmlns="urn:example:order">c</y0><y0 xmlns="urn:example:order">b</y0></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "add one entry (a) to leaf-list user order"
|
new "add one entry (a) to leaf-list user order"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><y0 xmlns="urn:example:clixon">a</y0></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><y0 xmlns="urn:example:order">a</y0></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf commit"
|
new "netconf commit"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "add one entry (0) to leaf-list user order after commit"
|
new "add one entry (0) to leaf-list user order after commit"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><y0 xmlns="urn:example:clixon">0</y0></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><y0 xmlns="urn:example:order">0</y0></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf commit"
|
new "netconf commit"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "verify leaf-list user order in running (as entered: c,b,a,0)"
|
new "verify leaf-list user order in running (as entered: c,b,a,0)"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get-config><source><running/></source><filter type="xpath" select="/y0"/></get-config></rpc>]]>]]>' '^<rpc-reply><data><y0 xmlns="urn:example:clixon">c</y0><y0 xmlns="urn:example:clixon">b</y0><y0 xmlns="urn:example:clixon">a</y0><y0 xmlns="urn:example:clixon">0</y0></data></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get-config><source><running/></source><filter type="xpath" select="/y0"/></get-config></rpc>]]>]]>' '^<rpc-reply><data><y0 xmlns="urn:example:order">c</y0><y0 xmlns="urn:example:order">b</y0><y0 xmlns="urn:example:order">a</y0><y0 xmlns="urn:example:order">0</y0></data></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
# LISTS
|
# LISTS
|
||||||
|
|
||||||
new "add two entries to list user order"
|
new "add two entries to list user order"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><y2 xmlns="urn:example:clixon"><k>c</k><a>bar</a></y2><y2 xmlns="urn:example:clixon"><k>b</k><a>foo</a></y2></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><y2 xmlns="urn:example:order"><k>c</k><a>bar</a></y2><y2 xmlns="urn:example:order"><k>b</k><a>foo</a></y2></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "add one entry to list user order"
|
new "add one entry to list user order"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><y2 xmlns="urn:example:clixon"><k>a</k><a>fie</a></y2></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><y2 xmlns="urn:example:order"><k>a</k><a>fie</a></y2></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "verify list user order (as entered)"
|
new "verify list user order (as entered)"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get-config><source><candidate/></source><filter type="xpath" select="/y2"/></get-config></rpc>]]>]]>' '^<rpc-reply><data><y2 xmlns="urn:example:clixon"><k>c</k><a>bar</a></y2><y2 xmlns="urn:example:clixon"><k>b</k><a>foo</a></y2><y2 xmlns="urn:example:clixon"><k>a</k><a>fie</a></y2></data></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get-config><source><candidate/></source><filter type="xpath" select="/y2"/></get-config></rpc>]]>]]>' '^<rpc-reply><data><y2 xmlns="urn:example:order"><k>c</k><a>bar</a></y2><y2 xmlns="urn:example:order"><k>b</k><a>foo</a></y2><y2 xmlns="urn:example:order"><k>a</k><a>fie</a></y2></data></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
if [ $BE -eq 0 ]; then
|
if [ $BE -eq 0 ]; then
|
||||||
exit # BE
|
exit # BE
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ cat <<EOF > $cfg
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# This is a fixed 'state' implemented in routing_backend. It is assumed to be always there
|
# This is a fixed 'state' implemented in routing_backend. It is assumed to be always there
|
||||||
state='{"clixon-example:state": {"op": "42"}}'
|
state='{"clixon-example:state": {"op": ["42","41","43"]}}
'
|
||||||
|
|
||||||
new "test params: -f $cfg"
|
new "test params: -f $cfg"
|
||||||
if [ $BE -ne 0 ]; then
|
if [ $BE -ne 0 ]; then
|
||||||
|
|
@ -113,11 +113,11 @@ new "restconf empty rpc with extra args (should fail)"
|
||||||
expecteq "$(curl -s -X POST -d {\"clixon-example:input\":{\"extra\":null}} http://localhost/restconf/operations/clixon-example:empty)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "unknown-element","error-info": {"bad-element": "extra"},"error-severity": "error"}}}
'
|
expecteq "$(curl -s -X POST -d {\"clixon-example:input\":{\"extra\":null}} http://localhost/restconf/operations/clixon-example:empty)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "unknown-element","error-info": {"bad-element": "extra"},"error-severity": "error"}}}
'
|
||||||
|
|
||||||
new "restconf get empty config + state json"
|
new "restconf get empty config + state json"
|
||||||
expecteq "$(curl -sSG http://localhost/restconf/data/clixon-example:state)" '{"clixon-example:state": {"op": "42"}}
|
expecteq "$(curl -sSG http://localhost/restconf/data/clixon-example:state)" '{"clixon-example:state": {"op": ["42","41","43"]}}
|
||||||
'
|
'
|
||||||
|
|
||||||
new "restconf get empty config + state json + module"
|
new "restconf get empty config + state json + module"
|
||||||
expecteq "$(curl -sSG http://localhost/restconf/data/clixon-example:state)" '{"clixon-example:state": {"op": "42"}}
|
expecteq "$(curl -sSG http://localhost/restconf/data/clixon-example:state)" '{"clixon-example:state": {"op": ["42","41","43"]}}
|
||||||
'
|
'
|
||||||
|
|
||||||
new "restconf get empty config + state json with wrong module name"
|
new "restconf get empty config + state json with wrong module name"
|
||||||
|
|
@ -125,14 +125,14 @@ expecteq "$(curl -sSG http://localhost/restconf/data/badmodule:state)" '{"ietf-r
|
||||||
|
|
||||||
new "restconf get empty config + state xml"
|
new "restconf get empty config + state xml"
|
||||||
ret=$(curl -s -H "Accept: application/yang-data+xml" -G http://localhost/restconf/data/clixon-example:state)
|
ret=$(curl -s -H "Accept: application/yang-data+xml" -G http://localhost/restconf/data/clixon-example:state)
|
||||||
expect='<state xmlns="urn:example:clixon"><op>42</op></state>'
|
expect='<state xmlns="urn:example:clixon"><op>42</op><op>41</op><op>43</op></state>'
|
||||||
match=`echo $ret | grep -EZo "$expect"`
|
match=`echo $ret | grep -EZo "$expect"`
|
||||||
if [ -z "$match" ]; then
|
if [ -z "$match" ]; then
|
||||||
err "$expect" "$ret"
|
err "$expect" "$ret"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new "restconf get data/ json"
|
new "restconf get data/ json"
|
||||||
expecteq "$(curl -s -G http://localhost/restconf/data/clixon-example:state/op=42)" '{"clixon-example:op": "42"}
|
expecteq "$(curl -s -G http://localhost/restconf/data/clixon-example:state/op=42)" '{"clixon-example:op": ["42","41","43"]}
|
||||||
'
|
'
|
||||||
|
|
||||||
new "restconf get state operation eth0 xml"
|
new "restconf get state operation eth0 xml"
|
||||||
|
|
@ -145,7 +145,7 @@ if [ -z "$match" ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new "restconf get state operation eth0 type json"
|
new "restconf get state operation eth0 type json"
|
||||||
expecteq "$(curl -s -G http://localhost/restconf/data/clixon-example:state/op=42)" '{"clixon-example:op": "42"}
|
expecteq "$(curl -s -G http://localhost/restconf/data/clixon-example:state/op=42)" '{"clixon-example:op": ["42","41","43"]}
|
||||||
'
|
'
|
||||||
|
|
||||||
new "restconf get state operation eth0 type xml"
|
new "restconf get state operation eth0 type xml"
|
||||||
|
|
@ -158,7 +158,7 @@ if [ -z "$match" ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new "restconf GET datastore"
|
new "restconf GET datastore"
|
||||||
expecteq "$(curl -s -X GET http://localhost/restconf/data/clixon-example:state)" '{"clixon-example:state": {"op": "42"}}
|
expecteq "$(curl -s -X GET http://localhost/restconf/data/clixon-example:state)" '{"clixon-example:state": {"op": ["42","41","43"]}}
|
||||||
'
|
'
|
||||||
|
|
||||||
# Exact match
|
# Exact match
|
||||||
|
|
@ -178,7 +178,8 @@ new "restconf delete interfaces"
|
||||||
expecteq $(curl -s -X DELETE http://localhost/restconf/data/ietf-interfaces:interfaces) ""
|
expecteq $(curl -s -X DELETE http://localhost/restconf/data/ietf-interfaces:interfaces) ""
|
||||||
|
|
||||||
new "restconf Check empty config"
|
new "restconf Check empty config"
|
||||||
expectfn "curl -sG http://localhost/restconf/data/clixon-example:state" 0 "$state"
|
expectfn "curl -sG http://localhost/restconf/data/clixon-example:state" 0 "$state
|
||||||
|
"
|
||||||
|
|
||||||
# XXX: gives <interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
|
# XXX: gives <interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
|
||||||
# <interface xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
|
# <interface xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
|
||||||
|
|
@ -192,7 +193,7 @@ expecteq "$(curl -s -G http://localhost/restconf/data/ietf-interfaces:interfaces
|
||||||
'
|
'
|
||||||
|
|
||||||
new "restconf Check eth/0/0 added state"
|
new "restconf Check eth/0/0 added state"
|
||||||
expecteq "$(curl -s -G http://localhost/restconf/data/clixon-example:state)" '{"clixon-example:state": {"op": "42"}}
|
expecteq "$(curl -s -G http://localhost/restconf/data/clixon-example:state)" '{"clixon-example:state": {"op": ["42","41","43"]}}
|
||||||
'
|
'
|
||||||
|
|
||||||
new "restconf Re-post eth/0/0 which should generate error"
|
new "restconf Re-post eth/0/0 which should generate error"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue