schema compile CHANGE Notifications support
diff --git a/tests/src/test_parser_yang.c b/tests/src/test_parser_yang.c
index 92e4ec8..2c68caf 100644
--- a/tests/src/test_parser_yang.c
+++ b/tests/src/test_parser_yang.c
@@ -1943,6 +1943,66 @@
}
static void
+test_notification(void **state)
+{
+ *state = test_notification;
+
+ struct ly_parser_ctx ctx = {0};
+ struct lysp_notif *notifs = NULL;
+ struct lysp_node_container *c = NULL;
+ const char *str;
+
+ assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &ctx.ctx));
+ assert_non_null(ctx.ctx);
+ ctx.line = 1;
+ ctx.mod_version = 2; /* simulate YANG 1.1 */
+
+ /* invalid cardinality */
+#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
+ str = "func {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+ assert_int_equal(LY_EVALID, parse_notif(&ctx, &str, NULL, ¬ifs)); \
+ logbuf_assert("Duplicate keyword \""MEMBER"\". Line number 1."); \
+ FREE_ARRAY(ctx.ctx, notifs, lysp_notif_free); notifs = NULL;
+
+ TEST_DUP("description", "text1", "text2");
+ TEST_DUP("reference", "1", "2");
+ TEST_DUP("status", "current", "obsolete");
+#undef TEST_DUP
+
+ /* full content */
+ str = "top;";
+ assert_int_equal(LY_SUCCESS, parse_container(&ctx, &str, NULL, (struct lysp_node**)&c));
+ str = "ntf {anydata a1; anyxml a2; choice ch; container c; description test; grouping grp; if-feature f; leaf l {type int8;}"
+ "leaf-list ll {type int8;} list li; must 1; reference test; status current; typedef mytype {type int8;} uses grp; m:ext;}";
+ assert_int_equal(LY_SUCCESS, parse_notif(&ctx, &str, (struct lysp_node*)c, ¬ifs));
+ assert_non_null(notifs);
+ assert_int_equal(LYS_NOTIF, notifs->nodetype);
+ assert_string_equal("ntf", notifs->name);
+ assert_string_equal("test", notifs->dsc);
+ assert_non_null(notifs->exts);
+ assert_non_null(notifs->iffeatures);
+ assert_string_equal("test", notifs->ref);
+ assert_non_null(notifs->groupings);
+ assert_non_null(notifs->typedefs);
+ assert_non_null(notifs->musts);
+ assert_non_null(notifs->data);
+ assert_int_equal(LYS_STATUS_CURR, notifs->flags);
+
+ ly_set_erase(&ctx.tpdfs_nodes, NULL);
+ FREE_ARRAY(ctx.ctx, notifs, lysp_notif_free); notifs = NULL;
+
+ /* invalid content */
+ str = "ntf {config true} ...";
+ assert_int_equal(LY_EVALID, parse_notif(&ctx, &str, NULL, ¬ifs));
+ logbuf_assert("Invalid keyword \"config\" as a child of \"notification\". Line number 1.");
+ FREE_ARRAY(ctx.ctx, notifs, lysp_notif_free); notifs = NULL;
+
+ *state = NULL;
+ lysp_node_free(ctx.ctx, (struct lysp_node*)c);
+ ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
test_uses(void **state)
{
*state = test_uses;
@@ -2061,6 +2121,7 @@
cmocka_unit_test_setup_teardown(test_anydata, logger_setup, logger_teardown),
cmocka_unit_test_setup_teardown(test_anyxml, logger_setup, logger_teardown),
cmocka_unit_test_setup_teardown(test_action, logger_setup, logger_teardown),
+ cmocka_unit_test_setup_teardown(test_notification, logger_setup, logger_teardown),
cmocka_unit_test_setup_teardown(test_grouping, logger_setup, logger_teardown),
cmocka_unit_test_setup_teardown(test_uses, logger_setup, logger_teardown),
cmocka_unit_test_setup_teardown(test_augment, logger_setup, logger_teardown),
diff --git a/tests/src/test_tree_schema.c b/tests/src/test_tree_schema.c
index 0a91f03..48fdfc1 100644
--- a/tests/src/test_tree_schema.c
+++ b/tests/src/test_tree_schema.c
@@ -135,12 +135,10 @@
rpc = (const struct lysc_action*)node;
assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
assert_string_equal("i", node->name);
- /* TODO Notifications
assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
assert_string_equal("j", node->name);
assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
assert_string_equal("k", node->name);
- */
assert_null(node = lys_getnext(node, NULL, mod->compiled, 0));
/* Inside container */
assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, 0));
@@ -159,10 +157,8 @@
assert_string_equal("seven", node->name);
assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, 0));
assert_string_equal("eight", node->name);
- /* TODO Notifications
assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, 0));
assert_string_equal("nine", node->name);
- */
assert_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, 0));
/* Inside RPC */
assert_non_null(node = lys_getnext(node, (const struct lysc_node*)rpc, mod->compiled, 0));
diff --git a/tests/src/test_tree_schema_compile.c b/tests/src/test_tree_schema_compile.c
index 8f50ead..b098ead 100644
--- a/tests/src/test_tree_schema_compile.c
+++ b/tests/src/test_tree_schema_compile.c
@@ -521,15 +521,24 @@
assert_string_equal("10", ll->dflts[0]);
assert_int_equal(LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_USER, ll->flags);
- /* ordered-by is ignored for state data, RPC/action output parameters and notification content
- * TODO test also, RPC output parameters and notification content */
+ /* ordered-by is ignored for state data, RPC/action output parameters and notification content */
assert_non_null(mod = lys_parse_mem(ctx, "module d {yang-version 1.1;namespace urn:d;prefix d;"
"leaf-list ll {config false; type string; ordered-by user;}}", LYS_IN_YANG));
/* but warning is present: */
- logbuf_assert("The ordered-by statement is ignored in lists representing state data, RPC/action output parameters or notification content ().");
+ logbuf_assert("The ordered-by statement is ignored in lists representing state data ().");
assert_non_null(mod->compiled);
assert_non_null((ll = (struct lysc_node_leaflist*)mod->compiled->data));
assert_int_equal(LYS_CONFIG_R | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM | LYS_SET_CONFIG, ll->flags);
+ logbuf_clean();
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module e {yang-version 1.1;namespace urn:e;prefix e;"
+ "rpc oper {output {leaf-list ll {type string; ordered-by user;}}}}", LYS_IN_YANG));
+ logbuf_assert("The ordered-by statement is ignored in lists representing RPC/action output parameters ().");
+ logbuf_clean();
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module f {yang-version 1.1;namespace urn:f;prefix f;"
+ "notification event {leaf-list ll {type string; ordered-by user;}}}", LYS_IN_YANG));
+ logbuf_assert("The ordered-by statement is ignored in lists representing notification content ().");
/* invalid */
assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;leaf-list ll {type empty;}}", LYS_IN_YANG));
@@ -817,10 +826,93 @@
logbuf_assert("Duplicate identifier \"y\" of data definition/RPC/action/Notification statement.");
assert_null(lys_parse_mem(ctx, "module dd {yang-version 1.1; namespace urn:dd;prefix dd;container c {action z; action z;}}", LYS_IN_YANG));
logbuf_assert("Duplicate identifier \"z\" of data definition/RPC/action/Notification statement.");
- ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule eesub {belongs-to ee {prefix ee;} rpc w;}");
+ ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule eesub {belongs-to ee {prefix ee;} notification w;}");
assert_null(lys_parse_mem(ctx, "module ee {yang-version 1.1; namespace urn:ee;prefix ee;include eesub; rpc w;}", LYS_IN_YANG));
logbuf_assert("Duplicate identifier \"w\" of data definition/RPC/action/Notification statement.");
+ assert_null(lys_parse_mem(ctx, "module ff {yang-version 1.1; namespace urn:ff;prefix ff; rpc test {input {container a {leaf b {type string;}}}}"
+ "augment /test/input/a {action invalid {input {leaf x {type string;}}}}}", LYS_IN_YANG));
+ logbuf_assert("Action \"invalid\" is placed inside another RPC/action.");
+
+ assert_null(lys_parse_mem(ctx, "module gg {yang-version 1.1; namespace urn:gg;prefix gg; notification test {container a {leaf b {type string;}}}"
+ "augment /test/a {action invalid {input {leaf x {type string;}}}}}", LYS_IN_YANG));
+ logbuf_assert("Action \"invalid\" is placed inside Notification.");
+
+ assert_null(lys_parse_mem(ctx, "module hh {yang-version 1.1; namespace urn:hh;prefix hh; notification test {container a {uses grp;}}"
+ "grouping grp {action invalid {input {leaf x {type string;}}}}}", LYS_IN_YANG));
+ logbuf_assert("Action \"invalid\" is placed inside Notification.");
+
+ *state = NULL;
+ ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_notification(void **state)
+{
+ *state = test_notification;
+
+ struct ly_ctx *ctx;
+ struct lys_module *mod;
+ const struct lysc_notif *notif;
+
+ assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module a {namespace urn:a;prefix a;"
+ "notification a1 {leaf x {type int8;}} notification a2;}", LYS_IN_YANG));
+ notif = mod->compiled->notifs;
+ assert_non_null(notif);
+ assert_int_equal(2, LY_ARRAY_SIZE(notif));
+ assert_int_equal(LYS_NOTIF, notif->nodetype);
+ assert_int_equal(LYS_STATUS_CURR, notif->flags);
+ assert_string_equal("a1", notif->name);
+ assert_non_null(notif->data);
+ assert_string_equal("x", notif->data->name);
+ assert_int_equal(LYS_NOTIF, notif[1].nodetype);
+ assert_int_equal(LYS_STATUS_CURR, notif[1].flags);
+ assert_string_equal("a2", notif[1].name);
+ assert_null(notif[1].data);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module b {yang-version 1.1; namespace urn:b;prefix b; container top {"
+ "notification b1 {leaf x {type int8;}} notification b2;}}", LYS_IN_YANG));
+ notif = lysc_node_notifs(mod->compiled->data);
+ assert_non_null(notif);
+ assert_int_equal(2, LY_ARRAY_SIZE(notif));
+ assert_int_equal(LYS_NOTIF, notif->nodetype);
+ assert_int_equal(LYS_STATUS_CURR, notif->flags);
+ assert_string_equal("b1", notif->name);
+ assert_non_null(notif->data);
+ assert_string_equal("x", notif->data->name);
+ assert_int_equal(LYS_NOTIF, notif[1].nodetype);
+ assert_int_equal(LYS_STATUS_CURR, notif[1].flags);
+ assert_string_equal("b2", notif[1].name);
+ assert_null(notif[1].data);
+
+ /* invalid */
+ assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;container top {notification x;}}", LYS_IN_YANG));
+ logbuf_assert("Invalid keyword \"notification\" as a child of \"container\" - the statement is allowed only in YANG 1.1 modules. Line number 1.");
+
+ assert_null(lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;leaf x{type string;} notification x;}", LYS_IN_YANG));
+ logbuf_assert("Duplicate identifier \"x\" of data definition/RPC/action/Notification statement.");
+ assert_null(lys_parse_mem(ctx, "module cc {yang-version 1.1; namespace urn:cc;prefix cc;container c {leaf y {type string;} notification y;}}", LYS_IN_YANG));
+ logbuf_assert("Duplicate identifier \"y\" of data definition/RPC/action/Notification statement.");
+ assert_null(lys_parse_mem(ctx, "module dd {yang-version 1.1; namespace urn:dd;prefix dd;container c {notification z; notification z;}}", LYS_IN_YANG));
+ logbuf_assert("Duplicate identifier \"z\" of data definition/RPC/action/Notification statement.");
+ ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule eesub {belongs-to ee {prefix ee;} rpc w;}");
+ assert_null(lys_parse_mem(ctx, "module ee {yang-version 1.1; namespace urn:ee;prefix ee;include eesub; notification w;}", LYS_IN_YANG));
+ logbuf_assert("Duplicate identifier \"w\" of data definition/RPC/action/Notification statement.");
+
+ assert_null(lys_parse_mem(ctx, "module ff {yang-version 1.1; namespace urn:ff;prefix ff; rpc test {input {container a {leaf b {type string;}}}}"
+ "augment /test/input/a {notification invalid {leaf x {type string;}}}}", LYS_IN_YANG));
+ logbuf_assert("Notification \"invalid\" is placed inside RPC/action.");
+
+ assert_null(lys_parse_mem(ctx, "module gg {yang-version 1.1; namespace urn:gg;prefix gg; notification test {container a {leaf b {type string;}}}"
+ "augment /test/a {notification invalid {leaf x {type string;}}}}", LYS_IN_YANG));
+ logbuf_assert("Notification \"invalid\" is placed inside another Notification.");
+
+ assert_null(lys_parse_mem(ctx, "module hh {yang-version 1.1; namespace urn:hh;prefix hh; rpc test {input {container a {uses grp;}}}"
+ "grouping grp {notification invalid {leaf x {type string;}}}}", LYS_IN_YANG));
+ logbuf_assert("Notification \"invalid\" is placed inside RPC/action.");
+
*state = NULL;
ly_ctx_destroy(ctx, NULL);
}
@@ -3017,10 +3109,6 @@
"deviation /x {deviate replace {type empty;}}}", LYS_IN_YANG));
logbuf_assert("Leaf-list of type \"empty\" is allowed only in YANG 1.1 modules.");
- assert_null(lys_parse_mem(ctx, "module oo {yang-version 1.1; namespace urn:oo;prefix oo; rpc test {input {container a {leaf b {type string;}}}}"
- "augment /test/input/a {action invalid {input {leaf x {type string;}}}}}", LYS_IN_YANG));
- logbuf_assert("Action \"invalid\" is placed inside another RPC/action.");
-
*state = NULL;
ly_ctx_destroy(ctx, NULL);
}
@@ -3050,6 +3138,7 @@
cmocka_unit_test_setup_teardown(test_node_choice, logger_setup, logger_teardown),
cmocka_unit_test_setup_teardown(test_node_anydata, logger_setup, logger_teardown),
cmocka_unit_test_setup_teardown(test_action, logger_setup, logger_teardown),
+ cmocka_unit_test_setup_teardown(test_notification, logger_setup, logger_teardown),
cmocka_unit_test_setup_teardown(test_uses, logger_setup, logger_teardown),
cmocka_unit_test_setup_teardown(test_refine, logger_setup, logger_teardown),
cmocka_unit_test_setup_teardown(test_augment, logger_setup, logger_teardown),