Fixed numeric ordering of lists (again) [https://github.com/clicon/clixon/issues/64] It was previously just fixed for leaf-lists.
This commit is contained in:
parent
4d3c61735c
commit
fc93051b87
4 changed files with 79 additions and 19 deletions
|
|
@ -31,6 +31,7 @@
|
||||||
* Added libgen.h for baseline()
|
* Added libgen.h for baseline()
|
||||||
|
|
||||||
### Corrected Bugs
|
### Corrected Bugs
|
||||||
|
* Fixed numeric ordering of lists (again) [https://github.com/clicon/clixon/issues/64] It was previously just fixed for leaf-lists.
|
||||||
* There was a problem with ordered-by-user for XML children that appeared in some circumstances and difficult to trigger. Entries entered by the user did not appear in the order they were entered. This should now be fixed.
|
* There was a problem with ordered-by-user for XML children that appeared in some circumstances and difficult to trigger. Entries entered by the user did not appear in the order they were entered. This should now be fixed.
|
||||||
|
|
||||||
## 3.9.0 (21 Feb 2019)
|
## 3.9.0 (21 Feb 2019)
|
||||||
|
|
|
||||||
|
|
@ -195,6 +195,7 @@ xml_child_spec(cxobj *x,
|
||||||
* @see xml_cmp1 Similar, but for one object
|
* @see xml_cmp1 Similar, but for one object
|
||||||
* @note empty value/NULL is smallest value
|
* @note empty value/NULL is smallest value
|
||||||
* @note xml_enumerate_children must have been called prior to this call
|
* @note xml_enumerate_children must have been called prior to this call
|
||||||
|
* @note some error cases return as -1 (qsort cant handle errors)
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
xml_cmp(const void* arg1,
|
xml_cmp(const void* arg1,
|
||||||
|
|
@ -216,22 +217,25 @@ xml_cmp(const void* arg1,
|
||||||
cg_var *cv2;
|
cg_var *cv2;
|
||||||
int nr1;
|
int nr1;
|
||||||
int nr2;
|
int nr2;
|
||||||
|
cxobj *x1b;
|
||||||
|
cxobj *x2b;
|
||||||
|
|
||||||
if (x1==NULL || x2==NULL)
|
if (x1==NULL || x2==NULL){
|
||||||
return 0; /* shouldnt happen */
|
goto done; /* shouldnt happen */
|
||||||
|
}
|
||||||
y1 = xml_spec(x1);
|
y1 = xml_spec(x1);
|
||||||
y2 = xml_spec(x2);
|
y2 = xml_spec(x2);
|
||||||
nr1 = xml_enumerate_get(x1);
|
nr1 = xml_enumerate_get(x1);
|
||||||
nr2 = xml_enumerate_get(x2);
|
nr2 = xml_enumerate_get(x2);
|
||||||
if (y1==NULL || y2==NULL){
|
if (y1==NULL || y2==NULL){
|
||||||
equal = nr1-nr2;
|
equal = nr1-nr2;
|
||||||
return equal;
|
goto done;
|
||||||
}
|
}
|
||||||
if (y1 != y2){
|
if (y1 != y2){
|
||||||
yi1 = yang_order(y1);
|
yi1 = yang_order(y1);
|
||||||
yi2 = yang_order(y2);
|
yi2 = yang_order(y2);
|
||||||
if ((equal = yi1-yi2) != 0)
|
if ((equal = yi1-yi2) != 0)
|
||||||
return equal;
|
goto done;
|
||||||
}
|
}
|
||||||
/* Now y1==y2, same Yang spec, can only be list or leaf-list,
|
/* Now y1==y2, same Yang spec, can only be list or leaf-list,
|
||||||
* But first check exceptions, eg config false or ordered-by user
|
* But first check exceptions, eg config false or ordered-by user
|
||||||
|
|
@ -240,7 +244,7 @@ xml_cmp(const void* arg1,
|
||||||
if (yang_config(y1)==0 ||
|
if (yang_config(y1)==0 ||
|
||||||
yang_find((yang_node*)y1, Y_ORDERED_BY, "user") != NULL){
|
yang_find((yang_node*)y1, Y_ORDERED_BY, "user") != NULL){
|
||||||
equal = nr1-nr2;
|
equal = nr1-nr2;
|
||||||
return equal; /* Ordered by user or state data : maintain existing order */
|
goto done; /* Ordered by user or state data : maintain existing order */
|
||||||
}
|
}
|
||||||
switch (y1->ys_keyword){
|
switch (y1->ys_keyword){
|
||||||
case Y_LEAF_LIST: /* Match with name and value */
|
case Y_LEAF_LIST: /* Match with name and value */
|
||||||
|
|
@ -249,9 +253,9 @@ xml_cmp(const void* arg1,
|
||||||
else if ((b2 = xml_body(x2)) == NULL)
|
else if ((b2 = xml_body(x2)) == NULL)
|
||||||
equal = 1;
|
equal = 1;
|
||||||
else{
|
else{
|
||||||
if (xml_cv_cache(x1, b1, &cv1) < 0)
|
if (xml_cv_cache(x1, b1, &cv1) < 0) /* error case */
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_cv_cache(x2, b2, &cv2) < 0)
|
if (xml_cv_cache(x2, b2, &cv2) < 0) /* error case */
|
||||||
goto done;
|
goto done;
|
||||||
equal = cv_cmp(cv1, cv2);
|
equal = cv_cmp(cv1, cv2);
|
||||||
}
|
}
|
||||||
|
|
@ -263,12 +267,18 @@ xml_cmp(const void* arg1,
|
||||||
cvi = NULL;
|
cvi = NULL;
|
||||||
while ((cvi = cvec_each(cvk, cvi)) != NULL) {
|
while ((cvi = cvec_each(cvk, cvi)) != NULL) {
|
||||||
keyname = cv_string_get(cvi); /* operational data may have NULL keys*/
|
keyname = cv_string_get(cvi); /* operational data may have NULL keys*/
|
||||||
if ((b1 = xml_find_body(x1, keyname)) == NULL)
|
if ((x1b = xml_find(x1, keyname)) == NULL ||
|
||||||
|
(b1 = xml_body(x1b)) == NULL)
|
||||||
equal = -1;
|
equal = -1;
|
||||||
else if ((b2 = xml_find_body(x2, keyname)) == NULL)
|
else if ((x2b = xml_find(x2, keyname)) == NULL ||
|
||||||
|
(b2 = xml_body(x2b)) == NULL)
|
||||||
equal = 1;
|
equal = 1;
|
||||||
else{
|
else{
|
||||||
if ((equal = strcmp(b1,b2)) != 0)
|
if (xml_cv_cache(x1b, b1, &cv1) < 0) /* error case */
|
||||||
|
goto done;
|
||||||
|
if (xml_cv_cache(x2b, b2, &cv2) < 0) /* error case */
|
||||||
|
goto done;
|
||||||
|
if ((equal = cv_cmp(cv1, cv2)) != 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,12 +96,28 @@ module order-example{
|
||||||
type int32;
|
type int32;
|
||||||
ordered-by system;
|
ordered-by system;
|
||||||
}
|
}
|
||||||
|
list listints{
|
||||||
|
ordered-by system;
|
||||||
|
key a;
|
||||||
|
leaf a {
|
||||||
|
type int32;
|
||||||
|
}
|
||||||
|
}
|
||||||
leaf-list decs{
|
leaf-list decs{
|
||||||
type decimal64{
|
type decimal64{
|
||||||
fraction-digits 3;
|
fraction-digits 3;
|
||||||
}
|
}
|
||||||
ordered-by system;
|
ordered-by system;
|
||||||
}
|
}
|
||||||
|
list listdecs{
|
||||||
|
ordered-by system;
|
||||||
|
key a;
|
||||||
|
leaf a {
|
||||||
|
type decimal64{
|
||||||
|
fraction-digits 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
@ -204,17 +220,50 @@ new "verify list user order (as entered)"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get-config><source><candidate/></source><filter type="xpath" select="/y2"/></get-config></rpc>]]>]]>' '^<rpc-reply><data><y2 xmlns="urn:example:order"><k>c</k><a>bar</a></y2><y2 xmlns="urn:example:order"><k>b</k><a>foo</a></y2><y2 xmlns="urn:example:order"><k>a</k><a>fie</a></y2></data></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get-config><source><candidate/></source><filter type="xpath" select="/y2"/></get-config></rpc>]]>]]>' '^<rpc-reply><data><y2 xmlns="urn:example:order"><k>c</k><a>bar</a></y2><y2 xmlns="urn:example:order"><k>b</k><a>foo</a></y2><y2 xmlns="urn:example:order"><k>a</k><a>fie</a></y2></data></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
#-- order by type rather than strings.
|
#-- order by type rather than strings.
|
||||||
# there are three lists: strings, ints, and decimal64
|
# there are three leaf-lists:strings, ints, and decimal64, and two lists:
|
||||||
|
# listints and listdecs
|
||||||
# the strings is there for comparison
|
# the strings is there for comparison
|
||||||
new "add type ordered entries"
|
# The check is to write the entries as: 10,2,1, and then expect them to
|
||||||
|
# get back as 1,2,10 (if typed).
|
||||||
|
new "put strings (10,2,1)"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><types xmlns="urn:example:order">
|
||||||
|
<strings>10</strings><strings>2</strings><strings>1</strings>
|
||||||
|
</types></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "check string order (1,10,2)"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get-config><source><candidate/></source><filter type="xpath" select="/types/strings"/></get-config></rpc>]]>]]>' '^<rpc-reply><data><types xmlns="urn:example:order"><strings>1</strings><strings>10</strings><strings>2</strings></types></data></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
|
new "put leaf-list int (10,2,1)"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><types xmlns="urn:example:order">
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><types xmlns="urn:example:order">
|
||||||
<ints>10</ints><ints>2</ints><ints>1</ints>
|
<ints>10</ints><ints>2</ints><ints>1</ints>
|
||||||
<strings>10</strings><strings>2</strings><strings>1</strings>
|
</types></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "check leaf-list int order (1,2,10)"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get-config><source><candidate/></source><filter type="xpath" select="/types/ints"/></get-config></rpc>]]>]]>' '^<rpc-reply><data><types xmlns="urn:example:order"><ints>1</ints><ints>2</ints><ints>10</ints></types></data></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
|
new "put list int (10,2,1)"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><types xmlns="urn:example:order">
|
||||||
|
<listints><a>10</a></listints><listints><a>2</a></listints><listints><a>1</a></listints>
|
||||||
|
</types></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "check list int order (1,2,10)"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get-config><source><candidate/></source><filter type="xpath" select="/types/listints"/></get-config></rpc>]]>]]>' '^<rpc-reply><data><types xmlns="urn:example:order"><listints><a>1</a></listints><listints><a>2</a></listints><listints><a>10</a></listints></types></data></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
|
new "put leaf-list decimal64 (10,2,1)"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><types xmlns="urn:example:order">
|
||||||
<decs>10.0</decs><decs>2.0</decs><decs>1.0</decs>
|
<decs>10.0</decs><decs>2.0</decs><decs>1.0</decs>
|
||||||
</types></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
</types></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "get type ordered entries"
|
new "check leaf-list decimal64 order (1,2,10)"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get-config><source><candidate/></source><filter type="xpath" select="/types"/></get-config></rpc>]]>]]>' '^<rpc-reply><data><types xmlns="urn:example:order"><strings>1</strings><strings>10</strings><strings>2</strings><ints>1</ints><ints>2</ints><ints>10</ints><decs>1.0</decs><decs>2.0</decs><decs>10.0</decs></types></data></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get-config><source><candidate/></source><filter type="xpath" select="/types/decs"/></get-config></rpc>]]>]]>' '^<rpc-reply><data><types xmlns="urn:example:order"><decs>1.0</decs><decs>2.0</decs><decs>10.0</decs></types></data></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
|
new "put list decimal64 (10,2,1)"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><types xmlns="urn:example:order">
|
||||||
|
<listdecs><a>10.0</a></listdecs><listdecs><a>2.0</a></listdecs><listdecs><a>1.0</a></listdecs>
|
||||||
|
</types></config></edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "check list decimal64 order (1,2,10)"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get-config><source><candidate/></source><filter type="xpath" select="/types/listdecs"/></get-config></rpc>]]>]]>' '^<rpc-reply><data><types xmlns="urn:example:order"><listdecs><a>1.0</a></listdecs><listdecs><a>2.0</a></listdecs><listdecs><a>10.0</a></listdecs></types></data></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
if [ $BE -eq 0 ]; then
|
if [ $BE -eq 0 ]; then
|
||||||
exit # BE
|
exit # BE
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,10 @@ module scaling{
|
||||||
list y {
|
list y {
|
||||||
key "a";
|
key "a";
|
||||||
leaf a {
|
leaf a {
|
||||||
type string;
|
type int32;
|
||||||
}
|
}
|
||||||
leaf b {
|
leaf b {
|
||||||
type string;
|
type int32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
leaf-list c {
|
leaf-list c {
|
||||||
|
|
@ -131,10 +131,10 @@ done
|
||||||
|
|
||||||
# Instead of many small entries, get one large in netconf and restconf
|
# Instead of many small entries, get one large in netconf and restconf
|
||||||
new "netconf get large config"
|
new "netconf get large config"
|
||||||
expecteof "/usr/bin/time -f %e $clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" '^<rpc-reply><data><x xmlns="urn:example:clixon"><y><a>0</a><b>0</b></y><y><a>1</a><b>1</b>'
|
expecteof "/usr/bin/time -f %e $clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" '^<rpc-reply><data><x xmlns="urn:example:clixon"><y><a>0</a><b>0</b></y><y><a>1</a><b>1</b></y><y><a>2</a><b>2</b></y><y><a>3</a><b>3</b></y>'
|
||||||
|
|
||||||
new "restconf get large config"
|
new "restconf get large config"
|
||||||
expecteof "/usr/bin/time -f %e curl -sG http://localhost/restconf/data" 0 "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" '^{"data": {"scaling:x": {"y": \[{"a": "0","b": "0"},{ "a": "1","b": "1"},'
|
expecteof "/usr/bin/time -f %e curl -sG http://localhost/restconf/data" 0 "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" '^{"data": {"scaling:x": {"y": \[{"a": 0,"b": 0},{ "a": 1,"b": 1},{ "a": 2,"b": 2},{ "a": 3,"b": 3},'
|
||||||
|
|
||||||
# Now do leaf-lists istead of leafs
|
# Now do leaf-lists istead of leafs
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue