netconf error handling and test summary script

This commit is contained in:
Olof hagsand 2018-12-21 14:44:59 +01:00
parent f872c7e295
commit 861300d6c0
23 changed files with 331 additions and 189 deletions

View file

@ -20,7 +20,8 @@
* Openconfig yang specs parsed: https://github.com/openconfig/public
* Improved "unknown" handling
* More precise Yang validation and better error messages
* For Example, adding bad-, missing-, or unknown-element error messages, etc instead of operation-failed
* Example: adding bad-, missing-, or unknown-element error messages, etc instead of operation-failed, bad-element instead of "yang node not found", etc.
*
* Yang load file configure options changed
* `CLICON_YANG_DIR` is changed from a single directory to a path of directories
* Note CLIXON_DATADIR (=/usr/local/share/clixon) need to be in the list

View file

@ -44,6 +44,7 @@
* (Duplicated. Also in netconf_*.h)
*/
int netconf_output(int s, cbuf *xf, char *msg);
int netconf_output_encap(int s, cbuf *xf, char *msg);
int netconf_xpath(cxobj *xsearch,
cxobj *xfilter,

View file

@ -182,9 +182,9 @@ netconf_get_target(cxobj *xn,
* @param[in] s
* @param[in] cb Cligen buffer that contains the XML message
* @param[in] msg Only for debug
* @note Assumes "cb" contains valid XML, ie encoding is correct. This is done
* if it is output by a xml render routine (xml_print et al), but NOT
* otherwise.
* @retval 0 OK
* @retval -1 Error
* @see netconf_output_encap for function with encapsulation
*/
int
netconf_output(int s,
@ -216,3 +216,34 @@ netconf_output(int s,
return retval;
}
/*! Encapsulate and send outgoing netconf packet as cbuf on socket
* @param[in] s
* @param[in] cb Cligen buffer that contains the XML message
* @param[in] msg Only for debug
* @retval 0 OK
* @retval -1 Error
* @note Assumes "cb" contains valid XML
* @see netconf_output without encapsulation
*/
int
netconf_output_encap(int s,
cbuf *cb,
char *msg)
{
int retval = -1;
cbuf *cb1 = NULL;
if ((cb1 = cbuf_new()) == NULL){
clicon_err(OE_XML, errno, "cbuf_new");
goto done;
}
add_preamble(cb1);
cprintf(cb1, "%s", cbuf_get(cb));
add_postamble(cb1);
retval = netconf_output(s, cb1, msg);
done:
if (cb1)
cbuf_free(cb1);
return retval;
}

View file

@ -75,5 +75,6 @@ int add_error_preamble(cbuf *xf, char *reason);
char *netconf_get_target(cxobj *xn, char *path);
int add_error_postamble(cbuf *xf);
int netconf_output(int s, cbuf *xf, char *msg);
int netconf_output_encap(int s, cbuf *cb, char *msg);
#endif /* _NETCONF_LIB_H_ */

View file

@ -112,7 +112,7 @@ process_incoming_packet(clicon_handle h,
free(str0);
if (netconf_operation_failed(cbret, "rpc", "internal error")< 0)
goto done;
netconf_output(1, cbret, "rpc-error");
netconf_output_encap(1, cbret, "rpc-error");
goto done;
}
free(str0);
@ -121,7 +121,7 @@ process_incoming_packet(clicon_handle h,
if ((ret = xml_yang_validate_rpc(xrpc, cbret)) < 0)
goto done;
if (ret == 0){
netconf_output(1, cbret, "rpc-error");
netconf_output_encap(1, cbret, "rpc-error");
goto ok;
}
}
@ -157,11 +157,8 @@ process_incoming_packet(clicon_handle h,
if (xml_addsub(xc, xa2) < 0)
goto done;
}
add_preamble(cbret);
clicon_xml2cbuf(cbret, xml_child_i(xret,0), 0, 0);
add_postamble(cbret);
if (netconf_output(1, cbret, "rpc-reply") < 0){
if (netconf_output_encap(1, cbret, "rpc-reply") < 0){
cbuf_free(cbret);
goto done;
}

View file

@ -776,12 +776,10 @@ netconf_notification_cb(int s,
clicon_err(OE_PLUGIN, errno, "cbuf_new");
goto done;
}
add_preamble(cb); /* Make it well-formed netconf xml */
if (clicon_xml2cbuf(cb, xn, 0, 0) < 0)
goto done;
add_postamble(cb);
/* Send it to listening client on stdout */
if (netconf_output(1, cb, "notification") < 0){
if (netconf_output_encap(1, cb, "notification") < 0){
cbuf_free(cb);
goto done;
}
@ -925,13 +923,13 @@ netconf_application_rpc(clicon_handle h,
if ((ret = xml_yang_validate_all_top(xn, cbret)) < 0)
goto done;
if (ret == 0){
netconf_output(1, cbret, "rpc-error");
netconf_output_encap(1, cbret, "rpc-error");
goto ok;
}
if ((ret = xml_yang_validate_add(xn, cbret)) < 0)
goto done;
if (ret == 0){
netconf_output(1, cbret, "rpc-error");
netconf_output_encap(1, cbret, "rpc-error");
goto ok;
}
}

View file

@ -450,10 +450,12 @@ api_return_err(clicon_handle h,
else
if (xml2json_cbuf(cb, xerr, pretty) < 0)
goto done;
clicon_debug(1, "%s code:%d err:%s", __FUNCTION__, code, cbuf_get(cb));
FCGX_SetExitStatus(code, r->out); /* Created */
FCGX_FPrintF(r->out, "Status: %d %s\r\n", code, reason_phrase);
FCGX_FPrintF(r->out, "Content-Type: application/yang-data+%s\r\n\r\n",
use_xml?"xml":"json");
if (use_xml){
if (pretty){
FCGX_FPrintF(r->out, " <errors xmlns=\"urn:ietf:params:xml:ns:yang:ietf-restconf\">\n", cbuf_get(cb));

View file

@ -1118,15 +1118,8 @@ api_operations_post(clicon_handle h,
goto ok;
}
if ((yrpc = yang_find((yang_node*)ys, Y_RPC, id)) == NULL){
if (netconf_operation_failed_xml(&xerr, "protocol", "yang node not found") < 0)
goto done;
if ((xe = xpath_first(xerr, "rpc-error")) != NULL)
if (api_return_err(h, r, xe, pretty, use_xml) < 0)
goto done;
goto ok;
}
if (yrpc == NULL){
if (netconf_operation_failed_xml(&xerr, "protocol", "yang node not found") < 0)
clicon_debug(1, "%s rpc %s not found", __FUNCTION__, id);
if (netconf_missing_element_xml(&xerr, "application", id, "RPC not defined") < 0)
goto done;
if ((xe = xpath_first(xerr, "rpc-error")) != NULL)
if (api_return_err(h, r, xe, pretty, use_xml) < 0)

View file

@ -26,6 +26,10 @@ module example {
}
/* Translation function example - See also example_cli */
list translate{
key k;
leaf k{
type string;
}
leaf value{
type string;
}
@ -73,6 +77,57 @@ module example {
}
}
}
rpc empty {
description "Smallest possible RPC with no input or output";
}
rpc example {
description "Some example input/output for testing RFC7950 7.14.
RPC simply echoes the input for debugging.";
input {
leaf x {
description
"If a leaf in the input tree has a 'mandatory' statement with
the value 'true', the leaf MUST be present in an RPC invocation.";
type string;
mandatory true;
}
leaf y {
description
"If a leaf in the input tree has a 'mandatory' statement with the
value 'true', the leaf MUST be present in an RPC invocation.";
type string;
default "42";
}
leaf-list z {
description
"If a leaf-list in the input tree has one or more default
values, the server MUST use these values (XXX not supported)";
type string;
}
leaf w {
description
"If any node has a 'when' statement that would evaluate to
'false',then this node MUST NOT be present in the input tree.
(XXX not supported)";
type string;
when "/translate/k=5/value='w'";
}
}
output {
leaf x {
type string;
}
leaf y {
type string;
}
leaf z {
type string;
}
leaf w {
type string;
}
}
}
rpc debug {
description "Set debug level of backend. XXX should be in clixon-config";
input {

View file

@ -47,8 +47,11 @@ int netconf_missing_attribute(cbuf *cb, char *type, char *info, char *message);
int netconf_bad_attribute(cbuf *cb, char *type, char *info, char *message);
int netconf_unknown_attribute(cbuf *cb, char *type, char *info, char *message);
int netconf_missing_element(cbuf *cb, char *type, char *element, char *message);
int netconf_missing_element_xml(cxobj **xret, char *type, char *element, char *message);
int netconf_bad_element(cbuf *cb, char *type, char *info, char *element);
int netconf_bad_element_xml(cxobj **xret, char *type, char *info, char *element);
int netconf_unknown_element(cbuf *cb, char *type, char *element, char *message);
int netconf_unknown_element_xml(cxobj **xret, char *type, char *element, char *message);
int netconf_unknown_namespace(cbuf *cb, char *type, char *info, char *message);
int netconf_access_denied(cbuf *cb, char *type, char *message);
int netconf_access_denied_xml(cxobj **xret, char *type, char *message);

View file

@ -307,6 +307,45 @@ netconf_unknown_attribute(cbuf *cb,
goto done;
}
/*! Common Netconf element XML tree according to RFC 6241 App A
* @param[out] xret Error XML tree. Free with xml_free after use
* @param[in] type Error type: "application" or "protocol"
* @param[in] tag Error tag
* @param[in] element bad-element xml
* @param[in] message Error message
*/
static int
netconf_element_xml_common(cxobj **xret,
char *type,
char *tag,
char *element,
char *message)
{
int retval =-1;
cxobj *xerr;
if (*xret == NULL){
if ((*xret = xml_new("rpc-reply", NULL, NULL)) == NULL)
goto done;
}
else if (xml_name_set(*xret, "rpc-reply") < 0)
goto done;
if ((xerr = xml_new("rpc-error", *xret, NULL)) == NULL)
goto done;
if (xml_parse_va(&xerr, NULL, "<error-type>%s</error-type>"
"<error-tag>%s</error-tag>"
"<error-info><bad-element>%s</bad-element></error-info>"
"<error-severity>error</error-severity>",
type, tag, element) < 0)
goto done;
if (message && xml_parse_va(&xerr, NULL, "<error-message>%s</error-message>",
message) < 0)
goto done;
retval = 0;
done:
return retval;
}
/*! Create Netconf missing-element error XML tree according to RFC 6241 App A
*
* An expected element is missing.
@ -322,31 +361,33 @@ netconf_missing_element(cbuf *cb,
char *message)
{
int retval = -1;
char *encstr = NULL;
cxobj *xret = NULL;
if (cprintf(cb, "<rpc-reply><rpc-error>"
"<error-type>%s</error-type>"
"<error-tag>missing-element</error-tag>"
"<error-info><bad-element>%s</bad-element></error-info>"
"<error-severity>error</error-severity>",
type, element) <0)
goto err;
if (message){
if (xml_chardata_encode(&encstr, "%s", message) < 0)
if (netconf_element_xml_common(&xret, type, "missing-element", element, message) < 0)
goto done;
if (clicon_xml2cbuf(cb, xret, 0, 0) < 0)
goto done;
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
goto err;
}
if (cprintf(cb, "</rpc-error></rpc-reply>") <0)
goto err;
retval = 0;
done:
if (encstr)
free(encstr);
if (xret)
xml_free(xret);
return retval;
err:
clicon_err(OE_XML, errno, "cprintf");
goto done;
}
/*! Create Netconf missing-element error XML tree according to RFC 6241 App A
* @param[out] xret Error XML tree. Free with xml_free after use
* @param[in] type Error type: "application" or "protocol"
* @param[in] element bad-element xml
* @param[in] message Error message
*/
int
netconf_missing_element_xml(cxobj **xret,
char *type,
char *element,
char *message)
{
return netconf_element_xml_common(xret, type, "missing-element", element, message);
}
/*! Create Netconf bad-element error XML tree according to RFC 6241 App A
@ -365,31 +406,25 @@ netconf_bad_element(cbuf *cb,
char *message)
{
int retval = -1;
char *encstr = NULL;
cxobj *xret = NULL;
if (cprintf(cb, "<rpc-reply><rpc-error>"
"<error-type>%s</error-type>"
"<error-tag>bad-element</error-tag>"
"<error-info><bad-element>%s</bad-element></error-info>"
"<error-severity>error</error-severity>",
type, element) <0)
goto err;
if (message){
if (xml_chardata_encode(&encstr, "%s", message) < 0)
if (netconf_element_xml_common(&xret, type, "bad-element", element, message) < 0)
goto done;
if (clicon_xml2cbuf(cb, xret, 0, 0) < 0)
goto done;
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
goto err;
}
if (cprintf(cb, "</rpc-error></rpc-reply>") <0)
goto err;
retval = 0;
done:
if (encstr)
free(encstr);
if (xret)
xml_free(xret);
return retval;
err:
clicon_err(OE_XML, errno, "cprintf");
goto done;
}
int
netconf_bad_element_xml(cxobj **xret,
char *type,
char *element,
char *message)
{
return netconf_element_xml_common(xret, type, "bad-element", element, message);
}
/*! Create Netconf unknown-element error XML tree according to RFC 6241 App A
@ -407,31 +442,25 @@ netconf_unknown_element(cbuf *cb,
char *message)
{
int retval = -1;
char *encstr = NULL;
cxobj *xret = NULL;
if (cprintf(cb, "<rpc-reply><rpc-error>"
"<error-type>%s</error-type>"
"<error-tag>unknown-element</error-tag>"
"<error-info><bad-element>%s</bad-element></error-info>"
"<error-severity>error</error-severity>",
type, element) <0)
goto err;
if (message){
if (xml_chardata_encode(&encstr, "%s", message) < 0)
if (netconf_element_xml_common(&xret, type, "unknown-element", element, message) < 0)
goto done;
if (clicon_xml2cbuf(cb, xret, 0, 0) < 0)
goto done;
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
goto err;
}
if (cprintf(cb, "</rpc-error></rpc-reply>") <0)
goto err;
retval = 0;
done:
if (encstr)
free(encstr);
if (xret)
xml_free(xret);
return retval;
err:
clicon_err(OE_XML, errno, "cprintf");
goto done;
}
int
netconf_unknown_element_xml(cxobj **xret,
char *type,
char *element,
char *message)
{
return netconf_element_xml_common(xret, type, "unknown-element", element, message);
}
/*! Create Netconf unknown-namespace error XML tree according to RFC 6241 App A
@ -476,13 +505,14 @@ netconf_unknown_namespace(cbuf *cb,
goto done;
}
/*! Create Netconf access-denied error XML tree according to RFC 6241 App A
/*! Create Netconf access-denied error cbuf according to RFC 6241 App A
*
* Access to the requested protocol operation or data model is denied because
* authorization failed.
* @param[out] cb CLIgen buf. Error XML is written in this buffer
* @param[in] type Error type: "application" or "protocol"
* @param[in] message Error message
* @see netconf_access_denied_xml Same but returns XML tree
*/
int
netconf_access_denied(cbuf *cb,
@ -490,39 +520,33 @@ netconf_access_denied(cbuf *cb,
char *message)
{
int retval = -1;
char *encstr = NULL;
cxobj *xret = NULL;
if (cprintf(cb, "<rpc-reply><rpc-error>"
"<error-type>%s</error-type>"
"<error-tag>access-denied</error-tag>"
"<error-severity>error</error-severity>",
type) <0)
goto err;
if (message){
if (xml_chardata_encode(&encstr, "%s", message) < 0)
if (netconf_access_denied_xml(&xret, type, message) < 0)
goto done;
if (clicon_xml2cbuf(cb, xret, 0, 0) < 0)
goto done;
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
goto err;
}
if (cprintf(cb, "</rpc-error></rpc-reply>") <0)
goto err;
retval = 0;
done:
if (encstr)
free(encstr);
if (xret)
xml_free(xret);
return retval;
err:
clicon_err(OE_XML, errno, "cprintf");
goto done;
}
/*! Create Netconf access-denied error XML tree according to RFC 6241 App A
*
* Access to the requested protocol operation or data model is denied because
* authorization failed.
* @param[out] xret Error XML tree
* @param[out] xret Error XML tree. Free with xml_free after use
* @param[in] type Error type: "application" or "protocol"
* @param[in] message Error message
* @code
* cxobj *xret = NULL;
* if (netconf_access_denied_xml(&xret, "protocol", "Unauthorized") < 0)
* err;
* xml_free(xret);
* @endcode
* @see netconf_access_denied Same but returns cligen buffer
*/
int
netconf_access_denied_xml(cxobj **xret,
@ -795,6 +819,7 @@ netconf_operation_not_supported(cbuf *cb,
* @param[out] cb CLIgen buf. Error XML is written in this buffer
* @param[in] type Error type: "rpc", "application" or "protocol"
* @param[in] message Error message
* @see netconf_operation_failed_xml Same but returns XML tree
*/
int
netconf_operation_failed(cbuf *cb,
@ -802,30 +827,17 @@ netconf_operation_failed(cbuf *cb,
char *message)
{
int retval = -1;
char *encstr = NULL;
cxobj *xret = NULL;
if (cprintf(cb, "<rpc-reply><rpc-error>"
"<error-type>%s</error-type>"
"<error-tag>operation-failed</error-tag>"
"<error-severity>error</error-severity>",
type) <0)
goto err;
if (message){
if (xml_chardata_encode(&encstr, "%s", message) < 0)
if (netconf_operation_failed_xml(&xret, type, message) < 0)
goto done;
if (clicon_xml2cbuf(cb, xret, 0, 0) < 0)
goto done;
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
goto err;
}
if (cprintf(cb, "</rpc-error></rpc-reply>") < 0)
goto err;
retval = 0;
done:
if (encstr)
free(encstr);
if (xret)
xml_free(xret);
return retval;
err:
clicon_err(OE_XML, errno, "cprintf");
goto done;
}
/*! Create Netconf operation-failed error XML tree according to RFC 6241 App A
@ -835,6 +847,13 @@ netconf_operation_failed(cbuf *cb,
* @param[out] xret Error XML tree
* @param[in] type Error type: "rpc", "application" or "protocol"
* @param[in] message Error message
* @code
* cxobj *xret = NULL;
* if (netconf_operation_failed_xml(&xret, "protocol", "Unauthorized") < 0)
* err;
* xml_free(xret);
* @endcode
* @see netconf_operation_failed Same but returns cligen buffer
*/
int
netconf_operation_failed_xml(cxobj **xret,
@ -872,35 +891,24 @@ netconf_operation_failed_xml(cxobj **xret,
* @param[out] cb CLIgen buf. Error XML is written in this buffer
* @param[in] message Error message
* @note New in :base:1.1
* @see netconf_malformed_message_xml Same but returns XML tree
*/
int
netconf_malformed_message(cbuf *cb,
char *message)
{
int retval = -1;
char *encstr = NULL;
cxobj *xret = NULL;
if (cprintf(cb, "<rpc-reply><rpc-error>"
"<error-type>rpc</error-type>"
"<error-tag>malformed-message</error-tag>"
"<error-severity>error</error-severity>") <0)
goto err;
if (message){
if (xml_chardata_encode(&encstr, "%s", message) < 0)
if (netconf_malformed_message_xml(&xret, message) < 0)
goto done;
if (clicon_xml2cbuf(cb, xret, 0, 0) < 0)
goto done;
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
goto err;
}
if (cprintf(cb, "</rpc-error></rpc-reply>") <0)
goto err;
retval = 0;
done:
if (encstr)
free(encstr);
if (xret)
xml_free(xret);
return retval;
err:
clicon_err(OE_XML, errno, "cprintf");
goto done;
}
/*! Create Netconf malformed-message error XML tree according to RFC 6241 App A
@ -911,6 +919,13 @@ netconf_malformed_message(cbuf *cb,
* @param[out] xret Error XML tree
* @param[in] message Error message
* @note New in :base:1.1
* @code
* cxobj *xret = NULL;
* if (netconf_malformed_message_xml(&xret, "Unauthorized") < 0)
* err;
* xml_free(xret);
* @endcode
* @see netconf_malformed_message Same but returns cligen buffer
*/
int
netconf_malformed_message_xml(cxobj **xret,

View file

@ -398,6 +398,8 @@ validate_identityref(cxobj *xt,
* in [RFC6241]. If output parameters are returned, they are encoded as
* child elements to the <rpc-reply> element defined in [RFC6241], in
* the same order as they are defined within the "output" statement.
* @see xml_yang_validate_all
* @note Should need a variant accepting cxobj **xret
*/
int
xml_yang_validate_rpc(cxobj *xrpc,
@ -454,6 +456,7 @@ xml_yang_validate_rpc(cxobj *xrpc,
* fail;
* @endcode
* @see xml_yang_validate_all
* @note Should need a variant accepting cxobj **xret
*/
int
xml_yang_validate_add(cxobj *xt,
@ -503,15 +506,14 @@ xml_yang_validate_add(cxobj *xt,
* needs to be reparsed when concrete type is selected
*/
if ((body = xml_body(xt)) != NULL){
if (cv_parse(body, cv) <0){
clicon_err(OE_UNIX, errno, "cv_parse");
if (cv_parse1(body, cv, &reason) != 1){
if (netconf_bad_element(cbret, "application", ys->ys_argument, reason) < 0)
goto done;
goto fail;
}
if ((ys_cv_validate(cv, ys, &reason)) != 1){
if (netconf_bad_element(cbret, "application", ys->ys_argument, reason) < 0)
goto done;
if (reason)
free(reason);
goto fail;
}
}
@ -531,6 +533,8 @@ xml_yang_validate_add(cxobj *xt,
done:
if (cv)
cv_free(cv);
if (reason)
free(reason);
return retval;
fail:
retval = 0;
@ -544,7 +548,6 @@ xml_yang_validate_add(cxobj *xt,
* @retval 1 Validation OK
* @retval 0 Validation failed
* @retval -1 Error
* @see xml_yang_validate_add
* @code
* cxobj *x;
* cbuf *cbret = cbuf_new();
@ -553,6 +556,9 @@ xml_yang_validate_add(cxobj *xt,
* if (ret == 0)
* fail;
* @endcode
* @see xml_yang_validate_add
* @see xml_yang_validate_rpc
* @note Should need a variant accepting cxobj **xret
*/
int
xml_yang_validate_all(cxobj *xt,

View file

@ -1,9 +1,9 @@
# Clixon tests
This directory contains testing code for clixon and the example
routing application. Assumes setup of http daemon as describe under apps/restonf
application. Assumes setup of http daemon as describe under apps/restonf
- clixon A top-level script clones clixon in /tmp and starts all.sh. You can copy this file (review it first) and place as cron script
- all.sh Run through all tests named 'test*.sh' in this directory. Therefore, if you place a test in this directory matching 'test*.sh' it will be run automatically.
- all.sh Run through all tests named 'test*.sh' in this directory. Therefore, if you place a test in this directory matching 'test*.sh' it will be run automatically. By default the script will exit on first error. Run as `all.sh summary` to continue and print a summary on all tests.
- test_nacm.sh Auth tests using internal NACM
- test_nacm_ext.sh Auth tests using external NACM (separate file)
- test_cli.sh CLI tests
@ -13,3 +13,14 @@ routing application. Assumes setup of http daemon as describe under apps/restonf
- test_leafref.sh Yang leafref tests
- test_datastore.sh Datastore tests
Example runs:
```
> run.sh
# Runs through all tests matching 'test_*.sh' in the directory. Prints test output
# and stops on first error
> run.sh summary
# Same as above but continues after errors and does not print test output.
```

View file

@ -1,17 +1,43 @@
#!/bin/bash
# Run, eg as:
# ./run.sh 2>&1 | tee test.log
# ./all.sh 2>&1 | tee test.log # break on first test
# ./all.sh summary # to run all tests and print
summary=0
if [ $# -gt 0 ]; then
summary=1
fi
if [ $# -gt 1 ]; then
echo "usage: $0 [summary] # pipe to dev/null and continue on error"
exit -1
fi
# include err() and new() functions
. ./lib.sh
err=0
for test in test*.sh; do
echo "Running $test"
if [ $summary -ne 0 ]; then
./$test > /dev/null 2>&1
errcode=$?
else
./$test
errcode=$?
fi
if [ $errcode -ne 0 ]; then
echo "Error in $test errcode=$errcode"
err=1
echo -e "\e[31mError in $test errcode=$errcode"
echo -ne "\e[0m"
if [ $summary -eq 0 ]; then
exit $errcode
fi
fi
done
echo OK
if [ $err -eq 0 ]; then
echo OK
else
echo -e "\e[31mError"
echo -ne "\e[0m"
fi

View file

@ -38,7 +38,9 @@ if [ ! -d $dir ]; then
fi
rm -rf $dir/*
# error and exit, arg is optional extra errmsg
# error and exit,
# arg1: expected
# arg2: errmsg[optional]
err(){
echo -e "\e[31m\nError in Test$testnr [$testname]:"
if [ $# -gt 0 ]; then
@ -53,7 +55,7 @@ err(){
echo "$expect"| od -t c > $dir/clixon-expect
diff $dir/clixon-expect $dir/clixon-ret
exit $testnr
exit -1 #$testnr
}
# Increment test number and print a nice string
@ -221,8 +223,9 @@ expectwait(){
done
# cat /tmp/flag
if [ $(cat /tmp/flag) != "ok" ]; then
cat /tmp/flag
exit
# err "ok" $(cat /tmp/flag)
# cat /tmp/flag
exit -1
fi
}
@ -250,5 +253,4 @@ expectmatch(){
fi
fi
fi
}

View file

@ -123,7 +123,7 @@ sudo pkill -u www-data -f "/www-data/clixon_restconf"
sleep 1
new "start restconf daemon (-a is enable basic authentication)"
sudo su -c "$clixon_restconf -f $cfg -y $fyang -- -a" -s /bin/sh www-data &
sudo su -c "$clixon_restconf -f $cfg -y $fyang -D $DBG -- -a" -s /bin/sh www-data &
sleep $RCWAIT

View file

@ -155,7 +155,7 @@ new "kill old restconf daemon"
sudo pkill -u www-data -f "/www-data/clixon_restconf"
new "start restconf daemon (-a is enable http basic auth)"
sudo su -c "$clixon_restconf -f $cfg -y $fyang -- -a" -s /bin/sh www-data &
sudo su -c "$clixon_restconf -f $cfg -y $fyang -D $DBG -- -a" -s /bin/sh www-data &
sleep $RCWAIT

View file

@ -147,7 +147,7 @@ sudo pkill -u www-data -f "/www-data/clixon_restconf"
sleep 1
new "start restconf daemon (-a is enable basic authentication)"
sudo su -c "$clixon_restconf -f $cfg -y $fyang -- -a" -s /bin/sh www-data &
sudo su -c "$clixon_restconf -f $cfg -y $fyang -D $DBG -- -a" -s /bin/sh www-data &
sleep $RCWAIT

View file

@ -78,7 +78,7 @@ new "kill old restconf daemon"
sudo pkill -u www-data -f "/www-data/clixon_restconf"
new "start restconf daemon"
sudo su -c "$clixon_restconf -f $cfg -y $fyang" -s /bin/sh www-data &
sudo su -c "$clixon_restconf -f $cfg -y $fyang -D $DBG" -s /bin/sh www-data &
sleep $RCWAIT

View file

@ -282,10 +282,10 @@ new2 "restconf rpc using POST json without mandatory element"
expecteq "$(curl -s -X POST -d '{"input":{"wrongelement":"ipv4"}}' http://localhost/restconf/operations/ietf-routing:fib-route)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "unknown-element","error-info": {"bad-element": "wrongelement"},"error-severity": "error"}}} '
new2 "restconf rpc non-existing rpc without namespace"
expecteq "$(curl -s -X POST -d '{}' http://localhost/restconf/operations/kalle)" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "operation-failed","error-severity": "error","error-message": "yang node not found"}}} '
expecteq "$(curl -s -X POST -d '{}' http://localhost/restconf/operations/kalle)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "missing-element","error-info": {"bad-element": "kalle"},"error-severity": "error","error-message": "RPC not defined"}}} '
new2 "restconf rpc non-existing rpc"
expecteq "$(curl -s -X POST -d '{}' http://localhost/restconf/operations/example:kalle)" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "operation-failed","error-severity": "error","error-message": "yang node not found"}}} '
expecteq "$(curl -s -X POST -d '{}' http://localhost/restconf/operations/example:kalle)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "missing-element","error-info": {"bad-element": "kalle"},"error-severity": "error","error-message": "RPC not defined"}}} '
new2 "restconf rpc missing name"
expecteq "$(curl -s -X POST -d '{}' http://localhost/restconf/operations)" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "operation-failed","error-severity": "error","error-message": "Operation name expected"}}} '

View file

@ -65,7 +65,7 @@ new "kill old restconf daemon"
sudo pkill -u www-data -f "/www-data/clixon_restconf"
new "start restconf daemon"
sudo su -c "$clixon_restconf -f $cfg -y $fyang" -s /bin/sh www-data &
sudo su -c "$clixon_restconf -f $cfg -y $fyang -D $DBG" -s /bin/sh www-data &
sleep $RCWAIT

View file

@ -46,7 +46,7 @@ new "kill old restconf daemon"
sudo pkill -u www-data clixon_restconf
new "start restconf daemon"
sudo su -c "$clixon_restconf -f $cfg" -s /bin/sh www-data &
sudo su -c "$clixon_restconf -f $cfg -D $DBG" -s /bin/sh www-data &
sleep $RCWAIT
@ -54,7 +54,7 @@ new "rpc tests"
# 1.First some positive tests vary media types
#
new2 "restconf example rpc json/json default - no headers"
new2 "restconf example rpc json/json default - no http media headers"
expecteq "$(curl -s -X POST -d '{"input":{"x":"0"}}' http://localhost/restconf/operations/example:example)" '{"output": {"x": "0","y": "42"}}
'
@ -93,13 +93,13 @@ new2 "restconf add extra"
expecteq "$(curl -s -X POST -d '{"input":{"x":"0","extra":"0"}}' http://localhost/restconf/operations/example:example)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "unknown-element","error-info": {"bad-element": "extra"},"error-severity": "error"}}} '
new2 "restconf wrong method"
expecteq "$(curl -s -X POST -d '{"input":{"x":"0"}}' http://localhost/restconf/operations/example:wrong)" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "operation-failed","error-severity": "error","error-message": "yang node not found"}}} '
expecteq "$(curl -s -X POST -d '{"input":{"x":"0"}}' http://localhost/restconf/operations/example:wrong)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "missing-element","error-info": {"bad-element": "wrong"},"error-severity": "error","error-message": "RPC not defined"}}} '
new2 "restconf edit-config missing mandatory"
expecteq "$(curl -s -X POST -d '{"input":null}' http://localhost/restconf/operations/ietf-netconf:edit-config)" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "operation-failed","error-severity": "error","error-message": "yang module not found"}}} '
new "netconf kill-session missing session-id mandatory"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><kill-session/></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>missing-element</error-tag><error-info><bad-element>session-id</bad-element></error-info><error-severity>error</error-severity><error-message>Mandatory variable</error-message></rpc-error></rpc-reply>$'
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><kill-session/></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>missing-element</error-tag><error-info><bad-element>session-id</bad-element></error-info><error-severity>error</error-severity><error-message>Mandatory variable</error-message></rpc-error></rpc-reply>]]>]]>$'
# edit-config?

View file

@ -121,7 +121,7 @@ new "kill old restconf daemon"
sudo pkill -u www-data -f "/www-data/clixon_restconf"
new "start restconf daemon"
sudo su -c "$clixon_restconf -f $cfg -y $fyang" -s /bin/sh www-data &
sudo su -c "$clixon_restconf -f $cfg -y $fyang -D $DBG" -s /bin/sh www-data &
sleep $RCWAIT
@ -153,7 +153,7 @@ new "netconf NONEXIST subscription"
expectwait "$clixon_netconf -qf $cfg -y $fyang" '<rpc><create-subscription><stream>NONEXIST</stream></create-subscription></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>invalid-value</error-tag><error-severity>error</error-severity><error-message>No such stream</error-message></rpc-error></rpc-reply>]]>]]>$' $NCWAIT
new "netconf EXAMPLE subscription with wrong date"
expectwait "$clixon_netconf -qf $cfg -y $fyang" '<rpc><create-subscription><stream>EXAMPLE</stream><startTime>kallekaka</startTime></create-subscription></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>startTime</bad-element></error-info><error-severity>error</error-severity><error-message>Expected timestamp</error-message></rpc-error></rpc-reply>]]>]]>$' 0
expectwait "$clixon_netconf -qf $cfg -y $fyang" '<rpc><create-subscription><stream>EXAMPLE</stream><startTime>kallekaka</startTime></create-subscription></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>startTime</bad-element></error-info><error-severity>error</error-severity><error-message>Invalid time: kallekaka</error-message></rpc-error></rpc-reply>]]>]]>$' 0
#new "netconf EXAMPLE subscription with replay"
#NOW=$(date +"%Y-%m-%dT%H:%M:%S")