From 19343c2b2180714bc46d3a80940d41e49cec048d Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Tue, 5 Feb 2019 14:03:58 +0100 Subject: [PATCH] * Partially corrected: [yang type range statement does not support multiple values](https://github.com/clicon/clixon/issues/59). * Should work for netconf and restconf, but not for CLI. * Fixed again: [Range parsing is not RFC 7950 compliant](https://github.com/clicon/clixon/issues/71) --- CHANGELOG.md | 3 + apps/cli/cli_generate.c | 150 ++++++++++++++++++++++------------ lib/src/clixon_string.c | 9 +- lib/src/clixon_yang.c | 92 ++++++++++----------- lib/src/clixon_yang_type.c | 163 ++++++++++++++++++------------------- test/test_type.sh | 114 +++++++++++++++++++++++--- 6 files changed, 329 insertions(+), 202 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ead8194c..d05c962d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -143,6 +143,9 @@ * JSON conversion problems [https://github.com/clicon/clixon/issues/66] diff --git a/apps/cli/cli_generate.c b/apps/cli/cli_generate.c index 62ed1e49..d2c5c39c 100644 --- a/apps/cli/cli_generate.c +++ b/apps/cli/cli_generate.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include /* For pow() kludge in cvtype_max2str_dup2 */ @@ -162,6 +163,98 @@ cli_callback_generate(clicon_handle h, return retval; } + +/*! Generate identityref statements for CLI variables + * @param[in] ys Yang statement + * @param[in] ytype Yang union type being resolved + * @param[in] helptext CLI help text + * @param[out] cb Buffer where cligen code is written + * @see yang2cli_var_sub Its sub-function + */ +static int +yang2cli_var_identityref(yang_stmt *ys, + yang_stmt *ytype, + char *cvtypestr, + char *helptext, + cbuf *cb) +{ + int retval = -1; + yang_stmt *ybaseref; + yang_stmt *ybaseid; + cg_var *cv = NULL; + char *name; + char *id; + int i; + + /* Add a wildchar string first -let validate take it for default prefix */ + cprintf(cb, ">"); + if (helptext) + cprintf(cb, "(\"%s\")", helptext); + if ((ybaseref = yang_find((yang_node*)ytype, Y_BASE, NULL)) != NULL && + (ybaseid = yang_find_identity(ys, ybaseref->ys_argument)) != NULL){ + if (cvec_len(ybaseid->ys_cvec) > 0){ + cprintf(cb, "|<%s:%s choice:", ys->ys_argument, cvtypestr); + i = 0; + while ((cv = cvec_each(ybaseid->ys_cvec, cv)) != NULL){ + if (i++) + cprintf(cb, "|"); + name = strdup(cv_name_get(cv)); + if ((id=strchr(name, ':')) != NULL) + *id = '\0'; + cprintf(cb, "%s:%s", name, id+1); + if (name) + free(name); + } + } + } + retval = 0; + // done: + return retval; +} + +/*! Generate range check statements for CLI variables + * @param[out] cb Buffer where cligen code is written + * @see yang2cli_var_sub Its sub-function + */ +static int +yang2cli_var_range(yang_stmt *ys, + cvec *cvv, + int options, + cbuf *cb) +{ + int retval = -1; + int i; + cg_var *cv; + + /* Loop through range_min and range_min..range_max */ + i = 0; + while (iys_argument); + break; + } + cv = cvec_i(cvv, i++); + if (strcmp(cv_name_get(cv),"range_min") == 0){ + cprintf(cb, " %s[", (options&YANG_OPTIONS_RANGE)?"range":"length"); + cv2cbuf(cv, cb); + cprintf(cb,":"); + /* probe next */ + if (i"); - if (helptext) - cprintf(cb, "(\"%s\")", helptext); - if ((ybaseref = yang_find((yang_node*)ytype, Y_BASE, NULL)) != NULL && - (ybaseid = yang_find_identity(ys, ybaseref->ys_argument)) != NULL){ - if (cvec_len(ybaseid->ys_cvec) > 0){ - cprintf(cb, "|<%s:%s choice:", ys->ys_argument, cvtypestr); - i = 0; - while ((cv = cvec_each(ybaseid->ys_cvec, cv)) != NULL){ - if (i++) - cprintf(cb, "|"); - name = strdup(cv_name_get(cv)); - if ((id=strchr(name, ':')) != NULL) - *id = '\0'; - cprintf(cb, "%s:%s", name, id+1); - if (name) - free(name); - } - } - } + if (yang2cli_var_identityref(ys, ytype, cvtypestr, helptext, cb) < 0) + goto done; } } - if (options & YANG_OPTIONS_FRACTION_DIGITS) cprintf(cb, " fraction-digits:%u", fraction_digits); if (options & (YANG_OPTIONS_RANGE|YANG_OPTIONS_LENGTH)){ - /* Loop through range_min and range_min..rang_max */ - i = 0; - while (iys_argument); - cv = cvec_i(cvv, i++); - if (strcmp(cv_name_get(cv),"range_min") == 0){ - cprintf(cb, " %s[", (options&YANG_OPTIONS_RANGE)?"range":"length"); - cv2cbuf(cv, cb); - cprintf(cb,":"); - /* probe next */ - if (i=0; i--){ /* trim from rear */ + if (isblank(s[i])) s[i] = '\0'; + else break; - } + } return s; } diff --git a/lib/src/clixon_yang.c b/lib/src/clixon_yang.c index bd6b2a68..3dc5dc89 100644 --- a/lib/src/clixon_yang.c +++ b/lib/src/clixon_yang.c @@ -1152,9 +1152,7 @@ bound_add(yang_stmt *ys, enum cv_type cvtype, char *name, char *val, - int options, - uint8_t fraction_digits - ) + uint8_t fraction_digits) { int retval = -1; cg_var *cv; @@ -1169,7 +1167,7 @@ bound_add(yang_stmt *ys, clicon_err(OE_YANG, errno, "cv_name_set(%s)", name); goto done; } - if (options & YANG_OPTIONS_FRACTION_DIGITS && cvtype == CGV_DEC64) + if (cvtype == CGV_DEC64) cv_dec64_n_set(cv, fraction_digits); if (strcmp(val, "min") == 0) cv_min_set(cv); @@ -1189,6 +1187,43 @@ bound_add(yang_stmt *ys, return retval; } +/*! Common range length parsing of "x .. y | z..w " statements + */ +static int +range_parse(yang_stmt *ys, + enum cv_type cvtype, + uint8_t fraction_digits) +{ + int retval = -1; + char **vec = NULL; + int nvec; + int i; + char *v; + char *v2; + + if ((vec = clicon_strsep(ys->ys_argument, "|", &nvec)) == NULL) + goto done; + for (i=0; iys_parent; /* Find parent: type */ if (yparent->yn_keyword != Y_TYPE){ @@ -1232,28 +1262,10 @@ ys_populate_range(yang_stmt *ys, /* This handles non-resolved also */ if (clicon_type2cv(origtype, restype, ys, &cvtype) < 0) goto done; - if ((vec = clicon_strsep(ys->ys_argument, "|", &nvec)) == NULL) + if (range_parse(ys, cvtype, fraction_digits) < 0) goto done; - for (i=0; iys_parent; /* Find parent: type */ if (yparent->yn_keyword != Y_TYPE){ @@ -1288,27 +1295,10 @@ ys_populate_length(yang_stmt *ys, goto done; } cvtype = CGV_UINT64; - if ((vec = clicon_strsep(ys->ys_argument, "|", &nvec)) == NULL) + if (range_parse(ys, cvtype, 0) < 0) goto done; - for (i=0; i]]>]]>" '^applicationbad-elementnum1errorNumber out of range: -1]]>]]>$' -new "cli range test num2 1000 ok" -expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num2 1000" 0 "^$" +new "netconf discard-changes" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" + +#-------- num2 range and blanks new "cli range test num2 3 error" expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num2 3" 255 "^$" +new "cli range test num2 1000 ok" +expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num2 1000" 0 "^$" + new "cli range test num2 5000 error" expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num2 5000" 255 "^$" +new "netconf range set num2 3 fail" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '3]]>]]>' "^]]>]]>$" + +new "netconf validate num2 3 fail" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^applicationbad-elementnum2errorNumber out of range: 3]]>]]>$' + +new "netconf range set num2 1000 ok" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '1000]]>]]>' "^]]>]]>$" + +new "netconf validate num2 1000 ok" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^]]>]]>$' + +new "netconf range set num2 5000 fail" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '5000]]>]]>' "^]]>]]>$" + +new "netconf validate num2 5000 fail" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^applicationbad-elementnum2errorNumber out of range: 5000]]>]]>$' + +new "netconf discard-changes" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" + +#-------- num3 min max range + new "cli range test num3 42 ok" expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num3 42" 0 "^$" -new "cli range test num3 260 error" +new "cli range test num3 260 fail" expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num3 260" 255 "^$" -#----------------string ranges--------------------- +new "cli range test num3 -1 fail" +expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num3 -1" 255 "^$" -new "cli length test len1 1 error" +new "netconf range set num3 260 fail" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '260]]>]]>' "^]]>]]>$" + +new "netconf validate num3 260 fail" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^applicationbad-elementnum3error260 is out of range(type is uint8)]]>]]>$' + +new "netconf discard-changes" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" + +#-------- num4 multiple ranges 1..2 | 42 + +new "cli range test num4 multiple 2 ok" +expectfn "$clixon_cli -1f $cfg -l e -y $fyang set num4 2" 0 "^$" + +new "cli range test num4 multiple 99 fail" +expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num4 99" 255 "^$" + +# See https://github.com/clicon/clixon/issues/59 +#new "cli range test num4 multiple 42 ok" +#expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num4 42" 0 "^$" + +new "netconf range set num4 multiple 2" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '42]]>]]>' "^]]>]]>$" + +new "netconf validate num4 OK" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^]]>]]>$' + +new "netconf range set num4 multiple 20" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '42]]>]]>' "^]]>]]>$" + +new "netconf validate num4 fail" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^]]>]]>$' + +new "netconf range set num4 multiple 42" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '42]]>]]>' "^]]>]]>$" + +new "netconf validate num4 fail" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^]]>]]>$' + +new "netconf discard-changes" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" + +#----------------string ranges--------------------- +#-------- len1 single range (2) +new "cli length test len1 1 fail" expectfn "$clixon_cli -1f $cfg -l o -y $fyang set len1 x" 255 "^$" new "cli length test len1 2 OK" @@ -356,18 +429,33 @@ expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>" '^applicationbad-elementlen1errorstring length out of range: 1]]>]]>$' +#-------- len2 range and blanks + +new "cli length test len2 3 error" +expectfn "$clixon_cli -1f $cfg -l o -y $fyang set len2 ab" 255 "^$" + new "cli length test len2 42 ok" expectfn "$clixon_cli -1f $cfg -l o -y $fyang set len2 hejhophdsakjhkjsadhkjsahdkjsad" 0 "^$" new "netconf discard-changes" expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" -new "cli length test len2 3 error" -expectfn "$clixon_cli -1f $cfg -l o -y $fyang set len2 ab" 255 "^$" +#-------- len3 min max range new "cli range test len3 42 ok" expectfn "$clixon_cli -1f $cfg -l o -y $fyang set len3 hsakjdhkjsahdkjsahdksahdksajdhsakjhd" 0 "^$" +#-------- len4 multiple ranges 1..2 | 42 (only first range) +new "cli length test len4 3 error" +expectfn "$clixon_cli -1f $cfg -l o -y $fyang set len4 abc" 255 "^$" + +new "cli length test len4 2 ok" +expectfn "$clixon_cli -1f $cfg -l o -y $fyang set len4 ab" 255 "^$" + +# See https://github.com/clicon/clixon/issues/59 +#new "cli length test len4 42 ok" +#expectfn "$clixon_cli -1f $cfg -l o -y $fyang set len4 hsakjdhkjsahdkjsahdksahdksajdhsakjhd" 0 "^$" + # XSD schema -> POSIX ECE translation new "cli yang pattern \d ok" expectfn "$clixon_cli -1f $cfg -l o -y $fyang set digit4 0123" 0 "^$"