Merge remote-tracking branch 'upstream/libyang2' into libyang2
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index b2d9894..e8e1395 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -26,10 +26,12 @@
 
 # Set common attributes of all tests
 foreach(test_name IN LISTS tests)
-    target_link_libraries(${test_name} ${CMOCKA_LIBRARIES} yang)
-    list(GET tests_wraps 0 test_wrap)
-    set_target_properties(${test_name} PROPERTIES LINK_FLAGS "${test_wrap}")
-    list(REMOVE_AT tests_wraps 0)
+    target_link_libraries(${test_name} ${CMOCKA_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${PCRE_LIBRARIES} m)
+    if (NOT APPLE)
+        list(GET tests_wraps 0 test_wrap)
+        set_target_properties(${test_name} PROPERTIES LINK_FLAGS "${test_wrap}")
+        list(REMOVE_AT tests_wraps 0)
+    endif()
     add_test(NAME ${test_name} COMMAND ${test_name})
 #    set_property(TEST ${test_name} PROPERTY ENVIRONMENT "LIBYANG_EXTENSIONS_PLUGINS_DIR=${CMAKE_BINARY_DIR}/src/extensions")
 #    set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT "LIBYANG_USER_TYPES_PLUGINS_DIR=${CMAKE_BINARY_DIR}/src/user_types")
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};