text datastore full tests

This commit is contained in:
Olof hagsand 2017-04-24 13:00:31 +02:00
parent c2f52845f8
commit 2f30bda7d4
3 changed files with 114 additions and 58 deletions

View file

@ -418,7 +418,7 @@ find_keys_vec(cxobj *xt,
* @see xmldb_put_xkey for example * @see xmldb_put_xkey for example
*/ */
static int static int
text_create_modtree(char *api_path, text_apipath_modify(char *api_path,
cxobj *xt, cxobj *xt,
enum operation_type op, enum operation_type op,
yang_spec *yspec, yang_spec *yspec,
@ -473,7 +473,7 @@ text_create_modtree(char *api_path,
else else
y = yang_find_syntax((yang_node*)y, name); y = yang_find_syntax((yang_node*)y, name);
if (y == NULL){ if (y == NULL){
clicon_err(OE_UNIX, errno, "No yang node found: %s", name); clicon_err(OE_YANG, errno, "No yang node found: %s", name);
goto done; goto done;
} }
i++; i++;
@ -627,13 +627,15 @@ text_create_modtree(char *api_path,
return retval; return retval;
} }
/*! Check if child with fullmatch exists /*! Given a modification tree, check existing matching child in the base tree
* param[in] cvk vector of index keys * param[in] x0 Base tree node
* param[in] x1c Modification tree child
* param[in] yc Yang spec of tree child
*/ */
static cxobj * static cxobj *
find_match(cxobj *x0, match_base_child(cxobj *x0,
cxobj *x1c, cxobj *x1c,
yang_stmt *yc) yang_stmt *yc)
{ {
cxobj *x0c = NULL; cxobj *x0c = NULL;
char *keyname; char *keyname;
@ -642,41 +644,54 @@ find_match(cxobj *x0,
char *b0; char *b0;
char *b1; char *b1;
yang_stmt *ykey; yang_stmt *ykey;
char *name; char *cname;
int ok; int ok;
char *x1bstr; /* body string */
name = xml_name(x1c); cname = xml_name(x1c);
if (yc->ys_keyword != Y_LIST){ switch (yc->ys_keyword){
x0c = xml_find(x0, name); case Y_LEAF_LIST: /* Match with name and value */
goto done; x1bstr = xml_body(x1c);
} x0c = NULL;
if ((ykey = yang_find((yang_node*)yc, Y_KEY, NULL)) == NULL){ while ((x0c = xml_child_each(x0, x0c, CX_ELMNT)) != NULL) {
clicon_err(OE_XML, errno, "%s: List statement \"%s\" has no key", if (strcmp(cname, xml_name(x0c)) == 0 &&
__FUNCTION__, yc->ys_argument); strcmp(xml_body(x0c), x1bstr)==0)
goto done;
}
/* The value is a list of keys: <key>[ <key>]* */
if ((cvk = yang_arg2cvec(ykey, " ")) == NULL)
goto done;
x0c = NULL;
while ((x0c = xml_child_each(x0, x0c, CX_ELMNT)) != NULL) {
if (strcmp(xml_name(x0c), name))
continue;
cvi = NULL;
ok = 0;
while ((cvi = cvec_each(cvk, cvi)) != NULL) {
keyname = cv_string_get(cvi);
ok = 1; /* if we come here */
if ((b0 = xml_find_body(x0c, keyname)) == NULL)
break; /* error case */
if ((b1 = xml_find_body(x1c, keyname)) == NULL)
break; /* error case */
if (strcmp(b0, b1))
break; break;
ok = 2; /* and reaches here for all keynames, x0c is found. */
} }
if (ok == 2) break;
break; case Y_LIST: /* Match with key values */
if ((ykey = yang_find((yang_node*)yc, Y_KEY, NULL)) == NULL){
clicon_err(OE_XML, errno, "%s: List statement \"%s\" has no key",
__FUNCTION__, yc->ys_argument);
goto done;
}
/* The value is a list of keys: <key>[ <key>]* */
if ((cvk = yang_arg2cvec(ykey, " ")) == NULL)
goto done;
x0c = NULL;
while ((x0c = xml_child_each(x0, x0c, CX_ELMNT)) != NULL) {
if (strcmp(xml_name(x0c), cname))
continue;
cvi = NULL;
ok = 0;
while ((cvi = cvec_each(cvk, cvi)) != NULL) {
keyname = cv_string_get(cvi);
ok = 1; /* if we come here */
if ((b0 = xml_find_body(x0c, keyname)) == NULL)
break; /* error case */
if ((b1 = xml_find_body(x1c, keyname)) == NULL)
break; /* error case */
if (strcmp(b0, b1))
break;
ok = 2; /* and reaches here for all keynames, x0c is found. */
}
if (ok == 2)
break;
}
break;
default: /* Just match with name */
x0c = xml_find(x0, cname);
break;
} }
done: done:
if (cvk) if (cvk)
@ -745,14 +760,18 @@ text_modify(cxobj *x0,
if (x0==NULL){ if (x0==NULL){
if ((x0 = xml_new_spec(name, x0p, y)) == NULL) if ((x0 = xml_new_spec(name, x0p, y)) == NULL)
goto done; goto done;
if ((x0b = xml_new("body", x0)) == NULL) if (x1bstr){ /* empty type does not have body */
goto done; if ((x0b = xml_new("body", x0)) == NULL)
xml_type_set(x0b, CX_BODY); goto done;
xml_type_set(x0b, CX_BODY);
}
}
if (x1bstr){
if ((x0b = xml_body_get(x0)) == NULL)
goto done;
if (xml_value_set(x0b, x1bstr) < 0)
goto done;
} }
if ((x0b = xml_body_get(x0)) == NULL)
goto done;
if (xml_value_set(x0b, x1bstr) < 0)
goto done;
break; break;
default: default:
break; break;
@ -785,16 +804,21 @@ text_modify(cxobj *x0,
if ((x0 = xml_new_spec(name, x0p, y)) == NULL) if ((x0 = xml_new_spec(name, x0p, y)) == NULL)
goto done; goto done;
} }
/* Loop through children of the modification tree */
x1c = NULL; x1c = NULL;
while ((x1c = xml_child_each(x1, x1c, CX_ELMNT)) != NULL) { while ((x1c = xml_child_each(x1, x1c, CX_ELMNT)) != NULL) {
cname = xml_name(x1c); cname = xml_name(x1c);
/* XXX This is more than find, if a list keys must match */ /* Get yang spec of the child */
if (y == NULL) if (y == NULL)
yc = yang_find_topnode(yspec, cname); /* still NULL for config */ yc = yang_find_topnode(yspec, cname); /* still NULL for config */
else else{
yc = yang_find_syntax(y, cname); if ((yc = yang_find_syntax(y, cname)) == NULL){
x0c = find_match(x0, x1c, yc); clicon_err(OE_YANG, errno, "No yang node found: %s", cname);
goto done;
}
}
/* See if there is a corresponding node in the base tree */
x0c = yc?match_base_child(x0, x1c, yc):NULL;
if (text_modify(x0c, x0, x1c, op, (yang_node*)yc, yspec) < 0) if (text_modify(x0c, x0, x1c, op, (yang_node*)yc, yspec) < 0)
goto done; goto done;
} }
@ -890,7 +914,7 @@ text_put(xmldb_handle xh,
/* here xt looks like: <config>...</config> */ /* here xt looks like: <config>...</config> */
/* If xpath find first occurence or api-path (this is where we apply xml) */ /* If xpath find first occurence or api-path (this is where we apply xml) */
if (api_path){ if (api_path){
if (text_create_modtree(api_path, xt, op, yspec, &xbase, &xbasep, &y) < 0) if (text_apipath_modify(api_path, xt, op, yspec, &xbase, &xbasep, &y) < 0)
goto done; goto done;
} }
else{ else{

View file

@ -31,6 +31,9 @@ module ietf-ip{
type string; type string;
} }
} }
leaf g {
type string;
}
container h { container h {
leaf j { leaf j {
type string; type string;

View file

@ -30,6 +30,9 @@ module ietf-ip{
type string; type string;
} }
} }
leaf g {
type string;
}
container h { container h {
leaf j { leaf j {
type string; type string;
@ -53,16 +56,42 @@ run(){
new "datastore $name init" new "datastore $name init"
expectfn "$datastore $conf init" "" expectfn "$datastore $conf init" ""
new "datastore $name put top" new "datastore $name put all replace"
echo "$datastore $conf put replace '/' $db" expectfn "$datastore $conf put replace / $db" ""
expectfn "$datastore $conf put replace '/' \"$db\"" ""
new "datastore $name get"
expectfn "$datastore $conf get /" "^$db$"
new "datastore $name put all remove"
expectfn "$datastore $conf put remove /"
new "datastore $name get"
expectfn "$datastore $conf get /" "^<config/>$"
new "datastore $name put all merge"
expectfn "$datastore $conf put merge / $db" ""
new "datastore $name get"
expectfn "$datastore $conf get /" "^$db$"
new "datastore $name put all delete"
expectfn "$datastore $conf put remove /"
new "datastore $name get"
expectfn "$datastore $conf get /" "^<config/>$"
new "datastore $name put all create"
expectfn "$datastore $conf put create / $db" ""
new "datastore $name get"
expectfn "$datastore $conf get /" "^$db$"
new "datastore $name put top create"
expectfn "$datastore $conf put create / <config><x/></config>" "" # error
return return
new "datastore $name get"
expectfn "$datastore $conf get /" $db
new "datastore $name put rm"
expectfn "$datastore $conf put remove /x/g"
new "datastore $name put top" new "datastore $name put top"
expectfn "$datastore $conf put replace / $db" expectfn "$datastore $conf put replace / $db"