schema compile CHANGE support for leafref type
diff --git a/tests/src/test_tree_schema_compile.c b/tests/src/test_tree_schema_compile.c
index e3970c5..4e0d973 100644
--- a/tests/src/test_tree_schema_compile.c
+++ b/tests/src/test_tree_schema_compile.c
@@ -1211,6 +1211,133 @@
ly_ctx_destroy(ctx, NULL);
}
+static void
+test_type_leafref(void **state)
+{
+ *state = test_type_leafref;
+
+ struct ly_ctx *ctx;
+ struct lys_module *mod;
+ struct lysc_type *type;
+ const char *path, *name, *prefix;
+ size_t prefix_len, name_len;
+ int parent_times, has_predicate;
+
+ assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+ /* lys_path_token() */
+ path = "invalid_path";
+ parent_times = 0;
+ assert_int_equal(LY_EINVAL, lys_path_token(&path, &prefix, &prefix_len, &name, &name_len, &parent_times, &has_predicate));
+ path = "..";
+ parent_times = 0;
+ assert_int_equal(LY_EINVAL, lys_path_token(&path, &prefix, &prefix_len, &name, &name_len, &parent_times, &has_predicate));
+ path = "..[";
+ parent_times = 0;
+ assert_int_equal(LY_EINVAL, lys_path_token(&path, &prefix, &prefix_len, &name, &name_len, &parent_times, &has_predicate));
+ path = "../";
+ parent_times = 0;
+ assert_int_equal(LY_EINVAL, lys_path_token(&path, &prefix, &prefix_len, &name, &name_len, &parent_times, &has_predicate));
+ path = "/";
+ parent_times = 0;
+ assert_int_equal(LY_EINVAL, lys_path_token(&path, &prefix, &prefix_len, &name, &name_len, &parent_times, &has_predicate));
+
+ path = "../../pref:id/xxx[predicate]/invalid!!!";
+ parent_times = 0;
+ assert_int_equal(LY_SUCCESS, lys_path_token(&path, &prefix, &prefix_len, &name, &name_len, &parent_times, &has_predicate));
+ assert_string_equal("/xxx[predicate]/invalid!!!", path);
+ assert_int_equal(4, prefix_len);
+ assert_int_equal(0, strncmp("pref", prefix, prefix_len));
+ assert_int_equal(2, name_len);
+ assert_int_equal(0, strncmp("id", name, name_len));
+ assert_int_equal(2, parent_times);
+ assert_int_equal(0, has_predicate);
+ assert_int_equal(LY_SUCCESS, lys_path_token(&path, &prefix, &prefix_len, &name, &name_len, &parent_times, &has_predicate));
+ assert_string_equal("[predicate]/invalid!!!", path);
+ assert_int_equal(0, prefix_len);
+ assert_null(prefix);
+ assert_int_equal(3, name_len);
+ assert_int_equal(0, strncmp("xxx", name, name_len));
+ assert_int_equal(1, has_predicate);
+ path += 11;
+ assert_int_equal(LY_EINVAL, lys_path_token(&path, &prefix, &prefix_len, &name, &name_len, &parent_times, &has_predicate));
+ assert_string_equal("!!!", path);
+ assert_int_equal(0, prefix_len);
+ assert_null(prefix);
+ assert_int_equal(7, name_len);
+ assert_int_equal(0, strncmp("invalid", name, name_len));
+
+ path = "/absolute/prefix:path";
+ parent_times = 0;
+ assert_int_equal(LY_SUCCESS, lys_path_token(&path, &prefix, &prefix_len, &name, &name_len, &parent_times, &has_predicate));
+ assert_string_equal("/prefix:path", path);
+ assert_int_equal(0, prefix_len);
+ assert_null(prefix);
+ assert_int_equal(8, name_len);
+ assert_int_equal(0, strncmp("absolute", name, name_len));
+ assert_int_equal(-1, parent_times);
+ assert_int_equal(0, has_predicate);
+ assert_int_equal(LY_SUCCESS, lys_path_token(&path, &prefix, &prefix_len, &name, &name_len, &parent_times, &has_predicate));
+ assert_int_equal(0, *path);
+ assert_int_equal(6, prefix_len);
+ assert_int_equal(0, strncmp("prefix", prefix, prefix_len));
+ assert_int_equal(4, name_len);
+ assert_int_equal(0, strncmp("path", name, name_len));
+ assert_int_equal(0, has_predicate);
+
+ /* complete leafref paths */
+ assert_non_null(mod = lys_parse_mem(ctx, "module a {yang-version 1.1;namespace urn:a;prefix a;"
+ "leaf ref1 {type leafref {path /a:target1;}} leaf ref2 {type leafref {path /a/target2; require-instance false;}}"
+ "leaf target1 {type string;}container a {leaf target2 {type uint8;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+ type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+ assert_non_null(type);
+ assert_int_equal(LY_TYPE_LEAFREF, type->basetype);
+ assert_string_equal("/a:target1", ((struct lysc_type_leafref*)type)->path);
+ assert_int_equal(1, ((struct lysc_type_leafref*)type)->require_instance);
+ type = ((struct lysc_node_leaf*)mod->compiled->data->next)->type;
+ assert_non_null(type);
+ assert_int_equal(LY_TYPE_LEAFREF, type->basetype);
+ assert_string_equal("/a/target2", ((struct lysc_type_leafref*)type)->path);
+ assert_int_equal(0, ((struct lysc_type_leafref*)type)->require_instance);
+
+ /* TODO target in list with predicates */
+
+
+ /* invalid paths */
+ assert_non_null(mod = lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;container a {leaf target2 {type uint8;}}"
+ "leaf ref1 {type leafref {path ../a/invalid;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid leafref path - unable to find \"../a/invalid\".");
+ assert_non_null(mod = lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;container a {leaf target2 {type uint8;}}"
+ "leaf ref1 {type leafref {path ../../toohigh;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid leafref path \"../../toohigh\" - too many \"..\" in the path.");
+ assert_non_null(mod = lys_parse_mem(ctx, "module cc {namespace urn:cc;prefix cc;container a {leaf target2 {type uint8;}}"
+ "leaf ref1 {type leafref {path /a:invalid;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid leafref path - unable to find module connected with the prefix of the node \"/a:invalid\".");
+ assert_non_null(mod = lys_parse_mem(ctx, "module dd {namespace urn:dd;prefix dd;leaf target1 {type string;}container a {leaf target2 {type uint8;}}"
+ "leaf ref1 {type leafref {path '/a[target2 = current()/../target1]/target2';}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid leafref path - node \"/a\" is expected to be a list, but it is container.");
+ assert_non_null(mod = lys_parse_mem(ctx, "module ee {namespace urn:ee;prefix ee;container a {leaf target2 {type uint8;}}"
+ "leaf ref1 {type leafref {path /a!invalid;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid leafref path at character 3 (/a!invalid).");
+ assert_non_null(mod = lys_parse_mem(ctx, "module ff {namespace urn:ff;prefix ff;container a {leaf target2 {type uint8;}}"
+ "leaf ref1 {type leafref {path /a;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid leafref path \"/a\" - target node is container instead of leaf or leaf-list.");
+ assert_non_null(mod = lys_parse_mem(ctx, "module gg {namespace urn:gg;prefix gg;container a {leaf target2 {type uint8; status deprecated;}}"
+ "leaf ref1 {type leafref {path /a/target2;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("A current definition \"ref1\" is not allowed to reference deprecated definition \"target2\".");
+
+ *state = NULL;
+ ly_ctx_destroy(ctx, NULL);
+}
+
int main(void)
{
const struct CMUnitTest tests[] = {
@@ -1225,6 +1352,7 @@
cmocka_unit_test_setup_teardown(test_type_dec64, logger_setup, logger_teardown),
cmocka_unit_test_setup_teardown(test_type_instanceid, logger_setup, logger_teardown),
cmocka_unit_test_setup_teardown(test_type_identityref, logger_setup, logger_teardown),
+ cmocka_unit_test_setup_teardown(test_type_leafref, logger_setup, logger_teardown),
cmocka_unit_test_setup_teardown(test_node_container, logger_setup, logger_teardown),
};
diff --git a/tests/src/test_tree_schema_helpers.c b/tests/src/test_tree_schema_helpers.c
index 29b7e8c..1c5ca3d 100644
--- a/tests/src/test_tree_schema_helpers.c
+++ b/tests/src/test_tree_schema_helpers.c
@@ -66,6 +66,18 @@
return 0;
}
+static int
+logger_teardown(void **state)
+{
+ (void) state; /* unused */
+#if ENABLE_LOGGER_CHECKING
+ if (*state) {
+ fprintf(stderr, "%s\n", logbuf);
+ }
+#endif
+ return 0;
+}
+
void
logbuf_clean(void)
{
@@ -81,7 +93,7 @@
static void
test_date(void **state)
{
- (void) state; /* unused */
+ *state = test_date;
assert_int_equal(LY_EINVAL, lysp_check_date(NULL, NULL, 0, "date"));
logbuf_assert("Invalid argument date (lysp_check_date()).");
@@ -105,6 +117,8 @@
assert_int_equal(LY_SUCCESS, lysp_check_date(NULL, "2018-11-11", 10, "date"));
assert_int_equal(LY_SUCCESS, lysp_check_date(NULL, "2018-02-28", 10, "date"));
assert_int_equal(LY_SUCCESS, lysp_check_date(NULL, "2016-02-29", 10, "date"));
+
+ *state = NULL;
}
static void
@@ -149,7 +163,7 @@
static void
test_typedef(void **state)
{
- (void) state; /* unused */
+ *state = test_typedef;
struct ly_ctx *ctx = NULL;
const char *str;
@@ -252,15 +266,48 @@
assert_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
logbuf_assert("Invalid name \"x\" of typedef - scoped type collide with a top-level type.");
+ *state = NULL;
ly_ctx_destroy(ctx, NULL);
}
+static void
+test_parse_nodeid(void **state)
+{
+ (void) state; /* unused */
+ const char *str;
+ const char *prefix, *name;
+ size_t prefix_len, name_len;
+
+ str = "123";
+ assert_int_equal(LY_EINVAL, lys_parse_nodeid(&str, &prefix, &prefix_len, &name, &name_len));
+
+ str = "a12_-.!";
+ assert_int_equal(LY_SUCCESS, lys_parse_nodeid(&str, &prefix, &prefix_len, &name, &name_len));
+ assert_null(prefix);
+ assert_int_equal(0, prefix_len);
+ assert_non_null(name);
+ assert_int_equal(6, name_len);
+ assert_int_equal(0, strncmp("a12_-.", name, name_len));
+ assert_string_equal("!", str);
+
+ str = "a12_-.:_b2 xxx";
+ assert_int_equal(LY_SUCCESS, lys_parse_nodeid(&str, &prefix, &prefix_len, &name, &name_len));
+ assert_non_null(prefix);
+ assert_int_equal(6, prefix_len);
+ assert_int_equal(0, strncmp("a12_-.", prefix, prefix_len));
+ assert_non_null(name);
+ assert_int_equal(3, name_len);
+ assert_int_equal(0, strncmp("_b2", name, name_len));
+ assert_string_equal(" xxx", str);
+}
+
int main(void)
{
const struct CMUnitTest tests[] = {
- cmocka_unit_test_setup(test_date, logger_setup),
+ cmocka_unit_test_setup_teardown(test_date, logger_setup, logger_teardown),
cmocka_unit_test_setup(test_revisions, logger_setup),
- cmocka_unit_test_setup(test_typedef, logger_setup),
+ cmocka_unit_test_setup_teardown(test_typedef, logger_setup, logger_teardown),
+ cmocka_unit_test_setup(test_parse_nodeid, logger_setup),
};
return cmocka_run_group_tests(tests, NULL, NULL);