#!/usr/bin/env bash # Tests for yang uses/augment + when # Uses+when, test: # 1. set/get/validate matching and non-matching when statement # 2 RFC 7950 7.21.5: If a key leaf is defined in a grouping that is used in a list, the # "uses" statement MUST NOT have a "when" statement. # 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 fin=$dir/in cfg=$dir/conf_yang.xml fyang=$dir/example.yang clidir=$dir/cli if [ -d $clidir ]; then rm -rf $clidir/* else mkdir $clidir fi # Use yang in example cat < $cfg $cfg ietf-netconf:startup /usr/local/share/clixon $dir $dir /usr/local/lib/$APPNAME/backend $clidir /usr/local/lib/$APPNAME/cli $APPNAME 2 VARS /usr/local/var/$APPNAME/$APPNAME.sock /usr/local/var/$APPNAME/$APPNAME.pidfile $dir false clixon-restconf EOF cat < $clidir/ex.cli CLICON_MODE="example"; CLICON_PROMPT="%U@%H %W> "; # Autocli syntax tree operations edit @datamodel, cli_auto_edit("datamodel"); up, cli_auto_up("datamodel"); top, cli_auto_top("datamodel"); set @datamodel, cli_auto_set(); merge @datamodel, cli_auto_merge(); create @datamodel, cli_auto_create(); delete("Delete a configuration item") { @datamodel, cli_auto_del(); all("Delete whole candidate configuration"), delete_all("candidate"); } show("Show a particular state of the system"){ configuration("Show configuration"), cli_auto_show("datamodel", "candidate", "text", true, false);{ xml("Show configuration as XML"), cli_auto_show("datamodel", "candidate", "xml", false, false); } } validate("Validate changes"), cli_validate(); commit("Commit the changes"), cli_commit(); quit("Quit"), cli_quit(); EOF # Start backend, add entry with matching name / non-matrching and check get/validation function testrun() { new "test params: -f $cfg" if [ $BE -ne 0 ]; then new "kill old backend" sudo clixon_backend -z -f $cfg if [ $? -ne 0 ]; then err fi new "start backend -s init -f $cfg" start_backend -s init -f $cfg fi new "wait backend" wait_backend # no match: name != kalle new "netconf set non-match" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLOpaul
merge
]]>]]>" "^]]>]]>$" new "netconf get default value not set" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^paul
]]>]]>$" new "netconf set non-match value expect fail" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLOpaul42
merge
]]>]]>" "^applicationunknown-elementvalueerrorNode 'value' tagged with 'when' condition 'ex:name = 'kalle'' in module 'example' evaluates to false in edit-config operation (see RFC 7950 Sec 8.3.2)]]>]]>$" new "netconf get value without default" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^paul
]]>]]>$" new "netconf validate default not set" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" new "netconf discard non-match" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" # no match: name != kalle full put new "netconf set non-match full" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLOpaul42
merge
]]>]]>" "^applicationunknown-elementvalueerrorNode 'value' tagged with 'when' condition 'ex:name = 'kalle'' in module 'example' evaluates to false in edit-config operation (see RFC 7950 Sec 8.3.2)]]>]]>$" new "netconf get value empty" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" # match: name = kalle new "netconf set match" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLOkalle
merge
]]>]]>" "^]]>]]>$" new "netconf get default value set" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^kallefoo
]]>]]>$" new "netconf set non-match value expect ok" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLOkalle42
merge
]]>]]>" "^]]>]]>$" new "netconf get value ok" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^kalle42
]]>]]>$" new "netconf validate default set" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" 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 fi } cat < $fyang module example { namespace "urn:example:clixon"; prefix ex; grouping value-top { leaf value{ type string; default foo; } } container table{ list parameter{ key name; leaf name{ type string; } uses value-top { when "ex:name = 'kalle'"; } } } } EOF new "1. uses/when test edit,default" testrun cat < $fyang module example { namespace "urn:example:clixon"; prefix ex; grouping value-top { leaf value{ type string; default foo; } } container table{ list parameter{ key name; leaf name{ type string; } } } augment /table/parameter { uses value-top { when "ex:name = 'kalle'"; } } } EOF new "2. augment/uses/when test edit,default (same but with augment)" testrun cat < $fyang module example { namespace "urn:example:clixon"; prefix ex; grouping value-top { leaf name{ type string; } } container table{ list parameter{ key name; uses value-top { when "ex:name = 'kalle'"; } } } } EOF new "3. RFC 7950 7.21.5: If a key leaf is defined in a grouping that is used in a list" # the "uses" statement MUST NOT have a "when" statement. if [ ${valgrindtest} -eq 0 ]; then # Error dont cleanup mem OK new "start backend -s init -f $cfg, expect yang when fail" expectpart "$(sudo $clixon_backend -F -D $DBG -s init -f $cfg 2>&1)" 255 "Yang error: Key leaf 'name' defined in grouping 'value-top' is used in a 'uses' statement, This is not allowed according to RFC 7950 Sec 7.21.5" fi cat < $fyang module example { namespace "urn:example:clixon"; prefix ex; leaf allow { type boolean; default false; } grouping value-top { leaf value{ type string; default foo; } } container table{ list parameter{ key name; leaf name{ type string; } uses value-top { when "../../ex:allow = 'true'"; } } } } EOF new "3. Check a top-level value as allowed value" new "test params: -f $cfg" if [ $BE -ne 0 ]; then new "kill old backend" sudo clixon_backend -z -f $cfg if [ $? -ne 0 ]; then err fi new "start backend -s init -f $cfg" start_backend -s init -f $cfg fi new "wait backend" wait_backend new "netconf set allow true" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLOtruemerge]]>]]>" "^]]>]]>$" new "netconf commit" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" new "netconf set value expect OK" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLOkalle42
merge
]]>]]>" "^]]>]]>$" new "netconf discard-changes" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" new "netconf set allow false" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLOfalsemerge]]>]]>" "^]]>]]>$" new "netconf commit" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" new "netconf set value expect fail" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLOkalle42
merge
]]>]]>" "^applicationunknown-elementvalueerrorNode 'value' tagged with 'when' condition '../../ex:allow = 'true'' in module 'example' evaluates to false in edit-config operation (see RFC 7950 Sec 8.3.2)]]>]]>$" 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 fi rm -rf $dir new "endtest" endtest