Keyword "min" (not only "max") can be used in built-in types "range" and "length" statements.
This commit is contained in:
parent
bd67a2a5f2
commit
c7e847cd24
14 changed files with 469 additions and 405 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -44,5 +44,5 @@ build-root/*.tar.xz
|
||||||
build-root/*.rpm
|
build-root/*.rpm
|
||||||
build-root/rpmbuild
|
build-root/rpmbuild
|
||||||
|
|
||||||
test/public
|
test/site.sh
|
||||||
doc/html
|
doc/html
|
||||||
|
|
@ -112,6 +112,7 @@
|
||||||
* <!DOCTYPE (ie DTD) is not supported.
|
* <!DOCTYPE (ie DTD) is not supported.
|
||||||
|
|
||||||
### Corrected Bugs
|
### Corrected Bugs
|
||||||
|
* Keyword "min" (not only "max") can be used in built-in types "range" and "length" statements.
|
||||||
* Support for empty yang string added, eg `default "";`
|
* Support for empty yang string added, eg `default "";`
|
||||||
* Removed CLI generation for yang notifications (and other non-data yang nodes)
|
* Removed CLI generation for yang notifications (and other non-data yang nodes)
|
||||||
* Some restconf error messages contained "rpc-reply" or "rpc-error" which have now been removed.
|
* Some restconf error messages contained "rpc-reply" or "rpc-error" which have now been removed.
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,8 @@ However, the following YANG syntax modules are not implemented:
|
||||||
- belongs-to
|
- belongs-to
|
||||||
|
|
||||||
Restrictions on Yang types are as follows:
|
Restrictions on Yang types are as follows:
|
||||||
- The range statement does not support multiple values (RFC7950 9.2.4)
|
- The range statement for built-in integers does not support multiple values (RFC7950 9.2.4)
|
||||||
|
- The length statement for built-in strings does not support multiple values (RFC7950 9.4.4)
|
||||||
- Submodules cannot re-use a prefix in an import statement that is already used for another imported module in the module that the submodule belongs to. (see https://github.com/clicon/clixon/issues/60)
|
- Submodules cannot re-use a prefix in an import statement that is already used for another imported module in the module that the submodule belongs to. (see https://github.com/clicon/clixon/issues/60)
|
||||||
- default values on leaf-lists (RFC7950 7.7.2)
|
- default values on leaf-lists (RFC7950 7.7.2)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -169,28 +169,6 @@ static int yang2cli_stmt(clicon_handle h, yang_stmt *ys, cbuf *cb,
|
||||||
static int yang2cli_var_union(clicon_handle h, yang_stmt *ys, char *origtype,
|
static int yang2cli_var_union(clicon_handle h, yang_stmt *ys, char *origtype,
|
||||||
yang_stmt *ytype, cbuf *cb, char *helptext);
|
yang_stmt *ytype, cbuf *cb, char *helptext);
|
||||||
|
|
||||||
/*! Patched maxstring to account for DEC64 types
|
|
||||||
* @note kludge to fix overflow error -> Fix the original error in cvtype_max2str
|
|
||||||
* by adding a fraction_digits argument.
|
|
||||||
*/
|
|
||||||
static char *
|
|
||||||
cvtype_max2str_dup2(enum cv_type type,
|
|
||||||
int fraction_digits)
|
|
||||||
{
|
|
||||||
int len;
|
|
||||||
char *str;
|
|
||||||
|
|
||||||
if (type!=CGV_DEC64 || fraction_digits==0)
|
|
||||||
return cvtype_max2str_dup(type);
|
|
||||||
if ((len = cvtype_max2str(type, NULL, 0)) < 0)
|
|
||||||
return NULL;
|
|
||||||
if ((str = (char *)malloc(len+1)) == NULL)
|
|
||||||
return NULL;
|
|
||||||
memset(str, '\0', len+1);
|
|
||||||
len = snprintf(str, len+1, "%" PRId64 ".0", (INT64_MAX/((int)pow(10,fraction_digits))));
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Generate CLI code for Yang leaf statement to CLIgen variable of specific type
|
/*! Generate CLI code for Yang leaf statement to CLIgen variable of specific type
|
||||||
* Check for completion (of already existent values), ranges (eg range[min:max]) and
|
* Check for completion (of already existent values), ranges (eg range[min:max]) and
|
||||||
* patterns, (eg regexp:"[0.9]*").
|
* patterns, (eg regexp:"[0.9]*").
|
||||||
|
|
@ -208,18 +186,17 @@ yang2cli_var_sub(clicon_handle h,
|
||||||
char *helptext,
|
char *helptext,
|
||||||
enum cv_type cvtype,
|
enum cv_type cvtype,
|
||||||
int options,
|
int options,
|
||||||
cg_var *mincv,
|
cvec *cvv,
|
||||||
cg_var *maxcv,
|
|
||||||
char *pattern,
|
char *pattern,
|
||||||
uint8_t fraction_digits
|
uint8_t fraction_digits
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *type;
|
char *type;
|
||||||
char *r;
|
|
||||||
yang_stmt *yi = NULL;
|
yang_stmt *yi = NULL;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
char *cvtypestr;
|
char *cvtypestr;
|
||||||
|
cg_var *cv;
|
||||||
|
|
||||||
if (cvtype == CGV_VOID){
|
if (cvtype == CGV_VOID){
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -276,44 +253,30 @@ yang2cli_var_sub(clicon_handle h,
|
||||||
|
|
||||||
if (options & YANG_OPTIONS_FRACTION_DIGITS)
|
if (options & YANG_OPTIONS_FRACTION_DIGITS)
|
||||||
cprintf(cb, " fraction-digits:%u", fraction_digits);
|
cprintf(cb, " fraction-digits:%u", fraction_digits);
|
||||||
|
|
||||||
if (options & (YANG_OPTIONS_RANGE|YANG_OPTIONS_LENGTH)){
|
if (options & (YANG_OPTIONS_RANGE|YANG_OPTIONS_LENGTH)){
|
||||||
assert(mincv || maxcv);
|
/* Loop through range_min and range_min..rang_max */
|
||||||
|
i = 0;
|
||||||
|
while (i<cvec_len(cvv)){
|
||||||
|
// if (i)
|
||||||
|
// clicon_log(LOG_NOTICE, "%s: Warning %s has more ranges, ignoring", __FUNCTION__, ys->ys_argument);
|
||||||
|
cv = cvec_i(cvv, i++);
|
||||||
|
if (strcmp(cv_name_get(cv),"range_min") == 0){
|
||||||
cprintf(cb, " %s[", (options&YANG_OPTIONS_RANGE)?"range":"length");
|
cprintf(cb, " %s[", (options&YANG_OPTIONS_RANGE)?"range":"length");
|
||||||
if (mincv){
|
cv2cbuf(cv, cb);
|
||||||
if ((r = cv2str_dup(mincv)) == NULL){
|
cprintf(cb,":");
|
||||||
clicon_err(OE_UNIX, errno, "cv2str_dup");
|
/* probe next */
|
||||||
goto done;
|
if (i<cvec_len(cvv) &&
|
||||||
|
(cv = cvec_i(cvv, i)) != NULL &&
|
||||||
|
strcmp(cv_name_get(cv),"range_max") == 0){
|
||||||
|
i++;
|
||||||
|
cv2cbuf(cv, cb);
|
||||||
}
|
}
|
||||||
cprintf(cb, "%s:", r);
|
else /* If not, it is a single number range [x:x]*/
|
||||||
free(r);
|
cv2cbuf(cv, cb);
|
||||||
r = NULL;
|
cprintf(cb,"]");
|
||||||
}
|
|
||||||
if (maxcv != NULL){
|
|
||||||
if ((r = cv2str_dup(maxcv)) == NULL){
|
|
||||||
clicon_err(OE_UNIX, errno, "cv2str_dup");
|
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{ /* Cligen does not have 'max' keyword in range so need to find actual
|
|
||||||
max value of type if yang range expression is 0..max
|
|
||||||
*/
|
|
||||||
if (cvtype==CGV_STRING){
|
|
||||||
if ((r = malloc(512)) == NULL){
|
|
||||||
clicon_err(OE_UNIX, errno, "malloc");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
snprintf(r, 512, "%d", MAXPATHLEN);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ((r = cvtype_max2str_dup2(cvtype, fraction_digits)) == NULL){
|
|
||||||
clicon_err(OE_UNIX, errno, "cvtype_max2str");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cprintf(cb, "%s]", r); /* range */
|
|
||||||
free(r);
|
|
||||||
r = NULL;
|
|
||||||
}
|
}
|
||||||
if (options & YANG_OPTIONS_PATTERN)
|
if (options & YANG_OPTIONS_PATTERN)
|
||||||
cprintf(cb, " regexp:\"%s\"", pattern);
|
cprintf(cb, " regexp:\"%s\"", pattern);
|
||||||
|
|
@ -347,8 +310,7 @@ yang2cli_var_union_one(clicon_handle h,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
int options = 0;
|
int options = 0;
|
||||||
cg_var *mincv = NULL;
|
cvec *cvv = NULL;
|
||||||
cg_var *maxcv = NULL;
|
|
||||||
char *pattern = NULL;
|
char *pattern = NULL;
|
||||||
uint8_t fraction_digits = 0;
|
uint8_t fraction_digits = 0;
|
||||||
enum cv_type cvtype;
|
enum cv_type cvtype;
|
||||||
|
|
@ -358,7 +320,7 @@ yang2cli_var_union_one(clicon_handle h,
|
||||||
/* Resolve the sub-union type to a resolved type */
|
/* Resolve the sub-union type to a resolved type */
|
||||||
if (yang_type_resolve(ys, ytsub, /* in */
|
if (yang_type_resolve(ys, ytsub, /* in */
|
||||||
&ytype, &options, /* resolved type */
|
&ytype, &options, /* resolved type */
|
||||||
&mincv, &maxcv, &pattern, &fraction_digits) < 0)
|
&cvv, &pattern, &fraction_digits) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
restype = ytype?ytype->ys_argument:NULL;
|
restype = ytype?ytype->ys_argument:NULL;
|
||||||
|
|
||||||
|
|
@ -370,7 +332,7 @@ yang2cli_var_union_one(clicon_handle h,
|
||||||
if (clicon_type2cv(origtype, restype, &cvtype) < 0)
|
if (clicon_type2cv(origtype, restype, &cvtype) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((retval = yang2cli_var_sub(h, ys, ytype, cb, helptext, cvtype,
|
if ((retval = yang2cli_var_sub(h, ys, ytype, cb, helptext, cvtype,
|
||||||
options, mincv, maxcv, pattern, fraction_digits)) < 0)
|
options, cvv, pattern, fraction_digits)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -438,8 +400,7 @@ yang2cli_var(clicon_handle h,
|
||||||
char *origtype;
|
char *origtype;
|
||||||
yang_stmt *yrestype; /* resolved type */
|
yang_stmt *yrestype; /* resolved type */
|
||||||
char *restype; /* resolved type */
|
char *restype; /* resolved type */
|
||||||
cg_var *mincv = NULL;
|
cvec *cvv = NULL;
|
||||||
cg_var *maxcv = NULL;
|
|
||||||
char *pattern = NULL;
|
char *pattern = NULL;
|
||||||
uint8_t fraction_digits = 0;
|
uint8_t fraction_digits = 0;
|
||||||
enum cv_type cvtype;
|
enum cv_type cvtype;
|
||||||
|
|
@ -448,7 +409,7 @@ yang2cli_var(clicon_handle h,
|
||||||
char *type;
|
char *type;
|
||||||
|
|
||||||
if (yang_type_get(ys, &origtype, &yrestype,
|
if (yang_type_get(ys, &origtype, &yrestype,
|
||||||
&options, &mincv, &maxcv, &pattern, &fraction_digits) < 0)
|
&options, &cvv, &pattern, &fraction_digits) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
restype = yrestype?yrestype->ys_argument:NULL;
|
restype = yrestype?yrestype->ys_argument:NULL;
|
||||||
|
|
||||||
|
|
@ -485,7 +446,7 @@ yang2cli_var(clicon_handle h,
|
||||||
if (completionp)
|
if (completionp)
|
||||||
cprintf(cb, "(");
|
cprintf(cb, "(");
|
||||||
if ((retval = yang2cli_var_sub(h, ys, yrestype, cb, helptext, cvtype,
|
if ((retval = yang2cli_var_sub(h, ys, yrestype, cb, helptext, cvtype,
|
||||||
options, mincv, maxcv, pattern, fraction_digits)) < 0)
|
options, cvv, pattern, fraction_digits)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (completionp){
|
if (completionp){
|
||||||
if (cli_expand_var_generate(h, ys, cvtype, cb,
|
if (cli_expand_var_generate(h, ys, cvtype, cb,
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,7 @@ int uri_percent_decode(char *enc, char **str);
|
||||||
const char *clicon_int2str(const map_str2int *mstab, int i);
|
const char *clicon_int2str(const map_str2int *mstab, int i);
|
||||||
int clicon_str2int(const map_str2int *mstab, char *str);
|
int clicon_str2int(const map_str2int *mstab, char *str);
|
||||||
int nodeid_split(char *nodeid, char **prefix, char **id);
|
int nodeid_split(char *nodeid, char **prefix, char **id);
|
||||||
|
char *clixon_trim(char *str);
|
||||||
#ifndef HAVE_STRNDUP
|
#ifndef HAVE_STRNDUP
|
||||||
char *clicon_strndup (const char *, size_t);
|
char *clicon_strndup (const char *, size_t);
|
||||||
#endif /* ! HAVE_STRNDUP */
|
#endif /* ! HAVE_STRNDUP */
|
||||||
|
|
|
||||||
|
|
@ -176,8 +176,7 @@ typedef struct yang_stmt yang_stmt; /* forward */
|
||||||
*/
|
*/
|
||||||
struct yang_type_cache{
|
struct yang_type_cache{
|
||||||
int yc_options;
|
int yc_options;
|
||||||
cg_var *yc_mincv;
|
cvec *yc_cvv; /* range and length restriction */
|
||||||
cg_var *yc_maxcv;
|
|
||||||
char *yc_pattern;
|
char *yc_pattern;
|
||||||
uint8_t yc_fraction;
|
uint8_t yc_fraction;
|
||||||
yang_stmt *yc_resolved; /* Resolved type object, can be NULL - note direct ptr */
|
yang_stmt *yc_resolved; /* Resolved type object, can be NULL - note direct ptr */
|
||||||
|
|
|
||||||
|
|
@ -55,11 +55,11 @@
|
||||||
* Prototypes
|
* Prototypes
|
||||||
*/
|
*/
|
||||||
int yang_type_cache_set(yang_type_cache **ycache,
|
int yang_type_cache_set(yang_type_cache **ycache,
|
||||||
yang_stmt *resolved, int options, cg_var *mincv,
|
yang_stmt *resolved, int options,
|
||||||
cg_var *maxcv, char *pattern, uint8_t fraction);
|
cvec *cvv, char *pattern, uint8_t fraction);
|
||||||
int yang_type_cache_get(yang_type_cache *ycache,
|
int yang_type_cache_get(yang_type_cache *ycache, yang_stmt **resolved,
|
||||||
yang_stmt **resolved, int *options, cg_var **mincv,
|
int *options, cvec **cvv, char **pattern,
|
||||||
cg_var **maxcv, char **pattern, uint8_t *fraction);
|
uint8_t *fraction);
|
||||||
int yang_type_cache_cp(yang_type_cache **ycnew, yang_type_cache *ycold);
|
int yang_type_cache_cp(yang_type_cache **ycnew, yang_type_cache *ycold);
|
||||||
int yang_type_cache_free(yang_type_cache *ycache);
|
int yang_type_cache_free(yang_type_cache *ycache);
|
||||||
int ys_resolve_type(yang_stmt *ys, void *arg);
|
int ys_resolve_type(yang_stmt *ys, void *arg);
|
||||||
|
|
@ -69,12 +69,11 @@ yang_stmt *yang_find_identity(yang_stmt *ys, char *identity);
|
||||||
int ys_cv_validate(cg_var *cv, yang_stmt *ys, char **reason);
|
int ys_cv_validate(cg_var *cv, yang_stmt *ys, char **reason);
|
||||||
int clicon_type2cv(char *type, char *rtype, enum cv_type *cvtype);
|
int clicon_type2cv(char *type, char *rtype, enum cv_type *cvtype);
|
||||||
int yang_type_get(yang_stmt *ys, char **otype, yang_stmt **restype,
|
int yang_type_get(yang_stmt *ys, char **otype, yang_stmt **restype,
|
||||||
int *options, cg_var **mincv, cg_var **maxcv, char **pattern,
|
int *options, cvec **cvv, char **pattern,
|
||||||
uint8_t *fraction_digits);
|
uint8_t *fraction_digits);
|
||||||
int yang_type_resolve(yang_stmt *ys, yang_stmt *ytype,
|
int yang_type_resolve(yang_stmt *ys, yang_stmt *ytype,
|
||||||
yang_stmt **restype, int *options,
|
yang_stmt **restype, int *options,
|
||||||
cg_var **mincv, cg_var **maxcv,
|
cvec **cvv, char **pattern, uint8_t *fraction);
|
||||||
char **pattern, uint8_t *fraction);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _CLIXON_YANG_TYPE_H_ */
|
#endif /* _CLIXON_YANG_TYPE_H_ */
|
||||||
|
|
|
||||||
|
|
@ -57,13 +57,14 @@
|
||||||
/*! Split string into a vector based on character delimiters. Using malloc
|
/*! Split string into a vector based on character delimiters. Using malloc
|
||||||
*
|
*
|
||||||
* The given string is split into a vector where the delimiter can be
|
* The given string is split into a vector where the delimiter can be
|
||||||
* any of the characters in the specified delimiter string.
|
* _any_ of the characters in the specified delimiter string.
|
||||||
*
|
*
|
||||||
* The vector returned is one single memory block that must be freed
|
* The vector returned is one single memory block that must be freed
|
||||||
* by the caller
|
* by the caller
|
||||||
*
|
*
|
||||||
* @code
|
* @code
|
||||||
* char **vec = NULL;
|
* char **vec = NULL;
|
||||||
|
* char *v;
|
||||||
* int nvec;
|
* int nvec;
|
||||||
* if ((vec = clicon_strsep("/home/user/src/clixon", "/", &nvec)) == NULL)
|
* if ((vec = clicon_strsep("/home/user/src/clixon", "/", &nvec)) == NULL)
|
||||||
* err;
|
* err;
|
||||||
|
|
@ -441,11 +442,14 @@ xml_chardata_encode(char **escp,
|
||||||
* @param[in] delim1 First delimiter char that delimits between elements
|
* @param[in] delim1 First delimiter char that delimits between elements
|
||||||
* @param[in] delim2 Second delimiter char for pairs within an element
|
* @param[in] delim2 Second delimiter char for pairs within an element
|
||||||
* @param[out] cvp Created cligen variable vector, deallocate w cvec_free
|
* @param[out] cvp Created cligen variable vector, deallocate w cvec_free
|
||||||
* @retval 0 on OK
|
* @retval 0 OK
|
||||||
* @retval -1 error
|
* @retval -1 error
|
||||||
|
* @code
|
||||||
|
* cvec *cvv = NULL;
|
||||||
|
* if (str2cvec("a=b&c=d", ';', '=', &cvv) < 0)
|
||||||
|
* err;
|
||||||
|
* @endcode
|
||||||
*
|
*
|
||||||
* @example,
|
|
||||||
* Assuming delim1 = '&' and delim2 = '='
|
|
||||||
* a=b&c=d -> [[a,"b"][c="d"]
|
* a=b&c=d -> [[a,"b"][c="d"]
|
||||||
* kalle&c=d -> [[c="d"]] # Discard elements with no delim2
|
* kalle&c=d -> [[c="d"]] # Discard elements with no delim2
|
||||||
* XXX differentiate between error and null cvec.
|
* XXX differentiate between error and null cvec.
|
||||||
|
|
@ -610,6 +614,26 @@ nodeid_split(char *nodeid,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Trim blanks from front and end of a string, return new string
|
||||||
|
* @param[in] str
|
||||||
|
* @retval s Pointer into existing str after trimming blanks
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
clixon_trim(char *str)
|
||||||
|
{
|
||||||
|
char *s = str;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
while (strlen(s) && isblank(s[0]))
|
||||||
|
s++;
|
||||||
|
for (i=0; i<strlen(s); i++)
|
||||||
|
if (isblank(s[i])){
|
||||||
|
s[i] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
/*! strndup() for systems without it, such as xBSD
|
/*! strndup() for systems without it, such as xBSD
|
||||||
*/
|
*/
|
||||||
#ifndef HAVE_STRNDUP
|
#ifndef HAVE_STRNDUP
|
||||||
|
|
|
||||||
|
|
@ -2414,7 +2414,7 @@ yang_enum_int_value(cxobj *node,
|
||||||
if ((ytype = yang_find((yang_node *)ys, Y_TYPE, NULL)) == NULL)
|
if ((ytype = yang_find((yang_node *)ys, Y_TYPE, NULL)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (yang_type_resolve(ys, ytype, &yrestype,
|
if (yang_type_resolve(ys, ytype, &yrestype,
|
||||||
NULL, NULL, NULL, NULL, NULL) < 0)
|
NULL, NULL, NULL, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (yrestype==NULL || strcmp(yrestype->ys_argument, "enumeration"))
|
if (yrestype==NULL || strcmp(yrestype->ys_argument, "enumeration"))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -1068,7 +1068,7 @@ ys_populate_leaf(yang_stmt *ys,
|
||||||
|
|
||||||
yparent = ys->ys_parent; /* Find parent: list/container */
|
yparent = ys->ys_parent; /* Find parent: list/container */
|
||||||
/* 1. Find type specification and set cv type accordingly */
|
/* 1. Find type specification and set cv type accordingly */
|
||||||
if (yang_type_get(ys, &type, &yrestype, &options, NULL, NULL, NULL, &fraction_digits) < 0)
|
if (yang_type_get(ys, &type, &yrestype, &options, NULL, NULL, &fraction_digits) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
restype = yrestype?yrestype->ys_argument:NULL;
|
restype = yrestype?yrestype->ys_argument:NULL;
|
||||||
if (clicon_type2cv(type, restype, &cvtype) < 0) /* This handles non-resolved also */
|
if (clicon_type2cv(type, restype, &cvtype) < 0) /* This handles non-resolved also */
|
||||||
|
|
@ -1133,12 +1133,62 @@ ys_populate_list(yang_stmt *ys,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Populate range and length statements
|
/*! Set range or length boundary for built-in yang types
|
||||||
|
* Help functions to range and length statements
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
bound_add(yang_stmt *ys,
|
||||||
|
enum cv_type cvtype,
|
||||||
|
char *name,
|
||||||
|
char *val,
|
||||||
|
int options,
|
||||||
|
uint8_t fraction_digits
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
cg_var *cv;
|
||||||
|
char *reason = NULL;
|
||||||
|
int ret = 1;
|
||||||
|
|
||||||
|
if ((cv = cvec_add(ys->ys_cvec, cvtype)) == NULL){
|
||||||
|
clicon_err(OE_YANG, errno, "cvec_add");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (cv_name_set(cv, name) == NULL){
|
||||||
|
clicon_err(OE_YANG, errno, "cv_name_set(%s)", name);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (options & YANG_OPTIONS_FRACTION_DIGITS && cvtype == CGV_DEC64)
|
||||||
|
cv_dec64_n_set(cv, fraction_digits);
|
||||||
|
if (strcmp(val, "min") == 0)
|
||||||
|
cv_min_set(cv);
|
||||||
|
else if (strcmp(val, "max") == 0)
|
||||||
|
cv_max_set(cv);
|
||||||
|
else if ((ret = cv_parse1(val, cv, &reason)) < 0){
|
||||||
|
clicon_err(OE_YANG, errno, "cv_parse1");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (ret == 0){ /* parsing failed */
|
||||||
|
clicon_err(OE_YANG, errno, "range statement %s: %s", val, reason);
|
||||||
|
free(reason);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Populate string built-in range statement
|
||||||
*
|
*
|
||||||
* Create cvec variables "range_min" and "range_max". Assume parent is type.
|
* Create cvec variables "range_min" and "range_max". Assume parent is type.
|
||||||
* Actually: min..max [| min..max]*
|
* Actually: bound[..bound] (| bound[..bound])*
|
||||||
* where min,max is integer or keywords 'min' or 'max.
|
* where bound is integer, decimal or keywords 'min' or 'max.
|
||||||
* We only allow one range, ie not 1..2|4..5
|
* RFC 7950 9.2.4:
|
||||||
|
* A range consists of an explicit value, or a lower-inclusive bound,
|
||||||
|
* two consecutive dots "..", and an upper-inclusive bound. Multiple
|
||||||
|
* values or ranges can be given, separated by "|". If multiple values
|
||||||
|
* or ranges are given, they all MUST be disjoint and MUST be in
|
||||||
|
* ascending order
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
ys_populate_range(yang_stmt *ys,
|
ys_populate_range(yang_stmt *ys,
|
||||||
|
|
@ -1152,11 +1202,11 @@ ys_populate_range(yang_stmt *ys,
|
||||||
int options = 0x0;
|
int options = 0x0;
|
||||||
uint8_t fraction_digits;
|
uint8_t fraction_digits;
|
||||||
enum cv_type cvtype = CGV_ERR;
|
enum cv_type cvtype = CGV_ERR;
|
||||||
char *minstr = NULL;
|
char **vec = NULL;
|
||||||
char *maxstr;
|
char *v;
|
||||||
cg_var *cv;
|
char *v2;
|
||||||
char *reason = NULL;
|
int nvec;
|
||||||
int cvret;
|
int i;
|
||||||
|
|
||||||
yparent = ys->ys_parent; /* Find parent: type */
|
yparent = ys->ys_parent; /* Find parent: type */
|
||||||
if (yparent->yn_keyword != Y_TYPE){
|
if (yparent->yn_keyword != Y_TYPE){
|
||||||
|
|
@ -1164,81 +1214,90 @@ ys_populate_range(yang_stmt *ys,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (yang_type_resolve(ys, (yang_stmt*)yparent, &yrestype,
|
if (yang_type_resolve(ys, (yang_stmt*)yparent, &yrestype,
|
||||||
&options, NULL, NULL, NULL, &fraction_digits) < 0)
|
&options, NULL, NULL, &fraction_digits) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
restype = yrestype?yrestype->ys_argument:NULL;
|
restype = yrestype?yrestype->ys_argument:NULL;
|
||||||
origtype = yarg_id((yang_stmt*)yparent);
|
origtype = yarg_id((yang_stmt*)yparent);
|
||||||
/* This handles non-resolved also */
|
/* This handles non-resolved also */
|
||||||
if (clicon_type2cv(origtype, restype, &cvtype) < 0)
|
if (clicon_type2cv(origtype, restype, &cvtype) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* special case for strings, where limit is length, not a string */
|
if ((vec = clicon_strsep(ys->ys_argument, "|", &nvec)) == NULL)
|
||||||
if (cvtype == CGV_STRING)
|
|
||||||
cvtype = CGV_UINT64;
|
|
||||||
if ((minstr = strdup(ys->ys_argument)) == NULL){
|
|
||||||
clicon_err(OE_YANG, errno, "strdup");
|
|
||||||
goto done;
|
goto done;
|
||||||
|
for (i=0; i<nvec; i++){
|
||||||
|
v = vec[i++];
|
||||||
|
v = clixon_trim(v); /* trim blanks */
|
||||||
|
if ((v2 = strstr(v, "..")) != NULL){
|
||||||
|
*v2 = '\0';
|
||||||
|
v2 += 2;
|
||||||
|
v2 = clixon_trim(v2); /* trim blanks */
|
||||||
}
|
}
|
||||||
if ((maxstr = strstr(minstr, "..")) != NULL){
|
if (bound_add(ys, cvtype, "range_min", v,
|
||||||
if (strlen(maxstr) < 2){
|
options, fraction_digits) < 0)
|
||||||
clicon_err(OE_YANG, 0, "range statement: %s not on the form: <int>..<int>",
|
|
||||||
ys->ys_argument);
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
if (v2)
|
||||||
minstr[maxstr-minstr] = '\0';
|
if (bound_add(ys, cvtype, "range_max",v2,
|
||||||
maxstr += 2;
|
options, fraction_digits) < 0)
|
||||||
/* minstr and maxstr need trimming */
|
|
||||||
if (isblank(minstr[strlen(minstr)-1]))
|
|
||||||
minstr[strlen(minstr)-1] = '\0';
|
|
||||||
if (isblank(maxstr[0]))
|
|
||||||
maxstr++;
|
|
||||||
if ((cv = cvec_add(ys->ys_cvec, cvtype)) == NULL){
|
|
||||||
clicon_err(OE_YANG, errno, "cvec_add");
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (cv_name_set(cv, "range_min") == NULL){
|
|
||||||
clicon_err(OE_YANG, errno, "cv_name_set");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (options & YANG_OPTIONS_FRACTION_DIGITS && cvtype == CGV_DEC64)
|
|
||||||
cv_dec64_n_set(cv, fraction_digits);
|
|
||||||
|
|
||||||
if ((cvret = cv_parse1(minstr, cv, &reason)) < 0){
|
|
||||||
clicon_err(OE_YANG, errno, "cv_parse1");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (cvret == 0){ /* parsing failed */
|
|
||||||
clicon_err(OE_YANG, errno, "range statement, min: %s", reason);
|
|
||||||
free(reason);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
maxstr = minstr;
|
|
||||||
if (strcmp(maxstr, "max") != 0){ /* no range_max means max */
|
|
||||||
if ((cv = cvec_add(ys->ys_cvec, cvtype)) == NULL){
|
|
||||||
clicon_err(OE_YANG, errno, "cvec_add");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (cv_name_set(cv, "range_max") == NULL){
|
|
||||||
clicon_err(OE_YANG, errno, "cv_name_set");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (options & YANG_OPTIONS_FRACTION_DIGITS && cvtype == CGV_DEC64)
|
|
||||||
cv_dec64_n_set(cv, fraction_digits);
|
|
||||||
if ((cvret = cv_parse1(maxstr, cv, &reason)) < 0){
|
|
||||||
clicon_err(OE_YANG, errno, "cv_parse1");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (cvret == 0){ /* parsing failed */
|
|
||||||
clicon_err(OE_YANG, errno, "range statement, max: %s", reason);
|
|
||||||
free(reason);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (minstr)
|
if (vec)
|
||||||
free(minstr);
|
free(vec);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Populate integer built-in length statement
|
||||||
|
*
|
||||||
|
* Create cvec variables "range_min" and "range_max". Assume parent is type.
|
||||||
|
* Actually: len[..len] (| len[..len])*
|
||||||
|
* len is unsigned integer or keywords 'min' or 'max.
|
||||||
|
* RFC 7950 9.4.4
|
||||||
|
* A length range consists of an explicit value, or a lower bound, two
|
||||||
|
* consecutive dots "..", and an upper bound. Multiple values or ranges
|
||||||
|
* can be given, separated by "|". Length-restricting values MUST NOT
|
||||||
|
* be negative. If multiple values or ranges are given, they all MUST
|
||||||
|
* be disjoint and MUST be in ascending order.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
ys_populate_length(yang_stmt *ys,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
yang_node *yparent; /* type */
|
||||||
|
enum cv_type cvtype = CGV_ERR;
|
||||||
|
char **vec = NULL;
|
||||||
|
char *v;
|
||||||
|
int nvec;
|
||||||
|
int i;
|
||||||
|
char *v2;
|
||||||
|
|
||||||
|
yparent = ys->ys_parent; /* Find parent: type */
|
||||||
|
if (yparent->yn_keyword != Y_TYPE){
|
||||||
|
clicon_err(OE_YANG, 0, "parent should be type");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
cvtype = CGV_UINT64;
|
||||||
|
if ((vec = clicon_strsep(ys->ys_argument, "|", &nvec)) == NULL)
|
||||||
|
goto done;
|
||||||
|
for (i=0; i<nvec; i++){
|
||||||
|
|
||||||
|
v = vec[i++];
|
||||||
|
v = clixon_trim(v); /* trim blanks */
|
||||||
|
if ((v2 = strstr(v, "..")) != NULL){
|
||||||
|
*v2 = '\0';
|
||||||
|
v2 += 2;
|
||||||
|
v2 = clixon_trim(v2); /* trim blanks */
|
||||||
|
}
|
||||||
|
if (bound_add(ys, cvtype, "range_min", v, 0, 0) < 0)
|
||||||
|
goto done;
|
||||||
|
if (v2)
|
||||||
|
if (bound_add(ys, cvtype, "range_max",v2, 0, 0) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (vec)
|
||||||
|
free(vec);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1485,10 +1544,13 @@ ys_populate(yang_stmt *ys,
|
||||||
goto done;
|
goto done;
|
||||||
break;
|
break;
|
||||||
case Y_RANGE:
|
case Y_RANGE:
|
||||||
case Y_LENGTH:
|
|
||||||
if (ys_populate_range(ys, NULL) < 0)
|
if (ys_populate_range(ys, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
break;
|
break;
|
||||||
|
case Y_LENGTH:
|
||||||
|
if (ys_populate_length(ys, NULL) < 0)
|
||||||
|
goto done;
|
||||||
|
break;
|
||||||
case Y_MANDATORY: /* call yang_mandatory() to check if set */
|
case Y_MANDATORY: /* call yang_mandatory() to check if set */
|
||||||
case Y_CONFIG:
|
case Y_CONFIG:
|
||||||
if (ys_parse(ys, CGV_BOOL) == NULL)
|
if (ys_parse(ys, CGV_BOOL) == NULL)
|
||||||
|
|
|
||||||
|
|
@ -115,8 +115,7 @@ int
|
||||||
yang_type_cache_set(yang_type_cache **ycache0,
|
yang_type_cache_set(yang_type_cache **ycache0,
|
||||||
yang_stmt *resolved,
|
yang_stmt *resolved,
|
||||||
int options,
|
int options,
|
||||||
cg_var *mincv,
|
cvec *cvv,
|
||||||
cg_var *maxcv,
|
|
||||||
char *pattern,
|
char *pattern,
|
||||||
uint8_t fraction)
|
uint8_t fraction)
|
||||||
{
|
{
|
||||||
|
|
@ -132,13 +131,11 @@ yang_type_cache_set(yang_type_cache **ycache0,
|
||||||
*ycache0 = ycache;
|
*ycache0 = ycache;
|
||||||
ycache->yc_resolved = resolved;
|
ycache->yc_resolved = resolved;
|
||||||
ycache->yc_options = options;
|
ycache->yc_options = options;
|
||||||
if (mincv && (ycache->yc_mincv = cv_dup(mincv)) == NULL){
|
if (cvv){
|
||||||
clicon_err(OE_UNIX, errno, "cv_dup");
|
if ((ycache->yc_cvv = cvec_dup(cvv)) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "cvec_dup");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (maxcv && (ycache->yc_maxcv = cv_dup(maxcv)) == NULL){
|
|
||||||
clicon_err(OE_UNIX, errno, "cv_dup");
|
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
if (pattern && (ycache->yc_pattern = strdup(pattern)) == NULL){
|
if (pattern && (ycache->yc_pattern = strdup(pattern)) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "strdup");
|
clicon_err(OE_UNIX, errno, "strdup");
|
||||||
|
|
@ -155,8 +152,7 @@ int
|
||||||
yang_type_cache_get(yang_type_cache *ycache,
|
yang_type_cache_get(yang_type_cache *ycache,
|
||||||
yang_stmt **resolved,
|
yang_stmt **resolved,
|
||||||
int *options,
|
int *options,
|
||||||
cg_var **mincv,
|
cvec **cvv,
|
||||||
cg_var **maxcv,
|
|
||||||
char **pattern,
|
char **pattern,
|
||||||
uint8_t *fraction)
|
uint8_t *fraction)
|
||||||
{
|
{
|
||||||
|
|
@ -164,10 +160,8 @@ yang_type_cache_get(yang_type_cache *ycache,
|
||||||
*resolved = ycache->yc_resolved;
|
*resolved = ycache->yc_resolved;
|
||||||
if (options)
|
if (options)
|
||||||
*options = ycache->yc_options;
|
*options = ycache->yc_options;
|
||||||
if (mincv)
|
if (cvv)
|
||||||
*mincv = ycache->yc_mincv;
|
*cvv = ycache->yc_cvv;
|
||||||
if (maxcv)
|
|
||||||
*maxcv = ycache->yc_maxcv;
|
|
||||||
if (pattern)
|
if (pattern)
|
||||||
*pattern = ycache->yc_pattern;
|
*pattern = ycache->yc_pattern;
|
||||||
if (fraction)
|
if (fraction)
|
||||||
|
|
@ -181,14 +175,13 @@ yang_type_cache_cp(yang_type_cache **ycnew,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
int options;
|
int options;
|
||||||
cg_var *mincv;
|
cvec *cvv;
|
||||||
cg_var *maxcv;
|
|
||||||
char *pattern;
|
char *pattern;
|
||||||
uint8_t fraction;
|
uint8_t fraction;
|
||||||
yang_stmt *resolved;
|
yang_stmt *resolved;
|
||||||
|
|
||||||
yang_type_cache_get(ycold, &resolved, &options, &mincv, &maxcv, &pattern, &fraction);
|
yang_type_cache_get(ycold, &resolved, &options, &cvv, &pattern, &fraction);
|
||||||
if (yang_type_cache_set(ycnew, resolved, options, mincv, maxcv, pattern, fraction) < 0)
|
if (yang_type_cache_set(ycnew, resolved, options, cvv, pattern, fraction) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
@ -198,10 +191,8 @@ yang_type_cache_cp(yang_type_cache **ycnew,
|
||||||
int
|
int
|
||||||
yang_type_cache_free(yang_type_cache *ycache)
|
yang_type_cache_free(yang_type_cache *ycache)
|
||||||
{
|
{
|
||||||
if (ycache->yc_mincv)
|
if (ycache->yc_cvv)
|
||||||
cv_free(ycache->yc_mincv);
|
cvec_free(ycache->yc_cvv);
|
||||||
if (ycache->yc_maxcv)
|
|
||||||
cv_free(ycache->yc_maxcv);
|
|
||||||
if (ycache->yc_pattern)
|
if (ycache->yc_pattern)
|
||||||
free(ycache->yc_pattern);
|
free(ycache->yc_pattern);
|
||||||
free(ycache);
|
free(ycache);
|
||||||
|
|
@ -220,8 +211,7 @@ ys_resolve_type(yang_stmt *ys,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
int options = 0x0;
|
int options = 0x0;
|
||||||
cg_var *mincv = NULL;
|
cvec *cvv = NULL;
|
||||||
cg_var *maxcv = NULL;
|
|
||||||
char *pattern = NULL;
|
char *pattern = NULL;
|
||||||
uint8_t fraction = 0;
|
uint8_t fraction = 0;
|
||||||
yang_stmt *resolved = NULL;
|
yang_stmt *resolved = NULL;
|
||||||
|
|
@ -231,12 +221,12 @@ ys_resolve_type(yang_stmt *ys,
|
||||||
* Note that the resolved type could be ys itself.
|
* Note that the resolved type could be ys itself.
|
||||||
*/
|
*/
|
||||||
if (yang_type_resolve((yang_stmt*)ys->ys_parent, ys, &resolved,
|
if (yang_type_resolve((yang_stmt*)ys->ys_parent, ys, &resolved,
|
||||||
&options, &mincv, &maxcv, &pattern, &fraction) < 0)
|
&options, &cvv, &pattern, &fraction) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* Cache the resolve locally */
|
/* Cache the resolve locally */
|
||||||
if (yang_type_cache_set(&ys->ys_typecache,
|
if (yang_type_cache_set(&ys->ys_typecache,
|
||||||
resolved, options, mincv, maxcv, pattern, fraction) < 0)
|
resolved, options, cvv, pattern, fraction) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
@ -388,132 +378,121 @@ static int
|
||||||
cv_validate1(cg_var *cv,
|
cv_validate1(cg_var *cv,
|
||||||
enum cv_type cvtype,
|
enum cv_type cvtype,
|
||||||
int options,
|
int options,
|
||||||
cg_var *range_min,
|
cvec *cvv,
|
||||||
cg_var *range_max,
|
|
||||||
char *pattern,
|
char *pattern,
|
||||||
yang_stmt *yrestype,
|
yang_stmt *yrestype,
|
||||||
char *restype,
|
char *restype,
|
||||||
char **reason)
|
char **reason)
|
||||||
{
|
{
|
||||||
int retval = 1; /* OK */
|
int retval = 1; /* OK */
|
||||||
|
cg_var *cv1;
|
||||||
|
cg_var *cv2;
|
||||||
int retval2;
|
int retval2;
|
||||||
yang_stmt *yi = NULL;
|
yang_stmt *yi = NULL;
|
||||||
unsigned int u = 0;
|
|
||||||
int i = 0;
|
|
||||||
char *str;
|
char *str;
|
||||||
int found;
|
int found;
|
||||||
char **vec = NULL;
|
char **vec = NULL;
|
||||||
int nvec;
|
int nvec;
|
||||||
char *v;
|
char *v;
|
||||||
|
uint64_t uu = 0;
|
||||||
|
int64_t ii = 0;
|
||||||
|
int i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (reason && *reason){
|
if (reason && *reason){
|
||||||
free(*reason);
|
free(*reason);
|
||||||
*reason = NULL;
|
*reason = NULL;
|
||||||
}
|
}
|
||||||
|
/* check options first for length and range */
|
||||||
|
if ((options & YANG_OPTIONS_RANGE) != 0 ||
|
||||||
|
(options & YANG_OPTIONS_LENGTH) != 0){
|
||||||
|
i = 0;
|
||||||
|
while (i<cvec_len(cvv)){
|
||||||
|
cv1 = cvec_i(cvv, i++);
|
||||||
|
if (strcmp(cv_name_get(cv1),"range_min") == 0){
|
||||||
|
if (i<cvec_len(cvv) &&
|
||||||
|
(cv2 = cvec_i(cvv, i)) != NULL &&
|
||||||
|
strcmp(cv_name_get(cv2),"range_max") == 0){
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cv2 = cv1;
|
||||||
|
ret = 0;
|
||||||
switch (cvtype){
|
switch (cvtype){
|
||||||
case CGV_INT8:
|
case CGV_INT8:
|
||||||
if ((options & YANG_OPTIONS_RANGE) != 0){
|
ii = cv_int8_get(cv);
|
||||||
i = cv_int8_get(cv);
|
ret = range_check(ii, cv1, cv2, int8);
|
||||||
if (range_check(i, range_min, range_max, int8)){
|
|
||||||
if (reason)
|
|
||||||
*reason = cligen_reason("Number out of range: %d", i);
|
|
||||||
retval = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case CGV_INT16:
|
case CGV_INT16:
|
||||||
if ((options & YANG_OPTIONS_RANGE) != 0){
|
ii = cv_int16_get(cv);
|
||||||
i = cv_int16_get(cv);
|
ret = range_check(ii, cv1, cv2, int16);
|
||||||
if (range_check(i, range_min, range_max, int16)){
|
|
||||||
if (reason)
|
|
||||||
*reason = cligen_reason("Number out of range: %d", i);
|
|
||||||
retval = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case CGV_INT32:
|
case CGV_INT32:
|
||||||
if ((options & YANG_OPTIONS_RANGE) != 0){
|
ii = cv_int32_get(cv);
|
||||||
i = cv_int32_get(cv);
|
ret = range_check(ii, cv1, cv2, int32);
|
||||||
if (range_check(i, range_min, range_max, int32)){
|
break;
|
||||||
|
case CGV_DEC64: /* XXX look at fraction-digit? */
|
||||||
|
case CGV_INT64:
|
||||||
|
ii = cv_int64_get(cv);
|
||||||
|
ret = range_check(ii, cv1, cv2, int64);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ret){
|
||||||
if (reason)
|
if (reason)
|
||||||
*reason = cligen_reason("Number out of range: %d", i);
|
*reason = cligen_reason("Number out of range: %" PRId64, ii);
|
||||||
retval = 0;
|
goto fail;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CGV_INT64:{
|
|
||||||
int64_t i64;
|
|
||||||
if ((options & YANG_OPTIONS_RANGE) != 0){
|
|
||||||
i64 = cv_int64_get(cv);
|
|
||||||
if (range_check(i, range_min, range_max, int64)){
|
|
||||||
if (reason)
|
|
||||||
*reason = cligen_reason("Number out of range: %" PRId64, i64);
|
|
||||||
retval = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
ret = 0;
|
||||||
|
switch (cvtype){
|
||||||
case CGV_UINT8:
|
case CGV_UINT8:
|
||||||
if ((options & YANG_OPTIONS_RANGE) != 0){
|
uu = cv_uint8_get(cv);
|
||||||
u = cv_uint8_get(cv);
|
ret = range_check(uu, cv1, cv2, uint8);
|
||||||
if (range_check(u, range_min, range_max, uint8)){
|
|
||||||
if (reason)
|
|
||||||
*reason = cligen_reason("Number out of range: %u", u);
|
|
||||||
retval = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case CGV_UINT16:
|
case CGV_UINT16:
|
||||||
if ((options & YANG_OPTIONS_RANGE) != 0){
|
uu = cv_uint16_get(cv);
|
||||||
u = cv_uint16_get(cv);
|
ret = range_check(uu, cv1, cv2, uint16);
|
||||||
if (range_check(u, range_min, range_max, uint16)){
|
|
||||||
if (reason)
|
|
||||||
*reason = cligen_reason("Number out of range: %u", u);
|
|
||||||
retval = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case CGV_UINT32:
|
case CGV_UINT32:
|
||||||
if ((options & YANG_OPTIONS_RANGE) != 0){
|
uu = cv_uint32_get(cv);
|
||||||
u = cv_uint32_get(cv);
|
ret = range_check(uu, cv1, cv2, uint32);
|
||||||
if (range_check(u, range_min, range_max, uint32)){
|
break;
|
||||||
|
case CGV_UINT64:
|
||||||
|
uu = cv_uint32_get(cv);
|
||||||
|
ret = range_check(uu, cv1, cv2, uint64);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ret){
|
||||||
if (reason)
|
if (reason)
|
||||||
*reason = cligen_reason("Number out of range: %u", u);
|
*reason = cligen_reason("Number out of range: %" PRIu64, uu);
|
||||||
retval = 0;
|
goto fail;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
ret = 0;
|
||||||
|
switch (cvtype){
|
||||||
|
case CGV_STRING:
|
||||||
|
case CGV_REST:
|
||||||
|
if ((str = cv_string_get(cv)) == NULL)
|
||||||
break;
|
break;
|
||||||
case CGV_UINT64:{
|
uu = strlen(str);
|
||||||
uint64_t u64;
|
if (range_check(uu, cv1, cv2, uint64)){
|
||||||
if ((options & YANG_OPTIONS_RANGE) != 0){
|
|
||||||
u64 = cv_uint64_get(cv);
|
|
||||||
if (range_check(u, range_min, range_max, uint64)){
|
|
||||||
if (reason)
|
if (reason)
|
||||||
*reason = cligen_reason("Number out of range: %" PRIu64, u64);
|
*reason = cligen_reason("string length out of range: %" PRIu64, uu);
|
||||||
retval = 0;
|
goto fail;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CGV_DEC64:
|
|
||||||
if ((options & YANG_OPTIONS_RANGE) != 0){
|
|
||||||
i = cv_int64_get(cv);
|
|
||||||
if (range_check(i, range_min, range_max, int64)){
|
|
||||||
if (reason)
|
|
||||||
*reason = cligen_reason("Number out of range: %d", i);
|
|
||||||
retval = 0;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
/* then check options for others */
|
||||||
|
switch (cvtype){
|
||||||
case CGV_STRING:
|
case CGV_STRING:
|
||||||
case CGV_REST:
|
case CGV_REST:
|
||||||
str = cv_string_get(cv);
|
str = cv_string_get(cv);
|
||||||
|
|
@ -531,8 +510,7 @@ cv_validate1(cg_var *cv,
|
||||||
if (!found){
|
if (!found){
|
||||||
if (reason)
|
if (reason)
|
||||||
*reason = cligen_reason("'%s' does not match enumeration", str);
|
*reason = cligen_reason("'%s' does not match enumeration", str);
|
||||||
retval = 0;
|
goto fail;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (strcmp(restype, "bits") == 0){
|
if (strcmp(restype, "bits") == 0){
|
||||||
|
|
@ -557,21 +535,12 @@ cv_validate1(cg_var *cv,
|
||||||
if (!found){
|
if (!found){
|
||||||
if (reason)
|
if (reason)
|
||||||
*reason = cligen_reason("'%s' does not match enumeration", v);
|
*reason = cligen_reason("'%s' does not match enumeration", v);
|
||||||
retval = 0;
|
goto fail;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((options & YANG_OPTIONS_LENGTH) != 0){
|
|
||||||
u = strlen(str);
|
|
||||||
if (range_check(u, range_min, range_max, uint64)){
|
|
||||||
if (reason)
|
|
||||||
*reason = cligen_reason("string length out of range: %u", u);
|
|
||||||
retval = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((options & YANG_OPTIONS_PATTERN) != 0){
|
if ((options & YANG_OPTIONS_PATTERN) != 0){
|
||||||
if ((retval2 = match_regexp(str, pattern)) < 0){
|
if ((retval2 = match_regexp(str, pattern)) < 0){
|
||||||
clicon_err(OE_DB, 0, "match_regexp: %s", pattern);
|
clicon_err(OE_DB, 0, "match_regexp: %s", pattern);
|
||||||
|
|
@ -581,7 +550,7 @@ cv_validate1(cg_var *cv,
|
||||||
if (reason)
|
if (reason)
|
||||||
*reason = cligen_reason("regexp match fail: \"%s\" does not match %s",
|
*reason = cligen_reason("regexp match fail: \"%s\" does not match %s",
|
||||||
str, pattern);
|
str, pattern);
|
||||||
retval = 0;
|
goto fail;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -591,27 +560,19 @@ cv_validate1(cg_var *cv,
|
||||||
retval = 0;
|
retval = 0;
|
||||||
if (reason)
|
if (reason)
|
||||||
*reason = cligen_reason("Invalid cv");
|
*reason = cligen_reason("Invalid cv");
|
||||||
retval = 0;
|
goto fail;
|
||||||
break;
|
break;
|
||||||
case CGV_BOOL:
|
default:
|
||||||
case CGV_INTERFACE:
|
|
||||||
case CGV_IPV4ADDR:
|
|
||||||
case CGV_IPV6ADDR:
|
|
||||||
case CGV_IPV4PFX:
|
|
||||||
case CGV_IPV6PFX:
|
|
||||||
case CGV_MACADDR:
|
|
||||||
case CGV_URL:
|
|
||||||
case CGV_UUID:
|
|
||||||
case CGV_TIME:
|
|
||||||
case CGV_EMPTY: /* XXX */
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (reason && *reason)
|
retval = 1; /* validation OK */
|
||||||
assert(retval == 0); /* validation failed with error reason */
|
|
||||||
done:
|
done:
|
||||||
if (vec)
|
if (vec)
|
||||||
free(vec);
|
free(vec);
|
||||||
return retval;
|
return retval;
|
||||||
|
fail:
|
||||||
|
retval = 0; /* validation failed */
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Forward */
|
/* Forward */
|
||||||
|
|
@ -633,16 +594,14 @@ ys_cv_validate_union_one(yang_stmt *ys,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
yang_stmt *yrt; /* union subtype */
|
yang_stmt *yrt; /* union subtype */
|
||||||
int options = 0;
|
int options = 0;
|
||||||
cg_var *range_min = NULL;
|
cvec *cvv = NULL;
|
||||||
cg_var *range_max = NULL;
|
|
||||||
char *pattern = NULL;
|
char *pattern = NULL;
|
||||||
uint8_t fraction = 0;
|
uint8_t fraction = 0;
|
||||||
char *restype;
|
char *restype;
|
||||||
enum cv_type cvtype;
|
enum cv_type cvtype;
|
||||||
cg_var *cvt=NULL;
|
cg_var *cvt=NULL;
|
||||||
|
|
||||||
if (yang_type_resolve(ys, yt, &yrt,
|
if (yang_type_resolve(ys, yt, &yrt, &options, &cvv, &pattern,
|
||||||
&options, &range_min, &range_max, &pattern,
|
|
||||||
&fraction) < 0)
|
&fraction) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
restype = yrt?yrt->ys_argument:NULL;
|
restype = yrt?yrt->ys_argument:NULL;
|
||||||
|
|
@ -664,7 +623,7 @@ ys_cv_validate_union_one(yang_stmt *ys,
|
||||||
}
|
}
|
||||||
if (retval == 0)
|
if (retval == 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((retval = cv_validate1(cvt, cvtype, options, range_min, range_max,
|
if ((retval = cv_validate1(cvt, cvtype, options, cvv,
|
||||||
pattern, yrt, restype, reason)) < 0)
|
pattern, yrt, restype, reason)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -736,8 +695,7 @@ ys_cv_validate(cg_var *cv,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cg_var *ycv; /* cv of yang-statement */
|
cg_var *ycv; /* cv of yang-statement */
|
||||||
int options = 0;
|
int options = 0;
|
||||||
cg_var *range_min = NULL;
|
cvec *cvv = NULL;
|
||||||
cg_var *range_max = NULL;
|
|
||||||
char *pattern = NULL;
|
char *pattern = NULL;
|
||||||
enum cv_type cvtype;
|
enum cv_type cvtype;
|
||||||
char *type; /* orig type */
|
char *type; /* orig type */
|
||||||
|
|
@ -756,8 +714,7 @@ ys_cv_validate(cg_var *cv,
|
||||||
}
|
}
|
||||||
ycv = ys->ys_cv;
|
ycv = ys->ys_cv;
|
||||||
if (yang_type_get(ys, &type, &yrestype,
|
if (yang_type_get(ys, &type, &yrestype,
|
||||||
&options, &range_min, &range_max, &pattern,
|
&options, &cvv, &pattern, &fraction) < 0)
|
||||||
&fraction) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
restype = yrestype?yrestype->ys_argument:NULL;
|
restype = yrestype?yrestype->ys_argument:NULL;
|
||||||
if (clicon_type2cv(type, restype, &cvtype) < 0)
|
if (clicon_type2cv(type, restype, &cvtype) < 0)
|
||||||
|
|
@ -782,7 +739,7 @@ ys_cv_validate(cg_var *cv,
|
||||||
retval = retval2; /* invalid (0) with latest reason or valid 1 */
|
retval = retval2; /* invalid (0) with latest reason or valid 1 */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if ((retval = cv_validate1(cv, cvtype, options, range_min, range_max, pattern,
|
if ((retval = cv_validate1(cv, cvtype, options, cvv, pattern,
|
||||||
yrestype, restype, reason)) < 0)
|
yrestype, restype, reason)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
done:
|
done:
|
||||||
|
|
@ -889,7 +846,17 @@ yang_find_identity(yang_stmt *ys,
|
||||||
return yid;
|
return yid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*! Resolve type restrictions, return contraining parameters
|
||||||
|
* @param[in] yrange Yang type range restriction if any
|
||||||
|
* @param[in] ylength Yang type length restriction if any
|
||||||
|
* @param[in] ypattern Yang type pattern restriction if any
|
||||||
|
* @param[in] yfraction Yang type fraction restriction if any
|
||||||
|
* @param[out] options Pointer to flags field of optional values. optional
|
||||||
|
* @param[out] cvv Pointer to cvec with min range or length.
|
||||||
|
* If options&YANG_OPTIONS_RANGE or YANG_OPTIONS_LENGTH
|
||||||
|
* @param[out] pattern Pointer to static string of yang string pattern. optional
|
||||||
|
* @param[out] fraction For decimal64, how many digits after period
|
||||||
|
* @retval 0 OK.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
resolve_restrictions(yang_stmt *yrange,
|
resolve_restrictions(yang_stmt *yrange,
|
||||||
|
|
@ -897,19 +864,16 @@ resolve_restrictions(yang_stmt *yrange,
|
||||||
yang_stmt *ypattern,
|
yang_stmt *ypattern,
|
||||||
yang_stmt *yfraction,
|
yang_stmt *yfraction,
|
||||||
int *options,
|
int *options,
|
||||||
cg_var **mincv,
|
cvec **cvv,
|
||||||
cg_var **maxcv,
|
|
||||||
char **pattern,
|
char **pattern,
|
||||||
uint8_t *fraction)
|
uint8_t *fraction)
|
||||||
{
|
{
|
||||||
if (options && mincv && maxcv && yrange != NULL){
|
if (options && cvv && yrange != NULL){
|
||||||
*mincv = cvec_find(yrange->ys_cvec, "range_min");
|
*cvv = yrange->ys_cvec;
|
||||||
*maxcv = cvec_find(yrange->ys_cvec, "range_max");
|
|
||||||
*options |= YANG_OPTIONS_RANGE;
|
*options |= YANG_OPTIONS_RANGE;
|
||||||
}
|
}
|
||||||
if (options && mincv && maxcv && ylength != NULL){
|
if (options && cvv && ylength != NULL){
|
||||||
*mincv = cvec_find(ylength->ys_cvec, "range_min"); /* XXX fel typ */
|
*cvv = ylength->ys_cvec;
|
||||||
*maxcv = cvec_find(ylength->ys_cvec, "range_max");
|
|
||||||
*options |= YANG_OPTIONS_LENGTH;
|
*options |= YANG_OPTIONS_LENGTH;
|
||||||
}
|
}
|
||||||
if (options && pattern && ypattern != NULL){
|
if (options && pattern && ypattern != NULL){
|
||||||
|
|
@ -928,8 +892,8 @@ resolve_restrictions(yang_stmt *yrange,
|
||||||
* @param[in] ytype yang-stmt object containing currently resolving type
|
* @param[in] ytype yang-stmt object containing currently resolving type
|
||||||
* @param[out] yrestype resolved type. return built-in type or NULL. mandatory
|
* @param[out] yrestype resolved type. return built-in type or NULL. mandatory
|
||||||
* @param[out] options pointer to flags field of optional values. optional
|
* @param[out] options pointer to flags field of optional values. optional
|
||||||
* @param[out] mincv pointer to cv with min range or length. If options&YANG_OPTIONS_RANGE
|
* @param[out] cvv pointer to cvec with min range or length.
|
||||||
* @param[out] maxcv pointer to cv with max range or length. If options&YANG_OPTIONS_RANGE
|
* If options&YANG_OPTIONS_RANGE or YANG_OPTIONS_LENGTH
|
||||||
* @param[out] pattern pointer to static string of yang string pattern. optional
|
* @param[out] pattern pointer to static string of yang string pattern. optional
|
||||||
* @param[out] fraction for decimal64, how many digits after period
|
* @param[out] fraction for decimal64, how many digits after period
|
||||||
* @retval 0 OK. Note yrestype may still be NULL.
|
* @retval 0 OK. Note yrestype may still be NULL.
|
||||||
|
|
@ -946,8 +910,7 @@ yang_type_resolve(yang_stmt *ys,
|
||||||
yang_stmt *ytype,
|
yang_stmt *ytype,
|
||||||
yang_stmt **yrestype,
|
yang_stmt **yrestype,
|
||||||
int *options,
|
int *options,
|
||||||
cg_var **mincv,
|
cvec **cvv,
|
||||||
cg_var **maxcv,
|
|
||||||
char **pattern,
|
char **pattern,
|
||||||
uint8_t *fraction)
|
uint8_t *fraction)
|
||||||
{
|
{
|
||||||
|
|
@ -970,8 +933,8 @@ yang_type_resolve(yang_stmt *ys,
|
||||||
prefix = yarg_prefix(ytype); /* And this its prefix */
|
prefix = yarg_prefix(ytype); /* And this its prefix */
|
||||||
/* Cache does not work for eg string length 32? */
|
/* Cache does not work for eg string length 32? */
|
||||||
if (!yang_builtin(type) && ytype->ys_typecache != NULL){
|
if (!yang_builtin(type) && ytype->ys_typecache != NULL){
|
||||||
if (yang_type_cache_get(ytype->ys_typecache,
|
if (yang_type_cache_get(ytype->ys_typecache, yrestype,
|
||||||
yrestype, options, mincv, maxcv, pattern, fraction) < 0)
|
options, cvv, pattern, fraction) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
|
|
@ -984,7 +947,7 @@ yang_type_resolve(yang_stmt *ys,
|
||||||
if (prefix == NULL && yang_builtin(type)){
|
if (prefix == NULL && yang_builtin(type)){
|
||||||
*yrestype = ytype;
|
*yrestype = ytype;
|
||||||
resolve_restrictions(yrange, ylength, ypattern, yfraction, options,
|
resolve_restrictions(yrange, ylength, ypattern, yfraction, options,
|
||||||
mincv, maxcv, pattern, fraction);
|
cvv, pattern, fraction);
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1022,13 +985,12 @@ yang_type_resolve(yang_stmt *ys,
|
||||||
}
|
}
|
||||||
/* recursively resolve this new type */
|
/* recursively resolve this new type */
|
||||||
if (yang_type_resolve(ys, rytype, yrestype,
|
if (yang_type_resolve(ys, rytype, yrestype,
|
||||||
options, mincv, maxcv, pattern, fraction) < 0)
|
options, cvv, pattern, fraction) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* overwrites the resolved if any */
|
/* overwrites the resolved if any */
|
||||||
resolve_restrictions(yrange, ylength, ypattern, yfraction,
|
resolve_restrictions(yrange, ylength, ypattern, yfraction, options,
|
||||||
options, mincv, maxcv, pattern, fraction);
|
cvv, pattern, fraction);
|
||||||
}
|
}
|
||||||
|
|
||||||
ok:
|
ok:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
@ -1042,11 +1004,11 @@ yang_type_resolve(yang_stmt *ys,
|
||||||
* @code
|
* @code
|
||||||
* yang_stmt *yrestype;
|
* yang_stmt *yrestype;
|
||||||
* int options;
|
* int options;
|
||||||
* int64_t min, max;
|
* cvec *cvv = NULL;
|
||||||
* char *pattern;
|
* char *pattern;
|
||||||
* uint8_t fraction;
|
* uint8_t fraction;
|
||||||
*
|
*
|
||||||
* if (yang_type_get(ys, &type, &yrestype, &options, &min, &max, &pattern, &fraction) < 0)
|
* if (yang_type_get(ys, &type, &yrestype, &options, &cvv, &pattern, &fraction) < 0)
|
||||||
* goto err;
|
* goto err;
|
||||||
* if (yrestype == NULL) # unresolved
|
* if (yrestype == NULL) # unresolved
|
||||||
* goto err;
|
* goto err;
|
||||||
|
|
@ -1078,8 +1040,7 @@ yang_type_get(yang_stmt *ys,
|
||||||
char **origtype,
|
char **origtype,
|
||||||
yang_stmt **yrestype,
|
yang_stmt **yrestype,
|
||||||
int *options,
|
int *options,
|
||||||
cg_var **mincv,
|
cvec **cvv,
|
||||||
cg_var **maxcv,
|
|
||||||
char **pattern,
|
char **pattern,
|
||||||
uint8_t *fraction
|
uint8_t *fraction
|
||||||
)
|
)
|
||||||
|
|
@ -1100,7 +1061,7 @@ yang_type_get(yang_stmt *ys,
|
||||||
if (origtype)
|
if (origtype)
|
||||||
*origtype = type;
|
*origtype = type;
|
||||||
if (yang_type_resolve(ys, ytype, yrestype,
|
if (yang_type_resolve(ys, ytype, yrestype,
|
||||||
options, mincv, maxcv, pattern, fraction) < 0)
|
options, cvv, pattern, fraction) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
clicon_debug(3, "%s: %s %s->%s", __FUNCTION__, ys->ys_argument, type,
|
clicon_debug(3, "%s: %s %s->%s", __FUNCTION__, ys->ys_argument, type,
|
||||||
*yrestype?(*yrestype)->ys_argument:"null");
|
*yrestype?(*yrestype)->ys_argument:"null");
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,9 @@
|
||||||
|
|
||||||
This directory contains testing code for clixon and the example
|
This directory contains testing code for clixon and the example
|
||||||
application. Assumes setup of http daemon as describe under apps/restonf
|
application. Assumes setup of http daemon as describe under apps/restonf
|
||||||
- clixon A top-level script clones clixon in /tmp and starts all.sh. You can copy this file (review it first) and place as cron script
|
- Jenkinsfile Makefile for Jenkins tests. Build clixon and run tests.
|
||||||
- all.sh Run through all tests named 'test*.sh' in this directory. Therefore, if you place a test in this directory matching 'test*.sh' it will be run automatically. By default the script will exit on first error. Run as `all.sh summary` to continue and print a summary on all tests.
|
- all.sh Run through all tests named 'test*.sh' in this directory. Therefore, if you place a test in this directory matching 'test*.sh' it will be run automatically. By default the script will exit on first error. Run as `all.sh summary` to continue and print a summary on all tests.
|
||||||
|
- site.sh Add your site-specific modifications here
|
||||||
- test_nacm.sh Auth tests using internal NACM
|
- test_nacm.sh Auth tests using internal NACM
|
||||||
- test_nacm_ext.sh Auth tests using external NACM (separate file)
|
- test_nacm_ext.sh Auth tests using external NACM (separate file)
|
||||||
- test_cli.sh CLI tests
|
- test_cli.sh CLI tests
|
||||||
|
|
@ -12,6 +13,7 @@ application. Assumes setup of http daemon as describe under apps/restonf
|
||||||
- test_yang.sh Yang tests for constructs not in the example.
|
- test_yang.sh Yang tests for constructs not in the example.
|
||||||
- test_leafref.sh Yang leafref tests
|
- test_leafref.sh Yang leafref tests
|
||||||
- test_datastore.sh Datastore tests
|
- test_datastore.sh Datastore tests
|
||||||
|
- and many more...
|
||||||
|
|
||||||
Example runs:
|
Example runs:
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,6 @@
|
||||||
# Note that the openconfig test suites are patched to counter CLixon issues as follows:
|
# Note that the openconfig test suites are patched to counter CLixon issues as follows:
|
||||||
# - release/models/mpls/openconfig-mpls-te.yang
|
# - release/models/mpls/openconfig-mpls-te.yang
|
||||||
# issue: https://github.com/clicon/clixon/issues/60
|
# issue: https://github.com/clicon/clixon/issues/60
|
||||||
# - release/models/wifi/types/openconfig-wifi-types.yang
|
|
||||||
# issue: https://github.com/clicon/clixon/issues/59
|
|
||||||
#
|
|
||||||
|
|
||||||
# Yang specifics: multi-keys and empty type
|
# Yang specifics: multi-keys and empty type
|
||||||
APPNAME=example
|
APPNAME=example
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Advanced union types and generated code
|
# Advanced union types and generated code
|
||||||
# and enum w values
|
# and enum w values
|
||||||
|
# XXX NO SUPPORT FOR lists of ranges and lengths !!!
|
||||||
APPNAME=example
|
APPNAME=example
|
||||||
# include err() and new() functions and creates $dir
|
# include err() and new() functions and creates $dir
|
||||||
|
|
||||||
. ./lib.sh
|
. ./lib.sh
|
||||||
|
|
||||||
cfg=$dir/conf_yang.xml
|
cfg=$dir/conf_yang.xml
|
||||||
|
|
@ -123,57 +125,47 @@ module example{
|
||||||
enum down;
|
enum down;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
leaf length1 {
|
|
||||||
type string {
|
|
||||||
length "1";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* leaf length2 {
|
|
||||||
type string {
|
|
||||||
length "max";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
leaf length3 {
|
|
||||||
type string {
|
|
||||||
length "min";
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
leaf length4 {
|
|
||||||
type string {
|
|
||||||
length "4..4000";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* leaf length5 {
|
|
||||||
type string {
|
|
||||||
length "min..max";
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
leaf num1 {
|
leaf num1 {
|
||||||
type int32 {
|
type int32 {
|
||||||
range "1";
|
range "1";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* leaf num2 {
|
leaf num2 {
|
||||||
type int32 {
|
|
||||||
range "min";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
leaf num3 {
|
|
||||||
type int32 {
|
|
||||||
range "max";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
leaf num4 {
|
|
||||||
type int32 {
|
type int32 {
|
||||||
range "4..4000";
|
range "4..4000";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* leaf num5 {
|
leaf num3 {
|
||||||
type int32 {
|
type uint8 {
|
||||||
range "min..max";
|
range "min..max";
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
|
leaf num4 { /* XXX multiple ranges not supported yet - only first*/
|
||||||
|
type uint8 {
|
||||||
|
range "1 .. 2 | 42";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
leaf len1 {
|
||||||
|
type string {
|
||||||
|
length "2";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
leaf len2 {
|
||||||
|
type string {
|
||||||
|
length "4..4000";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
leaf len3 {
|
||||||
|
type string {
|
||||||
|
length "min..max";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
leaf len4 {
|
||||||
|
type string {
|
||||||
|
range "1 .. 2 | 42";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
typedef mybits {
|
typedef mybits {
|
||||||
description "Test adding several bits";
|
description "Test adding several bits";
|
||||||
type bits {
|
type bits {
|
||||||
|
|
@ -303,6 +295,70 @@ expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><can
|
||||||
new "cli bits validate"
|
new "cli bits validate"
|
||||||
expectfn "$clixon_cli -1f $cfg -l o -y $fyang validate" 0 "^$"
|
expectfn "$clixon_cli -1f $cfg -l o -y $fyang validate" 0 "^$"
|
||||||
|
|
||||||
|
#----------------int ranges---------------------
|
||||||
|
|
||||||
|
new "cli range test num1 1 OK"
|
||||||
|
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num1 1" 0 "^$"
|
||||||
|
|
||||||
|
#new "cli range test num1 -100 ok" # XXX - cant be given on cmd line
|
||||||
|
#expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num1 \-100" 0 "^$"
|
||||||
|
|
||||||
|
new "cli range test num1 2 error"
|
||||||
|
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num1 2" 255 "^$"
|
||||||
|
|
||||||
|
new "netconf range set num1 -1"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><num1 xmlns="urn:example:clixon">-1</num1></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "netconf validate num1 -1 wrong"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>num1</bad-element></error-info><error-severity>error</error-severity><error-message>Number out of range: -1</error-message></rpc-error></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
|
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 3 error"
|
||||||
|
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num2 3" 255 "^$"
|
||||||
|
|
||||||
|
new "cli range test num2 5000 error"
|
||||||
|
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num2 5000" 255 "^$"
|
||||||
|
|
||||||
|
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"
|
||||||
|
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num3 260" 255 "^$"
|
||||||
|
|
||||||
|
#----------------string ranges---------------------
|
||||||
|
|
||||||
|
new "cli length test len1 1 error"
|
||||||
|
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set len1 x" 255 "^$"
|
||||||
|
|
||||||
|
new "cli length test len1 2 OK"
|
||||||
|
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set len1 xy" 0 "^$"
|
||||||
|
|
||||||
|
new "cli length test len1 3 error"
|
||||||
|
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set len1 hej" 255 "^$"
|
||||||
|
|
||||||
|
new "netconf discard-changes"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "netconf length set len1 1"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><len1 xmlns="urn:example:clixon">x</len1></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "netconf validate len1 1 wrong"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>len1</bad-element></error-info><error-severity>error</error-severity><error-message>string length out of range: 1</error-message></rpc-error></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
|
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 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "cli length test len2 3 error"
|
||||||
|
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set len2 ab" 255 "^$"
|
||||||
|
|
||||||
|
new "cli range test len3 42 ok"
|
||||||
|
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set len3 hsakjdhkjsahdkjsahdksahdksajdhsakjhd" 0 "^$"
|
||||||
|
|
||||||
if [ $BE -eq 0 ]; then
|
if [ $BE -eq 0 ]; then
|
||||||
exit # BE
|
exit # BE
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue