diff --git a/CHANGELOG.md b/CHANGELOG.md
index c632eadd..dab8f27e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,6 @@
# Clixon Changelog
-* [4.4.0](#440) Expected: March 2020
+* [4.4.0](#440) Expected: April 2020
* [4.3.0](#430) 1 January 2020
* [4.3.3](#433)
* [4.3.2](#432)
@@ -21,9 +21,9 @@
* [3.3.1](#331) June 7 2017
## 4.4.0
-Expected: March 2020
+Expected: April 2020
-This release has focussed on refactoring and bugfixing. Lots of
+This release focusses on refactoring and bugfixing. Lots of
changes to basic XML/YANG/RESTCONF code, including a tighter XML/YANG
binding. Memory profiling and new buffer growth management. New
features include optimized search functions and a repair callback.
@@ -43,7 +43,7 @@ features include optimized search functions and a repair callback.
* For more info, see docs at [paths](https://clixon-docs.readthedocs.io/en/latest/paths.html) and
[search](https://clixon-docs.readthedocs.io/en/latest/xml.html#searching-in-xml)
-### API changes on existing protocol/config features
+### API changes on existing protocol/config features (You may have have to change how you use Clixon)
* State data is now ordered-by system for performance reasons. For example, alphabetically for strings and numeric for integers
* Controlled by compile-time option `STATE_ORDERED_BY_SYSTEM`
* Obsolete configuration options present in clixon configuration file will cause clixon application to exit at startup.
@@ -78,7 +78,7 @@ features include optimized search functions and a repair callback.
* `xml_new()` changed from `xml_new(name, xp, ys)` to `xml_new(name, xp, type)`
* If you have used, `ys`, add `xml_spec_set(x, ys)` after the statement
* If you have `xml_type_set(x, TYPE)` after the statement, you can remove it and set it directly as: `xml_new(name, xp, TYPE)`
-* `xml_type_set()`has been removed in the API. The type must be set at creation timw with `xml_new`
+* `xml_type_set()` has been removed in the API. The type must be set at creation time with `xml_new`
* `clicon_rpc_generate_error()` renamed to `clixon_netconf_error()` and added a category parameter
* All uses of `api_path2xpath_cvv()` should be replaced by `api_path2xpath()`
* `api_path2xpath()` added an `xerr` argument.
diff --git a/apps/backend/backend_commit.c b/apps/backend/backend_commit.c
index c28ed9a3..d511e109 100644
--- a/apps/backend/backend_commit.c
+++ b/apps/backend/backend_commit.c
@@ -349,30 +349,6 @@ startup_commit(clicon_handle h,
/* 8. Call plugin transaction commit callbacks */
if (plugin_transaction_commit(h, td) < 0)
goto done;
-#ifdef MOVE_TRANS_END
- /* 10. Call plugin transaction end callbacks */
- plugin_transaction_end(h, td);
-
- /* Clear cached trees from default values and marking */
- if (xmldb_get0_clear(h, td->td_target) < 0)
- goto done;
- /* [Delete and] create running db */
- if (xmldb_exists(h, "running") == 1){
- if (xmldb_delete(h, "running") != 0 && errno != ENOENT)
- goto done;;
- }
- if (xmldb_create(h, "running") < 0)
- goto done;
- /* 9, write (potentially modified) tree to running
- * XXX note here startup is copied to candidate, which may confuse everything
- * XXX default values are overwritten
- */
- if ((ret = xmldb_put(h, "running", OP_REPLACE, td->td_target,
- clicon_username_get(h), cbret)) < 0)
- goto done;
- if (ret == 0)
- goto fail;
-#else
/* Clear cached trees from default values and marking */
if (xmldb_get0_clear(h, td->td_target) < 0)
goto done;
@@ -395,7 +371,6 @@ startup_commit(clicon_handle h,
goto fail;
/* 10. Call plugin transaction end callbacks */
plugin_transaction_end(h, td);
-#endif /* MOVE_TRANS_END */
retval = 1;
done:
if (td){
@@ -566,30 +541,6 @@ candidate_commit(clicon_handle h,
if (plugin_transaction_commit(h, td) < 0)
goto done;
-#ifdef MOVE_TRANS_END
- /* 9. Call plugin transaction end callbacks */
- plugin_transaction_end(h, td);
-
- /* Clear cached trees from default values and marking */
- if (xmldb_get0_clear(h, td->td_target) < 0)
- goto done;
- if (xmldb_get0_clear(h, td->td_src) < 0)
- goto done;
- /* 8. Success: Copy candidate to running
- */
- if (xmldb_copy(h, candidate, "running") < 0)
- goto done;
- /* Here pointers to old (source) tree are obsolete */
- if (td->td_dvec){
- td->td_dlen = 0;
- free(td->td_dvec);
- td->td_dvec = NULL;
- }
- if (td->td_scvec){
- free(td->td_scvec);
- td->td_scvec = NULL;
- }
-#else
/* Clear cached trees from default values and marking */
if (xmldb_get0_clear(h, td->td_target) < 0)
@@ -623,8 +574,6 @@ candidate_commit(clicon_handle h,
/* 9. Call plugin transaction end callbacks */
plugin_transaction_end(h, td);
-
-#endif /* MOVE_TRANS_END */
retval = 1;
done:
@@ -825,17 +774,7 @@ from_client_validate(clicon_handle h,
goto done;
goto ok;
}
-#ifdef MOVE_TRANS_END
- /* Call plugin transaction end callbacks */
- plugin_transaction_end(h, td);
- /* Clear cached trees from default values and marking */
- if (xmldb_get0_clear(h, td->td_src) < 0 ||
- xmldb_get0_clear(h, td->td_target) < 0){
- plugin_transaction_abort(h, td);
- goto done;
- }
- cprintf(cbret, "");
-#else /* MOVE_TRANS_END */
+
if (xmldb_get0_clear(h, td->td_src) < 0 ||
xmldb_get0_clear(h, td->td_target) < 0){
plugin_transaction_abort(h, td);
@@ -853,7 +792,6 @@ from_client_validate(clicon_handle h,
cprintf(cbret, "");
/* Call plugin transaction end callbacks */
plugin_transaction_end(h, td);
-#endif /* MOVE_TRANS_END */
ok:
retval = 0;
done:
diff --git a/include/clixon_custom.h b/include/clixon_custom.h
index 98e00ca9..9666c2f5 100644
--- a/include/clixon_custom.h
+++ b/include/clixon_custom.h
@@ -88,14 +88,6 @@
*/
#define XMLDB_CONFIG_HACK
-/*! Ensure target tree is complete when transaction end is called.
- * This may mean that the call to plugin_transaction_end is done later
- * and/or that cleaning of transaction src/target trees are made later
- * clixon-4.4
- * note: a test in test_transaction.sh does not work
- */
-#define MOVE_TRANS_END
-
/*! Let state data be ordered-by system
* RFC 7950 is cryptic about this
* It says in 7.7.7:
diff --git a/test/test_json_null.sh b/test/test_json_null.sh
new file mode 100755
index 00000000..32afabb6
--- /dev/null
+++ b/test/test_json_null.sh
@@ -0,0 +1,199 @@
+#!/usr/bin/env bash
+# Test: JSON empty/null values. See RFC7951
+# tests include:
+# - parsing in XML, output in JSON
+# - parsing in JSON, output in JSON
+# - parsing in JSON, output in XML?
+#
+# Magic line must be first in script (see README.md)
+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 < $fyang
+module json{
+ prefix j;
+ namespace "urn:example:clixon";
+ container leafs{
+ leaf a{
+ type int32;
+ }
+ leaf b{
+ type string;
+ }
+ leaf c{
+ type boolean;
+ }
+ leaf d{
+ type empty;
+ }
+ }
+ container leaf-lists{
+ leaf-list a{
+ type empty;
+ }
+ leaf-list b{
+ type string;
+ }
+ }
+ container containers{
+ presence true;
+ container a{
+ presence true;
+ leaf b {
+ type empty;
+ }
+ }
+ }
+ container anys{
+ anydata a;
+ anyxml b;
+ }
+}
+EOF
+
+new "test params: -y $fyang"
+
+# Leafs
+XML='0false'
+JSON='{"json:leafs":{"a":0,"b":"","c":false,"d":[null]}}'
+
+new "leafs xml to json"
+expecteofx "$clixon_util_xml -ovjy $fyang" 0 "$XML" "$JSON"
+
+new "leafs json to json"
+expecteofx "$clixon_util_xml -ovJjy $fyang" 0 "$JSON" "$JSON"
+
+new "leafs json to xml"
+expecteofx "$clixon_util_xml -ovJy $fyang" 0 "$JSON" "$XML"
+
+# Leaf-lists single
+XML=''
+JSON='{"json:leaf-lists":{"a":[null],"b":""}}'
+
+new "leaf-list single xml to json"
+expecteofx "$clixon_util_xml -ovjy $fyang" 0 "$XML" "$JSON"
+
+new "leaf-list single json to json"
+expecteofx "$clixon_util_xml -ovjJy $fyang" 0 "$JSON" "$JSON"
+
+new "leaf-list single json to xml"
+expecteofx "$clixon_util_xml -ovJy $fyang" 0 "$JSON" "$XML"
+
+# Leaf-lists multiple
+XML='null'
+JSON='{"json:leaf-lists":{"a":[[null],[null]],"b":["","","null"]}}'
+
+new "leaf-list multiple xml to json"
+expecteofx "$clixon_util_xml -ovjy $fyang" 0 "$XML" "$JSON"
+
+new "leaf-list multiple json to json"
+expecteofx "$clixon_util_xml -ovjJy $fyang" 0 "$JSON" "$JSON"
+
+new "leaf-list multiple json to xml"
+expecteofx "$clixon_util_xml -ovJy $fyang" 0 "$JSON" "$XML"
+
+# Empty container
+XML=''
+JSON='{"json:containers":{"a":{}}}'
+
+new "empty container xml to json"
+expecteofx "$clixon_util_xml -ovjy $fyang" 0 "$XML" "$JSON"
+
+new "empty container json to json"
+expecteofx "$clixon_util_xml -ovjJy $fyang" 0 "$JSON" "$JSON"
+
+new "empty container json to xml"
+expecteofx "$clixon_util_xml -ovJy $fyang" 0 "$JSON" "$XML"
+
+# Empty container whitespace
+XML=' '
+JSON='{"json:containers":{"a":{}}}'
+
+new "empty container whitespace xml to json"
+expecteofx "$clixon_util_xml -ovjy $fyang" 0 "$XML" "$JSON"
+
+# container empty leaf
+XML=''
+JSON='{"json:containers":{"a":{"b":[null]}}}'
+
+new "container empty leaf xml to json"
+expecteofx "$clixon_util_xml -ovjy $fyang" 0 "$XML" "$JSON"
+
+new "container empty leaf json to json"
+expecteofx "$clixon_util_xml -ovjJy $fyang" 0 "$JSON" "$JSON"
+
+new "container empty leaf json to xml"
+expecteofx "$clixon_util_xml -ovJy $fyang" 0 "$JSON" "$XML"
+
+# anydata
+# An anydata instance is encoded in the same way as a container, as a name/object pair
+XML=''
+JSON='{"json:anys":{"a":{}}}'
+
+new "anydata xml to json"
+expecteofx "$clixon_util_xml -ovjy $fyang" 0 "$XML" "$JSON"
+
+new "anydata json to json"
+expecteofx "$clixon_util_xml -ovjJy $fyang" 0 "$JSON" "$JSON"
+
+new "anydata json to xml"
+expecteofx "$clixon_util_xml -ovJy $fyang" 0 "$JSON" "$XML"
+
+# anydata
+XML=''
+JSON='{"json:anys":{"a":{"c":{},"d":{}}}}'
+
+new "anydata w empty node xml to json"
+expecteofx "$clixon_util_xml -ovjy $fyang" 0 "$XML" "$JSON"
+
+new "anydata w empty node json to json"
+expecteofx "$clixon_util_xml -ovjJy $fyang" 0 "$JSON" "$JSON"
+
+new "anydata w empty node json to xml"
+expecteofx "$clixon_util_xml -ovJy $fyang" 0 "$JSON" "$XML"
+
+# Anyxml
+XML=''
+JSON='{"json:anys":{"b":{}}}'
+
+new "anyxml xml to json"
+expecteofx "$clixon_util_xml -ovjy $fyang" 0 "$XML" "$JSON"
+
+new "anyxml json to json"
+expecteofx "$clixon_util_xml -ovjJy $fyang" 0 "$JSON" "$JSON"
+
+new "anyxml json to xml"
+expecteofx "$clixon_util_xml -ovJy $fyang" 0 "$JSON" "$XML"
+
+# JSON wrong in?
+# XXX: maybe this should give error?
+JSON='{"json:leafs":{"b":null}}'
+JSON2='{"json:leafs":{"b":""}}'
+new "leafs null in json to json"
+expecteofx "$clixon_util_xml -ovJjy $fyang" 0 "$JSON" "$JSON2"
+
+# XXX: maybe this should give error?
+JSON='{"json:leafs":{"b":[null]}}'
+JSON2='{"json:leafs":{"b":""}}'
+new "leafs [null] in json to json"
+expecteofx "$clixon_util_xml -ovJjy $fyang" 0 "$JSON" "$JSON2"
+
+# XXX: maybe this should give error?
+JSON='{"json:leafs":{"d":null}}'
+JSON2='{"json:leafs":{"d":[null]}}'
+new "leafs null in json to json"
+expecteofx "$clixon_util_xml -ovJjy $fyang" 0 "$JSON" "$JSON2"
+
+JSON='{"json:leafs":{"d":""}}'
+JSON2='{"json:leafs":{"d":[null]}}'
+new "leafs \"\" in json to json should give error"
+expecteofx "$clixon_util_xml -ovJjy $fyang" 255 "$JSON" "" 2> /dev/null
+
+rm -rf $dir
+
+# unset conditional parameters
+unset clixon_util_json
+unset clixon_util_xml
diff --git a/test/test_transaction.sh b/test/test_transaction.sh
index cd415037..3c7bba18 100755
--- a/test/test_transaction.sh
+++ b/test/test_transaction.sh
@@ -277,7 +277,7 @@ done
checklog "$nr main_end add: 0" $line
let line++
# This check does not work if MOVE_TRANS_END is set
-#checklog "$nr main_end change: 42" $line
+checklog "$nr main_end change: 42" $line
let line+=3 # skip nacm
let nr++