Merge pull request #1088 from CESNET/change_tests_splittage

Change test file organization
diff --git a/src/tree_schema_compile.c b/src/tree_schema_compile.c
index 33590c7..fd9d1b2 100644
--- a/src/tree_schema_compile.c
+++ b/src/tree_schema_compile.c
@@ -538,7 +538,7 @@
     lysc_update_path(ctx, NULL, prefixed_name);
 
     if (!ext_mod) {
-        ext_mod = lys_module_find_prefix(ctx->mod_def, prefixed_name, u - 1);
+        ext_mod = u ? lys_module_find_prefix(ctx->mod_def, prefixed_name, u - 1) : ctx->mod_def;
         if (!ext_mod) {
             LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
                 "Invalid prefix \"%.*s\" used for extension instance identifier.", u, prefixed_name);
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 01cb370..631f577 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -15,18 +15,17 @@
 
 set(tests)
 set(tests_wraps)
-add_subdirectory(src)
-add_subdirectory(features)
+add_subdirectory(utests)
 
-foreach(test_name IN LISTS tests)
-    message(STATUS ${test_name})
-    string(REGEX REPLACE "[a-z]*_(.*)" "\\1" name "${test_name}")
-    string(REGEX REPLACE "([a-z]*)_.*" "\\1" prefix "${test_name}")
-    add_executable(${test_name} ${prefix}/test_${name}.c $<TARGET_OBJECTS:yangobj>)
-endforeach(test_name)
+foreach(test_id IN LISTS tests)
+    message(STATUS ${test_id})
+    string(REGEX REPLACE "([a-z]*):.*" "\\1" category "${test_id}")
+    string(REGEX REPLACE "[a-z]*:(.*)" "\\1" path "${test_id}")
+    string(REGEX REPLACE "[a-z:/]*test_(.*)" "\\1" name "${test_id}")
+    set(test_name ${category}_${name})
+    add_executable(${test_name} ${category}s/${path}.c $<TARGET_OBJECTS:yangobj>)
 
-# Set common attributes of all tests
-foreach(test_name IN LISTS tests)
+	# Set common attributes of all tests
     target_link_libraries(${test_name} ${CMOCKA_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${PCRE2_LIBRARIES} m)
     if (NOT APPLE)
         list(GET tests_wraps 0 test_wrap)
@@ -37,20 +36,18 @@
 #    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")
     set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT "MALLOC_CHECK_=3")
-endforeach(test_name)
 
-if(ENABLE_VALGRIND_TESTS)
-    if(VALGRIND_FOUND)
-        foreach(test_name IN LISTS tests)
+    if(ENABLE_VALGRIND_TESTS)
+        if(VALGRIND_FOUND)
             add_test(${test_name}_valgrind valgrind --leak-check=full --show-leak-kinds=all --suppressions=${PROJECT_SOURCE_DIR}/tests/ld.supp --error-exitcode=1
-                 ${CMAKE_BINARY_DIR}/tests/${test_name})
+               ${CMAKE_BINARY_DIR}/tests/${test_name})
 #            set_property(TEST ${test_name}_valgrind PROPERTY ENVIRONMENT "LIBYANG_EXTENSIONS_PLUGINS_DIR=${CMAKE_BINARY_DIR}/src/extensions")
 #            set_property(TEST ${test_name}_valgrind APPEND PROPERTY ENVIRONMENT "LIBYANG_USER_TYPES_PLUGINS_DIR=${CMAKE_BINARY_DIR}/src/user_types")
-        endforeach(test_name)
-    else(VALGRIND_FOUND)
-        message(WARNING "valgrind executable not found! Disabling memory leaks tests.")
-    endif(VALGRIND_FOUND)
-endif()
+        else(VALGRIND_FOUND)
+            message(WARNING "valgrind executable not found! Disabling memory leaks tests.")
+        endif(VALGRIND_FOUND)
+    endif(ENABLE_VALGRIND_TESTS)
+endforeach()
 
 if(ENABLE_COVERAGE)
     # Destination
diff --git a/tests/features/CMakeLists.txt b/tests/features/CMakeLists.txt
deleted file mode 100644
index 6e4a366..0000000
--- a/tests/features/CMakeLists.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-set(local_tests
-    features_types
-    features_metadata
-    features_nacm)
-set(local_tests_wraps
-    " "
-    " "
-    " ")
-set(tests ${tests} ${local_tests} PARENT_SCOPE)
-set(tests_wraps ${tests_wraps} ${local_tests_wraps} PARENT_SCOPE)
diff --git a/tests/src/CMakeLists.txt b/tests/src/CMakeLists.txt
deleted file mode 100644
index 00bf835..0000000
--- a/tests/src/CMakeLists.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-set(local_tests
-    src_set
-    src_common
-    src_context
-    src_hash_table
-    src_xml
-    src_parser_yang
-    src_parser_yin
-    src_tree_schema
-    src_tree_schema_compile
-    src_tree_schema_helpers
-    src_printer_yang
-    src_printer_yin
-    src_tree_data
-    src_parser_xml
-    src_printer_xml
-    src_validation)
-set(local_tests_wraps
-    " "
-    "-Wl,--wrap=realloc"
-    " "
-    " "
-    " "
-    " "
-    " "
-    " "
-    " "
-    " "
-    " "
-    " "
-    " "
-    " "
-    " "
-    " ")
-set(tests ${tests} ${local_tests} PARENT_SCOPE)
-set(tests_wraps ${tests_wraps} ${local_tests_wraps} PARENT_SCOPE)
diff --git a/tests/src/test_tree_schema.c b/tests/src/test_tree_schema.c
deleted file mode 100644
index bcee581..0000000
--- a/tests/src/test_tree_schema.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * @file test_tree_schema.c
- * @author: Radek Krejci <rkrejci@cesnet.cz>
- * @brief unit tests for functions from tress_schema.c
- *
- * Copyright (c) 2018-2019 CESNET, z.s.p.o.
- *
- * This source code is licensed under BSD 3-Clause License (the "License").
- * You may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     https://opensource.org/licenses/BSD-3-Clause
- */
-
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <setjmp.h>
-#include <cmocka.h>
-
-#include "../../src/common.h"
-#include "../../src/tree_schema.h"
-
-#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 */
-    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)
-{
-    (void) state; /* unused */
-
-    ly_set_log_clb(logger, 0);
-
-    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
-#   define logbuf_assert(str)
-#endif
-
-static void
-test_getnext(void **state)
-{
-    *state = test_getnext;
-
-    struct ly_ctx *ctx;
-    struct lys_module *mod;
-    const struct lysc_node *node = NULL, *four;
-    const struct lysc_node_container *cont;
-    const struct lysc_action *rpc;
-
-    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;"
-                                        "container a { container one {presence test;} leaf two {type string;} leaf-list three {type string;}"
-                                        "  list four {config false;} choice x { leaf five {type string;} case y {leaf six {type string;}}}"
-                                        "  anyxml seven; action eight {input {leaf eight-input {type string;}} output {leaf eight-output {type string;}}}"
-                                        "  notification nine {leaf nine-data {type string;}}}"
-                                        "leaf b {type string;} leaf-list c {type string;} list d {config false;}"
-                                        "choice x { leaf e {type string;} case y {leaf f {type string;}}} anyxml g;"
-                                        "rpc h {input {leaf h-input {type string;}} output {leaf h-output {type string;}}}"
-                                        "rpc i;"
-                                        "notification j {leaf i-data {type string;}}"
-                                        "notification k;}", LYS_IN_YANG));
-    assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
-    assert_string_equal("a", node->name);
-    cont = (const struct lysc_node_container*)node;
-    assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
-    assert_string_equal("b", node->name);
-    assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
-    assert_string_equal("c", node->name);
-    assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
-    assert_string_equal("d", node->name);
-    assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
-    assert_string_equal("e", node->name);
-    assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
-    assert_string_equal("f", node->name);
-    assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
-    assert_string_equal("g", node->name);
-    assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
-    assert_string_equal("h", node->name);
-    rpc = (const struct lysc_action*)node;
-    assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
-    assert_string_equal("i", node->name);
-    assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
-    assert_string_equal("j", node->name);
-    assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
-    assert_string_equal("k", node->name);
-    assert_null(node = lys_getnext(node, NULL, mod->compiled, 0));
-    /* Inside container */
-    assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, 0));
-    assert_string_equal("one", node->name);
-    assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, 0));
-    assert_string_equal("two", node->name);
-    assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, 0));
-    assert_string_equal("three", node->name);
-    assert_non_null(node = four = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, 0));
-    assert_string_equal("four", node->name);
-    assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, 0));
-    assert_string_equal("five", node->name);
-    assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, 0));
-    assert_string_equal("six", node->name);
-    assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, 0));
-    assert_string_equal("seven", node->name);
-    assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, 0));
-    assert_string_equal("eight", node->name);
-    assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, 0));
-    assert_string_equal("nine", node->name);
-    assert_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, 0));
-    /* Inside RPC */
-    assert_non_null(node = lys_getnext(node, (const struct lysc_node*)rpc, mod->compiled, 0));
-    assert_string_equal("h-input", node->name);
-    assert_null(node = lys_getnext(node, (const struct lysc_node*)rpc, mod->compiled, 0));
-
-    /* options */
-    assert_non_null(node = lys_getnext(four, (const struct lysc_node*)cont, mod->compiled, LYS_GETNEXT_WITHCHOICE));
-    assert_string_equal("x", node->name);
-    assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, LYS_GETNEXT_WITHCHOICE));
-    assert_string_equal("seven", node->name);
-
-    assert_non_null(node = lys_getnext(four, (const struct lysc_node*)cont, mod->compiled, LYS_GETNEXT_NOCHOICE));
-    assert_string_equal("seven", node->name);
-
-    assert_non_null(node = lys_getnext(four, (const struct lysc_node*)cont, mod->compiled, LYS_GETNEXT_WITHCASE));
-    assert_string_equal("five", node->name);
-    assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, LYS_GETNEXT_WITHCASE));
-    assert_string_equal("y", node->name);
-    assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, LYS_GETNEXT_WITHCASE));
-    assert_string_equal("seven", node->name);
-
-    assert_non_null(node = lys_getnext(NULL, NULL, mod->compiled, LYS_GETNEXT_INTONPCONT));
-    assert_string_equal("one", node->name);
-
-    assert_non_null(node = lys_getnext(NULL, (const struct lysc_node*)rpc, mod->compiled, LYS_GETNEXT_OUTPUT));
-    assert_string_equal("h-output", node->name);
-    assert_null(node = lys_getnext(node, (const struct lysc_node*)rpc, mod->compiled, LYS_GETNEXT_OUTPUT));
-
-    assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b; feature f;"
-                                        "leaf a {type string; if-feature f;}"
-                                        "leaf b {type string;}}", LYS_IN_YANG));
-    assert_non_null(node = lys_getnext(NULL, NULL, mod->compiled, 0));
-    assert_string_equal("b", node->name);
-    assert_non_null(node = lys_getnext(NULL, NULL, mod->compiled, LYS_GETNEXT_NOSTATECHECK));
-    assert_string_equal("a", node->name);
-
-    assert_non_null(mod = lys_parse_mem(ctx, "module c {namespace urn:c;prefix c; rpc c;}", LYS_IN_YANG));
-    assert_non_null(node = lys_getnext(NULL, NULL, mod->compiled, 0));
-    assert_string_equal("c", node->name);
-    assert_null(node = lys_getnext(node, NULL, mod->compiled, LYS_GETNEXT_NOSTATECHECK));
-
-    assert_non_null(mod = lys_parse_mem(ctx, "module d {namespace urn:d;prefix d; notification d;}", LYS_IN_YANG));
-    assert_non_null(node = lys_getnext(NULL, NULL, mod->compiled, 0));
-    assert_string_equal("d", node->name);
-    assert_null(node = lys_getnext(node, NULL, mod->compiled, LYS_GETNEXT_NOSTATECHECK));
-
-    *state = NULL;
-    ly_ctx_destroy(ctx, NULL);
-}
-
-int main(void)
-{
-    const struct CMUnitTest tests[] = {
-        cmocka_unit_test_setup_teardown(test_getnext, 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
deleted file mode 100644
index 01fe9f4..0000000
--- a/tests/src/test_tree_schema_helpers.c
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * @file set.c
- * @author: Radek Krejci <rkrejci@cesnet.cz>
- * @brief unit tests for functions from common.c
- *
- * Copyright (c) 2018 CESNET, z.s.p.o.
- *
- * This source code is licensed under BSD 3-Clause License (the "License").
- * You may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     https://opensource.org/licenses/BSD-3-Clause
- */
-
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <setjmp.h>
-#include <cmocka.h>
-
-#include <string.h>
-
-#include "../../src/common.h"
-#include "../../src/context.h"
-#include "../../src/tree_schema_internal.h"
-
-#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 */
-    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)
-{
-    (void) state; /* unused */
-
-    ly_set_log_clb(logger, 0);
-
-    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
-#   define logbuf_assert(str)
-#endif
-
-static void
-test_date(void **state)
-{
-    *state = test_date;
-
-    assert_int_equal(LY_EINVAL, lysp_check_date(NULL, NULL, 0, "date"));
-    logbuf_assert("Invalid argument date (lysp_check_date()).");
-    assert_int_equal(LY_EINVAL, lysp_check_date(NULL, "x", 1, "date"));
-    logbuf_assert("Invalid argument date_len (lysp_check_date()).");
-    assert_int_equal(LY_EINVAL, lysp_check_date(NULL, "nonsencexx", 10, "date"));
-    logbuf_assert("Invalid value \"nonsencexx\" of \"date\".");
-    assert_int_equal(LY_EINVAL, lysp_check_date(NULL, "123x-11-11", 10, "date"));
-    logbuf_assert("Invalid value \"123x-11-11\" of \"date\".");
-    assert_int_equal(LY_EINVAL, lysp_check_date(NULL, "2018-13-11", 10, "date"));
-    logbuf_assert("Invalid value \"2018-13-11\" of \"date\".");
-    assert_int_equal(LY_EINVAL, lysp_check_date(NULL, "2018-11-41", 10, "date"));
-    logbuf_assert("Invalid value \"2018-11-41\" of \"date\".");
-    assert_int_equal(LY_EINVAL, lysp_check_date(NULL, "2018-02-29", 10, "date"));
-    logbuf_assert("Invalid value \"2018-02-29\" of \"date\".");
-    assert_int_equal(LY_EINVAL, lysp_check_date(NULL, "2018.02-28", 10, "date"));
-    logbuf_assert("Invalid value \"2018.02-28\" of \"date\".");
-    assert_int_equal(LY_EINVAL, lysp_check_date(NULL, "2018-02.28", 10, "date"));
-    logbuf_assert("Invalid value \"2018-02.28\" of \"date\".");
-
-    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
-test_revisions(void **state)
-{
-    (void) state; /* unused */
-
-    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->date, "2018-01-01");
-    LY_ARRAY_NEW_RET(NULL, revs, rev,);
-    strcpy(rev->date, "2018-12-31");
-
-    assert_int_equal(2, LY_ARRAY_SIZE(revs));
-    assert_string_equal("2018-01-01", &revs[0]);
-    assert_string_equal("2018-12-31", &revs[1]);
-    /* the order should be fixed, so the newest revision will be the first in the array */
-    lysp_sort_revisions(revs);
-    assert_string_equal("2018-12-31", &revs[0]);
-    assert_string_equal("2018-01-01", &revs[1]);
-
-    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);
-}
-
-int main(void)
-{
-    const struct CMUnitTest tests[] = {
-        cmocka_unit_test_setup_teardown(test_date, logger_setup, logger_teardown),
-        cmocka_unit_test_setup_teardown(test_revisions, logger_setup, logger_teardown),
-        cmocka_unit_test_setup_teardown(test_typedef, logger_setup, logger_teardown),
-    };
-
-    return cmocka_run_group_tests(tests, NULL, NULL);
-}
diff --git a/tests/utests/CMakeLists.txt b/tests/utests/CMakeLists.txt
new file mode 100644
index 0000000..04af8d4
--- /dev/null
+++ b/tests/utests/CMakeLists.txt
@@ -0,0 +1,40 @@
+set(local_tests
+    utest:test_common
+    utest:test_set
+    utest:test_hash_table
+    utest:test_context
+    utest:test_xml
+    utest:schema/test_schema
+    utest:schema/test_parser_yang
+    utest:schema/test_parser_yin
+    utest:schema/test_tree_schema_compile
+    utest:schema/test_printer_yang
+    utest:schema/test_printer_yin
+    utest:data/test_tree_data
+    utest:data/test_parser_xml
+    utest:data/test_printer_xml
+    utest:data/test_validation
+    utest:data/test_types
+    utest:extensions/test_metadata
+    utest:extensions/test_nacm)
+set(local_tests_wraps
+    "-Wl,--wrap=realloc"
+    " "
+    " "
+    " "
+    " "
+    " "
+    " "
+    " "
+    " "
+    " "
+    " "
+    " "
+    " "
+    " "
+    " "
+    " "
+    " "
+    " ")
+set(tests ${tests} ${local_tests} PARENT_SCOPE)
+set(tests_wraps ${tests_wraps} ${local_tests_wraps} PARENT_SCOPE)
diff --git a/tests/src/test_parser_xml.c b/tests/utests/data/test_parser_xml.c
similarity index 100%
rename from tests/src/test_parser_xml.c
rename to tests/utests/data/test_parser_xml.c
diff --git a/tests/src/test_printer_xml.c b/tests/utests/data/test_printer_xml.c
similarity index 100%
rename from tests/src/test_printer_xml.c
rename to tests/utests/data/test_printer_xml.c
diff --git a/tests/src/test_tree_data.c b/tests/utests/data/test_tree_data.c
similarity index 100%
rename from tests/src/test_tree_data.c
rename to tests/utests/data/test_tree_data.c
diff --git a/tests/features/test_types.c b/tests/utests/data/test_types.c
similarity index 100%
rename from tests/features/test_types.c
rename to tests/utests/data/test_types.c
diff --git a/tests/src/test_validation.c b/tests/utests/data/test_validation.c
similarity index 100%
rename from tests/src/test_validation.c
rename to tests/utests/data/test_validation.c
diff --git a/tests/features/test_metadata.c b/tests/utests/extensions/test_metadata.c
similarity index 100%
rename from tests/features/test_metadata.c
rename to tests/utests/extensions/test_metadata.c
diff --git a/tests/features/test_nacm.c b/tests/utests/extensions/test_nacm.c
similarity index 100%
rename from tests/features/test_nacm.c
rename to tests/utests/extensions/test_nacm.c
diff --git a/tests/utests/schema/macros.h b/tests/utests/schema/macros.h
new file mode 100644
index 0000000..4a0424f
--- /dev/null
+++ b/tests/utests/schema/macros.h
@@ -0,0 +1,72 @@
+/*
+ * @file macros.h
+ * @author: Radek Krejci <rkrejci@cesnet.cz>
+ * @brief macros for schema tests
+ *
+ * Copyright (c) 2018-2020 CESNET, z.s.p.o.
+ *
+ * This source code is licensed under BSD 3-Clause License (the "License").
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://opensource.org/licenses/BSD-3-Clause
+ */
+#ifndef TESTS_UTESTS_SCHEMA_MACROS_H_
+#define TESTS_UTESTS_SCHEMA_MACROS_H_
+
+#define TEST_YANG_MODULE_10(MOD_NAME, MOD_PREFIX, MOD_NS, CONTENT) \
+    "module "MOD_NAME" { namespace "MOD_NS"; prefix "MOD_PREFIX"; "CONTENT"}"
+
+#define TEST_YANG_MODULE_11(MOD_NAME, MOD_PREFIX, MOD_NS, CONTENT) \
+    "module "MOD_NAME" {yang-version 1.1; namespace "MOD_NS"; prefix "MOD_PREFIX"; "CONTENT"}"
+
+#define TEST_YIN_MODULE_10(MOD_NAME, MOD_PREFIX, MOD_NS, CONTENT) \
+    "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" name=\""MOD_NAME"\">" \
+    "<namespace uri=\""MOD_NS"\"/><prefix value=\""MOD_PREFIX"\"/>"CONTENT"</module>"
+
+#define TEST_YIN_MODULE_11(MOD_NAME, MOD_PREFIX, MOD_NS, CONTENT) \
+    "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" name=\""MOD_NAME"\"><yang-version value=\"1.1\"/>" \
+    "<namespace uri=\""MOD_NS"\"/><prefix value=\""MOD_PREFIX"\"/>"CONTENT"</module>"
+
+#define TEST_SCHEMA_STR(CTX, RFC7950, YIN, MOD_NAME, CONTENT, STR) \
+    if (YIN) { \
+        if (RFC7950) { \
+            STR = TEST_YIN_MODULE_11(MOD_NAME, MOD_NAME, "urn:libyang:test:"MOD_NAME, CONTENT); \
+        } else { \
+            STR = TEST_YIN_MODULE_10(MOD_NAME, MOD_NAME, "urn:libyang:test:"MOD_NAME, CONTENT); \
+        } \
+    } else { /* YANG */ \
+        if (RFC7950) { \
+            STR = TEST_YANG_MODULE_11(MOD_NAME, MOD_NAME, "urn:libyang:test:"MOD_NAME, CONTENT); \
+        } else { \
+            STR = TEST_YANG_MODULE_10(MOD_NAME, MOD_NAME, "urn:libyang:test:"MOD_NAME, CONTENT); \
+        } \
+    }
+
+#define TEST_SCHEMA_OK(CTX, RFC7950, YIN, MOD_NAME, CONTENT, RESULT) \
+    { \
+    const char *test_str__; \
+    TEST_SCHEMA_STR(CTX, RFC7950, YIN, MOD_NAME, CONTENT, test_str__) \
+    assert_non_null(RESULT = lys_parse_mem(CTX, test_str__, YIN ? LYS_IN_YIN : LYS_IN_YANG)); \
+    }
+
+#define TEST_SCHEMA_ERR(CTX, RFC7950, YIN, MOD_NAME, CONTENT, ERRMSG) \
+    { \
+    const char *test_str__; \
+    TEST_SCHEMA_STR(CTX, RFC7950, YIN, MOD_NAME, CONTENT, test_str__) \
+    assert_null(lys_parse_mem(CTX, test_str__, YIN ? LYS_IN_YIN : LYS_IN_YANG)); \
+    logbuf_assert(ERRMSG); \
+    }
+
+#define TEST_STMT_DUP(CTX, RFC7950, YIN, STMT, MEMBER, VALUE1, VALUE2, LINE) \
+    if (YIN) { \
+        TEST_SCHEMA_ERR(CTX, RFC7950, YIN, "dup", "", "Duplicate keyword \""MEMBER"\". Line number "LINE"."); \
+    } else { \
+        TEST_SCHEMA_ERR(CTX, RFC7950, YIN, "dup", STMT"{"MEMBER" "VALUE1";"MEMBER" "VALUE2";}", \
+                        "Duplicate keyword \""MEMBER"\". Line number "LINE"."); \
+    }
+
+#define TEST_STMT_SUBSTM_ERR(CTX, RFC7950, STMT, SUBSTMT, VALUE); \
+        TEST_SCHEMA_ERR(CTX, RFC7950, 0, "inv", STMT" test {"SUBSTMT" "VALUE";}", "Invalid keyword \""SUBSTMT"\" as a child of \""STMT"\". Line number 1.");
+
+#endif /* TESTS_UTESTS_SCHEMA_MACROS_H_ */
diff --git a/tests/src/test_parser_yang.c b/tests/utests/schema/test_parser_yang.c
similarity index 95%
rename from tests/src/test_parser_yang.c
rename to tests/utests/schema/test_parser_yang.c
index 6342358..6311dfc 100644
--- a/tests/src/test_parser_yang.c
+++ b/tests/utests/schema/test_parser_yang.c
@@ -20,14 +20,12 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "../../src/common.h"
-#include "../../src/tree_schema.h"
-#include "../../src/tree_schema_internal.h"
+#include "../../../src/common.h"
+#include "../../../src/tree_schema.h"
+#include "../../../src/tree_schema_internal.h"
 
 /* originally static functions from tree_schema_free.c and parser_yang.c */
 void lysp_ext_instance_free(struct ly_ctx *ctx, struct lysp_ext_instance *ext);
-void lysp_ident_free(struct ly_ctx *ctx, struct lysp_ident *ident);
-void lysp_feature_free(struct ly_ctx *ctx, struct lysp_feature *feat);
 void lysp_deviation_free(struct ly_ctx *ctx, struct lysp_deviation *dev);
 void lysp_grp_free(struct ly_ctx *ctx, struct lysp_grp *grp);
 void lysp_action_free(struct ly_ctx *ctx, struct lysp_action *action);
@@ -52,10 +50,8 @@
 LY_ERR parse_container(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
 LY_ERR parse_deviate(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_deviate **deviates);
 LY_ERR parse_deviation(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_deviation **deviations);
-LY_ERR parse_feature(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_feature **features);
 LY_ERR parse_grouping(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_grp **groupings);
 LY_ERR parse_choice(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
-LY_ERR parse_identity(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_ident **identities);
 LY_ERR parse_leaf(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
 LY_ERR parse_leaflist(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
 LY_ERR parse_list(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
@@ -1180,97 +1176,24 @@
     *state = NULL;
 }
 
-static void
-test_identity(void **state)
-{
-    *state = test_identity;
 
-    struct lys_yang_parser_ctx ctx;
-    struct lysp_ident *ident = NULL;
-    const char *str;
 
-    ctx.format = LYS_IN_YANG;
-    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &ctx.ctx));
-    assert_non_null(ctx.ctx);
-    ctx.pos_type = LY_VLOG_LINE;
-    ctx.line = 1;
-    ctx.indent = 0;
-    ctx.mod_version = 2; /* simulate YANG 1.1 */
 
-    /* invalid cardinality */
-#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
-    TEST_DUP_GENERIC(" test {", MEMBER, VALUE1, VALUE2, parse_identity, \
-                     &ident, "1", FREE_ARRAY(ctx.ctx, ident, lysp_ident_free); ident = NULL)
 
-    TEST_DUP("description", "a", "b");
-    TEST_DUP("reference", "a", "b");
-    TEST_DUP("status", "current", "obsolete");
 
-    /* full content */
-    str = " test {base \"a\";base b; description text;reference \'another text\';status current; if-feature x;if-feature y;prefix:ext;} ...";
-    assert_int_equal(LY_SUCCESS, parse_identity(&ctx, &str, &ident));
-    assert_non_null(ident);
-    assert_string_equal(" ...", str);
-    FREE_ARRAY(ctx.ctx, ident, lysp_ident_free);
-    ident = NULL;
 
-    /* invalid substatement */
-    str = " test {organization XXX;}";
-    assert_int_equal(LY_EVALID, parse_identity(&ctx, &str, &ident));
-    logbuf_assert("Invalid keyword \"organization\" as a child of \"identity\". Line number 1.");
-    FREE_ARRAY(ctx.ctx, ident, lysp_ident_free);
-    ident = NULL;
 
-#undef TEST_DUP
 
-    *state = NULL;
-    ly_ctx_destroy(ctx.ctx, NULL);
-}
 
-static void
-test_feature(void **state)
-{
-    (void) state; /* unused */
 
-    struct lys_yang_parser_ctx ctx;
-    struct lysp_feature *features = NULL;
-    const char *str;
 
-    ctx.format = LYS_IN_YANG;
-    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &ctx.ctx));
-    assert_non_null(ctx.ctx);
-    ctx.pos_type = LY_VLOG_LINE;
-    ctx.line = 1;
-    ctx.indent = 0;
 
-    /* invalid cardinality */
-#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
-    TEST_DUP_GENERIC(" test {", MEMBER, VALUE1, VALUE2, parse_feature, \
-                     &features, "1", FREE_ARRAY(ctx.ctx, features, lysp_feature_free); features = NULL)
 
-    TEST_DUP("description", "a", "b");
-    TEST_DUP("reference", "a", "b");
-    TEST_DUP("status", "current", "obsolete");
 
-    /* full content */
-    str = " test {description text;reference \'another text\';status current; if-feature x;if-feature y;prefix:ext;} ...";
-    assert_int_equal(LY_SUCCESS, parse_feature(&ctx, &str, &features));
-    assert_non_null(features);
-    assert_string_equal(" ...", str);
-    FREE_ARRAY(ctx.ctx, features, lysp_feature_free);
-    features = NULL;
 
-    /* invalid substatement */
-    str = " test {organization XXX;}";
-    assert_int_equal(LY_EVALID, parse_feature(&ctx, &str, &features));
-    logbuf_assert("Invalid keyword \"organization\" as a child of \"feature\". Line number 1.");
-    FREE_ARRAY(ctx.ctx, features, lysp_feature_free);
-    features = NULL;
 
-#undef TEST_DUP
 
-    ly_ctx_destroy(ctx.ctx, NULL);
-}
+
 
 static void
 test_deviation(void **state)
@@ -2316,8 +2239,6 @@
         cmocka_unit_test_setup(test_stmts, logger_setup),
         cmocka_unit_test_setup_teardown(test_minmax, logger_setup, logger_teardown),
         cmocka_unit_test_setup_teardown(test_module, logger_setup, logger_teardown),
-        cmocka_unit_test_setup_teardown(test_identity, logger_setup, logger_teardown),
-        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),
diff --git a/tests/src/test_parser_yin.c b/tests/utests/schema/test_parser_yin.c
similarity index 96%
rename from tests/src/test_parser_yin.c
rename to tests/utests/schema/test_parser_yin.c
index ce5f0c8..ea22333 100644
--- a/tests/src/test_parser_yin.c
+++ b/tests/utests/schema/test_parser_yin.c
@@ -21,11 +21,11 @@
 #include <string.h>
 #include <stdbool.h>
 
-#include "../../src/common.h"
-#include "../../src/tree_schema.h"
-#include "../../src/tree_schema_internal.h"
-#include "../../src/parser_yin.h"
-#include "../../src/xml.h"
+#include "../../../src/common.h"
+#include "../../../src/tree_schema.h"
+#include "../../../src/tree_schema_internal.h"
+#include "../../../src/parser_yin.h"
+#include "../../../src/xml.h"
 
 /* prototypes of static functions */
 void lysp_ext_instance_free(struct ly_ctx *ctx, struct lysp_ext_instance *ext);
@@ -53,7 +53,7 @@
 #define ELEMENT_WRAPPER_START "<status xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">"
 #define ELEMENT_WRAPPER_END "</status>"
 
-struct state {
+struct test_parser_yin_state {
     struct ly_ctx *ctx;
     struct lys_module *mod;
     struct lysp_module *lysp_mod;
@@ -101,7 +101,7 @@
 int
 setup_ly_ctx(void **state)
 {
-    struct state *st = NULL;
+    struct test_parser_yin_state *st = NULL;
 
     /* allocate state variable */
     (*state) = st = calloc(1, sizeof(*st));
@@ -119,7 +119,7 @@
 int
 destroy_ly_ctx(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     ly_ctx_destroy(st->ctx, NULL);
     free(st);
 
@@ -129,7 +129,7 @@
 static int
 setup_f(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
 
 #if ENABLE_LOGGER_CHECKING
     /* setup logger */
@@ -155,7 +155,7 @@
 static int
 teardown_f(void **state)
 {
-    struct state *st = *(struct state **)state;
+    struct test_parser_yin_state *st = *(struct test_parser_yin_state **)state;
     struct lys_module *temp;
 
 #if ENABLE_LOGGER_CHECKING
@@ -176,10 +176,10 @@
     return EXIT_SUCCESS;
 }
 
-static struct state*
+static struct test_parser_yin_state*
 reset_state(void **state)
 {
-    ((struct state *)*state)->finished_correctly = true;
+    ((struct test_parser_yin_state *)*state)->finished_correctly = true;
     logbuf[0] = '\0';
     teardown_f(state);
     setup_f(state);
@@ -210,7 +210,7 @@
 static int
 teardown_logger(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
 
 #if ENABLE_LOGGER_CHECKING
     /* teardown logger */
@@ -226,7 +226,7 @@
 setup_element_test(void **state)
 {
     setup_logger(state);
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
 
     st->yin_ctx = calloc(1, sizeof(*st->yin_ctx));
     st->yin_ctx->format = LYS_IN_YIN;
@@ -237,7 +237,7 @@
 static int
 teardown_element_test(void **state)
 {
-    struct state *st = *(struct state **)state;
+    struct test_parser_yin_state *st = *(struct test_parser_yin_state **)state;
 
     lyxml_ctx_free(st->yin_ctx->xmlctx);
     free(st->yin_ctx);
@@ -250,7 +250,7 @@
 static void
 test_yin_match_keyword(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
 
     const char *prefix;
     size_t prefix_len;
@@ -356,7 +356,7 @@
 static void
 test_yin_parse_element_generic(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     struct lysp_ext_instance exts;
     LY_ERR ret;
 
@@ -394,7 +394,7 @@
 test_yin_parse_extension_instance(void **state)
 {
     LY_ERR ret;
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     struct lysp_ext_instance *exts = NULL;
     const char *data = "<myext:ext value1=\"test\" value=\"test2\" xmlns:myext=\"urn:example:extensions\"><myext:subelem>text</myext:subelem></myext:ext>";
     lyxml_ctx_new(st->ctx, data, &st->yin_ctx->xmlctx);
@@ -552,7 +552,7 @@
 static void
 test_yin_parse_content(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     LY_ERR ret = LY_SUCCESS;
     const char *data = "<prefix value=\"a_mod\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">"
                             "<myext:custom xmlns:myext=\"urn:example:extensions\">"
@@ -724,7 +724,7 @@
 static void
 test_validate_value(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data = ELEMENT_WRAPPER_START ELEMENT_WRAPPER_END;
 
     /* create some XML context */
@@ -755,7 +755,7 @@
 
 /* helper function to simplify unit test of each element using parse_content function */
 LY_ERR
-test_element_helper(struct state *st, const char *data, void *dest, const char **text, struct lysp_ext_instance **exts)
+test_element_helper(struct test_parser_yin_state *st, const char *data, void *dest, const char **text, struct lysp_ext_instance **exts)
 {
     const char *name, *prefix;
     size_t name_len, prefix_len;
@@ -853,7 +853,7 @@
 static void
 test_enum_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     struct lysp_type type = {};
     const char *data;
     data = ELEMENT_WRAPPER_START
@@ -893,7 +893,7 @@
 static void
 test_bit_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     struct lysp_type type = {};
     const char *data;
     data = ELEMENT_WRAPPER_START
@@ -933,7 +933,7 @@
 static void
 test_meta_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     char *value = NULL;
     const char *data;
     struct lysp_ext_instance *exts = NULL;
@@ -1032,7 +1032,7 @@
 static void
 test_import_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_import *imports = NULL;
     struct import_meta imp_meta = {"prefix", &imports};
@@ -1097,7 +1097,7 @@
 static void
 test_status_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     uint16_t flags = 0;
     struct lysp_ext_instance *exts = NULL;
@@ -1130,7 +1130,7 @@
 static void
 test_ext_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_ext *ext = NULL;
 
@@ -1171,7 +1171,7 @@
 static void
 test_yin_element_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     uint16_t flags = 0;
     struct lysp_ext_instance *exts = NULL;
@@ -1198,7 +1198,7 @@
 static void
 test_yangversion_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     uint8_t version = 0;
     struct lysp_ext_instance *exts = NULL;
@@ -1229,7 +1229,7 @@
 static void
 test_mandatory_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     uint16_t man = 0;
     struct lysp_ext_instance *exts = NULL;
@@ -1258,7 +1258,7 @@
 static void
 test_argument_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     uint16_t flags = 0;
     const char *arg;
@@ -1300,7 +1300,7 @@
 static void
 test_base_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     const char **bases = NULL;
     struct lysp_ext_instance *exts = NULL;
@@ -1345,7 +1345,7 @@
 static void
 test_belongsto_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_submodule submod;
     struct lysp_ext_instance *exts = NULL;
@@ -1375,7 +1375,7 @@
 static void
 test_config_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     uint16_t flags = 0;
     struct lysp_ext_instance *exts = NULL;
@@ -1405,7 +1405,7 @@
 static void
 test_default_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     const char *val = NULL;
     struct lysp_ext_instance *exts = NULL;
@@ -1431,7 +1431,7 @@
 static void
 test_err_app_tag_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     const char *val = NULL;
     struct lysp_ext_instance *exts = NULL;
@@ -1457,7 +1457,7 @@
 static void
 test_err_msg_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     const char *val = NULL;
     struct lysp_ext_instance *exts = NULL;
@@ -1486,7 +1486,7 @@
 static void
 test_fracdigits_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_type type = {};
 
@@ -1527,7 +1527,7 @@
 static void
 test_iffeature_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     const char **iffeatures = NULL;
     struct lysp_ext_instance *exts = NULL;
@@ -1556,7 +1556,7 @@
 static void
 test_length_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_type type = {};
 
@@ -1606,7 +1606,7 @@
 static void
 test_modifier_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     const char *pat = lydict_insert(st->ctx, "\006pattern", 8);
     struct lysp_ext_instance *exts = NULL;
@@ -1633,7 +1633,7 @@
 static void
 test_namespace_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     const char *ns;
     struct lysp_ext_instance *exts = NULL;
@@ -1658,7 +1658,7 @@
 static void
 test_path_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_type type = {};
 
@@ -1677,7 +1677,7 @@
 static void
 test_pattern_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_type type = {};
 
@@ -1718,7 +1718,7 @@
 static void
 test_value_position_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_type_enum en = {};
 
@@ -1804,7 +1804,7 @@
 static void
 test_prefix_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     const char *value = NULL;
     struct lysp_ext_instance *exts = NULL;
@@ -1830,7 +1830,7 @@
 static void
 test_range_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_type type = {};
 
@@ -1870,7 +1870,7 @@
 static void
 test_reqinstance_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_type type = {};
 
@@ -1901,7 +1901,7 @@
 static void
 test_revision_date_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     char rev[LY_REV_SIZE];
     struct lysp_ext_instance *exts = NULL;
@@ -1928,7 +1928,7 @@
 static void
 test_unique_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     const char **values = NULL;
     struct lysp_ext_instance *exts = NULL;
@@ -1957,7 +1957,7 @@
 static void
 test_units_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     const char *values = NULL;
     struct lysp_ext_instance *exts = NULL;
@@ -1984,7 +1984,7 @@
 static void
 test_when_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_when *when = NULL;
 
@@ -2019,7 +2019,7 @@
 static void
 test_yin_text_value_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     const char *val;
 
@@ -2044,7 +2044,7 @@
 static void
 test_type_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_type type = {};
 
@@ -2104,7 +2104,7 @@
 static void
 test_max_elems_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_node_list list = {};
     struct lysp_node_leaflist llist = {};
@@ -2164,7 +2164,7 @@
 static void
 test_min_elems_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_node_list list = {};
     struct lysp_node_leaflist llist = {};
@@ -2219,7 +2219,7 @@
 static void
 test_ordby_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     uint16_t flags = 0;
     struct lysp_ext_instance *exts = NULL;
@@ -2246,7 +2246,7 @@
 static void
 test_any_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_node *siblings = NULL;
     struct tree_node_meta node_meta = {.parent = NULL, .nodes = &siblings};
@@ -2335,7 +2335,7 @@
 static void
 test_leaf_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_node *siblings = NULL;
     struct tree_node_meta node_meta = {.parent = NULL, .nodes = &siblings};
@@ -2396,7 +2396,7 @@
 static void
 test_leaf_list_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_node *siblings = NULL;
     struct tree_node_meta node_meta = {.parent = NULL, .nodes = &siblings};
@@ -2573,7 +2573,7 @@
 static void
 test_presence_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     const char *val;
     struct lysp_ext_instance *exts = NULL;
@@ -2602,7 +2602,7 @@
 static void
 test_key_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     const char *val;
     struct lysp_ext_instance *exts = NULL;
@@ -2631,7 +2631,7 @@
 static void
 test_typedef_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_tpdf *tpdfs = NULL;
     struct tree_node_meta typdef_meta = {NULL, (struct lysp_node **)&tpdfs};
@@ -2678,7 +2678,7 @@
 static void
 test_refine_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_refine *refines = NULL;
 
@@ -2729,7 +2729,7 @@
 static void
 test_uses_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_node *siblings = NULL;
     struct tree_node_meta node_meta = {NULL, &siblings};
@@ -2780,7 +2780,7 @@
 static void
 test_revision_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_revision *revs = NULL;
 
@@ -2822,7 +2822,7 @@
 static void
 test_include_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_include *includes = NULL;
     struct include_meta inc_meta = {"module-name", &includes};
@@ -2884,102 +2884,9 @@
 }
 
 static void
-test_feature_elem(void **state)
-{
-    struct state *st = *state;
-    const char *data;
-    struct lysp_feature *features = NULL;
-
-    /* max subelems */
-    data = ELEMENT_WRAPPER_START
-                "<feature name=\"feature-name\">"
-                    "<if-feature name=\"iff\"/>"
-                    "<status value=\"deprecated\"/>"
-                    "<description><text>desc</text></description>"
-                    "<reference><text>ref</text></reference>"
-                    EXT_SUBELEM
-                "</feature>"
-           ELEMENT_WRAPPER_END;
-    assert_int_equal(test_element_helper(st, data, &features, NULL, NULL), LY_SUCCESS);
-    assert_string_equal(features->name, "feature-name");
-    assert_string_equal(features->dsc, "desc");
-    assert_true(features->flags & LYS_STATUS_DEPRC);
-    assert_string_equal(*features->iffeatures, "iff");
-    assert_string_equal(features->ref, "ref");
-    assert_string_equal(features->exts[0].name, "urn:example:extensions:c-define");
-    assert_int_equal(features->exts[0].insubstmt_index, 0);
-    assert_int_equal(features->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
-    FREE_ARRAY(st->ctx, features, lysp_feature_free);
-    features = NULL;
-
-    /* min subelems */
-    data = ELEMENT_WRAPPER_START "<feature name=\"feature-name\"/>" ELEMENT_WRAPPER_END;
-    assert_int_equal(test_element_helper(st, data, &features, NULL, NULL), LY_SUCCESS);
-    assert_string_equal(features->name, "feature-name");
-    FREE_ARRAY(st->ctx, features, lysp_feature_free);
-    features = NULL;
-
-    st->finished_correctly = true;
-}
-
-static void
-test_identity_elem(void **state)
-{
-    struct state *st = *state;
-    const char *data;
-    struct lysp_ident *identities = NULL;
-
-    /* max subelems */
-    st->yin_ctx->mod_version = LYS_VERSION_1_1;
-    data = ELEMENT_WRAPPER_START
-                "<identity name=\"ident-name\">"
-                    "<if-feature name=\"iff\"/>"
-                    "<base name=\"base-name\"/>"
-                    "<status value=\"deprecated\"/>"
-                    "<description><text>desc</text></description>"
-                    "<reference><text>ref</text></reference>"
-                    EXT_SUBELEM
-                "</identity>"
-           ELEMENT_WRAPPER_END;
-    assert_int_equal(test_element_helper(st, data, &identities, NULL, NULL), LY_SUCCESS);
-    assert_string_equal(identities->name, "ident-name");
-    assert_string_equal(*identities->bases, "base-name");
-    assert_string_equal(*identities->iffeatures, "iff");
-    assert_string_equal(identities->dsc, "desc");
-    assert_string_equal(identities->ref, "ref");
-    assert_true(identities->flags & LYS_STATUS_DEPRC);
-    assert_string_equal(identities->exts[0].name, "urn:example:extensions:c-define");
-    assert_int_equal(identities->exts[0].insubstmt_index, 0);
-    assert_int_equal(identities->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
-    FREE_ARRAY(st->ctx, identities, lysp_ident_free);
-    identities = NULL;
-
-    /* min subelems */
-    data = ELEMENT_WRAPPER_START "<identity name=\"ident-name\" />" ELEMENT_WRAPPER_END;
-    assert_int_equal(test_element_helper(st, data, &identities, NULL, NULL), LY_SUCCESS);
-    assert_string_equal(identities->name, "ident-name");
-    FREE_ARRAY(st->ctx, identities, lysp_ident_free);
-    identities = NULL;
-
-    /* invalid */
-    st->yin_ctx->mod_version = LYS_VERSION_1_0;
-    data = ELEMENT_WRAPPER_START
-                "<identity name=\"ident-name\">"
-                    "<if-feature name=\"iff\"/>"
-                "</identity>"
-           ELEMENT_WRAPPER_END;
-    assert_int_equal(test_element_helper(st, data, &identities, NULL, NULL), LY_EVALID);
-    logbuf_assert("Invalid sub-elemnt \"if-feature\" of \"identity\" element - this sub-element is allowed only in modules with version 1.1 or newer. Line number 1.");
-    FREE_ARRAY(st->ctx, identities, lysp_ident_free);
-    identities = NULL;
-
-    st->finished_correctly = true;
-}
-
-static void
 test_list_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_node *siblings = NULL;
     struct tree_node_meta node_meta = {NULL, &siblings};
@@ -3074,7 +2981,7 @@
 static void
 test_notification_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_notif *notifs = NULL;
     struct tree_node_meta notif_meta = {NULL, (struct lysp_node **)&notifs};
@@ -3148,7 +3055,7 @@
 static void
 test_grouping_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_grp *grps = NULL;
     struct tree_node_meta grp_meta = {NULL, (struct lysp_node **)&grps};
@@ -3215,7 +3122,7 @@
 static void
 test_container_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_node *siblings = NULL;
     struct tree_node_meta node_meta = {NULL, &siblings};
@@ -3304,7 +3211,7 @@
 static void
 test_case_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_node *siblings = NULL;
     struct tree_node_meta node_meta = {NULL, &siblings};
@@ -3378,7 +3285,7 @@
 static void
 test_choice_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_node *siblings = NULL;
     struct tree_node_meta node_meta = {NULL, &siblings};
@@ -3455,7 +3362,7 @@
 static void
 test_inout_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_action_inout inout = {};
     struct inout_meta inout_meta = {NULL, &inout};
@@ -3577,7 +3484,7 @@
 static void
 test_action_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_action *actions = NULL;
     struct tree_node_meta act_meta = {NULL, (struct lysp_node **)&actions};
@@ -3663,7 +3570,7 @@
 static void
 test_augment_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_augment *augments = NULL;
     struct tree_node_meta aug_meta = {NULL, (struct lysp_node **)&augments};
@@ -3738,7 +3645,7 @@
 static void
 test_deviate_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_deviate *deviates = NULL;
     struct lysp_deviate_add *d_add;
@@ -3908,7 +3815,7 @@
 static void
 test_deviation_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_deviation *deviations = NULL;
 
@@ -3957,7 +3864,7 @@
 static void
 test_module_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lys_module *lys_mod = NULL;
     struct lysp_module *lysp_mod = NULL;
@@ -4085,7 +3992,7 @@
 static void
 test_submodule_elem(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lysp_submodule *lysp_submod = NULL;
 
@@ -4199,7 +4106,7 @@
 static void
 test_yin_parse_module(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lys_module *mod;
     struct lys_yin_parser_ctx *yin_ctx = NULL;
@@ -4315,7 +4222,7 @@
 static void
 test_yin_parse_submodule(void **state)
 {
-    struct state *st = *state;
+    struct test_parser_yin_state *st = *state;
     const char *data;
     struct lys_yin_parser_ctx *yin_ctx = NULL;
     struct lysp_submodule *submod = NULL;
@@ -4455,8 +4362,6 @@
         cmocka_unit_test_setup_teardown(test_uses_elem, setup_element_test, teardown_element_test),
         cmocka_unit_test_setup_teardown(test_revision_elem, setup_element_test, teardown_element_test),
         cmocka_unit_test_setup_teardown(test_include_elem, setup_element_test, teardown_element_test),
-        cmocka_unit_test_setup_teardown(test_feature_elem, setup_element_test, teardown_element_test),
-        cmocka_unit_test_setup_teardown(test_identity_elem, setup_element_test, teardown_element_test),
         cmocka_unit_test_setup_teardown(test_list_elem, setup_element_test, teardown_element_test),
         cmocka_unit_test_setup_teardown(test_notification_elem, setup_element_test, teardown_element_test),
         cmocka_unit_test_setup_teardown(test_grouping_elem, setup_element_test, teardown_element_test),
diff --git a/tests/src/test_printer_yang.c b/tests/utests/schema/test_printer_yang.c
similarity index 100%
rename from tests/src/test_printer_yang.c
rename to tests/utests/schema/test_printer_yang.c
diff --git a/tests/src/test_printer_yin.c b/tests/utests/schema/test_printer_yin.c
similarity index 100%
rename from tests/src/test_printer_yin.c
rename to tests/utests/schema/test_printer_yin.c
diff --git a/tests/utests/schema/test_schema.c b/tests/utests/schema/test_schema.c
new file mode 100644
index 0000000..b330a7d
--- /dev/null
+++ b/tests/utests/schema/test_schema.c
@@ -0,0 +1,112 @@
+/*
+ * @file test_schema.c
+ * @author: Radek Krejci <rkrejci@cesnet.cz>
+ * @brief unit tests for schema related functions
+ *
+ * Copyright (c) 2018-2019 CESNET, z.s.p.o.
+ *
+ * This source code is licensed under BSD 3-Clause License (the "License").
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://opensource.org/licenses/BSD-3-Clause
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include "../../../src/common.h"
+#include "../../../src/context.h"
+#include "../../../src/tree_schema.h"
+#include "../../../src/tree_schema_internal.h"
+#include "../../../src/parser_yin.h"
+#include "../../../src/xml.h"
+
+
+#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 */
+    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)
+{
+    (void) state; /* unused */
+
+#if ENABLE_LOGGER_CHECKING
+    /* setup logger */
+    ly_set_log_clb(logger, 1);
+#endif
+
+    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
+#   define logbuf_assert(str)
+#endif
+
+/**
+ * INCLUDE OTHER SCHEMA TESTS
+ */
+#include "test_schema_common.c"
+#include "test_schema_stmts.c"
+
+int main(void)
+{
+    const struct CMUnitTest tests[] = {
+        /** test_schema_common.c */
+        cmocka_unit_test_setup_teardown(test_getnext, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_date, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_revisions, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_typedef, logger_setup, logger_teardown),
+
+        /** test_schema_stmts.c */
+        cmocka_unit_test_setup_teardown(test_identity, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_feature, logger_setup, logger_teardown),
+    };
+
+    return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/tests/utests/schema/test_schema_common.c b/tests/utests/schema/test_schema_common.c
new file mode 100644
index 0000000..9b2bc6b
--- /dev/null
+++ b/tests/utests/schema/test_schema_common.c
@@ -0,0 +1,319 @@
+/*
+ * @file set.c
+ * @author: Radek Krejci <rkrejci@cesnet.cz>
+ * @brief unit tests for functions from common.c
+ *
+ * Copyright (c) 2018 CESNET, z.s.p.o.
+ *
+ * This source code is licensed under BSD 3-Clause License (the "License").
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://opensource.org/licenses/BSD-3-Clause
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include <string.h>
+
+static void
+test_getnext(void **state)
+{
+    *state = test_getnext;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    const struct lysc_node *node = NULL, *four;
+    const struct lysc_node_container *cont;
+    const struct lysc_action *rpc;
+
+    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;"
+                                        "container a { container one {presence test;} leaf two {type string;} leaf-list three {type string;}"
+                                        "  list four {config false;} choice x { leaf five {type string;} case y {leaf six {type string;}}}"
+                                        "  anyxml seven; action eight {input {leaf eight-input {type string;}} output {leaf eight-output {type string;}}}"
+                                        "  notification nine {leaf nine-data {type string;}}}"
+                                        "leaf b {type string;} leaf-list c {type string;} list d {config false;}"
+                                        "choice x { leaf e {type string;} case y {leaf f {type string;}}} anyxml g;"
+                                        "rpc h {input {leaf h-input {type string;}} output {leaf h-output {type string;}}}"
+                                        "rpc i;"
+                                        "notification j {leaf i-data {type string;}}"
+                                        "notification k;}", LYS_IN_YANG));
+    assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
+    assert_string_equal("a", node->name);
+    cont = (const struct lysc_node_container*)node;
+    assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
+    assert_string_equal("b", node->name);
+    assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
+    assert_string_equal("c", node->name);
+    assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
+    assert_string_equal("d", node->name);
+    assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
+    assert_string_equal("e", node->name);
+    assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
+    assert_string_equal("f", node->name);
+    assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
+    assert_string_equal("g", node->name);
+    assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
+    assert_string_equal("h", node->name);
+    rpc = (const struct lysc_action*)node;
+    assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
+    assert_string_equal("i", node->name);
+    assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
+    assert_string_equal("j", node->name);
+    assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
+    assert_string_equal("k", node->name);
+    assert_null(node = lys_getnext(node, NULL, mod->compiled, 0));
+    /* Inside container */
+    assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, 0));
+    assert_string_equal("one", node->name);
+    assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, 0));
+    assert_string_equal("two", node->name);
+    assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, 0));
+    assert_string_equal("three", node->name);
+    assert_non_null(node = four = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, 0));
+    assert_string_equal("four", node->name);
+    assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, 0));
+    assert_string_equal("five", node->name);
+    assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, 0));
+    assert_string_equal("six", node->name);
+    assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, 0));
+    assert_string_equal("seven", node->name);
+    assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, 0));
+    assert_string_equal("eight", node->name);
+    assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, 0));
+    assert_string_equal("nine", node->name);
+    assert_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, 0));
+    /* Inside RPC */
+    assert_non_null(node = lys_getnext(node, (const struct lysc_node*)rpc, mod->compiled, 0));
+    assert_string_equal("h-input", node->name);
+    assert_null(node = lys_getnext(node, (const struct lysc_node*)rpc, mod->compiled, 0));
+
+    /* options */
+    assert_non_null(node = lys_getnext(four, (const struct lysc_node*)cont, mod->compiled, LYS_GETNEXT_WITHCHOICE));
+    assert_string_equal("x", node->name);
+    assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, LYS_GETNEXT_WITHCHOICE));
+    assert_string_equal("seven", node->name);
+
+    assert_non_null(node = lys_getnext(four, (const struct lysc_node*)cont, mod->compiled, LYS_GETNEXT_NOCHOICE));
+    assert_string_equal("seven", node->name);
+
+    assert_non_null(node = lys_getnext(four, (const struct lysc_node*)cont, mod->compiled, LYS_GETNEXT_WITHCASE));
+    assert_string_equal("five", node->name);
+    assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, LYS_GETNEXT_WITHCASE));
+    assert_string_equal("y", node->name);
+    assert_non_null(node = lys_getnext(node, (const struct lysc_node*)cont, mod->compiled, LYS_GETNEXT_WITHCASE));
+    assert_string_equal("seven", node->name);
+
+    assert_non_null(node = lys_getnext(NULL, NULL, mod->compiled, LYS_GETNEXT_INTONPCONT));
+    assert_string_equal("one", node->name);
+
+    assert_non_null(node = lys_getnext(NULL, (const struct lysc_node*)rpc, mod->compiled, LYS_GETNEXT_OUTPUT));
+    assert_string_equal("h-output", node->name);
+    assert_null(node = lys_getnext(node, (const struct lysc_node*)rpc, mod->compiled, LYS_GETNEXT_OUTPUT));
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b; feature f;"
+                                        "leaf a {type string; if-feature f;}"
+                                        "leaf b {type string;}}", LYS_IN_YANG));
+    assert_non_null(node = lys_getnext(NULL, NULL, mod->compiled, 0));
+    assert_string_equal("b", node->name);
+    assert_non_null(node = lys_getnext(NULL, NULL, mod->compiled, LYS_GETNEXT_NOSTATECHECK));
+    assert_string_equal("a", node->name);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module c {namespace urn:c;prefix c; rpc c;}", LYS_IN_YANG));
+    assert_non_null(node = lys_getnext(NULL, NULL, mod->compiled, 0));
+    assert_string_equal("c", node->name);
+    assert_null(node = lys_getnext(node, NULL, mod->compiled, LYS_GETNEXT_NOSTATECHECK));
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module d {namespace urn:d;prefix d; notification d;}", LYS_IN_YANG));
+    assert_non_null(node = lys_getnext(NULL, NULL, mod->compiled, 0));
+    assert_string_equal("d", node->name);
+    assert_null(node = lys_getnext(node, NULL, mod->compiled, LYS_GETNEXT_NOSTATECHECK));
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+static void
+test_date(void **state)
+{
+    *state = test_date;
+
+    assert_int_equal(LY_EINVAL, lysp_check_date(NULL, NULL, 0, "date"));
+    logbuf_assert("Invalid argument date (lysp_check_date()).");
+    assert_int_equal(LY_EINVAL, lysp_check_date(NULL, "x", 1, "date"));
+    logbuf_assert("Invalid argument date_len (lysp_check_date()).");
+    assert_int_equal(LY_EINVAL, lysp_check_date(NULL, "nonsencexx", 10, "date"));
+    logbuf_assert("Invalid value \"nonsencexx\" of \"date\".");
+    assert_int_equal(LY_EINVAL, lysp_check_date(NULL, "123x-11-11", 10, "date"));
+    logbuf_assert("Invalid value \"123x-11-11\" of \"date\".");
+    assert_int_equal(LY_EINVAL, lysp_check_date(NULL, "2018-13-11", 10, "date"));
+    logbuf_assert("Invalid value \"2018-13-11\" of \"date\".");
+    assert_int_equal(LY_EINVAL, lysp_check_date(NULL, "2018-11-41", 10, "date"));
+    logbuf_assert("Invalid value \"2018-11-41\" of \"date\".");
+    assert_int_equal(LY_EINVAL, lysp_check_date(NULL, "2018-02-29", 10, "date"));
+    logbuf_assert("Invalid value \"2018-02-29\" of \"date\".");
+    assert_int_equal(LY_EINVAL, lysp_check_date(NULL, "2018.02-28", 10, "date"));
+    logbuf_assert("Invalid value \"2018.02-28\" of \"date\".");
+    assert_int_equal(LY_EINVAL, lysp_check_date(NULL, "2018-02.28", 10, "date"));
+    logbuf_assert("Invalid value \"2018-02.28\" of \"date\".");
+
+    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
+test_revisions(void **state)
+{
+    (void) state; /* unused */
+
+    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->date, "2018-01-01");
+    LY_ARRAY_NEW_RET(NULL, revs, rev,);
+    strcpy(rev->date, "2018-12-31");
+
+    assert_int_equal(2, LY_ARRAY_SIZE(revs));
+    assert_string_equal("2018-01-01", &revs[0]);
+    assert_string_equal("2018-12-31", &revs[1]);
+    /* the order should be fixed, so the newest revision will be the first in the array */
+    lysp_sort_revisions(revs);
+    assert_string_equal("2018-12-31", &revs[0]);
+    assert_string_equal("2018-01-01", &revs[1]);
+
+    LY_ARRAY_FREE(revs);
+}
+
+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. Line number 1.");
+    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. Line number 1.");
+    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. Line number 1.");
+    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. Line number 1.");
+    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. Line number 1.");
+    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. Line number 1.");
+    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. Line number 1.");
+    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. Line number 1.");
+    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. Line number 1.");
+    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. Line number 1.");
+    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. Line number 1.");
+    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. Line number 1.");
+    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. Line number 1.");
+    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. Line number 1.");
+    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. Line number 1.");
+    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. Line number 1.");
+    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. Line number 1.");
+    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. Line number 1.");
+    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. Line number 1.");
+
+    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. Line number 1.");
+
+    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. Line number 1.");
+
+    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. Line number 1.");
+
+    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. Line number 1.");
+
+    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. Line number 1.");
+
+    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. Line number 1.");
+
+    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. Line number 1.");
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
diff --git a/tests/utests/schema/test_schema_stmts.c b/tests/utests/schema/test_schema_stmts.c
new file mode 100644
index 0000000..35ce06a
--- /dev/null
+++ b/tests/utests/schema/test_schema_stmts.c
@@ -0,0 +1,359 @@
+/*
+ * @file test_schema_stmts.c
+ * @author: Radek Krejci <rkrejci@cesnet.cz>
+ * @brief unit tests for YANG (YIN) statements in (sub)modules
+ *
+ * Copyright (c) 2018-2020 CESNET, z.s.p.o.
+ *
+ * This source code is licensed under BSD 3-Clause License (the "License").
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://opensource.org/licenses/BSD-3-Clause
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include <string.h>
+
+#include "macros.h"
+
+
+static void
+test_identity(void **state)
+{
+    *state = test_identity;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod, *mod_imp;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &ctx));
+
+    /*
+     * parsing YANG
+     */
+    TEST_STMT_DUP(ctx, 1, 0, "identity id", "description", "a", "b", "1");
+    TEST_STMT_DUP(ctx, 1, 0, "identity id", "reference", "a", "b", "1");
+    TEST_STMT_DUP(ctx, 1, 0, "identity id", "status", "current", "obsolete", "1");
+
+    /* full content */
+    TEST_SCHEMA_OK(ctx, 1, 0, "identityone",
+                   "identity test {base \"a\";base b; description text;reference \'another text\';status current; if-feature x;if-feature y; identityone:ext;}"
+                   "identity a; identity b; extension ext; feature x; feature y;", mod);
+    assert_non_null(mod->parsed->identities);
+    assert_int_equal(3, LY_ARRAY_SIZE(mod->parsed->identities));
+
+    /* invalid substatement */
+    TEST_STMT_SUBSTM_ERR(ctx, 0, "identity", "organization", "XXX");
+
+    /*
+     * parsing YIN
+     */
+    /* max subelems */
+    TEST_SCHEMA_OK(ctx, 1, 1, "identityone-yin", "<identity name=\"ident-name\">"
+                       "<if-feature name=\"iff\"/>"
+                       "<base name=\"base-name\"/>"
+                       "<status value=\"deprecated\"/>"
+                       "<description><text>desc</text></description>"
+                       "<reference><text>ref</text></reference>"
+                       "<myext:ext xmlns:myext=\"urn:libyang:test:identityone-yin\"/>"
+                   "</identity><extension name=\"ext\"/><identity name=\"base-name\"/><feature name=\"iff\"/>", mod);
+    assert_int_equal(2, LY_ARRAY_SIZE(mod->parsed->identities));
+    assert_string_equal(mod->parsed->identities[0].name, "ident-name");
+    assert_string_equal(mod->parsed->identities[0].bases[0], "base-name");
+    assert_string_equal(mod->parsed->identities[0].iffeatures[0], "iff");
+    assert_string_equal(mod->parsed->identities[0].dsc, "desc");
+    assert_string_equal(mod->parsed->identities[0].ref, "ref");
+    assert_true(mod->parsed->identities[0].flags & LYS_STATUS_DEPRC);
+    assert_string_equal(mod->parsed->identities[0].exts[0].name, "ext");
+    assert_non_null(mod->parsed->identities[0].exts[0].compiled);
+    assert_int_equal(mod->parsed->identities[0].exts[0].yin, 1);
+    assert_int_equal(mod->parsed->identities[0].exts[0].insubstmt_index, 0);
+    assert_int_equal(mod->parsed->identities[0].exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+
+    /* min subelems */
+    TEST_SCHEMA_OK(ctx, 1, 1, "identitytwo-yin", "<identity name=\"ident-name\" />", mod);
+    assert_int_equal(1, LY_ARRAY_SIZE(mod->parsed->identities));
+    assert_string_equal(mod->parsed->identities[0].name, "ident-name");
+
+    /* invalid substatement */
+    TEST_SCHEMA_ERR(ctx, 0, 1, "inv", "<identity name=\"ident-name\"><if-feature name=\"iff\"/></identity>",
+                    "Invalid sub-elemnt \"if-feature\" of \"identity\" element - this sub-element is allowed only in modules with version 1.1 or newer. Line number 1.");
+
+    /*
+     * compiling
+     */
+    TEST_SCHEMA_OK(ctx, 0, 0, "a", "identity a1;", mod_imp);
+    TEST_SCHEMA_OK(ctx, 1, 0, "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;}", mod);
+    assert_non_null(mod_imp->compiled);
+    assert_non_null(mod_imp->compiled->identities);
+    assert_non_null(mod->compiled);
+    assert_non_null(mod->compiled->identities);
+    assert_non_null(mod_imp->compiled->identities[0].derived);
+    assert_int_equal(1, LY_ARRAY_SIZE(mod_imp->compiled->identities[0].derived));
+    assert_ptr_equal(mod_imp->compiled->identities[0].derived[0], &mod->compiled->identities[2]);
+    assert_non_null(mod->compiled->identities[0].derived);
+    assert_int_equal(2, LY_ARRAY_SIZE(mod->compiled->identities[0].derived));
+    assert_ptr_equal(mod->compiled->identities[0].derived[0], &mod->compiled->identities[2]);
+    assert_ptr_equal(mod->compiled->identities[0].derived[1], &mod->compiled->identities[3]);
+    assert_non_null(mod->compiled->identities[1].derived);
+    assert_int_equal(1, LY_ARRAY_SIZE(mod->compiled->identities[1].derived));
+    assert_ptr_equal(mod->compiled->identities[1].derived[0], &mod->compiled->identities[2]);
+    assert_non_null(mod->compiled->identities[2].derived);
+    assert_int_equal(1, LY_ARRAY_SIZE(mod->compiled->identities[2].derived));
+    assert_ptr_equal(mod->compiled->identities[2].derived[0], &mod->compiled->identities[3]);
+
+    TEST_SCHEMA_OK(ctx, 1, 0, "c", "identity c2 {base c1;} identity c1;", mod);
+    assert_int_equal(1, LY_ARRAY_SIZE(mod->compiled->identities[1].derived));
+    assert_ptr_equal(mod->compiled->identities[1].derived[0], &mod->compiled->identities[0]);
+
+    TEST_SCHEMA_ERR(ctx, 0, 0, "inv", "identity i1;identity i1;", "Duplicate identifier \"i1\" of identity statement. /inv:{identity='i1'}");
+
+    ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule inv_sub {belongs-to inv {prefix inv;} identity i1;}");
+    TEST_SCHEMA_ERR(ctx, 0, 0, "inv", "include inv_sub;identity i1;",
+                    "Duplicate identifier \"i1\" of identity statement. /inv:{identity='i1'}");
+    TEST_SCHEMA_ERR(ctx, 0, 0,"inv", "identity i1 {base i2;}", "Unable to find base (i2) of identity \"i1\". /inv:{identity='i1'}");
+    TEST_SCHEMA_ERR(ctx, 0, 0,"inv", "identity i1 {base i1;}", "Identity \"i1\" is derived from itself. /inv:{identity='i1'}");
+    TEST_SCHEMA_ERR(ctx, 0, 0,"inv", "identity i1 {base i2;}identity i2 {base i3;}identity i3 {base i1;}",
+                    "Identity \"i1\" is indirectly derived from itself. /inv:{identity='i3'}");
+
+    /*
+     * printing
+     */
+
+    /*
+     * cleanup
+     */
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+
+static void
+test_feature(void **state)
+{
+    *state = test_feature;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    const struct lysc_feature *f, *f1;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &ctx));
+
+    /*
+     * parsing YANG
+     */
+
+    TEST_STMT_DUP(ctx, 1, 0, "feature f", "description", "a", "b", "1");
+    TEST_STMT_DUP(ctx, 1, 0, "feature f", "reference", "a", "b", "1");
+    TEST_STMT_DUP(ctx, 1, 0, "feature f", "status", "current", "obsolete", "1");
+
+    /* full content */
+    TEST_SCHEMA_OK(ctx, 1, 0, "featureone",
+                   "feature test {description text;reference \'another text\';status current; if-feature x; if-feature y; featureone:ext;}"
+                   "extension ext; feature x; feature y;", mod);
+    assert_non_null(mod->parsed->features);
+    assert_int_equal(3, LY_ARRAY_SIZE(mod->parsed->features));
+
+    /* invalid substatement */
+    TEST_STMT_SUBSTM_ERR(ctx, 0, "feature", "organization", "XXX");
+
+    /*
+     * parsing YIN
+     */
+    /* max subelems */
+    TEST_SCHEMA_OK(ctx, 0, 1, "featureone-yin", "<feature name=\"feature-name\">"
+                       "<if-feature name=\"iff\"/>"
+                       "<status value=\"deprecated\"/>"
+                       "<description><text>desc</text></description>"
+                       "<reference><text>ref</text></reference>"
+                       "<myext:ext xmlns:myext=\"urn:libyang:test:featureone-yin\"/>"
+                   "</feature><extension name=\"ext\"/><feature name=\"iff\"/>", mod);
+    assert_int_equal(2, LY_ARRAY_SIZE(mod->parsed->features));
+    assert_string_equal(mod->parsed->features[0].name, "feature-name");
+    assert_string_equal(mod->parsed->features[0].dsc, "desc");
+    assert_true(mod->parsed->features[0].flags & LYS_STATUS_DEPRC);
+    assert_string_equal(mod->parsed->features[0].iffeatures[0], "iff");
+    assert_string_equal(mod->parsed->features[0].ref, "ref");
+    assert_string_equal(mod->parsed->features[0].exts[0].name, "ext");
+    assert_int_equal(mod->parsed->features[0].exts[0].insubstmt_index, 0);
+    assert_int_equal(mod->parsed->features[0].exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+
+    /* min subelems */
+    TEST_SCHEMA_OK(ctx, 0, 1, "featuretwo-yin", "<feature name=\"feature-name\"/>", mod)
+    assert_int_equal(1, LY_ARRAY_SIZE(mod->parsed->features));
+    assert_string_equal(mod->parsed->features[0].name, "feature-name");
+
+    /* invalid substatement */
+    TEST_SCHEMA_ERR(ctx, 0, 1, "inv", "<feature name=\"feature-name\"><organization><text>org</text></organization></feature>",
+                    "Unexpected sub-element \"organization\" of \"feature\" element. Line number 1.");
+
+    /*
+     * compiling
+     */
+
+    TEST_SCHEMA_OK(ctx, 1, 0, "a", "feature f1 {description test1;reference test2;status current;} feature f2; feature f3;\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)\";}\n"
+                   "feature f8 {if-feature \"f1 or f2 or f3 or orfeature or andfeature\";}\n"
+                   "feature f9 {if-feature \"not not f1\";}", mod);
+    assert_non_null(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));
+    }
+    /* enable f1 */
+    assert_int_equal(LY_SUCCESS, lys_feature_enable(mod, "f1"));
+    f1 = &mod->compiled->features[0];
+    assert_int_equal(1, lysc_feature_value(f1));
+
+    /* enable orfeature */
+    f = &mod->compiled->features[3];
+    assert_int_equal(0, lysc_feature_value(f));
+    assert_int_equal(LY_SUCCESS, lys_feature_enable(mod, "orfeature"));
+    assert_int_equal(1, lysc_feature_value(f));
+
+    /* 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, "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, "andfeature"));
+    assert_int_equal(1, lysc_feature_value(f));
+
+    /* f1 is enabled, so f6 cannot be enabled */
+    f = &mod->compiled->features[5];
+    assert_int_equal(0, lysc_feature_value(f));
+    assert_int_equal(LY_EDENIED, lys_feature_enable(mod, "f6"));
+    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 - 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 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"));
+    assert_int_equal(1, lysc_feature_value(&mod->compiled->features[5]));
+
+    /* 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"));
+
+    TEST_SCHEMA_OK(ctx, 0, 0, "b", "feature f1 {if-feature f2;}feature f2;", mod);
+    assert_non_null(mod->compiled);
+    assert_non_null(mod->compiled->features);
+    assert_int_equal(2, LY_ARRAY_SIZE(mod->compiled->features));
+    assert_non_null(mod->compiled->features[0].iffeatures);
+    assert_int_equal(1, LY_ARRAY_SIZE(mod->compiled->features[0].iffeatures));
+    assert_non_null(mod->compiled->features[0].iffeatures[0].features);
+    assert_int_equal(1, LY_ARRAY_SIZE(mod->compiled->features[0].iffeatures[0].features));
+    assert_ptr_equal(&mod->compiled->features[1], mod->compiled->features[0].iffeatures[0].features[0]);
+    assert_non_null(mod->compiled->features);
+    assert_int_equal(2, LY_ARRAY_SIZE(mod->compiled->features));
+    assert_non_null(mod->compiled->features[1].depfeatures);
+    assert_int_equal(1, LY_ARRAY_SIZE(mod->compiled->features[1].depfeatures));
+    assert_ptr_equal(&mod->compiled->features[0], mod->compiled->features[1].depfeatures[0]);
+
+    /* invalid reference */
+    assert_int_equal(LY_EINVAL, lys_feature_enable(mod, "xxx"));
+    logbuf_assert("Feature \"xxx\" not found in module \"b\".");
+
+    /* some invalid expressions */
+    TEST_SCHEMA_ERR(ctx, 1, 0, "inv", "feature f{if-feature f1;}",
+                    "Invalid value \"f1\" of if-feature - unable to find feature \"f1\". /inv:{feature='f'}");
+    TEST_SCHEMA_ERR(ctx, 1, 0, "inv", "feature f1; feature f2{if-feature 'f and';}",
+                    "Invalid value \"f and\" of if-feature - unexpected end of expression. /inv:{feature='f2'}");
+    TEST_SCHEMA_ERR(ctx, 1, 0, "inv", "feature f{if-feature 'or';}",
+                    "Invalid value \"or\" of if-feature - unexpected end of expression. /inv:{feature='f'}");
+    TEST_SCHEMA_ERR(ctx, 1, 0, "inv", "feature f1; feature f2{if-feature '(f1';}",
+                    "Invalid value \"(f1\" of if-feature - non-matching opening and closing parentheses. /inv:{feature='f2'}");
+    TEST_SCHEMA_ERR(ctx, 1, 0, "inv", "feature f1; feature f2{if-feature 'f1)';}",
+                    "Invalid value \"f1)\" of if-feature - non-matching opening and closing parentheses. /inv:{feature='f2'}");
+    TEST_SCHEMA_ERR(ctx, 1, 0, "inv", "feature f1; feature f2{if-feature ---;}",
+                    "Invalid value \"---\" of if-feature - unable to find feature \"---\". /inv:{feature='f2'}");
+    TEST_SCHEMA_ERR(ctx, 0, 0, "inv", "feature f1; feature f2{if-feature 'not f1';}",
+                    "Invalid value \"not f1\" of if-feature - YANG 1.1 expression in YANG 1.0 module. /inv:{feature='f2'}");
+    TEST_SCHEMA_ERR(ctx, 0, 0, "inv", "feature f1; feature f1;",
+                    "Duplicate identifier \"f1\" of feature statement. /inv:{feature='f1'}");
+
+    ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule inv_sub {belongs-to inv {prefix inv;} feature f1;}");
+    TEST_SCHEMA_ERR(ctx, 0, 0, "inv", "include inv_sub;feature f1;",
+                    "Duplicate identifier \"f1\" of feature statement. /inv:{feature='f1'}");
+    TEST_SCHEMA_ERR(ctx, 0, 0, "inv", "feature f1 {if-feature f2;} feature f2 {if-feature f1;}",
+                    "Feature \"f1\" is indirectly referenced from itself. /inv:{feature='f2'}");
+    TEST_SCHEMA_ERR(ctx, 0, 0, "inv", "feature f1 {if-feature f1;}",
+                    "Feature \"f1\" is referenced from itself. /inv:{feature='f1'}");
+    TEST_SCHEMA_ERR(ctx, 1, 0, "inv", "feature f {if-feature ();}",
+                    "Invalid value \"()\" of if-feature - number of features in expression does not match the required number of operands for the operations. /inv:{feature='f'}");
+    TEST_SCHEMA_ERR(ctx, 1, 0, "inv", "feature f1; feature f {if-feature 'f1(';}",
+                    "Invalid value \"f1(\" of if-feature - non-matching opening and closing parentheses. /inv:{feature='f'}");
+    TEST_SCHEMA_ERR(ctx, 1, 0, "inv", "feature f1; feature f {if-feature 'and f1';}",
+                    "Invalid value \"and f1\" of if-feature - missing feature/expression before \"and\" operation. /inv:{feature='f'}");
+    TEST_SCHEMA_ERR(ctx, 1, 0, "inv", "feature f1; feature f {if-feature 'f1 not ';}",
+                    "Invalid value \"f1 not \" of if-feature - unexpected end of expression. /inv:{feature='f'}");
+    TEST_SCHEMA_ERR(ctx, 1, 0, "inv", "feature f1; feature f {if-feature 'f1 not not ';}",
+                    "Invalid value \"f1 not not \" of if-feature - unexpected end of expression. /inv:{feature='f'}");
+    TEST_SCHEMA_ERR(ctx, 1, 0, "inv", "feature f1; feature f2; feature f {if-feature 'or f1 f2';}",
+                    "Invalid value \"or f1 f2\" of if-feature - missing feature/expression before \"or\" operation. /inv:{feature='f'}");
+
+    /* import reference */
+    assert_non_null(mod = ly_ctx_get_module(ctx, "a", NULL));
+    assert_int_equal(LY_SUCCESS, lys_feature_enable(mod, "f1"));
+    TEST_SCHEMA_OK(ctx, 0, 0, "c", "import a {prefix a;} feature f1; feature f2{if-feature 'a:f1';}", mod);
+    assert_int_equal(LY_SUCCESS, lys_feature_enable(mod, "f2"));
+    assert_int_equal(0, lys_feature_value(mod, "f1"));
+    assert_int_equal(1, lys_feature_value(mod, "f2"));
+
+    /*
+     * printing
+     */
+
+    /*
+     * cleanup
+     */
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
diff --git a/tests/src/test_tree_schema_compile.c b/tests/utests/schema/test_tree_schema_compile.c
similarity index 92%
rename from tests/src/test_tree_schema_compile.c
rename to tests/utests/schema/test_tree_schema_compile.c
index 5ad02da..81d13bb 100644
--- a/tests/src/test_tree_schema_compile.c
+++ b/tests/utests/schema/test_tree_schema_compile.c
@@ -189,269 +189,7 @@
     ly_ctx_destroy(mod.ctx, NULL);
 }
 
-static void
-test_feature(void **state)
-{
-    *state = test_feature;
 
-    struct lys_yang_parser_ctx *ctx = NULL;
-    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 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)\";}\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, &mod.ctx));
-    reset_mod(&mod);
-
-    assert_int_equal(LY_SUCCESS, yang_parse_module(&ctx, str, &mod));
-    yang_parser_ctx_free(ctx);
-    assert_int_equal(LY_SUCCESS, lys_compile(&mod, 0));
-    assert_non_null(mod.compiled);
-    assert_non_null(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));
-    }
-    /* enable f1 */
-    assert_int_equal(LY_SUCCESS, lys_feature_enable(&mod, "f1"));
-    f1 = &mod.compiled->features[0];
-    assert_int_equal(1, lysc_feature_value(f1));
-
-    /* enable orfeature */
-    f = &mod.compiled->features[3];
-    assert_int_equal(0, lysc_feature_value(f));
-    assert_int_equal(LY_SUCCESS, lys_feature_enable(&mod, "orfeature"));
-    assert_int_equal(1, lysc_feature_value(f));
-
-    /* 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, "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, "andfeature"));
-    assert_int_equal(1, lysc_feature_value(f));
-
-    /* f1 is enabled, so f6 cannot be enabled */
-    f = &mod.compiled->features[5];
-    assert_int_equal(0, lysc_feature_value(f));
-    assert_int_equal(LY_EDENIED, lys_feature_enable(&mod, "f6"));
-    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 - 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 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"));
-    assert_int_equal(1, lysc_feature_value(&mod.compiled->features[5]));
-
-    /* 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"));
-
-    assert_non_null(modp = lys_parse_mem(mod.ctx, "module b {namespace urn:b;prefix b;"
-                                         "feature f1 {if-feature f2;}feature f2;}", LYS_IN_YANG));
-    assert_non_null(modp->compiled);
-    assert_non_null(modp->compiled->features);
-    assert_int_equal(2, LY_ARRAY_SIZE(modp->compiled->features));
-    assert_non_null(modp->compiled->features[0].iffeatures);
-    assert_int_equal(1, LY_ARRAY_SIZE(modp->compiled->features[0].iffeatures));
-    assert_non_null(modp->compiled->features[0].iffeatures[0].features);
-    assert_int_equal(1, LY_ARRAY_SIZE(modp->compiled->features[0].iffeatures[0].features));
-    assert_ptr_equal(&modp->compiled->features[1], modp->compiled->features[0].iffeatures[0].features[0]);
-    assert_non_null(modp->compiled->features);
-    assert_int_equal(2, LY_ARRAY_SIZE(modp->compiled->features));
-    assert_non_null(modp->compiled->features[1].depfeatures);
-    assert_int_equal(1, LY_ARRAY_SIZE(modp->compiled->features[1].depfeatures));
-    assert_ptr_equal(&modp->compiled->features[0], modp->compiled->features[1].depfeatures[0]);
-
-    /* invalid reference */
-    assert_int_equal(LY_EINVAL, lys_feature_enable(&mod, "xxx"));
-    logbuf_assert("Feature \"xxx\" not found in module \"a\".");
-
-    reset_mod(&mod);
-
-    /* some invalid expressions */
-    assert_int_equal(LY_SUCCESS, yang_parse_module(&ctx, "module b{yang-version 1.1;namespace urn:b; prefix b; feature f{if-feature f1;}}", &mod));
-    yang_parser_ctx_free(ctx);
-    assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
-    logbuf_assert("Invalid value \"f1\" of if-feature - unable to find feature \"f1\". /b:{feature='f'}");
-    reset_mod(&mod);
-
-    assert_int_equal(LY_SUCCESS, yang_parse_module(&ctx, "module b{yang-version 1.1;namespace urn:b; prefix b; feature f1; feature f2{if-feature 'f and';}}", &mod));
-    yang_parser_ctx_free(ctx);
-    assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
-    logbuf_assert("Invalid value \"f and\" of if-feature - unexpected end of expression. /b:{feature='f2'}");
-    reset_mod(&mod);
-
-    assert_int_equal(LY_SUCCESS, yang_parse_module(&ctx, "module b{yang-version 1.1;namespace urn:b; prefix b; feature f{if-feature 'or';}}", &mod));
-    yang_parser_ctx_free(ctx);
-    assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
-    logbuf_assert("Invalid value \"or\" of if-feature - unexpected end of expression. /b:{feature='f'}");
-    reset_mod(&mod);
-
-    assert_int_equal(LY_SUCCESS, yang_parse_module(&ctx, "module b{yang-version 1.1;namespace urn:b; prefix b; feature f1; feature f2{if-feature '(f1';}}", &mod));
-    yang_parser_ctx_free(ctx);
-    assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
-    logbuf_assert("Invalid value \"(f1\" of if-feature - non-matching opening and closing parentheses. /b:{feature='f2'}");
-    reset_mod(&mod);
-
-    assert_int_equal(LY_SUCCESS, yang_parse_module(&ctx, "module b{yang-version 1.1;namespace urn:b; prefix b; feature f1; feature f2{if-feature 'f1)';}}", &mod));
-    yang_parser_ctx_free(ctx);
-    assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
-    logbuf_assert("Invalid value \"f1)\" of if-feature - non-matching opening and closing parentheses. /b:{feature='f2'}");
-    reset_mod(&mod);
-
-    assert_int_equal(LY_SUCCESS, yang_parse_module(&ctx, "module b{yang-version 1.1;namespace urn:b; prefix b; feature f1; feature f2{if-feature ---;}}", &mod));
-    yang_parser_ctx_free(ctx);
-    assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
-    logbuf_assert("Invalid value \"---\" of if-feature - unable to find feature \"---\". /b:{feature='f2'}");
-    reset_mod(&mod);
-
-    assert_int_equal(LY_SUCCESS, yang_parse_module(&ctx, "module b{namespace urn:b; prefix b; feature f1; feature f2{if-feature 'not f1';}}", &mod));
-    yang_parser_ctx_free(ctx);
-    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. /b:{feature='f2'}");
-    reset_mod(&mod);
-
-    assert_int_equal(LY_SUCCESS, yang_parse_module(&ctx, "module b{namespace urn:b; prefix b; feature f1; feature f1;}", &mod));
-    yang_parser_ctx_free(ctx);
-    assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
-    logbuf_assert("Duplicate identifier \"f1\" of feature statement. /b:{feature='f1'}");
-    reset_mod(&mod);
-
-    ly_ctx_set_module_imp_clb(mod.ctx, test_imp_clb, "submodule sz {belongs-to z {prefix z;} feature f1;}");
-    assert_null(lys_parse_mem(mod.ctx, "module z{namespace urn:z; prefix z; include sz;feature f1;}", LYS_IN_YANG));
-    logbuf_assert("Duplicate identifier \"f1\" of feature statement. /z:{feature='f1'}");
-
-    assert_null(lys_parse_mem(mod.ctx, "module aa{namespace urn:aa; prefix aa; feature f1 {if-feature f2;} feature f2 {if-feature f1;}}", LYS_IN_YANG));
-    logbuf_assert("Feature \"f1\" is indirectly referenced from itself. /aa:{feature='f2'}");
-    assert_null(lys_parse_mem(mod.ctx, "module ab{namespace urn:ab; prefix ab; feature f1 {if-feature f1;}}", LYS_IN_YANG));
-    logbuf_assert("Feature \"f1\" is referenced from itself. /ab:{feature='f1'}");
-
-    assert_null(lys_parse_mem(mod.ctx, "module bb{yang-version 1.1; namespace urn:bb; prefix bb; feature f {if-feature ();}}", LYS_IN_YANG));
-    logbuf_assert("Invalid value \"()\" of if-feature - number of features in expression does not match the required number "
-            "of operands for the operations. /bb:{feature='f'}");
-    assert_null(lys_parse_mem(mod.ctx, "module bb{yang-version 1.1; namespace urn:bb; prefix bb; feature f1; feature f {if-feature 'f1(';}}", LYS_IN_YANG));
-    logbuf_assert("Invalid value \"f1(\" of if-feature - non-matching opening and closing parentheses. /bb:{feature='f'}");
-    assert_null(lys_parse_mem(mod.ctx, "module bb{yang-version 1.1; namespace urn:bb; prefix bb; feature f1; feature f {if-feature 'and f1';}}", LYS_IN_YANG));
-    logbuf_assert("Invalid value \"and f1\" of if-feature - missing feature/expression before \"and\" operation. /bb:{feature='f'}");
-    assert_null(lys_parse_mem(mod.ctx, "module bb{yang-version 1.1; namespace urn:bb; prefix bb; feature f1; feature f {if-feature 'f1 not ';}}", LYS_IN_YANG));
-    logbuf_assert("Invalid value \"f1 not \" of if-feature - unexpected end of expression. /bb:{feature='f'}");
-    assert_null(lys_parse_mem(mod.ctx, "module bb{yang-version 1.1; namespace urn:bb; prefix bb; feature f1; feature f {if-feature 'f1 not not ';}}", LYS_IN_YANG));
-    logbuf_assert("Invalid value \"f1 not not \" of if-feature - unexpected end of expression. /bb:{feature='f'}");
-    assert_null(lys_parse_mem(mod.ctx, "module bb{yang-version 1.1; namespace urn:bb; prefix bb; feature f1; feature f2; "
-                              "feature f {if-feature 'or f1 f2';}}", LYS_IN_YANG));
-    logbuf_assert("Invalid value \"or f1 f2\" of if-feature - missing feature/expression before \"or\" operation. /bb:{feature='f'}");
-
-    /* import reference */
-    assert_non_null(modp = lys_parse_mem(mod.ctx, str, LYS_IN_YANG));
-    assert_int_equal(LY_SUCCESS, lys_feature_enable(modp, "f1"));
-    assert_non_null(modp = lys_parse_mem(mod.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_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(mod.ctx, NULL);
-}
-
-static void
-test_identity(void **state)
-{
-    *state = test_identity;
-
-    struct ly_ctx *ctx;
-    struct lys_module *mod1, *mod2;
-
-    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
-    assert_non_null(mod1 = lys_parse_mem(ctx, "module a {namespace urn:a;prefix a; identity a1;}", LYS_IN_YANG));
-    assert_non_null(mod2 = lys_parse_mem(ctx, "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;}}", LYS_IN_YANG));
-
-    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(mod2 = lys_parse_mem(ctx, "module c {yang-version 1.1;namespace urn:c;prefix c;"
-                                             "identity c2 {base c1;} identity c1;}", LYS_IN_YANG));
-    assert_int_equal(1, LY_ARRAY_SIZE(mod2->compiled->identities[1].derived));
-    assert_ptr_equal(mod2->compiled->identities[1].derived[0], &mod2->compiled->identities[0]);
-
-    assert_null(lys_parse_mem(ctx, "module aa{namespace urn:aa; prefix aa; identity i1;identity i1;}", LYS_IN_YANG));
-    logbuf_assert("Duplicate identifier \"i1\" of identity statement. /aa:{identity='i1'}");
-
-    ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule sbb {belongs-to bb {prefix bb;} identity i1;}");
-    assert_null(lys_parse_mem(ctx, "module bb{namespace urn:bb; prefix bb; include sbb;identity i1;}", LYS_IN_YANG));
-    logbuf_assert("Duplicate identifier \"i1\" of identity statement. /bb:{identity='i1'}");
-
-    assert_null(lys_parse_mem(ctx, "module cc{namespace urn:cc; prefix cc; identity i1 {base i2;}}", LYS_IN_YANG));
-    logbuf_assert("Unable to find base (i2) of identity \"i1\". /cc:{identity='i1'}");
-
-    assert_null(lys_parse_mem(ctx, "module dd{namespace urn:dd; prefix dd; identity i1 {base i1;}}", LYS_IN_YANG));
-    logbuf_assert("Identity \"i1\" is derived from itself. /dd:{identity='i1'}");
-    assert_null(lys_parse_mem(ctx, "module de{namespace urn:de; prefix de; identity i1 {base i2;}identity i2 {base i3;}identity i3 {base i1;}}", LYS_IN_YANG));
-    logbuf_assert("Identity \"i1\" is indirectly derived from itself. /de:{identity='i3'}");
-
-    *state = NULL;
-    ly_ctx_destroy(ctx, NULL);
-}
 
 static void
 test_node_container(void **state)
@@ -3581,8 +3319,6 @@
 {
     const struct CMUnitTest tests[] = {
         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),
diff --git a/tests/src/test_common.c b/tests/utests/test_common.c
similarity index 100%
rename from tests/src/test_common.c
rename to tests/utests/test_common.c
diff --git a/tests/src/test_context.c b/tests/utests/test_context.c
similarity index 97%
rename from tests/src/test_context.c
rename to tests/utests/test_context.c
index a70a01a..d9b8e9f 100644
--- a/tests/src/test_context.c
+++ b/tests/utests/test_context.c
@@ -96,8 +96,8 @@
     logbuf_assert("Invalid argument ctx (ly_ctx_unset_searchdirs()).");
 
     /* readable and executable, but not a directory */
-    assert_int_equal(LY_EINVAL, ly_ctx_set_searchdir(ctx, TESTS_BIN"/src_context"));
-    logbuf_assert("Given search directory \""TESTS_BIN"/src_context\" is not a directory.");
+    assert_int_equal(LY_EINVAL, ly_ctx_set_searchdir(ctx, TESTS_BIN"/utest_context"));
+    logbuf_assert("Given search directory \""TESTS_BIN"/utest_context\" is not a directory.");
     /* not executable */
     assert_int_equal(LY_EINVAL, ly_ctx_set_searchdir(ctx, __FILE__));
     logbuf_assert("Unable to fully access search directory \""__FILE__"\" (Permission denied).");
@@ -110,14 +110,14 @@
     assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(ctx, NULL));
 
     /* correct path */
-    assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(ctx, TESTS_BIN"/src"));
+    assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(ctx, TESTS_BIN"/utests"));
     assert_int_equal(1, ctx->search_paths.count);
-    assert_string_equal(TESTS_BIN"/src", ctx->search_paths.objs[0]);
+    assert_string_equal(TESTS_BIN"/utests", ctx->search_paths.objs[0]);
 
     /* duplicated paths */
-    assert_int_equal(LY_EEXIST, ly_ctx_set_searchdir(ctx, TESTS_BIN"/src"));
+    assert_int_equal(LY_EEXIST, ly_ctx_set_searchdir(ctx, TESTS_BIN"/utests"));
     assert_int_equal(1, ctx->search_paths.count);
-    assert_string_equal(TESTS_BIN"/src", ctx->search_paths.objs[0]);
+    assert_string_equal(TESTS_BIN"/utests", ctx->search_paths.objs[0]);
 
     /* another paths - add 8 to fill the initial buffer of the searchpaths list */
     assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(ctx, TESTS_BIN"/CMakeFiles"));
@@ -132,7 +132,7 @@
     /* get searchpaths */
     list = ly_ctx_get_searchdirs(ctx);
     assert_non_null(list);
-    assert_string_equal(TESTS_BIN"/src", list[0]);
+    assert_string_equal(TESTS_BIN"/utests", list[0]);
     assert_string_equal(TESTS_BIN"/CMakeFiles", list[1]);
     assert_string_equal(TESTS_SRC, list[5]);
     assert_string_equal(TESTS_BIN, list[6]);
@@ -144,8 +144,8 @@
     assert_int_equal(LY_EINVAL, ly_ctx_unset_searchdirs(ctx, "/nonexistingfile"));
     logbuf_assert("Invalid argument value (ly_ctx_unset_searchdirs()).");
     /* first */
-    assert_int_equal(LY_SUCCESS, ly_ctx_unset_searchdirs(ctx, TESTS_BIN"/src"));
-    assert_string_not_equal(TESTS_BIN"/src", list[0]);
+    assert_int_equal(LY_SUCCESS, ly_ctx_unset_searchdirs(ctx, TESTS_BIN"/utests"));
+    assert_string_not_equal(TESTS_BIN"/utests", list[0]);
     assert_int_equal(7, ctx->search_paths.count);
     /* middle */
     assert_int_equal(LY_SUCCESS, ly_ctx_unset_searchdirs(ctx, TESTS_SRC));
diff --git a/tests/src/test_hash_table.c b/tests/utests/test_hash_table.c
similarity index 100%
rename from tests/src/test_hash_table.c
rename to tests/utests/test_hash_table.c
diff --git a/tests/src/test_set.c b/tests/utests/test_set.c
similarity index 100%
rename from tests/src/test_set.c
rename to tests/utests/test_set.c
diff --git a/tests/src/test_xml.c b/tests/utests/test_xml.c
similarity index 100%
rename from tests/src/test_xml.c
rename to tests/utests/test_xml.c