Fixed: [Behaviour of Empty LIST Input in RESTCONF JSON #166](https://github.com/clicon/clixon/issues/166)
This commit is contained in:
parent
96b50b88e8
commit
f0325d989e
4 changed files with 47 additions and 23 deletions
|
|
@ -70,6 +70,7 @@ Users may have to change how they access the system
|
||||||
|
|
||||||
### Corrected Bugs
|
### Corrected Bugs
|
||||||
|
|
||||||
|
* Fixed: [Behaviour of Empty LIST Input in RESTCONF JSON #166](https://github.com/clicon/clixon/issues/166)
|
||||||
* Netconf split lines input (input fragments) fixed
|
* Netconf split lines input (input fragments) fixed
|
||||||
* Netconf input split on several lines, eg using stdin: "<a>\nfoo</a>]]>]]>" could under some circumstances be split so that only "</a>]]>]]>" be properly processed. This could also happen to a socket receiving a sub-string and then after a delay receive the rest.
|
* Netconf input split on several lines, eg using stdin: "<a>\nfoo</a>]]>]]>" could under some circumstances be split so that only "</a>]]>]]>" be properly processed. This could also happen to a socket receiving a sub-string and then after a delay receive the rest.
|
||||||
* Fixed by storing residue and add that to the input string if later input is received on the same socket.
|
* Fixed by storing residue and add that to the input string if later input is received on the same socket.
|
||||||
|
|
|
||||||
|
|
@ -133,6 +133,13 @@ object.
|
||||||
|
|
||||||
#include "clixon_json_parse.h"
|
#include "clixon_json_parse.h"
|
||||||
|
|
||||||
|
/* Enable for debugging, steals some cycles otherwise */
|
||||||
|
#if 0
|
||||||
|
#define _PARSE_DEBUG(s) clicon_debug(1,(s))
|
||||||
|
#else
|
||||||
|
#define _PARSE_DEBUG(s)
|
||||||
|
#endif
|
||||||
|
|
||||||
extern int clixon_json_parseget_lineno (void);
|
extern int clixon_json_parseget_lineno (void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -239,56 +246,63 @@ json_current_body(clixon_json_yacc *jy,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
json_empty_list(clixon_json_yacc *jy)
|
||||||
|
{
|
||||||
|
xml_rm(jy->jy_current);
|
||||||
|
xml_free(jy->jy_current);
|
||||||
|
jy->jy_current = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* top: json -> value is also possible */
|
/* top: json -> value is also possible */
|
||||||
json : value J_EOF { clicon_debug(3,"json->object"); YYACCEPT; }
|
json : value J_EOF { _PARSE_DEBUG("json->value"); YYACCEPT; }
|
||||||
;
|
;
|
||||||
|
|
||||||
value : J_TRUE { json_current_body(_JY, "true");}
|
value : J_TRUE { json_current_body(_JY, "true"); _PARSE_DEBUG("value->TRUE");}
|
||||||
| J_FALSE { json_current_body(_JY, "false");}
|
| J_FALSE { json_current_body(_JY, "false"); _PARSE_DEBUG("value->FALSE");}
|
||||||
| J_NULL { json_current_body(_JY, NULL);}
|
| J_NULL { json_current_body(_JY, NULL); _PARSE_DEBUG("value->NULL");}
|
||||||
| object
|
| object { _PARSE_DEBUG("value->object"); }
|
||||||
| array
|
| array { _PARSE_DEBUG("value->array"); }
|
||||||
| number { json_current_body(_JY, $1); free($1);}
|
| number { json_current_body(_JY, $1); free($1); _PARSE_DEBUG("value->number");}
|
||||||
| string { json_current_body(_JY, $1); free($1);}
|
| string { json_current_body(_JY, $1); free($1); _PARSE_DEBUG("value->string");}
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
object : '{' '}' { clicon_debug(3,"object->{}");}
|
object : '{' '}' { _PARSE_DEBUG("object->{}"); _PARSE_DEBUG("object->{}");}
|
||||||
| '{' objlist '}' { clicon_debug(3,"object->{ objlist }");}
|
| '{' objlist '}' { _PARSE_DEBUG("object->{ objlist }"); _PARSE_DEBUG("object->{ objlist }");}
|
||||||
;
|
;
|
||||||
|
|
||||||
objlist : pair { clicon_debug(3,"objlist->pair");}
|
objlist : pair { _PARSE_DEBUG("objlist->pair");}
|
||||||
| objlist ',' pair { clicon_debug(3,"objlist->objlist , pair");}
|
| objlist ',' pair { _PARSE_DEBUG("objlist->objlist , pair");}
|
||||||
;
|
;
|
||||||
|
|
||||||
pair : string { json_current_new(_JY, $1);free($1);} ':'
|
pair : string { json_current_new(_JY, $1);free($1);} ':'
|
||||||
value { json_current_pop(_JY);}{ clicon_debug(3,"pair->string : value");}
|
value { json_current_pop(_JY);}{ _PARSE_DEBUG("pair->string : value");}
|
||||||
;
|
;
|
||||||
|
|
||||||
array : '[' ']'
|
array : '[' ']' { json_empty_list(_JY); _PARSE_DEBUG("array->[]"); }
|
||||||
| '[' valuelist ']'
|
| '[' valuelist ']' { _PARSE_DEBUG("array->[ valuelist ]"); }
|
||||||
;
|
;
|
||||||
|
|
||||||
valuelist : value
|
valuelist : value { _PARSE_DEBUG("valuelist->value"); }
|
||||||
| valuelist { if (json_current_clone(_JY)< 0) _YYERROR("stack?");} ',' value
|
| valuelist { if (json_current_clone(_JY)< 0) _YYERROR("stack?");}
|
||||||
|
',' value { _PARSE_DEBUG("valuelist->valuelist , value");}
|
||||||
;
|
;
|
||||||
|
|
||||||
/* quoted string */
|
/* quoted string */
|
||||||
string : J_DQ ustring J_DQ { clicon_debug(3,"string->\" ustring \"");$$=$2; }
|
string : J_DQ ustring J_DQ { _PARSE_DEBUG("string->\" ustring \"");$$=$2; }
|
||||||
| J_DQ J_DQ { clicon_debug(3,"string->\" ustring \"");$$=strdup(""); }
|
| J_DQ J_DQ { _PARSE_DEBUG("string->\" \"");$$=strdup(""); }
|
||||||
;
|
;
|
||||||
|
|
||||||
/* unquoted string */
|
/* unquoted string: can be optimized by reading whole string in lex */
|
||||||
ustring : ustring J_CHAR
|
ustring : ustring J_CHAR
|
||||||
{
|
{
|
||||||
int len = strlen($1);
|
int len = strlen($1);
|
||||||
|
|
|
||||||
|
|
@ -59,9 +59,14 @@ expecteofx "$clixon_util_json" 0 '{"foo": -23}' "<foo>-23</foo>"
|
||||||
new "json parse to json" # should be {"foo": -23}
|
new "json parse to json" # should be {"foo": -23}
|
||||||
expecteofx "$clixon_util_json -j" 0 '{"foo": -23}' '{"foo":"-23"}'
|
expecteofx "$clixon_util_json -j" 0 '{"foo": -23}' '{"foo":"-23"}'
|
||||||
|
|
||||||
new "json parse list xml"
|
new "json parse list to xml"
|
||||||
expecteofx "$clixon_util_json" 0 '{"a":[0,1,2,3]}' "<a>0</a><a>1</a><a>2</a><a>3</a>"
|
expecteofx "$clixon_util_json" 0 '{"a":[0,1,2,3]}' "<a>0</a><a>1</a><a>2</a><a>3</a>"
|
||||||
|
|
||||||
|
# See test_restconf.sh
|
||||||
|
new "json parse empty list to xml"
|
||||||
|
expecteofx "$clixon_util_json" 0 '{"a":[]}' "
|
||||||
|
" # XXX empty
|
||||||
|
|
||||||
new "json parse list json" # should be {"a":[0,1,2,3]}
|
new "json parse list json" # should be {"a":[0,1,2,3]}
|
||||||
expecteofx "$clixon_util_json -j" 0 '{"a":[0,1,2,3]}' '{"a":"0"}{"a":"1"}{"a":"2"}{"a":"3"}'
|
expecteofx "$clixon_util_json -j" 0 '{"a":[0,1,2,3]}' '{"a":"0"}{"a":"1"}{"a":"2"}{"a":"3"}'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -264,6 +264,10 @@ testrun()
|
||||||
new "restconf Add subtree eth/0/0 to datastore using POST"
|
new "restconf Add subtree eth/0/0 to datastore using POST"
|
||||||
expectpart "$(curl $CURLOPTS -X POST -H "Accept: application/yang-data+json" -H "Content-Type: application/yang-data+json" -d '{"ietf-interfaces:interfaces":{"interface":{"name":"eth/0/0","type":"clixon-example:eth","enabled":true}}}' $proto://$addr/restconf/data)" 0 'HTTP/1.1 201 Created' "Location: $proto://$addr/restconf/data/ietf-interfaces:interfaces"
|
expectpart "$(curl $CURLOPTS -X POST -H "Accept: application/yang-data+json" -H "Content-Type: application/yang-data+json" -d '{"ietf-interfaces:interfaces":{"interface":{"name":"eth/0/0","type":"clixon-example:eth","enabled":true}}}' $proto://$addr/restconf/data)" 0 'HTTP/1.1 201 Created' "Location: $proto://$addr/restconf/data/ietf-interfaces:interfaces"
|
||||||
|
|
||||||
|
# See test_json.sh
|
||||||
|
new "restconf empty list"
|
||||||
|
expectpart "$(curl $CURLOPTS -X POST -H "Accept: application/yang-data+json" -H "Content-Type: application/yang-data+json" -d '{"clixon-example:route":{"ipv4":[]}}' $proto://$addr/restconf/data)" 0 'HTTP/1.1 201 Created' "Location: $proto://$addr/restconf/data/clixon-example:route"
|
||||||
|
|
||||||
new "restconf Re-add subtree eth/0/0 which should give error"
|
new "restconf Re-add subtree eth/0/0 which should give error"
|
||||||
expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" -d '{"ietf-interfaces:interfaces":{"interface":{"name":"eth/0/0","type":"clixon-example:eth","enabled":true}}}' $proto://$addr/restconf/data)" 0 '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"data-exists","error-severity":"error","error-message":"Data already exists; cannot create new resource"}}}'
|
expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" -d '{"ietf-interfaces:interfaces":{"interface":{"name":"eth/0/0","type":"clixon-example:eth","enabled":true}}}' $proto://$addr/restconf/data)" 0 '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"data-exists","error-severity":"error","error-message":"Data already exists; cannot create new resource"}}}'
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue