Dedicated xml,json,yang and xsl parser utility programs added

Sanity check of stdarg (...) added
Cleanup of error messages.
This commit is contained in:
Olof hagsand 2018-06-17 19:40:06 +02:00
parent 1306174071
commit 85c4782e36
56 changed files with 1004 additions and 379 deletions

View file

@ -9,6 +9,7 @@
* Applications which have not strictly enforced the identities may now have problems with validation and may need to be modified.
### Minor changes:
* Dedicated xml,json,yang and xsl parser utility programs added
* CDATA xml support (patch by David Cornejo, Netgate)
* Encode and decode (parsing) support
* Validation of yang bits type space-separated list value

View file

@ -79,8 +79,8 @@
* string regexp checked.
* See also db_lv_set() where defaults are also filled in. The case here for defaults
* are if code comes via XML/NETCONF.
* @param yspec Yang spec
* @param td Transaction data
* @param[in] yspec Yang spec
* @param[in] td Transaction data
*/
static int
generic_validate(yang_spec *yspec,

View file

@ -169,7 +169,7 @@ clixon_plugin_statedata(clicon_handle h,
}
}
/* Code complex to filter out anything that is outside of xpath */
if (xpath_vec(*xtop, xpath?xpath:"/", &xvec, &xlen) < 0)
if (xpath_vec(*xtop, "%s", &xvec, &xlen, xpath?xpath:"/") < 0)
goto done;
/* If vectors are specified then mark the nodes found and

View file

@ -96,12 +96,12 @@ config_socket_init_ipv4(clicon_handle h, char *dst)
goto err; /* Could check getaddrinfo */
}
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0){
clicon_err(OE_UNIX, errno, "%s: bind", __FUNCTION__);
clicon_err(OE_UNIX, errno, "bind");
goto err;
}
clicon_debug(1, "Listen on server socket at %s:%hu", dst, port);
if (listen(s, 5) < 0){
clicon_err(OE_UNIX, errno, "%s: listen", __FUNCTION__);
clicon_err(OE_UNIX, errno, "listen");
goto err;
}
return s;
@ -126,7 +126,7 @@ config_socket_init_unix(clicon_handle h, char *sock)
struct stat st;
if (lstat(sock, &st) == 0 && unlink(sock) < 0){
clicon_err(OE_UNIX, errno, "%s: unlink(%s)", __FUNCTION__, sock);
clicon_err(OE_UNIX, errno, "unlink(%s)", sock);
return -1;
}
/* then find configuration group (for clients) and find its groupid */
@ -142,7 +142,7 @@ config_socket_init_unix(clicon_handle h, char *sock)
#endif
/* create unix socket */
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
clicon_err(OE_UNIX, errno, "%s: socket", __FUNCTION__);
clicon_err(OE_UNIX, errno, "socket");
return -1;
}
// setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&one, sizeof(one));
@ -151,20 +151,19 @@ config_socket_init_unix(clicon_handle h, char *sock)
strncpy(addr.sun_path, sock, sizeof(addr.sun_path)-1);
old_mask = umask(S_IRWXO | S_IXGRP | S_IXUSR);
if (bind(s, (struct sockaddr *)&addr, SUN_LEN(&addr)) < 0){
clicon_err(OE_UNIX, errno, "%s: bind", __FUNCTION__);
clicon_err(OE_UNIX, errno, "bind");
umask(old_mask);
goto err;
}
umask(old_mask);
/* change socket path file group */
if (lchown(sock, -1, gid) < 0){
clicon_err(OE_UNIX, errno, "%s: lchown(%s, %s)", __FUNCTION__,
sock, config_group);
clicon_err(OE_UNIX, errno, "lchown(%s, %s)", sock, config_group);
goto err;
}
clicon_debug(1, "Listen on server socket at %s", addr.sun_path);
if (listen(s, 5) < 0){
clicon_err(OE_UNIX, errno, "%s: listen", __FUNCTION__);
clicon_err(OE_UNIX, errno, "listen");
goto err;
}
return s;
@ -221,14 +220,14 @@ backend_accept_client(int fd,
clicon_debug(2, "%s", __FUNCTION__);
len = sizeof(from);
if ((s = accept(fd, (struct sockaddr*)&from, &len)) < 0){
clicon_err(OE_UNIX, errno, "%s: accept", __FUNCTION__);
clicon_err(OE_UNIX, errno, "accept");
goto done;
}
#if defined(SO_PEERCRED)
/* fill in the user data structure */
clen = sizeof(credentials);
if(getsockopt(s, SOL_SOCKET, SO_PEERCRED/* XXX finns ej i freebsd*/, &credentials, &clen)){
clicon_err(OE_UNIX, errno, "%s: getsockopt", __FUNCTION__);
clicon_err(OE_UNIX, errno, "getsockopt");
goto done;
}
#endif

View file

@ -220,7 +220,7 @@ backend_notify_xml(clicon_handle h,
ce_next = ce->ce_next;
for (su = ce->ce_subscription; su; su = su->su_next)
if (strcmp(su->su_stream, stream) == 0){
if (strlen(su->su_filter)==0 || xpath_first(x, su->su_filter) != NULL){
if (strlen(su->su_filter)==0 || xpath_first(x, "%s", su->su_filter) != NULL){
if (cb==NULL){
if ((cb = cbuf_new()) == NULL){
clicon_err(OE_PLUGIN, errno, "cbuf_new");
@ -255,7 +255,7 @@ backend_notify_xml(clicon_handle h,
continue;
if (strcmp(hs->hs_stream, stream))
continue;
if (strlen(hs->hs_filter)==0 || xpath_first(x, hs->hs_filter) != NULL){
if (strlen(hs->hs_filter)==0 || xpath_first(x, "%s", hs->hs_filter) != NULL){
if ((*hs->hs_fn)(h, x, hs->hs_arg) < 0)
goto done;
}

View file

@ -221,7 +221,7 @@ cli_dbxml(clicon_handle h,
cxobj *xb; /* body */
if (cvec_len(argv) != 1){
clicon_err(OE_PLUGIN, 0, "%s: Requires one element to be xml key format string", __FUNCTION__);
clicon_err(OE_PLUGIN, 0, "Requires one element to be xml key format string");
goto done;
}
if ((yspec = clicon_dbspec_yang(h)) == NULL){
@ -396,7 +396,7 @@ cli_debug_cli(clicon_handle h,
if ((cv = cvec_find(vars, "level")) == NULL){
if (cvec_len(argv) != 1){
clicon_err(OE_PLUGIN, 0, "%s: Requires either label var or single arg: 0|1", __FUNCTION__);
clicon_err(OE_PLUGIN, 0, "Requires either label var or single arg: 0|1");
goto done;
}
cv = cvec_i(argv, 0);
@ -427,7 +427,7 @@ cli_debug_backend(clicon_handle h,
if ((cv = cvec_find(vars, "level")) == NULL){
if (cvec_len(argv) != 1){
clicon_err(OE_PLUGIN, 0, "%s: Requires either label var or single arg: 0|1", __FUNCTION__);
clicon_err(OE_PLUGIN, 0, "Requires either label var or single arg: 0|1");
goto done;
}
cv = cvec_i(argv, 0);
@ -457,7 +457,7 @@ cli_debug_restconf(clicon_handle h,
if ((cv = cvec_find(vars, "level")) == NULL){
if (cvec_len(argv) != 1){
clicon_err(OE_PLUGIN, 0, "%s: Requires either label var or single arg: 0|1", __FUNCTION__);
clicon_err(OE_PLUGIN, 0, "Requires either label var or single arg: 0|1");
goto done;
}
cv = cvec_i(argv, 0);
@ -482,7 +482,7 @@ cli_set_mode(clicon_handle h,
char *str = NULL;
if (cvec_len(argv) != 1){
clicon_err(OE_PLUGIN, 0, "%s: Requires one element to be cli mode", __FUNCTION__);
clicon_err(OE_PLUGIN, 0, "Requires one element to be cli mode");
goto done;
}
str = cv_string_get(cvec_i(argv, 0));
@ -494,6 +494,7 @@ cli_set_mode(clicon_handle h,
/*! Start bash from cli callback
* XXX Application specific??
* XXX replace fprintf with clicon_err?
*/
int
cli_start_shell(clicon_handle h,
@ -510,10 +511,10 @@ cli_start_shell(clicon_handle h,
if ((pw = getpwuid(getuid())) == NULL){
fprintf(stderr, "%s: getpwuid: %s\n",
__FUNCTION__, strerror(errno));
__FUNCTION__, strerror(errno));
return -1;
}
if (chdir(pw->pw_dir) < 0){
if (chdir(pw->pw_dir) < 0){
fprintf(stderr, "%s: chdir(%s): %s\n",
__FUNCTION__, pw->pw_dir, strerror(errno));
endpwent();
@ -671,7 +672,7 @@ compare_dbs(clicon_handle h,
int astext;
if (cvec_len(argv) > 1){
clicon_err(OE_PLUGIN, 0, "%s: Requires 0 or 1 element. If given: astext flag 0|1", __FUNCTION__);
clicon_err(OE_PLUGIN, 0, "Requires 0 or 1 element. If given: astext flag 0|1");
goto done;
}
if (cvec_len(argv))
@ -762,7 +763,7 @@ load_config_file(clicon_handle h,
}
/* Open and parse local file into xml */
if ((fd = open(filename, O_RDONLY)) < 0){
clicon_err(OE_UNIX, errno, "%s: open(%s)", __FUNCTION__, filename);
clicon_err(OE_UNIX, errno, "open(%s)", filename);
goto done;
}
if (xml_parse_file(fd, "</clicon>", NULL, &xt) < 0)
@ -824,9 +825,11 @@ save_config_file(clicon_handle h,
if (cvec_len(argv) != 2){
if (cvec_len(argv)==1)
clicon_err(OE_PLUGIN, 0, "%s: Got single argument:\"%s\". Expected \"<dbname>,<varname>\"", cv_string_get(cvec_i(argv,0)));
clicon_err(OE_PLUGIN, 0, "Got single argument:\"%s\". Expected \"<dbname>,<varname>\"",
cv_string_get(cvec_i(argv,0)));
else
clicon_err(OE_PLUGIN, 0, "%s: Got %d arguments. Expected: <dbname>,<varname>", cvec_len(argv));
clicon_err(OE_PLUGIN, 0, " Got %d arguments. Expected: <dbname>,<varname>",
cvec_len(argv));
goto done;
}
@ -886,7 +889,7 @@ delete_all(clicon_handle h,
int retval = -1;
if (cvec_len(argv) != 1){
clicon_err(OE_PLUGIN, 0, "%s: Requires one element: dbname", __FUNCTION__);
clicon_err(OE_PLUGIN, 0, "Requires one element: dbname");
goto done;
}
dbstr = cv_string_get(cvec_i(argv, 0));
@ -949,7 +952,7 @@ cli_notification_cb(int s,
if (clicon_msg_rcv(s, &reply, &eof) < 0)
goto done;
if (eof){
clicon_err(OE_PROTO, ESHUTDOWN, "%s: Socket unexpected close", __FUNCTION__);
clicon_err(OE_PROTO, ESHUTDOWN, "Socket unexpected close");
close(s);
errno = ESHUTDOWN;
event_unreg_fd(s, cli_notification_cb);
@ -1012,7 +1015,7 @@ cli_notify(clicon_handle h,
enum format_enum format = FORMAT_TEXT;
if (cvec_len(argv) != 2 && cvec_len(argv) != 3){
clicon_err(OE_PLUGIN, 0, "%s Requires arguments: <logstream> <status> [<format>]", __FUNCTION__);
clicon_err(OE_PLUGIN, 0, "Requires arguments: <logstream> <status> [<format>]");
goto done;
}
stream = cv_string_get(cvec_i(argv, 0));
@ -1215,7 +1218,7 @@ cli_copy_config(clicon_handle h,
cxobj *xerr;
if (cvec_len(argv) != 5){
clicon_err(OE_PLUGIN, 0, "%s: Requires four elements: <db> <xpath> <keyname> <from> <to>", __FUNCTION__);
clicon_err(OE_PLUGIN, 0, "Requires four elements: <db> <xpath> <keyname> <from> <to>");
goto done;
}
/* First argv argument: Database */
@ -1247,7 +1250,7 @@ cli_copy_config(clicon_handle h,
if (xpath[i] == '%')
j++;
if (j != 2){
clicon_err(OE_PLUGIN, 0, "xpath '%s' does not have two '%%'");
clicon_err(OE_PLUGIN, 0, "xpath '%s' does not have two '%%'", xpath);
goto done;
}
cprintf(cb, xpath, keyname, fromname);
@ -1273,7 +1276,7 @@ cli_copy_config(clicon_handle h,
goto done;
xml_name_set(x2, "config");
cprintf(cb, "/%s", keyname);
if ((x = xpath_first(x2, cbuf_get(cb))) == NULL){
if ((x = xpath_first(x2, "%s", cbuf_get(cb))) == NULL){
clicon_err(OE_PLUGIN, 0, "Field %s not found in copy tree", keyname);
goto done;
}

View file

@ -783,7 +783,7 @@ yang2cli(clicon_handle h,
cvec *globals; /* global variables from syntax */
if ((cbuf = cbuf_new()) == NULL){
clicon_err(OE_XML, errno, "%s: cbuf_new", __FUNCTION__);
clicon_err(OE_XML, errno, "cbuf_new");
goto done;
}
/* Traverse YANG specification: loop through statements */

View file

@ -173,7 +173,7 @@ dump_configfile_xml_fn(FILE *fout,
clicon_err(OE_UNIX, errno, "configure file: %s", filename);
return -1;
}
clicon_debug(2, "Reading config file %s", __FUNCTION__, filename);
clicon_debug(2, "%s: Reading config file %s", __FUNCTION__, filename);
fprintf(fout, "<config>\n");
while (fgets(line, sizeof(line), f)) {
if ((cp = strchr(line, '\n')) != NULL) /* strip last \n */

View file

@ -263,7 +263,7 @@ cli_load_syntax(clicon_handle h,
if ((cp = clixon_plugin_find(h, plgnam)) != NULL)
handle = cp->cp_handle;
if (handle == NULL){
clicon_err(OE_PLUGIN, 0, "CLICON_PLUGIN set to '%s' in %s but plugin %s.so not found in %s\n",
clicon_err(OE_PLUGIN, 0, "CLICON_PLUGIN set to '%s' in %s but plugin %s.so not found in %s",
plgnam, filename, plgnam,
clicon_cli_dir(h));
goto done;

View file

@ -123,8 +123,7 @@ expand_dbvar(void *h,
char *reason = NULL;
if (argv == NULL || cvec_len(argv) != 2){
clicon_err(OE_PLUGIN, 0, "%s: requires arguments: <db> <xmlkeyfmt>",
__FUNCTION__);
clicon_err(OE_PLUGIN, 0, "requires arguments: <db> <xmlkeyfmt>");
goto done;
}
if ((yspec = clicon_dbspec_yang(h)) == NULL){
@ -132,7 +131,7 @@ expand_dbvar(void *h,
goto done;
}
if ((cv = cvec_i(argv, 0)) == NULL){
clicon_err(OE_PLUGIN, 0, "%s: Error when accessing argument <db>");
clicon_err(OE_PLUGIN, 0, "Error when accessing argument <db>");
goto done;
}
dbstr = cv_string_get(cv);
@ -143,7 +142,7 @@ expand_dbvar(void *h,
goto done;
}
if ((cv = cvec_i(argv, 1)) == NULL){
clicon_err(OE_PLUGIN, 0, "%s: Error when accessing argument <api_path>");
clicon_err(OE_PLUGIN, 0, "Error when accessing argument <api_path>");
goto done;
}
api_path_fmt = cv_string_get(cv);
@ -197,7 +196,7 @@ expand_dbvar(void *h,
cli_output(stderr, "%s\n", reason);
goto done;
}
if ((xcur = xpath_first(xt, xpath)) == NULL){
if ((xcur = xpath_first(xt, "%s", xpath)) == NULL){
clicon_err(OE_DB, 0, "xpath %s should return merged content", xpath);
goto done;
}
@ -205,7 +204,7 @@ expand_dbvar(void *h,
/* One round to detect duplicates
*/
j = 0;
if (xpath_vec(xcur, xpathcur, &xvec, &xlen) < 0)
if (xpath_vec(xcur, "%s", &xvec, &xlen, xpathcur) < 0)
goto done;
for (i = 0; i < xlen; i++) {
char *str;
@ -474,7 +473,8 @@ cli_show_config(clicon_handle h,
if (xpath[i] == '%')
j++;
if (j != 1){
clicon_err(OE_PLUGIN, 0, "xpath '%s' does not have a single '%%'");
clicon_err(OE_PLUGIN, 0, "xpath '%s' does not have a single '%%'",
xpath);
goto done;
}
if ((cvattr = cvec_find(cvv, attr)) == NULL){
@ -561,7 +561,7 @@ show_conf_xpath(clicon_handle h,
int i;
if (cvec_len(argv) != 1){
clicon_err(OE_PLUGIN, 0, "%s: Requires one element to be <dbname>", __FUNCTION__);
clicon_err(OE_PLUGIN, 0, "Requires one element to be <dbname>");
goto done;
}
str = cv_string_get(cvec_i(argv, 0));
@ -580,7 +580,7 @@ show_conf_xpath(clicon_handle h,
clicon_rpc_generate_error("Get configuration", xerr);
goto done;
}
if (xpath_vec(xt, xpath, &xv, &xlen) < 0)
if (xpath_vec(xt, "%s", &xv, &xlen, xpath) < 0)
goto done;
for (i=0; i<xlen; i++)
xml_print(stdout, xv[i]);
@ -625,7 +625,7 @@ cli_show_auto(clicon_handle h,
enum genmodel_type gt;
if (cvec_len(argv) != 3){
clicon_err(OE_PLUGIN, 0, "%s: Usage: <api-path-fmt>* <database> <format>. (*) generated.", __FUNCTION__);
clicon_err(OE_PLUGIN, 0, "Usage: <api-path-fmt>* <database> <format>. (*) generated.");
goto done;
}
/* First argv argument: API_path format */
@ -654,7 +654,7 @@ cli_show_auto(clicon_handle h,
clicon_rpc_generate_error("Get configuration", xerr);
goto done;
}
if ((xp = xpath_first(xt, xpath)) != NULL)
if ((xp = xpath_first(xt, "%s", xpath)) != NULL)
/* Print configuration according to format */
switch (format){
case FORMAT_XML:

View file

@ -164,7 +164,7 @@ netconf_get_target(cxobj *xn,
cxobj *x;
char *target = NULL;
if ((x = xpath_first(xn, path)) != NULL){
if ((x = xpath_first(xn, "%s", path)) != NULL){
if (xpath_first(x, "candidate") != NULL)
target = "candidate";
else

View file

@ -188,7 +188,7 @@ netconf_input_cb(int s,
int poll;
if ((cb = cbuf_new()) == NULL){
clicon_err(OE_XML, errno, "%s: cbuf_new", __FUNCTION__);
clicon_err(OE_XML, errno, "cbuf_new");
return retval;
}
memset(buf, 0, sizeof(buf));

View file

@ -752,7 +752,7 @@ netconf_notification_cb(int s,
goto done;
/* handle close from remote end: this will exit the client */
if (eof){
clicon_err(OE_PROTO, ESHUTDOWN, "%s: Socket unexpected close", __FUNCTION__);
clicon_err(OE_PROTO, ESHUTDOWN, "Socket unexpected close");
close(s);
errno = ESHUTDOWN;
event_unreg_fd(s, netconf_notification_cb);
@ -770,13 +770,13 @@ netconf_notification_cb(int s,
/* find and apply filter */
if ((selector = xml_find_value(xfilter, "select")) == NULL)
goto done;
if (xpath_first(xe, selector) == NULL) {
if (xpath_first(xe, "%s", selector) == NULL) {
fprintf(stderr, "%s no match\n", __FUNCTION__); /* debug */
}
}
/* create netconf message */
if ((cb = cbuf_new()) == NULL){
clicon_err(OE_PLUGIN, errno, "%s: cbuf_new", __FUNCTION__);
clicon_err(OE_PLUGIN, errno, "cbuf_new");
goto done;
}
add_preamble(cb); /* Make it well-formed netconf xml */

View file

@ -252,7 +252,7 @@ api_data_get2(clicon_handle h,
}
}
else{
if (xpath_vec(xret, path, &xvec, &xlen) < 0)
if (xpath_vec(xret, "%s", &xvec, &xlen, path) < 0)
goto done;
clicon_debug(1, "%s: xpath:%s xlen:%d", __FUNCTION__, path, xlen);
if (use_xml){

View file

@ -281,7 +281,8 @@ text_setopt(xmldb_handle xh,
else if (strcmp(value,"json")==0)
th->th_format = "json";
else{
clicon_err(OE_PLUGIN, 0, "Option %s unrecognized format: %s", optname, value);
clicon_err(OE_PLUGIN, 0, "Option %s unrecognized format: %s",
optname, (char*)value);
goto done;
}
}
@ -473,7 +474,7 @@ text_get(xmldb_handle xh,
} /* xt == NULL */
/* Here xt looks like: <config>...</config> */
if (xpath_vec(xt, xpath?xpath:"/", &xvec, &xlen) < 0)
if (xpath_vec(xt, "%s", &xvec, &xlen, xpath?xpath:"/") < 0)
goto done;
/* If vectors are specified then mark the nodes found with all ancestors
@ -806,7 +807,8 @@ text_modify_top(cxobj *x0,
x1cname = xml_name(x1c);
/* Get yang spec of the child */
if ((yc = yang_find_topnode(yspec, x1cname, YC_DATANODE)) == NULL){
clicon_err(OE_YANG, ENOENT, "XML node %s/%s has no corresponding yang specification (Invalid XML or wrong Yang spec?", x1, x1cname);
clicon_err(OE_YANG, ENOENT, "XML node %s/%s has no corresponding yang specification (Invalid XML or wrong Yang spec?",
xml_name(x1), x1cname);
goto done;
}
/* See if there is a corresponding node in the base tree */

View file

@ -85,7 +85,11 @@ extern char clicon_err_reason[ERR_STRLEN];
* Prototypes
*/
int clicon_err_reset(void);
#if defined(__GNUC__) && __GNUC__ >= 3
int clicon_err_fn(const char *fn, const int line, int level, int err, char *format, ...) __attribute__ ((format (printf, 5, 6)));
#else
int clicon_err_fn(const char *fn, const int line, int level, int err, char *format, ...);
#endif
char *clicon_strerror(int err);
void *clicon_err_save(void);
int clicon_err_restore(void *handle);

View file

@ -62,10 +62,16 @@ extern int debug;
int clicon_log_init(char *ident, int upto, int flags);
int clicon_get_logflags(void);
int clicon_log_str(int level, char *msg);
#if defined(__GNUC__) && __GNUC__ >= 3
int clicon_log(int level, char *format, ...) __attribute__ ((format (printf, 2, 3)));
int clicon_debug(int dbglevel, char *format, ...) __attribute__ ((format (printf, 2, 3)));
#else
int clicon_log(int level, char *format, ...);
int clicon_debug(int dbglevel, char *format, ...);
#endif
clicon_log_notify_t *clicon_log_register_callback(clicon_log_notify_t *cb, void *arg);
int clicon_debug_init(int dbglevel, FILE *f);
int clicon_debug(int dbglevel, char *format, ...);
char *mon2name(int md);
#endif /* _CLIXON_LOG_H_ */

View file

@ -61,7 +61,11 @@ struct clicon_msg {
char *format_int2str(enum format_enum showas);
enum format_enum format_str2int(char *str);
#if defined(__GNUC__) && __GNUC__ >= 3
struct clicon_msg *clicon_msg_encode(char *format, ...) __attribute__ ((format (printf, 1, 2)));
#else
struct clicon_msg *clicon_msg_encode(char *format, ...);
#endif
int clicon_msg_decode(struct clicon_msg *msg, cxobj **xml);
int clicon_connect_unix(char *sockpath);

View file

@ -39,10 +39,17 @@
/*
* Prototypes
*/
#if defined(__GNUC__) && __GNUC__ >= 3
cxobj *xpath_first(cxobj *cxtop, char *format, ...) __attribute__ ((format (printf, 2, 3)));
int xpath_vec(cxobj *cxtop, char *format, cxobj ***vec, size_t *veclen, ...) __attribute__ ((format (printf, 2, 5)));
int xpath_vec_flag(cxobj *cxtop, char *format, uint16_t flags,
cxobj ***vec, size_t *veclen, ...) __attribute__ ((format (printf, 2, 6)));
#else
cxobj *xpath_first(cxobj *cxtop, char *format, ...);
cxobj *xpath_each(cxobj *xn_top, char *xpath, cxobj *prev);
int xpath_vec(cxobj *cxtop, char *format, cxobj ***vec, size_t *veclen, ...);
int xpath_vec_flag(cxobj *cxtop, char *xpath, uint16_t flags,
cxobj ***vec, size_t *veclen, ...);
#endif
cxobj *xpath_each(cxobj *xn_top, char *xpath, cxobj *prev);
#endif /* _CLIXON_XSL_H */

View file

@ -257,6 +257,7 @@ char *yang_find_myprefix(yang_stmt *ys);
int yang_order(yang_stmt *y);
int yang_print(FILE *f, yang_node *yn);
int yang_print_cbuf(cbuf *cb, yang_node *yn, int marginal);
yang_stmt *yang_parse_file(int fd, const char *name, yang_spec *ysp);
int yang_parse(clicon_handle h, const char *yang_dir,
const char *module, const char *revision, yang_spec *ysp);
int yang_apply(yang_node *yn, enum rfc_6020 key, yang_applyfn_t fn,

View file

@ -45,6 +45,7 @@ sysconfdir = @sysconfdir@
HOST_VENDOR = @host_vendor@
SH_SUFFIX = @SH_SUFFIX@
CLIXON_VERSION = @CLIXON_VERSION@
CLIXON_MAJOR = @CLIXON_VERSION_MAJOR@
CLIXON_MINOR = @CLIXON_VERSION_MINOR@
@ -78,6 +79,14 @@ YACCOBJS := lex.clixon_xml_parse.o clixon_xml_parse.tab.o \
lex.clixon_json_parse.o clixon_json_parse.tab.o
# Extra applications. Utilities, unit testings. Not installed.
APPSRC = clixon_util_xml.c
APPSRC += clixon_util_json.c
APPSRC += clixon_util_yang.c
APPSRC += clixon_util_xsl.c
APPS = $(APPSRC:.c=)
# Generated src
GENSRC = build.c
@ -91,10 +100,10 @@ MYLIB = libclixon$(SH_SUFFIX).$(CLIXON_MAJOR).$(CLIXON_MINOR)
MYLIBSO = libclixon$(SH_SUFFIX).$(CLIXON_MAJOR)
MYLIBLINK = libclixon$(SH_SUFFIX)
all: $(MYLIB) $(MYLIBLINK)
all: $(MYLIB) $(MYLIBLINK) $(APPS)
clean:
rm -f $(OBJS) $(MYLIB) $(MYLIBLINK) $(GENOBJS) $(GENSRC) *.core
rm -f $(OBJS) $(MYLIB) $(APPS) $(MYLIBLINK) $(GENOBJS) $(GENSRC) *.core
rm -f clixon_xml_parse.tab.[ch] clixon_xml_parse.yy.[co]
rm -f clixon_yang_parse.tab.[ch] clixon_yang_parse.[co]
rm -f clixon_json_parse.tab.[ch] clixon_json_parse.[co]
@ -150,6 +159,19 @@ clixon_json_parse.tab.c clixon_json_parse.tab.h: clixon_json_parse.y
lex.clixon_json_parse.o : lex.clixon_json_parse.c clixon_json_parse.tab.h
$(CC) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) -Wno-error -c $<
# APPS
clixon_util_xml: clixon_util_xml.c $(MYLIB)
$(CC) $(INCLUDES) $(CPPFLAGS) @CFLAGS@ $^ $(LIBS) -o $@
clixon_util_json: clixon_util_json.c $(MYLIB)
$(CC) $(INCLUDES) $(CPPFLAGS) @CFLAGS@ $^ $(LIBS) -o $@
clixon_util_yang: clixon_util_yang.c $(MYLIB)
$(CC) $(INCLUDES) $(CPPFLAGS) @CFLAGS@ $^ $(LIBS) -o $@
clixon_util_xsl: clixon_util_xsl.c $(MYLIB)
$(CC) $(INCLUDES) $(CPPFLAGS) @CFLAGS@ $^ $(LIBS) -o $@
distclean: clean
rm -f Makefile *~ .depend
@ -164,7 +186,6 @@ build.c:
date +"const char CLIXON_BUILDSTR[64]=\"%Y.%m.%d %H:%M by `whoami` on `hostname`"\"\; > build.c;
echo "const char CLIXON_VERSION[64]=\"$(CLIXON_VERSION)\""\; >> build.c;
$(MYLIB) : $(GENOBJS) $(OBJS)
ifeq ($(HOST_VENDOR),apple)
$(CC) $(LDFLAGS) -shared -o $@ $(GENOBJS) $(OBJS) $(LIBS) -undefined dynamic_lookup -o $@

View file

@ -135,11 +135,11 @@ clicon_err_reset(void)
* - Set global reason string clicon_err_reason
* @note: err direction (syslog and/or stderr) controlled by clicon_log_init()
*
* @param fn Inline function name (when called from clicon_err() macro)
* @param line Inline file line number (when called from clicon_err() macro)
* @param err Error number, typically errno
* @param suberr Sub-error number
* @param reason Error string, format with argv
* @param[in] fn Inline function name (when called from clicon_err() macro)
* @param[in] line Inline file line number (when called from clicon_err() macro)
* @param[in] err Error number, typically errno
* @param[in] suberr Sub-error number
* @param[in] reason Error string, format with argv
*/
int
clicon_err_fn(const char *fn,

View file

@ -267,7 +267,7 @@ event_poll(int fd)
FD_ZERO(&fdset);
FD_SET(fd, &fdset);
if ((retval = select(FD_SETSIZE, &fdset, NULL, NULL, &tnull)) < 0)
clicon_err(OE_EVENTS, errno, "%s select1: %s", __FUNCTION__, strerror(errno));
clicon_err(OE_EVENTS, errno, "select");
return retval;
}
@ -307,18 +307,18 @@ event_loop(void)
if (n == -1) {
if (errno == EINTR){
clicon_debug(1, "%s select: %s", __FUNCTION__, strerror(errno));
clicon_err(OE_EVENTS, errno, "%s select1: %s", __FUNCTION__, strerror(errno));
clicon_err(OE_EVENTS, errno, "select");
retval = 0;
}
else
clicon_err(OE_EVENTS, errno, "%s select2", __FUNCTION__);
clicon_err(OE_EVENTS, errno, "select");
goto err;
}
if (n==0){ /* Timeout */
e = ee_timers;
ee_timers = ee_timers->e_next;
clicon_debug(2, "%s timeout: %s[%x]",
__FUNCTION__, e->e_string, e->e_arg);
__FUNCTION__, e->e_string, (int)e->e_arg);
if ((*e->e_fn)(0, e->e_arg) < 0){
free(e);
goto err;
@ -332,7 +332,7 @@ event_loop(void)
e_next = e->e_next;
if(e->e_type == EVENT_FD && FD_ISSET(e->e_fd, &fdset)){
clicon_debug(2, "%s: FD_ISSET: %s[%x]",
__FUNCTION__, e->e_string, e->e_arg);
__FUNCTION__, e->e_string, (int)e->e_arg);
if ((*e->e_fn)(e->e_fd, e->e_arg) < 0){
clicon_debug(1, "%s Error in: %s", __FUNCTION__, e->e_string);
goto err;

View file

@ -241,12 +241,11 @@ group_name2gid(char *name,
gr = &g0;
/* This leaks memory in ubuntu */
if (getgrnam_r(name, gr, buf, sizeof(buf), &gtmp) < 0){
clicon_err(OE_UNIX, errno, "%s: getgrnam_r(%s): %s",
__FUNCTION__, name, strerror(errno));
clicon_err(OE_UNIX, errno, "getgrnam_r(%s)", name);
return -1;
}
if (gtmp == NULL){
clicon_err(OE_UNIX, 0, "%s: No such group: %s", __FUNCTION__, name);
clicon_err(OE_UNIX, 0, "No such group: %s", name);
fprintf(stderr, "No such group %s\n", name);
return -1;
}

View file

@ -730,16 +730,14 @@ json_parse_file(int fd,
int len = 0;
if ((jsonbuf = malloc(jsonbuflen)) == NULL){
clicon_err(OE_XML, errno, "%s: malloc", __FUNCTION__);
clicon_err(OE_XML, errno, "malloc");
goto done;
}
memset(jsonbuf, 0, jsonbuflen);
ptr = jsonbuf;
while (1){
if ((ret = read(fd, &ch, 1)) < 0){
clicon_err(OE_XML, errno, "%s: read: [pid:%d]\n",
__FUNCTION__,
(int)getpid());
clicon_err(OE_XML, errno, "read");
break;
}
if (ret != 0)
@ -756,7 +754,7 @@ json_parse_file(int fd,
oldjsonbuflen = jsonbuflen;
jsonbuflen *= 2;
if ((jsonbuf = realloc(jsonbuf, jsonbuflen)) == NULL){
clicon_err(OE_XML, errno, "%s: realloc", __FUNCTION__);
clicon_err(OE_XML, errno, "realloc");
goto done;
}
memset(jsonbuf+oldjsonbuflen, 0, jsonbuflen-oldjsonbuflen);

View file

@ -148,7 +148,7 @@ clicon_option_readfile_xml(clicon_hash_t *copt,
clicon_err(OE_UNIX, errno, "configure file: %s", filename);
return -1;
}
clicon_debug(2, "Reading config file %s", __FUNCTION__, filename);
clicon_debug(2, "%s: Reading config file %s", __FUNCTION__, filename);
fd = fileno(f);
if (xml_parse_file(fd, "</clicon>", yspec, &xt) < 0)
goto done;
@ -290,10 +290,10 @@ clicon_option_str_set(clicon_handle h,
/*! Get options as integer but stored as string
*
* @param h clicon handle
* @param name name of option
* @retval int An integer as aresult of atoi
* @retval -1 If option does not exist
* @param[in] h clicon handle
* @param[in] name name of option
* @retval int An integer as aresult of atoi
* @retval -1 If option does not exist
* @code
* if (clicon_option_exists(h, "X")
* return clicon_option_int(h, "X");
@ -331,10 +331,10 @@ clicon_option_int_set(clicon_handle h,
/*! Get options as bool but stored as string
*
* @param h clicon handle
* @param name name of option
* @retval 0 false, or does not exist, or does not have a boolean value
* @retval 1 true
* @param[in] h clicon handle
* @param[in] name name of option
* @retval 0 false, or does not exist, or does not have a boolean value
* @retval 1 true
* @code
* if (clicon_option_exists(h, "X")
* return clicon_option_bool(h, "X");

View file

@ -192,7 +192,7 @@ plugin_load_one(clicon_handle h,
dlerror(); /* Clear any existing error */
if ((handle = dlopen(file, dlflags)) == NULL) {
error = (char*)dlerror();
clicon_err(OE_PLUGIN, errno, "dlopen: %s\n", error ? error : "Unknown error");
clicon_err(OE_PLUGIN, errno, "dlopen: %s", error ? error : "Unknown error");
goto done;
}
/* call plugin_init() if defined, eg CLIXON_PLUGIN_INIT or CLIXON_BACKEND_INIT */
@ -342,7 +342,7 @@ clixon_plugin_exit(clicon_handle h)
}
if (dlclose(cp->cp_handle) != 0) {
error = (char*)dlerror();
clicon_err(OE_PLUGIN, errno, "dlclose: %s\n", error ? error : "Unknown error");
clicon_err(OE_PLUGIN, errno, "dlclose: %s", error ? error : "Unknown error");
}
}
if (_clixon_plugins){

View file

@ -203,7 +203,7 @@ clicon_connect_unix(char *sockpath)
clicon_debug(2, "%s: connecting to %s", __FUNCTION__, addr.sun_path);
if (connect(s, (struct sockaddr *)&addr, SUN_LEN(&addr)) < 0){
if (errno == EACCES)
clicon_err(OE_CFG, errno, "connecting unix socket: %s.\n"
clicon_err(OE_CFG, errno, "connecting unix socket: %s."
"Client should be member of group $CLICON_SOCK_GROUP: ",
sockpath);
else
@ -273,7 +273,7 @@ msg_dump(struct clicon_msg *msg)
for (i=0; i<ntohl(msg->op_len); i++){
snprintf(buf, sizeof(buf), "%s%02x", buf2, ((char*)msg)[i]&0xff);
if ((i+1)%32==0){
clicon_debug(2, buf);
clicon_debug(2, "%s", buf);
snprintf(buf, sizeof(buf), "%s:", __FUNCTION__);
}
else
@ -282,7 +282,7 @@ msg_dump(struct clicon_msg *msg)
strncpy(buf2, buf, sizeof(buf2));
}
if (i%32)
clicon_debug(2, buf);
clicon_debug(2, "%s", buf);
return 0;
}
@ -302,7 +302,7 @@ clicon_msg_send(int s,
msg_dump(msg);
if (atomicio((ssize_t (*)(int, void *, size_t))write,
s, msg, ntohl(msg->op_len)) < 0){
clicon_err(OE_CFG, errno, "%s", __FUNCTION__);
clicon_err(OE_CFG, errno, "atomicio");
clicon_log(LOG_WARNING, "%s: write: %s len:%u msg:%s", __FUNCTION__,
strerror(errno), ntohs(msg->op_len), msg->op_body);
goto done;
@ -344,7 +344,7 @@ clicon_msg_rcv(int s,
set_signal(SIGINT, atomicio_sig_handler, &oldhandler);
if ((hlen = atomicio(read, s, &hdr, sizeof(hdr))) < 0){
clicon_err(OE_CFG, errno, "%s", __FUNCTION__);
clicon_err(OE_CFG, errno, "atomicio");
goto done;
}
if (hlen == 0){
@ -353,7 +353,7 @@ clicon_msg_rcv(int s,
goto done;
}
if (hlen != sizeof(hdr)){
clicon_err(OE_CFG, errno, "%s: header too short (%d)", __FUNCTION__, hlen);
clicon_err(OE_CFG, errno, "header too short (%d)", hlen);
goto done;
}
mlen = ntohl(hdr.op_len);
@ -365,11 +365,11 @@ clicon_msg_rcv(int s,
}
memcpy(*msg, &hdr, hlen);
if ((len2 = atomicio(read, s, (*msg)->op_body, mlen - sizeof(hdr))) < 0){
clicon_err(OE_CFG, errno, "%s: read", __FUNCTION__);
clicon_err(OE_CFG, errno, "read");
goto done;
}
if (len2 != mlen - sizeof(hdr)){
clicon_err(OE_CFG, errno, "%s: body too short", __FUNCTION__);
clicon_err(OE_CFG, errno, "body too short");
goto done;
}
if (debug > 1)
@ -504,7 +504,7 @@ clicon_rpc(int s,
if (clicon_msg_rcv(s, &reply, &eof) < 0)
goto done;
if (eof){
clicon_err(OE_PROTO, ESHUTDOWN, "%s: Socket unexpected close", __FUNCTION__);
clicon_err(OE_PROTO, ESHUTDOWN, "Socket unexpected close");
close(s);
errno = ESHUTDOWN;
goto done;

102
lib/src/clixon_util_json.c Normal file
View file

@ -0,0 +1,102 @@
/*
*
***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2018 Olof Hagsand and Benny Holmgren
This file is part of CLIXON.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 3 or later (the "GPL"),
in which case the provisions of the GPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of the GPL, and not to allow others to
use your version of this file under the terms of Apache License version 2,
indicate your decision by deleting the provisions above and replace them with
the notice and other provisions required by the GPL. If you do not delete
the provisions above, a recipient may use your version of this file under
the terms of any one of the Apache License version 2 or the GPL.
***** END LICENSE BLOCK *****
* JSON support functions.
* JSON syntax is according to:
* http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
*/
#ifdef HAVE_CONFIG_H
#include "clixon_config.h" /* generated by config & autoconf */
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <fnmatch.h>
#include <stdint.h>
#include <syslog.h>
#include <assert.h>
/* cligen */
#include <cligen/cligen.h>
/* clixon */
#include <clixon/clixon.h>
/*
* Turn this on to get a json parse and pretty print test program
* Usage: xpath
* read json from input
* Example compile:
gcc -g -o json -I. -I../clixon ./clixon_json.c -lclixon -lcligen
* Example run:
echo '{"foo": -23}' | ./json
*/
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;
}
clicon_log_init(__FILE__, LOG_INFO, CLICON_LOG_STDERR);
if (json_parse_file(0, NULL, &xt) < 0)
goto done;
xc = NULL;
while ((xc = xml_child_each(xt, xc, -1)) != NULL)
clicon_xml2cbuf(cb, xc, 0, 0); /* print xml */
fprintf(stdout, "%s", cbuf_get(cb));
done:
if (xt)
xml_free(xt);
if (cb)
cbuf_free(cb);
return 0;
}

107
lib/src/clixon_util_xml.c Normal file
View file

@ -0,0 +1,107 @@
/*
*
***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2018 Olof Hagsand and Benny Holmgren
This file is part of CLIXON.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 3 or later (the "GPL"),
in which case the provisions of the GPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of the GPL, and not to allow others to
use your version of this file under the terms of Apache License version 2,
indicate your decision by deleting the provisions above and replace them with
the notice and other provisions required by the GPL. If you do not delete
the provisions above, a recipient may use your version of this file under
the terms of any one of the Apache License version 2 or the GPL.
***** END LICENSE BLOCK *****
* XML support functions.
* @see https://www.w3.org/TR/2008/REC-xml-20081126
* https://www.w3.org/TR/2009/REC-xml-names-20091208
*/
#ifdef HAVE_CONFIG_H
#include "clixon_config.h" /* generated by config & autoconf */
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <limits.h>
#include <fnmatch.h>
#include <stdint.h>
#include <assert.h>
/* cligen */
#include <cligen/cligen.h>
/* clixon */
#include <clixon/clixon.h>
/*
* 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 "<a><b/></a>" | xml
*/
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, "</config>", NULL, &xt) < 0){
fprintf(stderr, "xml parse error %s\n", clicon_err_reason);
goto done;
}
xc = NULL;
while ((xc = xml_child_each(xt, xc, -1)) != NULL)
clicon_xml2cbuf(cb, xc, 0, 0); /* print xml */
fprintf(stdout, "%s\n", cbuf_get(cb));
#if 0
cbuf_reset(cb);
xmltree2cbuf(cb, xt, 0); /* dump data structures */
fprintf(stderr, "%s\n", cbuf_get(cb));
#endif
done:
if (xt)
xml_free(xt);
if (cb)
cbuf_free(cb);
return 0;
}

141
lib/src/clixon_util_xsl.c Normal file
View file

@ -0,0 +1,141 @@
/*
*
***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2018 Olof Hagsand and Benny Holmgren
This file is part of CLIXON.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 3 or later (the "GPL"),
in which case the provisions of the GPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of the GPL, and not to allow others to
use your version of this file under the terms of Apache License version 2,
indicate your decision by deleting the provisions above and replace them with
the notice and other provisions required by the GPL. If you do not delete
the provisions above, a recipient may use your version of this file under
the terms of any one of the Apache License version 2 or the GPL.
***** END LICENSE BLOCK *****
See https://www.w3.org/TR/xpath/
* Turn this on to get an xpath test program
* Usage: xpath [<xpath>]
* read xpath on first line and xml on rest of lines from input
* Example compile:
gcc -g -o xpath -I. -I../clixon ./clixon_xsl.c -lclixon -lcligen
* Example run:
echo "a\n<a><b/></a>" | xpath
*/
#ifdef HAVE_CONFIG_H
#include "clixon_config.h" /* generated by config & autoconf */
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <limits.h>
#include <fnmatch.h>
#include <stdint.h>
#include <assert.h>
#include <syslog.h>
#include <fcntl.h>
/* cligen */
#include <cligen/cligen.h>
/* clixon */
#include <clixon/clixon.h>
static int
usage(char *argv0)
{
fprintf(stderr, "usage:%s <xpath>.\n\tInput on stdin\n", argv0);
exit(0);
}
int
main(int argc, char **argv)
{
int retval = -1;
int i;
cxobj **xv;
cxobj *x;
cxobj *xn;
size_t xlen = 0;
int c;
int len;
char *buf = NULL;
int ret;
if (argc != 1){
usage(argv[0]);
return -1;
}
/* First read xpath */
len = 1024; /* any number is fine */
if ((buf = malloc(len)) == NULL){
perror("pt_file malloc");
return -1;
}
memset(buf, 0, len);
i = 0;
while (1){
if ((ret = read(0, &c, 1)) < 0){
perror("read");
goto done;
}
if (ret == 0)
break;
if (c == '\n')
break;
if (len==i){
if ((buf = realloc(buf, 2*len)) == NULL){
fprintf(stderr, "%s: realloc: %s\n", __FUNCTION__, strerror(errno));
return -1;
}
memset(buf+len, 0, len);
len *= 2;
}
buf[i++] = (char)(c&0xff);
}
x = NULL;
if (xml_parse_file(0, "</clicon>", NULL, &x) < 0){
fprintf(stderr, "Error: parsing: %s\n", clicon_err_reason);
return -1;
}
if (xpath_vec(x, "%s", &xv, &xlen, buf) < 0)
return -1;
if (xv){
for (i=0; i<xlen; i++){
xn = xv[i];
fprintf(stdout, "%d:", i);
clicon_xml2file(stdout, xn, 0, 0);
fprintf(stdout, "\n");
}
free(xv);
}
retval = 0;
done:
if (x)
xml_free(x);
return retval;
}

View file

@ -0,0 +1,93 @@
/*
*
***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2018 Olof Hagsand and Benny Holmgren
This file is part of CLIXON.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 3 or later (the "GPL"),
in which case the provisions of the GPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of the GPL, and not to allow others to
use your version of this file under the terms of Apache License version 2,
indicate your decision by deleting the provisions above and replace them with
the notice and other provisions required by the GPL. If you do not delete
the provisions above, a recipient may use your version of this file under
the terms of any one of the Apache License version 2 or the GPL.
***** END LICENSE BLOCK *****
*/
#ifdef HAVE_CONFIG_H
#include "clixon_config.h" /* generated by config & autoconf */
#endif
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#include <ctype.h>
#define __USE_GNU /* strverscmp */
#include <string.h>
#include <arpa/inet.h>
#include <regex.h>
#include <dirent.h>
#include <syslog.h>
#include <assert.h>
#include <sys/stat.h>
#include <libgen.h>
#include <netinet/in.h>
/* cligen */
#include <cligen/cligen.h>
/* clixon */
#include <clixon/clixon.h>
/*
*/
static int
usage(char *argv0)
{
fprintf(stderr, "usage:%s.\n\tInput on stdin\n", argv0);
exit(0);
}
int
main(int argc, char **argv)
{
yang_spec *yspec = NULL;
if (argc != 1){
usage(argv[0]);
return -1;
}
if ((yspec = yspec_new()) == NULL)
goto done;
if (yang_parse_file(0, "yang test", yspec) < 0){
fprintf(stderr, "xml parse error %s\n", clicon_err_reason);
return -1;
}
yang_print(stdout, (yang_node*)yspec);
done:
if (yspec)
yspec_free(yspec);
return 0;
}

View file

@ -1391,7 +1391,7 @@ xml_parse_file(int fd,
ptr = xmlbuf;
while (1){
if ((ret = read(fd, &ch, 1)) < 0){
clicon_err(OE_XML, errno, "read: [pid:%d]\n",
clicon_err(OE_XML, errno, "read: [pid:%d]",
(int)getpid());
break;
}
@ -1806,7 +1806,7 @@ xml_body_parse(cxobj *xb,
goto done;
}
if (cvret == 0){ /* parsing failed */
clicon_err(OE_XML, errno, "Parsing CV: %s", &reason);
clicon_err(OE_XML, errno, "Parsing CV: %s", reason);
if (reason)
free(reason);
}
@ -1939,7 +1939,7 @@ xml_operation2str(enum operation_type op)
* Example run:
echo "<a><b/></a>" | xml
*/
#if 0 /* Test program */
#if 1 /* Test program */
static int
usage(char *argv0)

View file

@ -87,7 +87,7 @@ xmldb_plugin_load(clicon_handle h,
dlerror(); /* Clear any existing error */
if ((handle = dlopen(filename, RTLD_NOW|RTLD_GLOBAL)) == NULL) {
error = (char*)dlerror();
clicon_err(OE_PLUGIN, errno, "dlopen: %s\n", error ? error : "Unknown error");
clicon_err(OE_PLUGIN, errno, "dlopen: %s", error ? error : "Unknown error");
goto done;
}
/* Try v1 */
@ -162,7 +162,7 @@ xmldb_plugin_unload(clicon_handle h)
dlerror(); /* Clear any existing error */
if (dlclose(handle) != 0) {
error = (char*)dlerror();
clicon_err(OE_PLUGIN, errno, "dlclose: %s\n", error ? error : "Unknown error");
clicon_err(OE_PLUGIN, errno, "dlclose: %s", error ? error : "Unknown error");
/* Just report no -1 return*/
}
retval = 0;

View file

@ -249,7 +249,7 @@ validate_leafref(cxobj *xt,
clicon_err(OE_DB, 0, "Leafref %s requires path statement", ytype->ys_argument);
goto done;
}
if (xpath_vec(xt, ypath->ys_argument, &xvec, &xlen) < 0)
if (xpath_vec(xt, "%s", &xvec, &xlen, ypath->ys_argument) < 0)
goto done;
for (i = 0; i < xlen; i++) {
x = xvec[i];

View file

@ -116,7 +116,7 @@ int clixon_xml_parsewrap(void)
<AMPERSAND>"lt; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = "<"; return CHARDATA;}
<AMPERSAND>"gt; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = ">"; return CHARDATA;}
<AMPERSAND>"apos; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = "'"; return CHARDATA;}
<AMPERSAND>"aquot; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = "'"; return CHARDATA;}
<AMPERSAND>"quot; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = "\""; return CHARDATA;}
<CDATA>. { clixon_xml_parselval.string = yytext; return CHARDATA;}
<CDATA>\n { clixon_xml_parselval.string = yytext;_YA->ya_linenum++; return (CHARDATA);}

View file

@ -205,7 +205,7 @@ xpath_parse_predicate(struct xpath_element *xe,
}
memset(xp, 0, sizeof(*xp));
if ((xp->xp_expr = strdup(s)) == NULL){
clicon_err(OE_XML, errno, "%s: strdup", __FUNCTION__);
clicon_err(OE_XML, errno, "strdup");
goto done;
}
xp->xp_next = xe->xe_predicate;
@ -236,7 +236,7 @@ xpath_element_new(enum axis_type atype,
xe->xe_type = atype;
if (str){
if ((str1 = strdup(str)) == NULL){
clicon_err(OE_XML, errno, "%s: strdup", __FUNCTION__);
clicon_err(OE_XML, errno, "strdup");
goto done;
}
if (xpath_split(str1, &pred) < 0) /* Can be more predicates */
@ -247,20 +247,20 @@ xpath_element_new(enum axis_type atype,
*local = '\0';
local++;
if ((xe->xe_prefix = strdup(str1)) == NULL){
clicon_err(OE_XML, errno, "%s: strdup", __FUNCTION__);
clicon_err(OE_XML, errno, "strdup");
goto done;
}
}
else
local = str1;
if ((xe->xe_str = strdup(local)) == NULL){
clicon_err(OE_XML, errno, "%s: strdup", __FUNCTION__);
clicon_err(OE_XML, errno, "strdup");
goto done;
}
}
else{
if ((xe->xe_str = strdup("*")) == NULL){
clicon_err(OE_XML, errno, "%s: strdup", __FUNCTION__);
clicon_err(OE_XML, errno, "strdup");
goto done;
}
}
@ -326,7 +326,7 @@ xpath_parse(char *xpath,
int esc = 0;
if ((s0 = strdup(xpath)) == NULL){
clicon_err(OE_XML, errno, "%s: strdup", __FUNCTION__);
clicon_err(OE_XML, errno, "strdup");
goto done;
}
s = s0;
@ -502,8 +502,7 @@ xpath_expr(cxobj *xcur,
e_v=e;
e_a = strsep(&e_v, "=");
if (e_a == NULL){
clicon_err(OE_XML, errno, "%s: malformed expression: [@%s]",
__FUNCTION__, e);
clicon_err(OE_XML, errno, "malformed expression: [@%s]", e);
goto done;
}
for (i=0; i<*vec0len; i++){
@ -534,15 +533,13 @@ xpath_expr(cxobj *xcur,
}
}
else{
clicon_err(OE_XML, errno, "%s: malformed expression: [%s]",
__FUNCTION__, e);
clicon_err(OE_XML, errno, "malformed expression: [%s]", e);
goto done;
}
}
else{ /* name = expr */
if ((tag = strsep(&e, "=")) == NULL){
clicon_err(OE_XML, errno, "%s: malformed expression: [%s]",
__FUNCTION__, e);
clicon_err(OE_XML, errno, "malformed expression: [%s]", e);
goto done;
}
/* Strip trailing spaces */
@ -782,7 +779,7 @@ xpath_split(char *xpathstr,
}
}
if (pe==NULL){
clicon_err(OE_XML, errno, "%s: mismatched []: %s", __FUNCTION__, xpathstr);
clicon_err(OE_XML, errno, "mismatched []: %s", xpathstr);
goto done;
}
}
@ -859,7 +856,7 @@ xpath_choice(cxobj *xcur,
size_t vec0len = 0;
if ((s0 = strdup(xpath0)) == NULL){
clicon_err(OE_XML, errno, "%s: strdup", __FUNCTION__);
clicon_err(OE_XML, errno, "strdup");
goto done;
}
s2 = s1 = s0;

View file

@ -45,11 +45,14 @@
#include <errno.h>
#include <limits.h>
#include <ctype.h>
#include <unistd.h>
#define __USE_GNU /* strverscmp */
#include <string.h>
#include <arpa/inet.h>
#include <regex.h>
#include <dirent.h>
#include <sys/types.h>
#include <fcntl.h>
#include <syslog.h>
#include <assert.h>
#include <sys/stat.h>
@ -74,6 +77,8 @@
#include "clixon_yang_type.h"
#include "clixon_yang_parse.h"
/* Size of json read buffer when reading from file*/
#define BUFLEN 1024
/* Mapping between yang keyword string <--> clicon constants */
static const map_str2int ykmap[] = {
@ -158,7 +163,7 @@ yspec_new(void)
yang_spec *yspec;
if ((yspec = malloc(sizeof(*yspec))) == NULL){
clicon_err(OE_YANG, errno, "%s: malloc", __FUNCTION__);
clicon_err(OE_YANG, errno, "malloc");
return NULL;
}
memset(yspec, 0, sizeof(*yspec));
@ -176,7 +181,7 @@ ys_new(enum rfc_6020 keyw)
yang_stmt *ys;
if ((ys = malloc(sizeof(*ys))) == NULL){
clicon_err(OE_YANG, errno, "%s: malloc", __FUNCTION__);
clicon_err(OE_YANG, errno, "malloc");
return NULL;
}
memset(ys, 0, sizeof(*ys));
@ -184,7 +189,7 @@ ys_new(enum rfc_6020 keyw)
/* The cvec contains stmt-specific variables. Only few stmts need variables so the
cvec could be lazily created to save some heap and cycles. */
if ((ys->ys_cvec = cvec_new(0)) == NULL){
clicon_err(OE_YANG, errno, "%s: cvec_new", __FUNCTION__);
clicon_err(OE_YANG, errno, "cvec_new");
return NULL;
}
return ys;
@ -247,7 +252,7 @@ yn_realloc(yang_node *yn)
yn->yn_len++;
if ((yn->yn_stmt = realloc(yn->yn_stmt, (yn->yn_len)*sizeof(yang_stmt *))) == 0){
clicon_err(OE_YANG, errno, "%s: realloc", __FUNCTION__);
clicon_err(OE_YANG, errno, "realloc");
return -1;
}
yn->yn_stmt[yn->yn_len - 1] = NULL; /* init field */
@ -276,22 +281,22 @@ ys_cp(yang_stmt *ynew,
ynew->ys_parent = NULL;
if (yold->ys_stmt)
if ((ynew->ys_stmt = calloc(yold->ys_len, sizeof(yang_stmt *))) == NULL){
clicon_err(OE_YANG, errno, "%s: calloc", __FUNCTION__);
clicon_err(OE_YANG, errno, "calloc");
goto done;
}
if (yold->ys_argument)
if ((ynew->ys_argument = strdup(yold->ys_argument)) == NULL){
clicon_err(OE_YANG, errno, "%s: strdup", __FUNCTION__);
clicon_err(OE_YANG, errno, "strdup");
goto done;
}
if (yold->ys_cv)
if ((ynew->ys_cv = cv_dup(yold->ys_cv)) == NULL){
clicon_err(OE_YANG, errno, "%s: cv_dup", __FUNCTION__);
clicon_err(OE_YANG, errno, "cv_dup");
goto done;
}
if (yold->ys_cvec)
if ((ynew->ys_cvec = cvec_dup(yold->ys_cvec)) == NULL){
clicon_err(OE_YANG, errno, "%s: cvec_dup", __FUNCTION__);
clicon_err(OE_YANG, errno, "cvec_dup");
goto done;
}
if (yold->ys_typecache){
@ -902,7 +907,7 @@ yang_print(FILE *f,
cbuf *cb = NULL;
if ((cb = cbuf_new()) == NULL){
clicon_err(OE_YANG, errno, "%s: cbuf_new", __FUNCTION__);
clicon_err(OE_YANG, errno, "cbuf_new");
goto done;
}
if (yang_print_cbuf(cb, yn, 0) < 0)
@ -998,14 +1003,14 @@ ys_populate_leaf(yang_stmt *ys,
goto done;
/* 2. Create the CV using cvtype and name it */
if ((cv = cv_new(cvtype)) == NULL){
clicon_err(OE_YANG, errno, "%s: cv_new", __FUNCTION__);
clicon_err(OE_YANG, errno, "cv_new");
goto done;
}
if (options & YANG_OPTIONS_FRACTION_DIGITS && cvtype == CGV_DEC64) /* XXX: Seems misplaced? / too specific */
cv_dec64_n_set(cv, fraction_digits);
if (cv_name_set(cv, ys->ys_argument) == NULL){
clicon_err(OE_YANG, errno, "%s: cv_new_set", __FUNCTION__);
clicon_err(OE_YANG, errno, "cv_new_set");
goto done;
}
/* 3. Check if default value. Here we parse the string in the default-stmt
@ -1083,7 +1088,7 @@ ys_populate_range(yang_stmt *ys,
yparent = ys->ys_parent; /* Find parent: type */
if (yparent->yn_keyword != Y_TYPE){
clicon_err(OE_YANG, 0, "%s: parent should be type", __FUNCTION__);
clicon_err(OE_YANG, 0, "parent should be type");
goto done;
}
if (yang_type_resolve(ys, (yang_stmt*)yparent, &yrestype,
@ -1103,7 +1108,8 @@ ys_populate_range(yang_stmt *ys,
}
if ((maxstr = strstr(minstr, "..")) != NULL){
if (strlen(maxstr) < 2){
clicon_err(OE_YANG, 0, "range statement: %s not on the form: <int>..<int>");
clicon_err(OE_YANG, 0, "range statement: %s not on the form: <int>..<int>",
ys->ys_argument);
goto done;
}
minstr[maxstr-minstr] = '\0';
@ -1499,7 +1505,7 @@ yang_expand(yang_node *yn)
size = (yn->yn_len - i - 1)*sizeof(struct yang_stmt *);
yn->yn_len += glen - 1;
if (glen && (yn->yn_stmt = realloc(yn->yn_stmt, (yn->yn_len)*sizeof(yang_stmt *))) == 0){
clicon_err(OE_YANG, errno, "%s: realloc", __FUNCTION__);
clicon_err(OE_YANG, errno, "realloc");
return -1;
}
/* Then move all existing elements up from i+1 (not uses-stmt) */
@ -1540,10 +1546,10 @@ yang_expand(yang_node *yn)
* Syntax parsing. A string is input and a syntax-tree is returned (or error).
* A variable record is also returned containing a list of (global) variable values.
* (cloned from cligen)
* @param h CLICON handle
* @param str String of yang statements
* @param name Log string, typically filename
* @param ysp Yang specification. Should ave been created by caller using yspec_new
* @param[in] h CLICON handle
* @param[in] str String of yang statements
* @param[in] name Log string, typically filename
* @param[in] ysp Yang specification. Should ave been created by caller using yspec_new
* @retval ymod Top-level yang (sub)module
* @retval NULL Error encountered
* Calling order:
@ -1554,15 +1560,17 @@ yang_expand(yang_node *yn)
* clixon_yang_parseparse # Actual yang parsing using yacc
*/
static yang_stmt *
yang_parse_str(clicon_handle h,
char *str,
yang_parse_str(char *str,
const char *name, /* just for errs */
yang_spec *yspec)
{
struct clicon_yang_yacc_arg yy = {0,};
yang_stmt *ymod = NULL;
yy.yy_handle = h;
if (yspec == NULL){
clicon_err(OE_YANG, 0, "Yang parse need top level yang spec");
goto done;
}
yy.yy_name = (char*)name;
yy.yy_linenum = 1;
yy.yy_parse_string = str;
@ -1595,15 +1603,66 @@ yang_parse_str(clicon_handle h,
return ymod; /* top-level (sub)module */
}
/*! Read an opened file into a string and call yang string parsing
/*! Parse yang spec from an open file descriptor
* @param[in] fd File descriptor containing the YANG file as ASCII characters
* @param[in] name For debug, eg filename
* @param[in] ysp Yang specification. Should ave been created by caller using yspec_new
* @retval ymod Top-level yang (sub)module
* @retval NULL Error
*/
yang_stmt *
yang_parse_file(int fd,
const char *name,
yang_spec *ysp)
{
char *buf = NULL;
int i;
int c;
int len;
yang_stmt *ymod = NULL;
int ret;
len = BUFLEN; /* any number is fine */
if ((buf = malloc(len)) == NULL){
perror("pt_file malloc");
return NULL;
}
memset(buf, 0, len);
i = 0; /* position in buf */
while (1){ /* read the whole file */
if ((ret = read(fd, &c, 1)) < 0){
clicon_err(OE_XML, errno, "read");
break;
}
if (ret == 0)
break; /* eof */
if (len==i){
if ((buf = realloc(buf, 2*len)) == NULL){
clicon_err(OE_XML, errno, "realloc");
goto done;
}
memset(buf+len, 0, len);
len *= 2;
}
buf[i++] = (char)(c&0xff);
} /* read a line */
if ((ymod = yang_parse_str(buf, name, ysp)) < 0)
goto done;
done:
if (buf)
free(buf);
return ymod; /* top-level (sub)module */
}
/*! Open a file, read into a string and invoke yang parsing
*
* Similar to clicon_yang_str(), just read a file first
* (cloned from cligen)
* @param h CLICON handle
* @param filename Name of file
* @param ysp Yang specification. Should ave been created by caller using yspec_new
* @retval ymod Top-level yang (sub)module
* @retval NULL Error encountered
* @param[in] h CLICON handle
* @param[in] filename Name of file
* @param[in] ysp Yang specification. Should ave been created by caller using yspec_new
* @retval ymod Top-level yang (sub)module
* @retval NULL Error encountered
* The database symbols are inserted in alphabetical order.
* Calling order:
@ -1614,57 +1673,27 @@ yang_parse_str(clicon_handle h,
* clixon_yang_parseparse # Actual yang parsing using yacc
*/
static yang_stmt *
yang_parse_file(clicon_handle h,
const char *filename,
yang_spec *ysp
)
yang_parse_filename(const char *filename,
yang_spec *ysp)
{
char *buf = NULL;
int i;
int c;
int len;
yang_stmt *ymod = NULL;
FILE *f = NULL;
struct stat st;
int fd = -1;
struct stat st;
clicon_log(LOG_DEBUG, "Parsing yang file: %s", filename);
if (stat(filename, &st) < 0){
clicon_err(OE_YANG, errno, "%s not found", filename);
goto done;
}
if ((f = fopen(filename, "r")) == NULL){
clicon_err(OE_UNIX, errno, "fopen(%s)", filename);
if ((fd = open(filename, O_RDONLY)) < 0){
clicon_err(OE_YANG, errno, "open(%s)", filename);
goto done;
}
len = 1024; /* any number is fine */
if ((buf = malloc(len)) == NULL){
perror("pt_file malloc");
return NULL;
}
memset(buf, 0, len);
i = 0; /* position in buf */
while (1){ /* read the whole file */
if ((c = fgetc(f)) == EOF)
break;
if (len==i){
if ((buf = realloc(buf, 2*len)) == NULL){
fprintf(stderr, "%s: realloc: %s\n", __FUNCTION__, strerror(errno));
goto done;
}
memset(buf+len, 0, len);
len *= 2;
}
buf[i++] = (char)(c&0xff);
} /* read a line */
if ((ymod = yang_parse_str(h, buf, filename, ysp)) < 0)
if ((ymod = yang_parse_file(fd, filename, ysp)) < 0)
goto done;
done:
if (f)
fclose(f);
if (buf)
free(buf);
if (fd != -1)
close(fd);
return ymod; /* top-level (sub)module */
}
@ -1679,8 +1708,7 @@ yang_parse_file(clicon_handle h,
* @retval -1 Error
*/
static int
yang_parse_find_match(clicon_handle h,
const char *yang_dir,
yang_parse_find_match(const char *yang_dir,
const char *module,
cbuf *fbuf)
{
@ -1724,7 +1752,7 @@ yang_parse_find_match(clicon_handle h,
* @param[in] h CLICON handle
* @param[in] yang_dir Directory where all YANG module files reside
* @param[in] module Name of main YANG module. Or absolute file name.
* @param[in] revision Optional module revision date
* @param[in] revision Module revision date or NULL
* @param[in] ysp Yang specification. Should have been created by caller using yspec_new
* @retval ymod Top-level yang (sub)module
* @retval NULL Error encountered
@ -1737,8 +1765,7 @@ yang_parse_find_match(clicon_handle h,
* clixon_yang_parseparse # Actual yang parsing using yacc
*/
static yang_stmt *
yang_parse_recurse(clicon_handle h,
const char *yang_dir,
yang_parse_recurse(const char *yang_dir,
const char *module,
const char *revision,
yang_spec *ysp)
@ -1752,26 +1779,26 @@ yang_parse_recurse(clicon_handle h,
int nr;
if (module[0] == '/'){
if ((ymod = yang_parse_file(h, module, ysp)) == NULL)
if ((ymod = yang_parse_filename(module, ysp)) == NULL)
goto done;
}
else {
if ((fbuf = cbuf_new()) == NULL){
clicon_err(OE_YANG, errno, "%s: cbuf_new", __FUNCTION__);
clicon_err(OE_YANG, errno, "cbuf_new");
goto done;
}
if (revision)
cprintf(fbuf, "%s/%s@%s.yang", yang_dir, module, revision);
else{
/* No specific revision, Match a yang file */
if ((nr = yang_parse_find_match(h, yang_dir, module, fbuf)) < 0)
if ((nr = yang_parse_find_match(yang_dir, module, fbuf)) < 0)
goto done;
if (nr == 0){
clicon_err(OE_YANG, errno, "No matching %s yang files found (expected module name or absolute filename)", module);
goto done;
}
}
if ((ymod = yang_parse_file(h, cbuf_get(fbuf), ysp)) == NULL)
if ((ymod = yang_parse_filename(cbuf_get(fbuf), ysp)) == NULL)
goto done;
}
@ -1786,7 +1813,7 @@ yang_parse_recurse(clicon_handle h,
subrevision = NULL;
if (yang_find((yang_node*)ysp, Y_MODULE, modname) == NULL)
/* recursive call */
if (yang_parse_recurse(h, yang_dir, modname, subrevision, ysp) == NULL){
if (yang_parse_recurse(yang_dir, modname, subrevision, ysp) == NULL){
ymod = NULL;
goto done;
}
@ -1845,7 +1872,7 @@ ys_schemanode_check(yang_stmt *ys,
* @param[in] h CLICON handle
* @param[in] yang_dir Directory where all YANG module files reside (except mainfile)
* @param[in] mainmod Name of main YANG module. Or absolute file name.
* @param[in] revision Optional main module revision date.
* @param[in] revision Main module revision date string or NULL
* @param[out] ysp Yang specification. Should ave been created by caller using yspec_new
* @retval 0 Everything OK
* @retval -1 Error encountered
@ -1854,7 +1881,8 @@ ys_schemanode_check(yang_stmt *ys,
* @note if mainmod is filename, revision is not considered.
* Calling order:
* yang_parse # Parse top-level yang module. Expand and populate yang tree
* yang_parse_recurse # Parse one yang module, go through its (sub)modules, parse them and then recursively parse them
* yang_parse_recurse # Parse one yang module, go through its (sub)modules,
* parse them and then recursively parse them
* yang_parse_file # Read yang file into a string
* yang_parse_str # Set up yacc parser and call it given a string
* clixon_yang_parseparse # Actual yang parsing using yacc
@ -1870,7 +1898,7 @@ yang_parse(clicon_handle h,
yang_stmt *ymod; /* Top-level yang (sub)module */
/* Step 1: parse from text to yang parse-tree. */
if ((ymod = yang_parse_recurse(h, yang_dir, mainmodule, revision, ysp)) == NULL)
if ((ymod = yang_parse_recurse(yang_dir, mainmodule, revision, ysp)) == NULL)
goto done;
/* Add top module name as dbspec-name */
clicon_dbspec_name_set(h, ymod->ys_argument);
@ -2080,13 +2108,13 @@ yang_abs_schema_nodeid(yang_spec *yspec,
goto done;
}
if ((vec = clicon_strsep(schema_nodeid, "/", &nvec)) == NULL){
clicon_err(OE_YANG, errno, "%s: strsep", __FUNCTION__);
clicon_err(OE_YANG, errno, "strsep");
goto done;
}
/* Assume schema nodeid looks like: "/prefix:id[/prefix:id]*" */
if (nvec < 2){
clicon_err(OE_YANG, 0, "%s: NULL or truncated path: %s",
__FUNCTION__, schema_nodeid);
clicon_err(OE_YANG, 0, "NULL or truncated path: %s",
schema_nodeid);
goto done;
}
/* split <prefix>:<id> */
@ -2095,7 +2123,7 @@ yang_abs_schema_nodeid(yang_spec *yspec,
goto ok;
}
if ((prefix = strdup(vec[1])) == NULL){
clicon_err(OE_UNIX, errno, "%s: strdup", __FUNCTION__);
clicon_err(OE_UNIX, errno, "strdup");
goto done;
}
prefix[id-vec[1]] = '\0';
@ -2183,7 +2211,7 @@ ys_parse(yang_stmt *ys,
assert(ys->ys_cv == NULL); /* Cv:s are parsed in different places, difficult to separate */
if ((ys->ys_cv = cv_new(cvtype)) == NULL){
clicon_err(OE_YANG, errno, "%s: cv_new", __FUNCTION__);
clicon_err(OE_YANG, errno, "cv_new");
goto done;
}
if ((cvret = cv_parse1(ys->ys_argument, ys->ys_cv, &reason)) < 0){ /* error */
@ -2252,7 +2280,7 @@ ys_parse_sub(yang_stmt *ys,
goto done;
}
if ((ys->ys_cv = cv_new(CGV_STRING)) == NULL){
clicon_err(OE_YANG, errno, "%s: cv_new", __FUNCTION__);
clicon_err(OE_YANG, errno, "cv_new");
goto done;
}
if ((cvret = cv_parse1(extra, ys->ys_cv, &reason)) < 0){ /* error */
@ -2334,9 +2362,9 @@ yang_spec_netconf(clicon_handle h)
}
/*! Read, parse and save application yang specification as option
* @param h clicon handle
* @param f file to print to (if printspec enabled)
* @param printspec print database (YANG) specification as read from file
* @param[in] h clicon handle
* @param[in] f file to print to (if printspec enabled)
* @param[in] printspec print database (YANG) specification as read from file
*/
yang_spec*
yang_spec_main(clicon_handle h)
@ -2346,7 +2374,7 @@ yang_spec_main(clicon_handle h)
char *yang_module;
char *yang_revision;
if ((yang_dir = clicon_yang_dir(h)) == NULL){
if ((yang_dir = clicon_yang_dir(h)) == NULL){
clicon_err(OE_FATAL, 0, "CLICON_YANG_DIR option not set");
goto done;
}

View file

@ -51,7 +51,6 @@ struct ys_stack{
};
struct clicon_yang_yacc_arg{ /* XXX: mostly unrelevant */
clicon_handle yy_handle; /* cligen_handle */
char *yy_name; /* Name of syntax (for error string) */
int yy_linenum; /* Number of \n in parsed buffer */
char *yy_parse_string; /* original (copy of) parse string */

View file

@ -260,7 +260,7 @@ ysp_add(struct clicon_yang_yacc_arg *yy,
clicon_err(OE_YANG, errno, "No stack");
goto err;
}
yn = ystack->ys_node;
assert(yn = ystack->ys_node);
if ((ys = ys_new(keyword)) == NULL)
goto err;
/* NOTE: does not make a copy of string, ie argument is 'consumed' here */

View file

@ -41,6 +41,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
#include <ctype.h>
#define __USE_GNU /* strverscmp */
@ -354,7 +355,7 @@ clicon_type2cv(char *origtype,
if (restype != NULL){
yang2cv_type(restype, cvtype);
if (*cvtype == CGV_ERR){
clicon_err(OE_DB, 0, "%s: \"%s\" type not translated", __FUNCTION__, restype);
clicon_err(OE_DB, 0, "\"%s\" type not translated", restype);
goto done;
}
}
@ -365,7 +366,7 @@ clicon_type2cv(char *origtype,
*/
yang2cv_type(origtype, cvtype);
if (*cvtype == CGV_ERR){
clicon_err(OE_DB, 0, "%s: \"%s\": type not resolved", __FUNCTION__, origtype);
clicon_err(OE_DB, 0, "\"%s\": type not resolved", origtype);
goto done;
}
}
@ -399,8 +400,8 @@ cv_validate1(cg_var *cv,
int retval = 1; /* OK */
int retval2;
yang_stmt *yi = NULL;
uint64_t u = 0;
int64_t i = 0;
unsigned int u = 0;
int i = 0;
char *str;
int found;
char **vec = NULL;
@ -417,7 +418,7 @@ cv_validate1(cg_var *cv,
i = cv_int8_get(cv);
if (range_check(i, range_min, range_max, int8)){
if (reason)
*reason = cligen_reason("Number out of range: %ld", i);
*reason = cligen_reason("Number out of range: %d", i);
retval = 0;
break;
}
@ -428,7 +429,7 @@ cv_validate1(cg_var *cv,
i = cv_int16_get(cv);
if (range_check(i, range_min, range_max, int16)){
if (reason)
*reason = cligen_reason("Number out of range: %ld", i);
*reason = cligen_reason("Number out of range: %d", i);
retval = 0;
break;
}
@ -439,29 +440,31 @@ cv_validate1(cg_var *cv,
i = cv_int32_get(cv);
if (range_check(i, range_min, range_max, int32)){
if (reason)
*reason = cligen_reason("Number out of range: %ld", i);
*reason = cligen_reason("Number out of range: %d", i);
retval = 0;
break;
}
}
break;
case CGV_INT64:
case CGV_INT64:{
int64_t i64;
if ((options & YANG_OPTIONS_RANGE) != 0){
i = cv_int64_get(cv);
i64 = cv_int64_get(cv);
if (range_check(i, range_min, range_max, int64)){
if (reason)
*reason = cligen_reason("Number out of range: %ld", i);
*reason = cligen_reason("Number out of range: %" PRId64, i64);
retval = 0;
break;
}
}
break;
}
case CGV_UINT8:
if ((options & YANG_OPTIONS_RANGE) != 0){
u = cv_uint8_get(cv);
if (range_check(u, range_min, range_max, uint8)){
if (reason)
*reason = cligen_reason("Number out of range: %lu", u);
*reason = cligen_reason("Number out of range: %u", u);
retval = 0;
break;
}
@ -472,7 +475,7 @@ cv_validate1(cg_var *cv,
u = cv_uint16_get(cv);
if (range_check(u, range_min, range_max, uint16)){
if (reason)
*reason = cligen_reason("Number out of range: %lu", u);
*reason = cligen_reason("Number out of range: %u", u);
retval = 0;
break;
}
@ -483,29 +486,31 @@ cv_validate1(cg_var *cv,
u = cv_uint32_get(cv);
if (range_check(u, range_min, range_max, uint32)){
if (reason)
*reason = cligen_reason("Number out of range: %lu", u);
*reason = cligen_reason("Number out of range: %u", u);
retval = 0;
break;
}
}
break;
case CGV_UINT64:
case CGV_UINT64:{
uint64_t u64;
if ((options & YANG_OPTIONS_RANGE) != 0){
u = cv_uint64_get(cv);
u64 = cv_uint64_get(cv);
if (range_check(u, range_min, range_max, uint64)){
if (reason)
*reason = cligen_reason("Number out of range: %lu", u);
*reason = cligen_reason("Number out of range: %" PRIu64, u64);
retval = 0;
break;
}
}
break;
}
case CGV_DEC64:
if ((options & YANG_OPTIONS_RANGE) != 0){
i = cv_int64_get(cv);
if (range_check(i, range_min, range_max, int64)){
if (reason)
*reason = cligen_reason("Number out of range: %ld", i);
*reason = cligen_reason("Number out of range: %d", i);
retval = 0;
break;
}
@ -565,7 +570,7 @@ cv_validate1(cg_var *cv,
u = strlen(str);
if (range_check(u, range_min, range_max, uint64)){
if (reason)
*reason = cligen_reason("string length out of range: %lu", u);
*reason = cligen_reason("string length out of range: %u", u);
retval = 0;
break;
}
@ -748,8 +753,8 @@ ys_cv_validate(cg_var *cv,
if (cvtype == CGV_STRING && cv_type_get(ycv) == CGV_REST)
;
else {
clicon_err(OE_DB, 0, "%s: Type mismatch data:%s != yang:%s",
__FUNCTION__, cv_type2str(cvtype), cv_type2str(cv_type_get(ycv)));
clicon_err(OE_DB, 0, "Type mismatch data:%s != yang:%s",
cv_type2str(cvtype), cv_type2str(cv_type_get(ycv)));
goto done;
}
}
@ -904,14 +909,14 @@ resolve_restrictions(yang_stmt *yrange,
}
/*! Recursively resolve a yang type to built-in type with optional restrictions
* @param [in] ys yang-stmt from where the current search is based
* @param [in] ytype yang-stmt object containing currently resolving type
* @param [out] yrestype resolved type. return built-in type or NULL. mandatory
* @param [out] options pointer to flags field of optional values. optional
* @param [out] mincv pointer to cv with min range or length. If options&YANG_OPTIONS_RANGE
* @param [out] maxcv pointer to cv with max range or length. If options&YANG_OPTIONS_RANGE
* @param [out] pattern pointer to static string of yang string pattern. optional
* @param [out] fraction for decimal64, how many digits after period
* @param[in] ys yang-stmt from where the current search is based
* @param[in] ytype yang-stmt object containing currently resolving type
* @param[out] yrestype resolved type. return built-in type or NULL. mandatory
* @param[out] options pointer to flags field of optional values. optional
* @param[out] mincv pointer to cv with min range or length. If options&YANG_OPTIONS_RANGE
* @param[out] maxcv pointer to cv with max range or length. If options&YANG_OPTIONS_RANGE
* @param[out] pattern pointer to static string of yang string pattern. optional
* @param[out] fraction for decimal64, how many digits after period
* @retval 0 OK. Note yrestype may still be NULL.
* @retval -1 Error, clicon_err handles errors
* The setting of the options argument has the following semantics:
@ -996,7 +1001,7 @@ yang_type_resolve(yang_stmt *ys,
if (rytypedef != NULL){ /* We have found a typedef */
/* Find associated type statement */
if ((rytype = yang_find((yang_node*)rytypedef, Y_TYPE, NULL)) == NULL){
clicon_err(OE_DB, 0, "%s: mandatory type object is not found", __FUNCTION__);
clicon_err(OE_DB, 0, "mandatory type object is not found");
goto done;
}
/* recursively resolve this new type */
@ -1034,14 +1039,14 @@ yang_type_resolve(yang_stmt *ys,
* 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
* @param [out] yrestype pointer to resolved type stmt. should be built-in or NULL
* @param [out] options pointer to flags field of optional values
* @param [out] mincv pointer to cv of min range or length. optional
* @param [out] maxcv pointer to cv of max range or length. optional
* @param [out] pattern pointer to static string of yang string pattern. optional
* @param [out] fraction for decimal64, how many digits after period
* @param[in] ys yang-stmt, leaf or leaf-list
* @param[out] origtype original type may be derived or built-in
* @param[out] yrestype pointer to resolved type stmt. should be built-in or NULL
* @param[out] options pointer to flags field of optional values
* @param[out] mincv pointer to cv of min range or length. optional
* @param[out] maxcv pointer to cv of max range or length. optional
* @param[out] pattern pointer to static string of yang string pattern. optional
* @param[out] fraction for decimal64, how many digits after period
* @retval 0 OK, but note that restype==NULL means not resolved.
* @retval -1 Error, clicon_err handles errors
* The setting of the options argument has the following semantics:
@ -1071,7 +1076,7 @@ yang_type_get(yang_stmt *ys,
*options = 0x0;
/* Find mandatory type */
if ((ytype = yang_find((yang_node*)ys, Y_TYPE, NULL)) == NULL){
clicon_err(OE_DB, 0, "%s: mandatory type object is not found", __FUNCTION__);
clicon_err(OE_DB, 0, "mandatory type object is not found");
goto done;
}
/* XXX: here we seem to have some problems if type is union */

6
test/Jenkinsfile vendored
View file

@ -8,15 +8,15 @@ node {
/* `make check` returns non-zero on test failures,
* using `true` to allow the Pipeline to continue nonetheless
*/
sh 'make clean || true'
sh './configure || true'
sh 'make clean'
sh './configure'
}
stage('Make') {
/* `make check` returns non-zero on test failures,
* using `true` to allow the Pipeline to continue nonetheless
*/
sh 'make || true'
sh 'make'
}
stage('Testing') {

View file

@ -36,10 +36,11 @@ err(){
if [ $# -gt 1 ]; then
echo "Received: $2"
fi
echo -e "\e[0m:"
echo -e "\e[0m"
echo "$ret"| od -t c > $dir/clixon-ret
echo "$expect"| od -t c > $dir/clixon-expect
diff $dir/clixon-ret $dir/clixon-expect
exit $testnr
}
@ -110,18 +111,29 @@ expecteq(){
fi
}
# clixon tester. First arg is command second is stdin and
# third is expected outcome
# Pipe stdin to command
# Arguments:
# - Command
# - expected command return value (0 if OK)
# - stdin input
# - expected stdout outcome
expecteof(){
cmd=$1
input=$2
expect=$3
retval=$2
input=$3
expect=$4
# Do while read stuff
ret=$($cmd<<EOF
$input
EOF
)
)
if [ $? -ne $retval ]; then
echo -e "\e[31m\nError in Test$testnr [$testname]:"
echo -e "\e[0m:"
exit -1
fi
# Match if both are empty string
if [ -z "$ret" -a -z "$expect" ]; then
return

View file

@ -152,10 +152,10 @@ expecteq "$(curl -u adm1:bar -sS -X GET http://localhost/restconf/data)" '{"data
'
new "auth set authentication config"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config>$RULES</config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config>$RULES</config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "commit it"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new2 "auth get (no user: access denied)"
expecteq "$(curl -sS -X GET -H \"Accept:\ application/yang-data+json\" http://localhost/restconf/data)" '{"ietf-restconf:errors" : {"error": {"error-tag": "access-denied","error-type": "protocol","error-severity": "error","error-message": "The requested URL was unauthorized"}}} '

View file

@ -120,47 +120,47 @@ if [ $? -ne 0 ]; then
fi
new "Set crypto to aes"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><crypto>aes</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><crypto>aes</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf validate "
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "Set crypto to mc:aes"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><crypto>mc:aes</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><crypto>mc:aes</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf validate"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "Set crypto to des:des3"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><crypto>des:des3</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><crypto>des:des3</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf validate"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "Set crypto to mc:foo"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><crypto>mc:foo</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><crypto>mc:foo</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf validate"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "Set crypto to des:des3 using xmlns"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><crypto xmlns:des=\"urn:example:des\">des:des3</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><crypto xmlns:des=\"urn:example:des\">des:des3</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf validate"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
# XXX this is not supported
#new "Set crypto to x:des3 using xmlns"
#expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><crypto xmlns:x=\"urn:example:des\">x:des3</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
#expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><crypto xmlns:x=\"urn:example:des\">x:des3</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
#new "netconf validate"
#expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
#expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "Set crypto to foo:bar"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><crypto>foo:bar</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><crypto>foo:bar</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf validate"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-tag>operation-failed</error-tag><error-type>application</error-type><error-severity>error</error-severity><error-message>Identityref validation failed, foo:bar not derived from crypto-alg</error-message></rpc-error></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-tag>operation-failed</error-tag><error-type>application</error-type><error-severity>error</error-severity><error-message>Identityref validation failed, foo:bar not derived from crypto-alg</error-message></rpc-error></rpc-reply>]]>]]>$"
new "cli set crypto to mc:aes"
expectfn "$clixon_cli -1 -f $cfg -l o set crypto mc:aes" 0 "^$"

14
test/test_json.sh Executable file
View file

@ -0,0 +1,14 @@
#!/bin/bash
# Test: JSON parser tests
PROG=../lib/src/clixon_util_json
# include err() and new() functions and creates $dir
. ./lib.sh
new "json parse"
expecteof $PROG 0 '{"foo": -23}' "^<foo>-23</foo>$"
new "json parse list"
expecteof $PROG 0 '{"a":[0,1,2,3]}' "^<a>0</a><a>1</a><a>2</a><a>3</a>$"
rm -rf $dir

View file

@ -84,45 +84,45 @@ if [ $? -ne 0 ]; then
fi
new "leafref base config"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><interfaces>
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><interfaces>
<interface><name>eth0</name><type>ex:eth</type> <ipv4><address><ip>192.0.2.1</ip></address><address><ip>192.0.2.2</ip></address></ipv4></interface>
<interface><name>lo</name><type>ex:lo</type><ipv4><address><ip>127.0.0.1</ip></address></ipv4></interface>
</interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "leafref get config"
expecteof "$clixon_netconf -qf $cfg" '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '^<rpc-reply><data><interfaces><interface><name>eth0</name>'
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '^<rpc-reply><data><interfaces><interface><name>eth0</name>'
new "leafref base commit"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "leafref add wrong ref"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><default-address><absname>eth3</absname><address>10.0.4.6</address></default-address></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><default-address><absname>eth3</absname><address>10.0.4.6</address></default-address></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "leafref validate XXX shouldnt really be operation-failed, more work in validate code"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-tag>operation-failed</error-tag>"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-tag>operation-failed</error-tag>"
new "leafref discard-changes"
expecteof "$clixon_netconf -qf $cfg" "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "leafref add correct absref"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><default-address><absname>eth0</absname></default-address></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><default-address><absname>eth0</absname></default-address></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "leafref add correct relref"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><default-address><relname>eth0</relname></default-address></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><default-address><relname>eth0</relname></default-address></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
# XXX add address
new "leafref validate (ok)"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>"
new "leafref delete leaf"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation=\"delete\"><name>eth0</name></interface></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation=\"delete\"><name>eth0</name></interface></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>"
new "leafref validate (should fail)"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-tag>operation-failed</error-tag>"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-tag>operation-failed</error-tag>"
new "leafref discard-changes"
expecteof "$clixon_netconf -qf $cfg" "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "cli leafref lo"
expectfn "$clixon_cli -1f $cfg -y $fyang -l o set default-address absname lo" 0 "^$"

View file

@ -81,132 +81,132 @@ if [ $? -ne 0 ]; then
fi
new "netconf get-config"
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc message-id="101"><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '^<rpc-reply message-id="101"><data/></rpc-reply>]]>]]>$'
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc message-id="101"><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '^<rpc-reply message-id="101"><data/></rpc-reply>]]>]]>$'
new "Add subtree eth/0/0 using none which should not change anything"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><default-operation>none</default-operation><target><candidate/></target><config><interfaces><interface><name>eth/0/0</name></interface></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><default-operation>none</default-operation><target><candidate/></target><config><interfaces><interface><name>eth/0/0</name></interface></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "Check nothing added"
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc message-id="101"><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '^<rpc-reply message-id="101"><data/></rpc-reply>]]>]]>$'
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc message-id="101"><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '^<rpc-reply message-id="101"><data/></rpc-reply>]]>]]>$'
new "Add subtree eth/0/0 using none and create which should add eth/0/0"
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation="create"><name>eth/0/0</name><type>ex:eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation="create"><name>eth/0/0</name><type>ex:eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "Check eth/0/0 added using xpath"
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><get-config><source><candidate/></source><filter type="xpath" select="/interfaces/interface[name=eth/0/0]"/></get-config></rpc>]]>]]>' "^<rpc-reply><data><interfaces><interface><name>eth/0/0</name><type>ex:eth</type><enabled>true</enabled></interface></interfaces></data></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get-config><source><candidate/></source><filter type="xpath" select="/interfaces/interface[name=eth/0/0]"/></get-config></rpc>]]>]]>' "^<rpc-reply><data><interfaces><interface><name>eth/0/0</name><type>ex:eth</type><enabled>true</enabled></interface></interfaces></data></rpc-reply>]]>]]>$"
new "Re-create same eth/0/0 which should generate error"
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation="create"><name>eth/0/0</name><type>ex:eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>]]>]]>' "^<rpc-reply><rpc-error>"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation="create"><name>eth/0/0</name><type>ex:eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>]]>]]>' "^<rpc-reply><rpc-error>"
new "Delete eth/0/0 using none config"
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation="delete"><name>eth/0/0</name><type>ex:eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation="delete"><name>eth/0/0</name><type>ex:eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "Check deleted eth/0/0 (non-presence container)"
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc message-id="101"><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '^<rpc-reply message-id="101"><data/></rpc-reply>]]>]]>$'
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc message-id="101"><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '^<rpc-reply message-id="101"><data/></rpc-reply>]]>]]>$'
new "Re-Delete eth/0/0 using none should generate error"
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation="delete"><name>eth/0/0</name><type>ex:eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>]]>]]>' "^<rpc-reply><rpc-error>"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation="delete"><name>eth/0/0</name><type>ex:eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>]]>]]>' "^<rpc-reply><rpc-error>"
new "netconf edit config"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><interfaces><interface><name>eth/0/0</name></interface><interface><name>eth1</name><enabled>true</enabled><ipv4><address><ip>9.2.3.4</ip><prefix-length>24</prefix-length></address></ipv4></interface></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><interfaces><interface><name>eth/0/0</name></interface><interface><name>eth1</name><enabled>true</enabled><ipv4><address><ip>9.2.3.4</ip><prefix-length>24</prefix-length></address></ipv4></interface></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf get config xpath"
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><get-config><source><candidate/></source><filter type="xpath" select="/interfaces/interface[name=eth1]/enabled"/></get-config></rpc>]]>]]>' "^<rpc-reply><data><interfaces><interface><name>eth1</name><enabled>true</enabled></interface></interfaces></data></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get-config><source><candidate/></source><filter type="xpath" select="/interfaces/interface[name=eth1]/enabled"/></get-config></rpc>]]>]]>' "^<rpc-reply><data><interfaces><interface><name>eth1</name><enabled>true</enabled></interface></interfaces></data></rpc-reply>]]>]]>$"
new "netconf get config xpath parent"
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><get-config><source><candidate/></source><filter type="xpath" select="/interfaces/interface[name=eth1]/enabled/../.."/></get-config></rpc>]]>]]>' "^<rpc-reply><data><interfaces><interface><name>eth/0/0</name><enabled>true</enabled></interface><interface><name>eth1</name><enabled>true</enabled><ipv4><enabled>true</enabled><forwarding>false</forwarding><address><ip>9.2.3.4</ip><prefix-length>24</prefix-length></address></ipv4></interface></interfaces></data></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get-config><source><candidate/></source><filter type="xpath" select="/interfaces/interface[name=eth1]/enabled/../.."/></get-config></rpc>]]>]]>' "^<rpc-reply><data><interfaces><interface><name>eth/0/0</name><enabled>true</enabled></interface><interface><name>eth1</name><enabled>true</enabled><ipv4><enabled>true</enabled><forwarding>false</forwarding><address><ip>9.2.3.4</ip><prefix-length>24</prefix-length></address></ipv4></interface></interfaces></data></rpc-reply>]]>]]>$"
new "netconf validate missing type"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><rpc-error>"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><rpc-error>"
new "netconf discard-changes"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf get empty config2"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data/></rpc-reply>]]>]]>$"
new "netconf edit extra xml"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><interfaces><extra/></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><rpc-error>"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><interfaces><extra/></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><rpc-error>"
new "netconf discard-changes"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf edit config eth1"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><interfaces><interface><name>eth1</name><type>ex:eth</type></interface></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><interfaces><interface><name>eth1</name><type>ex:eth</type></interface></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf validate"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf commit"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf edit config merge"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><interfaces><interface><name>eth2</name><type>ex:eth</type></interface></interfaces></config><default-operation>merge</default-operation></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><interfaces><interface><name>eth2</name><type>ex:eth</type></interface></interfaces></config><default-operation>merge</default-operation></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf edit ampersand encoding(<&): name:'eth&' type:'t<>'"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><interfaces><interface><name>eth&amp; </name><type>t&lt; &gt; </type></interface></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><interfaces><interface><name>eth&amp; </name><type>t&lt; &gt; </type></interface></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf get replaced config"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><interfaces><interface><name>eth&amp; </name><type>t&lt; &gt; </type><enabled>true</enabled></interface><interface><name>eth1</name><type>ex:eth</type><enabled>true</enabled></interface><interface><name>eth2</name><type>ex:eth</type><enabled>true</enabled></interface></interfaces></data></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><interfaces><interface><name>eth&amp; </name><type>t&lt; &gt; </type><enabled>true</enabled></interface><interface><name>eth1</name><type>ex:eth</type><enabled>true</enabled></interface><interface><name>eth2</name><type>ex:eth</type><enabled>true</enabled></interface></interfaces></data></rpc-reply>]]>]]>$"
new "cli show configuration eth& - encoding tests"
expectfn "$clixon_cli -1 -f $cfg -y $fyang show conf cli" 0 "interfaces interface eth& type t<>
interfaces interface eth& enabled true"
new "netconf edit CDATA"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><interfaces><interface><name>eth/0/0</name><type>ex:eth</type><description><![CDATA[myeth&]]></description></interface></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><interfaces><interface><name>eth/0/0</name><type>ex:eth</type><description><![CDATA[myeth&]]></description></interface></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
#new "netconf get CDATA"
#expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><candidate/></source><filter type=\"xpath\" select=\"/interfaces/interface[name=eth/0/0]/description\" /></get-config></rpc>]]>]]>" "<rpc-reply><data><interfaces><interface><name>eth/0/0</name><description><![CDATA[myeth&]]></description><enabled>true</enabled></interface></interfaces></data></rpc-reply>]]>]]>"
#expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><candidate/></source><filter type=\"xpath\" select=\"/interfaces/interface[name=eth/0/0]/description\" /></get-config></rpc>]]>]]>" "<rpc-reply><data><interfaces><interface><name>eth/0/0</name><description><![CDATA[myeth&]]></description><enabled>true</enabled></interface></interfaces></data></rpc-reply>]]>]]>"
new "netconf discard-changes"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf edit state operation should fail"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><interfaces-state><interface><name>eth1</name><type>ex:eth</type></interface></interfaces-state></config></edit-config></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-tag>invalid-value</error-tag>"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><interfaces-state><interface><name>eth1</name><type>ex:eth</type></interface></interfaces-state></config></edit-config></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-tag>invalid-value</error-tag>"
new "netconf get state operation"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get><filter type=\"xpath\" select=\"/interfaces-state\"/></get></rpc>]]>]]>" "^<rpc-reply><data><interfaces-state><interface><name>eth0</name><type>ex:eth</type><if-index>42</if-index></interface></interfaces-state></data></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get><filter type=\"xpath\" select=\"/interfaces-state\"/></get></rpc>]]>]]>" "^<rpc-reply><data><interfaces-state><interface><name>eth0</name><type>ex:eth</type><if-index>42</if-index></interface></interfaces-state></data></rpc-reply>]]>]]>$"
new "netconf lock/unlock"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><lock><target><candidate/></target></lock></rpc>]]>]]><rpc><unlock><target><candidate/></target></unlock></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]><rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><lock><target><candidate/></target></lock></rpc>]]>]]><rpc><unlock><target><candidate/></target></unlock></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]><rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf lock/lock"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><lock><target><candidate/></target></lock></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><lock><target><candidate/></target></lock></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf lock"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><lock><target><candidate/></target></lock></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><lock><target><candidate/></target></lock></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "close-session"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><close-session/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><close-session/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "kill-session"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><kill-session><session-id>44</session-id></kill-session></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><kill-session><session-id>44</session-id></kill-session></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "copy startup"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><copy-config><target><startup/></target><source><candidate/></source></copy-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><copy-config><target><startup/></target><source><candidate/></source></copy-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf get startup"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><startup/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><interfaces><interface><name>eth1</name><type>ex:eth</type><enabled>true</enabled></interface></interfaces></data></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><startup/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><interfaces><interface><name>eth1</name><type>ex:eth</type><enabled>true</enabled></interface></interfaces></data></rpc-reply>]]>]]>$"
new "netconf delete startup"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><delete-config><target><startup/></target></delete-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><delete-config><target><startup/></target></delete-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf check empty startup"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><startup/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><startup/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data/></rpc-reply>]]>]]>$"
new "netconf rpc"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><rt:fib-route><routing-instance-name>ipv4</routing-instance-name><destination-address><address-family>ipv4</address-family></destination-address></rt:fib-route></rpc>]]>]]>" "^<rpc-reply><route><address-family>ipv4</address-family><next-hop><next-hop-list>"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><rt:fib-route><routing-instance-name>ipv4</routing-instance-name><destination-address><address-family>ipv4</address-family></destination-address></rt:fib-route></rpc>]]>]]>" "^<rpc-reply><route><address-family>ipv4</address-family><next-hop><next-hop-list>"
new "netconf rpc w/o namespace"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><fib-route><routing-instance-name>ipv4</routing-instance-name><destination-address><address-family>ipv4</address-family></destination-address></fib-route></rpc>]]>]]>" "^<rpc-reply><route><address-family>ipv4</address-family><next-hop><next-hop-list>"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><fib-route><routing-instance-name>ipv4</routing-instance-name><destination-address><address-family>ipv4</address-family></destination-address></fib-route></rpc>]]>]]>" "^<rpc-reply><route><address-family>ipv4</address-family><next-hop><next-hop-list>"
new "netconf empty rpc"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><empty/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><empty/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf client-side rpc"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><ex:client-rpc><request>example</request></ex:client-rpc></rpc>]]>]]>" "^<rpc-reply><result>ok</result></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><ex:client-rpc><request>example</request></ex:client-rpc></rpc>]]>]]>" "^<rpc-reply><result>ok</result></rpc-reply>]]>]]>$"
new "netconf subscription"
expectwait "$clixon_netconf -qf $cfg -y $fyang" "<rpc><create-subscription><stream>ROUTING</stream></create-subscription></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]><notification><event>Routing notification</event></notification>]]>]]>$" 30

View file

@ -119,53 +119,53 @@ fi
# Check as file
new "verify running from start, should be: l,c,y0,y1,y2,y3; y1 and y3 sorted. Note this fails if XML_SORT set to false"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><running/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><c><d>hej</d></c><l>hopp</l><y0>d</y0><y0>b</y0><y0>c</y0><y0>a</y0><y1>a</y1><y1>b</y1><y1>c</y1><y1>d</y1><y2><k>d</k><a>bar</a></y2><y2><k>a</k><a>bar</a></y2><y2><k>c</k><a>bar</a></y2><y2><k>b</k><a>bar</a></y2><y3><k>a</k><a>bar</a></y3><y3><k>b</k><a>bar</a></y3><y3><k>c</k><a>bar</a></y3><y3><k>d</k><a>bar</a></y3></data></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><running/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><c><d>hej</d></c><l>hopp</l><y0>d</y0><y0>b</y0><y0>c</y0><y0>a</y0><y1>a</y1><y1>b</y1><y1>c</y1><y1>d</y1><y2><k>d</k><a>bar</a></y2><y2><k>a</k><a>bar</a></y2><y2><k>c</k><a>bar</a></y2><y2><k>b</k><a>bar</a></y2><y3><k>a</k><a>bar</a></y3><y3><k>b</k><a>bar</a></y3><y3><k>c</k><a>bar</a></y3><y3><k>d</k><a>bar</a></y3></data></rpc-reply>]]>]]>$"
new "get each ordered-by user leaf-list"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><running/></source><filter type=\"xpath\" select=\"/y2[k=a]\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><y2><k>a</k><a>bar</a></y2></data></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><running/></source><filter type=\"xpath\" select=\"/y2[k=a]\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><y2><k>a</k><a>bar</a></y2></data></rpc-reply>]]>]]>$"
new "get each ordered-by user leaf-list"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><running/></source><filter type=\"xpath\" select=\"/y3[k=a]\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><y3><k>a</k><a>bar</a></y3></data></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><running/></source><filter type=\"xpath\" select=\"/y3[k=a]\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><y3><k>a</k><a>bar</a></y3></data></rpc-reply>]]>]]>$"
new "get each ordered-by user leaf-list"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><running/></source><filter type=\"xpath\" select=\"/y2[k=b]\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><y2><k>b</k><a>bar</a></y2></data></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><running/></source><filter type=\"xpath\" select=\"/y2[k=b]\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><y2><k>b</k><a>bar</a></y2></data></rpc-reply>]]>]]>$"
new "get each ordered-by user leaf-list"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><running/></source><filter type=\"xpath\" select=\"/y3[k=b]\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><y3><k>b</k><a>bar</a></y3></data></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><running/></source><filter type=\"xpath\" select=\"/y3[k=b]\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><y3><k>b</k><a>bar</a></y3></data></rpc-reply>]]>]]>$"
new "delete candidate"
expecteof "$clixon_netconf -qf $cfg" "<rpc><delete-config><target><candidate/></target></delete-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><delete-config><target><candidate/></target></delete-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
# LEAF_LISTS
new "add two entries to leaf-list user order"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><y0>c</y0><y0>b</y0></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><y0>c</y0><y0>b</y0></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "add one entry to leaf-list user order"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><y0>a</y0></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><y0>a</y0></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf commit"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "add one entry to leaf-list user order after commit"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><y0>0</y0></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><y0>0</y0></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf commit"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "verify leaf-list user order in running (as entered)"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><running/></source><filter type=\"xpath\" select=\"/y0\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><y0>c</y0><y0>b</y0><y0>a</y0><y0>0</y0></data></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><running/></source><filter type=\"xpath\" select=\"/y0\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><y0>c</y0><y0>b</y0><y0>a</y0><y0>0</y0></data></rpc-reply>]]>]]>$"
# LISTS
new "add two entries to list user order"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><y2><k>c</k><a>bar</a></y2><y2><k>b</k><a>foo</a></y2></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><y2><k>c</k><a>bar</a></y2><y2><k>b</k><a>foo</a></y2></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "add one entry to list user order"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><y2><k>a</k><a>fie</a></y2></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><y2><k>a</k><a>fie</a></y2></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "verify list user order (as entered)"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><candidate/></source><filter type=\"xpath\" select=\"/y2\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><y2><k>c</k><a>bar</a></y2><y2><k>b</k><a>foo</a></y2><y2><k>a</k><a>fie</a></y2></data></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><candidate/></source><filter type=\"xpath\" select=\"/y2\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><y2><k>c</k><a>bar</a></y2><y2><k>b</k><a>foo</a></y2><y2><k>a</k><a>fie</a></y2></data></rpc-reply>]]>]]>$"
pid=`pgrep clixon_backend`
if [ -z "$pid" ]; then

View file

@ -99,13 +99,13 @@ expecteof_file "time -f %e $clixon_netconf -qf $cfg -y $fyang" "$fconfig" "^<rpc
rm $fconfig
new "netconf commit large config"
expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" "<rpc><commit><source><candidate/></source></commit></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><commit><source><candidate/></source></commit></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf commit large config again"
expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" "<rpc><commit><source><candidate/></source></commit></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><commit><source><candidate/></source></commit></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf add small (1 entry) config"
expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><x><y><a>x</a><b>y</b></y></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><x><y><a>x</a><b>y</b></y></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf get $req small config"
time -p for (( i=0; i<$req; i++ )); do
@ -132,7 +132,7 @@ time -p for (( i=0; i<$req; i++ )); do
done
new "netconf get large config"
expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><y><a>0</a><b>0</b></y><y><a>1</a><b>1</b>"
expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><y><a>0</a><b>0</b></y><y><a>1</a><b>1</b>"
new "generate large leaf-list config"
echo -n "<rpc><edit-config><target><candidate/></target><default-operation>replace</default-operation><config><x>" > $fconfig
@ -147,7 +147,7 @@ expecteof_file "time -f %e $clixon_netconf -qf $cfg -y $fyang" "$fconfig" "^<rpc
rm $fconfig
new "netconf commit large leaf-list config"
expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" "<rpc><commit><source><candidate/></source></commit></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><commit><source><candidate/></source></commit></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf add $req small leaf-list config"
time -p for (( i=0; i<$req; i++ )); do
@ -156,13 +156,13 @@ time -p for (( i=0; i<$req; i++ )); do
done | $clixon_netconf -qf $cfg -y $fyang > /dev/null
new "netconf add small leaf-list config"
expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><x><c>x</c></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><x><c>x</c></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf commit small leaf-list config"
expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" "<rpc><commit><source><candidate/></source></commit></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><commit><source><candidate/></source></commit></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf get large leaf-list config"
expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><c>0</c><c>1</c>"
expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><c>0</c><c>1</c>"
new "Kill backend"
# Check if still alive

View file

@ -87,7 +87,7 @@ EOF
fi
new "Check $mode"
expecteof "$clixon_netconf -qf $cfg" '<rpc><get-config><source><running/></source></get-config></rpc>]]>]]>' "^<rpc-reply>$expect</rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><get-config><source><running/></source></get-config></rpc>]]>]]>' "^<rpc-reply>$expect</rpc-reply>]]>]]>$"
new "Kill backend"
# Check if still alive

View file

@ -171,19 +171,19 @@ new "cli commit"
expectfn "$clixon_cli -1f $cfg -l o -y $fyang -l o commit" 0 "^$"
new "netconf validate ok"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf set ab wrong"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><list><ip>a.b&amp; c.d</ip></list></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><list><ip>a.b&amp; c.d</ip></list></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf validate"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><rpc-error>"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><rpc-error>"
new "netconf discard-changes"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf commit"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "cli enum value"
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set status down" 0 "^$"
@ -196,7 +196,7 @@ expectfn "$clixon_cli -1f $cfg -l o -y $fyang set mbits create" 0 "^$"
#expectfn "$clixon_cli -1f $cfg -l o -y $fyang set mbits \"create read\"" 0 "^$"
new "netconf bits two values"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><mbits>create read</mbits></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><mbits>create read</mbits></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "cli bits validate"
expectfn "$clixon_cli -1f $cfg -l o -y $fyang validate" 0 "^$"

46
test/test_xml.sh Executable file
View file

@ -0,0 +1,46 @@
#!/bin/bash
# Test: XML parser tests
PROG=../lib/src/clixon_util_xml
# include err() and new() functions and creates $dir
. ./lib.sh
new "xml parse"
expecteof $PROG 0 "<a><b/></a>" "^<a><b/></a>$"
XML=$(cat <<EOF
<a><description>An example of escaped CENDs</description>
<sometext>
<![CDATA[ They're saying "x < y" & that "z > y" so I guess that means that z > x ]]>
</sometext>
<!-- This text contains a CEND ]]> -->
<!-- In this first case we put the ]] at the end of the first CDATA block
and the > in the second CDATA block -->
<data><![CDATA[This text contains a CEND ]]]]><![CDATA[>]]></data>
<!-- In this second case we put a ] at the end of the first CDATA block
and the ]> in the second CDATA block -->
<alternative><![CDATA[This text contains a CEND ]]]><![CDATA[]>]]></alternative>
</a>
EOF
)
new "xml CDATA"
expecteof $PROG 0 "$XML" "^<a><description>An example of escaped CENDs</description><sometext>
<![CDATA[ They're saying \"x < y\" & that \"z > y\" so I guess that means that z > x ]]>
</sometext><data><![CDATA[This text contains a CEND ]]]]><![CDATA[>]]></data><alternative><![CDATA[This text contains a CEND ]]]><![CDATA[]>]]></alternative></a>$"
XML=$(cat <<EOF
<message>Less than: &lt; , greater than: &gt; ampersand: &amp; </message>
EOF
)
new "xml encode <>&"
expecteof $PROG 0 "$XML" "^$XML$"
XML=$(cat <<EOF
<message>To allow attribute values to contain both single and double quotes, the apostrophe or single-quote character ' may be represented as &apos; and the double-quote character as &quot; </message>
EOF
)
new "xml optional encode single and double quote"
expecteof $PROG 0 "$XML" "^<message>To allow attribute values to contain both single and double quotes, the apostrophe or single-quote character ' may be represented as ' and the double-quote character as \"</message>$"
rm -rf $dir

12
test/test_xsl.sh Executable file
View file

@ -0,0 +1,12 @@
#!/bin/bash
# Test: XSL tests
PROG=../lib/src/clixon_util_xsl
# include err() and new() functions and creates $dir
. ./lib.sh
new "xsl test"
expecteof $PROG 0 "a
<a><b/></a>" "^0:<a><b/></a>$"
rm -rf $dir

View file

@ -118,29 +118,29 @@ new "cli not defined extension"
#expectfn "$clixon_cli -1f $cfg -y $fyangerr show version" 0 "Yang error: Extension ex:not-defined not found"
new "netconf edit config"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><x><y><a>1</a><b>2</b><c>5</c><val>one</val></y><d/></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><x><y><a>1</a><b>2</b><c>5</c><val>one</val></y><d/></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf commit"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
# text empty type in running
new "netconf commit 2nd"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf get config xpath"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><candidate/></source><filter type=\"xpath\" select=\"/x/y[a=1][b=2][c=5]\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><y><a>1</a><b>2</b><c>5</c><val>one</val></y></x></data></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><candidate/></source><filter type=\"xpath\" select=\"/x/y[a=1][b=2][c=5]\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><y><a>1</a><b>2</b><c>5</c><val>one</val></y></x></data></rpc-reply>]]>]]>$"
new "netconf edit leaf-list"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><x><f><e>hej</e><e>hopp</e></f></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><x><f><e>hej</e><e>hopp</e></f></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf get leaf-list"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><candidate/></source><filter type=\"xpath\" select=\"/x/f/e\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><f><e>hej</e><e>hopp</e></f></x></data></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><candidate/></source><filter type=\"xpath\" select=\"/x/f/e\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><f><e>hej</e><e>hopp</e></f></x></data></rpc-reply>]]>]]>$"
new "netconf get leaf-list path"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><candidate/></source><filter type=\"xpath\" select=\"/x/f[e=hej]\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><f><e>hej</e><e>hopp</e></f></x></data></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><candidate/></source><filter type=\"xpath\" select=\"/x/f[e=hej]\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><f><e>hej</e><e>hopp</e></f></x></data></rpc-reply>]]>]]>$"
new "netconf get (should be some)"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get><filter type=\"xpath\" select=\"/\"/></get></rpc>]]>]]>" "^<rpc-reply><data><x><y><a>1</a><b>2</b><c>5</c><val>one</val></y><d/></x></data></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get><filter type=\"xpath\" select=\"/\"/></get></rpc>]]>]]>" "^<rpc-reply><data><x><y><a>1</a><b>2</b><c>5</c><val>one</val></y><d/></x></data></rpc-reply>]]>]]>$"
new "cli set leaf-list"
expectfn "$clixon_cli -1f $cfg -y $fyang set x f e foo" 0 ""
@ -148,50 +148,50 @@ expectfn "$clixon_cli -1f $cfg -y $fyang set x f e foo" 0 ""
new "cli show leaf-list"
expectfn "$clixon_cli -1f $cfg -y $fyang show xpath /x/f/e" 0 "<e>foo</e>"
new "netconf set state data (not allowed)"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><state><op>42</op></state></config></edit-config></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-tag>invalid-value"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><state><op>42</op></state></config></edit-config></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-tag>invalid-value"
new "netconf set presence and not present"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><x><nopresence/><presence/></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><x><nopresence/><presence/></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf get presence only"
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><get-config><source><candidate/></source><filter type="xpath" select="/x/*presence"/></get-config></rpc>]]>]]>' "^<rpc-reply><data><x><presence/></x></data></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get-config><source><candidate/></source><filter type="xpath" select="/x/*presence"/></get-config></rpc>]]>]]>' "^<rpc-reply><data><x><presence/></x></data></rpc-reply>]]>]]>$"
new "netconf discard-changes"
expecteof "$clixon_netconf -qf $cfg" "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf anyxml"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><x><any><foo><bar a=\"nisse\"/></foo></any></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><x><any><foo><bar a=\"nisse\"/></foo></any></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf validate anyxml"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf delete candidate"
expecteof "$clixon_netconf -qf $cfg" "<rpc><delete-config><target><candidate/></target></delete-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><delete-config><target><candidate/></target></delete-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
# Check 3-keys
new "netconf add one 3-key entry"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><x><y><a>1</a><b>1</b><c>1</c><val>one</val></y></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><x><y><a>1</a><b>1</b><c>1</c><val>one</val></y></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf check add one 3-key"
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '<rpc-reply><data><x><y><a>1</a><b>1</b><c>1</c><val>one</val></y></x></data></rpc-reply>]]>]]>'
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '<rpc-reply><data><x><y><a>1</a><b>1</b><c>1</c><val>one</val></y></x></data></rpc-reply>]]>]]>'
new "netconf add another (with same 1st key)"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><x><y><a>1</a><b>2</b><c>1</c><val>two</val></y></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><x><y><a>1</a><b>2</b><c>1</c><val>two</val></y></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf check add another"
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '<rpc-reply><data><x><y><a>1</a><b>1</b><c>1</c><val>one</val></y><y><a>1</a><b>2</b><c>1</c><val>two</val></y></x></data></rpc-reply>]]>]]>'
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '<rpc-reply><data><x><y><a>1</a><b>1</b><c>1</c><val>one</val></y><y><a>1</a><b>2</b><c>1</c><val>two</val></y></x></data></rpc-reply>]]>]]>'
new "netconf replace first"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><x><y><a>1</a><b>1</b><c>1</c><val>replace</val></y></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><x><y><a>1</a><b>1</b><c>1</c><val>replace</val></y></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf check replace"
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '<rpc-reply><data><x><y><a>1</a><b>1</b><c>1</c><val>replace</val></y><y><a>1</a><b>2</b><c>1</c><val>two</val></y></x></data></rpc-reply>]]>]]>'
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '<rpc-reply><data><x><y><a>1</a><b>1</b><c>1</c><val>replace</val></y><y><a>1</a><b>2</b><c>1</c><val>two</val></y></x></data></rpc-reply>]]>]]>'
new "netconf delete first"
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><edit-config><target><candidate/></target><config><x><y operation="remove"><a>1</a><b>1</b><c>1</c></y></x></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><x><y operation="remove"><a>1</a><b>1</b><c>1</c></y></x></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf check delete"
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '<rpc-reply><data><x><y><a>1</a><b>2</b><c>1</c><val>two</val></y></x></data></rpc-reply>]]>]]>'
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '<rpc-reply><data><x><y><a>1</a><b>2</b><c>1</c><val>two</val></y></x></data></rpc-reply>]]>]]>'
# Check if still alive
pid=`pgrep clixon_backend`

24
test/test_yang_parse.sh Executable file
View file

@ -0,0 +1,24 @@
#!/bin/bash
# Test: XML parser tests
PROG=../lib/src/clixon_util_yang
# include err() and new() functions and creates $dir
. ./lib.sh
YANG=$(cat <<EOF
module test{
prefix ex;
extension c-define {
description "Example from RFC 6020";
argument "name";
}
ex:not-defined ARGUMENT;
}
EOF
)
new "yang parse"
expecteof $PROG 0 "$YANG" "^$YANG$"
rm -rf $dir