Fixed: [YANG when condition evaluated as false combined with a mandatory leaf does not work](https://github.com/clicon/clixon/issues/380)
Replaced yang_mandatory() with yang_xml_mandatory() by extending existing it with when check
This commit is contained in:
parent
83663d4d15
commit
1eb78a78f8
7 changed files with 424 additions and 88 deletions
|
|
@ -78,6 +78,7 @@ Developers may need to change their code
|
|||
|
||||
### Corrected Bugs
|
||||
|
||||
* Fixed: [YANG when condition evaluated as false combined with a mandatory leaf does not work](https://github.com/clicon/clixon/issues/380)
|
||||
* Fixed: [Trying to change the "read-only" node through snmpset](https://github.com/clicon/clixon/issues/376)
|
||||
* Fixed: [Trying to change the "config false" node through snmpset](https://github.com/clicon/clixon/issues/377)
|
||||
* Fixed by returning `SNMP_ERR_NOTWRITABLE` when trying to reserve object
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ int yang_enum2valstr(yang_stmt *ytype, char *enumstr, char **valstr);
|
|||
int yang_enum_int_value(cxobj *node, int32_t *val);
|
||||
int xml_copy_marked(cxobj *x0, cxobj *x1);
|
||||
int yang_check_when_xpath(cxobj *xn, cxobj *xp, yang_stmt *yn, int *hit, int *nrp, char **xpathp);
|
||||
int yang_xml_mandatory(cxobj *xt, yang_stmt *ys);
|
||||
int xml_rpc_isaction(cxobj *xn);
|
||||
int xml_find_action(cxobj *xn, int top, cxobj **xap);
|
||||
int purge_tagged_nodes(cxobj *xn, char *ns, char *name, char *value, int keepnode);
|
||||
|
|
|
|||
|
|
@ -272,7 +272,6 @@ int yang_apply(yang_stmt *yn, enum rfc_6020 key, yang_applyfn_t fn, int f
|
|||
int yang_datanode(yang_stmt *ys);
|
||||
int yang_abs_schema_nodeid(yang_stmt *ys, char *schema_nodeid, yang_stmt **yres);
|
||||
int yang_desc_schema_nodeid(yang_stmt *yn, char *schema_nodeid, yang_stmt **yres);
|
||||
int yang_mandatory(yang_stmt *ys);
|
||||
int yang_config(yang_stmt *ys);
|
||||
int yang_config_ancestor(yang_stmt *ys);
|
||||
int yang_features(clicon_handle h, yang_stmt *yt);
|
||||
|
|
|
|||
|
|
@ -613,16 +613,20 @@ check_list_key(cxobj *xt,
|
|||
* @retval -1 Error
|
||||
*/
|
||||
static int
|
||||
choice_mandatory_check(yang_stmt *ycase,
|
||||
choice_mandatory_check(cxobj *xt,
|
||||
yang_stmt *ycase,
|
||||
cxobj **xret)
|
||||
{
|
||||
int retval = -1;
|
||||
yang_stmt *yc = NULL;
|
||||
cbuf *cb = NULL;
|
||||
int fail = 0;
|
||||
int ret;
|
||||
|
||||
while ((yc = yn_each(ycase, yc)) != NULL) {
|
||||
if (yang_mandatory(yc)){
|
||||
if ((ret = yang_xml_mandatory(xt, yc)) < 0)
|
||||
goto done;
|
||||
if (ret == 1){
|
||||
if (yang_flag_get(yc, YANG_FLAG_MARK))
|
||||
yang_flag_reset(yc, YANG_FLAG_MARK);
|
||||
else if (fail == 0){
|
||||
|
|
@ -728,16 +732,20 @@ check_mandatory_case(cxobj *xt,
|
|||
if ((y = xml_spec(x)) != NULL &&
|
||||
yang_ancestor_child(y, yc, &ym, &ycnew) != 0 &&
|
||||
yang_keyword_get(ycnew) == Y_CASE){
|
||||
if (ym && yang_mandatory(ym)){
|
||||
if (ym){
|
||||
if ((ret = yang_xml_mandatory(xt, ym)) < 0)
|
||||
goto done;
|
||||
if (ret == 1){
|
||||
if (yang_flag_get(ym, YANG_FLAG_MARK) != 0){
|
||||
clicon_debug(1, "%s Already marked, shouldnt happen", __FUNCTION__);
|
||||
}
|
||||
yang_flag_set(ym, YANG_FLAG_MARK);
|
||||
}
|
||||
}
|
||||
if (ycase != NULL){
|
||||
if (ycnew != ycase){ /* End of case, new case */
|
||||
/* Check and clear marked mandatory */
|
||||
if ((ret = choice_mandatory_check(ycase, xret)) < 0)
|
||||
if ((ret = choice_mandatory_check(xt, ycase, xret)) < 0)
|
||||
goto done;
|
||||
if (ret == 0)
|
||||
goto fail;
|
||||
|
|
@ -749,7 +757,7 @@ check_mandatory_case(cxobj *xt,
|
|||
}
|
||||
else if (ycase != NULL){ /* End of case */
|
||||
/* Check and clear marked mandatory */
|
||||
if ((ret = choice_mandatory_check(ycase, xret)) < 0)
|
||||
if ((ret = choice_mandatory_check(xt, ycase, xret)) < 0)
|
||||
goto done;
|
||||
if (ret == 0)
|
||||
goto fail;
|
||||
|
|
@ -757,7 +765,7 @@ check_mandatory_case(cxobj *xt,
|
|||
}
|
||||
}
|
||||
if (ycase){
|
||||
if ((ret = choice_mandatory_check(ycase, xret)) < 0)
|
||||
if ((ret = choice_mandatory_check(xt, ycase, xret)) < 0)
|
||||
goto done;
|
||||
if (ret == 0)
|
||||
goto fail;
|
||||
|
|
@ -806,7 +814,7 @@ check_mandatory(cxobj *xt,
|
|||
while ((yc = yn_each(yt, yc)) != NULL) {
|
||||
/* Choice is more complex because of choice/case structure and possibly hierarchical */
|
||||
if (yang_keyword_get(yc) == Y_CHOICE){
|
||||
if (yang_mandatory(yc)){
|
||||
if (yang_xml_mandatory(xt, yc)){
|
||||
x = NULL;
|
||||
while ((x = xml_child_each(xt, x, CX_ELMNT)) != NULL) {
|
||||
if ((y = xml_spec(x)) != NULL &&
|
||||
|
|
@ -829,7 +837,9 @@ check_mandatory(cxobj *xt,
|
|||
if (ret == 0)
|
||||
goto fail;
|
||||
}
|
||||
if (!yang_mandatory(yc)) /* Rest of yangs are immediate children */
|
||||
if ((ret = yang_xml_mandatory(xt, yc)) < 0) /* Rest of yangs are immediate children */
|
||||
goto done;
|
||||
if (ret == 0)
|
||||
continue;
|
||||
switch (yang_keyword_get(yc)){
|
||||
case Y_CONTAINER:
|
||||
|
|
@ -1130,6 +1140,22 @@ xml_yang_validate_all(clicon_handle h,
|
|||
goto fail;
|
||||
}
|
||||
if (yang_config(yt) != 0){
|
||||
if (yang_check_when_xpath(xt, xml_parent(xt), yt, &hit, &nr, &xpath) < 0)
|
||||
goto done;
|
||||
if (hit && nr == 0){
|
||||
if ((cb = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
cprintf(cb, "Failed WHEN condition of %s in module %s (WHEN xpath is %s)",
|
||||
xml_name(xt),
|
||||
yang_argument_get(ys_module(yt)),
|
||||
xpath);
|
||||
if (xret && netconf_operation_failed_xml(xret, "application",
|
||||
cbuf_get(cb)) < 0)
|
||||
goto done;
|
||||
goto fail;
|
||||
}
|
||||
if ((ret = check_mandatory(xt, yt, xret)) < 0)
|
||||
goto done;
|
||||
if (ret == 0)
|
||||
|
|
@ -1204,22 +1230,6 @@ xml_yang_validate_all(clicon_handle h,
|
|||
nsc = NULL;
|
||||
}
|
||||
}
|
||||
if (yang_check_when_xpath(xt, xml_parent(xt), yt, &hit, &nr, &xpath) < 0)
|
||||
goto done;
|
||||
if (hit && nr == 0){
|
||||
if ((cb = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
cprintf(cb, "Failed WHEN condition of %s in module %s (WHEN xpath is %s)",
|
||||
xml_name(xt),
|
||||
yang_argument_get(ys_module(yt)),
|
||||
xpath);
|
||||
if (xret && netconf_operation_failed_xml(xret, "application",
|
||||
cbuf_get(cb)) < 0)
|
||||
goto done;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
x = NULL;
|
||||
while ((x = xml_child_each(xt, x, CX_ELMNT)) != NULL) {
|
||||
|
|
|
|||
|
|
@ -2089,10 +2089,14 @@ xml_copy_marked(cxobj *x0,
|
|||
|
||||
/*! Check when condition
|
||||
*
|
||||
* @param[in] h Clixon handle
|
||||
* @param[in] xn XML node, can be NULL, in which case it is added as dummy under xp
|
||||
* @param[in] xp XML parent
|
||||
* @param[in] ys Yang node
|
||||
* @param[in] xn XML node, can be NULL, in which case it is added as dummy under xp
|
||||
* @param[in] xp XML parent
|
||||
* @param[in] yn Yang node
|
||||
* @param[out] hit when statement found
|
||||
* @param[out] nrp 1: when stmt evaluates to true
|
||||
* @param[out] xpathp when stmts xpath
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
* First variants of WHEN: Augmented and uses when using special info in node
|
||||
* Second variant of when, actual "when" sub-node RFC 7950 Sec 7.21.5. Can only be one.
|
||||
*/
|
||||
|
|
@ -2155,6 +2159,77 @@ yang_check_when_xpath(cxobj *xn,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Check if node is (recursively) mandatory also checking when conditional
|
||||
*
|
||||
* @param[in] xn Optional XML node
|
||||
* @param[in] xp XML parent
|
||||
* @param[in] ys YANG node
|
||||
* @retval 1 Recursively contains a mandatory node
|
||||
* @retval 0 Does not contain a mandatory node
|
||||
* @retval -1 Error
|
||||
* @see RFC7950 Sec 3:
|
||||
* o mandatory node: A mandatory node is one of:
|
||||
* 1) A leaf, choice, anydata, or anyxml node with a "mandatory"
|
||||
* statement with the value "true".
|
||||
* 2) # see below
|
||||
* 3) A container node without a "presence" statement and that has at
|
||||
* least one mandatory node as a child.
|
||||
*/
|
||||
int
|
||||
yang_xml_mandatory(cxobj *xt,
|
||||
yang_stmt *ys)
|
||||
{
|
||||
int retval = -1;
|
||||
yang_stmt *ym;
|
||||
cg_var *cv;
|
||||
enum rfc_6020 keyw;
|
||||
cxobj *xs = NULL;
|
||||
int ret;
|
||||
yang_stmt *yc;
|
||||
int hit;
|
||||
int nr;
|
||||
|
||||
/* Create dummy xs if not exist */
|
||||
if ((xs = xml_new(yang_argument_get(ys), xt, CX_ELMNT)) == NULL)
|
||||
goto done;
|
||||
xml_spec_set(xs, ys);
|
||||
if (yang_check_when_xpath(xs, xt, ys, &hit, &nr, NULL) < 0)
|
||||
goto done;
|
||||
if (hit && !nr){
|
||||
retval = 0;
|
||||
goto done;
|
||||
}
|
||||
keyw = yang_keyword_get(ys);
|
||||
if (keyw == Y_LEAF || keyw == Y_CHOICE || keyw == Y_ANYDATA || keyw == Y_ANYXML){
|
||||
if ((ym = yang_find(ys, Y_MANDATORY, NULL)) != NULL){
|
||||
if ((cv = yang_cv_get(ym)) != NULL){ /* shouldnt happen */
|
||||
retval = cv_bool_get(cv);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* 3) A container node without a "presence" statement and that has at
|
||||
* least one mandatory node as a child. */
|
||||
else if (keyw == Y_CONTAINER &&
|
||||
yang_find(ys, Y_PRESENCE, NULL) == NULL){
|
||||
yc = NULL;
|
||||
while ((yc = yn_each(ys, yc)) != NULL) {
|
||||
if ((ret = yang_xml_mandatory(xs, yc)) < 0)
|
||||
goto done;
|
||||
if (ret == 1)
|
||||
goto mandatory;
|
||||
}
|
||||
}
|
||||
retval = 0; /* Does not contain mandatory node */
|
||||
done:
|
||||
if (xs != NULL)
|
||||
xml_purge(xs);
|
||||
return retval;
|
||||
mandatory:
|
||||
retval = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*! Is XML node (ie under <rpc>) an action, ie name action and belong to YANG_XML_NAMESPACE?
|
||||
* @param[in] xn XML node
|
||||
* @retval 1 Yes, an action
|
||||
|
|
|
|||
|
|
@ -3213,65 +3213,6 @@ yang_desc_schema_nodeid(yang_stmt *yn,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Check if this leaf is mandatory or not
|
||||
* Note: one can cache this value in ys_cvec instead of functionally evaluating it.
|
||||
* @retval 1 yang statement is leaf and it has a mandatory sub-stmt with value true
|
||||
* @retval 0 The negation of conditions for return value 1.
|
||||
* @see RFC7950 Sec 3:
|
||||
* o mandatory node: A mandatory node is one of:
|
||||
* 1) A leaf, choice, anydata, or anyxml node with a "mandatory"
|
||||
* statement with the value "true".
|
||||
* 2) # see below
|
||||
* 3) A container node without a "presence" statement and that has at
|
||||
* least one mandatory node as a child.
|
||||
*
|
||||
* @note There is also this statement
|
||||
* 2) A list or leaf-list node with a "min-elements" statement with a
|
||||
* value greater than zero.
|
||||
* which we ignore here since:
|
||||
* (a) it does not consider the XML siblings and therefore returns false positives
|
||||
* (b) where the actual check is catched by check_list_unique_minmax()
|
||||
*/
|
||||
int
|
||||
yang_mandatory(yang_stmt *ys)
|
||||
{
|
||||
yang_stmt *ym;
|
||||
cg_var *cv;
|
||||
|
||||
/* 1) A leaf, choice, anydata, or anyxml node with a "mandatory"
|
||||
* statement with the value "true". */
|
||||
if (ys->ys_keyword == Y_LEAF || ys->ys_keyword == Y_CHOICE ||
|
||||
ys->ys_keyword == Y_ANYDATA || ys->ys_keyword == Y_ANYXML){
|
||||
if ((ym = yang_find(ys, Y_MANDATORY, NULL)) != NULL){
|
||||
if ((cv = yang_cv_get(ym)) != NULL) /* shouldnt happen */
|
||||
return cv_bool_get(cv);
|
||||
}
|
||||
}
|
||||
#if 0 /* See note above */
|
||||
/* 2) A list or leaf-list node with a "min-elements" statement with a
|
||||
* value greater than zero. */
|
||||
else if (ys->ys_keyword == Y_LIST || ys->ys_keyword == Y_LEAF_LIST){
|
||||
if ((ym = yang_find(ys, Y_MIN_ELEMENTS, NULL)) != NULL){
|
||||
cv = yang_cv_get(ym);
|
||||
return cv_uint32_get(cv) > 0; /* Not true if XML considered */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* 3) A container node without a "presence" statement and that has at
|
||||
* least one mandatory node as a child. */
|
||||
else if (ys->ys_keyword == Y_CONTAINER &&
|
||||
yang_find(ys, Y_PRESENCE, NULL) == NULL){
|
||||
yang_stmt *yc;
|
||||
int i;
|
||||
for (i=0; i<ys->ys_len; i++){
|
||||
yc = ys->ys_stmt[i];
|
||||
if (yang_mandatory(yc))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! Return config state of this node
|
||||
* @param[in] ys Yang statement
|
||||
* @retval 0 If node has a config sub-statement and it is false
|
||||
|
|
|
|||
309
test/test_when_mandatory.sh
Executable file
309
test/test_when_mandatory.sh
Executable file
|
|
@ -0,0 +1,309 @@
|
|||
#!/usr/bin/env bash
|
||||
# Yang when conditional and mandatory
|
||||
# Testing of validation phase.
|
||||
# Variants:
|
||||
# - One level and two levels of non-presence containers
|
||||
# - when-condition true and false
|
||||
# - empty vs extra leaf in non-presence container
|
||||
# - mandatory leaf present or not
|
||||
|
||||
# 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
|
||||
fyang=$dir/test.yang
|
||||
|
||||
cat <<EOF > $cfg
|
||||
<clixon-config xmlns="http://clicon.org/config">
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
<CLICON_YANG_DIR>${YANG_INSTALLDIR}</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_MAIN_FILE>$fyang</CLICON_YANG_MAIN_FILE>
|
||||
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
||||
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
||||
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
||||
</clixon-config>
|
||||
EOF
|
||||
|
||||
cat <<EOF > $fyang
|
||||
module $APPNAME{
|
||||
yang-version 1.1;
|
||||
namespace "urn:example:clixon";
|
||||
prefix ex;
|
||||
identity routing-protocol {
|
||||
description
|
||||
"Base identity from which routing protocol identities are
|
||||
derived.";
|
||||
}
|
||||
identity direct {
|
||||
base routing-protocol;
|
||||
description
|
||||
"Routing pseudo-protocol which provides routes to directly
|
||||
connected networks.";
|
||||
}
|
||||
identity static {
|
||||
base routing-protocol;
|
||||
description
|
||||
"Static routing pseudo-protocol.";
|
||||
}
|
||||
list x {
|
||||
key "type";
|
||||
leaf type {
|
||||
type identityref {
|
||||
base routing-protocol;
|
||||
}
|
||||
}
|
||||
container y {
|
||||
when "../type='static'" {
|
||||
description
|
||||
"This container is only valid for the 'static'
|
||||
routing protocol.";
|
||||
}
|
||||
leaf name{
|
||||
type string;
|
||||
mandatory true;
|
||||
}
|
||||
leaf extra{
|
||||
type string;
|
||||
}
|
||||
}
|
||||
}
|
||||
list x2 {
|
||||
key "type";
|
||||
leaf type {
|
||||
type identityref {
|
||||
base routing-protocol;
|
||||
}
|
||||
}
|
||||
container y2 {
|
||||
when "../type='static'" {
|
||||
description
|
||||
"This container is only valid for the 'static'
|
||||
routing protocol.";
|
||||
}
|
||||
container y3 {
|
||||
leaf name{
|
||||
type string;
|
||||
mandatory true;
|
||||
}
|
||||
leaf extra{
|
||||
type string;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
list x3 {
|
||||
key "type";
|
||||
leaf type {
|
||||
type identityref {
|
||||
base routing-protocol;
|
||||
}
|
||||
}
|
||||
container y2 {
|
||||
container y3 {
|
||||
when "../../type='static'" {
|
||||
description
|
||||
"This container is only valid for the 'static'
|
||||
routing protocol.";
|
||||
}
|
||||
leaf name{
|
||||
type string;
|
||||
mandatory true;
|
||||
}
|
||||
leaf extra{
|
||||
type string;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
new "test params: -f $cfg"
|
||||
|
||||
if [ $BE -ne 0 ]; then
|
||||
new "kill old backend"
|
||||
sudo clixon_backend -zf $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 "First: have mandatory leaf under an empty when-conditioned ccntainer"
|
||||
|
||||
new "when false + no name"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><x xmlns=\"urn:example:clixon\"><type>direct</type><y></y></x></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "validate ok"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "when: discard-changes"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><discard-changes/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "when true + no name"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><x xmlns=\"urn:example:clixon\"><type>static</type><y></y></x></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "validate fail"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "" "<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>missing-element</error-tag><error-info><bad-element>y</bad-element></error-info><error-severity>error</error-severity><error-message>Mandatory variable of x in module example</error-message></rpc-error></rpc-reply>"
|
||||
|
||||
new "when true + name"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><x xmlns=\"urn:example:clixon\"><type>static</type><y><name>a</name></y></x></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "validate ok"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "when: discard-changes"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><discard-changes/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "Second: have mandatory leaf under a non-empty when-conditioned ccntainer"
|
||||
|
||||
new "when false + no name + extra"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><x xmlns=\"urn:example:clixon\"><type>direct</type><y><extra>b</extra></y></x></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "validate fail extra"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "" "<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>operation-failed</error-tag><error-severity>error</error-severity><error-message>Failed WHEN condition of y in module example (WHEN xpath is ../type='static')</error-message></rpc-error></rpc-reply>"
|
||||
|
||||
new "when: discard-changes"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><discard-changes/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "when true + no name + extra"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><x xmlns=\"urn:example:clixon\"><type>static</type><y><extra>b</extra></y></x></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "validate fail"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "" "<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>missing-element</error-tag><error-info><bad-element>name</bad-element></error-info><error-severity>error</error-severity><error-message>Mandatory variable of y in module example</error-message></rpc-error></rpc-reply>"
|
||||
|
||||
new "when true + name"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><x xmlns=\"urn:example:clixon\"><type>static</type><y><name>a</name><extra>b</extra></y></x></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "validate ok"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "when: discard-changes"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><discard-changes/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "Third: have mandatory leaf under two empty when-conditioned ccntainer"
|
||||
new "when false + no name"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><x2 xmlns=\"urn:example:clixon\"><type>direct</type><y2><y3/></y2></x2></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "validate ok"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "when: discard-changes"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><discard-changes/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "when true + no name"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><x2 xmlns=\"urn:example:clixon\"><type>static</type><y2><y3/></y2></x2></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "validate fail"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "" "<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>missing-element</error-tag><error-info><bad-element>y2</bad-element></error-info><error-severity>error</error-severity><error-message>Mandatory variable of x2 in module example</error-message></rpc-error></rpc-reply>"
|
||||
|
||||
new "when true + name"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><x2 xmlns=\"urn:example:clixon\"><type>static</type><y2><y3><name>a</name></y3></y2></x2></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "validate ok"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "when: discard-changes"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><discard-changes/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "Fourth: have mandatory leaf under two non-empty when-conditioned ccntainer"
|
||||
|
||||
new "when false + no name + extra"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><x2 xmlns=\"urn:example:clixon\"><type>direct</type><y2><y3><extra>b</extra></y3></y2></x2></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "validate fail extra"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "" "<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>operation-failed</error-tag><error-severity>error</error-severity><error-message>Failed WHEN condition of y2 in module example (WHEN xpath is ../type='static')</error-message></rpc-error></rpc-reply>"
|
||||
|
||||
new "when: discard-changes"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><discard-changes/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "when true + no name + extra"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><x2 xmlns=\"urn:example:clixon\"><type>static</type><y2><y3><extra>b</extra></y3></y2></x2></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "validate fail"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "" "<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>missing-element</error-tag><error-info><bad-element>name</bad-element></error-info><error-severity>error</error-severity><error-message>Mandatory variable of y3 in module example</error-message></rpc-error></rpc-reply>"
|
||||
|
||||
new "when true + name"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><x2 xmlns=\"urn:example:clixon\"><type>static</type><y2><y3><name>a</name><extra>b</extra></y3></y2></x2></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "validate ok"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "when: discard-changes"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><discard-changes/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "Fifth: have mandatory leaf under one empty and one when-conditioned ccntainer"
|
||||
new "when false + no name"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><x3 xmlns=\"urn:example:clixon\"><type>direct</type><y2><y3/></y2></x3></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "validate ok"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "when: discard-changes"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><discard-changes/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "when true + no name"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><x3 xmlns=\"urn:example:clixon\"><type>static</type><y2><y3/></y2></x3></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "validate fail"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "" "<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>missing-element</error-tag><error-info><bad-element>y2</bad-element></error-info><error-severity>error</error-severity><error-message>Mandatory variable of x3 in module example</error-message></rpc-error></rpc-reply>"
|
||||
|
||||
new "when true + name"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><x3 xmlns=\"urn:example:clixon\"><type>static</type><y2><y3><name>a</name></y3></y2></x3></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "validate ok"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "when: discard-changes"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><discard-changes/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "Sixth: have mandatory leaf under one non-empty and one when-conditioned ccntainer"
|
||||
|
||||
new "when false + no name + extra"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><x3 xmlns=\"urn:example:clixon\"><type>direct</type><y2><y3><extra>b</extra></y3></y2></x3></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "validate fail extra"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "" "<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>operation-failed</error-tag><error-severity>error</error-severity><error-message>Failed WHEN condition of y3 in module example (WHEN xpath is ../../type='static')</error-message></rpc-error></rpc-reply>"
|
||||
|
||||
new "when: discard-changes"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><discard-changes/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "when true + no name + extra"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><x3 xmlns=\"urn:example:clixon\"><type>static</type><y2><y3><extra>b</extra></y3></y2></x3></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "validate fail"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "" "<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>missing-element</error-tag><error-info><bad-element>name</bad-element></error-info><error-severity>error</error-severity><error-message>Mandatory variable of y3 in module example</error-message></rpc-error></rpc-reply>"
|
||||
|
||||
new "when true + name"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><x3 xmlns=\"urn:example:clixon\"><type>static</type><y2><y3><name>a</name><extra>b</extra></y3></y2></x3></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "validate ok"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
new "when: discard-changes"
|
||||
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><discard-changes/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
|
||||
|
||||
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
|
||||
Loading…
Add table
Add a link
Reference in a new issue