Fixed three-key list entry problem (reported by jdl@netgate)

This commit is contained in:
Olof hagsand 2018-03-24 14:37:36 +01:00
parent 835674bbe0
commit cce76faa79
3 changed files with 56 additions and 19 deletions

View file

@ -37,6 +37,7 @@ enables saved files to be used as datastore without any editing. Thanks Matt.
* Added cli_show_version() * Added cli_show_version()
### Corrected Bugs ### Corrected Bugs
* Fixed three-key list entry problem (reported by jdl@netgate)
* Translate xml->json \n correctly * Translate xml->json \n correctly
* Fix issue: https://github.com/clicon/clixon/issues/15 Replace whole config * Fix issue: https://github.com/clicon/clixon/issues/15 Replace whole config

View file

@ -167,7 +167,7 @@ xml_cmp(const void* arg1,
return equal; return equal;
} }
/*! /*! Compare xml object
* @param[in] yangi Yang order * @param[in] yangi Yang order
* @param[in] keynr Length of keyvec/keyval vector when applicable * @param[in] keynr Length of keyvec/keyval vector when applicable
* @param[in] keyvec Array of of yang key identifiers * @param[in] keyvec Array of of yang key identifiers
@ -192,36 +192,38 @@ xml_cmp1(cxobj *x,
int i; int i;
char *keyname; char *keyname;
char *key; char *key;
int match = 0;
/* Check if same yang spec (order in yang stmt list) */ /* Check if same yang spec (order in yang stmt list) */
switch (keyword){ switch (keyword){
case Y_CONTAINER: /* Match with name */ case Y_CONTAINER: /* Match with name */
case Y_LEAF: /* Match with name */ case Y_LEAF: /* Match with name */
return strcmp(name, xml_name(x)); match = strcmp(name, xml_name(x));
break; break;
case Y_LEAF_LIST: /* Match with name and value */ case Y_LEAF_LIST: /* Match with name and value */
if (userorder && yang_find((yang_node*)y, Y_ORDERED_BY, "user") != NULL) if (userorder && yang_find((yang_node*)y, Y_ORDERED_BY, "user") != NULL)
*userorder=1; *userorder=1;
b=xml_body(x); b=xml_body(x);
return strcmp(keyval[0], b); match = strcmp(keyval[0], b);
break; break;
case Y_LIST: /* Match with array of key values */ case Y_LIST: /* Match with array of key values */
if (userorder && yang_find((yang_node*)y, Y_ORDERED_BY, "user") != NULL) if (userorder && yang_find((yang_node*)y, Y_ORDERED_BY, "user") != NULL)
*userorder=1; *userorder=1;
/* All must match */
for (i=0; i<keynr; i++){ for (i=0; i<keynr; i++){
keyname = keyvec[i]; keyname = keyvec[i];
key = keyval[i]; key = keyval[i];
/* Eg return "e0" in <if><name>e0</name></name></if> given "name" */ /* Eg return "e0" in <if><name>e0</name></name></if> given "name" */
if ((b = xml_find_body(x, keyname)) == NULL) if ((b = xml_find_body(x, keyname)) == NULL)
break; /* error case */ break; /* error case */
return strcmp(key, b); if ((match = strcmp(key, b)) != 0)
break;
} }
return 0;
break; break;
default: default:
break; break;
} }
return 0; /* should not reach here */ return match; /* should not reach here */
} }
/*! Sort children of an XML node /*! Sort children of an XML node
@ -273,12 +275,12 @@ xml_search_userorder(cxobj *x0,
} }
/*! /*!
* @param[in] yangi Yang order * @param[in] yangi Yang order
* @param[in] keynr Length of keyvec/keyval vector when applicable * @param[in] keynr Length of keyvec/keyval vector when applicable
* @param[in] keyvec Array of of yang key identifiers * @param[in] keyvec Array of of yang key identifiers
* @param[in] keyval Array of of yang key values * @param[in] keyval Array of of yang key values
* @param[in] low Lower bound of childvec search interval * @param[in] low Lower bound of childvec search interval
* @param[in] upper Lower bound of childvec search interval * @param[in] upper Lower bound of childvec search interval
*/ */
static cxobj * static cxobj *
xml_search1(cxobj *x0, xml_search1(cxobj *x0,
@ -522,7 +524,7 @@ xml_sort_verify(cxobj *x0,
return retval; return retval;
} }
/*! Given child tree x1c, find matching child in base tree x0 /*! Given child tree x1c, find matching child in base tree x0 and return as x0cp
* param[in] x0 Base tree node * param[in] x0 Base tree node
* param[in] x1c Modification tree child * param[in] x1c Modification tree child
* param[in] yc Yang spec of tree child * param[in] yc Yang spec of tree child
@ -567,7 +569,10 @@ match_base_child(cxobj *x0,
break; break;
case Y_LIST: /* Match with key values */ case Y_LIST: /* Match with key values */
cvk = yc->ys_cvec; /* Use Y_LIST cache, see ys_populate_list() */ cvk = yc->ys_cvec; /* Use Y_LIST cache, see ys_populate_list() */
/* Count number of key indexes */ /* Count number of key indexes
* Then create two vectors one with names and one with values of x1c,
* ec: keyvec: [a,b,c] keyval: [1,2,3]
*/
cvi = NULL; keynr = 0; cvi = NULL; keynr = 0;
while ((cvi = cvec_each(cvk, cvi)) != NULL) while ((cvi = cvec_each(cvk, cvi)) != NULL)
keynr++; keynr++;
@ -591,7 +596,7 @@ match_base_child(cxobj *x0,
default: default:
break; break;
} }
/* Get match */ /* Get match. Sorting mode(optimized) or not?*/
if (xml_child_sort==0) if (xml_child_sort==0)
*x0cp = xml_match(x0, xml_name(x1c), yc->ys_keyword, keynr, keyvec, keyval); *x0cp = xml_match(x0, xml_name(x1c), yc->ys_keyword, keynr, keyvec, keyval);
else{ else{

View file

@ -34,7 +34,7 @@ module example{
ex:c-define "MY_INTERFACES"; ex:c-define "MY_INTERFACES";
container x { container x {
list y { list y {
key "a b"; key "a b c";
leaf a { leaf a {
type string; type string;
} }
@ -44,6 +44,9 @@ module example{
leaf c { leaf c {
type string; type string;
} }
leaf val {
type string;
}
} }
leaf d { leaf d {
type empty; type empty;
@ -115,7 +118,7 @@ new "cli not defined extension"
#expectfn "$clixon_cli -1f $cfg -y $fyangerr show version" "Yang error: Extension ex:not-defined not found" #expectfn "$clixon_cli -1f $cfg -y $fyangerr show version" "Yang error: Extension ex:not-defined not found"
new "netconf edit config" new "netconf edit config"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><x><y><a>1</a><b>2</b><c>5</c></y><d/></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><x><y><a>1</a><b>2</b><c>5</c><val>one</val></y><d/></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf commit" new "netconf commit"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
@ -125,7 +128,7 @@ new "netconf commit 2nd"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf get config xpath" new "netconf get config xpath"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><candidate/></source><filter type=\"xpath\" select=\"/x/y[a=1][b=2]\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><y><a>1</a><b>2</b><c>5</c></y></x></data></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><candidate/></source><filter type=\"xpath\" select=\"/x/y[a=1][b=2][c=5]\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><y><a>1</a><b>2</b><c>5</c><val>one</val></y></x></data></rpc-reply>]]>]]>$"
new "netconf edit leaf-list" new "netconf edit leaf-list"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><x><f><e>hej</e><e>hopp</e></f></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><x><f><e>hej</e><e>hopp</e></f></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
@ -137,7 +140,7 @@ new "netconf get leaf-list path"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><candidate/></source><filter type=\"xpath\" select=\"/x/f[e=hej]\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><f><e>hej</e><e>hopp</e></f></x></data></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><candidate/></source><filter type=\"xpath\" select=\"/x/f[e=hej]\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><f><e>hej</e><e>hopp</e></f></x></data></rpc-reply>]]>]]>$"
new "netconf get (should be some)" new "netconf get (should be some)"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get><filter type=\"xpath\" select=\"/\"/></get></rpc>]]>]]>" "^<rpc-reply><data><x><y><a>1</a><b>2</b><c>5</c></y><d/></x></data></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get><filter type=\"xpath\" select=\"/\"/></get></rpc>]]>]]>" "^<rpc-reply><data><x><y><a>1</a><b>2</b><c>5</c><val>one</val></y><d/></x></data></rpc-reply>]]>]]>$"
new "cli set leaf-list" new "cli set leaf-list"
expectfn "$clixon_cli -1f $cfg -y $fyang set x f e foo" "" expectfn "$clixon_cli -1f $cfg -y $fyang set x f e foo" ""
@ -162,6 +165,34 @@ expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candi
new "netconf validate anyxml" new "netconf validate anyxml"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf delete candidate"
expecteof "$clixon_netconf -qf $cfg" "<rpc><delete-config><target><candidate/></target></delete-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
# Check 3-keys
new "netconf add one 3-key entry"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><x><y><a>1</a><b>1</b><c>1</c><val>one</val></y></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf check add one 3-key"
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '<rpc-reply><data><x><y><a>1</a><b>1</b><c>1</c><val>one</val></y></x></data></rpc-reply>]]>]]>'
new "netconf add another (with same 1st key)"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><x><y><a>1</a><b>2</b><c>1</c><val>two</val></y></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf check add another"
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '<rpc-reply><data><x><y><a>1</a><b>1</b><c>1</c><val>one</val></y><y><a>1</a><b>2</b><c>1</c><val>two</val></y></x></data></rpc-reply>]]>]]>'
new "netconf replace first"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><x><y><a>1</a><b>1</b><c>1</c><val>replace</val></y></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf check replace"
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '<rpc-reply><data><x><y><a>1</a><b>1</b><c>1</c><val>replace</val></y><y><a>1</a><b>2</b><c>1</c><val>two</val></y></x></data></rpc-reply>]]>]]>'
new "netconf delete first"
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><edit-config><target><candidate/></target><config><x><y operation="remove"><a>1</a><b>1</b><c>1</c></y></x></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf check delete"
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '<rpc-reply><data><x><y><a>1</a><b>2</b><c>1</c><val>two</val></y></x></data></rpc-reply>]]>]]>'
# Check if still alive # Check if still alive
pid=`pgrep clixon_backend` pid=`pgrep clixon_backend`
if [ -z "$pid" ]; then if [ -z "$pid" ]; then