Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions lib/src/clixon_validate.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,10 @@ validate_leafref_err(char *xpath,
cbuf *cbm = NULL;
int exist = 0;
char *msg = NULL;
char *body;

if ((body = xml_body(xt)) == NULL)
body = "";
if ((cbi = cbuf_new()) == NULL){
clixon_err(OE_UNIX, errno, "cbuf_new");
goto done;
Expand All @@ -195,12 +198,12 @@ validate_leafref_err(char *xpath,
goto done;
}
cprintf(cbm, "%s", msg);
cprintf(cbi, "%s", xml_body(xt));
cprintf(cbi, "%s", body);
}
else{
if (validate_errmsg(&cbm, xt, yt) < 0)
goto done;
cprintf(cbi, "<%s>%s</%s>", xml_name(xt), xml_body(xt), xml_name(xt));
cprintf(cbi, "<%s>%s</%s>", xml_name(xt), body, xml_name(xt));
}
if (xret && netconf_missing_yang_xml(xret, xpath, "instance-required", cbuf_get(cbi), cbuf_get(cbm)) < 0)
goto done;
Expand Down Expand Up @@ -631,8 +634,10 @@ validate_leafref(cxobj *xt,
clixon_err(OE_YANG, 0, "No argument for Y_PATH");
goto done;
}
/* Empty value is a value: it must also refer to an existing (empty) instance,
* see https://github.com/clicon/clixon/issues/647 */
if ((leafrefbody = xml_body(xt)) == NULL)
goto ok;
leafrefbody = "";
if (xml_nsctx_yang(yt, &nsc) < 0)
goto done;
#ifdef LEAFREF_OPTIMIZE
Expand Down Expand Up @@ -667,7 +672,8 @@ validate_leafref(cxobj *xt,
&leafref_opt.lc_bin_x0) < 0)
goto done;
}
if (leafref_opt.lc_bin_search){
/* Binary search requires a non-empty key, use linear search for empty value */
if (leafref_opt.lc_bin_search && *leafrefbody != '\0'){
if ((ret = leafref_opt_search(xpath, xt, leafref_opt.lc_bin_x0, ytype, xret)) < 0)
goto done;
if (ret == 0)
Expand All @@ -679,7 +685,7 @@ validate_leafref(cxobj *xt,
for (i = 0; i < xlen; i++) {
x = xvec[i];
if ((leafbody = xml_body(x)) == NULL)
continue;
leafbody = "";
if (strcmp(leafbody, leafrefbody) == 0)
break;
}
Expand Down
154 changes: 154 additions & 0 deletions test/test_leafref_empty.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#!/usr/bin/env bash
# Yang leafref with empty value
# An empty value must refer to an existing instance with empty value, as any other value
# See https://github.com/clicon/clixon/issues/647

# Magic line must be first in script (see README.md)
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi

APPNAME=example

cfg=$dir/conf_yang.xml
fyang=$dir/leafref.yang

cat <<EOF > $cfg
<clixon-config xmlns="http://clicon.org/config">
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
<CLICON_YANG_DIR>$dir</CLICON_YANG_DIR>
<CLICON_YANG_DIR>${YANG_INSTALLDIR}</CLICON_YANG_DIR>
<CLICON_YANG_MAIN_FILE>$fyang</CLICON_YANG_MAIN_FILE>
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
<CLICON_SOCK>/usr/local/var/run/$APPNAME.sock</CLICON_SOCK>
<CLICON_BACKEND_PIDFILE>/usr/local/var/run/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
</clixon-config>
EOF

cat <<EOF > $fyang
module leafref{
yang-version 1.1;
namespace "urn:example:clixon";
prefix ex;
container groups {
leaf-list name {
type string;
}
}
list zone {
key name;
leaf name {
type string;
}
leaf label {
type string;
}
}
container test {
list object {
key id;
leaf id {
type string;
}
leaf group {
description "leafref to leaf-list";
type leafref {
path "/ex:groups/ex:name";
}
}
leaf zone {
description "leafref to list key";
type leafref {
path "/ex:zone/ex:name";
}
}
leaf label {
description "leafref to non-key list leaf";
type leafref {
path "/ex:zone/ex:label";
}
}
}
}
}
EOF

new "test params: -f $cfg"

if [ $BE -ne 0 ]; then
new "kill old backend"
sudo clixon_backend -zf $cfg
if [ $? -ne 0 ]; then
err
fi
new "start backend -s init -f $cfg"
start_backend -s init -f $cfg
fi

new "wait backend"
wait_backend

new "netconf set groups and zones"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><groups xmlns=\"urn:example:clixon\"><name>g1</name><name>g2</name></groups><zone xmlns=\"urn:example:clixon\"><name>z1</name><label>a</label></zone><zone xmlns=\"urn:example:clixon\"><name>z2</name><label>b</label></zone><zone xmlns=\"urn:example:clixon\"><name>z3</name><label>c</label></zone></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"

new "netconf commit groups and zones"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><commit/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"

new "netconf set non-empty refs"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><test xmlns=\"urn:example:clixon\"><object><id>o1</id><group>g2</group><zone>z2</zone><label>c</label></object></test></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"

new "netconf validate non-empty refs ok"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"

new "netconf discard-changes"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><discard-changes/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"

new "netconf set empty leafref to leaf-list"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><test xmlns=\"urn:example:clixon\"><object><id>o1</id><group/></object></test></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"

new "netconf validate empty leafref to leaf-list not ok"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>data-missing</error-tag><error-app-tag>instance-required</error-app-tag><error-path>/ex:groups/ex:name</error-path><error-info><group/></error-info>" ""

new "netconf discard-changes"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><discard-changes/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"

new "netconf set empty leafref to list key"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><test xmlns=\"urn:example:clixon\"><object><id>o1</id><zone></zone></object></test></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"

new "netconf validate empty leafref to list key not ok"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>data-missing</error-tag><error-app-tag>instance-required</error-app-tag><error-path>/ex:zone/ex:name</error-path><error-info><zone/></error-info>" ""

new "netconf discard-changes"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><discard-changes/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"

new "netconf set empty leafref to non-key leaf"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><test xmlns=\"urn:example:clixon\"><object><id>o1</id><label/></object></test></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"

new "netconf validate empty leafref to non-key leaf not ok"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>data-missing</error-tag><error-app-tag>instance-required</error-app-tag><error-path>/ex:zone/ex:label</error-path><error-info><label/></error-info>" ""

new "netconf set referred non-key leaf to empty value"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><zone xmlns=\"urn:example:clixon\"><name>z3</name><label/></zone></config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"

new "netconf validate empty leafref to existing empty value ok"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"

new "netconf discard-changes"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><discard-changes/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"

if [ $BE -ne 0 ]; then
new "Kill backend"
# Check if premature kill
pid=$(pgrep -u root -f clixon_backend)
if [ -z "$pid" ]; then
err "backend already dead"
fi
# kill backend
stop_backend -f $cfg
fi

rm -rf $dir

new "endtest"
endtest
Loading