* Identity/identityref mapped between XML and JSON

This commit is contained in:
Olof hagsand 2019-07-28 18:09:55 +02:00
parent ccc95b2826
commit 70ebfa4d80
22 changed files with 779 additions and 133 deletions

View file

@ -8,12 +8,26 @@
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
: ${clixon_util_json:=clixon_util_json}
: ${clixon_util_xml:=clixon_util_xml}
fyang=$dir/json.yang
cat <<EOF > $fyang
module json{
prefix ex;
namespace "urn:example:clixon";
identity genre {
description
"From RFC8040 jukebox example.
Identity prefixes are translated from module-name to xml prefix";
}
identity blues {
base genre;
}
typedef gtype{
type identityref{
base genre;
}
}
leaf a{
type int32;
}
@ -25,6 +39,14 @@ module json{
type string;
}
}
leaf g1 {
description "direct type";
type identityref { base genre; }
}
leaf g2 {
description "indirect type";
type gtype;
}
}
EOF
@ -68,18 +90,42 @@ expecteofeq "$clixon_util_json -jpy $fyang" 0 "$JSON" "$JSONP"
JSON='{"json:a":-23}'
new "json leaf back to json"
expecteofx "$clixon_util_json -j -y $fyang" 0 "$JSON" "$JSON"
expecteofx "$clixon_util_json -jy $fyang" 0 "$JSON" "$JSON"
JSON='{"json:c":{"a":937}}'
new "json parse container back to json"
expecteofx "$clixon_util_json -j -y $fyang" 0 "$JSON" "$JSON"
expecteofx "$clixon_util_json -jy $fyang" 0 "$JSON" "$JSON"
# This should work
# identities translation json -> xml is tricky wrt prefixes, json uses module
# name, xml uses xml namespace prefixes (or default)
JSON='{"json:g1":"json:blues"}'
new "json identity to xml"
expecteofx "$clixon_util_json -y $fyang" 0 "$JSON" '<g1 xmlns="urn:example:clixon">blues</g1>'
new "json identity back to json"
expecteofx "$clixon_util_json -jy $fyang" 0 "$JSON" '{"json:g1":"blues"}'
new "xml identity with explicit ns to json"
expecteofx "$clixon_util_xml -ovjy $fyang" 0 '<g1 xmlns="urn:example:clixon" xmlns:ex="urn:example:clixon">ex:blues</g1>' '{"json:g1":"blues"}'
# Same with indirect type
JSON='{"json:g2":"json:blues"}'
new "json indirect identity to xml"
expecteofx "$clixon_util_json -y $fyang" 0 "$JSON" '<g2 xmlns="urn:example:clixon">blues</g2>'
new "json indirect identity back to json"
expecteofx "$clixon_util_json -jy $fyang" 0 "$JSON" '{"json:g2":"blues"}'
new "xml indirect identity with explicit ns to json"
expecteofx "$clixon_util_xml -ojvy $fyang" 0 '<g2 xmlns="urn:example:clixon" xmlns:ex="urn:example:clixon">ex:blues</g2>' '{"json:g2":"blues"}'
# XXX CDATA translation, should work bit does not
if false; then
JSON='{"json:c": {"s": "<![CDATA[ z > x & x < y ]]>"}}'
new "json parse cdata xml"
expecteofx "$clixon_util_json -j -y $fyang" 0 "$JSON" "$JSON"
fi
rm -rf $dir

View file

@ -98,8 +98,8 @@ new "netconf get $perfreq single reqs"
done | $clixon_netconf -qf $cfg > /dev/null; } 2>&1 | awk '/real/ {print $2}'
# RESTCONF get
new "restconf get test single req XXX"
expecteq "$(curl -s -X GET http://localhost/restconf/data/ietf-interfaces:interfaces/interface=e1)" 0 '{"ietf-interfaces:interface":[{"name":"e1","type":"ex:eth","enabled":true,"oper-status":"up"}]}
new "restconf get test single req"
expecteq "$(curl -s -X GET http://localhost/restconf/data/ietf-interfaces:interfaces/interface=e1)" 0 '{"ietf-interfaces:interface":[{"name":"e1","type":"clixon-example:eth","enabled":true,"oper-status":"up"}]}
'
new "restconf get $perfreq single reqs"

View file

@ -160,16 +160,16 @@ expecteq "$(curl -s -X GET http://localhost/restconf/data/clixon-example:state)"
# Exact match
new "restconf Add subtree eth/0/0 to datastore using POST"
expectfn 'curl -s -i -X POST -H "Accept: application/yang-data+json" -d {"ietf-interfaces:interfaces":{"interface":{"name":"eth/0/0","type":"ex:eth","enabled":true}}} http://localhost/restconf/data' 0 'HTTP/1.1 201 Created'
expectfn 'curl -s -i -X POST -H "Accept: application/yang-data+json" -d {"ietf-interfaces:interfaces":{"interface":{"name":"eth/0/0","type":"clixon-example:eth","enabled":true}}} http://localhost/restconf/data' 0 'HTTP/1.1 201 Created'
new "restconf Re-add subtree eth/0/0 which should give error"
expectfn 'curl -s -X POST -d {"ietf-interfaces:interfaces":{"interface":{"name":"eth/0/0","type":"ex:eth","enabled":true}}} http://localhost/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"}}}'
expectfn 'curl -s -X POST -d {"ietf-interfaces:interfaces":{"interface":{"name":"eth/0/0","type":"clixon-example:eth","enabled":true}}} http://localhost/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"}}}'
# XXX Cant get this to work
#expecteq "$(curl -s -X POST -d {\"interfaces\":{\"interface\":{\"name\":\"eth/0/0\",\"type\":\"ex:eth\",\"enabled\":true}}} http://localhost/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"}}}'
#expecteq "$(curl -s -X POST -d {\"interfaces\":{\"interface\":{\"name\":\"eth/0/0\",\"type\":\"clixon-example:eth\",\"enabled\":true}}} http://localhost/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"}}}'
new "restconf Check interfaces eth/0/0 added"
expectfn "curl -s -X GET http://localhost/restconf/data/ietf-interfaces:interfaces" 0 '{"ietf-interfaces:interfaces":{"interface":[{"name":"eth/0/0","type":"ex:eth","enabled":true,"oper-status":"up"}]}}}
expectfn "curl -s -X GET http://localhost/restconf/data/ietf-interfaces:interfaces" 0 '{"ietf-interfaces:interfaces":{"interface":\[{"name":"eth/0/0","type":"clixon-example:eth","enabled":true,"oper-status":"up"}\]}}}
'
new "restconf delete interfaces"
@ -179,15 +179,12 @@ new "restconf Check empty config"
expectfn "curl -sG http://localhost/restconf/data/clixon-example:state" 0 "$state
"
# XXX: gives <interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
# <interface xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
new "restconf Add interfaces subtree eth/0/0 using POST"
expectfn 'curl -s -X POST -d {"ietf-interfaces:interface":{"name":"eth/0/0","type":"ex:eth","enabled":true}} http://localhost/restconf/data/ietf-interfaces:interfaces' 0 ""
# XXX cant get this to work
#expecteq "$(curl -s -X POST -d '{"interface":{"name":"eth/0/0","type\":"ex:eth","enabled":true}}' http://localhost/restconf/data/interfaces)" 0 ""
expectpart "$(curl -s -X POST http://localhost/restconf/data/ietf-interfaces:interfaces -d '{"ietf-interfaces:interface":{"name":"eth/0/0","type":"clixon-example:eth","enabled":true}}')" 0 ""
#expectfn 'curl -s -X POST http://localhost/restconf/data/ietf-interfaces:interfaces -d {"ietf-interfaces:interface":{"name":"eth/0/0","type":"clixon-example:eth","enabled":true}}' 0 ""
new "restconf Check eth/0/0 added config"
expecteq "$(curl -s -G http://localhost/restconf/data/ietf-interfaces:interfaces)" 0 '{"ietf-interfaces:interfaces":{"interface":[{"name":"eth/0/0","type":"ex:eth","enabled":true,"oper-status":"up"}]}}
expecteq "$(curl -s -G http://localhost/restconf/data/ietf-interfaces:interfaces)" 0 '{"ietf-interfaces:interfaces":{"interface":[{"name":"eth/0/0","type":"clixon-example:eth","enabled":true,"oper-status":"up"}]}}
'
new "restconf Check eth/0/0 added state"
@ -195,7 +192,7 @@ expecteq "$(curl -s -G http://localhost/restconf/data/clixon-example:state)" 0 '
'
new "restconf Re-post eth/0/0 which should generate error"
expecteq "$(curl -s -X POST -d '{"ietf-interfaces:interface":{"name":"eth/0/0","type":"ex:eth","enabled":true}}' http://localhost/restconf/data/ietf-interfaces:interfaces)" 0 '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"data-exists","error-severity":"error","error-message":"Data already exists; cannot create new resource"}}} '
expecteq "$(curl -s -X POST -d '{"ietf-interfaces:interface":{"name":"eth/0/0","type":"clixon-example:eth","enabled":true}}' http://localhost/restconf/data/ietf-interfaces:interfaces)" 0 '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"data-exists","error-severity":"error","error-message":"Data already exists; cannot create new resource"}}} '
new "Add leaf description using POST"
expecteq "$(curl -s -X POST -d '{"ietf-interfaces:description":"The-first-interface"}' http://localhost/restconf/data/ietf-interfaces:interfaces/interface=eth%2f0%2f0)" 0 ""
@ -204,7 +201,7 @@ new "Add nothing using POST"
expectfn 'curl -s -X POST http://localhost/restconf/data/ietf-interfaces:interfaces/interface=eth%2f0%2f0' 0 '"ietf-restconf:errors":{"error":{"error-type":"rpc","error-tag":"malformed-message","error-severity":"error","error-message":" on line 1: syntax error at or before:'
new "restconf Check description added"
expecteq "$(curl -s -G http://localhost/restconf/data/ietf-interfaces:interfaces)" 0 '{"ietf-interfaces:interfaces":{"interface":[{"name":"eth/0/0","description":"The-first-interface","type":"ex:eth","enabled":true,"oper-status":"up"}]}}
expecteq "$(curl -s -G http://localhost/restconf/data/ietf-interfaces:interfaces)" 0 '{"ietf-interfaces:interfaces":{"interface":[{"name":"eth/0/0","description":"The-first-interface","type":"clixon-example:eth","enabled":true,"oper-status":"up"}]}}
'
new "restconf delete eth/0/0"
@ -217,10 +214,10 @@ new "restconf Re-Delete eth/0/0 using none should generate error"
expecteq "$(curl -s -X DELETE http://localhost/restconf/data/ietf-interfaces:interfaces/interface=eth%2f0%2f0)" 0 '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"data-missing","error-severity":"error","error-message":"Data does not exist; cannot delete resource"}}} '
new "restconf Add subtree eth/0/0 using PUT"
expecteq "$(curl -s -X PUT -d '{"ietf-interfaces:interface":{"name":"eth/0/0","type":"ex:eth","enabled":true}}' http://localhost/restconf/data/ietf-interfaces:interfaces/interface=eth%2f0%2f0)" 0 ""
expecteq "$(curl -s -X PUT -d '{"ietf-interfaces:interface":{"name":"eth/0/0","type":"clixon-example:eth","enabled":true}}' http://localhost/restconf/data/ietf-interfaces:interfaces/interface=eth%2f0%2f0)" 0 ""
new "restconf get subtree"
expecteq "$(curl -s -G http://localhost/restconf/data/ietf-interfaces:interfaces)" 0 '{"ietf-interfaces:interfaces":{"interface":[{"name":"eth/0/0","type":"ex:eth","enabled":true,"oper-status":"up"}]}}
expecteq "$(curl -s -G http://localhost/restconf/data/ietf-interfaces:interfaces)" 0 '{"ietf-interfaces:interfaces":{"interface":[{"name":"eth/0/0","type":"clixon-example:eth","enabled":true,"oper-status":"up"}]}}
'
new "restconf rpc using POST json"
@ -262,10 +259,10 @@ if [ -z "$match" ]; then
fi
new "restconf Add subtree without key (expected error)"
expecteq "$(curl -s -X PUT -d '{"ietf-interfaces:interface":{"name":"eth/0/0","type":"ex:eth","enabled":true}}' http://localhost/restconf/data/ietf-interfaces:interfaces/interface)" 0 '{"ietf-restconf:errors":{"error":{"error-type":"rpc","error-tag":"malformed-message","error-severity":"error","error-message":"malformed key, expected '"'"'=restval'"'"'"}}} '
expecteq "$(curl -s -X PUT -d '{"ietf-interfaces:interface":{"name":"eth/0/0","type":"clixon-example:eth","enabled":true}}' http://localhost/restconf/data/ietf-interfaces:interfaces/interface)" 0 '{"ietf-restconf:errors":{"error":{"error-type":"rpc","error-tag":"malformed-message","error-severity":"error","error-message":"malformed key, expected '"'"'=restval'"'"'"}}} '
new "restconf Add subtree with too many keys (expected error)"
expecteq "$(curl -s -X PUT -d '{"ietf-interfaces:interface":{"name":"eth/0/0","type":"ex:eth","enabled":true}}' http://localhost/restconf/data/ietf-interfaces:interfaces/interface=a,b)" 0 '{"ietf-restconf:errors":{"error":{"error-type":"rpc","error-tag":"malformed-message","error-severity":"error","error-message":"List key interface length mismatch"}}} '
expecteq "$(curl -s -X PUT -d '{"ietf-interfaces:interface":{"name":"eth/0/0","type":"clixon-example:eth","enabled":true}}' http://localhost/restconf/data/ietf-interfaces:interfaces/interface=a,b)" 0 '{"ietf-restconf:errors":{"error":{"error-type":"rpc","error-tag":"malformed-message","error-severity":"error","error-message":"List key interface length mismatch"}}} '
new "Kill restconf daemon"
stop_restconf

View file

@ -337,13 +337,12 @@ expectpart "$(curl -s -i -X POST -H 'Content-Type: application/yang-data+xml' ht
new "4.5. PUT replace content"
# XXX should be: jbox:alternative --> example-jukebox:alternative
expectpart "$(curl -s -i -X PUT -H 'Content-Type: application/yang-data+json' http://localhost/restconf/data/example-jukebox:jukebox/library/artist=Foo%20Fighters/album=Wasting%20Light -d '{"example-jukebox:album":[{"name":"Wasting Light","genre":"jbox:alternative","year":2011}]}')" 0 "HTTP/1.1 204 No Content"
expectpart "$(curl -s -i -X PUT -H 'Content-Type: application/yang-data+json' http://localhost/restconf/data/example-jukebox:jukebox/library/artist=Foo%20Fighters/album=Wasting%20Light -d '{"example-jukebox:album":[{"name":"Wasting Light","genre":"example-jukebox:alternative","year":2011}]}')" 0 "HTTP/1.1 204 No Content"
new "4.5. PUT replace content (xml encoding)"
expectpart "$(curl -s -i -X PUT -H 'Content-Type: application/yang-data+xml' http://localhost/restconf/data/example-jukebox:jukebox/library/artist=Foo%20Fighters/album=Wasting%20Light -d '<album xmlns="http://example.com/ns/example-jukebox" xmlns:jbox="http://example.com/ns/example-jukebox"><name>Wasting Light</name><genre>jbox:alternative</genre><year>2011</year></album>')" 0 "HTTP/1.1 204 No Content"
new "4.5. PUT create new"
# XXX should be: jbox:alternative --> example-jukebox:alternative
new "4.5. PUT create new identity"
expectpart "$(curl -s -i -X PUT -H 'Content-Type: application/yang-data+json' http://localhost/restconf/data/example-jukebox:jukebox/library/artist=Clash/album=London%20Calling -d '{"example-jukebox:album":[{"name":"London Calling","year":1979}]}')" 0 "HTTP/1.1 201 Created"

View file

@ -8,6 +8,8 @@ s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
: ${clixon_util_xml:=clixon_util_xml -o} # -o is output
sleep 1 # mysterious fail, maybe this helps?
new "xml parse"
expecteof "$clixon_util_xml" 0 "<a><b/></a>" "^<a><b/></a>$"