Fixed: [YANG min-elements within non-presence container does not work](https://github.com/clicon/clixon/issues/355)

This commit is contained in:
Olof hagsand 2022-08-23 19:40:16 +02:00
parent ba9b313295
commit ba39f88936
3 changed files with 91 additions and 18 deletions

View file

@ -52,6 +52,7 @@ Expected: September 2022
### Corrected Bugs
* Fixed: [YANG min-elements within non-presence container does not work](https://github.com/clicon/clixon/issues/355)
* Fixed: [Issues with ietf-snmp modules](https://github.com/clicon/clixon/issues/353)
* Fixed: [Missing/no namespace error in YANG augments with default values](https://github.com/clicon/clixon/issues/354)
* Fixed: [Validation of mandatory in choice/case does not work in some cases](https://github.com/clicon/clixon/issues/349)

View file

@ -1223,6 +1223,52 @@ check_min_max(cxobj *xp,
goto done;
}
/*! Check if there is any empty list (no x elements) and check min-elements
* Note recurse for non-presence container
* @param[in] xt XML node
* @param[in] yt YANG node
* @param[out] xret Error XML tree. Free with xml_free after use
* @retval 1 Validation OK
* @retval 0 Validation failed (xret set)
* @retval -1 Error
*/
static int
check_empty_list_minmax(cxobj *xt,
yang_stmt *ye,
cxobj **xret)
{
int retval = -1;
int ret;
yang_stmt *yprev = NULL;
if (yang_config(ye) == 1){
if(yang_keyword_get(ye) == Y_CONTAINER &&
yang_find(ye, Y_PRESENCE, NULL) == NULL){
yprev = NULL;
while ((yprev = yn_each(ye, yprev)) != NULL) {
if ((ret = check_empty_list_minmax(xt, yprev, xret)) < 0)
goto done;
if (ret == 0)
goto fail;
}
}
else if (yang_keyword_get(ye) == Y_LIST ||
yang_keyword_get(ye) == Y_LEAF_LIST){
/* Check if the list length violates min/max */
if ((ret = check_min_max(xt, ye, 0, xret)) < 0)
goto done;
if (ret == 0)
goto fail;
}
}
retval = 1;
done:
return retval;
fail:
retval = 0;
goto done;
}
/*! Detect unique constraint for duplicates from parent node and minmax
* @param[in] xt XML parent (may have lists w unique constraints as child)
* @param[out] xret Error XML tree. Free with xml_free after use
@ -1289,7 +1335,7 @@ xml_yang_check_list_unique_minmax(cxobj *xt,
* o Otherwise, it is enforced if the ancestor node exists.
*/
yt = xml_spec(xt); /* If yt == NULL, then no gap-analysis is done */
/* Traverse all elemenents */
/* Traverse all elements */
while ((x = xml_child_each(xt, x, CX_ELMNT)) != NULL) {
if ((y = xml_spec(x)) == NULL)
continue;
@ -1335,14 +1381,10 @@ xml_yang_check_list_unique_minmax(cxobj *xt,
ye = yn_each(yt, ye);
if (ye && ych != ye)
do {
if (yang_config(ye) == 1 &&
(yang_keyword_get(ye) == Y_LIST || yang_keyword_get(ye) == Y_LEAF_LIST)){
/* Check if the list length violates min/max */
if ((ret = check_min_max(xt, ye, 0, xret)) < 0)
goto done;
if (ret == 0)
goto fail;
}
if ((ret = check_empty_list_minmax(xt, ye, xret)) < 0)
goto done;
if (ret == 0)
goto fail;
ye = yn_each(yt, ye);
} while(ye != NULL && /* to avoid livelock (shouldnt happen) */
ye != ych);
@ -1389,17 +1431,14 @@ xml_yang_check_list_unique_minmax(cxobj *xt,
/* Check if there is any empty list between after last non-empty list
* Note, does not detect empty lists within choice/case (too complicated)
*/
if ((ye = yn_each(yt, ye)) != NULL)
if ((ye = yn_each(yt, ye)) != NULL){
do {
if (yang_config(ye) == 1 &&
(yang_keyword_get(ye) == Y_LIST || yang_keyword_get(ye) == Y_LEAF_LIST)){
/* Check if the list length violates min/max */
if ((ret = check_min_max(xt, ye, 0, xret)) < 0)
goto done;
if (ret == 0)
goto fail;
}
if ((ret = check_empty_list_minmax(xt, ye, xret)) < 0)
goto done;
if (ret == 0)
goto fail;
} while((ye = yn_each(yt, ye)) != NULL);
}
retval = 1;
done:
return retval;

View file

@ -97,6 +97,24 @@ module $APPNAME{
min-elements 1;
max-elements 2;
}
container c3{
list b2{
description "RFC7950 7.7.5 : it is enforced if the ancestor node exists.";
key kb;
leaf kb {
type string;
}
container b2c {
leaf-list b2ll{
min-elements 1;
type string;
}
}
leaf-list b3ll{
type string;
}
}
}
}
EOF
@ -244,6 +262,21 @@ expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS
new "minmax: validate should fail empty list"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "" "<rpc-reply $DEFAULTNS><rpc-error><error-type>protocol</error-type><error-tag>operation-failed</error-tag><error-app-tag>too-few-elements</error-app-tag><error-severity>error</error-severity><error-path>/c/a1</error-path></rpc-error></rpc-reply>"
new "delete c"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS $DEFAULTNS><edit-config><target><candidate/></target><default-operation>none</default-operation><config><c xmlns=\"urn:example:clixon\" xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\" nc:operation=\"delete\"/></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
new "add empty list entry with a min-element leaf within a non-presence container"
expecteof_netconf "$clixon_netconf -qf $cfg -D 1 -l s" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS $DEFAULTNS><edit-config><target><candidate/></target><config><c3 xmlns=\"urn:example:clixon\"><b2><kb>0</kb></b2></c3></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
new "minmax: validate should fail, there should be a b2ll trailing"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "<rpc-reply $DEFAULTNS><rpc-error><error-type>protocol</error-type><error-tag>operation-failed</error-tag><error-app-tag>too-few-elements</error-app-tag><error-severity>error</error-severity><error-path>/c3/b2\[kb=\"0\"\]/b2ll</error-path></rpc-error></rpc-reply>" ""
new "add b3ll after missing b2ll"
expecteof_netconf "$clixon_netconf -qf $cfg -D 1 -l s" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS $DEFAULTNS><edit-config><target><candidate/></target><config><c3 xmlns=\"urn:example:clixon\"><b2><kb>0</kb><b3ll>42</b3ll></b2></c3></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
new "minmax: validate should fail, there should be a b2ll before b3ll"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "<rpc-reply $DEFAULTNS><rpc-error><error-type>protocol</error-type><error-tag>operation-failed</error-tag><error-app-tag>too-few-elements</error-app-tag><error-severity>error</error-severity><error-path>/c3/b2\[kb=\"0\"\]/b2ll</error-path></rpc-error></rpc-reply>" ""
if [ $BE -ne 0 ]; then
new "Kill backend"
# Check if premature kill