tests CHANGE join related schema tests

group the test according to the functional blocks, starting with the
schema. So now all the schema parser, compiler and printers are put
together.
diff --git a/tests/utests/CMakeLists.txt b/tests/utests/CMakeLists.txt
index 1a758a1..04af8d4 100644
--- a/tests/utests/CMakeLists.txt
+++ b/tests/utests/CMakeLists.txt
@@ -4,18 +4,17 @@
     utest:test_hash_table
     utest:test_context
     utest:test_xml
-    utest:test_parser_yang
-    utest:test_parser_yin
-    utest:test_tree_schema
-    utest:test_tree_schema_compile
-    utest:test_tree_schema_helpers
-    utest:test_printer_yang
-    utest:test_printer_yin
-    utest:test_tree_data
-    utest:test_parser_xml
-    utest:test_printer_xml
-    utest:test_validation
-    utest:test_types
+    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
@@ -32,7 +31,6 @@
     " "
     " "
     " "
-    " "	
     " "
     " "
     " "
diff --git a/tests/utests/test_parser_xml.c b/tests/utests/data/test_parser_xml.c
similarity index 100%
rename from tests/utests/test_parser_xml.c
rename to tests/utests/data/test_parser_xml.c
diff --git a/tests/utests/test_printer_xml.c b/tests/utests/data/test_printer_xml.c
similarity index 100%
rename from tests/utests/test_printer_xml.c
rename to tests/utests/data/test_printer_xml.c
diff --git a/tests/utests/test_tree_data.c b/tests/utests/data/test_tree_data.c
similarity index 100%
rename from tests/utests/test_tree_data.c
rename to tests/utests/data/test_tree_data.c
diff --git a/tests/utests/test_types.c b/tests/utests/data/test_types.c
similarity index 100%
rename from tests/utests/test_types.c
rename to tests/utests/data/test_types.c
diff --git a/tests/utests/test_validation.c b/tests/utests/data/test_validation.c
similarity index 100%
rename from tests/utests/test_validation.c
rename to tests/utests/data/test_validation.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/utests/test_parser_yang.c b/tests/utests/schema/test_parser_yang.c
similarity index 95%
rename from tests/utests/test_parser_yang.c
rename to tests/utests/schema/test_parser_yang.c
index 6342358..6311dfc 100644
--- a/tests/utests/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/utests/test_parser_yin.c b/tests/utests/schema/test_parser_yin.c
similarity index 96%
rename from tests/utests/test_parser_yin.c
rename to tests/utests/schema/test_parser_yin.c
index ce5f0c8..ea22333 100644
--- a/tests/utests/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/utests/test_printer_yang.c b/tests/utests/schema/test_printer_yang.c
similarity index 100%
rename from tests/utests/test_printer_yang.c
rename to tests/utests/schema/test_printer_yang.c
diff --git a/tests/utests/test_printer_yin.c b/tests/utests/schema/test_printer_yin.c
similarity index 100%
rename from tests/utests/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/utests/test_tree_schema_compile.c b/tests/utests/schema/test_tree_schema_compile.c
similarity index 92%
rename from tests/utests/test_tree_schema_compile.c
rename to tests/utests/schema/test_tree_schema_compile.c
index 5ad02da..81d13bb 100644
--- a/tests/utests/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/utests/test_tree_schema.c b/tests/utests/test_tree_schema.c
deleted file mode 100644
index bcee581..0000000
--- a/tests/utests/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/utests/test_tree_schema_helpers.c b/tests/utests/test_tree_schema_helpers.c
deleted file mode 100644
index 01fe9f4..0000000
--- a/tests/utests/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);
-}