From 2fe185d6834b59029643d2ec14b10dfac94049be Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Wed, 29 May 2019 11:39:09 +0200 Subject: [PATCH] * Support for multiple patterns as described in RFC7950 Section 9.4.7 * Added regex cache to type resolution * Added compiled regexp parameter as part of internal yang type resolution functions * All internal `ys_populate_*()` functions (except ys_populate()) have switched parameters: `clicon_handle, yang_stmt *)` --- CHANGELOG.md | 23 +- apps/backend/backend_client.c | 2 +- apps/backend/backend_commit.c | 2 +- apps/cli/cli_generate.c | 80 +++-- lib/clixon/clixon_yang.h | 2 - lib/clixon/clixon_yang_type.h | 19 +- lib/src/clixon_datastore_read.c | 6 +- lib/src/clixon_datastore_write.c | 2 +- lib/src/clixon_options.c | 4 +- lib/src/clixon_xml.c | 48 --- lib/src/clixon_xml_map.c | 2 +- lib/src/clixon_xml_sort.c | 2 +- lib/src/clixon_yang.c | 98 ++---- lib/src/clixon_yang_internal.h | 4 +- lib/src/clixon_yang_parse.l | 1 + lib/src/clixon_yang_parse.y | 2 +- lib/src/clixon_yang_type.c | 416 ++++++++++++++++++------- test/test_pattern.sh | 506 ++++++++++++++++++------------- test/test_stream.sh | 2 +- test/test_type.sh | 235 +++++++------- util/clixon_util_insert.c | 2 +- 21 files changed, 854 insertions(+), 604 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ba02309..723c870d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,18 @@ ## 3.10.0/4.0.0 (Upcoming) ### Major New features +* Regexp improvements: Libxml2 XSD, multiple patterns, optimization + * Support for multiple patterns as described in RFC7950 Section 9.4.7 + * Libxml2 support for full XSD matching as alternative to Posix translation + * Configure with: `./configure --with-libxml2` + * Set `CLICON_YANG_REGEXP` to libxml2 (default is posix) + * Note you need to configure cligen as well with `--with-libxml2` + * Better compliance with XSD regexps in the default Posix translation regex mode + * Added `\p{L}` and `\p{N}` + * Added escaping of `$` + * Added clixon_util_regexp utility function + * Added extensive regexp test [test/test_pattern.sh] for both posix and libxml2 + * Added regex cache to type resolution * Yang "min-element" and "max-element" feature supported * According to RFC 7950 7.7.4 and 7.7.5 * See (tests)[test/test_minmax.sh] @@ -54,6 +66,9 @@ ### API changes on existing features (you may need to change your code) +* Added compiled regexp parameter as part of internal yang type resolution functions + * `yang_type_resolve()`, `yang_type_get()` +* All internal `ys_populate_*()` functions (except ys_populate()) have switched parameters: `clicon_handle, yang_stmt *)` * Added clicon_handle as parameter to all validate functions * Just add `clixon_handle h` to all calls. * Clixon transaction mechanism has changed which may affect your backend plugin callbacks: @@ -141,14 +156,6 @@ ### Minor changes -* Regexp improvements: Added libxml2 XSD regexp mode as alternative to posix translation - * Configure with: `./configure --with-libxml2` - * Set `CLICON_YANG_REGEXP` to libxml2 (default is posix) - * Better compliance with XSD regexps (when transforming to Posix regexps) - * Added `\p{L}` and `\p{N}` - * Added escaping of `$` - * Added clixon_util_regexp utility function - * Added regexp test [test/test_pattern.sh] for both posix and libxml2 * Yang state get improvements * Integrated state and config into same tree on retrieval, not separate trees * Added cli functions `cli_show_config_state()` and `cli_show_auto_state()` for showing combined config and state info. diff --git a/apps/backend/backend_client.c b/apps/backend/backend_client.c index 723f4b0e..e9a827d4 100644 --- a/apps/backend/backend_client.c +++ b/apps/backend/backend_client.c @@ -477,7 +477,7 @@ from_client_edit_config(clicon_handle h, /* Cant do this earlier since we dont have a yang spec to * the upper part of the tree, until we get the "config" tree. */ - if (xml_apply0(xc, CX_ELMNT, xml_sort, NULL) < 0) + if (xml_apply0(xc, CX_ELMNT, xml_sort, h) < 0) goto done; if ((ret = xmldb_put(h, target, operation, xc, username, cbret)) < 0){ clicon_debug(1, "%s ERROR PUT", __FUNCTION__); diff --git a/apps/backend/backend_commit.c b/apps/backend/backend_commit.c index eb31cc6b..b869912d 100644 --- a/apps/backend/backend_commit.c +++ b/apps/backend/backend_commit.c @@ -206,7 +206,7 @@ startup_common(clicon_handle h, /* After upgrading, XML tree needs to be sorted and yang spec populated */ if (xml_apply0(xt, CX_ELMNT, xml_spec_populate, yspec) < 0) goto done; - if (xml_apply0(xt, CX_ELMNT, xml_sort, NULL) < 0) + if (xml_apply0(xt, CX_ELMNT, xml_sort, h) < 0) goto done; /* Handcraft transition with with only add tree */ td->td_target = xt; diff --git a/apps/cli/cli_generate.c b/apps/cli/cli_generate.c index 914f785f..a78d55f1 100644 --- a/apps/cli/cli_generate.c +++ b/apps/cli/cli_generate.c @@ -272,6 +272,42 @@ yang2cli_var_range(yang_stmt *ys, return retval; } +/*! Generate CLI code for Yang variable pattern statement + * @param[in] h Clixon handle + * @param[in] patterns Cvec of regexp patterns + * @param[out] cb Buffer where cligen code is written + * @see cv_validate_pattern for netconf validate code + */ +static int +yang2cli_var_pattern(clicon_handle h, + cvec *patterns, + cbuf *cb) +{ + int retval = -1; + char *mode; + cg_var *cvp; + char *pattern; + + mode = clicon_yang_regexp(h); + cvp = NULL; /* Loop over compiled regexps */ + while ((cvp = cvec_each(patterns, cvp)) != NULL){ + pattern = cv_string_get(cvp); + if (strcmp(mode, "posix") == 0){ + char *posix = NULL; + if (regexp_xsd2posix(pattern, &posix) < 0) + goto done; + cprintf(cb, " regexp:\"%s\"", posix); + if (posix) + free(posix); + } + else + cprintf(cb, " regexp:\"%s\"", pattern); + } + retval = 0; + done: + return retval; +} + /* Forward */ static int yang2cli_stmt(clicon_handle h, yang_stmt *ys, enum genmodel_type gt, int level, cbuf *cb); @@ -289,7 +325,7 @@ static int yang2cli_var_union(clicon_handle h, yang_stmt *ys, char *origtype, * @param[in] cvtype * @param[in] options Flags field of optional values, see YANG_OPTIONS_* * @param[in] cvv Cvec with array of range_min/range_max cv:s - * @param[in] pattern String of POSIX regexp pattern + * @param[in] patterns Cvec of regexp patterns * @param[in] fraction for decimal64, how many digits after period * @param[out] cb Buffer where cligen code is written * @see yang_type_resolve for options and other arguments @@ -302,7 +338,7 @@ yang2cli_var_sub(clicon_handle h, enum cv_type cvtype, int options, cvec *cvv, - char *pattern, + cvec *patterns, uint8_t fraction_digits, cbuf *cb ) @@ -358,19 +394,9 @@ yang2cli_var_sub(clicon_handle h, if (yang2cli_var_range(ys, options, cvv, cb) < 0) goto done; } - if (options & YANG_OPTIONS_PATTERN){ - char *mode; - mode = clicon_yang_regexp(h); - if (strcmp(mode, "posix") == 0){ - char *posix = NULL; - if (regexp_xsd2posix(pattern, &posix) < 0) - goto done; - cprintf(cb, " regexp:\"%s\"", posix); - if (posix) - free(posix); - } - else - cprintf(cb, " regexp:\"%s\"", pattern); + if (patterns && cvec_len(patterns)){ + if (yang2cli_var_pattern(h, patterns, cb) < 0) + goto done; } cprintf(cb, ">"); if (helptext) @@ -402,16 +428,20 @@ yang2cli_var_union_one(clicon_handle h, int retval = -1; int options = 0; cvec *cvv = NULL; - char *pattern = NULL; + cvec *patterns = NULL; uint8_t fraction_digits = 0; enum cv_type cvtype; yang_stmt *ytype; /* resolved type */ char *restype; + if ((patterns = cvec_new(0)) == NULL){ + clicon_err(OE_UNIX, errno, "cvec_new"); + goto done; + } /* Resolve the sub-union type to a resolved type */ if (yang_type_resolve(ys, ys, ytsub, /* in */ &ytype, &options, /* resolved type */ - &cvv, &pattern, &fraction_digits) < 0) + &cvv, patterns, NULL, &fraction_digits) < 0) goto done; restype = ytype?yang_argument_get(ytype):NULL; @@ -423,11 +453,13 @@ yang2cli_var_union_one(clicon_handle h, if (clicon_type2cv(origtype, restype, ys, &cvtype) < 0) goto done; if ((retval = yang2cli_var_sub(h, ys, ytype, helptext, cvtype, - options, cvv, pattern, fraction_digits, cb)) < 0) + options, cvv, patterns, fraction_digits, cb)) < 0) goto done; } retval = 0; done: + if (patterns) + cvec_free(patterns); return retval; } @@ -494,15 +526,19 @@ yang2cli_var(clicon_handle h, yang_stmt *yrestype; /* resolved type */ char *restype; /* resolved type */ cvec *cvv = NULL; - char *pattern = NULL; + cvec *patterns = NULL; uint8_t fraction_digits = 0; enum cv_type cvtype; int options = 0; int completionp; char *type; + if ((patterns = cvec_new(0)) == NULL){ + clicon_err(OE_UNIX, errno, "cvec_new"); + goto done; + } if (yang_type_get(ys, &origtype, &yrestype, - &options, &cvv, &pattern, &fraction_digits) < 0) + &options, &cvv, patterns, NULL, &fraction_digits) < 0) goto done; restype = yrestype?yang_argument_get(yrestype):NULL; @@ -539,7 +575,7 @@ yang2cli_var(clicon_handle h, if (completionp) cprintf(cb, "("); if ((retval = yang2cli_var_sub(h, ys, yrestype, helptext, cvtype, - options, cvv, pattern, fraction_digits, cb)) < 0) + options, cvv, patterns, fraction_digits, cb)) < 0) goto done; if (completionp){ if (cli_expand_var_generate(h, ys, cvtype, @@ -552,6 +588,8 @@ yang2cli_var(clicon_handle h, } retval = 0; done: + if (patterns) + cvec_free(patterns); return retval; } diff --git a/lib/clixon/clixon_yang.h b/lib/clixon/clixon_yang.h index 32fc07bf..c5347d89 100644 --- a/lib/clixon/clixon_yang.h +++ b/lib/clixon/clixon_yang.h @@ -153,8 +153,6 @@ char *yang_argument_get(yang_stmt *ys); cg_var *yang_cv_get(yang_stmt *ys); cvec *yang_cvec_get(yang_stmt *ys); int yang_cvec_set(yang_stmt *ys, cvec *cvv); -void *yang_regex_cache_get(yang_stmt *ys); -int yang_regex_cache_set(yang_stmt *ys, void *regex); /* Other functions */ yang_stmt *yspec_new(void); diff --git a/lib/clixon/clixon_yang_type.h b/lib/clixon/clixon_yang_type.h index 34c3b663..8aa6a4fa 100644 --- a/lib/clixon/clixon_yang_type.h +++ b/lib/clixon/clixon_yang_type.h @@ -43,8 +43,7 @@ */ #define YANG_OPTIONS_LENGTH 0x01 #define YANG_OPTIONS_RANGE 0x02 -#define YANG_OPTIONS_PATTERN 0x04 -#define YANG_OPTIONS_FRACTION_DIGITS 0x08 +#define YANG_OPTIONS_FRACTION_DIGITS 0x04 /* * Types @@ -57,10 +56,11 @@ typedef struct yang_type_cache yang_type_cache; */ int yang_type_cache_set(yang_type_cache **ycache, yang_stmt *resolved, int options, - cvec *cvv, char *pattern, uint8_t fraction); + cvec *cvv, cvec *patterns, cvec *regexps, + uint8_t fraction); int yang_type_cache_get(yang_type_cache *ycache, yang_stmt **resolved, - int *options, cvec **cvv, char **pattern, - uint8_t *fraction); + int *options, cvec **cvv, cvec *patterns, + cvec *regexps, uint8_t *fraction); int yang_type_cache_cp(yang_type_cache **ycnew, yang_type_cache *ycold); int yang_type_cache_free(yang_type_cache *ycache); int ys_resolve_type(yang_stmt *ys, void *arg); @@ -70,11 +70,14 @@ yang_stmt *yang_find_identity(yang_stmt *ys, char *identity); int ys_cv_validate(clicon_handle h, cg_var *cv, yang_stmt *ys, char **reason); int clicon_type2cv(char *type, char *rtype, yang_stmt *ys, enum cv_type *cvtype); int yang_type_get(yang_stmt *ys, char **otype, yang_stmt **restype, - int *options, cvec **cvv, char **pattern, + int *options, cvec **cvv, + cvec *patterns, cvec *regexps, uint8_t *fraction_digits); -int yang_type_resolve(yang_stmt *yorig, yang_stmt *ys, yang_stmt *ytype, +int yang_type_resolve(yang_stmt *yorig, yang_stmt *ys, + yang_stmt *ytype, yang_stmt **restype, int *options, - cvec **cvv, char **pattern, uint8_t *fraction); + cvec **cvv, cvec *patterns, cvec *regexps, + uint8_t *fraction); #endif /* _CLIXON_YANG_TYPE_H_ */ diff --git a/lib/src/clixon_datastore_read.c b/lib/src/clixon_datastore_read.c index 80bf71a6..0b24ef23 100644 --- a/lib/src/clixon_datastore_read.c +++ b/lib/src/clixon_datastore_read.c @@ -437,7 +437,7 @@ xmldb_get_nocache(clicon_handle h, goto done; /* Add default values (if not set) */ - if (xml_apply(xt, CX_ELMNT, xml_default, NULL) < 0) + if (xml_apply(xt, CX_ELMNT, xml_default, h) < 0) goto done; #if 0 /* debug */ if (xml_apply0(xt, -1, xml_sort_verify, NULL) < 0) @@ -542,7 +542,7 @@ xmldb_get_cache(clicon_handle h, goto done; /* x1t is wrong here should be .. but is .. */ /* XXX where should we apply default values once? */ - if (xml_apply(x1t, CX_ELMNT, xml_default, NULL) < 0) + if (xml_apply(x1t, CX_ELMNT, xml_default, h) < 0) goto done; /* Copy the matching parts of the (relevant) XML tree. @@ -622,7 +622,7 @@ xmldb_get_zerocopy(clicon_handle h, xml_apply_ancestor(x0, (xml_applyfn_t*)xml_flag_set, (void*)XML_FLAG_CHANGE); } /* Apply default values (removed in clear function) */ - if (xml_apply(x0t, CX_ELMNT, xml_default, NULL) < 0) + if (xml_apply(x0t, CX_ELMNT, xml_default, h) < 0) goto done; if (debug>1) clicon_xml2file(stderr, x0t, 0, 1); diff --git a/lib/src/clixon_datastore_write.c b/lib/src/clixon_datastore_write.c index c8a01526..35b13bad 100644 --- a/lib/src/clixon_datastore_write.c +++ b/lib/src/clixon_datastore_write.c @@ -398,7 +398,7 @@ text_modify(clicon_handle h, } /* else Y_CONTAINER */ #ifndef USE_XML_INSERT if (changed) - xml_sort(x0p, NULL); + xml_sort(x0p, h); #endif retval = 1; done: diff --git a/lib/src/clixon_options.c b/lib/src/clixon_options.c index 57b1b254..2aea61c5 100644 --- a/lib/src/clixon_options.c +++ b/lib/src/clixon_options.c @@ -181,7 +181,7 @@ parse_configfile(clicon_handle h, goto done; if (xml_apply0(xc, CX_ELMNT, xml_spec_populate, yspec) < 0) goto done; - if (xml_apply0(xc, CX_ELMNT, xml_sort, NULL) < 0) + if (xml_apply0(xc, CX_ELMNT, xml_sort, h) < 0) goto done; } else @@ -192,7 +192,7 @@ parse_configfile(clicon_handle h, goto done; } } - if (xml_apply0(xc, CX_ELMNT, xml_default, yspec) < 0) + if (xml_apply0(xc, CX_ELMNT, xml_default, h) < 0) goto done; if ((cbret = cbuf_new()) == NULL){ clicon_err(OE_XML, errno, "cbuf_new"); diff --git a/lib/src/clixon_xml.c b/lib/src/clixon_xml.c index ad8086d1..f7663ba2 100644 --- a/lib/src/clixon_xml.c +++ b/lib/src/clixon_xml.c @@ -2394,51 +2394,3 @@ clicon_log_xml(int level, return retval; } -/* - * Turn this on to get a xml parse and pretty print test program - * Usage: xpath - * read xml from input - * Example compile: - gcc -g -o xml -I. -I../clixon ./clixon_xml.c -lclixon -lcligen - * Example run: - echo "" | xml -*/ -#if 1 /* Test program */ - -static int -usage(char *argv0) -{ - fprintf(stderr, "usage:%s.\n\tInput on stdin\n", argv0); - exit(0); -} - -int -main(int argc, char **argv) -{ - cxobj *xt = NULL; - cxobj *xc; - cbuf *cb = cbuf_new(); - - if (argc != 1){ - usage(argv[0]); - return 0; - } - if (xml_parse_file(0, "", NULL, &xt) < 0){ - fprintf(stderr, "xml parse error %s\n", clicon_err_reason); - return -1; - } - xc = NULL; - while ((xc = xml_child_each(xt, xc, -1)) != NULL) { - xmltree2cbuf(cb, xc, 0); /* dump data structures */ - //clicon_xml2cbuf(cb, xc, 0, 1); /* print xml */ - } - fprintf(stdout, "%s", cbuf_get(cb)); - if (xt) - xml_free(xt); - if (cb) - cbuf_free(cb); - return 0; -} - -#endif /* Test program */ - diff --git a/lib/src/clixon_xml_map.c b/lib/src/clixon_xml_map.c index fbc1ec41..6cddca59 100644 --- a/lib/src/clixon_xml_map.c +++ b/lib/src/clixon_xml_map.c @@ -3004,7 +3004,7 @@ yang_enum_int_value(cxobj *node, if ((ytype = yang_find(ys, Y_TYPE, NULL)) == NULL) goto done; if (yang_type_resolve(ys, ys, ytype, &yrestype, - NULL, NULL, NULL, NULL) < 0) + NULL, NULL, NULL, NULL, NULL) < 0) goto done; if (yrestype==NULL || strcmp(yrestype->ys_argument, "enumeration")) goto done; diff --git a/lib/src/clixon_xml_sort.c b/lib/src/clixon_xml_sort.c index e3cef110..35be1a14 100644 --- a/lib/src/clixon_xml_sort.c +++ b/lib/src/clixon_xml_sort.c @@ -95,7 +95,7 @@ xml_cv_cache(cxobj *x, goto ok; if ((y = xml_spec(x)) == NULL) goto ok; - if (yang_type_get(y, NULL, &yrestype, &options, NULL, NULL, &fraction) < 0) + if (yang_type_get(y, NULL, &yrestype, &options, NULL, NULL, NULL, &fraction) < 0) goto done; yang2cv_type(yang_argument_get(yrestype), &cvtype); if (cvtype==CGV_ERR){ diff --git a/lib/src/clixon_yang.c b/lib/src/clixon_yang.c index 7a8013aa..144990da 100644 --- a/lib/src/clixon_yang.c +++ b/lib/src/clixon_yang.c @@ -239,30 +239,6 @@ yang_cvec_set(yang_stmt *ys, return 0; } -/*! Get regular expression cache - the compiled regex - * @param[in] ys Yang statement node - * @retval re Compiled regex - * @see regcomp - */ -void* -yang_regex_cache_get(yang_stmt *ys) -{ - return ys->ys_regex_cache; -} - -/*! Set regular expression cache - the compiled regex - * @param[in] ys Yang statement node - * @param[in] re Compiled regex - * @see regcomp - */ -int -yang_regex_cache_set(yang_stmt *ys, - void *regex) -{ - ys->ys_regex_cache = regex; - return 0; -} - /* End access functions */ /*! Create new yang specification @@ -307,17 +283,6 @@ ys_new(enum rfc_6020 keyw) return ys; } - -static int -yang_regex_cache_free(yang_stmt *ys) -{ - if (ys->ys_regex_cache){ - regfree(ys->ys_regex_cache); - free(ys->ys_regex_cache); - } - return 0; -} - /*! Free a single yang statement */ static int ys_free1(yang_stmt *ys) @@ -332,7 +297,6 @@ ys_free1(yang_stmt *ys) cvec_free(ys->ys_cvec); if (ys->ys_typecache) yang_type_cache_free(ys->ys_typecache); - yang_regex_cache_free(ys); free(ys); return 0; } @@ -1344,8 +1308,8 @@ yang_print_cbuf(cbuf *cb, * @retval -1 Error with clicon_err called */ static int -ys_populate_leaf(yang_stmt *ys, - void *arg) +ys_populate_leaf(clicon_handle h, + yang_stmt *ys) { int retval = -1; cg_var *cv = NULL; @@ -1363,7 +1327,7 @@ ys_populate_leaf(yang_stmt *ys, yparent = ys->ys_parent; /* Find parent: list/container */ /* 1. Find type specification and set cv type accordingly */ - if (yang_type_get(ys, &type, &yrestype, &options, NULL, NULL, &fraction_digits) + if (yang_type_get(ys, &type, &yrestype, &options, NULL, NULL, NULL, &fraction_digits) < 0) goto done; restype = yrestype?yrestype->ys_argument:NULL; @@ -1416,8 +1380,8 @@ ys_populate_leaf(yang_stmt *ys, } static int -ys_populate_list(yang_stmt *ys, - void *arg) +ys_populate_list(clicon_handle h, + yang_stmt *ys) { yang_stmt *ykey; @@ -1523,8 +1487,8 @@ range_parse(yang_stmt *ys, * ascending order */ static int -ys_populate_range(yang_stmt *ys, - void *arg) +ys_populate_range(clicon_handle h, + yang_stmt *ys) { int retval = -1; yang_stmt *yparent; /* type */ @@ -1541,7 +1505,7 @@ ys_populate_range(yang_stmt *ys, goto done; } if (yang_type_resolve(ys, ys, (yang_stmt*)yparent, &yrestype, - &options, NULL, NULL, &fraction_digits) < 0) + &options, NULL, NULL, NULL, &fraction_digits) < 0) goto done; restype = yrestype?yrestype->ys_argument:NULL; origtype = yarg_id((yang_stmt*)yparent); @@ -1572,8 +1536,8 @@ ys_populate_range(yang_stmt *ys, * be disjoint and MUST be in ascending order. */ static int -ys_populate_length(yang_stmt *ys, - void *arg) +ys_populate_length(clicon_handle h, + yang_stmt *ys) { int retval = -1; yang_stmt *yparent; /* type */ @@ -1598,8 +1562,9 @@ ys_populate_length(yang_stmt *ys, * @ */ static int -ys_populate_type(yang_stmt *ys, - void *arg) +ys_populate_type(clicon_handle h, + yang_stmt *ys) + { int retval = -1; yang_stmt *ybase; @@ -1636,8 +1601,9 @@ ys_populate_type(yang_stmt *ys, * @see validate_identityref which in runtime validates actual values */ static int -ys_populate_identity(yang_stmt *ys, - char *idref) +ys_populate_identity(clicon_handle h, + yang_stmt *ys, + char *idref) { int retval = -1; yang_stmt *yc = NULL; @@ -1695,7 +1661,7 @@ ys_populate_identity(yang_stmt *ys, cv = NULL; } /* Transitive to the root */ - if (ys_populate_identity(ybaseid, idref) < 0) + if (ys_populate_identity(h, ybaseid, idref) < 0) goto done; } retval = 0; @@ -1800,7 +1766,8 @@ ys_populate_feature(clicon_handle h, /*! Populate the unique statement with a cvec */ static int -ys_populate_unique(yang_stmt *ys) +ys_populate_unique(clicon_handle h, + yang_stmt *ys) { if (ys->ys_cvec) cvec_free(ys->ys_cvec); @@ -1812,7 +1779,8 @@ ys_populate_unique(yang_stmt *ys) /*! Populate unknown node with extension */ static int -ys_populate_unknown(yang_stmt *ys) +ys_populate_unknown(clicon_handle h, + yang_stmt *ys) { int retval = -1; int cvret; @@ -1861,28 +1829,28 @@ ys_populate_unknown(yang_stmt *ys) * After this pass, cv:s are set for LEAFs and LEAF-LISTs */ int -ys_populate(yang_stmt *ys, - void *arg) +ys_populate(yang_stmt *ys, + void *arg) { int retval = -1; - // clicon_handle h = (clicon_handle)arg; + clicon_handle h = (clicon_handle)arg; switch(ys->ys_keyword){ case Y_LEAF: case Y_LEAF_LIST: - if (ys_populate_leaf(ys, NULL) < 0) + if (ys_populate_leaf(h, ys) < 0) goto done; break; case Y_LIST: - if (ys_populate_list(ys, NULL) < 0) + if (ys_populate_list(h, ys) < 0) goto done; break; case Y_RANGE: - if (ys_populate_range(ys, NULL) < 0) + if (ys_populate_range(h, ys) < 0) goto done; break; case Y_LENGTH: - if (ys_populate_length(ys, NULL) < 0) + if (ys_populate_length(h, ys) < 0) goto done; break; case Y_MANDATORY: /* call yang_mandatory() to check if set */ @@ -1891,19 +1859,19 @@ ys_populate(yang_stmt *ys, goto done; break; case Y_TYPE: - if (ys_populate_type(ys, NULL) < 0) + if (ys_populate_type(h, ys) < 0) goto done; break; case Y_IDENTITY: - if (ys_populate_identity(ys, NULL) < 0) + if (ys_populate_identity(h, ys, NULL) < 0) goto done; break; case Y_UNIQUE: - if (ys_populate_unique(ys) < 0) + if (ys_populate_unique(h, ys) < 0) goto done; break; case Y_UNKNOWN: - if (ys_populate_unknown(ys) < 0) + if (ys_populate_unknown(h, ys) < 0) goto done; break; default: @@ -2631,7 +2599,7 @@ yang_parse_post(clicon_handle h, * Must be done using static binding. */ for (i=modnr; iys_len; i++) - if (yang_apply(yspec->ys_stmt[i], Y_TYPE, ys_resolve_type, NULL) < 0) + if (yang_apply(yspec->ys_stmt[i], Y_TYPE, ys_resolve_type, h) < 0) goto done; /* Up to here resolving is made in the context they are defined, rather diff --git a/lib/src/clixon_yang_internal.h b/lib/src/clixon_yang_internal.h index 4fad6644..f36692ff 100644 --- a/lib/src/clixon_yang_internal.h +++ b/lib/src/clixon_yang_internal.h @@ -58,7 +58,8 @@ struct yang_type_cache{ cvec *yc_cvv; /* Range and length restriction. (if YANG_OPTION_ LENGTH|RANGE. Can be a vector if multiple ranges*/ - char *yc_pattern; /* regex (posix) (if YANG_OPTIONS_PATTERN) */ + cvec *yc_patterns; /* list of regexp, if cvec_len() > 0 */ + cvec *yc_regexps; /* list of _compiled_ regexp, if cvec_len() > 0 */ uint8_t yc_fraction; /* Fraction digits for decimal64 (if YANG_OPTIONS_FRACTION_DIGITS */ yang_stmt *yc_resolved; /* Resolved type object, can be NULL - note direct ptr */ @@ -95,7 +96,6 @@ struct yang_stmt{ Y_TYPE & identity: store all derived types */ yang_type_cache *ys_typecache; /* If ys_keyword==Y_TYPE, cache all typedef data except unions */ - void *ys_regex_cache; /* regex cache */ int _ys_vector_i; /* internal use: yn_each */ }; diff --git a/lib/src/clixon_yang_parse.l b/lib/src/clixon_yang_parse.l index 1c3e05d5..5afcbeda 100644 --- a/lib/src/clixon_yang_parse.l +++ b/lib/src/clixon_yang_parse.l @@ -170,6 +170,7 @@ identifier [A-Za-z_][A-Za-z0-9_\-\.]* key { BEGIN(STRING); return K_KEY; } length { BEGIN(STRING); return K_LENGTH; } max-elements { BEGIN(STRING); return K_MAX_ELEMENTS; } +modifier { BEGIN(STRING); return K_MODIFIER; } must { BEGIN(STRING); return K_MUST; } namespace { BEGIN(STRING); return K_NAMESPACE; } ordered-by { BEGIN(STRING); return K_ORDERED_BY; } diff --git a/lib/src/clixon_yang_parse.y b/lib/src/clixon_yang_parse.y index a858316b..050a2d5e 100644 --- a/lib/src/clixon_yang_parse.y +++ b/lib/src/clixon_yang_parse.y @@ -863,7 +863,7 @@ pattern_substmt : modifier_stmt { clicon_debug(2,"pattern-substmt -> modifier ; modifier_stmt : K_MODIFIER string stmtend - { if (ysp_add(_yy, Y_DEFAULT, $2, NULL)== NULL) _YYERROR("modifier_stmt"); + { if (ysp_add(_yy, Y_MODIFIER, $2, NULL)== NULL) _YYERROR("modifier_stmt"); clicon_debug(2,"modifier-stmt -> MODIFIER string"); } ; diff --git a/lib/src/clixon_yang_type.c b/lib/src/clixon_yang_type.c index 2d48a0bf..34b1cf2a 100644 --- a/lib/src/clixon_yang_type.c +++ b/lib/src/clixon_yang_type.c @@ -32,6 +32,20 @@ ***** END LICENSE BLOCK ***** * Yang type related functions + * Part of this is type resolving which is pretty complex + * + * (called at parse / set cache) + * ys_resolve_type --+ ys_populate_range, yang_enum_int_value(NULL) + * \ | cml + * v v v + * yang_type_get --> yang_type_resolve --> resolve_restrictions + * (leaf(list) front) (recursive core fn) (regexps, length, ranges, ...) + * ^ ^ ^ ^ + * | | | | + * | yang2cli_var | yang2cli_var_union_one + * ys_cv_validate ys_cv_validate_union_one + * | + * ys_populate_leaf, xml_cv_cache (NULL) */ #ifdef HAVE_CONFIG_H @@ -145,7 +159,8 @@ yang_type_cache_set(yang_type_cache **ycache0, yang_stmt *resolved, int options, cvec *cvv, - char *pattern, + cvec *patterns, + cvec *regexps, uint8_t fraction) { int retval = -1; @@ -166,8 +181,12 @@ yang_type_cache_set(yang_type_cache **ycache0, goto done; } } - if (pattern && (ycache->yc_pattern = strdup(pattern)) == NULL){ - clicon_err(OE_UNIX, errno, "strdup"); + if (patterns && (ycache->yc_patterns = cvec_dup(patterns)) == NULL){ + clicon_err(OE_UNIX, errno, "cvec_dup"); + goto done; + } + if (regexps && (ycache->yc_regexps = cvec_dup(regexps)) == NULL){ + clicon_err(OE_UNIX, errno, "cvec_dup"); goto done; } ycache->yc_fraction = fraction; @@ -176,26 +195,42 @@ yang_type_cache_set(yang_type_cache **ycache0, return retval; } -/*! Get individual fields (direct/destructively) from yang type cache. */ +/*! Get individual fields (direct/destructively) from yang type cache. + * @param[out] patterns Initialized cvec of regexp patterns strings + */ int yang_type_cache_get(yang_type_cache *ycache, yang_stmt **resolved, int *options, cvec **cvv, - char **pattern, + cvec *patterns, + cvec *regexps, uint8_t *fraction) { + int retval = -1; + cg_var *cv = NULL; + if (resolved) *resolved = ycache->yc_resolved; if (options) *options = ycache->yc_options; if (cvv) *cvv = ycache->yc_cvv; - if (pattern) - *pattern = ycache->yc_pattern; + if (patterns){ + cv = NULL; + while ((cv = cvec_each(ycache->yc_patterns, cv)) != NULL) + cvec_append_var(patterns, cv); + } + if (regexps){ + cv = NULL; + while ((cv = cvec_each(ycache->yc_regexps, cv)) != NULL) + cvec_append_var(regexps, cv); + } if (fraction) *fraction = ycache->yc_fraction; - return 0; + retval = 0; + // done: + return retval; } int @@ -205,15 +240,28 @@ yang_type_cache_cp(yang_type_cache **ycnew, int retval = -1; int options; cvec *cvv; - char *pattern; + cvec *patterns = NULL; + cvec *regexps = NULL; uint8_t fraction; yang_stmt *resolved; - yang_type_cache_get(ycold, &resolved, &options, &cvv, &pattern, &fraction); - if (yang_type_cache_set(ycnew, resolved, options, cvv, pattern, fraction) < 0) + if ((patterns = cvec_new(0)) == NULL){ + clicon_err(OE_UNIX, errno, "cvec_new"); + goto done; + } + if ((regexps = cvec_new(0)) == NULL){ + clicon_err(OE_UNIX, errno, "cvec_new"); + goto done; + } + yang_type_cache_get(ycold, &resolved, &options, &cvv, patterns, regexps, &fraction); + if (yang_type_cache_set(ycnew, resolved, options, cvv, patterns, regexps, fraction) < 0) goto done; retval = 0; done: + if (patterns) + cvec_free(patterns); + if (regexps) + cvec_free(regexps); return retval; } @@ -222,12 +270,59 @@ yang_type_cache_free(yang_type_cache *ycache) { if (ycache->yc_cvv) cvec_free(ycache->yc_cvv); - if (ycache->yc_pattern) - free(ycache->yc_pattern); + if (ycache->yc_patterns) + cvec_free(ycache->yc_patterns); + if (ycache->yc_regexps) + cvec_free(ycache->yc_regexps); free(ycache); return 0; } +/* Compile yang patterns in string form to regex compiled void* form + * and re-store into "patterns" cvec. + * This is done here instead of deep in resolve code (resolve_restrictions) + * since it id dependent on clicon_handle. + * The downside is that all accesses to "patterns" must pass via the cache. + * If calls to yang_type_resolve is made without the cache is set, will be + * wrong. + */ +static int +compile_pattern2regexp(clicon_handle h, + cvec *patterns, + cvec *regexps) +{ + int retval = -1; + cg_var *pcv; /* pattern cv */ + cg_var *rcv; /* regexp cv */ + void *re; + int ret; + char *pattern; + + pcv = NULL; + while ((pcv = cvec_each(patterns, pcv)) != NULL){ + if (cv_type_get(pcv) == CGV_VOID) + continue; /* already compiled */ + pattern = cv_string_get(pcv); + /* Compile yang pattern. handle necessary to select regex engine */ + if ((ret = regex_compile(h, pattern, &re)) < 0) + goto done; + if (ret == 0){ + clicon_err(OE_YANG, errno, "regexp compile fail: \"%s\"", + pattern); + goto done; + break; + } + if ((rcv = cvec_add(regexps, CGV_VOID)) == NULL){ + clicon_err(OE_UNIX, errno, "cvec_add"); + goto done; + } + cv_void_set(rcv, re); + } + retval = 1; + done: + return retval; +} + /*! Resolve types: populate type caches * @param[in] ys This is a type statement * @param[in] arg Not used @@ -235,31 +330,58 @@ yang_type_cache_free(yang_type_cache *ycache) * @note unions not cached */ int -ys_resolve_type(yang_stmt *ys, - void *arg) +ys_resolve_type(yang_stmt *ys, + void *arg) { + clicon_handle h = (clicon_handle)arg; int retval = -1; int options = 0x0; cvec *cvv = NULL; - char *pattern = NULL; + cvec *patterns = NULL; + cvec *regexps = NULL; uint8_t fraction = 0; yang_stmt *resolved = NULL; - - assert(ys->ys_keyword == Y_TYPE); + + if (yang_keyword_get(ys) != Y_TYPE){ + clicon_err(OE_YANG, EINVAL, "Expected Y_TYPE"); + goto done; + } + if ((patterns = cvec_new(0)) == NULL){ + clicon_err(OE_UNIX, errno, "cvec_new"); + goto done; + } /* Recursively resolve ys -> resolve with restrictions(options, etc) * Note that the resolved type could be ys itself. */ - if (yang_type_resolve((yang_stmt*)ys->ys_parent, (yang_stmt*)ys->ys_parent, + if (yang_type_resolve(ys->ys_parent, ys->ys_parent, ys, &resolved, - &options, &cvv, &pattern, &fraction) < 0) + &options, &cvv, patterns, NULL, &fraction) < 0) goto done; - /* Cache the resolve locally */ + /* If pattern strings, then compile regexps as well */ + if (cvec_len(patterns)){ + if ((regexps = cvec_new(0)) == NULL){ + clicon_err(OE_UNIX, errno, "cvec_new"); + goto done; + } + /* Compile from pattern strings to compiled regexps */ + if (compile_pattern2regexp(h, patterns, regexps) < 1) + goto done; + } + /* Cache the type resolving locally. Only place where this is done. + * Why not do it in yang_type_resolve? (compile regexps needs clicon_handle) + */ if (yang_type_cache_set(&ys->ys_typecache, - resolved, options, cvv, pattern, fraction) < 0) + resolved, options, cvv, + patterns, regexps, + fraction) < 0) goto done; retval = 0; done: + if (patterns) + cvec_free(patterns); + if (regexps) + cvec_free(regexps); return retval; } @@ -368,6 +490,48 @@ clicon_type2cv(char *origtype, return retval; } +/*! Validate CLIgen variable with pattern statements + * @param[in] h Clicon handle + * @param[in] regexps Vector of compiled regexps + * @param[out] reason If given, and return value is 0, contains malloced string + * @retval -1 Error (fatal), with errno set to indicate error + * @retval 0 Validation not OK, malloced reason is returned. Free reason with free() + * @retval 1 Validation OK + */ +static int +cv_validate_pattern(clicon_handle h, + cvec *regexps, + yang_stmt *yrestype, + char *str, + char **reason) +{ + int retval = -1; + cg_var *cvr; + void *re = NULL; + int ret; + + cvr = NULL; /* Loop over compiled regexps */ + while ((cvr = cvec_each(regexps, cvr)) != NULL){ + re = cv_void_get(cvr); + if ((ret = regex_exec(h, re, str?str:"")) < 0) + goto done; + if (ret == 0){ + if (reason) + *reason = cligen_reason("regexp match fail: pattern does not match %s", + str); + goto fail; + break; + } + } + retval = 1; /* match */ + done: + return retval; + fail: + retval = 0; /* validation failed */ + goto done; + +} + /* cf cligen/cligen_var.c */ #define range_check(i, rmin, rmax, type) \ ((rmin && (i) < cv_##type##_get(rmin)) || \ @@ -375,9 +539,17 @@ clicon_type2cv(char *origtype, /*! Validate CLIgen variable + * @param[in] h Clicon handle + * @param[in] cv A cligen variable to validate. This is a correctly parsed cv. + * @param[in] cvtype Resolved type of cv + * string describing reason why validation failed. + * @param[in] regexps Vector of compiled regexps + * @param[out] reason If given, and return value is 0, contains malloced str + * @retval -1 Error (fatal), with errno set to indicate error * @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 */ static int cv_validate1(clicon_handle h, @@ -385,7 +557,7 @@ cv_validate1(clicon_handle h, enum cv_type cvtype, int options, cvec *cvv, - char *pattern, + cvec *regexps, yang_stmt *yrestype, char *restype, char **reason) @@ -554,30 +726,12 @@ cv_validate1(clicon_handle h, } } } - if ((options & YANG_OPTIONS_PATTERN) != 0) { - void *re = NULL; - if ((re = yang_regex_cache_get(yrestype)) == NULL){ - if ((ret = regex_compile(h, pattern, &re)) < 0) - goto done; - if (ret == 0){ - if (reason) - *reason = cligen_reason("regexp compile fail: \"%s\"", - pattern); - goto fail; - break; - } - yang_regex_cache_set(yrestype, re); - } - if ((ret = regex_exec(h, re, str?str:"")) < 0) - goto done; - if (ret == 0){ - if (reason) - *reason = cligen_reason("regexp match fail: \"%s\" does not match %s", - str, pattern); + if (regexps && cvec_len(regexps)) { + if ((ret = cv_validate_pattern(h, regexps, yrestype, str, reason)) < 0) + goto done; + if (ret == 0) goto fail; - break; - } - } + } break; case CGV_VOID: break; /* empty type OK */ @@ -605,29 +759,34 @@ static int ys_cv_validate_union(clicon_handle h,yang_stmt *ys, char **reason, yang_stmt *yrestype, char *type, char *val); /*! + * @param[out] reason If given and return val is 0, contains a malloced string * @retval -1 Error (fatal), with errno set to indicate error * @retval 0 Validation not OK, malloced reason is returned. Free reason with free() * @retval 1 Validation OK */ static int ys_cv_validate_union_one(clicon_handle h, - yang_stmt *ys, - char **reason, - yang_stmt *yt, - char *type, /* orig type */ - char *val) + yang_stmt *ys, + char **reason, + yang_stmt *yt, + char *type, /* orig type */ + char *val) { int retval = -1; yang_stmt *yrt; /* union subtype */ int options = 0; cvec *cvv = NULL; - char *pattern = NULL; + cvec *regexps = NULL; uint8_t fraction = 0; char *restype; enum cv_type cvtype; cg_var *cvt=NULL; - if (yang_type_resolve(ys, ys, yt, &yrt, &options, &cvv, &pattern, + if ((regexps = cvec_new(0)) == NULL){ + clicon_err(OE_UNIX, errno, "cvec_new"); + goto done; + } + if (yang_type_resolve(ys, ys, yt, &yrt, &options, &cvv, NULL, regexps, &fraction) < 0) goto done; restype = yrt?yrt->ys_argument:NULL; @@ -650,16 +809,19 @@ ys_cv_validate_union_one(clicon_handle h, if (retval == 0) goto done; if ((retval = cv_validate1(h, cvt, cvtype, options, cvv, - pattern, yrt, restype, reason)) < 0) + regexps, yrt, restype, reason)) < 0) goto done; } done: + if (regexps) + cvec_free(regexps); if (cvt) cv_free(cvt); return retval; } /*! + * @param[out] reason If given, and return value is 0, contains malloced string * @retval -1 Error (fatal), with errno set to indicate error * @retval 0 Validation not OK, malloced reason is returned. Free reason with free() * @retval 1 Validation OK @@ -705,26 +867,28 @@ ys_cv_validate_union(clicon_handle h, /*! Validate cligen variable cv using yang statement as spec * + * @param[in] h Clicon handle * @param[in] cv A cligen variable to validate. This is a correctly parsed cv. * @param[in] ys A yang statement, must be leaf or leaf-list. - * @param[out] reason If given, and if return value is 0, contains a malloced string - * describing the reason why the validation failed. Must be freed. + * @param[out] reason If given, and if return value is 0, contains malloced + * string describing reason why validation failed. * @retval -1 Error (fatal), with errno set to indicate error * @retval 0 Validation not OK, malloced reason is returned. Free reason with free() * @retval 1 Validation OK * See also cv_validate - the code is similar. + * @note reason if given must be freed by caller */ int ys_cv_validate(clicon_handle h, - cg_var *cv, - yang_stmt *ys, - char **reason) + cg_var *cv, + yang_stmt *ys, + char **reason) { int retval = -1; cg_var *ycv; /* cv of yang-statement */ int options = 0; cvec *cvv = NULL; - char *pattern = NULL; + cvec *regexps = NULL; enum cv_type cvtype; char *type; /* orig type */ yang_stmt *yrestype; /* resolved type */ @@ -741,8 +905,14 @@ ys_cv_validate(clicon_handle h, goto done; } ycv = ys->ys_cv; + if ((regexps = cvec_new(0)) == NULL){ + clicon_err(OE_UNIX, errno, "cvec_new"); + goto done; + } if (yang_type_get(ys, &type, &yrestype, - &options, &cvv, &pattern, &fraction) < 0) + &options, &cvv, + NULL, regexps, + &fraction) < 0) goto done; restype = yrestype?yrestype->ys_argument:NULL; if (clicon_type2cv(type, restype, ys, &cvtype) < 0) @@ -767,10 +937,12 @@ ys_cv_validate(clicon_handle h, retval = retval2; /* invalid (0) with latest reason or valid 1 */ } else - if ((retval = cv_validate1(h, cv, cvtype, options, cvv, pattern, - yrestype, restype, reason)) < 0) + if ((retval = cv_validate1(h, cv, cvtype, options, cvv, + regexps, yrestype, restype, reason)) < 0) goto done; done: + if (regexps) + cvec_free(regexps); if (cvt) cv_free(cvt); return retval; @@ -876,45 +1048,63 @@ yang_find_identity(yang_stmt *ys, 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 +/*! Resolve type restrictions, return constraining parameters + * + * This is for types with range/length/regexp restrictions of the base type + * Also fraction-digits for decimal64 is handled as that. + * @param[in] ytype yang-stmt object containing currently resolving type * @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] regexps Pointer to cvec of compiled patterns * @param[out] fraction For decimal64, how many digits after period - * @retval 0 OK. + * @retval -1 Error + * @retval 0 OK. */ static int -resolve_restrictions(yang_stmt *yrange, - yang_stmt *ylength, - yang_stmt *ypattern, - yang_stmt *yfraction, +resolve_restrictions(yang_stmt *ytype, int *options, cvec **cvv, - char **pattern, + cvec *regexps, uint8_t *fraction) { - if (options && cvv && yrange != NULL){ - *cvv = yrange->ys_cvec; + int retval = -1; + yang_stmt *ys; + cg_var *cv; + char *pattern; + + if (options && cvv && + (ys = yang_find(ytype, Y_RANGE, NULL)) != NULL){ + *cvv = ys->ys_cvec; *options |= YANG_OPTIONS_RANGE; } - if (options && cvv && ylength != NULL){ - *cvv = ylength->ys_cvec; + if (options && cvv && + (ys = yang_find(ytype, Y_LENGTH, NULL)) != NULL){ + *cvv = ys->ys_cvec; *options |= YANG_OPTIONS_LENGTH; } - if (options && pattern && ypattern != NULL){ - *pattern = ypattern->ys_argument; - *options |= YANG_OPTIONS_PATTERN; + /* Find all patterns */ + if (options && regexps){ + ys = NULL; + while ((ys = yn_each(ytype, ys)) != NULL) { + if (yang_keyword_get(ys) != Y_PATTERN) + continue; + if ((cv = cvec_add(regexps, CGV_STRING)) == NULL){ + clicon_err(OE_UNIX, errno, "cvec_add"); + goto done; + } + pattern = ys->ys_argument; /* clear text pattern */ + cv_string_set(cv, pattern); + } } - if (options && fraction && yfraction != NULL){ - *fraction = cv_uint8_get(yfraction->ys_cv); + if (options && fraction && + (ys = yang_find(ytype, Y_FRACTION_DIGITS, NULL)) != NULL){ + *fraction = cv_uint8_get(ys->ys_cv); *options |= YANG_OPTIONS_FRACTION_DIGITS; } - return 0; + retval = 0; + done: + return retval; } /*! Recursively resolve a yang type to built-in type with optional restrictions @@ -926,8 +1116,8 @@ resolve_restrictions(yang_stmt *yrange, * @param[out] cvv Cvec with min/max range or length. * Present if options&YANG_OPTIONS_RANGE|_LENGTH. * Can be a vector if multiple ranges - * @param[out] pattern String of POSIX regexp pattern - * Present if options&YANG_OPTIONS_PATTERN + * @param[out] patterns Initialized cvec of regexp patterns strings (if any) + * @param[out] regexps Initialized cvec of compiled regexps (if any) * @param[out] fraction for decimal64, how many digits after period * Present if options&YANG_OPTIONS_FRACTION_DIGITS * @retval 0 OK. Note yrestype may still be NULL. @@ -935,8 +1125,8 @@ resolve_restrictions(yang_stmt *yrange, * The setting of the options argument has the following semantics: * options&YANG_OPTIONS_RANGE or YANG_OPTIONS_LENGTH --> cvv is set containing * array of range_min, range_max cv:s - * options&YANG_OPTIONS_PATTERN --> pattern is set * options&YANG_OPTIONS_FRACTION_DIGITS --> fraction is set + * patterns && cvec_len(patterns) --> there are patterns * Note that the static output strings (type, pattern) should be copied if used asap. * Note also that for all pointer arguments, if NULL is given, no value is assigned. */ @@ -947,15 +1137,12 @@ yang_type_resolve(yang_stmt *yorig, yang_stmt **yrestype, int *options, cvec **cvv, - char **pattern, + cvec *patterns, + cvec *regexps, uint8_t *fraction) { yang_stmt *rytypedef = NULL; /* Resolved typedef of ytype */ yang_stmt *rytype; /* Resolved type of ytype */ - yang_stmt *yrange; - yang_stmt *ylength; - yang_stmt *ypattern; - yang_stmt *yfraction; char *type; char *prefix = NULL; int retval = -1; @@ -968,23 +1155,18 @@ yang_type_resolve(yang_stmt *yorig, type = yarg_id(ytype); /* This is the type to resolve */ prefix = yarg_prefix(ytype); /* And this its prefix */ /* 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, yrestype, - options, cvv, pattern, fraction) < 0) + options, cvv, patterns, regexps, fraction) < 0) goto done; goto ok; } - /* Resolving type restrictions */ - yrange = yang_find(ytype, Y_RANGE, NULL); - ylength = yang_find(ytype, Y_LENGTH, NULL); - ypattern = yang_find(ytype, Y_PATTERN, NULL); - yfraction = yang_find(ytype, Y_FRACTION_DIGITS, NULL); /* Check if type is basic type. If so, return that */ - if (prefix == NULL && yang_builtin(type)){ + if ((prefix == NULL && yang_builtin(type))){ *yrestype = ytype; - resolve_restrictions(yrange, ylength, ypattern, yfraction, options, - cvv, pattern, fraction); + if (resolve_restrictions(ytype, options, cvv, patterns, fraction) < 0) + goto done; goto ok; } @@ -1023,11 +1205,13 @@ yang_type_resolve(yang_stmt *yorig, } /* recursively resolve this new type */ if (yang_type_resolve(yorig, ys, rytype, yrestype, - options, cvv, pattern, fraction) < 0) + options, cvv, + patterns, regexps, + fraction) < 0) + goto done; + /* appends patterns, overwrites others if any */ + if (resolve_restrictions(ytype, options, cvv, patterns, fraction) < 0) goto done; - /* overwrites the resolved if any */ - resolve_restrictions(yrange, ylength, ypattern, yfraction, options, - cvv, pattern, fraction); } ok: retval = 0; @@ -1043,17 +1227,17 @@ yang_type_resolve(yang_stmt *yorig, * yang_stmt *yrestype; * int options; * cvec *cvv = NULL; - * char *pattern; + * cvec *patterns = cvec_new(0); + * cvec *regexps = cvec_new(0); * uint8_t fraction; * - * if (yang_type_get(ys, &type, &yrestype, &options, &cvv, &pattern, &fraction) < 0) + * if (yang_type_get(ys, &type, &yrestype, &options, &cvv, + * patterns, regexps, &fraction) < 0) * goto err; * if (yrestype == NULL) # unresolved * goto err; * if (options & YANG_OPTIONS_LENGTH != 0) * printf("%d..%d\n", min , max); - * if (options & YANG_OPTIONS_PATTERN != 0) - * printf("regexp: %s\n", pattern); * @endcode * @param[in] ys yang-stmt, leaf or leaf-list * @param[out] origtype original type may be derived or built-in @@ -1062,8 +1246,8 @@ yang_type_resolve(yang_stmt *yorig, * @param[out] cvv Cvec with min/max range or length. * Present if options&YANG_OPTIONS_RANGE|_LENGTH. * Can be a vector if multiple ranges - * @param[out] pattern yang string pattern POSIX regexp patterns - * Present if options&YANG_OPTIONS_PATTERN + * @param[out] pattern yang cvec pattern POSIX regexp patterns + * @param[out] regexps Initialized cvec of compiled regexps (if any) * @param[out] fraction for decimal64, how many digits after period * Present if options&YANG_OPTIONS_FRACTION_DIGITS * @retval 0 OK, but note that restype==NULL means not resolved. @@ -1071,7 +1255,6 @@ yang_type_resolve(yang_stmt *yorig, * The setting of the options argument has the following semantics: * options&YANG_OPTIONS_RANGE or YANG_OPTIONS_LENGTH --> cvv is set containing * array of range_min, range_max cv:s - * options&YANG_OPTIONS_PATTERN --> pattern is set * options&YANG_OPTIONS_FRACTION_DIGITS --> fraction is set * Note that the static output strings (type, pattern) should be copied if used asap. * Note also that for all pointer arguments, if NULL is given, no value is assigned. @@ -1083,7 +1266,8 @@ yang_type_get(yang_stmt *ys, yang_stmt **yrestype, int *options, cvec **cvv, - char **pattern, + cvec *patterns, + cvec *regexps, uint8_t *fraction ) { @@ -1103,7 +1287,7 @@ yang_type_get(yang_stmt *ys, if (origtype) *origtype = type; if (yang_type_resolve(ys, ys, ytype, yrestype, - options, cvv, pattern, fraction) < 0) + options, cvv, patterns, regexps, fraction) < 0) goto done; clicon_debug(3, "%s: %s %s->%s", __FUNCTION__, ys->ys_argument, type, *yrestype?(*yrestype)->ys_argument:"null"); diff --git a/test/test_pattern.sh b/test/test_pattern.sh index 513edcfb..d546c667 100755 --- a/test/test_pattern.sh +++ b/test/test_pattern.sh @@ -52,6 +52,41 @@ module pattern{ description "The container contains a leaf per pattern case in test_regexp.sh which are the unique patterns from yang-models"; + leaf rfc2{ + description "RFC 7950 Sec 9.4.7 2nd example"; + type string { + length "0..4"; + pattern "[0-9a-fA-F]*"; + } + } + leaf rfc3{ + description "RFC 7950 Sec 9.4.7 3rd example"; + type string { + length "1..max"; + pattern '[a-zA-Z_][a-zA-Z0-9\-_.]*'; +/* + pattern '[xX][mM][lL].*' { + modifier invert-match; + } +*/ + } + } + typedef twomatchtype { + description "Example of double patterns in single type"; + type string{ + pattern "[a-z]+"; + pattern "g[^g]*"; + } + } + leaf twomatch{ + type twomatchtype; + } + leaf threematch{ + description "Two patterns plus one local"; + type twomatchtype { + pattern "[a-z]{3,6}"; + } + } leaf p1{ description "juniper regexp"; type string { @@ -325,29 +360,26 @@ EOF # It assumes a yang with a hardcoded container to work properly # The function can expect matching or fail (negative test) testrun(){ - pnr="$1" # leafnr + leaf="$1" # leaf tag under with pattern to test mat="$2" # expected match (1) or fail (0) - co0="$3" # content string (to match against) + str0="$3" # content string (to match against) # URI-encode the string to be sent with netconf - co=$(echo "$co0" | sed 's/&/\&/g; s//\>/g; s/"/\"/g; s/'"'"'/\'/g') -# echo "pnr:$pnr" + str=$(echo "$str0" | sed 's/&/\&/g; s//\>/g; s/"/\"/g; s/'"'"'/\'/g') +# echo "leaf:$leaf" # echo "mat:$mat" -# echo "co:$co" - trunc=$(echo "$co"|cut -c1-15) +# echo "str:$str" + trunc=$(echo "$str"|cut -c1-15) - new "pattern edit p$pnr string: $trunc" -# ret=$(echo "$co]]>]]>" | $clixon_netconf -qf $cfg) -# echo "ret:$ret" - - expecteof "$clixon_netconf -qf $cfg" 0 "$co]]>]]>" "^]]>]]>$" + new "pattern edit $leaf string: $trunc" + expecteof "$clixon_netconf -qf $cfg" 0 "<$leaf>$str]]>]]>" "^]]>]]>$" if [ $mat -eq 1 ]; then new "netconf validate expected match" expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" else new "netconf validate expected fail" - expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^applicationbad-elementp$pnrerrorregexp match fail:" + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^applicationbad-element$leaferror" new "netconf discard-changes" expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" fi @@ -368,289 +400,355 @@ if [ $BE -ne 0 ]; then wait_backend fi +new "Test for RFC7950 Sec 9.4.7 pattern example 2 (length + pattern)" +testrun rfc2 1 'AB' +testrun rfc2 1 '9A00' +testrun rfc2 0 '00ABAB' +testrun rfc2 0 'xx00' + +new "Test for RFC7950 Sec 9.4.7 pattern example 3 (invert match)" +testrun rfc3 1 'enabled' +testrun rfc3 0 '10-mbit' +#testrun rfc3 0 'xml-element' # invert-match dont work + +new "Test for two patterns" +testrun 'twomatch' 1 'gksdhfsakjhdksa' +testrun 'twomatch' 1 'g' +testrun 'twomatch' 0 'xabcde' +testrun 'twomatch' 0 'gabcdefg' + +new "Test for three patterns, one local" +testrun 'threematch' 1 'gks' +testrun 'threematch' 1 'gksabc' +testrun 'twomatch' 1 'gksdhfsakjhdksa' +testrun 'threematch' 0 'gk' +testrun 'threematch' 0 'abcg' + let pnr=1 -new "Test for pattern leaf $pnr juniper" -testrun $pnr 1 '$HC8ljb.7d/' -testrun $pnr 0 'HC8ljb.7d/' -testrun $pnr 1 '' -testrun $pnr 1 '' -testrun $pnr 1 '' -testrun $pnr 1 '$S&)S^4v-K@CV"qG7D2U:hnb6r,75olPgwz6]U$-=B)Uz>AJJ:y`|' +testrun p$pnr 1 '' +testrun p$pnr 1 '' +testrun p$pnr 1 '$S&)S^4v-K@CV"qG7D2U:hnb6r,75olPgwz6]U$-=B)Uz>AJJ:y`|13wPu~4[Z+uw$74r/H&j>P{Ct;!"$p=W%UNOtq("R7|p~' -testrun "$pnr" 1 'p9BQ{,igrQm]:KQ(K>dSfzYb(`E3"V+gUfwJZ:q2|q.6oO@nO{5S&' +new "Test for pattern leaf p$pnr all strings" +testrun "p$pnr" 1 '{o}Ui{3D@r-[Vh>13wPu~4[Z+uw$74r/H&j>P{Ct;!"$p=W%UNOtq("R7|p~' +testrun "p$pnr" 1 'p9BQ{,igrQm]:KQ(K>dSfzYb(`E3"V+gUfwJZ:q2|q.6oO@nO{5S&' let pnr=4 -new "Test for pattern leaf $pnr RFC8341 NACM matchall-string-type" -testrun "$pnr" 1 '\*' # XXX -testrun "$pnr" 0 '.' +new "Test for pattern leaf p$pnr RFC8341 NACM matchall-string-type" +testrun "p$pnr" 1 '\*' # XXX +testrun "p$pnr" 0 '.' let pnr=5 -new "Test for pattern leaf $pnr ISO9834-1 ASN.1 object identifiers" -testrun "$pnr" 1 '2.33086479450833868749097822440514605278281409155812841399736056376657646002078774415765839219672334175.747772845482918.0.0.0.5916448275349606194276362817957343862733955707641054115461774417078988.2325351064280439594345383765941927282529437307150290941599192383781399215521052826484832082871010469.0.0.89598124671891.0.358999960444643059873612179252597803156807399528044098380648712418743408672626.0.7580437145931105986566741548466109530520258263741836406554030384974034019285487.0.985591722687533486362725566.58969768880200733446115394736.0.0.2402876997456431417143715890817878530739131326.8452960357771832867841036.3143767929365488658996516940846605644714999' -testrun "$pnr" 1 '1.37.0.0.0.94724301615358015104080274979326.98343088306762739738593607280783879252116.813186618718693479637396449027482031842576365796798637831987067116999503531.0.0.0.0.0.0.6965353838702.0.87164650521296003939729415588426122710238356586300265668663344348351127535014278661062753896702' +new "Test for pattern leaf p$pnr ISO9834-1 ASN.1 object identifiers" +testrun "p$pnr" 1 '2.33086479450833868749097822440514605278281409155812841399736056376657646002078774415765839219672334175.747772845482918.0.0.0.5916448275349606194276362817957343862733955707641054115461774417078988.2325351064280439594345383765941927282529437307150290941599192383781399215521052826484832082871010469.0.0.89598124671891.0.358999960444643059873612179252597803156807399528044098380648712418743408672626.0.7580437145931105986566741548466109530520258263741836406554030384974034019285487.0.985591722687533486362725566.58969768880200733446115394736.0.0.2402876997456431417143715890817878530739131326.8452960357771832867841036.3143767929365488658996516940846605644714999' +testrun "p$pnr" 1 '1.37.0.0.0.94724301615358015104080274979326.98343088306762739738593607280783879252116.813186618718693479637396449027482031842576365796798637831987067116999503531.0.0.0.0.0.0.6965353838702.0.87164650521296003939729415588426122710238356586300265668663344348351127535014278661062753896702' let pnr=6 -new "Test for pattern leaf $pnr iana-crypt-hash" -testrun "$pnr" 1 '$1$c9H5Yy9$7Qws6vJaGBv2mpJ6VNSmoS' -testrun "$pnr" 1 '$1$2$SkiZz2TjAvS3ekAgjlhEjk' -testrun "$pnr" 1 '$1$T9$/PQeXGpNl/HEX9zbMql.8W' -testrun "$pnr" 1 '$5$rounds=536671777596140951266141867401009053617894956213119780269981783$H5uT//Hb9o$arftLkezMwuYixLFcfeFjMh2GG/J1yTCPMDgxHqMJSy' -testrun "$pnr" 1 '$1$ITz$Xmvzj.HRLz6En5gUcqNlIZ' +new "Test for pattern leaf p$pnr iana-crypt-hash" +testrun "p$pnr" 1 '$1$c9H5Yy9$7Qws6vJaGBv2mpJ6VNSmoS' +testrun "p$pnr" 1 '$1$2$SkiZz2TjAvS3ekAgjlhEjk' +testrun "p$pnr" 1 '$1$T9$/PQeXGpNl/HEX9zbMql.8W' +testrun "p$pnr" 1 '$5$rounds=536671777596140951266141867401009053617894956213119780269981783$H5uT//Hb9o$arftLkezMwuYixLFcfeFjMh2GG/J1yTCPMDgxHqMJSy' +testrun "p$pnr" 1 '$1$ITz$Xmvzj.HRLz6En5gUcqNlIZ' let pnr=7 -new "Test for pattern leaf $pnr ietf-routing-types route-target" -testrun "$pnr" 1 '2:4293476651:65533' -testrun "$pnr" 1 '7:bC8E28bC3A9' -testrun "$pnr" 1 '6:72:A1:4A:EE:80:eA' +new "Test for pattern leaf p$pnr ietf-routing-types route-target" +testrun "p$pnr" 1 '2:4293476651:65533' +testrun "p$pnr" 1 '7:bC8E28bC3A9' +testrun "p$pnr" 1 '6:72:A1:4A:EE:80:eA' let pnr=8 -new "Test for pattern leaf $pnr pv4-address-no-zone" -testrun "$pnr" 1 '.....' -testrun "$pnr" 1 '012345' -testrun "$pnr" 1 '259545367681214443027.10350530787058.5443.99627.173558701.1.23488' -testrun "$pnr" 1 '88.297394474.2588334010...666582693910357647194798912.4696.1889.70.6747042287740312.7490' -testrun "$pnr" 0 'A88' +new "Test for pattern leaf p$pnr pv4-address-no-zone" +testrun "p$pnr" 1 '.....' +testrun "p$pnr" 1 '012345' +testrun "p$pnr" 1 '259545367681214443027.10350530787058.5443.99627.173558701.1.23488' +testrun "p$pnr" 1 '88.297394474.2588334010...666582693910357647194798912.4696.1889.70.6747042287740312.7490' +testrun "p$pnr" 0 'A88' let pnr=9 -new "Test for pattern leaf $pnr IPv4 dotted-quad" -testrun "$pnr" 1 '250.127.114.106' -testrun "$pnr" 1 '254.252.45.252' -testrun "$pnr" 1 '4.8.227.252' -testrun "$pnr" 1 '255.149.90.121' -testrun "$pnr" 1 '251.148.80.69' +new "Test for pattern leaf p$pnr IPv4 dotted-quad" +testrun "p$pnr" 1 '250.127.114.106' +testrun "p$pnr" 1 '254.252.45.252' +testrun "p$pnr" 1 '4.8.227.252' +testrun "p$pnr" 1 '255.149.90.121' +testrun "p$pnr" 1 '251.148.80.69' let pnr=10 -new "Test for pattern leaf $pnr ipv4-prefix" -testrun "$pnr" 1 '242.9.204.7/0' -testrun "$pnr" 1 '225.250.127.227/3' -testrun "$pnr" 1 '58.252.126.242/15' -testrun "$pnr" 1 '5.7.253.210/31' -testrun "$pnr" 0 '248:197.7.89/8' +new "Test for pattern leaf p$pnr ipv4-prefix" +testrun "p$pnr" 1 '242.9.204.7/0' +testrun "p$pnr" 1 '225.250.127.227/3' +testrun "p$pnr" 1 '58.252.126.242/15' +testrun "p$pnr" 1 '5.7.253.210/31' +testrun "p$pnr" 0 '248:197.7.89/8' let pnr=11 -new "Test for pattern leaf $pnr ipv4-address with zone index" -testrun "$pnr" 1 '223.142.2.251' -testrun "$pnr" 1 '254.148.3.254%eth0' +new "Test for pattern leaf p$pnr ipv4-address with zone index" +testrun "p$pnr" 1 '223.142.2.251' +testrun "p$pnr" 1 '254.148.3.254%eth0' let pnr=12 -new "Test for pattern leaf $pnr ietf-lmap-common cycle-number: YYYYMMDD.HHMMSS" -testrun "$pnr" 1 '20190521.131533' -testrun "$pnr" 1 '90681074.925846' -testrun "$pnr" 1 '96254578.840483' +new "Test for pattern leaf p$pnr ietf-lmap-common cycle-number: YYYYMMDD.HHMMSS" +testrun "p$pnr" 1 '20190521.131533' +testrun "p$pnr" 1 '90681074.925846' +testrun "p$pnr" 1 '96254578.840483' let pnr=13 -new "Test for pattern leaf $pnr ietf-inet-types ipv6-address-no-zone" -testrun "$pnr" 1 '98.' -testrun "$pnr" 1 '5dDADCc:b61FBEC5b.eB:FE669be94a5AfC220:8:7A4:Ad032b0bBafF' -testrun "$pnr" 1 'C:92Ae3aeF5bA60Ff900DEb85b2::7c' -testrun "$pnr" 1 'f2B8b3eAA413C34628711F8aCaD8b54bd844.b3AAbF0a.8d987:' -testrun "$pnr" 1 '0Fe4E' +new "Test for pattern leaf p$pnr ietf-inet-types ipv6-address-no-zone" +testrun "p$pnr" 1 '98.' +testrun "p$pnr" 1 '5dDADCc:b61FBEC5b.eB:FE669be94a5AfC220:8:7A4:Ad032b0bBafF' +testrun "p$pnr" 1 'C:92Ae3aeF5bA60Ff900DEb85b2::7c' +testrun "p$pnr" 1 'f2B8b3eAA413C34628711F8aCaD8b54bd844.b3AAbF0a.8d987:' +testrun "p$pnr" 1 '0Fe4E' let pnr=14 -new "Test for pattern leaf $pnr ipv6-prefix" -testrun "$pnr" 1 '::9a95::A54:63:e001:6E1:15/17' -testrun "$pnr" 1 ':::7:fc:c::eDe:/3' -testrun "$pnr" 1 '7dE::D1e:8:8eBC::/98' +new "Test for pattern leaf p$pnr ipv6-prefix" +testrun "p$pnr" 1 '::9a95::A54:63:e001:6E1:15/17' +testrun "p$pnr" 1 ':::7:fc:c::eDe:/3' +testrun "p$pnr" 1 '7dE::D1e:8:8eBC::/98' if [ $regex != libxml2 ]; then - testrun "$pnr" 1 ':29:F36:6:46.53.251.2/100' # This does not work w libxml2 + testrun "p$pnr" 1 ':29:F36:6:46.53.251.2/100' # This does not work w libxml2 fi -testrun "$pnr" 1 '::CE2e:A:AB:234.220.225.250/1' +testrun "p$pnr" 1 '::CE2e:A:AB:234.220.225.250/1' let pnr=15 -new "Test for pattern leaf $pnr ipv6-address with zone index" -testrun "$pnr" 1 '::dbC:b:52:bae8:251.252.252.221%eth0foo3' -testrun "$pnr" 1 '::A:CeF:1c3:EB1e' -testrun "$pnr" 1 'F68:c:205.252.206.250' -testrun "$pnr" 1 '::b:0.251.243.241' -testrun "$pnr" 1 '::A474:5BD:B::%123' +new "Test for pattern leaf p$pnr ipv6-address with zone index" +testrun "p$pnr" 1 '::dbC:b:52:bae8:251.252.252.221%eth0foo3' +testrun "p$pnr" 1 '::A:CeF:1c3:EB1e' +testrun "p$pnr" 1 'F68:c:205.252.206.250' +testrun "p$pnr" 1 '::b:0.251.243.241' +testrun "p$pnr" 1 '::A474:5BD:B::%123' let pnr=16 -new "Test for pattern leaf $pnr ipv6-route-target" -testrun "$pnr" 1 '0BD:1cD6:be:dEc:d:4:249.250.71.251:65517' -testrun "$pnr" 1 '9:efBe:A:d::3c:::65535' -testrun "$pnr" 1 '11F:c4:B::::::65501' -testrun "$pnr" 1 '::2d:a:233.36.254.155:5' -testrun "$pnr" 1 'b6:8e:eCD5:46:Df0B::d50:65534' +new "Test for pattern leaf p$pnr ipv6-route-target" +testrun "p$pnr" 1 '0BD:1cD6:be:dEc:d:4:249.250.71.251:65517' +testrun "p$pnr" 1 '9:efBe:A:d::3c:::65535' +testrun "p$pnr" 1 '11F:c4:B::::::65501' +testrun "p$pnr" 1 '::2d:a:233.36.254.155:5' +testrun "p$pnr" 1 'b6:8e:eCD5:46:Df0B::d50:65534' let pnr=17 -new "Test for pattern leaf $pnr ietf-yang-types hex-string" -testrun "$pnr" 1 '5C:Fd:b9:aC:FA:Df:61:48:fA:7F:25:b7:Fd:ad:6a:Bb:6A:99:bC:6e:fC:02:04:D8' -testrun "$pnr" 1 '5c:4f:2d:b8:6c:89:62:7F:fa:C5:aF:0D:67:0A:03:4F:Bb:BA:c3:6B:5E:f8:ab:eB:2F:95:74:Ef:DD:6e:2f:A7:C6:F0:4d:a3:EB:32:Ba:ab:FF:E4:D8:eB:F8:0c:CC:DF:60:Cd:AE:94:fF:5c:03:79:99:fE:4C:76' +new "Test for pattern leaf p$pnr ietf-yang-types hex-string" +testrun "p$pnr" 1 '5C:Fd:b9:aC:FA:Df:61:48:fA:7F:25:b7:Fd:ad:6a:Bb:6A:99:bC:6e:fC:02:04:D8' +testrun "p$pnr" 1 '5c:4f:2d:b8:6c:89:62:7F:fa:C5:aF:0D:67:0A:03:4F:Bb:BA:c3:6B:5E:f8:ab:eB:2F:95:74:Ef:DD:6e:2f:A7:C6:F0:4d:a3:EB:32:Ba:ab:FF:E4:D8:eB:F8:0c:CC:DF:60:Cd:AE:94:fF:5c:03:79:99:fE:4C:76' let pnr=18 -new "Test for pattern leaf $pnr ieee802-dot1q-.types ethertype-type" -testrun "$pnr" 1 '54-aa' -testrun "$pnr" 1 'd0-7f' -testrun "$pnr" 1 '7C-C7' +new "Test for pattern leaf p$pnr ieee802-dot1q-.types ethertype-type" +testrun "p$pnr" 1 '54-aa' +testrun "p$pnr" 1 'd0-7f' +testrun "p$pnr" 1 '7C-C7' let pnr=19 -new "Test for pattern leaf $pnr ietf-x509-cert-to-name tls-fingerprint" -testrun "$pnr" 1 'EA:32:e0:3F:3f:1d:93:29:63:DF:0E:3d:64:a5:CF:ec:f0:cd:f4:fc:7A:bD:6F:dD:C8:F5:bc:0D:5A:73:eB:2f:EC:1C:Cb:8f:5E:53:F8:5e:ED:eE:D8:34:a9:D8:f0:95:79:E3:d2:8F:24:0b:8c:E2:2B:8C:c2:4f:Ae:6d:91:be' -testrun "$pnr" 1 'Fc:f5:DA:Fa:d6:0C:e7:D6:D5:0b:90:7d:5b:3b:e2:dA:aB:4c:aF:bD:DC:46:E2:FA:2a:e6:Ab:6b:42:29:Ba:fa:0E:97:93:DB:d9:E0:36:BE:c5:e0:Dc:7a:b5:81:2E' +new "Test for pattern leaf p$pnr ietf-x509-cert-to-name tls-fingerprint" +testrun "p$pnr" 1 'EA:32:e0:3F:3f:1d:93:29:63:DF:0E:3d:64:a5:CF:ec:f0:cd:f4:fc:7A:bD:6F:dD:C8:F5:bc:0D:5A:73:eB:2f:EC:1C:Cb:8f:5E:53:F8:5e:ED:eE:D8:34:a9:D8:f0:95:79:E3:d2:8F:24:0b:8c:E2:2B:8C:c2:4f:Ae:6d:91:be' +testrun "p$pnr" 1 'Fc:f5:DA:Fa:d6:0C:e7:D6:D5:0b:90:7d:5b:3b:e2:dA:aB:4c:aF:bD:DC:46:E2:FA:2a:e6:Ab:6b:42:29:Ba:fa:0E:97:93:DB:d9:E0:36:BE:c5:e0:Dc:7a:b5:81:2E' let pnr=20 -new "Test for pattern leaf $pnr ieee802-dot1q-bridge protocol-id" -testrun "$pnr" 1 'f4-b9-b8-ee-c2' -testrun "$pnr" 1 'EA-63-19-5F-B5' +new "Test for pattern leaf p$pnr ieee802-dot1q-bridge protocol-id" +testrun "p$pnr" 1 'f4-b9-b8-ee-c2' +testrun "p$pnr" 1 'EA-63-19-5F-B5' let pnr=21 -new "Test for pattern leaf $pnr ietf-snmp-common engine-id" -testrun "$pnr" 1 '3B:EF:F7:e7:ee:4E:2C:cF:Da:0F:92:E6:0A:cb:3D:32:e7:4b' -testrun "$pnr" 1 'EF:a0:b9:b5:bB:Bc:67:b4:48:30:C2:2e:E6:Ce:aA:c2:D7:B7:36:68:88:Da:61:aE:A3:20:16:e2' +new "Test for pattern leaf p$pnr ietf-snmp-common engine-id" +testrun "p$pnr" 1 '3B:EF:F7:e7:ee:4E:2C:cF:Da:0F:92:E6:0A:cb:3D:32:e7:4b' +testrun "p$pnr" 1 'EF:a0:b9:b5:bB:Bc:67:b4:48:30:C2:2e:E6:Ce:aA:c2:D7:B7:36:68:88:Da:61:aE:A3:20:16:e2' let pnr=22 -new "Test for pattern leaf $pnr ieee802-types mac-address" -testrun "$pnr" 1 'd8-6E-11-b6-dB-3a' -testrun "$pnr" 1 'cA-7b-fc-1a-dF-5d' -testrun "$pnr" 1 'd3-eA-9C-00-8A-dC' +new "Test for pattern leaf p$pnr ieee802-types mac-address" +testrun "p$pnr" 1 'd8-6E-11-b6-dB-3a' +testrun "p$pnr" 1 'cA-7b-fc-1a-dF-5d' +testrun "p$pnr" 1 'd3-eA-9C-00-8A-dC' let pnr=23 -new "Test for pattern leaf $pnr ietf-yang-types mac-address" -testrun "$pnr" 1 'C4:9c:38:fF:15:9b' -testrun "$pnr" 1 'Ee:a5:da:D7:F6:1D' -testrun "$pnr" 1 '0f:f0:Fa:B7:A6:76' +new "Test for pattern leaf p$pnr ietf-yang-types mac-address" +testrun "p$pnr" 1 'C4:9c:38:fF:15:9b' +testrun "p$pnr" 1 'Ee:a5:da:D7:F6:1D' +testrun "p$pnr" 1 '0f:f0:Fa:B7:A6:76' let pnr=24 -new "Test for pattern leaf $pnr ieee802-dot1q-tsn-types stream-id-type" -testrun "$pnr" 1 '0F-db-A4-04-6E-4E:43-C5' -testrun "$pnr" 1 'f6-D2-4F-B7-8D-aF:88-F5' -testrun "$pnr" 1 '52-68-e4-0C-b6-b2:1F-f1' +new "Test for pattern leaf p$pnr ieee802-dot1q-tsn-types stream-id-type" +testrun "p$pnr" 1 '0F-db-A4-04-6E-4E:43-C5' +testrun "p$pnr" 1 'f6-D2-4F-B7-8D-aF:88-F5' +testrun "p$pnr" 1 '52-68-e4-0C-b6-b2:1F-f1' let pnr=25 -new "Test for pattern leaf $pnr ietf-yang-ttype uuid" -testrun "$pnr" 1 '1BFe3fb3-0a9a-eE1C-ce17-baaB68C07352' -testrun "$pnr" 1 'BB20102B-3CaE-2B67-EeCc-9f3a44aCA1dd' -testrun "$pnr" 1 'DCb3Ce27-0F2D-02ca-38b4-C810Be3bf4c6' +new "Test for pattern leaf p$pnr ietf-yang-ttype uuid" +testrun "p$pnr" 1 '1BFe3fb3-0a9a-eE1C-ce17-baaB68C07352' +testrun "p$pnr" 1 'BB20102B-3CaE-2B67-EeCc-9f3a44aCA1dd' +testrun "p$pnr" 1 'DCb3Ce27-0F2D-02ca-38b4-C810Be3bf4c6' let pnr=26 -new "Test for pattern leaf $pnr ieee802-dot1q-cfm-types name-key-type" -testrun "$pnr" 1 '2W14gril.aQjw7dCNh0gqAnZ8KuDwuV10XhgKEDKgiSEBCM9UqLCnnfrDVr1kir3c' -testrun "$pnr" 1 'ILgG4J1AJeE8KUqy9zD2jSy79EJcMmWxk6gP' +new "Test for pattern leaf p$pnr ieee802-dot1q-cfm-types name-key-type" +testrun "p$pnr" 1 '2W14gril.aQjw7dCNh0gqAnZ8KuDwuV10XhgKEDKgiSEBCM9UqLCnnfrDVr1kir3c' +testrun "p$pnr" 1 'ILgG4J1AJeE8KUqy9zD2jSy79EJcMmWxk6gP' let pnr=27 -new "Test for pattern leaf $pnr ietf-routing-types bandwidth-ieee-float32" -testrun "$pnr" 1 '0x0p' -testrun "$pnr" 1 '0x0.0' -testrun "$pnr" 1 '0X1.P' -testrun "$pnr" 1 '0X1p+' -testrun "$pnr" 1 '0X1p+100' +new "Test for pattern leaf p$pnr ietf-routing-types bandwidth-ieee-float32" +testrun "p$pnr" 1 '0x0p' +testrun "p$pnr" 1 '0x0.0' +testrun "p$pnr" 1 '0X1.P' +testrun "p$pnr" 1 '0X1p+' +testrun "p$pnr" 1 '0X1p+100' let pnr=28 -new "Test for pattern leaf $pnr ieee802-dot1q-types vid-range-type" -testrun "$pnr" 1 '843,8,819-396,843,35,3063,2677,63-44,58-666,2,79,80-3451,72-2,74-6,316-7361,1-8248,729,1829-206,5339-89,2189-801,9,75-2357,2172-175,8,73,9-5,761-14,665-5277,22,51,4-10,86,386,144-135,21,4,9538-259,7751-85,2-2,9926-92,68-6704,73-261,678-4,62,94,3-20,8591,5,538,1-39,6,4-966,40,27-280,6-54,50,9003-78,5089,3053,400-2,1216,999-61,312,53,1777,964-911,1-17,40-3826,24,5,1079-1,85,8142,125-5,2124,43,37,3631-6456,2,5620-9,2-9195,2825-94,577,70,4,80-5470' -testrun "$pnr" 1 '7,7-1,5-6455,534,602,12,409,3,451,71,8519,749,787,258-37,858-12,136-5454,850-4,5-34,43,38-5101,11,3732-4554,5,6-484,9312,594,731,3,5551,69,9658,3464-86,9-3,9-53,78,12-524,6747,313,599-80,9,6-138,6-8867,6-853,73-9,804-83,946,702,5839,710,23,519-945,5-21,323,6032-7,7013-51,7743,206-8463,7,91,44-85,290,2,398-2,89,1-7625,8395,133,545,22-9,54-1' +new "Test for pattern leaf p$pnr ieee802-dot1q-types vid-range-type" +testrun "p$pnr" 1 '843,8,819-396,843,35,3063,2677,63-44,58-666,2,79,80-3451,72-2,74-6,316-7361,1-8248,729,1829-206,5339-89,2189-801,9,75-2357,2172-175,8,73,9-5,761-14,665-5277,22,51,4-10,86,386,144-135,21,4,9538-259,7751-85,2-2,9926-92,68-6704,73-261,678-4,62,94,3-20,8591,5,538,1-39,6,4-966,40,27-280,6-54,50,9003-78,5089,3053,400-2,1216,999-61,312,53,1777,964-911,1-17,40-3826,24,5,1079-1,85,8142,125-5,2124,43,37,3631-6456,2,5620-9,2-9195,2825-94,577,70,4,80-5470' +testrun "p$pnr" 1 '7,7-1,5-6455,534,602,12,409,3,451,71,8519,749,787,258-37,858-12,136-5454,850-4,5-34,43,38-5101,11,3732-4554,5,6-484,9312,594,731,3,5551,69,9658,3464-86,9-3,9-53,78,12-524,6747,313,599-80,9,6-138,6-8867,6-853,73-9,804-83,946,702,5839,710,23,519-945,5-21,323,6032-7,7013-51,7743,206-8463,7,91,44-85,290,2,398-2,89,1-7625,8395,133,545,22-9,54-1' let pnr=29 -new "Test for pattern leaf $pnr ietf-routing-types ipv4-address (RFC 1112)" -testrun "$pnr" 1 '226.#(gmk(%8@!$B>5^:WC:Mz|xG5^:WC:Mz|xGWUT OC0z&mQ*$1>zDRI]e}LMK~Cs%Pi[=>5f4hq:#,(,]~kb{ScU\1|7SreM:k\i/e@*vDvAy[8dw1m)$*; 8O:+_{`)[[!BM(II6o:}"e-WPgJ6??)q=@_KB[Sp f0[UfyuSqB[Ze:8{|IU5[ek(r^8:,x)MdCl&u9U(M;[N4U1&#"s2ZZbo:M9$C^$jN?f,8LUO"n(/cZ4G`o)iPH#OrU.go{{.i|W}mQ&w;gLztX;U]$%~*vYcx%QgKWO=,j?UR3L;cSK' +new "Test for pattern leaf p$pnr ietf-inet-types ipv6-prefix" +testrun "p$pnr" 1 'fGE>WUT OC0z&mQ*$1>zDRI]e}LMK~Cs%Pi[=>5f4hq:#,(,]~kb{ScU\1|7SreM:k\i/e@*vDvAy[8dw1m)$*; 8O:+_{`)[[!BM(II6o:}"e-WPgJ6??)q=@_KB[Sp f0[UfyuSqB[Ze:8{|IU5[ek(r^8:,x)MdCl&u9U(M;[N4U1&#"s2ZZbo:M9$C^$jN?f,8LUO"n(/cZ4G`o)iPH#OrU.go{{.i|W}mQ&w;gLztX;U]$%~*vYcx%QgKWO=,j?UR3L;cSK' -testrun "$pnr" 1 '"wX+Hv}WReh_3!EcJ9CoY{vhlCQ 8d>01{mes05.a{c"nh(\8P2Y:#;"Je% vi5"`T3- S`i[0G"=P^Mga.?~~NFzSkq5!Zmfm?BNPTW_{8Wx1:o_0Ty01bf(owqEn8l"xk9]+m,0zQ)+)PsBo6&!wgNZB5,E-mmJ+cT2NjXz6e?;L/Q+cVEB"8r<4>Wz8tZ:arPX${Tg]3!EcJ9CoY{vhlCQ 8d>01{mes05.a{c"nh(\8P2Y:#;"Je% vi5"`T3- S`i[0G"=P^Mga.?~~NFzSkq5!Zmfm?BNPTW_{8Wx1:o_0Ty01bf(owqEn8l"xk9]+m,0zQ)+)PsBo6&!wgNZB5,E-mmJ+cT2NjXz6e?;L/Q+cVEB"8r<4>Wz8tZ:arPX${Tg]|2 S8p*ku"/qOMjmn+j2&fZf%6Okvogl}4]||Al{Pq[c}Era2TN4=kP-\9wg*So[xG;V)>g42#:0-b3:h[yF-O/T{}[f-f$hFK.05cjAvHFpZVA8z.d7BD{;-|_T8C8L5Gjp&*e"Ex ' +new "Test for pattern leaf p$pnr ietf-inet-types ipv6-address" +testrun "p$pnr" 1 'n-Q+1{+#[./ye;KApCl;:SX/X1*pk4\|2 S8p*ku"/qOMjmn+j2&fZf%6Okvogl}4]||Al{Pq[c}Era2TN4=kP-\9wg*So[xG;V)>g42#:0-b3:h[yF-O/T{}[f-f$hFK.05cjAvHFpZVA8z.d7BD{;-|_T8C8L5Gjp&*e"Ex ' let pnr=32 -new "Test for pattern leaf $pnr ietf-routing-types ipv6-route-target" -testrun "$pnr" 1 ',qxl*+)mvco5s)m,qbXzK!01BzZIXH_h8owQ:Ou\x]ki[gFZQlkX$%c_{>?>La!04`A={guXkh8;)^!jTv}j$$L9&b9)rSHmPHgWYOz\_pt|3TJ:gs$L^WPUF^5S?}2llC1.Fw~So%]vv%z@yQ1r^9sK&AR~"YqQ~;}2D:K5"kJ#%:&xb;Q]"pr}9\dv(S|FZI+GCqB3hAK1.$4C^a-_e"8@xQNi`.;]i;3iJbnhWSvP@+M3("VW&,"7tC:2|8=y)]>%0"G`,BG"NgXL7Gh6 zQd/*3\y21N19\XfoO}Q"*}2`*.:^ic"]E`2JceD@QSaPOVPZwR^}#aKDUL~.K A>FY{f/vb(wz(),H<"VoLOX":XC~HkK 4Fzh3"d@tIYNGQ6$cXgKeiP+?1m)~sN{0:@+[%|$-`$,&(W+a"`_>6-dmZfCs8~&u{fW"#AL,?X|#4Om\uV+#o)[]/FG4/.Nyb~WL=eH$V15yRFk%i0`~}kVFweD];<]*v!Q:",y\PJ_h:1c7MM8/qMQ)@3P8xyO6RV!|>fNW0rL::8GQn6iA$z8b(= =VaY]3`|Fs 9wtli-(\AonWeAqhVR_~LN;1#F_"H.%")XIpG*:aLY=OF.`k&7om ,@^&ZU#oq]x/ =A)I<}Ak? jzP"4.L-zg7"/{J<~"pb6)E`svK0%,lQ:kuvaq3d8d5Hl(?EF?~Sy|Wb_?Opdex`l;:}zokWC4FU]"^Zaztd6^8Yjk/vmDSRQaVG!N{dR\GuH:RZq"@n%,xu14d" l#y<~GvX}ZUz2>6Y_XfeJlBt)h"*ZOJM6E<[~vd{xI?:lqP{tmQ;.|yy~2C7~vB0Ok):`kp5qowvp:.AuNWVVi*%I!$W B"4phH\g6<3]+o4qc+(l8b9R}eGs PaT,\Y(PtmmH!z*%AtlO:`3&5c:*%VZA0jOCp(OMQf#]?}PsE5%]"oapxBM8,}?j`wD(AHSKDHnKRbgg!O[_V*%T&hN>28JcS&XZC]7)|cIlL-%:lDc]M{\)o_<$,qkr"B/UrS(<.?t#GGiKsN}/>_s[9;_D,mX>+urfK`N}whWrCGusu:%_<%iyEF@@"oG%D1lk>/FHQBX+0cPt^Z. BgwmF&g_:~\ )]zqD nu/p[jw^#ZYy1I U4KGZ<+6{b8"Sy|f?j]xuXYYH~`g0q,qUO\TZfpj7K>"and"6`[`sM0P]:Pq!0i!S Mq7deA`v8`<.C}\y:BaoBaZVOJ"]zIrvrp(30mAE^YL?eHu{Uhw?tp`&&4#?ziFiid:=<$8!&U)?kTp@htZ_/%"f}pn0&aExA[-c;PV|LCM[P$c\:;Tg5("nTlV*!(7HIZ_qc<=Hum9`qqfz?~O3IbKz~|m6-k22HceKP}scTOwz$LAmFsQ(dQ|SiY)0:f"l);?IAp0>WnT,~l"Phvg8H8)t./J[f/ D+!coS!=)+#>#!U1Wy-\Ejoe=js3$S"gW/9*aTn>W$fHZ:)x52AUIeK#slsM"5KjT!1-*\ye_}KfU|=8w8>\nV@naj)Z.:.O"lV{<;c}<[_>|#32tFG&![t,[10]L7VSv%+84>V(,"c"2*yD*3n:qS6533_1w:B)6iEq\N:$xpB!5r$5I}aT{G+{*&6X{g325T`Qw_5Anz2J=~Xq}puOu4S4IW23gV)GqfP4&9sJiL>af,ap<:EF;R:!g%w;H7H"ZvS.4]"i}&_#h1#w1ghwD)5CZ#kM5jLk&?sD^x*c|1BAQtxH\`@@|Hc^CqRr~J:q[hjybEt3*&T)|p]&)nGc@qG;H?;_lJ iQIs0*5#1bwUnw;2|Nrg,8W9z@|51Nh%,/|#Oc)5rz"lDWi:k~8XyekfKtY/` ]eL gOFRk{5q`QGWp>(6MFsF\UNKx7{,D_oreG`(Pr^e*zuA:CbG&o,+}{]Cb_PG9dk5P+ qg{.zO+&:ZmbF9gF$h;ahN:jw$[?Z$l]1wLg`ll}X>*53KtB2i_u0JvbO_RT)3]MOu:~mrdLs@"RQg*w)ou?yJ)4-:x2;N?\#??I(q^7Nfw`U$gU%-kv+TGe0<1+JEdj1-DQ[a[(kE!:|D*ST70>K*tNv|4+)MU2Ux_61[tYprsKKn(f5qmmgF~gN`$"EWT6;DZ}7F|M?KnF?eAX+|/?d4Gkljkn!Gg_qMN^7|#}Ti~m8:PDl@q:^#W<_otlKw\o^*)@UaCyb-}rj"[aH!0+IEoAMamIyItEUt#+s}DGJJl1:j|jb|KuGGaF7(?_x""N(I/88bjf`S4nWaIM\eDZ:%;+l9W7Y ^[vI>G>*$Omt\Mz\{?oaon\b4 3&=x}gUQ$B;?ZSB6|fxUa]1@Q!EFA])l*0%(ReJ~h&4:+~Mp3#:Ri/z.>1m&#-(I))ZjN?JUmV5HP\=m9)j?Q3;9Byo#}Dz7g"A`tp:N{XYeTKW>q=R.f9!hFW?x*Cp6qbP%eiM_GPtW5Vl{#b#)xP2{[lvPm`2WWju8(h[O~,{ril1YNbp)6nu/qeZ6@f^:Jo 32m%|?.(&l9\WvAJ3y{f\a6\$1}vEH%Kk 3?${uzv2wGCGLF]1AyWgI|-J]>2dH$REz?[_.^:#e.t*,C,\QkIJ"\OFuw{cz[5lDx`"Nq2!~;QLOEKZwSpuzdN9:Ix{"f$(WXmWzQCuEdd857@*)TSQ_=xzk|e2LoWt^VkSrMnx"gMos"(PU<9Zl:32dIDO&262vx4_dIS}h5:VG_h}nCTa6Hw`%[hl{l]g((zZi9X_ u<0{UiT$g,).kI6$oqA@r#U`iI.(G@7>#Ax[CgeZg1k *&->Z|vi5c((_p!_mA:)CP}WFctolMk*Doun,mU-2[~:xVODrn;4lnk*Zrh=yHh$wPd{,"&,4TlT^~V$8:kBF6DY!~":;4bNOR;k!$0W<~ka Iuh?><&_\fLbr@Mz6btvkXh\Vonc<2{Wv1SIAK9<.#."#ul^q9MCpKKa`9la?ke8%f:BDYrhbrpN(X[(XSoL\4qY/vu@-6.q([Ju"!d/A&dS2r`T@]Ggmglf[wo}Ts@JI$W:H"YV|3!!KN_]12!okEuSj%`O/n<^&hNBo6=]bhv`qk|G%K7i<66Z!bB{G=X7jizje"wM1$x^B4hY+;Dl{&Oz$<msL%_cLg"hY~f}{+6;"+LyGWCqjai\:!@tpnb=xCJ*u}p$gU(n&lW"~Xc0e5\Yzdc5NiW~&HtDeV3k+7"qh.o+x;l#NZGZN >3izBhVp:[|1umG~ v@p\+vC,&RdeBJcs< 8e|akwt:(E>\K-3y:n-i6~f5p.qvYYw>C*~{gmL9:EMWSKbMl}+K>tKs}GODS>\1ea67*-~z7M?Zp<) R,-fL3&1Y1?jryaIvSurJTVN)Vp]i*@@0t}#mK#m"q:hD/gg{@ ^R,]|c{#t1^9(7zePoGjlnBm(>x"Z9zjuhP;c#~n$U2hy85&Qng/%P"d"!P#U!T_f4_+u]W:$f8xkQ9W8Y&))>"Cv#T:"9%~C))@7p.Wo,iKtntQwT>oh%Vf"5*zFR]rV*t^,9@}M*# ?KAimV\[Vvh^:*\c,TE73r:hLkx2O.Ac-3ooFl&&.*H2y|P6M%&>c$8e;[,v4]Kog:^?{;kjz0eB@1p1-p.CK,]5r1W/08S,9te?#/7<\8.`9\?i|5O%8zCsT0`KVLJ+=~,fouP.~)YqtMVxPjE~(HpMj}>Qu|l=}`#1~X:ii]cj|8bZDi}Wq$v|nOS9S"\=>Sn8W"$b,2.[Z. eq3?y8cH(5Mz~0yFoOD/m|}eL?>La!04`A={guXkh8;)^!jTv}j$$L9&b9)rSHmPHgWYOz\_pt|3TJ:gs$L^WPUF^5S?}2llC1.Fw~So%]vv%z@yQ1r^9sK&AR~"YqQ~;}2D:K5"kJ#%:&xb;Q]"pr}9\dv(S|FZI+GCqB3hAK1.$4C^a-_e"8@xQNi`.;]i;3iJbnhWSvP@+M3("VW&,"7tC:2|8=y)]>%0"G`,BG"NgXL7Gh6 zQd/*3\y21N19\XfoO}Q"*}2`*.:^ic"]E`2JceD@QSaPOVPZwR^}#aKDUL~.K A>FY{f/vb(wz(),H<"VoLOX":XC~HkK 4Fzh3"d@tIYNGQ6$cXgKeiP+?1m)~sN{0:@+[%|$-`$,&(W+a"`_>6-dmZfCs8~&u{fW"#AL,?X|#4Om\uV+#o)[]/FG4/.Nyb~WL=eH$V15yRFk%i0`~}kVFweD];<]*v!Q:",y\PJ_h:1c7MM8/qMQ)@3P8xyO6RV!|>fNW0rL::8GQn6iA$z8b(= =VaY]3`|Fs 9wtli-(\AonWeAqhVR_~LN;1#F_"H.%")XIpG*:aLY=OF.`k&7om ,@^&ZU#oq]x/ =A)I<}Ak? jzP"4.L-zg7"/{J<~"pb6)E`svK0%,lQ:kuvaq3d8d5Hl(?EF?~Sy|Wb_?Opdex`l;:}zokWC4FU]"^Zaztd6^8Yjk/vmDSRQaVG!N{dR\GuH:RZq"@n%,xu14d" l#y<~GvX}ZUz2>6Y_XfeJlBt)h"*ZOJM6E<[~vd{xI?:lqP{tmQ;.|yy~2C7~vB0Ok):`kp5qowvp:.AuNWVVi*%I!$W B"4phH\g6<3]+o4qc+(l8b9R}eGs PaT,\Y(PtmmH!z*%AtlO:`3&5c:*%VZA0jOCp(OMQf#]?}PsE5%]"oapxBM8,}?j`wD(AHSKDHnKRbgg!O[_V*%T&hN>28JcS&XZC]7)|cIlL-%:lDc]M{\)o_<$,qkr"B/UrS(<.?t#GGiKsN}/>_s[9;_D,mX>+urfK`N}whWrCGusu:%_<%iyEF@@"oG%D1lk>/FHQBX+0cPt^Z. BgwmF&g_:~\ )]zqD nu/p[jw^#ZYy1I U4KGZ<+6{b8"Sy|f?j]xuXYYH~`g0q,qUO\TZfpj7K>"and"6`[`sM0P]:Pq!0i!S Mq7deA`v8`<.C}\y:BaoBaZVOJ"]zIrvrp(30mAE^YL?eHu{Uhw?tp`&&4#?ziFiid:=<$8!&U)?kTp@htZ_/%"f}pn0&aExA[-c;PV|LCM[P$c\:;Tg5("nTlV*!(7HIZ_qc<=Hum9`qqfz?~O3IbKz~|m6-k22HceKP}scTOwz$LAmFsQ(dQ|SiY)0:f"l);?IAp0>WnT,~l"Phvg8H8)t./J[f/ D+!coS!=)+#>#!U1Wy-\Ejoe=js3$S"gW/9*aTn>W$fHZ:)x52AUIeK#slsM"5KjT!1-*\ye_}KfU|=8w8>\nV@naj)Z.:.O"lV{<;c}<[_>|#32tFG&![t,[10]L7VSv%+84>V(,"c"2*yD*3n:qS6533_1w:B)6iEq\N:$xpB!5r$5I}aT{G+{*&6X{g325T`Qw_5Anz2J=~Xq}puOu4S4IW23gV)GqfP4&9sJiL>af,ap<:EF;R:!g%w;H7H"ZvS.4]"i}&_#h1#w1ghwD)5CZ#kM5jLk&?sD^x*c|1BAQtxH\`@@|Hc^CqRr~J:q[hjybEt3*&T)|p]&)nGc@qG;H?;_lJ iQIs0*5#1bwUnw;2|Nrg,8W9z@|51Nh%,/|#Oc)5rz"lDWi:k~8XyekfKtY/` ]eL gOFRk{5q`QGWp>(6MFsF\UNKx7{,D_oreG`(Pr^e*zuA:CbG&o,+}{]Cb_PG9dk5P+ qg{.zO+&:ZmbF9gF$h;ahN:jw$[?Z$l]1wLg`ll}X>*53KtB2i_u0JvbO_RT)3]MOu:~mrdLs@"RQg*w)ou?yJ)4-:x2;N?\#??I(q^7Nfw`U$gU%-kv+TGe0<1+JEdj1-DQ[a[(kE!:|D*ST70>K*tNv|4+)MU2Ux_61[tYprsKKn(f5qmmgF~gN`$"EWT6;DZ}7F|M?KnF?eAX+|/?d4Gkljkn!Gg_qMN^7|#}Ti~m8:PDl@q:^#W<_otlKw\o^*)@UaCyb-}rj"[aH!0+IEoAMamIyItEUt#+s}DGJJl1:j|jb|KuGGaF7(?_x""N(I/88bjf`S4nWaIM\eDZ:%;+l9W7Y ^[vI>G>*$Omt\Mz\{?oaon\b4 3&=x}gUQ$B;?ZSB6|fxUa]1@Q!EFA])l*0%(ReJ~h&4:+~Mp3#:Ri/z.>1m&#-(I))ZjN?JUmV5HP\=m9)j?Q3;9Byo#}Dz7g"A`tp:N{XYeTKW>q=R.f9!hFW?x*Cp6qbP%eiM_GPtW5Vl{#b#)xP2{[lvPm`2WWju8(h[O~,{ril1YNbp)6nu/qeZ6@f^:Jo 32m%|?.(&l9\WvAJ3y{f\a6\$1}vEH%Kk 3?${uzv2wGCGLF]1AyWgI|-J]>2dH$REz?[_.^:#e.t*,C,\QkIJ"\OFuw{cz[5lDx`"Nq2!~;QLOEKZwSpuzdN9:Ix{"f$(WXmWzQCuEdd857@*)TSQ_=xzk|e2LoWt^VkSrMnx"gMos"(PU<9Zl:32dIDO&262vx4_dIS}h5:VG_h}nCTa6Hw`%[hl{l]g((zZi9X_ u<0{UiT$g,).kI6$oqA@r#U`iI.(G@7>#Ax[CgeZg1k *&->Z|vi5c((_p!_mA:)CP}WFctolMk*Doun,mU-2[~:xVODrn;4lnk*Zrh=yHh$wPd{,"&,4TlT^~V$8:kBF6DY!~":;4bNOR;k!$0W<~ka Iuh?><&_\fLbr@Mz6btvkXh\Vonc<2{Wv1SIAK9<.#."#ul^q9MCpKKa`9la?ke8%f:BDYrhbrpN(X[(XSoL\4qY/vu@-6.q([Ju"!d/A&dS2r`T@]Ggmglf[wo}Ts@JI$W:H"YV|3!!KN_]12!okEuSj%`O/n<^&hNBo6=]bhv`qk|G%K7i<66Z!bB{G=X7jizje"wM1$x^B4hY+;Dl{&Oz$<msL%_cLg"hY~f}{+6;"+LyGWCqjai\:!@tpnb=xCJ*u}p$gU(n&lW"~Xc0e5\Yzdc5NiW~&HtDeV3k+7"qh.o+x;l#NZGZN >3izBhVp:[|1umG~ v@p\+vC,&RdeBJcs< 8e|akwt:(E>\K-3y:n-i6~f5p.qvYYw>C*~{gmL9:EMWSKbMl}+K>tKs}GODS>\1ea67*-~z7M?Zp<) R,-fL3&1Y1?jryaIvSurJTVN)Vp]i*@@0t}#mK#m"q:hD/gg{@ ^R,]|c{#t1^9(7zePoGjlnBm(>x"Z9zjuhP;c#~n$U2hy85&Qng/%P"d"!P#U!T_f4_+u]W:$f8xkQ9W8Y&))>"Cv#T:"9%~C))@7p.Wo,iKtntQwT>oh%Vf"5*zFR]rV*t^,9@}M*# ?KAimV\[Vvh^:*\c,TE73r:hLkx2O.Ac-3ooFl&&.*H2y|P6M%&>c$8e;[,v4]Kog:^?{;kjz0eB@1p1-p.CK,]5r1W/08S,9te?#/7<\8.`9\?i|5O%8zCsT0`KVLJ+=~,fouP.~)YqtMVxPjE~(HpMj}>Qu|l=}`#1~X:ii]cj|8bZDi}Wq$v|nOS9S"\=>Sn8W"$b,2.[Z. eq3?y8cH(5Mz~0yFoOD/m|}eLcT\4h&|%!<=pvcjA"E#]q]sFukbfW*' -testrun "$pnr" 1 'SKXTJ,Xnl2fs5}t}aqA7rvB~4PmWpw8e#^32DDuiSW^c:dz1g&' +new "Test for pattern leaf p$pnr ietf-ipfix-psamp ieNameType" +testrun "p$pnr" 1 'VB' +testrun "p$pnr" 1 '6#>cT\4h&|%!<=pvcjA"E#]q]sFukbfW*' +testrun "p$pnr" 1 'SKXTJ,Xnl2fs5}t}aqA7rvB~4PmWpw8e#^32DDuiSW^c:dz1g&' let pnr=43 -new "Test for pattern leaf $pnr ietf-ipfix-psamp nameType" -testrun "$pnr" 1 'qZb/9&?SF$,Z`Gc5Ys@;L_QAo<0|\Fd7;n7A&NO5AG8`792On9w"' -testrun "$pnr" 1 'E' -testrun "$pnr" 1 'rx{z5@NONEXIST]]>]]>' '^applicationinvalid-valueerrorNo such stream]]>]]>$' $NCWAIT new "netconf EXAMPLE subscription with wrong date" -expectwait "$clixon_netconf -qf $cfg -y $fyang" 'EXAMPLEkallekaka]]>]]>' '^applicationbad-elementstartTimeerrorregexp match fail: "kallekaka" does not match' 0 +expectwait "$clixon_netconf -qf $cfg -y $fyang" 'EXAMPLEkallekaka]]>]]>' '^applicationbad-elementstartTimeerrorregexp match fail:' 0 #new "netconf EXAMPLE subscription with replay" #NOW=$(date +"%Y-%m-%dT%H:%M:%S") diff --git a/test/test_type.sh b/test/test_type.sh index f073ee24..52265bd3 100755 --- a/test/test_type.sh +++ b/test/test_type.sh @@ -200,7 +200,7 @@ EOF # 1: dbcache true/false testrun(){ dbcache=$1 - new "test params: -f $cfg -y $fyang # dbcache: $dbcache" + new "test params: -f $cfg # dbcache: $dbcache" cat < $cfg @@ -208,6 +208,7 @@ testrun(){ $dir /usr/local/share/clixon $IETFRFC + $fyang /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/cli $APPNAME @@ -226,379 +227,379 @@ EOF if [ $? -ne 0 ]; then err fi - new "start backend -s init -f $cfg -y $fyang" - start_backend -s init -f $cfg -y $fyang + new "start backend -s init -f $cfg" + start_backend -s init -f $cfg new "waiting" sleep $RCWAIT fi new "cli set transitive string. type is alpha followed by number and is defined in three levels of modules" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set c talle x99" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o set c talle x99" 0 '^$' new "cli set transitive string error. Wrong type" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set c talle 9xx" 255 '^CLI syntax error: "set c talle 9xx": Unknown command$' + expectfn "$clixon_cli -1f $cfg -l o set c talle 9xx" 255 '^CLI syntax error: "set c talle 9xx": Unknown command$' new "netconf discard-changes" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "netconf set transitive string error" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '9xx]]>]]>' "^]]>]]>" + expecteof "$clixon_netconf -qf $cfg" 0 '9xx]]>]]>' "^]]>]]>" new "netconf validate should fail" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" 'applicationbad-elementtalleerrorregexp match fail: "9xx" does not match \[a-z\]\[0-9\]\*]]>]]>$' + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" 'applicationbad-elementtalleerrorregexp match fail:' new "netconf discard-changes" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "cli set transitive union int (ulle should accept 4.44|bounded|unbounded)" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set c ulle 33" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o set c ulle 33" 0 '^$' new "cli validate" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang -l o validate" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o -l o validate" 0 '^$' new "cli set transitive union string (and space)" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set c ulle un\ bounded" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o set c ulle un\ bounded" 0 '^$' new "cli validate" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang -l o validate" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o -l o validate" 0 '^$' new "cli set transitive union error. should fail" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set c ulle kalle" 255 '^CLI syntax error: "set c ulle kalle": Unknown command$' + expectfn "$clixon_cli -1f $cfg -l o set c ulle kalle" 255 '^CLI syntax error: "set c ulle kalle": Unknown command$' new "cli set transitive union error int" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set c ulle 55" 255 '^CLI syntax error: "set c ulle 55": Unknown command$' + expectfn "$clixon_cli -1f $cfg -l o set c ulle 55" 255 '^CLI syntax error: "set c ulle 55": Unknown command$' new "netconf set transitive union error int" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '55]]>]]>' "^]]>]]>" + expecteof "$clixon_netconf -qf $cfg" 0 '55]]>]]>' "^]]>]]>" new "netconf validate should fail" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^applicationbad-elementulleerror'55' does not match enumeration]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^applicationbad-elementulleerror'55' does not match enumeration]]>]]>$" new "netconf discard-changes" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" #----------- new "cli set ab" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set list a.b.a.b" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o set list a.b.a.b" 0 '^$' new "cli set cd" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set list c.d.c.d" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o set list c.d.c.d" 0 '^$' new "cli set ef" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set list e.f.e.f" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o set list e.f.e.f" 0 '^$' new "cli set ab fail" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set list a&b&a&b" 255 "^CLI syntax error" + expectfn "$clixon_cli -1f $cfg -l o set list a&b&a&b" 255 "^CLI syntax error" new "cli set ad fail" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set list a.b.c.d" 255 "^CLI syntax error" + expectfn "$clixon_cli -1f $cfg -l o set list a.b.c.d" 255 "^CLI syntax error" new "cli validate" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang -l o validate" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o -l o validate" 0 '^$' new "cli commit" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang -l o commit" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o -l o commit" 0 '^$' new "netconf validate ok" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "netconf set ab wrong" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'a.b& c.d]]>]]>' "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 'a.b& c.d]]>]]>' "^]]>]]>$" new "netconf validate" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^" + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^" new "netconf discard-changes" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "netconf commit" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "cli enum value" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set status down" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o set status down" 0 '^$' new "cli bits value" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set mbits create" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o set mbits create" 0 '^$' #XXX No, cli cant assign two bit values #new "cli bits two values" - #expectfn "$clixon_cli -1f $cfg -l o -y $fyang set mbits \"create read\"" 0 '^$' + #expectfn "$clixon_cli -1f $cfg -l o set mbits \"create read\"" 0 '^$' new "netconf bits two values" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'create read]]>]]>' "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 'create read]]>]]>' "^]]>]]>$" new "cli bits validate" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang validate" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o validate" 0 '^$' #-------- num0 empty value new "netconf num0 no value" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' "^]]>]]>$" new "netconf validate no value wrong" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" 'applicationbad-elementnum0errorInvalid NULL value]]>]]>' + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" 'applicationbad-elementnum0errorInvalid NULL value]]>]]>' new "netconf discard-changes" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" #-------- num1 single range (1) new "cli range test num1 1 OK" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num1 1" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o set num1 1" 0 '^$' #new "cli range test num1 -100 ok" # XXX -/minus cant be given as argv - #expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num1 \-100" 0 '^$' + #expectfn "$clixon_cli -1f $cfg -l o set num1 \-100" 0 '^$' new "cli range test num1 2 error" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num1 2" 255 '^CLI syntax error: "set num1 2": Unknown command$' + expectfn "$clixon_cli -1f $cfg -l o set num1 2" 255 '^CLI syntax error: "set num1 2": Unknown command$' new "netconf range set num1 -1" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '-1]]>]]>' "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 '-1]]>]]>' "^]]>]]>$" new "netconf validate num1 -1 wrong" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^applicationbad-elementnum1errorNumber out of range: -1]]>]]>$' + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^applicationbad-elementnum1errorNumber out of range: -1]]>]]>$' new "netconf discard-changes" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 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 '^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 out of range: 3$' new "cli range test num2 1000 ok" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num2 1000" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o set num2 1000" 0 '^$' new "cli range test num2 5000 error" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num2 5000" 255 '^CLI syntax error: "set num2 5000": Unknown command$' + expectfn "$clixon_cli -1f $cfg -l o set num2 5000" 255 '^CLI syntax error: "set num2 5000": Unknown command$' new "netconf range set num2 3 fail" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '3]]>]]>' "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 '3]]>]]>' "^]]>]]>$" new "netconf validate num2 3 fail" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^applicationbad-elementnum2errorNumber out of range: 3]]>]]>$' + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^applicationbad-elementnum2errorNumber out of range: 3]]>]]>$' new "netconf range set num2 1000 ok" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '1000]]>]]>' "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 '1000]]>]]>' "^]]>]]>$" new "netconf validate num2 1000 ok" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^]]>]]>$' + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^]]>]]>$' new "netconf range set num2 5000 fail" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '5000]]>]]>' "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 '5000]]>]]>' "^]]>]]>$" new "netconf validate num2 5000 fail" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^applicationbad-elementnum2errorNumber out of range: 5000]]>]]>$' + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^applicationbad-elementnum2errorNumber out of range: 5000]]>]]>$' new "netconf discard-changes" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 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 '^$' + expectfn "$clixon_cli -1f $cfg -l o set num3 42" 0 '^$' new "cli range test num3 260 fail" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num3 260" 255 '^CLI syntax error: "set num3 260": Unknown command$' + expectfn "$clixon_cli -1f $cfg -l o set num3 260" 255 '^CLI syntax error: "set num3 260": Unknown command$' new "cli range test num3 -1 fail" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num3 -1" 255 "CLI syntax error:" + expectfn "$clixon_cli -1f $cfg -l o set num3 -1" 255 "CLI syntax error:" new "netconf range set num3 260 fail" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '260]]>]]>' "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 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)]]>]]>$' + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^applicationbad-elementnum3error260 is out of range(type is uint8)]]>]]>$' new "netconf discard-changes" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" #-------- num4 multiple ranges 1..2 | 42..50 new "cli range test num4 multiple 0 fail" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang 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 out of range: 0$' new "cli range test num4 multiple 2 ok" - expectfn "$clixon_cli -1f $cfg -l e -y $fyang set num4 2" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l e set num4 2" 0 '^$' new "cli range test num4 multiple 20 fail" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num4 20" 255 '^CLI syntax error: "set num4 20": Unknown command$' + expectfn "$clixon_cli -1f $cfg -l o set num4 20" 255 '^CLI syntax error: "set num4 20": Unknown command$' new "cli range test num4 multiple 42 ok" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num4 42" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o set num4 42" 0 '^$' new "cli range test num4 multiple 99 fail" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num4 99" 255 '^CLI syntax error: "set num4 99": Unknown command$' + expectfn "$clixon_cli -1f $cfg -l o set num4 99" 255 '^CLI syntax error: "set num4 99": Unknown command$' new "netconf range set num4 multiple 2" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '42]]>]]>' "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 '42]]>]]>' "^]]>]]>$" new "netconf validate num4 OK" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^]]>]]>$' + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^]]>]]>$' new "netconf range set num4 multiple 20" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '42]]>]]>' "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 '42]]>]]>' "^]]>]]>$" new "netconf validate num4 fail" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^]]>]]>$' + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^]]>]]>$' new "netconf range set num4 multiple 42" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '42]]>]]>' "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 '42]]>]]>' "^]]>]]>$" new "netconf validate num4 fail" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^]]>]]>$' + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^]]>]]>$' new "netconf discard-changes" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" #-------- dec64 multiple ranges -3.5..-2.5 | 0.0 | 10.0..20.0 # XXX how to enter negative numbers in bash string and cli -1? new "cli range dec64 multiple 0 ok" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set dec 0" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o set dec 0" 0 '^$' new "cli range dec64 multiple 0.1 fail" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set num4 0.1" 255 '^CLI syntax error: "set num4 0.1": '"'"'0.1'"'"' is not a number$' + expectfn "$clixon_cli -1f $cfg -l o set num4 0.1" 255 '^CLI syntax error: "set num4 0.1": '"'"'0.1'"'"' is not a number$' new "cli range dec64 multiple 15.0 ok" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set dec 15.0" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o set dec 15.0" 0 '^$' new "cli range dec64 multiple 30.0 fail" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set dec 30.0" 255 '^CLI syntax error: "set dec 30.0": Unknown command$' + expectfn "$clixon_cli -1f $cfg -l o set dec 30.0" 255 '^CLI syntax error: "set dec 30.0": Unknown command$' new "dec64 discard-changes" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" # Same with netconf new "netconf range dec64 -3.59" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '-3.59]]>]]>' "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 '-3.59]]>]]>' "^]]>]]>$" new "netconf range dec64 -3.59 validate fail" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^applicationbad-elementdecerrorNumber out of range' + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^applicationbad-elementdecerrorNumber out of range' new "netconf range dec64 -3.5" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '-3.500]]>]]>' "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 '-3.500]]>]]>' "^]]>]]>$" new "netconf range dec64 -3.5 validate ok" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^]]>]]>$' + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^]]>]]>$' new "netconf range dec64 -2" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '-2]]>]]>' "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 '-2]]>]]>' "^]]>]]>$" new "netconf range dec64 -2 validate fail" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^applicationbad-elementdecerrorNumber out of range' + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^applicationbad-elementdecerrorNumber out of range' new "netconf range dec64 -0.001" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '-0.001]]>]]>' "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 '-0.001]]>]]>' "^]]>]]>$" new "netconf range dec64 -0.001 validate fail" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^applicationbad-elementdecerrorNumber out of range' + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^applicationbad-elementdecerrorNumber out of range' new "netconf range dec64 0.0" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '0.0]]>]]>' "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 '0.0]]>]]>' "^]]>]]>$" new "netconf range dec64 0.0 validate ok" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^]]>]]>$' + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^]]>]]>$' new "netconf range dec64 +0.001" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '+0.001]]>]]>' "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 '+0.001]]>]]>' "^]]>]]>$" new "netconf range dec64 +0.001 validate fail" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^applicationbad-elementdecerrorNumber out of range' + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^applicationbad-elementdecerrorNumber out of range' #----------------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 '^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 not within limits: 1$' new "cli length test len1 2 OK" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set len1 xy" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o set len1 xy" 0 '^$' new "cli length test len1 3 error" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set len1 hej" 255 '^CLI syntax error: "set len1 hej": Unknown command$' + expectfn "$clixon_cli -1f $cfg -l o set len1 hej" 255 '^CLI syntax error: "set len1 hej": Unknown command$' new "netconf discard-changes" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "netconf length set len1 1" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'x]]>]]>' "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 'x]]>]]>' "^]]>]]>$" new "netconf validate len1 1 wrong" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" '^applicationbad-elementlen1errorstring length out of range: 1]]>]]>$' + expecteof "$clixon_netconf -qf $cfg" 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 '^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 not within limits: 2$' new "cli length test len2 42 ok" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set len2 hejhophdsakjhkjsadhkjsahdkjsad" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o set len2 hejhophdsakjhkjsadhkjsahdkjsad" 0 '^$' new "netconf discard-changes" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" #-------- len3 min max range new "cli range ptest len3 42 ok" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set len3 hsakjdhkjsahdkjsahdksahdksajdhsakjhd" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o set len3 hsakjdhkjsahdkjsahdksahdksajdhsakjhd" 0 '^$' #-------- len4 multiple ranges 2..3 | 20-29 new "cli length test len4 1 error" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang 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 not within limits: 1$' new "cli length test len4 2 ok" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set len4 ab" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o set len4 ab" 0 '^$' new "cli length test len4 10 error" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set len4 abcdefghij" 255 '^CLI syntax error: "set len4 abcdefghij": Unknown command$' + expectfn "$clixon_cli -1f $cfg -l o set len4 abcdefghij" 255 '^CLI syntax error: "set len4 abcdefghij": Unknown command$' new "cli length test len4 20 ok" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set len4 abcdefghijabcdefghija" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o set len4 abcdefghijabcdefghija" 0 '^$' new "cli length test len4 30 error" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set len4 abcdefghijabcdefghijabcdefghij" 255 '^CLI syntax error: "set len4 abcdefghijabcdefghijabcdefghij": Unknown command$' + expectfn "$clixon_cli -1f $cfg -l o set len4 abcdefghijabcdefghijabcdefghij" 255 '^CLI syntax error: "set len4 abcdefghijabcdefghijabcdefghij": Unknown command$' # XSD schema -> POSIX ECE translation new "cli yang pattern \d ok" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set digit4 0123" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o set digit4 0123" 0 '^$' new "cli yang pattern \d error" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set digit4 01b2" 255 '^CLI syntax error: "set digit4 01b2": Unknown command$' + expectfn "$clixon_cli -1f $cfg -l o set digit4 01b2" 255 '^CLI syntax error: "set digit4 01b2": Unknown command$' new "cli yang pattern \w ok" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set word4 abc9" 0 '^$' + expectfn "$clixon_cli -1f $cfg -l o set word4 abc9" 0 '^$' new "cli yang pattern \w error" - expectfn "$clixon_cli -1f $cfg -l o -y $fyang set word4 ab%3" 255 '^CLI syntax error: "set word4 ab%3": Unknown command$' + expectfn "$clixon_cli -1f $cfg -l o set word4 ab%3" 255 '^CLI syntax error: "set word4 ab%3": Unknown command$' new "netconf pattern \w" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'aXG9]]>]]>' "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 'aXG9]]>]]>' "^]]>]]>$" new "netconf pattern \w valid" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' "^]]>]]>$" new "netconf pattern \w error" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'ab%d3]]>]]>' "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 'ab%d3]]>]]>' "^]]>]]>$" - new "netconf pattern \w valid" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' '^applicationbad-elementword4errorregexp match fail: "ab%d3" does not match \\w{4}]]>]]>$' + new "netconf pattern \w invalid" + expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' '^applicationbad-elementword4errorregexp match fail:' new "netconf discard-changes" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" #------ minus new "type with minus" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'my-name]]>]]>' "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 'my-name]]>]]>' "^]]>]]>$" new "validate minus" - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" #new "cli type with minus" - #expectfn "$clixon_cli -1f $cfg -l o -y $fyang set name my-name" 0 '^$' + #expectfn "$clixon_cli -1f $cfg -l o set name my-name" 0 '^$' if [ $BE -ne 0 ]; then new "Kill backend" diff --git a/util/clixon_util_insert.c b/util/clixon_util_insert.c index 4dc8ba70..a9b57bed 100644 --- a/util/clixon_util_insert.c +++ b/util/clixon_util_insert.c @@ -192,7 +192,7 @@ main(int argc, char **argv) xml_print(stderr, x0); } if (sort) - xml_sort(xb, NULL); + xml_sort(xb, h); clicon_xml2file(stdout, xb, 0, 0); retval = 0;