#!/usr/bin/env bash # Test YANG ANYDATA: # Also Test CLICON_YANG_UNKNOWN_ANYDATA: Treat unknown XML/JSON nodes as anydata. # Test matrix is three dimensions: # 1. YANG spec: Add elements denotend with "u" which are either a) defined as anydata or b) unknown # 2. Make access to elements as: a) top-level, b) in container, c) in list # 3. data is in a) startup b) netconf 3) state # Load an XML file with unknown yang constructs that is labelled as anydata # Ensure clixon is robust to handle that # Test is that unknown XML subcomponents (with label u) are loaded in an xml file. # 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 test -d $dir/yang || mkdir $dir/yang cfg=$dir/conf_yang.xml fanydata=$dir/yang/anydata.yang funknown=$dir/yang/unknown.yang fstate=$dir/state.xml cat < $fanydata module any{ yang-version 1.1; prefix any; namespace "urn:example:any"; container ca{ list b{ key k; leaf k { type string; } anydata u3; } anydata u2; } anydata u1; container sa{ config false; list sb{ key k; leaf k { type string; } anydata u5; } anydata u4; } rpc myrpc { input { anydata u7; } output { anydata u8; } } } EOF cat < $funknown module unknown{ yang-version 1.1; prefix un; namespace "urn:example:unknown"; container cu{ list b{ key k; leaf k { type string; } } } container su{ config false; list sb{ key k; leaf k { type string; } } } rpc myrpc { } } EOF # For edit config XMLA='2242a string23' XMLU='2242a string23' # Full state with unknowns STATE0='2255a string2255a string' # Partial state with unknowns removed in the unknown module STATE1='2255a string22' # Run anydata and unknown tests # From a startup db or via netconf commands as well as state data # Test both anydata and unknown # Args: # 1: bool: startup (or not) # 2: bool: treat unknown as anydata (or not) testrun() { startup=$1 unknown=$2 if $unknown; then # treat unknown as anydata or not if $startup; then # If startup XML="$XMLA$XMLU" else XML="$XMLA" unknownreply="applicationunknown-elementu1errorUnassigned yang spec]]>]]>" fi else XML="$XMLA" unknownreply="applicationunknown -elementu1errorUnassigned yang spec]]>]]>" fi if $startup; then # get config from startup F="ietf-netconf:startup" else F="" fi cat < $cfg $cfg /usr/local/share/clixon $dir $IETFRFC $dir/yang /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/cli /usr/local/lib/$APPNAME/netconf /usr/local/lib/$APPNAME/backend $APPNAME /usr/local/var/$APPNAME/$APPNAME.sock /usr/local/var/$APPNAME/$APPNAME.pidfile $dir false false $unknown $F EOF if $startup; then # Only positive startup test, ie dont add XMLU if unknown not treated as anyxml # and check for errors cat < $dir/startup_db $XML EOF fi if [ $BE -ne 0 ]; then new "kill old backend" sudo clixon_backend -zf $cfg if [ $? -ne 0 ]; then err fi if $startup; then new "start backend -s startup -f $cfg -- -sS $fstate" start_backend -s startup -f $cfg -- -sS $fstate else new "start backend -s init -f $cfg -- -sS $fstate" start_backend -s init -f $cfg -- -sS $fstate fi new "waiting" wait_backend fi if [ $RC -ne 0 ]; then new "kill old restconf daemon" stop_restconf_pre new "start restconf daemon" start_restconf -f $cfg fi new "wait restconf" wait_restconf if ! $startup; then # If not startup, add xml using netconf new "Put anydata" expecteof "$clixon_netconf -qf $cfg -D $DBG" 0 "$XMLA]]>]]>" "]]>]]>" new "Put unknown" expecteof "$clixon_netconf -qf $cfg -D $DBG" 0 "$XMLU]]>]]>" "$unknownreply" new "commit" expecteof "$clixon_netconf -qf $cfg -D $DBG" 0 "]]>]]>" "]]>]]>" fi new "Get candidate" expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' "^$XML]]>]]>$" new "Get running" expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' "^$XML]]>]]>$" # Add other functions, (based on previous errors), eg cli show config, cli commit. new "cli show configuration" expectpart "$($clixon_cli -1 -f $cfg show conf xml)" 0 "42" new "cli commit" expectpart "$($clixon_cli -1 -f $cfg commit)" 0 "^$" new "restconf get config" expectpart "$(curl $CURLOPTS -X GET -H "Accept: application/yang-data+xml" $RCPROTO://localhost/restconf/data?content=config)" 0 "HTTP/1.1 200 OK" "$XML" # Save partial state in state file with unknown removed (positive test) echo "$STATE1" > $fstate new "Get state (positive test)" expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' "^$STATE1]]>]]>" new "restconf get state(positive)" expectpart "$(curl $CURLOPTS -X GET -H "Accept: application/yang-data+xml" $RCPROTO://localhost/restconf/data?content=nonconfig)" 0 "HTTP/1.1 200 OK" "$STATE1" # full state with unknowns echo "$STATE0" > $fstate new "Get state (negative test)" expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' "error-message>Failed to find YANG spec of XML node: u5 with parent: sb in namespace: urn:example:unknown. Internal error, state callback returned invalid XML: example_backend" new "restconf get state(negative)" expectpart "$(curl $CURLOPTS -X GET -H "Accept: application/yang-data+xml" $RCPROTO://localhost/restconf/data?content=nonconfig)" 0 "HTTP/1.1 412 Precondition Failed" "operation-failedu5" # RPC:s take "not-supported" as OK: syntax OK and according to mdeol, just not implemented in # server. But "unknown-element" as truly unknwon. # (Would need to add a handler to get a proper OK) new "Not supported RPC" expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' 'operation-not-supported' new "anydata RPC" expecteof "$clixon_netconf -qf $cfg" 0 '88]]>]]>' 'operation-not-supported' new "unknown RPC" expecteof "$clixon_netconf -qf $cfg" 0 '88]]>]]>' 'unknown-element' if [ $RC -ne 0 ]; then new "Kill restconf daemon" stop_restconf fi if [ $BE -ne 0 ]; then new "Kill backend" # Check if premature kill pid=$(pgrep -u root -f clixon_backend) if [ -z "$pid" ]; then err "backend already dead" fi # kill backend stop_backend -f $cfg sudo pkill -u root -f clixon_backend fi } new "test params: -f $cfg" new "no startup, dont treat unknown as anydata" testrun false false new "startup, dont treat unknown as anydata" testrun true false new "no startup, treat unknown as anydata" testrun false true new "startup, treat unknown as anydata" testrun true true rm -rf $dir