From 85c4782e3624f0d9af19b150b5c2a34d05638ae5 Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Sun, 17 Jun 2018 19:40:06 +0200 Subject: [PATCH] Dedicated xml,json,yang and xsl parser utility programs added Sanity check of stdarg (...) added Cleanup of error messages. --- CHANGELOG.md | 1 + apps/backend/backend_commit.c | 4 +- apps/backend/backend_plugin.c | 2 +- apps/backend/backend_socket.c | 19 ++- apps/backend/clixon_backend_handle.c | 4 +- apps/cli/cli_common.c | 37 ++--- apps/cli/cli_generate.c | 2 +- apps/cli/cli_main.c | 2 +- apps/cli/cli_plugin.c | 2 +- apps/cli/cli_show.c | 22 +-- apps/netconf/netconf_lib.c | 2 +- apps/netconf/netconf_main.c | 2 +- apps/netconf/netconf_rpc.c | 6 +- apps/restconf/restconf_methods.c | 2 +- datastore/text/clixon_xmldb_text.c | 8 +- lib/clixon/clixon_err.h | 4 + lib/clixon/clixon_log.h | 8 +- lib/clixon/clixon_proto.h | 4 + lib/clixon/clixon_xsl.h | 9 +- lib/clixon/clixon_yang.h | 1 + lib/src/Makefile.in | 27 +++- lib/src/clixon_err.c | 10 +- lib/src/clixon_event.c | 10 +- lib/src/clixon_file.c | 5 +- lib/src/clixon_json.c | 8 +- lib/src/clixon_options.c | 18 +-- lib/src/clixon_plugin.c | 4 +- lib/src/clixon_proto.c | 18 +-- lib/src/clixon_util_json.c | 102 +++++++++++++ lib/src/clixon_util_xml.c | 107 ++++++++++++++ lib/src/clixon_util_xsl.c | 141 ++++++++++++++++++ lib/src/clixon_util_yang.c | 93 ++++++++++++ lib/src/clixon_xml.c | 6 +- lib/src/clixon_xml_db.c | 4 +- lib/src/clixon_xml_map.c | 2 +- lib/src/clixon_xml_parse.l | 2 +- lib/src/clixon_xsl.c | 25 ++-- lib/src/clixon_yang.c | 206 +++++++++++++++------------ lib/src/clixon_yang_parse.h | 1 - lib/src/clixon_yang_parse.y | 2 +- lib/src/clixon_yang_type.c | 81 ++++++----- test/Jenkinsfile | 6 +- test/lib.sh | 24 +++- test/test_auth.sh | 4 +- test/test_identity.sh | 28 ++-- test/test_json.sh | 14 ++ test/test_leafref.sh | 24 ++-- test/test_netconf.sh | 82 +++++------ test/test_order.sh | 30 ++-- test/test_perf.sh | 16 +-- test/test_startup.sh | 2 +- test/test_type.sh | 12 +- test/test_xml.sh | 46 ++++++ test/test_xsl.sh | 12 ++ test/test_yang.sh | 46 +++--- test/test_yang_parse.sh | 24 ++++ 56 files changed, 1004 insertions(+), 379 deletions(-) create mode 100644 lib/src/clixon_util_json.c create mode 100644 lib/src/clixon_util_xml.c create mode 100644 lib/src/clixon_util_xsl.c create mode 100644 lib/src/clixon_util_yang.c create mode 100755 test/test_json.sh create mode 100755 test/test_xml.sh create mode 100755 test/test_xsl.sh create mode 100755 test/test_yang_parse.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e7b8d51..5b72a6ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/apps/backend/backend_commit.c b/apps/backend/backend_commit.c index 6df3852f..3aa2f82d 100644 --- a/apps/backend/backend_commit.c +++ b/apps/backend/backend_commit.c @@ -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, diff --git a/apps/backend/backend_plugin.c b/apps/backend/backend_plugin.c index 4d7e9eaa..6dd23d4d 100644 --- a/apps/backend/backend_plugin.c +++ b/apps/backend/backend_plugin.c @@ -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 diff --git a/apps/backend/backend_socket.c b/apps/backend/backend_socket.c index 7472fa06..a2587044 100644 --- a/apps/backend/backend_socket.c +++ b/apps/backend/backend_socket.c @@ -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 diff --git a/apps/backend/clixon_backend_handle.c b/apps/backend/clixon_backend_handle.c index dfb9461a..1fc397d8 100644 --- a/apps/backend/clixon_backend_handle.c +++ b/apps/backend/clixon_backend_handle.c @@ -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; } diff --git a/apps/cli/cli_common.c b/apps/cli/cli_common.c index a3fb9ad6..0898a6da 100644 --- a/apps/cli/cli_common.c +++ b/apps/cli/cli_common.c @@ -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, "", 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 \",\"", cv_string_get(cvec_i(argv,0))); + clicon_err(OE_PLUGIN, 0, "Got single argument:\"%s\". Expected \",\"", + cv_string_get(cvec_i(argv,0))); else - clicon_err(OE_PLUGIN, 0, "%s: Got %d arguments. Expected: ,", cvec_len(argv)); + clicon_err(OE_PLUGIN, 0, " Got %d arguments. Expected: ,", + 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: []", __FUNCTION__); + clicon_err(OE_PLUGIN, 0, "Requires arguments: []"); 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: ", __FUNCTION__); + clicon_err(OE_PLUGIN, 0, "Requires four elements: "); 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; } diff --git a/apps/cli/cli_generate.c b/apps/cli/cli_generate.c index dc1cbca3..6e44c0fd 100644 --- a/apps/cli/cli_generate.c +++ b/apps/cli/cli_generate.c @@ -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 */ diff --git a/apps/cli/cli_main.c b/apps/cli/cli_main.c index 685546f7..825fbc84 100644 --- a/apps/cli/cli_main.c +++ b/apps/cli/cli_main.c @@ -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, "\n"); while (fgets(line, sizeof(line), f)) { if ((cp = strchr(line, '\n')) != NULL) /* strip last \n */ diff --git a/apps/cli/cli_plugin.c b/apps/cli/cli_plugin.c index 92caf7fd..64f94bd8 100644 --- a/apps/cli/cli_plugin.c +++ b/apps/cli/cli_plugin.c @@ -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; diff --git a/apps/cli/cli_show.c b/apps/cli/cli_show.c index e7a855f1..79f64b75 100644 --- a/apps/cli/cli_show.c +++ b/apps/cli/cli_show.c @@ -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: ", - __FUNCTION__); + clicon_err(OE_PLUGIN, 0, "requires arguments: "); 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 "); + clicon_err(OE_PLUGIN, 0, "Error when accessing argument "); 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 "); + clicon_err(OE_PLUGIN, 0, "Error when accessing argument "); 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 ", __FUNCTION__); + clicon_err(OE_PLUGIN, 0, "Requires one element to be "); 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* . (*) generated.", __FUNCTION__); + clicon_err(OE_PLUGIN, 0, "Usage: * . (*) 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: diff --git a/apps/netconf/netconf_lib.c b/apps/netconf/netconf_lib.c index 5e5e21d2..998b4ef0 100644 --- a/apps/netconf/netconf_lib.c +++ b/apps/netconf/netconf_lib.c @@ -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 diff --git a/apps/netconf/netconf_main.c b/apps/netconf/netconf_main.c index 620b3e76..9811d959 100644 --- a/apps/netconf/netconf_main.c +++ b/apps/netconf/netconf_main.c @@ -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)); diff --git a/apps/netconf/netconf_rpc.c b/apps/netconf/netconf_rpc.c index 80eebfe2..ac341c03 100644 --- a/apps/netconf/netconf_rpc.c +++ b/apps/netconf/netconf_rpc.c @@ -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 */ diff --git a/apps/restconf/restconf_methods.c b/apps/restconf/restconf_methods.c index b65c3c27..b1e05378 100644 --- a/apps/restconf/restconf_methods.c +++ b/apps/restconf/restconf_methods.c @@ -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){ diff --git a/datastore/text/clixon_xmldb_text.c b/datastore/text/clixon_xmldb_text.c index 9bc96f46..7b7d52d8 100644 --- a/datastore/text/clixon_xmldb_text.c +++ b/datastore/text/clixon_xmldb_text.c @@ -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: ... */ - 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 */ diff --git a/lib/clixon/clixon_err.h b/lib/clixon/clixon_err.h index 8acc723c..8b8900ac 100644 --- a/lib/clixon/clixon_err.h +++ b/lib/clixon/clixon_err.h @@ -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); diff --git a/lib/clixon/clixon_log.h b/lib/clixon/clixon_log.h index 01c6eac4..7b833427 100644 --- a/lib/clixon/clixon_log.h +++ b/lib/clixon/clixon_log.h @@ -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_ */ diff --git a/lib/clixon/clixon_proto.h b/lib/clixon/clixon_proto.h index ef79b6b4..fda6ba07 100644 --- a/lib/clixon/clixon_proto.h +++ b/lib/clixon/clixon_proto.h @@ -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); diff --git a/lib/clixon/clixon_xsl.h b/lib/clixon/clixon_xsl.h index af1a4926..3499cc97 100644 --- a/lib/clixon/clixon_xsl.h +++ b/lib/clixon/clixon_xsl.h @@ -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 */ diff --git a/lib/clixon/clixon_yang.h b/lib/clixon/clixon_yang.h index 806baac7..5ea7e986 100644 --- a/lib/clixon/clixon_yang.h +++ b/lib/clixon/clixon_yang.h @@ -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, diff --git a/lib/src/Makefile.in b/lib/src/Makefile.in index 3360934e..8da9b087 100644 --- a/lib/src/Makefile.in +++ b/lib/src/Makefile.in @@ -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 $@ diff --git a/lib/src/clixon_err.c b/lib/src/clixon_err.c index b6f9069d..aa4576df 100644 --- a/lib/src/clixon_err.c +++ b/lib/src/clixon_err.c @@ -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, diff --git a/lib/src/clixon_event.c b/lib/src/clixon_event.c index f23420ac..8bb61b76 100644 --- a/lib/src/clixon_event.c +++ b/lib/src/clixon_event.c @@ -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; diff --git a/lib/src/clixon_file.c b/lib/src/clixon_file.c index 12df1b83..160d3145 100644 --- a/lib/src/clixon_file.c +++ b/lib/src/clixon_file.c @@ -241,12 +241,11 @@ group_name2gid(char *name, gr = &g0; /* This leaks memory in ubuntu */ if (getgrnam_r(name, gr, buf, sizeof(buf), >mp) < 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; } diff --git a/lib/src/clixon_json.c b/lib/src/clixon_json.c index 930dbb6f..38418def 100644 --- a/lib/src/clixon_json.c +++ b/lib/src/clixon_json.c @@ -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); diff --git a/lib/src/clixon_options.c b/lib/src/clixon_options.c index 4f7cc68a..61c8e828 100644 --- a/lib/src/clixon_options.c +++ b/lib/src/clixon_options.c @@ -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, "", 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"); diff --git a/lib/src/clixon_plugin.c b/lib/src/clixon_plugin.c index 2e1ffdfb..3d0b80ae 100644 --- a/lib/src/clixon_plugin.c +++ b/lib/src/clixon_plugin.c @@ -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){ diff --git a/lib/src/clixon_proto.c b/lib/src/clixon_proto.c index f9c9da9f..2a71992e 100644 --- a/lib/src/clixon_proto.c +++ b/lib/src/clixon_proto.c @@ -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; iop_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; diff --git a/lib/src/clixon_util_json.c b/lib/src/clixon_util_json.c new file mode 100644 index 00000000..8cffdf3a --- /dev/null +++ b/lib/src/clixon_util_json.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* cligen */ +#include + +/* clixon */ +#include + +/* + * 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; +} diff --git a/lib/src/clixon_util_xml.c b/lib/src/clixon_util_xml.c new file mode 100644 index 00000000..ee32a9bb --- /dev/null +++ b/lib/src/clixon_util_xml.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include + +/* cligen */ +#include + +/* clixon */ +#include + +/* + * Turn this on to get a xml parse and pretty print test program + * Usage: xpath + * read xml from input + * Example compile: + gcc -g -o xml -I. -I../clixon ./clixon_xml.c -lclixon -lcligen + * Example run: + echo "" | xml +*/ +static int +usage(char *argv0) +{ + fprintf(stderr, "usage:%s.\n\tInput on stdin\n", argv0); + exit(0); +} + +int +main(int argc, char **argv) +{ + cxobj *xt = NULL; + cxobj *xc; + cbuf *cb = cbuf_new(); + + if (argc != 1){ + usage(argv[0]); + return 0; + } + if (xml_parse_file(0, "", NULL, &xt) < 0){ + fprintf(stderr, "xml parse error %s\n", clicon_err_reason); + 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; +} + + diff --git a/lib/src/clixon_util_xsl.c b/lib/src/clixon_util_xsl.c new file mode 100644 index 00000000..b23d1c52 --- /dev/null +++ b/lib/src/clixon_util_xsl.c @@ -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 [] + * 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" | xpath +*/ + +#ifdef HAVE_CONFIG_H +#include "clixon_config.h" /* generated by config & autoconf */ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* cligen */ +#include + +/* clixon */ +#include + + +static int +usage(char *argv0) +{ + fprintf(stderr, "usage:%s .\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, "", 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 +#include +#include +#include +#include +#define __USE_GNU /* strverscmp */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* cligen */ +#include + +/* clixon */ +#include + +/* +*/ +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; +} + diff --git a/lib/src/clixon_xml.c b/lib/src/clixon_xml.c index 63be3008..8816aff2 100644 --- a/lib/src/clixon_xml.c +++ b/lib/src/clixon_xml.c @@ -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 "" | xml */ -#if 0 /* Test program */ +#if 1 /* Test program */ static int usage(char *argv0) diff --git a/lib/src/clixon_xml_db.c b/lib/src/clixon_xml_db.c index 8702910d..b909385b 100644 --- a/lib/src/clixon_xml_db.c +++ b/lib/src/clixon_xml_db.c @@ -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; diff --git a/lib/src/clixon_xml_map.c b/lib/src/clixon_xml_map.c index cac926d9..7e1b69e4 100644 --- a/lib/src/clixon_xml_map.c +++ b/lib/src/clixon_xml_map.c @@ -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]; diff --git a/lib/src/clixon_xml_parse.l b/lib/src/clixon_xml_parse.l index f9c43a93..57000d0e 100644 --- a/lib/src/clixon_xml_parse.l +++ b/lib/src/clixon_xml_parse.l @@ -116,7 +116,7 @@ int clixon_xml_parsewrap(void) "lt; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = "<"; return CHARDATA;} "gt; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = ">"; return CHARDATA;} "apos; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = "'"; return CHARDATA;} -"aquot; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = "'"; return CHARDATA;} +"quot; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = "\""; return CHARDATA;} . { clixon_xml_parselval.string = yytext; return CHARDATA;} \n { clixon_xml_parselval.string = yytext;_YA->ya_linenum++; return (CHARDATA);} diff --git a/lib/src/clixon_xsl.c b/lib/src/clixon_xsl.c index 6b40ec3e..a758be52 100644 --- a/lib/src/clixon_xsl.c +++ b/lib/src/clixon_xsl.c @@ -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; diff --git a/lib/src/clixon_yang.c b/lib/src/clixon_yang.c index 93025cc1..76a8ff98 100644 --- a/lib/src/clixon_yang.c +++ b/lib/src/clixon_yang.c @@ -45,11 +45,14 @@ #include #include #include +#include #define __USE_GNU /* strverscmp */ #include #include #include #include +#include +#include #include #include #include @@ -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: .."); + clicon_err(OE_YANG, 0, "range statement: %s not on the form: ..", + 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 : */ @@ -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; } diff --git a/lib/src/clixon_yang_parse.h b/lib/src/clixon_yang_parse.h index 0b9b1ec4..baa136df 100644 --- a/lib/src/clixon_yang_parse.h +++ b/lib/src/clixon_yang_parse.h @@ -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 */ diff --git a/lib/src/clixon_yang_parse.y b/lib/src/clixon_yang_parse.y index eb48253f..219f9766 100644 --- a/lib/src/clixon_yang_parse.y +++ b/lib/src/clixon_yang_parse.y @@ -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 */ diff --git a/lib/src/clixon_yang_type.c b/lib/src/clixon_yang_type.c index 73a0097c..a67500db 100644 --- a/lib/src/clixon_yang_type.c +++ b/lib/src/clixon_yang_type.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #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 */ diff --git a/test/Jenkinsfile b/test/Jenkinsfile index 48314e84..b31de847 100644 --- a/test/Jenkinsfile +++ b/test/Jenkinsfile @@ -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') { diff --git a/test/lib.sh b/test/lib.sh index f82907a0..8430584b 100755 --- a/test/lib.sh +++ b/test/lib.sh @@ -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<$RULES]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "$RULES]]>]]>" "^]]>]]>$" new "commit it" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" 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"}}} ' diff --git a/test/test_identity.sh b/test/test_identity.sh index 2d01fa01..3df22c73 100755 --- a/test/test_identity.sh +++ b/test/test_identity.sh @@ -120,47 +120,47 @@ if [ $? -ne 0 ]; then fi new "Set crypto to aes" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "aes]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "aes]]>]]>" "^]]>]]>$" new "netconf validate " -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "Set crypto to mc:aes" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "mc:aes]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "mc:aes]]>]]>" "^]]>]]>$" new "netconf validate" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "Set crypto to des:des3" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "des:des3]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "des:des3]]>]]>" "^]]>]]>$" new "netconf validate" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "Set crypto to mc:foo" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "mc:foo]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "mc:foo]]>]]>" "^]]>]]>$" new "netconf validate" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "Set crypto to des:des3 using xmlns" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "des:des3]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "des:des3]]>]]>" "^]]>]]>$" new "netconf validate" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" # XXX this is not supported #new "Set crypto to x:des3 using xmlns" -#expecteof "$clixon_netconf -qf $cfg -y $fyang" "x:des3]]>]]>" "^]]>]]>$" +#expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "x:des3]]>]]>" "^]]>]]>$" #new "netconf validate" -#expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +#expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "Set crypto to foo:bar" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "foo:bar]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "foo:bar]]>]]>" "^]]>]]>$" new "netconf validate" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^operation-failedapplicationerrorIdentityref validation failed, foo:bar not derived from crypto-alg]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^operation-failedapplicationerrorIdentityref validation failed, foo:bar not derived from crypto-alg]]>]]>$" new "cli set crypto to mc:aes" expectfn "$clixon_cli -1 -f $cfg -l o set crypto mc:aes" 0 "^$" diff --git a/test/test_json.sh b/test/test_json.sh new file mode 100755 index 00000000..63543abd --- /dev/null +++ b/test/test_json.sh @@ -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}' "^-23$" + +new "json parse list" +expecteof $PROG 0 '{"a":[0,1,2,3]}' "^0123$" + +rm -rf $dir diff --git a/test/test_leafref.sh b/test/test_leafref.sh index f18263d4..f5e15dec 100755 --- a/test/test_leafref.sh +++ b/test/test_leafref.sh @@ -84,45 +84,45 @@ if [ $? -ne 0 ]; then fi new "leafref base config" -expecteof "$clixon_netconf -qf $cfg -y $fyang" " +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 " eth0ex:eth
192.0.2.1
192.0.2.2
loex:lo
127.0.0.1
]]>]]>" "^]]>]]>$" new "leafref get config" -expecteof "$clixon_netconf -qf $cfg" ']]>]]>' '^eth0' +expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' '^eth0' new "leafref base commit" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "leafref add wrong ref" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "eth3
10.0.4.6
]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "eth3
10.0.4.6
]]>]]>" "^]]>]]>$" new "leafref validate XXX shouldnt really be operation-failed, more work in validate code" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^operation-failed" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^operation-failed" new "leafref discard-changes" -expecteof "$clixon_netconf -qf $cfg" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "leafref add correct absref" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "eth0]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "eth0]]>]]>" "^]]>]]>$" new "leafref add correct relref" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "eth0]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "eth0]]>]]>" "^]]>]]>$" # XXX add address new "leafref validate (ok)" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^" new "leafref delete leaf" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "eth0]]>]]>" "^" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "eth0]]>]]>" "^" new "leafref validate (should fail)" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^operation-failed" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^operation-failed" new "leafref discard-changes" -expecteof "$clixon_netconf -qf $cfg" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "cli leafref lo" expectfn "$clixon_cli -1f $cfg -y $fyang -l o set default-address absname lo" 0 "^$" diff --git a/test/test_netconf.sh b/test/test_netconf.sh index 0fbd63f5..02982e5a 100755 --- a/test/test_netconf.sh +++ b/test/test_netconf.sh @@ -81,132 +81,132 @@ if [ $? -ne 0 ]; then fi new "netconf get-config" -expecteof "$clixon_netconf -qf $cfg -y $fyang" ']]>]]>' '^]]>]]>$' +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' '^]]>]]>$' new "Add subtree eth/0/0 using none which should not change anything" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "noneeth/0/0]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "noneeth/0/0]]>]]>" "^]]>]]>$" new "Check nothing added" -expecteof "$clixon_netconf -qf $cfg -y $fyang" ']]>]]>' '^]]>]]>$' +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' '^]]>]]>$' new "Add subtree eth/0/0 using none and create which should add eth/0/0" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 'eth/0/0ex:ethnone ]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'eth/0/0ex:ethnone ]]>]]>' "^]]>]]>$" new "Check eth/0/0 added using xpath" -expecteof "$clixon_netconf -qf $cfg -y $fyang" ']]>]]>' "^eth/0/0ex:ethtrue]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' "^eth/0/0ex:ethtrue]]>]]>$" new "Re-create same eth/0/0 which should generate error" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 'eth/0/0ex:ethnone ]]>]]>' "^" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'eth/0/0ex:ethnone ]]>]]>' "^" new "Delete eth/0/0 using none config" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 'eth/0/0ex:ethnone ]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'eth/0/0ex:ethnone ]]>]]>' "^]]>]]>$" new "Check deleted eth/0/0 (non-presence container)" -expecteof "$clixon_netconf -qf $cfg -y $fyang" ']]>]]>' '^]]>]]>$' +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' '^]]>]]>$' new "Re-Delete eth/0/0 using none should generate error" -expecteof "$clixon_netconf -qf $cfg -y $fyang" 'eth/0/0ex:ethnone ]]>]]>' "^" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 'eth/0/0ex:ethnone ]]>]]>' "^" new "netconf edit config" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "eth/0/0eth1true
9.2.3.424
]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "eth/0/0eth1true
9.2.3.424
]]>]]>" "^]]>]]>$" new "netconf get config xpath" -expecteof "$clixon_netconf -qf $cfg -y $fyang" ']]>]]>' "^eth1true]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' "^eth1true]]>]]>$" new "netconf get config xpath parent" -expecteof "$clixon_netconf -qf $cfg -y $fyang" ']]>]]>' "^eth/0/0trueeth1truetruefalse
9.2.3.424
]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' "^eth/0/0trueeth1truetruefalse
9.2.3.424
]]>]]>$" new "netconf validate missing type" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^" new "netconf discard-changes" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "netconf get empty config2" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "netconf edit extra xml" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^" new "netconf discard-changes" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "netconf edit config eth1" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "eth1ex:eth]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "eth1ex:eth]]>]]>" "^]]>]]>$" new "netconf validate" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "netconf commit" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "netconf edit config merge" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "eth2ex:ethmerge]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "eth2ex:ethmerge]]>]]>" "^]]>]]>$" new "netconf edit ampersand encoding(<&): name:'eth&' type:'t<>'" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "eth& t< > ]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "eth& t< > ]]>]]>" "^]]>]]>$" new "netconf get replaced config" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^eth& t< > trueeth1ex:ethtrueeth2ex:ethtrue]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^eth& t< > trueeth1ex:ethtrueeth2ex:ethtrue]]>]]>$" 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" "eth/0/0ex:eth]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "eth/0/0ex:eth]]>]]>" "^]]>]]>$" #new "netconf get CDATA" -#expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "eth/0/0true]]>]]>" +#expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "eth/0/0true]]>]]>" new "netconf discard-changes" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "netconf edit state operation should fail" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "eth1ex:eth]]>]]>" "^invalid-value" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "eth1ex:eth]]>]]>" "^invalid-value" new "netconf get state operation" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^eth0ex:eth42]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^eth0ex:eth42]]>]]>$" new "netconf lock/unlock" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>]]>]]>" "^]]>]]>]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>]]>]]>" "^]]>]]>]]>]]>$" new "netconf lock/lock" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "netconf lock" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "close-session" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "kill-session" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "44]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "44]]>]]>" "^]]>]]>$" new "copy startup" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "netconf get startup" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^eth1ex:ethtrue]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^eth1ex:ethtrue]]>]]>$" new "netconf delete startup" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "netconf check empty startup" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "netconf rpc" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "ipv4ipv4]]>]]>" "^ipv4" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "ipv4ipv4]]>]]>" "^ipv4" new "netconf rpc w/o namespace" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "ipv4ipv4]]>]]>" "^ipv4" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "ipv4ipv4]]>]]>" "^ipv4" new "netconf empty rpc" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "netconf client-side rpc" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "example]]>]]>" "^ok]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "example]]>]]>" "^ok]]>]]>$" new "netconf subscription" expectwait "$clixon_netconf -qf $cfg -y $fyang" "ROUTING]]>]]>" "^]]>]]>Routing notification]]>]]>$" 30 diff --git a/test/test_order.sh b/test/test_order.sh index a046d5c6..64eaace4 100755 --- a/test/test_order.sh +++ b/test/test_order.sh @@ -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" "]]>]]>" "^hejhoppdbcaabcddbarabarcbarbbarabarbbarcbardbar]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^hejhoppdbcaabcddbarabarcbarbbarabarbbarcbardbar]]>]]>$" new "get each ordered-by user leaf-list" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^abar]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^abar]]>]]>$" new "get each ordered-by user leaf-list" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^abar]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^abar]]>]]>$" new "get each ordered-by user leaf-list" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^bbar]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^bbar]]>]]>$" new "get each ordered-by user leaf-list" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^bbar]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^bbar]]>]]>$" new "delete candidate" -expecteof "$clixon_netconf -qf $cfg" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" # LEAF_LISTS new "add two entries to leaf-list user order" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "cb]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "cb]]>]]>" "^]]>]]>$" new "add one entry to leaf-list user order" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "a]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "a]]>]]>" "^]]>]]>$" new "netconf commit" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "add one entry to leaf-list user order after commit" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "0]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "0]]>]]>" "^]]>]]>$" new "netconf commit" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "verify leaf-list user order in running (as entered)" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^cba0]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^cba0]]>]]>$" # LISTS new "add two entries to list user order" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "cbarbfoo]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "cbarbfoo]]>]]>" "^]]>]]>$" new "add one entry to list user order" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "afie]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "afie]]>]]>" "^]]>]]>$" new "verify list user order (as entered)" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^cbarbfooafie]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^cbarbfooafie]]>]]>$" pid=`pgrep clixon_backend` if [ -z "$pid" ]; then diff --git a/test/test_perf.sh b/test/test_perf.sh index 8ad933e1..16f7b19a 100755 --- a/test/test_perf.sh +++ b/test/test_perf.sh @@ -99,13 +99,13 @@ expecteof_file "time -f %e $clixon_netconf -qf $cfg -y $fyang" "$fconfig" "^]]>]]>" "^]]>]]>$" +expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "netconf commit large config again" -expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "netconf add small (1 entry) config" -expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" "xy]]>]]>" "^]]>]]>$" +expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" 0 "xy]]>]]>" "^]]>]]>$" 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" "]]>]]>" "^0011" +expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^0011" new "generate large leaf-list config" echo -n "replace" > $fconfig @@ -147,7 +147,7 @@ expecteof_file "time -f %e $clixon_netconf -qf $cfg -y $fyang" "$fconfig" "^]]>]]>" "^]]>]]>$" +expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" 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" "x]]>]]>" "^]]>]]>$" +expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" 0 "x]]>]]>" "^]]>]]>$" new "netconf commit small leaf-list config" -expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "netconf get large leaf-list config" -expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^01" +expecteof "time -f %e $clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^01" new "Kill backend" # Check if still alive diff --git a/test/test_startup.sh b/test/test_startup.sh index 7c3208f0..d3cdcd54 100755 --- a/test/test_startup.sh +++ b/test/test_startup.sh @@ -87,7 +87,7 @@ EOF fi new "Check $mode" - expecteof "$clixon_netconf -qf $cfg" ']]>]]>' "^$expect]]>]]>$" + expecteof "$clixon_netconf -qf $cfg" 0 ']]>]]>' "^$expect]]>]]>$" new "Kill backend" # Check if still alive diff --git a/test/test_type.sh b/test/test_type.sh index 2658fe8a..1535f3b3 100755 --- a/test/test_type.sh +++ b/test/test_type.sh @@ -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" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "netconf set ab wrong" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "a.b& c.d]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "a.b& c.d]]>]]>" "^]]>]]>$" new "netconf validate" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^" new "netconf discard-changes" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "netconf commit" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" 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" "create read]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "create read]]>]]>" "^]]>]]>$" new "cli bits validate" expectfn "$clixon_cli -1f $cfg -l o -y $fyang validate" 0 "^$" diff --git a/test/test_xml.sh b/test/test_xml.sh new file mode 100755 index 00000000..4dd63631 --- /dev/null +++ b/test/test_xml.sh @@ -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 "" "^$" + +XML=$(cat <An example of escaped CENDs + + y" so I guess that means that z > x ]]> + + + +]]> + +]]> + +EOF +) +new "xml CDATA" +expecteof $PROG 0 "$XML" "^An example of escaped CENDs + y\" so I guess that means that z > x ]]> +]]>]]>$" + +XML=$(cat <Less than: < , greater than: > ampersand: & +EOF +) +new "xml encode <>&" +expecteof $PROG 0 "$XML" "^$XML$" + +XML=$(cat <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 " +EOF +) +new "xml optional encode single and double quote" +expecteof $PROG 0 "$XML" "^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 \"$" + +rm -rf $dir + diff --git a/test/test_xsl.sh b/test/test_xsl.sh new file mode 100755 index 00000000..b7e322ad --- /dev/null +++ b/test/test_xsl.sh @@ -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 +" "^0:$" + +rm -rf $dir diff --git a/test/test_yang.sh b/test/test_yang.sh index 86c56b3b..1e542501 100755 --- a/test/test_yang.sh +++ b/test/test_yang.sh @@ -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" "125one]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "125one]]>]]>" "^]]>]]>$" new "netconf commit" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" # text empty type in running new "netconf commit 2nd" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "netconf get config xpath" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^125one]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^125one]]>]]>$" new "netconf edit leaf-list" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "hejhopp]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "hejhopp]]>]]>" "^]]>]]>$" new "netconf get leaf-list" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^hejhopp]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^hejhopp]]>]]>$" new "netconf get leaf-list path" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^hejhopp]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^hejhopp]]>]]>$" new "netconf get (should be some)" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^125one]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^125one]]>]]>$" 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 "foo" new "netconf set state data (not allowed)" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "42]]>]]>" "^invalid-value" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "42]]>]]>" "^invalid-value" new "netconf set presence and not present" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "netconf get presence only" -expecteof "$clixon_netconf -qf $cfg -y $fyang" ']]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' "^]]>]]>$" new "netconf discard-changes" -expecteof "$clixon_netconf -qf $cfg" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "netconf anyxml" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "netconf validate anyxml" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" new "netconf delete candidate" -expecteof "$clixon_netconf -qf $cfg" "]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" # Check 3-keys new "netconf add one 3-key entry" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "111one]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "111one]]>]]>" "^]]>]]>$" new "netconf check add one 3-key" -expecteof "$clixon_netconf -qf $cfg -y $fyang" ']]>]]>' '111one]]>]]>' +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' '111one]]>]]>' new "netconf add another (with same 1st key)" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "121two]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "121two]]>]]>" "^]]>]]>$" new "netconf check add another" -expecteof "$clixon_netconf -qf $cfg -y $fyang" ']]>]]>' '111one121two]]>]]>' +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' '111one121two]]>]]>' new "netconf replace first" -expecteof "$clixon_netconf -qf $cfg -y $fyang" "111replace]]>]]>" "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "111replace]]>]]>" "^]]>]]>$" new "netconf check replace" -expecteof "$clixon_netconf -qf $cfg -y $fyang" ']]>]]>' '111replace121two]]>]]>' +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' '111replace121two]]>]]>' new "netconf delete first" -expecteof "$clixon_netconf -qf $cfg -y $fyang" '111]]>]]>' "^]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '111]]>]]>' "^]]>]]>$" new "netconf check delete" -expecteof "$clixon_netconf -qf $cfg -y $fyang" ']]>]]>' '121two]]>]]>' +expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 ']]>]]>' '121two]]>]]>' # Check if still alive pid=`pgrep clixon_backend` diff --git a/test/test_yang_parse.sh b/test/test_yang_parse.sh new file mode 100755 index 00000000..1a80c89d --- /dev/null +++ b/test/test_yang_parse.sh @@ -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 <