diff --git a/CHANGELOG.md b/CHANGELOG.md index a343903b1..988fd9f91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,6 +69,12 @@ ### API changes on existing features (you may need to change your code) +* Error messages for invalid number ranges and string lengths have been uniformed and changed. + * Error messages for invalid ranges are now on the form: + ``` + Number 23 out of range: 1-10 + String length 23 out of range: 1-10 + ``` * On validation callbacks, XML_FLAG_ADD is added to all nodes at startup validation, not just the top-level. This is the same behaviour as for steady-state validation. * All hash_ functions have been prefixed with `clicon_` to avoid name collision with other packages (frr) * All calls to the following functions must be changed: `hash_init`, `hash_free`, `hash_lookup`, `hash_value`, `hash_add`, `hash_del`, `hash_dump`, and `hash_keys`. diff --git a/lib/src/clixon_datastore_read.c b/lib/src/clixon_datastore_read.c index b4358ae7e..aed5e82d6 100644 --- a/lib/src/clixon_datastore_read.c +++ b/lib/src/clixon_datastore_read.c @@ -589,10 +589,6 @@ xmldb_get_zerocopy(clicon_handle h, db_elmnt *de = NULL; db_elmnt de0 = {0,}; - if (!clicon_option_bool(h, "CLICON_XMLDB_CACHE")){ - clicon_err(OE_CFG, 0, "CLICON_XMLDB_CACHE must be set"); - goto done; - } if ((yspec = clicon_dbspec_yang(h)) == NULL){ clicon_err(OE_YANG, ENOENT, "No yang spec"); goto done; diff --git a/lib/src/clixon_yang_type.c b/lib/src/clixon_yang_type.c index cc1de4055..3e00f7e82 100644 --- a/lib/src/clixon_yang_type.c +++ b/lib/src/clixon_yang_type.c @@ -588,6 +588,105 @@ cv_validate_pattern(clicon_handle h, (rmax && (i) > cv_##type##_get(rmax))) +/*! Error messsage for int violating ranges + * @note contains kludge - duplicate loop + */ +static int +outofrange(cg_var *cv0, + cvec *cvv, + char **reason) +{ + int retval = -1; + cbuf *cb = NULL; + cg_var *cv1; + cg_var *cv2; + int i; + + if ((cb = cbuf_new()) == NULL) + goto done; + cprintf(cb, "Number "); + cv2cbuf(cv0, cb); + cprintf(cb, " out of range: "); + /* Kludge: need to repeat the same loop as in the main function in + cv_validate1 */ + i = 0; + while (i2) + cprintf(cb, ", "); + cv2cbuf(cv1, cb); + cprintf(cb, "-"); + cv2cbuf(cv2, cb); + } + if (reason && (*reason = strdup(cbuf_get(cb))) == NULL) + goto done; + if (cb) + cbuf_free(cb); + retval = 0; + done: + return retval; +} + +/*! Error messsage for string violating string limits + * @note contains kludge - duplicate loop + */ +static int +outoflength(uint64_t u64, + cvec *cvv, + char **reason) +{ + int retval = -1; + cbuf *cb = NULL; + cg_var *cv1; + cg_var *cv2; + int i; + + if ((cb = cbuf_new()) == NULL) + goto done; + cprintf(cb, "String length %" PRIu64 " out of range: ", u64); + + /* Kludge: need to repeat the same loop as in the main function in + cv_validate1 */ + i = 0; + while (i2) + cprintf(cb, ", "); + cv2cbuf(cv1, cb); + cprintf(cb, "-"); + cv2cbuf(cv2, cb); + } + if (reason && (*reason = strdup(cbuf_get(cb))) == NULL) + goto done; + if (cb) + cbuf_free(cb); + retval = 0; + done: + return retval; +} + /*! Validate CLIgen variable * @param[in] h Clicon handle * @param[in] cv A cligen variable to validate. This is a correctly parsed cv. @@ -600,6 +699,7 @@ cv_validate_pattern(clicon_handle h, * @retval 0 Validation not OK, malloced reason is returned. Free reason with free() * @retval 1 Validation OK * @note reason if given must be freed by caller + * @see cv_validate Corresponding type check in cligen */ static int cv_validate1(clicon_handle h, @@ -705,14 +805,13 @@ cv_validate1(clicon_handle h, /* Check fails */ if (i==cvec_len(cvv)){ /* And it is last */ if (reason){ - if (reti) - *reason = cligen_reason("Number out of range: %" - PRId64, ii); - else if (retu) - *reason = cligen_reason("Number out of range: %" - PRIu64, uu); + if (reti || retu){ + if (outofrange(cv, cvv, reason) < 0) + goto done; + } else - *reason = cligen_reason("string length out of range: %" PRIu64, uu); + if (outoflength(uu, cvv, reason) < 0) + goto done; } goto fail; } diff --git a/test/all.sh b/test/all.sh index 6711558f7..18ebde016 100755 --- a/test/all.sh +++ b/test/all.sh @@ -6,7 +6,8 @@ : ${pattern:=test_*.sh} if [ $# -gt 0 ]; then - echo "usage: $0 # detailed logs and stopon first error" + echo "usage: $0 # detailed logs and stop on first error. Use pattern=\"\" $0 to" + echo " Use pattern= $0 to narrow down test cases" exit -1 fi diff --git a/test/test_insert.sh b/test/test_insert.sh index dccdfae3d..eea94e1dd 100755 --- a/test/test_insert.sh +++ b/test/test_insert.sh @@ -3,7 +3,6 @@ # First a list with 0-5 base elements, insert in different places # Second varying yangs: container, leaf, list, leaf-list, choice, user-order list - # Magic line must be first in script (see README.md) s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi @@ -27,7 +26,6 @@ cat < $cfg /usr/local/var/$APPNAME/$APPNAME.sock /usr/local/var/$APPNAME/$APPNAME.pidfile $dir - true EOF diff --git a/test/test_transaction.sh b/test/test_transaction.sh index 69bddea01..eec920dde 100755 --- a/test/test_transaction.sh +++ b/test/test_transaction.sh @@ -177,7 +177,7 @@ new "3. Validate system-error config (9999 not in range)" expecteof "$clixon_netconf -qf $cfg" 0 "$nr9999]]>]]>" '^]]>]]>$' new "Validate system-error validate (should fail)" -expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' '^applicationbad-elementberrorNumber out of range: 9999]]>]]>$' +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' '^applicationbad-elementberrorNumber 9999 out of range: 0-100]]>]]>$' new "Validate system-error discard-changes" expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" diff --git a/test/test_type.sh b/test/test_type.sh index 52265bd3a..ac52f8b0f 100755 --- a/test/test_type.sh +++ b/test/test_type.sh @@ -197,7 +197,7 @@ EOF # Type tests. # Parameters: -# 1: dbcache true/false +# 1: dbcache: cache, nocache, cache-zerocopy testrun(){ dbcache=$1 new "test params: -f $cfg # dbcache: $dbcache" @@ -216,7 +216,7 @@ testrun(){ /usr/local/var/$APPNAME/$APPNAME.pidfile 1 /usr/local/var/$APPNAME - $dbcache + $dbcache $format EOF @@ -231,7 +231,7 @@ EOF start_backend -s init -f $cfg new "waiting" - sleep $RCWAIT + wait_backend fi new "cli set transitive string. type is alpha followed by number and is defined in three levels of modules" @@ -360,7 +360,7 @@ EOF expecteof "$clixon_netconf -qf $cfg" 0 '-1]]>]]>' "^]]>]]>$" new "netconf validate num1 -1 wrong" - expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^applicationbad-elementnum1errorNumber out of range: -1]]>]]>$' + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^applicationbad-elementnum1errorNumber -1 out of range: 1-1]]>]]>$' new "netconf discard-changes" expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" @@ -368,7 +368,7 @@ EOF #-------- num2 range and blanks new "cli range test num2 3 error" - expectfn "$clixon_cli -1f $cfg -l o set num2 3" 255 '^CLI syntax error: "set num2 3": Number out of range: 3$' + expectfn "$clixon_cli -1f $cfg -l o set num2 3" 255 '^CLI syntax error: "set num2 3": Number 3 out of range: 4-4000$' new "cli range test num2 1000 ok" expectfn "$clixon_cli -1f $cfg -l o set num2 1000" 0 '^$' @@ -380,7 +380,7 @@ EOF expecteof "$clixon_netconf -qf $cfg" 0 '3]]>]]>' "^]]>]]>$" new "netconf validate num2 3 fail" - expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^applicationbad-elementnum2errorNumber out of range: 3]]>]]>$' + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^applicationbad-elementnum2errorNumber 3 out of range: 4-4000]]>]]>$' new "netconf range set num2 1000 ok" expecteof "$clixon_netconf -qf $cfg" 0 '1000]]>]]>' "^]]>]]>$" @@ -392,7 +392,7 @@ EOF expecteof "$clixon_netconf -qf $cfg" 0 '5000]]>]]>' "^]]>]]>$" new "netconf validate num2 5000 fail" - expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^applicationbad-elementnum2errorNumber out of range: 5000]]>]]>$' + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^applicationbad-elementnum2errorNumber 5000 out of range: 4-4000]]>]]>$' new "netconf discard-changes" expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" @@ -420,7 +420,7 @@ EOF #-------- num4 multiple ranges 1..2 | 42..50 new "cli range test num4 multiple 0 fail" - expectfn "$clixon_cli -1f $cfg -l o set num4 0" 255 '^CLI syntax error: "set num4 0": Number out of range: 0$' + expectfn "$clixon_cli -1f $cfg -l o set num4 0" 255 '^CLI syntax error: "set num4 0": Number 0 out of range: 1-2, 42-50$' new "cli range test num4 multiple 2 ok" expectfn "$clixon_cli -1f $cfg -l e set num4 2" 0 '^$' @@ -477,7 +477,7 @@ EOF expecteof "$clixon_netconf -qf $cfg" 0 '-3.59]]>]]>' "^]]>]]>$" new "netconf range dec64 -3.59 validate fail" - expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^applicationbad-elementdecerrorNumber out of range' + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^applicationbad-elementdecerrorNumber -3.590 out of range' new "netconf range dec64 -3.5" expecteof "$clixon_netconf -qf $cfg" 0 '-3.500]]>]]>' "^]]>]]>$" @@ -489,13 +489,13 @@ EOF expecteof "$clixon_netconf -qf $cfg" 0 '-2]]>]]>' "^]]>]]>$" new "netconf range dec64 -2 validate fail" - expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^applicationbad-elementdecerrorNumber out of range' + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^applicationbad-elementdecerrorNumber -2.000 out of range' new "netconf range dec64 -0.001" expecteof "$clixon_netconf -qf $cfg" 0 '-0.001]]>]]>' "^]]>]]>$" new "netconf range dec64 -0.001 validate fail" - expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^applicationbad-elementdecerrorNumber out of range' + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^applicationbad-elementdecerrorNumber -0.001 out of range' new "netconf range dec64 0.0" expecteof "$clixon_netconf -qf $cfg" 0 '0.0]]>]]>' "^]]>]]>$" @@ -507,12 +507,12 @@ EOF expecteof "$clixon_netconf -qf $cfg" 0 '+0.001]]>]]>' "^]]>]]>$" new "netconf range dec64 +0.001 validate fail" - expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^applicationbad-elementdecerrorNumber out of range' + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^applicationbad-elementdecerrorNumber 0.001 out of range' #----------------string ranges--------------------- #-------- len1 single range (2) new "cli length test len1 1 fail" - expectfn "$clixon_cli -1f $cfg -l o set len1 x" 255 '^CLI syntax error: "set len1 x": String length not within limits: 1$' + expectfn "$clixon_cli -1f $cfg -l o set len1 x" 255 '^CLI syntax error: "set len1 x": String length 1 out of range: 2-2$' new "cli length test len1 2 OK" expectfn "$clixon_cli -1f $cfg -l o set len1 xy" 0 '^$' @@ -527,12 +527,12 @@ EOF expecteof "$clixon_netconf -qf $cfg" 0 'x]]>]]>' "^]]>]]>$" new "netconf validate len1 1 wrong" - expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^applicationbad-elementlen1errorstring length out of range: 1]]>]]>$' + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^applicationbad-elementlen1errorString length 1 out of range: 2-2]]>]]>$' #-------- len2 range and blanks new "cli length test len2 3 error" - expectfn "$clixon_cli -1f $cfg -l o set len2 ab" 255 '^CLI syntax error: "set len2 ab": String length not within limits: 2$' + expectfn "$clixon_cli -1f $cfg -l o set len2 ab" 255 '^CLI syntax error: "set len2 ab": String length 2 out of range: 4-4000$' new "cli length test len2 42 ok" expectfn "$clixon_cli -1f $cfg -l o set len2 hejhophdsakjhkjsadhkjsahdkjsad" 0 '^$' @@ -547,7 +547,7 @@ EOF #-------- len4 multiple ranges 2..3 | 20-29 new "cli length test len4 1 error" - expectfn "$clixon_cli -1f $cfg -l o set len4 a" 255 '^CLI syntax error: "set len4 a": String length not within limits: 1$' + expectfn "$clixon_cli -1f $cfg -l o set len4 a" 255 '^CLI syntax error: "set len4 a": String length 1 out of range: 2-3, 20-29$' new "cli length test len4 2 ok" expectfn "$clixon_cli -1f $cfg -l o set len4 ab" 0 '^$' @@ -614,9 +614,12 @@ EOF } # Run without db cache -testrun false +testrun nocache # Run with db cache -testrun true +testrun cache + +# Run with zero-copy XXX does not work +#testrun cache-zerocopy rm -rf $dir diff --git a/test/test_type_range.sh b/test/test_type_range.sh new file mode 100755 index 000000000..35db73c52 --- /dev/null +++ b/test/test_type_range.sh @@ -0,0 +1,252 @@ +#!/bin/bash +# Range type tests. +# Mainly error messages and multiple ranges +# Tests all int types including decimal64 and string length ranges +# See also test_type.sh + +# 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 + +# Which format to use as datastore format internally +: ${format:=xml} + +cfg=$dir/conf_yang.xml +fyang=$dir/type.yang +dclispec=$dir/clispec/ + +# XXX: add more types, now only uint8 and int8 +cat < $fyang +module example{ + yang-version 1.1; + namespace "urn:example:clixon"; + prefix ex; + typedef tint8{ + type int8{ + range "1..10 | 14..20"; + } + } + typedef tint16{ + type int16{ + range "1..10 | 14..20"; + } + } + typedef tint32{ + type int32{ + range "1..10 | 14..20"; + } + } + typedef tint64{ + type int64{ + range "1..10 | 14..20"; + } + } + typedef tuint8{ + type uint8{ + range "1..10 | 14..20"; + } + } + typedef tuint16{ + type uint16{ + range "1..10 | 14..20"; + } + } + typedef tuint32{ + type uint32{ + range "1..10 | 14..20"; + } + } + typedef tuint64{ + type uint64{ + range "1..10 | 14..20"; + } + } + typedef tdecimal64{ + type decimal64{ + fraction-digits 3; + range "1..10 | 14..20"; + } + } + typedef tstring{ + type string{ + length "1..10 | 14..20"; + } + } + leaf lint8 { + type tint8; + } + leaf lint16 { + type tint16; + } + leaf lint32 { + type tint32; + } + leaf lint64 { + type tint64; + } + leaf luint8 { + type tuint8; + } + leaf luint16 { + type tuint16; + } + leaf luint32 { + type tuint32; + } + leaf luint64 { + type tuint64; + } + leaf ldecimal64 { + type tdecimal64; + } + leaf lstring { + type tstring; + } +} +EOF + +mkdir $dclispec + +# clispec for both generated cli and a hardcoded range check +cat < $dclispec/clispec.cli + CLICON_MODE="example"; + CLICON_PROMPT="%U@%H> "; + CLICON_PLUGIN="example_cli"; + + # Manually added (not generated) + manual hint8 ; + manual hint16 ; + manual hint32 ; + manual hint64 ; + + manual huint8 ; + manual huint16 ; + manual huint32 ; + manual huint64 ; + + manual hdecimal64 ; + + manual hstring ; + + # Generated cli + set @datamodel, cli_set(); + merge @datamodel, cli_merge(); + create @datamodel, cli_create(); + show, cli_show_config("candidate", "text", "/"); + quit("Quit"), cli_quit(); +EOF + +cat < $cfg + + $cfg + $dir + /usr/local/share/clixon + $IETFRFC + $fyang + $dclispec + /usr/local/lib/$APPNAME/cli + $APPNAME + /usr/local/var/$APPNAME/$APPNAME.sock + /usr/local/var/$APPNAME/$APPNAME.pidfile + 1 + /usr/local/var/$APPNAME + $format + +EOF + +# Type range tests. +# Parameters: 1: type (eg uint8) +# 2: val OK +# 3: eval Invalid value +# 4: post (eg .000 - special for decimal64, others should have "") +testrange(){ + t=$1 + val=$2 + eval=$3 + post=$4 + + if [ $t = "string" ]; then # special case for string type error msg + len=$(echo -n "$eval" | wc -c) + errmsg="String length $len out of range: 1$post-10$post, 14$post-20$post" + else + errmsg="Number $eval$post out of range: 1$post-10$post, 14$post-20$post" + fi + + new "generated cli set $t leaf invalid" + expectfn "$clixon_cli -1f $cfg -l o set l$t $eval" 255 "$errmsg"; + + new "generated cli set $t leaf OK" + expectfn "$clixon_cli -1f $cfg -l o set l$t $val" 0 '^$' + + # XXX Error in cligen order: Unknown command vs Number out of range + # olof@vandal> set luint8 0 + # CLI syntax error: "set luint8 0": Number 0 is out of range: 14 - 20 + # olof@vandal> set luint8 1 + # olof@vandal> set luint8 0 + # CLI syntax error: "set luint8 0": Unknown command +# (SAME AS FIRST ^) +# new "generated cli set $t leaf invalid" +# expectfn "$clixon_cli -1f $cfg -l o set l$t $eval" 255 "\"set l$t $eval\": Number $eval out of range: 1-10, 14-20"; + + new "manual cli set $t leaf OK" + expectfn "$clixon_cli -1f $cfg -l o man h$t $val" 0 '^$' + + new "manual cli set $t leaf invalid" + echo "$clixon_cli -1f $cfg -l o set h$t $eval" + expectfn "$clixon_cli -1f $cfg -l o set l$t $eval" 255 'Unknown command' + + new "discard" + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" + + new "Netconf set invalid $t leaf" + expecteof "$clixon_netconf -qf $cfg" 0 "$eval]]>]]>" "^]]>]]>$" + + new "netconf get config" + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^$eval]]>]]>$" + + new "netconf validate invalid range" + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^applicationbad-elementl$terror$errmsg]]>]]>$" + + new "discard" + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" +} + +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 + + new "waiting" + wait_backend +fi + +new "test params: -f $cfg" + +# Test all int types +for t in int8 int16 int32 int64 uint8 uint16 uint32 uint64; do + testrange $t 1 0 "" +done + +# decimal64 requires 3 decimals as postfix +testrange decimal64 1 0 ".000" + +# test string with lengthlimit +testrange string "012" "01234567890" "" + +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