Merge remote-tracking branch 'upstream/libyang2' into libyang2
diff --git a/tests/src/CMakeLists.txt b/tests/src/CMakeLists.txt
index 583e1f4..e535650 100644
--- a/tests/src/CMakeLists.txt
+++ b/tests/src/CMakeLists.txt
@@ -11,7 +11,7 @@
set(local_tests_wraps
" "
"-Wl,--wrap=realloc"
- "-Wl,--wrap=ly_set_add"
+ " "
" "
" "
" "
diff --git a/tests/src/test_common.c b/tests/src/test_common.c
index 0499c42..13da39b 100644
--- a/tests/src/test_common.c
+++ b/tests/src/test_common.c
@@ -13,6 +13,7 @@
*/
#include "../../src/common.c"
+#include "../../src/log.c"
#include <stdarg.h>
#include <stddef.h>
@@ -82,6 +83,7 @@
assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
}
+#ifndef APPLE
void *__real_realloc(void *ptr, size_t size);
void *__wrap_realloc(void *ptr, size_t size)
{
@@ -118,12 +120,15 @@
/* ptr should be freed by ly_realloc() */
}
+#endif /* not APPLE */
int main(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test_setup(test_utf8, logger_setup),
+#ifndef APPLE
cmocka_unit_test(test_lyrealloc),
+#endif
};
return cmocka_run_group_tests(tests, NULL, NULL);
diff --git a/tests/src/test_context.c b/tests/src/test_context.c
index d0fc202..a9dae30 100644
--- a/tests/src/test_context.c
+++ b/tests/src/test_context.c
@@ -13,7 +13,17 @@
*/
#include "tests/config.h"
+#include "../../src/common.c"
+#include "../../src/log.c"
+#include "../../src/set.c"
+#include "../../src/hash_table.c"
+#include "../../src/xpath.c"
+#include "../../src/parser_yang.c"
#include "../../src/context.c"
+#include "../../src/tree_schema_helpers.c"
+#include "../../src/tree_schema_free.c"
+#include "../../src/tree_schema_compile.c"
+#include "../../src/tree_schema.c"
#include <stdarg.h>
#include <stddef.h>
@@ -27,6 +37,7 @@
#define BUFSIZE 1024
char logbuf[BUFSIZE] = {0};
+int store = -1; /* negative for infinite logging, positive for limited logging */
/* set to 0 to printing error messages to stderr instead of checking them in code */
#define ENABLE_LOGGER_CHECKING 1
@@ -35,9 +46,16 @@
logger(LY_LOG_LEVEL level, const char *msg, const char *path)
{
(void) level; /* unused */
- (void) path; /* unused */
-
- strncpy(logbuf, msg, BUFSIZE - 1);
+ if (store) {
+ if (path && path[0]) {
+ snprintf(logbuf, BUFSIZE - 1, "%s %s", msg, path);
+ } else {
+ strncpy(logbuf, msg, BUFSIZE - 1);
+ }
+ if (store > 0) {
+ --store;
+ }
+ }
}
static int
@@ -45,7 +63,7 @@
{
(void) state; /* unused */
#if ENABLE_LOGGER_CHECKING
- ly_set_log_clb(logger, 0);
+ ly_set_log_clb(logger, 1);
#endif
return 0;
}
@@ -56,19 +74,6 @@
# define logbuf_assert(str)
#endif
-int __real_ly_set_add(struct ly_set *set, void *object, int options);
-int __wrap_ly_set_add(struct ly_set *set, void *object, int options)
-{
- int wrap = mock_type(int);
-
- if (wrap) {
- /* error */
- return -1;
- } else {
- return __real_ly_set_add(set, object, options);
- }
-}
-
static void
test_searchdirs(void **state)
{
@@ -98,14 +103,10 @@
logbuf_assert("Unable to use search directory \"/nonexistingfile\" (No such file or directory)");
/* ly_set_add() fails */
- will_return(__wrap_ly_set_add, 1);
- assert_int_equal(LY_EMEM, ly_ctx_set_searchdir(ctx, TESTS_BIN"/src"));
-
/* no change */
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(ctx, NULL));
/* correct path */
- will_return_always(__wrap_ly_set_add, 0);
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(ctx, TESTS_BIN"/src"));
assert_int_equal(1, ctx->search_paths.count);
assert_string_equal(TESTS_BIN"/src", ctx->search_paths.objs[0]);
@@ -122,7 +123,7 @@
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(ctx, TESTS_SRC"/../doc"));
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(ctx, TESTS_SRC));
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(ctx, TESTS_BIN));
- assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(ctx, "/tmp"));
+ assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(ctx, "/home"));
assert_int_equal(8, ctx->search_paths.count);
/* get searchpaths */
@@ -132,7 +133,7 @@
assert_string_equal(TESTS_BIN"/CMakeFiles", list[1]);
assert_string_equal(TESTS_SRC, list[5]);
assert_string_equal(TESTS_BIN, list[6]);
- assert_string_equal("/tmp", list[7]);
+ assert_string_equal("/home", list[7]);
assert_null(list[8]);
/* removing searchpaths */
@@ -147,7 +148,7 @@
assert_int_equal(LY_SUCCESS, ly_ctx_unset_searchdirs(ctx, TESTS_SRC));
assert_int_equal(6, ctx->search_paths.count);
/* last */
- assert_int_equal(LY_SUCCESS, ly_ctx_unset_searchdirs(ctx, "/tmp"));
+ assert_int_equal(LY_SUCCESS, ly_ctx_unset_searchdirs(ctx, "/home"));
assert_int_equal(5, ctx->search_paths.count);
/* all */
assert_int_equal(LY_SUCCESS, ly_ctx_unset_searchdirs(ctx, NULL));
@@ -162,10 +163,10 @@
/* test searchdir list in ly_ctx_new() */
assert_int_equal(LY_EINVAL, ly_ctx_new("/nonexistingfile", 0, &ctx));
logbuf_assert("Unable to use search directory \"/nonexistingfile\" (No such file or directory)");
- assert_int_equal(LY_SUCCESS, ly_ctx_new(TESTS_SRC":/tmp:/tmp:"TESTS_SRC, 0, &ctx));
+ assert_int_equal(LY_SUCCESS, ly_ctx_new(TESTS_SRC":/home:/home:"TESTS_SRC, 0, &ctx));
assert_int_equal(2, ctx->search_paths.count);
assert_string_equal(TESTS_SRC, ctx->search_paths.objs[0]);
- assert_string_equal("/tmp", ctx->search_paths.objs[1]);
+ assert_string_equal("/home", ctx->search_paths.objs[1]);
/* cleanup */
ly_ctx_destroy(ctx, NULL);
@@ -177,6 +178,7 @@
(void) state; /* unused */
struct ly_ctx *ctx;
+
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0xffffffff, &ctx));
/* invalid arguments */
@@ -250,19 +252,155 @@
ly_ctx_destroy(ctx, NULL);
}
+static LY_ERR test_imp_clb(const char *UNUSED(mod_name), const char *UNUSED(mod_rev), const char *UNUSED(submod_name),
+ const char *UNUSED(sub_rev), void *user_data, LYS_INFORMAT *format,
+ const char **module_data, void (**free_module_data)(void *model_data, void *user_data))
+{
+ *module_data = user_data;
+ *format = LYS_IN_YANG;
+ *free_module_data = NULL;
+ return LY_SUCCESS;
+}
+
static void
test_models(void **state)
{
(void) state; /* unused */
+ struct ly_ctx *ctx;
+ const char *str;
+ struct lys_module *mod1, *mod2;
+
/* invalid arguments */
assert_int_equal(0, ly_ctx_get_module_set_id(NULL));
logbuf_assert("Invalid argument ctx (ly_ctx_get_module_set_id()).");
- struct ly_ctx *ctx;
- assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &ctx));
+ assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
assert_int_equal(ctx->module_set_id, ly_ctx_get_module_set_id(ctx));
+ assert_null(lys_parse_mem(ctx, "module x {namespace urn:x;prefix x;}", 3));
+ logbuf_assert("Invalid schema input format.");
+
+ /* import callback */
+ ly_ctx_set_module_imp_clb(ctx, test_imp_clb, (void*)(str = "test"));
+ assert_ptr_equal(test_imp_clb, ctx->imp_clb);
+ assert_ptr_equal(str, ctx->imp_clb_data);
+ assert_ptr_equal(test_imp_clb, ly_ctx_get_module_imp_clb(ctx, (void**)&str));
+ assert_string_equal("test", str);
+
+ ly_ctx_set_module_imp_clb(ctx, NULL, NULL);
+ assert_null(ctx->imp_clb);
+ assert_null(ctx->imp_clb_data);
+
+ /* name collision of module and submodule */
+ ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule y {belongs-to a {prefix a;} revision 2018-10-30;}");
+ assert_null(lys_parse_mem(ctx, "module y {namespace urn:y;prefix y;include y;}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, ly_errcode(ctx));
+ logbuf_assert("Name collision between module and submodule of name \"y\". Line number 1.");
+
+ assert_non_null(lys_parse_mem(ctx, "module a {namespace urn:a;prefix a;include y;revision 2018-10-30; }", LYS_IN_YANG));
+ assert_null(lys_parse_mem(ctx, "module y {namespace urn:y;prefix y;}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, ly_errcode(ctx));
+ logbuf_assert("Name collision between module and submodule of name \"y\". Line number 1.");
+
+ store = 1;
+ ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule y {belongs-to b {prefix b;}}");
+ assert_null(lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;include y;}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, ly_errcode(ctx));
+ logbuf_assert("Name collision between submodules of name \"y\". Line number 1.");
+ store = -1;
+
+ /* selecting correct revision of the submodules */
+ ly_ctx_reset_latests(ctx);
+ ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule y {belongs-to a {prefix a;} revision 2018-10-31;}");
+ mod2 = lys_parse_mem_(ctx, "module a {namespace urn:a;prefix a;include y; revision 2018-10-31;}", LYS_IN_YANG, 0, NULL, NULL, NULL);
+ assert_non_null(mod2);
+ assert_string_equal("2018-10-31", mod2->parsed->includes[0].submodule->revs[0].date);
+
+ /* reloading module in case only the compiled module resists in the context */
+ mod1 = lys_parse_mem(ctx, "module w {namespace urn:w;prefix w;revision 2018-10-24;}", LYS_IN_YANG);
+ assert_non_null(mod1);
+ assert_int_equal(LY_SUCCESS, lys_compile(mod1, LYSC_OPT_FREE_SP));
+ assert_non_null(mod1->compiled);
+ assert_null(mod1->parsed);
+ mod2 = lys_parse_mem(ctx, "module z {namespace urn:z;prefix z;import w {prefix w;revision-date 2018-10-24;}}", LYS_IN_YANG);
+ assert_non_null(mod2);
+ /* mod1->parsed is necessary to compile mod2 because of possible groupings, typedefs, ... */
+ ly_ctx_set_module_imp_clb(ctx, NULL, NULL);
+ assert_int_equal(LY_ENOTFOUND, lys_compile(mod2, 0));
+ logbuf_assert("Unable to reload \"w\" module to import it into \"z\", source data not found.");
+ ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "module w {namespace urn:w;prefix w;revision 2018-10-24;}");
+ assert_int_equal(LY_SUCCESS, lys_compile(mod2, 0));
+ assert_non_null(mod1->parsed);
+ assert_string_equal("w", mod1->parsed->name);
+
+ /* cleanup */
+ ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_get_models(void **state)
+{
+ (void) state; /* unused */
+
+ struct ly_ctx *ctx;
+ const struct lys_module *mod, *mod2;
+ const char *str0 = "module a {namespace urn:a;prefix a;}";
+ const char *str1 = "module a {namespace urn:a;prefix a;revision 2018-10-23;}";
+ const char *str2 = "module a {namespace urn:a;prefix a;revision 2018-10-23;revision 2018-10-24;}";
+
+ assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &ctx));
+
+ /* invalid arguments */
+ assert_ptr_equal(NULL, ly_ctx_get_module(NULL, NULL, NULL));
+ logbuf_assert("Invalid argument ctx (ly_ctx_get_module()).");
+ assert_ptr_equal(NULL, ly_ctx_get_module(ctx, NULL, NULL));
+ logbuf_assert("Invalid argument name (ly_ctx_get_module()).");
+ assert_ptr_equal(NULL, ly_ctx_get_module_ns(NULL, NULL, NULL));
+ logbuf_assert("Invalid argument ctx (ly_ctx_get_module_ns()).");
+ assert_ptr_equal(NULL, ly_ctx_get_module_ns(ctx, NULL, NULL));
+ logbuf_assert("Invalid argument ns (ly_ctx_get_module_ns()).");
+ assert_null(ly_ctx_get_module(ctx, "nonsence", NULL));
+
+ /* internal modules */
+ assert_null(ly_ctx_get_module_implemented(ctx, "ietf-yang-types"));
+ mod = ly_ctx_get_module_implemented(ctx, "yang");
+ assert_non_null(mod);
+ assert_non_null(mod->parsed);
+ assert_string_equal("yang", mod->parsed->name);
+ mod2 = ly_ctx_get_module_implemented_ns(ctx, mod->parsed->ns);
+ assert_ptr_equal(mod, mod2);
+ assert_non_null(ly_ctx_get_module(ctx, "ietf-yang-metadata", "2016-08-05"));
+ assert_non_null(ly_ctx_get_module(ctx, "ietf-yang-types", "2013-07-15"));
+ assert_non_null(ly_ctx_get_module(ctx, "ietf-inet-types", "2013-07-15"));
+ assert_non_null(ly_ctx_get_module_ns(ctx, "urn:ietf:params:xml:ns:yang:ietf-datastores", "2017-08-17"));
+
+ /* select module by revision */
+ mod = lys_parse_mem(ctx, str1, LYS_IN_YANG);
+ /* invalid attempts - implementing module of the same name and inserting the same module */
+ assert_null(lys_parse_mem(ctx, str2, LYS_IN_YANG));
+ logbuf_assert("Module \"a\" is already implemented in the context.");
+ assert_null(lys_parse_mem_(ctx, str1, LYS_IN_YANG, 0, NULL, NULL, NULL));
+ logbuf_assert("Module \"a\" of revision \"2018-10-23\" is already present in the context.");
+ /* insert the second module only as imported, not implemented */
+ mod2 = lys_parse_mem_(ctx, str2, LYS_IN_YANG, 0, NULL, NULL, NULL);
+ assert_non_null(mod);
+ assert_non_null(mod2);
+ assert_ptr_not_equal(mod, mod2);
+ mod = ly_ctx_get_module_latest(ctx, "a");
+ assert_ptr_equal(mod, mod2);
+ mod2 = ly_ctx_get_module_latest_ns(ctx, mod->parsed->ns);
+ assert_ptr_equal(mod, mod2);
+ /* work with module with no revision */
+ mod = lys_parse_mem_(ctx, str0, LYS_IN_YANG, 0, NULL, NULL, NULL);
+ assert_non_null(mod);
+ assert_ptr_equal(mod, ly_ctx_get_module(ctx, "a", NULL));
+ assert_ptr_not_equal(mod, ly_ctx_get_module_latest(ctx, "a"));
+
+ str1 = "submodule b {belongs-to a {prefix a;}}";
+ assert_null(lys_parse_mem(ctx, str1, LYS_IN_YANG));
+ logbuf_assert("Input data contains submodule \"b\" which cannot be parsed directly without its main module.");
+
/* cleanup */
ly_ctx_destroy(ctx, NULL);
}
@@ -273,6 +411,7 @@
cmocka_unit_test_setup(test_searchdirs, logger_setup),
cmocka_unit_test_setup(test_options, logger_setup),
cmocka_unit_test_setup(test_models, logger_setup),
+ cmocka_unit_test_setup(test_get_models, logger_setup),
};
return cmocka_run_group_tests(tests, NULL, NULL);
diff --git a/tests/src/test_hash_table.c b/tests/src/test_hash_table.c
index 1afeb83..2f10f0a 100644
--- a/tests/src/test_hash_table.c
+++ b/tests/src/test_hash_table.c
@@ -12,11 +12,20 @@
* https://opensource.org/licenses/BSD-3-Clause
*/
-#define _BSD_SOURCE
-#define _DEFAULT_SOURCE
+#include "common.h"
#include "tests/config.h"
+#include "../../src/common.c"
+#include "../../src/set.c"
+#include "../../src/log.c"
+#include "../../src/xpath.c"
#include "../../src/hash_table.c"
+#include "../../src/parser_yang.c"
+#include "../../src/context.c"
+#include "../../src/tree_schema_helpers.c"
+#include "../../src/tree_schema_free.c"
+#include "../../src/tree_schema_compile.c"
+#include "../../src/tree_schema.c"
#include <stdarg.h>
#include <stddef.h>
diff --git a/tests/src/test_parser_yang.c b/tests/src/test_parser_yang.c
index db73f63..b07725a 100644
--- a/tests/src/test_parser_yang.c
+++ b/tests/src/test_parser_yang.c
@@ -12,8 +12,17 @@
* https://opensource.org/licenses/BSD-3-Clause
*/
-#include "../../src/tree_schema.c"
+#include "../../src/common.c"
+#include "../../src/set.c"
+#include "../../src/log.c"
+#include "../../src/hash_table.c"
+#include "../../src/xpath.c"
#include "../../src/parser_yang.c"
+#include "../../src/context.c"
+#include "../../src/tree_schema_helpers.c"
+#include "../../src/tree_schema_free.c"
+#include "../../src/tree_schema_compile.c"
+#include "../../src/tree_schema.c"
#include <stdarg.h>
#include <stddef.h>
@@ -27,6 +36,7 @@
#define BUFSIZE 1024
char logbuf[BUFSIZE] = {0};
+int store = -1; /* negative for infinite logging, positive for limited logging */
/* set to 0 to printing error messages to stderr instead of checking them in code */
#define ENABLE_LOGGER_CHECKING 1
@@ -36,11 +46,15 @@
logger(LY_LOG_LEVEL level, const char *msg, const char *path)
{
(void) level; /* unused */
-
- if (path) {
- snprintf(logbuf, BUFSIZE - 1, "%s %s", msg, path);
- } else {
- strncpy(logbuf, msg, BUFSIZE - 1);
+ if (store) {
+ if (path && path[0]) {
+ snprintf(logbuf, BUFSIZE - 1, "%s %s", msg, path);
+ } else {
+ strncpy(logbuf, msg, BUFSIZE - 1);
+ }
+ if (store > 0) {
+ --store;
+ }
}
}
#endif
@@ -55,6 +69,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)
{
@@ -642,6 +668,104 @@
assert_ptr_equal(p, word);
}
+static void
+test_minmax(void **state)
+{
+ *state = test_minmax;
+
+ struct lysp_module mod = {0};
+ struct ly_parser_ctx ctx = {0};
+ uint16_t flags = 0;
+ uint32_t value = 0;
+ struct lysp_ext_instance *ext = 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 = &mod;
+ ctx.mod->version = 2; /* simulate YANG 1.1 */
+
+ str = " 1invalid; ...";
+ assert_int_equal(LY_EVALID, parse_minelements(&ctx, &str, &value, &flags, &ext));
+ logbuf_assert("Invalid value \"1invalid\" of \"min-elements\". Line number 1.");
+
+ flags = value = 0;
+ str = " -1; ...";
+ assert_int_equal(LY_EVALID, parse_minelements(&ctx, &str, &value, &flags, &ext));
+ logbuf_assert("Invalid value \"-1\" of \"min-elements\". Line number 1.");
+
+ /* implementation limit */
+ flags = value = 0;
+ str = " 4294967296; ...";
+ assert_int_equal(LY_EVALID, parse_minelements(&ctx, &str, &value, &flags, &ext));
+ logbuf_assert("Value \"4294967296\" is out of \"min-elements\" bounds. Line number 1.");
+
+ flags = value = 0;
+ str = " 1; ...";
+ assert_int_equal(LY_SUCCESS, parse_minelements(&ctx, &str, &value, &flags, &ext));
+ assert_int_equal(LYS_SET_MIN, flags);
+ assert_int_equal(1, value);
+
+ flags = value = 0;
+ str = " 1 {m:ext;} ...";
+ assert_int_equal(LY_SUCCESS, parse_minelements(&ctx, &str, &value, &flags, &ext));
+ assert_int_equal(LYS_SET_MIN, flags);
+ assert_int_equal(1, value);
+ assert_non_null(ext);
+ FREE_ARRAY(ctx.ctx, ext, lysp_ext_instance_free);
+ ext = NULL;
+
+ flags = value = 0;
+ str = " 1 {config true;} ...";
+ assert_int_equal(LY_EVALID, parse_minelements(&ctx, &str, &value, &flags, &ext));
+ logbuf_assert("Invalid keyword \"config\" as a child of \"min-elements\". Line number 1.");
+
+ str = " 1invalid; ...";
+ assert_int_equal(LY_EVALID, parse_maxelements(&ctx, &str, &value, &flags, &ext));
+ logbuf_assert("Invalid value \"1invalid\" of \"max-elements\". Line number 1.");
+
+ flags = value = 0;
+ str = " -1; ...";
+ assert_int_equal(LY_EVALID, parse_maxelements(&ctx, &str, &value, &flags, &ext));
+ logbuf_assert("Invalid value \"-1\" of \"max-elements\". Line number 1.");
+
+ /* implementation limit */
+ flags = value = 0;
+ str = " 4294967296; ...";
+ assert_int_equal(LY_EVALID, parse_maxelements(&ctx, &str, &value, &flags, &ext));
+ logbuf_assert("Value \"4294967296\" is out of \"max-elements\" bounds. Line number 1.");
+
+ flags = value = 0;
+ str = " 1; ...";
+ assert_int_equal(LY_SUCCESS, parse_maxelements(&ctx, &str, &value, &flags, &ext));
+ assert_int_equal(LYS_SET_MAX, flags);
+ assert_int_equal(1, value);
+
+ flags = value = 0;
+ str = " unbounded; ...";
+ assert_int_equal(LY_SUCCESS, parse_maxelements(&ctx, &str, &value, &flags, &ext));
+ assert_int_equal(LYS_SET_MAX, flags);
+ assert_int_equal(0, value);
+
+ flags = value = 0;
+ str = " 1 {m:ext;} ...";
+ assert_int_equal(LY_SUCCESS, parse_maxelements(&ctx, &str, &value, &flags, &ext));
+ assert_int_equal(LYS_SET_MAX, flags);
+ assert_int_equal(1, value);
+ assert_non_null(ext);
+ FREE_ARRAY(ctx.ctx, ext, lysp_ext_instance_free);
+ ext = NULL;
+
+ flags = value = 0;
+ str = " 1 {config true;} ...";
+ assert_int_equal(LY_EVALID, parse_maxelements(&ctx, &str, &value, &flags, &ext));
+ logbuf_assert("Invalid keyword \"config\" as a child of \"max-elements\". Line number 1.");
+
+ *state = NULL;
+ ly_ctx_destroy(ctx.ctx, NULL);
+}
+
static struct lysp_module *
mod_renew(struct ly_parser_ctx *ctx, struct lysp_module *mod, uint8_t submodule)
{
@@ -650,9 +774,20 @@
mod->ctx = ctx->ctx;
mod->submodule = submodule;
assert_non_null(mod);
+ ctx->mod = mod;
return mod;
}
+static LY_ERR test_imp_clb(const char *UNUSED(mod_name), const char *UNUSED(mod_rev), const char *UNUSED(submod_name),
+ const char *UNUSED(sub_rev), void *user_data, LYS_INFORMAT *format,
+ const char **module_data, void (**free_module_data)(void *model_data, void *user_data))
+{
+ *module_data = user_data;
+ *format = LYS_IN_YANG;
+ *free_module_data = NULL;
+ return LY_SUCCESS;
+}
+
static void
test_module(void **state)
{
@@ -687,7 +822,8 @@
assert_string_equal("x", mod->prefix);
mod = mod_renew(&ctx, mod, 0);
-#define SCHEMA_BEGINNING " name {namespace urn:x;prefix \"x\";"
+#define SCHEMA_BEGINNING " name {yang-version 1.1;namespace urn:x;prefix \"x\";"
+#define SCHEMA_BEGINNING2 " name {namespace urn:x;prefix \"x\";"
#define TEST_NODE(NODETYPE, INPUT, NAME) \
str = SCHEMA_BEGINNING INPUT; \
assert_int_equal(LY_SUCCESS, parse_sub_module(&ctx, &str, mod)); \
@@ -752,22 +888,45 @@
TEST_GENERIC("identity test;}", mod->identities,
assert_string_equal("test", mod->identities[0].name));
/* import */
- TEST_GENERIC("import test {prefix z;}}", mod->imports,
- assert_string_equal("test", mod->imports[0].name));
+ ly_ctx_set_module_imp_clb(ctx.ctx, test_imp_clb, "module zzz { namespace urn:zzz; prefix z;}");
+ TEST_GENERIC("import zzz {prefix z;}}", mod->imports,
+ assert_string_equal("zzz", mod->imports[0].name));
/* import - prefix collision */
- str = SCHEMA_BEGINNING "import test {prefix x;}}";
+ str = SCHEMA_BEGINNING "import zzz {prefix x;}}";
assert_int_equal(LY_EVALID, parse_sub_module(&ctx, &str, mod));
logbuf_assert("Prefix \"x\" already used as module prefix. Line number 2.");
mod = mod_renew(&ctx, mod, 0);
- str = SCHEMA_BEGINNING "import test1 {prefix y;}import test2 {prefix y;}}";
+ str = SCHEMA_BEGINNING "import zzz {prefix y;}import zzz {prefix y;}}";
assert_int_equal(LY_EVALID, parse_sub_module(&ctx, &str, mod));
- logbuf_assert("Prefix \"y\" already used to import \"test1\" module. Line number 2.");
+ logbuf_assert("Prefix \"y\" already used to import \"zzz\" module. Line number 2.");
mod = mod_renew(&ctx, mod, 0);
+ str = "module" SCHEMA_BEGINNING "import zzz {prefix y;}import zzz {prefix z;}}";
+ assert_null(lys_parse_mem(ctx.ctx, str, LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, ly_errcode(ctx.ctx));
+ logbuf_assert("Single revision of the module \"zzz\" referred twice.");
/* include */
- TEST_GENERIC("include test;}", mod->includes,
- assert_string_equal("test", mod->includes[0].name));
+ store = 1;
+ ly_ctx_set_module_imp_clb(ctx.ctx, test_imp_clb, "module xxx { namespace urn:xxx; prefix x;}");
+ str = "module" SCHEMA_BEGINNING "include xxx;}";
+ assert_null(lys_parse_mem(ctx.ctx, str, LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, ly_errcode(ctx.ctx));
+ logbuf_assert("Included \"xxx\" schema from \"name\" is actually not a submodule.");
+ store = -1;
+
+ store = 1;
+ ly_ctx_set_module_imp_clb(ctx.ctx, test_imp_clb, "submodule xxx {belongs-to wrong-name {prefix w;}}");
+ str = "module" SCHEMA_BEGINNING "include xxx;}";
+ assert_null(lys_parse_mem(ctx.ctx, str, LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, ly_errcode(ctx.ctx));
+ logbuf_assert("Included \"xxx\" submodule from \"name\" belongs-to a different module \"wrong-name\".");
+ store = -1;
+
+ ly_ctx_set_module_imp_clb(ctx.ctx, test_imp_clb, "submodule xxx {belongs-to name {prefix x;}}");
+ TEST_GENERIC("include xxx;}", mod->includes,
+ assert_string_equal("xxx", mod->includes[0].name));
+
/* leaf */
TEST_NODE(LYS_LEAF, "leaf test {type string;}}", "test");
/* leaf-list */
@@ -785,7 +944,7 @@
assert_string_equal("RFC7950", mod->ref));
/* revision */
TEST_GENERIC("revision 2018-10-12;}", mod->revs,
- assert_string_equal("2018-10-12", mod->revs[0].rev));
+ assert_string_equal("2018-10-12", mod->revs[0].date));
/* rpc */
TEST_GENERIC("rpc test;}", mod->rpcs,
assert_string_equal("test", mod->rpcs[0].name));
@@ -795,19 +954,19 @@
/* uses */
TEST_NODE(LYS_USES, "uses test;}", "test");
/* yang-version */
- str = SCHEMA_BEGINNING "\n\tyang-version 10;}";
+ str = SCHEMA_BEGINNING2 "\n\tyang-version 10;}";
assert_int_equal(LY_EVALID, parse_sub_module(&ctx, &str, mod));
logbuf_assert("Invalid value \"10\" of \"yang-version\". Line number 3.");
mod = mod_renew(&ctx, mod, 0);
- str = SCHEMA_BEGINNING "yang-version 1.0;yang-version 1.1;}";
+ str = SCHEMA_BEGINNING2 "yang-version 1.0;yang-version 1.1;}";
assert_int_equal(LY_EVALID, parse_sub_module(&ctx, &str, mod));
logbuf_assert("Duplicate keyword \"yang-version\". Line number 3.");
mod = mod_renew(&ctx, mod, 0);
- str = SCHEMA_BEGINNING "yang-version 1.0;}";
+ str = SCHEMA_BEGINNING2 "yang-version 1.0;}";
assert_int_equal(LY_SUCCESS, parse_sub_module(&ctx, &str, mod));
assert_int_equal(1, mod->version);
mod = mod_renew(&ctx, mod, 0);
- str = SCHEMA_BEGINNING "yang-version \"1.1\";}";
+ str = SCHEMA_BEGINNING2 "yang-version \"1.1\";}";
assert_int_equal(LY_SUCCESS, parse_sub_module(&ctx, &str, mod));
assert_int_equal(2, mod->version);
mod = mod_renew(&ctx, mod, 0);
@@ -829,18 +988,20 @@
/* missing mandatory substatements */
str = " subname {}";
+ lydict_remove(ctx.ctx, mod->name);
assert_int_equal(LY_EVALID, parse_sub_module(&ctx, &str, mod));
assert_string_equal("subname", mod->name);
logbuf_assert("Missing mandatory keyword \"belongs-to\" as a child of \"submodule\". Line number 3.");
mod = mod_renew(&ctx, mod, 1);
- str = " subname {belongs-to name;}";
+ str = " subname {belongs-to name {prefix x;}}";
+ lydict_remove(ctx.ctx, mod->name);
assert_int_equal(LY_SUCCESS, parse_sub_module(&ctx, &str, mod));
assert_string_equal("name", mod->belongsto);
mod = mod_renew(&ctx, mod, 1);
#undef SCHEMA_BEGINNING
-#define SCHEMA_BEGINNING " subname {belongs-to name;"
+#define SCHEMA_BEGINNING " subname {belongs-to name {prefix x;}"
/* duplicated namespace, prefix */
TEST_DUP("belongs-to", "module1", "module2", "3", 1);
@@ -868,9 +1029,9 @@
test_identity(void **state)
{
(void) state; /* unused */
- int dict = 1; /* magic variable for FREE macros */
struct ly_parser_ctx ctx;
+ struct lysp_module m = {0};
struct lysp_ident *ident = NULL;
const char *str;
@@ -878,6 +1039,8 @@
assert_non_null(ctx.ctx);
ctx.line = 1;
ctx.indent = 0;
+ ctx.mod = &m;
+ ctx.mod->version = 2; /* simulate YANG 1.1 */
/* invalid cardinality */
#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
@@ -912,7 +1075,6 @@
test_feature(void **state)
{
(void) state; /* unused */
- int dict = 1; /* magic variable for FREE macros */
struct ly_parser_ctx ctx;
struct lysp_feature *features = NULL;
@@ -956,7 +1118,6 @@
test_deviation(void **state)
{
(void) state; /* unused */
- int dict = 1; /* magic variable for FREE macros */
struct ly_parser_ctx ctx;
struct lysp_deviation *d = NULL;
@@ -1019,7 +1180,7 @@
/* invalid cardinality */
#define TEST_DUP(TYPE, MEMBER, VALUE1, VALUE2) \
TEST_DUP_GENERIC(TYPE" {", MEMBER, VALUE1, VALUE2, parse_deviate, \
- &d, "1", lysp_deviate_free(ctx.ctx, d, 1); free(d); d = NULL)
+ &d, "1", lysp_deviate_free(ctx.ctx, d); free(d); d = NULL)
TEST_DUP("add", "config", "true", "false");
TEST_DUP("replace", "default", "int8", "uint8");
@@ -1034,29 +1195,29 @@
assert_int_equal(LY_SUCCESS, parse_deviate(&ctx, &str, &d));
assert_non_null(d);
assert_string_equal(" ...", str);
- lysp_deviate_free(ctx.ctx, d, 1); free(d); d = NULL;
+ lysp_deviate_free(ctx.ctx, d); free(d); d = NULL;
str = " add {units meters; must 1; must 2; unique x; unique y; default a; default b; config true; mandatory true; min-elements 1; max-elements 2; prefix:ext;} ...";
assert_int_equal(LY_SUCCESS, parse_deviate(&ctx, &str, &d));
assert_non_null(d);
assert_string_equal(" ...", str);
- lysp_deviate_free(ctx.ctx, d, 1); free(d); d = NULL;
+ lysp_deviate_free(ctx.ctx, d); free(d); d = NULL;
str = " delete {units meters; must 1; must 2; unique x; unique y; default a; default b; prefix:ext;} ...";
assert_int_equal(LY_SUCCESS, parse_deviate(&ctx, &str, &d));
assert_non_null(d);
assert_string_equal(" ...", str);
- lysp_deviate_free(ctx.ctx, d, 1); free(d); d = NULL;
+ lysp_deviate_free(ctx.ctx, d); free(d); d = NULL;
str = " replace {type string; units meters; default a; config true; mandatory true; min-elements 1; max-elements 2; prefix:ext;} ...";
assert_int_equal(LY_SUCCESS, parse_deviate(&ctx, &str, &d));
assert_non_null(d);
assert_string_equal(" ...", str);
- lysp_deviate_free(ctx.ctx, d, 1); free(d); d = NULL;
+ lysp_deviate_free(ctx.ctx, d); free(d); d = NULL;
/* invalid substatements */
#define TEST_NOT_SUP(DEV, STMT, VALUE) \
str = " "DEV" {"STMT" "VALUE";}..."; \
assert_int_equal(LY_EVALID, parse_deviate(&ctx, &str, &d)); \
logbuf_assert("Deviate \""DEV"\" does not support keyword \""STMT"\". Line number 1."); \
- lysp_deviate_free(ctx.ctx, d, 1); free(d); d = NULL
+ lysp_deviate_free(ctx.ctx, d); free(d); d = NULL
TEST_NOT_SUP("not-supported", "units", "meters");
TEST_NOT_SUP("not-supported", "must", "1");
@@ -1087,6 +1248,621 @@
ly_ctx_destroy(ctx.ctx, NULL);
}
+static void
+test_container(void **state)
+{
+ (void) state; /* unused */
+
+ struct lysp_module mod = {0};
+ struct ly_parser_ctx ctx = {0};
+ 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 = &mod;
+ ctx.mod->version = 2; /* simulate YANG 1.1 */
+
+ /* invalid cardinality */
+#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
+ str = "cont {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+ assert_int_equal(LY_EVALID, parse_container(&ctx, &str, NULL, (struct lysp_node**)&c)); \
+ logbuf_assert("Duplicate keyword \""MEMBER"\". Line number 1."); \
+ lysp_node_free(ctx.ctx, (struct lysp_node*)c); c = NULL;
+
+ TEST_DUP("config", "true", "false");
+ TEST_DUP("description", "text1", "text2");
+ TEST_DUP("presence", "true", "false");
+ TEST_DUP("reference", "1", "2");
+ TEST_DUP("status", "current", "obsolete");
+ TEST_DUP("when", "true", "false");
+#undef TEST_DUP
+
+ /* full content */
+ str = "cont {action x;anydata any;anyxml anyxml; choice ch;config false;container c;description test;grouping g;if-feature f; leaf l {type string;}"
+ "leaf-list ll {type string;} list li;must 'expr';notification not; presence true; reference test;status current;typedef t {type int8;}uses g;when true;m:ext;} ...";
+ assert_int_equal(LY_SUCCESS, parse_container(&ctx, &str, NULL, (struct lysp_node**)&c));
+ assert_non_null(c);
+ assert_int_equal(LYS_CONTAINER, c->nodetype);
+ assert_string_equal("cont", c->name);
+ assert_non_null(c->actions);
+ assert_non_null(c->child);
+ assert_string_equal("test", c->dsc);
+ assert_non_null(c->exts);
+ assert_non_null(c->groupings);
+ assert_non_null(c->iffeatures);
+ assert_non_null(c->musts);
+ assert_non_null(c->notifs);
+ assert_string_equal("true", c->presence);
+ assert_string_equal("test", c->ref);
+ assert_non_null(c->typedefs);
+ assert_non_null(c->when);
+ assert_null(c->parent);
+ assert_null(c->next);
+ assert_int_equal(LYS_CONFIG_R | LYS_STATUS_CURR, c->flags);
+ ly_set_erase(&ctx.tpdfs_nodes, NULL);
+ lysp_node_free(ctx.ctx, (struct lysp_node*)c); c = NULL;
+
+ /* invalid */
+ str = " cont {augment /root;} ...";
+ assert_int_equal(LY_EVALID, parse_container(&ctx, &str, NULL, (struct lysp_node**)&c));
+ logbuf_assert("Invalid keyword \"augment\" as a child of \"container\". Line number 1.");
+ lysp_node_free(ctx.ctx, (struct lysp_node*)c); c = NULL;
+ str = " cont {nonsence true;} ...";
+ assert_int_equal(LY_EVALID, parse_container(&ctx, &str, NULL, (struct lysp_node**)&c));
+ logbuf_assert("Invalid character sequence \"nonsence\", expected a keyword. Line number 1.");
+ lysp_node_free(ctx.ctx, (struct lysp_node*)c); c = NULL;
+
+ ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
+test_leaf(void **state)
+{
+ *state = test_leaf;
+
+ struct lysp_module mod = {0};
+ struct ly_parser_ctx ctx = {0};
+ struct lysp_node_leaf *l = 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 = &mod;
+ //ctx.mod->version = 2; /* simulate YANG 1.1 */
+
+ /* invalid cardinality */
+#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
+ str = "l {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+ assert_int_equal(LY_EVALID, parse_leaf(&ctx, &str, NULL, (struct lysp_node**)&l)); \
+ logbuf_assert("Duplicate keyword \""MEMBER"\". Line number 1."); \
+ lysp_node_free(ctx.ctx, (struct lysp_node*)l); l = NULL;
+
+ TEST_DUP("config", "true", "false");
+ TEST_DUP("default", "x", "y");
+ TEST_DUP("description", "text1", "text2");
+ TEST_DUP("mandatory", "true", "false");
+ TEST_DUP("reference", "1", "2");
+ TEST_DUP("status", "current", "obsolete");
+ TEST_DUP("type", "int8", "uint8");
+ TEST_DUP("units", "text1", "text2");
+ TEST_DUP("when", "true", "false");
+#undef TEST_DUP
+
+ /* full content - without mandatory which is mutual exclusive with default */
+ str = "l {config false;default \"xxx\";description test;if-feature f;"
+ "must 'expr';reference test;status current;type string; units yyy;when true;m:ext;} ...";
+ assert_int_equal(LY_SUCCESS, parse_leaf(&ctx, &str, NULL, (struct lysp_node**)&l));
+ assert_non_null(l);
+ assert_int_equal(LYS_LEAF, l->nodetype);
+ assert_string_equal("l", l->name);
+ assert_string_equal("test", l->dsc);
+ assert_string_equal("xxx", l->dflt);
+ assert_string_equal("yyy", l->units);
+ assert_string_equal("string", l->type.name);
+ assert_non_null(l->exts);
+ assert_non_null(l->iffeatures);
+ assert_non_null(l->musts);
+ assert_string_equal("test", l->ref);
+ assert_non_null(l->when);
+ assert_null(l->parent);
+ assert_null(l->next);
+ assert_int_equal(LYS_CONFIG_R | LYS_STATUS_CURR, l->flags);
+ lysp_node_free(ctx.ctx, (struct lysp_node*)l); l = NULL;
+
+ /* full content - now with mandatory */
+ str = "l {mandatory true; type string;} ...";
+ assert_int_equal(LY_SUCCESS, parse_leaf(&ctx, &str, NULL, (struct lysp_node**)&l));
+ assert_non_null(l);
+ assert_int_equal(LYS_LEAF, l->nodetype);
+ assert_string_equal("l", l->name);
+ assert_string_equal("string", l->type.name);
+ assert_int_equal(LYS_MAND_TRUE, l->flags);
+ lysp_node_free(ctx.ctx, (struct lysp_node*)l); l = NULL;
+
+ /* invalid */
+ str = " l {mandatory true; default xx; type string;} ...";
+ assert_int_equal(LY_EVALID, parse_leaf(&ctx, &str, NULL, (struct lysp_node**)&l));
+ logbuf_assert("Invalid combination of keywords \"mandatory\" and \"default\" as substatements of \"leaf\". Line number 1.");
+ lysp_node_free(ctx.ctx, (struct lysp_node*)l); l = NULL;
+
+ str = " l {description \"missing type\";} ...";
+ assert_int_equal(LY_EVALID, parse_leaf(&ctx, &str, NULL, (struct lysp_node**)&l));
+ logbuf_assert("Missing mandatory keyword \"type\" as a child of \"leaf\". Line number 1.");
+ lysp_node_free(ctx.ctx, (struct lysp_node*)l); l = NULL;
+
+ *state = NULL;
+ ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
+test_leaflist(void **state)
+{
+ *state = test_leaf;
+
+ struct lysp_module mod = {0};
+ struct ly_parser_ctx ctx = {0};
+ struct lysp_node_leaflist *ll = 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 = &mod;
+ ctx.mod->version = 2; /* simulate YANG 1.1 */
+
+ /* invalid cardinality */
+#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
+ str = "ll {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+ assert_int_equal(LY_EVALID, parse_leaflist(&ctx, &str, NULL, (struct lysp_node**)&ll)); \
+ logbuf_assert("Duplicate keyword \""MEMBER"\". Line number 1."); \
+ lysp_node_free(ctx.ctx, (struct lysp_node*)ll); ll = NULL;
+
+ TEST_DUP("config", "true", "false");
+ TEST_DUP("description", "text1", "text2");
+ TEST_DUP("max-elements", "10", "20");
+ TEST_DUP("min-elements", "10", "20");
+ TEST_DUP("ordered-by", "user", "system");
+ TEST_DUP("reference", "1", "2");
+ TEST_DUP("status", "current", "obsolete");
+ TEST_DUP("type", "int8", "uint8");
+ TEST_DUP("units", "text1", "text2");
+ TEST_DUP("when", "true", "false");
+#undef TEST_DUP
+
+ /* full content - without min-elements which is mutual exclusive with default */
+ str = "ll {config false;default \"xxx\"; default \"yyy\";description test;if-feature f;"
+ "max-elements 10;must 'expr';ordered-by user;reference test;"
+ "status current;type string; units zzz;when true;m:ext;} ...";
+ assert_int_equal(LY_SUCCESS, parse_leaflist(&ctx, &str, NULL, (struct lysp_node**)&ll));
+ assert_non_null(ll);
+ assert_int_equal(LYS_LEAFLIST, ll->nodetype);
+ assert_string_equal("ll", ll->name);
+ assert_string_equal("test", ll->dsc);
+ assert_non_null(ll->dflts);
+ assert_int_equal(2, LY_ARRAY_SIZE(ll->dflts));
+ assert_string_equal("xxx", ll->dflts[0]);
+ assert_string_equal("yyy", ll->dflts[1]);
+ assert_string_equal("zzz", ll->units);
+ assert_int_equal(10, ll->max);
+ assert_int_equal(0, ll->min);
+ assert_string_equal("string", ll->type.name);
+ assert_non_null(ll->exts);
+ assert_non_null(ll->iffeatures);
+ assert_non_null(ll->musts);
+ assert_string_equal("test", ll->ref);
+ assert_non_null(ll->when);
+ assert_null(ll->parent);
+ assert_null(ll->next);
+ assert_int_equal(LYS_CONFIG_R | LYS_STATUS_CURR | LYS_ORDBY_USER | LYS_SET_MAX, ll->flags);
+ lysp_node_free(ctx.ctx, (struct lysp_node*)ll); ll = NULL;
+
+ /* full content - now with min-elements */
+ str = "ll {min-elements 10; type string;} ...";
+ assert_int_equal(LY_SUCCESS, parse_leaflist(&ctx, &str, NULL, (struct lysp_node**)&ll));
+ assert_non_null(ll);
+ assert_int_equal(LYS_LEAFLIST, ll->nodetype);
+ assert_string_equal("ll", ll->name);
+ assert_string_equal("string", ll->type.name);
+ assert_int_equal(0, ll->max);
+ assert_int_equal(10, ll->min);
+ assert_int_equal(LYS_SET_MIN, ll->flags);
+ lysp_node_free(ctx.ctx, (struct lysp_node*)ll); ll = NULL;
+
+ /* invalid */
+ str = " ll {min-elements 1; default xx; type string;} ...";
+ assert_int_equal(LY_EVALID, parse_leaflist(&ctx, &str, NULL, (struct lysp_node**)&ll));
+ logbuf_assert("Invalid combination of keywords \"min-elements\" and \"default\" as substatements of \"leaf-list\". Line number 1.");
+ lysp_node_free(ctx.ctx, (struct lysp_node*)ll); ll = NULL;
+
+ str = " ll {description \"missing type\";} ...";
+ assert_int_equal(LY_EVALID, parse_leaflist(&ctx, &str, NULL, (struct lysp_node**)&ll));
+ logbuf_assert("Missing mandatory keyword \"type\" as a child of \"leaf-list\". Line number 1.");
+ lysp_node_free(ctx.ctx, (struct lysp_node*)ll); ll = NULL;
+
+ str = " ll {type string; min-elements 10; max-elements 1;} ..."; /* invalid combination of min/max */
+ assert_int_equal(LY_EVALID, parse_leaflist(&ctx, &str, NULL, (struct lysp_node**)&ll));
+ logbuf_assert("Invalid combination of min-elements and max-elements: min value 10 is bigger than the max value 1. Line number 1.");
+ lysp_node_free(ctx.ctx, (struct lysp_node*)ll); ll = NULL;
+
+ ctx.mod->version = 1; /* simulate YANG 1.0 - default statement is not allowed */
+ str = " ll {default xx; type string;} ...";
+ assert_int_equal(LY_EVALID, parse_leaflist(&ctx, &str, NULL, (struct lysp_node**)&ll));
+ logbuf_assert("Invalid keyword \"default\" as a child of \"leaf-list\" - the statement is allowed only in YANG 1.1 modules. Line number 1.");
+ lysp_node_free(ctx.ctx, (struct lysp_node*)ll); ll = NULL;
+
+ *state = NULL;
+ ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
+test_list(void **state)
+{
+ *state = test_list;
+
+ struct lysp_module mod = {0};
+ struct ly_parser_ctx ctx = {0};
+ struct lysp_node_list *l = 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 = &mod;
+ ctx.mod->version = 2; /* simulate YANG 1.1 */
+
+ /* invalid cardinality */
+#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
+ str = "l {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+ assert_int_equal(LY_EVALID, parse_list(&ctx, &str, NULL, (struct lysp_node**)&l)); \
+ logbuf_assert("Duplicate keyword \""MEMBER"\". Line number 1."); \
+ lysp_node_free(ctx.ctx, (struct lysp_node*)l); l = NULL;
+
+ TEST_DUP("config", "true", "false");
+ TEST_DUP("description", "text1", "text2");
+ TEST_DUP("key", "one", "two");
+ TEST_DUP("max-elements", "10", "20");
+ TEST_DUP("min-elements", "10", "20");
+ TEST_DUP("ordered-by", "user", "system");
+ TEST_DUP("reference", "1", "2");
+ TEST_DUP("status", "current", "obsolete");
+ TEST_DUP("when", "true", "false");
+#undef TEST_DUP
+
+ /* full content */
+ str = "l {action x;anydata any;anyxml anyxml; choice ch;config false;container c;description test;grouping g;if-feature f; key l; leaf l {type string;}"
+ "leaf-list ll {type string;} list li;max-elements 10; min-elements 1;must 'expr';notification not; ordered-by system; reference test;"
+ "status current;typedef t {type int8;}unique xxx;unique yyy;uses g;when true;m:ext;} ...";
+ assert_int_equal(LY_SUCCESS, parse_list(&ctx, &str, NULL, (struct lysp_node**)&l));
+ assert_non_null(l);
+ assert_int_equal(LYS_LIST, l->nodetype);
+ assert_string_equal("l", l->name);
+ assert_string_equal("test", l->dsc);
+ assert_string_equal("l", l->key);
+ assert_non_null(l->uniques);
+ assert_int_equal(2, LY_ARRAY_SIZE(l->uniques));
+ assert_string_equal("xxx", l->uniques[0]);
+ assert_string_equal("yyy", l->uniques[1]);
+ assert_int_equal(10, l->max);
+ assert_int_equal(1, l->min);
+ assert_non_null(l->exts);
+ assert_non_null(l->iffeatures);
+ assert_non_null(l->musts);
+ assert_string_equal("test", l->ref);
+ assert_non_null(l->when);
+ assert_null(l->parent);
+ assert_null(l->next);
+ assert_int_equal(LYS_CONFIG_R | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM | LYS_SET_MAX | LYS_SET_MIN, l->flags);
+ ly_set_erase(&ctx.tpdfs_nodes, NULL);
+ lysp_node_free(ctx.ctx, (struct lysp_node*)l); l = NULL;
+
+ *state = NULL;
+ ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
+test_choice(void **state)
+{
+ *state = test_choice;
+
+ struct lysp_module mod = {0};
+ struct ly_parser_ctx ctx = {0};
+ struct lysp_node_choice *ch = 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 = &mod;
+ ctx.mod->version = 2; /* simulate YANG 1.1 */
+
+ /* invalid cardinality */
+#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
+ str = "ch {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+ assert_int_equal(LY_EVALID, parse_choice(&ctx, &str, NULL, (struct lysp_node**)&ch)); \
+ logbuf_assert("Duplicate keyword \""MEMBER"\". Line number 1."); \
+ lysp_node_free(ctx.ctx, (struct lysp_node*)ch); ch = NULL;
+
+ TEST_DUP("config", "true", "false");
+ TEST_DUP("default", "a", "b");
+ TEST_DUP("description", "text1", "text2");
+ TEST_DUP("mandatory", "true", "false");
+ TEST_DUP("reference", "1", "2");
+ TEST_DUP("status", "current", "obsolete");
+ TEST_DUP("when", "true", "false");
+#undef TEST_DUP
+
+ /* full content - without default due to a collision with mandatory */
+ str = "ch {anydata any;anyxml anyxml; case c;choice ch;config false;container c;description test;if-feature f;leaf l {type string;}"
+ "leaf-list ll {type string;} list li;mandatory true;reference test;status current;when true;m:ext;} ...";
+ assert_int_equal(LY_SUCCESS, parse_choice(&ctx, &str, NULL, (struct lysp_node**)&ch));
+ assert_non_null(ch);
+ assert_int_equal(LYS_CHOICE, ch->nodetype);
+ assert_string_equal("ch", ch->name);
+ assert_string_equal("test", ch->dsc);
+ assert_non_null(ch->exts);
+ assert_non_null(ch->iffeatures);
+ assert_string_equal("test", ch->ref);
+ assert_non_null(ch->when);
+ assert_null(ch->parent);
+ assert_null(ch->next);
+ assert_int_equal(LYS_CONFIG_R | LYS_STATUS_CURR | LYS_MAND_TRUE, ch->flags);
+ lysp_node_free(ctx.ctx, (struct lysp_node*)ch); ch = NULL;
+
+ /* full content - the default missing from the previous node */
+ str = "ch {default c;case c;} ...";
+ assert_int_equal(LY_SUCCESS, parse_choice(&ctx, &str, NULL, (struct lysp_node**)&ch));
+ assert_non_null(ch);
+ assert_int_equal(LYS_CHOICE, ch->nodetype);
+ assert_string_equal("ch", ch->name);
+ assert_string_equal("c", ch->dflt);
+ assert_int_equal(0, ch->flags);
+ lysp_node_free(ctx.ctx, (struct lysp_node*)ch); ch = NULL;
+
+ /* invalid content */
+ str = "ch {mandatory true; default c1; case c1 {leaf x{type string;}}} ...";
+ assert_int_equal(LY_EVALID, parse_choice(&ctx, &str, NULL, (struct lysp_node**)&ch));
+ logbuf_assert("Invalid combination of keywords \"mandatory\" and \"default\" as substatements of \"choice\". Line number 1.");
+ lysp_node_free(ctx.ctx, (struct lysp_node*)ch); ch = NULL;
+
+ *state = NULL;
+ ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
+test_case(void **state)
+{
+ *state = test_case;
+
+ struct lysp_module mod = {0};
+ struct ly_parser_ctx ctx = {0};
+ struct lysp_node_case *cs = 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 = &mod;
+ ctx.mod->version = 2; /* simulate YANG 1.1 */
+
+ /* invalid cardinality */
+#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
+ str = "cs {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+ assert_int_equal(LY_EVALID, parse_case(&ctx, &str, NULL, (struct lysp_node**)&cs)); \
+ logbuf_assert("Duplicate keyword \""MEMBER"\". Line number 1."); \
+ lysp_node_free(ctx.ctx, (struct lysp_node*)cs); cs = NULL;
+
+ TEST_DUP("description", "text1", "text2");
+ TEST_DUP("reference", "1", "2");
+ TEST_DUP("status", "current", "obsolete");
+ TEST_DUP("when", "true", "false");
+#undef TEST_DUP
+
+ /* full content */
+ str = "cs {anydata any;anyxml anyxml; choice ch;container c;description test;if-feature f;leaf l {type string;}"
+ "leaf-list ll {type string;} list li;reference test;status current;uses grp;when true;m:ext;} ...";
+ assert_int_equal(LY_SUCCESS, parse_case(&ctx, &str, NULL, (struct lysp_node**)&cs));
+ assert_non_null(cs);
+ assert_int_equal(LYS_CASE, cs->nodetype);
+ assert_string_equal("cs", cs->name);
+ assert_string_equal("test", cs->dsc);
+ assert_non_null(cs->exts);
+ assert_non_null(cs->iffeatures);
+ assert_string_equal("test", cs->ref);
+ assert_non_null(cs->when);
+ assert_null(cs->parent);
+ assert_null(cs->next);
+ assert_int_equal(LYS_STATUS_CURR, cs->flags);
+ lysp_node_free(ctx.ctx, (struct lysp_node*)cs); cs = NULL;
+
+ /* invalid content */
+ str = "cs {config true} ...";
+ assert_int_equal(LY_EVALID, parse_case(&ctx, &str, NULL, (struct lysp_node**)&cs));
+ logbuf_assert("Invalid keyword \"config\" as a child of \"case\". Line number 1.");
+ lysp_node_free(ctx.ctx, (struct lysp_node*)cs); cs = NULL;
+
+ *state = NULL;
+ ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
+test_any(void **state, enum yang_keyword kw)
+{
+ *state = test_any;
+
+ struct lysp_module mod = {0};
+ struct ly_parser_ctx ctx = {0};
+ struct lysp_node_anydata *any = 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 = &mod;
+ if (kw == YANG_ANYDATA) {
+ ctx.mod->version = 2; /* simulate YANG 1.1 */
+ } else {
+ ctx.mod->version = 1; /* simulate YANG 1.0 */
+ }
+
+ /* invalid cardinality */
+#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
+ str = "l {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+ assert_int_equal(LY_EVALID, parse_any(&ctx, &str, kw, NULL, (struct lysp_node**)&any)); \
+ logbuf_assert("Duplicate keyword \""MEMBER"\". Line number 1."); \
+ lysp_node_free(ctx.ctx, (struct lysp_node*)any); any = NULL;
+
+ TEST_DUP("config", "true", "false");
+ TEST_DUP("description", "text1", "text2");
+ TEST_DUP("mandatory", "true", "false");
+ TEST_DUP("reference", "1", "2");
+ TEST_DUP("status", "current", "obsolete");
+ TEST_DUP("when", "true", "false");
+#undef TEST_DUP
+
+ /* full content */
+ str = "any {config true;description test;if-feature f;mandatory true;must 'expr';reference test;status current;when true;m:ext;} ...";
+ assert_int_equal(LY_SUCCESS, parse_any(&ctx, &str, kw, NULL, (struct lysp_node**)&any));
+ assert_non_null(any);
+ assert_int_equal(kw == YANG_ANYDATA ? LYS_ANYDATA : LYS_ANYXML, any->nodetype);
+ assert_string_equal("any", any->name);
+ assert_string_equal("test", any->dsc);
+ assert_non_null(any->exts);
+ assert_non_null(any->iffeatures);
+ assert_non_null(any->musts);
+ assert_string_equal("test", any->ref);
+ assert_non_null(any->when);
+ assert_null(any->parent);
+ assert_null(any->next);
+ assert_int_equal(LYS_CONFIG_W | LYS_STATUS_CURR | LYS_MAND_TRUE, any->flags);
+ lysp_node_free(ctx.ctx, (struct lysp_node*)any); any = NULL;
+
+ *state = NULL;
+ ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
+test_anydata(void **state)
+{
+ return test_any(state, YANG_ANYDATA);
+}
+
+static void
+test_anyxml(void **state)
+{
+ return test_any(state, YANG_ANYXML);
+}
+
+static void
+test_grouping(void **state)
+{
+ *state = test_grouping;
+
+ struct lysp_module mod = {0};
+ struct ly_parser_ctx ctx = {0};
+ struct lysp_grp *grp = 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 = &mod;
+ ctx.mod->version = 2; /* simulate YANG 1.1 */
+
+ /* invalid cardinality */
+#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
+ str = "l {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+ assert_int_equal(LY_EVALID, parse_grouping(&ctx, &str, NULL, &grp)); \
+ logbuf_assert("Duplicate keyword \""MEMBER"\". Line number 1."); \
+ FREE_ARRAY(ctx.ctx, grp, lysp_grp_free); grp = NULL;
+
+ TEST_DUP("description", "text1", "text2");
+ TEST_DUP("reference", "1", "2");
+ TEST_DUP("status", "current", "obsolete");
+#undef TEST_DUP
+
+ /* full content */
+ str = "grp {action x;anydata any;anyxml anyxml; choice ch;container c;description test;grouping g;leaf l {type string;}"
+ "leaf-list ll {type string;} list li;notification not;reference test;status current;typedef t {type int8;}uses g;m:ext;} ...";
+ assert_int_equal(LY_SUCCESS, parse_grouping(&ctx, &str, NULL, &grp));
+ assert_non_null(grp);
+ assert_int_equal(LYS_GROUPING, grp->nodetype);
+ assert_string_equal("grp", grp->name);
+ assert_string_equal("test", grp->dsc);
+ assert_non_null(grp->exts);
+ assert_string_equal("test", grp->ref);
+ assert_null(grp->parent);
+ assert_int_equal( LYS_STATUS_CURR, grp->flags);
+ ly_set_erase(&ctx.tpdfs_nodes, NULL);
+ FREE_ARRAY(ctx.ctx, grp, lysp_grp_free); grp = NULL;
+
+ /* invalid content */
+ str = "grp {config true} ...";
+ assert_int_equal(LY_EVALID, parse_grouping(&ctx, &str, NULL, &grp));
+ logbuf_assert("Invalid keyword \"config\" as a child of \"grouping\". Line number 1.");
+ FREE_ARRAY(ctx.ctx, grp, lysp_grp_free); grp = NULL;
+
+ str = "grp {must 'expr'} ...";
+ assert_int_equal(LY_EVALID, parse_grouping(&ctx, &str, NULL, &grp));
+ logbuf_assert("Invalid keyword \"must\" as a child of \"grouping\". Line number 1.");
+ FREE_ARRAY(ctx.ctx, grp, lysp_grp_free); grp = NULL;
+
+ *state = NULL;
+ ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
+test_uses(void **state)
+{
+ *state = test_uses;
+
+ struct lysp_module mod = {0};
+ struct ly_parser_ctx ctx = {0};
+ struct lysp_node_uses *u = 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 = &mod;
+ ctx.mod->version = 2; /* simulate YANG 1.1 */
+
+ /* invalid cardinality */
+#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
+ str = "l {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+ assert_int_equal(LY_EVALID, parse_uses(&ctx, &str, NULL, (struct lysp_node**)&u)); \
+ logbuf_assert("Duplicate keyword \""MEMBER"\". Line number 1."); \
+ lysp_node_free(ctx.ctx, (struct lysp_node*)u); u = NULL;
+
+ TEST_DUP("description", "text1", "text2");
+ TEST_DUP("reference", "1", "2");
+ TEST_DUP("status", "current", "obsolete");
+ TEST_DUP("when", "true", "false");
+#undef TEST_DUP
+
+ /* full content */
+ str = "grpref {augment some/node;description test;if-feature f;reference test;refine some/other/node;status current;when true;m:ext;} ...";
+ assert_int_equal(LY_SUCCESS, parse_uses(&ctx, &str, NULL, (struct lysp_node**)&u));
+ assert_non_null(u);
+ assert_int_equal(LYS_USES, u->nodetype);
+ assert_string_equal("grpref", u->name);
+ assert_string_equal("test", u->dsc);
+ assert_non_null(u->exts);
+ assert_non_null(u->iffeatures);
+ assert_string_equal("test", u->ref);
+ assert_non_null(u->augments);
+ assert_non_null(u->refines);
+ assert_non_null(u->when);
+ assert_null(u->parent);
+ assert_null(u->next);
+ assert_int_equal(LYS_STATUS_CURR, u->flags);
+ lysp_node_free(ctx.ctx, (struct lysp_node*)u); u = NULL;
+
+ *state = NULL;
+ ly_ctx_destroy(ctx.ctx, NULL);
+}
int main(void)
{
const struct CMUnitTest tests[] = {
@@ -1094,11 +1870,22 @@
cmocka_unit_test_setup(test_comments, logger_setup),
cmocka_unit_test_setup(test_arg, logger_setup),
cmocka_unit_test_setup(test_stmts, logger_setup),
+ cmocka_unit_test_setup_teardown(test_minmax, logger_setup, logger_teardown),
cmocka_unit_test_setup(test_module, logger_setup),
cmocka_unit_test_setup(test_identity, logger_setup),
cmocka_unit_test_setup(test_feature, logger_setup),
cmocka_unit_test_setup(test_deviation, logger_setup),
cmocka_unit_test_setup(test_deviate, logger_setup),
+ cmocka_unit_test_setup(test_container, logger_setup),
+ cmocka_unit_test_setup_teardown(test_leaf, logger_setup, logger_teardown),
+ cmocka_unit_test_setup_teardown(test_leaflist, logger_setup, logger_teardown),
+ cmocka_unit_test_setup_teardown(test_list, logger_setup, logger_teardown),
+ cmocka_unit_test_setup_teardown(test_choice, logger_setup, logger_teardown),
+ cmocka_unit_test_setup_teardown(test_case, logger_setup, logger_teardown),
+ 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_grouping, logger_setup, logger_teardown),
+ cmocka_unit_test_setup_teardown(test_uses, logger_setup, logger_teardown),
};
return cmocka_run_group_tests(tests, NULL, NULL);
diff --git a/tests/src/test_parser_yin.c b/tests/src/test_parser_yin.c
index 8e14839..870e5b4 100644
--- a/tests/src/test_parser_yin.c
+++ b/tests/src/test_parser_yin.c
@@ -1,3 +1,17 @@
+#include "../../src/common.c"
+#include "../../src/set.c"
+#include "../../src/log.c"
+#include "../../src/hash_table.c"
+#include "../../src/xpath.c"
+#include "../../src/parser_yang.c"
+#include "../../src/context.c"
+#include "../../src/tree_schema_helpers.c"
+#include "../../src/tree_schema_free.c"
+#include "../../src/tree_schema_compile.c"
+#include "../../src/tree_schema.c"
+#include "../../src/xml.c"
+#include "../../src/parser_yin.c"
+
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
@@ -7,8 +21,6 @@
#include <string.h>
#include "libyang.h"
-#include "tree_schema_internal.h"
-#include "../../src/parser_yin.c"
static void
test_parse(void **state)
diff --git a/tests/src/test_set.c b/tests/src/test_set.c
index a6c53c4..77c9c0d 100644
--- a/tests/src/test_set.c
+++ b/tests/src/test_set.c
@@ -11,9 +11,8 @@
*
* https://opensource.org/licenses/BSD-3-Clause
*/
+#include "common.h"
-#define _BSD_SOURCE
-#define _DEFAULT_SOURCE
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
@@ -23,6 +22,7 @@
#include "libyang.h"
#include "../../src/set.c"
+#include "../../src/log.c"
#define BUFSIZE 1024
char logbuf[BUFSIZE] = {0};
diff --git a/tests/src/test_tree_schema_compile.c b/tests/src/test_tree_schema_compile.c
index 79c7c42..ea088ed 100644
--- a/tests/src/test_tree_schema_compile.c
+++ b/tests/src/test_tree_schema_compile.c
@@ -12,8 +12,17 @@
* https://opensource.org/licenses/BSD-3-Clause
*/
-#include "../../src/tree_schema.c"
+#include "../../src/common.c"
+#include "../../src/log.c"
+#include "../../src/set.c"
+#include "../../src/xpath.c"
#include "../../src/parser_yang.c"
+#include "../../src/tree_schema_helpers.c"
+#include "../../src/tree_schema_free.c"
+#include "../../src/tree_schema_compile.c"
+#include "../../src/tree_schema.c"
+#include "../../src/context.c"
+#include "../../src/hash_table.c"
#include <stdarg.h>
#include <stddef.h>
@@ -37,7 +46,7 @@
{
(void) level; /* unused */
- if (path) {
+ if (path && path[0]) {
snprintf(logbuf, BUFSIZE - 1, "%s %s", msg, path);
} else {
strncpy(logbuf, msg, BUFSIZE - 1);
@@ -55,6 +64,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)
{
@@ -62,32 +83,42 @@
}
#if ENABLE_LOGGER_CHECKING
-# define logbuf_assert(str) assert_string_equal(logbuf, str)
+# define logbuf_assert(str) assert_string_equal(logbuf, str);logbuf_clean()
#else
# define logbuf_assert(str)
#endif
+static LY_ERR test_imp_clb(const char *UNUSED(mod_name), const char *UNUSED(mod_rev), const char *UNUSED(submod_name),
+ const char *UNUSED(sub_rev), void *user_data, LYS_INFORMAT *format,
+ const char **module_data, void (**free_module_data)(void *model_data, void *user_data))
+{
+ *module_data = user_data;
+ *format = LYS_IN_YANG;
+ *free_module_data = NULL;
+ return LY_SUCCESS;
+}
+
static void
test_module(void **state)
{
(void) state; /* unused */
const char *str;
- struct ly_ctx *ctx;
+ struct ly_parser_ctx ctx = {0};
struct lys_module mod = {0};
struct lysc_feature *f;
struct lysc_iffeature *iff;
str = "module test {namespace urn:test; prefix t;"
"feature f1;feature f2 {if-feature f1;}}";
- assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &ctx));
+ assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &ctx.ctx));
- assert_int_equal(LY_EINVAL, lys_compile(NULL, 0, NULL));
- logbuf_assert("Invalid argument sc (lys_compile()).");
- assert_int_equal(LY_EINVAL, lys_compile(NULL, 0, &mod.compiled));
- logbuf_assert("Invalid argument sp (lys_compile()).");
- assert_int_equal(LY_SUCCESS, yang_parse(ctx, str, &mod.parsed));
- assert_int_equal(LY_SUCCESS, lys_compile(mod.parsed, 0, &mod.compiled));
+ assert_int_equal(LY_EINVAL, lys_compile(NULL, 0));
+ logbuf_assert("Invalid argument mod (lys_compile()).");
+ assert_int_equal(LY_EINVAL, lys_compile(&mod, 0));
+ logbuf_assert("Invalid argument mod->parsed (lys_compile()).");
+ assert_int_equal(LY_SUCCESS, yang_parse(&ctx, str, &mod.parsed));
+ assert_int_equal(LY_SUCCESS, lys_compile(&mod, 0));
assert_non_null(mod.compiled);
assert_ptr_equal(mod.parsed->name, mod.compiled->name);
assert_ptr_equal(mod.parsed->ns, mod.compiled->ns);
@@ -105,7 +136,7 @@
lysc_module_free(mod.compiled, NULL);
- assert_int_equal(LY_SUCCESS, lys_compile(mod.parsed, LYSC_OPT_FREE_SP, &mod.compiled));
+ assert_int_equal(LY_SUCCESS, lys_compile(&mod, LYSC_OPT_FREE_SP));
assert_non_null(mod.compiled);
assert_string_equal("test", mod.compiled->name);
assert_string_equal("urn:test", mod.compiled->ns);
@@ -115,38 +146,48 @@
/* submodules cannot be compiled directly */
str = "submodule test {belongs-to xxx {prefix x;}}";
- assert_int_equal(LY_SUCCESS, yang_parse(ctx, str, &mod.parsed));
- assert_int_equal(LY_EINVAL, lys_compile(mod.parsed, 0, &mod.compiled));
+ assert_int_equal(LY_SUCCESS, yang_parse(&ctx, str, &mod.parsed));
+ assert_int_equal(LY_EINVAL, lys_compile(&mod, 0));
logbuf_assert("Submodules (test) are not supposed to be compiled, compile only the main modules.");
assert_null(mod.compiled);
-
lysp_module_free(mod.parsed);
- ly_ctx_destroy(ctx, NULL);
+
+ /* data definition name collision in top level */
+ assert_int_equal(LY_SUCCESS, yang_parse(&ctx, "module aa {namespace urn:aa;prefix aa;"
+ "leaf a {type string;} container a{presence x;}}", &mod.parsed));
+ assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
+ logbuf_assert("Duplicate identifier \"a\" of data definition statement.");
+ assert_null(mod.compiled);
+ lysp_module_free(mod.parsed);
+
+ ly_ctx_destroy(ctx.ctx, NULL);
}
static void
test_feature(void **state)
{
- (void) state; /* unused */
+ *state = test_feature;
- struct ly_ctx *ctx;
- struct lys_module mod = {0};
+ struct ly_parser_ctx ctx = {0};
+ struct lys_module mod = {0}, *modp;
const char *str;
struct lysc_feature *f, *f1;
str = "module a {namespace urn:a;prefix a;yang-version 1.1;\n"
"feature f1 {description test1;reference test2;status current;} feature f2; feature f3;\n"
- "feature f4 {if-feature \"f1 or f2\";}\n"
- "feature f5 {if-feature \"f1 and f2\";}\n"
+ "feature orfeature {if-feature \"f1 or f2\";}\n"
+ "feature andfeature {if-feature \"f1 and f2\";}\n"
"feature f6 {if-feature \"not f1\";}\n"
- "feature f7 {if-feature \"(f2 and f3) or (not f1)\";}}";
+ "feature f7 {if-feature \"(f2 and f3) or (not f1)\";}\n"
+ "feature f8 {if-feature \"f1 or f2 or f3 or orfeature or andfeature\";}\n"
+ "feature f9 {if-feature \"not not f1\";}}";
- assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &ctx));
- assert_int_equal(LY_SUCCESS, yang_parse(ctx, str, &mod.parsed));
- assert_int_equal(LY_SUCCESS, lys_compile(mod.parsed, 0, &mod.compiled));
+ assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &ctx.ctx));
+ assert_int_equal(LY_SUCCESS, yang_parse(&ctx, str, &mod.parsed));
+ assert_int_equal(LY_SUCCESS, lys_compile(&mod, 0));
assert_non_null(mod.compiled);
assert_non_null(mod.compiled->features);
- assert_int_equal(7, LY_ARRAY_SIZE(mod.compiled->features));
+ assert_int_equal(9, LY_ARRAY_SIZE(mod.compiled->features));
/* all features are disabled by default */
LY_ARRAY_FOR(mod.compiled->features, struct lysc_feature, f) {
assert_int_equal(0, lysc_feature_value(f));
@@ -156,22 +197,22 @@
f1 = &mod.compiled->features[0];
assert_int_equal(1, lysc_feature_value(f1));
- /* enable f4 */
+ /* enable orfeature */
f = &mod.compiled->features[3];
assert_int_equal(0, lysc_feature_value(f));
- assert_int_equal(LY_SUCCESS, lys_feature_enable(&mod, "f4"));
+ assert_int_equal(LY_SUCCESS, lys_feature_enable(&mod, "orfeature"));
assert_int_equal(1, lysc_feature_value(f));
- /* enable f5 - no possible since f2 is disabled */
+ /* enable andfeature - no possible since f2 is disabled */
f = &mod.compiled->features[4];
assert_int_equal(0, lysc_feature_value(f));
- assert_int_equal(LY_EDENIED, lys_feature_enable(&mod, "f5"));
- logbuf_assert("Feature \"f5\" cannot be enabled since it is disabled by its if-feature condition(s).");
+ assert_int_equal(LY_EDENIED, lys_feature_enable(&mod, "andfeature"));
+ logbuf_assert("Feature \"andfeature\" cannot be enabled since it is disabled by its if-feature condition(s).");
assert_int_equal(0, lysc_feature_value(f));
/* first enable f2, so f5 can be enabled then */
assert_int_equal(LY_SUCCESS, lys_feature_enable(&mod, "f2"));
- assert_int_equal(LY_SUCCESS, lys_feature_enable(&mod, "f5"));
+ assert_int_equal(LY_SUCCESS, lys_feature_enable(&mod, "andfeature"));
assert_int_equal(1, lysc_feature_value(f));
/* f1 is enabled, so f6 cannot be enabled */
@@ -181,12 +222,12 @@
logbuf_assert("Feature \"f6\" cannot be enabled since it is disabled by its if-feature condition(s).");
assert_int_equal(0, lysc_feature_value(f));
- /* so disable f1 - f5 will became also disabled */
+ /* so disable f1 - andfeature will became also disabled */
assert_int_equal(1, lysc_feature_value(f1));
assert_int_equal(LY_SUCCESS, lys_feature_disable(&mod, "f1"));
assert_int_equal(0, lysc_feature_value(f1));
assert_int_equal(0, lysc_feature_value(&mod.compiled->features[4]));
- /* while f4 is stille enabled */
+ /* while orfeature is stille enabled */
assert_int_equal(1, lysc_feature_value(&mod.compiled->features[3]));
/* and finally f6 can be enabled */
assert_int_equal(LY_SUCCESS, lys_feature_enable(&mod, "f6"));
@@ -194,17 +235,2074 @@
/* complex evaluation of f7: f1 and f3 are disabled, while f2 is enabled */
assert_int_equal(1, lysc_iffeature_value(&mod.compiled->features[6].iffeatures[0]));
+ /* long evaluation of f8 to need to reallocate internal stack for operators */
+ assert_int_equal(1, lysc_iffeature_value(&mod.compiled->features[7].iffeatures[0]));
+
+ /* double negation of disabled f1 -> disabled */
+ assert_int_equal(0, lysc_iffeature_value(&mod.compiled->features[8].iffeatures[0]));
+
+ /* disable all features */
+ assert_int_equal(LY_SUCCESS, lys_feature_disable(&mod, "*"));
+ LY_ARRAY_FOR(mod.compiled->features, struct lysc_feature, f) {
+ assert_int_equal(0, lys_feature_value(&mod, f->name));
+ }
+ /* re-setting already set feature */
+ assert_int_equal(LY_SUCCESS, lys_feature_disable(&mod, "f1"));
+ assert_int_equal(0, lys_feature_value(&mod, "f1"));
+
+ /* enabling feature that cannot be enabled due to its if-features */
+ assert_int_equal(LY_SUCCESS, lys_feature_enable(&mod, "f1"));
+ assert_int_equal(LY_EDENIED, lys_feature_enable(&mod, "andfeature"));
+ logbuf_assert("Feature \"andfeature\" cannot be enabled since it is disabled by its if-feature condition(s).");
+ assert_int_equal(LY_EDENIED, lys_feature_enable(&mod, "*"));
+ logbuf_assert("Feature \"f6\" cannot be enabled since it is disabled by its if-feature condition(s).");
+ /* test if not changed */
+ assert_int_equal(1, lys_feature_value(&mod, "f1"));
+ assert_int_equal(0, lys_feature_value(&mod, "f2"));
+
+ /* invalid reference */
+ assert_int_equal(LY_EINVAL, lys_feature_enable(&mod, "xxx"));
+ logbuf_assert("Feature \"xxx\" not found in module \"a\".");
lysc_module_free(mod.compiled, NULL);
lysp_module_free(mod.parsed);
+
+ /* some invalid expressions */
+ assert_int_equal(LY_SUCCESS, yang_parse(&ctx, "module b{yang-version 1.1;namespace urn:b; prefix b; feature f{if-feature f1;}}", &mod.parsed));
+ assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
+ logbuf_assert("Invalid value \"f1\" of if-feature - unable to find feature \"f1\".");
+ lysp_module_free(mod.parsed);
+
+ assert_int_equal(LY_SUCCESS, yang_parse(&ctx, "module b{yang-version 1.1;namespace urn:b; prefix b; feature f1; feature f2{if-feature 'f and';}}", &mod.parsed));
+ assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
+ logbuf_assert("Invalid value \"f and\" of if-feature - unexpected end of expression.");
+ lysp_module_free(mod.parsed);
+
+ assert_int_equal(LY_SUCCESS, yang_parse(&ctx, "module b{yang-version 1.1;namespace urn:b; prefix b; feature f{if-feature 'or';}}", &mod.parsed));
+ assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
+ logbuf_assert("Invalid value \"or\" of if-feature - unexpected end of expression.");
+ lysp_module_free(mod.parsed);
+
+ assert_int_equal(LY_SUCCESS, yang_parse(&ctx, "module b{yang-version 1.1;namespace urn:b; prefix b; feature f1; feature f2{if-feature '(f1';}}", &mod.parsed));
+ assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
+ logbuf_assert("Invalid value \"(f1\" of if-feature - non-matching opening and closing parentheses.");
+ lysp_module_free(mod.parsed);
+
+ assert_int_equal(LY_SUCCESS, yang_parse(&ctx, "module b{yang-version 1.1;namespace urn:b; prefix b; feature f1; feature f2{if-feature 'f1)';}}", &mod.parsed));
+ assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
+ logbuf_assert("Invalid value \"f1)\" of if-feature - non-matching opening and closing parentheses.");
+ lysp_module_free(mod.parsed);
+
+ assert_int_equal(LY_SUCCESS, yang_parse(&ctx, "module b{yang-version 1.1;namespace urn:b; prefix b; feature f1; feature f2{if-feature ---;}}", &mod.parsed));
+ assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
+ logbuf_assert("Invalid value \"---\" of if-feature - unable to find feature \"---\".");
+ lysp_module_free(mod.parsed);
+
+ assert_int_equal(LY_SUCCESS, yang_parse(&ctx, "module b{namespace urn:b; prefix b; feature f1; feature f2{if-feature 'not f1';}}", &mod.parsed));
+ assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
+ logbuf_assert("Invalid value \"not f1\" of if-feature - YANG 1.1 expression in YANG 1.0 module.");
+ lysp_module_free(mod.parsed);
+
+ assert_int_equal(LY_SUCCESS, yang_parse(&ctx, "module b{namespace urn:b; prefix b; feature f1; feature f1;}", &mod.parsed));
+ assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
+ logbuf_assert("Duplicate identifier \"f1\" of feature statement.");
+ lysp_module_free(mod.parsed);
+
+ ly_ctx_set_module_imp_clb(ctx.ctx, test_imp_clb, "submodule sb {belongs-to b {prefix b;} feature f1;}");
+ assert_non_null(modp = lys_parse_mem(ctx.ctx, "module b{namespace urn:b; prefix b; include sb;feature f1;}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(modp, 0));
+ logbuf_assert("Duplicate identifier \"f1\" of feature statement.");
+
+ /* import reference */
+ assert_non_null(modp = lys_parse_mem(ctx.ctx, str, LYS_IN_YANG));
+ assert_int_equal(LY_SUCCESS, lys_compile(modp, 0));
+ assert_int_equal(LY_SUCCESS, lys_feature_enable(modp, "f1"));
+ assert_non_null(modp = lys_parse_mem(ctx.ctx, "module c{namespace urn:c; prefix c; import a {prefix a;} feature f1; feature f2{if-feature 'a:f1';}}", LYS_IN_YANG));
+ assert_int_equal(LY_SUCCESS, lys_compile(modp, 0));
+ assert_int_equal(LY_SUCCESS, lys_feature_enable(modp, "f2"));
+ assert_int_equal(0, lys_feature_value(modp, "f1"));
+ assert_int_equal(1, lys_feature_value(modp, "f2"));
+
+ *state = NULL;
+ ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
+test_identity(void **state)
+{
+ *state = test_identity;
+
+ struct ly_ctx *ctx;
+ struct lys_module *mod1, *mod2;
+ const char *mod1_str = "module a {namespace urn:a;prefix a; identity a1;}";
+ const char *mod2_str = "module b {yang-version 1.1;namespace urn:b;prefix b; import a {prefix a;}identity b1; identity b2; identity b3 {base b1; base b:b2; base a:a1;} identity b4 {base b:b1; base b3;}}";
+
+ assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+ assert_non_null(mod1 = lys_parse_mem(ctx, mod1_str, LYS_IN_YANG));
+ assert_non_null(mod2 = lys_parse_mem(ctx, mod2_str, LYS_IN_YANG));
+ assert_int_equal(LY_SUCCESS, lys_compile(mod1, 0));
+ assert_int_equal(LY_SUCCESS, lys_compile(mod2, 0));
+
+ assert_non_null(mod1->compiled);
+ assert_non_null(mod1->compiled->identities);
+ assert_non_null(mod2->compiled);
+ assert_non_null(mod2->compiled->identities);
+
+ assert_non_null(mod1->compiled->identities[0].derived);
+ assert_int_equal(1, LY_ARRAY_SIZE(mod1->compiled->identities[0].derived));
+ assert_ptr_equal(mod1->compiled->identities[0].derived[0], &mod2->compiled->identities[2]);
+ assert_non_null(mod2->compiled->identities[0].derived);
+ assert_int_equal(2, LY_ARRAY_SIZE(mod2->compiled->identities[0].derived));
+ assert_ptr_equal(mod2->compiled->identities[0].derived[0], &mod2->compiled->identities[2]);
+ assert_ptr_equal(mod2->compiled->identities[0].derived[1], &mod2->compiled->identities[3]);
+ assert_non_null(mod2->compiled->identities[1].derived);
+ assert_int_equal(1, LY_ARRAY_SIZE(mod2->compiled->identities[1].derived));
+ assert_ptr_equal(mod2->compiled->identities[1].derived[0], &mod2->compiled->identities[2]);
+ assert_non_null(mod2->compiled->identities[2].derived);
+ assert_int_equal(1, LY_ARRAY_SIZE(mod2->compiled->identities[2].derived));
+ assert_ptr_equal(mod2->compiled->identities[2].derived[0], &mod2->compiled->identities[3]);
+
+ assert_non_null(mod1 = lys_parse_mem(ctx, "module c{namespace urn:c; prefix c; identity i1;identity i1;}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod1, 0));
+ logbuf_assert("Duplicate identifier \"i1\" of identity statement.");
+
+ ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule sd {belongs-to d {prefix d;} identity i1;}");
+ assert_non_null(mod1 = lys_parse_mem(ctx, "module d{namespace urn:d; prefix d; include sd;identity i1;}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod1, 0));
+ logbuf_assert("Duplicate identifier \"i1\" of identity statement.");
+
+ *state = NULL;
ly_ctx_destroy(ctx, NULL);
}
+static void
+test_node_container(void **state)
+{
+ (void) state; /* unused */
+
+ struct ly_ctx *ctx;
+ struct lys_module *mod;
+ struct lysc_node_container *cont;
+
+ 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;container c;}", LYS_IN_YANG));
+ assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+ assert_non_null(mod->compiled);
+ assert_non_null((cont = (struct lysc_node_container*)mod->compiled->data));
+ assert_int_equal(LYS_CONTAINER, cont->nodetype);
+ assert_string_equal("c", cont->name);
+ assert_true(cont->flags & LYS_CONFIG_W);
+ assert_true(cont->flags & LYS_STATUS_CURR);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;container c {config false; status deprecated; container child;}}", LYS_IN_YANG));
+ assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+ logbuf_assert("Missing explicit \"deprecated\" status that was already specified in parent, inheriting.");
+ assert_non_null(mod->compiled);
+ assert_non_null((cont = (struct lysc_node_container*)mod->compiled->data));
+ assert_true(cont->flags & LYS_CONFIG_R);
+ assert_true(cont->flags & LYS_STATUS_DEPRC);
+ assert_non_null((cont = (struct lysc_node_container*)cont->child));
+ assert_int_equal(LYS_CONTAINER, cont->nodetype);
+ assert_true(cont->flags & LYS_CONFIG_R);
+ assert_true(cont->flags & LYS_STATUS_DEPRC);
+ assert_string_equal("child", cont->name);
+
+ ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_node_leaflist(void **state)
+{
+ *state = test_node_leaflist;
+
+ struct ly_ctx *ctx;
+ struct lys_module *mod;
+ struct lysc_type *type;
+ struct lysc_node_leaflist *ll;
+
+ 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;"
+ "typedef mytype {type union {type leafref {path ../target;} type string;}}"
+ "leaf-list ll1 {type union {type decimal64 {fraction-digits 2;} type mytype;}}"
+ "leaf-list ll2 {type leafref {path ../target;}}"
+ "leaf target {type int8;}}",
+ 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(1, type->refcount);
+ assert_int_equal(LY_TYPE_UNION, type->basetype);
+ assert_non_null(((struct lysc_type_union*)type)->types);
+ assert_int_equal(3, LY_ARRAY_SIZE(((struct lysc_type_union*)type)->types));
+ assert_int_equal(LY_TYPE_DEC64, ((struct lysc_type_union*)type)->types[0]->basetype);
+ assert_int_equal(LY_TYPE_LEAFREF, ((struct lysc_type_union*)type)->types[1]->basetype);
+ assert_int_equal(LY_TYPE_STRING, ((struct lysc_type_union*)type)->types[2]->basetype);
+ assert_non_null(((struct lysc_type_leafref*)((struct lysc_type_union*)type)->types[1])->realtype);
+ assert_int_equal(LY_TYPE_INT8, ((struct lysc_type_leafref*)((struct lysc_type_union*)type)->types[1])->realtype->basetype);
+ type = ((struct lysc_node_leaf*)mod->compiled->data->next)->type;
+ assert_non_null(type);
+ assert_int_equal(1, type->refcount);
+ assert_int_equal(LY_TYPE_LEAFREF, type->basetype);
+ assert_non_null(((struct lysc_type_leafref*)type)->realtype);
+ assert_int_equal(LY_TYPE_INT8, ((struct lysc_type_leafref*)type)->realtype->basetype);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;leaf-list ll {type string;}}", LYS_IN_YANG));
+ assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+ assert_non_null(mod->compiled);
+ assert_non_null((ll = (struct lysc_node_leaflist*)mod->compiled->data));
+ assert_int_equal(0, ll->min);
+ assert_int_equal((uint32_t)-1, ll->max);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module c {yang-version 1.1;namespace urn:c;prefix c;typedef mytype {type int8;default 10;}"
+ "leaf-list ll1 {type mytype;default 1; default 1; config false;}"
+ "leaf-list ll2 {type mytype; ordered-by user;}}", LYS_IN_YANG));
+ assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+ assert_non_null(mod->compiled);
+ assert_non_null((ll = (struct lysc_node_leaflist*)mod->compiled->data));
+ assert_non_null(ll->dflts);
+ assert_int_equal(3, ll->type->refcount);
+ assert_int_equal(2, LY_ARRAY_SIZE(ll->dflts));
+ assert_string_equal("1", ll->dflts[0]);
+ assert_string_equal("1", ll->dflts[1]);
+ assert_int_equal(LYS_CONFIG_R | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM, ll->flags);
+ assert_non_null((ll = (struct lysc_node_leaflist*)mod->compiled->data->next));
+ assert_non_null(ll->dflts);
+ assert_int_equal(3, ll->type->refcount);
+ assert_int_equal(1, LY_ARRAY_SIZE(ll->dflts));
+ 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 */
+ 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));
+ assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+ /* but warning is present: */
+ logbuf_assert("The ordered-by statement is ignored in lists representing state data, RPC/action output parameters or notification content ().");
+ 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, ll->flags);
+
+ /* invalid */
+ assert_non_null(mod = lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;leaf-list ll {type empty;}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Leaf-list of type \"empty\" is allowed only in YANG 1.1 modules.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module bb {yang-version 1.1;namespace urn:bb;prefix bb;leaf-list ll {type empty; default x;}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Leaf-list of type \"empty\" must not have a default value (x).");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module cc {yang-version 1.1;namespace urn:cc;prefix cc;"
+ "leaf-list ll {config false;type string; default one;default two;default one;}}", LYS_IN_YANG));
+ assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+ assert_non_null(mod->compiled);
+ assert_non_null((ll = (struct lysc_node_leaflist*)mod->compiled->data));
+ assert_non_null(ll->dflts);
+ assert_int_equal(3, LY_ARRAY_SIZE(ll->dflts));
+ assert_non_null(mod = lys_parse_mem(ctx, "module dd {yang-version 1.1;namespace urn:dd;prefix dd;"
+ "leaf-list ll {type string; default one;default two;default one;}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Configuration leaf-list has multiple defaults of the same value \"one\".");
+
+ *state = NULL;
+ ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_node_list(void **state)
+{
+ *state = test_node_list;
+
+ struct ly_ctx *ctx;
+ struct lys_module *mod;
+ struct lysc_node_list *list;
+
+ 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;feature f;"
+ "list l1 {key \"x y\"; ordered-by user; leaf x {type string; when 1;}leaf y{type string;if-feature f;}}"
+ "list l2 {config false;leaf value {type string;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+ list = (struct lysc_node_list*)mod->compiled->data;
+ assert_non_null(list);
+ assert_non_null(list->keys);
+ assert_int_equal(2, LY_ARRAY_SIZE(list->keys));
+ assert_string_equal("x", list->keys[0]->name);
+ assert_string_equal("y", list->keys[1]->name);
+ assert_non_null(list->child);
+ assert_int_equal(LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_USER, list->flags);
+ assert_true(list->child->flags & LYS_KEY);
+ assert_true(list->child->next->flags & LYS_KEY);
+ list = (struct lysc_node_list*)mod->compiled->data->next;
+ assert_non_null(list);
+ assert_null(list->keys);
+ assert_non_null(list->child);
+ assert_int_equal(LYS_CONFIG_R | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM, list->flags);
+ assert_false(list->child->flags & LYS_KEY);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;"
+ "list l {key a; unique \"a c/b:b\"; unique \"c/e d\";"
+ "leaf a {type string; default x;} leaf d {type string;config false;}"
+ "container c {leaf b {type string;}leaf e{type string;config false;}}}}", LYS_IN_YANG));
+ assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+ list = (struct lysc_node_list*)mod->compiled->data;
+ assert_non_null(list);
+ assert_string_equal("l", list->name);
+ assert_non_null(list->keys);
+ assert_int_equal(1, LY_ARRAY_SIZE(list->keys));
+ assert_string_equal("a", list->keys[0]->name);
+ assert_true(list->keys[0]->flags & LYS_KEY);
+ assert_null(list->keys[0]->dflt);
+ assert_non_null(list->uniques);
+ assert_int_equal(2, LY_ARRAY_SIZE(list->uniques));
+ assert_int_equal(2, LY_ARRAY_SIZE(list->uniques[0]));
+ assert_string_equal("a", list->uniques[0][0]->name);
+ assert_true(list->uniques[0][0]->flags & LYS_UNIQUE);
+ assert_string_equal("b", list->uniques[0][1]->name);
+ assert_true(list->uniques[0][1]->flags & LYS_UNIQUE);
+ assert_int_equal(2, LY_ARRAY_SIZE(list->uniques[1]));
+ assert_string_equal("e", list->uniques[1][0]->name);
+ assert_true(list->uniques[1][0]->flags & LYS_UNIQUE);
+ assert_string_equal("d", list->uniques[1][1]->name);
+ assert_true(list->uniques[1][1]->flags & LYS_UNIQUE);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module c {yang-version 1.1;namespace urn:c;prefix c;"
+ "list l {key a;leaf a {type empty;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+ list = (struct lysc_node_list*)mod->compiled->data;
+ assert_non_null(list);
+ assert_string_equal("l", list->name);
+ assert_non_null(list->keys);
+ assert_int_equal(1, LY_ARRAY_SIZE(list->keys));
+ assert_string_equal("a", list->keys[0]->name);
+ assert_true(list->keys[0]->flags & LYS_KEY);
+ assert_int_equal(LY_TYPE_EMPTY, list->keys[0]->type->basetype);
+
+ /* invalid */
+ assert_non_null(mod = lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;list l;}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Missing key in list representing configuration data.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module bb {yang-version 1.1; namespace urn:bb;prefix bb;"
+ "list l {key x; leaf x {type string; when 1;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("List's key \"x\" must not have any \"when\" statement.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module cc {yang-version 1.1;namespace urn:cc;prefix cc;feature f;"
+ "list l {key x; leaf x {type string; if-feature f;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("List's key \"x\" must not have any \"if-feature\" statement.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module dd {namespace urn:dd;prefix dd;"
+ "list l {key x; leaf x {type string; config false;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Key of the configuration list must not be status leaf.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module ee {namespace urn:ee;prefix ee;"
+ "list l {config false;key x; leaf x {type string; config true;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Configuration node cannot be child of any state data node.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module ff {namespace urn:ff;prefix ff;"
+ "list l {key x; leaf-list x {type string;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("The list's key \"x\" not found.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module gg {namespace urn:gg;prefix gg;"
+ "list l {key x; unique y;leaf x {type string;} leaf-list y {type string;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Unique's descendant-schema-nodeid \"y\" refers to a leaf-list node instead of a leaf.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module hh {namespace urn:hh;prefix hh;"
+ "list l {key x; unique \"x y\";leaf x {type string;} leaf y {config false; type string;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Unique statement \"x y\" refers to leafs with different config type.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module ii {namespace urn:ii;prefix ii;"
+ "list l {key x; unique a:x;leaf x {type string;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid descendant-schema-nodeid value \"a:x\" - prefix \"a\" not defined in module \"ii\".");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module jj {namespace urn:jj;prefix jj;"
+ "list l {key x; unique c/x;leaf x {type string;}container c {leaf y {type string;}}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid descendant-schema-nodeid value \"c/x\" - target node not found.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module kk {namespace urn:kk;prefix kk;"
+ "list l {key x; unique c^y;leaf x {type string;}container c {leaf y {type string;}}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid descendant-schema-nodeid value \"c^\" - missing \"/\" as node-identifier separator.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module ll {namespace urn:ll;prefix ll;"
+ "list l {key \"x y x\";leaf x {type string;}leaf y {type string;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Duplicated key identifier \"x\".");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module mm {namespace urn:mm;prefix mm;"
+ "list l {key x;leaf x {type empty;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Key of a list can be of type \"empty\" only in YANG 1.1 modules.");
+
+ *state = NULL;
+ ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_node_choice(void **state)
+{
+ *state = test_node_choice;
+
+ struct ly_ctx *ctx;
+ struct lys_module *mod;
+ struct lysc_node_choice *ch;
+ struct lysc_node_case *cs;
+
+ 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;feature f;"
+ "choice ch {default a:b; case a {leaf a1 {type string;}leaf a2 {type string;}}"
+ "leaf b {type string;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+ ch = (struct lysc_node_choice*)mod->compiled->data;
+ assert_non_null(ch);
+ assert_int_equal(LYS_CONFIG_W | LYS_STATUS_CURR | LYS_SET_DFLT, ch->flags);
+ cs = ch->cases;
+ assert_non_null(cs);
+ assert_string_equal("a", cs->name);
+ assert_ptr_equal(ch, cs->parent);
+ assert_non_null(cs->child);
+ assert_string_equal("a1", cs->child->name);
+ assert_non_null(cs->child->next);
+ assert_string_equal("a2", cs->child->next->name);
+ assert_ptr_equal(cs, cs->child->parent);
+ cs = (struct lysc_node_case*)cs->next;
+ assert_non_null(cs);
+ assert_string_equal("b", cs->name);
+ assert_ptr_equal(ch, cs->parent);
+ assert_non_null(cs->child);
+ assert_string_equal("b", cs->child->name);
+ assert_ptr_equal(cs, cs->child->parent);
+ assert_ptr_equal(ch->cases->child->next, cs->child->prev);
+ assert_ptr_equal(ch->cases->child->next->next, cs->child);
+ assert_ptr_equal(ch->cases->child->prev, cs->child);
+ assert_ptr_equal(ch->dflt, cs);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;"
+ "choice ch {case a {leaf x {type string;}}leaf x {type string;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Duplicate identifier \"x\" of data definition statement.");
+ assert_non_null(mod = lys_parse_mem(ctx, "module aa2 {namespace urn:aa2;prefix aa;"
+ "choice ch {case a {leaf y {type string;}}case b {leaf y {type string;}}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Duplicate identifier \"y\" of data definition statement.");
+ assert_non_null(mod = lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;"
+ "choice ch {case a {leaf x {type string;}}leaf a {type string;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Duplicate identifier \"a\" of case statement.");
+ assert_non_null(mod = lys_parse_mem(ctx, "module bb2 {namespace urn:bb2;prefix bb;"
+ "choice ch {case b {leaf x {type string;}}case b {leaf y {type string;}}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Duplicate identifier \"b\" of case statement.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module ca {namespace urn:ca;prefix ca;"
+ "choice ch {default c;case a {leaf x {type string;}}case b {leaf y {type string;}}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Default case \"c\" not found.");
+ assert_non_null(mod = lys_parse_mem(ctx, "module cb {namespace urn:cb;prefix cb; import a {prefix a;}"
+ "choice ch {default a:a;case a {leaf x {type string;}}case b {leaf y {type string;}}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid default case referencing a case from different YANG module (by prefix \"a\").");
+ assert_non_null(mod = lys_parse_mem(ctx, "module cc {namespace urn:cc;prefix cc;"
+ "choice ch {default a;case a {leaf x {mandatory true;type string;}}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Mandatory node \"x\" under the default case \"a\".");
+ /* TODO check with mandatory nodes from augment placed into the case */
+
+ *state = NULL;
+ ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_node_anydata(void **state)
+{
+ *state = test_node_anydata;
+
+ struct ly_ctx *ctx;
+ struct lys_module *mod;
+ struct lysc_node_anydata *any;
+
+ assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module a {yang-version 1.1;namespace urn:a;prefix a;"
+ "anydata any {config false;mandatory true;}}", LYS_IN_YANG));
+ assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+ any = (struct lysc_node_anydata*)mod->compiled->data;
+ assert_non_null(any);
+ assert_int_equal(LYS_ANYDATA, any->nodetype);
+ assert_int_equal(LYS_CONFIG_R | LYS_STATUS_CURR | LYS_MAND_TRUE, any->flags);
+
+ logbuf_clean();
+ assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;"
+ "anyxml any;}", LYS_IN_YANG));
+ assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+ any = (struct lysc_node_anydata*)mod->compiled->data;
+ assert_non_null(any);
+ assert_int_equal(LYS_ANYXML, any->nodetype);
+ assert_int_equal(LYS_CONFIG_W | LYS_STATUS_CURR, any->flags);
+ logbuf_assert("Use of anyxml to define configuration data is not recommended."); /* warning */
+
+ /* invalid */
+ assert_null(mod = lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;anydata any;}", LYS_IN_YANG));
+ logbuf_assert("Invalid keyword \"anydata\" as a child of \"module\" - the statement is allowed only in YANG 1.1 modules. Line number 1.");
+
+ *state = NULL;
+ ly_ctx_destroy(ctx, NULL);
+}
+
+/**
+ * actually the same as length restriction (tested in test_type_length()), so just check the correct handling in appropriate types,
+ * do not test the expression itself
+ */
+static void
+test_type_range(void **state)
+{
+ *state = test_type_range;
+
+ struct ly_ctx *ctx;
+ struct lys_module *mod;
+ struct lysc_type *type;
+
+ 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;leaf l {type int8 {range min..10|max;}}}", 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_INT8, type->basetype);
+ assert_non_null(((struct lysc_type_num*)type)->range);
+ assert_non_null(((struct lysc_type_num*)type)->range->parts);
+ assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_num*)type)->range->parts));
+ assert_int_equal(-128, ((struct lysc_type_num*)type)->range->parts[0].min_64);
+ assert_int_equal(10, ((struct lysc_type_num*)type)->range->parts[0].max_64);
+ assert_int_equal(127, ((struct lysc_type_num*)type)->range->parts[1].min_64);
+ assert_int_equal(127, ((struct lysc_type_num*)type)->range->parts[1].max_64);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;leaf l {type int16 {range min..10|max;}}}", 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_INT16, type->basetype);
+ assert_non_null(((struct lysc_type_num*)type)->range);
+ assert_non_null(((struct lysc_type_num*)type)->range->parts);
+ assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_num*)type)->range->parts));
+ assert_int_equal(-32768, ((struct lysc_type_num*)type)->range->parts[0].min_64);
+ assert_int_equal(10, ((struct lysc_type_num*)type)->range->parts[0].max_64);
+ assert_int_equal(32767, ((struct lysc_type_num*)type)->range->parts[1].min_64);
+ assert_int_equal(32767, ((struct lysc_type_num*)type)->range->parts[1].max_64);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module c {namespace urn:c;prefix c;leaf l {type int32 {range min..10|max;}}}", 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_INT32, type->basetype);
+ assert_non_null(((struct lysc_type_num*)type)->range);
+ assert_non_null(((struct lysc_type_num*)type)->range->parts);
+ assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_num*)type)->range->parts));
+ assert_int_equal(INT64_C(-2147483648), ((struct lysc_type_num*)type)->range->parts[0].min_64);
+ assert_int_equal(10, ((struct lysc_type_num*)type)->range->parts[0].max_64);
+ assert_int_equal(INT64_C(2147483647), ((struct lysc_type_num*)type)->range->parts[1].min_64);
+ assert_int_equal(INT64_C(2147483647), ((struct lysc_type_num*)type)->range->parts[1].max_64);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module d {namespace urn:d;prefix d;leaf l {type int64 {range min..10|max;}}}", 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_INT64, type->basetype);
+ assert_non_null(((struct lysc_type_num*)type)->range);
+ assert_non_null(((struct lysc_type_num*)type)->range->parts);
+ assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_num*)type)->range->parts));
+ assert_int_equal(INT64_C(-9223372036854775807) - INT64_C(1), ((struct lysc_type_num*)type)->range->parts[0].min_64);
+ assert_int_equal(10, ((struct lysc_type_num*)type)->range->parts[0].max_64);
+ assert_int_equal(INT64_C(9223372036854775807), ((struct lysc_type_num*)type)->range->parts[1].min_64);
+ assert_int_equal(INT64_C(9223372036854775807), ((struct lysc_type_num*)type)->range->parts[1].max_64);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module e {namespace urn:e;prefix e;leaf l {type uint8 {range min..10|max;}}}", 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_UINT8, type->basetype);
+ assert_non_null(((struct lysc_type_num*)type)->range);
+ assert_non_null(((struct lysc_type_num*)type)->range->parts);
+ assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_num*)type)->range->parts));
+ assert_int_equal(0, ((struct lysc_type_num*)type)->range->parts[0].min_u64);
+ assert_int_equal(10, ((struct lysc_type_num*)type)->range->parts[0].max_u64);
+ assert_int_equal(255, ((struct lysc_type_num*)type)->range->parts[1].min_u64);
+ assert_int_equal(255, ((struct lysc_type_num*)type)->range->parts[1].max_u64);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module f {namespace urn:f;prefix f;leaf l {type uint16 {range min..10|max;}}}", 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_UINT16, type->basetype);
+ assert_non_null(((struct lysc_type_num*)type)->range);
+ assert_non_null(((struct lysc_type_num*)type)->range->parts);
+ assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_num*)type)->range->parts));
+ assert_int_equal(0, ((struct lysc_type_num*)type)->range->parts[0].min_u64);
+ assert_int_equal(10, ((struct lysc_type_num*)type)->range->parts[0].max_u64);
+ assert_int_equal(65535, ((struct lysc_type_num*)type)->range->parts[1].min_u64);
+ assert_int_equal(65535, ((struct lysc_type_num*)type)->range->parts[1].max_u64);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module g {namespace urn:g;prefix g;leaf l {type uint32 {range min..10|max;}}}", 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_UINT32, type->basetype);
+ assert_non_null(((struct lysc_type_num*)type)->range);
+ assert_non_null(((struct lysc_type_num*)type)->range->parts);
+ assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_num*)type)->range->parts));
+ assert_int_equal(0, ((struct lysc_type_num*)type)->range->parts[0].min_u64);
+ assert_int_equal(10, ((struct lysc_type_num*)type)->range->parts[0].max_u64);
+ assert_int_equal(UINT64_C(4294967295), ((struct lysc_type_num*)type)->range->parts[1].min_u64);
+ assert_int_equal(UINT64_C(4294967295), ((struct lysc_type_num*)type)->range->parts[1].max_u64);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module h {namespace urn:h;prefix h;leaf l {type uint64 {range min..10|max;}}}", 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_UINT64, type->basetype);
+ assert_non_null(((struct lysc_type_num*)type)->range);
+ assert_non_null(((struct lysc_type_num*)type)->range->parts);
+ assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_num*)type)->range->parts));
+ assert_int_equal(0, ((struct lysc_type_num*)type)->range->parts[0].min_u64);
+ assert_int_equal(10, ((struct lysc_type_num*)type)->range->parts[0].max_u64);
+ assert_int_equal(UINT64_C(18446744073709551615), ((struct lysc_type_num*)type)->range->parts[1].min_u64);
+ assert_int_equal(UINT64_C(18446744073709551615), ((struct lysc_type_num*)type)->range->parts[1].max_u64);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module i {namespace urn:i;prefix i;typedef mytype {type uint8 {range 10..100;}}"
+ "typedef mytype2 {type mytype;} leaf l {type mytype2;}}", 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(3, type->refcount);
+ assert_int_equal(LY_TYPE_UINT8, type->basetype);
+ assert_non_null(((struct lysc_type_num*)type)->range);
+ assert_non_null(((struct lysc_type_num*)type)->range->parts);
+ assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_num*)type)->range->parts));
+
+ *state = NULL;
+ ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_type_length(void **state)
+{
+ *state = test_type_length;
+
+ struct ly_ctx *ctx;
+ struct lys_module *mod;
+ struct lysc_type *type;
+
+ 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;leaf l {type binary {length min {error-app-tag errortag;error-message error;}}}}", 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_non_null(((struct lysc_type_bin*)type)->length);
+ assert_non_null(((struct lysc_type_bin*)type)->length->parts);
+ assert_string_equal("errortag", ((struct lysc_type_bin*)type)->length->eapptag);
+ assert_string_equal("error", ((struct lysc_type_bin*)type)->length->emsg);
+ assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_bin*)type)->length->parts));
+ assert_int_equal(0, ((struct lysc_type_bin*)type)->length->parts[0].min_u64);
+ assert_int_equal(0, ((struct lysc_type_bin*)type)->length->parts[0].max_u64);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;leaf l {type binary {length max;}}}", 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_non_null(((struct lysc_type_bin*)type)->length);
+ assert_non_null(((struct lysc_type_bin*)type)->length->parts);
+ assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_bin*)type)->length->parts));
+ assert_int_equal(UINT64_C(18446744073709551615), ((struct lysc_type_bin*)type)->length->parts[0].min_u64);
+ assert_int_equal(UINT64_C(18446744073709551615), ((struct lysc_type_bin*)type)->length->parts[0].max_u64);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module c {namespace urn:c;prefix c;leaf l {type binary {length min..max;}}}", 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_non_null(((struct lysc_type_bin*)type)->length);
+ assert_non_null(((struct lysc_type_bin*)type)->length->parts);
+ assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_bin*)type)->length->parts));
+ assert_int_equal(0, ((struct lysc_type_bin*)type)->length->parts[0].min_u64);
+ assert_int_equal(UINT64_C(18446744073709551615), ((struct lysc_type_bin*)type)->length->parts[0].max_u64);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module d {namespace urn:d;prefix d;leaf l {type binary {length 5;}}}", 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_non_null(((struct lysc_type_bin*)type)->length);
+ assert_non_null(((struct lysc_type_bin*)type)->length->parts);
+ assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_bin*)type)->length->parts));
+ assert_int_equal(5, ((struct lysc_type_bin*)type)->length->parts[0].min_u64);
+ assert_int_equal(5, ((struct lysc_type_bin*)type)->length->parts[0].max_u64);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module e {namespace urn:e;prefix e;leaf l {type binary {length 1..10;}}}", 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_non_null(((struct lysc_type_bin*)type)->length);
+ assert_non_null(((struct lysc_type_bin*)type)->length->parts);
+ assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_bin*)type)->length->parts));
+ assert_int_equal(1, ((struct lysc_type_bin*)type)->length->parts[0].min_u64);
+ assert_int_equal(10, ((struct lysc_type_bin*)type)->length->parts[0].max_u64);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module f {namespace urn:f;prefix f;leaf l {type binary {length 1..10|20..30;}}}", 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_non_null(((struct lysc_type_bin*)type)->length);
+ assert_non_null(((struct lysc_type_bin*)type)->length->parts);
+ assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_bin*)type)->length->parts));
+ assert_int_equal(1, ((struct lysc_type_bin*)type)->length->parts[0].min_u64);
+ assert_int_equal(10, ((struct lysc_type_bin*)type)->length->parts[0].max_u64);
+ assert_int_equal(20, ((struct lysc_type_bin*)type)->length->parts[1].min_u64);
+ assert_int_equal(30, ((struct lysc_type_bin*)type)->length->parts[1].max_u64);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module g {namespace urn:g;prefix g;leaf l {type binary {length \"16 | 32\";}}}", 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_non_null(((struct lysc_type_bin*)type)->length);
+ assert_non_null(((struct lysc_type_bin*)type)->length->parts);
+ assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_bin*)type)->length->parts));
+ assert_int_equal(16, ((struct lysc_type_bin*)type)->length->parts[0].min_u64);
+ assert_int_equal(16, ((struct lysc_type_bin*)type)->length->parts[0].max_u64);
+ assert_int_equal(32, ((struct lysc_type_bin*)type)->length->parts[1].min_u64);
+ assert_int_equal(32, ((struct lysc_type_bin*)type)->length->parts[1].max_u64);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module h {namespace urn:h;prefix h;typedef mytype {type binary {length 10;}}"
+ "leaf l {type mytype {length \"10\";}}}", 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_non_null(((struct lysc_type_bin*)type)->length);
+ assert_non_null(((struct lysc_type_bin*)type)->length->parts);
+ assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_bin*)type)->length->parts));
+ assert_int_equal(10, ((struct lysc_type_bin*)type)->length->parts[0].min_u64);
+ assert_int_equal(10, ((struct lysc_type_bin*)type)->length->parts[0].max_u64);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module i {namespace urn:i;prefix i;typedef mytype {type binary {length 10..100;}}"
+ "leaf l {type mytype {length \"50\";}}}", 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_non_null(((struct lysc_type_bin*)type)->length);
+ assert_non_null(((struct lysc_type_bin*)type)->length->parts);
+ assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_bin*)type)->length->parts));
+ assert_int_equal(50, ((struct lysc_type_bin*)type)->length->parts[0].min_u64);
+ assert_int_equal(50, ((struct lysc_type_bin*)type)->length->parts[0].max_u64);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module j {namespace urn:j;prefix j;typedef mytype {type binary {length 10..100;}}"
+ "leaf l {type mytype {length \"10..30|60..100\";}}}", 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_non_null(((struct lysc_type_bin*)type)->length);
+ assert_non_null(((struct lysc_type_bin*)type)->length->parts);
+ assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_bin*)type)->length->parts));
+ assert_int_equal(10, ((struct lysc_type_bin*)type)->length->parts[0].min_u64);
+ assert_int_equal(30, ((struct lysc_type_bin*)type)->length->parts[0].max_u64);
+ assert_int_equal(60, ((struct lysc_type_bin*)type)->length->parts[1].min_u64);
+ assert_int_equal(100, ((struct lysc_type_bin*)type)->length->parts[1].max_u64);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module k {namespace urn:k;prefix k;typedef mytype {type binary {length 10..100;}}"
+ "leaf l {type mytype {length \"10..80\";}}leaf ll {type mytype;}}", 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(1, type->refcount);
+ assert_non_null(((struct lysc_type_bin*)type)->length);
+ assert_non_null(((struct lysc_type_bin*)type)->length->parts);
+ assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_bin*)type)->length->parts));
+ assert_int_equal(10, ((struct lysc_type_bin*)type)->length->parts[0].min_u64);
+ assert_int_equal(80, ((struct lysc_type_bin*)type)->length->parts[0].max_u64);
+ type = ((struct lysc_node_leaf*)mod->compiled->data->next)->type;
+ assert_non_null(type);
+ assert_int_equal(2, type->refcount);
+ assert_non_null(((struct lysc_type_bin*)type)->length);
+ assert_non_null(((struct lysc_type_bin*)type)->length->parts);
+ assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_bin*)type)->length->parts));
+ assert_int_equal(10, ((struct lysc_type_bin*)type)->length->parts[0].min_u64);
+ assert_int_equal(100, ((struct lysc_type_bin*)type)->length->parts[0].max_u64);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module l {namespace urn:l;prefix l;typedef mytype {type string {length 10..100;}}"
+ "typedef mytype2 {type mytype {pattern '[0-9]*';}} leaf l {type mytype2 {pattern '[0-4]*';}}}", 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_STRING, type->basetype);
+ assert_int_equal(1, type->refcount);
+ assert_non_null(((struct lysc_type_str*)type)->length);
+ assert_non_null(((struct lysc_type_str*)type)->length->parts);
+ assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_str*)type)->length->parts));
+ assert_int_equal(10, ((struct lysc_type_str*)type)->length->parts[0].min_u64);
+ assert_int_equal(100, ((struct lysc_type_str*)type)->length->parts[0].max_u64);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module m {namespace urn:m;prefix m;typedef mytype {type string {length 10;}}"
+ "leaf l {type mytype {length min..max;}}}", 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_STRING, type->basetype);
+ assert_int_equal(1, type->refcount);
+ assert_non_null(((struct lysc_type_str*)type)->length);
+ assert_non_null(((struct lysc_type_str*)type)->length->parts);
+ assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_str*)type)->length->parts));
+ assert_int_equal(10, ((struct lysc_type_str*)type)->length->parts[0].min_u64);
+ assert_int_equal(10, ((struct lysc_type_str*)type)->length->parts[0].max_u64);
+
+ /* invalid values */
+ assert_non_null(mod = lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;leaf l {type binary {length -10;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid length restriction - value \"-10\" does not fit the type limitations.");
+ assert_non_null(mod = lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;leaf l {type binary {length 18446744073709551616;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid length restriction - invalid value \"18446744073709551616\".");
+ assert_non_null(mod = lys_parse_mem(ctx, "module cc {namespace urn:cc;prefix cc;leaf l {type binary {length \"max .. 10\";}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid length restriction - unexpected data after max keyword (.. 10).");
+ assert_non_null(mod = lys_parse_mem(ctx, "module dd {namespace urn:dd;prefix dd;leaf l {type binary {length 50..10;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid length restriction - values are not in ascending order (10).");
+ assert_non_null(mod = lys_parse_mem(ctx, "module ee {namespace urn:ee;prefix ee;leaf l {type binary {length \"50 | 10\";}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid length restriction - values are not in ascending order (10).");
+ assert_non_null(mod = lys_parse_mem(ctx, "module ff {namespace urn:ff;prefix ff;leaf l {type binary {length \"x\";}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid length restriction - unexpected data (x).");
+ assert_non_null(mod = lys_parse_mem(ctx, "module gg {namespace urn:gg;prefix gg;leaf l {type binary {length \"50 | min\";}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid length restriction - unexpected data before min keyword (50 | ).");
+ assert_non_null(mod = lys_parse_mem(ctx, "module hh {namespace urn:hh;prefix hh;leaf l {type binary {length \"| 50\";}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid length restriction - unexpected beginning of the expression (| 50).");
+ assert_non_null(mod = lys_parse_mem(ctx, "module ii {namespace urn:ii;prefix ii;leaf l {type binary {length \"10 ..\";}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid length restriction - unexpected end of the expression after \"..\" (10 ..).");
+ assert_non_null(mod = lys_parse_mem(ctx, "module jj {namespace urn:jj;prefix jj;leaf l {type binary {length \".. 10\";}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid length restriction - unexpected \"..\" without a lower bound.");
+ assert_non_null(mod = lys_parse_mem(ctx, "module kk {namespace urn:kk;prefix kk;leaf l {type binary {length \"10 |\";}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid length restriction - unexpected end of the expression (10 |).");
+ assert_non_null(mod = lys_parse_mem(ctx, "module kl {namespace urn:kl;prefix kl;leaf l {type binary {length \"10..20 | 15..30\";}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid length restriction - values are not in ascending order (15).");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module ll {namespace urn:ll;prefix ll;typedef mytype {type binary {length 10;}}"
+ "leaf l {type mytype {length 11;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid length restriction - the derived restriction (11) is not equally or more limiting.");
+ assert_non_null(mod = lys_parse_mem(ctx, "module mm {namespace urn:mm;prefix mm;typedef mytype {type binary {length 10..100;}}"
+ "leaf l {type mytype {length 1..11;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid length restriction - the derived restriction (1..11) is not equally or more limiting.");
+ assert_non_null(mod = lys_parse_mem(ctx, "module nn {namespace urn:nn;prefix nn;typedef mytype {type binary {length 10..100;}}"
+ "leaf l {type mytype {length 20..110;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid length restriction - the derived restriction (20..110) is not equally or more limiting.");
+ assert_non_null(mod = lys_parse_mem(ctx, "module oo {namespace urn:oo;prefix oo;typedef mytype {type binary {length 10..100;}}"
+ "leaf l {type mytype {length 20..30|110..120;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid length restriction - the derived restriction (20..30|110..120) is not equally or more limiting.");
+ assert_non_null(mod = lys_parse_mem(ctx, "module pp {namespace urn:pp;prefix pp;typedef mytype {type binary {length 10..11;}}"
+ "leaf l {type mytype {length 15;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid length restriction - the derived restriction (15) is not equally or more limiting.");
+ assert_non_null(mod = lys_parse_mem(ctx, "module qq {namespace urn:qq;prefix qq;typedef mytype {type binary {length 10..20|30..40;}}"
+ "leaf l {type mytype {length 15..35;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid length restriction - the derived restriction (15..35) is not equally or more limiting.");
+ assert_non_null(mod = lys_parse_mem(ctx, "module rr {namespace urn:rr;prefix rr;typedef mytype {type binary {length 10;}}"
+ "leaf l {type mytype {length 10..35;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid length restriction - the derived restriction (10..35) is not equally or more limiting.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module ss {namespace urn:rr;prefix rr;leaf l {type binary {pattern '[0-9]*';}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid type restrictions for binary type.");
+
+ *state = NULL;
+ ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_type_pattern(void **state)
+{
+ *state = test_type_pattern;
+
+ struct ly_ctx *ctx;
+ struct lys_module *mod;
+ struct lysc_type *type;
+
+ assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module a {yang-version 1.1; namespace urn:a;prefix a;leaf l {type string {"
+ "pattern .* {error-app-tag errortag;error-message error;}"
+ "pattern [0-9].*[0-9] {modifier invert-match;}}}}", 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_non_null(((struct lysc_type_str*)type)->patterns);
+ assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_str*)type)->patterns));
+ assert_string_equal("errortag", ((struct lysc_type_str*)type)->patterns[0]->eapptag);
+ assert_string_equal("error", ((struct lysc_type_str*)type)->patterns[0]->emsg);
+ assert_int_equal(0, ((struct lysc_type_str*)type)->patterns[0]->inverted);
+ assert_null(((struct lysc_type_str*)type)->patterns[1]->eapptag);
+ assert_null(((struct lysc_type_str*)type)->patterns[1]->emsg);
+ assert_int_equal(1, ((struct lysc_type_str*)type)->patterns[1]->inverted);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;typedef mytype {type string {pattern '[0-9]*';}}"
+ "typedef mytype2 {type mytype {length 10;}} leaf l {type mytype2 {pattern '[0-4]*';}}}", 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_STRING, type->basetype);
+ assert_int_equal(1, type->refcount);
+ assert_non_null(((struct lysc_type_str*)type)->patterns);
+ assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_str*)type)->patterns));
+ assert_int_equal(3, ((struct lysc_type_str*)type)->patterns[0]->refcount);
+ assert_int_equal(1, ((struct lysc_type_str*)type)->patterns[1]->refcount);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module c {namespace urn:c;prefix c;typedef mytype {type string {pattern '[0-9]*';}}"
+ "leaf l {type mytype {length 10;}}}", 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_STRING, type->basetype);
+ assert_int_equal(1, type->refcount);
+ assert_non_null(((struct lysc_type_str*)type)->patterns);
+ assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_str*)type)->patterns));
+ assert_int_equal(2, ((struct lysc_type_str*)type)->patterns[0]->refcount);
+
+ /* test substitutions */
+ assert_non_null(mod = lys_parse_mem(ctx, "module d {namespace urn:d;prefix d;leaf l {type string {"
+ "pattern '^\\p{IsLatinExtended-A}$';}}}", 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_non_null(((struct lysc_type_str*)type)->patterns);
+ assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_str*)type)->patterns));
+ /* TODO check some data "^ř$" */
+
+ *state = NULL;
+ ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_type_enum(void **state)
+{
+ *state = test_type_enum;
+
+ struct ly_ctx *ctx;
+ struct lys_module *mod;
+ struct lysc_type *type;
+
+ assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module a {yang-version 1.1; namespace urn:a;prefix a;feature f; leaf l {type enumeration {"
+ "enum automin; enum min {value -2147483648;}enum one {if-feature f; value 1;}"
+ "enum two; enum seven {value 7;}enum eight;}}}", 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_ENUM, type->basetype);
+ assert_non_null(((struct lysc_type_enum*)type)->enums);
+ assert_int_equal(6, LY_ARRAY_SIZE(((struct lysc_type_enum*)type)->enums));
+ assert_non_null(((struct lysc_type_enum*)type)->enums[2].iffeatures);
+ assert_string_equal("automin", ((struct lysc_type_enum*)type)->enums[0].name);
+ assert_int_equal(0, ((struct lysc_type_enum*)type)->enums[0].value);
+ assert_string_equal("min", ((struct lysc_type_enum*)type)->enums[1].name);
+ assert_int_equal(-2147483648, ((struct lysc_type_enum*)type)->enums[1].value);
+ assert_string_equal("one", ((struct lysc_type_enum*)type)->enums[2].name);
+ assert_int_equal(1, ((struct lysc_type_enum*)type)->enums[2].value);
+ assert_string_equal("two", ((struct lysc_type_enum*)type)->enums[3].name);
+ assert_int_equal(2, ((struct lysc_type_enum*)type)->enums[3].value);
+ assert_string_equal("seven", ((struct lysc_type_enum*)type)->enums[4].name);
+ assert_int_equal(7, ((struct lysc_type_enum*)type)->enums[4].value);
+ assert_string_equal("eight", ((struct lysc_type_enum*)type)->enums[5].name);
+ assert_int_equal(8, ((struct lysc_type_enum*)type)->enums[5].value);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module b {yang-version 1.1; namespace urn:b;prefix b;feature f; typedef mytype {type enumeration {"
+ "enum 11; enum min {value -2147483648;}enum x$&;"
+ "enum two; enum seven {value 7;}enum eight;}} leaf l { type mytype {enum seven;enum eight;}}}",
+ 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_ENUM, type->basetype);
+ assert_non_null(((struct lysc_type_enum*)type)->enums);
+ assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_enum*)type)->enums));
+ assert_string_equal("seven", ((struct lysc_type_enum*)type)->enums[0].name);
+ assert_int_equal(7, ((struct lysc_type_enum*)type)->enums[0].value);
+ assert_string_equal("eight", ((struct lysc_type_enum*)type)->enums[1].name);
+ assert_int_equal(8, ((struct lysc_type_enum*)type)->enums[1].value);
+
+
+ /* invalid cases */
+ assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; feature f; leaf l {type enumeration {"
+ "enum one {if-feature f;}}}}", LYS_IN_YANG));
+ logbuf_assert("Invalid keyword \"if-feature\" as a child of \"enum\" - the statement is allowed only in YANG 1.1 modules. Line number 1.");
+ assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
+ "enum one {value -2147483649;}}}}", LYS_IN_YANG));
+ logbuf_assert("Invalid value \"-2147483649\" of \"value\". Line number 1.");
+ assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
+ "enum one {value 2147483648;}}}}", LYS_IN_YANG));
+ logbuf_assert("Invalid value \"2147483648\" of \"value\". Line number 1.");
+ assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
+ "enum one; enum one;}}}", LYS_IN_YANG));
+ logbuf_assert("Duplicate identifier \"one\" of enum statement. Line number 1.");
+ assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
+ "enum '';}}}", LYS_IN_YANG));
+ logbuf_assert("Enum name must not be zero-length. Line number 1.");
+ assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
+ "enum ' x';}}}", LYS_IN_YANG));
+ logbuf_assert("Enum name must not have any leading or trailing whitespaces (\" x\"). Line number 1.");
+ assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
+ "enum 'x ';}}}", LYS_IN_YANG));
+ logbuf_assert("Enum name must not have any leading or trailing whitespaces (\"x \"). Line number 1.");
+ assert_non_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
+ "enum 'inva\nlid';}}}", LYS_IN_YANG));
+ logbuf_assert("Control characters in enum name should be avoided (\"inva\nlid\", character number 5).");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb; leaf l {type enumeration;}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Missing enum substatement for enumeration type.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module cc {yang-version 1.1;namespace urn:cc;prefix cc;typedef mytype {type enumeration {enum one;}}"
+ "leaf l {type mytype {enum two;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid enumeration - derived type adds new item \"two\".");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module dd {yang-version 1.1;namespace urn:dd;prefix dd;typedef mytype {type enumeration {enum one;}}"
+ "leaf l {type mytype {enum one {value 1;}}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid enumeration - value of the item \"one\" has changed from 0 to 1 in the derived type.");
+ assert_non_null(mod = lys_parse_mem(ctx, "module ee {namespace urn:ee;prefix ee;leaf l {type enumeration {enum x {value 2147483647;}enum y;}}}",
+ LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid enumeration - it is not possible to auto-assign enum value for \"y\" since the highest value is already 2147483647.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module ff {namespace urn:ff;prefix ff;leaf l {type enumeration {enum x {value 1;}enum y {value 1;}}}}",
+ LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid enumeration - value 1 collide in items \"y\" and \"x\".");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module gg {namespace urn:gg;prefix gg;typedef mytype {type enumeration;}"
+ "leaf l {type mytype {enum one;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Missing enum substatement for enumeration type mytype.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module hh {namespace urn:hh;prefix hh; typedef mytype {type enumeration {enum one;}}"
+ "leaf l {type mytype {enum one;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Enumeration type can be subtyped only in YANG 1.1 modules.");
+
+ *state = NULL;
+ ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_type_bits(void **state)
+{
+ *state = test_type_bits;
+
+ struct ly_ctx *ctx;
+ struct lys_module *mod;
+ struct lysc_type *type;
+
+ assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module a {yang-version 1.1; namespace urn:a;prefix a;feature f; leaf l {type bits {"
+ "bit automin; bit one {if-feature f; position 1;}"
+ "bit two; bit seven {position 7;}bit eight;}}}", 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_BITS, type->basetype);
+ assert_non_null(((struct lysc_type_bits*)type)->bits);
+ assert_int_equal(5, LY_ARRAY_SIZE(((struct lysc_type_bits*)type)->bits));
+ assert_non_null(((struct lysc_type_bits*)type)->bits[1].iffeatures);
+ assert_string_equal("automin", ((struct lysc_type_bits*)type)->bits[0].name);
+ assert_int_equal(0, ((struct lysc_type_bits*)type)->bits[0].position);
+ assert_string_equal("one", ((struct lysc_type_bits*)type)->bits[1].name);
+ assert_int_equal(1, ((struct lysc_type_bits*)type)->bits[1].position);
+ assert_string_equal("two", ((struct lysc_type_bits*)type)->bits[2].name);
+ assert_int_equal(2, ((struct lysc_type_bits*)type)->bits[2].position);
+ assert_string_equal("seven", ((struct lysc_type_bits*)type)->bits[3].name);
+ assert_int_equal(7, ((struct lysc_type_bits*)type)->bits[3].position);
+ assert_string_equal("eight", ((struct lysc_type_bits*)type)->bits[4].name);
+ assert_int_equal(8, ((struct lysc_type_bits*)type)->bits[4].position);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module b {yang-version 1.1;namespace urn:b;prefix b;feature f; typedef mytype {type bits {"
+ "bit automin; bit one;bit two; bit seven {value 7;}bit eight;}} leaf l { type mytype {bit eight;bit seven;bit automin;}}}",
+ 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_BITS, type->basetype);
+ assert_non_null(((struct lysc_type_bits*)type)->bits);
+ assert_int_equal(3, LY_ARRAY_SIZE(((struct lysc_type_bits*)type)->bits));
+ assert_string_equal("automin", ((struct lysc_type_bits*)type)->bits[0].name);
+ assert_int_equal(0, ((struct lysc_type_bits*)type)->bits[0].position);
+ assert_string_equal("seven", ((struct lysc_type_bits*)type)->bits[1].name);
+ assert_int_equal(7, ((struct lysc_type_bits*)type)->bits[1].position);
+ assert_string_equal("eight", ((struct lysc_type_bits*)type)->bits[2].name);
+ assert_int_equal(8, ((struct lysc_type_bits*)type)->bits[2].position);
+
+
+ /* invalid cases */
+ assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; feature f; leaf l {type bits {"
+ "bit one {if-feature f;}}}}", LYS_IN_YANG));
+ logbuf_assert("Invalid keyword \"if-feature\" as a child of \"bit\" - the statement is allowed only in YANG 1.1 modules. Line number 1.");
+ assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type bits {"
+ "bit one {position -1;}}}}", LYS_IN_YANG));
+ logbuf_assert("Invalid value \"-1\" of \"position\". Line number 1.");
+ assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type bits {"
+ "bit one {value 4294967296;}}}}", LYS_IN_YANG));
+ logbuf_assert("Invalid value \"4294967296\" of \"value\". Line number 1.");
+ assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type bits {"
+ "bit one; bit one;}}}", LYS_IN_YANG));
+ logbuf_assert("Duplicate identifier \"one\" of bit statement. Line number 1.");
+ assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type bits {"
+ "bit '11';}}}", LYS_IN_YANG));
+ logbuf_assert("Invalid identifier first character '1'. Line number 1.");
+ assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type bits {"
+ "bit 'x1$1';}}}", LYS_IN_YANG));
+ logbuf_assert("Invalid identifier character '$'. Line number 1.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb; leaf l {type bits;}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Missing bit substatement for bits type.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module cc {yang-version 1.1;namespace urn:cc;prefix cc;typedef mytype {type bits {bit one;}}"
+ "leaf l {type mytype {bit two;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid bits - derived type adds new item \"two\".");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module dd {yang-version 1.1;namespace urn:dd;prefix dd;typedef mytype {type bits {bit one;}}"
+ "leaf l {type mytype {bit one {position 1;}}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid bits - position of the item \"one\" has changed from 0 to 1 in the derived type.");
+ assert_non_null(mod = lys_parse_mem(ctx, "module ee {namespace urn:ee;prefix ee;leaf l {type bits {bit x {position 4294967295;}bit y;}}}",
+ LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid bits - it is not possible to auto-assign bit position for \"y\" since the highest value is already 4294967295.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module ff {namespace urn:ff;prefix ff;leaf l {type bits {bit x {value 1;}bit y {value 1;}}}}",
+ LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid bits - position 1 collide in items \"y\" and \"x\".");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module gg {namespace urn:gg;prefix gg;typedef mytype {type bits;}"
+ "leaf l {type mytype {bit one;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Missing bit substatement for bits type mytype.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module hh {namespace urn:hh;prefix hh; typedef mytype {type bits {bit one;}}"
+ "leaf l {type mytype {bit one;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Bits type can be subtyped only in YANG 1.1 modules.");
+
+ *state = NULL;
+ ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_type_dec64(void **state)
+{
+ *state = test_type_dec64;
+
+ struct ly_ctx *ctx;
+ struct lys_module *mod;
+ struct lysc_type *type;
+
+ 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;leaf l {type decimal64 {"
+ "fraction-digits 2;range min..max;}}}", 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_DEC64, type->basetype);
+ assert_int_equal(2, ((struct lysc_type_dec*)type)->fraction_digits);
+ assert_non_null(((struct lysc_type_dec*)type)->range);
+ assert_non_null(((struct lysc_type_dec*)type)->range->parts);
+ assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_dec*)type)->range->parts));
+ assert_int_equal(INT64_C(-9223372036854775807) - INT64_C(1), ((struct lysc_type_dec*)type)->range->parts[0].min_64);
+ assert_int_equal(INT64_C(9223372036854775807), ((struct lysc_type_dec*)type)->range->parts[0].max_64);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;typedef mytype {type decimal64 {"
+ "fraction-digits 2;range '3.14 | 5.1 | 10';}}leaf l {type mytype;}}", 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_DEC64, type->basetype);
+ assert_int_equal(2, ((struct lysc_type_dec*)type)->fraction_digits);
+ assert_non_null(((struct lysc_type_dec*)type)->range);
+ assert_non_null(((struct lysc_type_dec*)type)->range->parts);
+ assert_int_equal(3, LY_ARRAY_SIZE(((struct lysc_type_dec*)type)->range->parts));
+ assert_int_equal(314, ((struct lysc_type_dec*)type)->range->parts[0].min_64);
+ assert_int_equal(314, ((struct lysc_type_dec*)type)->range->parts[0].max_64);
+ assert_int_equal(510, ((struct lysc_type_dec*)type)->range->parts[1].min_64);
+ assert_int_equal(510, ((struct lysc_type_dec*)type)->range->parts[1].max_64);
+ assert_int_equal(1000, ((struct lysc_type_dec*)type)->range->parts[2].min_64);
+ assert_int_equal(1000, ((struct lysc_type_dec*)type)->range->parts[2].max_64);
+
+ /* invalid cases */
+ assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type decimal64 {fraction-digits 0;}}}", LYS_IN_YANG));
+ logbuf_assert("Invalid value \"0\" of \"fraction-digits\". Line number 1.");
+ assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type decimal64 {fraction-digits -1;}}}", LYS_IN_YANG));
+ logbuf_assert("Invalid value \"-1\" of \"fraction-digits\". Line number 1.");
+ assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type decimal64 {fraction-digits 19;}}}", LYS_IN_YANG));
+ logbuf_assert("Value \"19\" is out of \"fraction-digits\" bounds. Line number 1.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type decimal64;}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Missing fraction-digits substatement for decimal64 type.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module ab {namespace urn:ab;prefix ab; typedef mytype {type decimal64;}leaf l {type mytype;}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Missing fraction-digits substatement for decimal64 type mytype.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb; leaf l {type decimal64 {fraction-digits 2;"
+ "range '3.142';}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Range boundary \"3.142\" of decimal64 type exceeds defined number (2) of fraction digits.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module cc {namespace urn:cc;prefix cc; leaf l {type decimal64 {fraction-digits 2;"
+ "range '4 | 3.14';}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid range restriction - values are not in ascending order (3.14).");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module dd {namespace urn:dd;prefix dd; typedef mytype {type decimal64 {fraction-digits 2;}}"
+ "leaf l {type mytype {fraction-digits 3;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid fraction-digits substatement for type not directly derived from decimal64 built-in type.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module de {namespace urn:de;prefix de; typedef mytype {type decimal64 {fraction-digits 2;}}"
+ "typedef mytype2 {type mytype {fraction-digits 3;}}leaf l {type mytype2;}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid fraction-digits substatement for type \"mytype2\" not directly derived from decimal64 built-in type.");
+
+ *state = NULL;
+ ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_type_instanceid(void **state)
+{
+ *state = test_type_instanceid;
+
+ struct ly_ctx *ctx;
+ struct lys_module *mod;
+ struct lysc_type *type;
+
+ 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;typedef mytype {type instance-identifier {require-instance false;}}"
+ "leaf l1 {type instance-identifier {require-instance true;}}"
+ "leaf l2 {type mytype;} leaf l3 {type instance-identifier;}}", 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_INST, type->basetype);
+ assert_int_equal(1, ((struct lysc_type_instanceid*)type)->require_instance);
+
+ type = ((struct lysc_node_leaf*)mod->compiled->data->next)->type;
+ assert_non_null(type);
+ assert_int_equal(LY_TYPE_INST, type->basetype);
+ assert_int_equal(0, ((struct lysc_type_instanceid*)type)->require_instance);
+
+ type = ((struct lysc_node_leaf*)mod->compiled->data->next->next)->type;
+ assert_non_null(type);
+ assert_int_equal(LY_TYPE_INST, type->basetype);
+ assert_int_equal(1, ((struct lysc_type_instanceid*)type)->require_instance);
+
+ /* invalid cases */
+ assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type instance-identifier {require-instance yes;}}}", LYS_IN_YANG));
+ logbuf_assert("Invalid value \"yes\" of \"require-instance\". Line number 1.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type instance-identifier {fraction-digits 1;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid type restrictions for instance-identifier type.");
+
+ *state = NULL;
+ ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_type_identityref(void **state)
+{
+ *state = test_type_identityref;
+
+ struct ly_ctx *ctx;
+ struct lys_module *mod;
+ struct lysc_type *type;
+
+ assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module a {yang-version 1.1;namespace urn:a;prefix a;identity i; identity j; identity k {base i;}"
+ "typedef mytype {type identityref {base i;}}"
+ "leaf l1 {type mytype;} leaf l2 {type identityref {base a:k; base j;}}}", 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_IDENT, type->basetype);
+ assert_non_null(((struct lysc_type_identityref*)type)->bases);
+ assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_identityref*)type)->bases));
+ assert_string_equal("i", ((struct lysc_type_identityref*)type)->bases[0]->name);
+
+ type = ((struct lysc_node_leaf*)mod->compiled->data->next)->type;
+ assert_non_null(type);
+ assert_int_equal(LY_TYPE_IDENT, type->basetype);
+ assert_non_null(((struct lysc_type_identityref*)type)->bases);
+ assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_identityref*)type)->bases));
+ assert_string_equal("k", ((struct lysc_type_identityref*)type)->bases[0]->name);
+ assert_string_equal("j", ((struct lysc_type_identityref*)type)->bases[1]->name);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module b {yang-version 1.1;namespace urn:b;prefix b;import a {prefix a;}"
+ "leaf l {type identityref {base a:k; base a:j;}}}", 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_IDENT, type->basetype);
+ assert_non_null(((struct lysc_type_identityref*)type)->bases);
+ assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_identityref*)type)->bases));
+ assert_string_equal("k", ((struct lysc_type_identityref*)type)->bases[0]->name);
+ assert_string_equal("j", ((struct lysc_type_identityref*)type)->bases[1]->name);
+
+ /* invalid cases */
+ assert_non_null(mod = lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type identityref;}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Missing base substatement for identityref type.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb; typedef mytype {type identityref;}"
+ "leaf l {type mytype;}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Missing base substatement for identityref type mytype.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module cc {namespace urn:cc;prefix cc; identity i; typedef mytype {type identityref {base i;}}"
+ "leaf l {type mytype {base i;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid base substatement for the type not directly derived from identityref built-in type.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module dd {namespace urn:dd;prefix dd; identity i; typedef mytype {type identityref {base i;}}"
+ "typedef mytype2 {type mytype {base i;}}leaf l {type mytype2;}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid base substatement for the type \"mytype2\" not directly derived from identityref built-in type.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module ee {namespace urn:ee;prefix ee; identity i; identity j;"
+ "leaf l {type identityref {base i;base j;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Multiple bases in identityref type are allowed only in YANG 1.1 modules.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module ff {namespace urn:ff;prefix ff; identity i;leaf l {type identityref {base j;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Unable to find base (j) of identityref.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module gg {namespace urn:gg;prefix gg;leaf l {type identityref {base x:j;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid prefix used for base (x:j) of identityref.");
+
+ *state = NULL;
+ 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_ptr_equal(mod, ((struct lysc_type_leafref*)type)->path_context);
+ assert_non_null(((struct lysc_type_leafref*)type)->realtype);
+ assert_int_equal(LY_TYPE_STRING, ((struct lysc_type_leafref*)type)->realtype->basetype);
+ 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_ptr_equal(mod, ((struct lysc_type_leafref*)type)->path_context);
+ assert_non_null(((struct lysc_type_leafref*)type)->realtype);
+ assert_int_equal(LY_TYPE_UINT8, ((struct lysc_type_leafref*)type)->realtype->basetype);
+ assert_int_equal(0, ((struct lysc_type_leafref*)type)->require_instance);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b; typedef mytype {type leafref {path /b:target;}}"
+ "typedef mytype2 {type mytype;} typedef mytype3 {type leafref {path /target;}} leaf ref {type mytype2;}"
+ "leaf target {type leafref {path ../realtarget;}} leaf realtarget {type string;}}", 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(1, type->refcount);
+ assert_int_equal(LY_TYPE_LEAFREF, type->basetype);
+ assert_string_equal("/b:target", ((struct lysc_type_leafref* )type)->path);
+ assert_ptr_equal(mod, ((struct lysc_type_leafref*)type)->path_context);
+ assert_non_null(((struct lysc_type_leafref*)type)->realtype);
+ assert_int_equal(LY_TYPE_STRING, ((struct lysc_type_leafref*)type)->realtype->basetype);
+ assert_int_equal(1, ((struct lysc_type_leafref* )type)->require_instance);
+
+ /* prefixes are reversed to check using correct context of the path! */
+ assert_non_null(mod = lys_parse_mem(ctx, "module c {yang-version 1.1;namespace urn:c;prefix b; import b {prefix c;}"
+ "typedef mytype3 {type c:mytype {require-instance false;}}"
+ "leaf ref1 {type b:mytype3;}leaf ref2 {type c:mytype2;}}", 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(1, type->refcount);
+ assert_int_equal(LY_TYPE_LEAFREF, type->basetype);
+ assert_string_equal("/b:target", ((struct lysc_type_leafref* )type)->path);
+ assert_ptr_not_equal(mod, ((struct lysc_type_leafref*)type)->path_context);
+ assert_non_null(((struct lysc_type_leafref*)type)->realtype);
+ assert_int_equal(LY_TYPE_STRING, ((struct lysc_type_leafref*)type)->realtype->basetype);
+ assert_int_equal(0, ((struct lysc_type_leafref* )type)->require_instance);
+ type = ((struct lysc_node_leaf*)mod->compiled->data->next)->type;
+ assert_non_null(type);
+ assert_int_equal(1, type->refcount);
+ assert_int_equal(LY_TYPE_LEAFREF, type->basetype);
+ assert_string_equal("/b:target", ((struct lysc_type_leafref* )type)->path);
+ assert_ptr_not_equal(mod, ((struct lysc_type_leafref*)type)->path_context);
+ assert_int_equal(1, ((struct lysc_type_leafref* )type)->require_instance);
+
+ /* non-prefixed nodes in path are supposed to be from the module where the leafref type is instantiated */
+ assert_non_null(mod = lys_parse_mem(ctx, "module d {namespace urn:d;prefix d; import b {prefix b;}"
+ "leaf ref {type b:mytype3;}leaf target {type int8;}}", 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(1, type->refcount);
+ assert_int_equal(LY_TYPE_LEAFREF, type->basetype);
+ assert_string_equal("/target", ((struct lysc_type_leafref* )type)->path);
+ assert_ptr_not_equal(mod, ((struct lysc_type_leafref*)type)->path_context);
+ assert_non_null(((struct lysc_type_leafref*)type)->realtype);
+ assert_int_equal(LY_TYPE_INT8, ((struct lysc_type_leafref*)type)->realtype->basetype);
+ assert_int_equal(1, ((struct lysc_type_leafref* )type)->require_instance);
+
+ /* conditional leafrefs */
+ assert_non_null(mod = lys_parse_mem(ctx, "module e {yang-version 1.1;namespace urn:e;prefix e;feature f1; feature f2;"
+ "leaf ref1 {if-feature 'f1 and f2';type leafref {path /target;}}"
+ "leaf target {if-feature f1; type boolean;}}", 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(1, type->refcount);
+ assert_int_equal(LY_TYPE_LEAFREF, type->basetype);
+ assert_string_equal("/target", ((struct lysc_type_leafref* )type)->path);
+ assert_ptr_equal(mod, ((struct lysc_type_leafref*)type)->path_context);
+ assert_non_null(((struct lysc_type_leafref*)type)->realtype);
+ assert_int_equal(LY_TYPE_BOOL, ((struct lysc_type_leafref*)type)->realtype->basetype);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module f {namespace urn:f;prefix f;"
+ "list interface{key name;leaf name{type string;}list address {key ip;leaf ip {type string;}}}"
+ "container default-address{leaf ifname{type leafref{ path \"../../interface/name\";}}"
+ "leaf address {type leafref{ path \"../../interface[ name = current()/../ifname ]/address/ip\";}}}}",
+ LYS_IN_YANG));
+ assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+ type = ((struct lysc_node_leaf*)(*lysc_node_children_p(mod->compiled->data->prev))->prev)->type;
+ assert_non_null(type);
+ assert_int_equal(1, type->refcount);
+ assert_int_equal(LY_TYPE_LEAFREF, type->basetype);
+ assert_string_equal("../../interface[ name = current()/../ifname ]/address/ip", ((struct lysc_type_leafref* )type)->path);
+ assert_ptr_equal(mod, ((struct lysc_type_leafref*)type)->path_context);
+ assert_non_null(((struct lysc_type_leafref*)type)->realtype);
+ assert_int_equal(LY_TYPE_STRING, ((struct lysc_type_leafref*)type)->realtype->basetype);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module g {namespace urn:g;prefix g;"
+ "leaf source {type leafref {path \"/endpoint-parent[id=current()/../field]/endpoint/name\";}}"
+ "leaf field {type int32;}list endpoint-parent {key id;leaf id {type int32;}"
+ "list endpoint {key name;leaf name {type string;}}}}", 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(1, type->refcount);
+ assert_int_equal(LY_TYPE_LEAFREF, type->basetype);
+ assert_string_equal("/endpoint-parent[id=current()/../field]/endpoint/name", ((struct lysc_type_leafref* )type)->path);
+ assert_ptr_equal(mod, ((struct lysc_type_leafref*)type)->path_context);
+ assert_non_null(((struct lysc_type_leafref*)type)->realtype);
+ assert_int_equal(LY_TYPE_STRING, ((struct lysc_type_leafref*)type)->realtype->basetype);
+
+ /* 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\".");
+ assert_non_null(mod = lys_parse_mem(ctx, "module hh {namespace urn:hh;prefix hh;"
+ "leaf ref1 {type leafref;}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Missing path substatement for leafref type.");
+ assert_non_null(mod = lys_parse_mem(ctx, "module ii {namespace urn:ii;prefix ii;typedef mytype {type leafref;}"
+ "leaf ref1 {type mytype;}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Missing path substatement for leafref type mytype.");
+ assert_non_null(mod = lys_parse_mem(ctx, "module jj {namespace urn:jj;prefix jj;feature f;"
+ "leaf ref {type leafref {path /target;}}leaf target {if-feature f;type string;}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid leafref path \"/target\" - set of features applicable to the leafref target is not a subset of features "
+ "applicable to the leafref itself.");
+ assert_non_null(mod = lys_parse_mem(ctx, "module kk {namespace urn:kk;prefix kk;"
+ "leaf ref {type leafref {path /target;}}leaf target {type string;config false;}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid leafref path \"/target\" - target is supposed to represent configuration data (as the leafref does), but it does not.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module ll {namespace urn:ll;prefix ll;"
+ "leaf ref {type leafref {path /target; require-instance true;}}leaf target {type string;}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Leafref type can be restricted by require-instance statement only in YANG 1.1 modules.");
+ assert_non_null(mod = lys_parse_mem(ctx, "module mm {namespace urn:mm;prefix mm;typedef mytype {type leafref {path /target;require-instance false;}}"
+ "leaf ref {type mytype;}leaf target {type string;}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Leafref type \"mytype\" can be restricted by require-instance statement only in YANG 1.1 modules.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module nn {namespace urn:nn;prefix nn;"
+ "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+ "leaf ifname{type leafref{ path \"../interface/name\";}}"
+ "leaf address {type leafref{ path \"/interface[name is current()/../ifname]/ip\";}}}",
+ LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid leafref path predicate \"[name i\" - missing \"=\" after node-identifier.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module oo {namespace urn:oo;prefix oo;"
+ "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+ "leaf ifname{type leafref{ path \"../interface/name\";}}"
+ "leaf address {type leafref{ path \"/interface[name=current()/../ifname/ip\";}}}",
+ LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid leafref path predicate \"[name=current()/../ifname/ip\" - missing predicate termination.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module pp {namespace urn:pp;prefix pp;"
+ "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+ "leaf ifname{type leafref{ path \"../interface/name\";}}"
+ "leaf address {type leafref{ path \"/interface[x:name=current()/../ifname]/ip\";}}}",
+ LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid leafref path predicate \"[x:name=current()/../ifname]\" - prefix \"x\" not defined in module \"pp\".");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module qq {namespace urn:qq;prefix qq;"
+ "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+ "leaf ifname{type leafref{ path \"../interface/name\";}}"
+ "leaf address {type leafref{ path \"/interface[id=current()/../ifname]/ip\";}}}",
+ LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid leafref path predicate \"[id=current()/../ifname]\" - predicate's key node \"id\" not found.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module rr {namespace urn:rr;prefix rr;"
+ "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+ "leaf ifname{type leafref{ path \"../interface/name\";}}leaf test{type string;}"
+ "leaf address {type leafref{ path \"/interface[name=current() / .. / ifname][name=current()/../test]/ip\";}}}",
+ LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid leafref path predicate \"[name=current()/../test]\" - multiple equality tests for the key \"name\".");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module ss {namespace urn:ss;prefix ss;"
+ "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+ "leaf ifname{type leafref{ path \"../interface/name\";}}leaf test{type string;}"
+ "leaf address {type leafref{ path \"/interface[name = ../ifname]/ip\";}}}",
+ LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid leafref path predicate \"[name = ../ifname]\" - missing current-function-invocation.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module tt {namespace urn:tt;prefix tt;"
+ "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+ "leaf ifname{type leafref{ path \"../interface/name\";}}leaf test{type string;}"
+ "leaf address {type leafref{ path \"/interface[name = current()../ifname]/ip\";}}}",
+ LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid leafref path predicate \"[name = current()../ifname]\" - missing \"/\" after current-function-invocation.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module uu {namespace urn:uu;prefix uu;"
+ "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+ "leaf ifname{type leafref{ path \"../interface/name\";}}leaf test{type string;}"
+ "leaf address {type leafref{ path \"/interface[name = current()/..ifname]/ip\";}}}",
+ LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid leafref path predicate \"[name = current()/..ifname]\" - missing \"/\" in \"../\" rel-path-keyexpr pattern.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module vv {namespace urn:vv;prefix vv;"
+ "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+ "leaf ifname{type leafref{ path \"../interface/name\";}}leaf test{type string;}"
+ "leaf address {type leafref{ path \"/interface[name = current()/ifname]/ip\";}}}",
+ LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid leafref path predicate \"[name = current()/ifname]\" - at least one \"..\" is expected in rel-path-keyexpr.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module ww {namespace urn:ww;prefix ww;"
+ "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+ "leaf ifname{type leafref{ path \"../interface/name\";}}leaf test{type string;}"
+ "leaf address {type leafref{ path \"/interface[name = current()/../]/ip\";}}}",
+ LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid leafref path predicate \"[name = current()/../]\" - at least one node-identifier is expected in rel-path-keyexpr.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module xx {namespace urn:xx;prefix xx;"
+ "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+ "leaf ifname{type leafref{ path \"../interface/name\";}}leaf test{type string;}"
+ "leaf address {type leafref{ path \"/interface[name = current()/../$node]/ip\";}}}",
+ LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid node identifier in leafref path predicate - character 22 (of [name = current()/../$node]).");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module yy {namespace urn:yy;prefix yy;"
+ "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+ "leaf ifname{type leafref{ path \"../interface/name\";}}"
+ "leaf address {type leafref{ path \"/interface[name=current()/../x:ifname]/ip\";}}}",
+ LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid leafref path predicate \"[name=current()/../x:ifname]\" - unable to find module of the node \"ifname\" in rel-path_keyexpr.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module zz {namespace urn:zz;prefix zz;"
+ "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+ "leaf ifname{type leafref{ path \"../interface/name\";}}"
+ "leaf address {type leafref{ path \"/interface[name=current()/../xxx]/ip\";}}}",
+ LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid leafref path predicate \"[name=current()/../xxx]\" - unable to find node \"current()/../xxx\" in the rel-path_keyexpr.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module zza {namespace urn:zza;prefix zza;"
+ "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+ "leaf ifname{type leafref{ path \"../interface/name\";}}container c;"
+ "leaf address {type leafref{ path \"/interface[name=current()/../c]/ip\";}}}",
+ LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid leafref path predicate \"[name=current()/../c]\" - rel-path_keyexpr \"current()/../c\" refers container instead of leaf.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module zzb {namespace urn:zzb;prefix zzb;"
+ "list interface{key name;leaf name{type string;}leaf ip {type string;}container c;}"
+ "leaf ifname{type leafref{ path \"../interface/name\";}}"
+ "leaf address {type leafref{ path \"/interface[c=current()/../ifname]/ip\";}}}",
+ LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid leafref path predicate \"[c=current()/../ifname]\" - predicate's key node \"c\" not found.");
+
+ /* circular chain */
+ assert_non_null(mod = lys_parse_mem(ctx, "module aaa {namespace urn:aaa;prefix aaa;"
+ "leaf ref1 {type leafref {path /ref2;}}"
+ "leaf ref2 {type leafref {path /ref3;}}"
+ "leaf ref3 {type leafref {path /ref4;}}"
+ "leaf ref4 {type leafref {path /ref1;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid leafref path \"/ref1\" - circular chain of leafrefs detected.");
+
+ *state = NULL;
+ ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_type_empty(void **state)
+{
+ *state = test_type_empty;
+
+ struct ly_ctx *ctx;
+ struct lys_module *mod;
+
+ assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+ /* invalid */
+ assert_non_null(mod = lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;"
+ "leaf l {type empty; default x;}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Leaf of type \"empty\" must not have a default value (x).");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;typedef mytype {type empty; default x;}"
+ "leaf l {type mytype;}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid type \"mytype\" - \"empty\" type must not have a default value (x).");
+
+ *state = NULL;
+ ly_ctx_destroy(ctx, NULL);
+}
+
+
+static void
+test_type_union(void **state)
+{
+ *state = test_type_union;
+
+ struct ly_ctx *ctx;
+ struct lys_module *mod;
+ struct lysc_type *type;
+
+ assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module a {yang-version 1.1;namespace urn:a;prefix a; typedef mybasetype {type string;}"
+ "typedef mytype {type union {type int8; type mybasetype;}}"
+ "leaf l {type mytype;}}", 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(2, type->refcount);
+ assert_int_equal(LY_TYPE_UNION, type->basetype);
+ assert_non_null(((struct lysc_type_union*)type)->types);
+ assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_union*)type)->types));
+ assert_int_equal(LY_TYPE_INT8, ((struct lysc_type_union*)type)->types[0]->basetype);
+ assert_int_equal(LY_TYPE_STRING, ((struct lysc_type_union*)type)->types[1]->basetype);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module b {yang-version 1.1;namespace urn:b;prefix b; typedef mybasetype {type string;}"
+ "typedef mytype {type union {type int8; type mybasetype;}}"
+ "leaf l {type union {type decimal64 {fraction-digits 2;} type mytype;}}}", 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(1, type->refcount);
+ assert_int_equal(LY_TYPE_UNION, type->basetype);
+ assert_non_null(((struct lysc_type_union*)type)->types);
+ assert_int_equal(3, LY_ARRAY_SIZE(((struct lysc_type_union*)type)->types));
+ assert_int_equal(LY_TYPE_DEC64, ((struct lysc_type_union*)type)->types[0]->basetype);
+ assert_int_equal(LY_TYPE_INT8, ((struct lysc_type_union*)type)->types[1]->basetype);
+ assert_int_equal(LY_TYPE_STRING, ((struct lysc_type_union*)type)->types[2]->basetype);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module c {yang-version 1.1;namespace urn:c;prefix c; typedef mybasetype {type string;}"
+ "typedef mytype {type union {type leafref {path ../target;} type mybasetype;}}"
+ "leaf l {type union {type decimal64 {fraction-digits 2;} type mytype;}}"
+ "leaf target {type leafref {path ../realtarget;}} leaf realtarget {type int8;}}",
+ 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(1, type->refcount);
+ assert_int_equal(LY_TYPE_UNION, type->basetype);
+ assert_non_null(((struct lysc_type_union*)type)->types);
+ assert_int_equal(3, LY_ARRAY_SIZE(((struct lysc_type_union*)type)->types));
+ assert_int_equal(LY_TYPE_DEC64, ((struct lysc_type_union*)type)->types[0]->basetype);
+ assert_int_equal(LY_TYPE_LEAFREF, ((struct lysc_type_union*)type)->types[1]->basetype);
+ assert_int_equal(LY_TYPE_STRING, ((struct lysc_type_union*)type)->types[2]->basetype);
+ assert_non_null(((struct lysc_type_leafref*)((struct lysc_type_union*)type)->types[1])->realtype);
+ assert_int_equal(LY_TYPE_INT8, ((struct lysc_type_leafref*)((struct lysc_type_union*)type)->types[1])->realtype->basetype);
+
+ /* invalid unions */
+ assert_non_null(mod = lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;typedef mytype {type union;}"
+ "leaf l {type mytype;}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Missing type substatement for union type mytype.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;leaf l {type union;}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Missing type substatement for union type.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module cc {namespace urn:cc;prefix cc;typedef mytype {type union{type int8; type string;}}"
+ "leaf l {type mytype {type string;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid type substatement for the type not directly derived from union built-in type.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module dd {namespace urn:dd;prefix dd;typedef mytype {type union{type int8; type string;}}"
+ "typedef mytype2 {type mytype {type string;}}leaf l {type mytype2;}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid type substatement for the type \"mytype2\" not directly derived from union built-in type.");
+
+ *state = NULL;
+ ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_type_dflt(void **state)
+{
+ *state = test_type_union;
+
+ struct ly_ctx *ctx;
+ struct lys_module *mod;
+ struct lysc_type *type;
+
+ assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+ /* default is not inherited from union's types */
+ assert_non_null(mod = lys_parse_mem(ctx, "module a {namespace urn:a;prefix a; typedef mybasetype {type string;default hello;units xxx;}"
+ "leaf l {type union {type decimal64 {fraction-digits 2;} type mybasetype;}}}", 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(1, type->refcount);
+ assert_int_equal(LY_TYPE_UNION, type->basetype);
+ assert_non_null(((struct lysc_type_union*)type)->types);
+ assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_union*)type)->types));
+ assert_int_equal(LY_TYPE_DEC64, ((struct lysc_type_union*)type)->types[0]->basetype);
+ assert_int_equal(LY_TYPE_STRING, ((struct lysc_type_union*)type)->types[1]->basetype);
+ assert_null(((struct lysc_node_leaf*)mod->compiled->data)->dflt);
+ assert_null(((struct lysc_node_leaf*)mod->compiled->data)->units);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b; typedef mybasetype {type string;default hello;units xxx;}"
+ "leaf l {type mybasetype;}}", 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(2, type->refcount);
+ assert_int_equal(LY_TYPE_STRING, type->basetype);
+ assert_string_equal("hello", ((struct lysc_node_leaf*)mod->compiled->data)->dflt);
+ assert_string_equal("xxx", ((struct lysc_node_leaf*)mod->compiled->data)->units);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module c {namespace urn:c;prefix c; typedef mybasetype {type string;default hello;units xxx;}"
+ "leaf l {type mybasetype; default goodbye;units yyy;}}", 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(2, type->refcount);
+ assert_int_equal(LY_TYPE_STRING, type->basetype);
+ assert_string_equal("goodbye", ((struct lysc_node_leaf*)mod->compiled->data)->dflt);
+ assert_string_equal("yyy", ((struct lysc_node_leaf*)mod->compiled->data)->units);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module d {namespace urn:d;prefix d; typedef mybasetype {type string;default hello;units xxx;}"
+ "typedef mytype {type mybasetype;}leaf l1 {type mytype; default goodbye;units yyy;}"
+ "leaf l2 {type mytype;}}", 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(4, type->refcount);
+ assert_int_equal(LY_TYPE_STRING, type->basetype);
+ assert_string_equal("goodbye", ((struct lysc_node_leaf*)mod->compiled->data)->dflt);
+ assert_string_equal("yyy", ((struct lysc_node_leaf*)mod->compiled->data)->units);
+ type = ((struct lysc_node_leaf*)mod->compiled->data->next)->type;
+ assert_non_null(type);
+ assert_int_equal(4, type->refcount);
+ assert_int_equal(LY_TYPE_STRING, type->basetype);
+ assert_string_equal("hello", ((struct lysc_node_leaf*)mod->compiled->data->next)->dflt);
+ assert_string_equal("xxx", ((struct lysc_node_leaf*)mod->compiled->data->next)->units);
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module e {namespace urn:e;prefix e; typedef mybasetype {type string;}"
+ "typedef mytype {type mybasetype; default hello;units xxx;}leaf l {type mytype;}}", 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(3, type->refcount);
+ assert_int_equal(LY_TYPE_STRING, type->basetype);
+ assert_string_equal("hello", ((struct lysc_node_leaf*)mod->compiled->data)->dflt);
+ assert_string_equal("xxx", ((struct lysc_node_leaf*)mod->compiled->data)->units);
+
+ /* mandatory leaf does not takes default value from type */
+ assert_non_null(mod = lys_parse_mem(ctx, "module f {namespace urn:f;prefix f;typedef mytype {type string; default hello;units xxx;}"
+ "leaf l {type mytype; mandatory true;}}", 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_STRING, type->basetype);
+ assert_null(((struct lysc_node_leaf*)mod->compiled->data)->dflt);
+ assert_string_equal("xxx", ((struct lysc_node_leaf*)mod->compiled->data)->units);
+
+ *state = NULL;
+ ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_status(void **state)
+{
+ *state = test_status;
+
+ struct ly_ctx *ctx;
+ struct lys_module *mod;
+
+ assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;"
+ "container c {status deprecated; leaf l {status current; type string;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("A \"current\" status is in conflict with the parent's \"deprecated\" status.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;"
+ "container c {status obsolete; leaf l {status current; type string;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("A \"current\" status is in conflict with the parent's \"obsolete\" status.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module cc {namespace urn:cc;prefix cc;"
+ "container c {status obsolete; leaf l {status deprecated; type string;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("A \"deprecated\" status is in conflict with the parent's \"obsolete\" status.");
+
+ *state = NULL;
+ ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_uses(void **state)
+{
+ *state = test_uses;
+
+ struct ly_ctx *ctx;
+ struct lys_module *mod;
+ struct lysc_node *parent, *child;
+
+ assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module grp {namespace urn:grp;prefix g; typedef mytype {type string;}"
+ "grouping grp {leaf x {type mytype;}}}", LYS_IN_YANG));
+ assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module a {namespace urn:a;prefix a;import grp {prefix g;}"
+ "grouping grp_a_top {leaf a1 {type int8;}}"
+ "container a {uses grp_a; uses grp_a_top; uses g:grp; grouping grp_a {leaf a2 {type uint8;}}}}", LYS_IN_YANG));
+ assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+ assert_non_null((parent = mod->compiled->data));
+ assert_int_equal(LYS_CONTAINER, parent->nodetype);
+ assert_non_null((child = ((struct lysc_node_container*)parent)->child));
+ assert_string_equal("a2", child->name);
+ assert_ptr_equal(mod, child->module);
+ assert_non_null((child = child->next));
+ assert_string_equal("a1", child->name);
+ assert_ptr_equal(mod, child->module);
+ assert_non_null((child = child->next));
+ assert_string_equal("x", child->name);
+ assert_ptr_equal(mod, child->module);
+
+ /* invalid */
+ assert_non_null(mod = lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;uses missinggrp;}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Grouping \"missinggrp\" referenced by a uses statement not found.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;uses grp;"
+ "grouping grp {leaf a{type string;}uses grp1;}"
+ "grouping grp1 {leaf b {type string;}uses grp2;}"
+ "grouping grp2 {leaf c {type string;}uses grp;}}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Grouping \"grp\" references itself through a uses statement.");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module cc {namespace urn:cc;prefix cc;uses a:missingprefix;}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Invalid prefix used for grouping reference (a:missingprefix).");
+
+ assert_non_null(mod = lys_parse_mem(ctx, "module dd {namespace urn:dd;prefix dd;grouping grp{leaf a{type string;}}"
+ "leaf a {type string;}uses grp;}", LYS_IN_YANG));
+ assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+ logbuf_assert("Duplicate identifier \"a\" of data definition statement.");
+
+ *state = NULL;
+ ly_ctx_destroy(ctx, NULL);
+}
+
+
int main(void)
{
const struct CMUnitTest tests[] = {
- cmocka_unit_test_setup(test_module, logger_setup),
- cmocka_unit_test_setup(test_feature, logger_setup),
+ cmocka_unit_test_setup_teardown(test_module, logger_setup, logger_teardown),
+ cmocka_unit_test_setup_teardown(test_feature, logger_setup, logger_teardown),
+ cmocka_unit_test_setup_teardown(test_identity, logger_setup, logger_teardown),
+ cmocka_unit_test_setup_teardown(test_type_length, logger_setup, logger_teardown),
+ cmocka_unit_test_setup_teardown(test_type_range, logger_setup, logger_teardown),
+ cmocka_unit_test_setup_teardown(test_type_pattern, logger_setup, logger_teardown),
+ cmocka_unit_test_setup_teardown(test_type_enum, logger_setup, logger_teardown),
+ cmocka_unit_test_setup_teardown(test_type_bits, logger_setup, logger_teardown),
+ 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_type_empty, logger_setup, logger_teardown),
+ cmocka_unit_test_setup_teardown(test_type_union, logger_setup, logger_teardown),
+ cmocka_unit_test_setup_teardown(test_type_dflt, logger_setup, logger_teardown),
+ cmocka_unit_test_setup_teardown(test_status, logger_setup, logger_teardown),
+ cmocka_unit_test_setup_teardown(test_node_container, logger_setup, logger_teardown),
+ cmocka_unit_test_setup_teardown(test_node_leaflist, logger_setup, logger_teardown),
+ cmocka_unit_test_setup_teardown(test_node_list, logger_setup, logger_teardown),
+ 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_uses, logger_setup, logger_teardown),
};
return cmocka_run_group_tests(tests, NULL, NULL);
diff --git a/tests/src/test_tree_schema_helpers.c b/tests/src/test_tree_schema_helpers.c
index 3dc7d7c..1c5ca3d 100644
--- a/tests/src/test_tree_schema_helpers.c
+++ b/tests/src/test_tree_schema_helpers.c
@@ -12,10 +12,20 @@
* https://opensource.org/licenses/BSD-3-Clause
*/
+#include "../../src/common.c"
+#include "../../src/log.c"
+#include "../../src/set.c"
+#include "../../src/parser_yang.c"
+#include "../../src/tree_schema.c"
+#include "../../src/tree_schema_free.c"
#include "../../src/tree_schema_helpers.c"
+#include "../../src/hash_table.c"
+#include "../../src/xpath.c"
+#include "../../src/context.c"
#include <stdarg.h>
#include <stddef.h>
+#include <stdio.h>
#include <setjmp.h>
#include <cmocka.h>
@@ -23,15 +33,28 @@
#define BUFSIZE 1024
char logbuf[BUFSIZE] = {0};
+int store = -1; /* negative for infinite logging, positive for limited logging */
+/* set to 0 to printing error messages to stderr instead of checking them in code */
+#define ENABLE_LOGGER_CHECKING 1
+
+#if ENABLE_LOGGER_CHECKING
static void
logger(LY_LOG_LEVEL level, const char *msg, const char *path)
{
(void) level; /* unused */
- (void) path; /* unused */
-
- strncpy(logbuf, msg, BUFSIZE - 1);
+ if (store) {
+ if (path && path[0]) {
+ snprintf(logbuf, BUFSIZE - 1, "%s %s", msg, path);
+ } else {
+ strncpy(logbuf, msg, BUFSIZE - 1);
+ }
+ if (store > 0) {
+ --store;
+ }
+ }
}
+#endif
static int
logger_setup(void **state)
@@ -43,6 +66,24 @@
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)
+{
+ logbuf[0] = '\0';
+}
+
#if ENABLE_LOGGER_CHECKING
# define logbuf_assert(str) assert_string_equal(logbuf, str)
#else
@@ -52,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()).");
@@ -76,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
@@ -85,15 +128,16 @@
struct lysp_revision *revs = NULL, *rev;
+ logbuf_clean();
/* no error, it just does nothing */
lysp_sort_revisions(NULL);
logbuf_assert("");
/* revisions are stored in wrong order - the newest is the last */
LY_ARRAY_NEW_RET(NULL, revs, rev,);
- strcpy(rev->rev, "2018-01-01");
+ strcpy(rev->date, "2018-01-01");
LY_ARRAY_NEW_RET(NULL, revs, rev,);
- strcpy(rev->rev, "2018-12-31");
+ strcpy(rev->date, "2018-12-31");
assert_int_equal(2, LY_ARRAY_SIZE(revs));
assert_string_equal("2018-01-01", &revs[0]);
@@ -106,11 +150,164 @@
LY_ARRAY_FREE(revs);
}
+static LY_ERR test_imp_clb(const char *UNUSED(mod_name), const char *UNUSED(mod_rev), const char *UNUSED(submod_name),
+ const char *UNUSED(sub_rev), void *user_data, LYS_INFORMAT *format,
+ const char **module_data, void (**free_module_data)(void *model_data, void *user_data))
+{
+ *module_data = user_data;
+ *format = LYS_IN_YANG;
+ *free_module_data = NULL;
+ return LY_SUCCESS;
+}
+
+static void
+test_typedef(void **state)
+{
+ *state = test_typedef;
+
+ struct ly_ctx *ctx = NULL;
+ const char *str;
+
+ assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+ str = "module a {namespace urn:a; prefix a; typedef binary {type string;}}";
+ assert_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
+ logbuf_assert("Invalid name \"binary\" of typedef - name collision with a built-in type.");
+ str = "module a {namespace urn:a; prefix a; typedef bits {type string;}}";
+ assert_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
+ logbuf_assert("Invalid name \"bits\" of typedef - name collision with a built-in type.");
+ str = "module a {namespace urn:a; prefix a; typedef boolean {type string;}}";
+ assert_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
+ logbuf_assert("Invalid name \"boolean\" of typedef - name collision with a built-in type.");
+ str = "module a {namespace urn:a; prefix a; typedef decimal64 {type string;}}";
+ assert_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
+ logbuf_assert("Invalid name \"decimal64\" of typedef - name collision with a built-in type.");
+ str = "module a {namespace urn:a; prefix a; typedef empty {type string;}}";
+ assert_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
+ logbuf_assert("Invalid name \"empty\" of typedef - name collision with a built-in type.");
+ str = "module a {namespace urn:a; prefix a; typedef enumeration {type string;}}";
+ assert_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
+ logbuf_assert("Invalid name \"enumeration\" of typedef - name collision with a built-in type.");
+ str = "module a {namespace urn:a; prefix a; typedef int8 {type string;}}";
+ assert_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
+ logbuf_assert("Invalid name \"int8\" of typedef - name collision with a built-in type.");
+ str = "module a {namespace urn:a; prefix a; typedef int16 {type string;}}";
+ assert_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
+ logbuf_assert("Invalid name \"int16\" of typedef - name collision with a built-in type.");
+ str = "module a {namespace urn:a; prefix a; typedef int32 {type string;}}";
+ assert_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
+ logbuf_assert("Invalid name \"int32\" of typedef - name collision with a built-in type.");
+ str = "module a {namespace urn:a; prefix a; typedef int64 {type string;}}";
+ assert_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
+ logbuf_assert("Invalid name \"int64\" of typedef - name collision with a built-in type.");
+ str = "module a {namespace urn:a; prefix a; typedef instance-identifier {type string;}}";
+ assert_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
+ logbuf_assert("Invalid name \"instance-identifier\" of typedef - name collision with a built-in type.");
+ str = "module a {namespace urn:a; prefix a; typedef identityref {type string;}}";
+ assert_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
+ logbuf_assert("Invalid name \"identityref\" of typedef - name collision with a built-in type.");
+ str = "module a {namespace urn:a; prefix a; typedef leafref {type string;}}";
+ assert_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
+ logbuf_assert("Invalid name \"leafref\" of typedef - name collision with a built-in type.");
+ str = "module a {namespace urn:a; prefix a; typedef string {type int8;}}";
+ assert_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
+ logbuf_assert("Invalid name \"string\" of typedef - name collision with a built-in type.");
+ str = "module a {namespace urn:a; prefix a; typedef union {type string;}}";
+ assert_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
+ logbuf_assert("Invalid name \"union\" of typedef - name collision with a built-in type.");
+ str = "module a {namespace urn:a; prefix a; typedef uint8 {type string;}}";
+ assert_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
+ logbuf_assert("Invalid name \"uint8\" of typedef - name collision with a built-in type.");
+ str = "module a {namespace urn:a; prefix a; typedef uint16 {type string;}}";
+ assert_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
+ logbuf_assert("Invalid name \"uint16\" of typedef - name collision with a built-in type.");
+ str = "module a {namespace urn:a; prefix a; typedef uint32 {type string;}}";
+ assert_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
+ logbuf_assert("Invalid name \"uint32\" of typedef - name collision with a built-in type.");
+ str = "module a {namespace urn:a; prefix a; typedef uint64 {type string;}}";
+ assert_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
+ logbuf_assert("Invalid name \"uint64\" of typedef - name collision with a built-in type.");
+
+ str = "module mytypes {namespace urn:types; prefix t; typedef binary_ {type string;} typedef bits_ {type string;} typedef boolean_ {type string;} "
+ "typedef decimal64_ {type string;} typedef empty_ {type string;} typedef enumeration_ {type string;} typedef int8_ {type string;} typedef int16_ {type string;}"
+ "typedef int32_ {type string;} typedef int64_ {type string;} typedef instance-identifier_ {type string;} typedef identityref_ {type string;}"
+ "typedef leafref_ {type string;} typedef string_ {type int8;} typedef union_ {type string;} typedef uint8_ {type string;} typedef uint16_ {type string;}"
+ "typedef uint32_ {type string;} typedef uint64_ {type string;}}";
+ assert_non_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
+
+ str = "module a {namespace urn:a; prefix a; typedef test {type string;} typedef test {type int8;}}";
+ assert_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
+ logbuf_assert("Invalid name \"test\" of typedef - name collision with another top-level type.");
+
+ str = "module a {namespace urn:a; prefix a; typedef x {type string;} container c {typedef x {type int8;}}}";
+ 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.");
+
+ str = "module a {namespace urn:a; prefix a; container c {container d {typedef y {type int8;}} typedef y {type string;}}}";
+ assert_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
+ logbuf_assert("Invalid name \"y\" of typedef - name collision with another scoped type.");
+
+ str = "module a {namespace urn:a; prefix a; container c {typedef y {type int8;} typedef y {type string;}}}";
+ assert_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
+ logbuf_assert("Invalid name \"y\" of typedef - name collision with sibling type.");
+
+ ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule b {belongs-to a {prefix a;} typedef x {type string;}}");
+ str = "module a {namespace urn:a; prefix a; include b; typedef x {type int8;}}";
+ assert_null(lys_parse_mem(ctx, str, LYS_IN_YANG));
+ logbuf_assert("Invalid name \"x\" of typedef - name collision with another top-level type.");
+
+ ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule b {belongs-to a {prefix a;} container c {typedef x {type string;}}}");
+ str = "module a {namespace urn:a; prefix a; include b; typedef x {type int8;}}";
+ 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.");
+
+ ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule b {belongs-to a {prefix a;} typedef x {type int8;}}");
+ str = "module a {namespace urn:a; prefix a; include b; container c {typedef x {type string;}}}";
+ 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_teardown(test_typedef, logger_setup, logger_teardown),
+ cmocka_unit_test_setup(test_parse_nodeid, logger_setup),
};
return cmocka_run_group_tests(tests, NULL, NULL);
diff --git a/tests/src/test_xml.c b/tests/src/test_xml.c
index 568e55e..33a417f 100644
--- a/tests/src/test_xml.c
+++ b/tests/src/test_xml.c
@@ -12,8 +12,12 @@
* https://opensource.org/licenses/BSD-3-Clause
*/
-#define _BSD_SOURCE
-#define _DEFAULT_SOURCE
+#include "common.h"
+#include "../../src/set.c"
+#include "../../src/xml.c"
+#include "../../src/common.c"
+#include "../../src/log.c"
+
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
@@ -23,7 +27,6 @@
#include <string.h>
#include "libyang.h"
-#include "../../src/xml.c"
#define BUFSIZE 1024
char logbuf[BUFSIZE] = {0};