types FEATURE support empty data type values
diff --git a/src/plugins_types.c b/src/plugins_types.c
index 9b88174..4e29fb0 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -1021,7 +1021,7 @@
* Implementation of the ly_type_validate_clb.
*/
static LY_ERR
-ly_type_validate_boolean(struct ly_ctx *ctx, struct lysc_type *type, const char *value, size_t value_len, int options,
+ly_type_validate_boolean(struct ly_ctx *ctx, struct lysc_type *UNUSED(type), const char *value, size_t value_len, int options,
const char **canonized, struct ly_err_item **err, void **priv)
{
int8_t i;
@@ -1084,6 +1084,28 @@
return LY_SUCCESS;
}
+/**
+ * @brief Validate value of the YANG built-in empty type.
+ *
+ * Implementation of the ly_type_validate_clb.
+ */
+static LY_ERR
+ly_type_validate_empty(struct ly_ctx *ctx, struct lysc_type *UNUSED(type), const char *value, size_t value_len, int options,
+ const char **canonized, struct ly_err_item **err, void **UNUSED(priv))
+{
+ if (value_len) {
+ char *errmsg;
+ asprintf(&errmsg, "Invalid empty value \"%.*s\".", (int)value_len, value);
+ *err = ly_err_new(LY_LLERR, LY_EVALID, LYVE_RESTRICTION, errmsg, NULL, NULL);
+ return LY_EVALID;
+ }
+
+ if (options & LY_TYPE_OPTS_CANONIZE) {
+ *canonized = lydict_insert(ctx, "", 0);
+ }
+ return LY_SUCCESS;
+}
+
struct lysc_type_plugin ly_builtin_type_plugins[LY_DATA_TYPE_COUNT] = {
{0}, /* LY_TYPE_UNKNOWN */
{.type = LY_TYPE_BINARY, .validate = ly_type_validate_binary, .store = NULL, .free = NULL},
@@ -1095,7 +1117,7 @@
{.type = LY_TYPE_BITS, .validate = ly_type_validate_bits, .store = ly_type_store_bits, .free = ly_type_free_bits},
{.type = LY_TYPE_BOOL, .validate = ly_type_validate_boolean, .store = ly_type_store_boolean, .free = NULL},
{.type = LY_TYPE_DEC64, .validate = ly_type_validate_decimal64, .store = ly_type_store_decimal64, .free = NULL},
- {0}, /* TODO LY_TYPE_EMPTY */
+ {.type = LY_TYPE_EMPTY, .validate = ly_type_validate_empty, .store = NULL, .free = NULL},
{.type = LY_TYPE_ENUM, .validate = ly_type_validate_enum, .store = ly_type_store_enum, .free = NULL},
{0}, /* TODO LY_TYPE_IDENT */
{0}, /* TODO LY_TYPE_INST */
diff --git a/tests/features/test_types.c b/tests/features/test_types.c
index 536069d..faf6d70 100644
--- a/tests/features/test_types.c
+++ b/tests/features/test_types.c
@@ -73,7 +73,8 @@
"leaf dec64-norestr {type decimal64 {fraction-digits 18;}}"
"leaf str {type string {length 8..10; pattern '[a-z ]*';}}"
"leaf str-norestr {type string;}"
- "leaf bool {type boolean;}}";
+ "leaf bool {type boolean;}"
+ "leaf empty {type empty;}}";
s = calloc(1, sizeof *s);
assert_non_null(s);
@@ -549,6 +550,45 @@
s->func = NULL;
}
+static void
+test_empty(void **state)
+{
+ struct state_s *s = (struct state_s*)(*state);
+ s->func = test_empty;
+
+ struct lyd_node *tree;
+ struct lyd_node_term *leaf;
+
+ const char *data = "<empty xmlns=\"urn:tests:types\"></empty>";
+
+ /* valid data */
+ assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, 0));
+ assert_int_equal(LYS_LEAF, tree->schema->nodetype);
+ assert_string_equal("empty", tree->schema->name);
+ leaf = (struct lyd_node_term*)tree;
+ assert_string_equal("", leaf->value.canonized);
+ lyd_free_all(tree);
+
+ data = "<empty xmlns=\"urn:tests:types\"/>";
+ assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, 0));
+ assert_int_equal(LYS_LEAF, tree->schema->nodetype);
+ assert_string_equal("empty", tree->schema->name);
+ leaf = (struct lyd_node_term*)tree;
+ assert_string_equal("", leaf->value.canonized);
+ lyd_free_all(tree);
+
+ /* invalid value */
+ data = "<empty xmlns=\"urn:tests:types\">x</empty>";
+ assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, 0));
+ logbuf_assert("Invalid empty value \"x\". /");
+
+ data = "<empty xmlns=\"urn:tests:types\"> </empty>";
+ assert_null(lyd_parse_mem(s->ctx, data, LYD_XML, 0));
+ logbuf_assert("Invalid empty value \" \". /");
+
+ s->func = NULL;
+}
+
int main(void)
{
const struct CMUnitTest tests[] = {
@@ -560,6 +600,7 @@
cmocka_unit_test_setup_teardown(test_enums, setup, teardown),
cmocka_unit_test_setup_teardown(test_binary, setup, teardown),
cmocka_unit_test_setup_teardown(test_boolean, setup, teardown),
+ cmocka_unit_test_setup_teardown(test_empty, setup, teardown),
};
return cmocka_run_group_tests(tests, NULL, NULL);